Commit graph

28 commits

Author SHA1 Message Date
SergeantPanda
0dc8898e8b refactor(epg): separate programme index into dedicated table for optimized data handling
- Moved the `programme_index` from the `EPGSource` model to a new `EPGSourceIndex` table, ensuring that the large JSON blob is only loaded when explicitly accessed, thus improving query performance and memory efficiency.
- Updated related queries and API views to utilize the new structure, including adjustments to EPG generation and import logic to prevent unnecessary data loading.
- Enhanced memory management in the EPG grid endpoint to reduce worker RSS during response handling.
2026-06-23 15:10:27 -05:00
SergeantPanda
04394b7eac fix(epg): enhance DB connection management and error handling during EPG refreshes
- Implemented robust DB connection management in `refresh_epg_data` to handle transient errors, ensuring reliable status updates for EPG sources.
- Added retry logic for database queries and improved error handling to prevent task failures from unhandled exceptions.
- Updated EPG source status handling to ensure accurate reporting of errors and terminal states during refresh operations.
2026-06-18 16:39:52 -05:00
SergeantPanda
c2ac08fdfd enhancement(epg): Performance improvements and API enhancements for EPG refreshes.
- Updated EPG import logic to reject dummy sources without loading the large `programme_index`, optimizing memory usage during API calls.
2026-06-18 15:53:55 -05:00
SergeantPanda
34c938b1ce feat(epg): implement staging and batch processing for EPG program updates
- Introduced a temporary staging table for efficient batch processing of EPG program inserts, reducing memory and I/O contention during updates.
- Enhanced the `parse_programs_for_source` function to stream parsed rows into the staging table before swapping them atomically into the main program data.
- Added unit tests to validate the new staging and swapping logic, ensuring existing programs are preserved during failures and that batch processing works as intended.
2026-06-15 19:50:50 -05:00
SergeantPanda
7ed9b11a89 Refactor Schedules Direct EPG handling and enhance guide fetch logic
- Replaced individual EPG program parse tasks with a centralized dispatch function to streamline guide refresh for newly assigned EPG IDs.
- Implemented batching for guide fetches when multiple EPGs are mapped, reducing redundant API calls and improving efficiency.
- Updated related utility functions to support the new fetching strategy and added tests to ensure correct behavior under various scenarios.
2026-06-11 16:41:30 -05:00
SergeantPanda
c274bd7fbb Enhance Schedules Direct integration with per-channel guide fetch and improved EPG handling
- Implemented a targeted guide fetch for Schedules Direct when mapping a channel, ensuring immediate data availability without redundant API calls.
- Updated EPG signals to queue guide fetches for newly mapped channels, streamlining the process and improving user experience.
- Refactored existing logic to skip unnecessary program refreshes for dummy sources and ensure proper handling of Schedules Direct data.
- Added unit tests to validate the new fetching behavior and ensure robustness of the integration.
2026-06-11 13:54:19 -05:00
SergeantPanda
205deb150b Implement schedule MD5 delta detection and backfill logic for improved cache management
- Added functions to compute schedule changes based on MD5 hashes and backfill missing dates for mapped stations.
- Enhanced handling of orphaned ProgramData records for unmapped EPG entries during schedule fetch.
- Introduced unit tests to validate MD5 comparison, backfill logic, and metadata fetching requirements.
2026-06-11 12:31:30 -05:00
SergeantPanda
b928de7d50 fix(epg): resolve EPG channel list refresh issue after parsing completion
- Addressed a bug where the EPG channel list did not refresh after a source finished parsing channels due to the `epg_refresh` WebSocket handler using a stale snapshot. The handler now correctly reads the current store state and ensures `fetchEPGData()` is called upon completion of channel parsing.
- Updated tests to verify that the frontend receives the correct parsing completion signals.
2026-06-07 09:56:25 -05:00
SergeantPanda
7e906ad78e feat(epg): enhance poster style selection and fetching logic
Introduce a new poster style selection feature in the EPG settings, allowing users to choose their preferred artwork style. Update the logic for fetching and displaying program artwork from Schedules Direct, ensuring that the selected style is honored with appropriate fallbacks. Set default poster art to 'primary'. Add comprehensive tests to validate the poster selection functionality across various scenarios.
2026-06-05 10:14:07 -05:00
Shokkstokk
4eec542ef8
Merge branch 'dev' into feature/schedules-direct-epg 2026-06-03 23:38:54 -04:00
Five Boroughs
374c05952b
test(epg): cover real EPG source formats and index lookup edge cases 2026-05-31 22:26:39 +02:00
Five Boroughs
f8919b0d98
fix(epg): handle attr-spacing and named entities in index lookup, unblock boot rebuild 2026-05-31 21:57:26 +02:00
Five Boroughs
10d558f136
perf(epg): async index build, defer index column, tight build lock, channel-id canonicalization, retry-on-error 2026-05-31 17:13:11 +02:00
Five Boroughs
2cfea1df0f
perf(epg): per-channel interleaved tracking, defer first-preview build
Also renames the migration to `0023_` to resolve collision with
upstream `0022_alter_epgdata_name`. Rationale in #938.
2026-05-31 17:13:11 +02:00
Five Boroughs
7c0c513f8f
test(epg,frontend): add coverage for current-program lookup and preview behavior 2026-05-31 17:13:11 +02:00
SergeantPanda
33c1db4c9f fix(test): ensure password field is excluded from EPGSourceSerializer output 2026-05-31 10:04:07 -05:00
mwhit
6f316977ad fix(epg): address reviewer feedback on SD integration
- Rename api_key to password (RemoveField + AddField) for clarity and reusability
- Move sd_changes_remaining/sd_changes_reset_at to custom_properties JSONField
  instead of nullable columns on all EPGSource rows
- Replace sd_program_md5 column on ProgramData with SDProgramMD5 relation table
  keyed by epg_source + program_id, fixing the key mismatch bug in program
  MD5 delta detection
- Fix total_changed counter: .items() -> .values() so len() returns date count
  not tuple length
- Add missing SD lineup management endpoints to api_views.py
  (sd_lineups GET/POST/DELETE, sd_lineups_search POST)
- Regenerate migration 0023_schedules_direct using Django to ensure correct
  index names and schema
2026-05-18 22:46:56 +00:00
mwhit
6b9d621cf7 feat(epg): add Schedules Direct API integration
- Add EPGSource username field and SDScheduleMD5 model for MD5 delta sync
- Implement full Schedules Direct fetch with SHA1 auth, token caching,
  20-day schedule window, and MD5-based delta sync to minimize API usage
- Add lineup manager UI allowing users to search and manage SD lineups
- Add stations-only fetch on source creation for immediate EPG matching
- Enforce 2-hour minimum refresh interval to respect SD rate limits,
  with first-fetch bypass when no prior full refresh exists
- Add real-time progress updates via synchronous Redis WebSocket delivery,
  bypassing gevent.spawn for reliable delivery from Celery prefork workers
- Refactor EPGsTable status cell into standalone EPGStatusCell component
  with direct Zustand subscription for live progress bar updates
- Guard XMLTV parse trigger for channels linked to SD EPG sources
- Add 15 backend tests covering auth, credentials, signals, and serializers

Migrations: 0023 (username field), 0024 (api_key help_text), 0025 (SD fields + SDScheduleMD5)
2026-05-17 04:52:07 +00:00
SergeantPanda
c486f641a8 fix(epg): improve parameter descriptions and enhance title whole word matching tests. Fix bug with postgres whole words (they use \y not \b for regex)
Co-authored-by: Copilot <copilot@github.com>
2026-04-24 15:46:56 -05:00
SergeantPanda
3435d77d20 feat(epg): enhance title search functionality with case-insensitivity and quoted phrases
Co-authored-by: Copilot <copilot@github.com>
2026-04-24 15:14:52 -05:00
SergeantPanda
f89df3284e fix(epg): fix and clean up EPG program search API and tests
- Fix test user: set user_level=1 (STANDARD), REMOTE_ADDR="127.0.0.1" to
  satisfy IsStandardUser + network_access_allowed checks; move user creation
  to setUpTestData (1 DB write per class instead of per test)
- Fix parenthesis parser: group_result was computed then silently discarded;
  rewrite parse_expression to recursively compose Q objects correctly so
  queries like "(Newcastle OR NEW) AND (Villa OR AST)" work as documented
- Fix field selection performance: resolve allowed fields before serialization
  and pass as context; get_channels/get_streams short-circuit when not requested
- Move import re to top of file; remove mid-file alias regex_module
- Convert ProgramSearchAPIView standalone APIView into @action(detail=False)
  on ProgramViewSet so the router registers programs/search/ before
  programs/{pk}/ automatically, eliminating the URL ordering dependency
- Scope permission to the action directly via permission_classes=[IsStandardUser]
  rather than adding "search" to the global permission_classes_by_action dict
- Add test_title_parenthetical_grouping to cover the fixed parser path
- Tighten existing test assertions (case-insensitive, whole-word, description
  AND, page_size cap) to catch regressions rather than passing vacuously

Co-authored-by: Copilot <copilot@github.com>
2026-04-24 14:37:12 -05:00
SergeantPanda
672f135b51 tests: Enhance program search API tests for case insensitivity and whole word matching
Co-authored-by: Copilot <copilot@github.com>
2026-04-24 13:31:04 -05:00
SergeantPanda
07f6c65ae7 refactor: Removed unneeded files and created a new test that uses django.
Co-authored-by: Copilot <copilot@github.com>
2026-04-24 11:34:41 -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. &eacute;, &icirc;) 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
79dc113a1c remove infer_is_live()
After discussion, decided to keep live badge inference deterministic
2026-03-12 16:01:35 -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
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
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