Changeset 4d81de5 in Klonkt


Ignore:
Timestamp:
08/08/2026 05:30:29 AM (5 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
cf5073b
Parents:
34e63f0
git-author:
Robin <roboburr@…> (08/08/2026 05:28:46 AM)
git-committer:
Robin <roboburr@…> (08/08/2026 05:30:29 AM)
Message:

De feed vertelt ook WAT voor kanaal dit is

Funkwhale maakte van dev@… een kanaal en las de rss_url netjes uit
de Link-array op onze actor -- maar liet content_category leeg. Dat is de
aanwijzing: hij bouwt zo'n kanaal langs de RSS-kant op, en leest de categorie
daar. Niet uit category op de AP-actor.

Dus itunes-velden erbij op kanaalniveau: author, summary, image (de site-avatar,
absoluut gemaakt) en category. En per track de eigen artiest en hoes, naast de
duur die er al stond.

EN IK HEB MIJN EIGEN CATEGORIE-REGEL AANGESCHERPT. Die keek naar ELKE track,
ook een gated -- zodat een site met uitsluitend afgeschermde muziek toch "hier
is muziek" naar de hele fediverse riep. Dat botst met de regel die we overal
aanhouden: een gesloten track is AFWEZIG, niet stilletjes aanwezig. Nu tellen
alleen opengezette tracks, en zeggen de feed en de actor hetzelfde. Er staat
een test op die precies dat vastlegt: een gated track maakt er nog geen
muziekkanaal van.

Dat maakt de regel strenger dan hij vanmiddag was. Bewust: naar buiten toe is
een kanaal zonder publieke muziek geen muziekkanaal.

4 tests.

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

Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • src/routes/feed.js

    r34e63f0 r4d81de5  
    6666  const tracks = siteOpenTracks(site.id);
    6767  const lastBuild = posts[0]?.published_at || new Date().toISOString();
     68
     69  // De itunes-velden waar een podcast-app een kanaal aan herkent. Funkwhale
     70  // bouwde onze kanaalpagina langs de RSS-kant op en liet de categorie leeg,
     71  // want die leest hij hier -- niet uit `category` op de AP-actor.
     72  //
     73  // De categorie volgt DEZELFDE regel als daar: alleen 'Music' als er ook
     74  // werkelijk publieke muziek is. Een blog zonder open track is naar buiten
     75  // toe geen muziekkanaal, en gated muziek telt niet mee -- afwezig is
     76  // afwezig, ook in een categorie.
     77  const abs = (u) => !u ? null : (/^https?:/i.test(u) ? u : `${base}${u.startsWith('/') ? '' : '/'}${u}`);
     78  const kanaalKunst = abs(site.profile_photo || site.og_image_default || null);
     79  const kanaalTags = [
     80    `    <itunes:author>${escapeXml(site.author || site.title || '')}</itunes:author>`,
     81    site.description || site.tagline
     82      ? `    <itunes:summary>${escapeXml(site.description || site.tagline)}</itunes:summary>` : null,
     83    kanaalKunst ? `    <itunes:image href="${escapeXml(kanaalKunst)}" />` : null,
     84    tracks.length ? '    <itunes:category text="Music" />' : null,
     85  ].filter(Boolean).join('\n');
    6886
    6987  const wanneer = (d) => { const t = Date.parse(d); return Number.isNaN(t) ? 0 : t; };
     
    88106      <description>${escapeXml(t.artist || '')}</description>
    89107      <enclosure url="${escapeXml(`${base}/audio/stream/${encodeURIComponent(fn)}`)}" length="${Number(t.size) || 0}" type="${escapeXml(t.mime_type || 'audio/mpeg')}" />${t.duration ? `
    90       <itunes:duration>${Math.round(t.duration)}</itunes:duration>` : ''}
     108      <itunes:duration>${Math.round(t.duration)}</itunes:duration>` : ''}${t.artist ? `
     109      <itunes:author>${escapeXml(t.artist)}</itunes:author>` : ''}${abs(t.cover_url) ? `
     110      <itunes:image href="${escapeXml(abs(t.cover_url))}" />` : ''}
    91111    </item>` };
    92112    }),
     
    103123    <lastBuildDate>${new Date(lastBuild).toUTCString()}</lastBuildDate>
    104124    <atom:link href="${escapeXml(base + '/feed.xml')}" rel="self" type="application/rss+xml" />
     125${kanaalTags}
    105126${items}
    106127  </channel>
  • src/services/ActivityPubService.js

    r34e63f0 r4d81de5  
    233233 * de kast, niet enable_audio_player -- die staat standaard aan en zegt niets.
    234234 */
    235 function channelCategory(site) {
    236   try {
    237     return db.prepare('SELECT 1 FROM audio_tracks WHERE site_id = ? LIMIT 1').get(site.id) ? 'music' : null;
     235export function channelCategory(site) {
     236  try {
     237    // ALLEEN opengezette tracks tellen. Eerst keek dit naar elke track, ook een
     238    // gated -- en dan roept een site met uitsluitend afgeschermde muziek toch
     239    // "hier is muziek" naar de hele fediverse. Dat botst met de regel die we
     240    // overal aanhouden: een gesloten track is AFWEZIG, niet stilletjes
     241    // aanwezig. Naar buiten toe is een kanaal zonder publieke muziek geen
     242    // muziekkanaal.
     243    return db.prepare('SELECT 1 FROM audio_tracks WHERE site_id = ? AND fedi_open = 1 LIMIT 1').get(site.id) ? 'music' : null;
    238244  } catch { return null; }
    239245}
     
    60396045  AP_CONTEXT, getOrCreateKeys, apWants, sendAP, actorId, noteId, stripLeadingMentions,
    60406046  buildActor, buildNote, buildCreate, buildOutbox, buildFollowers, buildFollowing, buildFeatured,
    6041   channelUrls, timelineFields, guessMediaType,
     6047  channelUrls, channelCategory, timelineFields, guessMediaType,
    60426048  siteOpenTracks, openTrack, buildTrackAudio, buildTrackCollection, buildTrackCreate,
    60436049  buildPlaylistCollection, playlistOpenTracks, listPlaylistsAP, playlistLinkTags,
  • test/channel-actor.test.js

    r34e63f0 r4d81de5  
    3636});
    3737
    38 test('met muziek is de category "music"', () => {
     38test('een GATED track maakt er nog geen muziekkanaal van', () => {
     39  // Aangescherpt: eerst telde elke track mee, ook een afgeschermde -- dan riep
     40  // een site met uitsluitend gated muziek toch "hier is muziek" naar buiten.
     41  // Afwezig is afwezig, ook in een categorie.
     42  db.prepare('INSERT INTO media (id, site_id, filename, storage_path, mime_type, size) VALUES (?,?,?,?,?,1)')
     43    .run('m0', 's1', 'dicht.mp3', 'audio/dicht.mp3', 'audio/mpeg');
     44  db.prepare('INSERT INTO audio_tracks (id, site_id, title, media_id, fedi_open) VALUES (?,?,?,?,0)')
     45    .run('t0', 's1', 'Achter de poort', 'm0');
     46  assert.equal(AP.buildActor(BASE, site()).category, undefined);
     47});
     48
     49test('met OPENGEZETTE muziek is de category "music"', () => {
    3950  db.prepare('INSERT INTO media (id, site_id, filename, storage_path, mime_type, size) VALUES (?,?,?,?,?,1)')
    4051    .run('m1', 's1', 'a.mp3', 'audio/a.mp3', 'audio/mpeg');
    41   db.prepare('INSERT INTO audio_tracks (id, site_id, title, media_id) VALUES (?,?,?,?)')
     52  db.prepare('INSERT INTO audio_tracks (id, site_id, title, media_id, fedi_open) VALUES (?,?,?,?,1)')
    4253    .run('t1', 's1', 'Een nummer', 'm1');
    4354  assert.equal(AP.buildActor(BASE, site()).category, 'music');
Note: See TracChangeset for help on using the changeset viewer.