diff --git a/CHANGELOG.md b/CHANGELOG.md index 985aab37..7f273a20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Fixed VOD refresh failures caused by orphaned logo references: Added validation to detect and clear logo foreign key references when the logo no longer exists in the database, preventing "VODLogo matching query does not exist" errors. Also improved logo assignment logic to properly handle cases where logo URLs exist but logo creation fails, ensuring VOD content updates successfully even when logos are deleted or unavailable. +- Fixed VOD refresh failures when logos are deleted: Changed logo comparisons to use `logo_id` (raw FK integer) instead of `logo` (related object) to avoid Django's lazy loading, which triggers a database fetch that fails if the referenced logo no longer exists. Also improved orphaned logo detection to properly clear stale references when logo URLs exist but logos are missing from the database. - Fixed channel profile filtering to properly restrict content based on assigned channel profiles for all non-admin users (user_level < 10) instead of only streamers (user_level == 0). This corrects the XtreamCodes API endpoints (`get_live_categories` and `get_live_streams`) along with M3U and EPG generation, ensuring standard users (level 1) are properly restricted by their assigned channel profiles. Previously, "Standard" users with channel profiles assigned would see all channels instead of only those in their assigned profiles. - Fixed NumPy baseline detection in Docker entrypoint. Now calls `numpy.show_config()` directly with case-insensitive grep instead of incorrectly wrapping the output. - Fixed SettingsUtils frontend tests for new grouped settings architecture. Updated test suite to properly verify grouped JSON settings (stream_settings, dvr_settings, etc.) instead of individual CharField settings, including tests for type conversions, array-to-CSV transformations, and special handling of proxy_settings and network_access. diff --git a/apps/vod/tasks.py b/apps/vod/tasks.py index b0c66434..c24023d6 100644 --- a/apps/vod/tasks.py +++ b/apps/vod/tasks.py @@ -73,7 +73,9 @@ def refresh_vod_content(account_id): return f"Batch VOD refresh completed for account {account.name} in {duration:.2f} seconds" except Exception as e: + import traceback logger.error(f"Error refreshing VOD for account {account_id}: {str(e)}") + logger.error(f"Full traceback:\n{traceback.format_exc()}") # Send error notification send_m3u_update(account_id, "vod_refresh", 100, status="error", @@ -558,16 +560,16 @@ def process_movie_batch(account, batch, categories, relations, scan_start_time=N if logo_url and len(logo_url) <= 500: if logo_url in existing_logos: new_logo = existing_logos[logo_url] - if movie.logo != new_logo: + if movie.logo_id != new_logo.id: movie._logo_to_update = new_logo logo_updated = True - elif movie.logo: + elif movie.logo_id: # Logo URL exists but logo creation failed or logo not found # Clear the orphaned logo reference logger.warning(f"Logo URL provided but logo not found in database for movie '{movie.name}', clearing logo reference") movie._logo_to_update = None logo_updated = True - elif (not logo_url or len(logo_url) > 500) and movie.logo: + elif (not logo_url or len(logo_url) > 500) and movie.logo_id: # Clear logo if no logo URL provided or URL is too long movie._logo_to_update = None logo_updated = True @@ -669,8 +671,6 @@ def process_movie_batch(account, batch, categories, relations, scan_start_time=N for movie in movies_to_update: if hasattr(movie, '_logo_to_update'): movie.logo = movie._logo_to_update - # Validate logo reference exists before saving - validate_logo_reference(movie, "Movie") movie.save(update_fields=['logo']) # Update relations to reference the correct movie objects (with PKs) @@ -917,16 +917,16 @@ def process_series_batch(account, batch, categories, relations, scan_start_time= if logo_url and len(logo_url) <= 500: if logo_url in existing_logos: new_logo = existing_logos[logo_url] - if series.logo != new_logo: + if series.logo_id != new_logo.id: series._logo_to_update = new_logo logo_updated = True - elif series.logo: + elif series.logo_id: # Logo URL exists but logo creation failed or logo not found # Clear the orphaned logo reference logger.warning(f"Logo URL provided but logo not found in database for series '{series.name}', clearing logo reference") series._logo_to_update = None logo_updated = True - elif (not logo_url or len(logo_url) > 500) and series.logo: + elif (not logo_url or len(logo_url) > 500) and series.logo_id: # Clear logo if no logo URL provided or URL is too long series._logo_to_update = None logo_updated = True @@ -1028,8 +1028,6 @@ def process_series_batch(account, batch, categories, relations, scan_start_time= for series in series_to_update: if hasattr(series, '_logo_to_update'): series.logo = series._logo_to_update - # Validate logo reference exists before saving - validate_logo_reference(series, "Series") series.save(update_fields=['logo']) # Update relations to reference the correct series objects (with PKs) @@ -2194,33 +2192,3 @@ def refresh_movie_advanced_data(m3u_movie_relation_id, force_refresh=False): except Exception as e: logger.error(f"Error refreshing advanced movie data for relation {m3u_movie_relation_id}: {str(e)}") return f"Error: {str(e)}" - - -def validate_logo_reference(obj, obj_type="object"): - """ - Validate that a VOD logo reference exists in the database. - If not, set it to None to prevent foreign key constraint violations. - - Args: - obj: Object with a logo attribute - obj_type: String description of the object type for logging - - Returns: - bool: True if logo was valid or None, False if logo was invalid and cleared - """ - if not hasattr(obj, 'logo') or not obj.logo: - return True - - if not obj.logo.pk: - # Logo doesn't have a primary key, so it's not saved - obj.logo = None - return False - - try: - # Verify the logo exists in the database - VODLogo.objects.get(pk=obj.logo.pk) - return True - except VODLogo.DoesNotExist: - logger.warning(f"VOD Logo with ID {obj.logo.pk} does not exist in database for {obj_type} '{getattr(obj, 'name', 'Unknown')}', setting to None") - obj.logo = None - return False