From 3a9d83a44bf3c9378c3cedf1670e2d3ff5d7496f Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Wed, 31 Jul 2019 12:39:15 -0400 Subject: [PATCH] feat: async refactor --- src/controllers/composer.js | 130 +++++++++++--------------- src/controllers/home.js | 76 +++++++-------- src/controllers/popular.js | 52 +++++------ src/controllers/recent.js | 180 ++++++++++++++---------------------- src/controllers/top.js | 47 ++++------ 5 files changed, 201 insertions(+), 284 deletions(-) diff --git a/src/controllers/composer.js b/src/controllers/composer.js index 93263d2ed0..baec8b62f6 100644 --- a/src/controllers/composer.js +++ b/src/controllers/composer.js @@ -1,46 +1,40 @@ 'use strict'; -var async = require('async'); -var nconf = require('nconf'); +const nconf = require('nconf'); -var user = require('../user'); -var plugins = require('../plugins'); -var topics = require('../topics'); -var posts = require('../posts'); -var helpers = require('./helpers'); +const user = require('../user'); +const plugins = require('../plugins'); +const topics = require('../topics'); +const posts = require('../posts'); +const helpers = require('./helpers'); -exports.get = function (req, res, callback) { +exports.get = async function (req, res, callback) { res.locals.metaTags = { ...res.locals.metaTags, name: 'robots', content: 'noindex', }; - async.waterfall([ - function (next) { - plugins.fireHook('filter:composer.build', { - req: req, - res: res, - next: callback, - templateData: {}, - }, next); - }, - function (data) { - if (data.templateData.disabled) { - res.render('', { - title: '[[modules:composer.compose]]', - }); - } else { - data.templateData.title = '[[modules:composer.compose]]'; - res.render('compose', data.templateData); - } - }, - ], callback); + const data = await plugins.fireHook('filter:composer.build', { + req: req, + res: res, + next: callback, + templateData: {}, + }); + + if (data.templateData.disabled) { + res.render('', { + title: '[[modules:composer.compose]]', + }); + } else { + data.templateData.title = '[[modules:composer.compose]]'; + res.render('compose', data.templateData); + } }; -exports.post = function (req, res) { - var body = req.body; - var data = { +exports.post = async function (req, res) { + const body = req.body; + const data = { uid: req.uid, req: req, timestamp: Date.now(), @@ -52,49 +46,37 @@ exports.post = function (req, res) { if (!data.content) { return helpers.noScriptErrors(req, res, '[[error:invalid-data]]', 400); } - - async.waterfall([ - function (next) { - function queueOrPost(postFn, data, next) { - async.waterfall([ - function (next) { - posts.shouldQueue(req.uid, data, next); - }, - function (shouldQueue, next) { - if (shouldQueue) { - delete data.req; - posts.addToQueue(data, next); - } else { - postFn(data, next); - } - }, - ], next); - } - if (body.tid) { - data.tid = body.tid; - queueOrPost(topics.reply, data, next); - } else if (body.cid) { - data.cid = body.cid; - data.title = body.title; - data.tags = []; - data.thumb = ''; - queueOrPost(topics.post, data, next); - } else { - next(new Error('[[error:invalid-data]]')); - } - }, - function (result, next) { - if (result.queued) { - return res.redirect((nconf.get('relative_path') || '/')); - } - var uid = result.uid ? result.uid : result.topicData.uid; - user.updateOnlineUsers(uid); - next(null, result.pid ? '/post/' + result.pid : '/topic/' + result.topicData.slug); - }, - ], function (err, path) { - if (err) { - return helpers.noScriptErrors(req, res, err.message, 400); + async function queueOrPost(postFn, data) { + const shouldQueue = await posts.shouldQueue(req.uid, data); + if (shouldQueue) { + delete data.req; + return await posts.addToQueue(data); } + return await postFn(data); + } + + try { + let result; + if (body.tid) { + data.tid = body.tid; + result = await queueOrPost(topics.reply, data); + } else if (body.cid) { + data.cid = body.cid; + data.title = body.title; + data.tags = []; + data.thumb = ''; + result = await queueOrPost(topics.post, data); + } else { + throw new Error('[[error:invalid-data]]'); + } + if (result.queued) { + return res.redirect((nconf.get('relative_path') || '/')); + } + const uid = result.uid ? result.uid : result.topicData.uid; + user.updateOnlineUsers(uid); + const path = result.pid ? '/post/' + result.pid : '/topic/' + result.topicData.slug; res.redirect(nconf.get('relative_path') + path); - }); + } catch (err) { + helpers.noScriptErrors(req, res, err.message, 400); + } }; diff --git a/src/controllers/home.js b/src/controllers/home.js index a97b391052..e882f57e21 100644 --- a/src/controllers/home.js +++ b/src/controllers/home.js @@ -1,66 +1,52 @@ 'use strict'; -var async = require('async'); -var url = require('url'); +const url = require('url'); -var plugins = require('../plugins'); -var meta = require('../meta'); -var user = require('../user'); +const plugins = require('../plugins'); +const meta = require('../meta'); +const user = require('../user'); function adminHomePageRoute() { return (meta.config.homePageRoute || meta.config.homePageCustom || '').replace(/^\/+/, '') || 'categories'; } -function getUserHomeRoute(uid, callback) { - async.waterfall([ - function (next) { - user.getSettings(uid, next); - }, - function (settings, next) { - var route = adminHomePageRoute(); +async function getUserHomeRoute(uid) { + const settings = await user.getSettings(uid); + let route = adminHomePageRoute(); - if (settings.homePageRoute !== 'undefined' && settings.homePageRoute !== 'none') { - route = (settings.homePageRoute || route).replace(/^\/+/, ''); - } + if (settings.homePageRoute !== 'undefined' && settings.homePageRoute !== 'none') { + route = (settings.homePageRoute || route).replace(/^\/+/, ''); + } - next(null, route); - }, - ], callback); + return route; } -function rewrite(req, res, next) { +async function rewrite(req, res, next) { if (req.path !== '/' && req.path !== '/api/' && req.path !== '/api') { return next(); } + let route = adminHomePageRoute(); + if (meta.config.allowUserHomePage) { + route = await getUserHomeRoute(req.uid, next); + } - async.waterfall([ - function (next) { - if (meta.config.allowUserHomePage) { - getUserHomeRoute(req.uid, next); - } else { - next(null, adminHomePageRoute()); - } - }, - function (route, next) { - var parsedUrl; - try { - parsedUrl = url.parse(route, true); - } catch (err) { - return next(err); - } + let parsedUrl; + try { + parsedUrl = url.parse(route, true); + } catch (err) { + return next(err); + } - var pathname = parsedUrl.pathname; - var hook = 'action:homepage.get:' + pathname; - if (!plugins.hasListeners(hook)) { - req.url = req.path + (!req.path.endsWith('/') ? '/' : '') + pathname; - } else { - res.locals.homePageRoute = pathname; - } - req.query = Object.assign(parsedUrl.query, req.query); + const pathname = parsedUrl.pathname; + const hook = 'action:homepage.get:' + pathname; + if (!plugins.hasListeners(hook)) { + req.url = req.path + (!req.path.endsWith('/') ? '/' : '') + pathname; + } else { + res.locals.homePageRoute = pathname; + } + req.query = Object.assign(parsedUrl.query, req.query); - next(); - }, - ], next); + next(); } exports.rewrite = rewrite; diff --git a/src/controllers/popular.js b/src/controllers/popular.js index 138fc11817..371eb5f42d 100644 --- a/src/controllers/popular.js +++ b/src/controllers/popular.js @@ -1,36 +1,30 @@ 'use strict'; -var async = require('async'); -var nconf = require('nconf'); -var validator = require('validator'); +const nconf = require('nconf'); +const validator = require('validator'); -var helpers = require('./helpers'); -var recentController = require('./recent'); +const helpers = require('./helpers'); +const recentController = require('./recent'); -var popularController = module.exports; +const popularController = module.exports; -popularController.get = function (req, res, next) { - async.waterfall([ - function (next) { - recentController.getData(req, 'popular', 'posts', next); - }, - function (data, next) { - if (!data) { - return next(); - } - var term = helpers.terms[req.query.term] || 'alltime'; - if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/popular') || req.originalUrl.startsWith(nconf.get('relative_path') + '/popular')) { - data.title = '[[pages:popular-' + term + ']]'; - var breadcrumbs = [{ text: '[[global:header.popular]]' }]; - data.breadcrumbs = helpers.buildBreadcrumbs(breadcrumbs); - } - var feedQs = data.rssFeedUrl.split('?')[1]; - data.rssFeedUrl = nconf.get('relative_path') + '/popular/' + (validator.escape(String(req.query.term)) || 'alltime') + '.rss'; - if (req.loggedIn) { - data.rssFeedUrl += '?' + feedQs; - } - res.render('popular', data); - }, - ], next); +popularController.get = async function (req, res, next) { + const data = await recentController.getData(req, 'popular', 'posts'); + if (!data) { + return next(); + } + const term = helpers.terms[req.query.term] || 'alltime'; + if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/popular') || req.originalUrl.startsWith(nconf.get('relative_path') + '/popular')) { + data.title = '[[pages:popular-' + term + ']]'; + const breadcrumbs = [{ text: '[[global:header.popular]]' }]; + data.breadcrumbs = helpers.buildBreadcrumbs(breadcrumbs); + } + + const feedQs = data.rssFeedUrl.split('?')[1]; + data.rssFeedUrl = nconf.get('relative_path') + '/popular/' + (validator.escape(String(req.query.term)) || 'alltime') + '.rss'; + if (req.loggedIn) { + data.rssFeedUrl += '?' + feedQs; + } + res.render('popular', data); }; diff --git a/src/controllers/recent.js b/src/controllers/recent.js index ed7f8e5ea4..a223924c75 100644 --- a/src/controllers/recent.js +++ b/src/controllers/recent.js @@ -1,131 +1,93 @@ 'use strict'; -var async = require('async'); -var nconf = require('nconf'); +const nconf = require('nconf'); -var user = require('../user'); -var categories = require('../categories'); -var topics = require('../topics'); -var meta = require('../meta'); -var helpers = require('./helpers'); -var pagination = require('../pagination'); -var privileges = require('../privileges'); +const user = require('../user'); +const categories = require('../categories'); +const topics = require('../topics'); +const meta = require('../meta'); +const helpers = require('./helpers'); +const pagination = require('../pagination'); +const privileges = require('../privileges'); -var recentController = module.exports; +const recentController = module.exports; -recentController.get = function (req, res, next) { - async.waterfall([ - function (next) { - recentController.getData(req, 'recent', 'recent', next); - }, - function (data, next) { - if (!data) { - return next(); - } - res.render('recent', data); - }, - ], next); +recentController.get = async function (req, res, next) { + const data = await recentController.getData(req, 'recent', 'recent'); + if (!data) { + return next(); + } + res.render('recent', data); }; -recentController.getData = function (req, url, sort, callback) { - var page = parseInt(req.query.page, 10) || 1; - var stop = 0; - var term = helpers.terms[req.query.term]; - var settings; - var cid = req.query.cid; - var filter = req.query.filter || ''; - var categoryData; - var rssToken; - var canPost; +recentController.getData = async function (req, url, sort) { + const page = parseInt(req.query.page, 10) || 1; + let term = helpers.terms[req.query.term]; + const cid = req.query.cid; + const filter = req.query.filter || ''; if (!helpers.validFilters[filter] || (!term && req.query.term)) { - return callback(null, null); + return null; } term = term || 'alltime'; - async.waterfall([ - function (next) { - async.parallel({ - settings: function (next) { - user.getSettings(req.uid, next); - }, - categories: function (next) { - const states = [categories.watchStates.watching, categories.watchStates.notwatching]; - if (filter === 'watched') { - states.push(categories.watchStates.ignoring); - } - helpers.getCategoriesByStates(req.uid, cid, states, next); - }, - rssToken: function (next) { - user.auth.getFeedToken(req.uid, next); - }, - canPost: function (next) { - canPostTopic(req.uid, next); - }, - }, next); - }, - function (results, next) { - rssToken = results.rssToken; - settings = results.settings; - categoryData = results.categories; - canPost = results.canPost; + const states = [categories.watchStates.watching, categories.watchStates.notwatching]; + if (filter === 'watched') { + states.push(categories.watchStates.ignoring); + } - var start = Math.max(0, (page - 1) * settings.topicsPerPage); - stop = start + settings.topicsPerPage - 1; + const [settings, categoryData, rssToken, canPost] = await Promise.all([ + user.getSettings(req.uid), + helpers.getCategoriesByStates(req.uid, cid, states), + user.auth.getFeedToken(req.uid), + canPostTopic(req.uid), + ]); - topics.getSortedTopics({ - cids: cid, - uid: req.uid, - start: start, - stop: stop, - filter: filter, - term: term, - sort: sort, - query: req.query, - }, next); - }, - function (data, next) { - data.canPost = canPost; - data.categories = categoryData.categories; - data.allCategoriesUrl = url + helpers.buildQueryString('', filter, ''); - data.selectedCategory = categoryData.selectedCategory; - data.selectedCids = categoryData.selectedCids; - data['feeds:disableRSS'] = meta.config['feeds:disableRSS']; - data.rssFeedUrl = nconf.get('relative_path') + '/' + url + '.rss'; - if (req.loggedIn) { - data.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken; - } - data.title = meta.config.homePageTitle || '[[pages:home]]'; + const start = Math.max(0, (page - 1) * settings.topicsPerPage); + const stop = start + settings.topicsPerPage - 1; - data.filters = helpers.buildFilters(url, filter, req.query); - data.selectedFilter = data.filters.find(filter => filter && filter.selected); - data.terms = helpers.buildTerms(url, term, req.query); - data.selectedTerm = data.terms.find(term => term && term.selected); + const data = await topics.getSortedTopics({ + cids: cid, + uid: req.uid, + start: start, + stop: stop, + filter: filter, + term: term, + sort: sort, + query: req.query, + }); - var pageCount = Math.max(1, Math.ceil(data.topicCount / settings.topicsPerPage)); - data.pagination = pagination.create(page, pageCount, req.query); + data.canPost = canPost; + data.categories = categoryData.categories; + data.allCategoriesUrl = url + helpers.buildQueryString('', filter, ''); + data.selectedCategory = categoryData.selectedCategory; + data.selectedCids = categoryData.selectedCids; + data['feeds:disableRSS'] = meta.config['feeds:disableRSS']; + data.rssFeedUrl = nconf.get('relative_path') + '/' + url + '.rss'; + if (req.loggedIn) { + data.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken; + } + data.title = meta.config.homePageTitle || '[[pages:home]]'; - if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/' + url) || req.originalUrl.startsWith(nconf.get('relative_path') + '/' + url)) { - data.title = '[[pages:' + url + ']]'; - data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[' + url + ':title]]' }]); - } + data.filters = helpers.buildFilters(url, filter, req.query); + data.selectedFilter = data.filters.find(filter => filter && filter.selected); + data.terms = helpers.buildTerms(url, term, req.query); + data.selectedTerm = data.terms.find(term => term && term.selected); - next(null, data); - }, - ], callback); + var pageCount = Math.max(1, Math.ceil(data.topicCount / settings.topicsPerPage)); + data.pagination = pagination.create(page, pageCount, req.query); + + if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/' + url) || req.originalUrl.startsWith(nconf.get('relative_path') + '/' + url)) { + data.title = '[[pages:' + url + ']]'; + data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[' + url + ':title]]' }]); + } + + return data; }; -function canPostTopic(uid, callback) { - async.waterfall([ - function (next) { - categories.getAllCidsFromSet('categories:cid', next); - }, - function (cids, next) { - privileges.categories.filterCids('topics:create', cids, uid, next); - }, - function (cids, next) { - next(null, cids.length > 0); - }, - ], callback); +async function canPostTopic(uid) { + let cids = await categories.getAllCidsFromSet('categories:cid'); + cids = await privileges.categories.filterCids('topics:create', cids, uid); + return cids.length > 0; } diff --git a/src/controllers/top.js b/src/controllers/top.js index 718d9cfa47..4a482baaf5 100644 --- a/src/controllers/top.js +++ b/src/controllers/top.js @@ -1,35 +1,28 @@ 'use strict'; -var async = require('async'); -var nconf = require('nconf'); -var validator = require('validator'); +const nconf = require('nconf'); +const validator = require('validator'); -var helpers = require('./helpers'); -var recentController = require('./recent'); +const helpers = require('./helpers'); +const recentController = require('./recent'); -var topController = module.exports; +const topController = module.exports; -topController.get = function (req, res, next) { - async.waterfall([ - function (next) { - recentController.getData(req, 'top', 'votes', next); - }, - function (data, next) { - if (!data) { - return next(); - } - var term = helpers.terms[req.query.term] || 'alltime'; - if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/top') || req.originalUrl.startsWith(nconf.get('relative_path') + '/top')) { - data.title = '[[pages:top-' + term + ']]'; - } +topController.get = async function (req, res, next) { + const data = await recentController.getData(req, 'top', 'votes'); + if (!data) { + return next(); + } + const term = helpers.terms[req.query.term] || 'alltime'; + if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/top') || req.originalUrl.startsWith(nconf.get('relative_path') + '/top')) { + data.title = '[[pages:top-' + term + ']]'; + } - var feedQs = data.rssFeedUrl.split('?')[1]; - data.rssFeedUrl = nconf.get('relative_path') + '/top/' + (validator.escape(String(req.query.term)) || 'alltime') + '.rss'; - if (req.loggedIn) { - data.rssFeedUrl += '?' + feedQs; - } - res.render('top', data); - }, - ], next); + const feedQs = data.rssFeedUrl.split('?')[1]; + data.rssFeedUrl = nconf.get('relative_path') + '/top/' + (validator.escape(String(req.query.term)) || 'alltime') + '.rss'; + if (req.loggedIn) { + data.rssFeedUrl += '?' + feedQs; + } + res.render('top', data); };