diff --git a/models/forms/actionhandler.js b/models/forms/actionhandler.js index 3bc1a054..f41bcc4d 100644 --- a/models/forms/actionhandler.js +++ b/models/forms/actionhandler.js @@ -95,58 +95,42 @@ module.exports = async (req, res, next) => { } messages.push(message); } - if (req.body.delete_ip_board || req.body.delete_ip_global) { - const deletePostIps = res.locals.posts.map(x => x.ip); - let query = { - 'ip': { - '$in': deletePostIps + if (req.body.delete || req.body.delete_ip_board || req.body.delete_ip_global) { + if (req.body.delete_ip_board || req.body.delete_ip_global) { + const deletePostIps = res.locals.posts.map(x => x.ip); + let query = { + 'ip': { + '$in': deletePostIps + } + }; + if (req.body.delete_ip_board) { + query['board'] = req.params.board; } - }; - if (req.body.delete_ip_board) { - query['board'] = req.params.board; + const deleteIpPosts = await Posts.db.find(query).toArray(); + res.locals.posts = res.locals.posts.concat(deleteIpPosts); } - const deleteIpPosts = await Posts.db.find(query).toArray(); - res.locals.posts = res.locals.posts.concat(deleteIpPosts); - if (deleteIpPosts && deleteIpPosts.length > 0) { - const { action, message } = await deletePosts(deleteIpPosts, req.params.board); + if (req.body.delete_file) { + const { message } = await deletePostsFiles(res.locals.posts, false); //delete files, not just unlink messages.push(message); - if (action) { - aggregateNeeded = true; - } else { - req.body.delete_ip_board = false; - req.body.delete_ip_global = false; - res.locals.actions.anyValid--; - } } - } else if (req.body.delete) { - const { action, message } = await deletePosts(passwordPosts, req.params.board); + const { action, message } = await deletePosts(res.locals.posts, req.body.delete_ip_global ? null : req.params.board); messages.push(message); if (action) { aggregateNeeded = true; - } else { - req.body.delete = false; - res.locals.actions.anyValid--; } } else { // if it was getting deleted, we cant do any of these - if (req.body.delete_file || req.body.unlink_file) { + if (req.body.unlink_file || req.body.delete_file) { const { message, action, query } = await deletePostsFiles(passwordPosts, req.body.unlink_file); if (action) { aggregateNeeded = true; passwordCombinedQuery[action] = { ...passwordCombinedQuery[action], ...query} - } else { - req.body.delete_file = false; - req.body.unlink_file = false; - res.locals.actions.anyValid--; } messages.push(message); } else if (req.body.spoiler) { const { message, action, query } = spoilerPosts(passwordPosts); if (action) { passwordCombinedQuery[action] = { ...passwordCombinedQuery[action], ...query} - } else { - req.body.spoiler = false; - res.locals.actions.anyValid--; } messages.push(message); } @@ -155,9 +139,6 @@ module.exports = async (req, res, next) => { const { message, action, query } = sagePosts(res.locals.posts); if (action) { combinedQuery[action] = { ...combinedQuery[action], ...query} - } else { - req.body.sage = false; - res.locals.actions.anyValid--; } messages.push(message); } @@ -165,9 +146,6 @@ module.exports = async (req, res, next) => { const { message, action, query } = lockPosts(res.locals.posts); if (action) { combinedQuery[action] = { ...combinedQuery[action], ...query} - } else { - req.body.lock = false; - res.locals.actions.anyValid--; } messages.push(message); } @@ -175,9 +153,6 @@ module.exports = async (req, res, next) => { const { message, action, query } = stickyPosts(res.locals.posts); if (action) { combinedQuery[action] = { ...combinedQuery[action], ...query} - } else { - req.body.sticky = false; - res.locals.actions.anyValid--; } messages.push(message); } @@ -185,9 +160,6 @@ module.exports = async (req, res, next) => { const { message, action, query } = cyclePosts(res.locals.posts); if (action) { combinedQuery[action] = { ...combinedQuery[action], ...query} - } else { - req.body.cyclic = false; - res.locals.actions.anyValid--; } messages.push(message); } @@ -202,9 +174,6 @@ module.exports = async (req, res, next) => { const { message, action, query } = dismissReports(res.locals.posts); if (action) { combinedQuery[action] = { ...combinedQuery[action], ...query} - } else { - req.body.dismiss = false; - res.locals.actions.anyValid--; } messages.push(message); } @@ -219,166 +188,161 @@ module.exports = async (req, res, next) => { const { message, action, query } = dismissGlobalReports(res.locals.posts); if (action) { combinedQuery[action] = { ...combinedQuery[action], ...query} - } else { - req.body.global_dismiss = false; - res.locals.actions.anyValid--; } messages.push(message); } } - if (res.locals.actions.anyValid > 0) { - const bulkWrites = []; - if (Object.keys(combinedQuery).length > 0) { - bulkWrites.push({ - 'updateMany': { - 'filter': { - '_id': { - '$in': postMongoIds - } - }, - 'update': combinedQuery - } - }); - } - if (Object.keys(passwordCombinedQuery).length > 0) { - bulkWrites.push({ - 'updateMany': { - 'filter': { - '_id': { - '$in': passwordPostMongoIds - } - }, - 'update': passwordCombinedQuery - } - }); - } - - //execute actions now - if (bulkWrites.length > 0) { - await Posts.db.bulkWrite(bulkWrites); - } - - //if there are actions that can cause some rebuilding - if (res.locals.actions.anyBuild > 0) { - - //recalculate replies and image counts - if (aggregateNeeded) { - const selectedPosts = res.locals.posts.filter(post => post.thread !== null); -//TODO: do this in a better way. - await Promise.all(selectedPosts.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; + const bulkWrites = []; + if (Object.keys(combinedQuery).length > 0) { + bulkWrites.push({ + 'updateMany': { + 'filter': { + '_id': { + '$in': postMongoIds } - Posts.setReplyCounts(post.board, post.thread, replyposts, replyfiles); - })); + }, + 'update': combinedQuery } - - //make it into an OR query for the db - const queryOrs = []; - for (let i = 0; i < threadBoards.length; i++) { - const threadBoard = threadBoards[i]; - //convert this to an array while we are here - boardThreadMap[threadBoard].threads = [...boardThreadMap[threadBoard].threads] - queryOrs.push({ - 'board': threadBoard, - 'postId': { - '$in': boardThreadMap[threadBoard].threads + }); + } + if (Object.keys(passwordCombinedQuery).length > 0) { + bulkWrites.push({ + 'updateMany': { + 'filter': { + '_id': { + '$in': passwordPostMongoIds } - }) + }, + 'update': passwordCombinedQuery } + }); + } - //fetch threads per board that we only checked posts for - let threadsEachBoard = await Posts.db.find({ - 'thread': null, - '$or': queryOrs - }).toArray(); + //execute actions now + if (bulkWrites.length > 0) { + await Posts.db.bulkWrite(bulkWrites); + } - //combine it with what we already had - const selectedThreads = res.locals.posts.filter(post => post.thread === null) - threadsEachBoard = threadsEachBoard.concat(selectedThreads) + //if there are actions that can cause some rebuilding + if (res.locals.actions.anyBuild > 0) { - //get the oldest and newest thread for each board to determine how to delete - const threadBounds = threadsEachBoard.reduce((acc, curr) => { - if (!acc[curr.board] || curr.bumped < acc[curr.board].bumped) { - acc[curr.board] = { oldest: null, newest: null}; - } - if (!acc[curr.board].oldest || curr.bumped < acc[curr.board].oldest.bumped) { - acc[curr.board].oldest = curr; - } - if (!acc[curr.board].newest || curr.bumped > acc[curr.board].newest.bumped) { - acc[curr.board].newest = curr; + //recalculate replies and image counts + if (aggregateNeeded) { + const selectedPosts = res.locals.posts.filter(post => post.thread !== null); +//TODO: do this in a better way. + await Promise.all(selectedPosts.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; } - return acc; - }, {}); + Posts.setReplyCounts(post.board, post.thread, replyposts, replyfiles); + })); + } - const parallelPromises = [] - const boardNames = Object.keys(threadBounds); - const buildBoards = {}; - const multiBoards = await Boards.db.find({ - '_id': { - '$in': boardNames + //make it into an OR query for the db + const queryOrs = []; + for (let i = 0; i < threadBoards.length; i++) { + const threadBoard = threadBoards[i]; + //convert this to an array while we are here + boardThreadMap[threadBoard].threads = [...boardThreadMap[threadBoard].threads] + queryOrs.push({ + 'board': threadBoard, + 'postId': { + '$in': boardThreadMap[threadBoard].threads } - }).toArray(); - multiBoards.forEach(board => { - buildBoards[board._id] = board; - }); + }) + } - for (let i = 0; i < boardNames.length; i++) { - const boardName = boardNames[i]; - const bounds = threadBounds[boardName]; - //rebuild impacted threads - for (let j = 0; j < boardThreadMap[boardName].threads.length; j++) { - parallelPromises.push(buildThread(boardThreadMap[boardName].threads[j], buildBoards[boardName])); - } - //refersh any pages affected - const afterPages = Math.ceil((await Posts.getPages(boardName)) / 10); - let catalogRebuild = true; - if (beforePages[boardName] && beforePages[boardName] !== afterPages) { - //amount of pages changed, rebuild all pages and delete any further pages (if pages amount decreased) - if (afterPages < beforePages[boardName]) { - //amount of pages decreased - for (let k = beforePages[boardName]; k > afterPages; k--) { - //deleting html for pages that no longer should exist - parallelPromises.push(remove(`${uploadDirectory}html/${boardName}/${k}.html`)); - } + //fetch threads per board that we only checked posts for + let threadsEachBoard = await Posts.db.find({ + 'thread': null, + '$or': queryOrs + }).toArray(); + + //combine it with what we already had + const selectedThreads = res.locals.posts.filter(post => post.thread === null) + threadsEachBoard = threadsEachBoard.concat(selectedThreads) + + //get the oldest and newest thread for each board to determine how to delete + const threadBounds = threadsEachBoard.reduce((acc, curr) => { + if (!acc[curr.board] || curr.bumped < acc[curr.board].bumped) { + acc[curr.board] = { oldest: null, newest: null}; + } + if (!acc[curr.board].oldest || curr.bumped < acc[curr.board].oldest.bumped) { + acc[curr.board].oldest = curr; + } + if (!acc[curr.board].newest || curr.bumped > acc[curr.board].newest.bumped) { + acc[curr.board].newest = curr; + } + return acc; + }, {}); + + const parallelPromises = [] + const boardNames = Object.keys(threadBounds); + const buildBoards = {}; + const multiBoards = await Boards.db.find({ + '_id': { + '$in': boardNames + } + }).toArray(); + multiBoards.forEach(board => { + buildBoards[board._id] = board; + }); + + for (let i = 0; i < boardNames.length; i++) { + const boardName = boardNames[i]; + const bounds = threadBounds[boardName]; + //rebuild impacted threads + for (let j = 0; j < boardThreadMap[boardName].threads.length; j++) { + parallelPromises.push(buildThread(boardThreadMap[boardName].threads[j], buildBoards[boardName])); + } + //refersh any pages affected + const afterPages = Math.ceil((await Posts.getPages(boardName)) / 10); + let catalogRebuild = true; + if (beforePages[boardName] && beforePages[boardName] !== afterPages) { + //amount of pages changed, rebuild all pages and delete any further pages (if pages amount decreased) + if (afterPages < beforePages[boardName]) { + //amount of pages decreased + for (let k = beforePages[boardName]; k > afterPages; k--) { + //deleting html for pages that no longer should exist + parallelPromises.push(remove(`${uploadDirectory}html/${boardName}/${k}.html`)); } - parallelPromises.push(buildBoardMultiple(buildBoards[boardName], 1, afterPages)); - } else { - //number of pages did not change, only possibly building existing pages - const threadPageOldest = await Posts.getThreadPage(boardName, bounds.oldest); - const threadPageNewest = bounds.oldest.postId === bounds.newest.postId ? threadPageOldest : await Posts.getThreadPage(boardName, bounds.newest); - if (req.body.delete || req.body.delete_ip_board || req.body.delete_ip_global) { - if (!boardThreadMap[boardName].directThreads) { - //onyl deleting posts from threads, so thread order wont change, thus we dont delete all pages after - parallelPromises.push(buildBoardMultiple(buildBoards[boardName], threadPageNewest, threadPageOldest)); - } else { - //deleting threads, so we delete all pages after - parallelPromises.push(buildBoardMultiple(buildBoards[boardName], threadPageNewest, afterPages)); - } - } else if (req.body.sticky) { //else if -- if deleting, other actions are not executed/irrelevant - //rebuild current and newer pages - parallelPromises.push(buildBoardMultiple(buildBoards[boardName], 1, threadPageOldest)); - } else if (req.body.lock || req.body.sage || req.body.cyclic || req.body.unlink_file) { - parallelPromises.push(buildBoardMultiple(buildBoards[boardName], threadPageNewest, threadPageOldest)); - } else if (req.body.spoiler || req.body.ban || req.body.global_ban) { + } + parallelPromises.push(buildBoardMultiple(buildBoards[boardName], 1, afterPages)); + } else { + //number of pages did not change, only possibly building existing pages + const threadPageOldest = await Posts.getThreadPage(boardName, bounds.oldest); + const threadPageNewest = bounds.oldest.postId === bounds.newest.postId ? threadPageOldest : await Posts.getThreadPage(boardName, bounds.newest); + if (req.body.delete || req.body.delete_ip_board || req.body.delete_ip_global) { + if (!boardThreadMap[boardName].directThreads) { + //onyl deleting posts from threads, so thread order wont change, thus we dont delete all pages after parallelPromises.push(buildBoardMultiple(buildBoards[boardName], threadPageNewest, threadPageOldest)); - if (!boardThreadMap[boardName].directThreads) { - catalogRebuild = false; - //these actions dont affect the catalog tile since not on an OP and dont change reply/image counts - } + } else { + //deleting threads, so we delete all pages after + parallelPromises.push(buildBoardMultiple(buildBoards[boardName], threadPageNewest, afterPages)); + } + } else if (req.body.sticky) { //else if -- if deleting, other actions are not executed/irrelevant + //rebuild current and newer pages + parallelPromises.push(buildBoardMultiple(buildBoards[boardName], 1, threadPageOldest)); + } else if (req.body.lock || req.body.sage || req.body.cyclic || req.body.unlink_file) { + parallelPromises.push(buildBoardMultiple(buildBoards[boardName], threadPageNewest, threadPageOldest)); + } else if (req.body.spoiler || req.body.ban || req.body.global_ban) { + parallelPromises.push(buildBoardMultiple(buildBoards[boardName], threadPageNewest, threadPageOldest)); + if (!boardThreadMap[boardName].directThreads) { + catalogRebuild = false; + //these actions dont affect the catalog tile since not on an OP and dont change reply/image counts } } - if (catalogRebuild) { - //the actions will affect the catalog, so we better rebuild it - parallelPromises.push(buildCatalog(buildBoards[boardName])); - } } - await Promise.all(parallelPromises); + if (catalogRebuild) { + //the actions will affect the catalog, so we better rebuild it + parallelPromises.push(buildCatalog(buildBoards[boardName])); + } } + await Promise.all(parallelPromises); } } catch (err) {