// Live PeerTube + Rumble — capacité « direct » testée hors réseau. // - mapPeertubeItem : règle `isLive` → type/kind/isLive (doctrine phase 3.2), // durée jamais émise sur un direct, viewers = spectateurs. // - parseCardsHtml mode 'live' : items de rumble.com/browse/live typés live, // jamais des Shorts, slug de chaîne extrait (filtre channel-content). import { mapPeertubeItem } from '../providers/peertube.mjs'; import { parseCardsHtml } from '../providers/rumble.mjs'; import { isLiveItem, isShortItem } from '../search-filters.mjs'; let pass = 0; const eq = (a, b, m) => { const x = JSON.stringify(a), y = JSON.stringify(b); if (x !== y) throw new Error(`${m}\n expected ${y}\n got ${x}`); pass++; console.log(` V ${m}`); }; // --- PeerTube : item en direct --- const live = mapPeertubeItem({ uuid: 'u1', name: 'Direct', url: 'https://instance/w/u1', isLive: true, viewers: 42, duration: 123, views: 5, account: { displayName: 'A' }, channel: { name: 'ch' }, }); eq(live.type, 'live', 'PT live: type live'); eq(live.kind, 'live', 'PT live: kind live'); eq(live.isLive, true, 'PT live: isLive posé'); eq(live.duration, undefined, 'PT live: durée jamais émise (temps écoulé)'); eq(live.viewers, 42, 'PT live: viewers = spectateurs'); eq(live.views, 5, 'PT live: vues conservées (live a les deux compteurs)'); eq(isLiveItem(live), true, 'isLiveItem serveur le classe live'); eq(isShortItem(live, 'peertube'), false, 'un direct n’est jamais un Short'); // --- PeerTube : VOD classique inchangée --- const vod = mapPeertubeItem({ uuid: 'u2', name: 'Vid', duration: 123, isLive: false }); eq(vod.type, 'video', 'PT vod: type video'); eq(vod.kind, 'vod', 'PT vod: kind vod'); eq(vod.duration, 123, 'PT vod: durée conservée'); eq(vod.isLive, undefined, 'PT vod: pas de champ isLive inventé'); eq(isLiveItem(vod), false, 'PT vod n’est pas live'); // --- Rumble : mode live sur une carte type browse --- const html = ``; const items = parseCardsHtml(html, { mode: 'live' }); eq(items.length, 2, 'mode live: 2 cartes parsées'); const [i1] = items; eq(i1.videoId, 'v9z1live', 'mode live: id extrait au slug'); eq(i1.type, 'live', 'mode live: type live'); eq(i1.kind, 'live', 'mode live: kind live'); eq(i1.isLive, true, 'mode live: isLive posé'); eq(i1.isShort, false, 'mode live: jamais un Short'); eq(i1.channelId, 'WarRoom', 'mode live: slug de chaîne extrait'); eq(isLiveItem(i1), true, 'mode live passe isLiveItem'); // --- Même HTML en mode browse : tout reste une VOD (pas de régression) --- const browse = parseCardsHtml(html, { mode: 'browse' }); eq(browse[0].type, 'video', 'mode browse: type video (pas de fuite live)'); eq(browse[0].isLive, undefined, 'mode browse: pas de isLive inventé'); eq(browse[0].isShort, false, 'mode browse: durée inconnue => pas short'); eq(browse[0].channelId, 'WarRoom', 'mode browse: channelId extrait (additif)'); console.log(`\nOK ${pass} assertions`);