Changeset 6e9bc70 in Klonkt for src/services
- Timestamp:
- 10/12/2026 04:15:08 PM (2 days ago)
- Branches:
- main
- Children:
- 61d52ed
- Parents:
- 746d98a
- Location:
- src/services
- Files:
-
- 1 added
- 4 edited
-
ActivityPubService.js (modified) (1 diff)
-
ap-inbox.js (modified) (2 diffs)
-
ap-timeline.js (modified) (2 diffs)
-
conversation-key.js (added)
-
guardianship/delivery.js (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ActivityPubService.js
r746d98a r6e9bc70 549 549 attributedTo: meR, 550 550 inReplyTo: post.in_reply_to || undefined, 551 // FEP-7888 (shaer-mbji): het gesprek waar dit bij hoort, in AS2 dat 552 // andere servers ook lezen. Alleen op wat er een heeft -- oude rijen en 553 // gewone antwoorden blijven precies zoals ze waren. 554 context: post.context || undefined, 551 555 content: post.content, 552 556 // Reply language (rich replies): the AS2 language map next to `content`. -
src/services/ap-inbox.js
r746d98a r6e9bc70 30 30 import { fwStmts } from './ap-following.js'; 31 31 import * as HubInvite from './hub-invite.js'; 32 import * as ConversationKey from './conversation-key.js'; 32 33 33 34 /** … … 852 853 // laten voor iedereen die de objectvorm stuurt. 853 854 const ouder = safeUrl(typeof o.inReplyTo === 'string' ? o.inReplyTo : (o.inReplyTo && o.inReplyTo.id)) || null; 854 const r = db.prepare(`INSERT OR IGNORE INTO ap_mentions (slug, object_uri, note_url, actor_uri, actor_name, actor_handle, actor_icon, actor_url, content, published, in_reply_to, help_request, wave, has_guardians, emoji_json, actor_emoji_json, media_json, created_at) 855 VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,${NU_ISO})`) 855 // WIE ER NOG MEER BIJ WAS (shaer-mbji). De afzender plus iedere 856 // persoon in to/cc, zonder ons. Zonder dit wist een bericht van 857 // Anna aan jou en Ben niet meer dat Ben erbij was, en kwam het 858 // alleen in het gesprek met Anna terecht. 859 // 860 // ALLEEN VOOR EEN DIRECT BERICHT. Deze tabel draagt ook publieke 861 // posts die ons noemen, en een openbare post aan jou en Ben is geen 862 // besloten gesprek met z'n drieën -- dat zou een groep verzinnen 863 // die niemand begon. Die blijft bij zijn afzender, zoals altijd. 864 const ander = noteVisibility(o) === 'direct' 865 ? ConversationKey.participantsOf(o, actorUri, actorId(base, slug)) 866 : [actorUri]; 867 const conv = ConversationKey.conversationKey(ander) || actorUri; 868 const r = db.prepare(`INSERT OR IGNORE INTO ap_mentions (slug, object_uri, note_url, actor_uri, actor_name, actor_handle, actor_icon, actor_url, content, published, in_reply_to, help_request, wave, has_guardians, emoji_json, actor_emoji_json, media_json, conv, participants, context, created_at) 869 VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,${NU_ISO})`) 856 870 .run(slug, o.id, safeUrl(o.url) || null, actorUri, ai.name, ai.handle, ai.icon, ai.url, html, o.published || null, ouder, help ? 1 : 0, wave ? 1 : 0, hasG ? 1 : 0, 857 extractEmojiTags(o.tag), emojiJsonOf(ai.emojis), mediaFromNote(o)); 871 extractEmojiTags(o.tag), emojiJsonOf(ai.emojis), mediaFromNote(o), 872 conv, JSON.stringify(ander), ConversationKey.contextOf(o)); 858 873 if (r.changes) { 859 874 // The quote / link-preview card resolves out of band (a remote -
src/services/ap-timeline.js
r746d98a r6e9bc70 248 248 */ 249 249 250 // `other` is hier DE GESPREKSSLEUTEL (shaer-mbji, conversation-key.js), en niet 251 // meer per se één persoon. Voor één ander is dat zijn URI, precies zoals 252 // altijd; voor een groep de gesorteerde set. De naam van de kolom bleef, want 253 // koppen, geschiedenis, leesmarkeringen en ongelezen lezen hem allemaal -- en 254 // die werken nu per gesprek in plaats van per persoon zonder dat er een regel 255 // in hoefde te veranderen. 256 // 257 // Oude rijen hebben geen `conv` en lezen zoals ze altijd lazen: een binnenkomer 258 // bij zijn afzender, een uitgaande bij elke ontvanger afzonderlijk. Geen 259 // migratie die de geschiedenis herschikt; alleen wat nieuw is, groepeert. 250 260 const CONVERSATION_UNION = ` 251 SELECT m.actor_uri AS other, ${STEMPEL('COALESCE(m.published, m.created_at)')} AS stamp, 261 SELECT COALESCE(NULLIF(m.conv, ''), m.actor_uri) AS other, 262 ${STEMPEL('COALESCE(m.published, m.created_at)')} AS stamp, 252 263 'in' AS direction, m.object_uri AS ref 253 264 FROM ap_mentions m 254 265 WHERE m.slug = @slug AND m.actor_uri IS NOT NULL AND m.actor_uri <> '' 266 UNION ALL 267 SELECT o.conv AS other, ${STEMPEL('o.created_at')} AS stamp, 268 'out' AS direction, o.id AS ref 269 FROM ap_outbox o 270 WHERE o.site_slug = @slug AND o.visibility = 'direct' 271 AND o.conv IS NOT NULL AND o.conv <> '' 255 272 UNION ALL 256 273 SELECT j.value AS other, ${STEMPEL('o.created_at')} AS stamp, … … 259 276 JOIN json_each(COALESCE(NULLIF(o.to_actors, ''), json_array(o.to_actor))) j 260 277 WHERE o.site_slug = @slug AND o.visibility = 'direct' 278 AND (o.conv IS NULL OR o.conv = '') 261 279 AND j.value IS NOT NULL AND j.value <> ''`; 262 280 -
src/services/guardianship/delivery.js
r746d98a r6e9bc70 14 14 import db, { NU_ISO } from '../../config/database.js'; 15 15 import { carriesGuardians } from './context.js'; 16 import * as ConversationKey from '../conversation-key.js'; 16 17 17 18 const PUBLIC = 'https://www.w3.org/ns/activitystreams#Public'; … … 33 34 if (!to.length && !cc.length) return 'public'; // no addressing at all: legacy client, keep old behavior 34 35 return 'direct'; 36 } 37 38 /** 39 * De context (FEP-7888) van het bericht waarop geantwoord wordt, als we die 40 * kennen: uit wat binnenkwam of uit wat we zelf stuurden. Een antwoord hoort in 41 * het gesprek van zijn ouder, en niet in een vers gesprek ernaast. 42 */ 43 function contextFor(slug, inReplyTo) { 44 if (!inReplyTo) return null; 45 try { 46 const binnen = db.prepare('SELECT context FROM ap_mentions WHERE slug = ? AND object_uri = ? AND context IS NOT NULL') 47 .get(slug, inReplyTo); 48 if (binnen && binnen.context) return binnen.context; 49 // Een eigen note heeft als uri .../ap/notes/<id>; de id is de outbox-sleutel. 50 const eigen = /\/ap\/notes\/([^/?#]+)$/.exec(String(inReplyTo)); 51 if (eigen) { 52 const rij = db.prepare('SELECT context FROM ap_outbox WHERE site_slug = ? AND id = ? AND context IS NOT NULL') 53 .get(slug, eigen[1]); 54 if (rij && rij.context) return rij.context; 55 } 56 } catch { /* geen context is ook een antwoord */ } 57 return null; 35 58 } 36 59 … … 144 167 .map((a) => ({ url: a.url, mediaType: String(a.mediaType), name: String(a.name || '').slice(0, 120) })); 145 168 const id = crypto.randomUUID(); 146 db.prepare(`INSERT INTO ap_outbox (id, site_slug, post_id, post_slug, in_reply_to, to_actor, to_handle, content, language, attachments, visibility, to_actors, help_request, wave, away_until, created_at) 147 VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,${NU_ISO})`) 148 .run(id, site.slug, '', null, inReplyTo || null, resolved[0].uri, resolved[0].handle, content, lang, media.length ? JSON.stringify(media) : null, 'direct', JSON.stringify(resolved.map((r) => r.uri)), helpRequest ? 1 : 0, wave ? 1 : 0, awayUntil || null); 169 // Het gesprek waar dit bij hoort (shaer-mbji): de set ontvangers. Aan Anna en 170 // Ben samen is één gesprek, en niet twee die elk de helft dragen. 171 const conv = ConversationKey.conversationKey(resolved.map((r) => r.uri)); 172 // FEP-7888: het gesprek een naam geven die andere servers ook lezen. Is dit 173 // een antwoord op iets met een context, dan hoort het in diezelfde; anders 174 // begint hier een nieuwe. 175 const context = contextFor(site.slug, inReplyTo) || `${base}/ap/contexts/${crypto.randomUUID()}`; 176 db.prepare(`INSERT INTO ap_outbox (id, site_slug, post_id, post_slug, in_reply_to, to_actor, to_handle, content, language, attachments, visibility, to_actors, help_request, wave, away_until, conv, context, created_at) 177 VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,${NU_ISO})`) 178 .run(id, site.slug, '', null, inReplyTo || null, resolved[0].uri, resolved[0].handle, content, lang, media.length ? JSON.stringify(media) : null, 'direct', JSON.stringify(resolved.map((r) => r.uri)), helpRequest ? 1 : 0, wave ? 1 : 0, awayUntil || null, conv, context); 149 179 const row = getOutboxRow(id); 150 180 const note = buildReplyNote(base, site, row);
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)