diff --git a/apps/master-api/src/viaplay/play.ts b/apps/master-api/src/viaplay/play.ts index d1d3665..14bd3b7 100644 --- a/apps/master-api/src/viaplay/play.ts +++ b/apps/master-api/src/viaplay/play.ts @@ -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(); 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 { - const errors: string[] = []; +): Promise { 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,29 +570,23 @@ async function playEndedEventAsVod( settings.config.httpTimeoutMs, event ); - if (clip && !guids.includes(clip.guid)) { - const played = await resolveViaplayGuidPlayInner(sessionSecret, clip.guid, { - productUrl: clip.pageUrl, - }); - if ( - isDontGoPlaceholder(played.streamUrl) || - isLiveDashMpd(played.streamUrl) || - !isVodDashMpd(played.streamUrl) - ) { - errors.push(`${clip.guid}: clip was Don't go of live-dash`); - } else { - return { ...played, live: false }; - } + if (!clip || !isViaplayClipGuid(clip.guid) || guids.includes(clip.guid)) { + return null; } - } catch (err) { - errors.push(`clip: ${err instanceof Error ? err.message : String(err)}`); + const played = await resolveViaplayGuidPlayInner(sessionSecret, clip.guid, { + productUrl: clip.pageUrl, + }); + if ( + isDontGoPlaceholder(played.streamUrl) || + isLiveDashMpd(played.streamUrl) || + !isVodDashMpd(played.streamUrl) + ) { + return null; + } + return { ...played, live: false }; + } catch { + return null; } - - throw new AppError( - "UPSTREAM", - `Geen VOD-replay (vod-dash/vp-sports-clip). ${errors.slice(-3).join(" · ")}`, - 502 - ); } export async function ensureViaplayEventReady( @@ -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; } }