From 57a73c4854106913a258fceed8508f1da9e5aa7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Wed, 14 Jan 2026 18:47:52 -0500 Subject: [PATCH] refactor: crossposts.get to support multiple tids --- src/categories/recentreplies.js | 2 +- src/topics/crossposts.js | 46 ++++++++++++++++++++------------- test/topics/crossposts.js | 12 ++++----- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/categories/recentreplies.js b/src/categories/recentreplies.js index e1be6a9a6d..1021181e22 100644 --- a/src/categories/recentreplies.js +++ b/src/categories/recentreplies.js @@ -101,7 +101,7 @@ module.exports = function (Categories) { tids, ['tid', 'mainPid', 'slug', 'title', 'teaserPid', 'cid', 'postcount'] ), - Promise.all(tids.map(async tid => topics.crossposts.get(tid))), + topics.crossposts.get(tids), ]); topicData.forEach((topic) => { diff --git a/src/topics/crossposts.js b/src/topics/crossposts.js index b4ae973ad2..e677e11481 100644 --- a/src/topics/crossposts.js +++ b/src/topics/crossposts.js @@ -1,5 +1,6 @@ 'use strict'; +const _ = require('lodash'); const db = require('../database'); const topics = require('.'); const user = require('../user'); @@ -10,30 +11,39 @@ const utils = require('../utils'); const Crossposts = module.exports; -Crossposts.get = async function (tid) { - const crosspostIds = await db.getSortedSetMembers(`tid:${tid}:crossposts`); - let crossposts = await db.getObjects(crosspostIds.map(id => `crosspost:${id}`)); - const cids = crossposts.reduce((cids, crossposts) => { - cids.add(crossposts.cid); - return cids; - }, new Set()); - let categoriesData = await categories.getCategoriesFields( - Array.from(cids), ['cid', 'name', 'icon', 'bgColor', 'color', 'slug'] +Crossposts.get = async function (tids) { + const isArray = Array.isArray(tids); + if (!isArray) { + tids = [tids]; + } + + const crosspostIds = await db.getSortedSetsMembers(tids.map(tid => `tid:${tid}:crossposts`)); + const allCrosspostIds = crosspostIds.flat(); + const allCrossposts = await db.getObjects(allCrosspostIds.map(id => `crosspost:${id}`)); + + const categoriesData = await categories.getCategoriesFields( + _.uniq(allCrossposts.map(c => c.cid)), ['cid', 'name', 'icon', 'bgColor', 'color', 'slug'] ); - categoriesData = categoriesData.reduce((map, category) => { + + const categoriesMap = categoriesData.reduce((map, category) => { map.set(parseInt(category.cid, 10), category); return map; }, new Map()); - crossposts = crossposts.map((crosspost, idx) => { - crosspost.id = crosspostIds[idx]; - crosspost.category = categoriesData.get(parseInt(crosspost.cid, 10)); - crosspost.uid = utils.isNumber(crosspost.uid) ? parseInt(crosspost.uid) : crosspost.uid; - crosspost.cid = utils.isNumber(crosspost.cid) ? parseInt(crosspost.cid) : crosspost.cid; - return crosspost; - }); + const crosspostMap = allCrossposts.reduce((map, crosspost, index) => { + const id = allCrosspostIds[index]; + if (id && crosspost) { + map.set(id, crosspost); + crosspost.id = id; + crosspost.category = categoriesMap.get(parseInt(crosspost.cid, 10)); + crosspost.uid = utils.isNumber(crosspost.uid) ? parseInt(crosspost.uid, 10) : crosspost.uid; + crosspost.cid = utils.isNumber(crosspost.cid) ? parseInt(crosspost.cid, 10) : crosspost.cid; + } + return map; + }, new Map()); - return crossposts; + const crossposts = crosspostIds.map(ids => ids.map(id => crosspostMap.get(id))); + return isArray ? crossposts : crossposts[0]; }; Crossposts.add = async function (tid, cid, uid) { diff --git a/test/topics/crossposts.js b/test/topics/crossposts.js index ec6fe66aa5..cac82f9d0b 100644 --- a/test/topics/crossposts.js +++ b/test/topics/crossposts.js @@ -159,9 +159,9 @@ describe('Crossposting (& related logic)', () => { it('should not let another user uncrosspost', async () => { const uid2 = await user.create({ username: utils.generateUUID().slice(0, 8) }); - assert.rejects( + await assert.rejects( topics.crossposts.remove(tid, cid2, uid2), - '[[error:invalid-data]]', + { message: '[[error:invalid-data]]' }, ); }); @@ -184,9 +184,9 @@ describe('Crossposting (& related logic)', () => { }); it('should throw on uncrossposting if already uncrossposted', async () => { - assert.rejects( + await assert.rejects( topics.crossposts.remove(tid, cid2, uid), - '[[error:invalid-data]]', + { message: '[[error:invalid-data]]' }, ); }); }); @@ -286,9 +286,9 @@ describe('Crossposting (& related logic)', () => { it('should fail to uncrosspost if not mod of passed-in category', async () => { await privileges.categories.give(['moderate'], cid1, [privUid]); - assert.rejects( + await assert.rejects( topics.crossposts.remove(tid, cid2, privUid), - '[[error:invalid-data]]', + { message: '[[error:invalid-data]]' }, ); });