Changeset 80c36a1 in Klonkt for src/services


Ignore:
Timestamp:
06/27/2026 01:04:55 AM (3 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
dcff893
Parents:
e390844
Message:

feat(fedi): fans-only = followers-only federation (option A)

A fan_only post now federates to your followers but addressed followers-only (to:
followers, no Public) so only they see it in their feed and it can't be boosted public.
buildNote sets the audience from post.fan_only; create/save/scheduler/delete hooks no
longer skip fan_only (they pass fan_only through). The public outbox still excludes
fan_only, and the on-site fan-gate is unchanged (so it stays hidden on the site).

Location:
src/services
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    re390844 r80c36a1  
    240240    url: human,
    241241    published: new Date(post.published_at || post.created_at || Date.now()).toISOString(),
    242     to: [PUBLIC],
    243     cc: [`${aId}/followers`],
     242    // fan_only = "fans only" → followers-only visibility (delivered to your followers
     243    // but not addressed to Public, so Mastodon shows it only to them and can't boost it).
     244    to: post.fan_only ? [`${aId}/followers`] : [PUBLIC],
     245    cc: post.fan_only ? [] : [`${aId}/followers`],
    244246    tag: Array.isArray(post.tags) ? post.tags.map((t) => ({ type: 'Hashtag', name: '#' + String(t).replace(/\s+/g, '') })) : [],
    245247    replies: `${id}/replies`,
  • src/services/Scheduler.js

    re390844 r80c36a1  
    3232      // get a duplicate FTS row → duplicate search hits.
    3333      try { ftsDel.run(p.id); fts.run(HtmlSanitizerService.toPlainText(p.content || ''), p.title || '', p.username || '', p.id); } catch { /* FTS failure is non-fatal */ }
    34       // ActivityPub: federate the now-published post to followers.
    35       if (!p.fan_only) {
    36         try {
    37           const site = siteStmt.get(p.site_id);
    38           if (site) {
    39             ActivityPubService.deliverCreate(site, {
    40               id: p.id, slug: p.slug, title: p.title || p.slug,
    41               content: p.content, cover_image_url: p.cover_image_url || null,
    42               published_at: p.published_at || p.publish_at, created_at: p.created_at,
    43             }).catch(() => { /* best-effort */ });
    44           }
    45         } catch { /* non-fatal */ }
    46       }
     34      // ActivityPub: federate the now-published post to followers (fan_only → followers-only).
     35      try {
     36        const site = siteStmt.get(p.site_id);
     37        if (site) {
     38          ActivityPubService.deliverCreate(site, {
     39            id: p.id, slug: p.slug, title: p.title || p.slug,
     40            content: p.content, cover_image_url: p.cover_image_url || null,
     41            published_at: p.published_at || p.publish_at, created_at: p.created_at, fan_only: p.fan_only,
     42          }).catch(() => { /* best-effort */ });
     43        }
     44      } catch { /* non-fatal */ }
    4745    }
    4846    return due.length;
Note: See TracChangeset for help on using the changeset viewer.