diff --git a/install/package.json b/install/package.json index aceb51ca0a..2db4af4748 100644 --- a/install/package.json +++ b/install/package.json @@ -95,7 +95,7 @@ "nconf": "0.12.1", "nodebb-plugin-2factor": "7.5.3", "nodebb-plugin-composer-default": "10.2.36", - "nodebb-plugin-dbsearch": "6.2.3", + "nodebb-plugin-dbsearch": "6.2.4", "nodebb-plugin-emoji": "5.1.15", "nodebb-plugin-emoji-android": "4.0.0", "nodebb-plugin-markdown": "12.2.6", diff --git a/src/topics/suggested.js b/src/topics/suggested.js index 2d6f7db99c..f23f0a7079 100644 --- a/src/topics/suggested.js +++ b/src/topics/suggested.js @@ -6,23 +6,27 @@ const _ = require('lodash'); const db = require('../database'); const user = require('../user'); const privileges = require('../privileges'); -const search = require('../search'); +const plugins = require('../plugins'); module.exports = function (Topics) { Topics.getSuggestedTopics = async function (tid, uid, start, stop, cutoff = 0) { let tids; tid = parseInt(tid, 10); cutoff = cutoff === 0 ? cutoff : (cutoff * 2592000000); + const { cid, title, tags } = await Topics.getTopicFields(tid, [ + 'cid', 'title', 'tags', + ]); + const [tagTids, searchTids] = await Promise.all([ - getTidsWithSameTags(tid, cutoff), - getSearchTids(tid, uid, cutoff), + getTidsWithSameTags(tid, tags.map(t => t.value), cutoff), + getSearchTids(tid, title, cid, cutoff), ]); tids = _.uniq(tagTids.concat(searchTids)); let categoryTids = []; if (stop !== -1 && tids.length < stop - start + 1) { - categoryTids = await getCategoryTids(tid, cutoff); + categoryTids = await getCategoryTids(tid, cid, cutoff); } tids = _.shuffle(_.uniq(tids.concat(categoryTids))); tids = await privileges.topics.filterTids('topics:read', tids, uid); @@ -36,36 +40,37 @@ module.exports = function (Topics) { return topicData; }; - async function getTidsWithSameTags(tid, cutoff) { - const tags = await Topics.getTopicTags(tid); + async function getTidsWithSameTags(tid, tags, cutoff) { let tids = cutoff === 0 ? await db.getSortedSetRevRange(tags.map(tag => `tag:${tag}:topics`), 0, -1) : await db.getSortedSetRevRangeByScore(tags.map(tag => `tag:${tag}:topics`), 0, -1, '+inf', Date.now() - cutoff); tids = tids.filter(_tid => _tid !== tid); // remove self - return _.shuffle(_.uniq(tids)).slice(0, 10).map(Number); + return _.shuffle(_.uniq(tids)).slice(0, 10); } - async function getSearchTids(tid, uid, cutoff) { - const topicData = await Topics.getTopicFields(tid, ['title', 'cid']); - const data = await search.search({ - query: topicData.title, - searchIn: 'titles', + async function getSearchTids(tid, title, cid, cutoff) { + let { ids: tids } = await plugins.hooks.fire('filter:search.query', { + index: 'topic', + content: title, matchWords: 'any', - categories: [topicData.cid], - uid: uid, - returnIds: true, - timeRange: cutoff !== 0 ? cutoff / 1000 : 0, - timeFilter: 'newer', + cid: [cid], + limit: 20, + ids: [], }); - data.tids = data.tids.filter(_tid => _tid !== tid); // remove self - return _.shuffle(data.tids).slice(0, 10).map(Number); + tids = tids.filter(_tid => _tid !== tid); // remove self + if (cutoff) { + const topicData = await Topics.getTopicsFields(tids, ['tid', 'timestamp']); + const now = Date.now(); + tids = topicData.filter(t => t && t.timestamp > now - cutoff).map(t => t.tid); + } + + return _.shuffle(tids).slice(0, 10).map(String); } - async function getCategoryTids(tid, cutoff) { - const cid = await Topics.getTopicField(tid, 'cid'); + async function getCategoryTids(tid, cid, cutoff) { const tids = cutoff === 0 ? await db.getSortedSetRevRange(`cid:${cid}:tids:lastposttime`, 0, 9) : await db.getSortedSetRevRangeByScore(`cid:${cid}:tids:lastposttime`, 0, 10, '+inf', Date.now() - cutoff); - return _.shuffle(tids.map(Number).filter(_tid => _tid !== tid)); + return _.shuffle(tids.filter(_tid => _tid !== tid)); } };