Changeset f50a84b in Klonkt


Ignore:
Timestamp:
08/13/2026 01:09:55 PM (4 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
c3e736c
Parents:
013e16c
Message:

Jouw teksten, en de twee dingen die ze beloofden (shaer-mbz)

De titel is nu "MusicBrainz Koppeling" met jouw omschrijving eronder, in drie
talen. Maar die omschrijving belooft twee dingen die de code nog niet deed, en
een label dat liegt is erger dan een lelijk label. Dus allebei gebouwd.

"OF JE MUSICBRAINZ ID ALS JE DIE KENT". Plak je een UUID, dan wordt hij
rechtstreeks opgezocht in plaats van gezocht. Dat is geen luxe: een
zoekopdracht OP een UUID levert bij MusicBrainz niets op, dus zonder deze tak
gaf plakken juist het slechtste resultaat.

"MET TERUG-WEG VALIDATIE". Een koppeling van onze kant is een bewering --
iedereen kan een id in een veld typen. Pas als de MusicBrainz-pagina TERUGWIJST
naar dit domein is het een paar, en dan weet een lezer dat dezelfde persoon aan
allebei de kanten stond. Dezelfde gedachte als rel="me". Het paneel zegt
"wederzijds" of "nog eenzijdig", en bij dat laatste staat erbij WAT je moet doen:
het domein op je MusicBrainz-pagina zetten onder "social networking".

Wij zetten die terugwijzing niet zelf. Kan niet via hun API, en hoort ook niet.

ECHT GEMETEN, en dat gaf de test zijn vorm: robo-burr staat in MusicBrainz met
score 100 (24abe2be-c0bc-4c63-9642-d6f89ec6a00a, "AKA roboburr") en heeft
precies EEN url-relatie -- type "social network", naar sound-fabrics.com. Voor
dev.klonkt.com is de terug-weg dus false, en dat is precies de waarde van de
controle. Die vorm staat nu in een test.

Bij een storing komt er false EN een lege lijst uit: niet kunnen kijken is niet
hetzelfde als niet gevonden, en nooit stilletjes "wederzijds".

Een controle erbij die eist dat alle drie de talen dezelfde mb_-sleutels
hebben. Bij het herschrijven waren er zeven weggevallen die het scherm nog
gebruikt -- een gat in een vertaling geeft een leeg label en dat valt nooit
vanzelf op.

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

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/assets/js/mod/admin-seo.js

    r013e16c rf50a84b  
    6464    uit.hidden = true;
    6565    uit.replaceChildren();
     66    checkTerugweg(mbid);
    6667  }
    6768
    6869  const wis = document.getElementById('mb-wis');
    6970  if (wis) wis.addEventListener('click', () => zet('', ''));
     71
     72  // DE TERUG-WEG. Wij zetten hem niet -- dat kan niet via hun API en hoort ook
     73  // niet -- we kijken alleen of de artiestenpagina ons domein noemt. Zolang dat
     74  // niet zo is staat er "nog eenzijdig", want een halve koppeling die als
     75  // bevestigd leest is het soort stilte waar we vandaag al genoeg van zagen.
     76  const terugweg = document.getElementById('mb-terugweg');
     77  async function checkTerugweg(mbid) {
     78    if (!terugweg) return;
     79    if (!mbid) { terugweg.hidden = true; terugweg.textContent = ''; return; }
     80    terugweg.hidden = false;
     81    terugweg.className = 'mb-terugweg';
     82    terugweg.textContent = T.aseo_mb_checking || 'Terug-weg controleren…';
     83    try {
     84      const r = await fetch(`/admin/seo/api/musicbrainz/terugweg?mbid=${encodeURIComponent(mbid)}`, { credentials: 'same-origin' });
     85      const j = await r.json();
     86      terugweg.className = 'mb-terugweg ' + (j.verified ? 'is-ok' : 'is-eenzijdig');
     87      terugweg.textContent = j.verified
     88        ? (T.aseo_mb_verified || 'Wederzijds.')
     89        : (T.aseo_mb_unverified || 'Nog eenzijdig.');
     90    } catch {
     91      terugweg.hidden = true;
     92    }
     93  }
     94  // Meteen bij het openen, want de artiest kan hem intussen op MusicBrainz
     95  // hebben gezet en hoort dat hier te zien zonder opnieuw te koppelen.
     96  if (idVeld.value) checkTerugweg(idVeld.value);
    7097
    7198  async function zoek() {
  • src/routes/admin-seo.js

    r013e16c rf50a84b  
    6262  const q = String(req.query.q || (site && (site.publisher_name || site.title)) || '').trim();
    6363  if (!q) return res.json({ ok: true, q: '', kandidaten: [] });
     64  // Wie zijn id al kent plakt het hier. Een zoekopdracht op een UUID levert bij
     65  // MusicBrainz niets op, dus zonder deze tak geeft plakken juist het slechtste
     66  // resultaat.
     67  if (isMbid(q)) {
     68    const een = await MusicBrainz.haalArtiest(q);
     69    return res.json({ ok: true, q, kandidaten: een ? [een] : [] });
     70  }
    6471  res.json({ ok: true, q, kandidaten: await MusicBrainz.zoekArtiesten(q) });
     72});
     73
     74/**
     75 * De terug-weg: noemt de MusicBrainz-pagina ons domein? (shaer-mbz)
     76 *
     77 * Een koppeling van onze kant is een bewering -- iedereen kan een id typen.
     78 * Pas als de artiestenpagina TERUGWIJST is het een paar. Wij zetten die
     79 * verwijzing niet zelf: dat kan niet via hun API en hoort ook niet, de artiest
     80 * doet dat op musicbrainz.org onder "social networking".
     81 */
     82router.get('/api/musicbrainz/terugweg', requireGod, async (req, res) => {
     83  const mbid = String(req.query.mbid || '').trim().toLowerCase();
     84  const base = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, '');
     85  if (!isMbid(mbid) || !base) return res.json({ ok: true, verified: false, urls: [] });
     86  res.json({ ok: true, ...(await MusicBrainz.controleerTerugweg(mbid, base)) });
    6587});
    6688
  • src/services/MusicBrainzService.js

    r013e16c rf50a84b  
    8080}
    8181
     82/**
     83 * Een MBID rechtstreeks opzoeken. Wie zijn id al kent hoeft niet te zoeken --
     84 * en een zoekopdracht op een UUID levert bij MusicBrainz niets op, dus zonder
     85 * deze tak zou plakken juist het slechtste resultaat geven.
     86 */
     87export async function haalArtiest(mbid) {
     88  if (!isMbid(mbid)) return null;
     89  const url = `${BASIS}/artist/${encodeURIComponent(mbid)}?inc=url-rels&fmt=json`;
     90  try {
     91    await opDeBeurt();
     92    const r = await safeFetch(url, { headers: { Accept: 'application/json', 'User-Agent': userAgent() } });
     93    if (!r || !r.ok) return null;
     94    return kandidaat(await r.json());
     95  } catch {
     96    return null;
     97  }
     98}
     99
     100/**
     101 * DE TERUG-WEG. Noemt de MusicBrainz-pagina van deze artiest ons domein?
     102 *
     103 * Een koppeling van onze kant is een bewering: iedereen kan een MBID in een
     104 * veld typen. Pas als de artiestenpagina TERUGWIJST is het een paar, en dan
     105 * weet een lezer dat dezelfde persoon aan allebei de kanten stond. Dat is
     106 * dezelfde gedachte als rel="me" bij Mastodon.
     107 *
     108 * Wij zetten die terugwijzing NIET zelf: via hun API kan het niet, en het hoort
     109 * ook niet -- de artiest doet dat op musicbrainz.org onder "social networking".
     110 * Wij kijken alleen of hij er staat.
     111 *
     112 * Geeft { verified, urls } -- bij een storing verified:false en een lege lijst,
     113 * want niet kunnen kijken is niet hetzelfde als niet gevonden.
     114 */
     115export async function controleerTerugweg(mbid, domein) {
     116  const leeg = { verified: false, urls: [] };
     117  if (!isMbid(mbid) || !domein) return leeg;
     118  let host;
     119  try { host = new URL(domein).host.toLowerCase(); } catch { return leeg; }
     120  const url = `${BASIS}/artist/${encodeURIComponent(mbid)}?inc=url-rels&fmt=json`;
     121  try {
     122    await opDeBeurt();
     123    const r = await safeFetch(url, { headers: { Accept: 'application/json', 'User-Agent': userAgent() } });
     124    if (!r || !r.ok) return leeg;
     125    const doc = await r.json();
     126    const urls = (doc.relations || [])
     127      .map((rel) => rel && rel.url && rel.url.resource)
     128      .filter((u) => typeof u === 'string');
     129    const wijst = urls.some((u) => { try { return new URL(u).host.toLowerCase() === host; } catch { return false; } });
     130    return { verified: wijst, urls };
     131  } catch {
     132    return leeg;
     133  }
     134}
     135
    82136/** Een kandidaat, teruggebracht tot wat een mens nodig heeft om te kiezen. */
    83137function kandidaat(a) {
     
    104158// ze precies wonen.
    105159export { isMbid, artiestUrl };
    106 export default { zoekArtiesten, isMbid, artiestUrl };
     160export default { zoekArtiesten, haalArtiest, controleerTerugweg, isMbid, artiestUrl };
  • src/services/i18n.js

    r013e16c rf50a84b  
    360360    'aaud.fedi_off': 'Niet op de fediverse gedeeld (alleen webspeler, bestand verborgen) — klik om te delen',
    361361    'aaud.embed_player': 'Embedbare speler',
    362     'aseo.mb_legend': 'MusicBrainz (dezelfde artiest elders)',
    363     'aseo.mb_search_label': 'Zoek jezelf op',
    364     'aseo.mb_search_hint': 'de naam waaronder je muziek uitbrengt',
    365     'aseo.mb_hint': 'MusicBrainz is het open register van de muziekwereld. Koppel je eigen pagina en je komt als sameAs in de JSON-LD van deze site én in je fediverse-profiel te staan — zo weten zoekmachines en muziekdiensten dat jouw muziek van jou is. Je verandert er niets mee bij MusicBrainz zelf; we verwijzen er alleen naar.',
    366     'aseo.mb_search': 'Zoeken',
    367     'aseo.mb_placeholder': 'Je artiestennaam',
    368     'aseo.mb_none': 'Niets gevonden. Sta je er nog niet in? Dan kun je jezelf aanmelden op musicbrainz.org — dat kan alleen daar, niet vanuit Klonkt.',
    369     'aseo.mb_pick': 'Dit ben ik',
     362    'aseo.mb_legend': 'MusicBrainz Koppeling',
    370363    'aseo.mb_linked': 'Gekoppeld aan',
    371364    'aseo.mb_unlink': 'Ontkoppelen',
    372365    'aseo.mb_open': 'Bekijk op MusicBrainz',
     366    'aseo.mb_pick': 'Dit ben ik',
     367    'aseo.mb_none': 'Niets gevonden. Sta je er nog niet in? Dan kun je jezelf aanmelden op musicbrainz.org — dat kan alleen daar, niet vanuit Klonkt.',
    373368    'aseo.mb_busy': 'Zoeken…',
    374369    'aseo.mb_fail': 'MusicBrainz is even niet bereikbaar.',
     370    'aseo.mb_hint': 'Hier koppel je je MusicBrainz artiest id aan je domein, met terug-weg validatie van je "social networking" profiel pagina.',
     371    'aseo.mb_search_label': 'Zoek op je naam',
     372    'aseo.mb_search_hint': 'je artiestennaam of je MusicBrainz id als je die kent',
     373    'aseo.mb_placeholder': 'Ozzy Osbourne',
     374    'aseo.mb_search': 'Opzoeken',
     375    'aseo.mb_verified': 'Wederzijds: de MusicBrainz-pagina wijst terug naar dit domein.',
     376    'aseo.mb_unverified': 'Nog eenzijdig. Zet dit domein op je MusicBrainz-pagina onder "social networking", dan is de koppeling van twee kanten bevestigd.',
     377    'aseo.mb_checking': 'Terug-weg controleren…',
    375378    'aaud.embed_hint': 'Plak deze code op je eigen website/blog om je muziek met deze speler in te sluiten:',
    376379    'aaud.preview_player': 'Speler-voorbeeld openen',
     
    13201323    'aaud.fedi_off': 'Not shared on the fediverse (web player only, file hidden) — click to share',
    13211324    'aaud.embed_player': 'Embeddable player',
    1322     'aseo.mb_legend': 'MusicBrainz (the same artist elsewhere)',
    1323     'aseo.mb_search_label': 'Look yourself up',
    1324     'aseo.mb_search_hint': 'the name you release music under',
    1325     'aseo.mb_hint': 'MusicBrainz is the music world\u2019s open register. Link your own page and it appears as sameAs in this site\u2019s JSON-LD and in your fediverse profile — so search engines and music services know your music is yours. It changes nothing at MusicBrainz itself; we only point at it.',
    1326     'aseo.mb_search': 'Search',
    1327     'aseo.mb_placeholder': 'Your artist name',
    1328     'aseo.mb_none': 'Nothing found. Not in there yet? You can add yourself on musicbrainz.org — that can only be done there, not from Klonkt.',
    1329     'aseo.mb_pick': 'This is me',
     1325    'aseo.mb_legend': 'MusicBrainz link',
    13301326    'aseo.mb_linked': 'Linked to',
    13311327    'aseo.mb_unlink': 'Unlink',
    13321328    'aseo.mb_open': 'View on MusicBrainz',
     1329    'aseo.mb_pick': 'This is me',
     1330    'aseo.mb_none': 'Nothing found. Not in there yet? You can add yourself on musicbrainz.org — that can only be done there, not from Klonkt.',
    13331331    'aseo.mb_busy': 'Searching…',
    13341332    'aseo.mb_fail': 'MusicBrainz is unreachable right now.',
     1333    'aseo.mb_hint': 'Link your MusicBrainz artist id to your domain here, with back-way validation from your "social networking" profile page.',
     1334    'aseo.mb_search_label': 'Search for your name',
     1335    'aseo.mb_search_hint': 'your artist name, or your MusicBrainz id if you know it',
     1336    'aseo.mb_placeholder': 'Ozzy Osbourne',
     1337    'aseo.mb_search': 'Look up',
     1338    'aseo.mb_verified': 'Mutual: the MusicBrainz page points back at this domain.',
     1339    'aseo.mb_unverified': 'Still one-sided. Add this domain to your MusicBrainz page under "social networking" and the link is confirmed from both ends.',
     1340    'aseo.mb_checking': 'Checking the back-way…',
    13351341    'aaud.embed_hint': 'Paste this code on your own website/blog to embed your music with this player:',
    13361342    'aaud.preview_player': 'Open player preview',
     
    22792285    'aaud.fedi_off': 'Nicht im Fediverse geteilt (nur Web-Player, Datei verborgen) — zum Teilen klicken',
    22802286    'aaud.embed_player': 'Einbettbarer Player',
    2281     'aseo.mb_legend': 'MusicBrainz (dieselbe Künstlerin anderswo)',
    2282     'aseo.mb_search_label': 'Dich selbst suchen',
    2283     'aseo.mb_search_hint': 'der Name, unter dem du Musik veröffentlichst',
    2284     'aseo.mb_hint': 'MusicBrainz ist das offene Register der Musikwelt. Verknüpfe deine Seite, und sie erscheint als sameAs im JSON-LD dieser Website und in deinem Fediverse-Profil — so wissen Suchmaschinen und Musikdienste, dass deine Musik von dir ist. Bei MusicBrainz selbst ändert sich nichts; wir verweisen nur darauf.',
    2285     'aseo.mb_search': 'Suchen',
    2286     'aseo.mb_placeholder': 'Dein Künstlername',
    2287     'aseo.mb_none': 'Nichts gefunden. Noch nicht dabei? Du kannst dich auf musicbrainz.org eintragen — das geht nur dort, nicht aus Klonkt heraus.',
    2288     'aseo.mb_pick': 'Das bin ich',
     2287    'aseo.mb_legend': 'MusicBrainz-Verknüpfung',
    22892288    'aseo.mb_linked': 'Verknüpft mit',
    22902289    'aseo.mb_unlink': 'Trennen',
    22912290    'aseo.mb_open': 'Bei MusicBrainz ansehen',
     2291    'aseo.mb_pick': 'Das bin ich',
     2292    'aseo.mb_none': 'Nichts gefunden. Noch nicht dabei? Du kannst dich auf musicbrainz.org eintragen — das geht nur dort, nicht aus Klonkt heraus.',
    22922293    'aseo.mb_busy': 'Suche läuft…',
    22932294    'aseo.mb_fail': 'MusicBrainz ist gerade nicht erreichbar.',
     2295    'aseo.mb_hint': 'Hier verknüpfst du deine MusicBrainz-Künstler-ID mit deiner Domain, mit Rückweg-Validierung über deine "social networking"-Profilseite.',
     2296    'aseo.mb_search_label': 'Nach deinem Namen suchen',
     2297    'aseo.mb_search_hint': 'dein Künstlername oder deine MusicBrainz-ID, falls du sie kennst',
     2298    'aseo.mb_placeholder': 'Ozzy Osbourne',
     2299    'aseo.mb_search': 'Nachschlagen',
     2300    'aseo.mb_verified': 'Gegenseitig: die MusicBrainz-Seite verweist zurück auf diese Domain.',
     2301    'aseo.mb_unverified': 'Noch einseitig. Trage diese Domain auf deiner MusicBrainz-Seite unter "social networking" ein, dann ist die Verknüpfung von beiden Seiten bestätigt.',
     2302    'aseo.mb_checking': 'Rückweg wird geprüft…',
    22942303    'aaud.embed_hint': 'Füge diesen Code auf deiner eigenen Website/deinem Blog ein, um deine Musik mit diesem Player einzubetten:',
    22952304    'aaud.preview_player': 'Player-Vorschau öffnen',
  • src/views/pages/admin-seo.ejs

    r013e16c rf50a84b  
    107107        <button type="button" class="btn" id="mb-wis"><%= t('aseo.mb_unlink') %></button>
    108108      </p>
     109      <%# De terug-weg. Een koppeling van onze kant is een BEWERING -- iedereen
     110          kan een id typen. Pas als de MusicBrainz-pagina terugwijst is het een
     111          paar, en dat staat hier met zoveel woorden zodat "eenzijdig" niet als
     112          "klaar" leest. %>
     113      <p class="mb-terugweg" id="mb-terugweg" hidden></p>
    109114
    110115      <label>
  • test/musicbrainz.test.js

    r013e16c rf50a84b  
    162162  assert.equal(term.sameAs['@type'], '@id', 'het is een URI en geen tekst');
    163163});
     164
     165// ── De terug-weg (Robins "social networking"-validatie) ───────────────────
     166
     167test('een MBID in het zoekveld wordt rechtstreeks opgezocht', async () => {
     168  // Zoeken op een UUID levert bij MusicBrainz niets op, dus zonder deze tak
     169  // geeft plakken juist het slechtste resultaat.
     170  globalThis.fetch = async (url) => {
     171    verzoeken.push({ url: String(url) });
     172    return { ok: true, json: async () => ({ id: '8be31978-1884-4773-beae-f73df35b92aa', name: 'robo-burr', disambiguation: 'AKA roboburr' }) };
     173  };
     174  verzoeken.length = 0;
     175  const een = await MB.haalArtiest('8be31978-1884-4773-beae-f73df35b92aa');
     176  assert.equal(een.naam, 'robo-burr');
     177  assert.match(verzoeken[0].url, /\/artist\/8be31978-1884-4773-beae-f73df35b92aa\?/, 'de lookup, niet de zoekopdracht');
     178  assert.equal(await MB.haalArtiest('nirvana'), null, 'geen MBID, geen lookup');
     179});
     180
     181test('de terug-weg is pas waar als de pagina ONS domein noemt', async () => {
     182  // Echt gemeten op 13-8: robo-burr heeft precies een url-relatie, type
     183  // "social network", naar sound-fabrics.com. Dus voor dev.klonkt.com hoort
     184  // hier false uit te komen -- en dat is de waarde van de controle.
     185  globalThis.fetch = async () => ({
     186    ok: true,
     187    json: async () => ({ relations: [{ type: 'social network', url: { resource: 'https://sound-fabrics.com/' } }] }),
     188  });
     189  const mbid = '24abe2be-c0bc-4c63-9642-d6f89ec6a00a';
     190  const mis = await MB.controleerTerugweg(mbid, 'https://dev.klonkt.com');
     191  assert.equal(mis.verified, false, 'een andere site is geen terugweg');
     192  assert.deepEqual(mis.urls, ['https://sound-fabrics.com/']);
     193
     194  const raak = await MB.controleerTerugweg(mbid, 'https://sound-fabrics.com');
     195  assert.equal(raak.verified, true, 'dezelfde host telt, ongeacht pad of slash');
     196});
     197
     198test('niet kunnen kijken is niet hetzelfde als niet gevonden', async () => {
     199  // Bij een storing false EN een lege lijst -- nooit stilletjes "wederzijds".
     200  globalThis.fetch = async () => { throw new Error('weg'); };
     201  const uit = await MB.controleerTerugweg('24abe2be-c0bc-4c63-9642-d6f89ec6a00a', 'https://dev.klonkt.com');
     202  assert.deepEqual(uit, { verified: false, urls: [] });
     203});
Note: See TracChangeset for help on using the changeset viewer.