chore: eslint prefer-template

v1.18.x
Peter Jaszkowiak 4 years ago committed by Julian Lam
parent 4ee0f1459d
commit 707b55b6a5

@ -111,7 +111,6 @@
"prefer-rest-params": "off", "prefer-rest-params": "off",
"prefer-spread": "off", "prefer-spread": "off",
"prefer-arrow-callback": "off", "prefer-arrow-callback": "off",
"prefer-template": "off",
"no-var": "off", "no-var": "off",
"vars-on-top": "off", "vars-on-top": "off",

@ -53,22 +53,22 @@ module.exports = function (grunt) {
} }
} }
const styleUpdated_Client = plugins.map(p => 'node_modules/' + p + '/*.less') const styleUpdated_Client = plugins.map(p => `node_modules/${p}/*.less`)
.concat(plugins.map(p => 'node_modules/' + p + '/*.css')) .concat(plugins.map(p => `node_modules/${p}/*.css`))
.concat(plugins.map(p => 'node_modules/' + p + '/+(public|static|less)/**/*.less')) .concat(plugins.map(p => `node_modules/${p}/+(public|static|less)/**/*.less`))
.concat(plugins.map(p => 'node_modules/' + p + '/+(public|static)/**/*.css')); .concat(plugins.map(p => `node_modules/${p}/+(public|static)/**/*.css`));
const styleUpdated_Admin = plugins.map(p => 'node_modules/' + p + '/*.less') const styleUpdated_Admin = plugins.map(p => `node_modules/${p}/*.less`)
.concat(plugins.map(p => 'node_modules/' + p + '/*.css')) .concat(plugins.map(p => `node_modules/${p}/*.css`))
.concat(plugins.map(p => 'node_modules/' + p + '/+(public|static|less)/**/*.less')) .concat(plugins.map(p => `node_modules/${p}/+(public|static|less)/**/*.less`))
.concat(plugins.map(p => 'node_modules/' + p + '/+(public|static)/**/*.css')); .concat(plugins.map(p => `node_modules/${p}/+(public|static)/**/*.css`));
const clientUpdated = plugins.map(p => 'node_modules/' + p + '/+(public|static)/**/*.js'); const clientUpdated = plugins.map(p => `node_modules/${p}/+(public|static)/**/*.js`);
const serverUpdated = plugins.map(p => 'node_modules/' + p + '/*.js') const serverUpdated = plugins.map(p => `node_modules/${p}/*.js`)
.concat(plugins.map(p => 'node_modules/' + p + '/+(lib|src)/**/*.js')); .concat(plugins.map(p => `node_modules/${p}/+(lib|src)/**/*.js`));
const templatesUpdated = plugins.map(p => 'node_modules/' + p + '/+(public|static|templates)/**/*.tpl'); const templatesUpdated = plugins.map(p => `node_modules/${p}/+(public|static|templates)/**/*.tpl`);
const langUpdated = plugins.map(p => 'node_modules/' + p + '/+(public|static|languages)/**/*.json'); const langUpdated = plugins.map(p => `node_modules/${p}/+(public|static|languages)/**/*.json`);
grunt.config(['watch'], { grunt.config(['watch'], {
styleUpdated_Client: { styleUpdated_Client: {
@ -202,7 +202,7 @@ function addBaseThemes(plugins) {
let baseTheme; let baseTheme;
do { do {
try { try {
baseTheme = require(themeId + '/theme').baseTheme; baseTheme = require(`${themeId}/theme`).baseTheme;
} catch (err) { } catch (err) {
console.log(err); console.log(err);
} }

@ -49,7 +49,7 @@ winston.verbose('* using configuration stored in: %s', configFile);
if (!process.send) { if (!process.send) {
// If run using `node app`, log GNU copyright info along with server info // If run using `node app`, log GNU copyright info along with server info
winston.info('NodeBB v' + nconf.get('version') + ' Copyright (C) 2013-' + (new Date()).getFullYear() + ' NodeBB Inc.'); winston.info(`NodeBB v${nconf.get('version')} Copyright (C) 2013-${(new Date()).getFullYear()} NodeBB Inc.`);
winston.info('This program comes with ABSOLUTELY NO WARRANTY.'); winston.info('This program comes with ABSOLUTELY NO WARRANTY.');
winston.info('This is free software, and you are welcome to redistribute it under certain conditions.'); winston.info('This is free software, and you are welcome to redistribute it under certain conditions.');
winston.info(''); winston.info('');

@ -14,7 +14,7 @@ const questions = {
}; };
module.exports = async function (config) { module.exports = async function (config) {
winston.info('\nNow configuring ' + config.database + ' database:'); winston.info(`\nNow configuring ${config.database} database:`);
const databaseConfig = await getDatabaseConfig(config); const databaseConfig = await getDatabaseConfig(config);
return saveDatabaseConfig(config, databaseConfig); return saveDatabaseConfig(config, databaseConfig);
}; };
@ -40,7 +40,7 @@ async function getDatabaseConfig(config) {
} }
return await promptGet(questions.postgres); return await promptGet(questions.postgres);
} }
throw new Error('unknown database : ' + config.database); throw new Error(`unknown database : ${config.database}`);
} }
function saveDatabaseConfig(config, databaseConfig) { function saveDatabaseConfig(config, databaseConfig) {
@ -79,7 +79,7 @@ function saveDatabaseConfig(config, databaseConfig) {
ssl: databaseConfig['postgres:ssl'], ssl: databaseConfig['postgres:ssl'],
}; };
} else { } else {
throw new Error('unknown database : ' + config.database); throw new Error(`unknown database : ${config.database}`);
} }
const allQuestions = questions.redis.concat(questions.mongo).concat(questions.postgres); const allQuestions = questions.redis.concat(questions.mongo).concat(questions.postgres);

@ -27,8 +27,8 @@ const formats = [
]; ];
const timestampFormat = winston.format((info) => { const timestampFormat = winston.format((info) => {
var dateString = new Date().toISOString() + ' [' + global.process.pid + ']'; var dateString = `${new Date().toISOString()} [${global.process.pid}]`;
info.level = dateString + ' - ' + info.level; info.level = `${dateString} - ${info.level}`;
return info; return info;
}); });
formats.push(timestampFormat()); formats.push(timestampFormat());
@ -69,7 +69,7 @@ const viewsDir = path.join(paths.baseDir, 'build/public/templates');
web.install = async function (port) { web.install = async function (port) {
port = port || 4567; port = port || 4567;
winston.info('Launching web installer on port ' + port); winston.info(`Launching web installer on port ${port}`);
app.use(express.static('public', {})); app.use(express.static('public', {}));
app.engine('tpl', function (filepath, options, callback) { app.engine('tpl', function (filepath, options, callback) {
@ -119,7 +119,7 @@ function ping(req, res) {
function welcome(req, res) { function welcome(req, res) {
var dbs = ['redis', 'mongo', 'postgres']; var dbs = ['redis', 'mongo', 'postgres'];
var databases = dbs.map(function (databaseName) { var databases = dbs.map(function (databaseName) {
var questions = require('../src/database/' + databaseName).questions.filter(function (question) { var questions = require(`../src/database/${databaseName}`).questions.filter(function (question) {
return question && !question.hideOnWebInstall; return question && !question.hideOnWebInstall;
}); });
@ -132,7 +132,7 @@ function welcome(req, res) {
var defaults = require('./data/defaults'); var defaults = require('./data/defaults');
res.render('install/index', { res.render('install/index', {
url: nconf.get('url') || (req.protocol + '://' + req.get('host')), url: nconf.get('url') || (`${req.protocol}://${req.get('host')}`),
launchUrl: launchUrl, launchUrl: launchUrl,
skipGeneralSetup: !!nconf.get('url'), skipGeneralSetup: !!nconf.get('url'),
databases: databases, databases: databases,
@ -161,7 +161,7 @@ function install(req, res) {
// Flatten any objects in setupEnvVars // Flatten any objects in setupEnvVars
const pushToRoot = function (parentKey, key) { const pushToRoot = function (parentKey, key) {
setupEnvVars[parentKey + '__' + key] = setupEnvVars[parentKey][key]; setupEnvVars[`${parentKey}__${key}`] = setupEnvVars[parentKey][key];
}; };
for (var j in setupEnvVars) { for (var j in setupEnvVars) {
if (setupEnvVars.hasOwnProperty(j) && typeof setupEnvVars[j] === 'object' && setupEnvVars[j] !== null && !Array.isArray(setupEnvVars[j])) { if (setupEnvVars.hasOwnProperty(j) && typeof setupEnvVars[j] === 'object' && setupEnvVars[j] !== null && !Array.isArray(setupEnvVars[j])) {
@ -258,7 +258,7 @@ async function compileLess() {
const css = await lessRenderAsync(style, { filename: path.resolve(installSrc) }); const css = await lessRenderAsync(style, { filename: path.resolve(installSrc) });
await fs.promises.writeFile(path.join(__dirname, '../public/installer.css'), css.css); await fs.promises.writeFile(path.join(__dirname, '../public/installer.css'), css.css);
} catch (err) { } catch (err) {
winston.error('Unable to compile LESS: \n' + err.stack); winston.error(`Unable to compile LESS: \n${err.stack}`);
throw err; throw err;
} }
} }

@ -40,7 +40,7 @@ Loader.init = function (callback) {
if (silent) { if (silent) {
console.log = function () { console.log = function () {
var args = Array.prototype.slice.call(arguments); var args = Array.prototype.slice.call(arguments);
output.write(args.join(' ') + '\n'); output.write(`${args.join(' ')}\n`);
}; };
} }
@ -51,7 +51,7 @@ Loader.init = function (callback) {
Loader.displayStartupMessages = function (callback) { Loader.displayStartupMessages = function (callback) {
console.log(''); console.log('');
console.log('NodeBB v' + pkg.version + ' Copyright (C) 2013-2014 NodeBB Inc.'); console.log(`NodeBB v${pkg.version} Copyright (C) 2013-2014 NodeBB Inc.`);
console.log('This program comes with ABSOLUTELY NO WARRANTY.'); console.log('This program comes with ABSOLUTELY NO WARRANTY.');
console.log('This is free software, and you are welcome to redistribute it under certain conditions.'); console.log('This is free software, and you are welcome to redistribute it under certain conditions.');
console.log('For the full license, please visit: http://www.gnu.org/copyleft/gpl.html'); console.log('For the full license, please visit: http://www.gnu.org/copyleft/gpl.html');
@ -71,12 +71,12 @@ Loader.addWorkerEvents = function (worker) {
Loader.timesStarted = 0; Loader.timesStarted = 0;
}, 10000); }, 10000);
} else { } else {
console.log((numProcs * 3) + ' restarts in 10 seconds, most likely an error on startup. Halting.'); console.log(`${numProcs * 3} restarts in 10 seconds, most likely an error on startup. Halting.`);
process.exit(); process.exit();
} }
} }
console.log('[cluster] Child Process (' + worker.pid + ') has exited (code: ' + code + ', signal: ' + signal + ')'); console.log(`[cluster] Child Process (${worker.pid}) has exited (code: ${code}, signal: ${signal})`);
if (!(worker.suicide || code === 0)) { if (!(worker.suicide || code === 0)) {
console.log('[cluster] Spinning up another process...'); console.log('[cluster] Spinning up another process...');
@ -110,7 +110,7 @@ Loader.addWorkerEvents = function (worker) {
Loader.start = function (callback) { Loader.start = function (callback) {
numProcs = getPorts().length; numProcs = getPorts().length;
console.log('Clustering enabled: Spinning up ' + numProcs + ' process(es).\n'); console.log(`Clustering enabled: Spinning up ${numProcs} process(es).\n`);
for (var x = 0; x < numProcs; x += 1) { for (var x = 0; x < numProcs; x += 1) {
forkWorker(x, x === 0); forkWorker(x, x === 0);
@ -126,7 +126,7 @@ function forkWorker(index, isPrimary) {
var args = []; var args = [];
if (!ports[index]) { if (!ports[index]) {
return console.log('[cluster] invalid port for worker : ' + index + ' ports: ' + ports.length); return console.log(`[cluster] invalid port for worker : ${index} ports: ${ports.length}`);
} }
process.env.isPrimary = isPrimary; process.env.isPrimary = isPrimary;

@ -59,13 +59,13 @@ function nsToTitle(namespace) {
const fallbackCache = {}; const fallbackCache = {};
async function initFallback(namespace) { async function initFallback(namespace) {
const template = await fs.promises.readFile(path.resolve(nconf.get('views_dir'), namespace + '.tpl'), 'utf8'); const template = await fs.promises.readFile(path.resolve(nconf.get('views_dir'), `${namespace}.tpl`), 'utf8');
var title = nsToTitle(namespace); var title = nsToTitle(namespace);
var translations = sanitize(template); var translations = sanitize(template);
translations = Translator.removePatterns(translations); translations = Translator.removePatterns(translations);
translations = simplify(translations); translations = simplify(translations);
translations += '\n' + title; translations += `\n${title}`;
return { return {
namespace: namespace, namespace: namespace,
@ -107,16 +107,16 @@ async function buildNamespace(language, namespace) {
title = '[[admin/menu:dashboard]]'; title = '[[admin/menu:dashboard]]';
} else { } else {
title = title.match(/admin\/(.+?)\/(.+?)$/); title = title.match(/admin\/(.+?)\/(.+?)$/);
title = '[[admin/menu:section-' + title = `[[admin/menu:section-${
(title[1] === 'development' ? 'advanced' : title[1]) + title[1] === 'development' ? 'advanced' : title[1]
']]' + (title[2] ? (' > [[admin/menu:' + }]]${title[2] ? (` > [[admin/menu:${
title[1] + '/' + title[2] + ']]') : ''); title[1]}/${title[2]}]]`) : ''}`;
} }
title = await translator.translate(title); title = await translator.translate(title);
return { return {
namespace: namespace, namespace: namespace,
translations: str + '\n' + title, translations: `${str}\n${title}`,
title: title, title: title,
}; };
} catch (err) { } catch (err) {

@ -12,7 +12,7 @@ const isPrerelease = /^v?\d+\.\d+\.\d+-.+$/;
function getLatestVersion(callback) { function getLatestVersion(callback) {
const headers = { const headers = {
Accept: 'application/vnd.github.v3+json', Accept: 'application/vnd.github.v3+json',
'User-Agent': encodeURIComponent('NodeBB Admin Control Panel/' + meta.config.title), 'User-Agent': encodeURIComponent(`NodeBB Admin Control Panel/${meta.config.title}`),
}; };
if (versionCacheLastModified) { if (versionCacheLastModified) {

@ -131,7 +131,7 @@ Analytics.writeData = async function () {
if (Object.keys(counters).length > 0) { if (Object.keys(counters).length > 0) {
for (const key in counters) { for (const key in counters) {
if (counters.hasOwnProperty(key)) { if (counters.hasOwnProperty(key)) {
dbQueue.push(db.sortedSetIncrBy('analytics:' + key, counters[key], today.getTime())); dbQueue.push(db.sortedSetIncrBy(`analytics:${key}`, counters[key], today.getTime()));
delete counters[key]; delete counters[key];
} }
} }
@ -139,7 +139,7 @@ Analytics.writeData = async function () {
try { try {
await Promise.all(dbQueue); await Promise.all(dbQueue);
} catch (err) { } catch (err) {
winston.error('[analytics] Encountered error while writing analytics to data store\n' + err.stack); winston.error(`[analytics] Encountered error while writing analytics to data store\n${err.stack}`);
throw err; throw err;
} }
}; };
@ -147,7 +147,7 @@ Analytics.writeData = async function () {
Analytics.getHourlyStatsForSet = async function (set, hour, numHours) { Analytics.getHourlyStatsForSet = async function (set, hour, numHours) {
// Guard against accidental ommission of `analytics:` prefix // Guard against accidental ommission of `analytics:` prefix
if (!set.startsWith('analytics:')) { if (!set.startsWith('analytics:')) {
set = 'analytics:' + set; set = `analytics:${set}`;
} }
const terms = {}; const terms = {};
@ -180,7 +180,7 @@ Analytics.getHourlyStatsForSet = async function (set, hour, numHours) {
Analytics.getDailyStatsForSet = async function (set, day, numDays) { Analytics.getDailyStatsForSet = async function (set, day, numDays) {
// Guard against accidental ommission of `analytics:` prefix // Guard against accidental ommission of `analytics:` prefix
if (!set.startsWith('analytics:')) { if (!set.startsWith('analytics:')) {
set = 'analytics:' + set; set = `analytics:${set}`;
} }
const daysArr = []; const daysArr = [];
@ -218,10 +218,10 @@ Analytics.getSummary = async function () {
Analytics.getCategoryAnalytics = async function (cid) { Analytics.getCategoryAnalytics = async function (cid) {
return await utils.promiseParallel({ return await utils.promiseParallel({
'pageviews:hourly': Analytics.getHourlyStatsForSet('analytics:pageviews:byCid:' + cid, Date.now(), 24), 'pageviews:hourly': Analytics.getHourlyStatsForSet(`analytics:pageviews:byCid:${cid}`, Date.now(), 24),
'pageviews:daily': Analytics.getDailyStatsForSet('analytics:pageviews:byCid:' + cid, Date.now(), 30), 'pageviews:daily': Analytics.getDailyStatsForSet(`analytics:pageviews:byCid:${cid}`, Date.now(), 30),
'topics:daily': Analytics.getDailyStatsForSet('analytics:topics:byCid:' + cid, Date.now(), 7), 'topics:daily': Analytics.getDailyStatsForSet(`analytics:topics:byCid:${cid}`, Date.now(), 7),
'posts:daily': Analytics.getDailyStatsForSet('analytics:posts:byCid:' + cid, Date.now(), 7), 'posts:daily': Analytics.getDailyStatsForSet(`analytics:posts:byCid:${cid}`, Date.now(), 7),
}); });
}; };

@ -163,9 +163,9 @@ groupsAPI.leave = async function (caller, data) {
const username = await user.getUserField(data.uid, 'username'); const username = await user.getUserField(data.uid, 'username');
const notification = await notifications.create({ const notification = await notifications.create({
type: 'group-leave', type: 'group-leave',
bodyShort: '[[groups:membership.leave.notification_title, ' + username + ', ' + groupName + ']]', bodyShort: `[[groups:membership.leave.notification_title, ${username}, ${groupName}]]`,
nid: 'group:' + validator.escape(groupName) + ':uid:' + data.uid + ':group-leave', nid: `group:${validator.escape(groupName)}:uid:${data.uid}:group-leave`,
path: '/groups/' + slugify(groupName), path: `/groups/${slugify(groupName)}`,
from: data.uid, from: data.uid,
}); });
const uids = await groups.getOwners(groupName); const uids = await groups.getOwners(groupName);

@ -70,7 +70,7 @@ async function logTopicAction(action, req, tid, title) {
return; return;
} }
await events.log({ await events.log({
type: 'topic-' + action, type: `topic-${action}`,
uid: req.uid, uid: req.uid,
ip: req.ip, ip: req.ip,
tid: tid, tid: tid,
@ -88,7 +88,7 @@ exports.postCommand = async function (caller, command, eventName, notification,
} }
if (!data.room_id) { if (!data.room_id) {
throw new Error('[[error:invalid-room-id, ' + data.room_id + ' ]]'); throw new Error(`[[error:invalid-room-id, ${data.room_id} ]]`);
} }
const [exists, deleted] = await Promise.all([ const [exists, deleted] = await Promise.all([
posts.exists(data.pid), posts.exists(data.pid),
@ -111,7 +111,7 @@ exports.postCommand = async function (caller, command, eventName, notification,
filter:post.bookmark filter:post.bookmark
filter:post.unbookmark filter:post.unbookmark
*/ */
const filteredData = await plugins.hooks.fire('filter:post.' + command, { const filteredData = await plugins.hooks.fire(`filter:post.${command}`, {
data: data, data: data,
uid: caller.uid, uid: caller.uid,
}); });
@ -121,8 +121,8 @@ exports.postCommand = async function (caller, command, eventName, notification,
async function executeCommand(caller, command, eventName, notification, data) { async function executeCommand(caller, command, eventName, notification, data) {
const result = await posts[command](data.pid, caller.uid); const result = await posts[command](data.pid, caller.uid);
if (result && eventName) { if (result && eventName) {
websockets.in('uid_' + caller.uid).emit('posts.' + command, result); websockets.in(`uid_${caller.uid}`).emit(`posts.${command}`, result);
websockets.in(data.room_id).emit('event:' + eventName, result); websockets.in(data.room_id).emit(`event:${eventName}`, result);
} }
if (result && command === 'upvote') { if (result && command === 'upvote') {
socketHelpers.upvote(result, notification); socketHelpers.upvote(result, notification);

@ -50,13 +50,13 @@ postsAPI.edit = async function (caller, data) {
const contentLen = utils.stripHTMLTags(data.content).trim().length; const contentLen = utils.stripHTMLTags(data.content).trim().length;
if (data.title && data.title.length < meta.config.minimumTitleLength) { if (data.title && data.title.length < meta.config.minimumTitleLength) {
throw new Error('[[error:title-too-short, ' + meta.config.minimumTitleLength + ']]'); throw new Error(`[[error:title-too-short, ${meta.config.minimumTitleLength}]]`);
} else if (data.title && data.title.length > meta.config.maximumTitleLength) { } else if (data.title && data.title.length > meta.config.maximumTitleLength) {
throw new Error('[[error:title-too-long, ' + meta.config.maximumTitleLength + ']]'); throw new Error(`[[error:title-too-long, ${meta.config.maximumTitleLength}]]`);
} else if (meta.config.minimumPostLength !== 0 && contentLen < meta.config.minimumPostLength) { } else if (meta.config.minimumPostLength !== 0 && contentLen < meta.config.minimumPostLength) {
throw new Error('[[error:content-too-short, ' + meta.config.minimumPostLength + ']]'); throw new Error(`[[error:content-too-short, ${meta.config.minimumPostLength}]]`);
} else if (contentLen > meta.config.maximumPostLength) { } else if (contentLen > meta.config.maximumPostLength) {
throw new Error('[[error:content-too-long, ' + meta.config.maximumPostLength + ']]'); throw new Error(`[[error:content-too-long, ${meta.config.maximumPostLength}]]`);
} }
data.uid = caller.uid; data.uid = caller.uid;
@ -81,19 +81,19 @@ postsAPI.edit = async function (caller, data) {
returnData.topic = { ...postObj[0].topic, ...editResult.post.topic }; returnData.topic = { ...postObj[0].topic, ...editResult.post.topic };
if (!editResult.post.deleted) { if (!editResult.post.deleted) {
websockets.in('topic_' + editResult.topic.tid).emit('event:post_edited', editResult); websockets.in(`topic_${editResult.topic.tid}`).emit('event:post_edited', editResult);
return returnData; return returnData;
} }
const memberData = await groups.getMembersOfGroups([ const memberData = await groups.getMembersOfGroups([
'administrators', 'administrators',
'Global Moderators', 'Global Moderators',
'cid:' + editResult.topic.cid + ':privileges:moderate', `cid:${editResult.topic.cid}:privileges:moderate`,
'cid:' + editResult.topic.cid + ':privileges:groups:moderate', `cid:${editResult.topic.cid}:privileges:groups:moderate`,
]); ]);
const uids = _.uniq(_.flatten(memberData).concat(String(caller.uid))); const uids = _.uniq(_.flatten(memberData).concat(String(caller.uid)));
uids.forEach(uid => websockets.in('uid_' + uid).emit('event:post_edited', editResult)); uids.forEach(uid => websockets.in(`uid_${uid}`).emit('event:post_edited', editResult));
return returnData; return returnData;
}; };
@ -123,7 +123,7 @@ async function deleteOrRestore(caller, data, params) {
await deleteOrRestoreTopicOf(params.command, data.pid, caller); await deleteOrRestoreTopicOf(params.command, data.pid, caller);
} }
websockets.in('topic_' + postData.tid).emit(params.event, postData); websockets.in(`topic_${postData.tid}`).emit(params.event, postData);
await events.log({ await events.log({
type: params.type, type: params.type,
@ -165,7 +165,7 @@ postsAPI.purge = async function (caller, data) {
require('../posts/cache').del(data.pid); require('../posts/cache').del(data.pid);
await posts.purge(data.pid, caller.uid); await posts.purge(data.pid, caller.uid);
websockets.in('topic_' + postData.tid).emit('event:post_purged', postData); websockets.in(`topic_${postData.tid}`).emit('event:post_purged', postData);
const topicData = await topics.getTopicFields(postData.tid, ['title', 'cid']); const topicData = await topics.getTopicFields(postData.tid, ['title', 'cid']);
await events.log({ await events.log({
@ -295,5 +295,5 @@ postsAPI.restoreDiff = async (caller, data) => {
} }
const edit = await posts.diffs.restore(data.pid, data.since, caller.uid, apiHelpers.buildReqObject(caller)); const edit = await posts.diffs.restore(data.pid, data.since, caller.uid, apiHelpers.buildReqObject(caller));
websockets.in('topic_' + edit.topic.tid).emit('event:post_edited', edit); websockets.in(`topic_${edit.topic.tid}`).emit('event:post_edited', edit);
}; };

@ -117,7 +117,7 @@ usersAPI.updateSettings = async function (caller, data) {
acpLang: defaults.acpLang, acpLang: defaults.acpLang,
}; };
// load raw settings without parsing values to booleans // load raw settings without parsing values to booleans
const current = await db.getObject('user:' + data.uid + ':settings'); const current = await db.getObject(`user:${data.uid}:settings`);
const payload = { ...defaults, ...current, ...data.settings }; const payload = { ...defaults, ...current, ...data.settings };
delete payload.uid; delete payload.uid;
@ -144,10 +144,10 @@ usersAPI.follow = async function (caller, data) {
const userData = await user.getUserFields(caller.uid, ['username', 'userslug']); const userData = await user.getUserFields(caller.uid, ['username', 'userslug']);
const notifObj = await notifications.create({ const notifObj = await notifications.create({
type: 'follow', type: 'follow',
bodyShort: '[[notifications:user_started_following_you, ' + userData.username + ']]', bodyShort: `[[notifications:user_started_following_you, ${userData.username}]]`,
nid: 'follow:' + data.uid + ':uid:' + caller.uid, nid: `follow:${data.uid}:uid:${caller.uid}`,
from: caller.uid, from: caller.uid,
path: '/uid/' + data.uid + '/followers', path: `/uid/${data.uid}/followers`,
mergeId: 'notifications:user_started_following_you', mergeId: 'notifications:user_started_following_you',
}); });
if (!notifObj) { if (!notifObj) {
@ -173,13 +173,13 @@ usersAPI.ban = async function (caller, data) {
} }
const banData = await user.bans.ban(data.uid, data.until, data.reason); const banData = await user.bans.ban(data.uid, data.until, data.reason);
await db.setObjectField('uid:' + data.uid + ':ban:' + banData.timestamp, 'fromUid', caller.uid); await db.setObjectField(`uid:${data.uid}:ban:${banData.timestamp}`, 'fromUid', caller.uid);
if (!data.reason) { if (!data.reason) {
data.reason = await translator.translate('[[user:info.banned-no-reason]]'); data.reason = await translator.translate('[[user:info.banned-no-reason]]');
} }
sockets.in('uid_' + data.uid).emit('event:banned', { sockets.in(`uid_${data.uid}`).emit('event:banned', {
until: data.until, until: data.until,
reason: validator.escape(String(data.reason || '')), reason: validator.escape(String(data.reason || '')),
}); });
@ -213,7 +213,7 @@ usersAPI.unban = async function (caller, data) {
await user.bans.unban(data.uid); await user.bans.unban(data.uid);
sockets.in('uid_' + data.uid).emit('event:unbanned'); sockets.in(`uid_${data.uid}`).emit('event:unbanned');
await events.log({ await events.log({
type: 'user-unban', type: 'user-unban',

@ -41,7 +41,7 @@ exports.processSortedSet = async function (setKey, process, options) {
while (true) { while (true) {
/* eslint-disable no-await-in-loop */ /* eslint-disable no-await-in-loop */
const ids = await db['getSortedSetRange' + (options.withScores ? 'WithScores' : '')](setKey, start, stop); const ids = await db[`getSortedSetRange${options.withScores ? 'WithScores' : ''}`](setKey, start, stop);
if (!ids.length || options.doneIf(start, stop, ids)) { if (!ids.length || options.doneIf(start, stop, ids)) {
return; return;
} }

@ -40,12 +40,12 @@ module.exports = function (opts) {
if (!Array.isArray(keys)) { if (!Array.isArray(keys)) {
keys = [keys]; keys = [keys];
} }
pubsub.publish(cache.name + ':cache:del', keys); pubsub.publish(`${cache.name}:cache:del`, keys);
keys.forEach(key => cacheDel.apply(cache, [key])); keys.forEach(key => cacheDel.apply(cache, [key]));
}; };
cache.reset = function () { cache.reset = function () {
pubsub.publish(cache.name + ':cache:reset'); pubsub.publish(`${cache.name}:cache:reset`);
localReset(); localReset();
}; };
@ -55,11 +55,11 @@ module.exports = function (opts) {
cache.misses = 0; cache.misses = 0;
} }
pubsub.on(cache.name + ':cache:reset', function () { pubsub.on(`${cache.name}:cache:reset`, function () {
localReset(); localReset();
}); });
pubsub.on(cache.name + ':cache:del', function (keys) { pubsub.on(`${cache.name}:cache:del`, function (keys) {
if (Array.isArray(keys)) { if (Array.isArray(keys)) {
keys.forEach(key => cacheDel.apply(cache, [key])); keys.forEach(key => cacheDel.apply(cache, [key]));
} }

@ -10,7 +10,7 @@ module.exports = function (Categories) {
if (!Array.isArray(cids)) { if (!Array.isArray(cids)) {
cids = [cids]; cids = [cids];
} }
const pids = await db.getSortedSetRevRange(cids.map(cid => 'cid:' + cid + ':pids'), 0, 24); const pids = await db.getSortedSetRevRange(cids.map(cid => `cid:${cid}:pids`), 0, 24);
const postData = await posts.getPostsFields(pids, ['uid']); const postData = await posts.getPostsFields(pids, ['uid']);
return _.uniq(postData.map(post => post.uid).filter(uid => uid)); return _.uniq(postData.map(post => post.uid).filter(uid => uid));
}; };

@ -15,8 +15,8 @@ module.exports = function (Categories) {
const parentCid = data.parentCid ? data.parentCid : 0; const parentCid = data.parentCid ? data.parentCid : 0;
const cid = await db.incrObjectField('global', 'nextCid'); const cid = await db.incrObjectField('global', 'nextCid');
data.name = String(data.name || 'Category ' + cid); data.name = String(data.name || `Category ${cid}`);
const slug = cid + '/' + slugify(data.name); const slug = `${cid}/${slugify(data.name)}`;
const order = data.order || cid; // If no order provided, place it at the end const order = data.order || cid; // If no order provided, place it at the end
const colours = Categories.assignColours(); const colours = Categories.assignColours();
@ -50,15 +50,15 @@ module.exports = function (Categories) {
category = result.category; category = result.category;
await db.setObject('category:' + category.cid, category); await db.setObject(`category:${category.cid}`, category);
if (!category.descriptionParsed) { if (!category.descriptionParsed) {
await Categories.parseDescription(category.cid, category.description); await Categories.parseDescription(category.cid, category.description);
} }
await db.sortedSetAddBulk([ await db.sortedSetAddBulk([
['categories:cid', category.order, category.cid], ['categories:cid', category.order, category.cid],
['cid:' + parentCid + ':children', category.order, category.cid], [`cid:${parentCid}:children`, category.order, category.cid],
['categories:name', 0, data.name.substr(0, 200).toLowerCase() + ':' + category.cid], ['categories:name', 0, `${data.name.substr(0, 200).toLowerCase()}:${category.cid}`],
]); ]);
const defaultPrivileges = [ const defaultPrivileges = [
@ -83,7 +83,7 @@ module.exports = function (Categories) {
await privileges.categories.give(modPrivileges, category.cid, ['administrators', 'Global Moderators']); await privileges.categories.give(modPrivileges, category.cid, ['administrators', 'Global Moderators']);
await privileges.categories.give(['groups:find', 'groups:read', 'groups:topics:read'], category.cid, ['guests', 'spiders']); await privileges.categories.give(['groups:find', 'groups:read', 'groups:topics:read'], category.cid, ['guests', 'spiders']);
cache.del(['categories:cid', 'cid:' + parentCid + ':children']); cache.del(['categories:cid', `cid:${parentCid}:children`]);
if (data.cloneFromCid && parseInt(data.cloneFromCid, 10)) { if (data.cloneFromCid && parseInt(data.cloneFromCid, 10)) {
category = await Categories.copySettingsFrom(data.cloneFromCid, category.cid, !data.parentCid); category = await Categories.copySettingsFrom(data.cloneFromCid, category.cid, !data.parentCid);
} }
@ -125,8 +125,8 @@ module.exports = function (Categories) {
Categories.copySettingsFrom = async function (fromCid, toCid, copyParent) { Categories.copySettingsFrom = async function (fromCid, toCid, copyParent) {
const [source, destination] = await Promise.all([ const [source, destination] = await Promise.all([
db.getObject('category:' + fromCid), db.getObject(`category:${fromCid}`),
db.getObject('category:' + toCid), db.getObject(`category:${toCid}`),
]); ]);
if (!source) { if (!source) {
throw new Error('[[error:invalid-cid]]'); throw new Error('[[error:invalid-cid]]');
@ -135,9 +135,9 @@ module.exports = function (Categories) {
const oldParent = parseInt(destination.parentCid, 10) || 0; const oldParent = parseInt(destination.parentCid, 10) || 0;
const newParent = parseInt(source.parentCid, 10) || 0; const newParent = parseInt(source.parentCid, 10) || 0;
if (copyParent && newParent !== parseInt(toCid, 10)) { if (copyParent && newParent !== parseInt(toCid, 10)) {
await db.sortedSetRemove('cid:' + oldParent + ':children', toCid); await db.sortedSetRemove(`cid:${oldParent}:children`, toCid);
await db.sortedSetAdd('cid:' + newParent + ':children', source.order, toCid); await db.sortedSetAdd(`cid:${newParent}:children`, source.order, toCid);
cache.del(['cid:' + oldParent + ':children', 'cid:' + newParent + ':children']); cache.del([`cid:${oldParent}:children`, `cid:${newParent}:children`]);
} }
destination.description = source.description; destination.description = source.description;
@ -157,7 +157,7 @@ module.exports = function (Categories) {
destination.parentCid = source.parentCid || 0; destination.parentCid = source.parentCid || 0;
} }
await db.setObject('category:' + toCid, destination); await db.setObject(`category:${toCid}`, destination);
await copyTagWhitelist(fromCid, toCid); await copyTagWhitelist(fromCid, toCid);
@ -167,10 +167,10 @@ module.exports = function (Categories) {
}; };
async function copyTagWhitelist(fromCid, toCid) { async function copyTagWhitelist(fromCid, toCid) {
const data = await db.getSortedSetRangeWithScores('cid:' + fromCid + ':tag:whitelist', 0, -1); const data = await db.getSortedSetRangeWithScores(`cid:${fromCid}:tag:whitelist`, 0, -1);
await db.delete('cid:' + toCid + ':tag:whitelist'); await db.delete(`cid:${toCid}:tag:whitelist`);
await db.sortedSetAdd('cid:' + toCid + ':tag:whitelist', data.map(item => item.score), data.map(item => item.value)); await db.sortedSetAdd(`cid:${toCid}:tag:whitelist`, data.map(item => item.score), data.map(item => item.value));
cache.del('cid:' + toCid + ':tag:whitelist'); cache.del(`cid:${toCid}:tag:whitelist`);
} }
Categories.copyPrivilegesFrom = async function (fromCid, toCid, group) { Categories.copyPrivilegesFrom = async function (fromCid, toCid, group) {
@ -190,8 +190,8 @@ module.exports = function (Categories) {
}; };
async function copyPrivileges(privileges, fromCid, toCid) { async function copyPrivileges(privileges, fromCid, toCid) {
const toGroups = privileges.map(privilege => 'group:cid:' + toCid + ':privileges:' + privilege + ':members'); const toGroups = privileges.map(privilege => `group:cid:${toCid}:privileges:${privilege}:members`);
const fromGroups = privileges.map(privilege => 'group:cid:' + fromCid + ':privileges:' + privilege + ':members'); const fromGroups = privileges.map(privilege => `group:cid:${fromCid}:privileges:${privilege}:members`);
const currentMembers = await db.getSortedSetsMembers(toGroups.concat(fromGroups)); const currentMembers = await db.getSortedSetsMembers(toGroups.concat(fromGroups));
const copyGroups = _.uniq(_.flatten(currentMembers)); const copyGroups = _.uniq(_.flatten(currentMembers));
@ -201,8 +201,8 @@ module.exports = function (Categories) {
} }
async function copyPrivilegesByGroup(privilegeList, fromCid, toCid, group) { async function copyPrivilegesByGroup(privilegeList, fromCid, toCid, group) {
const fromGroups = privilegeList.map(privilege => 'group:cid:' + fromCid + ':privileges:' + privilege + ':members'); const fromGroups = privilegeList.map(privilege => `group:cid:${fromCid}:privileges:${privilege}:members`);
const toGroups = privilegeList.map(privilege => 'group:cid:' + toCid + ':privileges:' + privilege + ':members'); const toGroups = privilegeList.map(privilege => `group:cid:${toCid}:privileges:${privilege}:members`);
const [fromChecks, toChecks] = await Promise.all([ const [fromChecks, toChecks] = await Promise.all([
db.isMemberOfSortedSets(fromGroups, group), db.isMemberOfSortedSets(fromGroups, group),
db.isMemberOfSortedSets(toGroups, group), db.isMemberOfSortedSets(toGroups, group),

@ -19,7 +19,7 @@ module.exports = function (Categories) {
return []; return [];
} }
const keys = cids.map(cid => 'category:' + cid); const keys = cids.map(cid => `category:${cid}`);
const categories = await (fields.length ? db.getObjectsFields(keys, fields) : db.getObjects(keys)); const categories = await (fields.length ? db.getObjectsFields(keys, fields) : db.getObjects(keys));
const result = await plugins.hooks.fire('filter:category.getFields', { const result = await plugins.hooks.fire('filter:category.getFields', {
cids: cids, cids: cids,
@ -56,11 +56,11 @@ module.exports = function (Categories) {
}; };
Categories.setCategoryField = async function (cid, field, value) { Categories.setCategoryField = async function (cid, field, value) {
await db.setObjectField('category:' + cid, field, value); await db.setObjectField(`category:${cid}`, field, value);
}; };
Categories.incrementCategoryFieldBy = async function (cid, field, value) { Categories.incrementCategoryFieldBy = async function (cid, field, value) {
await db.incrObjectFieldBy('category:' + cid, field, value); await db.incrObjectFieldBy(`category:${cid}`, field, value);
}; };
}; };

@ -11,13 +11,13 @@ var cache = require('../cache');
module.exports = function (Categories) { module.exports = function (Categories) {
Categories.purge = async function (cid, uid) { Categories.purge = async function (cid, uid) {
await batch.processSortedSet('cid:' + cid + ':tids', async function (tids) { await batch.processSortedSet(`cid:${cid}:tids`, async function (tids) {
await async.eachLimit(tids, 10, async function (tid) { await async.eachLimit(tids, 10, async function (tid) {
await topics.purgePostsAndTopic(tid, uid); await topics.purgePostsAndTopic(tid, uid);
}); });
}, { alwaysStartAt: 0 }); }, { alwaysStartAt: 0 });
const pinnedTids = await db.getSortedSetRevRange('cid:' + cid + ':tids:pinned', 0, -1); const pinnedTids = await db.getSortedSetRevRange(`cid:${cid}:tids:pinned`, 0, -1);
await async.eachLimit(pinnedTids, 10, async function (tid) { await async.eachLimit(pinnedTids, 10, async function (tid) {
await topics.purgePostsAndTopic(tid, uid); await topics.purgePostsAndTopic(tid, uid);
}); });
@ -30,41 +30,41 @@ module.exports = function (Categories) {
const cid = categoryData.cid; const cid = categoryData.cid;
await db.sortedSetRemoveBulk([ await db.sortedSetRemoveBulk([
['categories:cid', cid], ['categories:cid', cid],
['categories:name', categoryData.name.substr(0, 200).toLowerCase() + ':' + cid], ['categories:name', `${categoryData.name.substr(0, 200).toLowerCase()}:${cid}`],
]); ]);
await removeFromParent(cid); await removeFromParent(cid);
await deleteTags(cid); await deleteTags(cid);
await db.deleteAll([ await db.deleteAll([
'cid:' + cid + ':tids', `cid:${cid}:tids`,
'cid:' + cid + ':tids:pinned', `cid:${cid}:tids:pinned`,
'cid:' + cid + ':tids:posts', `cid:${cid}:tids:posts`,
'cid:' + cid + ':tids:votes', `cid:${cid}:tids:votes`,
'cid:' + cid + ':tids:lastposttime', `cid:${cid}:tids:lastposttime`,
'cid:' + cid + ':recent_tids', `cid:${cid}:recent_tids`,
'cid:' + cid + ':pids', `cid:${cid}:pids`,
'cid:' + cid + ':read_by_uid', `cid:${cid}:read_by_uid`,
'cid:' + cid + ':uid:watch:state', `cid:${cid}:uid:watch:state`,
'cid:' + cid + ':children', `cid:${cid}:children`,
'cid:' + cid + ':tag:whitelist', `cid:${cid}:tag:whitelist`,
'category:' + cid, `category:${cid}`,
]); ]);
await groups.destroy(privileges.privilegeList.map(privilege => 'cid:' + cid + ':privileges:' + privilege)); await groups.destroy(privileges.privilegeList.map(privilege => `cid:${cid}:privileges:${privilege}`));
} }
async function removeFromParent(cid) { async function removeFromParent(cid) {
const [parentCid, children] = await Promise.all([ const [parentCid, children] = await Promise.all([
Categories.getCategoryField(cid, 'parentCid'), Categories.getCategoryField(cid, 'parentCid'),
db.getSortedSetRange('cid:' + cid + ':children', 0, -1), db.getSortedSetRange(`cid:${cid}:children`, 0, -1),
]); ]);
const bulkAdd = []; const bulkAdd = [];
const childrenKeys = children.map(function (cid) { const childrenKeys = children.map(function (cid) {
bulkAdd.push(['cid:0:children', cid, cid]); bulkAdd.push(['cid:0:children', cid, cid]);
return 'category:' + cid; return `category:${cid}`;
}); });
await Promise.all([ await Promise.all([
db.sortedSetRemove('cid:' + parentCid + ':children', cid), db.sortedSetRemove(`cid:${parentCid}:children`, cid),
db.setObjectField(childrenKeys, 'parentCid', 0), db.setObjectField(childrenKeys, 'parentCid', 0),
db.sortedSetAddBulk(bulkAdd), db.sortedSetAddBulk(bulkAdd),
]); ]);
@ -72,17 +72,17 @@ module.exports = function (Categories) {
cache.del([ cache.del([
'categories:cid', 'categories:cid',
'cid:0:children', 'cid:0:children',
'cid:' + parentCid + ':children', `cid:${parentCid}:children`,
'cid:' + parentCid + ':children:all', `cid:${parentCid}:children:all`,
'cid:' + cid + ':children', `cid:${cid}:children`,
'cid:' + cid + ':children:all', `cid:${cid}:children:all`,
'cid:' + cid + ':tag:whitelist', `cid:${cid}:tag:whitelist`,
]); ]);
} }
async function deleteTags(cid) { async function deleteTags(cid) {
const tags = await db.getSortedSetMembers('cid:' + cid + ':tags'); const tags = await db.getSortedSetMembers(`cid:${cid}:tags`);
await db.deleteAll(tags.map(tag => 'cid:' + cid + ':tag:' + tag + ':topics')); await db.deleteAll(tags.map(tag => `cid:${cid}:tag:${tag}:topics`));
await db.delete('cid:' + cid + ':tags'); await db.delete(`cid:${cid}:tags`);
} }
}; };

@ -25,9 +25,9 @@ require('./search')(Categories);
Categories.exists = async function (cid) { Categories.exists = async function (cid) {
if (Array.isArray(cid)) { if (Array.isArray(cid)) {
return await db.exists(cid.map(cid => 'category:' + cid)); return await db.exists(cid.map(cid => `category:${cid}`));
} }
return await db.exists('category:' + cid); return await db.exists(`category:${cid}`);
}; };
Categories.getCategoryById = async function (data) { Categories.getCategoryById = async function (data) {
@ -98,8 +98,8 @@ Categories.getModerators = async function (cid) {
Categories.getModeratorUids = async function (cids) { Categories.getModeratorUids = async function (cids) {
const groupNames = cids.reduce(function (memo, cid) { const groupNames = cids.reduce(function (memo, cid) {
memo.push('cid:' + cid + ':privileges:moderate'); memo.push(`cid:${cid}:privileges:moderate`);
memo.push('cid:' + cid + ':privileges:groups:moderate'); memo.push(`cid:${cid}:privileges:groups:moderate`);
return memo; return memo;
}, []); }, []);
@ -150,7 +150,7 @@ Categories.getTagWhitelist = async function (cids) {
const cachedData = {}; const cachedData = {};
const nonCachedCids = cids.filter((cid) => { const nonCachedCids = cids.filter((cid) => {
const data = cache.get('cid:' + cid + ':tag:whitelist'); const data = cache.get(`cid:${cid}:tag:whitelist`);
const isInCache = data !== undefined; const isInCache = data !== undefined;
if (isInCache) { if (isInCache) {
cachedData[cid] = data; cachedData[cid] = data;
@ -162,12 +162,12 @@ Categories.getTagWhitelist = async function (cids) {
return cids.map(cid => cachedData[cid]); return cids.map(cid => cachedData[cid]);
} }
const keys = nonCachedCids.map(cid => 'cid:' + cid + ':tag:whitelist'); const keys = nonCachedCids.map(cid => `cid:${cid}:tag:whitelist`);
const data = await db.getSortedSetsMembers(keys); const data = await db.getSortedSetsMembers(keys);
nonCachedCids.forEach((cid, index) => { nonCachedCids.forEach((cid, index) => {
cachedData[cid] = data[index]; cachedData[cid] = data[index];
cache.set('cid:' + cid + ':tag:whitelist', data[index]); cache.set(`cid:${cid}:tag:whitelist`, data[index]);
}); });
return cids.map(cid => cachedData[cid]); return cids.map(cid => cachedData[cid]);
}; };
@ -252,12 +252,12 @@ Categories.getChildrenCids = async function (rootCid) {
if (!childrenCids.length) { if (!childrenCids.length) {
return; return;
} }
keys = childrenCids.map(cid => 'cid:' + cid + ':children'); keys = childrenCids.map(cid => `cid:${cid}:children`);
childrenCids.forEach(cid => allCids.push(parseInt(cid, 10))); childrenCids.forEach(cid => allCids.push(parseInt(cid, 10)));
await recursive(keys); await recursive(keys);
} }
const key = 'cid:' + rootCid + ':children'; const key = `cid:${rootCid}:children`;
const cacheKey = key + ':all'; const cacheKey = `${key}:all`;
const childrenCids = cache.get(cacheKey); const childrenCids = cache.get(cacheKey);
if (childrenCids) { if (childrenCids) {
return childrenCids.slice(); return childrenCids.slice();
@ -368,7 +368,7 @@ Categories.buildForSelectCategories = function (categories, fields, parentCid) {
category.depth = depth; category.depth = depth;
categoriesData.push(category); categoriesData.push(category);
if (Array.isArray(category.children)) { if (Array.isArray(category.children)) {
category.children.forEach(child => recursive(child, categoriesData, '&nbsp;&nbsp;&nbsp;&nbsp;' + level, depth + 1)); category.children.forEach(child => recursive(child, categoriesData, `&nbsp;&nbsp;&nbsp;&nbsp;${level}`, depth + 1));
} }
} }
parentCid = parentCid || 0; parentCid = parentCid || 0;

@ -15,26 +15,26 @@ module.exports = function (Categories) {
if (!parseInt(count, 10)) { if (!parseInt(count, 10)) {
return []; return [];
} }
let pids = await db.getSortedSetRevRange('cid:' + cid + ':pids', 0, count - 1); let pids = await db.getSortedSetRevRange(`cid:${cid}:pids`, 0, count - 1);
pids = await privileges.posts.filter('topics:read', pids, uid); pids = await privileges.posts.filter('topics:read', pids, uid);
return await posts.getPostSummaryByPids(pids, uid, { stripTags: true }); return await posts.getPostSummaryByPids(pids, uid, { stripTags: true });
}; };
Categories.updateRecentTid = async function (cid, tid) { Categories.updateRecentTid = async function (cid, tid) {
const [count, numRecentReplies] = await Promise.all([ const [count, numRecentReplies] = await Promise.all([
db.sortedSetCard('cid:' + cid + ':recent_tids'), db.sortedSetCard(`cid:${cid}:recent_tids`),
db.getObjectField('category:' + cid, 'numRecentReplies'), db.getObjectField(`category:${cid}`, 'numRecentReplies'),
]); ]);
if (count >= numRecentReplies) { if (count >= numRecentReplies) {
const data = await db.getSortedSetRangeWithScores('cid:' + cid + ':recent_tids', 0, count - numRecentReplies); const data = await db.getSortedSetRangeWithScores(`cid:${cid}:recent_tids`, 0, count - numRecentReplies);
const shouldRemove = !(data.length === 1 && count === 1 && data[0].value === String(tid)); const shouldRemove = !(data.length === 1 && count === 1 && data[0].value === String(tid));
if (data.length && shouldRemove) { if (data.length && shouldRemove) {
await db.sortedSetsRemoveRangeByScore(['cid:' + cid + ':recent_tids'], '-inf', data[data.length - 1].score); await db.sortedSetsRemoveRangeByScore([`cid:${cid}:recent_tids`], '-inf', data[data.length - 1].score);
} }
} }
if (numRecentReplies > 0) { if (numRecentReplies > 0) {
await db.sortedSetAdd('cid:' + cid + ':recent_tids', Date.now(), tid); await db.sortedSetAdd(`cid:${cid}:recent_tids`, Date.now(), tid);
} }
await plugins.hooks.fire('action:categories.updateRecentTid', { cid: cid, tid: tid }); await plugins.hooks.fire('action:categories.updateRecentTid', { cid: cid, tid: tid });
}; };
@ -45,7 +45,7 @@ module.exports = function (Categories) {
let index = 0; let index = 0;
do { do {
/* eslint-disable no-await-in-loop */ /* eslint-disable no-await-in-loop */
const pids = await db.getSortedSetRevRange('cid:' + cid + ':pids', index, index); const pids = await db.getSortedSetRevRange(`cid:${cid}:pids`, index, index);
if (!pids.length) { if (!pids.length) {
return; return;
} }
@ -77,7 +77,7 @@ module.exports = function (Categories) {
}); });
keys = result.keys; keys = result.keys;
} else { } else {
keys = categoriesToLoad.map(c => 'cid:' + c.cid + ':recent_tids'); keys = categoriesToLoad.map(c => `cid:${c.cid}:recent_tids`);
} }
const results = await db.getSortedSetsMembers(keys); const results = await db.getSortedSetsMembers(keys);
@ -174,19 +174,19 @@ module.exports = function (Categories) {
const bulkRemove = []; const bulkRemove = [];
const bulkAdd = []; const bulkAdd = [];
postData.forEach((post) => { postData.forEach((post) => {
bulkRemove.push(['cid:' + oldCid + ':uid:' + post.uid + ':pids', post.pid]); bulkRemove.push([`cid:${oldCid}:uid:${post.uid}:pids`, post.pid]);
bulkRemove.push(['cid:' + oldCid + ':uid:' + post.uid + ':pids:votes', post.pid]); bulkRemove.push([`cid:${oldCid}:uid:${post.uid}:pids:votes`, post.pid]);
bulkAdd.push(['cid:' + cid + ':uid:' + post.uid + ':pids', post.timestamp, post.pid]); bulkAdd.push([`cid:${cid}:uid:${post.uid}:pids`, post.timestamp, post.pid]);
if (post.votes > 0) { if (post.votes > 0) {
bulkAdd.push(['cid:' + cid + ':uid:' + post.uid + ':pids:votes', post.votes, post.pid]); bulkAdd.push([`cid:${cid}:uid:${post.uid}:pids:votes`, post.votes, post.pid]);
} }
}); });
const postsToReAdd = postData.filter(p => !p.deleted && !topicDeleted); const postsToReAdd = postData.filter(p => !p.deleted && !topicDeleted);
const timestamps = postsToReAdd.map(p => p && p.timestamp); const timestamps = postsToReAdd.map(p => p && p.timestamp);
await Promise.all([ await Promise.all([
db.sortedSetRemove('cid:' + oldCid + ':pids', pids), db.sortedSetRemove(`cid:${oldCid}:pids`, pids),
db.sortedSetAdd('cid:' + cid + ':pids', timestamps, postsToReAdd.map(p => p.pid)), db.sortedSetAdd(`cid:${cid}:pids`, timestamps, postsToReAdd.map(p => p.pid)),
db.sortedSetRemoveBulk(bulkRemove), db.sortedSetRemoveBulk(bulkRemove),
db.sortedSetAddBulk(bulkAdd), db.sortedSetAddBulk(bulkAdd),
]); ]);
@ -200,8 +200,8 @@ module.exports = function (Categories) {
} }
await Promise.all([ await Promise.all([
db.incrObjectFieldBy('category:' + oldCid, 'post_count', -postCount), db.incrObjectFieldBy(`category:${oldCid}`, 'post_count', -postCount),
db.incrObjectFieldBy('category:' + newCid, 'post_count', postCount), db.incrObjectFieldBy(`category:${newCid}`, 'post_count', postCount),
]); ]);
} }
}; };

@ -67,7 +67,7 @@ module.exports = function (Categories) {
} }
const data = await db.getSortedSetScan({ const data = await db.getSortedSetScan({
key: 'categories:name', key: 'categories:name',
match: '*' + String(query).toLowerCase() + '*', match: `*${String(query).toLowerCase()}*`,
limit: hardCap || 500, limit: hardCap || 500,
}); });
return data.map(data => parseInt(data.split(':').pop(), 10)); return data.map(data => parseInt(data.split(':').pop(), 10));

@ -92,24 +92,24 @@ module.exports = function (Categories) {
Categories.buildTopicsSortedSet = async function (data) { Categories.buildTopicsSortedSet = async function (data) {
const cid = data.cid; const cid = data.cid;
let set = 'cid:' + cid + ':tids'; let set = `cid:${cid}:tids`;
const sort = data.sort || (data.settings && data.settings.categoryTopicSort) || meta.config.categoryTopicSort || 'newest_to_oldest'; const sort = data.sort || (data.settings && data.settings.categoryTopicSort) || meta.config.categoryTopicSort || 'newest_to_oldest';
if (sort === 'most_posts') { if (sort === 'most_posts') {
set = 'cid:' + cid + ':tids:posts'; set = `cid:${cid}:tids:posts`;
} else if (sort === 'most_votes') { } else if (sort === 'most_votes') {
set = 'cid:' + cid + ':tids:votes'; set = `cid:${cid}:tids:votes`;
} }
if (data.targetUid) { if (data.targetUid) {
set = 'cid:' + cid + ':uid:' + data.targetUid + ':tids'; set = `cid:${cid}:uid:${data.targetUid}:tids`;
} }
if (data.tag) { if (data.tag) {
if (Array.isArray(data.tag)) { if (Array.isArray(data.tag)) {
set = [set].concat(data.tag.map(tag => 'tag:' + tag + ':topics')); set = [set].concat(data.tag.map(tag => `tag:${tag}:topics`));
} else { } else {
set = [set, 'tag:' + data.tag + ':topics']; set = [set, `tag:${data.tag}:topics`];
} }
} }
const result = await plugins.hooks.fire('filter:categories.buildTopicsSortedSet', { const result = await plugins.hooks.fire('filter:categories.buildTopicsSortedSet', {
@ -130,7 +130,7 @@ module.exports = function (Categories) {
}; };
Categories.getAllTopicIds = async function (cid, start, stop) { Categories.getAllTopicIds = async function (cid, start, stop) {
return await db.getSortedSetRange(['cid:' + cid + ':tids:pinned', 'cid:' + cid + ':tids'], start, stop); return await db.getSortedSetRange([`cid:${cid}:tids:pinned`, `cid:${cid}:tids`], start, stop);
}; };
Categories.getPinnedTids = async function (data) { Categories.getPinnedTids = async function (data) {
@ -141,7 +141,7 @@ module.exports = function (Categories) {
}); });
return result && result.pinnedTids; return result && result.pinnedTids;
} }
const pinnedTids = await db.getSortedSetRevRange('cid:' + data.cid + ':tids:pinned', data.start, data.stop); const pinnedTids = await db.getSortedSetRevRange(`cid:${data.cid}:tids:pinned`, data.start, data.stop);
return await topics.tools.checkPinExpiry(pinnedTids); return await topics.tools.checkPinExpiry(pinnedTids);
}; };
@ -166,11 +166,11 @@ module.exports = function (Categories) {
return; return;
} }
const promises = [ const promises = [
db.sortedSetAdd('cid:' + cid + ':pids', postData.timestamp, postData.pid), db.sortedSetAdd(`cid:${cid}:pids`, postData.timestamp, postData.pid),
db.incrObjectField('category:' + cid, 'post_count'), db.incrObjectField(`category:${cid}`, 'post_count'),
]; ];
if (!pinned) { if (!pinned) {
promises.push(db.sortedSetIncrBy('cid:' + cid + ':tids:posts', 1, postData.tid)); promises.push(db.sortedSetIncrBy(`cid:${cid}:tids:posts`, 1, postData.tid));
} }
await Promise.all(promises); await Promise.all(promises);
await Categories.updateRecentTidForCid(cid); await Categories.updateRecentTidForCid(cid);

@ -7,7 +7,7 @@ module.exports = function (Categories) {
if (!Array.isArray(cids) || !cids.length || parseInt(uid, 10) <= 0) { if (!Array.isArray(cids) || !cids.length || parseInt(uid, 10) <= 0) {
return; return;
} }
let keys = cids.map(cid => 'cid:' + cid + ':read_by_uid'); let keys = cids.map(cid => `cid:${cid}:read_by_uid`);
const hasRead = await db.isMemberOfSets(keys, uid); const hasRead = await db.isMemberOfSets(keys, uid);
keys = keys.filter((key, index) => !hasRead[index]); keys = keys.filter((key, index) => !hasRead[index]);
await db.setsAdd(keys, uid); await db.setsAdd(keys, uid);
@ -17,7 +17,7 @@ module.exports = function (Categories) {
if (!parseInt(cid, 10)) { if (!parseInt(cid, 10)) {
return; return;
} }
await db.delete('cid:' + cid + ':read_by_uid'); await db.delete(`cid:${cid}:read_by_uid`);
}; };
Categories.hasReadCategories = async function (cids, uid) { Categories.hasReadCategories = async function (cids, uid) {
@ -25,7 +25,7 @@ module.exports = function (Categories) {
return cids.map(() => false); return cids.map(() => false);
} }
const sets = cids.map(cid => 'cid:' + cid + ':read_by_uid'); const sets = cids.map(cid => `cid:${cid}:read_by_uid`);
return await db.isMemberOfSets(sets, uid); return await db.isMemberOfSets(sets, uid);
}; };
@ -33,6 +33,6 @@ module.exports = function (Categories) {
if (parseInt(uid, 10) <= 0) { if (parseInt(uid, 10) <= 0) {
return false; return false;
} }
return await db.isSetMember('cid:' + cid + ':read_by_uid', uid); return await db.isSetMember(`cid:${cid}:read_by_uid`, uid);
}; };
}; };

@ -25,7 +25,7 @@ module.exports = function (Categories) {
if (modifiedFields.hasOwnProperty('name')) { if (modifiedFields.hasOwnProperty('name')) {
const translated = await translator.translate(modifiedFields.name); const translated = await translator.translate(modifiedFields.name);
modifiedFields.slug = cid + '/' + slugify(translated); modifiedFields.slug = `${cid}/${slugify(translated)}`;
} }
const result = await plugins.hooks.fire('filter:category.update', { cid: cid, category: modifiedFields }); const result = await plugins.hooks.fire('filter:category.update', { cid: cid, category: modifiedFields });
@ -54,7 +54,7 @@ module.exports = function (Categories) {
return await updateOrder(cid, value); return await updateOrder(cid, value);
} }
await db.setObjectField('category:' + cid, key, value); await db.setObjectField(`category:${cid}`, key, value);
if (key === 'description') { if (key === 'description') {
await Categories.parseDescription(cid, value); await Categories.parseDescription(cid, value);
} }
@ -71,26 +71,26 @@ module.exports = function (Categories) {
} }
const oldParent = await Categories.getCategoryField(cid, 'parentCid'); const oldParent = await Categories.getCategoryField(cid, 'parentCid');
await Promise.all([ await Promise.all([
db.sortedSetRemove('cid:' + oldParent + ':children', cid), db.sortedSetRemove(`cid:${oldParent}:children`, cid),
db.sortedSetAdd('cid:' + newParent + ':children', cid, cid), db.sortedSetAdd(`cid:${newParent}:children`, cid, cid),
db.setObjectField('category:' + cid, 'parentCid', newParent), db.setObjectField(`category:${cid}`, 'parentCid', newParent),
]); ]);
cache.del([ cache.del([
'cid:' + oldParent + ':children', `cid:${oldParent}:children`,
'cid:' + newParent + ':children', `cid:${newParent}:children`,
'cid:' + oldParent + ':children:all', `cid:${oldParent}:children:all`,
'cid:' + newParent + ':children:all', `cid:${newParent}:children:all`,
]); ]);
} }
async function updateTagWhitelist(cid, tags) { async function updateTagWhitelist(cid, tags) {
tags = tags.split(',').map(tag => utils.cleanUpTag(tag, meta.config.maximumTagLength)) tags = tags.split(',').map(tag => utils.cleanUpTag(tag, meta.config.maximumTagLength))
.filter(Boolean); .filter(Boolean);
await db.delete('cid:' + cid + ':tag:whitelist'); await db.delete(`cid:${cid}:tag:whitelist`);
const scores = tags.map((tag, index) => index); const scores = tags.map((tag, index) => index);
await db.sortedSetAdd('cid:' + cid + ':tag:whitelist', scores, tags); await db.sortedSetAdd(`cid:${cid}:tag:whitelist`, scores, tags);
cache.del('cid:' + cid + ':tag:whitelist'); cache.del(`cid:${cid}:tag:whitelist`);
} }
async function updateOrder(cid, order) { async function updateOrder(cid, order) {
@ -98,7 +98,7 @@ module.exports = function (Categories) {
await db.sortedSetsAdd('categories:cid', order, cid); await db.sortedSetsAdd('categories:cid', order, cid);
const childrenCids = await db.getSortedSetRange( const childrenCids = await db.getSortedSetRange(
'cid:' + parentCid + ':children', 0, -1 `cid:${parentCid}:children`, 0, -1
); );
const currentIndex = childrenCids.indexOf(String(cid)); const currentIndex = childrenCids.indexOf(String(cid));
@ -112,20 +112,20 @@ module.exports = function (Categories) {
// recalculate orders from array indices // recalculate orders from array indices
await db.sortedSetAdd( await db.sortedSetAdd(
'cid:' + parentCid + ':children', `cid:${parentCid}:children`,
childrenCids.map((cid, index) => index + 1), childrenCids.map((cid, index) => index + 1),
childrenCids childrenCids
); );
await db.setObjectBulk( await db.setObjectBulk(
childrenCids.map(cid => 'category:' + cid), childrenCids.map(cid => `category:${cid}`),
childrenCids.map((cid, index) => ({ order: index + 1 })) childrenCids.map((cid, index) => ({ order: index + 1 }))
); );
cache.del([ cache.del([
'categories:cid', 'categories:cid',
'cid:' + parentCid + ':children', `cid:${parentCid}:children`,
'cid:' + parentCid + ':children:all', `cid:${parentCid}:children:all`,
]); ]);
} }
@ -136,8 +136,8 @@ module.exports = function (Categories) {
async function updateName(cid, newName) { async function updateName(cid, newName) {
const oldName = await Categories.getCategoryField(cid, 'name'); const oldName = await Categories.getCategoryField(cid, 'name');
await db.sortedSetRemove('categories:name', oldName.substr(0, 200).toLowerCase() + ':' + cid); await db.sortedSetRemove('categories:name', `${oldName.substr(0, 200).toLowerCase()}:${cid}`);
await db.sortedSetAdd('categories:name', 0, newName.substr(0, 200).toLowerCase() + ':' + cid); await db.sortedSetAdd('categories:name', 0, `${newName.substr(0, 200).toLowerCase()}:${cid}`);
await db.setObjectField('category:' + cid, 'name', newName); await db.setObjectField(`category:${cid}`, 'name', newName);
} }
}; };

@ -25,7 +25,7 @@ module.exports = function (Categories) {
if (!Array.isArray(cids) || !cids.length) { if (!Array.isArray(cids) || !cids.length) {
return []; return [];
} }
const keys = cids.map(cid => 'cid:' + cid + ':uid:watch:state'); const keys = cids.map(cid => `cid:${cid}:uid:watch:state`);
const [userSettings, states] = await Promise.all([ const [userSettings, states] = await Promise.all([
user.getSettings(uid), user.getSettings(uid),
db.sortedSetsScore(keys, uid), db.sortedSetsScore(keys, uid),
@ -35,7 +35,7 @@ module.exports = function (Categories) {
Categories.getIgnorers = async function (cid, start, stop) { Categories.getIgnorers = async function (cid, start, stop) {
const count = (stop === -1) ? -1 : (stop - start + 1); const count = (stop === -1) ? -1 : (stop - start + 1);
return await db.getSortedSetRevRangeByScore('cid:' + cid + ':uid:watch:state', start, count, Categories.watchStates.ignoring, Categories.watchStates.ignoring); return await db.getSortedSetRevRangeByScore(`cid:${cid}:uid:watch:state`, start, count, Categories.watchStates.ignoring, Categories.watchStates.ignoring);
}; };
Categories.filterIgnoringUids = async function (cid, uids) { Categories.filterIgnoringUids = async function (cid, uids) {
@ -47,7 +47,7 @@ module.exports = function (Categories) {
Categories.getUidsWatchStates = async function (cid, uids) { Categories.getUidsWatchStates = async function (cid, uids) {
const [userSettings, states] = await Promise.all([ const [userSettings, states] = await Promise.all([
user.getMultipleUserSettings(uids), user.getMultipleUserSettings(uids),
db.sortedSetScores('cid:' + cid + ':uid:watch:state', uids), db.sortedSetScores(`cid:${cid}:uid:watch:state`, uids),
]); ]);
return states.map((state, index) => state || Categories.watchStates[userSettings[index].categoryWatchState]); return states.map((state, index) => state || Categories.watchStates[userSettings[index].categoryWatchState]);
}; };

@ -18,18 +18,18 @@ Command.prototype.helpInformation = function () {
var desc = []; var desc = [];
if (this._description) { if (this._description) {
desc = [ desc = [
' ' + this._description, ` ${this._description}`,
'', '',
]; ];
} }
var cmdName = this._name; var cmdName = this._name;
if (this._alias) { if (this._alias) {
cmdName = cmdName + ' | ' + this._alias; cmdName = `${cmdName} | ${this._alias}`;
} }
var usage = [ var usage = [
'', '',
' Usage: ' + cmdName[commandColor] + ' '.reset + this.usage(), ` Usage: ${cmdName[commandColor]}${' '.reset}${this.usage()}`,
'', '',
]; ];
@ -43,7 +43,7 @@ Command.prototype.helpInformation = function () {
'', '',
' Options:', ' Options:',
'', '',
'' + this.optionHelp().replace(/^/gm, ' '), `${this.optionHelp().replace(/^/gm, ' ')}`,
'', '',
]; ];
@ -57,7 +57,7 @@ Command.prototype.helpInformation = function () {
function humanReadableArgName(arg) { function humanReadableArgName(arg) {
var nameOutput = arg.name + (arg.variadic === true ? '...' : ''); var nameOutput = arg.name + (arg.variadic === true ? '...' : '');
return arg.required ? '<' + nameOutput + '>' : '[' + nameOutput + ']'; return arg.required ? `<${nameOutput}>` : `[${nameOutput}]`;
} }
Command.prototype.usage = function () { Command.prototype.usage = function () {
@ -67,7 +67,7 @@ Command.prototype.usage = function () {
var usage = '[options]'[optionColor] + var usage = '[options]'[optionColor] +
(this.commands.length ? ' [command]' : '')[subCommandColor] + (this.commands.length ? ' [command]' : '')[subCommandColor] +
(this._args.length ? ' ' + args.join(' ') : '')[argColor]; (this._args.length ? ` ${args.join(' ')}` : '')[argColor];
return usage; return usage;
}; };
@ -90,10 +90,10 @@ Command.prototype.commandHelp = function () {
}).join(' '); }).join(' ');
return [ return [
cmd._name[subCommandColor] + `${cmd._name[subCommandColor] +
(cmd._alias ? ' | ' + cmd._alias : '')[subCommandColor] + (cmd._alias ? ` | ${cmd._alias}` : '')[subCommandColor] +
(cmd.options.length ? ' [options]' : '')[subOptionColor] + (cmd.options.length ? ' [options]' : '')[subOptionColor]
' ' + args[subArgColor], } ${args[subArgColor]}`,
cmd._description, cmd._description,
]; ];
}); });
@ -107,7 +107,7 @@ Command.prototype.commandHelp = function () {
' Commands:', ' Commands:',
'', '',
commands.map(function (cmd) { commands.map(function (cmd) {
var desc = cmd[1] ? ' ' + cmd[1] : ''; var desc = cmd[1] ? ` ${cmd[1]}` : '';
return pad(cmd[0], width) + desc; return pad(cmd[0], width) + desc;
}).join('\n').replace(/^/gm, ' '), }).join('\n').replace(/^/gm, ' '),
'', '',
@ -120,8 +120,8 @@ Command.prototype.optionHelp = function () {
// Append the help information // Append the help information
return this.options return this.options
.map(function (option) { .map(function (option) {
return pad(option.flags, width)[optionColor] + ' ' + option.description; return `${pad(option.flags, width)[optionColor]} ${option.description}`;
}) })
.concat([pad('-h, --help', width)[optionColor] + ' output usage information']) .concat([`${pad('-h, --help', width)[optionColor]} output usage information`])
.join('\n'); .join('\n');
}; };

@ -43,7 +43,7 @@ try {
const checkVersion = function (packageName) { const checkVersion = function (packageName) {
const version = JSON.parse(fs.readFileSync(path.join(paths.nodeModules, packageName, 'package.json'), 'utf8')).version; const version = JSON.parse(fs.readFileSync(path.join(paths.nodeModules, packageName, 'package.json'), 'utf8')).version;
if (!semver.satisfies(version, defaultPackage.dependencies[packageName])) { if (!semver.satisfies(version, defaultPackage.dependencies[packageName])) {
const e = new TypeError('Incorrect dependency version: ' + packageName); const e = new TypeError(`Incorrect dependency version: ${packageName}`);
e.code = 'DEP_WRONG_VERSION'; e.code = 'DEP_WRONG_VERSION';
throw e; throw e;
} }
@ -194,7 +194,7 @@ program
}); });
program program
.command('build [targets...]') .command('build [targets...]')
.description('Compile static assets ' + '(JS, CSS, templates, languages)'.red) .description(`Compile static assets ${'(JS, CSS, templates, languages)'.red}`)
.option('-s, --series', 'Run builds in series without extra processes') .option('-s, --series', 'Run builds in series without extra processes')
.action(function (targets, options) { .action(function (targets, options) {
require('./manage').build(targets.length ? targets : true, options); require('./manage').build(targets.length ? targets : true, options);
@ -265,12 +265,12 @@ program
.option('-s, --schema', 'Update NodeBB data store schema', false) .option('-s, --schema', 'Update NodeBB data store schema', false)
.option('-b, --build', 'Rebuild assets', false) .option('-b, --build', 'Rebuild assets', false)
.on('--help', function () { .on('--help', function () {
console.log('\n' + [ console.log(`\n${[
'When running particular upgrade scripts, options are ignored.', 'When running particular upgrade scripts, options are ignored.',
'By default all options are enabled. Passing any options disables that default.', 'By default all options are enabled. Passing any options disables that default.',
'Only package and dependency updates: ' + './nodebb upgrade -mi'.yellow, `Only package and dependency updates: ${'./nodebb upgrade -mi'.yellow}`,
'Only database update: ' + './nodebb upgrade -s'.yellow, `Only database update: ${'./nodebb upgrade -s'.yellow}`,
].join('\n')); ].join('\n')}`);
}) })
.action(function (scripts, options) { .action(function (scripts, options) {
require('./upgrade').upgrade(scripts.length ? scripts : true, options); require('./upgrade').upgrade(scripts.length ? scripts : true, options);

@ -23,7 +23,7 @@ async function activate(plugin) {
await db.init(); await db.init();
if (!pluginNamePattern.test(plugin)) { if (!pluginNamePattern.test(plugin)) {
// Allow omission of `nodebb-plugin-` // Allow omission of `nodebb-plugin-`
plugin = 'nodebb-plugin-' + plugin; plugin = `nodebb-plugin-${plugin}`;
} }
const isInstalled = await plugins.isInstalled(plugin); const isInstalled = await plugins.isInstalled(plugin);
if (!isInstalled) { if (!isInstalled) {
@ -42,7 +42,7 @@ async function activate(plugin) {
text: plugin, text: plugin,
}); });
} catch (err) { } catch (err) {
winston.error('An error occurred during plugin activation\n' + err.stack); winston.error(`An error occurred during plugin activation\n${err.stack}`);
} }
process.exit(0); process.exit(0);
} }
@ -72,7 +72,7 @@ async function listPlugins() {
// Pretty output // Pretty output
process.stdout.write('Active plugins:\n'); process.stdout.write('Active plugins:\n');
combined.forEach((plugin) => { combined.forEach((plugin) => {
process.stdout.write('\t* ' + plugin.id + (plugin.version ? '@' + plugin.version : '') + ' ('); process.stdout.write(`\t* ${plugin.id}${plugin.version ? `@${plugin.version}` : ''} (`);
process.stdout.write(plugin.installed ? 'installed'.green : 'not installed'.red); process.stdout.write(plugin.installed ? 'installed'.green : 'not installed'.red);
process.stdout.write(', '); process.stdout.write(', ');
process.stdout.write(plugin.active ? 'enabled'.green : 'disabled'.yellow); process.stdout.write(plugin.active ? 'enabled'.green : 'disabled'.yellow);
@ -85,9 +85,9 @@ async function listPlugins() {
async function listEvents(count) { async function listEvents(count) {
await db.init(); await db.init();
const eventData = await events.getEvents('', 0, (count || 10) - 1); const eventData = await events.getEvents('', 0, (count || 10) - 1);
console.log(('\nDisplaying last ' + count + ' administrative events...').bold); console.log((`\nDisplaying last ${count} administrative events...`).bold);
eventData.forEach(function (event) { eventData.forEach(function (event) {
console.log(' * ' + String(event.timestampISO).green + ' ' + String(event.type).yellow + (event.text ? ' ' + event.text : '') + ' (uid: '.reset + (event.uid ? event.uid : 0) + ')'); console.log(` * ${String(event.timestampISO).green} ${String(event.type).yellow}${event.text ? ` ${event.text}` : ''}${' (uid: '.reset}${event.uid ? event.uid : 0})`);
}); });
process.exit(); process.exit();
} }
@ -95,28 +95,28 @@ async function listEvents(count) {
async function info() { async function info() {
console.log(''); console.log('');
const version = require('../../package.json').version; const version = require('../../package.json').version;
console.log(' version: ' + version); console.log(` version: ${version}`);
console.log(' Node ver: ' + process.version); console.log(` Node ver: ${process.version}`);
const hash = childProcess.execSync('git rev-parse HEAD'); const hash = childProcess.execSync('git rev-parse HEAD');
console.log(' git hash: ' + hash); console.log(` git hash: ${hash}`);
const config = require('../../config.json'); const config = require('../../config.json');
console.log(' database: ' + config.database); console.log(` database: ${config.database}`);
await db.init(); await db.init();
const info = await db.info(db.client); const info = await db.info(db.client);
switch (config.database) { switch (config.database) {
case 'redis': case 'redis':
console.log(' version: ' + info.redis_version); console.log(` version: ${info.redis_version}`);
console.log(' disk sync: ' + info.rdb_last_bgsave_status); console.log(` disk sync: ${info.rdb_last_bgsave_status}`);
break; break;
case 'mongo': case 'mongo':
console.log(' version: ' + info.version); console.log(` version: ${info.version}`);
console.log(' engine: ' + info.storageEngine); console.log(` engine: ${info.storageEngine}`);
break; break;
} }
@ -138,7 +138,7 @@ async function info() {
console.log(''); console.log('');
console.log(graph.toString()); console.log(graph.toString());
console.log('Pageviews, last 24h (min: ' + min + ' max: ' + max + ')'); console.log(`Pageviews, last 24h (min: ${min} max: ${max})`);
process.exit(); process.exit();
} }

@ -75,9 +75,9 @@ function installAll() {
}); });
} catch (e) { } catch (e) {
console.log('Error installing dependencies!'); console.log('Error installing dependencies!');
console.log('message: ' + e.message); console.log(`message: ${e.message}`);
console.log('stdout: ' + e.stdout); console.log(`stdout: ${e.stdout}`);
console.log('stderr: ' + e.stderr); console.log(`stderr: ${e.stderr}`);
throw e; throw e;
} }
} }

@ -22,7 +22,7 @@ exports.reset = async function (options) {
} else { } else {
if (!themeNamePattern.test(themeId)) { if (!themeNamePattern.test(themeId)) {
// Allow omission of `nodebb-theme-` // Allow omission of `nodebb-theme-`
themeId = 'nodebb-theme-' + themeId; themeId = `nodebb-theme-${themeId}`;
} }
await resetTheme(themeId); await resetTheme(themeId);
@ -35,7 +35,7 @@ exports.reset = async function (options) {
} else { } else {
if (!pluginNamePattern.test(pluginId)) { if (!pluginNamePattern.test(pluginId)) {
// Allow omission of `nodebb-plugin-` // Allow omission of `nodebb-plugin-`
pluginId = 'nodebb-plugin-' + pluginId; pluginId = `nodebb-plugin-${pluginId}`;
} }
await resetPlugin(pluginId); await resetPlugin(pluginId);
@ -56,7 +56,7 @@ exports.reset = async function (options) {
if (!tasks.length) { if (!tasks.length) {
console.log([ console.log([
'No arguments passed in, so nothing was reset.\n'.yellow, 'No arguments passed in, so nothing was reset.\n'.yellow,
'Use ./nodebb reset ' + '{-t|-p|-w|-s|-a}'.red, `Use ./nodebb reset ${'{-t|-p|-w|-s|-a}'.red}`,
' -t\tthemes', ' -t\tthemes',
' -p\tplugins', ' -p\tplugins',
' -w\twidgets', ' -w\twidgets',
@ -80,7 +80,7 @@ exports.reset = async function (options) {
winston.info('[reset] Reset complete. Please run `./nodebb build` to rebuild assets.'); winston.info('[reset] Reset complete. Please run `./nodebb build` to rebuild assets.');
process.exit(0); process.exit(0);
} catch (err) { } catch (err) {
winston.error('[reset] Errors were encountered during reset -- ' + err.message); winston.error(`[reset] Errors were encountered during reset -- ${err.message}`);
process.exit(1); process.exit(1);
} }
}; };
@ -111,7 +111,7 @@ async function resetThemeTo(themeId) {
id: themeId, id: themeId,
}); });
await meta.configs.set('bootswatchSkin', ''); await meta.configs.set('bootswatchSkin', '');
winston.info('[reset] Theme reset to ' + themeId + ' and default skin'); winston.info(`[reset] Theme reset to ${themeId} and default skin`);
} }
async function resetPlugin(pluginId) { async function resetPlugin(pluginId) {
@ -133,7 +133,7 @@ async function resetPlugin(pluginId) {
winston.info('[reset] No action taken.'); winston.info('[reset] No action taken.');
} }
} catch (err) { } catch (err) {
winston.error('[reset] Could not disable plugin: ' + pluginId + ' encountered error %s\n' + err.stack); winston.error(`[reset] Could not disable plugin: ${pluginId} encountered error %s\n${err.stack}`);
throw err; throw err;
} }
} }

@ -38,19 +38,19 @@ function start(options) {
return; return;
} }
if (options.log) { if (options.log) {
console.log('\n' + [ console.log(`\n${[
'Starting NodeBB with logging output'.bold, 'Starting NodeBB with logging output'.bold,
'Hit '.red + 'Ctrl-C '.bold + 'to exit'.red, 'Hit '.red + 'Ctrl-C '.bold + 'to exit'.red,
'The NodeBB process will continue to run in the background', 'The NodeBB process will continue to run in the background',
'Use "' + './nodebb stop'.yellow + '" to stop the NodeBB server', `Use "${'./nodebb stop'.yellow}" to stop the NodeBB server`,
].join('\n')); ].join('\n')}`);
} else if (!options.silent) { } else if (!options.silent) {
console.log('\n' + [ console.log(`\n${[
'Starting NodeBB'.bold, 'Starting NodeBB'.bold,
' "' + './nodebb stop'.yellow + '" to stop the NodeBB server', ` "${'./nodebb stop'.yellow}" to stop the NodeBB server`,
' "' + './nodebb log'.yellow + '" to view server output', ` "${'./nodebb log'.yellow}" to view server output`,
' "' + './nodebb help'.yellow + '" for more commands\n'.reset, ` "${'./nodebb help'.yellow}${'" for more commands\n'.reset}`,
].join('\n')); ].join('\n')}`);
} }
// Spawn a new NodeBB process // Spawn a new NodeBB process
@ -96,15 +96,15 @@ function restart(options) {
function status() { function status() {
getRunningPid(function (err, pid) { getRunningPid(function (err, pid) {
if (!err) { if (!err) {
console.log('\n' + [ console.log(`\n${[
'NodeBB Running '.bold + ('(pid ' + pid.toString() + ')').cyan, 'NodeBB Running '.bold + (`(pid ${pid.toString()})`).cyan,
'\t"' + './nodebb stop'.yellow + '" to stop the NodeBB server', `\t"${'./nodebb stop'.yellow}" to stop the NodeBB server`,
'\t"' + './nodebb log'.yellow + '" to view server output', `\t"${'./nodebb log'.yellow}" to view server output`,
'\t"' + './nodebb restart'.yellow + '" to restart NodeBB\n', `\t"${'./nodebb restart'.yellow}" to restart NodeBB\n`,
].join('\n')); ].join('\n')}`);
} else { } else {
console.log('\nNodeBB is not running'.bold); console.log('\nNodeBB is not running'.bold);
console.log('\t"' + './nodebb start'.yellow + '" to launch the NodeBB server\n'.reset); console.log(`\t"${'./nodebb start'.yellow}${'" to launch the NodeBB server\n'.reset}`);
} }
}); });
} }

@ -16,7 +16,7 @@ function setup(initConfig) {
winston.info('NodeBB Setup Triggered via Command Line'); winston.info('NodeBB Setup Triggered via Command Line');
console.log('\nWelcome to NodeBB v' + pkg.version + '!'); console.log(`\nWelcome to NodeBB v${pkg.version}!`);
console.log('\nThis looks like a new installation, so you\'ll have to answer a few questions about your environment before we can proceed.'); console.log('\nThis looks like a new installation, so you\'ll have to answer a few questions about your environment before we can proceed.');
console.log('Press enter to accept the default setting (shown in brackets).'); console.log('Press enter to accept the default setting (shown in brackets).');
@ -50,16 +50,16 @@ function setup(initConfig) {
separator += '='; separator += '=';
} }
} }
console.log('\n' + separator + '\n'); console.log(`\n${separator}\n`);
if (err) { if (err) {
winston.error('There was a problem completing NodeBB setup\n' + err.stack); winston.error(`There was a problem completing NodeBB setup\n${err.stack}`);
throw err; throw err;
} else { } else {
if (data.hasOwnProperty('password')) { if (data.hasOwnProperty('password')) {
console.log('An administrative user was automatically created for you:'); console.log('An administrative user was automatically created for you:');
console.log(' Username: ' + data.username + ''); console.log(` Username: ${data.username}`);
console.log(' Password: ' + data.password + ''); console.log(` Password: ${data.password}`);
console.log(''); console.log('');
} }
console.log('NodeBB Setup Completed. Run "./nodebb start" to manually start your NodeBB server.'); console.log('NodeBB Setup Completed. Run "./nodebb start" to manually start your NodeBB server.');

@ -126,7 +126,7 @@ function checkPlugins(standalone, callback) {
request({ request({
method: 'GET', method: 'GET',
url: 'https://packages.nodebb.org/api/v1/suggest?version=' + payload.version + '&package[]=' + toCheck.join('&package[]='), url: `https://packages.nodebb.org/api/v1/suggest?version=${payload.version}&package[]=${toCheck.join('&package[]=')}`,
json: true, json: true,
}, function (err, res, body) { }, function (err, res, body) {
if (err) { if (err) {
@ -175,9 +175,9 @@ function upgradePlugins(callback) {
} }
if (found && found.length) { if (found && found.length) {
process.stdout.write('\n\nA total of ' + String(found.length).bold + ' package(s) can be upgraded:\n\n'); process.stdout.write(`\n\nA total of ${String(found.length).bold} package(s) can be upgraded:\n\n`);
found.forEach(function (suggestObj) { found.forEach(function (suggestObj) {
process.stdout.write(' * '.yellow + suggestObj.name.reset + ' (' + suggestObj.current.yellow + ' -> '.reset + suggestObj.suggested.green + ')\n'.reset); process.stdout.write(`${' * '.yellow + suggestObj.name.reset} (${suggestObj.current.yellow}${' -> '.reset}${suggestObj.suggested.green}${')\n'.reset}`);
}); });
} else { } else {
if (standalone) { if (standalone) {
@ -202,7 +202,7 @@ function upgradePlugins(callback) {
if (['y', 'Y', 'yes', 'YES'].includes(result.upgrade)) { if (['y', 'Y', 'yes', 'YES'].includes(result.upgrade)) {
console.log('\nUpgrading packages...'); console.log('\nUpgrading packages...');
const args = packageManagerInstallArgs.concat(found.map(function (suggestObj) { const args = packageManagerInstallArgs.concat(found.map(function (suggestObj) {
return suggestObj.name + '@' + suggestObj.suggested; return `${suggestObj.name}@${suggestObj.suggested}`;
})); }));
cproc.execFile(packageManagerExecutable, args, { stdio: 'ignore' }, function (err) { cproc.execFile(packageManagerExecutable, args, { stdio: 'ignore' }, function (err) {

@ -55,7 +55,7 @@ var steps = {
function runSteps(tasks) { function runSteps(tasks) {
tasks = tasks.map(function (key, i) { tasks = tasks.map(function (key, i) {
return function (next) { return function (next) {
process.stdout.write('\n' + ((i + 1) + '. ').bold + steps[key].message.yellow); process.stdout.write(`\n${(`${i + 1}. `).bold}${steps[key].message.yellow}`);
return steps[key].handler(function (err) { return steps[key].handler(function (err) {
if (err) { return next(err); } if (err) { return next(err); }
next(); next();
@ -65,7 +65,7 @@ function runSteps(tasks) {
async.series(tasks, function (err) { async.series(tasks, function (err) {
if (err) { if (err) {
console.error('Error occurred during upgrade: ' + err.stack); console.error(`Error occurred during upgrade: ${err.stack}`);
throw err; throw err;
} }
@ -74,7 +74,7 @@ function runSteps(tasks) {
var columns = process.stdout.columns; var columns = process.stdout.columns;
var spaces = columns ? new Array(Math.floor(columns / 2) - (message.length / 2) + 1).join(' ') : ' '; var spaces = columns ? new Array(Math.floor(columns / 2) - (message.length / 2) + 1).join(' ') : ' ';
console.log('\n\n' + spaces + message.green.bold + '\n'.reset); console.log(`\n\n${spaces}${message.green.bold}${'\n'.reset}`);
process.exit(); process.exit();
}); });

@ -10,7 +10,7 @@ const middleware = require('../middleware');
exports.handle404 = function handle404(req, res) { exports.handle404 = function handle404(req, res) {
const relativePath = nconf.get('relative_path'); const relativePath = nconf.get('relative_path');
const isClientScript = new RegExp('^' + relativePath + '\\/assets\\/src\\/.+\\.js(\\?v=\\w+)?$'); const isClientScript = new RegExp(`^${relativePath}\\/assets\\/src\\/.+\\.js(\\?v=\\w+)?$`);
if (plugins.hooks.hasListeners('action:meta.override404')) { if (plugins.hooks.hasListeners('action:meta.override404')) {
return plugins.hooks.fire('action:meta.override404', { return plugins.hooks.fire('action:meta.override404', {
@ -22,12 +22,12 @@ exports.handle404 = function handle404(req, res) {
if (isClientScript.test(req.url)) { if (isClientScript.test(req.url)) {
res.type('text/javascript').status(404).send('Not Found'); res.type('text/javascript').status(404).send('Not Found');
} else if (req.path.startsWith(relativePath + '/assets/uploads') || (req.get('accept') && !req.get('accept').includes('text/html')) || req.path === '/favicon.ico') { } else if (req.path.startsWith(`${relativePath}/assets/uploads`) || (req.get('accept') && !req.get('accept').includes('text/html')) || req.path === '/favicon.ico') {
meta.errors.log404(req.path || ''); meta.errors.log404(req.path || '');
res.sendStatus(404); res.sendStatus(404);
} else if (req.accepts('html')) { } else if (req.accepts('html')) {
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
winston.warn('Route requested but not found: ' + req.url); winston.warn(`Route requested but not found: ${req.url}`);
} }
meta.errors.log404(req.path.replace(/^\/api/, '') || ''); meta.errors.log404(req.path.replace(/^\/api/, '') || '');

@ -28,12 +28,12 @@ blocksController.getBlocks = async function (req, res, next) {
data.uids = data.uids.slice(start, stop + 1); data.uids = data.uids.slice(start, stop + 1);
userData.users = await user.getUsers(data.uids, req.uid); userData.users = await user.getUsers(data.uids, req.uid);
userData.title = '[[pages:account/blocks, ' + userData.username + ']]'; userData.title = `[[pages:account/blocks, ${userData.username}]]`;
const pageCount = Math.ceil(userData.counts.blocks / resultsPerPage); const pageCount = Math.ceil(userData.counts.blocks / resultsPerPage);
userData.pagination = pagination.create(page, pageCount); userData.pagination = pagination.create(page, pageCount);
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[user:blocks]]' }]); userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: '[[user:blocks]]' }]);
res.render('account/blocks', userData); res.render('account/blocks', userData);
}; };

@ -34,9 +34,9 @@ categoriesController.get = async function (req, res, next) {
} }
}); });
userData.categories = categoriesData; userData.categories = categoriesData;
userData.title = '[[pages:account/watched_categories, ' + userData.username + ']]'; userData.title = `[[pages:account/watched_categories, ${userData.username}]]`;
userData.breadcrumbs = helpers.buildBreadcrumbs([ userData.breadcrumbs = helpers.buildBreadcrumbs([
{ text: userData.username, url: '/user/' + userData.userslug }, { text: userData.username, url: `/user/${userData.userslug}` },
{ text: '[[pages:categories]]' }, { text: '[[pages:categories]]' },
]); ]);
userData.pagination = pagination.create(page, pageCount, req.query); userData.pagination = pagination.create(page, pageCount, req.query);

@ -61,5 +61,5 @@ chatsController.redirectToChat = async function (req, res, next) {
return next(); return next();
} }
const roomid = parseInt(req.params.roomid, 10); const roomid = parseInt(req.params.roomid, 10);
helpers.redirect(res, '/user/' + userslug + '/chats' + (roomid ? '/' + roomid : '')); helpers.redirect(res, `/user/${userslug}/chats${roomid ? `/${roomid}` : ''}`);
}; };

@ -16,7 +16,7 @@ consentController.get = async function (req, res, next) {
if (!userData) { if (!userData) {
return next(); return next();
} }
const consented = await db.getObjectField('user:' + userData.uid, 'gdpr_consent'); const consented = await db.getObjectField(`user:${userData.uid}`, 'gdpr_consent');
userData.gdpr_consent = parseInt(consented, 10) === 1; userData.gdpr_consent = parseInt(consented, 10) === 1;
userData.digest = { userData.digest = {
frequency: meta.config.dailyDigestFreq || 'off', frequency: meta.config.dailyDigestFreq || 'off',
@ -24,7 +24,7 @@ consentController.get = async function (req, res, next) {
}; };
userData.title = '[[user:consent.title]]'; userData.title = '[[user:consent.title]]';
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[user:consent.title]]' }]); userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: '[[user:consent.title]]' }]);
res.render('account/consent', userData); res.render('account/consent', userData);
}; };

@ -24,7 +24,7 @@ editController.get = async function (req, res, next) {
userData.allowProfilePicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:profile-picture']; userData.allowProfilePicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:profile-picture'];
userData.allowCoverPicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:cover-picture']; userData.allowCoverPicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:cover-picture'];
userData.allowProfileImageUploads = meta.config.allowProfileImageUploads; userData.allowProfileImageUploads = meta.config.allowProfileImageUploads;
userData.allowedProfileImageExtensions = user.getAllowedProfileImageExtensions().map(ext => '.' + ext).join(', '); userData.allowedProfileImageExtensions = user.getAllowedProfileImageExtensions().map(ext => `.${ext}`).join(', ');
userData.allowMultipleBadges = meta.config.allowMultipleBadges === 1; userData.allowMultipleBadges = meta.config.allowMultipleBadges === 1;
userData.allowAccountDelete = meta.config.allowAccountDelete === 1; userData.allowAccountDelete = meta.config.allowAccountDelete === 1;
userData.allowWebsite = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:website']; userData.allowWebsite = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:website'];
@ -55,11 +55,11 @@ editController.get = async function (req, res, next) {
}); });
userData.groupSelectSize = Math.min(10, Math.max(5, userData.groups.length + 1)); userData.groupSelectSize = Math.min(10, Math.max(5, userData.groups.length + 1));
userData.title = '[[pages:account/edit, ' + userData.username + ']]'; userData.title = `[[pages:account/edit, ${userData.username}]]`;
userData.breadcrumbs = helpers.buildBreadcrumbs([ userData.breadcrumbs = helpers.buildBreadcrumbs([
{ {
text: userData.username, text: userData.username,
url: '/user/' + userData.userslug, url: `/user/${userData.userslug}`,
}, },
{ {
text: '[[user:edit]]', text: '[[user:edit]]',
@ -86,7 +86,7 @@ async function renderRoute(name, req, res, next) {
if (!userData) { if (!userData) {
return next(); return next();
} }
if (meta.config[name + ':disableEdit'] && !userData.isAdmin) { if (meta.config[`${name}:disableEdit`] && !userData.isAdmin) {
return helpers.notAllowed(req, res); return helpers.notAllowed(req, res);
} }
@ -95,22 +95,22 @@ async function renderRoute(name, req, res, next) {
userData.minimumPasswordStrength = meta.config.minimumPasswordStrength; userData.minimumPasswordStrength = meta.config.minimumPasswordStrength;
} }
userData.title = '[[pages:account/edit/' + name + ', ' + userData.username + ']]'; userData.title = `[[pages:account/edit/${name}, ${userData.username}]]`;
userData.breadcrumbs = helpers.buildBreadcrumbs([ userData.breadcrumbs = helpers.buildBreadcrumbs([
{ {
text: userData.username, text: userData.username,
url: '/user/' + userData.userslug, url: `/user/${userData.userslug}`,
}, },
{ {
text: '[[user:edit]]', text: '[[user:edit]]',
url: '/user/' + userData.userslug + '/edit', url: `/user/${userData.userslug}/edit`,
}, },
{ {
text: '[[user:' + name + ']]', text: `[[user:${name}]]`,
}, },
]); ]);
res.render('account/edit/' + name, userData); res.render(`account/edit/${name}`, userData);
} }
async function getUserData(req) { async function getUserData(req) {

@ -26,7 +26,7 @@ async function getFollow(tpl, name, req, res, next) {
const start = Math.max(0, page - 1) * resultsPerPage; const start = Math.max(0, page - 1) * resultsPerPage;
const stop = start + resultsPerPage - 1; const stop = start + resultsPerPage - 1;
userData.title = '[[pages:' + tpl + ', ' + userData.username + ']]'; userData.title = `[[pages:${tpl}, ${userData.username}]]`;
const method = name === 'following' ? 'getFollowing' : 'getFollowers'; const method = name === 'following' ? 'getFollowing' : 'getFollowers';
userData.users = await user[method](userData.uid, start, stop); userData.users = await user[method](userData.uid, start, stop);
@ -35,7 +35,7 @@ async function getFollow(tpl, name, req, res, next) {
const pageCount = Math.ceil(count / resultsPerPage); const pageCount = Math.ceil(count / resultsPerPage);
userData.pagination = pagination.create(page, pageCount); userData.pagination = pagination.create(page, pageCount);
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[user:' + name + ']]' }]); userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: `[[user:${name}]]` }]);
res.render(tpl, userData); res.render(tpl, userData);
} }

@ -19,7 +19,7 @@ groupsController.get = async function (req, res, next) {
group.members = members[index]; group.members = members[index];
}); });
userData.groups = groupsData; userData.groups = groupsData;
userData.title = '[[pages:account/groups, ' + userData.username + ']]'; userData.title = `[[pages:account/groups, ${userData.username}]]`;
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[global:header.groups]]' }]); userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: '[[global:header.groups]]' }]);
res.render('account/groups', userData); res.render('account/groups', userData);
}; };

@ -93,7 +93,7 @@ helpers.getUserDataByUserSlug = async function (userslug, callerUID) {
userData.sso = results.sso.associations; userData.sso = results.sso.associations;
userData.banned = Boolean(userData.banned); userData.banned = Boolean(userData.banned);
userData.website = validator.escape(String(userData.website || '')); userData.website = validator.escape(String(userData.website || ''));
userData.websiteLink = !userData.website.startsWith('http') ? 'http://' + userData.website : userData.website; userData.websiteLink = !userData.website.startsWith('http') ? `http://${userData.website}` : userData.website;
userData.websiteName = userData.website.replace(validator.escape('http://'), '').replace(validator.escape('https://'), ''); userData.websiteName = userData.website.replace(validator.escape('http://'), '').replace(validator.escape('https://'), '');
userData.fullname = validator.escape(String(userData.fullname || '')); userData.fullname = validator.escape(String(userData.fullname || ''));
@ -143,17 +143,17 @@ async function getCounts(userData, callerUID) {
const uid = userData.uid; const uid = userData.uid;
const cids = await categories.getCidsByPrivilege('categories:cid', callerUID, 'topics:read'); const cids = await categories.getCidsByPrivilege('categories:cid', callerUID, 'topics:read');
const promises = { const promises = {
posts: db.sortedSetsCardSum(cids.map(c => 'cid:' + c + ':uid:' + uid + ':pids')), posts: db.sortedSetsCardSum(cids.map(c => `cid:${c}:uid:${uid}:pids`)),
best: db.sortedSetsCardSum(cids.map(c => 'cid:' + c + ':uid:' + uid + ':pids:votes')), best: db.sortedSetsCardSum(cids.map(c => `cid:${c}:uid:${uid}:pids:votes`)),
topics: db.sortedSetsCardSum(cids.map(c => 'cid:' + c + ':uid:' + uid + ':tids')), topics: db.sortedSetsCardSum(cids.map(c => `cid:${c}:uid:${uid}:tids`)),
}; };
if (userData.isAdmin || userData.isSelf) { if (userData.isAdmin || userData.isSelf) {
promises.ignored = db.sortedSetCard('uid:' + uid + ':ignored_tids'); promises.ignored = db.sortedSetCard(`uid:${uid}:ignored_tids`);
promises.watched = db.sortedSetCard('uid:' + uid + ':followed_tids'); promises.watched = db.sortedSetCard(`uid:${uid}:followed_tids`);
promises.upvoted = db.sortedSetCard('uid:' + uid + ':upvote'); promises.upvoted = db.sortedSetCard(`uid:${uid}:upvote`);
promises.downvoted = db.sortedSetCard('uid:' + uid + ':downvote'); promises.downvoted = db.sortedSetCard(`uid:${uid}:downvote`);
promises.bookmarks = db.sortedSetCard('uid:' + uid + ':bookmarks'); promises.bookmarks = db.sortedSetCard(`uid:${uid}:bookmarks`);
promises.uploaded = db.sortedSetCard('uid:' + uid + ':uploads'); promises.uploaded = db.sortedSetCard(`uid:${uid}:uploads`);
promises.categoriesWatched = user.getWatchedCategories(uid); promises.categoriesWatched = user.getWatchedCategories(uid);
promises.blocks = user.getUserField(userData.uid, 'blocksCount'); promises.blocks = user.getUserField(userData.uid, 'blocksCount');
} }

@ -21,8 +21,8 @@ infoController.get = async function (req, res, next) {
const [history, sessions, usernames, emails, notes] = await Promise.all([ const [history, sessions, usernames, emails, notes] = await Promise.all([
user.getModerationHistory(userData.uid), user.getModerationHistory(userData.uid),
user.auth.getSessions(userData.uid, req.sessionID), user.auth.getSessions(userData.uid, req.sessionID),
user.getHistory('user:' + userData.uid + ':usernames'), user.getHistory(`user:${userData.uid}:usernames`),
user.getHistory('user:' + userData.uid + ':emails'), user.getHistory(`user:${userData.uid}:emails`),
getNotes(userData, start, stop), getNotes(userData, start, stop),
]); ]);
@ -37,7 +37,7 @@ infoController.get = async function (req, res, next) {
userData.pagination = pagination.create(page, pageCount, req.query); userData.pagination = pagination.create(page, pageCount, req.query);
} }
userData.title = '[[pages:account/info]]'; userData.title = '[[pages:account/info]]';
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[user:account_info]]' }]); userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: '[[user:account_info]]' }]);
res.render('account/info', userData); res.render('account/info', userData);
}; };
@ -48,7 +48,7 @@ async function getNotes(userData, start, stop) {
} }
const [notes, count] = await Promise.all([ const [notes, count] = await Promise.all([
user.getModerationNotes(userData.uid, start, stop), user.getModerationNotes(userData.uid, start, stop),
db.sortedSetCard('uid:' + userData.uid + ':moderation:notes'), db.sortedSetCard(`uid:${userData.uid}:moderation:notes`),
]); ]);
return { notes: notes, count: count }; return { notes: notes, count: count };
} }

@ -17,7 +17,7 @@ const templateToData = {
noItemsFoundKey: '[[topic:bookmarks.has_no_bookmarks]]', noItemsFoundKey: '[[topic:bookmarks.has_no_bookmarks]]',
crumb: '[[user:bookmarks]]', crumb: '[[user:bookmarks]]',
getSets: function (callerUid, userData) { getSets: function (callerUid, userData) {
return 'uid:' + userData.uid + ':bookmarks'; return `uid:${userData.uid}:bookmarks`;
}, },
}, },
'account/posts': { 'account/posts': {
@ -26,7 +26,7 @@ const templateToData = {
crumb: '[[global:posts]]', crumb: '[[global:posts]]',
getSets: async function (callerUid, userData) { getSets: async function (callerUid, userData) {
const cids = await categories.getCidsByPrivilege('categories:cid', callerUid, 'topics:read'); const cids = await categories.getCidsByPrivilege('categories:cid', callerUid, 'topics:read');
return cids.map(c => 'cid:' + c + ':uid:' + userData.uid + ':pids'); return cids.map(c => `cid:${c}:uid:${userData.uid}:pids`);
}, },
}, },
'account/upvoted': { 'account/upvoted': {
@ -34,7 +34,7 @@ const templateToData = {
noItemsFoundKey: '[[user:has_no_upvoted_posts]]', noItemsFoundKey: '[[user:has_no_upvoted_posts]]',
crumb: '[[global:upvoted]]', crumb: '[[global:upvoted]]',
getSets: function (callerUid, userData) { getSets: function (callerUid, userData) {
return 'uid:' + userData.uid + ':upvote'; return `uid:${userData.uid}:upvote`;
}, },
}, },
'account/downvoted': { 'account/downvoted': {
@ -42,7 +42,7 @@ const templateToData = {
noItemsFoundKey: '[[user:has_no_downvoted_posts]]', noItemsFoundKey: '[[user:has_no_downvoted_posts]]',
crumb: '[[global:downvoted]]', crumb: '[[global:downvoted]]',
getSets: function (callerUid, userData) { getSets: function (callerUid, userData) {
return 'uid:' + userData.uid + ':downvote'; return `uid:${userData.uid}:downvote`;
}, },
}, },
'account/best': { 'account/best': {
@ -51,7 +51,7 @@ const templateToData = {
crumb: '[[global:best]]', crumb: '[[global:best]]',
getSets: async function (callerUid, userData) { getSets: async function (callerUid, userData) {
const cids = await categories.getCidsByPrivilege('categories:cid', callerUid, 'topics:read'); const cids = await categories.getCidsByPrivilege('categories:cid', callerUid, 'topics:read');
return cids.map(c => 'cid:' + c + ':uid:' + userData.uid + ':pids:votes'); return cids.map(c => `cid:${c}:uid:${userData.uid}:pids:votes`);
}, },
}, },
'account/watched': { 'account/watched': {
@ -59,7 +59,7 @@ const templateToData = {
noItemsFoundKey: '[[user:has_no_watched_topics]]', noItemsFoundKey: '[[user:has_no_watched_topics]]',
crumb: '[[user:watched]]', crumb: '[[user:watched]]',
getSets: function (callerUid, userData) { getSets: function (callerUid, userData) {
return 'uid:' + userData.uid + ':followed_tids'; return `uid:${userData.uid}:followed_tids`;
}, },
getTopics: async function (set, req, start, stop) { getTopics: async function (set, req, start, stop) {
const sort = req.query.sort; const sort = req.query.sort;
@ -92,7 +92,7 @@ const templateToData = {
noItemsFoundKey: '[[user:has_no_ignored_topics]]', noItemsFoundKey: '[[user:has_no_ignored_topics]]',
crumb: '[[user:ignored]]', crumb: '[[user:ignored]]',
getSets: function (callerUid, userData) { getSets: function (callerUid, userData) {
return 'uid:' + userData.uid + ':ignored_tids'; return `uid:${userData.uid}:ignored_tids`;
}, },
}, },
'account/topics': { 'account/topics': {
@ -101,7 +101,7 @@ const templateToData = {
crumb: '[[global:topics]]', crumb: '[[global:topics]]',
getSets: async function (callerUid, userData) { getSets: async function (callerUid, userData) {
const cids = await categories.getCidsByPrivilege('categories:cid', callerUid, 'topics:read'); const cids = await categories.getCidsByPrivilege('categories:cid', callerUid, 'topics:read');
return cids.map(c => 'cid:' + c + ':uid:' + userData.uid + ':tids'); return cids.map(c => `cid:${c}:uid:${userData.uid}:tids`);
}, },
}, },
}; };
@ -167,19 +167,19 @@ async function getFromUserSet(template, req, res, callback) {
userData.pagination = pagination.create(page, pageCount, req.query); userData.pagination = pagination.create(page, pageCount, req.query);
userData.noItemsFoundKey = data.noItemsFoundKey; userData.noItemsFoundKey = data.noItemsFoundKey;
userData.title = '[[pages:' + template + ', ' + userData.username + ']]'; userData.title = `[[pages:${template}, ${userData.username}]]`;
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: data.crumb }]); userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: data.crumb }]);
userData.showSort = template === 'account/watched'; userData.showSort = template === 'account/watched';
const baseUrl = (req.baseUrl + req.path.replace(/^\/api/, '')); const baseUrl = (req.baseUrl + req.path.replace(/^\/api/, ''));
userData.sortOptions = [ userData.sortOptions = [
{ url: baseUrl + '?sort=votes', name: '[[global:votes]]' }, { url: `${baseUrl}?sort=votes`, name: '[[global:votes]]' },
{ url: baseUrl + '?sort=posts', name: '[[global:posts]]' }, { url: `${baseUrl}?sort=posts`, name: '[[global:posts]]' },
{ url: baseUrl + '?sort=views', name: '[[global:views]]' }, { url: `${baseUrl}?sort=views`, name: '[[global:views]]' },
{ url: baseUrl + '?sort=lastpost', name: '[[global:lastpost]]' }, { url: `${baseUrl}?sort=lastpost`, name: '[[global:lastpost]]' },
{ url: baseUrl + '?sort=firstpost', name: '[[global:firstpost]]' }, { url: `${baseUrl}?sort=firstpost`, name: '[[global:firstpost]]' },
]; ];
userData.sortOptions.forEach(function (option) { userData.sortOptions.forEach(function (option) {
option.selected = option.url.includes('sort=' + req.query.sort); option.selected = option.url.includes(`sort=${req.query.sort}`);
}); });
res.render(template, userData); res.render(template, userData);

@ -21,7 +21,7 @@ profileController.get = async function (req, res, next) {
if (res.locals.isAPI) { if (res.locals.isAPI) {
req.params.userslug = lowercaseSlug; req.params.userslug = lowercaseSlug;
} else { } else {
return res.redirect(nconf.get('relative_path') + '/user/' + lowercaseSlug); return res.redirect(`${nconf.get('relative_path')}/user/${lowercaseSlug}`);
} }
} }
@ -82,7 +82,7 @@ async function getBestPosts(callerUid, userData) {
async function getPosts(callerUid, userData, setSuffix) { async function getPosts(callerUid, userData, setSuffix) {
const cids = await categories.getCidsByPrivilege('categories:cid', callerUid, 'topics:read'); const cids = await categories.getCidsByPrivilege('categories:cid', callerUid, 'topics:read');
const keys = cids.map(c => 'cid:' + c + ':uid:' + userData.uid + ':' + setSuffix); const keys = cids.map(c => `cid:${c}:uid:${userData.uid}:${setSuffix}`);
let hasMorePosts = true; let hasMorePosts = true;
let start = 0; let start = 0;
const count = 10; const count = 10;

@ -14,7 +14,7 @@ sessionController.get = async function (req, res, next) {
userData.sessions = await user.auth.getSessions(userData.uid, req.sessionID); userData.sessions = await user.auth.getSessions(userData.uid, req.sessionID);
userData.title = '[[pages:account/sessions]]'; userData.title = '[[pages:account/sessions]]';
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[pages:account/sessions]]' }]); userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: '[[pages:account/sessions]]' }]);
res.render('account/sessions', userData); res.render('account/sessions', userData);
}; };

@ -116,7 +116,7 @@ settingsController.get = async function (req, res, next) {
userData.maxPostsPerPage = meta.config.maxPostsPerPage; userData.maxPostsPerPage = meta.config.maxPostsPerPage;
userData.title = '[[pages:account/settings]]'; userData.title = '[[pages:account/settings]]';
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[user:settings]]' }]); userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: '[[user:settings]]' }]);
res.render('account/settings', userData); res.render('account/settings', userData);
}; };
@ -132,8 +132,8 @@ const doUnsubscribe = async (payload) => {
user.updateDigestSetting(payload.uid, 'off'), user.updateDigestSetting(payload.uid, 'off'),
]); ]);
} else if (payload.template === 'notification') { } else if (payload.template === 'notification') {
const current = await db.getObjectField('user:' + payload.uid + ':settings', 'notificationType_' + payload.type); const current = await db.getObjectField(`user:${payload.uid}:settings`, `notificationType_${payload.type}`);
await user.setSetting(payload.uid, 'notificationType_' + payload.type, (current === 'notificationemail' ? 'notification' : 'none')); await user.setSetting(payload.uid, `notificationType_${payload.type}`, (current === 'notificationemail' ? 'notification' : 'none'));
} }
return true; return true;
}; };
@ -173,7 +173,7 @@ settingsController.unsubscribePost = async function (req, res) {
await doUnsubscribe(payload); await doUnsubscribe(payload);
res.sendStatus(200); res.sendStatus(200);
} catch (err) { } catch (err) {
winston.error('[settings/unsubscribe] One-click unsubscribe failed with error: ' + err.message); winston.error(`[settings/unsubscribe] One-click unsubscribe failed with error: ${err.message}`);
res.sendStatus(500); res.sendStatus(500);
} }
}; };
@ -200,7 +200,7 @@ async function getNotificationSettings(userData) {
const setting = userData.settings[type]; const setting = userData.settings[type];
return { return {
name: type, name: type,
label: '[[notifications:' + type + ']]', label: `[[notifications:${type}]]`,
none: setting === 'none', none: setting === 'none',
notification: setting === 'notification', notification: setting === 'notification',
email: setting === 'email', email: setting === 'email',

@ -21,8 +21,8 @@ uploadsController.get = async function (req, res, next) {
const start = (page - 1) * itemsPerPage; const start = (page - 1) * itemsPerPage;
const stop = start + itemsPerPage - 1; const stop = start + itemsPerPage - 1;
const [itemCount, uploadNames] = await Promise.all([ const [itemCount, uploadNames] = await Promise.all([
db.sortedSetCard('uid:' + userData.uid + ':uploads'), db.sortedSetCard(`uid:${userData.uid}:uploads`),
db.getSortedSetRevRange('uid:' + userData.uid + ':uploads', start, stop), db.getSortedSetRevRange(`uid:${userData.uid}:uploads`, start, stop),
]); ]);
userData.uploads = uploadNames.map(function (uploadName) { userData.uploads = uploadNames.map(function (uploadName) {
@ -34,7 +34,7 @@ uploadsController.get = async function (req, res, next) {
const pageCount = Math.ceil(itemCount / itemsPerPage); const pageCount = Math.ceil(itemCount / itemsPerPage);
userData.pagination = pagination.create(page, pageCount, req.query); userData.pagination = pagination.create(page, pageCount, req.query);
userData.privateUploads = meta.config.privateUploads === 1; userData.privateUploads = meta.config.privateUploads === 1;
userData.title = '[[pages:account/uploads, ' + userData.username + ']]'; userData.title = `[[pages:account/uploads, ${userData.username}]]`;
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[global:uploads]]' }]); userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: '[[global:uploads]]' }]);
res.render('account/uploads', userData); res.render('account/uploads', userData);
}; };

@ -5,5 +5,5 @@ const appearanceController = module.exports;
appearanceController.get = function (req, res) { appearanceController.get = function (req, res) {
const term = req.params.term ? req.params.term : 'themes'; const term = req.params.term ? req.params.term : 'themes';
res.render('admin/appearance/' + term, {}); res.render(`admin/appearance/${term}`, {});
}; };

@ -48,7 +48,7 @@ cacheController.dump = function (req, res, next) {
} }
const data = JSON.stringify(caches[req.query.name].dump(), null, 4); const data = JSON.stringify(caches[req.query.name].dump(), null, 4);
res.setHeader('Content-disposition', 'attachment; filename= ' + req.query.name + '-cache.json'); res.setHeader('Content-disposition', `attachment; filename= ${req.query.name}-cache.json`);
res.setHeader('Content-type', 'application/json'); res.setHeader('Content-type', 'application/json');
res.write(data, function (err) { res.write(data, function (err) {
if (err) { if (err) {

@ -109,7 +109,7 @@ async function buildBreadcrumbs(req, categoryData) {
const breadcrumbs = [ const breadcrumbs = [
{ {
text: categoryData.name, text: categoryData.name,
url: nconf.get('relative_path') + '/admin/manage/categories?cid=' + categoryData.cid, url: `${nconf.get('relative_path')}/admin/manage/categories?cid=${categoryData.cid}`,
cid: categoryData.cid, cid: categoryData.cid,
}, },
]; ];
@ -117,7 +117,7 @@ async function buildBreadcrumbs(req, categoryData) {
const crumbs = allCrumbs.filter(c => c.cid); const crumbs = allCrumbs.filter(c => c.cid);
crumbs.forEach(function (c) { crumbs.forEach(function (c) {
c.url = '/admin/manage/categories?cid=' + c.cid; c.url = `/admin/manage/categories?cid=${c.cid}`;
}); });
crumbs.unshift({ crumbs.unshift({
text: '[[admin/manage/categories:top-level]]', text: '[[admin/manage/categories:top-level]]',

@ -69,7 +69,7 @@ async function getLatestVersion() {
try { try {
return await versions.getLatestVersion(); return await versions.getLatestVersion();
} catch (err) { } catch (err) {
winston.error('[acp] Failed to fetch latest version\n' + err.stack); winston.error(`[acp] Failed to fetch latest version\n${err.stack}`);
} }
return null; return null;
} }
@ -94,7 +94,7 @@ dashboardController.getAnalytics = async (req, res, next) => {
} }
const method = req.query.units === 'days' ? analytics.getDailyStatsForSet : analytics.getHourlyStatsForSet; const method = req.query.units === 'days' ? analytics.getDailyStatsForSet : analytics.getHourlyStatsForSet;
let payload = await Promise.all(sets.map(set => method('analytics:' + set, until, count))); let payload = await Promise.all(sets.map(set => method(`analytics:${set}`, until, count)));
payload = _.zipObject(sets, payload); payload = _.zipObject(sets, payload);
res.json({ res.json({

@ -21,7 +21,7 @@ eventsController.get = async function (req, res) {
const currentFilter = req.query.type || ''; const currentFilter = req.query.type || '';
const [eventCount, eventData] = await Promise.all([ const [eventCount, eventData] = await Promise.all([
db.sortedSetCount('events:time' + (currentFilter ? ':' + currentFilter : ''), from || '-inf', to), db.sortedSetCount(`events:time${currentFilter ? `:${currentFilter}` : ''}`, from || '-inf', to),
events.getEvents(currentFilter, start, stop, from || '-inf', to), events.getEvents(currentFilter, start, stop, from || '-inf', to),
]); ]);

@ -85,13 +85,13 @@ groupsController.getCSV = async function (req, res) {
const members = (await groups.getMembersOfGroups([groupName]))[0]; const members = (await groups.getMembersOfGroups([groupName]))[0];
const fields = ['email', 'username', 'uid']; const fields = ['email', 'username', 'uid'];
const userData = await user.getUsersFields(members, fields); const userData = await user.getUsersFields(members, fields);
let csvContent = fields.join(',') + '\n'; let csvContent = `${fields.join(',')}\n`;
csvContent += userData.reduce((memo, user) => { csvContent += userData.reduce((memo, user) => {
memo += user.email + ',' + user.username + ',' + user.uid + '\n'; memo += `${user.email},${user.username},${user.uid}\n`;
return memo; return memo;
}, ''); }, '');
res.attachment(validator.escape(groupName) + '_members.csv'); res.attachment(`${validator.escape(groupName)}_members.csv`);
res.setHeader('Content-Type', 'text/csv'); res.setHeader('Content-Type', 'text/csv');
res.end(csvContent); res.end(csvContent);
}; };

@ -11,7 +11,7 @@ hooksController.get = function (req, res) {
const current = { const current = {
hookName: key, hookName: key,
methods: [], methods: [],
index: 'hook-' + hookIndex, index: `hook-${hookIndex}`,
count: plugins.loadedHooks[key].length, count: plugins.loadedHooks[key].length,
}; };
@ -20,7 +20,7 @@ hooksController.get = function (req, res) {
id: hookData.id, id: hookData.id,
priority: hookData.priority, priority: hookData.priority,
method: hookData.method ? validator.escape(hookData.method.toString()) : 'No plugin function!', method: hookData.method ? validator.escape(hookData.method.toString()) : 'No plugin function!',
index: hookIndex + '-code-' + methodIndex, index: `${hookIndex}-code-${methodIndex}`,
}); });
}); });
hooks.push(current); hooks.push(current);

@ -49,7 +49,7 @@ infoController.get = function (req, res) {
pubsub.on('sync:node:info:start', async function () { pubsub.on('sync:node:info:start', async function () {
try { try {
const data = await getNodeInfo(); const data = await getNodeInfo();
data.id = os.hostname() + ':' + nconf.get('port'); data.id = `${os.hostname()}:${nconf.get('port')}`;
pubsub.publish('sync:node:info:end', { data: data, id: data.id }); pubsub.publish('sync:node:info:end', { data: data, id: data.id });
} catch (err) { } catch (err) {
winston.error(err.stack); winston.error(err.stack);
@ -107,13 +107,13 @@ async function getNodeInfo() {
function humanReadableUptime(seconds) { function humanReadableUptime(seconds) {
if (seconds < 60) { if (seconds < 60) {
return Math.floor(seconds) + 's'; return `${Math.floor(seconds)}s`;
} else if (seconds < 3600) { } else if (seconds < 3600) {
return Math.floor(seconds / 60) + 'm'; return `${Math.floor(seconds / 60)}m`;
} else if (seconds < 3600 * 24) { } else if (seconds < 3600 * 24) {
return Math.floor(seconds / (60 * 60)) + 'h'; return `${Math.floor(seconds / (60 * 60))}h`;
} }
return Math.floor(seconds / (60 * 60 * 24)) + 'd'; return `${Math.floor(seconds / (60 * 60 * 24))}d`;
} }
async function getGitInfo() { async function getGitInfo() {

@ -15,7 +15,7 @@ const settingsController = module.exports;
settingsController.get = async function (req, res) { settingsController.get = async function (req, res) {
const term = req.params.term || 'general'; const term = req.params.term || 'general';
res.render('admin/settings/' + term); res.render(`admin/settings/${term}`);
}; };
settingsController.email = async (req, res) => { settingsController.email = async (req, res) => {
@ -33,7 +33,7 @@ settingsController.user = async (req, res) => {
const notificationSettings = notificationTypes.map(function (type) { const notificationSettings = notificationTypes.map(function (type) {
return { return {
name: type, name: type,
label: '[[notifications:' + type + ']]', label: `[[notifications:${type}]]`,
}; };
}); });
res.render('admin/settings/user', { res.render('admin/settings/user', {

@ -73,8 +73,8 @@ function buildBreadcrumbs(currentFolder) {
crumbs.push({ crumbs.push({
text: part || 'Uploads', text: part || 'Uploads',
url: part ? url: part ?
(nconf.get('relative_path') + '/admin/manage/uploads?dir=' + dir) : (`${nconf.get('relative_path')}/admin/manage/uploads?dir=${dir}`) :
nconf.get('relative_path') + '/admin/manage/uploads', `${nconf.get('relative_path')}/admin/manage/uploads`,
}); });
currentPath = dir; currentPath = dir;
}); });
@ -92,14 +92,14 @@ async function getFileData(currentDir, file) {
if (stat.isDirectory()) { if (stat.isDirectory()) {
filesInDir = await fs.promises.readdir(path.join(currentDir, file)); filesInDir = await fs.promises.readdir(path.join(currentDir, file));
} }
const url = nconf.get('upload_url') + currentDir.replace(nconf.get('upload_path'), '') + '/' + file; const url = `${nconf.get('upload_url') + currentDir.replace(nconf.get('upload_path'), '')}/${file}`;
return { return {
name: file, name: file,
path: path.join(currentDir, file).replace(nconf.get('upload_path'), ''), path: path.join(currentDir, file).replace(nconf.get('upload_path'), ''),
url: url, url: url,
fileCount: Math.max(0, filesInDir.length - 1), // ignore .gitignore fileCount: Math.max(0, filesInDir.length - 1), // ignore .gitignore
size: stat.size, size: stat.size,
sizeHumanReadable: (stat.size / 1024).toFixed(1) + 'KiB', sizeHumanReadable: `${(stat.size / 1024).toFixed(1)}KiB`,
isDirectory: stat.isDirectory(), isDirectory: stat.isDirectory(),
isFile: stat.isFile(), isFile: stat.isFile(),
mtime: stat.mtimeMs, mtime: stat.mtimeMs,
@ -118,7 +118,7 @@ uploadsController.uploadCategoryPicture = async function (req, res, next) {
} }
if (validateUpload(res, uploadedFile, allowedImageTypes)) { if (validateUpload(res, uploadedFile, allowedImageTypes)) {
const filename = 'category-' + params.cid + path.extname(uploadedFile.name); const filename = `category-${params.cid}${path.extname(uploadedFile.name)}`;
await uploadImage(filename, 'category', uploadedFile, req, res, next); await uploadImage(filename, 'category', uploadedFile, req, res, next);
} }
}; };
@ -152,7 +152,7 @@ uploadsController.uploadTouchIcon = async function (req, res, next) {
/* eslint-disable no-await-in-loop */ /* eslint-disable no-await-in-loop */
await image.resizeImage({ await image.resizeImage({
path: uploadedFile.path, path: uploadedFile.path,
target: path.join(nconf.get('upload_path'), 'system', 'touchicon-' + size + '.png'), target: path.join(nconf.get('upload_path'), 'system', `touchicon-${size}.png`),
width: size, width: size,
height: size, height: size,
}); });
@ -227,7 +227,7 @@ async function upload(name, req, res, next) {
function validateUpload(res, uploadedFile, allowedTypes) { function validateUpload(res, uploadedFile, allowedTypes) {
if (!allowedTypes.includes(uploadedFile.type)) { if (!allowedTypes.includes(uploadedFile.type)) {
file.delete(uploadedFile.path); file.delete(uploadedFile.path);
res.json({ error: '[[error:invalid-image-type, ' + allowedTypes.join('&#44; ') + ']]' }); res.json({ error: `[[error:invalid-image-type, ${allowedTypes.join('&#44; ')}]]` });
return false; return false;
} }

@ -153,7 +153,7 @@ usersController.search = async function (req, res) {
} }
const data = await db.getSortedSetScan({ const data = await db.getSortedSetScan({
key: searchBy + ':sorted', key: `${searchBy}:sorted`,
match: query, match: query,
limit: hardCap || (resultsPerPage * 10), limit: hardCap || (resultsPerPage * 10),
}); });
@ -233,13 +233,13 @@ async function render(req, res, data) {
data.inviteOnly = registrationType === 'invite-only' || registrationType === 'admin-invite-only'; data.inviteOnly = registrationType === 'invite-only' || registrationType === 'admin-invite-only';
data.adminInviteOnly = registrationType === 'admin-invite-only'; data.adminInviteOnly = registrationType === 'admin-invite-only';
data['sort_' + data.sortBy] = true; data[`sort_${data.sortBy}`] = true;
if (req.query.searchBy) { if (req.query.searchBy) {
data['searchBy_' + validator.escape(String(req.query.searchBy))] = true; data[`searchBy_${validator.escape(String(req.query.searchBy))}`] = true;
} }
const filterBy = Array.isArray(req.query.filters || []) ? (req.query.filters || []) : [req.query.filters]; const filterBy = Array.isArray(req.query.filters || []) ? (req.query.filters || []) : [req.query.filters];
filterBy.forEach(function (filter) { filterBy.forEach(function (filter) {
data['filterBy_' + validator.escape(String(filter))] = true; data[`filterBy_${validator.escape(String(filter))}`] = true;
}); });
data.userCount = parseInt(await db.getObjectField('global', 'userCount'), 10); data.userCount = parseInt(await db.getObjectField('global', 'userCount'), 10);
if (data.adminInviteOnly) { if (data.adminInviteOnly) {

@ -35,10 +35,10 @@ async function registerAndLoginUser(req, res, userData) {
req.session.registration = userData; req.session.registration = userData;
if (req.body.noscript === 'true') { if (req.body.noscript === 'true') {
res.redirect(nconf.get('relative_path') + '/register/complete'); res.redirect(`${nconf.get('relative_path')}/register/complete`);
return; return;
} }
res.json({ next: nconf.get('relative_path') + '/register/complete' }); res.json({ next: `${nconf.get('relative_path')}/register/complete` });
return; return;
} }
const queue = await user.shouldQueueUser(req.ip); const queue = await user.shouldQueueUser(req.ip);
@ -57,7 +57,7 @@ async function registerAndLoginUser(req, res, userData) {
await user.joinGroupsFromInvitation(uid, userData.email); await user.joinGroupsFromInvitation(uid, userData.email);
} }
await user.deleteInvitationKey(userData.email); await user.deleteInvitationKey(userData.email);
const next = req.session.returnTo || nconf.get('relative_path') + '/'; const next = req.session.returnTo || `${nconf.get('relative_path')}/`;
const complete = await plugins.hooks.fire('filter:register.complete', { uid: uid, next: next }); const complete = await plugins.hooks.fire('filter:register.complete', { uid: uid, next: next });
req.session.returnTo = complete.next; req.session.returnTo = complete.next;
return complete; return complete;
@ -154,17 +154,17 @@ authenticationController.registerComplete = function (req, res, next) {
var done = function (err, data) { var done = function (err, data) {
delete req.session.registration; delete req.session.registration;
if (err) { if (err) {
return res.redirect(nconf.get('relative_path') + '/?register=' + encodeURIComponent(err.message)); return res.redirect(`${nconf.get('relative_path')}/?register=${encodeURIComponent(err.message)}`);
} }
if (!err && data && data.message) { if (!err && data && data.message) {
return res.redirect(nconf.get('relative_path') + '/?register=' + encodeURIComponent(data.message)); return res.redirect(`${nconf.get('relative_path')}/?register=${encodeURIComponent(data.message)}`);
} }
if (req.session.returnTo) { if (req.session.returnTo) {
res.redirect(nconf.get('relative_path') + req.session.returnTo); res.redirect(nconf.get('relative_path') + req.session.returnTo);
} else { } else {
res.redirect(nconf.get('relative_path') + '/'); res.redirect(`${nconf.get('relative_path')}/`);
} }
}; };
@ -174,7 +174,7 @@ authenticationController.registerComplete = function (req, res, next) {
const errors = results.map(result => result.reason && result.reason.message).filter(Boolean); const errors = results.map(result => result.reason && result.reason.message).filter(Boolean);
if (errors.length) { if (errors.length) {
req.flash('errors', errors); req.flash('errors', errors);
return res.redirect(nconf.get('relative_path') + '/register/complete'); return res.redirect(`${nconf.get('relative_path')}/register/complete`);
} }
if (req.session.registration.register === true) { if (req.session.registration.register === true) {
@ -203,7 +203,7 @@ authenticationController.registerAbort = function (req, res) {
// End the session and redirect to home // End the session and redirect to home
req.session.destroy(function () { req.session.destroy(function () {
res.clearCookie(nconf.get('sessionKey'), meta.configs.cookie.get()); res.clearCookie(nconf.get('sessionKey'), meta.configs.cookie.get());
res.redirect(nconf.get('relative_path') + '/'); res.redirect(`${nconf.get('relative_path')}/`);
}); });
}; };
@ -241,7 +241,7 @@ authenticationController.login = async (req, res, next) => {
} else if (loginWith.includes('username') && !validator.isEmail(req.body.username)) { } else if (loginWith.includes('username') && !validator.isEmail(req.body.username)) {
(res.locals.continueLogin || continueLogin)(strategy, req, res, next); (res.locals.continueLogin || continueLogin)(strategy, req, res, next);
} else { } else {
err = '[[error:wrong-login-type-' + loginWith + ']]'; err = `[[error:wrong-login-type-${loginWith}]]`;
(res.locals.noScriptErrors || helpers.noScriptErrors)(req, res, err, 400); (res.locals.noScriptErrors || helpers.noScriptErrors)(req, res, err, 400);
} }
}); });
@ -273,12 +273,12 @@ function continueLogin(strategy, req, res, next) {
plugins.hooks.fire('action:login.continue', { req, userData }); plugins.hooks.fire('action:login.continue', { req, userData });
if (userData.passwordExpiry && userData.passwordExpiry < Date.now()) { if (userData.passwordExpiry && userData.passwordExpiry < Date.now()) {
winston.verbose('[auth] Triggering password reset for uid ' + userData.uid + ' due to password policy'); winston.verbose(`[auth] Triggering password reset for uid ${userData.uid} due to password policy`);
req.session.passwordExpired = true; req.session.passwordExpired = true;
const code = await user.reset.generate(userData.uid); const code = await user.reset.generate(userData.uid);
res.status(200).send({ res.status(200).send({
next: nconf.get('relative_path') + '/reset/' + code, next: `${nconf.get('relative_path')}/reset/${code}`,
}); });
} else { } else {
delete req.query.lang; delete req.query.lang;
@ -290,11 +290,11 @@ function continueLogin(strategy, req, res, next) {
nconf.get('relative_path') + req.session.returnTo; nconf.get('relative_path') + req.session.returnTo;
delete req.session.returnTo; delete req.session.returnTo;
} else { } else {
destination = nconf.get('relative_path') + '/'; destination = `${nconf.get('relative_path')}/`;
} }
if (req.body.noscript === 'true') { if (req.body.noscript === 'true') {
res.redirect(destination + '?loggedin'); res.redirect(`${destination}?loggedin`);
} else { } else {
res.status(200).send({ res.status(200).send({
next: destination, next: destination,
@ -352,11 +352,11 @@ authenticationController.onSuccessfulLogin = async function (req, uid) {
user.updateOnlineUsers(uid), user.updateOnlineUsers(uid),
]); ]);
if (uid > 0) { if (uid > 0) {
await db.setObjectField('uid:' + uid + ':sessionUUID:sessionId', uuid, req.sessionID); await db.setObjectField(`uid:${uid}:sessionUUID:sessionId`, uuid, req.sessionID);
} }
// Force session check for all connected socket.io clients with the same session id // Force session check for all connected socket.io clients with the same session id
sockets.in('sess_' + req.sessionID).emit('checkSession', uid); sockets.in(`sess_${req.sessionID}`).emit('checkSession', uid);
plugins.hooks.fire('action:user.loggedIn', { uid: uid, req: req }); plugins.hooks.fire('action:user.loggedIn', { uid: uid, req: req });
} catch (err) { } catch (err) {
@ -435,9 +435,9 @@ authenticationController.logout = async function (req, res, next) {
await plugins.hooks.fire('static:user.loggedOut', { req: req, res: res, uid: uid, sessionID: sessionID }); await plugins.hooks.fire('static:user.loggedOut', { req: req, res: res, uid: uid, sessionID: sessionID });
// Force session check for all connected socket.io clients with the same session id // Force session check for all connected socket.io clients with the same session id
sockets.in('sess_' + sessionID).emit('checkSession', 0); sockets.in(`sess_${sessionID}`).emit('checkSession', 0);
const payload = { const payload = {
next: nconf.get('relative_path') + '/', next: `${nconf.get('relative_path')}/`,
}; };
plugins.hooks.fire('filter:user.logout', payload); plugins.hooks.fire('filter:user.logout', payload);
@ -458,8 +458,8 @@ async function getBanInfo(uid) {
banInfo.reason = await translator.translate('[[user:info.banned-no-reason]]'); banInfo.reason = await translator.translate('[[user:info.banned-no-reason]]');
} }
return banInfo.banned_until ? return banInfo.banned_until ?
'[[error:user-banned-reason-until, ' + banInfo.banned_until_readable + ', ' + banInfo.reason + ']]' : `[[error:user-banned-reason-until, ${banInfo.banned_until_readable}, ${banInfo.reason}]]` :
'[[error:user-banned-reason, ' + banInfo.reason + ']]'; `[[error:user-banned-reason, ${banInfo.reason}]]`;
} catch (err) { } catch (err) {
if (err.message === 'no-ban-info') { if (err.message === 'no-ban-info') {
return '[[error:user-banned]]'; return '[[error:user-banned]]';

@ -48,7 +48,7 @@ categoriesController.list = async function (req, res) {
} }
}); });
if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/categories') || req.originalUrl.startsWith(nconf.get('relative_path') + '/categories')) { if (req.originalUrl.startsWith(`${nconf.get('relative_path')}/api/categories`) || req.originalUrl.startsWith(`${nconf.get('relative_path')}/categories`)) {
data.title = '[[pages:categories]]'; data.title = '[[pages:categories]]';
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: data.title }]); data.breadcrumbs = helpers.buildBreadcrumbs([{ text: data.title }]);
res.locals.metaTags.push({ res.locals.metaTags.push({

@ -42,19 +42,19 @@ categoryController.get = async function (req, res, next) {
return next(); return next();
} }
if (topicIndex < 0) { if (topicIndex < 0) {
return helpers.redirect(res, '/category/' + categoryFields.slug); return helpers.redirect(res, `/category/${categoryFields.slug}`);
} }
if (!userPrivileges.read) { if (!userPrivileges.read) {
return helpers.notAllowed(req, res); return helpers.notAllowed(req, res);
} }
if (!res.locals.isAPI && (!req.params.slug || categoryFields.slug !== cid + '/' + req.params.slug) && (categoryFields.slug && categoryFields.slug !== cid + '/')) { if (!res.locals.isAPI && (!req.params.slug || categoryFields.slug !== `${cid}/${req.params.slug}`) && (categoryFields.slug && categoryFields.slug !== `${cid}/`)) {
return helpers.redirect(res, '/category/' + categoryFields.slug, true); return helpers.redirect(res, `/category/${categoryFields.slug}`, true);
} }
if (categoryFields.link) { if (categoryFields.link) {
await db.incrObjectField('category:' + cid, 'timesClicked'); await db.incrObjectField(`category:${cid}`, 'timesClicked');
return helpers.redirect(res, validator.unescape(categoryFields.link)); return helpers.redirect(res, validator.unescape(categoryFields.link));
} }
@ -86,7 +86,7 @@ categoryController.get = async function (req, res, next) {
} }
if (topicIndex > Math.max(categoryData.topic_count - 1, 0)) { if (topicIndex > Math.max(categoryData.topic_count - 1, 0)) {
return helpers.redirect(res, '/category/' + categoryData.slug + '/' + categoryData.topic_count); return helpers.redirect(res, `/category/${categoryData.slug}/${categoryData.topic_count}`);
} }
const pageCount = Math.max(1, Math.ceil(categoryData.topic_count / userSettings.topicsPerPage)); const pageCount = Math.max(1, Math.ceil(categoryData.topic_count / userSettings.topicsPerPage));
if (userSettings.usePagination && currentPage > pageCount) { if (userSettings.usePagination && currentPage > pageCount) {
@ -119,10 +119,10 @@ categoryController.get = async function (req, res, next) {
categoryData.showSelect = userPrivileges.editable; categoryData.showSelect = userPrivileges.editable;
categoryData.showTopicTools = userPrivileges.editable; categoryData.showTopicTools = userPrivileges.editable;
categoryData.topicIndex = topicIndex; categoryData.topicIndex = topicIndex;
categoryData.rssFeedUrl = url + '/category/' + categoryData.cid + '.rss'; categoryData.rssFeedUrl = `${url}/category/${categoryData.cid}.rss`;
if (parseInt(req.uid, 10)) { if (parseInt(req.uid, 10)) {
categories.markAsRead([cid], req.uid); categories.markAsRead([cid], req.uid);
categoryData.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken; categoryData.rssFeedUrl += `?uid=${req.uid}&token=${rssToken}`;
} }
addTags(categoryData, res); addTags(categoryData, res);
@ -131,11 +131,11 @@ categoryController.get = async function (req, res, next) {
categoryData['reputation:disabled'] = meta.config['reputation:disabled']; categoryData['reputation:disabled'] = meta.config['reputation:disabled'];
categoryData.pagination = pagination.create(currentPage, pageCount, req.query); categoryData.pagination = pagination.create(currentPage, pageCount, req.query);
categoryData.pagination.rel.forEach(function (rel) { categoryData.pagination.rel.forEach(function (rel) {
rel.href = url + '/category/' + categoryData.slug + rel.href; rel.href = `${url}/category/${categoryData.slug}${rel.href}`;
res.locals.linkTags.push(rel); res.locals.linkTags.push(rel);
}); });
analytics.increment(['pageviews:byCid:' + categoryData.cid]); analytics.increment([`pageviews:byCid:${categoryData.cid}`]);
res.render('category', categoryData); res.render('category', categoryData);
}; };
@ -144,12 +144,12 @@ async function buildBreadcrumbs(req, categoryData) {
const breadcrumbs = [ const breadcrumbs = [
{ {
text: categoryData.name, text: categoryData.name,
url: relative_path + '/category/' + categoryData.slug, url: `${relative_path}/category/${categoryData.slug}`,
cid: categoryData.cid, cid: categoryData.cid,
}, },
]; ];
const crumbs = await helpers.buildCategoryBreadcrumbs(categoryData.parentCid); const crumbs = await helpers.buildCategoryBreadcrumbs(categoryData.parentCid);
if (req.originalUrl.startsWith(relative_path + '/api/category') || req.originalUrl.startsWith(relative_path + '/category')) { if (req.originalUrl.startsWith(`${relative_path}/api/category`) || req.originalUrl.startsWith(`${relative_path}/category`)) {
categoryData.breadcrumbs = crumbs.concat(breadcrumbs); categoryData.breadcrumbs = crumbs.concat(breadcrumbs);
} }
} }

@ -77,11 +77,11 @@ exports.post = async function (req, res) {
throw new Error('[[error:invalid-data]]'); throw new Error('[[error:invalid-data]]');
} }
if (result.queued) { if (result.queued) {
return res.redirect((nconf.get('relative_path') || '/') + '?noScriptMessage=[[success:post-queued]]'); return res.redirect(`${nconf.get('relative_path') || '/'}?noScriptMessage=[[success:post-queued]]`);
} }
const uid = result.uid ? result.uid : result.topicData.uid; const uid = result.uid ? result.uid : result.topicData.uid;
user.updateOnlineUsers(uid); user.updateOnlineUsers(uid);
const path = result.pid ? '/post/' + result.pid : '/topic/' + result.topicData.slug; const path = result.pid ? `/post/${result.pid}` : `/topic/${result.topicData.slug}`;
res.redirect(nconf.get('relative_path') + path); res.redirect(nconf.get('relative_path') + path);
} catch (err) { } catch (err) {
helpers.noScriptErrors(req, res, err.message, 400); helpers.noScriptErrors(req, res, err.message, 400);

@ -9,7 +9,7 @@ var middleware = require('../middleware');
exports.handleURIErrors = async function handleURIErrors(err, req, res, next) { exports.handleURIErrors = async function handleURIErrors(err, req, res, next) {
// Handle cases where malformed URIs are passed in // Handle cases where malformed URIs are passed in
if (err instanceof URIError) { if (err instanceof URIError) {
const cleanPath = req.path.replace(new RegExp('^' + nconf.get('relative_path')), ''); const cleanPath = req.path.replace(new RegExp(`^${nconf.get('relative_path')}`), '');
var tidMatch = cleanPath.match(/^\/topic\/(\d+)\//); var tidMatch = cleanPath.match(/^\/topic\/(\d+)\//);
var cidMatch = cleanPath.match(/^\/category\/(\d+)\//); var cidMatch = cleanPath.match(/^\/category\/(\d+)\//);
@ -18,8 +18,8 @@ exports.handleURIErrors = async function handleURIErrors(err, req, res, next) {
} else if (cidMatch) { } else if (cidMatch) {
res.redirect(nconf.get('relative_path') + cidMatch[0]); res.redirect(nconf.get('relative_path') + cidMatch[0]);
} else { } else {
winston.warn('[controller] Bad request: ' + req.path); winston.warn(`[controller] Bad request: ${req.path}`);
if (req.path.startsWith(nconf.get('relative_path') + '/api')) { if (req.path.startsWith(`${nconf.get('relative_path')}/api`)) {
res.status(400).json({ res.status(400).json({
error: '[[global:400.title]]', error: '[[global:400.title]]',
}); });
@ -38,7 +38,7 @@ exports.handleURIErrors = async function handleURIErrors(err, req, res, next) {
exports.handleErrors = function handleErrors(err, req, res, next) { // eslint-disable-line no-unused-vars exports.handleErrors = function handleErrors(err, req, res, next) { // eslint-disable-line no-unused-vars
var cases = { var cases = {
EBADCSRFTOKEN: function () { EBADCSRFTOKEN: function () {
winston.error(req.path + '\n' + err.message); winston.error(`${req.path}\n${err.message}`);
res.sendStatus(403); res.sendStatus(403);
}, },
'blacklisted-ip': function () { 'blacklisted-ip': function () {
@ -52,7 +52,7 @@ exports.handleErrors = function handleErrors(err, req, res, next) { // eslint-di
return res.locals.isAPI ? res.set('X-Redirect', err.path).status(200).json(err.path) : res.redirect(nconf.get('relative_path') + err.path); return res.locals.isAPI ? res.set('X-Redirect', err.path).status(200).json(err.path) : res.redirect(nconf.get('relative_path') + err.path);
} }
winston.error(req.path + '\n' + err.stack); winston.error(`${req.path}\n${err.stack}`);
res.status(status || 500); res.status(status || 500);
@ -70,7 +70,7 @@ exports.handleErrors = function handleErrors(err, req, res, next) { // eslint-di
}, function (_err, data) { }, function (_err, data) {
if (_err) { if (_err) {
// Assume defaults // Assume defaults
winston.warn('[errors/handle] Unable to retrieve plugin handlers for errors: ' + _err.message); winston.warn(`[errors/handle] Unable to retrieve plugin handlers for errors: ${_err.message}`);
data.cases = cases; data.cases = cases;
} }

@ -35,7 +35,7 @@ groupsController.details = async function (req, res, next) {
if (res.locals.isAPI) { if (res.locals.isAPI) {
req.params.slug = lowercaseSlug; req.params.slug = lowercaseSlug;
} else { } else {
return res.redirect(nconf.get('relative_path') + '/groups/' + lowercaseSlug); return res.redirect(`${nconf.get('relative_path')}/groups/${lowercaseSlug}`);
} }
} }
const groupName = await groups.getGroupNameByGroupSlug(req.params.slug); const groupName = await groups.getGroupNameByGroupSlug(req.params.slug);
@ -74,7 +74,7 @@ groupsController.details = async function (req, res, next) {
groupData.isOwner = groupData.isOwner || isAdmin || (isGlobalMod && !groupData.system); groupData.isOwner = groupData.isOwner || isAdmin || (isGlobalMod && !groupData.system);
res.render('groups/details', { res.render('groups/details', {
title: '[[pages:group, ' + groupData.displayName + ']]', title: `[[pages:group, ${groupData.displayName}]]`,
group: groupData, group: groupData,
posts: posts, posts: posts,
isAdmin: isAdmin, isAdmin: isAdmin,
@ -103,11 +103,11 @@ groupsController.members = async function (req, res, next) {
if (isHidden && !isMember && !isAdminOrGlobalMod) { if (isHidden && !isMember && !isAdminOrGlobalMod) {
return next(); return next();
} }
const users = await user.getUsersFromSet('group:' + groupName + ':members', req.uid, start, stop); const users = await user.getUsersFromSet(`group:${groupName}:members`, req.uid, start, stop);
const breadcrumbs = helpers.buildBreadcrumbs([ const breadcrumbs = helpers.buildBreadcrumbs([
{ text: '[[pages:groups]]', url: '/groups' }, { text: '[[pages:groups]]', url: '/groups' },
{ text: validator.escape(String(groupName)), url: '/groups/' + req.params.slug }, { text: validator.escape(String(groupName)), url: `/groups/${req.params.slug}` },
{ text: '[[groups:details.members]]' }, { text: '[[groups:details.members]]' },
]); ]);

@ -30,7 +30,7 @@ helpers.noScriptErrors = async function (req, res, error, httpStatus) {
loggedIn: req.loggedIn, loggedIn: req.loggedIn,
error: error, error: error,
returnLink: true, returnLink: true,
title: '[[global:' + httpStatusString + '.title]]', title: `[[global:${httpStatusString}.title]]`,
}); });
}; };
@ -48,18 +48,18 @@ helpers.buildQueryString = function (query, key, value) {
delete queryObj[key]; delete queryObj[key];
} }
delete queryObj._; delete queryObj._;
return Object.keys(queryObj).length ? '?' + querystring.stringify(queryObj) : ''; return Object.keys(queryObj).length ? `?${querystring.stringify(queryObj)}` : '';
}; };
helpers.addLinkTags = function (params) { helpers.addLinkTags = function (params) {
params.res.locals.linkTags = params.res.locals.linkTags || []; params.res.locals.linkTags = params.res.locals.linkTags || [];
params.res.locals.linkTags.push({ params.res.locals.linkTags.push({
rel: 'canonical', rel: 'canonical',
href: url + '/' + params.url, href: `${url}/${params.url}`,
}); });
params.tags.forEach(function (rel) { params.tags.forEach(function (rel) {
rel.href = url + '/' + params.url + rel.href; rel.href = `${url}/${params.url}${rel.href}`;
params.res.locals.linkTags.push(rel); params.res.locals.linkTags.push(rel);
}); });
}; };
@ -140,7 +140,7 @@ helpers.notAllowed = async function (req, res, error) {
helpers.formatApiResponse(401, res, error); helpers.formatApiResponse(401, res, error);
} else { } else {
req.session.returnTo = req.url; req.session.returnTo = req.url;
res.redirect(relative_path + '/login'); res.redirect(`${relative_path}/login`);
} }
}; };
@ -179,7 +179,7 @@ helpers.buildCategoryBreadcrumbs = async function (cid) {
if (!data.disabled && !data.isSection) { if (!data.disabled && !data.isSection) {
breadcrumbs.unshift({ breadcrumbs.unshift({
text: String(data.name), text: String(data.name),
url: relative_path + '/category/' + data.slug, url: `${relative_path}/category/${data.slug}`,
cid: cid, cid: cid,
}); });
} }
@ -188,13 +188,13 @@ helpers.buildCategoryBreadcrumbs = async function (cid) {
if (meta.config.homePageRoute && meta.config.homePageRoute !== 'categories') { if (meta.config.homePageRoute && meta.config.homePageRoute !== 'categories') {
breadcrumbs.unshift({ breadcrumbs.unshift({
text: '[[global:header.categories]]', text: '[[global:header.categories]]',
url: relative_path + '/categories', url: `${relative_path}/categories`,
}); });
} }
breadcrumbs.unshift({ breadcrumbs.unshift({
text: '[[global:home]]', text: '[[global:home]]',
url: relative_path + '/', url: `${relative_path}/`,
}); });
return breadcrumbs; return breadcrumbs;
@ -204,7 +204,7 @@ helpers.buildBreadcrumbs = function (crumbs) {
const breadcrumbs = [ const breadcrumbs = [
{ {
text: '[[global:home]]', text: '[[global:home]]',
url: relative_path + '/', url: `${relative_path}/`,
}, },
]; ];
@ -369,7 +369,7 @@ helpers.trimChildren = function (category) {
helpers.setCategoryTeaser = function (category) { helpers.setCategoryTeaser = function (category) {
if (Array.isArray(category.posts) && category.posts.length && category.posts[0]) { if (Array.isArray(category.posts) && category.posts.length && category.posts[0]) {
category.teaser = { category.teaser = {
url: nconf.get('relative_path') + '/post/' + category.posts[0].pid, url: `${nconf.get('relative_path')}/post/${category.posts[0].pid}`,
timestampISO: category.posts[0].timestampISO, timestampISO: category.posts[0].timestampISO,
pid: category.posts[0].pid, pid: category.posts[0].pid,
topic: category.posts[0].topic, topic: category.posts[0].topic,

@ -38,7 +38,7 @@ async function rewrite(req, res, next) {
} }
const pathname = parsedUrl.pathname; const pathname = parsedUrl.pathname;
const hook = 'action:homepage.get:' + pathname; const hook = `action:homepage.get:${pathname}`;
if (!plugins.hooks.hasListeners(hook)) { if (!plugins.hooks.hasListeners(hook)) {
req.url = req.path + (!req.path.endsWith('/') ? '/' : '') + pathname; req.url = req.path + (!req.path.endsWith('/') ? '/' : '') + pathname;
} else { } else {
@ -52,7 +52,7 @@ async function rewrite(req, res, next) {
exports.rewrite = rewrite; exports.rewrite = rewrite;
function pluginHook(req, res, next) { function pluginHook(req, res, next) {
var hook = 'action:homepage.get:' + res.locals.homePageRoute; var hook = `action:homepage.get:${res.locals.homePageRoute}`;
plugins.hooks.fire(hook, { plugins.hooks.fire(hook, {
req: req, req: req,

@ -113,7 +113,7 @@ Controllers.login = async function (req, res) {
data.alternate_logins = loginStrategies.length > 0; data.alternate_logins = loginStrategies.length > 0;
data.authentication = loginStrategies; data.authentication = loginStrategies;
data.allowRegistration = registrationType === 'normal'; data.allowRegistration = registrationType === 'normal';
data.allowLoginWith = '[[login:' + allowLoginWith + ']]'; data.allowLoginWith = `[[login:${allowLoginWith}]]`;
data.breadcrumbs = helpers.buildBreadcrumbs([{ data.breadcrumbs = helpers.buildBreadcrumbs([{
text: '[[global:login]]', text: '[[global:login]]',
}]); }]);
@ -187,7 +187,7 @@ Controllers.register = async function (req, res, next) {
Controllers.registerInterstitial = async function (req, res, next) { Controllers.registerInterstitial = async function (req, res, next) {
if (!req.session.hasOwnProperty('registration')) { if (!req.session.hasOwnProperty('registration')) {
return res.redirect(nconf.get('relative_path') + '/register'); return res.redirect(`${nconf.get('relative_path')}/register`);
} }
try { try {
const data = await plugins.hooks.fire('filter:register.interstitial', { const data = await plugins.hooks.fire('filter:register.interstitial', {
@ -230,11 +230,11 @@ Controllers.robots = function (req, res) {
if (meta.config['robots:txt']) { if (meta.config['robots:txt']) {
res.send(meta.config['robots:txt']); res.send(meta.config['robots:txt']);
} else { } else {
res.send('User-agent: *\n' + res.send(`${'User-agent: *\n' +
'Disallow: ' + nconf.get('relative_path') + '/admin/\n' + 'Disallow: '}${nconf.get('relative_path')}/admin/\n` +
'Disallow: ' + nconf.get('relative_path') + '/reset/\n' + `Disallow: ${nconf.get('relative_path')}/reset/\n` +
'Disallow: ' + nconf.get('relative_path') + '/compose\n' + `Disallow: ${nconf.get('relative_path')}/compose\n` +
'Sitemap: ' + nconf.get('url') + '/sitemap.xml'); `Sitemap: ${nconf.get('url')}/sitemap.xml`);
} }
}; };
@ -252,37 +252,37 @@ Controllers.manifest = async function (req, res) {
if (meta.config['brand:touchIcon']) { if (meta.config['brand:touchIcon']) {
manifest.icons.push({ manifest.icons.push({
src: nconf.get('relative_path') + '/assets/uploads/system/touchicon-36.png', src: `${nconf.get('relative_path')}/assets/uploads/system/touchicon-36.png`,
sizes: '36x36', sizes: '36x36',
type: 'image/png', type: 'image/png',
density: 0.75, density: 0.75,
}, { }, {
src: nconf.get('relative_path') + '/assets/uploads/system/touchicon-48.png', src: `${nconf.get('relative_path')}/assets/uploads/system/touchicon-48.png`,
sizes: '48x48', sizes: '48x48',
type: 'image/png', type: 'image/png',
density: 1.0, density: 1.0,
}, { }, {
src: nconf.get('relative_path') + '/assets/uploads/system/touchicon-72.png', src: `${nconf.get('relative_path')}/assets/uploads/system/touchicon-72.png`,
sizes: '72x72', sizes: '72x72',
type: 'image/png', type: 'image/png',
density: 1.5, density: 1.5,
}, { }, {
src: nconf.get('relative_path') + '/assets/uploads/system/touchicon-96.png', src: `${nconf.get('relative_path')}/assets/uploads/system/touchicon-96.png`,
sizes: '96x96', sizes: '96x96',
type: 'image/png', type: 'image/png',
density: 2.0, density: 2.0,
}, { }, {
src: nconf.get('relative_path') + '/assets/uploads/system/touchicon-144.png', src: `${nconf.get('relative_path')}/assets/uploads/system/touchicon-144.png`,
sizes: '144x144', sizes: '144x144',
type: 'image/png', type: 'image/png',
density: 3.0, density: 3.0,
}, { }, {
src: nconf.get('relative_path') + '/assets/uploads/system/touchicon-192.png', src: `${nconf.get('relative_path')}/assets/uploads/system/touchicon-192.png`,
sizes: '192x192', sizes: '192x192',
type: 'image/png', type: 'image/png',
density: 4.0, density: 4.0,
}, { }, {
src: nconf.get('relative_path') + '/assets/uploads/system/touchicon-512.png', src: `${nconf.get('relative_path')}/assets/uploads/system/touchicon-512.png`,
sizes: '512x512', sizes: '512x512',
type: 'image/png', type: 'image/png',
density: 10.0, density: 10.0,
@ -292,13 +292,13 @@ Controllers.manifest = async function (req, res) {
if (meta.config['brand:maskableIcon']) { if (meta.config['brand:maskableIcon']) {
manifest.icons.push({ manifest.icons.push({
src: nconf.get('relative_path') + '/assets/uploads/system/maskableicon-orig.png', src: `${nconf.get('relative_path')}/assets/uploads/system/maskableicon-orig.png`,
type: 'image/png', type: 'image/png',
purpose: 'maskable', purpose: 'maskable',
}); });
} else if (meta.config['brand:touchIcon']) { } else if (meta.config['brand:touchIcon']) {
manifest.icons.push({ manifest.icons.push({
src: nconf.get('relative_path') + '/assets/uploads/system/touchicon-orig.png', src: `${nconf.get('relative_path')}/assets/uploads/system/touchicon-orig.png`,
type: 'image/png', type: 'image/png',
purpose: 'maskable', purpose: 'maskable',
}); });

@ -138,11 +138,11 @@ modsController.flags.detail = async function (req, res, next) {
return memo; return memo;
}, {}), }, {}),
title: '[[pages:flag-details, ' + req.params.flagId + ']]', title: `[[pages:flag-details, ${req.params.flagId}]]`,
privileges: results.privileges, privileges: results.privileges,
breadcrumbs: helpers.buildBreadcrumbs([ breadcrumbs: helpers.buildBreadcrumbs([
{ text: '[[pages:flags]]', url: '/flags' }, { text: '[[pages:flags]]', url: '/flags' },
{ text: '[[pages:flag-details, ' + req.params.flagId + ']]' }, { text: `[[pages:flag-details, ${req.params.flagId}]]` },
]), ]),
})); }));
}; };
@ -187,14 +187,14 @@ modsController.postQueue = async function (req, res, next) {
title: '[[pages:post-queue]]', title: '[[pages:post-queue]]',
posts: postData, posts: postData,
...categoriesData, ...categoriesData,
allCategoriesUrl: 'post-queue' + helpers.buildQueryString(req.query, 'cid', ''), allCategoriesUrl: `post-queue${helpers.buildQueryString(req.query, 'cid', '')}`,
pagination: pagination.create(page, pageCount), pagination: pagination.create(page, pageCount),
breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:post-queue]]' }]), breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:post-queue]]' }]),
}); });
}; };
async function getQueuedPosts(ids) { async function getQueuedPosts(ids) {
const keys = ids.map(id => 'post:queue:' + id); const keys = ids.map(id => `post:queue:${id}`);
const postData = await db.getObjects(keys); const postData = await db.getObjects(keys);
postData.forEach(function (data) { postData.forEach(function (data) {
if (data) { if (data) {

@ -30,16 +30,16 @@ function generateXML() {
height: '16', height: '16',
type: 'image/x-icon', type: 'image/x-icon',
} }, } },
nconf.get('url') + '/favicon.ico', `${nconf.get('url')}/favicon.ico`,
] }, ] },
{ Url: { { Url: {
_attr: { _attr: {
type: 'text/html', type: 'text/html',
method: 'get', method: 'get',
template: nconf.get('url') + '/search?term={searchTerms}&in=titlesposts', template: `${nconf.get('url')}/search?term={searchTerms}&in=titlesposts`,
}, },
} }, } },
{ 'moz:SearchForm': nconf.get('url') + '/search' }, { 'moz:SearchForm': `${nconf.get('url')}/search` },
], ],
}], { declaration: true, indent: '\t' }); }], { declaration: true, indent: '\t' });
} }

@ -6,7 +6,7 @@ const db = require('../database');
module.exports.ping = async function (req, res, next) { module.exports.ping = async function (req, res, next) {
try { try {
await db.getObject('config'); await db.getObject('config');
res.status(200).send(req.path === nconf.get('relative_path') + '/sping' ? 'healthy' : '200'); res.status(200).send(req.path === `${nconf.get('relative_path')}/sping` ? 'healthy' : '200');
} catch (err) { } catch (err) {
next(err); next(err);
} }

@ -15,16 +15,16 @@ popularController.get = async function (req, res, next) {
return next(); return next();
} }
const term = helpers.terms[req.query.term] || 'alltime'; 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')) { if (req.originalUrl.startsWith(`${nconf.get('relative_path')}/api/popular`) || req.originalUrl.startsWith(`${nconf.get('relative_path')}/popular`)) {
data.title = '[[pages:popular-' + term + ']]'; data.title = `[[pages:popular-${term}]]`;
const breadcrumbs = [{ text: '[[global:header.popular]]' }]; const breadcrumbs = [{ text: '[[global:header.popular]]' }];
data.breadcrumbs = helpers.buildBreadcrumbs(breadcrumbs); data.breadcrumbs = helpers.buildBreadcrumbs(breadcrumbs);
} }
const feedQs = data.rssFeedUrl.split('?')[1]; const feedQs = data.rssFeedUrl.split('?')[1];
data.rssFeedUrl = nconf.get('relative_path') + '/popular/' + validator.escape(String(req.query.term || 'alltime')) + '.rss'; data.rssFeedUrl = `${nconf.get('relative_path')}/popular/${validator.escape(String(req.query.term || 'alltime'))}.rss`;
if (req.loggedIn) { if (req.loggedIn) {
data.rssFeedUrl += '?' + feedQs; data.rssFeedUrl += `?${feedQs}`;
} }
res.render('popular', data); res.render('popular', data);
}; };

@ -26,7 +26,7 @@ postsController.redirectToPost = async function (req, res, next) {
} }
const qs = querystring.stringify(req.query); const qs = querystring.stringify(req.query);
helpers.redirect(res, qs ? path + '?' + qs : path); helpers.redirect(res, qs ? `${path}?${qs}` : path);
}; };
postsController.getRecentPosts = async function (req, res) { postsController.getRecentPosts = async function (req, res) {

@ -62,9 +62,9 @@ recentController.getData = async function (req, url, sort) {
data.selectedCategory = categoryData.selectedCategory; data.selectedCategory = categoryData.selectedCategory;
data.selectedCids = categoryData.selectedCids; data.selectedCids = categoryData.selectedCids;
data['feeds:disableRSS'] = meta.config['feeds:disableRSS'] || 0; data['feeds:disableRSS'] = meta.config['feeds:disableRSS'] || 0;
data.rssFeedUrl = nconf.get('relative_path') + '/' + url + '.rss'; data.rssFeedUrl = `${nconf.get('relative_path')}/${url}.rss`;
if (req.loggedIn) { if (req.loggedIn) {
data.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken; data.rssFeedUrl += `?uid=${req.uid}&token=${rssToken}`;
} }
data.title = meta.config.homePageTitle || '[[pages:home]]'; data.title = meta.config.homePageTitle || '[[pages:home]]';
@ -77,9 +77,9 @@ recentController.getData = async function (req, url, sort) {
data.pagination = pagination.create(page, pageCount, req.query); data.pagination = pagination.create(page, pageCount, req.query);
helpers.addLinkTags({ url: url, res: req.res, tags: data.pagination.rel }); helpers.addLinkTags({ url: url, res: req.res, tags: data.pagination.rel });
if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/' + url) || req.originalUrl.startsWith(nconf.get('relative_path') + '/' + url)) { if (req.originalUrl.startsWith(`${nconf.get('relative_path')}/api/${url}`) || req.originalUrl.startsWith(`${nconf.get('relative_path')}/${url}`)) {
data.title = '[[pages:' + url + ']]'; data.title = `[[pages:${url}]]`;
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[' + url + ':title]]' }]); data.breadcrumbs = helpers.buildBreadcrumbs([{ text: `[[${url}:title]]` }]);
} }
return data; return data;

@ -22,7 +22,7 @@ tagsController.getTag = async function (req, res) {
topics: [], topics: [],
tag: tag, tag: tag,
breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[tags:tags]]', url: '/tags' }, { text: tag }]), breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[tags:tags]]', url: '/tags' }, { text: tag }]),
title: '[[pages:tag, ' + tag + ']]', title: `[[pages:tag, ${tag}]]`,
}; };
const [settings, cids] = await Promise.all([ const [settings, cids] = await Promise.all([
user.getSettings(req.uid), user.getSettings(req.uid),
@ -51,10 +51,10 @@ tagsController.getTag = async function (req, res) {
const pageCount = Math.max(1, Math.ceil(topicCount / settings.topicsPerPage)); const pageCount = Math.max(1, Math.ceil(topicCount / settings.topicsPerPage));
templateData.pagination = pagination.create(page, pageCount); templateData.pagination = pagination.create(page, pageCount);
helpers.addLinkTags({ url: 'tags/' + tag, res: req.res, tags: templateData.pagination.rel }); helpers.addLinkTags({ url: `tags/${tag}`, res: req.res, tags: templateData.pagination.rel });
templateData['feeds:disableRSS'] = meta.config['feeds:disableRSS']; templateData['feeds:disableRSS'] = meta.config['feeds:disableRSS'];
templateData.rssFeedUrl = nconf.get('relative_path') + '/tags/' + tag + '.rss'; templateData.rssFeedUrl = `${nconf.get('relative_path')}/tags/${tag}.rss`;
res.render('tag', templateData); res.render('tag', templateData);
}; };

@ -15,14 +15,14 @@ topController.get = async function (req, res, next) {
return next(); return next();
} }
const term = helpers.terms[req.query.term] || 'alltime'; 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')) { if (req.originalUrl.startsWith(`${nconf.get('relative_path')}/api/top`) || req.originalUrl.startsWith(`${nconf.get('relative_path')}/top`)) {
data.title = '[[pages:top-' + term + ']]'; data.title = `[[pages:top-${term}]]`;
} }
const feedQs = data.rssFeedUrl.split('?')[1]; const feedQs = data.rssFeedUrl.split('?')[1];
data.rssFeedUrl = nconf.get('relative_path') + '/top/' + validator.escape(String(req.query.term || 'alltime')) + '.rss'; data.rssFeedUrl = `${nconf.get('relative_path')}/top/${validator.escape(String(req.query.term || 'alltime'))}.rss`;
if (req.loggedIn) { if (req.loggedIn) {
data.rssFeedUrl += '?' + feedQs; data.rssFeedUrl += `?${feedQs}`;
} }
res.render('top', data); res.render('top', data);
}; };

@ -48,8 +48,8 @@ topicsController.get = async function getTopic(req, res, callback) {
return helpers.notAllowed(req, res); return helpers.notAllowed(req, res);
} }
if (!res.locals.isAPI && (!req.params.slug || topicData.slug !== tid + '/' + req.params.slug) && (topicData.slug && topicData.slug !== tid + '/')) { if (!res.locals.isAPI && (!req.params.slug || topicData.slug !== `${tid}/${req.params.slug}`) && (topicData.slug && topicData.slug !== `${tid}/`)) {
return helpers.redirect(res, '/topic/' + topicData.slug + (postIndex ? '/' + postIndex : '') + (currentPage > 1 ? '?page=' + currentPage : ''), true); return helpers.redirect(res, `/topic/${topicData.slug}${postIndex ? `/${postIndex}` : ''}${currentPage > 1 ? `?page=${currentPage}` : ''}`, true);
} }
if (postIndex === 'unread') { if (postIndex === 'unread') {
@ -57,11 +57,11 @@ topicsController.get = async function getTopic(req, res, callback) {
} }
if (utils.isNumber(postIndex) && topicData.postcount > 0 && (postIndex < 1 || postIndex > topicData.postcount)) { if (utils.isNumber(postIndex) && topicData.postcount > 0 && (postIndex < 1 || postIndex > topicData.postcount)) {
return helpers.redirect(res, '/topic/' + req.params.topic_id + '/' + req.params.slug + (postIndex > topicData.postcount ? '/' + topicData.postcount : '')); return helpers.redirect(res, `/topic/${req.params.topic_id}/${req.params.slug}${postIndex > topicData.postcount ? `/${topicData.postcount}` : ''}`);
} }
postIndex = Math.max(1, postIndex); postIndex = Math.max(1, postIndex);
const sort = req.query.sort || settings.topicPostSort; const sort = req.query.sort || settings.topicPostSort;
const set = sort === 'most_votes' ? 'tid:' + tid + ':posts:votes' : 'tid:' + tid + ':posts'; const set = sort === 'most_votes' ? `tid:${tid}:posts:votes` : `tid:${tid}:posts`;
const reverse = sort === 'newest_to_oldest' || sort === 'most_votes'; const reverse = sort === 'newest_to_oldest' || sort === 'most_votes';
if (settings.usePagination && !req.query.page) { if (settings.usePagination && !req.query.page) {
currentPage = calculatePageFromIndex(postIndex, settings); currentPage = calculatePageFromIndex(postIndex, settings);
@ -85,9 +85,9 @@ topicsController.get = async function getTopic(req, res, callback) {
topicData.updateUrlWithPostIndex = settings.updateUrlWithPostIndex; topicData.updateUrlWithPostIndex = settings.updateUrlWithPostIndex;
topicData.allowMultipleBadges = meta.config.allowMultipleBadges === 1; topicData.allowMultipleBadges = meta.config.allowMultipleBadges === 1;
topicData.privateUploads = meta.config.privateUploads === 1; topicData.privateUploads = meta.config.privateUploads === 1;
topicData.rssFeedUrl = relative_path + '/topic/' + topicData.tid + '.rss'; topicData.rssFeedUrl = `${relative_path}/topic/${topicData.tid}.rss`;
if (req.loggedIn) { if (req.loggedIn) {
topicData.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken; topicData.rssFeedUrl += `?uid=${req.uid}&token=${rssToken}`;
} }
topicData.postIndex = postIndex; topicData.postIndex = postIndex;
@ -98,12 +98,12 @@ topicsController.get = async function getTopic(req, res, callback) {
addTags(topicData, req, res), addTags(topicData, req, res),
incrementViewCount(req, tid), incrementViewCount(req, tid),
markAsRead(req, tid), markAsRead(req, tid),
analytics.increment(['pageviews:byCid:' + topicData.category.cid]), analytics.increment([`pageviews:byCid:${topicData.category.cid}`]),
]); ]);
topicData.pagination = pagination.create(currentPage, pageCount, req.query); topicData.pagination = pagination.create(currentPage, pageCount, req.query);
topicData.pagination.rel.forEach(function (rel) { topicData.pagination.rel.forEach(function (rel) {
rel.href = url + '/topic/' + topicData.slug + rel.href; rel.href = `${url}/topic/${topicData.slug}${rel.href}`;
res.locals.linkTags.push(rel); res.locals.linkTags.push(rel);
}); });
@ -157,7 +157,7 @@ async function buildBreadcrumbs(topicData) {
const breadcrumbs = [ const breadcrumbs = [
{ {
text: topicData.category.name, text: topicData.category.name,
url: relative_path + '/category/' + topicData.category.slug, url: `${relative_path}/category/${topicData.category.slug}`,
cid: topicData.category.cid, cid: topicData.category.cid,
}, },
{ {
@ -185,7 +185,7 @@ async function addTags(topicData, req, res) {
} }
if (description.length > 255) { if (description.length > 255) {
description = description.substr(0, 255) + '...'; description = `${description.substr(0, 255)}...`;
} }
description = description.replace(/\n/g, ' '); description = description.replace(/\n/g, ' ');
@ -229,7 +229,7 @@ async function addTags(topicData, req, res) {
res.locals.linkTags = [ res.locals.linkTags = [
{ {
rel: 'canonical', rel: 'canonical',
href: url + '/topic/' + topicData.slug, href: `${url}/topic/${topicData.slug}`,
}, },
]; ];
@ -244,7 +244,7 @@ async function addTags(topicData, req, res) {
if (topicData.category) { if (topicData.category) {
res.locals.linkTags.push({ res.locals.linkTags.push({
rel: 'up', rel: 'up',
href: url + '/category/' + topicData.category.slug, href: `${url}/category/${topicData.category.slug}`,
}); });
} }
} }
@ -252,7 +252,7 @@ async function addTags(topicData, req, res) {
async function addOGImageTags(res, topicData, postAtIndex) { async function addOGImageTags(res, topicData, postAtIndex) {
const uploads = postAtIndex ? await posts.uploads.listWithSizes(postAtIndex.pid) : []; const uploads = postAtIndex ? await posts.uploads.listWithSizes(postAtIndex.pid) : [];
const images = uploads.map((upload) => { const images = uploads.map((upload) => {
upload.name = url + upload_url + '/files/' + upload.name; upload.name = `${url + upload_url}/files/${upload.name}`;
return upload; return upload;
}); });
if (topicData.thumbs) { if (topicData.thumbs) {
@ -270,7 +270,7 @@ async function addOGImageTags(res, topicData, postAtIndex) {
function addOGImageTag(res, image) { function addOGImageTag(res, image) {
let imageUrl; let imageUrl;
if (typeof image === 'string' && !image.startsWith('http')) { if (typeof image === 'string' && !image.startsWith('http')) {
imageUrl = url + image.replace(new RegExp('^' + relative_path), ''); imageUrl = url + image.replace(new RegExp(`^${relative_path}`), '');
} else if (typeof image === 'object') { } else if (typeof image === 'object') {
imageUrl = image.name; imageUrl = image.name;
} else { } else {
@ -345,7 +345,7 @@ topicsController.pagination = async function (req, res, callback) {
const paginationData = pagination.create(currentPage, pageCount); const paginationData = pagination.create(currentPage, pageCount);
paginationData.rel.forEach(function (rel) { paginationData.rel.forEach(function (rel) {
rel.href = url + '/topic/' + topic.slug + rel.href; rel.href = `${url}/topic/${topic.slug}${rel.href}`;
}); });
res.json({ pagination: paginationData }); res.json({ pagination: paginationData });

@ -41,15 +41,15 @@ unreadController.get = async function (req, res) {
if (userSettings.usePagination && (page < 1 || page > data.pageCount)) { if (userSettings.usePagination && (page < 1 || page > data.pageCount)) {
req.query.page = Math.max(1, Math.min(data.pageCount, page)); req.query.page = Math.max(1, Math.min(data.pageCount, page));
return helpers.redirect(res, '/unread?' + querystring.stringify(req.query)); return helpers.redirect(res, `/unread?${querystring.stringify(req.query)}`);
} }
data.showSelect = true; data.showSelect = true;
data.showTopicTools = isPrivileged; data.showTopicTools = isPrivileged;
data.allCategoriesUrl = 'unread' + helpers.buildQueryString(req.query, 'cid', ''); data.allCategoriesUrl = `unread${helpers.buildQueryString(req.query, 'cid', '')}`;
data.selectedCategory = categoryData.selectedCategory; data.selectedCategory = categoryData.selectedCategory;
data.selectedCids = categoryData.selectedCids; data.selectedCids = categoryData.selectedCids;
data.selectCategoryLabel = '[[unread:mark_as_read]]'; data.selectCategoryLabel = '[[unread:mark_as_read]]';
if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/unread') || req.originalUrl.startsWith(nconf.get('relative_path') + '/unread')) { if (req.originalUrl.startsWith(`${nconf.get('relative_path')}/api/unread`) || req.originalUrl.startsWith(`${nconf.get('relative_path')}/unread`)) {
data.title = '[[pages:unread]]'; data.title = '[[pages:unread]]';
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[unread:title]]' }]); data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[unread:title]]' }]);
} }

@ -162,14 +162,14 @@ uploadsController.uploadFile = async function (uid, uploadedFile) {
} }
if (uploadedFile.size > meta.config.maximumFileSize * 1024) { if (uploadedFile.size > meta.config.maximumFileSize * 1024) {
throw new Error('[[error:file-too-big, ' + meta.config.maximumFileSize + ']]'); throw new Error(`[[error:file-too-big, ${meta.config.maximumFileSize}]]`);
} }
const allowed = file.allowedExtensions(); const allowed = file.allowedExtensions();
const extension = path.extname(uploadedFile.name).toLowerCase(); const extension = path.extname(uploadedFile.name).toLowerCase();
if (allowed.length > 0 && (!extension || extension === '.' || !allowed.includes(extension))) { if (allowed.length > 0 && (!extension || extension === '.' || !allowed.includes(extension))) {
throw new Error('[[error:invalid-file-type, ' + allowed.join('&#44; ') + ']]'); throw new Error(`[[error:invalid-file-type, ${allowed.join('&#44; ')}]]`);
} }
return await saveFileToLocal(uid, 'files', uploadedFile); return await saveFileToLocal(uid, 'files', uploadedFile);
@ -179,7 +179,7 @@ async function saveFileToLocal(uid, folder, uploadedFile) {
const name = uploadedFile.name || 'upload'; const name = uploadedFile.name || 'upload';
const extension = path.extname(name) || ''; const extension = path.extname(name) || '';
const filename = Date.now() + '-' + validator.escape(name.substr(0, name.length - extension.length)).substr(0, 255) + extension; const filename = `${Date.now()}-${validator.escape(name.substr(0, name.length - extension.length)).substr(0, 255)}${extension}`;
const upload = await file.saveFileToLocal(filename, folder, uploadedFile.path); const upload = await file.saveFileToLocal(filename, folder, uploadedFile.path);
const storedFile = { const storedFile = {
@ -188,7 +188,7 @@ async function saveFileToLocal(uid, folder, uploadedFile) {
name: uploadedFile.name, name: uploadedFile.name,
}; };
const fileKey = upload.url.replace(nconf.get('upload_url'), ''); const fileKey = upload.url.replace(nconf.get('upload_url'), '');
await db.sortedSetAdd('uid:' + uid + ':uploads', Date.now(), fileKey); await db.sortedSetAdd(`uid:${uid}:uploads`, Date.now(), fileKey);
const data = await plugins.hooks.fire('filter:uploadStored', { uid: uid, uploadedFile: uploadedFile, storedFile: storedFile }); const data = await plugins.hooks.fire('filter:uploadStored', { uid: uid, uploadedFile: uploadedFile, storedFile: storedFile });
return data.storedFile; return data.storedFile;
} }

@ -77,15 +77,15 @@ userController.getUserDataByUID = async function (callerUid, uid) {
}; };
userController.exportPosts = async function (req, res, next) { userController.exportPosts = async function (req, res, next) {
sendExport(res.locals.uid + '_posts.csv', 'text/csv', res, next); sendExport(`${res.locals.uid}_posts.csv`, 'text/csv', res, next);
}; };
userController.exportUploads = function (req, res, next) { userController.exportUploads = function (req, res, next) {
sendExport(res.locals.uid + '_uploads.zip', 'application/zip', res, next); sendExport(`${res.locals.uid}_uploads.zip`, 'application/zip', res, next);
}; };
userController.exportProfile = async function (req, res, next) { userController.exportProfile = async function (req, res, next) {
sendExport(res.locals.uid + '_profile.json', 'application/json', res, next); sendExport(`${res.locals.uid}_profile.json`, 'application/json', res, next);
}; };
function sendExport(filename, type, res, next) { function sendExport(filename, type, res, next) {
@ -93,7 +93,7 @@ function sendExport(filename, type, res, next) {
root: path.join(__dirname, '../../build/export'), root: path.join(__dirname, '../../build/export'),
headers: { headers: {
'Content-Type': type, 'Content-Type': type,
'Content-Disposition': 'attachment; filename=' + filename, 'Content-Disposition': `attachment; filename=${filename}`,
}, },
}, function (err) { }, function (err) {
if (err) { if (err) {

@ -37,7 +37,7 @@ usersController.search = async function (req, res) {
const section = req.query.section || 'joindate'; const section = req.query.section || 'joindate';
searchData.pagination = pagination.create(req.query.page, searchData.pageCount, req.query); searchData.pagination = pagination.create(req.query.page, searchData.pageCount, req.query);
searchData['section_' + section] = true; searchData[`section_${section}`] = true;
searchData.displayUserSearch = true; searchData.displayUserSearch = true;
await render(req, res, searchData); await render(req, res, searchData);
}; };
@ -141,7 +141,7 @@ usersController.getUsers = async function (set, uid, query) {
isAdmin: isAdmin, isAdmin: isAdmin,
isGlobalMod: isGlobalMod, isGlobalMod: isGlobalMod,
displayUserSearch: canSearch, displayUserSearch: canSearch,
['section_' + (query.section || 'joindate')]: true, [`section_${query.section || 'joindate'}`]: true,
}; };
}; };

@ -146,7 +146,7 @@ Users.revokeSession = async (req, res) => {
return helpers.formatApiResponse(404, res); return helpers.formatApiResponse(404, res);
} }
const sids = await db.getSortedSetRange('uid:' + req.params.uid + ':sessions', 0, -1); const sids = await db.getSortedSetRange(`uid:${req.params.uid}:sessions`, 0, -1);
let _id; let _id;
for (const sid of sids) { for (const sid of sids) {
/* eslint-disable no-await-in-loop */ /* eslint-disable no-await-in-loop */
@ -204,7 +204,7 @@ Users.invite = async (req, res) => {
invites = await user.getInvitesNumber(req.uid); invites = await user.getInvitesNumber(req.uid);
} }
if (!isAdmin && max && invites >= max) { if (!isAdmin && max && invites >= max) {
return helpers.formatApiResponse(403, res, new Error('[[error:invite-maximum-met, ' + invites + ', ' + max + ']]')); return helpers.formatApiResponse(403, res, new Error(`[[error:invite-maximum-met, ${invites}, ${max}]]`));
} }
await user.sendInvitationEmail(req.uid, email, groupsToJoin); await user.sendInvitationEmail(req.uid, email, groupsToJoin);

@ -17,9 +17,9 @@ coverPhoto.getDefaultProfileCover = function (uid) {
}; };
function getCover(type, id) { function getCover(type, id) {
const defaultCover = relative_path + '/assets/images/cover-default.png'; const defaultCover = `${relative_path}/assets/images/cover-default.png`;
if (meta.config[type + ':defaultCovers']) { if (meta.config[`${type}:defaultCovers`]) {
const covers = String(meta.config[type + ':defaultCovers']).trim().split(/[\s,]+/g); const covers = String(meta.config[`${type}:defaultCovers`]).trim().split(/[\s,]+/g);
let coverPhoto = defaultCover; let coverPhoto = defaultCover;
if (!covers.length) { if (!covers.length) {
return coverPhoto; return coverPhoto;

@ -3,7 +3,7 @@
module.exports.create = function (name) { module.exports.create = function (name) {
const cacheCreate = require('../cacheCreate'); const cacheCreate = require('../cacheCreate');
return cacheCreate({ return cacheCreate({
name: name + '-object', name: `${name}-object`,
max: 40000, max: 40000,
length: function () { return 1; }, length: function () { return 1; },
maxAge: 0, maxAge: 0,

@ -10,7 +10,7 @@ if (!databaseName) {
process.exit(); process.exit();
} }
const primaryDB = require('./' + databaseName); const primaryDB = require(`./${databaseName}`);
primaryDB.parseIntFields = function (data, intFields, requestedFields) { primaryDB.parseIntFields = function (data, intFields, requestedFields) {
intFields.forEach((field) => { intFields.forEach((field) => {
@ -25,7 +25,7 @@ primaryDB.initSessionStore = async function () {
let sessionStoreDB = primaryDB; let sessionStoreDB = primaryDB;
if (nconf.get('session_store')) { if (nconf.get('session_store')) {
sessionStoreDB = require('./' + sessionStoreConfig.name); sessionStoreDB = require(`./${sessionStoreConfig.name}`);
} else if (nconf.get('redis')) { } else if (nconf.get('redis')) {
// if redis is specified, use it as session store over others // if redis is specified, use it as session store over others
sessionStoreDB = require('./redis'); sessionStoreDB = require('./redis');

@ -12,7 +12,7 @@ connection.getConnectionString = function (mongo) {
var usernamePassword = ''; var usernamePassword = '';
var uri = mongo.uri || ''; var uri = mongo.uri || '';
if (mongo.username && mongo.password) { if (mongo.username && mongo.password) {
usernamePassword = nconf.get('mongo:username') + ':' + encodeURIComponent(nconf.get('mongo:password')) + '@'; usernamePassword = `${nconf.get('mongo:username')}:${encodeURIComponent(nconf.get('mongo:password'))}@`;
} else if (!uri.includes('@') || !uri.slice(uri.indexOf('://') + 3, uri.indexOf('@'))) { } else if (!uri.includes('@') || !uri.slice(uri.indexOf('://') + 3, uri.indexOf('@'))) {
winston.warn('You have no mongo username/password setup!'); winston.warn('You have no mongo username/password setup!');
} }
@ -35,10 +35,10 @@ connection.getConnectionString = function (mongo) {
var servers = []; var servers = [];
for (var i = 0; i < hosts.length; i += 1) { for (var i = 0; i < hosts.length; i += 1) {
servers.push(hosts[i] + ':' + ports[i]); servers.push(`${hosts[i]}:${ports[i]}`);
} }
return uri || 'mongodb://' + usernamePassword + servers.join() + '/' + mongo.database; return uri || `mongodb://${usernamePassword}${servers.join()}/${mongo.database}`;
}; };
connection.getConnectionOptions = function (mongo) { connection.getConnectionOptions = function (mongo) {

@ -60,7 +60,7 @@ helpers.buildMatchQuery = function (match) {
} }
_match = utils.escapeRegexChars(_match); _match = utils.escapeRegexChars(_match);
if (!match.startsWith('*')) { if (!match.startsWith('*')) {
_match = '^' + _match; _match = `^${_match}`;
} }
if (!match.endsWith('*')) { if (!match.endsWith('*')) {
_match += '$'; _match += '$';

@ -12,7 +12,7 @@ module.exports = function (module) {
return await sortedSetAddBulk(key, score, value); return await sortedSetAddBulk(key, score, value);
} }
if (!utils.isNumber(score)) { if (!utils.isNumber(score)) {
throw new Error('[[error:invalid-score, ' + score + ']]'); throw new Error(`[[error:invalid-score, ${score}]]`);
} }
value = helpers.valueToString(value); value = helpers.valueToString(value);
@ -35,7 +35,7 @@ module.exports = function (module) {
} }
for (let i = 0; i < scores.length; i += 1) { for (let i = 0; i < scores.length; i += 1) {
if (!utils.isNumber(scores[i])) { if (!utils.isNumber(scores[i])) {
throw new Error('[[error:invalid-score, ' + scores[i] + ']]'); throw new Error(`[[error:invalid-score, ${scores[i]}]]`);
} }
} }
values = values.map(helpers.valueToString); values = values.map(helpers.valueToString);
@ -54,7 +54,7 @@ module.exports = function (module) {
const isArrayOfScores = Array.isArray(scores); const isArrayOfScores = Array.isArray(scores);
if ((!isArrayOfScores && !utils.isNumber(scores)) || if ((!isArrayOfScores && !utils.isNumber(scores)) ||
(isArrayOfScores && scores.map(s => utils.isNumber(s)).includes(false))) { (isArrayOfScores && scores.map(s => utils.isNumber(s)).includes(false))) {
throw new Error('[[error:invalid-score, ' + scores + ']]'); throw new Error(`[[error:invalid-score, ${scores}]]`);
} }
if (isArrayOfScores && scores.length !== keys.length) { if (isArrayOfScores && scores.length !== keys.length) {
@ -77,7 +77,7 @@ module.exports = function (module) {
var bulk = module.client.collection('objects').initializeUnorderedBulkOp(); var bulk = module.client.collection('objects').initializeUnorderedBulkOp();
data.forEach(function (item) { data.forEach(function (item) {
if (!utils.isNumber(item[1])) { if (!utils.isNumber(item[1])) {
throw new Error('[[error:invalid-score, ' + item[1] + ']]'); throw new Error(`[[error:invalid-score, ${item[1]}]]`);
} }
bulk.find({ _key: item[0], value: String(item[2]) }).upsert().updateOne({ $set: { score: parseFloat(item[1]) } }); bulk.find({ _key: item[0], value: String(item[2]) }).upsert().updateOne({ $set: { score: parseFloat(item[1]) } });
}); });

@ -164,7 +164,7 @@ module.exports = function (module) {
const aggregate = {}; const aggregate = {};
if (params.aggregate) { if (params.aggregate) {
aggregate['$' + params.aggregate.toLowerCase()] = '$score'; aggregate[`$${params.aggregate.toLowerCase()}`] = '$score';
} else { } else {
aggregate.$sum = '$score'; aggregate.$sum = '$score';
} }

@ -35,7 +35,7 @@ module.exports = function (module) {
var aggregate = {}; var aggregate = {};
if (params.aggregate) { if (params.aggregate) {
aggregate['$' + params.aggregate.toLowerCase()] = '$score'; aggregate[`$${params.aggregate.toLowerCase()}`] = '$score';
} else { } else {
aggregate.$sum = '$score'; aggregate.$sum = '$score';
} }

@ -55,7 +55,7 @@ postgresModule.init = async function () {
try { try {
await checkUpgrade(client); await checkUpgrade(client);
} catch (err) { } catch (err) {
winston.error('NodeBB could not connect to your PostgreSQL database. PostgreSQL returned the following error: ' + err.message); winston.error(`NodeBB could not connect to your PostgreSQL database. PostgreSQL returned the following error: ${err.message}`);
throw err; throw err;
} finally { } finally {
client.release(); client.release();
@ -339,7 +339,7 @@ postgresModule.createIndices = function (callback) {
async.apply(query, `CREATE INDEX IF NOT EXISTS "idx__legacy_object__expireAt" ON "legacy_object"("expireAt" ASC)`), async.apply(query, `CREATE INDEX IF NOT EXISTS "idx__legacy_object__expireAt" ON "legacy_object"("expireAt" ASC)`),
], function (err) { ], function (err) {
if (err) { if (err) {
winston.error('Error creating index ' + err.message); winston.error(`Error creating index ${err.message}`);
return callback(err); return callback(err);
} }
winston.info('[database] Checking database indices done!'); winston.info('[database] Checking database indices done!');

@ -48,7 +48,7 @@ SELECT "type"
}); });
if (res.rows[0].type !== type) { if (res.rows[0].type !== type) {
throw new Error('database: cannot insert ' + JSON.stringify(key) + ' as ' + type + ' because it already exists as ' + res.rows[0].type); throw new Error(`database: cannot insert ${JSON.stringify(key)} as ${type} because it already exists as ${res.rows[0].type}`);
} }
}; };
@ -84,8 +84,8 @@ SELECT "_key", "type"
var invalid = res.rows.filter(r => r.type !== type); var invalid = res.rows.filter(r => r.type !== type);
if (invalid.length) { if (invalid.length) {
const parts = invalid.map(r => JSON.stringify(r._key) + ' is ' + r.type); const parts = invalid.map(r => `${JSON.stringify(r._key)} is ${r.type}`);
throw new Error('database: cannot insert multiple objects as ' + type + ' because they already exist: ' + parts.join(', ')); throw new Error(`database: cannot insert multiple objects as ${type} because they already exist: ${parts.join(', ')}`);
} }
var missing = keys.filter(function (k) { var missing = keys.filter(function (k) {
@ -93,7 +93,7 @@ SELECT "_key", "type"
}); });
if (missing.length) { if (missing.length) {
throw new Error('database: failed to insert keys for objects: ' + JSON.stringify(missing)); throw new Error(`database: failed to insert keys for objects: ${JSON.stringify(missing)}`);
} }
}; };

@ -45,10 +45,10 @@ module.exports = function (module) {
module.scan = async function (params) { module.scan = async function (params) {
let match = params.match; let match = params.match;
if (match.startsWith('*')) { if (match.startsWith('*')) {
match = '%' + match.substring(1); match = `%${match.substring(1)}`;
} }
if (match.endsWith('*')) { if (match.endsWith('*')) {
match = match.substring(0, match.length - 1) + '%'; match = `${match.substring(0, match.length - 1)}%`;
} }
const res = await module.pool.query({ const res = await module.pool.query({

@ -59,7 +59,7 @@ module.exports = function (module) {
} }
const res = await module.pool.query({ const res = await module.pool.query({
name: 'getSortedSetRangeWithScores' + (sort > 0 ? 'Asc' : 'Desc'), name: `getSortedSetRangeWithScores${sort > 0 ? 'Asc' : 'Desc'}`,
text: ` text: `
SELECT z."value", SELECT z."value",
z."score" z."score"
@ -68,7 +68,7 @@ SELECT z."value",
ON o."_key" = z."_key" ON o."_key" = z."_key"
AND o."type" = z."type" AND o."type" = z."type"
WHERE o."_key" = ANY($1::TEXT[]) WHERE o."_key" = ANY($1::TEXT[])
ORDER BY z."score" ` + (sort > 0 ? 'ASC' : 'DESC') + ` ORDER BY z."score" ${sort > 0 ? 'ASC' : 'DESC'}
LIMIT $3::INTEGER LIMIT $3::INTEGER
OFFSET $2::INTEGER`, OFFSET $2::INTEGER`,
values: [key, start, limit], values: [key, start, limit],
@ -124,7 +124,7 @@ OFFSET $2::INTEGER`,
} }
const res = await module.pool.query({ const res = await module.pool.query({
name: 'getSortedSetRangeByScoreWithScores' + (sort > 0 ? 'Asc' : 'Desc'), name: `getSortedSetRangeByScoreWithScores${sort > 0 ? 'Asc' : 'Desc'}`,
text: ` text: `
SELECT z."value", SELECT z."value",
z."score" z."score"
@ -135,7 +135,7 @@ SELECT z."value",
WHERE o."_key" = ANY($1::TEXT[]) WHERE o."_key" = ANY($1::TEXT[])
AND (z."score" >= $4::NUMERIC OR $4::NUMERIC IS NULL) AND (z."score" >= $4::NUMERIC OR $4::NUMERIC IS NULL)
AND (z."score" <= $5::NUMERIC OR $5::NUMERIC IS NULL) AND (z."score" <= $5::NUMERIC OR $5::NUMERIC IS NULL)
ORDER BY z."score" ` + (sort > 0 ? 'ASC' : 'DESC') + ` ORDER BY z."score" ${sort > 0 ? 'ASC' : 'DESC'}
LIMIT $3::INTEGER LIMIT $3::INTEGER
OFFSET $2::INTEGER`, OFFSET $2::INTEGER`,
values: [key, start, count, min, max], values: [key, start, count, min, max],
@ -248,13 +248,13 @@ SELECT o."_key" k,
async function getSortedSetRank(sort, keys, values) { async function getSortedSetRank(sort, keys, values) {
values = values.map(helpers.valueToString); values = values.map(helpers.valueToString);
const res = await module.pool.query({ const res = await module.pool.query({
name: 'getSortedSetRank' + sort, name: `getSortedSetRank${sort}`,
text: ` text: `
SELECT (SELECT r SELECT (SELECT r
FROM (SELECT z."value" v, FROM (SELECT z."value" v,
RANK() OVER (PARTITION BY o."_key" RANK() OVER (PARTITION BY o."_key"
ORDER BY z."score" ` + sort + `, ORDER BY z."score" ${sort},
z."value" ` + sort + `) - 1 r z."value" ${sort}) - 1 r
FROM "legacy_object_live" o FROM "legacy_object_live" o
INNER JOIN "legacy_zset" z INNER JOIN "legacy_zset" z
ON o."_key" = z."_key" ON o."_key" = z."_key"
@ -518,14 +518,14 @@ RETURNING "score" s`,
var q = buildLexQuery(key, min, max); var q = buildLexQuery(key, min, max);
const res = await module.pool.query({ const res = await module.pool.query({
name: 'sortedSetLexCount' + q.suffix, name: `sortedSetLexCount${q.suffix}`,
text: ` text: `
SELECT COUNT(*) c SELECT COUNT(*) c
FROM "legacy_object_live" o FROM "legacy_object_live" o
INNER JOIN "legacy_zset" z INNER JOIN "legacy_zset" z
ON o."_key" = z."_key" ON o."_key" = z."_key"
AND o."type" = z."type" AND o."type" = z."type"
WHERE ` + q.where, WHERE ${q.where}`,
values: q.values, values: q.values,
}); });
@ -540,17 +540,17 @@ SELECT COUNT(*) c
q.values.push(start); q.values.push(start);
q.values.push(count <= 0 ? null : count); q.values.push(count <= 0 ? null : count);
const res = await module.pool.query({ const res = await module.pool.query({
name: 'sortedSetLex' + (sort > 0 ? 'Asc' : 'Desc') + q.suffix, name: `sortedSetLex${sort > 0 ? 'Asc' : 'Desc'}${q.suffix}`,
text: ` text: `
SELECT z."value" v SELECT z."value" v
FROM "legacy_object_live" o FROM "legacy_object_live" o
INNER JOIN "legacy_zset" z INNER JOIN "legacy_zset" z
ON o."_key" = z."_key" ON o."_key" = z."_key"
AND o."type" = z."type" AND o."type" = z."type"
WHERE ` + q.where + ` WHERE ${q.where}
ORDER BY z."value" ` + (sort > 0 ? 'ASC' : 'DESC') + ` ORDER BY z."value" ${sort > 0 ? 'ASC' : 'DESC'}
LIMIT $` + q.values.length + `::INTEGER LIMIT $${q.values.length}::INTEGER
OFFSET $` + (q.values.length - 1) + `::INTEGER`, OFFSET $${q.values.length - 1}::INTEGER`,
values: q.values, values: q.values,
}); });
@ -560,13 +560,13 @@ OFFSET $` + (q.values.length - 1) + `::INTEGER`,
module.sortedSetRemoveRangeByLex = async function (key, min, max) { module.sortedSetRemoveRangeByLex = async function (key, min, max) {
var q = buildLexQuery(key, min, max); var q = buildLexQuery(key, min, max);
await module.pool.query({ await module.pool.query({
name: 'sortedSetRemoveRangeByLex' + q.suffix, name: `sortedSetRemoveRangeByLex${q.suffix}`,
text: ` text: `
DELETE FROM "legacy_zset" z DELETE FROM "legacy_zset" z
USING "legacy_object_live" o USING "legacy_object_live" o
WHERE o."_key" = z."_key" WHERE o."_key" = z."_key"
AND o."type" = z."type" AND o."type" = z."type"
AND ` + q.where, AND ${q.where}`,
values: q.values, values: q.values,
}); });
}; };
@ -582,15 +582,15 @@ DELETE FROM "legacy_zset" z
if (min.match(/^\(/)) { if (min.match(/^\(/)) {
q.values.push(min.substr(1)); q.values.push(min.substr(1));
q.suffix += 'GT'; q.suffix += 'GT';
q.where += ` AND z."value" > $` + q.values.length + `::TEXT COLLATE "C"`; q.where += ` AND z."value" > $${q.values.length}::TEXT COLLATE "C"`;
} else if (min.match(/^\[/)) { } else if (min.match(/^\[/)) {
q.values.push(min.substr(1)); q.values.push(min.substr(1));
q.suffix += 'GE'; q.suffix += 'GE';
q.where += ` AND z."value" >= $` + q.values.length + `::TEXT COLLATE "C"`; q.where += ` AND z."value" >= $${q.values.length}::TEXT COLLATE "C"`;
} else { } else {
q.values.push(min); q.values.push(min);
q.suffix += 'GE'; q.suffix += 'GE';
q.where += ` AND z."value" >= $` + q.values.length + `::TEXT COLLATE "C"`; q.where += ` AND z."value" >= $${q.values.length}::TEXT COLLATE "C"`;
} }
} }
@ -598,15 +598,15 @@ DELETE FROM "legacy_zset" z
if (max.match(/^\(/)) { if (max.match(/^\(/)) {
q.values.push(max.substr(1)); q.values.push(max.substr(1));
q.suffix += 'LT'; q.suffix += 'LT';
q.where += ` AND z."value" < $` + q.values.length + `::TEXT COLLATE "C"`; q.where += ` AND z."value" < $${q.values.length}::TEXT COLLATE "C"`;
} else if (max.match(/^\[/)) { } else if (max.match(/^\[/)) {
q.values.push(max.substr(1)); q.values.push(max.substr(1));
q.suffix += 'LE'; q.suffix += 'LE';
q.where += ` AND z."value" <= $` + q.values.length + `::TEXT COLLATE "C"`; q.where += ` AND z."value" <= $${q.values.length}::TEXT COLLATE "C"`;
} else { } else {
q.values.push(max); q.values.push(max);
q.suffix += 'LE'; q.suffix += 'LE';
q.where += ` AND z."value" <= $` + q.values.length + `::TEXT COLLATE "C"`; q.where += ` AND z."value" <= $${q.values.length}::TEXT COLLATE "C"`;
} }
} }
@ -616,11 +616,11 @@ DELETE FROM "legacy_zset" z
module.getSortedSetScan = async function (params) { module.getSortedSetScan = async function (params) {
let match = params.match; let match = params.match;
if (match.startsWith('*')) { if (match.startsWith('*')) {
match = '%' + match.substring(1); match = `%${match.substring(1)}`;
} }
if (match.endsWith('*')) { if (match.endsWith('*')) {
match = match.substring(0, match.length - 1) + '%'; match = `${match.substring(0, match.length - 1)}%`;
} }
const res = await module.pool.query({ const res = await module.pool.query({

@ -13,7 +13,7 @@ module.exports = function (module) {
return await sortedSetAddBulk(key, score, value); return await sortedSetAddBulk(key, score, value);
} }
if (!utils.isNumber(score)) { if (!utils.isNumber(score)) {
throw new Error('[[error:invalid-score, ' + score + ']]'); throw new Error(`[[error:invalid-score, ${score}]]`);
} }
value = helpers.valueToString(value); value = helpers.valueToString(value);
score = parseFloat(score); score = parseFloat(score);
@ -41,7 +41,7 @@ module.exports = function (module) {
} }
for (let i = 0; i < scores.length; i += 1) { for (let i = 0; i < scores.length; i += 1) {
if (!utils.isNumber(scores[i])) { if (!utils.isNumber(scores[i])) {
throw new Error('[[error:invalid-score, ' + scores[i] + ']]'); throw new Error(`[[error:invalid-score, ${scores[i]}]]`);
} }
} }
values = values.map(helpers.valueToString); values = values.map(helpers.valueToString);
@ -71,7 +71,7 @@ DO UPDATE SET "score" = EXCLUDED."score"`,
const isArrayOfScores = Array.isArray(scores); const isArrayOfScores = Array.isArray(scores);
if ((!isArrayOfScores && !utils.isNumber(scores)) || if ((!isArrayOfScores && !utils.isNumber(scores)) ||
(isArrayOfScores && scores.map(s => utils.isNumber(s)).includes(false))) { (isArrayOfScores && scores.map(s => utils.isNumber(s)).includes(false))) {
throw new Error('[[error:invalid-score, ' + scores + ']]'); throw new Error(`[[error:invalid-score, ${scores}]]`);
} }
if (isArrayOfScores && scores.length !== keys.length) { if (isArrayOfScores && scores.length !== keys.length) {
@ -110,7 +110,7 @@ INSERT INTO "legacy_zset" ("_key", "value", "score")
const scores = []; const scores = [];
data.forEach(function (item) { data.forEach(function (item) {
if (!utils.isNumber(item[1])) { if (!utils.isNumber(item[1])) {
throw new Error('[[error:invalid-score, ' + item[1] + ']]'); throw new Error(`[[error:invalid-score, ${item[1]}]]`);
} }
keys.push(item[0]); keys.push(item[0]);
scores.push(item[1]); scores.push(item[1]);

@ -56,10 +56,10 @@ SELECT COUNT(*) c
} }
const res = await module.pool.query({ const res = await module.pool.query({
name: 'getSortedSetIntersect' + aggregate + (params.sort > 0 ? 'Asc' : 'Desc') + 'WithScores', name: `getSortedSetIntersect${aggregate}${params.sort > 0 ? 'Asc' : 'Desc'}WithScores`,
text: ` text: `
WITH A AS (SELECT z."value", WITH A AS (SELECT z."value",
` + aggregate + `(z."score" * k."weight") "score", ${aggregate}(z."score" * k."weight") "score",
COUNT(*) c COUNT(*) c
FROM UNNEST($1::TEXT[], $2::NUMERIC[]) k("_key", "weight") FROM UNNEST($1::TEXT[], $2::NUMERIC[]) k("_key", "weight")
INNER JOIN "legacy_object_live" o INNER JOIN "legacy_object_live" o
@ -72,7 +72,7 @@ SELECT A."value",
A."score" A."score"
FROM A FROM A
WHERE c = array_length($1::TEXT[], 1) WHERE c = array_length($1::TEXT[], 1)
ORDER BY A."score" ` + (params.sort > 0 ? 'ASC' : 'DESC') + ` ORDER BY A."score" ${params.sort > 0 ? 'ASC' : 'DESC'}
LIMIT $4::INTEGER LIMIT $4::INTEGER
OFFSET $3::INTEGER`, OFFSET $3::INTEGER`,
values: [sets, weights, start, limit], values: [sets, weights, start, limit],

@ -50,10 +50,10 @@ SELECT COUNT(DISTINCT z."value") c
} }
const res = await module.pool.query({ const res = await module.pool.query({
name: 'getSortedSetUnion' + aggregate + (params.sort > 0 ? 'Asc' : 'Desc') + 'WithScores', name: `getSortedSetUnion${aggregate}${params.sort > 0 ? 'Asc' : 'Desc'}WithScores`,
text: ` text: `
WITH A AS (SELECT z."value", WITH A AS (SELECT z."value",
` + aggregate + `(z."score" * k."weight") "score" ${aggregate}(z."score" * k."weight") "score"
FROM UNNEST($1::TEXT[], $2::NUMERIC[]) k("_key", "weight") FROM UNNEST($1::TEXT[], $2::NUMERIC[]) k("_key", "weight")
INNER JOIN "legacy_object_live" o INNER JOIN "legacy_object_live" o
ON o."_key" = k."_key" ON o."_key" = k."_key"
@ -64,7 +64,7 @@ WITH A AS (SELECT z."value",
SELECT A."value", SELECT A."value",
A."score" A."score"
FROM A FROM A
ORDER BY A."score" ` + (params.sort > 0 ? 'ASC' : 'DESC') + ` ORDER BY A."score" ${params.sort > 0 ? 'ASC' : 'DESC'}
LIMIT $4::INTEGER LIMIT $4::INTEGER
OFFSET $3::INTEGER`, OFFSET $3::INTEGER`,
values: [sets, weights, start, limit], values: [sets, weights, start, limit],

@ -83,7 +83,7 @@ redisModule.info = async function (cxn) {
} }
}); });
const keyInfo = redisData['db' + nconf.get('redis:database')]; const keyInfo = redisData[`db${nconf.get('redis:database')}`];
if (keyInfo) { if (keyInfo) {
const split = keyInfo.split(','); const split = keyInfo.split(',');
redisData.keys = (split[0] || '').replace('keys=', ''); redisData.keys = (split[0] || '').replace('keys=', '');
@ -108,7 +108,7 @@ redisModule.socketAdapter = async function () {
const pub = await connection.connect(nconf.get('redis')); const pub = await connection.connect(nconf.get('redis'));
const sub = await connection.connect(nconf.get('redis')); const sub = await connection.connect(nconf.get('redis'));
return redisAdapter({ return redisAdapter({
key: 'db:' + nconf.get('redis:database') + ':adapter_key', key: `db:${nconf.get('redis:database')}:adapter_key`,
pubClient: pub, pubClient: pub,
subClient: sub, subClient: sub,
}); });

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save