Changeset 9026de5 in Klonkt
- Timestamp:
- 08/16/2026 02:25:04 PM (3 weeks ago)
- Branches:
- main
- Children:
- 749605a
- Parents:
- 7090fd2
- Files:
-
- 2 edited
-
src/services/music/index.js (modified) (5 diffs)
-
test/ap-fw-track.test.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/services/music/index.js
r7090fd2 r9026de5 485 485 if (!pl) return null; 486 486 const abs = (u) => !u ? null : (/^https?:/i.test(u) ? u : `${base}${u.startsWith('/') ? '' : '/'}${u}`); 487 // GEEN epoch als terugval. `published` is bij hen verplicht, maar 1970 is een 488 // ANTWOORD en geen ontbrekend veld -- en dat is erger: een lezer kan een gat 489 // opmerken, een leugen niet. playlists.created_at heeft een default, dus als 490 // hij hier ontbreekt is er een leespad dat de kolom laat vallen. Dat willen we 491 // zien, niet maskeren. (Zo kwam op 16-8 de route boven water die id, title, 492 // artist, year, cover_url en kind selecteerde en de rest niet.) 493 const wanneer = pl.created_at ? new Date(pl.created_at).toISOString() : null; 487 // WANNEER IS DEZE PLAAT GEPUBLICEERD. De post die hem uitbrengt gaat voor, en 488 // niet als noodgreep maar omdat hij het beter weet: playlists.created_at is 489 // het moment waarop de RIJ is aangemaakt, en dat kan weken eerder zijn terwijl 490 // je nog aan het samenstellen was. AS2 `published` vraagt wanneer het object 491 // openbaar werd, en dat is de post. 492 // 493 // GEEN epoch als laatste terugval. `published` is bij hen verplicht, maar 1970 494 // is een ANTWOORD en geen ontbrekend veld -- en dat is erger: een lezer kan een 495 // gat opmerken, een leugen niet. Zo kwam op 16-8 de route boven water die id, 496 // title, artist, year, cover_url en kind selecteerde en de rest niet. 497 // 498 // OOK VOOR `released`, en daar had ik het eerst mis (Robin, 16-8). Mijn 499 // bezwaar was: post je vandaag een plaat uit 2018, dan beweert dit dat hij 500 // vandaag uitkwam. Dat gebeurt ook -- maar bij de meeste Klonkt-sites IS de 501 // post het uitbrengen, en GEEN datum is slechter dan een datum die op het 502 // gewone geval klopt. Het handmatige veld is precies het gereedschap voor de 503 // uitzondering: bij een heruitgave vul je hem in en die wint. 504 const postDatum = (pl._post && pl._post.uit_wanneer) ? new Date(pl._post.uit_wanneer) : null; 505 const wanneer = postDatum ? postDatum.toISOString() 506 : (pl.created_at ? new Date(pl.created_at).toISOString() : null); 494 507 // Dezelfde lening als in buildPlaylistCollection: de post die de plaat 495 508 // uitbrengt geeft zijn titel, en de eigen titel blijft als alsoKnownAs staan. … … 504 517 }; 505 518 if (titel !== pl.title) album.alsoKnownAs = pl.title; 506 // `released` alleen als er een ECHTE datum is. `year` vult hem niet aan: een 507 // jaartal is geen dag, en dat is de reden dat release_date bestaat. 519 // Het ingevulde veld wint altijd; anders de DAG waarop de post verscheen. 520 // `year` vult hem nog steeds niet aan, en dat is geen inconsequentie: een 521 // jaartal is geen dag, terwijl de postdatum een gebeurtenis is die werkelijk 522 // heeft plaatsgevonden. Het verschil is verzinnen versus afleiden. 508 523 if (pl.release_date) album.released = pl.release_date; 524 else if (postDatum) album.released = postDatum.toISOString().slice(0, 10); 509 525 if (pl.mb_release_id) album.musicbrainzId = pl.mb_release_id; 510 526 const hoes = abs(pl.cover_url || null); … … 522 538 const hostPosts = site.id ? trackHostPosts(site.id) : null; 523 539 const albums = site.id ? trackAlbums(site.id) : null; 540 // EEN keer opzoeken en twee keer gebruiken: het Album leent er zijn datums en 541 // titel van, leenVanPost onderaan zijn tekst en tags. Twee losse aanroepen 542 // zouden niet alleen dubbel werk zijn maar ook uiteen kunnen lopen -- en dan 543 // staat er weer iets anders op het ingesloten object dan op zijn eigen URI. 544 const post = site.id ? uitgavePost(site.id, playlist.id) : null; 524 545 const items = (rows || []).map((r) => buildTrackAudio(base, site, r, { coverFallback: playlist.cover_url || null, hostPosts, albums })); 525 546 const out = pagedCollection(`${actorId(base, site.slug)}/playlists/${playlist.id}`, items, { … … 547 568 // staat toch al ingesloten op de track. 548 569 if ((playlist.kind || 'album') === 'album') { 549 const album = buildAlbumObject(base, site, playlist);570 const album = buildAlbumObject(base, site, { ...playlist, _post: post }); 550 571 for (const veld of ['published', 'released', 'musicbrainzId', 'artist_credit', 'image']) { 551 572 if (album[veld] !== undefined) out[veld] = album[veld]; 552 573 } 553 574 } 554 return leenVanPost(base, site, out, uitgavePost(site.id, playlist.id));575 return leenVanPost(base, site, out, post); 555 576 } 556 577 … … 577 598 try { 578 599 const rijen = db.prepare(` 579 SELECT id, slug, title, excerpt, content, cover_image_url, tags 600 SELECT id, slug, title, excerpt, content, cover_image_url, tags, 601 COALESCE(published_at, created_at) AS uit_wanneer 580 602 FROM posts 581 603 WHERE site_id = ? AND status = 'published' -
test/ap-fw-track.test.js
r7090fd2 r9026de5 204 204 assert.equal(col.artist_credit, undefined); 205 205 }); 206 207 test('published EN released lenen de datum van de uitgavepost', () => { 208 // De post is het moment van uitbrengen. Geen datum is slechter dan een datum 209 // die op het gewone geval klopt; voor een heruitgave vul je het veld in. 210 db.prepare(`INSERT INTO posts (id, site_id, author_id, slug, title, content, status, published_at) 211 VALUES ('p-uit','s1','u1','de-plaat-uit','De Plaat Is Er','<p>[[playlist:de-plaat]]</p>','published','2026-05-04T12:00:00Z')`).run(); 212 // De fixture zette hierboven al een release_date; die wint terecht, dus voor 213 // DEZE test moet hij weg. (Dat de eerste versie hier omviel is het bewijs dat 214 // de voorrang werkt.) 215 db.prepare("UPDATE playlists SET release_date = NULL WHERE id = 'de-plaat'").run(); 216 const al = audio('t1').track.album; 217 assert.equal(al.published, '2026-05-04T12:00:00.000Z'); 218 assert.equal(al.released, '2026-05-04', 'released is een DAG, geen tijdstip'); 219 }); 220 221 test('een ingevulde uitgavedatum wint van de postdatum', () => { 222 // Dit is het geval waarvoor het veld bestaat: oud werk dat je vandaag post. 223 db.prepare("UPDATE playlists SET release_date = '2018-09-01' WHERE id = 'de-plaat'").run(); 224 const al = audio('t1').track.album; 225 assert.equal(al.released, '2018-09-01', 'de postdatum overschreef het ingevulde veld'); 226 db.prepare("UPDATE playlists SET release_date = NULL WHERE id = 'de-plaat'").run(); 227 }); 228 229 test('geen post en geen veld: dan geen released', () => { 230 // Afwezig is afwezig -- we leiden af waar er iets af te leiden valt, en 231 // verzinnen niets waar dat niet zo is. 232 db.prepare("INSERT INTO playlists (id, site_id, title, kind) VALUES ('kaal','s1','Kale Plaat','album')").run(); 233 db.prepare("INSERT INTO playlist_tracks (playlist_id, track_id, position) VALUES ('kaal','t9',1)").run(); 234 const al = audio('t9').track.album; 235 assert.equal(al.name, 'Kale Plaat'); 236 assert.equal(al.released, undefined); 237 }); 238 239 test('een GEPLANDE post: de geplande dag telt, niet wanneer de worker draaide', () => { 240 // Robins vraag (16-8). Drie schakels moeten kloppen: 241 // 242 // 1. zolang de post 'scheduled' is vindt uitgavePost hem NIET (die filtert 243 // op status='published'), dus de plaat heeft nog geen uitgavedatum -- 244 // hij is immers nog niet uit; 245 // 2. de Scheduler zet published_at op COALESCE(published_at, publish_at, 246 // CURRENT_TIMESTAMP), dus op de GEPLANDE tijd; 247 // 3. wij lezen COALESCE(published_at, created_at) en komen daar dus op uit. 248 // 249 // Dat derde punt is waarom created_at hier nooit wint: bij een gepubliceerde 250 // post staat published_at altijd gevuld. En punt 2 is waarom een server die 251 // een uur plat lag geen uur te late uitgavedatum oplevert. 252 db.prepare("INSERT INTO playlists (id, site_id, title, kind) VALUES ('gepland','s1','Geplande Plaat','album')").run(); 253 db.prepare("INSERT INTO playlist_tracks (playlist_id, track_id, position) VALUES ('gepland','t2',1)").run(); 254 db.prepare(`INSERT INTO posts (id, site_id, author_id, slug, title, content, status, publish_at, created_at, published_at) 255 VALUES ('p-gepland','s1','u1','komt-nog','Komt Nog','<p>[[playlist:gepland]]</p>','scheduled', 256 '2026-12-24T09:00:00Z','2026-06-01T08:00:00Z',NULL)`).run(); 257 258 // Nog gepland: geen datum, want de plaat is nog niet uit. 259 assert.equal(audio('t2').track.album.released, undefined, 'een geplande post bracht al iets uit'); 260 261 // De Scheduler doet zijn werk -- en draait expres LATER dan gepland. 262 db.prepare(`UPDATE posts SET status = 'published', 263 published_at = COALESCE(published_at, publish_at, CURRENT_TIMESTAMP) WHERE id = 'p-gepland'`).run(); 264 265 const al = audio('t2').track.album; 266 assert.equal(al.released, '2026-12-24', 'niet de geplande dag'); 267 assert.equal(al.published, '2026-12-24T09:00:00.000Z'); 268 assert.notEqual(al.released, '2026-06-01', 'de creatiedatum lekte door'); 269 });
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)