Files
NodeBB/src/categories/recentreplies.js

252 lines
6.7 KiB
JavaScript
Raw Normal View History

2014-03-12 21:41:53 -04:00
'use strict';
2016-04-29 20:35:49 +03:00
var async = require('async');
2017-05-26 01:39:40 -06:00
var _ = require('lodash');
2014-04-24 18:59:19 -04:00
2016-04-29 20:35:49 +03:00
var db = require('../database');
var posts = require('../posts');
var topics = require('../topics');
2016-08-27 01:52:08 +03:00
var privileges = require('../privileges');
var batch = require('../batch');
2014-03-12 21:41:53 -04:00
module.exports = function (Categories) {
Categories.getRecentReplies = function (cid, uid, count, callback) {
2014-11-19 11:02:28 -05:00
if (!parseInt(count, 10)) {
2014-11-14 16:22:05 -05:00
return callback(null, []);
}
2016-08-27 01:52:08 +03:00
async.waterfall([
function (next) {
db.getSortedSetRevRange('cid:' + cid + ':pids', 0, count - 1, next);
},
function (pids, next) {
privileges.posts.filter('topics:read', pids, uid, next);
},
function (pids, next) {
2017-02-18 12:30:49 -07:00
posts.getPostSummaryByPids(pids, uid, { stripTags: true }, next);
2017-02-17 19:31:21 -07:00
},
], callback);
2014-03-12 21:41:53 -04:00
};
Categories.updateRecentTid = function (cid, tid, callback) {
2017-05-24 15:07:03 -04:00
async.waterfall([
function (next) {
async.parallel({
count: function (next) {
db.sortedSetCard('cid:' + cid + ':recent_tids', next);
},
numRecentReplies: function (next) {
db.getObjectField('category:' + cid, 'numRecentReplies', next);
},
}, next);
},
2017-05-24 15:07:03 -04:00
function (results, next) {
if (results.count < results.numRecentReplies) {
return db.sortedSetAdd('cid:' + cid + ':recent_tids', Date.now(), tid, callback);
}
db.getSortedSetRangeWithScores('cid:' + cid + ':recent_tids', 0, results.count - results.numRecentReplies, next);
2017-02-17 19:31:21 -07:00
},
2017-05-24 15:07:03 -04:00
function (data, next) {
if (!data.length) {
return next();
}
db.sortedSetsRemoveRangeByScore(['cid:' + cid + ':recent_tids'], '-inf', data[data.length - 1].score, next);
},
function (next) {
db.sortedSetAdd('cid:' + cid + ':recent_tids', Date.now(), tid, next);
},
], callback);
};
2017-07-15 16:24:46 -04:00
Categories.updateRecentTidForCid = function (cid, callback) {
async.waterfall([
function (next) {
db.getSortedSetRevRange('cid:' + cid + ':pids', 0, 0, next);
},
function (pid, next) {
pid = pid[0];
posts.getPostField(pid, 'tid', next);
},
function (tid, next) {
2018-10-22 21:58:34 -04:00
if (!tid) {
2017-07-15 16:24:46 -04:00
return next();
}
Categories.updateRecentTid(cid, tid, next);
},
], callback);
};
Categories.getRecentTopicReplies = function (categoryData, uid, callback) {
2014-09-16 16:10:02 -04:00
if (!Array.isArray(categoryData) || !categoryData.length) {
2016-01-10 10:59:04 +02:00
return callback();
2014-09-16 16:10:02 -04:00
}
2016-08-27 01:52:08 +03:00
async.waterfall([
function (next) {
2018-11-29 16:47:13 +01:00
const categoriesToLoad = categoryData.filter(category => category && category.numRecentReplies && parseInt(category.numRecentReplies, 10) > 0);
2018-11-21 16:42:57 -05:00
const keys = categoriesToLoad.map(category => 'cid:' + category.cid + ':recent_tids');
db.getSortedSetsMembers(keys, next);
},
function (results, next) {
2017-10-30 15:26:12 -04:00
var tids = _.uniq(_.flatten(results).filter(Boolean));
2014-08-14 09:59:40 -04:00
privileges.topics.filterTids('topics:read', tids, uid, next);
},
function (tids, next) {
getTopics(tids, uid, next);
},
function (topics, next) {
assignTopicsToCategories(categoryData, topics);
2015-08-19 15:53:37 -04:00
bubbleUpChildrenPosts(categoryData);
next();
2017-02-17 19:31:21 -07:00
},
], callback);
2014-08-14 09:59:40 -04:00
};
function getTopics(tids, uid, callback) {
var topicData;
2015-07-10 16:43:25 -04:00
async.waterfall([
function (next) {
topics.getTopicsFields(tids, ['tid', 'mainPid', 'slug', 'title', 'teaserPid', 'cid', 'postcount'], next);
2015-07-10 16:43:25 -04:00
},
function (_topicData, next) {
2016-04-28 14:18:19 -04:00
topicData = _topicData;
topicData.forEach(function (topic) {
2016-05-23 11:39:35 +03:00
if (topic) {
topic.teaserPid = topic.teaserPid || topic.mainPid;
}
});
var cids = _.uniq(topicData.map(topic => topic && topic.cid).filter(cid => parseInt(cid, 10)));
async.parallel({
2016-08-27 01:52:08 +03:00
categoryData: async.apply(Categories.getCategoriesFields, cids, ['cid', 'parentCid']),
teasers: async.apply(topics.getTeasers, _topicData, uid),
}, next);
2016-04-28 14:18:19 -04:00
},
function (results, next) {
var parentCids = {};
results.categoryData.forEach(function (category) {
parentCids[category.cid] = category.parentCid;
});
results.teasers.forEach(function (teaser, index) {
if (teaser) {
teaser.cid = topicData[index].cid;
2017-02-18 14:29:52 -07:00
teaser.parentCid = parseInt(parentCids[teaser.cid], 10) || 0;
teaser.tid = undefined;
teaser.uid = undefined;
teaser.user.uid = undefined;
teaser.topic = {
slug: topicData[index].slug,
title: topicData[index].title,
};
}
2015-07-10 16:43:25 -04:00
});
results.teasers = results.teasers.filter(Boolean);
next(null, results.teasers);
2017-02-17 19:31:21 -07:00
},
2015-07-10 16:43:25 -04:00
], callback);
}
function assignTopicsToCategories(categories, topics) {
categories.forEach(function (category) {
2018-11-29 16:47:13 +01:00
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));
}
});
}
2015-08-19 15:53:37 -04:00
function bubbleUpChildrenPosts(categoryData) {
categoryData.forEach(function (category) {
2018-11-29 16:47:13 +01:00
if (category) {
if (category.posts.length) {
return;
}
var posts = [];
getPostsRecursive(category, posts);
2015-08-19 15:53:37 -04:00
2018-11-29 16:47:13 +01:00
posts.sort((a, b) => b.pid - a.pid);
if (posts.length) {
category.posts = [posts[0]];
}
2015-08-19 15:53:37 -04:00
}
});
}
2015-08-20 14:23:20 -04:00
function getPostsRecursive(category, posts) {
if (Array.isArray(category.posts)) {
category.posts.forEach(function (p) {
posts.push(p);
});
}
2015-08-20 14:23:20 -04:00
category.children.forEach(function (child) {
2015-08-20 14:23:20 -04:00
getPostsRecursive(child, posts);
});
}
Categories.moveRecentReplies = function (tid, oldCid, cid, callback) {
callback = callback || function () {};
2017-07-15 16:24:46 -04:00
2017-05-24 15:07:03 -04:00
async.waterfall([
2017-07-15 16:24:46 -04:00
function (next) {
updatePostCount(tid, oldCid, cid, next);
},
2017-05-24 15:07:03 -04:00
function (next) {
topics.getPids(tid, next);
},
function (pids, next) {
batch.processArray(pids, function (pids, next) {
async.waterfall([
function (next) {
posts.getPostsFields(pids, ['timestamp'], next);
},
function (postData, next) {
var timestamps = postData.map(function (post) {
return post && post.timestamp;
});
async.parallel([
function (next) {
db.sortedSetRemove('cid:' + oldCid + ':pids', pids, next);
},
function (next) {
db.sortedSetAdd('cid:' + cid + ':pids', timestamps, pids, next);
},
], next);
},
], next);
}, next);
},
], callback);
};
2014-04-24 18:59:19 -04:00
2017-05-24 15:07:03 -04:00
function updatePostCount(tid, oldCid, newCid, callback) {
async.waterfall([
function (next) {
topics.getTopicField(tid, 'postcount', next);
},
function (postCount, next) {
2018-10-25 17:02:59 -04:00
if (!postCount) {
2017-05-24 15:07:03 -04:00
return callback();
}
async.parallel([
function (next) {
2017-05-24 15:07:03 -04:00
db.incrObjectFieldBy('category:' + oldCid, 'post_count', -postCount, next);
},
2017-05-24 15:07:03 -04:00
function (next) {
db.incrObjectFieldBy('category:' + newCid, 'post_count', postCount, next);
2017-02-17 19:31:21 -07:00
},
2017-07-15 16:24:46 -04:00
], function (err) {
next(err);
});
2017-05-24 15:07:03 -04:00
},
], callback);
2014-06-17 13:11:09 -04:00
}
2014-03-12 21:41:53 -04:00
};