diff --git a/src/categories/topics.js b/src/categories/topics.js index 918cc4c244..64e9046614 100644 --- a/src/categories/topics.js +++ b/src/categories/topics.js @@ -99,7 +99,8 @@ module.exports = function (Categories) { most_views: `cid:${cid}:tids:views`, }; - const set = new Set([sortToSet.hasOwnProperty(sort) ? sortToSet[sort] : `cid:${cid}:tids`]); + const mainSet = sortToSet.hasOwnProperty(sort) ? sortToSet[sort] : `cid:${cid}:tids`; + const set = new Set([mainSet]); if (data.tag) { if (Array.isArray(data.tag)) { @@ -116,6 +117,7 @@ module.exports = function (Categories) { } if (parseInt(cid, 10) === -1 && uid > 0) { + set.delete(mainSet); set.add(`uid:${uid}:inbox`); } const setValue = Array.from(set); @@ -251,4 +253,24 @@ module.exports = function (Categories) { }); notifications.push(notification, followers); }; + + Categories.sortTidsBySet = async (tids, cid, sort) => { + sort = sort || meta.config.categoryTopicSort || 'recently_replied'; + const sortToSet = { + recently_replied: `cid:${cid}:tids`, + recently_created: `cid:${cid}:tids:create`, + most_posts: `cid:${cid}:tids:posts`, + most_votes: `cid:${cid}:tids:votes`, + most_views: `cid:${cid}:tids:views`, + }; + + const orderBy = sortToSet[sort]; + const scores = await db.sortedSetScores(orderBy, tids); + const sorted = tids + .map((tid, idx) => [tid, scores[idx]]) + .sort(([, a], [, b]) => b - a) + .map(([tid]) => tid); + + return sorted; + }; }; diff --git a/src/controllers/activitypub/topics.js b/src/controllers/activitypub/topics.js index 7a871a6876..68bcbc66a5 100644 --- a/src/controllers/activitypub/topics.js +++ b/src/controllers/activitypub/topics.js @@ -20,22 +20,6 @@ const validSorts = [ 'recently_replied', 'recently_created', 'most_posts', 'most_votes', 'most_views', ]; -async function getTids(data) { - // Poor man's intersect used instead of getSortedSetIntersect because the zsets are huge - const sets = await categories.buildTopicsSortedSet(data); - const intersect = Array.isArray(sets); - const mainSet = intersect ? sets.shift() : sets; - let tids = await db.getSortedSetRevRange(mainSet, 0, 499); - if (!intersect) { - return tids.slice(data.start, data.stop + 1); - } - - let intersection = await Promise.all(sets.map(async set => db.isSortedSetMembers(set, tids))); - intersection = intersection.reduce((memo, cur) => memo.map((show, idx) => show && cur[idx])); - tids = tids.filter((_, idx) => intersection[idx]); - return tids.slice(data.start, data.stop + 1); -} - controller.list = async function (req, res) { if (!req.uid) { return helpers.redirect(res, '/recent?cid=-1', false); @@ -69,7 +53,8 @@ controller.list = async function (req, res) { data.name = '[[world:name]]'; delete data.children; - const tids = await getTids(cidQuery); + let tids = await categories.getTopicIds(cidQuery); + tids = await categories.sortTidsBySet(tids, -1, sort); // sorting not handled if cid is -1 data.topicCount = tids.length; data.topics = await topics.getTopicsByTids(tids, { uid: req.uid }); topics.calculateTopicIndices(data.topics, start);