Commit graph

1533 commits

Author SHA1 Message Date
SergeantPanda
cd0eba9654
Merge pull request #1098 from CodeBormen/fix/ghost-streams-stuck-initializing
fix: stuck channel states and ghost clients in TS proxy
2026-03-15 20:07:44 -05:00
None
55f0a49d68 fix: improve test coverage and add missing metadata constants
- Rewrite ghost client tests to call real ChannelStatus and ClientManager code paths instead of reimplementing detection logic in test helpers
- Rewrite initializing state tests to invoke StreamManager.run() so the real finally block executes under test
- Replace hardcoded state list tests with assertions against ChannelState.PRE_ACTIVE frozenset
- Add missing SOURCE_BITRATE and FFMPEG_BITRATE constants to ChannelMetadataField (referenced by channel_status.py but never defined, causing AttributeError on detailed stats)
2026-03-15 19:39:15 -05:00
SergeantPanda
2d2b3e45f4 fix: harden ghost client cleanup and PRE_ACTIVE state guard
- Change ChannelState.PRE_ACTIVE from list to frozenset (immutable,
  O(1) membership tests, no risk of silent mutation)

- Add optional client_ids parameter to ClientManager.remove_ghost_clients()
  so callers that have already fetched SMEMBERS can pass it through,
  eliminating a redundant Redis round-trip

- Pass pre-fetched client_ids from get_basic_channel_info() into
  remove_ghost_clients() to remove the duplicate SMEMBERS call
2026-03-15 19:08:38 -05: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
SergeantPanda
0815b3df14 tests: Add backend test for expiration feature. 2026-03-15 16:42:11 -05:00
SergeantPanda
bd11b0e832 Change notification for account expiry to admin only. 2026-03-15 16:03:41 -05:00
SergeantPanda
09d5f6bb9f Update expiration date handling in M3U components to ensure UTC format 2026-03-15 16:00:23 -05:00
None
40d0bc9567 fix: cap keepalive mode duration to prevent indefinite client hold
- Add MAX_KEEPALIVE_DURATION = 300s to TSConfig
- Track keepalive_start_time in _stream_data_generator; disconnect after cap is exceeded with a warning log
- Reset timer on real data so independent stalls don't accumulate
- Fix pre-existing test helper missing throttle attributes in NonOwnerWorkerKeepaliveTests
2026-03-15 14:22:57 -05:00
cmcpherson274
c8b665dc98
Update last_active timestamp in keepalive logic
Update last active timestamp for clients during failover.
2026-03-15 14:08:43 -04:00
cmcpherson274
10ea165c2c
Refactor packet handling with locking mechanism 2026-03-15 14:04:59 -04:00
SergeantPanda
1d4603dadd Enhancement: Optimize profile expiration handling and update task naming for clarity 2026-03-15 12:42:34 -05:00
cmcpherson274
f7085e5dc2
Add 'last_active' field to stats in stream_generator 2026-03-15 12:10:38 -04:00
cmcpherson274
fd9ca28316
Modify client TTL handling in client_manager.py
Updated client manager to refresh TTL without updating last_active timestamp.
2026-03-15 12:08:32 -04:00
cmcpherson274
cf1aef6747
Implement buffer reset method for stream transitions
Added a method to reset internal buffers to prevent corruption during stream transitions.
2026-03-15 12:06:32 -04:00
None
01a214851d fix: catch all exceptions in entity resolution to avoid breaking EPG refresh
Previously only UnicodeDecodeError/UnicodeEncodeError were caught. Unexpected errors like disk full or permission denied would propagate
and crash the EPG refresh, which would have succeeded before the preprocessing step existed. Now all exceptions are caught and logged, leaving the original file untouched for lxml to handle as before.
2026-03-15 01:11:29 -05:00
None
1f97143bf8 fix: resolve HTML named entities in XMLTV files before parsing
lxml 6.0.2 with recover=True silently drops HTML named entities (e.g. é, î) that are not valid XML, causing channel names and program data to lose characters during EPG ingestion.

- Add preprocessing step in fetch_xmltv() that converts HTML named entities to Unicode while preserving XML-predefined entities
- Detect encoding from XML declaration, fall back to UTF-8 for unknown codecs, skip files that fail to decode cleanly
- Guard against entities resolving to XML-special characters and html.unescape partial matching edge cases
- Add 28 unit tests covering entity resolution, encoding detection, and file-level processing
2026-03-15 00:59:58 -05:00
None
c65ace1a7c fix: stuck channel states and ghost clients in TS proxy
- Write ERROR via ownership check OR state guard fallback when ownership TTL expired during retries
- Add INITIALIZING to cleanup task grace period monitoring
- Validate client SET entries against metadata hashes in orphaned channel cleanup; remove ghosts and clean up when no real clients remain
- Stats page self-heals by removing ghost SET entries on read
- Extract remove_ghost_clients() helper to ClientManager
- Add ChannelState.PRE_ACTIVE constant
- Fix 6 pre-existing NonOwnerWorkerKeepalive test failures
2026-03-14 19:24:01 -05:00
SergeantPanda
b22f9e8e07 Enhancement: Account expiration tracking and notifications for M3U profiles 2026-03-14 18:38:59 -05:00
SergeantPanda
216dd7fc40
Merge pull request #1072 from CodeBormen/feat/1065-Add-Subtitle-and-Season-Episode-to-Guide
feat: Add subtitle and season/episode to TV Guide (#1065)
2026-03-13 16:48:20 -05:00
SergeantPanda
284aafcf5e Bug Fix: EPG programme parsing crash when an XMLTV source contains programme titles exceeding 255 characters. Previously, a single oversized title would cause the entire bulk_create batch to fail with a database truncation error, silently dropping all programmes in that batch. Titles are now truncated to 255 characters before being saved. (Fixes #1039)
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-03-13 15:35:43 -05:00
SergeantPanda
1f50217dbe perf(epg): speed up TV guide grid load 2k channels from 18s to ~8s
Replace DRF ModelSerializer with .values() + plain dict construction in
EPGGridAPIView, eliminating per-row serializer instantiation, field
object creation, and OrderedDict overhead across ~12k programs.

Pre-compute season/episode at import time instead of on every API request:
- Extract S/E from onscreen episode-num inline in extract_custom_properties()
  immediately after storing the raw value, rather than in a separate pass
- Add missing description-based S/E fallback to parse_programs_for_tvg_id(),
  bringing it in line with parse_programs_for_source()

Remove runtime extract_season_episode() call from ProgramDataSerializer and
EPGGridAPIView — values are now guaranteed to be in custom_properties after
import, so season/episode resolution is a plain dict lookup at request time.

Also remove unnecessary select_related("epg") JOIN and .count() query from
the grid endpoint.
2026-03-13 12:16:10 -05:00
dekzter
1dd368278c reverted value checking for consistency, added in user id to client info 2026-03-13 09:57:22 -04:00
dekzter
f69a462253 merged in dev 2026-03-13 08:22:44 -04:00
None
79dc113a1c remove infer_is_live()
After discussion, decided to keep live badge inference deterministic
2026-03-12 16:01:35 -05:00
None
49825f3733 Merge remote-tracking branch 'origin/dev' into feat/1065-Add-Subtitle-and-Season-Episode-to-Guide 2026-03-10 11:17:00 -05:00
None
b72a9a870e feat(guide): redesign guide with detail modal, progress bars, and season/episode display
Replace expanded inline cards with a ProgramDetailModal for viewing full program
details. Add real-time progress bars to currently-airing programs using direct DOM manipulation. Extract and display season/episode info from EPG data with a 3-tier fallback (custom_properties → onscreen_episode → description text).

Backend:
- Add ProgramDetailSerializer for rich EPG data (categories, credits, ratings, images, external IDs) served on the detail endpoint
- Add infer_is_live() for status badges (live, new, premiere, finale)
- Add shared S/E extraction utilities in apps/epg/utils.py
- Optimize querysets with select_related("epg")

Frontend:
- ProgramDetailModal with conditional field rendering and image fallback chain
- Progress bars via scaleX transform updated every second
- Parallel data fetching with Promise.all for channels + programs
- Browser tab visibility recovery for progress bars
- Now-line with triangle marker and sub-millisecond precision
- Card layout: title, season/episode + subtitle, time + badges
- Shared formatSeasonEpisode() and external URL helpers
2026-03-10 10:53:19 -05:00
SergeantPanda
39865d3732 Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into pr/CodeBormen/943 2026-03-08 18:04:11 -05:00
SergeantPanda
70a0b43c8a Cleanup frontend and backend if valid item ids change. 2026-03-08 17:05:26 -05:00
SergeantPanda
63234a4a46 Bug Fix: Restore integrations/system groups and fix channels reference after rebase 2026-03-08 16:35:34 -05:00
SergeantPanda
d5aaa0277c security: Do not allow user to give themselves admin or super_user privileges. 2026-03-08 16:30:48 -05:00
SergeantPanda
a4ad9a9135 Move python test into tests folder. Fix frontend test after merge changes. 2026-03-08 16:30:47 -05:00
SergeantPanda
cde39c0e13 Fixed logic with default orders. 2026-03-08 16:30:42 -05:00
Jeff Casimir
8fb88827ae Fix code review findings for navigation ordering PR
P1 (Critical):
- Replace undefined @swagger_auto_schema with @extend_schema
- Add custom_properties validation with size limits
- Add merge semantics in serializer update() to prevent data loss

P2 (Important):
- Add debouncing (800ms) for drag operations in NavOrderForm
- Add error handling with notifications for visibility toggle
- Use store getters in Sidebar instead of direct property access
- Cache hiddenNav before render loop

P3 (Nice-to-have):
- Add canHide: false to settings nav item
- Fix admin check to use >= instead of ==
- Fix ESLint unused variable warnings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 16:28:29 -05:00
Jeff Casimir
edf81ef6c6 Add PATCH method to /me/ endpoint for user preferences
- Allow users to update their own profile via PATCH /api/accounts/users/me/
- Supports partial updates to custom_properties (including navOrder)
- Add comprehensive test coverage for the endpoint

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 16:25:47 -05:00
SergeantPanda
ea9f4f4bbd Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into pr/JCBird1012/1062 2026-03-08 12:00:46 -05:00
SergeantPanda
dfb91db987 Bug Fix: VOD orphan cleanup crashing with a ForeignKeyViolation (IntegrityError) when a concurrent refresh task created a new M3UMovieRelation or M3USeriesRelation for a movie/series between the orphan-detection query and the DELETE SQL. Both orphaned_movies.delete() and orphaned_series.delete() are now wrapped in try/except IntegrityError; affected records are skipped with a warning and will be cleaned up on the next scheduled run. 2026-03-08 11:56:52 -05:00
SergeantPanda
753bc1a893 fix(stream-preview): restore stream_name and stream_stats for stream previews
Stream.get_stream() was never called in the preview path of
generate_stream_url(), so the channel_stream and stream_profile
Redis keys were never written. This caused the stream_id to be
missing from channel metadata, which silently broke two things:

- Stats page showed no stream name or logo
- stream_stats were never saved to the database

Fix: replace the manual profile-selection loop in the preview path
with a direct call to Stream.get_stream(), matching the channel path
exactly. This also fixes a pre-existing non-atomic slot reservation
(read-then-check vs INCR-first) that could over-allocate connections
on concurrent previews.

Regression introduced in 49b7b9e2.
2026-03-08 11:46:31 -05:00
SergeantPanda
9876a25e62 Bug Fix: XC stream refresh crashing with a null value in column "name" database error when a provider returns streams with a null or empty name. Affected streams are now assigned a generated fallback name in the format <account name> - <stream_id> so the refresh completes successfully and the stream remains accessible. A warning is logged for each affected stream. 2026-03-07 18:33:17 -06:00
SergeantPanda
3d27161755 Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into pr/nickgerrer/1022 2026-03-06 17:22:44 -06:00
SergeantPanda
2373044adb Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into pr/CodeBormen/1052 2026-03-06 16:12:52 -06:00
SergeantPanda
4aa0d3ae01 feat(epg): enhance EPGGridAPIView to include live and new tags for dummy programs. 2026-03-06 13:43:53 -06:00
None
a9c90059d6 feat: add status badges (live, new, premiere, finale) to guide cards
Add is_new, is_live, is_premiere, and is_finale fields to the EPG program API and render them as colored badges in the TV guide.

- Compact card: S/E, LIVE, and NEW badges on the title row
- Expanded card: all badges (S/E, LIVE, NEW, PREMIERE, FINALE) on the subtitle row, now moved directly after title for consistency
- PREMIERE/FINALE detected from premiere_text (case-insensitive)
- PREMIERE/FINALE only shown in expanded view to conserve space
- Badge order: S/E → LIVE → NEW → PREMIERE → FINALE
2026-03-06 12:19:00 -06:00
SergeantPanda
fa0a963ad9 refactor(epg/guide): streamline season/episode extraction and guide card layout
- Consolidate serializer season/episode parsing into a single to_representation
  pass: one custom_properties read, regex runs at most once per program
- Compact card: S/E badge inline with title; secondary row shows sub_title with
  description fallback
- Expanded card: sub_title and S/E badge share a row above the description
- Fix secondary text color for legibility on dark backgrounds (#a0aec0 → #e2e8f0)
- Fix expanded card overflow (height:100% → flex:1 1 0) so action buttons stay visible
- Bump expanded card height 180 → 200px, description max-height 80 → 100px
2026-03-06 10:44:11 -06:00
Jonathan Caicedo
a51eb37075 fix: M3U EXTINF parsing for attributes ending in double equals
fixes: #1055
2026-03-06 08:10:30 -05:00
None
ee112de84a feat: add subtitle and season/episode to TV guide
Display sub_title (episode name) and season/episode badge on guide program cards. Extract season/episode from custom_properties with fallback parsing of onscreen_episode format (e.g. "S12 E6").

- Add season/episode SerializerMethodFields to ProgramDataSerializer
- Parse onscreen_episode string as fallback when xmltv_ns data absent
- Display sub_title with S/E badge on guide cards
- Show description for programs without sub_title (movies)
- Add formatSeasonEpisode utility with full test coverage
- Add 15 backend serializer tests and 12 frontend utility tests

Fulfills #1065
2026-03-05 23:41:16 -06:00
SergeantPanda
bf87c44a72 Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into pr/CodeBormen/1063 2026-03-05 16:48:34 -06:00
SergeantPanda
78aa8cf353 Enhancement: Change default new client behind seconds from 2 to 5 for stability. 2026-03-05 15:36:12 -06:00
SergeantPanda
37fa6aac20
Merge pull request #1023 from CodeBormen/fix/940-Duplicate-Recordings-With-Corruption
fix(dvr): fix duplicate recording execution and add manual stop
2026-03-05 14:11:41 -06:00
None
ce9f7ccbf9 fix(m3u): fix Celery worker memory leak during M3U/XC refresh
Restructure cleanup in refresh_single_m3u_account so del statements
run before gc.collect(), enabling cyclic garbage collection. Add worker_max_memory_per_child as a safety net against memory fragmentation.

Closes #1012, Closes #1053
2026-03-05 13:47:20 -06:00
Jonathan Caicedo
c6cf9443d2 fix: guard is_adult parsing against invalid values
or whatever other fun things providers might shove down the wire...
2026-03-05 14:16:21 -05:00