diff --git a/src/activitypub/notes.js b/src/activitypub/notes.js index f49cb5113a..2bc4f4f871 100644 --- a/src/activitypub/notes.js +++ b/src/activitypub/notes.js @@ -7,6 +7,7 @@ const topics = require('../topics'); const posts = require('../posts'); const utils = require('../utils'); const pubsub = require('../pubsub'); +const slugify = require('../slugify'); const activitypub = module.parent.exports; const Notes = module.exports; @@ -98,7 +99,7 @@ Notes.assertTopic = async (uid, id) => { const chain = Array.from(await Notes.getParentChain(uid, id)); 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)); + const members = await db.isSortedSetMembers(`tid:${tid}:posts`, chain.map(p => p.pid)); if (tid && members.every(Boolean)) { // All cached, return early. winston.info('[notes/assertTopic] No new notes to process.'); @@ -121,17 +122,21 @@ Notes.assertTopic = async (uid, id) => { unprocessed.map(n => n.timestamp), ]; + // mainPid doesn't belong in posts zset + ids.pop(); + timestamps.pop(); + await Promise.all([ - db.setObject(`topicRemote:${tid}`, { + db.setObject(`topic:${tid}`, { tid, uid: authorId, cid: cid || -1, mainPid, title, - slug: `../world/${tid}`, + slug: `${tid}/${slugify(title)}`, timestamp, }), - db.sortedSetAdd(`tidRemote:${tid}:posts`, timestamps, ids), + db.sortedSetAdd(`tid:${tid}:posts`, timestamps, ids), Notes.assert(uid, unprocessed), ]); await Promise.all([ // must be done after .assert() @@ -145,20 +150,20 @@ Notes.assertTopic = async (uid, id) => { }; Notes.updateTopicCounts = async function (tid) { - const pids = await db.getSortedSetMembers(`tidRemote:${tid}:posts`); + const pids = await db.getSortedSetMembers(`tid:${tid}:posts`); let uids = await db.getObjectsFields(pids.map(p => `post:${p}`), ['uid']); uids = uids.reduce((set, { uid }) => { set.add(uid); return set; }, new Set()); - db.setObject(`topicRemote:${tid}`, { + db.setObject(`topic:${tid}`, { postercount: uids.size, postcount: pids.length, }); }; Notes.getTopicPosts = async (tid, uid, start, stop) => { - const pids = await db.getSortedSetRange(`tidRemote:${tid}:posts`, start, stop); + const pids = await db.getSortedSetRange(`tid:${tid}:posts`, start, stop); return await posts.getPostsByPids(pids, uid); }; diff --git a/src/categories/data.js b/src/categories/data.js index 4568d4850d..49de0a4f4e 100644 --- a/src/categories/data.js +++ b/src/categories/data.js @@ -13,6 +13,19 @@ const intFields = [ 'minTags', 'maxTags', 'postQueue', 'subCategoriesPerPage', ]; +const worldCategory = { + cid: -1, + name: 'World', + description: '[[error:invalid-data]]', + descriptionParsed: 'what', + icon: 'fa-globe', + bgColor: '#0000ff', + color: '#ffffff', + slug: '../world', + parentCid: 0, + disabled: 0, // todo +}; + module.exports = function (Categories) { Categories.getCategoriesFields = async function (cids, fields) { if (!Array.isArray(cids) || !cids.length) { @@ -21,6 +34,12 @@ module.exports = function (Categories) { const keys = cids.map(cid => `category:${cid}`); const categories = await db.getObjects(keys, fields); + + // Handle cid -1 + if (cids.includes(-1)) { + categories.splice(cids.indexOf(-1), 1, worldCategory); + } + const result = await plugins.hooks.fire('filter:category.getFields', { cids: cids, categories: categories, diff --git a/src/controllers/topics.js b/src/controllers/topics.js index 7eeb463d89..5324bb9ca6 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -2,6 +2,7 @@ const nconf = require('nconf'); const qs = require('querystring'); +const validator = require('validator'); const user = require('../user'); const meta = require('../meta'); @@ -9,14 +10,11 @@ const topics = require('../topics'); const categories = require('../categories'); const posts = require('../posts'); const privileges = require('../privileges'); -const activitypub = require('../activitypub'); const helpers = require('./helpers'); const pagination = require('../pagination'); const utils = require('../utils'); const analytics = require('../analytics'); -const activitypubController = require('./activitypub'); - const topicsController = module.exports; const url = nconf.get('url'); @@ -24,14 +22,10 @@ const relative_path = nconf.get('relative_path'); const upload_url = nconf.get('upload_url'); topicsController.get = async function getTopic(req, res, next) { - if (req.params.topic_id === 'remote' && activitypub.helpers.isUri(req.query.resource)) { - return activitypubController.topics.get(req, res, next); - } - const tid = req.params.topic_id; if ( (req.params.post_index && !utils.isNumber(req.params.post_index) && req.params.post_index !== 'unread') || - !utils.isNumber(tid) + (!utils.isNumber(tid) && !validator.isUUID(tid)) ) { return next(); } diff --git a/src/socket.io/topics/infinitescroll.js b/src/socket.io/topics/infinitescroll.js index 3b478154ee..40ccbb4b0c 100644 --- a/src/socket.io/topics/infinitescroll.js +++ b/src/socket.io/topics/infinitescroll.js @@ -23,8 +23,7 @@ module.exports = function (SocketTopics) { throw new Error('[[error:no-privileges]]'); } - 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 set = data.topicPostSort === 'most_votes' ? `tid:${data.tid}:posts:votes` : `tid:${data.tid}:posts`; const reverse = data.topicPostSort === 'newest_to_oldest' || data.topicPostSort === 'most_votes'; let start = Math.max(0, parseInt(data.after, 10)); diff --git a/src/topics/data.js b/src/topics/data.js index 572a86f2be..968c346cbc 100644 --- a/src/topics/data.js +++ b/src/topics/data.js @@ -26,7 +26,7 @@ module.exports = function (Topics) { fields.push('timestamp'); } - const keys = tids.map(tid => `${validator.isUUID(String(tid)) ? 'topicRemote' : 'topic'}:${tid}`); + const keys = tids.map(tid => `topic:${tid}`); const topics = await db.getObjects(keys, fields); const result = await plugins.hooks.fire('filter:topic.getFields', { tids: tids, @@ -63,13 +63,11 @@ module.exports = function (Topics) { }; Topics.setTopicField = async function (tid, field, value) { - const setPrefix = validator.isUUID(String(tid)) ? 'topicRemote' : 'topic'; - await db.setObjectField(`${setPrefix}:${tid}`, field, value); + await db.setObjectField(`topic:${tid}`, field, value); }; Topics.setTopicFields = async function (tid, data) { - const setPrefix = validator.isUUID(String(tid)) ? 'topicRemote' : 'topic'; - await db.setObject(`${setPrefix}:${tid}`, data); + await db.setObject(`topic:${tid}`, data); }; Topics.deleteTopicField = async function (tid, field) { diff --git a/src/topics/posts.js b/src/topics/posts.js index d55982f4f3..2605edce31 100644 --- a/src/topics/posts.js +++ b/src/topics/posts.js @@ -231,10 +231,9 @@ module.exports = function (Topics) { Topics.getLatestUndeletedReply = async function (tid) { let isDeleted = false; let index = 0; - 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); + const pids = await db.getSortedSetRevRange(`tid:${tid}:posts`, index, index); if (!pids.length) { return null; } @@ -312,7 +311,7 @@ module.exports = function (Topics) { }; async function incrementFieldAndUpdateSortedSet(tid, field, by, set) { - const value = await db.incrObjectFieldBy(`${validator.isUUID(String(tid)) ? 'topicRemote' : 'topic'}:${tid}`, field, by); + const value = await db.incrObjectFieldBy(`topic:${tid}`, field, by); await db[Array.isArray(set) ? 'sortedSetsAdd' : 'sortedSetAdd'](set, value, tid); } diff --git a/src/topics/recent.js b/src/topics/recent.js index d360a44f10..bd2236a457 100644 --- a/src/topics/recent.js +++ b/src/topics/recent.js @@ -70,13 +70,19 @@ module.exports = function (Topics) { }; Topics.updateRecent = async function (tid, timestamp) { - let data = { tid: tid, timestamp: timestamp }; + let data = { tid, timestamp }; + + // Topics in /world are excluded from /recent + const cid = await Topics.getTopicField(tid, 'cid'); + if (cid === -1) { + return; + } + if (plugins.hooks.hasListeners('filter:topics.updateRecent')) { - data = await plugins.hooks.fire('filter:topics.updateRecent', { tid: tid, timestamp: timestamp }); + data = await plugins.hooks.fire('filter:topics.updateRecent', data); } if (data && data.tid && data.timestamp) { - const setPrefix = validator.isUUID(String(data.tid)) ? 'topicsRemote' : 'topics'; - await db.sortedSetAdd(`${setPrefix}:recent`, data.timestamp, data.tid); + await db.sortedSetAdd(`topics:recent`, data.timestamp, data.tid); } }; };