mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-02 12:05:57 +01:00
Topic await errors (#7727)
* feat: derp await * feat: restore user.getSettings * feat: cleanup * feat: make tid const * feat: cleanup * fix: tests * feat: deprecate filter:controllers.topic.get * feat: rewrite post-index logic * feat: change calculation to match others * fix: use .async * feat: remove try/catch wrapper
This commit is contained in:
committed by
GitHub
parent
5e46cf9b09
commit
bd640a1107
@@ -8,7 +8,7 @@ var winston = require('winston');
|
||||
var user = require('../user');
|
||||
var meta = require('../meta');
|
||||
var topics = require('../topics');
|
||||
var posts = require('../posts').async;
|
||||
var posts = require('../posts');
|
||||
var privileges = require('../privileges');
|
||||
var plugins = require('../plugins');
|
||||
var helpers = require('./helpers');
|
||||
@@ -18,191 +18,140 @@ var analytics = require('../analytics');
|
||||
|
||||
var topicsController = module.exports;
|
||||
|
||||
topicsController.get = function getTopic(req, res, callback) {
|
||||
var tid = req.params.topic_id;
|
||||
var currentPage = parseInt(req.query.page, 10) || 1;
|
||||
var pageCount = 1;
|
||||
var postCount = 0;
|
||||
var topicData;
|
||||
var userPrivileges;
|
||||
var settings;
|
||||
var rssToken;
|
||||
topicsController.get = async function getTopic(req, res, callback) {
|
||||
const tid = req.params.topic_id;
|
||||
|
||||
if ((req.params.post_index && !utils.isNumber(req.params.post_index) && req.params.post_index !== 'unread') || !utils.isNumber(tid)) {
|
||||
return callback();
|
||||
}
|
||||
let postIndex = parseInt(req.params.post_index, 10) || 1;
|
||||
const [
|
||||
userPrivileges,
|
||||
settings,
|
||||
topicData,
|
||||
rssToken,
|
||||
] = await Promise.all([
|
||||
privileges.async.topics.get(tid, req.uid),
|
||||
user.async.getSettings(req.uid),
|
||||
topics.async.getTopicData(tid),
|
||||
user.async.auth.getFeedToken(req.uid),
|
||||
]);
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
async.parallel({
|
||||
privileges: function (next) {
|
||||
privileges.topics.get(tid, req.uid, next);
|
||||
},
|
||||
settings: function (next) {
|
||||
user.getSettings(req.uid, next);
|
||||
},
|
||||
topic: function (next) {
|
||||
topics.getTopicData(tid, next);
|
||||
},
|
||||
rssToken: function (next) {
|
||||
user.auth.getFeedToken(req.uid, next);
|
||||
},
|
||||
}, next);
|
||||
},
|
||||
function (results, next) {
|
||||
topicData = results.topic;
|
||||
if (!topicData) {
|
||||
return callback();
|
||||
}
|
||||
var currentPage = parseInt(req.query.page, 10) || 1;
|
||||
const pageCount = Math.max(1, Math.ceil((topicData && topicData.postcount) / settings.postsPerPage));
|
||||
if (!topicData || userPrivileges.disabled || (settings.usePagination && (currentPage < 1 || currentPage > pageCount))) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
userPrivileges = results.privileges;
|
||||
rssToken = results.rssToken;
|
||||
if (!userPrivileges['topics:read'] || (topicData.deleted && !userPrivileges.view_deleted)) {
|
||||
return helpers.notAllowed(req, res);
|
||||
}
|
||||
|
||||
if (!userPrivileges['topics:read'] || (results.topic.deleted && !userPrivileges.view_deleted)) {
|
||||
return helpers.notAllowed(req, res);
|
||||
}
|
||||
if (!res.locals.isAPI && (!req.params.slug || topicData.slug !== tid + '/' + req.params.slug) && (topicData.slug && topicData.slug !== tid + '/')) {
|
||||
return helpers.redirect(res, '/topic/' + topicData.slug + (postIndex ? '/' + postIndex : '') + (currentPage > 1 ? '?page=' + currentPage : ''));
|
||||
}
|
||||
|
||||
if (!res.locals.isAPI && (!req.params.slug || results.topic.slug !== tid + '/' + req.params.slug) && (results.topic.slug && results.topic.slug !== tid + '/')) {
|
||||
var url = '/topic/' + results.topic.slug;
|
||||
if (req.params.post_index) {
|
||||
url += '/' + req.params.post_index;
|
||||
}
|
||||
if (currentPage > 1) {
|
||||
url += '?page=' + currentPage;
|
||||
}
|
||||
return helpers.redirect(res, url);
|
||||
}
|
||||
if (postIndex === 'unread') {
|
||||
postIndex = await topics.async.getUserBookmark(tid, req.uid);
|
||||
}
|
||||
|
||||
settings = results.settings;
|
||||
postCount = results.topic.postcount;
|
||||
pageCount = Math.max(1, Math.ceil(postCount / settings.postsPerPage));
|
||||
if (utils.isNumber(postIndex) && (postIndex < 1 || postIndex > topicData.postcount)) {
|
||||
return helpers.redirect(res, '/topic/' + req.params.topic_id + '/' + req.params.slug + (postIndex > topicData.postcount ? '/' + topicData.postcount : ''));
|
||||
}
|
||||
postIndex = Math.max(1, postIndex);
|
||||
const sort = req.query.sort || settings.topicPostSort;
|
||||
const set = sort === 'most_votes' ? 'tid:' + tid + ':posts:votes' : 'tid:' + tid + ':posts';
|
||||
const reverse = sort === 'newest_to_oldest' || sort === 'most_votes';
|
||||
if (settings.usePagination && !req.query.page) {
|
||||
currentPage = calculatePageFromIndex(postIndex, settings);
|
||||
}
|
||||
const { start, stop } = calculateStartStop(currentPage, postIndex, settings);
|
||||
|
||||
if (utils.isNumber(req.params.post_index) && (req.params.post_index < 1 || req.params.post_index > postCount)) {
|
||||
return helpers.redirect(res, '/topic/' + req.params.topic_id + '/' + req.params.slug + (req.params.post_index > postCount ? '/' + postCount : ''));
|
||||
}
|
||||
await topics.async.getTopicWithPosts(topicData, set, req.uid, start, stop, reverse);
|
||||
|
||||
if (settings.usePagination && (currentPage < 1 || currentPage > pageCount)) {
|
||||
return callback();
|
||||
}
|
||||
topics.modifyPostsByPrivilege(topicData, userPrivileges);
|
||||
|
||||
if (req.params.post_index === 'unread') {
|
||||
topics.getUserBookmark(tid, req.uid, next);
|
||||
} else {
|
||||
next(null, req.params.post_index);
|
||||
}
|
||||
},
|
||||
function (post_index, next) {
|
||||
req.params.post_index = post_index;
|
||||
const hookData = await plugins.async.fireHook('filter:controllers.topic.get', { topicData: topicData, uid: req.uid });
|
||||
await Promise.all([
|
||||
buildBreadcrumbs(hookData.topicData),
|
||||
addTags(topicData, req, res),
|
||||
]);
|
||||
|
||||
var set = 'tid:' + tid + ':posts';
|
||||
var reverse = false;
|
||||
// `sort` qs has priority over user setting
|
||||
var sort = req.query.sort || settings.topicPostSort;
|
||||
if (sort === 'newest_to_oldest') {
|
||||
reverse = true;
|
||||
} else if (sort === 'most_votes') {
|
||||
reverse = true;
|
||||
set = 'tid:' + tid + ':posts:votes';
|
||||
}
|
||||
topicData.privileges = userPrivileges;
|
||||
topicData.topicStaleDays = meta.config.topicStaleDays;
|
||||
topicData['reputation:disabled'] = meta.config['reputation:disabled'];
|
||||
topicData['downvote:disabled'] = meta.config['downvote:disabled'];
|
||||
topicData['feeds:disableRSS'] = meta.config['feeds:disableRSS'];
|
||||
topicData.bookmarkThreshold = meta.config.bookmarkThreshold;
|
||||
topicData.postEditDuration = meta.config.postEditDuration;
|
||||
topicData.postDeleteDuration = meta.config.postDeleteDuration;
|
||||
topicData.scrollToMyPost = settings.scrollToMyPost;
|
||||
topicData.allowMultipleBadges = meta.config.allowMultipleBadges === 1;
|
||||
topicData.rssFeedUrl = nconf.get('relative_path') + '/topic/' + topicData.tid + '.rss';
|
||||
if (req.loggedIn) {
|
||||
topicData.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken;
|
||||
}
|
||||
|
||||
var postIndex = 0;
|
||||
topicData.postIndex = postIndex;
|
||||
topicData.pagination = pagination.create(currentPage, pageCount, req.query);
|
||||
topicData.pagination.rel.forEach(function (rel) {
|
||||
rel.href = nconf.get('url') + '/topic/' + topicData.slug + rel.href;
|
||||
res.locals.linkTags.push(rel);
|
||||
});
|
||||
|
||||
req.params.post_index = parseInt(req.params.post_index, 10) || 0;
|
||||
if (reverse && req.params.post_index === 1) {
|
||||
req.params.post_index = 0;
|
||||
}
|
||||
if (!settings.usePagination) {
|
||||
if (req.params.post_index !== 0) {
|
||||
currentPage = 1;
|
||||
}
|
||||
if (reverse) {
|
||||
postIndex = Math.max(0, postCount - (req.params.post_index || postCount) - Math.ceil(settings.postsPerPage / 2));
|
||||
} else {
|
||||
postIndex = Math.max(0, (req.params.post_index || 1) - Math.ceil(settings.postsPerPage / 2));
|
||||
}
|
||||
} else if (!req.query.page) {
|
||||
var index;
|
||||
if (reverse) {
|
||||
index = Math.max(0, postCount - (req.params.post_index || postCount) + 2);
|
||||
} else {
|
||||
index = Math.max(0, req.params.post_index) || 0;
|
||||
}
|
||||
incrementViewCount(req, tid);
|
||||
|
||||
currentPage = Math.max(1, Math.ceil(index / settings.postsPerPage));
|
||||
}
|
||||
markAsRead(req, tid);
|
||||
|
||||
var start = ((currentPage - 1) * settings.postsPerPage) + postIndex;
|
||||
var stop = start + settings.postsPerPage - 1;
|
||||
analytics.increment(['pageviews:byCid:' + topicData.category.cid]);
|
||||
|
||||
topics.getTopicWithPosts(topicData, set, req.uid, start, stop, reverse, next);
|
||||
},
|
||||
function (topicData, next) {
|
||||
if (topicData.category.disabled) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
topics.modifyPostsByPrivilege(topicData, userPrivileges);
|
||||
|
||||
plugins.fireHook('filter:controllers.topic.get', { topicData: topicData, uid: req.uid }, next);
|
||||
},
|
||||
function (data, next) {
|
||||
buildBreadcrumbs(data.topicData, next);
|
||||
},
|
||||
async function (topicData) {
|
||||
await addTags(topicData, req, res);
|
||||
return topicData;
|
||||
},
|
||||
function (topicData) {
|
||||
topicData.privileges = userPrivileges;
|
||||
topicData.topicStaleDays = meta.config.topicStaleDays;
|
||||
topicData['reputation:disabled'] = meta.config['reputation:disabled'];
|
||||
topicData['downvote:disabled'] = meta.config['downvote:disabled'];
|
||||
topicData['feeds:disableRSS'] = meta.config['feeds:disableRSS'];
|
||||
topicData.bookmarkThreshold = meta.config.bookmarkThreshold;
|
||||
topicData.postEditDuration = meta.config.postEditDuration;
|
||||
topicData.postDeleteDuration = meta.config.postDeleteDuration;
|
||||
topicData.scrollToMyPost = settings.scrollToMyPost;
|
||||
topicData.allowMultipleBadges = meta.config.allowMultipleBadges === 1;
|
||||
topicData.rssFeedUrl = nconf.get('relative_path') + '/topic/' + topicData.tid + '.rss';
|
||||
if (req.loggedIn) {
|
||||
topicData.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken;
|
||||
}
|
||||
|
||||
topicData.postIndex = req.params.post_index;
|
||||
topicData.pagination = pagination.create(currentPage, pageCount, req.query);
|
||||
topicData.pagination.rel.forEach(function (rel) {
|
||||
rel.href = nconf.get('url') + '/topic/' + topicData.slug + rel.href;
|
||||
res.locals.linkTags.push(rel);
|
||||
});
|
||||
|
||||
if (req.uid >= 0) {
|
||||
req.session.tids_viewed = req.session.tids_viewed || {};
|
||||
if (!req.session.tids_viewed[tid] || req.session.tids_viewed[tid] < Date.now() - 3600000) {
|
||||
topics.increaseViewCount(tid);
|
||||
req.session.tids_viewed[tid] = Date.now();
|
||||
}
|
||||
}
|
||||
|
||||
if (req.loggedIn) {
|
||||
topics.markAsRead([tid], req.uid, function (err, markedRead) {
|
||||
if (err) {
|
||||
return winston.error(err);
|
||||
}
|
||||
if (markedRead) {
|
||||
topics.pushUnreadCount(req.uid);
|
||||
topics.markTopicNotificationsRead([tid], req.uid);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
analytics.increment(['pageviews:byCid:' + topicData.category.cid]);
|
||||
|
||||
res.render('topic', topicData);
|
||||
},
|
||||
], callback);
|
||||
res.render('topic', topicData);
|
||||
};
|
||||
|
||||
function buildBreadcrumbs(topicData, callback) {
|
||||
function calculatePageFromIndex(postIndex, settings) {
|
||||
return 1 + Math.floor((postIndex - 1) / settings.postsPerPage);
|
||||
}
|
||||
|
||||
function calculateStartStop(page, postIndex, settings) {
|
||||
var startSkip = 0;
|
||||
|
||||
if (!settings.usePagination) {
|
||||
if (postIndex !== 0) {
|
||||
page = 1;
|
||||
}
|
||||
startSkip = Math.max(0, postIndex - Math.ceil(settings.postsPerPage / 2));
|
||||
}
|
||||
|
||||
const start = ((page - 1) * settings.postsPerPage) + startSkip;
|
||||
const stop = start + settings.postsPerPage - 1;
|
||||
return { start: Math.max(0, start), stop: Math.max(0, stop) };
|
||||
}
|
||||
|
||||
function incrementViewCount(req, tid) {
|
||||
if (req.uid >= 0) {
|
||||
req.session.tids_viewed = req.session.tids_viewed || {};
|
||||
if (!req.session.tids_viewed[tid] || req.session.tids_viewed[tid] < Date.now() - 3600000) {
|
||||
topics.increaseViewCount(tid);
|
||||
req.session.tids_viewed[tid] = Date.now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function markAsRead(req, tid) {
|
||||
if (req.loggedIn) {
|
||||
topics.markAsRead([tid], req.uid, function (err, markedRead) {
|
||||
if (err) {
|
||||
return winston.error(err);
|
||||
}
|
||||
if (markedRead) {
|
||||
topics.pushUnreadCount(req.uid);
|
||||
topics.markTopicNotificationsRead([tid], req.uid);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function buildBreadcrumbs(topicData) {
|
||||
var breadcrumbs = [
|
||||
{
|
||||
text: topicData.category.name,
|
||||
@@ -212,22 +161,12 @@ function buildBreadcrumbs(topicData, callback) {
|
||||
text: topicData.title,
|
||||
},
|
||||
];
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
helpers.buildCategoryBreadcrumbs(topicData.category.parentCid, next);
|
||||
},
|
||||
function (crumbs, next) {
|
||||
topicData.breadcrumbs = crumbs.concat(breadcrumbs);
|
||||
next(null, topicData);
|
||||
},
|
||||
], callback);
|
||||
const parentCrumbs = await helpers.async.buildCategoryBreadcrumbs(topicData.category.parentCid);
|
||||
topicData.breadcrumbs = parentCrumbs.concat(breadcrumbs);
|
||||
}
|
||||
|
||||
async function addTags(topicData, req, res) {
|
||||
var postAtIndex = topicData.posts.find(function (postData) {
|
||||
return parseInt(postData.index, 10) === parseInt(Math.max(0, req.params.post_index - 1), 10);
|
||||
});
|
||||
var postAtIndex = topicData.posts.find(p => parseInt(p.index, 10) === parseInt(Math.max(0, req.params.post_index - 1), 10));
|
||||
|
||||
var description = '';
|
||||
if (postAtIndex && postAtIndex.content) {
|
||||
@@ -300,7 +239,7 @@ async function addTags(topicData, req, res) {
|
||||
}
|
||||
|
||||
async function addOGImageTags(res, topicData, postAtIndex) {
|
||||
const uploads = postAtIndex ? await posts.uploads.listWithSizes(postAtIndex.pid) : [];
|
||||
const uploads = postAtIndex ? await posts.async.uploads.listWithSizes(postAtIndex.pid) : [];
|
||||
const images = uploads.map((upload) => {
|
||||
upload.name = nconf.get('url') + nconf.get('upload_url') + '/files/' + upload.name;
|
||||
return upload;
|
||||
|
||||
Reference in New Issue
Block a user