refactor: generate a topic id when asserting a new topic

This commit is contained in:
Julian Lam
2024-01-19 11:31:04 -05:00
parent 981b4f146d
commit 2ff70fdde2
9 changed files with 39 additions and 34 deletions

View File

@@ -73,14 +73,17 @@ Notes.getParentChain = async (uid, input) => {
return chain;
};
Notes.assertParentChain = async (chain) => {
Notes.assertParentChain = async (chain, tid) => {
const data = [];
chain.reduce((child, parent) => {
data.push([`pid:${parent.pid}:replies`, child.timestamp, child.pid]);
return parent;
});
await db.sortedSetAddBulk(data);
await Promise.all([
db.sortedSetAddBulk(data),
db.setObjectBulk(chain.map(post => [`post:${post.pid}`, { tid }])),
]);
};
Notes.assertTopic = async (uid, id) => {
@@ -92,22 +95,22 @@ Notes.assertTopic = async (uid, id) => {
*/
const chain = Array.from(await Notes.getParentChain(uid, id));
const { pid: tid, uid: authorId, timestamp, name, content } = chain[chain.length - 1];
let { pid: mainPid, tid, uid: authorId, timestamp, name, content } = chain[chain.length - 1];
const members = await db.isSortedSetMembers(`tidRemote:${tid}:posts`, chain.map(p => p.pid));
if (members.every(Boolean)) {
if (tid && members.every(Boolean)) {
// All cached, return early.
winston.info('[notes/assertTopic] No new notes to process.');
return tid;
}
let title = name || utils.stripHTMLTags(content);
if (title.length > 256) {
title = `${title.slice(0, 256)}...`;
}
tid = tid || utils.generateUUID();
const cid = await topics.getTopicField(tid, 'cid');
let title = name || utils.decodeHTMLEntities(utils.stripHTMLTags(content));
if (title.length > 64) {
title = `${title.slice(0, 64)}...`;
}
const unprocessed = chain.filter((p, idx) => !members[idx]);
winston.info(`[notes/assertTopic] ${unprocessed.length} new note(s) found.`);
@@ -121,16 +124,16 @@ Notes.assertTopic = async (uid, id) => {
tid,
uid: authorId,
cid: cid || -1,
mainPid: tid,
mainPid,
title,
slug: `remote?resource=${encodeURIComponent(tid)}`,
slug: `../world/${tid}`,
timestamp,
}),
db.sortedSetAdd(`tidRemote:${tid}:posts`, timestamps, ids),
Notes.assert(uid, unprocessed),
]);
await Promise.all([ // must be done after .assert()
Notes.assertParentChain(chain),
Notes.assertParentChain(chain, tid),
Notes.updateTopicCounts(tid),
topics.updateLastPostTimeFromLastPid(tid),
topics.updateTeaser(tid),

View File

@@ -44,14 +44,13 @@ controller.get = async function (req, res, next) {
* Ideally we would use the existing topicsController.get...
* this controller may be a stopgap towards that end goal.
*/
const pid = await notes.resolveId(req.uid, req.query.resource);
if (pid !== req.query.resource) {
return helpers.redirect(res, `/topic/remote?resource=${pid}`, true);
}
// const pid = await notes.resolveId(req.uid, req.query.resource);
// if (pid !== req.query.resource) {
// return helpers.redirect(res, `/topic/remote?resource=${pid}`, true);
// }
const tid = await notes.assertTopic(req.uid, req.query.resource);
let postIndex = Math.max(1, await db.sortedSetRank(`tidRemote:${tid}:posts`, req.query.resource));
const tid = req.params.topic_id;
let postIndex = parseInt(req.params.post_index, 10) || 1;
const [
userPrivileges,
settings,

View File

@@ -61,6 +61,7 @@ function modifyPost(post, fields) {
if (activitypub.helpers.isUri(post.pid)) {
intFields.splice(intFields.indexOf('pid'), 1);
intFields.splice(intFields.indexOf('uid'), 1);
intFields.splice(intFields.indexOf('tid'), 1);
}
db.parseIntFields(post, intFields, fields);
if (post.hasOwnProperty('upvotes') && post.hasOwnProperty('downvotes')) {

View File

@@ -3,7 +3,8 @@
const helpers = require('./helpers');
module.exports = function (app, middleware, controllers) {
helpers.setupPageRoute(app, '/world/:view?', [middleware.activitypub.enabled], controllers.activitypub.topics.list);
helpers.setupPageRoute(app, '/world', [middleware.activitypub.enabled], controllers.activitypub.topics.list);
helpers.setupPageRoute(app, '/world/:topic_id/:post_index?', [middleware.activitypub.enabled], controllers.activitypub.topics.get);
/**
* These controllers only respond if the sender is making an json+activitypub style call (i.e. S2S-only)

View File

@@ -1,11 +1,12 @@
'use strict';
const validator = require('validator');
const topics = require('../../topics');
const privileges = require('../../privileges');
const meta = require('../../meta');
const utils = require('../../utils');
const social = require('../../social');
const activitypub = require('../../activitypub');
module.exports = function (SocketTopics) {
SocketTopics.loadMore = async function (socket, data) {
@@ -22,7 +23,7 @@ module.exports = function (SocketTopics) {
throw new Error('[[error:no-privileges]]');
}
const setPrefix = activitypub.helpers.isUri(data.tid) ? 'tidRemote' : 'tid';
const setPrefix = validator.isUUID(String(data.tid)) ? 'tidRemote' : 'tid';
const set = data.topicPostSort === 'most_votes' ? `${setPrefix}:${data.tid}:posts:votes` : `${setPrefix}:${data.tid}:posts`;
const reverse = data.topicPostSort === 'newest_to_oldest' || data.topicPostSort === 'most_votes';
let start = Math.max(0, parseInt(data.after, 10));

View File

@@ -7,7 +7,6 @@ const categories = require('../categories');
const utils = require('../utils');
const translator = require('../translator');
const plugins = require('../plugins');
const activitypub = require('../activitypub');
const intFields = [
'tid', 'cid', 'uid', 'mainPid', 'postcount',
@@ -27,7 +26,7 @@ module.exports = function (Topics) {
fields.push('timestamp');
}
const keys = tids.map(tid => `${activitypub.helpers.isUri(tid) ? 'topicRemote' : 'topic'}:${tid}`);
const keys = tids.map(tid => `${validator.isUUID(String(tid)) ? 'topicRemote' : 'topic'}:${tid}`);
const topics = await db.getObjects(keys, fields);
const result = await plugins.hooks.fire('filter:topic.getFields', {
tids: tids,
@@ -64,12 +63,12 @@ module.exports = function (Topics) {
};
Topics.setTopicField = async function (tid, field, value) {
const setPrefix = activitypub.helpers.isUri(tid) ? 'topicRemote' : 'topic';
const setPrefix = validator.isUUID(String(tid)) ? 'topicRemote' : 'topic';
await db.setObjectField(`${setPrefix}:${tid}`, field, value);
};
Topics.setTopicFields = async function (tid, data) {
const setPrefix = activitypub.helpers.isUri(tid) ? 'topicRemote' : 'topic';
const setPrefix = validator.isUUID(String(tid)) ? 'topicRemote' : 'topic';
await db.setObject(`${setPrefix}:${tid}`, data);
};
@@ -98,7 +97,7 @@ function modifyTopic(topic, fields) {
return;
}
if (activitypub.helpers.isUri(topic.tid)) {
if (validator.isUUID(String(topic.tid))) {
intFields.splice(intFields.indexOf('uid'), 1);
intFields.splice(intFields.indexOf('tid'), 1);
}

View File

@@ -72,10 +72,10 @@ Topics.getTopicsByTids = async function (tids, options) {
const topics = await Topics.getTopicsData(tids);
const uids = _.uniq(topics
.map(t => t && t.uid && t.uid.toString())
.filter(v => utils.isNumber(v) || activitypub.helpers.isUri(v)));
.filter(v => utils.isNumber(v) || validator.isUUID(String(v))));
const cids = _.uniq(topics
.map(t => t && t.cid && t.cid.toString())
.filter(v => utils.isNumber(v) || activitypub.helpers.isUri(v)));
.filter(v => utils.isNumber(v) || validator.isUUID(String(v))));
const guestTopics = topics.filter(t => t && t.uid === 0);
async function loadGuestHandles() {

View File

@@ -231,7 +231,7 @@ module.exports = function (Topics) {
Topics.getLatestUndeletedReply = async function (tid) {
let isDeleted = false;
let index = 0;
const setPrefix = activitypub.helpers.isUri(tid) ? 'tidRemote' : 'tid';
const setPrefix = validator.isUUID(String(tid)) ? 'tidRemote' : 'tid';
do {
/* eslint-disable no-await-in-loop */
const pids = await db.getSortedSetRevRange(`${setPrefix}:${tid}:posts`, index, index);
@@ -312,7 +312,7 @@ module.exports = function (Topics) {
};
async function incrementFieldAndUpdateSortedSet(tid, field, by, set) {
const value = await db.incrObjectFieldBy(`${activitypub.helpers.isUri(tid) ? 'topicRemote' : 'topic'}:${tid}`, field, by);
const value = await db.incrObjectFieldBy(`${validator.isUUID(String(tid)) ? 'topicRemote' : 'topic'}:${tid}`, field, by);
await db[Array.isArray(set) ? 'sortedSetsAdd' : 'sortedSetAdd'](set, value, tid);
}

View File

@@ -1,10 +1,11 @@
'use strict';
const validator = require('validator');
const db = require('../database');
const plugins = require('../plugins');
const posts = require('../posts');
const activitypub = require('../activitypub');
module.exports = function (Topics) {
const terms = {
@@ -74,7 +75,7 @@ module.exports = function (Topics) {
data = await plugins.hooks.fire('filter:topics.updateRecent', { tid: tid, timestamp: timestamp });
}
if (data && data.tid && data.timestamp) {
const setPrefix = activitypub.helpers.isUri(data.tid) ? 'topicsRemote' : 'topics';
const setPrefix = validator.isUUID(String(data.tid)) ? 'topicsRemote' : 'topics';
await db.sortedSetAdd(`${setPrefix}:recent`, data.timestamp, data.tid);
}
};