From 620d873c88f2337627a2728e3bb1c2f9a48bb6af Mon Sep 17 00:00:00 2001 From: fatchan Date: Sun, 21 Apr 2019 12:05:45 +0000 Subject: [PATCH] seems better - aggregate on dlete, increment on new post --- controllers/forms.js | 48 ++++++++++++++++++++++++++---- db/posts.js | 51 ++++++++++++++++++++------------ models/forms/deletepostsfiles.js | 12 ++++---- models/forms/make-post.js | 9 ++++++ views/mixins/catalogtile.pug | 2 +- 5 files changed, 90 insertions(+), 32 deletions(-) diff --git a/controllers/forms.js b/controllers/forms.js index 0e3b3e4b..69f7fc22 100644 --- a/controllers/forms.js +++ b/controllers/forms.js @@ -312,7 +312,7 @@ router.post('/board/:board/actions', Boards.exists, banCheck, numberConverter, a if (req.body.ban_reason && req.body.ban_reason.length > 50) { errors.push('Ban reason must be 50 characters or less'); } - if (req.body.report && (!req.body.report_reason || req.body.report_reason.length === 0)) { + if ((req.body.report || req.body.global_report) && (!req.body.report_reason || req.body.report_reason.length === 0)) { errors.push('Reports must have a reason') } @@ -362,6 +362,7 @@ router.post('/board/:board/actions', Boards.exists, banCheck, numberConverter, a const messages = []; const combinedQuery = {}; const passwordCombinedQuery = {}; + let aggregateNeeded = false; try { if (hasPerms) { // if getting global banned, board ban doesnt matter @@ -376,11 +377,13 @@ router.post('/board/:board/actions', Boards.exists, banCheck, numberConverter, a if (req.body.delete) { const { message } = await deletePosts(req, res, next, passwordPosts); messages.push(message); + aggregateNeeded = true; } else { // if it was getting deleted, we cant do any of these if (req.body.delete_file) { const { message, action, query } = await deletePostsFiles(passwordPosts); if (action) { + aggregateNeeded = true; passwordCombinedQuery[action] = { ...passwordCombinedQuery[action], ...query} } messages.push(message); @@ -464,6 +467,20 @@ router.post('/board/:board/actions', Boards.exists, banCheck, numberConverter, a ) } await Promise.all(dbPromises); + if (aggregateNeeded) { + const threadsToUpdate = [...new Set(posts.filter(post => post.thread !== null))]; + //recalculate and set correct aggregation numbers again + await Promise.all(threadsToUpdate.map(async (post) => { + const replyCounts = await Posts.getReplyCounts(post.board, post.thread); + let replyposts = 0; + let replyfiles = 0; + if (replyCounts[0]) { + replyposts = replyCounts[0].replyposts; + replyfiles = replyCounts[0].replyfiles; + } + Posts.setReplyCounts(post.board, post.thread, replyposts, replyfiles); + })); + } } catch (err) { return next(err); } @@ -562,6 +579,7 @@ router.post('/global/actions', checkPermsMiddleware, numberConverter, async(req, const postMongoIds = posts.map(post => Mongo.ObjectId(post._id)); const messages = []; const combinedQuery = {}; + let aggregateNeeded = false; try { if (req.body.global_ban) { const { message } = await banPoster(req, res, next, null, posts); @@ -570,11 +588,13 @@ router.post('/global/actions', checkPermsMiddleware, numberConverter, async(req, if (req.body.delete) { const { message } = await deletePosts(req, res, next, posts); messages.push(message); + aggregateNeeded = true; } else { // if it was getting deleted, we cant do any of these if (req.body.delete_file) { const { message, action, query } = await deletePostsFiles(posts); if (action) { + aggregateNeeded = true; combinedQuery[action] = { ...combinedQuery[action], ...query} } messages.push(message); @@ -587,11 +607,27 @@ router.post('/global/actions', checkPermsMiddleware, numberConverter, async(req, messages.push(message); } } - await Posts.db.updateMany({ - '_id': { - '$in': postMongoIds - } - }, combinedQuery) + if (Object.keys(combinedQuery).length > 0) { + await Posts.db.updateMany({ + '_id': { + '$in': postMongoIds + } + }, combinedQuery); + } + if (aggregateNeeded) { + const threadsToUpdate = [...new Set(posts.filter(post => post.thread !== null))]; + //recalculate and set correct aggregation numbers again + await Promise.all(threadsToUpdate.map(async (post) => { + const replyCounts = await Posts.getReplyCounts(post.board, post.thread); + let replyposts = 0; + let replyfiles = 0; + if (replyCounts[0]) { + replyposts = replyCounts[0].replyposts; + replyfiles = replyCounts[0].replyfiles; + } + Posts.setReplyCounts(post.board, post.thread, replyposts, replyfiles); + })); + } } catch (err) { return next(err); } diff --git a/db/posts.js b/db/posts.js index e5c25a03..f8925533 100644 --- a/db/posts.js +++ b/db/posts.js @@ -49,18 +49,17 @@ module.exports = { //temporary mitigation for deletion issue if (replies.length >= 5) { - //count omitted image and posts - const counts = await module.exports.getOmitted(board, thread.postId); + //cout omitted image and posts const numPreviewImages = replies.reduce((acc, post) => { return acc + post.files.length }, 0); - thread.omittedimages = counts[0].images - numPreviewImages; - thread.omittedposts = counts[0].posts - replies.length; + thread.omittedimages = thread.replyfiles - numPreviewImages; + thread.omittedposts = thread.replyposts - replies.length; } })); return threads; }, - getOmitted: (board, thread) => { + getReplyCounts: (board, thread) => { return db.aggregate([ { '$match': { @@ -70,12 +69,10 @@ module.exports = { }, { '$group': { '_id': null, - // omitted posts is number of documents returned - 'posts': { + 'replyposts': { '$sum': 1 }, - //files is sum of all length of files arrays - 'images': { + 'replyfiles': { '$sum': { '$size': '$files' } @@ -85,6 +82,18 @@ module.exports = { ]).toArray(); }, + setReplyCounts: (board, thread, replyposts, replyfiles) => { + return db.updateOne({ + 'postId': thread, + 'board': board + }, { + '$set': { + 'replyposts': replyposts, + 'replyfiles': replyfiles, + } + }) + }, + getPages: (board) => { return db.countDocuments({ 'board': board, @@ -93,7 +102,6 @@ module.exports = { }, getThread: async (board, id) => { - // get thread post and potential replies concurrently const data = await Promise.all([ db.findOne({ @@ -111,13 +119,11 @@ module.exports = { }), module.exports.getThreadPosts(board, id) ]) - // attach the replies to the thread post const thread = data[0]; if (thread) { thread.replies = data[1]; } - return thread; }, @@ -225,18 +231,25 @@ module.exports = { insertOne: async (board, data, thread) => { - //if a reply to thread, bump if not sage if (data.thread !== null && data.email !== 'sage' && !thread.saged) { - await db.updateOne({ + const filter = { 'postId': data.thread, 'board': board - }, { - '$set': { - 'bumped':Date.now() + } + const query = { + '$inc': { + 'replyposts': 1, + 'replyfiles': data.files.length } - }); + } + if (data.email !== 'sage' && !thread.saged) { + query['$set'] = { + 'bumped': Date.now() + } + } + await db.updateOne(filter, query); } else { - //this is a new thread, so set the bump date instead + //this is a new thread, so set the bump date data.bumped = Date.now() } diff --git a/models/forms/deletepostsfiles.js b/models/forms/deletepostsfiles.js index 06fbd7af..7142d60a 100644 --- a/models/forms/deletepostsfiles.js +++ b/models/forms/deletepostsfiles.js @@ -14,6 +14,12 @@ module.exports = async (posts) => { fileNames = fileNames.concat(post.files.map(x => x.filename)) }) + if (fileNames.length === 0) { + return { + message: 'No files to delete' + } + } + //delete all the files using the filenames await Promise.all(fileNames.map(async filename => { //dont question it. @@ -23,12 +29,6 @@ module.exports = async (posts) => { ]) })); - if (fileNames.length === 0) { - return { - message: 'No files to delete' - } - } - return { message:`Deleted ${fileNames.length} file(s) across ${posts.length} post(s)`, action:'$set', diff --git a/models/forms/make-post.js b/models/forms/make-post.js index db1eb486..3299adde 100644 --- a/models/forms/make-post.js +++ b/models/forms/make-post.js @@ -55,6 +55,13 @@ module.exports = async (req, res, next, numFiles) => { 'redirect': redirect }); } + if (thread.replyposts >= 100) { //reply limit + return res.status(400).render('message', { + 'title': 'Bad request', + 'message': 'Thread reached reply limit', + 'redirect': redirect + }); + } salt = thread.salt; redirect += `/thread/${req.body.thread}` } @@ -193,6 +200,8 @@ module.exports = async (req, res, next, numFiles) => { 'files': files, 'reports': [], 'globalreports': [], + 'replyposts': 0, + 'replyfiles': 0, 'sticky': false, 'locked': false, 'saged': false, diff --git a/views/mixins/catalogtile.pug b/views/mixins/catalogtile.pug index ac39bea6..440bab07 100644 --- a/views/mixins/catalogtile.pug +++ b/views/mixins/catalogtile.pug @@ -15,7 +15,7 @@ mixin catalogtile(board, post, truncate) header.post-info span: a(href=postURL) ##{post.postId} span Replies: #{post.replyposts} - span Images: #{post.replyimages} + span Images: #{post.replyfiles} br if post.message blockquote.no-m-p.post-message !{post.message}