diff --git a/src/activitypub/actors.js b/src/activitypub/actors.js index 5aa64ee1e8..991f8223f8 100644 --- a/src/activitypub/actors.js +++ b/src/activitypub/actors.js @@ -163,3 +163,34 @@ Actors.assert = async (ids, options = {}) => { return actors; }; + +Actors.getLocalFollowers = async (id) => { + const response = { + uids: new Set(), + cids: new Set(), + }; + + if (!activitypub.helpers.isUri(id)) { + return response; + } + + const members = await db.getSortedSetMembers(`followersRemote:${id}`); + + members.forEach((id) => { + if (utils.isNumber(id)) { + response.uids.add(parseInt(id, 10)); + } else if (id.startsWith('cid|') && utils.isNumber(id.slice(4))) { + response.cids.add(parseInt(id.slice(4), 10)); + } + }); + + return response; +}; + +Actors.getLocalFollowersCount = async (id) => { + if (!activitypub.helpers.isUri(id)) { + return false; + } + + return await db.sortedSetCard(`followersRemote:${id}`); +}; diff --git a/src/activitypub/inbox.js b/src/activitypub/inbox.js index 0da51bd37e..53e2ab2762 100644 --- a/src/activitypub/inbox.js +++ b/src/activitypub/inbox.js @@ -122,8 +122,8 @@ inbox.announce = async (req) => { socketHelpers.sendNotificationToPostOwner(pid, actor, 'announce', 'notifications:activitypub.announce'); } else { // Remote object - const isFollowed = await db.sortedSetCard(`followersRemote:${actor}`); - if (!isFollowed) { + const numFollowers = await activitypub.actors.getLocalFollowersCount(actor); + if (!numFollowers) { winston.info(`[activitypub/inbox.announce] Rejecting ${object.id} via ${actor} due to no followers`); reject('Announce', object, actor); return; @@ -135,7 +135,13 @@ inbox.announce = async (req) => { return; } - ({ tid } = await activitypub.notes.assert(0, pid, { skipChecks: true })); // checks skipped; done above. + const { cids } = await activitypub.actors.getLocalFollowers(actor); + let cid = null; + if (cids.size > 0) { + cid = Array.from(cids)[0]; + } + + ({ tid } = await activitypub.notes.assert(0, pid, { cid, skipChecks: true })); // checks skipped; done above. if (!tid) { return; } diff --git a/src/activitypub/notes.js b/src/activitypub/notes.js index 8e1d6232ef..9a2196e39a 100644 --- a/src/activitypub/notes.js +++ b/src/activitypub/notes.js @@ -65,7 +65,7 @@ Notes.assert = async (uid, input, options = { skipChecks: false }) => { ({ cid, mainPid } = await topics.getTopicFields(tid, ['tid', 'cid', 'mainPid'])); } else { // mainPid ok to leave as-is - cid = -1; + cid = options.cid || -1; title = name || utils.decodeHTMLEntities(utils.stripHTMLTags(content)); if (title.length > meta.config.maximumTitleLength) { title = `${title.slice(0, meta.config.maximumTitleLength - 3)}...`; @@ -179,7 +179,7 @@ async function assertRelation(post) { */ // Is followed by at least one local user - const isFollowed = await db.sortedSetCard(`followersRemote:${post.uid}`); + const numFollowers = await activitypub.actors.getLocalFollowersCount(post.uid); // Local user is mentioned const { tag } = post._activitypub; @@ -199,7 +199,7 @@ async function assertRelation(post) { uids = uids.filter(Boolean); } - return isFollowed || uids.length; + return numFollowers > 0 || uids.length; } Notes.updateLocalRecipients = async (id, { to, cc }) => { @@ -214,11 +214,12 @@ Notes.updateLocalRecipients = async (id, { to, cc }) => { const followedUid = await db.getObjectField('followersUrl:uid', recipient); if (followedUid) { - const followers = await db.getSortedSetMembers(`followersRemote:${followedUid}`); - if (followers.length) { - uids.add(...followers.map(uid => parseInt(uid, 10))); + const { uids: followers } = await activitypub.actors.getLocalFollowers(followedUid); + if (followers.size > 0) { + followers.forEach((uid) => { + uids.add(uid); + }); } - // return; } }));