Commit graph

86 commits

Author SHA1 Message Date
SergeantPanda
46695588f7 fix(m3u): enhance custom properties handling and DB connection management
- Implemented `ensure_custom_properties_dict()` to normalize custom properties across various models and serializers, addressing issues with legacy JSON-encoded strings.
- Updated M3U account and channel group models to ensure custom properties are consistently stored as dictionaries during save operations.
- Enhanced Celery task management by ensuring old DB connections are closed before and after tasks, improving reliability and preventing errors during account refresh operations. (Fixes #1338)
2026-06-18 14:59:09 -05:00
SergeantPanda
67239d921d fix(proxy): enhance channel teardown and client management
- Improved channel teardown process to prevent lingering upstream connections and ensure proper resource cleanup.
- Enhanced client management by implementing checks for ghost clients and ensuring accurate client disconnection handling.
- Updated logging to provide clearer insights during channel initialization and teardown, including handling of unavailable channels.
- Refined stream manager behavior to manage ownership transitions more effectively and prevent blocking during shutdown.
2026-06-14 21:41:50 -05:00
SergeantPanda
4fc12bca4a refactor(m3u, channels, proxy): enhance stream assignment logic and error handling
- Improved logging in the Stream model for better debugging of profile evaluations.
- Introduced a new method `_stream_assignment_is_reusable` in the Channel model to determine if existing stream assignments can be reused, enhancing efficiency.
- Updated the release logic in `release_profile_slot` to utilize stored credential keys, reducing unnecessary database lookups.
- Simplified error handling in the `get_stream_info_for_switch` function to ensure proper stream release on exceptions.
- Enhanced tests for connection pool management and error handling in the ServerGroupsTable component to improve reliability and user feedback.
2026-06-09 17:59:12 -05:00
SergeantPanda
bc046b3c92 refactor(m3u, channels): streamline stream assignment and server group management
- Renamed `_clear_stream_assignment_keys` to `_release_stale_stream_assignment` for clarity and updated its logic to release pool counters.
- Introduced new functions for managing credential slots during profile switches, enhancing the handling of shared connection limits across server groups.
- Removed the `max_streams` field from the `ServerGroup` model and updated related components to reflect this change, simplifying the server group management.
- Updated frontend components to integrate server group management, allowing for dynamic creation and editing of server groups.
- Enhanced error handling in stream URL generation to provide more informative feedback on connection issues.
- Added tests for stale assignment release and credential management during profile switches.
2026-06-09 13:40:16 -05:00
SergeantPanda
0f0e855507 Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into pr/Goldenfreddy0703/1254 2026-06-09 11:16:39 -05:00
Goldenfreddy0703
abdf2d7864 Fix credential release on deleted profile and round 3 review items.
Store credential Redis keys at reserve so release works when the profile row is deleted. Return reserve failure reasons to avoid fingerprint DB queries on logging paths. Document unlimited profile bypass in pool logic and Server Group UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 19:51:20 -04:00
SergeantPanda
b63650799a docs: Restored todo as this did not resolve it. Cleaned up overly verbose comment. 2026-05-29 17:07:55 -05:00
Goldenfreddy0703
6e07dce3f1 Fix maintainer review items without breaking multi-login rotation.
Cap credential-scoped group counters at profile.max_streams (not group.max_streams),
skip credential counters when fingerprint resolution fails, and always swap profile
counters on update_stream_profile. Restore per-profile-only selection for VOD/live
switches so a second stream can use a different login without invalid HTTP errors.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-29 17:07:52 -04:00
nemesbak
5eb118478b fix(channels): honor stream profile override in Channel.get_stream_profile()
Channel.get_stream_profile() read self.stream_profile directly, bypassing
the override system. The override-aware property effective_stream_profile_obj
already existed and called _resolve_effective_fk('stream_profile') which
correctly picks override.stream_profile when set, but nothing in the
streaming path called it.

As a result, a per-channel 'Stream Profile' override saved through the UI
was visible in the channel edit form (yellow pencil indicator appeared) but
silently ignored at stream time — Dispatcharr always used the global default
profile regardless of what was configured per-channel.

Fix: call effective_stream_profile_obj in get_stream_profile() so that all
callers (live proxy url_utils, input manager, views) automatically pick up
channel-level overrides without any further changes.

Fixes #1268

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 13:39:05 +02:00
Goldenfreddy0703
bb9b95b4a4 Refactor connection pools to manual ServerGroups with profile rotation.
Drop auto-fingerprint migration and restore per-profile selection for live/VOD.
Enforce shared limits on reserve using login-scoped group counters, and add
Server Groups UI for manual account assignment per maintainer feedback (#1137).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-23 20:18:45 -04:00
Goldenfreddy0703
d89f634213 Enforce shared credential connection pools across M3U accounts (#1137)
Group M3U/XC accounts and profiles that share the same provider login into auto-assigned ServerGroups keyed by credential fingerprint. Enforce combined Redis limits for live TV and VOD via apps/m3u/connection_pool.py.

- Per-profile fingerprinting (XC transforms and STD stream URLs)

- VOD profile selection tries alternates when default credential pool is full (fixes live then VOD failure)

- Stats UI shows provider login from active stream URL

- Tests: apps/m3u/tests/test_connection_pool.py (11 tests, all passing)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-20 03:30:48 -04:00
SergeantPanda
dc649ffd88 Enhancement: Initial fmp4 support and major ts_proxy refactor 2026-05-08 17:46:47 -05:00
None
b2b108bfe5 rename Channel.user_hidden to Channel.hidden_from_output
The previous name suggested "hidden from a specific user account" rather than "hidden from downstream client output", which was the actual
behavior. The new name is unambiguous and matches the help_text language ("Exclude this channel from downstream client output").

Mechanical rename across the migration, model, serializer, signals, sync logic, output endpoints, frontend forms / tables / utils, tests, and CHANGELOG. 77 occurrences across 20 files.

No behavior change.
2026-05-01 19:44:16 -05:00
None
6fed444e43 feat: Auto-sync overhaul (FR #1196)
Per-field channel overrides for auto-synced channels, hide-from-output flag, range-bounded auto-numbering with re-pack, multi-stream channel safety, multi-provider shared-range merging, and an across-the-board move from per-row sync writes to bulk operations.

Migrations:

apps/channels:

0036_channeloverride_and_user_hidden,
0037_backfill_auto_created_by_null,
0038_channelgroupm3uaccount_auto_sync_channel_end,
0039_channel_channel_number_nullable

apps/m3u:
0020_m3uaccount_auto_cleanup_unused_channels

See CHANGELOG.md for the full commit log
2026-05-01 14:05:06 -05:00
SergeantPanda
db6755a009 Enhancement: Add database index on Stream.name to improve query performance and reduce disk spill during sorting (Fixes #1209) 2026-04-30 14:28:26 -05:00
SergeantPanda
69e0cba86e Bug Fix: EPG channel name vlaue too long for type character varying(255) (Fixes #1134)
Some checks are pending
CI Pipeline / prepare (push) Waiting to run
CI Pipeline / docker (amd64, ubuntu-24.04) (push) Blocked by required conditions
CI Pipeline / docker (arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
CI Pipeline / create-manifest (push) Blocked by required conditions
Build and Push Multi-Arch Docker Image / build-and-push (push) Waiting to run
2026-04-21 09:23:35 -05:00
dekzter
90a600b48f merged in dev 2026-03-26 12:17:43 -04:00
SergeantPanda
c44a3ad5f9 Bug Fix: Stream.last_seen and ChannelGroupM3UAccount.last_seen model defaults now use django.utils.timezone.now instead of datetime.datetime.now, eliminating spurious RuntimeWarning: DateTimeField received a naive datetime warnings emitted during test database creation and on new record creation when USE_TZ=True. 2026-03-15 16:59:51 -05:00
dekzter
f69a462253 merged in dev 2026-03-13 08:22:44 -04:00
dekzter
6f4665e6eb merged in dev 2026-02-26 08:20:20 -05:00
None
c69718b559 Fix: Make release_stream() idempotent to prevent double-DECR on rapid channel switching
Multiple code paths call release_stream() during channel shutdown (stream generator cleanup, _clean_redis_keys, ChannelService.stop_channel), causing
the profile_connections counter to be decremented multiple times for the same stream. The metadata hash fallback persisted longer than the primary keys, allowing subsequent calls to find stale stream_id/m3u_profile and DECR again.

Changes:
- Clear STREAM_ID and M3U_PROFILE metadata fields after decrementing in both the primary and fallback paths, making release_stream() safe to call multiple times
- Add metadata fallback when stream_profile:{id} key is missing but channel_stream:{id} exists, preventing a counter leak in that edge case
- Replace redundant get_stream() call in views.py with direct Redis reads to avoid side-effect INCR from a method that can allocate connection slots
2026-02-17 21:18:20 -06:00
None
837ba84768 fix(ts-proxy): Restore Stream.get_stream() with atomic slot reservation
Stream.get_stream() was incorrectly removed as dead code in commit
33f68a98. It is actually called get_stream_object()
in views.py when a stream hash (not channel UUID) is used, such as
during stream preview. The variable is named channel but holds a
Stream instance, which masked the dependency during analysis.

Restored with the INCR-first-then-check pattern applied, fixing the
same TOCTOU vulnerability the original method had.
2026-02-11 23:57:10 -06:00
None
6826e94921 Add boolean return to Stream.release_stream()
Stream.release_stream() now returns True on success and False when no
profile info could be found in stream_profile:{stream_id}. This allows
callers to detect and handle failed releases.

Enhanced logging to include stream ID for better traceability.

Based on PR #838 by patchy8736
2026-02-11 19:27:45 -06:00
None
56719d93fe Add boolean return and metadata fallback to Channel.release_stream()
Channel.release_stream() now returns True on success and False when no
stream/profile info could be found for cleanup. This allows callers to
detect and handle failed releases.

When the primary Redis keys (channel_stream/stream_profile) are already cleaned up by the proxy, the method falls back to the channel metadata hash (ts_proxy:channel:{uuid}:metadata) to recover stream_id and profile_id for proper connection counter cleanup.

Uses str(self.uuid) for metadata key lookup - fixes a bug in PR #838
which used self.id (integer PK), but metadata is keyed by UUID.

Enhanced logging now includes channel UUID for better traceability.

Based on PR #838 by patchy8736
2026-02-11 19:16:01 -06:00
None
33f68a9808 Remove unused Stream.get_stream() with TOCTOU vulnerability
Remove the Stream.get_stream() method which had the same TOCTOU race condition as Channel.get_stream()

All stream acquisition goes through
Channel.get_stream(), making this dead code. Removing it eliminates
a potential source of connection capacity leaks

Based on PR #838 by patchy8736
2026-02-11 19:11:28 -06:00
None
5a4b51b60a Fix TOCTOU race condition in Channel.get_stream() with atomic slot reservation
Add _check_and_reserve_profile_slot() method that uses an INCR-first-then-check pattern to atomically reserve connection slots. This eliminates the TOCTOU race condition where separate GET > check > INCR operations allowed concurrent requests to both pass the capacity check, exceeding max_streams.

For profiles with max_streams=0 (unlimited), INCR is skipped entirely. If over capacity, the increment is rolled back with DECR.

Based on PR #838 by patchy8736, adapted from Lua script to native Redis commands for consistency with project style and easier debugging.
2026-02-11 18:08:24 -06:00
None
15d67c7f65 Atomize profile counter swap in update_stream_profile to prevent counter drift
DECR/SET/INCR during stream profile switches are now executed in a Redis
pipeline, preventing partial updates if an exception occurs mid-operation
2026-02-10 18:30:43 -06:00
SergeantPanda
9ffd595c96 Enhancement: Added stream_id (provider stream identifier) and stream_chno (provider channel number) fields to Stream model. For XC accounts, the stream hash now uses the stable stream_id instead of the URL when hashing, ensuring XC streams maintain their identity and channel associations even when account credentials or server URLs change. Supports both XC num and M3U tvg-chno/channel-number attributes. 2026-01-31 17:47:46 -06:00
dekzter
dba70b3c58 outstanding commits, may revisit later 2026-01-27 15:23:07 -05:00
SergeantPanda
d33d047a94 Enhancement: - Mature content filtering support:
- Added `is_adult` boolean field to both Stream and Channel models with database indexing for efficient filtering and sorting
  - Automatically populated during M3U/XC refresh operations by extracting `is_adult` value from provider data
  - Type-safe conversion supporting both integer (0/1) and string ("0"/"1") formats from different providers
  - UI controls in channel edit form (Switch with tooltip) and bulk edit form (Select dropdown) for easy management
  - XtreamCodes API support with proper integer formatting (0/1) in live stream responses
  - Automatic propagation from streams to channels during both single and bulk channel creation operations
  - Included in serializers for full API support
  - User-level content filtering: Non-admin users can opt to hide mature content channels across all interfaces (web UI, M3U playlists, EPG data, XtreamCodes API) via "Hide Mature Content" toggle in user settings (stored in custom_properties, admin users always see all content)
2026-01-17 15:00:28 -06:00
SergeantPanda
a84553d15c Enhancement: Stale status indicators for streams and groups: Added is_stale field to both Stream and ChannelGroupM3UAccount models to track items in their grace period (seen in previous refresh but not current). 2026-01-09 13:53:01 -06:00
SergeantPanda
cc9d38212e Enhancement: Groups now follow the same stale retention logic as streams, using the account's stale_stream_days setting. Groups that temporarily disappear from an M3U source are retained for the configured retention period instead of being immediately deleted, preserving user settings and preventing data loss when providers temporarily remove/re-add groups. (Closes #809) 2026-01-09 12:03:55 -06:00
SergeantPanda
73956924f5 Enhancement: 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 2025-12-18 15:26:08 -06:00
SergeantPanda
5c27bd2c10 Enhancement: Increase maximum URL length for Stream model to 4096 characters (from 2000) and add validation for URL length in processing tasks.
Fixes #585
2025-10-28 15:02:36 -05:00
SergeantPanda
0d987aae99 Enhancement: If a stream profile is set for a custom stream, when previewing the stream Dispatcharr will now use the assigned stream profile. Fixes #186 2025-10-18 16:24:47 -05:00
SergeantPanda
e01338f055 Enhancement: Properly track channel creation time and channel update times in the database. XC Get Live streams will now use this for the added field. 2025-10-06 18:07:51 -05:00
OkinawaBoss
8db9689999
Merge branch 'DVR-Update' into dev 2025-10-06 06:25:40 -07:00
SergeantPanda
a3e4f23891 Enhancement: Add m3u_id parameter to generate_hash_key and update related calls 2025-10-02 09:14:22 -05:00
Dispatcharr
eee4ab0725 Update for recurring rules 2025-09-19 16:21:28 -05:00
Dispatcharr
424a450654 DVR Features and bug fixes
Added ability to use custom comskip.ini
Added series recording without reliance on EPG
Fixed comskip bug
Fixed timezone mismatch when scheduling DVR recordings

No migrations completed yet
2025-09-18 10:23:16 -05:00
SergeantPanda
ed0b291237 Skip disabled m3u accounts when choosing streams during playback.
Closes #402
2025-09-15 17:36:31 -05:00
SergeantPanda
6f6c28ca7c Convert custom_properties to jsonb in the backend. 2025-09-02 09:41:51 -05:00
dekzter
a19bd14a84 added vod category filtering 2025-08-22 16:59:00 -04:00
SergeantPanda
6180b4ffef Save stream stats to database. 2025-07-28 21:40:29 -05:00
SergeantPanda
b91a2286e4 Add auto-created tracking to Channel model and related serializers
- Introduced `auto_created` and `auto_created_by` fields in the Channel model to track channels created via M3U auto channel sync.
- Updated ChannelSerializer to include these new fields and added a method to retrieve the name of the M3U account that created the channel.
- Modified sync_auto_channels task to set these fields when creating channels and to filter existing channels accordingly.
2025-07-13 16:32:52 -05:00
SergeantPanda
ea81cfb1af Add auto channel sync settings to ChannelGroupM3UAccount and update related components
- Introduced `auto_channel_sync` and `auto_sync_channel_start` fields in the ChannelGroupM3UAccount model.
- Added API endpoint to update M3U group settings.
- Updated M3UGroupFilter component to manage auto sync settings.
- Enhanced M3URefreshNotification and M3U components for better user guidance.
- Created a Celery task for automatic channel synchronization after M3U refresh.
2025-07-13 15:59:25 -05:00
dekzter
74d58515d0 user management, user levels, user level channel access 2025-05-18 11:19:34 -04:00
MooseOnTheLoose
88a7312397
Merge branch 'dev' into main 2025-05-08 19:16:49 -05:00
MooseyOnTheLoosey
5bae7997c0 Removing more debug 2025-05-08 09:50:19 -05:00
MooseyOnTheLoosey
88866cc905 Updated channel numbers from integer to float 2025-05-08 09:12:10 -05:00