mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 16:46:12 +01:00
@@ -264,7 +264,7 @@ Helpers.resolveObjects = async (ids) => {
|
|||||||
if (!post) {
|
if (!post) {
|
||||||
throw new Error('[[error:activitypub.invalid-id]]');
|
throw new Error('[[error:activitypub.invalid-id]]');
|
||||||
}
|
}
|
||||||
return activitypub.mocks.note(post);
|
return activitypub.mocks.notes.public(post);
|
||||||
}
|
}
|
||||||
case 'category': {
|
case 'category': {
|
||||||
if (!await categories.exists(resolvedId)) {
|
if (!await categories.exists(resolvedId)) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const user = require('../user');
|
|||||||
const categories = require('../categories');
|
const categories = require('../categories');
|
||||||
const posts = require('../posts');
|
const posts = require('../posts');
|
||||||
const topics = require('../topics');
|
const topics = require('../topics');
|
||||||
|
const messaging = require('../messaging');
|
||||||
const plugins = require('../plugins');
|
const plugins = require('../plugins');
|
||||||
const slugify = require('../slugify');
|
const slugify = require('../slugify');
|
||||||
const translator = require('../translator');
|
const translator = require('../translator');
|
||||||
@@ -271,7 +272,9 @@ Mocks.actors.category = async (cid) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Mocks.note = async (post) => {
|
Mocks.notes = {};
|
||||||
|
|
||||||
|
Mocks.notes.public = async (post) => {
|
||||||
const id = `${nconf.get('url')}/post/${post.pid}`;
|
const id = `${nconf.get('url')}/post/${post.pid}`;
|
||||||
|
|
||||||
// Return a tombstone for a deleted post
|
// Return a tombstone for a deleted post
|
||||||
@@ -434,7 +437,6 @@ Mocks.note = async (post) => {
|
|||||||
attributedTo: `${nconf.get('url')}/uid/${post.user.uid}`,
|
attributedTo: `${nconf.get('url')}/uid/${post.user.uid}`,
|
||||||
context: `${nconf.get('url')}/topic/${post.topic.tid}`,
|
context: `${nconf.get('url')}/topic/${post.topic.tid}`,
|
||||||
audience: `${nconf.get('url')}/category/${post.category.cid}`,
|
audience: `${nconf.get('url')}/category/${post.category.cid}`,
|
||||||
sensitive: false, // todo
|
|
||||||
summary: null,
|
summary: null,
|
||||||
name,
|
name,
|
||||||
content: post.content,
|
content: post.content,
|
||||||
@@ -447,6 +449,66 @@ Mocks.note = async (post) => {
|
|||||||
return object;
|
return object;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Mocks.notes.private = async ({ messageObj }) => {
|
||||||
|
// todo: deleted messages
|
||||||
|
let uids = await messaging.getUidsInRoom(messageObj.roomId, 0, -1);
|
||||||
|
const remoteUids = uids.filter(uid => !utils.isNumber(uid));
|
||||||
|
uids = uids.map(uid => (utils.isNumber(uid) ? `${nconf.get('url')}/uid/${uid}` : uid));
|
||||||
|
const id = `${nconf.get('url')}/message/${messageObj.mid}`;
|
||||||
|
const to = new Set(uids);
|
||||||
|
const published = messageObj.timestampISO;
|
||||||
|
const updated = messageObj.edited ? messageObj.editedISO : undefined;
|
||||||
|
const content = await messaging.parse(messageObj.content, messageObj.fromuid, 0, messageObj.roomId, false);
|
||||||
|
|
||||||
|
let source;
|
||||||
|
const markdownEnabled = await plugins.isActive('nodebb-plugin-markdown');
|
||||||
|
if (markdownEnabled) {
|
||||||
|
source = {
|
||||||
|
content: messageObj.content,
|
||||||
|
mediaType: 'text/markdown',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mentions = await user.getUsersFields(remoteUids, ['uid', 'userslug']);
|
||||||
|
const tag = [];
|
||||||
|
tag.push(...mentions.map(({ uid, userslug }) => ({
|
||||||
|
type: 'Mention',
|
||||||
|
href: uid,
|
||||||
|
name: userslug,
|
||||||
|
})));
|
||||||
|
|
||||||
|
let inReplyTo;
|
||||||
|
if (messageObj.toMid) {
|
||||||
|
inReplyTo = utils.isNumber(messageObj.toMid) ?
|
||||||
|
`${nconf.get('url')}/api/v3/chats/${messageObj.roomId}/messages/${messageObj.toMid}` :
|
||||||
|
messageObj.toMid;
|
||||||
|
}
|
||||||
|
|
||||||
|
const object = {
|
||||||
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
|
id,
|
||||||
|
type: 'Note',
|
||||||
|
to: Array.from(to),
|
||||||
|
cc: [],
|
||||||
|
inReplyTo,
|
||||||
|
published,
|
||||||
|
updated,
|
||||||
|
url: id,
|
||||||
|
attributedTo: `${nconf.get('url')}/uid/${messageObj.fromuid}`,
|
||||||
|
// context: `${nconf.get('url')}/topic/${post.topic.tid}`,
|
||||||
|
// audience: `${nconf.get('url')}/category/${post.category.cid}`,
|
||||||
|
summary: null,
|
||||||
|
// name,
|
||||||
|
content: content,
|
||||||
|
source,
|
||||||
|
tag,
|
||||||
|
// attachment: [], // todo
|
||||||
|
// replies: `${id}/replies`, // todo
|
||||||
|
};
|
||||||
|
|
||||||
|
return object;
|
||||||
|
};
|
||||||
|
|
||||||
Mocks.tombstone = async properties => ({
|
Mocks.tombstone = async properties => ({
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
type: 'Tombstone',
|
type: 'Tombstone',
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const privileges = require('../privileges');
|
|||||||
const activitypub = require('../activitypub');
|
const activitypub = require('../activitypub');
|
||||||
const posts = require('../posts');
|
const posts = require('../posts');
|
||||||
const topics = require('../topics');
|
const topics = require('../topics');
|
||||||
|
const messaging = require('../messaging');
|
||||||
const utils = require('../utils');
|
const utils = require('../utils');
|
||||||
|
|
||||||
const activitypubApi = module.exports;
|
const activitypubApi = module.exports;
|
||||||
@@ -180,7 +181,7 @@ activitypubApi.create.note = enabledCheck(async (caller, { pid, post }) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const object = await activitypub.mocks.note(post);
|
const object = await activitypub.mocks.notes.public(post);
|
||||||
const { to, cc, targets } = await buildRecipients(object, { pid, uid: post.user.uid });
|
const { to, cc, targets } = await buildRecipients(object, { pid, uid: post.user.uid });
|
||||||
const { cid } = post.category;
|
const { cid } = post.category;
|
||||||
const followers = await activitypub.notes.getCategoryFollowers(cid);
|
const followers = await activitypub.notes.getCategoryFollowers(cid);
|
||||||
@@ -211,6 +212,21 @@ activitypubApi.create.note = enabledCheck(async (caller, { pid, post }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
activitypubApi.create.privateNote = enabledCheck(async (caller, { mid, messageObj }) => {
|
||||||
|
if (!messageObj) {
|
||||||
|
messageObj = await messaging.getMessageFields(mid, []);
|
||||||
|
if (!messageObj) {
|
||||||
|
throw new Error('[[error:invalid-data]]');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const { roomId } = messageObj;
|
||||||
|
let targets = await messaging.getUidsInRoom(roomId, 0, -1);
|
||||||
|
targets = targets.filter(uid => !utils.isNumber(uid)); // remote uids only
|
||||||
|
|
||||||
|
const payload = await activitypub.mocks.notes.private({ messageObj });
|
||||||
|
await activitypub.send('uid', messageObj.fromuid, targets, payload);
|
||||||
|
});
|
||||||
|
|
||||||
activitypubApi.update = {};
|
activitypubApi.update = {};
|
||||||
|
|
||||||
activitypubApi.update.profile = enabledCheck(async (caller, { uid }) => {
|
activitypubApi.update.profile = enabledCheck(async (caller, { uid }) => {
|
||||||
@@ -249,7 +265,7 @@ activitypubApi.update.note = enabledCheck(async (caller, { post }) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const object = await activitypub.mocks.note(post);
|
const object = await activitypub.mocks.notes.public(post);
|
||||||
const { to, cc, targets } = await buildRecipients(object, { pid: post.pid, uid: post.user.uid });
|
const { to, cc, targets } = await buildRecipients(object, { pid: post.pid, uid: post.user.uid });
|
||||||
|
|
||||||
const allowed = await privileges.posts.can('topics:read', post.pid, activitypub._constants.uid);
|
const allowed = await privileges.posts.can('topics:read', post.pid, activitypub._constants.uid);
|
||||||
@@ -281,7 +297,7 @@ activitypubApi.delete.note = enabledCheck(async (caller, { pid }) => {
|
|||||||
|
|
||||||
const id = `${nconf.get('url')}/post/${pid}`;
|
const id = `${nconf.get('url')}/post/${pid}`;
|
||||||
const post = (await posts.getPostSummaryByPids([pid], caller.uid, { stripTags: false })).pop();
|
const post = (await posts.getPostSummaryByPids([pid], caller.uid, { stripTags: false })).pop();
|
||||||
const object = await activitypub.mocks.note(post);
|
const object = await activitypub.mocks.notes.public(post);
|
||||||
const { to, cc, targets } = await buildRecipients(object, { pid, uid: post.user.uid });
|
const { to, cc, targets } = await buildRecipients(object, { pid, uid: post.user.uid });
|
||||||
|
|
||||||
const allowed = await privileges.posts.can('topics:read', pid, activitypub._constants.uid);
|
const allowed = await privileges.posts.can('topics:read', pid, activitypub._constants.uid);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const privileges = require('../../privileges');
|
|||||||
const posts = require('../../posts');
|
const posts = require('../../posts');
|
||||||
const topics = require('../../topics');
|
const topics = require('../../topics');
|
||||||
const categories = require('../../categories');
|
const categories = require('../../categories');
|
||||||
|
const messaging = require('../../messaging');
|
||||||
const activitypub = require('../../activitypub');
|
const activitypub = require('../../activitypub');
|
||||||
const utils = require('../../utils');
|
const utils = require('../../utils');
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ Actors.note = async function (req, res) {
|
|||||||
return res.sendStatus(404);
|
return res.sendStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
const payload = await activitypub.mocks.note(post);
|
const payload = await activitypub.mocks.notes.public(post);
|
||||||
res.status(200).json(payload);
|
res.status(200).json(payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -184,3 +185,14 @@ Actors.category = async function (req, res, next) {
|
|||||||
const payload = await activitypub.mocks.actors.category(req.params.cid);
|
const payload = await activitypub.mocks.actors.category(req.params.cid);
|
||||||
res.status(200).json(payload);
|
res.status(200).json(payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Actors.message = async function (req, res, next) {
|
||||||
|
// Handle requests for remote content
|
||||||
|
if (!utils.isNumber(req.params.mid)) {
|
||||||
|
return res.set('Location', req.params.mid).sendStatus(308);
|
||||||
|
}
|
||||||
|
|
||||||
|
const messageObj = await messaging.getMessageFields(req.params.mid, []);
|
||||||
|
const payload = await activitypub.mocks.notes.private({ messageObj });
|
||||||
|
res.status(200).json(payload);
|
||||||
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const db = require('../database');
|
|||||||
const notifications = require('../notifications');
|
const notifications = require('../notifications');
|
||||||
const user = require('../user');
|
const user = require('../user');
|
||||||
const io = require('../socket.io');
|
const io = require('../socket.io');
|
||||||
|
const api = require('../api');
|
||||||
const plugins = require('../plugins');
|
const plugins = require('../plugins');
|
||||||
const utils = require('../utils');
|
const utils = require('../utils');
|
||||||
|
|
||||||
@@ -79,8 +80,10 @@ module.exports = function (Messaging) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sendNotification(fromUid, roomId, messageObj);
|
await Promise.all([
|
||||||
// await federate(fromUid, roomId, messageObj);
|
sendNotification(fromUid, roomId, messageObj),
|
||||||
|
!isPublic ? api.activitypub.create.privateNote({ uid: fromUid }, { messageObj }) : null,
|
||||||
|
]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
winston.error(`[messaging/notifications] Unabled to send notification\n${err.stack}`);
|
winston.error(`[messaging/notifications] Unabled to send notification\n${err.stack}`);
|
||||||
}
|
}
|
||||||
@@ -142,7 +145,4 @@ module.exports = function (Messaging) {
|
|||||||
await notifications.push(notification, uidsToNotify);
|
await notifications.push(notification, uidsToNotify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// async function federate(fromUid, roomId, messageObj) {
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,4 +45,6 @@ module.exports = function (app, middleware, controllers) {
|
|||||||
app.post('/category/:cid/inbox', [...inboxMiddlewares, middleware.assert.category, ...inboxMiddlewares], controllers.activitypub.postInbox);
|
app.post('/category/:cid/inbox', [...inboxMiddlewares, middleware.assert.category, ...inboxMiddlewares], controllers.activitypub.postInbox);
|
||||||
app.get('/category/:cid/outbox', [...middlewares, middleware.assert.category], controllers.activitypub.getCategoryOutbox);
|
app.get('/category/:cid/outbox', [...middlewares, middleware.assert.category], controllers.activitypub.getCategoryOutbox);
|
||||||
app.post('/category/:cid/outbox', [...middlewares, middleware.assert.category], controllers.activitypub.postOutbox);
|
app.post('/category/:cid/outbox', [...middlewares, middleware.assert.category], controllers.activitypub.postOutbox);
|
||||||
|
|
||||||
|
app.get('/message/:mid', [...middlewares, middleware.assert.message], controllers.activitypub.actors.message);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user