Changeset dc8e9bd in Klonkt
- Timestamp:
- 06/24/2026 02:31:09 PM (3 months ago)
- Branches:
- main
- Children:
- 40cf2ef
- Parents:
- 59f0170
- File:
-
- 1 edited
-
src/services/ActivityPubService.js (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ActivityPubService.js
r59f0170 rdc8e9bd 526 526 if (a) inboxes.add((a.endpoints && a.endpoints.sharedInbox) || a.inbox); 527 527 } 528 if (parent.threadInbox) inboxes.add(parent.threadInbox); // post author's server (nesting) 528 if (parent.threadInbox) inboxes.add(parent.threadInbox); // back-compat (single) 529 (parent.threadInboxes || []).forEach((i) => inboxes.add(i)); // whole ancestor chain 529 530 for (const f of fStmts().list.all(site.slug)) inboxes.add(f.shared_inbox || f.inbox); 530 531 inboxes.delete(`${me}/inbox`); // never deliver to ourselves (already in ap_outbox) … … 552 553 // link our reply to that local post so it shows nested in the post thread. 553 554 const localTgt = findThreadTarget(note.id, (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, '')); 554 // If this note is itself a reply (a comment), also reach the original post's 555 // author so THEIR server threads our reply under the comment. 556 let threadInbox = null; 557 if (note.inReplyTo) { 558 const parentUrl = typeof note.inReplyTo === 'string' ? note.inReplyTo : (note.inReplyTo && note.inReplyTo.id); 559 const parentNote = parentUrl ? await fetchActor(parentUrl).catch(() => null) : null; 560 const pAtt = parentNote && (typeof parentNote.attributedTo === 'string' ? parentNote.attributedTo : (parentNote.attributedTo && parentNote.attributedTo.id)); 561 if (pAtt && pAtt !== actorUri) { 562 const pa = await fetchActor(pAtt).catch(() => null); 563 threadInbox = pa && ((pa.endpoints && pa.endpoints.sharedInbox) || pa.inbox); 555 // Walk the WHOLE reply chain upward (comment → parent comment → … → root post) 556 // and collect every ancestor author's inbox, so each participant's server — 557 // including the original post's author — receives + threads our reply. 558 const threadInboxes = []; 559 const seenInbox = new Set(); 560 let cursor = note.inReplyTo, guard = 0; 561 while (cursor && guard++ < 6) { 562 const url = typeof cursor === 'string' ? cursor : (cursor && cursor.id); 563 if (!url) break; 564 const pn = await fetchActor(url).catch(() => null); 565 if (!pn) break; 566 const pa = typeof pn.attributedTo === 'string' ? pn.attributedTo : (pn.attributedTo && pn.attributedTo.id); 567 if (pa && pa !== actorUri) { 568 const paDoc = await fetchActor(pa).catch(() => null); 569 const inbox = paDoc && ((paDoc.endpoints && paDoc.endpoints.sharedInbox) || paDoc.inbox); 570 if (inbox && !seenInbox.has(inbox)) { seenInbox.add(inbox); threadInboxes.push(inbox); } 564 571 } 572 cursor = pn.inReplyTo; // climb to the next ancestor 565 573 } 566 574 const rawHtml = String(note.content || '').replace(/\[\[(track|album|playlist):[^\]]+\]\]/gi, ''); … … 578 586 content: HtmlSanitizerService.sanitize(rawHtml), // full, sanitized 579 587 images, 580 threadInbox , // post author's inbox (if a comment)588 threadInboxes, // every ancestor author's inbox 581 589 localPostId: localTgt ? localTgt.post_id : '', // our post this belongs to (if any) 582 590 preview: HtmlSanitizerService.toPlainText(note.content || '').slice(0, 240),
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)