You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nodebb/src/categories/recentreplies.js

192 lines
6.3 KiB
JavaScript

'use strict';
var _ = require('lodash');
11 years ago
9 years ago
var db = require('../database');
var posts = require('../posts');
var topics = require('../topics');
var privileges = require('../privileges');
var batch = require('../batch');
module.exports = function (Categories) {
Categories.getRecentReplies = async function (cid, uid, count) {
if (!parseInt(count, 10)) {
return [];
}
let pids = await db.getSortedSetRevRange('cid:' + cid + ':pids', 0, count - 1);
pids = await privileges.posts.filter('topics:read', pids, uid);
return await posts.getPostSummaryByPids(pids, uid, { stripTags: true });
};
Categories.updateRecentTid = async function (cid, tid) {
const [count, numRecentReplies] = await Promise.all([
db.sortedSetCard('cid:' + cid + ':recent_tids'),
db.getObjectField('category:' + cid, 'numRecentReplies'),
]);
if (count < numRecentReplies) {
return await db.sortedSetAdd('cid:' + cid + ':recent_tids', Date.now(), tid);
}
const data = await db.getSortedSetRangeWithScores('cid:' + cid + ':recent_tids', 0, count - numRecentReplies);
const shouldRemove = !(data.length === 1 && count === 1 && data[0].value === String(tid));
if (data.length && shouldRemove) {
await db.sortedSetsRemoveRangeByScore(['cid:' + cid + ':recent_tids'], '-inf', data[data.length - 1].score);
}
await db.sortedSetAdd('cid:' + cid + ':recent_tids', Date.now(), tid);
};
8 years ago
Categories.updateRecentTidForCid = async function (cid) {
let postData;
let topicData;
let index = 0;
do {
/* eslint-disable no-await-in-loop */
const pids = await db.getSortedSetRevRange('cid:' + cid + ':pids', index, index);
if (!pids.length) {
return;
}
postData = await posts.getPostFields(pids[0], ['tid', 'deleted']);
if (postData && postData.tid && !postData.deleted) {
topicData = await topics.getTopicData(postData.tid);
}
index += 1;
} while (!topicData || topicData.deleted);
if (postData && postData.tid) {
await Categories.updateRecentTid(cid, postData.tid);
}
8 years ago
};
Categories.getRecentTopicReplies = async function (categoryData, uid) {
11 years ago
if (!Array.isArray(categoryData) || !categoryData.length) {
return;
11 years ago
}
const categoriesToLoad = categoryData.filter(category => category && category.numRecentReplies && parseInt(category.numRecentReplies, 10) > 0);
const keys = categoriesToLoad.map(category => 'cid:' + category.cid + ':recent_tids');
const results = await db.getSortedSetsMembers(keys);
let tids = _.uniq(_.flatten(results).filter(Boolean));
tids = await privileges.topics.filterTids('topics:read', tids, uid);
const topics = await getTopics(tids, uid);
assignTopicsToCategories(categoryData, topics);
11 years ago
bubbleUpChildrenPosts(categoryData);
11 years ago
};
async function getTopics(tids, uid) {
const topicData = await topics.getTopicsFields(tids, ['tid', 'mainPid', 'slug', 'title', 'teaserPid', 'cid', 'postcount']);
topicData.forEach(function (topic) {
if (topic) {
topic.teaserPid = topic.teaserPid || topic.mainPid;
}
});
var cids = _.uniq(topicData.map(topic => topic && topic.cid).filter(cid => parseInt(cid, 10)));
const [categoryData, teasers] = await Promise.all([
Categories.getCategoriesFields(cids, ['cid', 'parentCid']),
topics.getTeasers(topicData, uid),
]);
var parentCids = {};
categoryData.forEach(function (category) {
parentCids[category.cid] = category.parentCid;
});
teasers.forEach(function (teaser, index) {
if (teaser) {
teaser.cid = topicData[index].cid;
teaser.parentCid = parseInt(parentCids[teaser.cid], 10) || 0;
teaser.tid = undefined;
teaser.uid = undefined;
teaser.topic = {
slug: topicData[index].slug,
title: topicData[index].title,
};
}
});
return teasers.filter(Boolean);
10 years ago
}
function assignTopicsToCategories(categories, topics) {
categories.forEach(function (category) {
if (category) {
category.posts = topics.filter(topic => topic.cid && (topic.cid === category.cid || topic.parentCid === category.cid))
.sort((a, b) => b.pid - a.pid)
.slice(0, parseInt(category.numRecentReplies, 10));
}
});
}
10 years ago
function bubbleUpChildrenPosts(categoryData) {
categoryData.forEach(function (category) {
if (category) {
if (category.posts.length) {
return;
}
var posts = [];
getPostsRecursive(category, posts);
10 years ago
posts.sort((a, b) => b.pid - a.pid);
if (posts.length) {
category.posts = [posts[0]];
}
10 years ago
}
});
}
10 years ago
function getPostsRecursive(category, posts) {
if (Array.isArray(category.posts)) {
category.posts.forEach(function (p) {
posts.push(p);
});
}
10 years ago
category.children.forEach(function (child) {
10 years ago
getPostsRecursive(child, posts);
});
}
// terrible name, should be topics.moveTopicPosts
Categories.moveRecentReplies = async function (tid, oldCid, cid) {
await updatePostCount(tid, oldCid, cid);
const [pids, topicDeleted] = await Promise.all([
topics.getPids(tid),
topics.getTopicField(tid, 'deleted'),
]);
await batch.processArray(pids, async function (pids) {
const postData = await posts.getPostsFields(pids, ['pid', 'deleted', 'uid', 'timestamp', 'upvotes', 'downvotes']);
const bulkRemove = [];
const bulkAdd = [];
fix(style): updated code to follow new eslint recommendations Squashed commit of the following: commit f9ce878b269b3568f0d649309aae1af4dcfdfeef Author: Julian Lam <[email protected]> Date: Tue Aug 13 14:30:46 2019 -0400 fix(style): updated code to follow new eslint recommendations commit 80dd370e413f22badb96ff2138e7991dfff6d836 Author: Julian Lam <[email protected]> Date: Tue Aug 13 14:14:58 2019 -0400 fix(deps): update dependency sitemap to v4 Squashed commit of the following: commit f4dd9cabb21e26fdc21f8413be822ea7c64251f8 Author: Julian Lam <[email protected]> Date: Tue Aug 13 11:33:05 2019 -0400 fix: resolved breaking changes from sitemap v4 upgrade commit 9043415ee16dcc27a8dcc2e4479d1bc5e2d1b60e Merge: e3352b272 72590b346 Author: Julian Lam <[email protected]> Date: Tue Aug 13 11:09:55 2019 -0400 Merge branch 'master' into renovate/sitemap-4.x commit e3352b272eb9400bdb00774973181397803765e4 Author: Renovate Bot <[email protected]> Date: Mon Aug 12 07:59:05 2019 +0000 fix(deps): update dependency sitemap to v4 commit 8e3c0cdcae22acc32d352be8bb72d60e7502dbc5 Author: Renovate Bot <[email protected]> Date: Fri Aug 9 00:49:51 2019 +0000 fix(deps): update dependency commander to v3 commit 2104449d38818f2fa4d44b3a58a0a168781acbfb Author: Renovate Bot <[email protected]> Date: Tue Aug 13 15:00:27 2019 +0000 fix(deps): update dependency mongodb to v3.3.0 commit d2937f446a21131c070ae5d0ff33d67cfe465b8c Author: Barış Soner Uşaklı <[email protected]> Date: Tue Aug 13 10:36:48 2019 -0400 feat: async/await admin/controllers commit 1b97e8b199f960dc24e5722702f27499ae049914 Author: Misty (Bot) <[email protected]> Date: Tue Aug 13 09:28:39 2019 +0000 Latest translations and fallbacks commit 69a48957a2f0d23c4d194b664bda3a0431179c01 Author: Barış Soner Uşaklı <[email protected]> Date: Mon Aug 12 21:56:09 2019 -0400 feat: async/await commit b9b2a7e593a452de4bef6d0ab6abe368a3bdb8dd Author: Barış Soner Uşaklı <[email protected]> Date: Mon Aug 12 20:58:29 2019 -0400 feat: async/await refactor controllers/accounts commit a8d43a175974a0c8ae3dc132bf51a7ed9a4c6305 Author: Baris Usakli <[email protected]> Date: Mon Aug 12 14:49:40 2019 -0400 feat: async/await controllers/accounts commit 2f25aae57bf9dbe98d655276770e56bed9ec023b Author: Barış Soner Uşaklı <[email protected]> Date: Sun Aug 11 23:09:50 2019 -0400 fix: #7831, fix pagination convert to async/await commit c9e83f2374572264855a04156278eef256b0a20c Author: Barış Soner Uşaklı <[email protected]> Date: Sun Aug 11 00:14:35 2019 -0400 fix: remove empty line commit 30be91b26c4dd7583412c4e8d56e9c1688e48a44 Author: Barış Soner Uşaklı <[email protected]> Date: Sun Aug 11 00:13:41 2019 -0400 fix: remove useless catchs and empty line commit 2e4a71c0b6104738f15ffbfe3246105b922fdfb3 Author: Renovate Bot <[email protected]> Date: Sat Aug 10 06:51:50 2019 +0000 chore(deps): update dependency eslint-config-airbnb-base to v14
6 years ago
postData.forEach(post => {
bulkRemove.push(['cid:' + oldCid + ':uid:' + post.uid + ':pids', post.pid]);
bulkRemove.push(['cid:' + oldCid + ':uid:' + post.uid + ':pids:votes', post.pid]);
bulkAdd.push(['cid:' + cid + ':uid:' + post.uid + ':pids', post.timestamp, post.pid]);
if (post.votes > 0) {
bulkAdd.push(['cid:' + cid + ':uid:' + post.uid + ':pids:votes', post.votes, post.pid]);
}
});
10 years ago
const postsToReAdd = postData.filter(p => !p.deleted && !topicDeleted);
const timestamps = postsToReAdd.map(p => p && p.timestamp);
await Promise.all([
db.sortedSetRemove('cid:' + oldCid + ':pids', pids),
db.sortedSetAdd('cid:' + cid + ':pids', timestamps, postsToReAdd.map(p => p.pid)),
db.sortedSetRemoveBulk(bulkRemove),
db.sortedSetAddBulk(bulkAdd),
]);
}, { batch: 500 });
8 years ago
};
11 years ago
async function updatePostCount(tid, oldCid, newCid) {
const postCount = await topics.getTopicField(tid, 'postcount');
if (!postCount) {
return;
}
await Promise.all([
db.incrObjectFieldBy('category:' + oldCid, 'post_count', -postCount),
db.incrObjectFieldBy('category:' + newCid, 'post_count', postCount),
]);
11 years ago
}
};