feat(main): main
This commit is contained in:
@@ -58,13 +58,26 @@ class AiringSchema(Schema):
|
||||
ends_at: datetime
|
||||
slot_kind: str
|
||||
status: str
|
||||
exact_playback_offset_seconds: float = 0.0
|
||||
|
||||
@staticmethod
|
||||
def from_airing(airing) -> 'AiringSchema':
|
||||
media_path = None
|
||||
exact_offset = 0.0
|
||||
|
||||
# Calculate exactly how far into the video we should be right now
|
||||
now = timezone.now()
|
||||
# if the airing hasn't started yet, offset is 0
|
||||
if now >= airing.starts_at:
|
||||
exact_offset = (now - airing.starts_at).total_seconds()
|
||||
|
||||
if airing.media_item:
|
||||
item = airing.media_item
|
||||
|
||||
# If the item has a known runtime, and we are looping it, modulo the offset
|
||||
if item.runtime_seconds and item.runtime_seconds > 0:
|
||||
exact_offset = exact_offset % item.runtime_seconds
|
||||
|
||||
# 1. Determine if this item is from a YouTube source
|
||||
is_youtube = False
|
||||
if item.media_source and item.media_source.source_type in ['youtube', 'youtube_channel', 'youtube_playlist']:
|
||||
@@ -102,6 +115,7 @@ class AiringSchema(Schema):
|
||||
ends_at=airing.ends_at,
|
||||
slot_kind=airing.slot_kind,
|
||||
status=airing.status,
|
||||
exact_playback_offset_seconds=max(0.0, exact_offset)
|
||||
)
|
||||
|
||||
@router.get("/", response=List[ChannelSchema])
|
||||
@@ -112,7 +126,61 @@ def list_channels(request):
|
||||
)
|
||||
|
||||
|
||||
class ChannelStatusSchema(Schema):
|
||||
total_upcoming_airings: int
|
||||
total_cached_airings: int
|
||||
percent_cached: float
|
||||
missing_items: List[dict]
|
||||
|
||||
@router.get("/{channel_id}/status", response=ChannelStatusSchema)
|
||||
def get_channel_status(request, channel_id: int):
|
||||
channel = get_object_or_404(Channel, id=channel_id)
|
||||
now = timezone.now()
|
||||
window_end = now + timedelta(hours=24)
|
||||
|
||||
airings = Airing.objects.filter(
|
||||
channel=channel,
|
||||
ends_at__gt=now,
|
||||
starts_at__lte=window_end
|
||||
).select_related('media_item')
|
||||
|
||||
total = 0
|
||||
cached = 0
|
||||
missing = []
|
||||
|
||||
for a in airings:
|
||||
total += 1
|
||||
item = a.media_item
|
||||
if item and item.cached_file_path:
|
||||
# We don't do path.exists() here to keep it fast, but we could.
|
||||
cached += 1
|
||||
elif item:
|
||||
missing.append({
|
||||
"id": item.id,
|
||||
"title": item.title,
|
||||
"starts_at": a.starts_at.isoformat()
|
||||
})
|
||||
|
||||
pct = (cached / total * 100.0) if total > 0 else 100.0
|
||||
|
||||
return {
|
||||
"total_upcoming_airings": total,
|
||||
"total_cached_airings": cached,
|
||||
"percent_cached": pct,
|
||||
"missing_items": missing
|
||||
}
|
||||
|
||||
@router.post("/{channel_id}/download")
|
||||
def trigger_channel_download(request, channel_id: int):
|
||||
get_object_or_404(Channel, id=channel_id)
|
||||
from core.services.cache import run_cache
|
||||
|
||||
# Run cache explicitly for this channel for the next 24 hours
|
||||
result = run_cache(hours=24, prune_only=False, channel_id=channel_id)
|
||||
return result
|
||||
|
||||
@router.get("/{channel_id}", response=ChannelSchema)
|
||||
|
||||
def get_channel(request, channel_id: int):
|
||||
return get_object_or_404(Channel, id=channel_id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user