Refactor content relation retrieval to use a single DB query for active relations, improving efficiency. Update return values to include candidates for failover handling.
Implemented VOD failover logic to iterate over all active M3U relations, selecting the first account with spare capacity instead of relying on a single highest-priority relation. This change enhances reliability by allowing for provider failover in case of account saturation.
- Added calls to `close_old_connections()` in `stream_vod()` and `build_vod_stats_data()` to prevent connection leaks during long-lived streaming responses and background stats refreshes.
- Improved connection handling in various components to ensure proper resource cleanup and prevent blocking issues.
- Introduced `dispatcharr_user_agent`, `dispatcharr_dvr_user_agent`, and `dispatcharr_http_headers` functions in `core.utils` to standardize User-Agent strings and HTTP headers for outbound requests.
- Updated various components, including `LogoViewSet`, `EPGSourceViewSet`, and VOD proxy views, to utilize the new header functions, ensuring consistent User-Agent usage across the application.
- Enhanced the handling of Schedules Direct API requests by including proper User-Agent headers, addressing previous API compliance issues.
- Eliminated redundant extraction of provider usernames from stream URLs in both ChannelStatus and VOD stats data functions, simplifying the codebase.
- Updated frontend components to reflect the removal of provider username display, streamlining the UI.
- Enhanced overall readability and maintainability of the code by reducing complexity in handling stream URLs.
- 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.
Issue: When `process_movie_batch` / `process_series_batch`
(apps/vod/tasks.py) creates duplicate vod_movie / vod_episode records
during a refresh, existing M3U*Relation rows get repointed to the new
records. The old UUIDs that external players (Emby / Jellyfin /
ChannelsDVR) cached in `.strm` URLs are left orphaned, and the proxy
404s on every subsequent request — even though the same request
already carries a stable `stream_id` that uniquely identifies a live
relation.
This patch makes `_get_content_and_relation` use a soft UUID lookup
and, if it misses, fall back to resolving content via
`M3UMovieRelation.stream_id` / `M3UEpisodeRelation.stream_id`. The
fallback respects the strictest match first: when
`preferred_m3u_account_id` is also present, that account is queried
first; otherwise the highest-priority active relation matching the
stream_id wins (same ordering the existing relation-selection logic
uses).
This is read-side graceful degradation, complementary to the
write-side root fix proposed in closed#973 (re-use the relation's
existing movie/series during refresh rather than rematching by TMDB
ID). The two PRs together would fully resolve#961: #973 prevents new
orphaning, this PR makes any URL that ships a stream_id survive past
orphaning. URLs without a stream_id (e.g. XC-compat
`/movie/<user>/<pass>/<id>.mkv`) are NOT covered by this patch — they
need the root fix.
Series-UUID lookups (`/proxy/vod/series/<UUID>`) are left UUID-only by
design — players cache episode and movie URLs, not series URLs. Same
pattern can be added as a follow-up if needed.
Tests: 7 new mock-based regression tests covering both branches,
verified against `:dev`. UUID-first happy path is unchanged
(M3U*Relation table never queried when the UUID resolves).
Related: #961 (open), closed#973 (root fix abandoned for inactivity).
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>
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>
- Removed dead VOD URL routes: `VODPlaylistView` (playlist generation), `VODPositionView` (position tracking), and the class-based `VODStatsView` (replaced by the existing function-based `vod_stats` view).
- Removed dead `updateVODPosition()` API method from `frontend/src/api.js`, which called the now-removed position tracking endpoint.
Add support for authentication when connecting to external Redis instances in modular deployment mode. This enables secure Redis deployments using either password-only authentication (Redis <6) or
username + password authentication (Redis 6+ ACL).
Changes:
- Add REDIS_PASSWORD and REDIS_USER environment variables
- Implement URL encoding for special characters in passwords
- Update all Redis connection points to support auth
- Add comprehensive documentation and examples to docker-compose.yml
- Maintains full backward compatibility (empty defaults = no auth)
All authentication mechanisms have been fully tested including pasword-only authentication, Redis 6+ ACL authentication with username + password, volume-mounted configuration files, and special character handling.
Existing deployments are not effected, authentication support is entirely opt-in using docker-compose.
Also, acknowledging the fact that the docker-compose file for modular deployments has been getting out of hand with auth support, the docker-compose.yml file was re-formatted for better visibility in configuration. This seemed like a better way to go than mandating a .env file.
Replace hardcoded localhost:6379 values throughout codebase with environment-based configuration. Add REDIS_PORT support and allow REDIS_URL override for external Redis services. Configure Celery broker/result backend to use Redis settings with environment variable overrides.
Closes#762