feat: note attachments via link preview plugin

This commit is contained in:
Julian Lam
2024-04-10 22:01:44 -04:00
parent b8daa02fa8
commit 6fc6cc33cd
4 changed files with 66 additions and 37 deletions

View File

@@ -213,7 +213,6 @@ Mocks.note = async (post) => {
const id = `${nconf.get('url')}/post/${post.pid}`;
const published = new Date(parseInt(post.timestamp, 10)).toISOString();
// todo: post visibility
const to = new Set([activitypub._constants.publicAddress]);
const cc = new Set([`${nconf.get('url')}/uid/${post.user.uid}/followers`]);
@@ -281,6 +280,13 @@ Mocks.note = async (post) => {
}
}
let attachment = await posts.attachments.get(post.pid) || [];
attachment = attachment.map(({ mediaType, url }) => ({
type: 'Document',
mediaType,
url,
}));
const object = {
'@context': 'https://www.w3.org/ns/activitystreams',
id,
@@ -298,7 +304,7 @@ Mocks.note = async (post) => {
content: post.content,
source,
tag,
attachment: [], // todo... requires refactoring of link preview plugin
attachment,
// replies: {} todo...
};

View File

@@ -1,7 +1,6 @@
'use strict';
const winston = require('winston');
const crypto = require('crypto');
const nconf = require('nconf');
const db = require('../database');
@@ -135,7 +134,7 @@ Notes.assert = async (uid, input, options = { skipChecks: false }) => {
_activitypub: mainPost._activitypub,
}),
Notes.updateLocalRecipients(mainPid, { to, cc }),
Notes.saveAttachments(mainPid, attachment),
posts.attachments.update(mainPid, attachment),
]);
unprocessed.pop();
}
@@ -148,7 +147,7 @@ Notes.assert = async (uid, input, options = { skipChecks: false }) => {
await Promise.all([
topics.reply(post),
Notes.updateLocalRecipients(post.pid, { to, cc }),
Notes.saveAttachments(post.pid, attachment),
posts.attachments.update(post.pid, attachment),
]);
// Category announce
@@ -228,38 +227,6 @@ Notes.updateLocalRecipients = async (id, { to, cc }) => {
}
};
Notes.saveAttachments = async (id, attachments) => {
if (!attachments) {
return;
}
const bulkOps = {
hash: [],
zset: {
score: [],
value: [],
},
};
attachments.filter(Boolean).forEach(({ 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}`;
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;

54
src/posts/attachments.js Normal file
View File

@@ -0,0 +1,54 @@
'use strict';
const crypto = require('crypto');
const db = require('../database');
const Attachments = module.exports;
Attachments.get = async (pid) => {
const hashes = await db.getSortedSetMembers(`post:${pid}:attachments`);
const keys = hashes.map(hash => `attachment:${hash}`);
const attachments = (await db.getObjects(keys)).filter(Boolean);
return attachments;
};
Attachments.update = async (pid, attachments) => {
if (!attachments) {
return;
}
const bulkOps = {
hash: [],
zset: {
score: [],
value: [],
},
};
attachments.filter(Boolean).forEach(({ _type, 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}`;
if (_type) {
_type = 'attachment';
}
bulkOps.hash.push([key, { _type, 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:${pid}:attachments`, bulkOps.zset.score, bulkOps.zset.value),
]);
};
// todo
// Attachments.remove = async (pid) => { ... }

View File

@@ -27,6 +27,8 @@ require('./queue')(Posts);
require('./diffs')(Posts);
require('./uploads')(Posts);
Posts.attachments = require('./attachments');
Posts.exists = async function (pids) {
return await db.exists(
Array.isArray(pids) ? pids.map(pid => `post:${pid}`) : `post:${pids}`