Changeset 484adf8 in Klonkt for src/services/ActivityPubService.js
- Timestamp:
- 06/26/2026 11:16:45 AM (2 months ago)
- Branches:
- main
- Children:
- 5045c30
- Parents:
- 5783c67
- File:
-
- 1 edited
-
src/services/ActivityPubService.js (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ActivityPubService.js
r5783c67 r484adf8 662 662 } 663 663 const media = JSON.stringify(_atts); 664 // "Feature" = show in the Cirkel (local only). We do NOT auto-Announce 665 // incoming posts to the fediverse — that flooded followers (esp. on the 666 // initial backfill). Boosting to the fediverse is a deliberate, one-time 667 // "boost the latest 5" action at feature time (see boostLatestN). 664 668 for (const s of subs) { 665 669 tlStmts().ins.run(o.id, s.slug, actorUri, ai.name, ai.handle, ai.icon, ai.url, html, o.url || null, o.published || null, media); 666 // "Feature an artist": auto-boost (re-Announce) their new posts to our own followers.667 if (s.auto_boost) sendInteraction({ slug: s.slug }, 'boost', o.id, actorUri).catch(() => { /* best-effort */ });668 670 } 669 671 console.log('[AP] timeline +', actorUri, 'x' + subs.length); … … 1181 1183 catch (e) { console.warn('[AP] follow deliver failed:', e.message); } 1182 1184 console.log('[AP] follow', site.slug, '→', actor.id); 1183 return { ok: true, name: ai.name, handle: ai.handle };1185 return { ok: true, name: ai.name, handle: ai.handle, actor: actor.id }; 1184 1186 } 1185 1187 … … 1231 1233 console.log('[AP]', type, site.slug, '→', targetNoteId, 'delivered', delivered); 1232 1234 return { ok: true, delivered }; 1235 } 1236 1237 // One-time "boost the latest N posts" of an account to the fediverse — the 1238 // deliberate, bounded alternative to auto-boosting every post. Opt-in at feature 1239 // time so featuring an artist never floods your followers with their whole backlog. 1240 export async function boostLatestN(site, actorUrl, n = 5) { 1241 try { 1242 const actor = await fetchActor(actorUrl).catch(() => null); 1243 if (!actor || !actor.outbox) return { ok: false, boosted: 0 }; 1244 const getJson = async (u) => { try { const r = await fetch(u, { headers: { Accept: 'application/activity+json' } }); return r.ok ? await r.json() : null; } catch { return null; } }; 1245 let coll = await getJson(actor.outbox); 1246 let items = (coll && coll.orderedItems) || []; 1247 if (!items.length && coll && coll.first) { 1248 const page = typeof coll.first === 'string' ? await getJson(coll.first) : coll.first; 1249 items = (page && page.orderedItems) || []; 1250 } 1251 const noteIds = items 1252 .filter((it) => it && it.type === 'Create' && it.object) 1253 .map((it) => (typeof it.object === 'string' ? it.object : it.object.id)) 1254 .filter(Boolean) 1255 .slice(0, n); // outbox is newest-first → the latest N 1256 let boosted = 0; 1257 for (const id of noteIds) { try { const r = await sendInteraction(site, 'boost', id, actorUrl); if (r && r.ok) boosted++; } catch { /* best-effort */ } } 1258 return { ok: true, boosted }; 1259 } catch { return { ok: false, boosted: 0 }; } 1233 1260 } 1234 1261 … … 1319 1346 listOutbox, deliverOutboxDelete, 1320 1347 webfingerResolve, followActor, resolveRemoteActor, unfollowActor, listFollowing, setAutoBoost, getTimeline, sendInteraction, 1321 autoBoostCount, getCirkelPosts, getCirkelMembers, autoMigrateCircles, selfHealTimeline, 1348 autoBoostCount, getCirkelPosts, getCirkelMembers, autoMigrateCircles, selfHealTimeline, boostLatestN, 1322 1349 getNotifications, listBlocks, isBlockedAny, blockTarget, unblock, 1323 1350 deliverWithRetry, enqueueDelivery, processDeliveryQueue, startDeliveryWorker,
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)