feat(main): commit

This commit is contained in:
2026-03-08 16:48:58 -04:00
parent 567766eaed
commit f37382d2b8
29 changed files with 3735 additions and 223 deletions

View File

@@ -1,16 +1,29 @@
from django.core.management.base import BaseCommand
from core.models import AppUser, Library, Channel, MediaItem, Airing, ScheduleTemplate
from core.services.scheduler import ScheduleGenerator
from django.utils import timezone
from datetime import timedelta
from datetime import timedelta, date
import textwrap
class Command(BaseCommand):
help = "Displays a beautifully formatted terminal dashboard of the current backend state."
def add_arguments(self, parser):
parser.add_argument('--channel', type=int, help='Inspect specific channel schedule')
parser.add_argument('--test-generate', action='store_true', help='Trigger generation for today if inspecting a channel')
def get_color(self, text, code):
"""Helper to wrap string in bash color codes"""
return f"\033[{code}m{text}\033[0m"
def handle(self, *args, **options):
channel_id = options.get('channel')
test_generate = options.get('test_generate')
if channel_id:
self.inspect_channel(channel_id, test_generate)
return
# 1. Gather Aggregate Metrics
total_users = AppUser.objects.count()
total_libraries = Library.objects.count()
@@ -46,7 +59,7 @@ class Command(BaseCommand):
for c in channels:
status_color = "1;32" if c.is_active else "1;31"
status_text = "ACTIVE" if c.is_active else "INACTIVE"
self.stdout.write(f"\n 📺 [{c.channel_number or '-'}] {c.name} ({self.get_color(status_text, status_color)})")
self.stdout.write(f"\n 📺 [{c.id}] {c.name} (Ch {c.channel_number or '-'}) ({self.get_color(status_text, status_color)})")
# Show templates
templates = c.scheduletemplate_set.filter(is_active=True).order_by('-priority')
@@ -57,4 +70,40 @@ class Command(BaseCommand):
blocks_count = t.scheduleblock_set.count()
self.stdout.write(f" 📄 Template: {t.name} (Priority {t.priority}) -> {blocks_count} Blocks")
self.stdout.write(f"\nUse {self.get_color('--channel <id>', '1;37')} to inspect detailed schedule.\n")
def inspect_channel(self, channel_id, test_generate):
try:
channel = Channel.objects.get(id=channel_id)
except Channel.DoesNotExist:
self.stdout.write(self.get_color(f"Error: Channel {channel_id} not found.", "1;31"))
return
if test_generate:
self.stdout.write(self.get_color(f"\nTriggering schedule generation for {channel.name}...", "1;33"))
generator = ScheduleGenerator(channel)
count = generator.generate_for_date(date.today())
self.stdout.write(f"Done. Created {self.get_color(str(count), '1;32')} new airings.")
now = timezone.now()
end_window = now + timedelta(hours=12)
airings = Airing.objects.filter(
channel=channel,
ends_at__gt=now,
starts_at__lt=end_window
).select_related('media_item').order_by('starts_at')
self.stdout.write(self.get_color(f"\n=== Schedule for {channel.name} (Next 12h) ===", "1;34"))
if not airings:
self.stdout.write(self.get_color(" (No airings scheduled in this window)", "1;33"))
else:
for a in airings:
time_str = f"{a.starts_at.strftime('%H:%M')} - {a.ends_at.strftime('%H:%M')}"
if a.starts_at <= now <= a.ends_at:
self.stdout.write(f" {self.get_color('▶ ON AIR', '1;32')} {self.get_color(time_str, '1;37')} | {a.media_item.title}")
else:
self.stdout.write(f" {time_str} | {a.media_item.title}")
self.stdout.write("\n")