""" management command: cache_upcoming Delegates to core.services.cache.run_cache() — the same logic exposed by the API endpoint, so CLI and web UI behavior are always in sync. Usage: python manage.py cache_upcoming # default: next 24 hours python manage.py cache_upcoming --hours 48 python manage.py cache_upcoming --prune-only """ from django.core.management.base import BaseCommand from core.services.cache import run_cache class Command(BaseCommand): help = "Download YouTube videos for upcoming airings and prune old cache files." def add_arguments(self, parser): parser.add_argument( "--hours", type=int, default=24, help="How many hours ahead to scan for upcoming airings (default: 24).", ) parser.add_argument( "--prune-only", action="store_true", default=False, help="Only delete expired cache files; do not download anything new.", ) def handle(self, *args, **options): hours = options["hours"] prune_only = options["prune_only"] self.stdout.write(f"▶ Running cache worker (window: {hours}h, prune-only: {prune_only})") result = run_cache(hours=hours, prune_only=prune_only) self.stdout.write(self.style.SUCCESS(f" 🗑 Pruned: {result['pruned']}")) self.stdout.write(self.style.SUCCESS(f" ↓ Downloaded: {result['downloaded']}")) self.stdout.write(self.style.SUCCESS(f" ✓ Already cached: {result['already_cached']}")) if result["failed"]: self.stderr.write(self.style.ERROR(f" ✗ Failed: {result['failed']}")) for item in result["items"]: icon = {"downloaded": "↓", "cached": "✓", "failed": "✗"}.get(item["status"], "?") line = f" {icon} [{item['status']:10}] {item['title'][:70]}" if item.get("error"): line += f" — {item['error']}" self.stdout.write(line)