diff --git a/CHANGELOG.md b/CHANGELOG.md index d5532173..b6ff642d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - VOD client stop button in Stats page: Users can now disconnect individual VOD clients from the Stats view, similar to the existing channel client disconnect functionality. - Automated configuration backup/restore system with scheduled backups, retention policies, and async task processing - Thanks [@stlalpha](https://github.com/stlalpha) (Closes #153) +- Stream group as available hash option: Users can now select 'Group' as a hash key option in Settings → Stream Settings → M3U Hash Key, allowing streams to be differentiated by their group membership in addition to name, URL, TVG-ID, and M3U ID ### Changed diff --git a/apps/channels/models.py b/apps/channels/models.py index 3dfb392b..88df3661 100644 --- a/apps/channels/models.py +++ b/apps/channels/models.py @@ -119,11 +119,11 @@ class Stream(models.Model): return self.name or self.url or f"Stream ID {self.id}" @classmethod - def generate_hash_key(cls, name, url, tvg_id, keys=None, m3u_id=None): + def generate_hash_key(cls, name, url, tvg_id, keys=None, m3u_id=None, group=None): if keys is None: keys = CoreSettings.get_m3u_hash_key().split(",") - stream_parts = {"name": name, "url": url, "tvg_id": tvg_id, "m3u_id": m3u_id} + stream_parts = {"name": name, "url": url, "tvg_id": tvg_id, "m3u_id": m3u_id, "group": group} hash_parts = {key: stream_parts[key] for key in keys if key in stream_parts} diff --git a/apps/m3u/tasks.py b/apps/m3u/tasks.py index cb82402e..87759ab9 100644 --- a/apps/m3u/tasks.py +++ b/apps/m3u/tasks.py @@ -792,7 +792,7 @@ def process_xc_category_direct(account_id, batch, groups, hash_keys): group_title = group_name stream_hash = Stream.generate_hash_key( - name, url, tvg_id, hash_keys, m3u_id=account_id + name, url, tvg_id, hash_keys, m3u_id=account_id, group=group_title ) stream_props = { "name": name, @@ -966,7 +966,7 @@ def process_m3u_batch_direct(account_id, batch, groups, hash_keys): ) continue - stream_hash = Stream.generate_hash_key(name, url, tvg_id, hash_keys, m3u_id=account_id) + stream_hash = Stream.generate_hash_key(name, url, tvg_id, hash_keys, m3u_id=account_id, group=group_title) stream_props = { "name": name, "url": url, diff --git a/core/tasks.py b/core/tasks.py index f757613b..207e7c5e 100644 --- a/core/tasks.py +++ b/core/tasks.py @@ -513,7 +513,8 @@ def rehash_streams(keys): for obj in batch: # Generate new hash - new_hash = Stream.generate_hash_key(obj.name, obj.url, obj.tvg_id, keys, m3u_id=obj.m3u_account_id) + group_name = obj.channel_group.name if obj.channel_group else None + new_hash = Stream.generate_hash_key(obj.name, obj.url, obj.tvg_id, keys, m3u_id=obj.m3u_account_id, group=group_name) # Check if this hash already exists in our tracking dict or in database if new_hash in hash_keys: diff --git a/frontend/src/pages/Settings.jsx b/frontend/src/pages/Settings.jsx index 74de842e..46ad4710 100644 --- a/frontend/src/pages/Settings.jsx +++ b/frontend/src/pages/Settings.jsx @@ -1056,6 +1056,10 @@ const SettingsPage = () => { value: 'm3u_id', label: 'M3U ID', }, + { + value: 'group', + label: 'Group', + }, ]} {...form.getInputProps('m3u-hash-key')} key={form.key('m3u-hash-key')}