Fix air_date not populating for series.

This commit is contained in:
SergeantPanda 2025-08-07 19:28:42 -05:00
parent 56922e1c01
commit 8d37c678d3
5 changed files with 49 additions and 13 deletions

View file

@ -383,7 +383,6 @@ class SeriesViewSet(viewsets.ReadOnlyModelViewSet):
'rating': series.rating,
'tmdb_id': series.tmdb_id,
'imdb_id': series.imdb_id,
'youtube_trailer': (series.custom_properties or {}).get('trailer') or (series.custom_properties or {}).get('youtube_trailer', ''),
'category_id': relation.category.id if relation.category else None,
'category_name': relation.category.name if relation.category else None,
'cover': {
@ -426,11 +425,13 @@ class SeriesViewSet(viewsets.ReadOnlyModelViewSet):
'episode_number': episode.episode_number,
'season_number': episode.season_number,
'description': episode.description,
'release_date': episode.release_date,
'air_date': episode.air_date,
'plot': episode.description,
'duration': episode.duration,
'rating': episode.rating,
'movie_image': episode_relation.custom_properties.get('info', {}).get('movie_image') if episode_relation and episode_relation.custom_properties else None,
'tmdb_id': episode.tmdb_id,
'imdb_id': episode.imdb_id,
'movie_image': episode_relation.custom_properties.get("info", {}).get('info', {}).get('movie_image') if episode_relation and episode_relation.custom_properties else None,
'container_extension': episode_relation.container_extension if episode_relation else 'mp4',
'type': 'episode',
'series': {

View file

@ -111,7 +111,7 @@ class Episode(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
name = models.CharField(max_length=255)
description = models.TextField(blank=True, null=True)
release_date = models.DateField(blank=True, null=True)
air_date = models.DateField(blank=True, null=True)
rating = models.CharField(max_length=10, blank=True, null=True)
duration = models.IntegerField(blank=True, null=True, help_text="Duration in minutes")

View file

@ -8,6 +8,7 @@ from .models import (
M3USeriesRelation, M3UMovieRelation, M3UEpisodeRelation
)
from apps.channels.models import Logo
from datetime import datetime
import logging
import json
import re
@ -298,8 +299,7 @@ def refresh_series_episodes(account, series, external_series_id, episodes_data=N
series.description = info.get('plot', series.description)
series.rating = info.get('rating', series.rating)
series.genre = info.get('genre', series.genre)
if info.get('releasedate'):
series.year = extract_year(info.get('releasedate'))
series.year = extract_year_from_data(info)
series.save()
episodes_data = series_info.get('episodes', {})
@ -347,8 +347,10 @@ def process_episode(account, series, episode_data, season_number):
if info:
description = info.get('plot') or info.get('overview', '')
rating = episode_data.get('rating', '')
release_date = extract_year_from_data(episode_data.get('info'))
rating = info.get('rating', '')
# Use helper function to parse air_date
air_date = extract_date_from_data(info)
# Create or update episode
episode, created = Episode.objects.update_or_create(
@ -359,7 +361,10 @@ def process_episode(account, series, episode_data, season_number):
'name': episode_name,
'description': description,
'rating': rating,
'release_date': release_date,
'air_date': air_date,
'duration': convert_duration_to_minutes(info.get('duration_secs')),
'tmdb_id': info.get('tmdb_id'),
'imdb_id': info.get('imdb_id'),
}
)
@ -658,4 +663,32 @@ def cleanup_orphaned_vod_content():
# Episodes will be cleaned up via CASCADE when series are deleted
logger.info(f"Cleaned up {movie_count} orphaned movies and {series_count} orphaned series")
return f"Cleaned up {movie_count} movies and {series_count} series"
return f"Cleaned up {movie_count} movies and {series_count} series"
def extract_date_from_data(data):
"""Extract date from various data sources with fallback options"""
try:
for date_field in ['air_date', 'releaseDate', 'release_date']:
date_value = data.get(date_field)
if date_value and isinstance(date_value, str) and date_value.strip():
parsed = parse_date(date_value)
if parsed:
return parsed
except Exception:
# Don't fail processing if date extraction fails
pass
return None
def parse_date(date_string):
"""Parse date string into a datetime object"""
if not date_string:
return None
try:
# Try to parse ISO format first
return datetime.fromisoformat(date_string)
except ValueError:
# Fallback to parsing with strptime for common formats
try:
return datetime.strptime(date_string, '%Y-%m-%d')
except ValueError:
return None # Return None if parsing fails

View file

@ -626,7 +626,7 @@ const SeriesModal = ({ series, opened, onClose }) => {
</Table.Td>
<Table.Td>
<Text size="xs" color="dimmed">
{episode.release_date ? new Date(episode.release_date).toLocaleDateString() : 'N/A'}
{episode.air_date ? new Date(episode.air_date).toLocaleDateString() : 'N/A'}
</Text>
</Table.Td>
<Table.Td>

View file

@ -308,7 +308,7 @@ const useVODStore = create((set, get) => ({
description: episode.plot || '',
season_number: parseInt(seasonNumber) || 0,
episode_number: episode.episode_number || 0,
duration: episode.duration ? Math.floor(episode.duration / 60) : null,
duration: episode.duration || null,
rating: episode.rating || '',
container_extension: episode.container_extension || '',
series: {
@ -318,8 +318,10 @@ const useVODStore = create((set, get) => ({
type: 'episode',
uuid: episode.id, // Use the stream ID as UUID for playback
logo: episode.movie_image ? { url: episode.movie_image } : null,
release_date: episode.release_date || null,
air_date: episode.air_date || null,
movie_image: episode.movie_image || null,
tmdb_id: episode.tmdb_id || '',
imdb_id: episode.imdb_id || '',
};
episodesData[episode.id] = episodeData;
});