Changeset 3bbf73d in Klonkt


Ignore:
Timestamp:
08/10/2026 02:43:16 PM (4 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
f0a33e1
Parents:
f549cf5
Message:

Alleen namen: het Nederlands van vandaag terug naar Engels

shaer-8ms zegt het al: Engelse namen, Nederlands commentaar waar dat helpt. Ik
ben er vandaag opnieuw van afgedreven en zet dat recht voordat er meer bovenop
komt -- gatesFor, messageItem, sentItem, conversationItems, ownHandle,
CONVERSATION_UNION, MESSAGE_COLUMNS, cursorOf, en de locals eromheen
(rows/more/oldest/direction/incoming/heads/self/size).

Geen gedrag, alleen namen, en daarom een eigen commit: die is na te lopen.
851/851 groen voor en na. Het commentaar blijft Nederlands.

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

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/routes/activitypub.js

    rf549cf5 r3bbf73d  
    289289// dat evenveel kopieen worden -- en een poort die op een van die plekken
    290290// vergeten wordt, levert stil iets uit dat dicht hoorde te staan.
    291 function leesPoorten(site) {
     291function gatesFor(site) {
    292292  const isWard = (() => { try { return Guardianship.listGuardians(site.slug).length > 0; } catch { return false; } })();
    293293  const embeds = Guardianship.externalEmbedsAllowed(site.external_embeds, isWard);
     
    314314
    315315/** De naam waaronder deze lezer zichzelf herkent in een Mention. */
    316 function eigenHandle(base, slug) {
     316function ownHandle(base, slug) {
    317317  try { return `@${slug}@${new URL(base).host}`; } catch { return `@${slug}`; }
    318318}
     
    323323// opschrijven is twee vormen die uit de pas kunnen lopen, en dat merk je pas
    324324// als een kaart ergens anders rendert dan waar je keek.
    325 function berichtItem(m, { base, me, myHandle, p }) {
     325function messageItem(m, { base, me, myHandle, p }) {
    326326  return {
    327327    id: `${m.object_uri}#create`,
     
    359359
    360360/** Een eigen verzonden note als AS2-item, zelfde vorm als de inbox-leg. */
    361 function verzondenItem(n, { me, mine }) {
     361function sentItem(n, { me, mine }) {
    362362  return {
    363363    id: `${n.id}#create`,
     
    383383// ophoudt.
    384384//
    385 // Beide lopen langs dezelfde poorten als de inbox-lezing (leesPoorten) en
    386 // dezelfde kaartvorm (berichtItem/verzondenItem). Messages dicht sluit ook
     385// Beide lopen langs dezelfde poorten als de inbox-lezing (gatesFor) en
     386// dezelfde kaartvorm (messageItem/sentItem). Messages dicht sluit ook
    387387// hier vreemden en vrienden, maar nooit het guardian-kanaal en nooit de boei.
    388 function gesprekItems(req, auth, refs) {
     388function conversationItems(req, auth, refs) {
    389389  const base = baseUrl(req);
    390   const P = leesPoorten(auth.site);
     390  const P = gatesFor(auth.site);
    391391  const me = AP.actorId(base, auth.site.slug);
    392   const ctx = { base, me, myHandle: eigenHandle(base, auth.site.slug), p: P };
     392  const ctx = { base, me, myHandle: ownHandle(base, auth.site.slug), p: P };
    393393  const mine = AP.selfAuthor(base, auth.site);
    394394  const guardianUris = (() => { try { return new Set(Guardianship.listGuardians(auth.site.slug).map((g) => g.other_uri)); } catch { return new Set(); } })();
    395395
    396   const binnen = new Map(AP.messageRowsByUri(auth.site.slug, refs.filter((r) => r.richting === 'in').map((r) => r.ref))
     396  const incoming = new Map(AP.messageRowsByUri(auth.site.slug, refs.filter((r) => r.direction === 'in').map((r) => r.ref))
    397397    .map((m) => [m.object_uri, m]));
    398   const uit = [];
     398  const items = [];
    399399  for (const r of refs) {
    400     if (r.richting === 'in') {
    401       const m = binnen.get(r.ref);
     400    if (r.direction === 'in') {
     401      const m = incoming.get(r.ref);
    402402      if (!m) continue;
    403403      if (!(P.messagesAllowed || m.help_request || guardianUris.has(m.actor_uri))) continue;
    404       uit.push(berichtItem(m, ctx));
     404      items.push(messageItem(m, ctx));
    405405    } else {
    406406      const n = AP.getOutboxNote(base, r.ref);
    407407      // Je eigen woorden blijven van jou: een dichte messages-poort verbergt
    408408      // niet wat je zelf gezegd hebt.
    409       if (n) uit.push(verzondenItem(n, { me, mine }));
     409      if (n) items.push(sentItem(n, { me, mine }));
    410410    }
    411411  }
    412   return uit;
     412  return items;
    413413}
    414414
     
    416416  const auth = OAuth.verifyBearer(req.headers.authorization);
    417417  if (!auth || auth.site.slug !== req.params.slug) return res.status(403).end();
    418   const koppen = AP.conversationHeads(auth.site.slug);
    419   const items = gesprekItems(req, auth, koppen);
     418  const heads = AP.conversationHeads(auth.site.slug);
     419  const items = conversationItems(req, auth, heads);
    420420  AP.sendAP(res, {
    421421    '@context': AP.AP_CONTEXT,
     
    433433  const other = String(req.query.with || '');
    434434  if (!/^https?:\/\//i.test(other)) return res.status(400).json({ error: 'with must be an actor URI' });
    435   const uit = AP.conversationHistory(auth.site.slug, other, {
     435  const page = AP.conversationHistory(auth.site.slug, other, {
    436436    before: req.query.before ? String(req.query.before) : null,
    437437    limit: req.query.limit,
    438438  });
    439   const items = gesprekItems(req, auth, uit.rijen);
     439  const items = conversationItems(req, auth, page.rows);
    440440  // De paginagrootte reist mee in next: vroeg je om 30, dan hoort de volgende
    441441  // pagina er ook 30 te zijn. Zonder dit wordt hij stilletjes de standaard, en
    442442  // dan klopt het ritme van een 'load more' niet meer met wat de gebruiker ziet.
    443   const maat = req.query.limit ? `&limit=${encodeURIComponent(String(req.query.limit))}` : '';
    444   const zelf = `${baseUrl(req)}/ap/users/${encodeURIComponent(auth.site.slug)}/messages?with=${encodeURIComponent(other)}`;
     443  const size = req.query.limit ? `&limit=${encodeURIComponent(String(req.query.limit))}` : '';
     444  const self = `${baseUrl(req)}/ap/users/${encodeURIComponent(auth.site.slug)}/messages?with=${encodeURIComponent(other)}`;
    445445  AP.sendAP(res, {
    446446    '@context': AP.AP_CONTEXT,
    447     id: req.query.before ? `${zelf}${maat}&before=${encodeURIComponent(String(req.query.before))}` : `${zelf}${maat}`,
     447    id: req.query.before ? `${self}${size}&before=${encodeURIComponent(String(req.query.before))}` : `${self}${size}`,
    448448    type: 'OrderedCollectionPage',
    449     partOf: zelf,
     449    partOf: self,
    450450    orderedItems: items,
    451451    // De volgende pagina is de standaardvorm van 'er is meer' (AS2). Ontbreekt
    452452    // hij, dan is het gesprek op -- en dat mag de client weten zonder gokken,
    453453    // want anders kan een 'load more' niet eerlijk verschijnen.
    454     next: uit.meer && uit.oudste ? `${zelf}${maat}&before=${encodeURIComponent(uit.oudste)}` : undefined,
     454    next: page.more && page.oldest ? `${self}${size}&before=${encodeURIComponent(page.oldest)}` : undefined,
    455455  }, 'private, no-store');
    456456});
     
    587587  // here, at serialisation: a blocked embed is never sent, because an embed the
    588588  // client merely hides has still been delivered to the device.
    589   // De poorten van deze lezer (leesPoorten): een plek waar ze berekend worden,
     589  // De poorten van deze lezer (gatesFor): een plek waar ze berekend worden,
    590590  // zodat de gesprekslezingen dezelfde stand eerbiedigen en niet hun eigen
    591591  // kopie krijgen die kan gaan afwijken.
    592   const P = leesPoorten(auth.site);
     592  const P = gatesFor(auth.site);
    593593  const {
    594594    embedsAllowed, playbackAllowed, imagesAllowed, musicAllowed, quotesAllowed,
     
    676676  // beschermt niemand. De hulpvraag zelf gaat aan de innamekant al altijd voor.
    677677  const guardianUris = (() => { try { return new Set(Guardianship.listGuardians(auth.site.slug).map((g) => g.other_uri)); } catch { return new Set(); } })();
    678   const berichtCtx = { base, me, myHandle, p: P };
     678  const messageCtx = { base, me, myHandle, p: P };
    679679  const messages = AP.getDirectMessages(auth.site.slug, 60)
    680680    .filter((m) => messagesAllowed || m.help_request || guardianUris.has(m.actor_uri))
    681     .map((m) => berichtItem(m, berichtCtx));
     681    .map((m) => messageItem(m, messageCtx));
    682682  // Inbound REPLIES on your own posts: stored as interactions (the web's
    683683  // comment machinery), never as mentions, so this read missed them and a
  • src/services/ActivityPubService.js

    rf549cf5 r3bbf73d  
    42104210// visibility 'direct'. Een publiek antwoord is geen gesprek en hoort niet als
    42114211// gezicht in de hemel.
    4212 const GESPREK_UNIE = `
     4212const CONVERSATION_UNION = `
    42134213  SELECT m.actor_uri AS other, COALESCE(m.published, m.created_at) AS stamp,
    4214          'in' AS richting, m.object_uri AS ref
     4214         'in' AS direction, m.object_uri AS ref
    42154215    FROM ap_mentions m
    42164216   WHERE m.slug = @slug AND m.actor_uri IS NOT NULL AND m.actor_uri <> ''
    42174217  UNION ALL
    42184218  SELECT j.value AS other, o.created_at AS stamp,
    4219          'uit' AS richting, o.id AS ref
     4219         'out' AS direction, o.id AS ref
    42204220    FROM ap_outbox o
    42214221    JOIN json_each(COALESCE(NULLIF(o.to_actors, ''), json_array(o.to_actor))) j
     
    42334233  try {
    42344234    return db.prepare(`
    4235       SELECT other, stamp, richting, ref FROM (
     4235      SELECT other, stamp, direction, ref FROM (
    42364236        SELECT *, ROW_NUMBER() OVER (PARTITION BY other ORDER BY stamp DESC, ref DESC) AS rn
    4237           FROM (${GESPREK_UNIE})
     4237          FROM (${CONVERSATION_UNION})
    42384238      ) WHERE rn = 1
    42394239      ORDER BY stamp DESC, ref DESC`).all({ slug });
     
    42604260 * ontbreekt alleen iets in het midden.
    42614261 */
    4262 const cursorVan = (r) => (r ? `${r.stamp}|${r.ref}` : null);
     4262const cursorOf = (r) => (r ? `${r.stamp}|${r.ref}` : null);
    42634263
    42644264export function conversationHistory(slug, other, { before = null, limit = 60 } = {}) {
    42654265  try {
    42664266    const n = Math.min(Math.max(parseInt(limit, 10) || 60, 1), 200);
    4267     const knip = String(before || '').indexOf('|');
    4268     const bStamp = before && knip > 0 ? String(before).slice(0, knip) : null;
    4269     const bRef = before && knip > 0 ? String(before).slice(knip + 1) : null;
    4270     const rijen = db.prepare(`
    4271       SELECT other, stamp, richting, ref FROM (${GESPREK_UNIE})
     4267    const sep = String(before || '').indexOf('|');
     4268    const bStamp = before && sep > 0 ? String(before).slice(0, sep) : null;
     4269    const bRef = before && sep > 0 ? String(before).slice(sep + 1) : null;
     4270    const rows = db.prepare(`
     4271      SELECT other, stamp, direction, ref FROM (${CONVERSATION_UNION})
    42724272       WHERE other = @other
    42734273         AND (@bStamp IS NULL OR stamp < @bStamp OR (stamp = @bStamp AND ref < @bRef))
    42744274       ORDER BY stamp DESC, ref DESC LIMIT @n`).all({ slug, other, bStamp, bRef, n: n + 1 });
    4275     const meer = rijen.length > n;
    4276     const uit = meer ? rijen.slice(0, n) : rijen;
    4277     return { rijen: uit, meer, oudste: cursorVan(uit[uit.length - 1]) };
    4278   } catch { return { rijen: [], meer: false, oudste: null }; }
     4275    const more = rows.length > n;
     4276    const page = more ? rows.slice(0, n) : rows;
     4277    return { rows: page, more, oldest: cursorOf(page[page.length - 1]) };
     4278  } catch { return { rows: [], more: false, oldest: null }; }
    42794279}
    42804280
    42814281// De kolommen die een bericht tot kaart maken. Een constante, want de
    4282 // gesprekslezing haalt dezelfde rijen op: twee lijsten die uiteenlopen leveren
     4282// gesprekslezing haalt dezelfde rows op: twee lijsten die uiteenlopen leveren
    42834283// een kaart die op de ene plek een plaatje heeft en op de andere niet.
    4284 const BERICHT_KOLOMMEN = `
     4284const MESSAGE_COLUMNS = `
    42854285      m.object_uri, m.note_url, m.actor_uri, m.actor_name, m.actor_handle, m.actor_icon, m.actor_url,
    42864286      m.content, m.published, m.created_at, m.wave, m.help_request,
     
    42934293  try {
    42944294    const gaten = lijst.map(() => '?').join(',');
    4295     return db.prepare(`SELECT ${BERICHT_KOLOMMEN} FROM ap_mentions m
     4295    return db.prepare(`SELECT ${MESSAGE_COLUMNS} FROM ap_mentions m
    42964296                        WHERE m.slug = ? AND m.object_uri IN (${gaten})`).all(slug, ...lijst);
    42974297  } catch { return []; }
     
    43014301  try {
    43024302    return db.prepare(`
    4303       SELECT ${BERICHT_KOLOMMEN}
     4303      SELECT ${MESSAGE_COLUMNS}
    43044304      FROM ap_mentions m
    43054305      WHERE m.slug = ?
  • test/conversations.test.js

    rf549cf5 r3bbf73d  
    2626const VREEMDE = 'https://elders/u/vreemde';
    2727
    28 const binnen = (uri, van, stamp) =>
     28const arrived = (uri, van, stamp) =>
    2929  db.prepare(`INSERT INTO ap_mentions (slug, object_uri, actor_uri, actor_name, content, published)
    3030              VALUES ('kind', ?, ?, 'iemand', '<p>hoi</p>', ?)`).run(uri, van, stamp);
    31 const verstuurd = (id, naar, stamp, visibility = 'direct') =>
     31const sent = (id, naar, stamp, visibility = 'direct') =>
    3232  db.prepare(`INSERT INTO ap_outbox (id, site_slug, post_id, to_actor, to_actors, content, visibility, created_at)
    3333              VALUES (?, 'kind', 'p1', ?, ?, '<p>terug</p>', ?, ?)`)
     
    3535
    3636// Een DRUK gesprek met oma: genoeg om in de oude lezing de rest weg te drukken.
    37 for (let i = 0; i < 80; i++) binnen(`https://elders/n/oma-${i}`, OMA, `2026-08-09T10:${String(i % 60).padStart(2, '0')}:00Z`);
     37for (let i = 0; i < 80; i++) arrived(`https://elders/n/oma-${i}`, OMA, `2026-08-09T10:${String(i % 60).padStart(2, '0')}:00Z`);
    3838// En een stil gesprek met tante, ouder dan al die drukte.
    39 binnen('https://elders/n/tante-1', TANTE, '2026-08-01T09:00:00Z');
    40 verstuurd('mijn-1', TANTE, '2026-08-01T09:30:00Z');
     39arrived('https://elders/n/tante-1', TANTE, '2026-08-01T09:00:00Z');
     40sent('mijn-1', TANTE, '2026-08-01T09:30:00Z');
    4141// Een PUBLIEK antwoord aan een vreemde is geen gesprek.
    42 verstuurd('mijn-publiek', VREEMDE, '2026-08-09T12:00:00Z', 'public');
     42sent('mijn-publiek', VREEMDE, '2026-08-09T12:00:00Z', 'public');
    4343
    4444test('de oude lezing verliest tante achter een druk gesprek -- dat is de bug', () => {
     
    4949
    5050test('een rij per tegenpartij, hoe druk de drukste ook is', () => {
    51   const koppen = AP.conversationHeads('kind');
    52   assert.deepEqual(koppen.map((k) => k.other), [OMA, TANTE], 'nieuwste gesprek eerst, allebei aanwezig');
     51  const heads = AP.conversationHeads('kind');
     52  assert.deepEqual(heads.map((k) => k.other), [OMA, TANTE], 'nieuwste gesprek eerst, allebei aanwezig');
    5353});
    5454
     
    5858
    5959test('het gesprek draagt beide kanten onder EEN limiet', () => {
    60   const g = AP.conversationHistory('kind', TANTE, { limit: 60 });
    61   assert.equal(g.rijen.length, 2);
    62   assert.deepEqual(g.rijen.map((r) => r.richting), ['uit', 'in'], 'nieuwste eerst, mijn antwoord bovenaan');
    63   assert.equal(g.meer, false);
     60  const talk = AP.conversationHistory('kind', TANTE, { limit: 60 });
     61  assert.equal(talk.rows.length, 2);
     62  assert.deepEqual(talk.rows.map((r) => r.direction), ['out', 'in'], 'nieuwste eerst, mijn antwoord bovenaan');
     63  assert.equal(talk.more, false);
    6464});
    6565
     
    6767  // De 80 berichten van oma delen stempels (i % 60), en dat is met opzet:
    6868  // twee berichten in dezelfde seconde is bij DM's een gesprek, geen randgeval.
    69   const eerste = AP.conversationHistory('kind', OMA, { limit: 30 });
    70   assert.equal(eerste.rijen.length, 30);
    71   assert.equal(eerste.meer, true, 'er is meer, en dat mag de client weten');
     69  const first = AP.conversationHistory('kind', OMA, { limit: 30 });
     70  assert.equal(first.rows.length, 30);
     71  assert.equal(first.more, true, 'er is meer, en dat mag de client weten');
    7272
    73   const tweede = AP.conversationHistory('kind', OMA, { limit: 30, before: eerste.oudste });
    74   assert.equal(tweede.rijen.length, 30);
    75   // Geen overlap en geen gat: de tweede pagina begint waar de eerste ophield.
    76   const ids = new Set(eerste.rijen.map((r) => r.ref));
    77   assert.ok(tweede.rijen.every((r) => !ids.has(r.ref)), 'geen dubbele');
     73  const second = AP.conversationHistory('kind', OMA, { limit: 30, before: first.oldest });
     74  assert.equal(second.rows.length, 30);
     75  // Geen overlap en geen gat: de second pagina begint waar de first ophield.
     76  const ids = new Set(first.rows.map((r) => r.ref));
     77  assert.ok(second.rows.every((r) => !ids.has(r.ref)), 'geen dubbele');
    7878
    79   const derde = AP.conversationHistory('kind', OMA, { limit: 30, before: tweede.oudste });
    80   assert.equal(derde.rijen.length, 20, 'de staart');
    81   assert.equal(derde.meer, false, 'en dan is het op');
     79  const third = AP.conversationHistory('kind', OMA, { limit: 30, before: second.oldest });
     80  assert.equal(third.rows.length, 20, 'de staart');
     81  assert.equal(third.more, false, 'en dan is het op');
    8282  // Alles bij elkaar: precies 80, geen dubbele en niets overgeslagen. Met een
    8383  // cursor op alleen de stempel zou de grensseconde hier stil wegvallen.
    84   const alles = new Set([...eerste.rijen, ...tweede.rijen, ...derde.rijen].map((r) => r.ref));
    85   assert.equal(alles.size, 80, 'elke berichtje precies een keer');
     84  const allRefs = new Set([...first.rows, ...second.rows, ...third.rows].map((r) => r.ref));
     85  assert.equal(allRefs.size, 80, 'elke berichtje precies een keer');
    8686});
    8787
     
    101101  t.after(() => server.close());
    102102  await new Promise((r) => server.once('listening', r));
    103   const haal = async (pad) => {
     103  const get = async (pad) => {
    104104    const r = await fetch(`http://127.0.0.1:${server.address().port}${pad}`,
    105105      { headers: { Authorization: `Bearer ${bearer}` } });
     
    108108  const slug = '/ap/users/kind';
    109109
    110   const g = await haal(`${slug}/conversations`);
    111   assert.equal(g.status, 200);
    112   assert.equal(g.body.totalItems, 2, 'oma en tante, en niet de publieke vreemde');
     110  const list = await get(`${slug}/conversations`);
     111  assert.equal(list.status, 200);
     112  assert.equal(list.body.totalItems, 2, 'oma en tante, en niet de publieke vreemde');
    113113  // De byline zit in de ingesloten actor, net als overal sinds shaer-nmw.
    114   assert.ok(g.body.orderedItems.every((i) => i.object.attributedTo));
     114  assert.ok(list.body.orderedItems.every((i) => i.object.attributedTo));
    115115
    116   const eerste = await haal(`${slug}/messages?with=${encodeURIComponent(OMA)}&limit=30`);
    117   assert.equal(eerste.body.orderedItems.length, 30);
    118   assert.ok(eerste.body.next, 'er is meer, en de standaardvorm zegt het');
    119   assert.ok(eerste.body.next.includes('limit=30'), 'de paginagrootte reist mee');
     116  const first = await get(`${slug}/messages?with=${encodeURIComponent(OMA)}&limit=30`);
     117  assert.equal(first.body.orderedItems.length, 30);
     118  assert.ok(first.body.next, 'er is meer, en de standaardvorm zegt het');
     119  assert.ok(first.body.next.includes('limit=30'), 'de paginagrootte reist mee');
    120120
    121121  // De next-link volgen doet wat hij belooft: geen dubbele, en uiteindelijk op.
    122   const pad2 = eerste.body.next.replace(/^https?:\/\/[^/]+/, '');
    123   const tweede = await haal(pad2);
    124   const eersteIds = new Set(eerste.body.orderedItems.map((i) => i.object.id));
    125   assert.ok(tweede.body.orderedItems.every((i) => !eersteIds.has(i.object.id)), 'geen overlap');
    126   const derde = await haal(tweede.body.next.replace(/^https?:\/\/[^/]+/, ''));
    127   assert.equal(derde.body.orderedItems.length, 20);
    128   assert.equal(derde.body.next, undefined, 'op is op, en dat staat er ook');
     122  const path2 = first.body.next.replace(/^https?:\/\/[^/]+/, '');
     123  const second = await get(path2);
     124  const firstIds = new Set(first.body.orderedItems.map((i) => i.object.id));
     125  assert.ok(second.body.orderedItems.every((i) => !firstIds.has(i.object.id)), 'geen overlap');
     126  const third = await get(second.body.next.replace(/^https?:\/\/[^/]+/, ''));
     127  assert.equal(third.body.orderedItems.length, 20);
     128  assert.equal(third.body.next, undefined, 'op is op, en dat staat er ook');
    129129
    130130  // Een gesprek draagt beide kanten; het eigen antwoord aan tante hoort erbij.
    131   const tante = await haal(`${slug}/messages?with=${encodeURIComponent(TANTE)}`);
    132   assert.equal(tante.body.orderedItems.length, 2);
    133   assert.ok(tante.body.orderedItems.some((i) => i.actor === 'https://klonkt.test/ap/users/kind'), 'mijn eigen kant zit erin');
     131  const withAunt = await get(`${slug}/messages?with=${encodeURIComponent(TANTE)}`);
     132  assert.equal(withAunt.body.orderedItems.length, 2);
     133  assert.ok(withAunt.body.orderedItems.some((i) => i.actor === 'https://klonkt.test/ap/users/kind'), 'mijn eigen kant zit erin');
    134134
    135   const stuk = await haal(`${slug}/messages?with=nonsens`);
    136   assert.equal(stuk.status, 400, 'geen actor-uri, geen gesprek');
     135  const broken = await get(`${slug}/messages?with=nonsens`);
     136  assert.equal(broken.status, 400, 'geen actor-uri, geen gesprek');
    137137});
  • test/standard-shapes.test.js

    rf549cf5 r3bbf73d  
    117117    { headers: { Authorization: `Bearer ${bearer}` } })).json();
    118118
    119   const tekst = JSON.stringify(doc);
    120   // Op de SLEUTEL, niet op een stuk tekst: 'shaer:quote' zit ook in
     119  const text = JSON.stringify(doc);
     120  // Op de SLEUTEL, niet op een stuk text: 'shaer:quote' zit ook in
    121121  // shaer:quoteCards, en dat is een poortnaam die blijft. Een te grove zeef
    122122  // zou hier rood staan om iets dat klopt -- of erger, groen om iets dat niet
    123123  // klopt.
    124   for (const weg of ['shaer:author', 'shaer:booster', 'shaer:quote', 'shaer:embed']) {
    125     assert.ok(!tekst.includes(`"${weg}":`), `${weg} hoort weg te zijn`);
     124  for (const gone of ['shaer:author', 'shaer:booster', 'shaer:quote', 'shaer:embed']) {
     125    assert.ok(!text.includes(`"${gone}":`), `${gone} hoort weg te zijn`);
    126126  }
    127127  // Wat WEL mag blijven, en waarom: per-lezer-interactiestatus heeft in AS2
    128128  // geen tegenhanger (Mastodon lost het in zijn eigen REST-API op), en de
    129129  // FEP-633c-termen zijn bewust van ons en in standaardisatie.
    130   assert.ok(tekst.includes('shaer:liked'), 'interactiestatus blijft, die heeft geen standaard');
     130  assert.ok(text.includes('shaer:liked'), 'interactiestatus blijft, die heeft geen standaard');
    131131
    132132  const item = doc.orderedItems.find((i) => i.object.id === 'https://elders/n1');
  • test/thread.test.js

    rf549cf5 r3bbf73d  
    5555// een ECHT verzoek aan een testserver op localhost, en dat mag de stub niet
    5656// beantwoorden met zijn 404.
    57 const echteFetch = globalThis.fetch;
     57const realFetch = globalThis.fetch;
    5858
    5959globalThis.fetch = async (url) => {
     
    171171  t.after(() => server.close());
    172172  await new Promise((r) => server.once('listening', r));
    173   const haal = async () => (await (await echteFetch(
     173  const get = async () => (await (await realFetch(
    174174    `http://127.0.0.1:${server.address().port}/ap/users/kind/thread?object=${encodeURIComponent(BRON)}`,
    175175    { headers: { Authorization: `Bearer ${bearer}` } })).json());
    176176
    177   const doc = await haal();
     177  const doc = await get();
    178178  assert.ok(!JSON.stringify(doc).includes('"shaer:author":'), 'geen dialect meer op deze leg');
    179   const vanTante = doc.orderedItems.find((n) => n.id.endsWith('/replies/2'));
    180   assert.equal(vanTante.attributedTo.name, 'tante', 'de byline zit in attributedTo');
    181   assert.equal(vanTante.attributedTo.preferredUsername, 'tante');
    182   assert.ok((vanTante.tag || []).some((x) => x.type === 'Emoji'), 'open poort: de emoji van het antwoord blijft');
     179  const fromAunt = doc.orderedItems.find((n) => n.id.endsWith('/replies/2'));
     180  assert.equal(fromAunt.attributedTo.name, 'tante', 'de byline zit in attributedTo');
     181  assert.equal(fromAunt.attributedTo.preferredUsername, 'tante');
     182  assert.ok((fromAunt.tag || []).some((x) => x.type === 'Emoji'), 'open poort: de emoji van het antwoord blijft');
    183183
    184184  // Poort dicht: FEP-9098 zit in de tag van de ingesloten actor, dus daar
     
    188188  db.prepare("INSERT INTO ap_guardianships (slug, other_uri, role, status) VALUES ('kind', ?, 'guardian', 'accepted')")
    189189    .run('https://203.0.113.20/users/tante');
    190   const dicht = await haal();
    191   const na = dicht.orderedItems.find((n) => n.id.endsWith('/replies/2'));
    192   assert.ok(!(na.tag || []).some((x) => x.type === 'Emoji'), 'dichte poort: geen emoji meer');
    193   assert.ok(!na.attributedTo.tag, 'ook niet in de byline');
     190  const closed = await get();
     191  const after = closed.orderedItems.find((n) => n.id.endsWith('/replies/2'));
     192  assert.ok(!(after.tag || []).some((x) => x.type === 'Emoji'), 'dichte poort: geen emoji meer');
     193  assert.ok(!after.attributedTo.tag, 'ook niet in de byline');
    194194});
    195195
     
    217217  const vorige = globalThis.fetch;
    218218  t.after(() => { globalThis.fetch = vorige; });
    219   const vraag = async (uri) => {
    220     const r = await echteFetch(
     219  const ask = async (uri) => {
     220    const r = await realFetch(
    221221      `http://127.0.0.1:${server.address().port}/ap/users/kind/thread?object=${encodeURIComponent(uri)}`,
    222222      { headers: { Authorization: `Bearer ${bearer}` } });
     
    226226  // De bron zegt nee -- precies wat boiert.eu doet met een friends-only post
    227227  // voor iemand die de auteur niet (meer) volgt.
    228   const DICHT = 'https://203.0.113.50/notes/dicht';
     228  const SHUT = 'https://203.0.113.50/notes/dicht';
    229229  globalThis.fetch = async () => new Response('nope', { status: 404 });
    230   const nee = await vraag(DICHT);
    231   assert.equal(nee.status, 404);
    232   assert.equal(nee.body.error, 'not shared by source');
    233   assert.equal(nee.body.sourceStatus, 404);
     230  const refused = await ask(SHUT);
     231  assert.equal(refused.status, 404);
     232  assert.equal(refused.body.error, 'not shared by source');
     233  assert.equal(refused.body.sourceStatus, 404);
    234234
    235235  // De bron ligt eruit. Dezelfde lege uitkomst, een andere waarheid.
    236   const STUK = 'https://203.0.113.51/notes/stuk';
     236  const BROKEN = 'https://203.0.113.51/notes/stuk';
    237237  globalThis.fetch = async () => new Response('boem', { status: 500 });
    238   const stuk = await vraag(STUK);
    239   assert.equal(stuk.status, 502);
    240   assert.equal(stuk.body.error, 'source unreachable');
    241 });
     238  const broken = await ask(BROKEN);
     239  assert.equal(broken.status, 502);
     240  assert.equal(broken.body.error, 'source unreachable');
     241});
Note: See TracChangeset for help on using the changeset viewer.