Commit graph

3889 commits

Author SHA1 Message Date
SergeantPanda
097e7118ef Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into dev
Some checks are pending
Backend Tests / Plan test groups (push) Waiting to run
Backend Tests / (push) Blocked by required conditions
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
Frontend Tests / test (push) Waiting to run
2026-07-17 15:45:34 +00:00
SergeantPanda
52c97120fb
Merge pull request #1442 from nagelm/fix/machine-independent-date-tests
test(frontend): make date assertions machine-independent
2026-07-17 10:45:02 -05:00
SergeantPanda
9da83d76fa changelog: Update for pr 1442 2026-07-17 15:44:25 +00:00
SergeantPanda
b91385aacb Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into pr/nagelm/1442 2026-07-17 15:40:28 +00:00
SergeantPanda
1f30e2076d
Merge pull request #1441 from nagelm/fix/toast-html-error-bodies
fix(ui): stop rendering raw HTML error pages in toast notifications (#1261, item 1)
2026-07-17 10:33:36 -05:00
SergeantPanda
5263e18ed9 fix(api): improve error handling for API responses
- Enhanced the `formatApiError` function to better format failed API responses, preventing raw HTML error pages from being displayed in toasts. JSON error bodies are now prioritized for user-friendly messages, while HTML and empty bodies are collapsed to a concise status line. Long plain-text bodies are truncated for readability.
- Updated tests to cover new error formatting behavior, ensuring accurate extraction of error messages from various JSON structures.
2026-07-17 15:31:56 +00:00
SergeantPanda
9ee5ba2535 Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into pr/nagelm/1441 2026-07-17 15:19:35 +00:00
SergeantPanda
6157bc1177 changelog: update for url validation pr. 2026-07-17 14:04:03 +00:00
SergeantPanda
42248743fa
Merge pull request #1381 from recurst/patch-1
Allow underscores in non-FQDN hostnames
2026-07-17 09:01:13 -05:00
SergeantPanda
540f3d9bed Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into dev 2026-07-17 13:57:34 +00:00
SergeantPanda
61df45c895 changelog: Update for frontend test/refactor pr. 2026-07-17 13:56:26 +00:00
SergeantPanda
1b99f105c4
Merge pull request #1444 from nick4810/tests/frontend-unit-tests
Tests/frontend unit tests
2026-07-17 08:52:42 -05:00
SergeantPanda
8bcc7c9ebe feat(timeshift): enhance catch-up programme handling and UI updates
Some checks are pending
Backend Tests / Plan test groups (push) Waiting to run
Backend Tests / (push) Blocked by required conditions
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
Frontend Tests / test (push) Waiting to run
- Updated the catch-up stats UI to advance to the next EPG programme when playback continues past the original programme's end, improving user experience.
- Enhanced the `get_programme_info` function to resolve the guide entry based on the playhead position, ensuring accurate display of the current programme.
- Introduced new utility functions for computing catch-up playback position and checking if the playhead is outside the displayed programme window, optimizing session management.
- Added tests to validate the new functionality and ensure correct behaviour of the catch-up features.
2026-07-16 23:10:06 +00:00
SergeantPanda
6f62d807f4 feat(timeshift): add position reporting for catch-up sessions
- Introduced a new endpoint `POST /api/catchup/sessions/<session_id>/position/` for native clients to report their playhead position and pause state during catch-up sessions.
- Updated the catch-up session handling to include a `paused` flag, allowing accurate tracking of playback state without seeking the provider stream.
- Enhanced the Redis storage mechanism to accommodate the new position and pause data, ensuring real-time updates for admin stats.
- Added tests to validate the new position reporting functionality and its integration with existing catch-up features.
2026-07-16 22:06:27 +00:00
SergeantPanda
14bfd25d9a feat(timeshift): enhance catch-up session handling with optional duration support
- Introduced an optional `duration` parameter for catch-up sessions, allowing clients to specify the programme length in minutes. This value is preferred over EPG-derived durations and includes a buffer for provider lag.
- Updated the API views and serializers to accept and process the new `duration` field.
- Enhanced the catch-up proxy implementation to utilize the client-supplied duration, improving playback accuracy.
- Added tests to validate the new duration handling and ensure proper integration with existing functionality.
2026-07-16 21:26:06 +00:00
SergeantPanda
d3d51780dd fix(schema): enhance Swagger/OpenAPI schema generation for concurrent requests 2026-07-16 19:24:46 +00:00
SergeantPanda
cdfe16ae5d fix(schema): resolve Swagger/OpenAPI schema generation issues under concurrent requests
- Implemented a new `LockedSpectacularAPIView` to handle schema generation, ensuring it no longer fails due to concurrent gevent requests. The schema builds are now single-flight per process and cached in Django's cache, allowing all workers to share the result.
- Updated the `urls.py` to use the new view for schema generation, enhancing stability and performance.
2026-07-16 18:57:57 +00:00
SergeantPanda
388c4bd28d Enhancement: update catch-up features and enhance stream ordering logic
Some checks are pending
Backend Tests / Plan test groups (push) Waiting to run
Backend Tests / (push) Blocked by required conditions
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
Frontend Tests / test (push) Waiting to run
- Improved multi-provider failover by preferring streams with sufficient catch-up days.
- Added new helper functions for calculating programme age and ordering catch-up streams.
- Removed deprecated XMLTV settings from the frontend and backend.
- Updated tests to validate new stream ordering logic and catch-up functionality.
2026-07-16 15:33:34 +00:00
SergeantPanda
6bd42c83f4
Merge pull request #1440 from dillardblom/fix/catchup-incoming-query-url-style
Some checks are pending
Backend Tests / Plan test groups (push) Waiting to run
Backend Tests / (push) Blocked by required conditions
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
fix(timeshift): accept QUERY-style incoming catch-up requests (streaming/timeshift.php)
2026-07-15 17:22:51 -05:00
SergeantPanda
e6244adc0b docs: Remove mentions of specific clients as they could change and isn't fully inclusive anyway. 2026-07-15 22:16:00 +00:00
SergeantPanda
b475bbc07b changelog: add support for QUERY-style catch-up requests 2026-07-15 22:08:35 +00:00
SergeantPanda
23dc7c0a92 Merge branch 'dev' of https://github.com/Dispatcharr/Dispatcharr into fix/catchup-incoming-query-url-style 2026-07-15 22:05:35 +00:00
SergeantPanda
33ada59dba fix(timeshift): refine catch-up timestamp handling and enhance EOF probe logic
Updated the catch-up timestamp normalization to reflect XC client specifications. Introduced a new mechanism to handle near-EOF duration probes, ensuring that playback statistics are preserved without reanchoring to the end of the file. Additionally, improved the handling of presentation lengths in the timeshift proxy to align with XC behavior. Updated tests to validate these changes and ensure robust playback functionality.
2026-07-15 21:26:25 +00:00
Nick Sandstrom
817ebf21a9 Added tests for components 2026-07-14 14:21:54 -07:00
Nick Sandstrom
07d17a5ffc Extracted ManageReposModal from PluginBrowse 2026-07-14 14:21:53 -07:00
Nick Sandstrom
99fc71de99 Slight refactoring of components 2026-07-14 14:21:53 -07:00
Nick Sandstrom
f6ad115a1f Added tests for utils 2026-07-14 14:21:53 -07:00
Nick Sandstrom
6d5a5a549a Extracted utils 2026-07-14 14:21:53 -07:00
nagelm
8cb1dab5ce test(frontend): make date assertions machine-independent
Three tests encoded the machine's timezone or locale into their
expectations and fail on any box east of UTC (observed on UTC+12/13;
CI's UTC and US-locale dev machines never see it):

- dateTimeUtils isSame: compared 10:00Z/11:00Z on the 15th as 'same
  day', but isSame works on local calendar days and no UTC instant
  falls on the same date in every timezone (at UTC+13 those are 23:00
  on the 15th and 00:00 on the 16th). Use timezone-less datetimes,
  which mean the same calendar day everywhere.
- RecordingUtils toDateString: formatted a UTC-noon instant and
  expected the UTC date, but toDateString renders local time (UTC+12
  renders the next day). Construct the Date with local components.
- SeriesModalUtils getEpisodeAirdate: the code renders the viewer's
  locale via toLocaleDateString() by design, but the test hardcoded
  the en-US shape (it tolerated the timezone day-shift with /1[4|5]/
  yet not the day/month order). Compute the expectation with the same
  API so the test asserts the wiring, not a specific locale.

No production code changes.
2026-07-14 23:00:04 +12:00
nagelm
ed1c449234 fix(ui): stop rendering raw HTML error pages in toast notifications (#1261)
Failed API responses whose body is not JSON - Django's HTML "Server
Error (500)" page, nginx's HTML 502/504 pages when the backend is down
or timing out - were interpolated verbatim into the error toast,
showing users a wall of markup.

request() deliberately keeps the raw text when JSON.parse fails, and
errorNotification() rendered `${status} - ${body}` unconditionally.
Route the body through a new formatApiError() helper (in utils.js so it
is unit-testable without importing the store-heavy api module):

- JSON object bodies keep their existing pretty-printed formatting
- markup and empty bodies collapse to the response's own status line:
  the declared Content-Type decides what counts as markup (body
  sniffing only as fallback when the header is missing), and the label
  comes from the fetch Response's statusText - the protocol's reason
  phrase, defined for every status code, rather than a hardcoded status
  map. HTTP/2+ transmits no reason phrase, so an empty statusText falls
  back to a generic label. request() already attaches the Response to
  the error, so no call-site changes are needed.
- the full suppressed body goes to console.debug so the markup stays
  available for troubleshooting (deliberate, not a leftover debug
  statement)
- plain-text bodies are truncated at 200 chars as a backstop
- errors without a status keep the error.message fallback
2026-07-14 20:37:58 +12:00
SergeantPanda
d1344adb4f chore(uwsgi): update configuration for worker reload mechanism
Added a new file entry to .gitignore for .uwsgi-reload and modified uwsgi.debug.ini to implement a touch-based worker reload mechanism, replacing the previous py-autoreload setting. This change enhances the management of API worker reloads during development.
2026-07-14 00:53:03 +00:00
SergeantPanda
ab8e3f93c6 tests: Fix backend timeshift test.
Some checks failed
Backend Tests / Plan test groups (push) Has been cancelled
CI Pipeline / prepare (push) Has been cancelled
Build and Push Multi-Arch Docker Image / build-and-push (push) Has been cancelled
Backend Tests / (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-07-13 23:31:31 +00:00
Dillard Blom
e5d33861e6 Accept QUERY-style incoming catch-up requests (streaming/timeshift.php)
Clients that build catch-up requests in QUERY layout (e.g. Open-TV /
Fred TV: /streaming/timeshift.php?username=...&stream=...&start=...)
had no matching urlpattern, so the request silently fell through to
the frontend's <path:unused_path> catch-all and got served index.html
(200 OK, wrong content) instead of reaching the proxy — no error, no
log line, the client just fails to play.

The PATH-style layout (timeshift/<user>/<pass>/<stream_id>/<ts>/<dur>)
already worked; QUERY-style autodetection already existed for outgoing
provider requests (helpers.build_timeshift_url_format_a/_b) but was
never mirrored to the incoming route.

Split timeshift_proxy into a shared _timeshift_proxy_impl plus two thin
entry points (PATH-style timeshift_proxy, new QUERY-style
timeshift_proxy_query) so both incoming layouts are recognized.

Reported against the predecessor plugin as dispatcharr_timeshift#10;
reproduced identically against dispatcharr:dev (confirmed via nginx
access log: a QUERY-style request returned 200 with a response body
exactly matching the size of frontend/dist/index.html).
2026-07-13 22:13:42 +02:00
SergeantPanda
ea9eaf4d0c fix(timeshift): enhance session handling and playback logic
Some checks failed
Backend Tests / Plan test groups (push) Has been cancelled
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
Backend Tests / (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
Updated the session handling mechanism to improve user experience during reconnects. The first request without a `session_id` now receives a `301` redirect with a minted `session_id`, while reconnects that omit `session_id` but match an existing pool entry are served immediately without a redirect. Additionally, refined playback logic for plain GET requests to restart from byte 0, aligning with provider behavior. Updated tests to reflect these changes and ensure proper session reuse and playback anchoring.
2026-07-12 21:09:40 +00:00
SergeantPanda
58d60bf733 chore(changelog): update CHANGELOG.md to reflect recent enhancements in unit tests and Backup Manager functionality
- Added entry for extended frontend unit tests covering plugin, backup, and settings components.
- Updated Backup Manager to ensure the "Created" column refreshes when date/time format preferences change.
2026-07-12 14:35:05 +00:00
SergeantPanda
d56680cad8
Merge pull request #1424 from nick4810:tests/frontend-unit-tests
Tests/frontend unit tests
2026-07-12 09:27:26 -05:00
SergeantPanda
2f60dc91ae fix(proxy): enhance stream switching logic and error handling
Some checks failed
Backend Tests / Plan test groups (push) Has been cancelled
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
Backend Tests / (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
Updated the stream switching mechanism in the proxy server to ensure that the `stream_id` is persisted correctly and that the requesting worker waits for confirmation from the owning worker in multi-worker deployments. Improved error handling for stream switch failures, returning appropriate HTTP status codes (502/504) based on the confirmation status. Additionally, refined the metadata update process to handle cases where the requested URL is already in use, ensuring a successful response without unnecessary operations. This change addresses issues with stale metadata and enhances the robustness of the stream switching feature. (Fixes #1412)
2026-07-11 18:21:48 +00:00
SergeantPanda
c6e3f57e26 fix(timeshift): enhance session matching logic for fresh sessions
Updated the session matching logic to improve handling of fresh sessions. Introduced a new parameter, `fresh_session`, to skip adopting idle exact-media pools when a new session ID is provided. This prevents unnecessary reconnections to previously abandoned programme slots. Added tests to verify that fresh sessions correctly skip idle matches while retaining busy exact-media sessions and allowing channel hops. This change enhances the robustness of the timeshift feature and improves user experience during session transitions.
2026-07-11 17:32:07 +00:00
SergeantPanda
e887b9e1e5
Merge pull request #1432 from Dispatcharr/timeshift-api
feat(timeshift): add catch-up playback, stats, and admin APIs
2026-07-11 12:18:38 -05:00
SergeantPanda
223dff33ed feat(timeshift): add catch-up playback, stats, and admin APIs
Add end-to-end catch-up support for XC clients and native apps: provider
proxy with failover and per-viewer session pooling, REST session minting
for tokenless playback URLs, catch-up admin stats, combined connection
stats, and Stats UI with dedicated cards plus websocket updates.

Includes Redis namespace consolidation under timeshift:* (dropping legacy
timeshift_ id prefixes), dedicated catch-up stop by session_id, and
cleaner channel/client metadata split for stats keys.

Closes #133
2026-07-11 17:14:31 +00:00
SergeantPanda
3c2c42ce66 fix(epg): prevent crashes for channels with null channel numbers in XMLTV export
Some checks failed
Backend Tests / Plan test groups (push) Has been cancelled
CI Pipeline / prepare (push) Has been cancelled
Build and Push Multi-Arch Docker Image / build-and-push (push) Has been cancelled
Backend Tests / (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
Updated the EPG generation logic to ensure that channels without a channel number do not cause crashes in the XMLTV export. Implemented a deferred assignment mechanism for channels with null numbers, allowing them to receive valid integers during processing. Added tests to verify that the XMLTV output remains stable and valid even when channels are unnumbered.
2026-07-10 02:42:50 +00:00
SergeantPanda
5c5b866bcf fix(vod): prevent group selection loss on empty category fetch
Implemented logic to abort the VOD refresh process when the provider returns no categories, preserving existing group selections. This change prevents unintended deletions of category relations and ensures that accounts retain their current settings during transient provider outages or API issues. Updated logging to reflect the abort condition for better traceability.
2026-07-09 21:26:36 +00:00
SergeantPanda
9ad198beb3 fix(live-streams): prevent crashes for channels with null channel numbers
Updated the handling of channels in the live streams setup to ensure that channels without a channel number do not cause crashes. Implemented logic to assign a valid number to these channels during processing. Added tests to verify that the system correctly assigns numbers to channels with null values, ensuring stability in the live streams feature.
2026-07-09 20:02:57 +00:00
SergeantPanda
c1c32686bd fix(timeshift): ensure database connections are closed before returning responses
Some checks are pending
Backend Tests / Plan test groups (push) Waiting to run
Backend Tests / (push) Blocked by required conditions
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
Added a helper function to close old database connections in the `timeshift_proxy` view before returning any HTTP responses. This change prevents potential database connection leaks and ensures that connections are properly managed during the request lifecycle. Updated tests to verify that connections are closed appropriately in various response scenarios.

Also stores provider_tz_name with session pool in redis to avoid an extra database call.
2026-07-09 17:03:53 +00:00
SergeantPanda
6f2e99f47d
Merge pull request #1425 from cedric-marcoux:fix/timeshift-seek-position
fix(timeshift): serve the requested position when reusing a session (FF/RW snaps back to rewind anchor)
2026-07-09 11:51:57 -05:00
SergeantPanda
27deef9ad6 feat(epg): Improve performance during cold rebuilds by yielding to gevent hub
Enhanced the `/output/epg` cold rebuild process to prevent freezing of the gevent uWSGI worker. The `_stream_build` function now yields control to the gevent hub after processing each cached chunk, allowing other requests to be handled concurrently. This change improves responsiveness during CPU-bound XMLTV generation. Additionally, introduced a new utility function, `_cooperative_yield`, to facilitate yielding in CPU-bound loops.
2026-07-09 15:32:51 +00:00
Nick Sandstrom
3c658a6fc6 Fixed mock path 2026-07-09 01:44:14 -07:00
Cédric Marcoux
35dce2b7f8 fix(timeshift): drop stale byte state and harden descriptor update on seek
Self-review follow-ups on the position fix:

- When the position actually moves, drop content_length/serving_range from
  the pool entry — they describe the PREVIOUS position's file, and keeping
  them would feed the near-EOF/displacement heuristics another programme's
  size (a metadata probe near the new file's EOF could displace live
  playback, or a genuine scrub could be misjudged as a probe). The next
  successful open repopulates both.
- Guard the update under the pool lock and skip it when the entry has
  vanished (Redis restart/eviction) — a bare HSET would resurrect a
  partial, TTL-less hash that answers every later request for that
  session_id with 503.
- Align the reuse-path timezone lookup with the fresh path
  (is_active=True on the default-profile filter).

Three more tests: byte state dropped on move / kept on same-position
update, vanished entry never resurrected, tz fallback to the reserved
profile when no active default exists.
2026-07-09 08:40:31 +02:00
Cédric Marcoux
7655060149 fix(timeshift): serve the requested position when reusing a session
Clients (TiviMate) keep the ?session_id= query when they rebuild the seek
URL with a new start timestamp, so every timestamp-jump FF/RW landed on
the reused session's STORED provider_timestamp — playback snapped back to
the position the session was created for (the rewind anchor), 100%
reproducible: two requests with different start values on one session
returned byte-identical streams.

The reuse path now always recomputes the provider timestamp from the
REQUESTED one (the provider zone is a property of the account — read from
the default profile's server_info, same as the fresh path) and moves the
pool descriptor (media_id + provider_timestamp) to the position actually
served, so fingerprint matching and same-channel displacement keep
comparing against reality. Slot continuity is unchanged.

Regression tests: reused session serves the requested timestamp (unit),
descriptor follows the seek (unit), and an end-to-end timestamp-jump with
the same session_id reaches the new position through timeshift_proxy.
2026-07-09 07:42:19 +02:00
Nick Sandstrom
65fcaa885e Syntax formatting changes 2026-07-08 15:03:03 -07:00