import { ensureViaplayEventReady } from "./play"; import { loadViaplayConfigOnly, saveViaplayPreLiveResult, } from "./settings"; export type ViaplayPreLiveSummary = { checked: number; refreshed: number; skipped: number; failed: number; durationMs: number; triggeredBy: "schedule" | "manual"; }; async function sleep(ms: number) { if (ms <= 0) return; await new Promise((r) => setTimeout(r, ms)); } export async function runViaplayPreLive( sessionSecret: string, triggeredBy: "schedule" | "manual" = "manual" ): Promise { const started = Date.now(); const config = await loadViaplayConfigOnly(); const counts = { checked: 0, refreshed: 0, skipped: 0, failed: 0 }; if (!config) { return { ...counts, durationMs: 0, triggeredBy }; } const now = Date.now(); const windowMs = config.preLiveMinutes * 60_000; const concurrency = config.preLiveConcurrency; const staggerMs = config.preLiveStaggerMs; const fetchKeys = config.fetchKeysIfMissing; const candidates = config.events.filter((e) => { // binnen pre-live venster of al live; niet ended if (e.endMs < now) return false; if (e.startMs - now > windowMs) return false; // cache-first: skip als MPD + keys al klaar if (e.mpdUrl && e.hasKeys) return false; // clear feeds zonder DRM: skip als MPD al gecached en geen PSSH if (e.mpdUrl && e.hasPssh === false && e.mpdCachedAt) return false; return true; }); counts.checked = candidates.length; let active = 0; const queue = [...candidates]; async function worker() { for (;;) { const event = queue.shift(); if (!event) return; while (active >= concurrency) { await sleep(200); } active += 1; try { await ensureViaplayEventReady(sessionSecret, event, { fetchKeys, }); counts.refreshed += 1; } catch { counts.failed += 1; } finally { active -= 1; if (staggerMs > 0) { await sleep(staggerMs); } } } } const workers = Array.from( { length: Math.min(concurrency, Math.max(1, candidates.length)) }, () => worker() ); if (!candidates.length) counts.skipped = config.events.length; await Promise.all(workers); const summary: ViaplayPreLiveSummary = { ...counts, durationMs: Date.now() - started, triggeredBy, }; await saveViaplayPreLiveResult(summary as unknown as Record); return summary; } let workerStarted = false; export function startViaplayPreLiveWorker(getSecret: () => string) { if (workerStarted) return; workerStarted = true; const tick = async () => { try { const config = await loadViaplayConfigOnly(); if (!config?.preLiveEnabled) return; if (!config.accounts.some((a) => a.enabled !== false)) return; await runViaplayPreLive(getSecret(), "schedule"); } catch { /* worker mag niet crashen */ } }; // eerste tick na 45s, daarna per interval uit settings (min 30s) setTimeout(() => { void tick(); setInterval(() => { void (async () => { const config = await loadViaplayConfigOnly(); const sec = config?.preLiveIntervalSeconds ?? 60; // setInterval fixed; we just run tick — interval is approx 60s base void sec; await tick(); })(); }, 60_000); }, 45_000); }