From 620d65d1de0d84c0fcbc029bdd0b80766fd36eeb Mon Sep 17 00:00:00 2001 From: SergeantPanda Date: Sun, 18 Jan 2026 15:52:50 -0600 Subject: [PATCH] Bug Fix: Fixed XtreamCodes API crash when channels have NULL channel_group: The `player_api.php` endpoint (`xc_get_live_streams`) now gracefully handles channels without an assigned channel_group by dynamically looking up and assigning them to "Default Group" instead of crashing with AttributeError. Additionally, the Channel serializer now auto-assigns new channels to "Default Group" when `channel_group_id` is omitted during creation, preventing future NULL channel_group issues. --- CHANGELOG.md | 1 + apps/channels/serializers.py | 7 +++++++ apps/output/views.py | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ff0bf14..26589be7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed XtreamCodes API crash when channels have NULL channel_group: The `player_api.php` endpoint (`xc_get_live_streams`) now gracefully handles channels without an assigned channel_group by dynamically looking up and assigning them to "Default Group" instead of crashing with AttributeError. Additionally, the Channel serializer now auto-assigns new channels to "Default Group" when `channel_group_id` is omitted during creation, preventing future NULL channel_group issues. - Fixed streams table column header overflow: Implemented fixed-height column headers (30px max-height) with pill-style filter display showing first selection plus count (e.g., "Sport +3"). Prevents header expansion when multiple filters are selected, maintaining compact table layout. (Fixes #613) - Fixed VOD logo cleanup button count: The "Cleanup Unused" button now displays the total count of all unused logos across all pages instead of only counting unused logos on the current page. - 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. diff --git a/apps/channels/serializers.py b/apps/channels/serializers.py index 42853ca1..53c07292 100644 --- a/apps/channels/serializers.py +++ b/apps/channels/serializers.py @@ -332,6 +332,13 @@ class ChannelSerializer(serializers.ModelSerializer): "channel_number", Channel.get_next_available_channel_number() ) validated_data["channel_number"] = channel_number + + # Auto-assign Default Group if no channel_group is specified + if "channel_group" not in validated_data or validated_data.get("channel_group") is None: + from apps.channels.models import ChannelGroup + default_group, _ = ChannelGroup.objects.get_or_create(name="Default Group") + validated_data["channel_group"] = default_group + channel = Channel.objects.create(**validated_data) # Add streams in the specified order diff --git a/apps/output/views.py b/apps/output/views.py index a34ff45f..ba75246a 100644 --- a/apps/output/views.py +++ b/apps/output/views.py @@ -2210,8 +2210,8 @@ def xc_get_live_streams(request, user, category_id=None): "epg_channel_id": str(channel_num_int), "added": int(channel.created_at.timestamp()), "is_adult": int(channel.is_adult), - "category_id": str(channel.channel_group.id), - "category_ids": [channel.channel_group.id], + "category_id": str(channel.channel_group.id if channel.channel_group else ChannelGroup.objects.get_or_create(name="Default Group")[0].id), + "category_ids": [channel.channel_group.id if channel.channel_group else ChannelGroup.objects.get_or_create(name="Default Group")[0].id], "custom_sid": None, "tv_archive": 0, "direct_source": "",