diff --git a/apps/channels/migrations/0019_channel_tvc_guide_stationid.py b/apps/channels/migrations/0019_channel_tvc_guide_stationid.py
new file mode 100644
index 00000000..86f76b82
--- /dev/null
+++ b/apps/channels/migrations/0019_channel_tvc_guide_stationid.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.1.6 on 2025-05-04 00:02
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('dispatcharr_channels', '0018_channelgroupm3uaccount_custom_properties_and_more'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='channel',
+ name='tvc_guide_stationid',
+ field=models.CharField(blank=True, max_length=255, null=True),
+ ),
+ ]
diff --git a/apps/channels/models.py b/apps/channels/models.py
index f158c2d0..dc5c50fb 100644
--- a/apps/channels/models.py
+++ b/apps/channels/models.py
@@ -236,6 +236,8 @@ class Channel(models.Model):
help_text="Channel group this channel belongs to."
)
tvg_id = models.CharField(max_length=255, blank=True, null=True)
+ tvc_guide_stationid = models.CharField(max_length=255, blank=True, null=True)
+
epg_data = models.ForeignKey(
EPGData,
on_delete=models.SET_NULL,
diff --git a/apps/channels/serializers.py b/apps/channels/serializers.py
index a23e4637..ce3910a4 100644
--- a/apps/channels/serializers.py
+++ b/apps/channels/serializers.py
@@ -152,6 +152,7 @@ class ChannelSerializer(serializers.ModelSerializer):
'name',
'channel_group_id',
'tvg_id',
+ 'tvc_guide_stationid',
'epg_data_id',
'streams',
'stream_profile_id',
diff --git a/apps/output/views.py b/apps/output/views.py
index 9429d9ca..5a5335d3 100644
--- a/apps/output/views.py
+++ b/apps/output/views.py
@@ -30,12 +30,17 @@ def generate_m3u(request, profile_name=None):
tvg_logo = ""
if channel.logo:
tvg_logo = request.build_absolute_uri(reverse('api:channels:logo-cache', args=[channel.logo.id]))
+
+ # create possible gracenote id insertion
+ tvc_guide_stationid = ""
+ if len(channel.tvc_guide_stationid) > 0:
+ tvc_guide_stationid = f'tvc-guide-stationid="{channel.tvc_guide_stationid}" '
channel_number = channel.channel_number
extinf_line = (
f'#EXTINF:-1 tvg-id="{tvg_id}" tvg-name="{tvg_name}" tvg-logo="{tvg_logo}" '
- f'tvg-chno="{channel_number}" group-title="{group_title}",{channel.name}\n'
+ f'tvg-chno="{channel_number}" {tvc_guide_stationid}group-title="{group_title}",{channel.name}\n'
)
base_url = request.build_absolute_uri('/')[:-1]
diff --git a/frontend/src/api.js b/frontend/src/api.js
index 274ff1fa..b2ecf820 100644
--- a/frontend/src/api.js
+++ b/frontend/src/api.js
@@ -347,6 +347,11 @@ export default class API {
payload.tvg_id = null;
}
+ // Ensure tvc_guide_stationid is included properly (not as empty string)
+ if (payload.tvc_guide_stationid === '') {
+ payload.tvc_guide_stationid = null;
+ }
+
// Handle channel_number properly
if (payload.channel_number === '') {
payload.channel_number = null;
diff --git a/frontend/src/components/forms/Channel.jsx b/frontend/src/components/forms/Channel.jsx
index 5c913060..5c7243e9 100644
--- a/frontend/src/components/forms/Channel.jsx
+++ b/frontend/src/components/forms/Channel.jsx
@@ -98,6 +98,7 @@ const Channel = ({ channel = null, isOpen, onClose }) => {
channel_group_id: Object.keys(channelGroups)[0],
stream_profile_id: '0',
tvg_id: '',
+ tvc_guide_stationid: '',
epg_data_id: '',
logo_id: '',
},
@@ -122,6 +123,9 @@ const Channel = ({ channel = null, isOpen, onClose }) => {
// Ensure tvg_id is properly included (no empty strings)
formattedValues.tvg_id = formattedValues.tvg_id || null;
+ // Ensure tvc_guide_stationid is properly included (no empty strings)
+ formattedValues.tvc_guide_stationid = formattedValues.tvc_guide_stationid || null;
+
if (channel) {
// If there's an EPG to set, use our enhanced endpoint
if (values.epg_data_id !== (channel.epg_data_id ?? '')) {
@@ -187,6 +191,7 @@ const Channel = ({ channel = null, isOpen, onClose }) => {
? `${channel.stream_profile_id}`
: '0',
tvg_id: channel.tvg_id,
+ tvc_guide_stationid: channel.tvc_guide_stationid,
epg_data_id: channel.epg_data_id ?? '',
logo_id: `${channel.logo_id}`,
});
@@ -673,6 +678,16 @@ const Channel = ({ channel = null, isOpen, onClose }) => {
error={formik.errors.tvg_id ? formik.touched.tvg_id : ''}
size="xs"
/>
+
+