From 6a2e6963c4966b9c7e1f9753843a02fc7b41ac87 Mon Sep 17 00:00:00 2001 From: kappa118 Date: Tue, 25 Feb 2025 17:07:22 -0500 Subject: [PATCH 1/2] added tvg-id to programmes, added channel group creation when creating from stream if it doesn't already exist --- apps/channels/api_views.py | 12 +++++++++--- apps/epg/admin.py | 2 +- apps/epg/models.py | 1 + apps/epg/serializers.py | 2 +- apps/epg/tasks.py | 5 +++-- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/apps/channels/api_views.py b/apps/channels/api_views.py index cd14fa7f..c08f9807 100644 --- a/apps/channels/api_views.py +++ b/apps/channels/api_views.py @@ -22,15 +22,15 @@ class StreamViewSet(viewsets.ModelViewSet): qs = super().get_queryset() # Exclude streams from inactive M3U accounts qs = qs.exclude(m3u_account__is_active=False) - + assigned = self.request.query_params.get('assigned') if assigned is not None: qs = qs.filter(channels__id=assigned) - + unassigned = self.request.query_params.get('unassigned') if unassigned == '1': qs = qs.filter(channels__isnull=True) - + return qs # ───────────────────────────────────────────────────────── @@ -102,11 +102,17 @@ class ChannelViewSet(viewsets.ModelViewSet): return Response({"error": "Missing stream_id"}, status=status.HTTP_400_BAD_REQUEST) stream = get_object_or_404(Stream, pk=stream_id) + # Create a channel group from the stream group name if it doesn't already exist + channel_group, created = ChannelGroup.objects.get_or_create( + name=stream.group_name + ) + # Include the stream's tvg_id in the channel data channel_data = { 'channel_number': request.data.get('channel_number', 0), 'channel_name': request.data.get('channel_name', f"Channel from {stream.name}"), 'tvg_id': stream.tvg_id, # Inherit tvg-id from the stream + 'channel_group_id': channel_group.id, } serializer = self.get_serializer(data=channel_data) serializer.is_valid(raise_exception=True) diff --git a/apps/epg/admin.py b/apps/epg/admin.py index 69738bf4..49fcd734 100644 --- a/apps/epg/admin.py +++ b/apps/epg/admin.py @@ -10,7 +10,7 @@ class EPGSourceAdmin(admin.ModelAdmin): @admin.register(ProgramData) class ProgramAdmin(admin.ModelAdmin): list_display = ['title', 'get_channel_tvg_id', 'start_time', 'end_time'] - list_filter = ['epg__channel'] # updated here + list_filter = ['epg__channel', 'tvg_id'] # updated here search_fields = ['title', 'epg__channel__channel_name'] # updated here def get_channel_tvg_id(self, obj): diff --git a/apps/epg/models.py b/apps/epg/models.py index 6672ce0d..4a81baee 100644 --- a/apps/epg/models.py +++ b/apps/epg/models.py @@ -35,6 +35,7 @@ class ProgramData(models.Model): title = models.CharField(max_length=255) sub_title = models.CharField(max_length=255, blank=True, null=True) description = models.TextField(blank=True, null=True) + tvg_id = models.TextField(max_length=255) def __str__(self): return f"{self.title} ({self.start_time} - {self.end_time})" diff --git a/apps/epg/serializers.py b/apps/epg/serializers.py index b0c5b9df..4812a9b0 100644 --- a/apps/epg/serializers.py +++ b/apps/epg/serializers.py @@ -10,7 +10,7 @@ class EPGSourceSerializer(serializers.ModelSerializer): class ProgramDataSerializer(serializers.ModelSerializer): class Meta: model = ProgramData - fields = ['id', 'start_time', 'end_time', 'title', 'sub_title', 'description'] + fields = ['id', 'start_time', 'end_time', 'title', 'sub_title', 'description', 'tvg_id'] class EPGDataSerializer(serializers.ModelSerializer): programs = ProgramDataSerializer(many=True, read_only=True) diff --git a/apps/epg/tasks.py b/apps/epg/tasks.py index 6b6dc4d3..7bcc159e 100644 --- a/apps/epg/tasks.py +++ b/apps/epg/tasks.py @@ -48,7 +48,7 @@ def fetch_xmltv(source): 'title': title, 'description': desc, }) - + # Process each channel group for tvg_id, programmes in programmes_by_channel.items(): try: @@ -66,7 +66,7 @@ def fetch_xmltv(source): if not created and epg_data.channel_name != channel.channel_name: epg_data.channel_name = channel.channel_name epg_data.save(update_fields=['channel_name']) - + logger.info(f"Processing {len(programmes)} programme(s) for channel '{channel.channel_name}'.") # For each programme, update or create a ProgramData record with transaction.atomic(): @@ -75,6 +75,7 @@ def fetch_xmltv(source): epg=epg_data, start_time=prog['start_time'], title=prog['title'], + tvg_id=tvg_id, defaults={ 'end_time': prog['end_time'], 'description': prog['description'], From 849bf2f73be5827c63121340f4bfa62c114a8a8d Mon Sep 17 00:00:00 2001 From: kappa118 Date: Wed, 26 Feb 2025 10:23:06 -0500 Subject: [PATCH 2/2] fixed tvg_id logic --- apps/channels/serializers.py | 14 ++++++++++++++ apps/epg/models.py | 2 +- apps/epg/tasks.py | 5 +++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/apps/channels/serializers.py b/apps/channels/serializers.py index 5494196d..60516f74 100644 --- a/apps/channels/serializers.py +++ b/apps/channels/serializers.py @@ -12,6 +12,7 @@ class StreamSerializer(serializers.ModelSerializer): allow_null=True, required=False ) + class Meta: model = Stream fields = [ @@ -29,6 +30,19 @@ class StreamSerializer(serializers.ModelSerializer): 'stream_profile_id', ] + def get_fields(self): + fields = super().get_fields() + + # Unable to edit specific properties if this stream was created from an M3U account + if self.instance and getattr(self.instance, 'm3u_account', None): + fields['id'].read_only = True + fields['name'].read_only = True + fields['url'].read_only = True + fields['m3u_account'].read_only = True + fields['tvg_id'].read_only = True + fields['group_name'].read_only = True + + return fields # # Channel Group diff --git a/apps/epg/models.py b/apps/epg/models.py index 4a81baee..c660824b 100644 --- a/apps/epg/models.py +++ b/apps/epg/models.py @@ -35,7 +35,7 @@ class ProgramData(models.Model): title = models.CharField(max_length=255) sub_title = models.CharField(max_length=255, blank=True, null=True) description = models.TextField(blank=True, null=True) - tvg_id = models.TextField(max_length=255) + tvg_id = models.TextField(max_length=255, null=True) def __str__(self): return f"{self.title} ({self.start_time} - {self.end_time})" diff --git a/apps/epg/tasks.py b/apps/epg/tasks.py index 7bcc159e..adcad616 100644 --- a/apps/epg/tasks.py +++ b/apps/epg/tasks.py @@ -47,6 +47,7 @@ def fetch_xmltv(source): 'end_time': stop_time, 'title': title, 'description': desc, + 'tvg_id': channel_tvg_id, }) # Process each channel group @@ -75,11 +76,11 @@ def fetch_xmltv(source): epg=epg_data, start_time=prog['start_time'], title=prog['title'], - tvg_id=tvg_id, defaults={ 'end_time': prog['end_time'], 'description': prog['description'], - 'sub_title': '' + 'sub_title': '', + 'tvg_id': tvg_id, } ) if created: