source: Klonkt/test/youtube-playlist.test.js@ 995b100

main
Last change on this file since 995b100 was 995b100, checked in by Robin <roboburr@…>, 3 weeks ago

YouTube-playlists in een post, met dezelfde parsing als de hub

Een link naar een YouTube-album speelde het eerste nummer en stopte, en
een kale playlist-link werd helemaal niet als YouTube herkend.
detectProvider hield alleen de video-id vast en gooide list= weg.

De ref kent nu drie vormen, exact die van de Klonkt hub, zodat één ref
tussen de twee heen en weer kan zonder vertaling:

"<video>" een video
"<video>?list=<L>" die video, en door de lijst heen
"list:<L>" de hele playlist (YouTube's videoseries)

list mag voor of na v= staan en is in een gebakken href vaak
entity-gecodeerd (&amp;), dus er wordt over de hele URL gezocht in plaats
van op een vaste volgorde. youtube-nocookie.com telt mee als host: dat is
wat een embed zelf uitzendt en dus wat mensen terugplakken.

videoseries is EXACT elf tekens, net als een video-id. Geen lengte- of
grensregel vangt hem -- hij moet bij naam uitgesloten worden. Ik liep er
tijdens het bouwen zelf in met een grenscontrole die eroverheen leek te
gaan; vandaar de test die hem apart vastlegt.

Aan de clientkant (embed-player.js) kennen ytId/ytList/ytEmbedSrc dezelfde
drie vormen. Twee dingen die daar meekomen:

  • De poster interpoleerde een null video-id tot i.ytimg.com/vi/null/hqdefault.jpg -- een 404 als achtergrond. Een kale playlist heeft geen video, en krijgt nu gewoon geen poster.
  • YouTube meldt binnen een playlist "ended" TUSSEN elk tweetal nummers. Daar meteen onEnded op vuren geeft de wachtrij door na nummer één en kapt het album af. Op een lijst wachten we daarom 2,5 seconde, en telt alleen een stilte die niet door het volgende nummer wordt onderbroken -- dezelfde regel als in de hub.

De dode youtubeIframe() is meegegaan: hij wordt nergens aangeroepen, maar
een terugval die de playlist stil laat vallen is de ergste soort, want
die ziet eruit alsof het werkte.

Wat hier NIET in zit: de hub haalt ook de nummerlijst van een playlist op
(Data API met sleutel, anders keyless via de RSS-feed). Dat vraagt een
sleutel en een bewaarplek en is een aparte keuze.

Co-Authored-By: Claude Opus 5 <noreply@…>

  • Property mode set to 100644
File size: 3.6 KB
Line 
1// YouTube-playlists in een post (Bart, 17-8): dezelfde parsing als de Klonkt
2// hub, zodat een link naar een album ook als album speelt.
3//
4// Tot nu toe hield detectProvider alleen de video-id vast en gooide `list=`
5// weg, en een kale `youtube.com/playlist?list=…` herkende hij niet als YouTube.
6// Een link naar een album speelde daarmee het eerste nummer en stopte.
7//
8// De ref kent drie vormen, gelijk aan die van de hub, zodat één ref tussen de
9// twee heen en weer kan zonder vertaling:
10// "<video>" | "<video>?list=<L>" | "list:<L>"
11import { test } from 'node:test';
12import assert from 'node:assert/strict';
13
14const { default: AudioEmbedService } = await import('../src/services/AudioEmbedService.js');
15const det = (u) => AudioEmbedService.detectProvider(u);
16
17test('een gewone video blijft precies wat hij was', () => {
18 const r = det('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
19 assert.equal(r.provider, 'youtube');
20 assert.equal(r.id, 'dQw4w9WgXcQ');
21 assert.equal(r.list, null);
22 assert.equal(r.ref, 'dQw4w9WgXcQ');
23});
24
25test('een video BINNEN een playlist houdt allebei', () => {
26 for (const u of [
27 'https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=PLabc123def456',
28 'https://www.youtube.com/watch?list=PLabc123def456&v=dQw4w9WgXcQ', // andere volgorde
29 'https://www.youtube.com/watch?v=dQw4w9WgXcQ&amp;list=PLabc123def456', // uit een gebakken href
30 'https://youtu.be/dQw4w9WgXcQ?list=PLabc123def456',
31 ]) {
32 const r = det(u);
33 assert.equal(r.ref, 'dQw4w9WgXcQ?list=PLabc123def456', u);
34 assert.equal(r.id, 'dQw4w9WgXcQ', u);
35 assert.equal(r.list, 'PLabc123def456', u);
36 }
37});
38
39test('een kale playlist wordt herkend, en heeft geen video', () => {
40 const r = det('https://www.youtube.com/playlist?list=PLabc123def456');
41 assert.equal(r.provider, 'youtube');
42 assert.equal(r.id, null);
43 assert.equal(r.ref, 'list:PLabc123def456');
44});
45
46// Dit is de val: `videoseries` is EXACT elf tekens, net als een video-id. Geen
47// enkele lengteregel vangt hem; hij moet bij naam genoemd worden. Ik liep er bij
48// het bouwen zelf in, met een grenscontrole die eroverheen leek te gaan.
49test('videoseries is een markering, geen video-id', () => {
50 for (const u of [
51 'https://www.youtube.com/embed/videoseries?list=PLabc123def456',
52 'https://www.youtube-nocookie.com/embed/videoseries?list=PLabc123def456', // wat een embed zelf uitzendt
53 ]) {
54 const r = det(u);
55 assert.ok(r, u);
56 assert.equal(r.id, null, 'videoseries mag nooit als video-id doorgaan: ' + u);
57 assert.equal(r.ref, 'list:PLabc123def456', u);
58 }
59});
60
61test('een link zonder video en zonder lijst levert niets op', () => {
62 assert.equal(det('https://www.youtube.com/watch?x=1'), null);
63 assert.equal(det('javascript:alert(1)//youtu.be/dQw4w9WgXcQ'), null, 'het schema-slot blijft dicht');
64});
65
66test('de placeholder draagt de ref, niet alleen de video', () => {
67 const html = AudioEmbedService.generateIframe('youtube', det('https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=PLabc123def456'));
68 assert.match(html, /data-embed-ref="dQw4w9WgXcQ\?list=PLabc123def456"/);
69 const kaal = AudioEmbedService.generateIframe('youtube', det('https://www.youtube.com/playlist?list=PLabc123def456'));
70 assert.match(kaal, /data-embed-ref="list:PLabc123def456"/);
71});
72
73test('de iframe-terugval laat de playlist niet stilletjes vallen', () => {
74 assert.match(AudioEmbedService.youtubeIframe({ ref: 'list:PLabc123def456' }),
75 /embed\/videoseries\?list=PLabc123def456/);
76 assert.match(AudioEmbedService.youtubeIframe({ ref: 'dQw4w9WgXcQ?list=PLabc123def456' }),
77 /embed\/dQw4w9WgXcQ\?list=PLabc123def456/);
78 assert.match(AudioEmbedService.youtubeIframe({ id: 'dQw4w9WgXcQ' }), /embed\/dQw4w9WgXcQ"/);
79});
Note: See TracBrowser for help on using the repository browser.