Enables Xtream catch-up/timeshift from the Favorites and Recent surfaces (per-playlist and global), not just Live TV, and adds start-over replay of the currently-airing programme. Carries tv_archive/tv_archive_duration through the favorites and recently-viewed DB projections and maps them onto UnifiedCollectionItem; tv_archive_duration is interpreted as days, matching live-stream-layout.controlledArchiveDays. Closes #1138. Co-authored-by: Claude <noreply@anthropic.com>
5.3 KiB
Xtream Portal Compatibility
This document captures the Xtream Codes compatibility rules shared by the Electron and PWA paths.
Connection Input
Xtream server URLs are normalized through
normalizeXtreamServerUrl from @iptvnator/shared/interfaces.
Rules:
- Only
httpandhttpsURLs are accepted. - URL username/password credentials are rejected.
- Leading and trailing whitespace is ignored.
- Trailing slashes are removed.
- Full API or playlist URLs ending in
/player_api.phpor/get.phpare reduced to the portal base URL. - Provider subpaths are preserved. For example,
https://example.test/panel/player_api.php?...becomeshttps://example.test/panel.
The Xtream import form may extract username and password from full
get.php or player_api.php URLs, but stored playlist metadata should keep
the normalized serverUrl plus trimmed credentials.
Account Status
Account status handling uses resolveXtreamPortalStatus.
Compatibility rules:
- Status text is case-insensitive, so
Active,active, andACTIVEare treated the same. authvalues1,'1', andtruecan mark a response as active when no status text is present.authvalues0,'0', andfalsemark the response inactive.exp_datevalues0, negative numbers, missing values, or invalid values are treated as no expiry.- A past positive
exp_datemarks the account expired even when status is active.
Status probes try account-info-compatible Xtream variants in this order:
action=get_account_info- no
action action=get_profile
This fallback exists because real panels differ even when they advertise Xtream Codes compatibility.
Request Construction
Electron IPC and the PWA backend both construct API requests by appending
/player_api.php to the normalized portal base URL. They must not append
player_api.php to an already full player_api.php or get.php URL.
Credentials sent to the API are trimmed before serialization.
The PWA backend only proxies Xtream requests through registered provider
targets. Those targets are validated when registered and revalidated before the
/xtream proxy request, including protocol, URL credentials, DNS resolution,
and private-network checks.
User-Agent
Electron's XTREAM_REQUEST and XTREAM_PROBE_URL handlers
(apps/electron-backend/src/app/events/xtream.events.ts) send a shared
XTREAM_CLIENT_USER_AGENT constant on every outgoing request. Some Xtream
panels sit behind a WAF (e.g. Cloudflare) configured to challenge
generic/incomplete browser-looking User-Agents while allowlisting known IPTV
player clients; a player-style User-Agent (currently a VLC signature) avoids
that challenge page, whereas a browser-looking but non-browser TLS/HTTP client
(axios/curl with a Chrome or empty User-Agent) can be blocked even though a
real browser or a VLC-style client passes. Keep all three request sites using
the shared constant instead of inlining the string again.
Playback URL Formats
When account info includes user_info.allowed_output_formats, the current
Xtream playlist keeps those formats for the active session. The default
application format is auto: live stream URL construction chooses m3u8 when
the provider allows HLS, falls back to ts when MPEG-TS is the only known
standard format, and otherwise uses the first provider-advertised format. If
the provider does not advertise output formats, auto falls back to m3u8.
Manual ts and m3u8 settings remain supported; when a manual setting is not
allowed by the portal, URL construction falls back to the first
provider-allowed format.
If stored Xtream playback credentials contain an invalid server URL or blank username/password, stream URL construction returns an empty URL instead of throwing during playback.
Catch-Up Playback URLs
Xtream-compatible portals differ on archive playback URL shape. IPTVnator supports these catch-up variants:
- REST-style
/timeshift/{username}/{password}/{duration}/{start}/{streamId}.tsand.m3u8. - Legacy
/streaming/timeshift.php?username=...&password=...&stream=...&start=...&duration=...with optionalextension=tsorextension=m3u8.
Electron probes concrete catch-up variants before caching a playlist-level
choice. The cache key includes the playlist id and the normalized
allowed_output_formats advertised by the provider, so a catch-up variant
detected before account capabilities are known cannot force stale MPEG-TS URLs
after the portal later reports HLS-only playback. The probe uses a short range
GET, follows only validated redirects, and accepts only 200 or 206 as
playable. MPEG-TS is preferred before HLS when the provider allows it because
some portals return a valid HLS manifest while the first media segment fails in
Chromium/video.js. PWA fallback keeps the REST MPEG-TS URL when no Electron
probe API is available.
Catch-up is offered from the Xtream Live TV tab and from the unified
collection surfaces (per-playlist and global Favorites and Recent). The
tv_archive / tv_archive_duration columns are carried through the
favorites and recently-viewed DB projections and mapped onto
UnifiedCollectionItem.tvArchive / tvArchiveDuration so the shared live
tab can gate the timeline's archive window. tv_archive_duration is
interpreted as days everywhere, matching
live-stream-layout.controlledArchiveDays (issue #1138).