53 lines
2.0 KiB
Python
53 lines
2.0 KiB
Python
"""
|
|
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)
|