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");