stremio/apps/master-api/src/viewer/ziggo-epg-art.test.ts
Jos Vooges | STH bc847b222d Fix empty Ziggo Sport event covers by keeping FAAB live thumbs.
Stop replacing working FAAB thumbs with Gracenote URLs that 404, and only enrich highlights after verifying EventImages exist.
2026-09-24 02:02:23 +02:00

152 lines
5 KiB
TypeScript

import {
artUrlsFromMergedId,
isLiveChannelThumb,
isReplayOrHighlightTitle,
isZiggoSportChannel,
needsZiggoArtEnrichment,
normalizeTitleTokens,
pickBestZiggoMatch,
segmentKeysForRange,
seriesAnchorTokens,
stripLiveThumbs,
titleOverlapScore,
timesOverlap,
type ZiggoEpgEvent,
} from "./ziggo-epg-art";
function assert(cond: unknown, msg: string) {
if (!cond) throw new Error(msg);
}
assert(isLiveChannelThumb("https://zst1-akm-cdn-triple.akamaized.net/live/zs1/thumb.jpg?scale=640x360"), "akamai live");
assert(isLiveChannelThumb("https://staticqbr-prod-nl.gnp.cloud.ziggogo.tv/image-service/latest/NL_000094_019321"), "latest");
assert(!isLiveChannelThumb("https://staticqbr-prod-nl.gnp.cloud.ziggogo.tv/image-service/ImagesEPG/EventImages/p24692584_bd_h8_aa.jpg"), "gracenote ok");
assert(isZiggoSportChannel("Ziggo Sport 1"), "zs1");
assert(isZiggoSportChannel("Ziggo Sport"), "zs");
assert(!isZiggoSportChannel("ESPN"), "espn");
assert(isReplayOrHighlightTitle("Moto3 BWIN Grand Prix of Austria (samenvatting)"), "samenvatting");
assert(
!needsZiggoArtEnrichment({
name: "ATP 250: Chengdu Open",
channel: "Ziggo Sport 1",
imageLandscape: "https://zst1-akm-cdn-triple.akamaized.net/live/zs1/thumb.jpg?scale=640",
images: [],
}),
"keep FAAB live thumb for normal events"
);
assert(
needsZiggoArtEnrichment({
name: "Moto3 BWIN Grand Prix of Austria (samenvatting)",
channel: "Ziggo Sport 1",
imageLandscape: "https://zst1-akm-cdn-triple.akamaized.net/live/zs1/thumb.jpg?scale=640",
images: [],
}),
"enrich highlight live thumb"
);
assert(
needsZiggoArtEnrichment({
name: "ATP 250",
channel: "Ziggo Sport 1",
imageLandscape: "https://go.ziggosporttotaal.nl/assets/channels/light/ziggo_sport_1.png",
images: [],
}),
"enrich logo-only"
);
const arts = artUrlsFromMergedId("24692584|nl");
assert(arts?.landscape.includes("p24692584_bd_h8_aa.jpg"), "landscape url");
assert(arts?.portrait.includes("p24692584_b_v12_aa.jpg"), "portrait url");
assert(titleOverlapScore("GT World Challenge: Nederland Race 2", "GT World Challenge Hoogtepunten Nederland: Race 2") >= 0.5, "overlap");
assert(normalizeTitleTokens("Ziggo Sport: GT World Challenge").has("gtworld"), "gtworld alias");
assert(normalizeTitleTokens("Grand Prix of Austria").has("oostenrijk"), "austria→oostenrijk");
assert(seriesAnchorTokens("Moto3 BWIN Grand Prix of Austria").has("moto3"), "anchor moto3");
const start = Date.parse("2026-09-20T23:00:00Z");
const end = Date.parse("2026-09-21T00:00:00Z");
assert(timesOverlap(start, end, 1789945200, 1789948800), "time overlap");
const candidates: ZiggoEpgEvent[] = [
{
id: "a",
channelId: "NL_000094_019321",
title: "GT World Challenge Hoogtepunten",
seriesName: "Nederland: Race 2",
startTime: 1789945200,
endTime: 1789948800,
mergedId: "24692584|nl",
},
{
id: "b",
channelId: "NL_000094_019321",
title: "Voetbalavond",
startTime: 1789945200,
endTime: 1789948800,
mergedId: "1|nl",
},
];
const hit = pickBestZiggoMatch(candidates, {
title: "GT World Challenge: Nederland Race 2 (hoogtepunten)",
startMs: start,
endMs: end,
});
assert(hit?.id === "a", "pick GT not football");
// Moto3 samenvatting days later than live session — must still resolve via loose match
const motoCands: ZiggoEpgEvent[] = [
{
id: "m3",
channelId: "NL_000094_019321",
title: "Moto3",
seriesName: "GP van Oostenrijk: Kwalificatie 2",
startTime: 1789815900,
endTime: 1789817700,
mergedId: "15289756|nl",
},
{
id: "foot",
channelId: "NL_000094_019321",
title: "Eredivisie samenvatting",
seriesName: "Ajax - PSV",
startTime: 1789972200,
endTime: 1789974000,
mergedId: "999|nl",
},
];
const motoHit = pickBestZiggoMatch(motoCands, {
title: "Moto3 BWIN Grand Prix of Austria (samenvatting)",
startMs: Date.parse("2026-09-21T06:30:00Z"),
endMs: Date.parse("2026-09-21T07:00:00Z"),
});
assert(motoHit?.id === "m3", `moto3 loose match got ${motoHit?.id}`);
assert(motoHit?.mergedId === "15289756|nl", "moto3 mergedId");
const stripped = stripLiveThumbs(
{
id: "x",
name: "Moto3",
channel: "Ziggo Sport 1",
network: "Ziggo Sport 1",
start: "2026-09-21T06:30:00Z",
stop: "2026-09-21T07:00:00Z",
imageLandscape: "https://zst1-akm-cdn-triple.akamaized.net/live/zs1/thumb.jpg?scale=640",
imageBackdrop: null,
imagePortrait: null,
logoUrl: null,
images: [
"https://go.ziggosporttotaal.nl/assets/channels/light/ziggo_sport_1.png",
"https://zst1-akm-cdn-triple.akamaized.net/live/zs1/thumb.jpg?scale=640",
],
},
"https://go.ziggosporttotaal.nl/assets/channels/light/ziggo_sport_1.png"
);
assert(!isLiveChannelThumb(stripped.imageLandscape), "stripped landscape");
assert(!(stripped.images ?? []).some(isLiveChannelThumb), "no live thumbs left");
const keys = segmentKeysForRange(start, end);
assert(keys.length >= 1, "segment keys");
assert(keys.every((k) => /^\d{14}$/.test(k)), "key format");
console.log("ziggo-epg-art tests ok");