diff --git a/src/activitypub/mocks.js b/src/activitypub/mocks.js
index 2f7b157d2b..290ab13fc8 100644
--- a/src/activitypub/mocks.js
+++ b/src/activitypub/mocks.js
@@ -40,6 +40,95 @@ const sanitizeConfig = {
},
};
+Mocks._normalize = async (object) => {
+ // Normalized incoming AP objects into expected types for easier mocking
+ let { attributedTo, url, image, content, source } = object;
+
+ switch (true) { // non-string attributedTo handling
+ case Array.isArray(attributedTo): {
+ attributedTo = attributedTo.reduce((valid, cur) => {
+ if (typeof cur === 'string') {
+ valid.push(cur);
+ } else if (typeof cur === 'object') {
+ if (cur.type === 'Person' && cur.id) {
+ valid.push(cur.id);
+ }
+ }
+
+ return valid;
+ }, []);
+ attributedTo = attributedTo.shift(); // take first valid uid
+ break;
+ }
+
+ case typeof attributedTo === 'object' && attributedTo.hasOwnProperty('id'): {
+ attributedTo = attributedTo.id;
+ }
+ }
+
+ let sourceContent = source && source.mediaType === 'text/markdown' ? source.content : undefined;
+ if (sourceContent) {
+ content = null;
+ sourceContent = await activitypub.helpers.remoteAnchorToLocalProfile(sourceContent, true);
+ } else if (content && content.length) {
+ content = sanitize(content, sanitizeConfig);
+ content = await activitypub.helpers.remoteAnchorToLocalProfile(content);
+ } else {
+ content = 'This post did not contain any content.';
+ }
+
+ switch (true) {
+ case image && image.hasOwnProperty('url') && !!image.url: {
+ image = image.url;
+ break;
+ }
+
+ case image && typeof image === 'string': {
+ // no change
+ break;
+ }
+
+ default: {
+ image = null;
+ }
+ }
+ if (image) {
+ const parsed = new URL(image);
+ if (!mime.getType(parsed.pathname).startsWith('image/')) {
+ activitypub.helpers.log(`[activitypub/mocks.post] Received image not identified as image due to MIME type: ${image}`);
+ image = null;
+ }
+ }
+
+ if (url) { // Handle url array
+ if (Array.isArray(url)) {
+ url = url.reduce((valid, cur) => {
+ if (typeof cur === 'string') {
+ valid.push(cur);
+ } else if (typeof cur === 'object') {
+ if (cur.type === 'Link' && cur.href) {
+ if (!cur.mediaType || (cur.mediaType && cur.mediaType === 'text/html')) {
+ valid.push(cur.href);
+ }
+ }
+ }
+
+ return valid;
+ }, []);
+ url = url.shift(); // take first valid url
+ }
+ }
+
+ return {
+ ...object,
+ attributedTo,
+ content,
+ sourceContent,
+ image,
+ url,
+ };
+};
+
Mocks.profile = async (actors, hostMap) => {
// Should only ever be called by activitypub.actors.assert
const profiles = await Promise.all(actors.map(async (actor) => {
@@ -154,6 +243,8 @@ Mocks.post = async (objects) => {
}
const posts = await Promise.all(objects.map(async (object) => {
+ object = await Mocks._normalize(object);
+
if (
!activitypub._constants.acceptedPostTypes.includes(object.type) ||
!activitypub.helpers.isUri(object.id) // sanity-check the id
@@ -166,31 +257,10 @@ Mocks.post = async (objects) => {
url,
attributedTo: uid,
inReplyTo: toPid,
- published, updated, name, content, source,
+ published, updated, name, content, sourceContent,
type, to, cc, audience, attachment, tag, image,
} = object;
- switch (true) { // non-string attributedTo handling
- case Array.isArray(uid): {
- uid = uid.reduce((valid, cur) => {
- if (typeof cur === 'string') {
- valid.push(cur);
- } else if (typeof cur === 'object') {
- if (cur.type === 'Person' && cur.id) {
- valid.push(cur.id);
- }
- }
-
- return valid;
- }, []);
- uid = uid.shift(); // take first valid uid
- break;
- }
-
- case typeof uid === 'object' && uid.hasOwnProperty('id'): {
- uid = uid.id;
- }
- }
await activitypub.actors.assert(uid);
const resolved = await activitypub.helpers.resolveLocalId(toPid);
@@ -202,59 +272,6 @@ Mocks.post = async (objects) => {
let edited = new Date(updated);
edited = Number.isNaN(edited.valueOf()) ? undefined : edited;
- let sourceContent = source && source.mediaType === 'text/markdown' ? source.content : undefined;
- if (sourceContent) {
- content = null;
- sourceContent = await activitypub.helpers.remoteAnchorToLocalProfile(sourceContent, true);
- } else if (content && content.length) {
- content = sanitize(content, sanitizeConfig);
- content = await activitypub.helpers.remoteAnchorToLocalProfile(content);
- } else {
- content = 'This post did not contain any content.';
- }
-
- switch (true) {
- case image && image.hasOwnProperty('url') && !!image.url: {
- image = image.url;
- break;
- }
-
- case image && typeof image === 'string': {
- // no change
- break;
- }
-
- default: {
- image = null;
- }
- }
- if (image) {
- const parsed = new URL(image);
- if (!mime.getType(parsed.pathname).startsWith('image/')) {
- activitypub.helpers.log(`[activitypub/mocks.post] Received image not identified as image due to MIME type: ${image}`);
- image = null;
- }
- }
-
- if (url) { // Handle url array
- if (Array.isArray(url)) {
- url = url.reduce((valid, cur) => {
- if (typeof cur === 'string') {
- valid.push(cur);
- } else if (typeof cur === 'object') {
- if (cur.type === 'Link' && cur.href) {
- if (!cur.mediaType || (cur.mediaType && cur.mediaType === 'text/html')) {
- valid.push(cur.href);
- }
- }
- }
-
- return valid;
- }, []);
- url = url.shift(); // take first valid url
- }
- }
-
if (type === 'Video') {
attachment = attachment || [];
attachment.push({ url });
@@ -281,6 +298,19 @@ Mocks.post = async (objects) => {
return single ? posts.pop() : posts;
};
+Mocks.message = async (object) => {
+ object = await Mocks._normalize(object);
+
+ const message = {
+ mid: object.id,
+ uid: object.attributedTo,
+ content: object.content,
+ // ip: caller.ip,
+ };
+
+ return message;
+};
+
Mocks.actors = {};
Mocks.actors.user = async (uid) => {
diff --git a/src/activitypub/notes.js b/src/activitypub/notes.js
index 26dbbc0bd1..920fe69205 100644
--- a/src/activitypub/notes.js
+++ b/src/activitypub/notes.js
@@ -286,31 +286,30 @@ Notes.assertPrivate = async (object) => {
timestamp = Date.now();
}
+ const payload = await activitypub.mocks.message(object);
+
if (!roomId) {
- roomId = await messaging.newRoom(object.attributedTo, { uids: [...recipients] });
+ roomId = await messaging.newRoom(payload.uid, { uids: [...recipients] });
}
// Add any new members to the chat
const added = Array.from(recipients).filter(uid => !participantUids.includes(uid));
const assertion = await activitypub.actors.assert(added);
if (assertion) {
- await messaging.addUsersToRoom(object.attributedTo, added, roomId);
+ await messaging.addUsersToRoom(payload.uid, added, roomId);
}
// Add message to room
const message = await messaging.sendMessage({
- mid: object.id,
- uid: object.attributedTo,
- roomId: roomId,
- content: object.content,
- toMid: toMid,
+ ...payload,
timestamp: Date.now(),
- // ip: caller.ip,
+ roomId: roomId,
+ toMid: toMid,
});
- messaging.notifyUsersInRoom(object.attributedTo, roomId, message);
+ messaging.notifyUsersInRoom(payload.uid, roomId, message);
// Set real timestamp back so that the message shows even though it predates room joining
- await messaging.setMessageField(object.id, 'timestamp', timestamp);
+ await messaging.setMessageField(payload.mid, 'timestamp', timestamp);
return { roomId };
};