Ignore:
Timestamp:
06/26/2026 11:16:45 AM (2 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
5045c30
Parents:
5783c67
Message:

feat(cirkel): featuring is local-only; optional one-time 'boost latest 5'

Per Robin+Bart: featuring an artist = show their posts in your Cirkel (local) — it
no longer auto-Announces every incoming post to the fediverse (that flooded
followers, esp. on the follow backfill). Boosting to the fediverse is now a
deliberate, opt-in 'boost the latest 5' checkbox at follow time (off by default,
one-time). boostLatestN() reads the actor outbox and boosts the 5 newest. Labels
reworked (auto-boost -> Uitgelicht / feature in circle). nl/en/de.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    r5783c67 r484adf8  
    662662        }
    663663        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).
    664668        for (const s of subs) {
    665669          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 */ });
    668670        }
    669671        console.log('[AP] timeline +', actorUri, 'x' + subs.length);
     
    11811183  catch (e) { console.warn('[AP] follow deliver failed:', e.message); }
    11821184  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 };
    11841186}
    11851187
     
    12311233  console.log('[AP]', type, site.slug, '→', targetNoteId, 'delivered', delivered);
    12321234  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.
     1240export 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 }; }
    12331260}
    12341261
     
    13191346  listOutbox, deliverOutboxDelete,
    13201347  webfingerResolve, followActor, resolveRemoteActor, unfollowActor, listFollowing, setAutoBoost, getTimeline, sendInteraction,
    1321   autoBoostCount, getCirkelPosts, getCirkelMembers, autoMigrateCircles, selfHealTimeline,
     1348  autoBoostCount, getCirkelPosts, getCirkelMembers, autoMigrateCircles, selfHealTimeline, boostLatestN,
    13221349  getNotifications, listBlocks, isBlockedAny, blockTarget, unblock,
    13231350  deliverWithRetry, enqueueDelivery, processDeliveryQueue, startDeliveryWorker,
Note: See TracChangeset for help on using the changeset viewer.