From 1b2b308a7e0636dc5ec4457e9fef12d92ff37786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Wed, 17 Jul 2019 00:17:21 -0400 Subject: [PATCH] feat: #7743, posts module --- src/posts/bookmarks.js | 117 +++++++---------- src/posts/category.js | 86 ++++--------- src/posts/create.js | 140 ++++++++------------ src/posts/data.js | 84 +++++------- src/posts/delete.js | 284 +++++++++++++++-------------------------- test/posts.js | 8 ++ 6 files changed, 262 insertions(+), 457 deletions(-) diff --git a/src/posts/bookmarks.js b/src/posts/bookmarks.js index c609408821..fd50af9465 100644 --- a/src/posts/bookmarks.js +++ b/src/posts/bookmarks.js @@ -1,99 +1,68 @@ 'use strict'; -var async = require('async'); - -var db = require('../database'); -var plugins = require('../plugins'); +const db = require('../database'); +const plugins = require('../plugins'); module.exports = function (Posts) { - Posts.bookmark = function (pid, uid, callback) { - toggleBookmark('bookmark', pid, uid, callback); + Posts.bookmark = async function (pid, uid) { + return await toggleBookmark('bookmark', pid, uid); }; - Posts.unbookmark = function (pid, uid, callback) { - toggleBookmark('unbookmark', pid, uid, callback); + Posts.unbookmark = async function (pid, uid) { + return await toggleBookmark('unbookmark', pid, uid); }; - function toggleBookmark(type, pid, uid, callback) { + async function toggleBookmark(type, pid, uid) { if (parseInt(uid, 10) <= 0) { - return callback(new Error('[[error:not-logged-in]]')); + throw new Error('[[error:not-logged-in]]'); } - var isBookmarking = type === 'bookmark'; - var postData; - var hasBookmarked; - var owner; - async.waterfall([ - function (next) { - async.parallel({ - owner: function (next) { - Posts.getPostField(pid, 'uid', next); - }, - postData: function (next) { - Posts.getPostFields(pid, ['pid', 'uid'], next); - }, - hasBookmarked: function (next) { - Posts.hasBookmarked(pid, uid, next); - }, - }, next); - }, - function (results, next) { - owner = results.owner; - postData = results.postData; - hasBookmarked = results.hasBookmarked; + const isBookmarking = type === 'bookmark'; - if (isBookmarking && hasBookmarked) { - return callback(new Error('[[error:already-bookmarked]]')); - } + const [postData, hasBookmarked] = await Promise.all([ + Posts.getPostFields(pid, ['pid', 'uid']), + Posts.hasBookmarked(pid, uid), + ]); - if (!isBookmarking && !hasBookmarked) { - return callback(new Error('[[error:already-unbookmarked]]')); - } + if (isBookmarking && hasBookmarked) { + throw new Error('[[error:already-bookmarked]]'); + } - if (isBookmarking) { - db.sortedSetAdd('uid:' + uid + ':bookmarks', Date.now(), pid, next); - } else { - db.sortedSetRemove('uid:' + uid + ':bookmarks', pid, next); - } - }, - function (next) { - db[isBookmarking ? 'setAdd' : 'setRemove']('pid:' + pid + ':users_bookmarked', uid, next); - }, - function (next) { - db.setCount('pid:' + pid + ':users_bookmarked', next); - }, - function (count, next) { - postData.bookmarks = count; - Posts.setPostField(pid, 'bookmarks', count, next); - }, - function (next) { - var current = hasBookmarked ? 'bookmarked' : 'unbookmarked'; + if (!isBookmarking && !hasBookmarked) { + throw new Error('[[error:already-unbookmarked]]'); + } - plugins.fireHook('action:post.' + type, { - pid: pid, - uid: uid, - owner: owner, - current: current, - }); + if (isBookmarking) { + await db.sortedSetAdd('uid:' + uid + ':bookmarks', Date.now(), pid); + } else { + await db.sortedSetRemove('uid:' + uid + ':bookmarks', pid); + } + await db[isBookmarking ? 'setAdd' : 'setRemove']('pid:' + pid + ':users_bookmarked', uid); + postData.bookmarks = await db.setCount('pid:' + pid + ':users_bookmarked'); + await Posts.setPostField(pid, 'bookmarks', postData.bookmarks); + + plugins.fireHook('action:post.' + type, { + pid: pid, + uid: uid, + owner: postData.uid, + current: hasBookmarked ? 'bookmarked' : 'unbookmarked', + }); - next(null, { - post: postData, - isBookmarked: isBookmarking, - }); - }, - ], callback); + return { + post: postData, + isBookmarked: isBookmarking, + }; } - Posts.hasBookmarked = function (pid, uid, callback) { + Posts.hasBookmarked = async function (pid, uid) { if (parseInt(uid, 10) <= 0) { - return callback(null, Array.isArray(pid) ? pid.map(() => false) : false); + return Array.isArray(pid) ? pid.map(() => false) : false; } if (Array.isArray(pid)) { - var sets = pid.map(pid => 'pid:' + pid + ':users_bookmarked'); - db.isMemberOfSets(sets, uid, callback); - } else { - db.isSetMember('pid:' + pid + ':users_bookmarked', uid, callback); + const sets = pid.map(pid => 'pid:' + pid + ':users_bookmarked'); + return await db.isMemberOfSets(sets, uid); } + return await db.isSetMember('pid:' + pid + ':users_bookmarked', uid); }; }; diff --git a/src/posts/category.js b/src/posts/category.js index 3cfc3e4d09..c84fe73007 100644 --- a/src/posts/category.js +++ b/src/posts/category.js @@ -1,83 +1,41 @@ 'use strict'; -var async = require('async'); -var _ = require('lodash'); -var db = require('../database'); -var topics = require('../topics'); +const _ = require('lodash'); + +const db = require('../database'); +const topics = require('../topics'); module.exports = function (Posts) { - Posts.getCidByPid = function (pid, callback) { - async.waterfall([ - function (next) { - Posts.getPostField(pid, 'tid', next); - }, - function (tid, next) { - topics.getTopicField(tid, 'cid', next); - }, - ], callback); + Posts.getCidByPid = async function (pid) { + const tid = await Posts.getPostField(pid, 'tid'); + return await topics.getTopicField(tid, 'cid'); }; - Posts.getCidsByPids = function (pids, callback) { - var tids; - var postData; - async.waterfall([ - function (next) { - Posts.getPostsFields(pids, ['tid'], next); - }, - function (_postData, next) { - postData = _postData; - tids = _.uniq(postData.map(post => post && post.tid).filter(Boolean)); - - topics.getTopicsFields(tids, ['cid'], next); - }, - function (topicData, next) { - var map = {}; - topicData.forEach(function (topic, index) { - if (topic) { - map[tids[index]] = topic.cid; - } - }); - - var cids = postData.map(post => map[post.tid]); - next(null, cids); - }, - ], callback); + Posts.getCidsByPids = async function (pids) { + const postData = await Posts.getPostsFields(pids, ['tid']); + const tids = _.uniq(postData.map(post => post && post.tid).filter(Boolean)); + const topicData = await topics.getTopicsFields(tids, ['cid']); + const tidToTopic = _.zipObject(tids, topicData); + const cids = postData.map(post => tidToTopic[post.tid].cid); + return cids; }; - Posts.filterPidsByCid = function (pids, cid, callback) { + Posts.filterPidsByCid = async function (pids, cid) { if (!cid) { - return setImmediate(callback, null, pids); + return pids; } if (!Array.isArray(cid) || cid.length === 1) { - return filterPidsBySingleCid(pids, cid, callback); + return await filterPidsBySingleCid(pids, cid); } - - async.waterfall([ - function (next) { - async.map(cid, function (cid, next) { - Posts.filterPidsByCid(pids, cid, next); - }, next); - }, - function (pidsArr, next) { - next(null, _.union.apply(_, pidsArr)); - }, - ], callback); + const pidsArr = await Promise.all(cid.map(c => Posts.filterPidsByCid(pids, c))); + return _.union.apply(_, pidsArr); }; - function filterPidsBySingleCid(pids, cid, callback) { - async.waterfall([ - function (next) { - db.isSortedSetMembers('cid:' + parseInt(cid, 10) + ':pids', pids, next); - }, - function (isMembers, next) { - pids = pids.filter(function (pid, index) { - return pid && isMembers[index]; - }); - next(null, pids); - }, - ], callback); + async function filterPidsBySingleCid(pids, cid) { + const isMembers = await db.isSortedSetMembers('cid:' + parseInt(cid, 10) + ':pids', pids); + return pids.filter((pid, index) => pid && isMembers[index]); } }; diff --git a/src/posts/create.js b/src/posts/create.js index 1b2ec02acf..4e1ef12640 100644 --- a/src/posts/create.js +++ b/src/posts/create.js @@ -1,6 +1,5 @@ 'use strict'; -var async = require('async'); var _ = require('lodash'); var meta = require('../meta'); @@ -13,102 +12,73 @@ var groups = require('../groups'); var utils = require('../utils'); module.exports = function (Posts) { - Posts.create = function (data, callback) { + Posts.create = async function (data) { // This is an internal method, consider using Topics.reply instead - var uid = data.uid; - var tid = data.tid; - var content = data.content.toString(); - var timestamp = data.timestamp || Date.now(); - var isMain = data.isMain || false; + const uid = data.uid; + const tid = data.tid; + const content = data.content.toString(); + const timestamp = data.timestamp || Date.now(); + const isMain = data.isMain || false; if (!uid && parseInt(uid, 10) !== 0) { - return callback(new Error('[[error:invalid-uid]]')); + throw new Error('[[error:invalid-uid]]'); } if (data.toPid && !utils.isNumber(data.toPid)) { - return callback(new Error('[[error:invalid-pid]]')); + throw new Error('[[error:invalid-pid]]'); } - var postData; + const pid = await db.incrObjectField('global', 'nextPid'); + let postData = { + pid: pid, + uid: uid, + tid: tid, + content: content, + timestamp: timestamp, + deleted: 0, + }; - async.waterfall([ - function (next) { - db.incrObjectField('global', 'nextPid', next); - }, - function (pid, next) { - postData = { - pid: pid, - uid: uid, - tid: tid, - content: content, - timestamp: timestamp, - deleted: 0, - }; + if (data.toPid) { + postData.toPid = data.toPid; + } + if (data.ip && meta.config.trackIpPerPost) { + postData.ip = data.ip; + } + if (data.handle && !parseInt(uid, 10)) { + postData.handle = data.handle; + } - if (data.toPid) { - postData.toPid = data.toPid; - } + let result = await plugins.fireHook('filter:post.create', { post: postData, data: data }); + postData = result.post; + await db.setObject('post:' + postData.pid, postData); - if (data.ip && meta.config.trackIpPerPost) { - postData.ip = data.ip; - } + const topicData = await topics.getTopicFields(tid, ['cid', 'pinned']); + postData.cid = topicData.cid; - if (data.handle && !parseInt(uid, 10)) { - postData.handle = data.handle; - } + await Promise.all([ + db.sortedSetAdd('posts:pid', timestamp, postData.pid), + db.incrObjectField('global', 'postCount'), + user.onNewPostMade(postData), + topics.onNewPostMade(postData), + categories.onNewPostMade(topicData.cid, topicData.pinned, postData), + groups.onNewPostMade(postData), + addReplyTo(postData, timestamp), + Posts.uploads.sync(postData.pid), + ]); - plugins.fireHook('filter:post.create', { post: postData, data: data }, next); - }, - function (data, next) { - postData = data.post; - db.setObject('post:' + postData.pid, postData, next); - }, - function (next) { - topics.getTopicFields(tid, ['cid', 'pinned'], next); - }, - function (topicData, next) { - postData.cid = topicData.cid; - async.parallel([ - function (next) { - user.onNewPostMade(postData, next); - }, - function (next) { - topics.onNewPostMade(postData, next); - }, - function (next) { - categories.onNewPostMade(topicData.cid, topicData.pinned, postData, next); - }, - function (next) { - groups.onNewPostMade(postData, next); - }, - function (next) { - db.sortedSetAdd('posts:pid', timestamp, postData.pid, next); - }, - function (next) { - if (!postData.toPid) { - return next(null); - } - async.parallel([ - async.apply(db.sortedSetAdd, 'pid:' + postData.toPid + ':replies', timestamp, postData.pid), - async.apply(db.incrObjectField, 'post:' + postData.toPid, 'replies'), - ], next); - }, - function (next) { - db.incrObjectField('global', 'postCount', next); - }, - async.apply(Posts.uploads.sync, postData.pid), - ], function (err) { - next(err); - }); - }, - function (next) { - plugins.fireHook('filter:post.get', { post: postData, uid: data.uid }, next); - }, - function (data, next) { - data.post.isMain = isMain; - plugins.fireHook('action:post.save', { post: _.clone(data.post) }); - next(null, data.post); - }, - ], callback); + result = await plugins.fireHook('filter:post.get', { post: postData, uid: data.uid }); + result.post.isMain = isMain; + plugins.fireHook('action:post.save', { post: _.clone(result.post) }); + return result.post; }; + + async function addReplyTo(postData, timestamp) { + if (!postData.toPid) { + return; + } + await Promise.all([ + db.sortedSetAdd('pid:' + postData.toPid + ':replies', timestamp, postData.pid), + db.incrObjectField('post:' + postData.toPid, 'replies'), + ]); + } }; diff --git a/src/posts/data.js b/src/posts/data.js index aa53fca6c1..06204ca30e 100644 --- a/src/posts/data.js +++ b/src/posts/data.js @@ -1,10 +1,8 @@ 'use strict'; -var async = require('async'); - -var db = require('../database'); -var plugins = require('../plugins'); -var utils = require('../utils'); +const db = require('../database'); +const plugins = require('../plugins'); +const utils = require('../utils'); const intFields = [ 'uid', 'pid', 'tid', 'deleted', 'timestamp', @@ -12,67 +10,49 @@ const intFields = [ ]; module.exports = function (Posts) { - Posts.getPostsFields = function (pids, fields, callback) { + Posts.getPostsFields = async function (pids, fields) { if (!Array.isArray(pids) || !pids.length) { - return callback(null, []); + return []; } - - async.waterfall([ - function (next) { - const keys = pids.map(pid => 'post:' + pid); - if (fields.length) { - db.getObjectsFields(keys, fields, next); - } else { - db.getObjects(keys, next); - } - }, - function (posts, next) { - plugins.fireHook('filter:post.getFields', { posts: posts, fields: fields }, next); - }, - function (data, next) { - data.posts.forEach(post => modifyPost(post, fields)); - next(null, Array.isArray(data.posts) ? data.posts : null); - }, - ], callback); + const keys = pids.map(pid => 'post:' + pid); + let postData; + if (fields.length) { + postData = await db.getObjectsFields(keys, fields); + } else { + postData = await db.getObjects(keys); + } + const result = await plugins.fireHook('filter:post.getFields', { posts: postData, fields: fields }); + result.posts.forEach(post => modifyPost(post, fields)); + return Array.isArray(result.posts) ? result.posts : null; }; - Posts.getPostData = function (pid, callback) { - Posts.getPostsFields([pid], [], function (err, posts) { - callback(err, posts && posts.length ? posts[0] : null); - }); + Posts.getPostData = async function (pid) { + const posts = await Posts.getPostsFields([pid], []); + return posts && posts.length ? posts[0] : null; }; - Posts.getPostsData = function (pids, callback) { - Posts.getPostsFields(pids, [], callback); + Posts.getPostsData = async function (pids) { + return await Posts.getPostsFields(pids, []); }; - Posts.getPostField = function (pid, field, callback) { - Posts.getPostFields(pid, [field], function (err, post) { - callback(err, post ? post[field] : null); - }); + Posts.getPostField = async function (pid, field) { + const post = await Posts.getPostFields(pid, [field]); + return post ? post[field] : null; }; - Posts.getPostFields = function (pid, fields, callback) { - Posts.getPostsFields([pid], fields, function (err, posts) { - callback(err, posts ? posts[0] : null); - }); + Posts.getPostFields = async function (pid, fields) { + const posts = await Posts.getPostsFields([pid], fields); + return posts ? posts[0] : null; }; - Posts.setPostField = function (pid, field, value, callback) { - Posts.setPostFields(pid, { [field]: value }, callback); + Posts.setPostField = async function (pid, field, value) { + await Posts.setPostFields(pid, { [field]: value }); }; - Posts.setPostFields = function (pid, data, callback) { - async.waterfall([ - function (next) { - db.setObject('post:' + pid, data, next); - }, - function (next) { - data.pid = pid; - plugins.fireHook('action:post.setFields', { data: data }); - next(); - }, - ], callback); + Posts.setPostFields = async function (pid, data) { + await db.setObject('post:' + pid, data); + data.pid = pid; + plugins.fireHook('action:post.setFields', { data: data }); }; }; diff --git a/src/posts/delete.js b/src/posts/delete.js index 29bf7ae0ae..e3c135a211 100644 --- a/src/posts/delete.js +++ b/src/posts/delete.js @@ -1,212 +1,132 @@ 'use strict'; -var async = require('async'); -var _ = require('lodash'); +const _ = require('lodash'); -var db = require('../database'); -var topics = require('../topics'); -var user = require('../user'); -var groups = require('../groups'); -var notifications = require('../notifications'); -var plugins = require('../plugins'); +const db = require('../database'); +const topics = require('../topics'); +const categories = require('../categories'); +const user = require('../user'); +const groups = require('../groups'); +const notifications = require('../notifications'); +const plugins = require('../plugins'); module.exports = function (Posts) { - Posts.delete = function (pid, uid, callback) { - deleteOrRestore('delete', pid, uid, callback); + Posts.delete = async function (pid, uid) { + return await deleteOrRestore('delete', pid, uid); }; - Posts.restore = function (pid, uid, callback) { - deleteOrRestore('restore', pid, uid, callback); + Posts.restore = async function (pid, uid) { + return await deleteOrRestore('restore', pid, uid); }; - function deleteOrRestore(type, pid, uid, callback) { - var postData; + async function deleteOrRestore(type, pid, uid) { const isDeleting = type === 'delete'; - async.waterfall([ - function (next) { - plugins.fireHook('filter:post.' + type, { pid: pid, uid: uid }, next); - }, - function (data, next) { - Posts.setPostFields(pid, { - deleted: isDeleting ? 1 : 0, - deleterUid: isDeleting ? uid : 0, - }, next); - }, - function (next) { - Posts.getPostFields(pid, ['pid', 'tid', 'uid', 'content', 'timestamp'], next); - }, - function (_post, next) { - postData = _post; - topics.getTopicFields(_post.tid, ['tid', 'cid', 'pinned'], next); - }, - function (topicData, next) { - postData.cid = topicData.cid; - async.parallel([ - function (next) { - topics.updateLastPostTimeFromLastPid(postData.tid, next); - }, - function (next) { - if (isDeleting) { - db.sortedSetRemove('cid:' + topicData.cid + ':pids', pid, next); - } else { - db.sortedSetAdd('cid:' + topicData.cid + ':pids', postData.timestamp, pid, next); - } - }, - function (next) { - topics.updateTeaser(postData.tid, next); - }, - ], next); - }, - function (results, next) { - plugins.fireHook('action:post.' + type, { post: _.clone(postData), uid: uid }); - next(null, postData); - }, - ], callback); + await plugins.fireHook('filter:post.' + type, { pid: pid, uid: uid }); + await Posts.setPostFields(pid, { + deleted: isDeleting ? 1 : 0, + deleterUid: isDeleting ? uid : 0, + }); + const postData = await Posts.getPostFields(pid, ['pid', 'tid', 'uid', 'content', 'timestamp']); + const topicData = await topics.getTopicFields(postData.tid, ['tid', 'cid', 'pinned']); + postData.cid = topicData.cid; + await Promise.all([ + topics.updateLastPostTimeFromLastPid(postData.tid), + topics.updateTeaser(postData.tid), + isDeleting ? + db.sortedSetRemove('cid:' + topicData.cid + ':pids', pid) : + db.sortedSetAdd('cid:' + topicData.cid + ':pids', postData.timestamp, pid), + ]); + plugins.fireHook('action:post.' + type, { post: _.clone(postData), uid: uid }); + return postData; } - Posts.purge = function (pid, uid, callback) { - let postData; - async.waterfall([ - function (next) { - Posts.getPostData(pid, next); - }, - function (_postData, next) { - postData = _postData; - if (!postData) { - return callback(); - } - plugins.fireHook('filter:post.purge', { post: postData, pid: pid, uid: uid }, next); - }, - function (data, next) { - async.parallel([ - async.apply(deletePostFromTopicUserNotification, postData), - async.apply(deletePostFromCategoryRecentPosts, pid), - async.apply(deletePostFromUsersBookmarks, pid), - async.apply(deletePostFromUsersVotes, pid), - async.apply(deletePostFromReplies, postData), - async.apply(deletePostFromGroups, postData), - async.apply(db.sortedSetsRemove, ['posts:pid', 'posts:votes', 'posts:flagged'], pid), - ], err => next(err)); - }, - function (next) { - plugins.fireHook('action:post.purge', { post: postData, uid: uid }); - db.delete('post:' + pid, next); - }, - ], callback); + Posts.purge = async function (pid, uid) { + const postData = await Posts.getPostData(pid); + if (!postData) { + return; + } + + await plugins.fireHook('filter:post.purge', { post: postData, pid: pid, uid: uid }); + await Promise.all([ + deletePostFromTopicUserNotification(postData), + deletePostFromCategoryRecentPosts(pid), + deletePostFromUsersBookmarks(pid), + deletePostFromUsersVotes(pid), + deletePostFromReplies(postData), + deletePostFromGroups(postData), + db.sortedSetsRemove(['posts:pid', 'posts:votes', 'posts:flagged'], pid), + ]); + plugins.fireHook('action:post.purge', { post: postData, uid: uid }); + await db.delete('post:' + pid); }; - function deletePostFromTopicUserNotification(postData, callback) { - async.waterfall([ - function (next) { - db.sortedSetsRemove([ - 'tid:' + postData.tid + ':posts', - 'tid:' + postData.tid + ':posts:votes', - 'uid:' + postData.uid + ':posts', - ], postData.pid, next); - }, - function (next) { - topics.getTopicFields(postData.tid, ['tid', 'cid', 'pinned'], next); - }, - function (topicData, next) { - const tasks = [ - async.apply(db.decrObjectField, 'global', 'postCount'), - async.apply(db.decrObjectField, 'category:' + topicData.cid, 'post_count'), - async.apply(db.sortedSetRemove, 'cid:' + topicData.cid + ':uid:' + postData.uid + ':pids', postData.pid), - async.apply(db.sortedSetRemove, 'cid:' + topicData.cid + ':uid:' + postData.uid + ':pids:votes', postData.pid), - async.apply(topics.decreasePostCount, postData.tid), - async.apply(topics.updateTeaser, postData.tid), - async.apply(topics.updateLastPostTimeFromLastPid, postData.tid), - async.apply(db.sortedSetIncrBy, 'tid:' + postData.tid + ':posters', -1, postData.uid), - async.apply(user.incrementUserPostCountBy, postData.uid, -1), - async.apply(notifications.rescind, 'new_post:tid:' + postData.tid + ':pid:' + postData.pid + ':uid:' + postData.uid), - ]; - if (!topicData.pinned) { - tasks.push(async.apply(db.sortedSetIncrBy, 'cid:' + topicData.cid + ':tids:posts', -1, postData.tid)); - } - async.parallel(tasks, next); - }, - ], function (err) { - callback(err); - }); + async function deletePostFromTopicUserNotification(postData) { + await db.sortedSetsRemove([ + 'tid:' + postData.tid + ':posts', + 'tid:' + postData.tid + ':posts:votes', + 'uid:' + postData.uid + ':posts', + ], postData.pid); + const topicData = await topics.getTopicFields(postData.tid, ['tid', 'cid', 'pinned']); + const tasks = [ + db.decrObjectField('global', 'postCount'), + db.decrObjectField('category:' + topicData.cid, 'post_count'), + db.sortedSetRemove('cid:' + topicData.cid + ':uid:' + postData.uid + ':pids', postData.pid), + db.sortedSetRemove('cid:' + topicData.cid + ':uid:' + postData.uid + ':pids:votes', postData.pid), + topics.decreasePostCount(postData.tid), + topics.updateTeaser(postData.tid), + topics.updateLastPostTimeFromLastPid(postData.tid), + db.sortedSetIncrBy('tid:' + postData.tid + ':posters', -1, postData.uid), + user.incrementUserPostCountBy(postData.uid, -1), + notifications.rescind('new_post:tid:' + postData.tid + ':pid:' + postData.pid + ':uid:' + postData.uid), + ]; + if (!topicData.pinned) { + tasks.push(db.sortedSetIncrBy, 'cid:' + topicData.cid + ':tids:posts', -1, postData.tid); + } + await Promise.all(tasks); } - function deletePostFromCategoryRecentPosts(pid, callback) { - async.waterfall([ - function (next) { - db.getSortedSetRange('categories:cid', 0, -1, next); - }, - function (cids, next) { - const sets = cids.map(cid => 'cid:' + cid + ':pids'); - db.sortedSetsRemove(sets, pid, next); - }, - ], callback); + async function deletePostFromCategoryRecentPosts(pid) { + const cids = await categories.getAllCidsFromSet('categories:cid'); + const sets = cids.map(cid => 'cid:' + cid + ':pids'); + await db.sortedSetsRemove(sets, pid); } - function deletePostFromUsersBookmarks(pid, callback) { - async.waterfall([ - function (next) { - db.getSetMembers('pid:' + pid + ':users_bookmarked', next); - }, - function (uids, next) { - const sets = uids.map(uid => 'uid:' + uid + ':bookmarks'); - db.sortedSetsRemove(sets, pid, next); - }, - function (next) { - db.delete('pid:' + pid + ':users_bookmarked', next); - }, - ], callback); + async function deletePostFromUsersBookmarks(pid) { + const uids = await db.getSetMembers('pid:' + pid + ':users_bookmarked'); + const sets = uids.map(uid => 'uid:' + uid + ':bookmarks'); + await db.sortedSetsRemove(sets, pid); + await db.delete('pid:' + pid + ':users_bookmarked'); } - function deletePostFromUsersVotes(pid, callback) { - async.waterfall([ - function (next) { - async.parallel({ - upvoters: function (next) { - db.getSetMembers('pid:' + pid + ':upvote', next); - }, - downvoters: function (next) { - db.getSetMembers('pid:' + pid + ':downvote', next); - }, - }, next); - }, - function (results, next) { - async.parallel([ - function (next) { - const upvoterSets = results.upvoters.map(uid => 'uid:' + uid + ':upvote'); - const downvoterSets = results.downvoters.map(uid => 'uid:' + uid + ':downvote'); - db.sortedSetsRemove(upvoterSets.concat(downvoterSets), pid, next); - }, - function (next) { - db.deleteAll(['pid:' + pid + ':upvote', 'pid:' + pid + ':downvote'], next); - }, - ], next); - }, - ], callback); + async function deletePostFromUsersVotes(pid) { + const [upvoters, downvoters] = await Promise.all([ + db.getSetMembers('pid:' + pid + ':upvote'), + db.getSetMembers('pid:' + pid + ':downvote'), + ]); + const upvoterSets = upvoters.map(uid => 'uid:' + uid + ':upvote'); + const downvoterSets = downvoters.map(uid => 'uid:' + uid + ':downvote'); + await Promise.all([ + db.sortedSetsRemove(upvoterSets.concat(downvoterSets), pid), + db.deleteAll(['pid:' + pid + ':upvote', 'pid:' + pid + ':downvote']), + ]); } - function deletePostFromReplies(postData, callback) { + async function deletePostFromReplies(postData) { if (!parseInt(postData.toPid, 10)) { - return setImmediate(callback); + return; } - async.parallel([ - async.apply(db.sortedSetRemove, 'pid:' + postData.toPid + ':replies', postData.pid), - async.apply(db.decrObjectField, 'post:' + postData.toPid, 'replies'), - ], callback); + await Promise.all([ + db.sortedSetRemove('pid:' + postData.toPid + ':replies', postData.pid), + db.decrObjectField('post:' + postData.toPid, 'replies'), + ]); } - function deletePostFromGroups(postData, callback) { + async function deletePostFromGroups(postData) { if (!parseInt(postData.uid, 10)) { - return setImmediate(callback); + return; } - async.waterfall([ - function (next) { - groups.getUserGroupMembership('groups:visible:createtime', [postData.uid], next); - }, - function (groupNames, next) { - groupNames = groupNames[0]; - const keys = groupNames.map(groupName => 'group:' + groupName + ':member:pids'); - db.sortedSetsRemove(keys, postData.pid, next); - }, - ], callback); + const groupNames = await groups.getUserGroupMembership('groups:visible:createtime', [postData.uid]); + const keys = groupNames[0].map(groupName => 'group:' + groupName + ':member:pids'); + await db.sortedSetsRemove(keys, postData.pid); } }; diff --git a/test/posts.js b/test/posts.js index 211cc0f9b0..72c49af7fb 100644 --- a/test/posts.js +++ b/test/posts.js @@ -901,6 +901,14 @@ describe('Post\'s', function () { done(); }); }); + + it('should filter pids by multiple cids', function (done) { + posts.filterPidsByCid([postData.pid, 100, 101], [cid], function (err, pids) { + assert.ifError(err); + assert.deepEqual([postData.pid], pids); + done(); + }); + }); }); it('should error if user does not exist', function (done) {