- Timestamp:
- 07/19/2026 03:53:49 PM (7 weeks ago)
- Branches:
- main
- Children:
- 2d66d66
- Parents:
- bf72108
- git-author:
- Robin <roboburr@…> (07/19/2026 03:53:33 PM)
- git-committer:
- Robin <roboburr@…> (07/19/2026 03:53:49 PM)
- Location:
- src
- Files:
-
- 2 edited
-
routes/activitypub.js (modified) (1 diff)
-
services/ActivityPubService.js (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/routes/activitypub.js
rbf72108 r4407c67 84 84 }); 85 85 86 // ── Followers (count only) ──────────────────────────────────────── 86 // ── Followers (count-only public, full for the owner) ───────────── 87 // A C2S bearer scoped to this site (the account owner) gets the real actor 88 // URIs so their own client can build a friends list; everyone else gets the 89 // count only (privacy). 87 90 router.get('/ap/users/:slug/followers', (req, res) => { 88 const site = publicSite(req.params.slug); 89 if (!site) return res.status(404).end(); 91 const auth = OAuth.verifyBearer(req.headers.authorization); 92 const owner = auth && auth.site.slug === req.params.slug; 93 const site = owner ? auth.site : publicSite(req.params.slug); 94 if (!site) return res.status(404).end(); 95 if (owner) { 96 const items = db.prepare('SELECT actor_uri FROM ap_followers WHERE slug = ? ORDER BY created_at').all(site.slug).map((r) => r.actor_uri); 97 return AP.sendAP(res, AP.buildFollowers(baseUrl(req), site, items.length, items)); 98 } 90 99 const n = db.prepare('SELECT COUNT(*) n FROM ap_followers WHERE slug = ?').get(site.slug).n; 91 100 AP.sendAP(res, AP.buildFollowers(baseUrl(req), site, n)); 92 101 }); 93 102 94 // ── Following (count only) ────────────────────────────────────────103 // ── Following (count-only public, full for the owner) ───────────── 95 104 router.get('/ap/users/:slug/following', (req, res) => { 96 const site = publicSite(req.params.slug); 97 if (!site) return res.status(404).end(); 105 const auth = OAuth.verifyBearer(req.headers.authorization); 106 const owner = auth && auth.site.slug === req.params.slug; 107 const site = owner ? auth.site : publicSite(req.params.slug); 108 if (!site) return res.status(404).end(); 109 if (owner) { 110 let items = []; 111 try { items = db.prepare("SELECT actor_uri FROM ap_following WHERE slug = ? AND status = 'accepted' ORDER BY created_at").all(site.slug).map((r) => r.actor_uri); } catch { /* table may not exist */ } 112 return AP.sendAP(res, AP.buildFollowing(baseUrl(req), site, items.length, items)); 113 } 98 114 let n = 0; 99 115 try { n = db.prepare("SELECT COUNT(*) n FROM ap_following WHERE slug = ? AND status = 'accepted'").get(site.slug).n; } catch { /* table may not exist */ } -
src/services/ActivityPubService.js
rbf72108 r4407c67 542 542 } 543 543 544 export function buildFollowers(base, site, count) { 544 // Public callers get a count-only collection (privacy). The authenticated 545 // account owner (a C2S bearer scoped to this site) gets the real actor URIs via 546 // `items`, so their own client can build a friends list. 547 export function buildFollowers(base, site, count, items = null) { 545 548 const id = `${actorId(base, site.slug)}/followers`; 546 549 return { … … 548 551 id, 549 552 type: 'OrderedCollection', 550 totalItems: count || 0,551 orderedItems: [], // hidden for privacy; count only553 totalItems: items ? items.length : (count || 0), 554 orderedItems: items || [], // count-only for the public; full for the owner 552 555 }; 553 556 } … … 555 558 // The accounts this site follows — count only, mirroring buildFollowers. The spec lists 556 559 // `following` as a standard actor property; Hubzilla/Friendica + crawlers expect it. 557 export function buildFollowing(base, site, count ) {560 export function buildFollowing(base, site, count, items = null) { 558 561 const id = `${actorId(base, site.slug)}/following`; 559 562 return { … … 561 564 id, 562 565 type: 'OrderedCollection', 563 totalItems: count || 0,564 orderedItems: [], // count only566 totalItems: items ? items.length : (count || 0), 567 orderedItems: items || [], // count-only for the public; full for the owner 565 568 }; 566 569 }
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)