feat(downloads): download completed Xtream catch-up programmes as TS (#1572)

* feat(epg): copy catch-up programme URLs without changing playback

* feat(downloads): save completed Xtream archive programmes as TS

* fix(epg): let newer archive copy requests supersede pending work

* fix(downloads): protect archive partials and independent submissions

* fix(downloads): verify archive identity through finalization

* fix(downloads): bound archive storage and capture cleanup entries

* fix(downloads): preserve archive ownership across failure paths

* fix(downloads): recover explicitly verified archive completions

* fix(downloads): journal archive promotion before publishing files

* fix(downloads): reset archive proof before an explicit restart

* fix(downloads): preserve archive recovery ownership and interruption

* fix(downloads): verify durable archive identity at resume open

* fix(downloads): fence archive commands during completion commit

* fix(downloads): persist archive ownership throughout its lifecycle

* fix(downloads): protect archive removal and missing-file recovery

* fix(downloads): journal private cleanup captures for recovery

* fix(downloads): journal active archive cleanup before removal

* fix(downloads): clean settled archives before deleting stale rows

* fix(downloads): preserve archive ownership on removal and resubmission

* fix(downloads): recover proven archive completions before retry

* fix(downloads): recover local archives before remote transfer checks

* test(downloads): resolve archive fixture from workspace root

* fix(downloads): distinguish reused archive inodes by creation time

* fix(downloads): bind fresh archive reservations to owned files

* fix(downloads): clean reservations when ownership writes fail

* fix(downloads): commit archive reservation and ownership atomically

* fix(downloads): retain captures until replacement restoration succeeds

* fix(downloads): require durable ownership before cleanup relocation

* fix(downloads): preserve 64-bit archive file identities on Windows

* refactor(release): keep capture fixture constants in their shared module

* fix(downloads): preserve the last link of captured foreign files

* fix(downloads): expose retained archive recovery files

* fix(downloads): keep recovery instructions open while copying
This commit is contained in:
4gray authored and GitHub committed 2026-09-08 20:33:05 +02:00
1 parent a7f3860102
commit bad8a0991e
117 files changed
+7510 -880

No files matched your search

+2
View File
@@ -94,3 +94,5 @@ export * from './lib/stalker-vod-details.interface';
// Unified VOD details (discriminated union + adapters)
export * from './lib/vod-details-adapters';
export * from './lib/vod-details-item.interface';
export * from './lib/catchup-download.interface';
@@ -0,0 +1,17 @@
/** Provider-clock instants in seconds; independent of the viewer's EPG offset. */
export interface CatchupDownloadMetadata {
channelName: string;
startTimestamp: number;
stopTimestamp: number;
/** Last known archive availability; absent when the provider gives no window. */
expiresAt?: number;
}
export type DownloadContentType = 'vod' | 'episode' | 'catchup';
/** Manual recovery is required before a captured unrelated file can be released. */
export interface DownloadRecoveryResult {
success: boolean;
error?: string;
recoveryPath?: string;
}
@@ -1,3 +1,8 @@
import type {
CatchupDownloadMetadata,
DownloadRecoveryResult,
DownloadContentType,
} from './catchup-download.interface';
import {
EmbeddedMpvBounds,
EmbeddedMpvRecordingStartOptions,
@@ -585,7 +590,8 @@ export interface ElectronBridgeDownloadHeaders {
export interface ElectronBridgeDownloadStartPayload {
playlistId: string;
xtreamId: number;
contentType: ElectronBridgePlaybackContentType;
contentType: DownloadContentType;
catchup?: CatchupDownloadMetadata | null;
title: string;
url: string;
posterUrl?: string;
@@ -616,7 +622,8 @@ export interface ElectronDownloadItem {
id: number;
playlistId: string;
xtreamId: number;
contentType: ElectronBridgePlaybackContentType;
contentType: DownloadContentType;
catchup?: CatchupDownloadMetadata | null;
seriesXtreamId?: number;
seasonNumber?: number;
episodeNumber?: number;
@@ -1290,7 +1297,7 @@ export interface ElectronBridgeApi {
downloadsRedownloadMissing: (
downloadId: number
) => Promise<ElectronBridgeDownloadRedownloadResult>;
downloadsRemove: (downloadId: number) => Promise<ElectronBridgeErrorResult>;
downloadsRemove: (downloadId: number) => Promise<DownloadRecoveryResult>;
downloadsGetList: (playlistId?: string) => Promise<ElectronDownloadItem[]>;
downloadsGet: (downloadId: number) => Promise<ElectronDownloadItem | null>;
downloadsUpdateMetadata: (
@@ -1305,7 +1312,7 @@ export interface ElectronBridgeApi {
downloadsPlayFile: (filePath: string) => Promise<ElectronBridgeErrorResult>;
downloadsClearCompleted: (
playlistId?: string
) => Promise<ElectronBridgeResult>;
) => Promise<DownloadRecoveryResult>;
onDownloadsUpdate: (callback: () => void) => () => void;
// Live-TV recordings surface. Optional: older Electron builds have no
// recordings bridge, and `supportsRecordings` (not `supportsDownloads`)