Ignore:
Timestamp:
08/16/2026 03:06:18 PM (3 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
a5caa73
Parents:
a5515b4 (diff), 9026de5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Bibliotheek en album-federatie terug op main (shaer-0nh, shaer-756s)

Achttien commits, in drie brokken.

DE BIBLIOTHEEK. Een Library-skelet met een eigen volgerssoort: wie de
bibliotheek volgt krijgt de muziek en met opzet niet de gewone posts, en
die staan daarom in een eigen tabel -- een vlag die iemand vergeet te
filteren bezorgt stilletjes de Krant aan mensen die er niet om vroegen.
Daarna wat er nodig bleek om werkelijk gelezen te worden: audience
(zonder dat gaf hun create() een KeyError en dus een 500 op onze URL),
de ongeordende collectievorm, en paginering op elke collectie die first
belooft -- die laatste vond meteen dat featured hetzelfde gat had.

HET VOCABULAIRE. fw:track in de kleine vorm die Emissary ook stuurt,
artist_credit met de site-actor als Artist (mogelijk geworden door de
MusicBrainz-koppeling), en het album als ingesloten fw:Album met
released, musicbrainzId en een eigen artist_credit. Daarvoor kwamen er
twee kolommen op playlists, alleen bij kind='album' en afgedwongen in
PlaylistService -- niet in het scherm, want de API ligt open.

HET BEHEER. De vijf mediapagina's stonden op drie verschillende
ontwerpen; nu op een gedeelde ax-romp, met de primitieven op een plek in
plaats van in acht kopieen. De playlist-modal ging alsnog door i18n: die
teksten stonden hard in het script, wat niet opviel omdat het toevallig
de brontaal was.

WAT ER NIET IN ZIT: bitrate en size top-level als fw:. Dat is bewust
(shaer-3f8a). Hun eigen outbox zet ze op de Link, net als wij, en het
wordt een gesprek in plaats van een aanpassing -- briefing in
~/bewaard/funkwhale-briefing-en.md.

Gereedschap dat meekomt: scripts/funkwhale-gat.mjs meet het gat naar hun
ingest, admin-css.mjs en admin-css-gelijk.mjs ontleden en vergelijken de
beheer-CSS, render-admin-views.mjs rendert de views gevuld en leeg. Die
laatste drie omdat de testsuite geen enkele view aanraakt.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    ra5515b4 r749605a  
    3434// De muziekkant woont in music/ (shaer-drc). Doorgeven wat hier altijd
    3535// vandaan kwam, zodat elke bestaande aanroep blijft werken.
     36import { luisteraars } from './music/index.js';
    3637import { TRACK_KOLOMMEN,
    3738  playlistOpenTracks, siteOpenTracks, openTrack, trackHostPosts,
     
    3940  buildPlaylistCollection, listPlaylistsAP, playlistLinkTags,
    4041  buildPostTrackCollection, uitgavePost,
     42  buildLibrary, libraryId,
    4143  licentieUri, channelCategory,
    4244} from './music/index.js';
     
    4648  buildPlaylistCollection, listPlaylistsAP, playlistLinkTags, licentieUri,
    4749  buildPostTrackCollection, uitgavePost,
     50  buildLibrary, libraryId,
    4851};
    4952
     
    354357  const pagina = pickLink(o.url, () => true);
    355358  return { html: HtmlSanitizerService.sanitize(o.content || ''), atts, url: pagina ? pagina.href : null };
     359}
     360
     361/**
     362 * De site achter een library-uri, of null. Zelfde strengheid als localSlugOf:
     363 * de uri moet met ONZE basis beginnen en de site moet bestaan -- anders levert
     364 * andermans /library met dezelfde padstaart hier een volger op onze naam op.
     365 */
     366function libraryOwnerSlug(uri) {
     367  const u = String(uri || '');
     368  if (!u.endsWith('/library')) return null;
     369  return localSlugOf(u.slice(0, -'/library'.length));
    356370}
    357371
     
    11861200// these as the "Featured" tab (pinned to the profile). Posts come ordered by pin
    11871201// rank; embedded as full Notes so a remote server doesn't need extra fetches.
    1188 export function buildFeatured(base, site, posts) {
     1202export function buildFeatured(base, site, posts, { page = false } = {}) {
    11891203  const id = `${actorId(base, site.slug)}/featured`;
    11901204  const items = (posts || []).map((p) => buildNote(base, site, p));
    1191   return pagedCollection(id, items);
     1205  return pagedCollection(id, items, { page });
    11921206}
    11931207
     
    23542368  if (type === 'Follow') {
    23552369    const who = typeof act.actor === 'string' ? act.actor : (act.actor && act.actor.id);
     2370    // EERST: volgt iemand onze BIBLIOTHEEK in plaats van onze actor? (shaer-0nh)
     2371    //
     2372    // Een luisteraar krijgt de muziek en NIET de gewone posts -- wie zich
     2373    // abonneert op een platenkast heeft niet om de Krant gevraagd. Vandaar een
     2374    // eigen tabel: zolang ze daar staan kan een postbezorging ze niet per
     2375    // ongeluk meenemen.
     2376    //
     2377    // De bibliotheek is openbaar (alles erin is fedi_open), dus dit accepteert
     2378    // meteen. Er valt niets goed te keuren, en dan is wachten oneerlijk.
     2379    const libSlug = libraryOwnerSlug(typeof act.object === 'string' ? act.object : (act.object && act.object.id));
     2380    if (who && libSlug) {
     2381      const remote = await fetchActor(who);
     2382      if (!remote || !remote.inbox) return 202;
     2383      const fi = actorInfo(remote, who);
     2384      luisteraars.voegToe(libSlug, {
     2385        actorUri: who, inbox: remote.inbox,
     2386        sharedInbox: (remote.endpoints && remote.endpoints.sharedInbox) || null,
     2387        name: fi.name, handle: fi.handle, icon: fi.icon,
     2388      });
     2389      const keys = getOrCreateKeys(libSlug);
     2390      const accept = {
     2391        '@context': AP_CONTEXT,
     2392        id: `${actorId(base, libSlug)}#accept-library-${Date.now()}-${rid()}`,
     2393        type: 'Accept', actor: actorId(base, libSlug), object: act,
     2394      };
     2395      deliver(remote.inbox, accept, `${actorId(base, libSlug)}#main-key`, keys.privatePem)
     2396        .catch(() => { /* de volger staat er; een mislukte Accept mag dat niet omgooien */ });
     2397      console.log('[AP] library follow from', who, '->', libSlug);
     2398      return 202;
     2399    }
    23562400    // slugParam is de eigenaar van een per-actor inbox; op de GEDEELDE inbox is
    23572401    // die er niet en werd de slug uit act.object geraden. Zonder hostcontrole
     
    24372481    return 202;
    24382482  }
     2483  // Een luisteraar die weggaat, hoort meteen weg te zijn.
     2484  if (type === 'Undo' && act.object && act.object.type === 'Follow') {
     2485    const doel = typeof act.object.object === 'string' ? act.object.object : (act.object.object && act.object.object.id);
     2486    const libSlug = libraryOwnerSlug(doel);
     2487    const wie = typeof act.actor === 'string' ? act.actor : (act.actor && act.actor.id);
     2488    if (libSlug && wie && luisteraars.verwijder(libSlug, wie)) {
     2489      console.log('[AP] library unfollow from', wie, '->', libSlug);
     2490      return 202;
     2491    }
     2492  }
     2493
    24392494  if (type === 'Undo' && act.object) {
    24402495    const who = typeof act.actor === 'string' ? act.actor : (act.actor && act.actor.id);
     
    68096864  buildPlaylistCollection, playlistOpenTracks, listPlaylistsAP, playlistLinkTags,
    68106865  buildPostTrackCollection, uitgavePost,
     6866  buildLibrary, libraryId,
    68116867  followerCount, deliver, fetchActor, verifyRequest, handleInbox, deliverCreate, deliverDelete, deliverUpdate, deliverActorUpdate, resyncFeaturedPins,
    68126868  feedCursor, feedChangesSince, waitForFeedChange,
Note: See TracChangeset for help on using the changeset viewer.