Fall back to KAP catch-up when an ended event has no byguid VOD.

This commit is contained in:
Jos Vooges | STH 2026-09-28 23:49:57 +02:00
parent 2137235881
commit d06b984b9d

View file

@ -458,21 +458,25 @@ async function dropEventMpdCache(mediaGuid: string, reason: string) {
});
}
function isViaplayClipGuid(guid: string | null | undefined): boolean {
return /vp-sports-clip/i.test(String(guid || ""));
}
function isNoPrioritizedVideo(message: string | null | undefined): boolean {
return /no prioritized video found/i.test(String(message || ""));
}
function vodGuidCandidates(event: ViaplayEventSnapshot): string[] {
const out: string[] = [];
const seen = new Set<string>();
const push = (raw: string | null | undefined) => {
const g = String(raw || "").trim();
if (!g || seen.has(g)) return;
if (!g || seen.has(g) || !isViaplayClipGuid(g)) return;
seen.add(g);
out.push(g);
};
push(event.guid);
push(event.mediaGuid);
for (const g of [...out]) {
if (/-NL$/i.test(g)) push(g.replace(/-NL$/i, ""));
else if (!/vp-sports-clip/i.test(g)) push(`${g}-NL`);
}
return out;
}
@ -531,14 +535,13 @@ async function findCatchupClip(
}
/**
* Terugkijken = VOD (HAR: play.viaplay.com/byguid → vod-dash / vp-sports-clip),
* niet KAP op een live-TV-MPD die al is afgelopen.
* Alleen echte clips (HAR: vp-sports-clip → vod-dash). Live-EPG-id's (S2609…)
* hebben geen byguid-VOD — die gaan via play-live + KAP.
*/
async function playEndedEventAsVod(
async function tryEndedEventVod(
sessionSecret: string,
event: ViaplayEventSnapshot
): Promise<ResolveViaplayPlayResult> {
const errors: string[] = [];
): Promise<ResolveViaplayPlayResult | null> {
const guids = vodGuidCandidates(event);
for (const guid of guids) {
@ -551,14 +554,12 @@ async function playEndedEventAsVod(
isLiveDashMpd(played.streamUrl) ||
!isVodDashMpd(played.streamUrl)
) {
errors.push(`${guid}: geen vod-dash (${mediaPathOf(played.streamUrl)})`);
continue;
}
return { ...played, live: false };
} catch (err) {
errors.push(
`${guid}: ${err instanceof Error ? err.message : String(err)}`
);
const msg = err instanceof Error ? err.message : String(err);
if (isNoPrioritizedVideo(msg)) break;
}
}
@ -569,7 +570,9 @@ async function playEndedEventAsVod(
settings.config.httpTimeoutMs,
event
);
if (clip && !guids.includes(clip.guid)) {
if (!clip || !isViaplayClipGuid(clip.guid) || guids.includes(clip.guid)) {
return null;
}
const played = await resolveViaplayGuidPlayInner(sessionSecret, clip.guid, {
productUrl: clip.pageUrl,
});
@ -578,21 +581,13 @@ async function playEndedEventAsVod(
isLiveDashMpd(played.streamUrl) ||
!isVodDashMpd(played.streamUrl)
) {
errors.push(`${clip.guid}: clip was Don't go of live-dash`);
} else {
return null;
}
return { ...played, live: false };
} catch {
return null;
}
}
} catch (err) {
errors.push(`clip: ${err instanceof Error ? err.message : String(err)}`);
}
throw new AppError(
"UPSTREAM",
`Geen VOD-replay (vod-dash/vp-sports-clip). ${errors.slice(-3).join(" · ")}`,
502
);
}
export async function ensureViaplayEventReady(
sessionSecret: string,
@ -609,7 +604,8 @@ export async function ensureViaplayEventReady(
const ended = Date.now() > event.endMs;
if (ended) {
return await playEndedEventAsVod(sessionSecret, event);
const vod = await tryEndedEventVod(sessionSecret, event);
if (vod) return vod;
}
const cachedMpd = channelMpdFromEvents(settings.config.events, event);
@ -1194,6 +1190,8 @@ async function resolveViaplayGuidPlayInner(
triedAccounts: triedLabels.length,
triedLabels,
});
// Product heeft geen VOD — andere accounts geven hetzelfde.
if (isNoPrioritizedVideo(lastError.message)) break;
}
}