diff --git a/src/api/activitypub.js b/src/api/activitypub.js index 7e4ae7da18..19e9087539 100644 --- a/src/api/activitypub.js +++ b/src/api/activitypub.js @@ -350,7 +350,7 @@ activitypubApi.announce = {}; activitypubApi.announce.note = enabledCheck(async (caller, { tid }) => { const { mainPid: pid, cid } = await topics.getTopicFields(tid, ['mainPid', 'cid']); - // Only remote posts can be announced to real categories + // Only remote posts can be announced to local categories if (utils.isNumber(pid) || parseInt(cid, 10) === -1) { return; } @@ -379,6 +379,63 @@ activitypubApi.announce.note = enabledCheck(async (caller, { tid }) => { }); }); +activitypubApi.announce.delete = enabledCheck(async ({ uid }, { tid }) => { + const now = new Date(); + const { mainPid: pid, cid } = await topics.getTopicFields(tid, ['mainPid', 'cid']); + + // Only local categories + if (!utils.isNumber(cid) || parseInt(cid, 10) < 1) { + return; + } + + const allowed = await privileges.categories.can('topics:read', cid, activitypub._constants.uid); + if (!allowed) { + activitypub.helpers.log(`[activitypub/api] Not federating announce of pid ${pid} to the fediverse due to privileges.`); + return; + } + + const { to, cc, targets } = await activitypub.buildRecipients({ + to: [activitypub._constants.publicAddress], + cc: [`${nconf.get('url')}/category/${cid}/followers`], + }, { cid }); + + const deleteTpl = { + id: `${nconf.get('url')}/topic/${tid}#activity/delete/${now.getTime()}`, + type: 'Delete', + actor: `${nconf.get('url')}/category/${cid}`, + to, + cc, + origin: `${nconf.get('url')}/category/${cid}`, + }; + + // 7888 variant + await activitypub.send('cid', cid, Array.from(targets), { + id: `${nconf.get('url')}/topic/${tid}#activity/announce/delete/${now.getTime()}`, + type: 'Announce', + actor: `${nconf.get('url')}/category/${cid}`, + to, + cc, + object: { + ...deleteTpl, + object: `${nconf.get('url')}/topic/${tid}`, + }, + }); + + // 1b12 variant + await activitypub.send('cid', cid, Array.from(targets), { + id: `${nconf.get('url')}/post/${encodeURIComponent(pid)}#activity/announce/delete/${now.getTime()}`, + type: 'Announce', + actor: `${nconf.get('url')}/category/${cid}`, + to, + cc, + object: { + ...deleteTpl, + actor: `${nconf.get('url')}/uid/${uid}`, + object: utils.isNumber(pid) ? `${nconf.get('url')}/post/${pid}` : pid, + }, + }); +}); + activitypubApi.undo = {}; // activitypubApi.undo.follow = diff --git a/src/posts/delete.js b/src/posts/delete.js index 5668ac3750..dddb33e6a9 100644 --- a/src/posts/delete.js +++ b/src/posts/delete.js @@ -34,6 +34,7 @@ module.exports = function (Posts) { await Promise.all([ topics.updateLastPostTimeFromLastPid(postData.tid), topics.updateTeaser(postData.tid), + isDeleting ? activitypub.notes.delete(pid) : null, isDeleting ? db.sortedSetRemove(`cid:${topicData.cid}:pids`, pid) : db.sortedSetAdd(`cid:${topicData.cid}:pids`, postData.timestamp, pid), diff --git a/src/topics/delete.js b/src/topics/delete.js index e97fd0a98e..d07a3aee5b 100644 --- a/src/topics/delete.js +++ b/src/topics/delete.js @@ -8,6 +8,7 @@ const categories = require('../categories'); const flags = require('../flags'); const plugins = require('../plugins'); const batch = require('../batch'); +const api = require('../api'); const utils = require('../utils'); module.exports = function (Topics) { @@ -80,6 +81,7 @@ module.exports = function (Topics) { } deletedTopic.tags = tags; await deleteFromFollowersIgnorers(tid); + await api.activitypub.announce.delete({ uid }, { tid }), await Promise.all([ db.deleteAll([ diff --git a/src/topics/tools.js b/src/topics/tools.js index 294615b38a..65505bde67 100644 --- a/src/topics/tools.js +++ b/src/topics/tools.js @@ -7,6 +7,7 @@ const topics = require('.'); const categories = require('../categories'); const user = require('../user'); const plugins = require('../plugins'); +const api = require('../api'); const privileges = require('../privileges'); const utils = require('../utils'); @@ -277,6 +278,13 @@ module.exports = function (Topics) { const oldCid = topicData.cid; await categories.moveRecentReplies(tid, oldCid, cid); + // AP: Announce(Delete(Object)) + if (cid === -1) { + await api.activitypub.announce.delete({ uid: data.uid }, { tid }); + } else { + // tbd: api.activitypub.announce.move + } + await Promise.all([ Topics.setTopicFields(tid, { cid: cid,