Changeset 971d00b in Klonkt
- Timestamp:
- 08/06/2026 06:48:32 AM (5 weeks ago)
- Branches:
- main
- Children:
- 99a7b40
- Parents:
- 39111c0
- git-author:
- Robin <roboburr@…> (08/06/2026 06:48:31 AM)
- git-committer:
- Claude (agent) <aiclaude@…> (08/06/2026 06:48:32 AM)
- Files:
-
- 2 edited
-
src/services/ActivityPubService.js (modified) (3 diffs)
-
test/messages-conversations.test.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ActivityPubService.js
r39111c0 r971d00b 627 627 // outboxId), sorted as one stream. Consecutive likes/boosts on the same post collapse into 628 628 // one grouped item (actors list + count) so activity doesn't drown out conversations. 629 /** ap_outbox.attachments ([{url, mediaType, name}]) naar de vorm die note-body 630 * leest (media_json: [{url, type, name}]). Geeft null bij niets of rommel, 631 * zodat een kapotte kolom hooguit media kost en niet de hele regel. */ 632 function outboxMediaJson(attachments) { 633 if (!attachments) return null; 634 try { 635 const list = JSON.parse(attachments); 636 if (!Array.isArray(list) || !list.length) return null; 637 const media = list 638 .filter((a) => a && a.url) 639 .map((a) => ({ url: a.url, type: a.mediaType || a.type || '', name: a.name || undefined })); 640 return media.length ? JSON.stringify(media) : null; 641 } catch { return null; } 642 } 643 629 644 export function getMessages(slug, limit, offset) { 630 645 const off = Math.max(0, offset || 0); … … 641 656 in_reply_to: m.in_reply_to, post_slug: m.post_slug, content: m.content, 642 657 editable: m.editable, language: m.language, created_at: m.created_at, 658 // Je eigen bericht hoort er hetzelfde uit te zien als dat van een ander: 659 // note-body rendert Berichten, de Krant en de Guardian-PWA, maar leest 660 // media uit media_json met een `type`, terwijl ap_outbox ze als 661 // `attachments` met een `mediaType` bewaart. Zonder deze vertaling kwam 662 // een foto die JIJ meestuurde als kale tekst binnen. 663 media_json: outboxMediaJson(m.attachments), 643 664 }); 644 665 } … … 3020 3041 // gaat staan (zie threadKey). Zonder die kolom viel een uitwisseling uit 3021 3042 // elkaar in "Verzonden" en "Gesprekken". 3022 return db.prepare('SELECT id, content, to_handle, to_actor, to_actors, post_slug, in_reply_to, language, created_at FROM ap_outbox WHERE site_slug = ? ORDER BY created_at DESC')3043 return db.prepare('SELECT id, content, to_handle, to_actor, to_actors, post_slug, in_reply_to, attachments, language, created_at FROM ap_outbox WHERE site_slug = ? ORDER BY created_at DESC') 3023 3044 .all(siteSlug).map((r) => { const c = stripLeadingMentions(r.content); return { ...r, content: c, editable: outboxEditableText(c) }; }); 3024 3045 } -
test/messages-conversations.test.js
r39111c0 r971d00b 132 132 assert.equal(a, b, 'dezelfde tegenpartij hoort dezelfde sleutel te geven'); 133 133 }); 134 135 test('een eigen bericht met media rendert als een post, niet als kale tekst', async () => { 136 // note-body (gedeeld met de Krant) leest media_json met een `type`; ap_outbox 137 // bewaart attachments met een `mediaType`. Zonder vertaling viel een foto die 138 // JIJ meestuurde weg. 139 const db = (await import('../src/config/database.js')).default; 140 db.prepare('INSERT INTO users (id, username, email, password_hash, role) VALUES (?,?,?,?,?)') 141 .run('mu', 'mu', 'mu@test', 'x', 'god'); 142 db.prepare('INSERT INTO sites (id, slug, title, owner_id) VALUES (?,?,?,?)').run('ms', 'media', 'Media', 'mu'); 143 db.prepare(`INSERT INTO ap_outbox (id, site_slug, post_id, post_slug, to_handle, content, attachments, created_at) 144 VALUES ('om1','media','pm1','een-post','@anna@a.test','<p>kijk</p>',?,'2026-08-06 09:00:00')`) 145 .run(JSON.stringify([{ url: '/media/foto.png', mediaType: 'image/png', name: 'foto' }])); 146 147 const t = AP.getMessages('media', 50, 0).find((i) => i.type === 'thread'); 148 const sent = t.messages.find((m) => m.type === 'sent'); 149 assert.deepEqual(JSON.parse(sent.media_json), [{ url: '/media/foto.png', type: 'image/png', name: 'foto' }]); 150 }); 151 152 test('een eigen bericht zonder of met kapotte media houdt gewoon zijn tekst', async () => { 153 const db = (await import('../src/config/database.js')).default; 154 db.prepare('INSERT INTO sites (id, slug, title, owner_id) VALUES (?,?,?,?)').run('ms2', 'media2', 'M2', 'mu'); 155 db.prepare(`INSERT INTO ap_outbox (id, site_slug, post_id, post_slug, to_handle, content, attachments, created_at) 156 VALUES ('om2','media2','pm2','p','@anna@a.test','<p>a</p>','geen json','2026-08-06 09:00:00'), 157 ('om3','media2','pm3','p','@bo@b.test','<p>b</p>',NULL,'2026-08-06 09:01:00')`).run(); 158 const threads = AP.getMessages('media2', 50, 0).filter((i) => i.type === 'thread'); 159 const alle = threads.flatMap((t) => t.messages); 160 assert.equal(alle.length, 2, 'geen bericht mag verdwijnen door kapotte media'); 161 for (const m of alle) assert.equal(m.media_json, null); 162 });
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)