From 4541caa4f8036f206e14a790cbb49f10ee67dea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sat, 13 Jul 2019 17:23:31 -0400 Subject: [PATCH] feat: #7743 , user/block, user/categories --- src/user/blocks.js | 146 ++++++++++++++++------------------------- src/user/categories.js | 89 +++++++++---------------- 2 files changed, 87 insertions(+), 148 deletions(-) diff --git a/src/user/blocks.js b/src/user/blocks.js index a0a1b8ea44..c8fd75ed95 100644 --- a/src/user/blocks.js +++ b/src/user/blocks.js @@ -16,117 +16,84 @@ module.exports = function (User) { }), }; - User.blocks.is = function (targetUid, uid, callback) { - User.blocks.list(uid, function (err, blocks) { - callback(err, blocks.includes(parseInt(targetUid, 10))); - }); + User.blocks.is = async function (targetUid, uid) { + const blocks = await User.blocks.list(uid); + return blocks.includes(parseInt(targetUid, 10)); }; - User.blocks.can = function (callerUid, blockerUid, blockeeUid, callback) { + User.blocks.can = async function (callerUid, blockerUid, blockeeUid) { // Guests can't block if (blockerUid === 0 || blockeeUid === 0) { - return setImmediate(callback, new Error('[[error:cannot-block-guest]]')); + throw new Error('[[error:cannot-block-guest]]'); } else if (blockerUid === blockeeUid) { - return setImmediate(callback, new Error('[[error:cannot-block-self]]')); + throw new Error('[[error:cannot-block-self]]'); } // Administrators and global moderators cannot be blocked // Only admins/mods can block users as another user - async.waterfall([ - function (next) { - async.parallel({ - isCallerAdminOrMod: function (next) { - User.isAdminOrGlobalMod(callerUid, next); - }, - isBlockeeAdminOrMod: function (next) { - User.isAdminOrGlobalMod(blockeeUid, next); - }, - }, next); - }, - function (results, next) { - if (results.isBlockeeAdminOrMod) { - return callback(new Error('[[error:cannot-block-privileged]]')); - } - if (parseInt(callerUid, 10) !== parseInt(blockerUid, 10) && !results.isCallerAdminOrMod) { - return callback(new Error()); - } - - next(); - }, - ], callback); + const [isCallerAdminOrMod, isBlockeeAdminOrMod] = await Promise.all([ + User.isAdminOrGlobalMod(callerUid), + User.isAdminOrGlobalMod(blockeeUid), + ]); + if (isBlockeeAdminOrMod) { + throw new Error('[[error:cannot-block-privileged]]'); + } + if (parseInt(callerUid, 10) !== parseInt(blockerUid, 10) && !isCallerAdminOrMod) { + throw new Error(); + } }; - User.blocks.list = function (uid, callback) { + User.blocks.list = async function (uid) { if (User.blocks._cache.has(parseInt(uid, 10))) { - return setImmediate(callback, null, User.blocks._cache.get(parseInt(uid, 10))); + return User.blocks._cache.get(parseInt(uid, 10)); } - db.getSortedSetRange('uid:' + uid + ':blocked_uids', 0, -1, function (err, blocked) { - if (err) { - return callback(err); - } - - blocked = blocked.map(uid => parseInt(uid, 10)).filter(Boolean); - User.blocks._cache.set(parseInt(uid, 10), blocked); - callback(null, blocked); - }); + let blocked = await db.getSortedSetRange('uid:' + uid + ':blocked_uids', 0, -1); + blocked = blocked.map(uid => parseInt(uid, 10)).filter(Boolean); + User.blocks._cache.set(parseInt(uid, 10), blocked); + return blocked; }; pubsub.on('user:blocks:cache:del', function (uid) { User.blocks._cache.del(uid); }); - User.blocks.add = function (targetUid, uid, callback) { - async.waterfall([ - async.apply(User.blocks.applyChecks, true, targetUid, uid), - async.apply(db.sortedSetAdd.bind(db), 'uid:' + uid + ':blocked_uids', Date.now(), targetUid), - async.apply(User.incrementUserFieldBy, uid, 'blocksCount', 1), - function (_blank, next) { - User.blocks._cache.del(parseInt(uid, 10)); - pubsub.publish('user:blocks:cache:del', parseInt(uid, 10)); - setImmediate(next); - }, - ], callback); + User.blocks.add = async function (targetUid, uid) { + await User.blocks.applyChecks('block', targetUid, uid); + await db.sortedSetAdd('uid:' + uid + ':blocked_uids', Date.now(), targetUid); + await User.incrementUserFieldBy(uid, 'blocksCount', 1); + User.blocks._cache.del(parseInt(uid, 10)); + pubsub.publish('user:blocks:cache:del', parseInt(uid, 10)); }; - User.blocks.remove = function (targetUid, uid, callback) { - async.waterfall([ - async.apply(User.blocks.applyChecks, false, targetUid, uid), - async.apply(db.sortedSetRemove.bind(db), 'uid:' + uid + ':blocked_uids', targetUid), - async.apply(User.decrementUserFieldBy, uid, 'blocksCount', 1), - function (_blank, next) { - User.blocks._cache.del(parseInt(uid, 10)); - pubsub.publish('user:blocks:cache:del', parseInt(uid, 10)); - setImmediate(next); - }, - ], callback); + User.blocks.remove = async function (targetUid, uid) { + await User.blocks.applyChecks('unblock', targetUid, uid); + await db.sortedSetRemove('uid:' + uid + ':blocked_uids', targetUid); + await User.decrementUserFieldBy(uid, 'blocksCount', 1); + User.blocks._cache.del(parseInt(uid, 10)); + pubsub.publish('user:blocks:cache:del', parseInt(uid, 10)); }; - User.blocks.applyChecks = function (block, targetUid, uid, callback) { - User.blocks.can(uid, uid, targetUid, function (err) { - if (err) { - return callback(err); - } - - User.blocks.is(targetUid, uid, function (err, is) { - callback(err || (is === block ? new Error('[[error:already-' + (block ? 'blocked' : 'unblocked') + ']]') : null)); - }); - }); + User.blocks.applyChecks = async function (type, targetUid, uid) { + await User.blocks.can(uid, uid, targetUid); + const isBlock = type === 'block'; + const is = await User.blocks.is(targetUid, uid); + if (is === isBlock) { + throw new Error('[[error:already-' + (isBlock ? 'blocked' : 'unblocked') + ']]'); + } }; - User.blocks.filterUids = function (targetUid, uids, callback) { - async.filter(uids, function (uid, next) { - User.blocks.is(targetUid, uid, function (err, blocked) { - next(err, !blocked); - }); - }, callback); + User.blocks.filterUids = async function (targetUid, uids) { + return await async.filter(uids, async function (uid) { + const isBlocked = await User.blocks.is(targetUid, uid); + return !isBlocked; + }); }; - User.blocks.filter = function (uid, property, set, callback) { + User.blocks.filter = async function (uid, property, set) { // Given whatever is passed in, iterates through it, and removes entries made by blocked uids // property is optional - if (Array.isArray(property) && typeof set === 'function' && !callback) { - callback = set; + if (Array.isArray(property) && typeof set === 'undefined') { set = property; property = 'uid'; } @@ -139,20 +106,17 @@ module.exports = function (User) { const check = item.hasOwnProperty(property) ? item[property] : item; return ['number', 'string'].includes(typeof check); })) { - return callback(null, set); + return set; } const isPlain = typeof set[0] !== 'object'; - User.blocks.list(uid, function (err, blocked_uids) { - if (err) { - return callback(err); - } - - set = set.filter(function (item) { - return !blocked_uids.includes(parseInt(isPlain ? item : item[property], 10)); - }); + const blocked_uids = await User.blocks.list(uid); + const blockedSet = new Set(blocked_uids); - callback(null, set); + set = set.filter(function (item) { + return !blockedSet.has(parseInt(isPlain ? item : item[property], 10)); }); + + return set; }; }; diff --git a/src/user/categories.js b/src/user/categories.js index 23492d2b3b..0978eb9da5 100644 --- a/src/user/categories.js +++ b/src/user/categories.js @@ -1,89 +1,64 @@ 'use strict'; -const async = require('async'); const _ = require('lodash'); const db = require('../database'); const categories = require('../categories'); module.exports = function (User) { - User.setCategoryWatchState = function (uid, cid, state, callback) { + User.setCategoryWatchState = async function (uid, cid, state) { if (!(parseInt(uid, 10) > 0)) { - return setImmediate(callback); + return; } - const isStateValid = Object.keys(categories.watchStates).some(key => categories.watchStates[key] === parseInt(state, 10)); + const isStateValid = Object.values(categories.watchStates).includes(parseInt(state, 10)); if (!isStateValid) { - return setImmediate(callback, new Error('[[error:invalid-watch-state]]')); + throw new Error('[[error:invalid-watch-state]]'); } - async.waterfall([ - function (next) { - categories.exists(cid, next); - }, - function (exists, next) { - if (!exists) { - return next(new Error('[[error:no-category]]')); - } - - db.sortedSetAdd('cid:' + cid + ':uid:watch:state', state, uid, next); - }, - ], callback); + const exists = await categories.exists(cid); + if (!exists) { + throw new Error('[[error:no-category]]'); + } + await db.sortedSetAdd('cid:' + cid + ':uid:watch:state', state, uid); }; - User.getCategoryWatchState = function (uid, callback) { - if (parseInt(uid, 10) <= 0) { - return setImmediate(callback, null, {}); + User.getCategoryWatchState = async function (uid) { + if (!(parseInt(uid, 10) > 0)) { + return {}; } - let cids; - async.waterfall([ - function (next) { - categories.getAllCidsFromSet('categories:cid', next); - }, - function (_cids, next) { - cids = _cids; - categories.getWatchState(cids, uid, next); - }, - function (states, next) { - next(null, _.zipObject(cids, states)); - }, - ], callback); + const cids = await categories.getAllCidsFromSet('categories:cid'); + const states = await categories.getWatchState(cids, uid); + return _.zipObject(cids, states); }; - User.getIgnoredCategories = function (uid, callback) { - if (parseInt(uid, 10) <= 0) { - return setImmediate(callback, null, []); + User.getIgnoredCategories = async function (uid) { + if (!(parseInt(uid, 10) > 0)) { + return []; } - User.getCategoriesByStates(uid, [categories.watchStates.ignoring], callback); + return await User.getCategoriesByStates(uid, [categories.watchStates.ignoring]); }; - User.getWatchedCategories = function (uid, callback) { - if (parseInt(uid, 10) <= 0) { - return setImmediate(callback, null, []); + User.getWatchedCategories = async function (uid) { + if (!(parseInt(uid, 10) > 0)) { + return []; } - User.getCategoriesByStates(uid, [categories.watchStates.watching], callback); + return await User.getCategoriesByStates(uid, [categories.watchStates.watching]); }; - User.getCategoriesByStates = function (uid, states, callback) { + User.getCategoriesByStates = async function (uid, states) { if (!(parseInt(uid, 10) > 0)) { - return categories.getAllCidsFromSet('categories:cid', callback); + return await categories.getAllCidsFromSet('categories:cid'); } - - async.waterfall([ - function (next) { - User.getCategoryWatchState(uid, next); - }, - function (userState, next) { - const cids = Object.keys(userState); - next(null, cids.filter(cid => states.includes(userState[cid]))); - }, - ], callback); + const userState = await User.getCategoryWatchState(uid); + const cids = Object.keys(userState); + return cids.filter(cid => states.includes(userState[cid])); }; - User.ignoreCategory = function (uid, cid, callback) { - User.setCategoryWatchState(uid, cid, categories.watchStates.ignoring, callback); + User.ignoreCategory = async function (uid, cid) { + await User.setCategoryWatchState(uid, cid, categories.watchStates.ignoring); }; - User.watchCategory = function (uid, cid, callback) { - User.setCategoryWatchState(uid, cid, categories.watchStates.watching, callback); + User.watchCategory = async function (uid, cid) { + await User.setCategoryWatchState(uid, cid, categories.watchStates.watching); }; };