from django.core.management.base import BaseCommand from django.utils import timezone from podcasts.models import PodcastFeed from podcasts.views import _in_backoff_q, _refresh_feeds, refresh_due class Command(BaseCommand): help = 'Refresh podcast feeds (fetch new episodes from RSS)' def add_arguments(self, parser): parser.add_argument('--feed-id', type=int, help='Refresh only this feed ID (even when backing off)') parser.add_argument('--limit', type=int, default=0, help='Max number of feeds to refresh') parser.add_argument( '--full', action='store_true', help='Download every feed in full (ignore ETag/Last-Modified) and take in episodes skipped before ' '(e.g. video ones); those out before the last refresh go into the list, not into "Neu"', ) def handle(self, *args, **options): qs = PodcastFeed.objects.all().order_by('last_refreshed_at') if options['feed_id']: qs = qs.filter(pk=options['feed_id']) else: # A feed failing 3+ times in a row is tried every 2, 4, 8, 16, # at most 24 hours instead of every hour. qs = qs.exclude(_in_backoff_q(timezone.now())) # Each feed as often as its interval says (docs/podcasts.md): by its rhythm, # or hourly, daily, weekly. --feed-id and --full take every one. if not options['full']: qs = qs.filter(pk__in=refresh_due(list(qs.select_related('user')))) if options['limit']: qs = qs[: options['limit']] if not qs.exists(): self.stdout.write('No feeds to refresh.') return # Parallel downloads, one per distinct feed URL (see _refresh_feeds). refreshed, failed, new = _refresh_feeds(qs, full=options['full']) self.stdout.write(f'{refreshed} feeds refreshed, {failed} failed, +{new} episodes')