diff --git a/public/src/client/topic/events.js b/public/src/client/topic/events.js index 62ec136331..73e1a91efc 100644 --- a/public/src/client/topic/events.js +++ b/public/src/client/topic/events.js @@ -101,15 +101,15 @@ define('forum/topic/events', [ } function onPostEdited(data) { - if (!data || !data.post || parseInt(data.post.tid, 10) !== parseInt(ajaxify.data.tid, 10)) { + if (!data || !data.post || String(data.post.tid) !== String(ajaxify.data.tid)) { return; } const editedPostEl = components.get('post/content', data.post.pid).filter(function (index, el) { - return parseInt($(el).closest('[data-pid]').attr('data-pid'), 10) === parseInt(data.post.pid, 10); + return String($(el).closest('[data-pid]').attr('data-pid')) === String(data.post.pid); }); const postContainer = $(`[data-pid="${data.post.pid}"]`); const editorEl = postContainer.find('[component="post/editor"]').filter(function (index, el) { - return parseInt($(el).closest('[data-pid]').attr('data-pid'), 10) === parseInt(data.post.pid, 10); + return String($(el).closest('[data-pid]').attr('data-pid')) === String(data.post.pid); }); const topicTitle = components.get('topic/title'); const navbarTitle = components.get('navbar/title').find('span'); diff --git a/src/activitypub/mocks.js b/src/activitypub/mocks.js index 088a4fd6c6..13b6d4d3b7 100644 --- a/src/activitypub/mocks.js +++ b/src/activitypub/mocks.js @@ -90,6 +90,7 @@ Mocks.post = async (objects) => { inReplyTo: toPid, to, cc, + attachment, } = object; const timestamp = new Date(published).getTime(); @@ -108,7 +109,7 @@ Mocks.post = async (objects) => { edited, editor: edited ? uid : undefined, - _activitypub: { to, cc }, + _activitypub: { to, cc, attachment }, }; return payload; diff --git a/src/activitypub/notes.js b/src/activitypub/notes.js index f88ac19397..d9e037a248 100644 --- a/src/activitypub/notes.js +++ b/src/activitypub/notes.js @@ -1,6 +1,7 @@ 'use strict'; const winston = require('winston'); +const crypto = require('crypto'); const db = require('../database'); const user = require('../user'); @@ -41,8 +42,9 @@ Notes.assert = async (uid, input, options = {}) => { } // Parse ActivityPub-specific data - const { to, cc } = postData._activitypub; + const { to, cc, attachment } = postData._activitypub; await Notes.updateLocalRecipients(id, { to, cc }); + await Notes.saveAttachments(id, attachment); const hash = { ...postData }; delete hash._activitypub; @@ -83,6 +85,35 @@ Notes.updateLocalRecipients = async (id, { to, cc }) => { } }; +Notes.saveAttachments = async (id, attachments) => { + const bulkOps = { + hash: [], + zset: { + score: [], + value: [], + }, + }; + + attachments.filter(Boolean).map(({ mediaType, url, name, width, height }, idx) => { + if (!url) { // only required property + return; + } + + const hash = crypto.createHash('sha256').update(url).digest('hex'); + const key = `attachment:${hash}`; + console.log('attachment key is', key); + + bulkOps.hash.push([key, { mediaType, url, name, width, height }]); + bulkOps.zset.score.push(idx); + bulkOps.zset.value.push(hash); + }); + + await Promise.all([ + db.setObjectBulk(bulkOps.hash), + db.sortedSetAdd(`post:${id}:attachments`, bulkOps.zset.score, bulkOps.zset.value), + ]); +}; + Notes.getParentChain = async (uid, input) => { // Traverse upwards via `inReplyTo` until you find the root-level Note const id = activitypub.helpers.isUri(input) ? input : input.id; diff --git a/src/cache/lru.js b/src/cache/lru.js index fc6eb69147..e4fb790c93 100644 --- a/src/cache/lru.js +++ b/src/cache/lru.js @@ -57,6 +57,14 @@ module.exports = function (opts) { }); }); + cache.has = function (key) { + if (!cache.enabled) { + return false; + } + + return lruCache.has(key); + }; + cache.set = function (key, value, ttl) { if (!cache.enabled) { return; diff --git a/src/posts/parse.js b/src/posts/parse.js index 803df00e3e..ff8ccae4d2 100644 --- a/src/posts/parse.js +++ b/src/posts/parse.js @@ -61,15 +61,12 @@ module.exports = function (Posts) { return postData; } - if (!activitypub.helpers.isUri(postData.pid) || postData.hasOwnProperty('sourceContent')) { - ({ postData } = await plugins.hooks.fire('filter:parse.post', { postData })); - } else { - postData.content = await Posts.sanitize(postData.content); - } + ({ postData } = await plugins.hooks.fire('filter:parse.post', { postData })); postData.content = translator.escape(postData.content); if (postData.pid) { cache.set(pid, postData.content); } + return postData; };