Fix Viaplay stream-href template expansion that broke VOD play.
RFC 6570 {?params} must become ?, not be stripped — otherwise byguid query is invalid and play fails.
This commit is contained in:
parent
c6bd855334
commit
2e6dc3bab9
1 changed files with 47 additions and 16 deletions
|
|
@ -709,14 +709,17 @@ function parsePlayStreamBody(
|
|||
|
||||
/**
|
||||
* Bouw play.viaplay.com URL uit templated stream-href (content-API).
|
||||
* Strip `{?deviceId,...}` en vul device-params + bestaande query.
|
||||
* RFC 6570 `{?deviceId,...}` → `?` (niet strippen: anders blijft `byguid&deviceKey=` over).
|
||||
*/
|
||||
export function expandViaplayStreamHref(
|
||||
hrefRaw: string,
|
||||
creds: ViaplayAccountCreds,
|
||||
opts: { deviceKey: string }
|
||||
): string {
|
||||
const cleaned = hrefRaw.replace(/\{\?[^}]+\}/g, "");
|
||||
const cleaned = hrefRaw
|
||||
.replace(/\{\?[^}]+\}/g, "?")
|
||||
.replace(/\?&/, "?")
|
||||
.replace(/\?{2,}/g, "?");
|
||||
const u = new URL(cleaned);
|
||||
u.searchParams.set("deviceId", creds.deviceId || randomUUID());
|
||||
u.searchParams.set("deviceName", "web");
|
||||
|
|
@ -854,22 +857,50 @@ export async function playByGuid(
|
|||
`play-byguid mislukt (${res.status})`;
|
||||
throw new Error(msg);
|
||||
}
|
||||
const played = parsePlayStreamBody(body, guid);
|
||||
let played = parsePlayStreamBody(body, guid);
|
||||
if (!played.title && pageTitle) played.title = pageTitle;
|
||||
|
||||
// Fallback-promo herkennen
|
||||
const title = (played.title || "").toLowerCase();
|
||||
if (/viaplay\s*presents|don'?t\s*go|viaplay\s*documentary/i.test(title)) {
|
||||
throw new Error(
|
||||
`Viaplay gaf fallback-stream (“${played.title}”) — check tokens/producturl`
|
||||
);
|
||||
}
|
||||
if (played.mpdUrl && /live-dash|play-live|tve_/i.test(played.mpdUrl)) {
|
||||
throw new Error("Viaplay gaf live-stream i.p.v. VOD voor deze clip");
|
||||
}
|
||||
// Clips horen op vod-cdn
|
||||
if (played.mpdUrl && !/vod-/i.test(played.mpdUrl)) {
|
||||
throw new Error(`Onverwachte VOD-MPD host: ${played.mpdUrl.slice(0, 80)}`);
|
||||
// Kapotte stream-href of ontbrekende producturl → promo-docu.
|
||||
// Dan één keer opnieuw met expliciete HAR-query i.p.v. hard falen.
|
||||
const titleLc = (played.title || "").toLowerCase();
|
||||
const looksLikePromo = /viaplay\s*presents|don'?t\s*go|viaplay\s*documentary/i.test(
|
||||
titleLc
|
||||
);
|
||||
if (looksLikePromo && streamHref) {
|
||||
let productUrlFinal = productUrl;
|
||||
try {
|
||||
const pu = new URL(productUrl);
|
||||
if (!pu.searchParams.has("partial")) pu.searchParams.set("partial", "true");
|
||||
productUrlFinal = pu.toString();
|
||||
} catch {
|
||||
/* keep */
|
||||
}
|
||||
const returnUrl =
|
||||
(opts.returnUrl && String(opts.returnUrl).trim()) ||
|
||||
`https://content.viaplay.com/${opts.deviceKey}/sport`;
|
||||
const sectionPath = (opts.sectionPath && String(opts.sectionPath).trim()) || "/sport";
|
||||
const u = new URL("https://play.viaplay.com/api/stream/byguid");
|
||||
u.searchParams.set("deviceId", creds.deviceId || randomUUID());
|
||||
u.searchParams.set("deviceName", "web");
|
||||
u.searchParams.set("deviceType", "pc");
|
||||
u.searchParams.set("userAgent", VIAPLAY_USER_AGENT);
|
||||
u.searchParams.set("deviceKey", opts.deviceKey);
|
||||
u.searchParams.set("guid", guid);
|
||||
u.searchParams.set("cse", "true");
|
||||
u.searchParams.set("producturl", productUrlFinal);
|
||||
u.searchParams.set("returnurl", returnUrl);
|
||||
u.searchParams.set("sectionPath", sectionPath);
|
||||
u.searchParams.set("defaultAvailabilityContext", "svod");
|
||||
if (creds.profileId) u.searchParams.set("profileId", creds.profileId);
|
||||
const retry = await fetchJson(u.toString(), {
|
||||
headers: authHeaders(creds),
|
||||
timeoutMs: opts.timeoutMs,
|
||||
});
|
||||
const retryBody = asRecord(retry.json);
|
||||
if (retry.status === 200 && retryBody) {
|
||||
played = parsePlayStreamBody(retryBody, guid);
|
||||
if (!played.title && pageTitle) played.title = pageTitle;
|
||||
}
|
||||
}
|
||||
return played;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue