Audio bleibt bevorzugt, wenn eine Folge beides hat; Endungen werden am Pfad erkannt (Query-Strings stören nicht mehr). refresh_feeds --full liest alle Feeds ohne ETag neu ein; dabei gefundene Folgen, die vor dem letzten Abruf erschienen sind, kommen in die Liste, nicht nach „Neu“. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
39 lines
1.6 KiB
Python
39 lines
1.6 KiB
Python
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
|
|
|
|
|
|
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()))
|
|
|
|
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')
|