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
This commit is contained in:
Julian Lam
2025-02-07 08:21:41 -05:00
parent 608317ba28
commit 9fd6ac6bb8
4 changed files with 71 additions and 57 deletions

36
src/activitypub/feps.js Normal file
View File

@@ -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,
});
};

View File

@@ -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;
}

View File

@@ -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.');

View File

@@ -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) => {