Commit Graph
2681 Commits
Author SHA1 Message Date
euzu 45c10edd3d ci: bump version v3.3.147 v3.3.147 2026-10-12 14:36:37 +00:00
euzuandGitHub 0d53b22479 fix hls: start rebased retained sessions on the new origin window (#911)
* fix hls: start rebased retained sessions on the new origin window

* fix hls: only drop rebase head when unused and tail is not continued
2026-10-12 16:35:17 +02:00
euzu d9482aeca1 ci: bump version v3.3.146 v3.3.146 2026-10-12 07:54:15 +00:00
euzuandGitHub d1c4056965 fix hls: require fresh origin window for new playback on retained ses… (#910)
* fix hls: require fresh origin window for new playback on retained sessions, count known-length revision bodies as completed

- New playback leases joining a retained shared session no longer start
on
  a stale committed window. If the origin window was last confirmed more
  than two target durations ago, admission requires a fresh commit
  (StaleEntryWindow) using the strict pinned host and no recovery burst.
  This prevents the forward jump after fast-start entry.
- RevisionResponseStream tracks bytes sent. A known-length body that is
  dropped after its final byte is now recorded as completed and marks
  segment completion instead of logging outcome=dropped.
- Add an end-to-end re-entry regression test covering progressive,
  first_ready and conservative, plus unit tests for the commit
  requirement and revision completion.
2026-10-12 09:53:04 +02:00
euzu e6032679ac ci: bump version v3.3.145 v3.3.145 2026-10-09 23:15:32 +00:00
euzuandGitHub a3124a37f5 fix epg: adopt guide channel ID casing on matched live streams, fix frontend: hide column rail on empty tables (#908)
* - fix epg: adopt guide channel ID casing on matched live streams
Synchronize the stream's `epg_channel_id` to the exact casing of the
matched XMLTV guide channel. This fixes exact-key B+Tree lookups in short
EPG and client API responses when stream and guide IDs differ in case.

- fix frontend: hide column rail on empty tables

* - fix epg: adopt guide channel ID casing on matched live streams
Synchronize the stream's `epg_channel_id` to the exact casing of the
matched XMLTV guide channel. This fixes exact-key B+Tree lookups in short
EPG and client API responses when stream and guide IDs differ in case.

- fix frontend: hide column rail on empty tables
2026-10-09 23:12:57 +02:00
euzu d158b152d2 ci: bump version v3.3.144 v3.3.144 2026-10-09 15:43:05 +00:00
d35875e3d1 fix hls close revision file at reader deadline (#907)
* fix hls close revision file at reader deadline

Move the progressive revision reader onto its own task and feed the
response stream through a bounded channel. At the deadline the watchdog
aborts the reader, so the file handle and revision pin are released
even if a stalled client never polls the stream again.

Each open revision file now holds its own pin, so GC cannot retire a
revision while a handle is open, including one held by an in-flight
blocking read.

* fix hls close revision file at reader deadline

Move the progressive revision reader onto its own task and feed the
response stream through a bounded channel. At the deadline the watchdog
aborts the reader, so the file handle and revision pin are released
even if a stalled client never polls the stream again.

Each open revision file now holds its own pin, so GC cannot retire a
revision while a handle is open, including one held by an in-flight
blocking read.

---------

Co-authored-by: euzu <euzu@proton.me>
2026-10-09 17:41:39 +02:00
euzu 7cfd9ac3a9 ci: bump version v3.3.143 v3.3.143 2026-10-08 11:29:50 +00:00
euzuandGitHub 62aea2a2fe persist table layouts and unify column metadata (#906)
* **New Features**
  * Customize table columns by showing, hiding, and reordering them, with keyboard or pointer controls.
  * Save layouts per account, restore defaults, and resolve conflicts when preferences change elsewhere. On installations without web authentication, settings are shared.
  * CSV tables now support saved layouts for recognized table structures.
* **Bug Fixes**
  * Improved pagination bounds and page-size validation.
  * Settings requests now return clearer errors for oversized or unreadable request bodies, and recheck access after waiting for settings to become available.
* **Documentation**
  * Added guidance for table customization and the settings API.
2026-10-08 13:28:41 +02:00
euzu e5313faa38 ci: bump version v3.3.142 v3.3.142 2026-10-07 16:42:29 +00:00
75dab00847 fix(frontend): clean up websocket callbacks and reconnect timers on s… (#904)
* fix(frontend): clean up websocket callbacks and reconnect timers on session expiry

* fix(frontend): clean up websocket callbacks and reconnect timers on session expiry

---------

Co-authored-by: euzu <euzu@proton.me>
2026-10-07 18:41:13 +02:00
euzu ac0dad8342 ci: bump version v3.3.141 v3.3.141 2026-10-07 13:42:46 +00:00
euzuandGitHub 91433fe37f Fix/dvr recording (#903)
* fix(dvr): correct source resolution, HLS headers and proxy routing

* fix(dvr): support concurrent live recordings within provider capacity
2026-10-07 15:41:19 +02:00
euzu aa687e6e3f ci: bump version v3.3.140 v3.3.140 2026-10-06 17:29:10 +00:00
euzuandGitHub 8b4d27b79f fix(m3u): use alias token for Flussonic catch-up archives (#902)
* fix(m3u): use alias token for Flussonic catch-up archives

Catch-up archive URLs are built from the main account's live URL. On an
alias allocation the M3U URL index only knows live URLs, so the lookup
missed and the archive manifest was fetched with the main stream token.
DVR segments inherited it, and the provider attributed the playback to
the main account.

On an index miss for a Flussonic archive file, resolve the live file in
the same directory through the alias index (one lookup pass for all
candidates) and keep the requested archive file name with the alias
query.

Query-based catch-up templates (append mode) are not covered.

* fix(dvr): retry ffmpeg spawn while executable is busy

Spawning a just-written executable can fail with ETXTBSY when a
concurrently forked process still holds an inherited write descriptor
before its exec. This made run_recording_preempts_fake_ffmpeg_and_
preserves_window_semantics flaky on CI.

Retry the spawn up to five times with a short backoff on
ExecutableFileBusy; other errors fail immediately as before.

* fix(hls): resolve single-variant archive master in shared cache

Archive URLs that return a master playlist with one #EXT-X-STREA
child failed with segment_uri_without_extinf. The variant's media
playlist is now fetched and fed to the cache timeline.

- skip masters with several variants or separate #EXT-X-MEDIA tr
- send entry credentials only to the entry origin
- send master cookies only to the master origin
- merge master and variant session cookies by name
- keep the recovery binding on the entry URL
2026-10-06 19:28:11 +02:00
euzu 509e2cfeee ci: bump version v3.3.139 v3.3.139 2026-10-06 05:56:43 +00:00
euzuandGitHub d27570bc79 Refactored EPG View (#901)
* **New Features**
  * Added an EPG group view with channel counts, programme details, and channel search.
  * Added timeline zooming and panning, recording controls for eligible upcoming programmes, and a resizable side panel with keyboard and pointer controls.
* **Improvements**
  * EPG group and grid results support JSON or CBOR responses and show up to 1,000 channels per group.
  * Channel filters support case-insensitive text and regular expressions; invalid patterns are rejected with an error.
2026-10-06 07:55:19 +02:00
euzu 7511f719f1 ci: bump version v3.3.138 v3.3.138 2026-10-05 17:56:23 +00:00
euzuandGitHub b409b784b8 WebUI fixes (#900)
Some WebUI fixes
2026-10-05 19:55:13 +02:00
euzu 9183ca0846 ci: bump version v3.3.137 v3.3.137 2026-10-05 10:20:26 +00:00
euzuandGitHub f1ffffccd3 small fix for source editor and doc update (#899)
- Added Flussonic UserAgent docs
- Fixed possible problem in Source Editor
2026-10-05 12:19:07 +02:00
euzu 9cebb510ef ci: bump version v3.3.136 v3.3.136 2026-10-04 14:04:05 +00:00
euzuandGitHub 91f6c57159 Fix/merge live and vod recording (#876)
feat(dvr)!: unify live and VOD/series recording into one recoverable DVR

Merge fix/merge_live_and_vod_recording into develop.

- One recording queue for scheduled live captures and VOD/series transfers,
  with a shared transition graph, provider-slot scheduling, resumable HTTP
  transfers (strong ETag / Last-Modified validation) and ffmpeg live capture.
- Crash-recoverable persistence: B+Tree repository with a journal-first
  recovery history; one file can be shared by several library entries.
- Admission checks quota and disk on request, at transfer start (real size)
  and before an entry attaches to a finished file; idempotent requests.
- REST is command-only; state reaches clients via owner-filtered WebSocket
  snapshots.
- Deleting a recording removes the file once no entry holds it; removing an
  entry keeps a finished file and cleans up orphaned partials.
- User ids derive from the configured username (web:/api:); the identity
  registry is gone.
- Spanish locale added; ru/ar completed; locale parity test.

BREAKING CHANGE: `video.download` is now `video.recording` (nested
`recording` keys move up, `download_priority`/`recording_priority` become
`priority`); old configs fail to load with a migration hint.
BREAKING CHANGE: `/api/v1/file/download*` and `/file/record` are removed in
favour of `/api/v1/recording/*`.
BREAKING CHANGE: `download.*` and `recording.write` permissions are replaced
by `recording.read|create|manage|delete`; tokens from before the change must
re-authenticate.
BREAKING CHANGE: the old recording queue does not migrate; existing
`identity_registry.json` is ignored.
2026-10-04 16:02:55 +02:00
euzu b4290e8724 ci: bump version v3.3.135 v3.3.135 2026-10-03 16:09:21 +00:00
euzuandGitHub 3b656f56b5 fix(hls): return upstream status for HLS resources (#896)
* fix(hls): return upstream status for HLS resources

- no TS fallback for failed segments, init and keys
- bounded capacity wait on pinned account (manifest 5s, media 2s)
- reject waiting requests after session end or account switch
- per-origin provider cookie jar, read at send time
- opt-in flussonic_hls_audio_tracks input option

* fix(hls): return upstream status for HLS resources

- no TS fallback for failed segments, init and keys
- bounded capacity wait on pinned account (manifest 5s, media 2s)
- reject waiting requests after session end or account switch
- per-origin provider cookie jar, read at send time
- opt-in flussonic_hls_audio_tracks input option

* fix(hls): return upstream status for HLS resources

- no TS fallback for failed segments, init and keys
- bounded capacity wait on pinned account (manifest 5s, media 2s)
- reject waiting requests after session end or account switch
- per-origin provider cookie jar, read at send time
- opt-in flussonic_hls_audio_tracks input option
2026-10-03 18:07:59 +02:00
euzu e85361736c ci: bump version v3.3.134 v3.3.134 2026-10-02 18:17:45 +00:00
a4feb08c48 fix(hls): keep provider account across client IP changes (#895)
* fix(hls): keep provider account across client IP changes

Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.

- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
  refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core

* fix(hls): keep provider account across client IP changes

Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.

- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
  refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core

* fix(hls): keep provider account across client IP changes

Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.

- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
  refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core

* fix(hls): keep provider account across client IP changes

Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.

- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
  refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core

* fix(hls): keep provider account across client IP changes

Wrap live HLS media playlists in a single-variant master whose variant
URI is a sealed owner token, so playlist refreshes from changing client
IPs keep their owner, lease and provider affinity. Expired sessions are
recreated from the token with the same access and admission checks.

- Classify HLS resources by playlist tag, not by .m3u8 extension
- Answer non-HLS 200 bodies as failed manifests (entry: unavailable,
  refresh: 502)
- Pin child manifests and media URIs to the resolving provider account
- Add reverse_proxy.stream.hls_wrap_media_playlist (default true)
- Split AppState into app_state/ containers; move HTTP clients to core

---------

Co-authored-by: euzu <euzu@proton.me>
2026-10-02 20:16:20 +02:00
euzu 154206ed74 ci: bump version v3.3.133 v3.3.133 2026-10-01 16:56:29 +00:00
b8486cffc7 fix(hls): keep provider affinity after reconnect lease expiry (#894)
* fix(hls): keep provider affinity after reconnect lease expiry

- Remember the provider that last delivered media for reconnect-capable
  playback (HLS, DASH, Catchup, VOD) beyond the lease window. The
  preference holds no slot, never forces grace and falls back to the
  lineup when the provider is full.
- End it on provider failure, preemption, kick, timeout or admin
  terminate; stale cleanups are rejected by binding tag, request ID and
  session token. Retry token claims stay bounded.
- Terminate and kick now release the HLS binding they acquired.
- Add reverse_proxy.stream.provider_affinity_ttl_secs (default 120,
  max 86400) with Web UI field, docs and translations.
- Testkit: pause_millis steps, TTL overrides and the
  m3u-hls-provider-affinity-after-lease-expiry scenario.

* fix(hls): keep provider affinity after reconnect lease expiry

- Remember the provider that last delivered media for reconnect-capable
  playback (HLS, DASH, Catchup, VOD) beyond the lease window. The
  preference holds no slot, never forces grace and falls back to the
  lineup when the provider is full.
- End it on provider failure, preemption, kick, timeout or admin
  terminate; stale cleanups are rejected by binding tag, request ID and
  session token. Retry token claims stay bounded.
- Terminate and kick now release the HLS binding they acquired.
- Add reverse_proxy.stream.provider_affinity_ttl_secs (default 120,
  max 86400) with Web UI field, docs and translations.
- Testkit: pause_millis steps, TTL overrides and the
  m3u-hls-provider-affinity-after-lease-expiry scenario.

* fix(hls): keep provider affinity after reconnect lease expiry

- Remember the provider that last delivered media for reconnect-capable
  playback (HLS, DASH, Catchup, VOD) beyond the lease window. The
  preference holds no slot, never forces grace and falls back to the
  lineup when the provider is full.
- End it on provider failure, preemption, kick, timeout or admin
  terminate; stale cleanups are rejected by binding tag, request ID and
  session token. Retry token claims stay bounded.
- Terminate and kick now release the HLS binding they acquired.
- Add reverse_proxy.stream.provider_affinity_ttl_secs (default 120,
  max 86400) with Web UI field, docs and translations.
- Testkit: pause_millis steps, TTL overrides and the
  m3u-hls-provider-affinity-after-lease-expiry scenario.

---------

Co-authored-by: euzu <euzu@proton.me>
2026-10-01 18:55:22 +02:00
euzu 559d18a373 ci: bump version v3.3.132 v3.3.132 2026-10-01 12:47:36 +00:00
1960861ee7 fix(provider): exclude and persist banned/expired accounts (#893)
- Store terminal account states in source.yml/CSV; keep Pending runtime-only
- On 401/403, only flag the account for the throttled expiry worker
- Lift stored bans on panel renewal or credential update
- Persist per file in one batch; back up only when content changes
- Use the first usable alias for playlists when the root is blocked

Co-authored-by: euzu <euzu@proton.me>
2026-10-01 14:46:19 +02:00
euzuandGitHub 0bd087d288 fix(provider): exclude and persist banned/expired accounts (#891)
* fix(provider): exclude and persist banned/expired accounts

- Store terminal account states in source.yml/CSV; keep Pending runtime-only
- On 401/403, only flag the account for the throttled expiry worker
- Lift stored bans on panel renewal or credential update
- Persist per file in one batch; back up only when content changes
- Use the first usable alias for playlists when the root is blocked

* fix(provider): exclude and persist banned/expired accounts

- Store terminal account states in source.yml/CSV; keep Pending runtime-only
- On 401/403, only flag the account for the throttled expiry worker
- Lift stored bans on panel renewal or credential update
- Persist per file in one batch; back up only when content changes
- Use the first usable alias for playlists when the root is blocked
2026-10-01 14:24:02 +02:00
euzu 93b1603412 ci: bump version v3.3.131 v3.3.131 2026-10-01 06:19:04 +00:00
euzuandGitHub d280a5484f fix(hls): reuse stable provider lease owners across playback retries (#890)
* fix(hls): reuse stable provider lease owners across playback retries

Keep public HLS tokens unique while sharing provider leases by
client/user/channel fingerprint. Preserve request ID and binding
generation guards and scope socket cleanup to the original session.

Add regression tests for repeated retries, stale cleanup, reused
sockets and M3U alias fallback with an A=2/B=4 provider pool.

* fix(hls): reuse stable provider lease owners across playback retries
- Keep public HLS tokens unique while sharing provider leases by
client/user/channel fingerprint. Preserve request ID and binding
generation guards and scope socket cleanup to the original session.

- Add regression tests for repeated retries, stale cleanup, reused
sockets and M3U alias fallback with an A=2/B=4 provider pool.

fix: proxy external Xtream VOD sources in M3U reverse mode
- Resolve stored VOD URLs using the existing input identity.
- Use canonical movie URLs for alias accounts with the original stream ID.
- Keep redirects internal and stop forwarding upstream Referer headers.
- Add regression tests for CDN URLs, aliases, ranges, and URL leakage

* fix(hls): reuse stable provider lease owners across playback retries
- Keep public HLS tokens unique while sharing provider leases by
client/user/channel fingerprint. Preserve request ID and binding
generation guards and scope socket cleanup to the original session.

- Add regression tests for repeated retries, stale cleanup, reused
sockets and M3U alias fallback with an A=2/B=4 provider pool.

fix: proxy external Xtream VOD sources in M3U reverse mode
- Resolve stored VOD URLs using the existing input identity.
- Use canonical movie URLs for alias accounts with the original stream ID.
- Keep redirects internal and stop forwarding upstream Referer headers.
- Add regression tests for CDN URLs, aliases, ranges, and URL leakage
2026-10-01 08:16:56 +02:00
euzu 6f9687c890 ci: bump version v3.3.130 v3.3.130 2026-09-30 23:24:33 +00:00
euzuandGitHub 308fd87288 Fix/flussonic (#889)
* **New Features**
  * Added a setting to limit Flussonic HLS catch-up archive duration. Valid values range from 1 second to 7 days; the default is 4 hours.
  * Bounded archive requests are capped at the configured limit, while shorter valid requests retain their requested duration. Changes apply after a playlist refresh.
  * Added a dashboard credits card with app and TMDB attribution.
* **Bug Fixes**
  * Open filter dialogs now render in the document body when available, helping them display correctly.
* **Documentation**
  * Documented the archive-duration setting and bounded-archive behavior.
2026-10-01 01:21:50 +02:00
euzu c09c06f663 ci: bump version v3.3.129 v3.3.129 2026-09-30 15:31:19 +00:00
euzuandGitHub 89ec7c0e97 Fix/filter input and flussonic fix (#888)
* filter input for user form

* added opt-in bounded Flussonic HLS catch-up

- Add flussonic_hls_catchup input option with native default
- Generate bounded archive sources during M3U import
- Preserve live URLs and query tokens
- Expose native and bounded_archive in the WebUI select

* added opt-in bounded Flussonic HLS catch-up

- Add flussonic_hls_catchup input option with native default
- Generate bounded archive sources during M3U import
- Preserve live URLs and query tokens
- Expose native and bounded_archive in the WebUI select
2026-09-30 17:28:58 +02:00
euzu 02fba44fd4 ci: bump version v3.3.128 v3.3.128 2026-09-30 08:44:20 +00:00
euzuandGitHub e703c8dd87 fix: honor explicit Flussonic HLS catchup-source with bounded archive… (#887)
* **New Features**
  * Added support for bounded Flussonic HLS catch-up playback when an explicit source is configured, with valid start times and durations of up to seven days.
  * Bounded archive playlist resources now inherit missing query parameters from their source while preserving values provided by child resources. Cross-origin URLs remain unchanged.
* **Bug Fixes**
  * Rewritten Flussonic catch-up output now uses the rewritten mode without retaining the original catch-up type or provider token.
2026-09-30 10:41:54 +02:00
euzu 59e0f242ab ci: bump version v3.3.127 v3.3.127 2026-09-30 07:03:47 +00:00
euzuandGitHub 92346301c1 Fixed: tmdb error stops pipeline processing (#886)
* **Bug Fixes**
  * Playlist publication now continues when optional content curation is unavailable or encounters service, credential, request-limit, or certificate issues.
  * In these cases, regular catalog content can still be published to supported outputs and saved to the cache. Curation-specific views are omitted when they cannot be prepared.
  * Empty playlists continue to be rejected by the regular publication process.
2026-09-30 09:02:32 +02:00
euzu 67515b120e ci: bump version v3.3.126 v3.3.126 2026-09-27 08:25:35 +00:00
euzuandGitHub 305587f40b fix: retry unstarted streams on an available provider alias (#885)
* **Bug Fixes**
  * Playback retries can use another available provider when playback has not started, helping requests proceed if the initially selected provider is unavailable.
  * Once playback has started, retries continue using the same eligible provider to preserve playback continuity.
  * Provider selection follows the same rules for regular playback and forced reopens, reducing unnecessary provider pinning before media begins.
  * Series episode URLs can resolve to the correct account-specific playback address.
2026-09-27 10:23:35 +02:00
euzu de577f6773 ci: bump version v3.3.125 v3.3.125 2026-09-27 07:43:45 +00:00
eb24e51a65 test(curation): cover post-merge admission contracts (#881)
* test(curation): cover post-merge admission contracts

Add regression coverage for the merged TMDB/Trakt behavior and correct the stale first-page changelog wording. Keep all existing tests and production code unchanged.

* test(curation): isolate admission fixture from environment proxies

Use the existing no_proxy test-client pattern at the fixture boundary. Preserve the missing TMDB transport, both catalog policies and all assertions; no production transport changes.

---------

Co-authored-by: Juanjo Presa <juanjop@gmail.com>
Co-authored-by: euzu <euzu@proton.me>
2026-09-27 09:42:49 +02:00
euzu 11efe7a24e ci: bump version v3.3.124 v3.3.124 2026-09-26 16:57:25 +00:00
euzuandGitHub 278bf41d2c Fix/stalker (#884)
* **New Features**
  * Stalker playback resolves channel links on request, using available channel commands and falling back to the stored command when needed.
  * If a portal rejects a session, playback retries once after reconnecting.

* **Bug Fixes**
  * Reading playlists or resolving playback for a different portal identity no longer replaces the published catalog or clears its refresh checkpoint.
  * A failed channel playback no longer prevents other published channels from remaining available.

* **Documentation**
  * Updated Stalker playback guidance to describe on-demand link resolution and session recovery.
2026-09-26 18:56:17 +02:00
euzu 3e1bb60551 ci: bump version v3.3.123 v3.3.123 2026-09-26 15:05:04 +00:00