mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-01-23 02:35:14 +00:00
Fixed some vod apis, converted duration to duration_secs, add custom_poperties to vod_episode
This commit is contained in:
parent
3ac84e530a
commit
4d7987214b
7 changed files with 238 additions and 131 deletions
|
|
@ -1099,7 +1099,7 @@ def xc_get_vod_streams(request, user, category_id=None):
|
|||
),
|
||||
#'stream_icon': movie.logo.url if movie.logo else '',
|
||||
"rating": movie.rating or "0",
|
||||
"rating_5based": float(movie.rating or 0) / 2 if movie.rating else 0,
|
||||
"rating_5based": round(float(movie.rating or 0) / 2, 2) if movie.rating else 0,
|
||||
"added": str(movie.created_at.timestamp()),
|
||||
"is_adult": 0,
|
||||
"tmdb_id": movie.tmdb_id or "",
|
||||
|
|
@ -1197,17 +1197,18 @@ def xc_get_series(request, user, category_id=None):
|
|||
)
|
||||
),
|
||||
"plot": series.description or "",
|
||||
"cast": "",
|
||||
"director": "",
|
||||
"cast": series.custom_properties.get('cast', '') if series.custom_properties else "",
|
||||
"director": series.custom_properties.get('director', '') if series.custom_properties else "",
|
||||
"genre": series.genre or "",
|
||||
"release_date": str(series.year) if series.year else "",
|
||||
"release_date": series.custom_properties.get('release_date', str(series.year) if series.year else "") if series.custom_properties else (str(series.year) if series.year else ""),
|
||||
"last_modified": int(relation.updated_at.timestamp()),
|
||||
"rating": series.rating or "0",
|
||||
"rating_5based": float(series.rating or 0) / 2 if series.rating else 0,
|
||||
"backdrop_path": [],
|
||||
"youtube_trailer": "",
|
||||
"episode_run_time": "",
|
||||
"rating_5based": round(float(series.rating or 0) / 2, 2) if series.rating else 0,
|
||||
"backdrop_path": series.custom_properties.get('backdrop_path', []) if series.custom_properties else [],
|
||||
"youtube_trailer": series.custom_properties.get('youtube_trailer', '') if series.custom_properties else "",
|
||||
"episode_run_time": series.custom_properties.get('episode_run_time', '') if series.custom_properties else "",
|
||||
"category_id": str(relation.category.id) if relation.category else "0",
|
||||
"category_ids": [int(relation.category.id)] if relation.category else [],
|
||||
})
|
||||
|
||||
return series_list
|
||||
|
|
@ -1241,6 +1242,31 @@ def xc_get_series_info(request, user, series_id):
|
|||
except M3USeriesRelation.DoesNotExist:
|
||||
raise Http404()
|
||||
|
||||
# Check if we need to refresh detailed info (similar to vod api_views pattern)
|
||||
try:
|
||||
should_refresh = (
|
||||
not series_relation.last_episode_refresh or
|
||||
series_relation.last_episode_refresh < timezone.now() - timedelta(hours=24)
|
||||
)
|
||||
|
||||
# Check if detailed data has been fetched
|
||||
custom_props = series_relation.custom_properties or {}
|
||||
episodes_fetched = custom_props.get('episodes_fetched', False)
|
||||
detailed_fetched = custom_props.get('detailed_fetched', False)
|
||||
|
||||
# Force refresh if episodes/details have never been fetched or time interval exceeded
|
||||
if not episodes_fetched or not detailed_fetched or should_refresh:
|
||||
from apps.vod.tasks import refresh_series_episodes
|
||||
account = series_relation.m3u_account
|
||||
if account and account.is_active:
|
||||
refresh_series_episodes(account, series, series_relation.external_series_id)
|
||||
# Refresh objects from database after task completion
|
||||
series.refresh_from_db()
|
||||
series_relation.refresh_from_db()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error refreshing series data for relation {series_relation.id}: {str(e)}")
|
||||
|
||||
# Get episodes for this series from the same M3U account
|
||||
episode_relations = M3UEpisodeRelation.objects.filter(
|
||||
episode__series=series,
|
||||
|
|
@ -1284,11 +1310,63 @@ def xc_get_series_info(request, user, series_id):
|
|||
}
|
||||
})
|
||||
|
||||
# Build response
|
||||
# Build response using potentially refreshed data
|
||||
series_data = {
|
||||
'name': series.name,
|
||||
'description': series.description or '',
|
||||
'year': series.year,
|
||||
'genre': series.genre or '',
|
||||
'rating': series.rating or '0',
|
||||
'cast': '',
|
||||
'director': '',
|
||||
'youtube_trailer': '',
|
||||
'episode_run_time': '',
|
||||
'backdrop_path': [],
|
||||
}
|
||||
|
||||
# Add detailed info from custom_properties if available
|
||||
try:
|
||||
if series.custom_properties:
|
||||
custom_data = series.custom_properties
|
||||
series_data.update({
|
||||
'cast': custom_data.get('cast', ''),
|
||||
'director': custom_data.get('director', ''),
|
||||
'youtube_trailer': custom_data.get('youtube_trailer', ''),
|
||||
'episode_run_time': custom_data.get('episode_run_time', ''),
|
||||
'backdrop_path': custom_data.get('backdrop_path', []),
|
||||
})
|
||||
|
||||
# Check relation custom_properties for detailed_info
|
||||
if series_relation.custom_properties and 'detailed_info' in series_relation.custom_properties:
|
||||
detailed_info = series_relation.custom_properties['detailed_info']
|
||||
|
||||
# Override with detailed_info values where available
|
||||
for key in ['name', 'description', 'year', 'genre', 'rating']:
|
||||
if detailed_info.get(key):
|
||||
series_data[key] = detailed_info[key]
|
||||
|
||||
# Handle plot vs description
|
||||
if detailed_info.get('plot'):
|
||||
series_data['description'] = detailed_info['plot']
|
||||
elif detailed_info.get('description'):
|
||||
series_data['description'] = detailed_info['description']
|
||||
|
||||
# Update additional fields from detailed info
|
||||
series_data.update({
|
||||
'cast': detailed_info.get('cast', series_data['cast']),
|
||||
'director': detailed_info.get('director', series_data['director']),
|
||||
'youtube_trailer': detailed_info.get('youtube_trailer', series_data['youtube_trailer']),
|
||||
'episode_run_time': detailed_info.get('episode_run_time', series_data['episode_run_time']),
|
||||
'backdrop_path': detailed_info.get('backdrop_path', series_data['backdrop_path']),
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error parsing series custom_properties: {str(e)}")
|
||||
|
||||
info = {
|
||||
"seasons": list(seasons.keys()),
|
||||
"info": {
|
||||
"name": series.name,
|
||||
"name": series_data['name'],
|
||||
"cover": (
|
||||
None if not series.logo
|
||||
else build_absolute_uri_with_port(
|
||||
|
|
@ -1296,17 +1374,17 @@ def xc_get_series_info(request, user, series_id):
|
|||
reverse("api:channels:logo-cache", args=[series.logo.id])
|
||||
)
|
||||
),
|
||||
"plot": series.description or "",
|
||||
"cast": "",
|
||||
"director": "",
|
||||
"genre": series.genre or "",
|
||||
"release_date": str(series.year) if series.year else "",
|
||||
"plot": series_data['description'],
|
||||
"cast": series_data['cast'],
|
||||
"director": series_data['director'],
|
||||
"genre": series_data['genre'],
|
||||
"release_date": str(series_data['year']) if series_data['year'] else "",
|
||||
"last_modified": int(series_relation.updated_at.timestamp()),
|
||||
"rating": series.rating or "0",
|
||||
"rating_5based": float(series.rating or 0) / 2 if series.rating else 0,
|
||||
"backdrop_path": [],
|
||||
"youtube_trailer": "",
|
||||
"episode_run_time": "",
|
||||
"rating": series_data['rating'],
|
||||
"rating_5based": round(float(series_data['rating'] or 0) / 2, 2) if series_data['rating'] else 0,
|
||||
"backdrop_path": series_data['backdrop_path'],
|
||||
"youtube_trailer": series_data['youtube_trailer'],
|
||||
"episode_run_time": series_data['episode_run_time'],
|
||||
"category_id": str(series_relation.category.id) if series_relation.category else "0",
|
||||
},
|
||||
"episodes": dict(seasons)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class SeriesAdmin(admin.ModelAdmin):
|
|||
|
||||
@admin.register(Movie)
|
||||
class MovieAdmin(admin.ModelAdmin):
|
||||
list_display = ['name', 'year', 'genre', 'duration', 'created_at']
|
||||
list_display = ['name', 'year', 'genre', 'duration_secs', 'created_at']
|
||||
list_filter = ['year', 'created_at']
|
||||
search_fields = ['name', 'description', 'tmdb_id', 'imdb_id']
|
||||
readonly_fields = ['uuid', 'created_at', 'updated_at']
|
||||
|
|
@ -33,7 +33,7 @@ class MovieAdmin(admin.ModelAdmin):
|
|||
|
||||
@admin.register(Episode)
|
||||
class EpisodeAdmin(admin.ModelAdmin):
|
||||
list_display = ['name', 'series', 'season_number', 'episode_number', 'duration', 'created_at']
|
||||
list_display = ['name', 'series', 'season_number', 'episode_number', 'duration_secs', 'created_at']
|
||||
list_filter = ['series', 'season_number', 'created_at']
|
||||
search_fields = ['name', 'description', 'series__name']
|
||||
readonly_fields = ['uuid', 'created_at', 'updated_at']
|
||||
|
|
|
|||
|
|
@ -77,14 +77,6 @@ class MovieViewSet(viewsets.ReadOnlyModelViewSet):
|
|||
serializer = M3UMovieRelationSerializer(relations, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
def _convert_duration_to_minutes(self, duration_secs):
|
||||
"""Convert duration from seconds to minutes"""
|
||||
if not duration_secs:
|
||||
return 0
|
||||
try:
|
||||
return int(duration_secs) // 60
|
||||
except (ValueError, TypeError):
|
||||
return 0
|
||||
|
||||
@action(detail=True, methods=['get'], url_path='provider-info')
|
||||
def provider_info(self, request, pk=None):
|
||||
|
|
@ -144,8 +136,7 @@ class MovieViewSet(viewsets.ReadOnlyModelViewSet):
|
|||
'tmdb_id': movie.tmdb_id or info.get('tmdb_id', ''),
|
||||
'imdb_id': movie.imdb_id or info.get('imdb_id', ''),
|
||||
'youtube_trailer': (movie.custom_properties or {}).get('youtube_trailer') or info.get('youtube_trailer') or info.get('trailer', ''),
|
||||
'duration': movie.duration or (int(info.get('duration_secs', 0)) // 60 if info.get('duration_secs') else None),
|
||||
'duration_secs': info.get('duration_secs', (movie.duration or 0) * 60),
|
||||
'duration_secs': movie.duration_secs or info.get('duration_secs'),
|
||||
'age': info.get('age', ''),
|
||||
'backdrop_path': (movie.custom_properties or {}).get('backdrop_path') or info.get('backdrop_path', []),
|
||||
'cover': info.get('cover_big', ''),
|
||||
|
|
@ -365,7 +356,7 @@ class SeriesViewSet(viewsets.ReadOnlyModelViewSet):
|
|||
'description': episode.description,
|
||||
'air_date': episode.air_date,
|
||||
'plot': episode.description,
|
||||
'duration': episode.duration,
|
||||
'duration_secs': episode.duration_secs,
|
||||
'rating': episode.rating,
|
||||
'tmdb_id': episode.tmdb_id,
|
||||
'imdb_id': episode.imdb_id,
|
||||
|
|
|
|||
16
apps/vod/migrations/0002_episode_custom_properties.py
Normal file
16
apps/vod/migrations/0002_episode_custom_properties.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Generated by Django A.I. on 2025-08-09
|
||||
from django.db import migrations, models
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('vod', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='episode',
|
||||
name='custom_properties',
|
||||
field=models.JSONField(blank=True, null=True, help_text='Custom properties for this episode'),
|
||||
),
|
||||
]
|
||||
31
apps/vod/migrations/0003_duration_secs.py
Normal file
31
apps/vod/migrations/0003_duration_secs.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Generated by Django A.I. on 2025-08-09
|
||||
from django.db import migrations, models
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('vod', '0002_episode_custom_properties'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='movie',
|
||||
old_name='duration',
|
||||
new_name='duration_secs',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='movie',
|
||||
name='duration_secs',
|
||||
field=models.IntegerField(blank=True, null=True, help_text='Duration in seconds'),
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='episode',
|
||||
old_name='duration',
|
||||
new_name='duration_secs',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='episode',
|
||||
name='duration_secs',
|
||||
field=models.IntegerField(blank=True, null=True, help_text='Duration in seconds'),
|
||||
),
|
||||
]
|
||||
|
|
@ -78,7 +78,7 @@ class Movie(models.Model):
|
|||
year = models.IntegerField(blank=True, null=True)
|
||||
rating = models.CharField(max_length=10, blank=True, null=True)
|
||||
genre = models.CharField(max_length=255, blank=True, null=True)
|
||||
duration = models.IntegerField(blank=True, null=True, help_text="Duration in minutes")
|
||||
duration_secs = models.IntegerField(blank=True, null=True, help_text="Duration in seconds")
|
||||
logo = models.ForeignKey(Logo, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
|
||||
# Metadata IDs for deduplication
|
||||
|
|
@ -113,7 +113,7 @@ class Episode(models.Model):
|
|||
description = models.TextField(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")
|
||||
duration_secs = models.IntegerField(blank=True, null=True, help_text="Duration in seconds")
|
||||
|
||||
# Episode specific fields
|
||||
series = models.ForeignKey(Series, on_delete=models.CASCADE, related_name='episodes')
|
||||
|
|
@ -124,6 +124,9 @@ class Episode(models.Model):
|
|||
tmdb_id = models.CharField(max_length=50, blank=True, null=True, help_text="TMDB ID for metadata", db_index=True)
|
||||
imdb_id = models.CharField(max_length=50, blank=True, null=True, help_text="IMDB ID for metadata", db_index=True)
|
||||
|
||||
# Custom properties for episode
|
||||
custom_properties = models.JSONField(blank=True, null=True, help_text="Custom properties for this episode")
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -120,26 +120,26 @@ def process_movie_basic(client, account, movie_data, category):
|
|||
# Extract trailer
|
||||
trailer = movie_data.get('trailer') or movie_data.get('youtube_trailer') or ''
|
||||
|
||||
duration_minutes = None
|
||||
duration_secs = None
|
||||
|
||||
# Try to extract duration from various possible fields
|
||||
if movie_data.get('duration_secs'):
|
||||
duration_minutes = convert_duration_to_minutes(movie_data.get('duration_secs'))
|
||||
duration_secs = int(movie_data.get('duration_secs'))
|
||||
elif movie_data.get('duration'):
|
||||
# Handle duration that might be in different formats
|
||||
duration_str = str(movie_data.get('duration'))
|
||||
if duration_str.isdigit():
|
||||
duration_minutes = int(duration_str) # Assume minutes if just a number
|
||||
duration_secs = int(duration_str) * 60 # Assume minutes if just a number
|
||||
else:
|
||||
# Try to parse time format like "01:30:00"
|
||||
try:
|
||||
time_parts = duration_str.split(':')
|
||||
if len(time_parts) == 3:
|
||||
hours, minutes, seconds = map(int, time_parts)
|
||||
duration_minutes = (hours * 60) + minutes
|
||||
duration_secs = (hours * 3600) + (minutes * 60) + seconds
|
||||
elif len(time_parts) == 2:
|
||||
minutes, seconds = map(int, time_parts)
|
||||
duration_minutes = minutes
|
||||
duration_secs = minutes * 60 + seconds
|
||||
except (ValueError, AttributeError):
|
||||
pass
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ def process_movie_basic(client, account, movie_data, category):
|
|||
'plot': description,
|
||||
'rating': rating,
|
||||
'genre': genre,
|
||||
'duration_secs': movie_data.get('duration_secs'),
|
||||
'duration_secs': duration_secs,
|
||||
'trailer': trailer,
|
||||
}
|
||||
|
||||
|
|
@ -213,35 +213,15 @@ def process_series_basic(client, account, series_data, category):
|
|||
tmdb_id = series_data.get('tmdb') or series_data.get('tmdb_id')
|
||||
imdb_id = series_data.get('imdb') or series_data.get('imdb_id')
|
||||
|
||||
# Extract additional metadata that matches the actual API response
|
||||
description = series_data.get('plot') or series_data.get('description') or series_data.get('overview') or ''
|
||||
rating = series_data.get('rating') or series_data.get('vote_average') or ''
|
||||
genre = series_data.get('genre') or ''
|
||||
|
||||
# Extract trailer
|
||||
youtube_trailer = series_data.get('trailer') or series_data.get('youtube_trailer') or ''
|
||||
|
||||
# Extract backdrop path
|
||||
backdrop_path = series_data.get('backdrop_path') or ''
|
||||
|
||||
# Build info dict with all extracted data
|
||||
info = {
|
||||
'plot': description,
|
||||
'rating': rating,
|
||||
'genre': genre,
|
||||
'youtube_trailer': youtube_trailer,
|
||||
'backdrop_path': backdrop_path,
|
||||
}
|
||||
|
||||
# Use find_or_create_series to handle duplicates properly
|
||||
logger.debug(f"Processing series: {name} ({year})")
|
||||
series = find_or_create_series(
|
||||
name=name,
|
||||
year=year,
|
||||
tmdb_id=tmdb_id,
|
||||
imdb_id=imdb_id,
|
||||
info=info
|
||||
info=series_data
|
||||
)
|
||||
|
||||
# Handle logo from basic data if available
|
||||
if series_data.get('cover'):
|
||||
logo, _ = Logo.objects.get_or_create(
|
||||
|
|
@ -362,7 +342,7 @@ def process_episode(account, series, episode_data, season_number):
|
|||
'description': description,
|
||||
'rating': rating,
|
||||
'air_date': air_date,
|
||||
'duration': convert_duration_to_minutes(info.get('duration_secs')),
|
||||
'duration_secs': info.get('duration_secs'),
|
||||
'tmdb_id': info.get('tmdb_id'),
|
||||
'imdb_id': info.get('imdb_id'),
|
||||
}
|
||||
|
|
@ -433,9 +413,9 @@ def find_or_create_movie(name, year, tmdb_id, imdb_id, info):
|
|||
movie.imdb_id = imdb_id
|
||||
updated = True
|
||||
|
||||
duration = convert_duration_to_minutes(info.get('duration_secs'))
|
||||
if duration and duration != movie.duration:
|
||||
movie.duration = duration
|
||||
duration_secs = info.get('duration_secs')
|
||||
if duration_secs and duration_secs != movie.duration_secs:
|
||||
movie.duration_secs = duration_secs
|
||||
updated = True
|
||||
|
||||
# Update custom_properties with trailer and other metadata
|
||||
|
|
@ -471,7 +451,7 @@ def find_or_create_movie(name, year, tmdb_id, imdb_id, info):
|
|||
description=info.get('plot') or info.get('description', ''),
|
||||
rating=info.get('rating', ''),
|
||||
genre=info.get('genre', ''),
|
||||
duration=convert_duration_to_minutes(info.get('duration_secs')),
|
||||
duration_secs=info.get('duration_secs'),
|
||||
custom_properties=custom_props if custom_props else None
|
||||
)
|
||||
|
||||
|
|
@ -479,7 +459,7 @@ def find_or_create_movie(name, year, tmdb_id, imdb_id, info):
|
|||
def find_or_create_series(name, year, tmdb_id, imdb_id, info):
|
||||
"""Find existing series or create new one based on metadata"""
|
||||
series = None
|
||||
|
||||
updated = False
|
||||
# Try to find by TMDB ID first
|
||||
if tmdb_id:
|
||||
series = Series.objects.filter(tmdb_id=tmdb_id).first()
|
||||
|
|
@ -496,56 +476,9 @@ def find_or_create_series(name, year, tmdb_id, imdb_id, info):
|
|||
if not series:
|
||||
series = Series.objects.filter(name=name).first()
|
||||
|
||||
# If we found an existing series, update it
|
||||
if series:
|
||||
updated = False
|
||||
if info.get('plot') and info.get('plot') != series.description:
|
||||
series.description = info.get('plot')
|
||||
updated = True
|
||||
if info.get('rating') and info.get('rating') != series.rating:
|
||||
series.rating = info.get('rating')
|
||||
updated = True
|
||||
if info.get('genre') and info.get('genre') != series.genre:
|
||||
series.genre = info.get('genre')
|
||||
updated = True
|
||||
if year and year != series.year:
|
||||
series.year = year
|
||||
updated = True
|
||||
if tmdb_id and tmdb_id != series.tmdb_id:
|
||||
series.tmdb_id = tmdb_id
|
||||
updated = True
|
||||
if imdb_id and imdb_id != series.imdb_id:
|
||||
series.imdb_id = imdb_id
|
||||
updated = True
|
||||
|
||||
# Update custom_properties with trailer and other metadata
|
||||
custom_props = series.custom_properties or {}
|
||||
custom_props_updated = False
|
||||
if info.get('trailer') and info.get('trailer') != custom_props.get('youtube_trailer'):
|
||||
custom_props['youtube_trailer'] = info.get('trailer')
|
||||
custom_props_updated = True
|
||||
if info.get('youtube_trailer') and info.get('youtube_trailer') != custom_props.get('youtube_trailer'):
|
||||
custom_props['youtube_trailer'] = info.get('youtube_trailer')
|
||||
custom_props_updated = True
|
||||
if info.get('backdrop_path') and info.get('backdrop_path') != custom_props.get('backdrop_path'):
|
||||
custom_props['backdrop_path'] = info.get('backdrop_path')
|
||||
custom_props_updated = True
|
||||
if custom_props_updated:
|
||||
series.custom_properties = custom_props
|
||||
updated = True
|
||||
|
||||
if updated:
|
||||
series.save()
|
||||
return series
|
||||
|
||||
# Create new series if not found
|
||||
custom_props = {}
|
||||
if info.get('youtube_trailer'):
|
||||
custom_props['youtube_trailer'] = info.get('youtube_trailer')
|
||||
if info.get('backdrop_path'):
|
||||
custom_props['backdrop_path'] = info.get('backdrop_path')
|
||||
|
||||
return Series.objects.create(
|
||||
# If still not found, create a new series
|
||||
if not series:
|
||||
series = Series.objects.create(
|
||||
name=name,
|
||||
year=year,
|
||||
tmdb_id=tmdb_id,
|
||||
|
|
@ -553,9 +486,72 @@ def find_or_create_series(name, year, tmdb_id, imdb_id, info):
|
|||
description=info.get('plot', ''),
|
||||
rating=info.get('rating', ''),
|
||||
genre=info.get('genre', ''),
|
||||
custom_properties=custom_props if custom_props else None
|
||||
)
|
||||
|
||||
# Update series metadata
|
||||
if info.get('plot') and info.get('plot') != series.description:
|
||||
series.description = info.get('plot')
|
||||
updated = True
|
||||
if info.get('rating') and info.get('rating') != series.rating:
|
||||
series.rating = info.get('rating')
|
||||
updated = True
|
||||
if info.get('genre') and info.get('genre') != series.genre:
|
||||
series.genre = info.get('genre')
|
||||
updated = True
|
||||
if year and year != series.year:
|
||||
series.year = year
|
||||
updated = True
|
||||
if tmdb_id and tmdb_id != series.tmdb_id:
|
||||
series.tmdb_id = tmdb_id
|
||||
updated = True
|
||||
if imdb_id and imdb_id != series.imdb_id:
|
||||
series.imdb_id = imdb_id
|
||||
updated = True
|
||||
|
||||
# Update custom_properties with trailer and other metadata
|
||||
custom_props = series.custom_properties or {}
|
||||
custom_props_updated = False
|
||||
if info.get('trailer') and info.get('trailer') != custom_props.get('youtube_trailer'):
|
||||
custom_props['youtube_trailer'] = info.get('trailer')
|
||||
custom_props_updated = True
|
||||
if info.get('youtube_trailer') and info.get('youtube_trailer') != custom_props.get('youtube_trailer'):
|
||||
custom_props['youtube_trailer'] = info.get('youtube_trailer')
|
||||
custom_props_updated = True
|
||||
if info.get('backdrop_path') and info.get('backdrop_path') != custom_props.get('backdrop_path'):
|
||||
custom_props['backdrop_path'] = info.get('backdrop_path')
|
||||
custom_props_updated = True
|
||||
if info.get('episode_run_time') and info.get('episode_run_time') != custom_props.get('episode_run_time'):
|
||||
custom_props['episode_run_time'] = info.get('episode_run_time')
|
||||
custom_props_updated = True
|
||||
if info.get('cast') and info.get('cast') != custom_props.get('cast'):
|
||||
custom_props['cast'] = info.get('cast')
|
||||
custom_props_updated = True
|
||||
if info.get('director') and info.get('director') != custom_props.get('director'):
|
||||
custom_props['director'] = info.get('director')
|
||||
custom_props_updated = True
|
||||
if (
|
||||
(info.get('release_date') and info.get('release_date') != custom_props.get('release_date')) or
|
||||
(info.get('releaseDate') and info.get('releaseDate') != custom_props.get('release_date')) or
|
||||
(info.get('releasedate') and info.get('releasedate') != custom_props.get('release_date'))
|
||||
):
|
||||
# Prefer release_date, then releaseDate, then releasedate
|
||||
release_date_val = (
|
||||
info.get('release_date') or
|
||||
info.get('releaseDate') or
|
||||
info.get('releasedate')
|
||||
)
|
||||
custom_props['release_date'] = release_date_val
|
||||
custom_props_updated = True
|
||||
if not year and custom_props.get('release_date'):
|
||||
year = extract_year(custom_props.get('release_date'))
|
||||
updated = True
|
||||
if custom_props_updated:
|
||||
series.custom_properties = custom_props
|
||||
updated = True
|
||||
if updated:
|
||||
series.save()
|
||||
return series
|
||||
|
||||
|
||||
def extract_year(date_string):
|
||||
"""Extract year from date string"""
|
||||
|
|
@ -628,14 +624,6 @@ def extract_year_from_data(data, title_key='name'):
|
|||
return None
|
||||
|
||||
|
||||
def convert_duration_to_minutes(duration_secs):
|
||||
"""Convert duration from seconds to minutes"""
|
||||
if not duration_secs:
|
||||
return None
|
||||
try:
|
||||
return int(duration_secs) // 60
|
||||
except (ValueError, TypeError):
|
||||
return None
|
||||
|
||||
@shared_task
|
||||
def cleanup_orphaned_vod_content():
|
||||
|
|
@ -727,9 +715,9 @@ def refresh_movie_advanced_data(m3u_movie_relation_id, force_refresh=False):
|
|||
movie.genre = info.get('genre')
|
||||
updated = True
|
||||
if info.get('duration_secs'):
|
||||
duration = int(info.get('duration_secs')) // 60
|
||||
if duration != movie.duration:
|
||||
movie.duration = duration
|
||||
duration_secs = int(info.get('duration_secs'))
|
||||
if duration_secs != movie.duration_secs:
|
||||
movie.duration_secs = duration_secs
|
||||
updated = True
|
||||
# Check for releasedate or release_date
|
||||
release_date_value = info.get('releasedate') or info.get('release_date')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue