Commit graph

54 commits

Author SHA1 Message Date
SergeantPanda
e596a508c7 refactor(models): Simplify comments for catch-up fields in Stream and Channel models, clarifying their population process. Update migration docstring for consistency. Remove outdated comments in ProxyServer and URLs related to timeshift handling. 2026-06-26 12:39:54 -05:00
Cédric Marcoux
1703d6a703 feat(timeshift): address review — network gate, catch-up failover, live_proxy revert, setting moved to proxy settings
Implements all four points from the latest review, plus hardening from a
pre-submission audit pass.

1. Access control: timeshift_proxy now enforces
   network_access_allowed(request, "STREAMS", user) — same key and placement
   as the live XC stream endpoint.

2. Catch-up failover: the proxy walks the channel's catch-up streams in
   channelstream order (get_channel_catchup_streams), mirroring live
   playback. Each attempt carries its own provider context: account
   credentials, provider stream id, reported server_info timezone (the
   UTC->provider conversion is recomputed per attempt), user-agent, and the
   per-account URL-format cache. The first streamable response wins; if all
   providers fail the last failure is returned.
   Ban-safety is per account: a decisive auth/ban-class failure (401/403/406)
   marks the account and skips its remaining streams (e.g. FHD/HD variants of
   the same channel) instead of hammering a banning provider, while other
   accounts — different hosts — are still tried. Streams from disabled M3U
   accounts are excluded, same as live dispatch. Redirects stay enabled on
   purpose (XC providers legitimately 302 to load-balanced streaming nodes);
   the 3xx decisive branch is kept as defense-in-depth and documented as such.

3. apps/proxy/live_proxy/views.py restored byte-identical to upstream — the
   leftover channel-id wrapper from the removed provider-stream-id fallback
   is gone (zero-line diff).

4. Single remaining setting relocated: xmltv_prev_days_override now lives in
   proxy_settings (backend default in get_proxy_settings, consumed by the
   XMLTV prev_days resolution). The timeshift_settings group,
   TIMESHIFT_DEFAULTS, get_timeshift_settings, the Settings → Timeshift form
   and tab are all removed; the field appears under Settings → Proxy Settings
   (0 = auto-detect, capped at 30).

Audit hardening in the same pass:
- Updated the proxy-settings defaults unit test for the new key (would have
  failed CI otherwise).
- Migration backfills use schema_editor.connection instead of the global
  connection (multi-database correctness).
- CHANGELOG and module docstring brought in line with the final architecture
  (PATH-first cascade, failover, setting under Proxy Settings).
- Tests grown to 69 backend tests: failover success/exhaustion/skip
  semantics, decisive-account skip vs soft-failure retry, per-stream
  timezone conversion (different zones per provider), 406/connection-error
  cascade paths, stream-limit and no-eligible-stream outcomes,
  network-gate 403, server_info strict-UTC guarantee, EPG duration window
  resolution, and DB-backed coverage of xc_password auth, user_level access
  and the failover stream ordering (catch-up-only, active accounts,
  channelstream order). The format-cache test now runs on an isolated
  locmem cache.
2026-06-11 20:08:16 +02:00
Cédric Marcoux
2909c9b339 chore(timeshift): pre-review hardening and dead-code cleanup
- http_streamer.py: restore HTTPStreamReader to its upstream form and keep
  only the find_ts_sync() addition. The response=/extra_headers=/
  strip_ts_preamble= extensions had no remaining callers since the timeshift
  view moved to direct iter_content streaming (delta shrinks from +235/-83
  lines to +28).
- Unify the catchup_days semantics everywhere: a channel's archive depth is
  MAX(catchup_days) over its CATCH-UP streams only. The SQL rollup now uses
  a FILTER (WHERE s.is_catchup) aggregate and the ChannelStream signal uses
  the same MAX aggregation (it previously took the first stream by order,
  and the rollup aggregated over all streams including non-catchup ones).
- Migration backfill: also accept the lowercase 'true' that ->> extraction
  yields for JSON booleans.
- get_channel_catchup_info(): drop the tv_archive_duration key — its only
  caller never used it.
- Document why timeshift termination fails closed when Redis is unavailable
  (denying the new stream is what protects the provider connection limit),
  and update the stale stop-key comment (5 s cadence, not 100 chunks).
2026-06-10 22:05:01 +02:00
SergeantPanda
09f4ec91f1 refactor: Remove catchup_provider_stream_id field and related logic from Channel model and migrations 2026-06-02 11:59:09 -05:00
Cédric Marcoux
97038624fe migration: sync catchup_provider_stream_id help_text
The Channel.catchup_provider_stream_id model field carries a help_text that
was not reflected in migration 0038, leaving makemigrations --check dirty.
Add the AlterField migration so model and migration state match (no schema
change — help_text only).
2026-06-01 13:43:56 +02:00
Cédric Marcoux
3b8717c4ce fix: timeshift stream management, channel resolution, and streaming throughput
- Channel resolution: resolve by Channel.id first (what the XC API emits
  to clients), fall back to provider stream_id for backward compatibility.
  Fixes 404 on all timeshift requests from XC clients.

- Stream management: timeshift is now a first-class citizen alongside live
  and VOD in the stream-limits system.  get_user_active_connections()
  detects type='timeshift', attempt_stream_termination() sets a Redis
  stop key (same pattern as VOD), and the timeshift view calls
  check_user_stream_limits() before connecting upstream.  The stream
  generator checks the stop key every 100 chunks.  Fixes infinite retry
  loops on max_connections=1 providers for live→timeshift and
  timeshift→timeshift transitions.

- Streaming: replaced HTTPStreamReader thread+pipe with direct
  iter_content+yield (same pattern as VOD proxy).  The pipe approach
  deadlocked under gevent because the reader thread's select() competed
  with the greenlet's pipe read for hub scheduling.  Throughput went
  from ~74 B/s to 13+ MB/s.

- TS preamble: peek now strips pre-sync bytes (PHP warnings, BOM) before
  prepending to the stream, preventing corrupt TS output.

- Credential safety: _redact_url() now truncates to scheme://host/...
  to avoid leaking XC path-based credentials in logs.

- Tests: updated 5 tests that referenced the removed HTTPStreamReader.
  21/21 timeshift tests pass.

- Migration: fixed SyntaxWarning for unescaped regex in 0038.
2026-05-27 23:32:57 +02:00
Cédric Marcoux
2781b21a89 feat: built-in XC catch-up (timeshift) support
Adds native catch-up/timeshift replay for Xtream Codes providers through
the same HTTPStreamReader transport pipeline as live TV.

Timeshift proxy (apps/timeshift/):
- URL cascade: 3 candidate timestamp formats per provider, per-account
  format cache for fast-forward seek performance
- MPEG-TS preamble stripping (shared with HTTPStreamReader)
- Stats integration: timeshift viewers appear on /stats with TIMESHIFT badge
- Auth via hmac.compare_digest on XC password

Catchup detection — denormalized for zero-cost output queries:
- Stream.is_catchup + Stream.catchup_days populated at XC import time
- Channel.has_catchup + Channel.catchup_days + Channel.catchup_provider_stream_id
  rolled up via ChannelStream post_save signal (UI path) and explicit SQL
  after bulk_create (import path)
- _xc_channel_entry() reads denormalized fields instead of per-channel
  custom_properties JSON introspection (eliminates N+1 queries)
- Migration 0038 backfills existing data via raw SQL

XC API enhancements:
- server_info.timezone + start/end + time_now use configured timezone
  (triple consistency rule — fixes wrong-programme-plays bug)
- Dynamic has_archive flag + auto prev_days for catch-up channels
- XMLTV timestamps rewritten to local timezone for catch-up clients

HTTPStreamReader extended (apps/proxy/live_proxy/input/http_streamer.py):
- 1 MB pipe buffer via fcntl F_SETPIPE_SZ (eliminates producer/consumer
  ping-pong that halved throughput)
- Pre-opened response= for URL cascade workflows
- strip_ts_preamble= for XC servers emitting PHP warnings before TS
- find_ts_sync() as shared utility
- Builds on upstream O_NONBLOCK + select() write loop

Provider stream_id lookup order:
- stream_xc() and xc_get_epg() try internal Channel.id first, fall back
  to provider stream_id only when needed (avoids unconditional query on
  every request)

Also includes:
- VOD provider cascade in stream_vod() — iterates all M3U relations by
  priority when first provider is at capacity
- Defensive null-safety: custom_sid: None → "" in get_live_streams,
  get_vod_streams, get_vod_info, get_series_info (fixes iPlayTV crash on
  JSON null for string fields)
- Timeshift settings UI (timezone selector, debug toggle)
- StreamConnectionCard violet TIMESHIFT badge
- Orphan cleanup skips timeshift_* virtual channels
2026-05-27 13:13:20 +02:00
SergeantPanda
137241f873 Bug Fix: Fix auto sync migration. (Fixes #1259)
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-05-22 13:53:00 -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
b9b3ded71c refactor(migrations): merge channels FR #1196 migrations into single 0037
Consolidates 0037_channeloverride_and_user_hidden, 0038_backfill_auto_created_by_null,
0039_channelgroupm3uaccount_auto_sync_channel_end, and 0040_channel_channel_number_nullable
into a single 0037_auto_sync_overhaul migration.

The merged migration runs operations in dependency-respecting order:
  1. AddField    Channel.user_hidden
  2. CreateModel ChannelOverride
  3. AddField    ChannelGroupM3UAccount.auto_sync_channel_end
  4. RunPython   backfill_auto_created_by_null
  5. AlterField  Channel.channel_number (nullable)
  6. RunPython   noop / reverse_backfill_channel_number_nulls

Also, update CHANGELOG.md and update migration references in test
2026-05-01 18:32:23 -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
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
da598d3b33 Missed migration for previous feature. 2026-01-31 21:26:34 -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
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
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
1a541bd133 Bug fix: Unable to preview custom streams. 2025-10-18 15:52:48 -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
Dispatcharr
dea6411e1c Time Zones
- Added time zone settings
2025-10-06 07:46:23 -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
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
18d4c39291 Combined migrations. 2025-07-13 18:09:30 -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
SergeantPanda
3b2250895d Fixed migrations. 2025-05-15 14:38:28 -05:00
MooseOnTheLoose
88a7312397
Merge branch 'dev' into main 2025-05-08 19:16:49 -05:00
MooseyOnTheLoosey
88866cc905 Updated channel numbers from integer to float 2025-05-08 09:12:10 -05:00
Reggie Burnett
fcd1722d3a Add support for Channels DVR tvc-guide-stationid 2025-05-03 19:24:51 -05:00
dekzter
f295ee219c removed db index here, I don't think it's needed 2025-04-27 10:54:39 -04:00
dekzter
3054cf2ae9 initial xtreamcodes support 2025-04-27 10:32:29 -04:00
dekzter
3e2f91abf8 hopefully finalizing table rewrite 2025-04-23 11:02:00 -04:00
dekzter
ccdb8ab00d more table bug fixes, query optimizations, re-added channel expansion stream table with reworked drag-and-drop 2025-04-19 08:37:43 -04:00
dekzter
2fcadfcc57 forgot to commit migration 2025-04-07 15:02:01 -04:00
dekzter
00f6e7c1cd first run at recordings, among other things 2025-04-05 18:59:15 -04:00
dekzter
e7c4324b64 updated logo url field 2025-04-04 11:24:31 -04:00
dekzter
a41b205629 fully supported channel profiles 2025-04-03 08:59:06 -04:00
dekzter
c5e0de5d48 logos, channel numbers, websocket regex test so we can properly test against python regex and not javascript 2025-04-02 16:27:28 -04:00
dekzter
de5063d20b epg refactor, new relations and matching 2025-03-26 13:28:03 -04:00
dekzter
50f068c358 Refactored m3u refresh, optimized it, added progress notification on the frontend 2025-03-20 16:55:10 -04:00
dekzter
8cdf9a40cf m3u modifications so streams are identified by hash, configurable, also streams now have channel_groups instead of a string for groups 2025-03-19 16:35:49 -04:00
dekzter
45a9c3026a custom streams now work 2025-03-17 18:38:37 -04:00
dekzter
4cef55a9c2 updated channel with uuid 2025-03-16 09:46:07 -04:00
dekzter
9711d7ab34 modified database fields for consistency, removed custom_url from streams (no longer needed) 2025-03-16 09:07:10 -04:00
dekzter
a9437e9214 new migrations 2025-03-05 17:18:04 -05:00