Commit graph

3942 commits

Author SHA1 Message Date
SergeantPanda
b1cb70c5d2
Merge pull request #975 from Dispatcharr/connect
Feature: Connect
2026-02-16 15:27:56 -06:00
SergeantPanda
968551c1a6 Enhancement: M3U generation for Xtream Codes API endpoints now use proper XC-style stream URLs (/live/username/password/channel_id) instead of UUID-based stream endpoints, ensuring full compatibility with XC clients. (Fixes #839) 2026-02-16 13:45:57 -06:00
SergeantPanda
6ebcf18e48
Merge pull request #991 from Dispatcharr/cron-scheduling
feat(scheduling): add cron builder and refactor scheduling components (Closes #165)
2026-02-16 10:55:43 -06:00
SergeantPanda
717cce92ec
Merge branch 'dev' into cron-scheduling 2026-02-16 10:55:33 -06:00
dekzter
55a5180ee1 hardening of script handling with configurable variables - making script execution more secure 2026-02-15 07:37:00 -05:00
dekzter
055d2604ca better form validation 2026-02-15 07:36:29 -05:00
dekzter
45d0f180fe added endpoint for testing connections with a dummy payload 2026-02-15 07:36:08 -05:00
Northern Powerhouse
14fa187a4e Fix datetime validation and test timestamp format
- Add proper datetime validation in API with 400 error responses
- Fix test timestamp format (was creating invalid +00:00Z format)
- Time filters now properly validate and return errors on invalid input
- All 26 tests passing with correct filtering behavior
2026-02-14 16:05:23 +01:00
Northern Powerhouse
5dac7acc93 Add comprehensive test suite for EPG search API endpoint
- Add pytest-based test suite with 32+ test cases
- Test all features: text search, AND/OR operators, regex, whole words
- Test time filtering: airing_at, start/end time ranges
- Test channel/stream/group filtering
- Test pagination and field selection
- Test edge cases and error handling
- Configurable via environment variables (host, port, credentials)
- Include test runner script and documentation
- Support for CI/CD integration with JUnit XML output

Usage:
  ./tests/run_tests.sh
  pytest tests/test_epg_search_api.py -v
  DISPATCHARR_HOST=192.168.1.180 pytest tests/test_epg_search_api.py -v
2026-02-14 15:52:47 +01:00
Northern Powerhouse
22978aa132 Add EPG program search API endpoint with advanced filtering
- Add ProgramSearchResultSerializer with nested channel/stream data
- Implement ProgramSearchAPIView with comprehensive filtering:
  * Text search with AND/OR operators and parenthetical grouping
  * Regex pattern matching support
  * Whole word matching to avoid partial matches
  * Time-based filtering (airing_at, start/end ranges)
  * Channel/stream/group filtering
  * Configurable field selection for response customization
  * Pagination (50 default, 500 max per page)
- Add /api/epg/programs/search/ endpoint
- Add comprehensive API documentation
- Enhanced Swagger/OpenAPI schema with examples

Examples:
  - Complex queries: (Newcastle OR NEW) AND (Villa OR AST)
  - Whole words: title=NEW&title_whole_words=true
  - Regex: title=^Premier&title_regex=true
  - Time filtering: airing_at=2026-02-14T20:00:00Z
2026-02-14 15:48:02 +01:00
None
4842bb87fa Fix: VOD proxy connection counter leak on client disconnect
Three fixes:
- TOCTOU: Replace GET-check-INCR with atomic INCR-first-then-check pattern in both connection managers to prevent concurrent requests exceeding max_streams
- Immediate DECR: Decrement profile counter directly in stream generator exit paths (normal completion, client disconnect, error) instead of deferring to daemon thread cleanup which may never execute
- Rollback: Decrement profile counter on create_connection() failure so the reserved slot is released

Fixes #962
2026-02-13 19:37:06 -06:00
SergeantPanda
96d13253c8
Merge pull request #981 from Dispatcharr:auto-sync-channel-numbers
Some checks failed
CI Pipeline / prepare (push) Has been cancelled
Build and Push Multi-Arch Docker Image / build-and-push (push) Has been cancelled
Frontend Tests / test (push) Has been cancelled
CI Pipeline / docker (amd64, ubuntu-24.04) (push) Has been cancelled
CI Pipeline / docker (arm64, ubuntu-24.04-arm) (push) Has been cancelled
CI Pipeline / create-manifest (push) Has been cancelled
Enhancement: Allow multiple channel numbering modes for auto channel sync
2026-02-13 15:40:35 -06:00
SergeantPanda
5ed8b7a954 changelog: Update changelog for auto channel sync changes. 2026-02-13 15:39:27 -06:00
SergeantPanda
fb2f156fd8 Bug Fix: Fixes a bug with auto channel sync where channel numbers could be duplicated if multiple groups overlapped. 2026-02-13 15:07:24 -06:00
SergeantPanda
2c9f6d7360 Enhancement: For auto channel sync, allow using provider number, fixed start number or next available. (Closes #956, #433) 2026-02-13 14:34:22 -06:00
dekzter
e030906cdd more supported events, better UI (columns) for events in connection editor 2026-02-13 12:20:40 -05:00
dekzter
1236d3968f forgot dangling import 2026-02-13 12:02:33 -05:00
dekzter
3b0a890e94 fixed circular import 2026-02-13 11:48:59 -05:00
dekzter
f1d6b86278 refactored frontend usage of 'all channels' to only pull down IDs, query for individual channels as necessary 2026-02-13 11:46:17 -05:00
dekzter
fe9854c522 more supported events 2026-02-12 19:28:43 -05:00
SergeantPanda
890992a9f9 feat(scheduling): add cron builder and refactor scheduling components (Closes #165)
Add cron expression support for M3U and EPG refreshes with interactive
builder modal and quick reference examples. Refactor backup scheduling
to use shared ScheduleInput component for consistency.

- New CronBuilder modal with preset buttons and custom field editors
- Info popover with common cron expression examples
- Shared ScheduleInput component for interval/cron toggle
2026-02-12 18:08:13 -06:00
Patrick McDonagh
a52b3dfbe5
fix: add support for legacy numpy in celery entrypoint 2026-02-12 13:08:25 -06:00
None
51b5824737 Fix cleanup paths for stream preview
Fix exception handling in _clean_redis_keys() and stop_channel()
   where `except Channel.DoesNotExist` didn't catch ValidationError from invalid UUID format, bypassing the Stream fallback path.
2026-02-12 00:09:29 -06:00
None
20ce45f7ad fix(ts-proxy): Add Stream fallback in cleanup path to prevent counter leak on stream preview
When previewing a stream directly (via stream hash), the cleanup in stream_generator.py tried Channel.objects.get(uuid=stream_hash) which failed with ValidationError since the hash is not a UUID. This
prevented release_stream() from running, permanently leaking the
connection counter. With max_streams=1, a single preview permanently blocked all subsequent streams.

Added Stream.objects.get(stream_hash=...) fallback so the cleanup
path works for both Channel (UUID) and Stream (hash) identifiers.
Also added Stream import to stream_generator.py.
2026-02-12 00:02:40 -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
8bb8a0fca9 fix(ts-proxy): Remove redundant local import causing UnboundLocalError
The local `from apps.channels.models import Channel` inside a
conditional block in _handle_client_disconnect() shadowed the top-level import. When the condition was False, Python's function-level scoping caused line 462's Channel.objects.get() to raise UnboundLocalError. Channel is already imported at module level (line 11), making the local import unnecessary.

Discovered when testing proxy changes
2026-02-11 20:52:30 -06:00
None
6360271e28 Fix unprotected _clean_redis_keys() call in check_if_channel_exists
Wrap _clean_redis_keys() call in check_if_channel_exists() with
try/except to prevent exception propagation when Channel/Stream
lookup or release_stream() encounters DB or Redis errors.
2026-02-11 20:09:17 -06:00
None
fe17d0d585 Check release_stream() boolean return at all call sites
All 12 call sites for Channel.release_stream() and Stream.release_stream() now check the boolean return value and log warnings when release fails.

Files updated:
- server.py: 4 call sites (zombie cleanup + _clean_redis_keys)
- channel_service.py: 2 call sites (stop_channel)
- stream_generator.py: 1 call site (last client disconnect)
- views.py: 4 call sites (failed init, redirect, init failure, exception)
- url_utils.py: 1 call site (URL generation error)

Also fixed bare except clause in _clean_redis_keys and uncaught
Stream.DoesNotExist in channel_service.stop_channel.

Based on PR #838 by patchy8736
2026-02-11 19:49:11 -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
dekzter
bc72ea7310 merged in dev 2026-02-11 19:51:21 -05:00
dekzter
e6ffeb19de added event support to plugins 2026-02-11 19:50:11 -05: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
SergeantPanda
a05f89ab85 changelog: Update changelog for modular connection check pr.
Some checks failed
CI Pipeline / prepare (push) Has been cancelled
Build and Push Multi-Arch Docker Image / build-and-push (push) Has been cancelled
CI Pipeline / docker (amd64, ubuntu-24.04) (push) Has been cancelled
CI Pipeline / docker (arm64, ubuntu-24.04-arm) (push) Has been cancelled
CI Pipeline / create-manifest (push) Has been cancelled
2026-02-11 16:56:25 -06:00
SergeantPanda
43a9ad8582
Merge pull request #964 from CodeBormen/fix/952-PostgreSQL-Socket-Check
Fix modular mode PostgreSQL/Redis connection checks
2026-02-11 16:52:29 -06:00
SergeantPanda
9007064166 Add clarity to roadmap.
Some checks failed
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) Has been cancelled
2026-02-11 16:27:40 -06:00
SergeantPanda
96fbd2859c Updated Readme. 2026-02-11 16:27:31 -06:00
None
39646f0b01 Fix modular mode PostgreSQL/Redis connection checks
Replace raw Python AF_INET socket checks with pg_isready (PostgreSQL) and socket.create_connection (Redis) in modular deployment mode

The raw socket check may fail in some Docker environments depending on networking and DNS configurations, causing indefinite hangs. Replaced database check with native pg_isready
and memstore checck with AF_UNSPEC in the case IPv6 is enabled.

Fixes #952
2026-02-10 23:00:35 -06:00
None
cf96287c90 Add guard to remove_connection()
- multi_worker_connection_manager.py: Add missing count > 0 guard to multi-worker remove_connection()

This method doesn't appear to be called anywhere but added the guard in case it is put back into service
2026-02-10 19:06:51 -06:00
None
9e8f227f49 Fix: VOD proxy double-DECR of profile connection counter during cleanup
- multi_worker_connection_manager.py: Error handler at line 1042: removed connection_manager=self from cleanup() call since the DECR was already done at line 1036. Prevents double-DECR.

- connection_manager.py: Added connection_key_exists check before calling remove_connection(). The fallback DECR from session data now only fires when the connection tracking key has already expired. Prevents double-DECR.
2026-02-10 18:58:17 -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
None
16309cd9b4 Remove if logic from scheduled shutdown
- stream_generator.py: _schedule_channel_shutdown_if_needed() already guards itself, the if logic created conflict between release_stream() and stop_channel(), so if the stream was already released the shutdown would not be scheduled
2026-02-10 18:15:48 -06:00
Matt Grutza
32119789ab
Merge branch 'Dispatcharr:main' into Feature/854-Add-Ability-to-sort-Channels-by-Group 2026-02-10 17:54:12 -06:00
Matt Grutza
bc231b3f64
Merge branch 'Dispatcharr:main' into fix/945-XC-profile-refresh-extract-wrong-credentials 2026-02-10 17:52:07 -06:00
Matt Grutza
681ffe1779
Merge branch 'Dispatcharr:main' into fix/947-Connection-capacity-leak-failed-stream-initialization-permanently-consumes-connection-slot 2026-02-10 17:51:25 -06:00
Damien
549aefe453
Merge branch 'dev' into feature-819-UserTableUpdate 2026-02-10 21:30:38 +00:00
GitHub Actions
197acddb1d Release v0.19.0
Some checks failed
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
Base Image Build / prepare (push) Has been cancelled
Frontend Tests / test (push) Has been cancelled
Base Image Build / docker (amd64, ubuntu-24.04) (push) Has been cancelled
Base Image Build / docker (arm64, ubuntu-24.04-arm) (push) Has been cancelled
Base Image Build / create-manifest (push) Has been cancelled
2026-02-10 21:15:08 +00:00
SergeantPanda
75ed2f3351
Merge pull request #960 from Dispatcharr/dev
Release - v0.19.0
2026-02-10 15:11:38 -06:00
SergeantPanda
bbef201dde
Merge branch 'main' into dev 2026-02-10 15:10:28 -06:00