From 9fd6ac6bb8b47461b6975a1833bd86313e0c9311 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 7 Feb 2025 08:21:41 -0500 Subject: [PATCH] refactor: move 1b12 announce logic out of inbox and into separate feps module 1b12 announces were previously only happening for local creates and received activities, but they should happen for all local activities as well. re: #13072 --- src/activitypub/feps.js | 36 +++++++++++++++++++++++++++ src/activitypub/inbox.js | 38 ++++------------------------ src/activitypub/index.js | 1 + src/api/activitypub.js | 53 ++++++++++++++++++++++------------------ 4 files changed, 71 insertions(+), 57 deletions(-) create mode 100644 src/activitypub/feps.js diff --git a/src/activitypub/feps.js b/src/activitypub/feps.js new file mode 100644 index 0000000000..3c4cf5ef1c --- /dev/null +++ b/src/activitypub/feps.js @@ -0,0 +1,36 @@ +'use strict'; + +const nconf = require('nconf'); +const winston = require('winston'); + +const posts = require('../posts'); + +const activitypub = module.parent.exports; +const Feps = module.exports; + +Feps.announce = async function announce(id, activity) { + let localId; + if (String(id).startsWith(nconf.get('url'))) { + ({ id: localId } = await activitypub.helpers.resolveLocalId(id)); + } + const cid = await posts.getCidByPid(localId || id); + + const followers = await activitypub.notes.getCategoryFollowers(cid); + if (!followers.length) { + return; + } + + const { actor } = activity; + if (actor && !actor.startsWith(nconf.get('url'))) { + followers.unshift(actor); + } + + winston.info(`[activitypub/inbox.announce(1b12)] Announcing ${activity.type} to followers of cid ${cid}`); + await activitypub.send('cid', cid, followers, { + id: `${nconf.get('url')}/post/${encodeURIComponent(id)}#activity/announce/${Date.now()}`, + type: 'Announce', + to: [`${nconf.get('url')}/category/${cid}/followers`], + cc: [actor, activitypub._constants.publicAddress], + object: activity, + }); +}; diff --git a/src/activitypub/inbox.js b/src/activitypub/inbox.js index 2887caac04..0087f34b24 100644 --- a/src/activitypub/inbox.js +++ b/src/activitypub/inbox.js @@ -32,34 +32,6 @@ function reject(type, object, target, senderType = 'uid', id = 0) { }).catch(err => winston.error(err.stack)); } -// FEP 1b12 -async function announce(id, activity) { - let localId; - if (id.startsWith(nconf.get('url'))) { - ({ id: localId } = await activitypub.helpers.resolveLocalId(id)); - } - const cid = await posts.getCidByPid(localId || id); - - const followers = await activitypub.notes.getCategoryFollowers(cid); - if (!followers.length) { - return; - } - - const { actor } = activity; - followers.unshift(actor); - - winston.info(`[activitypub/inbox.announce(1b12)] Announcing ${activity.type} to followers of cid ${cid}`); - await Promise.all([activity, activity.object].map(async (object) => { - await activitypub.send('cid', cid, followers, { - id: `${nconf.get('url')}/post/${encodeURIComponent(id)}#activity/announce/${Date.now()}`, - type: 'Announce', - to: [`${nconf.get('url')}/category/${cid}/followers`], - cc: [actor, activitypub._constants.publicAddress], - object, - }); - })); -} - inbox.create = async (req) => { const { object } = req.body; @@ -71,7 +43,7 @@ inbox.create = async (req) => { const asserted = await activitypub.notes.assert(0, object); if (asserted) { - announce(object.id, req.body); + activitypub.feps.announce(object.id, req.body); api.activitypub.add(req, { pid: object.id }); } }; @@ -141,7 +113,7 @@ inbox.update = async (req) => { const asserted = await activitypub.notes.assert(0, object.id); if (asserted) { - announce(object.id, req.body); + activitypub.feps.announce(object.id, req.body); } break; } @@ -229,7 +201,7 @@ inbox.delete = async (req) => { switch (true) { case isNote: { const uid = await posts.getPostField(pid, 'uid'); - await announce(pid, req.body); + await activitypub.feps.announce(pid, req.body); await api.posts[method]({ uid }, { pid }); break; } @@ -263,7 +235,7 @@ inbox.like = async (req) => { winston.verbose(`[activitypub/inbox/like] id ${id} via ${actor}`); const result = await posts.upvote(id, actor); - announce(object.id, req.body); + activitypub.feps.announce(object.id, req.body); socketHelpers.upvote(result, 'notifications:upvoted-your-post-in'); }; @@ -529,7 +501,7 @@ inbox.undo = async (req) => { } await posts.unvote(id, actor); - announce(object.object, req.body); + activitypub.feps.announce(object.object, req.body); notifications.rescind(`upvote:post:${id}:uid:${actor}`); break; } diff --git a/src/activitypub/index.js b/src/activitypub/index.js index 1884eb76ef..501ac3402a 100644 --- a/src/activitypub/index.js +++ b/src/activitypub/index.js @@ -56,6 +56,7 @@ ActivityPub.notes = require('./notes'); ActivityPub.contexts = require('./contexts'); ActivityPub.actors = require('./actors'); ActivityPub.instances = require('./instances'); +ActivityPub.feps = require('./feps'); ActivityPub.startJobs = () => { ActivityPub.helpers.log('[activitypub/jobs] Registering jobs.'); diff --git a/src/api/activitypub.js b/src/api/activitypub.js index 76abcc9c51..c66cf9bde9 100644 --- a/src/api/activitypub.js +++ b/src/api/activitypub.js @@ -128,8 +128,6 @@ activitypubApi.create.note = enabledCheck(async (caller, { pid, post }) => { const { to, cc, targets } = await activitypub.buildRecipients(object, { pid, uid: post.user.uid }); object.to = to; object.cc = cc; - const { cid } = post.category; - const followers = await activitypub.notes.getCategoryFollowers(cid); const payload = { id: `${object.id}#activity/create/${Date.now()}`, @@ -140,22 +138,11 @@ activitypubApi.create.note = enabledCheck(async (caller, { pid, post }) => { object, }; - await activitypub.send('uid', caller.uid, Array.from(targets), payload); - - setTimeout(() => { // Delay sending to avoid potential race condition - if (followers.length) { - Promise.all([payload, payload.object].map(async (object) => { - await activitypub.send('cid', cid, followers, { - id: `${nconf.get('url')}/post/${encodeURIComponent(object.object ? object.object.id : object.id)}#activity/announce/${Date.now()}`, - type: 'Announce', - to: [activitypub._constants.publicAddress], - cc: [`${nconf.get('url')}/category/${cid}/followers`], - object, - }); - })).catch(err => winston.error(err.stack)); - } - activitypubApi.add(caller, { pid }); - }, 5000); + await Promise.all([ + activitypub.send('uid', caller.uid, Array.from(targets), payload), + activitypub.feps.announce(pid, payload), + activitypubApi.add(caller, { pid }), + ]); }); activitypubApi.create.privateNote = enabledCheck(async (caller, { messageObj }) => { @@ -232,7 +219,10 @@ activitypubApi.update.note = enabledCheck(async (caller, { post }) => { object, }; - await activitypub.send('uid', caller.uid, Array.from(targets), payload); + await Promise.all([ + activitypub.send('uid', caller.uid, Array.from(targets), payload), + activitypub.feps.announce(post.pid, payload), + ]); }); activitypubApi.update.privateNote = enabledCheck(async (caller, { messageObj }) => { @@ -286,7 +276,10 @@ activitypubApi.delete.note = enabledCheck(async (caller, { pid }) => { origin: object.context, }; - await activitypub.send('uid', caller.uid, Array.from(targets), payload); + await Promise.all([ + activitypub.send('uid', caller.uid, Array.from(targets), payload), + activitypub.feps.announce(pid, payload), + ]); }); activitypubApi.like = {}; @@ -301,11 +294,17 @@ activitypubApi.like.note = enabledCheck(async (caller, { pid }) => { return; } - await activitypub.send('uid', caller.uid, [uid], { + const payload = { id: `${nconf.get('url')}/uid/${caller.uid}#activity/like/${encodeURIComponent(pid)}`, type: 'Like', + actor: `${nconf.get('url')}/uid/${caller.uid}`, object: pid, - }); + }; + + await Promise.all([ + activitypub.send('uid', caller.uid, [uid], payload), + activitypub.feps.announce(pid, payload), + ]); }); activitypubApi.announce = {}; @@ -355,16 +354,22 @@ activitypubApi.undo.like = enabledCheck(async (caller, { pid }) => { return; } - await activitypub.send('uid', caller.uid, [uid], { + const payload = { id: `${nconf.get('url')}/uid/${caller.uid}#activity/undo:like/${encodeURIComponent(pid)}/${Date.now()}`, type: 'Undo', + actor: `${nconf.get('url')}/uid/${caller.uid}`, object: { actor: `${nconf.get('url')}/uid/${caller.uid}`, id: `${nconf.get('url')}/uid/${caller.uid}#activity/like/${encodeURIComponent(pid)}`, type: 'Like', object: pid, }, - }); + }; + + await Promise.all([ + activitypub.send('uid', caller.uid, [uid], payload), + activitypub.feps.announce(pid, payload), + ]); }); activitypubApi.flag = enabledCheck(async (caller, flag) => {