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-spread": "off",
"prefer-arrow-callback": "off",
"prefer-template": "off",
"no-var": "off",
"vars-on-top": "off",

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

@ -49,7 +49,7 @@ winston.verbose('* using configuration stored in: %s', configFile);
if (!process.send) {
// 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 is free software, and you are welcome to redistribute it under certain conditions.');
winston.info('');

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

@ -27,8 +27,8 @@ const formats = [
];
const timestampFormat = winston.format((info) => {
var dateString = new Date().toISOString() + ' [' + global.process.pid + ']';
info.level = dateString + ' - ' + info.level;
var dateString = `${new Date().toISOString()} [${global.process.pid}]`;
info.level = `${dateString} - ${info.level}`;
return info;
});
formats.push(timestampFormat());
@ -69,7 +69,7 @@ const viewsDir = path.join(paths.baseDir, 'build/public/templates');
web.install = async function (port) {
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.engine('tpl', function (filepath, options, callback) {
@ -119,7 +119,7 @@ function ping(req, res) {
function welcome(req, res) {
var dbs = ['redis', 'mongo', 'postgres'];
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;
});
@ -132,7 +132,7 @@ function welcome(req, res) {
var defaults = require('./data/defaults');
res.render('install/index', {
url: nconf.get('url') || (req.protocol + '://' + req.get('host')),
url: nconf.get('url') || (`${req.protocol}://${req.get('host')}`),
launchUrl: launchUrl,
skipGeneralSetup: !!nconf.get('url'),
databases: databases,
@ -161,7 +161,7 @@ function install(req, res) {
// Flatten any objects in setupEnvVars
const pushToRoot = function (parentKey, key) {
setupEnvVars[parentKey + '__' + key] = setupEnvVars[parentKey][key];
setupEnvVars[`${parentKey}__${key}`] = setupEnvVars[parentKey][key];
};
for (var j in setupEnvVars) {
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) });
await fs.promises.writeFile(path.join(__dirname, '../public/installer.css'), css.css);
} catch (err) {
winston.error('Unable to compile LESS: \n' + err.stack);
winston.error(`Unable to compile LESS: \n${err.stack}`);
throw err;
}
}

@ -40,7 +40,7 @@ Loader.init = function (callback) {
if (silent) {
console.log = function () {
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) {
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 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');
@ -71,12 +71,12 @@ Loader.addWorkerEvents = function (worker) {
Loader.timesStarted = 0;
}, 10000);
} 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();
}
}
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)) {
console.log('[cluster] Spinning up another process...');
@ -110,7 +110,7 @@ Loader.addWorkerEvents = function (worker) {
Loader.start = function (callback) {
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) {
forkWorker(x, x === 0);
@ -126,7 +126,7 @@ function forkWorker(index, isPrimary) {
var args = [];
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;

@ -59,13 +59,13 @@ function nsToTitle(namespace) {
const fallbackCache = {};
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 translations = sanitize(template);
translations = Translator.removePatterns(translations);
translations = simplify(translations);
translations += '\n' + title;
translations += `\n${title}`;
return {
namespace: namespace,
@ -107,16 +107,16 @@ async function buildNamespace(language, namespace) {
title = '[[admin/menu:dashboard]]';
} else {
title = title.match(/admin\/(.+?)\/(.+?)$/);
title = '[[admin/menu:section-' +
(title[1] === 'development' ? 'advanced' : title[1]) +
']]' + (title[2] ? (' > [[admin/menu:' +
title[1] + '/' + title[2] + ']]') : '');
title = `[[admin/menu:section-${
title[1] === 'development' ? 'advanced' : title[1]
}]]${title[2] ? (` > [[admin/menu:${
title[1]}/${title[2]}]]`) : ''}`;
}
title = await translator.translate(title);
return {
namespace: namespace,
translations: str + '\n' + title,
translations: `${str}\n${title}`,
title: title,
};
} catch (err) {

@ -12,7 +12,7 @@ const isPrerelease = /^v?\d+\.\d+\.\d+-.+$/;
function getLatestVersion(callback) {
const headers = {
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) {

@ -131,7 +131,7 @@ Analytics.writeData = async function () {
if (Object.keys(counters).length > 0) {
for (const key in counters) {
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];
}
}
@ -139,7 +139,7 @@ Analytics.writeData = async function () {
try {
await Promise.all(dbQueue);
} 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;
}
};
@ -147,7 +147,7 @@ Analytics.writeData = async function () {
Analytics.getHourlyStatsForSet = async function (set, hour, numHours) {
// Guard against accidental ommission of `analytics:` prefix
if (!set.startsWith('analytics:')) {
set = 'analytics:' + set;
set = `analytics:${set}`;
}
const terms = {};
@ -180,7 +180,7 @@ Analytics.getHourlyStatsForSet = async function (set, hour, numHours) {
Analytics.getDailyStatsForSet = async function (set, day, numDays) {
// Guard against accidental ommission of `analytics:` prefix
if (!set.startsWith('analytics:')) {
set = 'analytics:' + set;
set = `analytics:${set}`;
}
const daysArr = [];
@ -218,10 +218,10 @@ Analytics.getSummary = async function () {
Analytics.getCategoryAnalytics = async function (cid) {
return await utils.promiseParallel({
'pageviews:hourly': Analytics.getHourlyStatsForSet('analytics:pageviews:byCid:' + cid, Date.now(), 24),
'pageviews:daily': Analytics.getDailyStatsForSet('analytics:pageviews:byCid:' + cid, Date.now(), 30),
'topics:daily': Analytics.getDailyStatsForSet('analytics:topics:byCid:' + cid, Date.now(), 7),
'posts:daily': Analytics.getDailyStatsForSet('analytics:posts:byCid:' + cid, Date.now(), 7),
'pageviews:hourly': Analytics.getHourlyStatsForSet(`analytics:pageviews:byCid:${cid}`, Date.now(), 24),
'pageviews:daily': Analytics.getDailyStatsForSet(`analytics:pageviews:byCid:${cid}`, Date.now(), 30),
'topics:daily': Analytics.getDailyStatsForSet(`analytics:topics: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 notification = await notifications.create({
type: 'group-leave',
bodyShort: '[[groups:membership.leave.notification_title, ' + username + ', ' + groupName + ']]',
nid: 'group:' + validator.escape(groupName) + ':uid:' + data.uid + ':group-leave',
path: '/groups/' + slugify(groupName),
bodyShort: `[[groups:membership.leave.notification_title, ${username}, ${groupName}]]`,
nid: `group:${validator.escape(groupName)}:uid:${data.uid}:group-leave`,
path: `/groups/${slugify(groupName)}`,
from: data.uid,
});
const uids = await groups.getOwners(groupName);

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

@ -50,13 +50,13 @@ postsAPI.edit = async function (caller, data) {
const contentLen = utils.stripHTMLTags(data.content).trim().length;
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) {
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) {
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) {
throw new Error('[[error:content-too-long, ' + meta.config.maximumPostLength + ']]');
throw new Error(`[[error:content-too-long, ${meta.config.maximumPostLength}]]`);
}
data.uid = caller.uid;
@ -81,19 +81,19 @@ postsAPI.edit = async function (caller, data) {
returnData.topic = { ...postObj[0].topic, ...editResult.post.topic };
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;
}
const memberData = await groups.getMembersOfGroups([
'administrators',
'Global Moderators',
'cid:' + editResult.topic.cid + ':privileges:moderate',
'cid:' + editResult.topic.cid + ':privileges:groups:moderate',
`cid:${editResult.topic.cid}:privileges:moderate`,
`cid:${editResult.topic.cid}:privileges:groups:moderate`,
]);
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;
};
@ -123,7 +123,7 @@ async function deleteOrRestore(caller, data, params) {
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({
type: params.type,
@ -165,7 +165,7 @@ postsAPI.purge = async function (caller, data) {
require('../posts/cache').del(data.pid);
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']);
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));
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,
};
// 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 };
delete payload.uid;
@ -144,10 +144,10 @@ usersAPI.follow = async function (caller, data) {
const userData = await user.getUserFields(caller.uid, ['username', 'userslug']);
const notifObj = await notifications.create({
type: 'follow',
bodyShort: '[[notifications:user_started_following_you, ' + userData.username + ']]',
nid: 'follow:' + data.uid + ':uid:' + caller.uid,
bodyShort: `[[notifications:user_started_following_you, ${userData.username}]]`,
nid: `follow:${data.uid}:uid:${caller.uid}`,
from: caller.uid,
path: '/uid/' + data.uid + '/followers',
path: `/uid/${data.uid}/followers`,
mergeId: 'notifications:user_started_following_you',
});
if (!notifObj) {
@ -173,13 +173,13 @@ usersAPI.ban = async function (caller, data) {
}
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) {
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,
reason: validator.escape(String(data.reason || '')),
});
@ -213,7 +213,7 @@ usersAPI.unban = async function (caller, data) {
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({
type: 'user-unban',

@ -41,7 +41,7 @@ exports.processSortedSet = async function (setKey, process, options) {
while (true) {
/* 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)) {
return;
}

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

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

@ -19,7 +19,7 @@ module.exports = function (Categories) {
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 result = await plugins.hooks.fire('filter:category.getFields', {
cids: cids,
@ -56,11 +56,11 @@ module.exports = function (Categories) {
};
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) {
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) {
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 topics.purgePostsAndTopic(tid, uid);
});
}, { 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 topics.purgePostsAndTopic(tid, uid);
});
@ -30,41 +30,41 @@ module.exports = function (Categories) {
const cid = categoryData.cid;
await db.sortedSetRemoveBulk([
['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 deleteTags(cid);
await db.deleteAll([
'cid:' + cid + ':tids',
'cid:' + cid + ':tids:pinned',
'cid:' + cid + ':tids:posts',
'cid:' + cid + ':tids:votes',
'cid:' + cid + ':tids:lastposttime',
'cid:' + cid + ':recent_tids',
'cid:' + cid + ':pids',
'cid:' + cid + ':read_by_uid',
'cid:' + cid + ':uid:watch:state',
'cid:' + cid + ':children',
'cid:' + cid + ':tag:whitelist',
'category:' + cid,
`cid:${cid}:tids`,
`cid:${cid}:tids:pinned`,
`cid:${cid}:tids:posts`,
`cid:${cid}:tids:votes`,
`cid:${cid}:tids:lastposttime`,
`cid:${cid}:recent_tids`,
`cid:${cid}:pids`,
`cid:${cid}:read_by_uid`,
`cid:${cid}:uid:watch:state`,
`cid:${cid}:children`,
`cid:${cid}:tag:whitelist`,
`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) {
const [parentCid, children] = await Promise.all([
Categories.getCategoryField(cid, 'parentCid'),
db.getSortedSetRange('cid:' + cid + ':children', 0, -1),
db.getSortedSetRange(`cid:${cid}:children`, 0, -1),
]);
const bulkAdd = [];
const childrenKeys = children.map(function (cid) {
bulkAdd.push(['cid:0:children', cid, cid]);
return 'category:' + cid;
return `category:${cid}`;
});
await Promise.all([
db.sortedSetRemove('cid:' + parentCid + ':children', cid),
db.sortedSetRemove(`cid:${parentCid}:children`, cid),
db.setObjectField(childrenKeys, 'parentCid', 0),
db.sortedSetAddBulk(bulkAdd),
]);
@ -72,17 +72,17 @@ module.exports = function (Categories) {
cache.del([
'categories:cid',
'cid:0:children',
'cid:' + parentCid + ':children',
'cid:' + parentCid + ':children:all',
'cid:' + cid + ':children',
'cid:' + cid + ':children:all',
'cid:' + cid + ':tag:whitelist',
`cid:${parentCid}:children`,
`cid:${parentCid}:children:all`,
`cid:${cid}:children`,
`cid:${cid}:children:all`,
`cid:${cid}:tag:whitelist`,
]);
}
async function deleteTags(cid) {
const tags = await db.getSortedSetMembers('cid:' + cid + ':tags');
await db.deleteAll(tags.map(tag => 'cid:' + cid + ':tag:' + tag + ':topics'));
await db.delete('cid:' + cid + ':tags');
const tags = await db.getSortedSetMembers(`cid:${cid}:tags`);
await db.deleteAll(tags.map(tag => `cid:${cid}:tag:${tag}:topics`));
await db.delete(`cid:${cid}:tags`);
}
};

@ -25,9 +25,9 @@ require('./search')(Categories);
Categories.exists = async function (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) {
@ -98,8 +98,8 @@ Categories.getModerators = async function (cid) {
Categories.getModeratorUids = async function (cids) {
const groupNames = cids.reduce(function (memo, cid) {
memo.push('cid:' + cid + ':privileges:moderate');
memo.push('cid:' + cid + ':privileges:groups:moderate');
memo.push(`cid:${cid}:privileges:moderate`);
memo.push(`cid:${cid}:privileges:groups:moderate`);
return memo;
}, []);
@ -150,7 +150,7 @@ Categories.getTagWhitelist = async function (cids) {
const cachedData = {};
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;
if (isInCache) {
cachedData[cid] = data;
@ -162,12 +162,12 @@ Categories.getTagWhitelist = async function (cids) {
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);
nonCachedCids.forEach((cid, 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]);
};
@ -252,12 +252,12 @@ Categories.getChildrenCids = async function (rootCid) {
if (!childrenCids.length) {
return;
}
keys = childrenCids.map(cid => 'cid:' + cid + ':children');
keys = childrenCids.map(cid => `cid:${cid}:children`);
childrenCids.forEach(cid => allCids.push(parseInt(cid, 10)));
await recursive(keys);
}
const key = 'cid:' + rootCid + ':children';
const cacheKey = key + ':all';
const key = `cid:${rootCid}:children`;
const cacheKey = `${key}:all`;
const childrenCids = cache.get(cacheKey);
if (childrenCids) {
return childrenCids.slice();
@ -368,7 +368,7 @@ Categories.buildForSelectCategories = function (categories, fields, parentCid) {
category.depth = depth;
categoriesData.push(category);
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;

@ -15,26 +15,26 @@ module.exports = function (Categories) {
if (!parseInt(count, 10)) {
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);
return await posts.getPostSummaryByPids(pids, uid, { stripTags: true });
};
Categories.updateRecentTid = async function (cid, tid) {
const [count, numRecentReplies] = await Promise.all([
db.sortedSetCard('cid:' + cid + ':recent_tids'),
db.getObjectField('category:' + cid, 'numRecentReplies'),
db.sortedSetCard(`cid:${cid}:recent_tids`),
db.getObjectField(`category:${cid}`, '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));
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) {
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 });
};
@ -45,7 +45,7 @@ module.exports = function (Categories) {
let index = 0;
do {
/* 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) {
return;
}
@ -77,7 +77,7 @@ module.exports = function (Categories) {
});
keys = result.keys;
} 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);
@ -174,19 +174,19 @@ module.exports = function (Categories) {
const bulkRemove = [];
const bulkAdd = [];
postData.forEach((post) => {
bulkRemove.push(['cid:' + oldCid + ':uid:' + post.uid + ':pids', 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]);
bulkRemove.push([`cid:${oldCid}:uid:${post.uid}:pids`, 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]);
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 timestamps = postsToReAdd.map(p => p && p.timestamp);
await Promise.all([
db.sortedSetRemove('cid:' + oldCid + ':pids', pids),
db.sortedSetAdd('cid:' + cid + ':pids', timestamps, postsToReAdd.map(p => p.pid)),
db.sortedSetRemove(`cid:${oldCid}:pids`, pids),
db.sortedSetAdd(`cid:${cid}:pids`, timestamps, postsToReAdd.map(p => p.pid)),
db.sortedSetRemoveBulk(bulkRemove),
db.sortedSetAddBulk(bulkAdd),
]);
@ -200,8 +200,8 @@ module.exports = function (Categories) {
}
await Promise.all([
db.incrObjectFieldBy('category:' + oldCid, 'post_count', -postCount),
db.incrObjectFieldBy('category:' + newCid, 'post_count', postCount),
db.incrObjectFieldBy(`category:${oldCid}`, 'post_count', -postCount),
db.incrObjectFieldBy(`category:${newCid}`, 'post_count', postCount),
]);
}
};

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

@ -92,24 +92,24 @@ module.exports = function (Categories) {
Categories.buildTopicsSortedSet = async function (data) {
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';
if (sort === 'most_posts') {
set = 'cid:' + cid + ':tids:posts';
set = `cid:${cid}:tids:posts`;
} else if (sort === 'most_votes') {
set = 'cid:' + cid + ':tids:votes';
set = `cid:${cid}:tids:votes`;
}
if (data.targetUid) {
set = 'cid:' + cid + ':uid:' + data.targetUid + ':tids';
set = `cid:${cid}:uid:${data.targetUid}:tids`;
}
if (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 {
set = [set, 'tag:' + data.tag + ':topics'];
set = [set, `tag:${data.tag}:topics`];
}
}
const result = await plugins.hooks.fire('filter:categories.buildTopicsSortedSet', {
@ -130,7 +130,7 @@ module.exports = function (Categories) {
};
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) {
@ -141,7 +141,7 @@ module.exports = function (Categories) {
});
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);
};
@ -166,11 +166,11 @@ module.exports = function (Categories) {
return;
}
const promises = [
db.sortedSetAdd('cid:' + cid + ':pids', postData.timestamp, postData.pid),
db.incrObjectField('category:' + cid, 'post_count'),
db.sortedSetAdd(`cid:${cid}:pids`, postData.timestamp, postData.pid),
db.incrObjectField(`category:${cid}`, 'post_count'),
];
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 Categories.updateRecentTidForCid(cid);

@ -7,7 +7,7 @@ module.exports = function (Categories) {
if (!Array.isArray(cids) || !cids.length || parseInt(uid, 10) <= 0) {
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);
keys = keys.filter((key, index) => !hasRead[index]);
await db.setsAdd(keys, uid);
@ -17,7 +17,7 @@ module.exports = function (Categories) {
if (!parseInt(cid, 10)) {
return;
}
await db.delete('cid:' + cid + ':read_by_uid');
await db.delete(`cid:${cid}:read_by_uid`);
};
Categories.hasReadCategories = async function (cids, uid) {
@ -25,7 +25,7 @@ module.exports = function (Categories) {
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);
};
@ -33,6 +33,6 @@ module.exports = function (Categories) {
if (parseInt(uid, 10) <= 0) {
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')) {
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 });
@ -54,7 +54,7 @@ module.exports = function (Categories) {
return await updateOrder(cid, value);
}
await db.setObjectField('category:' + cid, key, value);
await db.setObjectField(`category:${cid}`, key, value);
if (key === 'description') {
await Categories.parseDescription(cid, value);
}
@ -71,26 +71,26 @@ module.exports = function (Categories) {
}
const oldParent = await Categories.getCategoryField(cid, 'parentCid');
await Promise.all([
db.sortedSetRemove('cid:' + oldParent + ':children', cid),
db.sortedSetAdd('cid:' + newParent + ':children', cid, cid),
db.setObjectField('category:' + cid, 'parentCid', newParent),
db.sortedSetRemove(`cid:${oldParent}:children`, cid),
db.sortedSetAdd(`cid:${newParent}:children`, cid, cid),
db.setObjectField(`category:${cid}`, 'parentCid', newParent),
]);
cache.del([
'cid:' + oldParent + ':children',
'cid:' + newParent + ':children',
'cid:' + oldParent + ':children:all',
'cid:' + newParent + ':children:all',
`cid:${oldParent}:children`,
`cid:${newParent}:children`,
`cid:${oldParent}:children:all`,
`cid:${newParent}:children:all`,
]);
}
async function updateTagWhitelist(cid, tags) {
tags = tags.split(',').map(tag => utils.cleanUpTag(tag, meta.config.maximumTagLength))
.filter(Boolean);
await db.delete('cid:' + cid + ':tag:whitelist');
await db.delete(`cid:${cid}:tag:whitelist`);
const scores = tags.map((tag, index) => index);
await db.sortedSetAdd('cid:' + cid + ':tag:whitelist', scores, tags);
cache.del('cid:' + cid + ':tag:whitelist');
await db.sortedSetAdd(`cid:${cid}:tag:whitelist`, scores, tags);
cache.del(`cid:${cid}:tag:whitelist`);
}
async function updateOrder(cid, order) {
@ -98,7 +98,7 @@ module.exports = function (Categories) {
await db.sortedSetsAdd('categories:cid', order, cid);
const childrenCids = await db.getSortedSetRange(
'cid:' + parentCid + ':children', 0, -1
`cid:${parentCid}:children`, 0, -1
);
const currentIndex = childrenCids.indexOf(String(cid));
@ -112,20 +112,20 @@ module.exports = function (Categories) {
// recalculate orders from array indices
await db.sortedSetAdd(
'cid:' + parentCid + ':children',
`cid:${parentCid}:children`,
childrenCids.map((cid, index) => index + 1),
childrenCids
);
await db.setObjectBulk(
childrenCids.map(cid => 'category:' + cid),
childrenCids.map(cid => `category:${cid}`),
childrenCids.map((cid, index) => ({ order: index + 1 }))
);
cache.del([
'categories:cid',
'cid:' + parentCid + ':children',
'cid:' + parentCid + ':children:all',
`cid:${parentCid}:children`,
`cid:${parentCid}:children:all`,
]);
}
@ -136,8 +136,8 @@ module.exports = function (Categories) {
async function updateName(cid, newName) {
const oldName = await Categories.getCategoryField(cid, 'name');
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.setObjectField('category:' + cid, 'name', newName);
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.setObjectField(`category:${cid}`, 'name', newName);
}
};

@ -25,7 +25,7 @@ module.exports = function (Categories) {
if (!Array.isArray(cids) || !cids.length) {
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([
user.getSettings(uid),
db.sortedSetsScore(keys, uid),
@ -35,7 +35,7 @@ module.exports = function (Categories) {
Categories.getIgnorers = async function (cid, start, stop) {
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) {
@ -47,7 +47,7 @@ module.exports = function (Categories) {
Categories.getUidsWatchStates = async function (cid, uids) {
const [userSettings, states] = await Promise.all([
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]);
};

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

@ -43,7 +43,7 @@ try {
const checkVersion = function (packageName) {
const version = JSON.parse(fs.readFileSync(path.join(paths.nodeModules, packageName, 'package.json'), 'utf8')).version;
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';
throw e;
}
@ -194,7 +194,7 @@ program
});
program
.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')
.action(function (targets, options) {
require('./manage').build(targets.length ? targets : true, options);
@ -265,12 +265,12 @@ program
.option('-s, --schema', 'Update NodeBB data store schema', false)
.option('-b, --build', 'Rebuild assets', false)
.on('--help', function () {
console.log('\n' + [
console.log(`\n${[
'When running particular upgrade scripts, options are ignored.',
'By default all options are enabled. Passing any options disables that default.',
'Only package and dependency updates: ' + './nodebb upgrade -mi'.yellow,
'Only database update: ' + './nodebb upgrade -s'.yellow,
].join('\n'));
`Only package and dependency updates: ${'./nodebb upgrade -mi'.yellow}`,
`Only database update: ${'./nodebb upgrade -s'.yellow}`,
].join('\n')}`);
})
.action(function (scripts, options) {
require('./upgrade').upgrade(scripts.length ? scripts : true, options);

@ -23,7 +23,7 @@ async function activate(plugin) {
await db.init();
if (!pluginNamePattern.test(plugin)) {
// Allow omission of `nodebb-plugin-`
plugin = 'nodebb-plugin-' + plugin;
plugin = `nodebb-plugin-${plugin}`;
}
const isInstalled = await plugins.isInstalled(plugin);
if (!isInstalled) {
@ -42,7 +42,7 @@ async function activate(plugin) {
text: plugin,
});
} 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);
}
@ -72,7 +72,7 @@ async function listPlugins() {
// Pretty output
process.stdout.write('Active plugins:\n');
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(', ');
process.stdout.write(plugin.active ? 'enabled'.green : 'disabled'.yellow);
@ -85,9 +85,9 @@ async function listPlugins() {
async function listEvents(count) {
await db.init();
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) {
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();
}
@ -95,28 +95,28 @@ async function listEvents(count) {
async function info() {
console.log('');
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');
console.log(' git hash: ' + hash);
console.log(` git hash: ${hash}`);
const config = require('../../config.json');
console.log(' database: ' + config.database);
console.log(` database: ${config.database}`);
await db.init();
const info = await db.info(db.client);
switch (config.database) {
case 'redis':
console.log(' version: ' + info.redis_version);
console.log(' disk sync: ' + info.rdb_last_bgsave_status);
console.log(` version: ${info.redis_version}`);
console.log(` disk sync: ${info.rdb_last_bgsave_status}`);
break;
case 'mongo':
console.log(' version: ' + info.version);
console.log(' engine: ' + info.storageEngine);
console.log(` version: ${info.version}`);
console.log(` engine: ${info.storageEngine}`);
break;
}
@ -138,7 +138,7 @@ async function info() {
console.log('');
console.log(graph.toString());
console.log('Pageviews, last 24h (min: ' + min + ' max: ' + max + ')');
console.log(`Pageviews, last 24h (min: ${min} max: ${max})`);
process.exit();
}

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

@ -22,7 +22,7 @@ exports.reset = async function (options) {
} else {
if (!themeNamePattern.test(themeId)) {
// Allow omission of `nodebb-theme-`
themeId = 'nodebb-theme-' + themeId;
themeId = `nodebb-theme-${themeId}`;
}
await resetTheme(themeId);
@ -35,7 +35,7 @@ exports.reset = async function (options) {
} else {
if (!pluginNamePattern.test(pluginId)) {
// Allow omission of `nodebb-plugin-`
pluginId = 'nodebb-plugin-' + pluginId;
pluginId = `nodebb-plugin-${pluginId}`;
}
await resetPlugin(pluginId);
@ -56,7 +56,7 @@ exports.reset = async function (options) {
if (!tasks.length) {
console.log([
'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',
' -p\tplugins',
' -w\twidgets',
@ -80,7 +80,7 @@ exports.reset = async function (options) {
winston.info('[reset] Reset complete. Please run `./nodebb build` to rebuild assets.');
process.exit(0);
} 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);
}
};
@ -111,7 +111,7 @@ async function resetThemeTo(themeId) {
id: themeId,
});
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) {
@ -133,7 +133,7 @@ async function resetPlugin(pluginId) {
winston.info('[reset] No action taken.');
}
} 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;
}
}

@ -38,19 +38,19 @@ function start(options) {
return;
}
if (options.log) {
console.log('\n' + [
console.log(`\n${[
'Starting NodeBB with logging output'.bold,
'Hit '.red + 'Ctrl-C '.bold + 'to exit'.red,
'The NodeBB process will continue to run in the background',
'Use "' + './nodebb stop'.yellow + '" to stop the NodeBB server',
].join('\n'));
`Use "${'./nodebb stop'.yellow}" to stop the NodeBB server`,
].join('\n')}`);
} else if (!options.silent) {
console.log('\n' + [
console.log(`\n${[
'Starting NodeBB'.bold,
' "' + './nodebb stop'.yellow + '" to stop the NodeBB server',
' "' + './nodebb log'.yellow + '" to view server output',
' "' + './nodebb help'.yellow + '" for more commands\n'.reset,
].join('\n'));
` "${'./nodebb stop'.yellow}" to stop the NodeBB server`,
` "${'./nodebb log'.yellow}" to view server output`,
` "${'./nodebb help'.yellow}${'" for more commands\n'.reset}`,
].join('\n')}`);
}
// Spawn a new NodeBB process
@ -96,15 +96,15 @@ function restart(options) {
function status() {
getRunningPid(function (err, pid) {
if (!err) {
console.log('\n' + [
'NodeBB Running '.bold + ('(pid ' + pid.toString() + ')').cyan,
'\t"' + './nodebb stop'.yellow + '" to stop the NodeBB server',
'\t"' + './nodebb log'.yellow + '" to view server output',
'\t"' + './nodebb restart'.yellow + '" to restart NodeBB\n',
].join('\n'));
console.log(`\n${[
'NodeBB Running '.bold + (`(pid ${pid.toString()})`).cyan,
`\t"${'./nodebb stop'.yellow}" to stop the NodeBB server`,
`\t"${'./nodebb log'.yellow}" to view server output`,
`\t"${'./nodebb restart'.yellow}" to restart NodeBB\n`,
].join('\n')}`);
} else {
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');
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('Press enter to accept the default setting (shown in brackets).');
@ -50,16 +50,16 @@ function setup(initConfig) {
separator += '=';
}
}
console.log('\n' + separator + '\n');
console.log(`\n${separator}\n`);
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;
} else {
if (data.hasOwnProperty('password')) {
console.log('An administrative user was automatically created for you:');
console.log(' Username: ' + data.username + '');
console.log(' Password: ' + data.password + '');
console.log(` Username: ${data.username}`);
console.log(` Password: ${data.password}`);
console.log('');
}
console.log('NodeBB Setup Completed. Run "./nodebb start" to manually start your NodeBB server.');

@ -126,7 +126,7 @@ function checkPlugins(standalone, callback) {
request({
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,
}, function (err, res, body) {
if (err) {
@ -175,9 +175,9 @@ function upgradePlugins(callback) {
}
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) {
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 {
if (standalone) {
@ -202,7 +202,7 @@ function upgradePlugins(callback) {
if (['y', 'Y', 'yes', 'YES'].includes(result.upgrade)) {
console.log('\nUpgrading packages...');
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) {

@ -55,7 +55,7 @@ var steps = {
function runSteps(tasks) {
tasks = tasks.map(function (key, i) {
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) {
if (err) { return next(err); }
next();
@ -65,7 +65,7 @@ function runSteps(tasks) {
async.series(tasks, function (err) {
if (err) {
console.error('Error occurred during upgrade: ' + err.stack);
console.error(`Error occurred during upgrade: ${err.stack}`);
throw err;
}
@ -74,7 +74,7 @@ function runSteps(tasks) {
var columns = process.stdout.columns;
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();
});

@ -10,7 +10,7 @@ const middleware = require('../middleware');
exports.handle404 = function handle404(req, res) {
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')) {
return plugins.hooks.fire('action:meta.override404', {
@ -22,12 +22,12 @@ exports.handle404 = function handle404(req, res) {
if (isClientScript.test(req.url)) {
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 || '');
res.sendStatus(404);
} else if (req.accepts('html')) {
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/, '') || '');

@ -28,12 +28,12 @@ blocksController.getBlocks = async function (req, res, next) {
data.uids = data.uids.slice(start, stop + 1);
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);
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);
};

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

@ -61,5 +61,5 @@ chatsController.redirectToChat = async function (req, res, next) {
return next();
}
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) {
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.digest = {
frequency: meta.config.dailyDigestFreq || 'off',
@ -24,7 +24,7 @@ consentController.get = async function (req, res, next) {
};
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);
};

@ -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.allowCoverPicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:cover-picture'];
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.allowAccountDelete = meta.config.allowAccountDelete === 1;
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.title = '[[pages:account/edit, ' + userData.username + ']]';
userData.title = `[[pages:account/edit, ${userData.username}]]`;
userData.breadcrumbs = helpers.buildBreadcrumbs([
{
text: userData.username,
url: '/user/' + userData.userslug,
url: `/user/${userData.userslug}`,
},
{
text: '[[user:edit]]',
@ -86,7 +86,7 @@ async function renderRoute(name, req, res, next) {
if (!userData) {
return next();
}
if (meta.config[name + ':disableEdit'] && !userData.isAdmin) {
if (meta.config[`${name}:disableEdit`] && !userData.isAdmin) {
return helpers.notAllowed(req, res);
}
@ -95,22 +95,22 @@ async function renderRoute(name, req, res, next) {
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([
{
text: userData.username,
url: '/user/' + userData.userslug,
url: `/user/${userData.userslug}`,
},
{
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) {

@ -26,7 +26,7 @@ async function getFollow(tpl, name, req, res, next) {
const start = Math.max(0, page - 1) * resultsPerPage;
const stop = start + resultsPerPage - 1;
userData.title = '[[pages:' + tpl + ', ' + userData.username + ']]';
userData.title = `[[pages:${tpl}, ${userData.username}]]`;
const method = name === 'following' ? 'getFollowing' : 'getFollowers';
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);
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);
}

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

@ -93,7 +93,7 @@ helpers.getUserDataByUserSlug = async function (userslug, callerUID) {
userData.sso = results.sso.associations;
userData.banned = Boolean(userData.banned);
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.fullname = validator.escape(String(userData.fullname || ''));
@ -143,17 +143,17 @@ async function getCounts(userData, callerUID) {
const uid = userData.uid;
const cids = await categories.getCidsByPrivilege('categories:cid', callerUID, 'topics:read');
const promises = {
posts: db.sortedSetsCardSum(cids.map(c => 'cid:' + c + ':uid:' + uid + ':pids')),
best: db.sortedSetsCardSum(cids.map(c => 'cid:' + c + ':uid:' + uid + ':pids:votes')),
topics: db.sortedSetsCardSum(cids.map(c => 'cid:' + c + ':uid:' + uid + ':tids')),
posts: db.sortedSetsCardSum(cids.map(c => `cid:${c}:uid:${uid}:pids`)),
best: db.sortedSetsCardSum(cids.map(c => `cid:${c}:uid:${uid}:pids:votes`)),
topics: db.sortedSetsCardSum(cids.map(c => `cid:${c}:uid:${uid}:tids`)),
};
if (userData.isAdmin || userData.isSelf) {
promises.ignored = db.sortedSetCard('uid:' + uid + ':ignored_tids');
promises.watched = db.sortedSetCard('uid:' + uid + ':followed_tids');
promises.upvoted = db.sortedSetCard('uid:' + uid + ':upvote');
promises.downvoted = db.sortedSetCard('uid:' + uid + ':downvote');
promises.bookmarks = db.sortedSetCard('uid:' + uid + ':bookmarks');
promises.uploaded = db.sortedSetCard('uid:' + uid + ':uploads');
promises.ignored = db.sortedSetCard(`uid:${uid}:ignored_tids`);
promises.watched = db.sortedSetCard(`uid:${uid}:followed_tids`);
promises.upvoted = db.sortedSetCard(`uid:${uid}:upvote`);
promises.downvoted = db.sortedSetCard(`uid:${uid}:downvote`);
promises.bookmarks = db.sortedSetCard(`uid:${uid}:bookmarks`);
promises.uploaded = db.sortedSetCard(`uid:${uid}:uploads`);
promises.categoriesWatched = user.getWatchedCategories(uid);
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([
user.getModerationHistory(userData.uid),
user.auth.getSessions(userData.uid, req.sessionID),
user.getHistory('user:' + userData.uid + ':usernames'),
user.getHistory('user:' + userData.uid + ':emails'),
user.getHistory(`user:${userData.uid}:usernames`),
user.getHistory(`user:${userData.uid}:emails`),
getNotes(userData, start, stop),
]);
@ -37,7 +37,7 @@ infoController.get = async function (req, res, next) {
userData.pagination = pagination.create(page, pageCount, req.query);
}
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);
};
@ -48,7 +48,7 @@ async function getNotes(userData, start, stop) {
}
const [notes, count] = await Promise.all([
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 };
}

@ -17,7 +17,7 @@ const templateToData = {
noItemsFoundKey: '[[topic:bookmarks.has_no_bookmarks]]',
crumb: '[[user:bookmarks]]',
getSets: function (callerUid, userData) {
return 'uid:' + userData.uid + ':bookmarks';
return `uid:${userData.uid}:bookmarks`;
},
},
'account/posts': {
@ -26,7 +26,7 @@ const templateToData = {
crumb: '[[global:posts]]',
getSets: async function (callerUid, userData) {
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': {
@ -34,7 +34,7 @@ const templateToData = {
noItemsFoundKey: '[[user:has_no_upvoted_posts]]',
crumb: '[[global:upvoted]]',
getSets: function (callerUid, userData) {
return 'uid:' + userData.uid + ':upvote';
return `uid:${userData.uid}:upvote`;
},
},
'account/downvoted': {
@ -42,7 +42,7 @@ const templateToData = {
noItemsFoundKey: '[[user:has_no_downvoted_posts]]',
crumb: '[[global:downvoted]]',
getSets: function (callerUid, userData) {
return 'uid:' + userData.uid + ':downvote';
return `uid:${userData.uid}:downvote`;
},
},
'account/best': {
@ -51,7 +51,7 @@ const templateToData = {
crumb: '[[global:best]]',
getSets: async function (callerUid, userData) {
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': {
@ -59,7 +59,7 @@ const templateToData = {
noItemsFoundKey: '[[user:has_no_watched_topics]]',
crumb: '[[user:watched]]',
getSets: function (callerUid, userData) {
return 'uid:' + userData.uid + ':followed_tids';
return `uid:${userData.uid}:followed_tids`;
},
getTopics: async function (set, req, start, stop) {
const sort = req.query.sort;
@ -92,7 +92,7 @@ const templateToData = {
noItemsFoundKey: '[[user:has_no_ignored_topics]]',
crumb: '[[user:ignored]]',
getSets: function (callerUid, userData) {
return 'uid:' + userData.uid + ':ignored_tids';
return `uid:${userData.uid}:ignored_tids`;
},
},
'account/topics': {
@ -101,7 +101,7 @@ const templateToData = {
crumb: '[[global:topics]]',
getSets: async function (callerUid, userData) {
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.noItemsFoundKey = data.noItemsFoundKey;
userData.title = '[[pages:' + template + ', ' + userData.username + ']]';
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: data.crumb }]);
userData.title = `[[pages:${template}, ${userData.username}]]`;
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: data.crumb }]);
userData.showSort = template === 'account/watched';
const baseUrl = (req.baseUrl + req.path.replace(/^\/api/, ''));
userData.sortOptions = [
{ url: baseUrl + '?sort=votes', name: '[[global:votes]]' },
{ url: baseUrl + '?sort=posts', name: '[[global:posts]]' },
{ url: baseUrl + '?sort=views', name: '[[global:views]]' },
{ url: baseUrl + '?sort=lastpost', name: '[[global:lastpost]]' },
{ url: baseUrl + '?sort=firstpost', name: '[[global:firstpost]]' },
{ url: `${baseUrl}?sort=votes`, name: '[[global:votes]]' },
{ url: `${baseUrl}?sort=posts`, name: '[[global:posts]]' },
{ url: `${baseUrl}?sort=views`, name: '[[global:views]]' },
{ url: `${baseUrl}?sort=lastpost`, name: '[[global:lastpost]]' },
{ url: `${baseUrl}?sort=firstpost`, name: '[[global:firstpost]]' },
];
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);

@ -21,7 +21,7 @@ profileController.get = async function (req, res, next) {
if (res.locals.isAPI) {
req.params.userslug = lowercaseSlug;
} 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) {
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 start = 0;
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.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);
};

@ -116,7 +116,7 @@ settingsController.get = async function (req, res, next) {
userData.maxPostsPerPage = meta.config.maxPostsPerPage;
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);
};
@ -132,8 +132,8 @@ const doUnsubscribe = async (payload) => {
user.updateDigestSetting(payload.uid, 'off'),
]);
} else if (payload.template === 'notification') {
const current = await db.getObjectField('user:' + payload.uid + ':settings', 'notificationType_' + payload.type);
await user.setSetting(payload.uid, 'notificationType_' + payload.type, (current === 'notificationemail' ? 'notification' : 'none'));
const current = await db.getObjectField(`user:${payload.uid}:settings`, `notificationType_${payload.type}`);
await user.setSetting(payload.uid, `notificationType_${payload.type}`, (current === 'notificationemail' ? 'notification' : 'none'));
}
return true;
};
@ -173,7 +173,7 @@ settingsController.unsubscribePost = async function (req, res) {
await doUnsubscribe(payload);
res.sendStatus(200);
} 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);
}
};
@ -200,7 +200,7 @@ async function getNotificationSettings(userData) {
const setting = userData.settings[type];
return {
name: type,
label: '[[notifications:' + type + ']]',
label: `[[notifications:${type}]]`,
none: setting === 'none',
notification: setting === 'notification',
email: setting === 'email',

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

@ -5,5 +5,5 @@ const appearanceController = module.exports;
appearanceController.get = function (req, res) {
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);
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.write(data, function (err) {
if (err) {

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

@ -69,7 +69,7 @@ async function getLatestVersion() {
try {
return await versions.getLatestVersion();
} 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;
}
@ -94,7 +94,7 @@ dashboardController.getAnalytics = async (req, res, next) => {
}
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);
res.json({

@ -21,7 +21,7 @@ eventsController.get = async function (req, res) {
const currentFilter = req.query.type || '';
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),
]);

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

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

@ -49,7 +49,7 @@ infoController.get = function (req, res) {
pubsub.on('sync:node:info:start', async function () {
try {
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 });
} catch (err) {
winston.error(err.stack);
@ -107,13 +107,13 @@ async function getNodeInfo() {
function humanReadableUptime(seconds) {
if (seconds < 60) {
return Math.floor(seconds) + 's';
return `${Math.floor(seconds)}s`;
} else if (seconds < 3600) {
return Math.floor(seconds / 60) + 'm';
return `${Math.floor(seconds / 60)}m`;
} 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() {

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

@ -73,8 +73,8 @@ function buildBreadcrumbs(currentFolder) {
crumbs.push({
text: part || 'Uploads',
url: part ?
(nconf.get('relative_path') + '/admin/manage/uploads?dir=' + dir) :
nconf.get('relative_path') + '/admin/manage/uploads',
(`${nconf.get('relative_path')}/admin/manage/uploads?dir=${dir}`) :
`${nconf.get('relative_path')}/admin/manage/uploads`,
});
currentPath = dir;
});
@ -92,14 +92,14 @@ async function getFileData(currentDir, file) {
if (stat.isDirectory()) {
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 {
name: file,
path: path.join(currentDir, file).replace(nconf.get('upload_path'), ''),
url: url,
fileCount: Math.max(0, filesInDir.length - 1), // ignore .gitignore
size: stat.size,
sizeHumanReadable: (stat.size / 1024).toFixed(1) + 'KiB',
sizeHumanReadable: `${(stat.size / 1024).toFixed(1)}KiB`,
isDirectory: stat.isDirectory(),
isFile: stat.isFile(),
mtime: stat.mtimeMs,
@ -118,7 +118,7 @@ uploadsController.uploadCategoryPicture = async function (req, res, next) {
}
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);
}
};
@ -152,7 +152,7 @@ uploadsController.uploadTouchIcon = async function (req, res, next) {
/* eslint-disable no-await-in-loop */
await image.resizeImage({
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,
height: size,
});
@ -227,7 +227,7 @@ async function upload(name, req, res, next) {
function validateUpload(res, uploadedFile, allowedTypes) {
if (!allowedTypes.includes(uploadedFile.type)) {
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;
}

@ -153,7 +153,7 @@ usersController.search = async function (req, res) {
}
const data = await db.getSortedSetScan({
key: searchBy + ':sorted',
key: `${searchBy}:sorted`,
match: query,
limit: hardCap || (resultsPerPage * 10),
});
@ -233,13 +233,13 @@ async function render(req, res, data) {
data.inviteOnly = registrationType === 'invite-only' || registrationType === 'admin-invite-only';
data.adminInviteOnly = registrationType === 'admin-invite-only';
data['sort_' + data.sortBy] = true;
data[`sort_${data.sortBy}`] = true;
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];
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);
if (data.adminInviteOnly) {

@ -35,10 +35,10 @@ async function registerAndLoginUser(req, res, userData) {
req.session.registration = userData;
if (req.body.noscript === 'true') {
res.redirect(nconf.get('relative_path') + '/register/complete');
res.redirect(`${nconf.get('relative_path')}/register/complete`);
return;
}
res.json({ next: nconf.get('relative_path') + '/register/complete' });
res.json({ next: `${nconf.get('relative_path')}/register/complete` });
return;
}
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.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 });
req.session.returnTo = complete.next;
return complete;
@ -154,17 +154,17 @@ authenticationController.registerComplete = function (req, res, next) {
var done = function (err, data) {
delete req.session.registration;
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) {
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) {
res.redirect(nconf.get('relative_path') + req.session.returnTo);
} 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);
if (errors.length) {
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) {
@ -203,7 +203,7 @@ authenticationController.registerAbort = function (req, res) {
// End the session and redirect to home
req.session.destroy(function () {
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)) {
(res.locals.continueLogin || continueLogin)(strategy, req, res, next);
} else {
err = '[[error:wrong-login-type-' + loginWith + ']]';
err = `[[error:wrong-login-type-${loginWith}]]`;
(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 });
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;
const code = await user.reset.generate(userData.uid);
res.status(200).send({
next: nconf.get('relative_path') + '/reset/' + code,
next: `${nconf.get('relative_path')}/reset/${code}`,
});
} else {
delete req.query.lang;
@ -290,11 +290,11 @@ function continueLogin(strategy, req, res, next) {
nconf.get('relative_path') + req.session.returnTo;
delete req.session.returnTo;
} else {
destination = nconf.get('relative_path') + '/';
destination = `${nconf.get('relative_path')}/`;
}
if (req.body.noscript === 'true') {
res.redirect(destination + '?loggedin');
res.redirect(`${destination}?loggedin`);
} else {
res.status(200).send({
next: destination,
@ -352,11 +352,11 @@ authenticationController.onSuccessfulLogin = async function (req, uid) {
user.updateOnlineUsers(uid),
]);
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
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 });
} 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 });
// 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 = {
next: nconf.get('relative_path') + '/',
next: `${nconf.get('relative_path')}/`,
};
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]]');
}
return banInfo.banned_until ?
'[[error:user-banned-reason-until, ' + banInfo.banned_until_readable + ', ' + banInfo.reason + ']]' :
'[[error:user-banned-reason, ' + banInfo.reason + ']]';
`[[error:user-banned-reason-until, ${banInfo.banned_until_readable}, ${banInfo.reason}]]` :
`[[error:user-banned-reason, ${banInfo.reason}]]`;
} catch (err) {
if (err.message === 'no-ban-info') {
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.breadcrumbs = helpers.buildBreadcrumbs([{ text: data.title }]);
res.locals.metaTags.push({

@ -42,19 +42,19 @@ categoryController.get = async function (req, res, next) {
return next();
}
if (topicIndex < 0) {
return helpers.redirect(res, '/category/' + categoryFields.slug);
return helpers.redirect(res, `/category/${categoryFields.slug}`);
}
if (!userPrivileges.read) {
return helpers.notAllowed(req, res);
}
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);
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);
}
if (categoryFields.link) {
await db.incrObjectField('category:' + cid, 'timesClicked');
await db.incrObjectField(`category:${cid}`, 'timesClicked');
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)) {
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));
if (userSettings.usePagination && currentPage > pageCount) {
@ -119,10 +119,10 @@ categoryController.get = async function (req, res, next) {
categoryData.showSelect = userPrivileges.editable;
categoryData.showTopicTools = userPrivileges.editable;
categoryData.topicIndex = topicIndex;
categoryData.rssFeedUrl = url + '/category/' + categoryData.cid + '.rss';
categoryData.rssFeedUrl = `${url}/category/${categoryData.cid}.rss`;
if (parseInt(req.uid, 10)) {
categories.markAsRead([cid], req.uid);
categoryData.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken;
categoryData.rssFeedUrl += `?uid=${req.uid}&token=${rssToken}`;
}
addTags(categoryData, res);
@ -131,11 +131,11 @@ categoryController.get = async function (req, res, next) {
categoryData['reputation:disabled'] = meta.config['reputation:disabled'];
categoryData.pagination = pagination.create(currentPage, pageCount, req.query);
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);
});
analytics.increment(['pageviews:byCid:' + categoryData.cid]);
analytics.increment([`pageviews:byCid:${categoryData.cid}`]);
res.render('category', categoryData);
};
@ -144,12 +144,12 @@ async function buildBreadcrumbs(req, categoryData) {
const breadcrumbs = [
{
text: categoryData.name,
url: relative_path + '/category/' + categoryData.slug,
url: `${relative_path}/category/${categoryData.slug}`,
cid: categoryData.cid,
},
];
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);
}
}

@ -77,11 +77,11 @@ exports.post = async function (req, res) {
throw new Error('[[error:invalid-data]]');
}
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;
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);
} catch (err) {
helpers.noScriptErrors(req, res, err.message, 400);

@ -9,7 +9,7 @@ var middleware = require('../middleware');
exports.handleURIErrors = async function handleURIErrors(err, req, res, next) {
// Handle cases where malformed URIs are passed in
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 cidMatch = cleanPath.match(/^\/category\/(\d+)\//);
@ -18,8 +18,8 @@ exports.handleURIErrors = async function handleURIErrors(err, req, res, next) {
} else if (cidMatch) {
res.redirect(nconf.get('relative_path') + cidMatch[0]);
} else {
winston.warn('[controller] Bad request: ' + req.path);
if (req.path.startsWith(nconf.get('relative_path') + '/api')) {
winston.warn(`[controller] Bad request: ${req.path}`);
if (req.path.startsWith(`${nconf.get('relative_path')}/api`)) {
res.status(400).json({
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
var cases = {
EBADCSRFTOKEN: function () {
winston.error(req.path + '\n' + err.message);
winston.error(`${req.path}\n${err.message}`);
res.sendStatus(403);
},
'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);
}
winston.error(req.path + '\n' + err.stack);
winston.error(`${req.path}\n${err.stack}`);
res.status(status || 500);
@ -70,7 +70,7 @@ exports.handleErrors = function handleErrors(err, req, res, next) { // eslint-di
}, function (_err, data) {
if (_err) {
// 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;
}

@ -35,7 +35,7 @@ groupsController.details = async function (req, res, next) {
if (res.locals.isAPI) {
req.params.slug = lowercaseSlug;
} 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);
@ -74,7 +74,7 @@ groupsController.details = async function (req, res, next) {
groupData.isOwner = groupData.isOwner || isAdmin || (isGlobalMod && !groupData.system);
res.render('groups/details', {
title: '[[pages:group, ' + groupData.displayName + ']]',
title: `[[pages:group, ${groupData.displayName}]]`,
group: groupData,
posts: posts,
isAdmin: isAdmin,
@ -103,11 +103,11 @@ groupsController.members = async function (req, res, next) {
if (isHidden && !isMember && !isAdminOrGlobalMod) {
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([
{ 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]]' },
]);

@ -30,7 +30,7 @@ helpers.noScriptErrors = async function (req, res, error, httpStatus) {
loggedIn: req.loggedIn,
error: error,
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._;
return Object.keys(queryObj).length ? '?' + querystring.stringify(queryObj) : '';
return Object.keys(queryObj).length ? `?${querystring.stringify(queryObj)}` : '';
};
helpers.addLinkTags = function (params) {
params.res.locals.linkTags = params.res.locals.linkTags || [];
params.res.locals.linkTags.push({
rel: 'canonical',
href: url + '/' + params.url,
href: `${url}/${params.url}`,
});
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);
});
};
@ -140,7 +140,7 @@ helpers.notAllowed = async function (req, res, error) {
helpers.formatApiResponse(401, res, error);
} else {
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) {
breadcrumbs.unshift({
text: String(data.name),
url: relative_path + '/category/' + data.slug,
url: `${relative_path}/category/${data.slug}`,
cid: cid,
});
}
@ -188,13 +188,13 @@ helpers.buildCategoryBreadcrumbs = async function (cid) {
if (meta.config.homePageRoute && meta.config.homePageRoute !== 'categories') {
breadcrumbs.unshift({
text: '[[global:header.categories]]',
url: relative_path + '/categories',
url: `${relative_path}/categories`,
});
}
breadcrumbs.unshift({
text: '[[global:home]]',
url: relative_path + '/',
url: `${relative_path}/`,
});
return breadcrumbs;
@ -204,7 +204,7 @@ helpers.buildBreadcrumbs = function (crumbs) {
const breadcrumbs = [
{
text: '[[global:home]]',
url: relative_path + '/',
url: `${relative_path}/`,
},
];
@ -369,7 +369,7 @@ helpers.trimChildren = function (category) {
helpers.setCategoryTeaser = function (category) {
if (Array.isArray(category.posts) && category.posts.length && category.posts[0]) {
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,
pid: category.posts[0].pid,
topic: category.posts[0].topic,

@ -38,7 +38,7 @@ async function rewrite(req, res, next) {
}
const pathname = parsedUrl.pathname;
const hook = 'action:homepage.get:' + pathname;
const hook = `action:homepage.get:${pathname}`;
if (!plugins.hooks.hasListeners(hook)) {
req.url = req.path + (!req.path.endsWith('/') ? '/' : '') + pathname;
} else {
@ -52,7 +52,7 @@ async function rewrite(req, res, next) {
exports.rewrite = rewrite;
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, {
req: req,

@ -113,7 +113,7 @@ Controllers.login = async function (req, res) {
data.alternate_logins = loginStrategies.length > 0;
data.authentication = loginStrategies;
data.allowRegistration = registrationType === 'normal';
data.allowLoginWith = '[[login:' + allowLoginWith + ']]';
data.allowLoginWith = `[[login:${allowLoginWith}]]`;
data.breadcrumbs = helpers.buildBreadcrumbs([{
text: '[[global:login]]',
}]);
@ -187,7 +187,7 @@ Controllers.register = async function (req, res, next) {
Controllers.registerInterstitial = async function (req, res, next) {
if (!req.session.hasOwnProperty('registration')) {
return res.redirect(nconf.get('relative_path') + '/register');
return res.redirect(`${nconf.get('relative_path')}/register`);
}
try {
const data = await plugins.hooks.fire('filter:register.interstitial', {
@ -230,11 +230,11 @@ Controllers.robots = function (req, res) {
if (meta.config['robots:txt']) {
res.send(meta.config['robots:txt']);
} else {
res.send('User-agent: *\n' +
'Disallow: ' + nconf.get('relative_path') + '/admin/\n' +
'Disallow: ' + nconf.get('relative_path') + '/reset/\n' +
'Disallow: ' + nconf.get('relative_path') + '/compose\n' +
'Sitemap: ' + nconf.get('url') + '/sitemap.xml');
res.send(`${'User-agent: *\n' +
'Disallow: '}${nconf.get('relative_path')}/admin/\n` +
`Disallow: ${nconf.get('relative_path')}/reset/\n` +
`Disallow: ${nconf.get('relative_path')}/compose\n` +
`Sitemap: ${nconf.get('url')}/sitemap.xml`);
}
};
@ -252,37 +252,37 @@ Controllers.manifest = async function (req, res) {
if (meta.config['brand:touchIcon']) {
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',
type: 'image/png',
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',
type: 'image/png',
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',
type: 'image/png',
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',
type: 'image/png',
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',
type: 'image/png',
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',
type: 'image/png',
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',
type: 'image/png',
density: 10.0,
@ -292,13 +292,13 @@ Controllers.manifest = async function (req, res) {
if (meta.config['brand:maskableIcon']) {
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',
purpose: 'maskable',
});
} else if (meta.config['brand:touchIcon']) {
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',
purpose: 'maskable',
});

@ -138,11 +138,11 @@ modsController.flags.detail = async function (req, res, next) {
return memo;
}, {}),
title: '[[pages:flag-details, ' + req.params.flagId + ']]',
title: `[[pages:flag-details, ${req.params.flagId}]]`,
privileges: results.privileges,
breadcrumbs: helpers.buildBreadcrumbs([
{ 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]]',
posts: postData,
...categoriesData,
allCategoriesUrl: 'post-queue' + helpers.buildQueryString(req.query, 'cid', ''),
allCategoriesUrl: `post-queue${helpers.buildQueryString(req.query, 'cid', '')}`,
pagination: pagination.create(page, pageCount),
breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:post-queue]]' }]),
});
};
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);
postData.forEach(function (data) {
if (data) {

@ -30,16 +30,16 @@ function generateXML() {
height: '16',
type: 'image/x-icon',
} },
nconf.get('url') + '/favicon.ico',
`${nconf.get('url')}/favicon.ico`,
] },
{ Url: {
_attr: {
type: 'text/html',
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' });
}

@ -6,7 +6,7 @@ const db = require('../database');
module.exports.ping = async function (req, res, next) {
try {
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) {
next(err);
}

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

@ -26,7 +26,7 @@ postsController.redirectToPost = async function (req, res, next) {
}
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) {

@ -62,9 +62,9 @@ recentController.getData = async function (req, url, sort) {
data.selectedCategory = categoryData.selectedCategory;
data.selectedCids = categoryData.selectedCids;
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) {
data.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken;
data.rssFeedUrl += `?uid=${req.uid}&token=${rssToken}`;
}
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);
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)) {
data.title = '[[pages:' + url + ']]';
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[' + url + ':title]]' }]);
if (req.originalUrl.startsWith(`${nconf.get('relative_path')}/api/${url}`) || req.originalUrl.startsWith(`${nconf.get('relative_path')}/${url}`)) {
data.title = `[[pages:${url}]]`;
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: `[[${url}:title]]` }]);
}
return data;

@ -22,7 +22,7 @@ tagsController.getTag = async function (req, res) {
topics: [],
tag: 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([
user.getSettings(req.uid),
@ -51,10 +51,10 @@ tagsController.getTag = async function (req, res) {
const pageCount = Math.max(1, Math.ceil(topicCount / settings.topicsPerPage));
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.rssFeedUrl = nconf.get('relative_path') + '/tags/' + tag + '.rss';
templateData.rssFeedUrl = `${nconf.get('relative_path')}/tags/${tag}.rss`;
res.render('tag', templateData);
};

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

@ -48,8 +48,8 @@ topicsController.get = async function getTopic(req, res, callback) {
return helpers.notAllowed(req, res);
}
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);
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);
}
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)) {
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);
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';
if (settings.usePagination && !req.query.page) {
currentPage = calculatePageFromIndex(postIndex, settings);
@ -85,9 +85,9 @@ topicsController.get = async function getTopic(req, res, callback) {
topicData.updateUrlWithPostIndex = settings.updateUrlWithPostIndex;
topicData.allowMultipleBadges = meta.config.allowMultipleBadges === 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) {
topicData.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken;
topicData.rssFeedUrl += `?uid=${req.uid}&token=${rssToken}`;
}
topicData.postIndex = postIndex;
@ -98,12 +98,12 @@ topicsController.get = async function getTopic(req, res, callback) {
addTags(topicData, req, res),
incrementViewCount(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.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);
});
@ -157,7 +157,7 @@ async function buildBreadcrumbs(topicData) {
const breadcrumbs = [
{
text: topicData.category.name,
url: relative_path + '/category/' + topicData.category.slug,
url: `${relative_path}/category/${topicData.category.slug}`,
cid: topicData.category.cid,
},
{
@ -185,7 +185,7 @@ async function addTags(topicData, req, res) {
}
if (description.length > 255) {
description = description.substr(0, 255) + '...';
description = `${description.substr(0, 255)}...`;
}
description = description.replace(/\n/g, ' ');
@ -229,7 +229,7 @@ async function addTags(topicData, req, res) {
res.locals.linkTags = [
{
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) {
res.locals.linkTags.push({
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) {
const uploads = postAtIndex ? await posts.uploads.listWithSizes(postAtIndex.pid) : [];
const images = uploads.map((upload) => {
upload.name = url + upload_url + '/files/' + upload.name;
upload.name = `${url + upload_url}/files/${upload.name}`;
return upload;
});
if (topicData.thumbs) {
@ -270,7 +270,7 @@ async function addOGImageTags(res, topicData, postAtIndex) {
function addOGImageTag(res, image) {
let imageUrl;
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') {
imageUrl = image.name;
} else {
@ -345,7 +345,7 @@ topicsController.pagination = async function (req, res, callback) {
const paginationData = pagination.create(currentPage, pageCount);
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 });

@ -41,15 +41,15 @@ unreadController.get = async function (req, res) {
if (userSettings.usePagination && (page < 1 || page > data.pageCount)) {
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.showTopicTools = isPrivileged;
data.allCategoriesUrl = 'unread' + helpers.buildQueryString(req.query, 'cid', '');
data.allCategoriesUrl = `unread${helpers.buildQueryString(req.query, 'cid', '')}`;
data.selectedCategory = categoryData.selectedCategory;
data.selectedCids = categoryData.selectedCids;
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.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[unread:title]]' }]);
}

@ -162,14 +162,14 @@ uploadsController.uploadFile = async function (uid, uploadedFile) {
}
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 extension = path.extname(uploadedFile.name).toLowerCase();
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);
@ -179,7 +179,7 @@ async function saveFileToLocal(uid, folder, uploadedFile) {
const name = uploadedFile.name || 'upload';
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 storedFile = {
@ -188,7 +188,7 @@ async function saveFileToLocal(uid, folder, uploadedFile) {
name: uploadedFile.name,
};
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 });
return data.storedFile;
}

@ -77,15 +77,15 @@ userController.getUserDataByUID = async function (callerUid, uid) {
};
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) {
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) {
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) {
@ -93,7 +93,7 @@ function sendExport(filename, type, res, next) {
root: path.join(__dirname, '../../build/export'),
headers: {
'Content-Type': type,
'Content-Disposition': 'attachment; filename=' + filename,
'Content-Disposition': `attachment; filename=${filename}`,
},
}, function (err) {
if (err) {

@ -37,7 +37,7 @@ usersController.search = async function (req, res) {
const section = req.query.section || 'joindate';
searchData.pagination = pagination.create(req.query.page, searchData.pageCount, req.query);
searchData['section_' + section] = true;
searchData[`section_${section}`] = true;
searchData.displayUserSearch = true;
await render(req, res, searchData);
};
@ -141,7 +141,7 @@ usersController.getUsers = async function (set, uid, query) {
isAdmin: isAdmin,
isGlobalMod: isGlobalMod,
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);
}
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;
for (const sid of sids) {
/* eslint-disable no-await-in-loop */
@ -204,7 +204,7 @@ Users.invite = async (req, res) => {
invites = await user.getInvitesNumber(req.uid);
}
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);

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

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

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

@ -12,7 +12,7 @@ connection.getConnectionString = function (mongo) {
var usernamePassword = '';
var uri = mongo.uri || '';
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('@'))) {
winston.warn('You have no mongo username/password setup!');
}
@ -35,10 +35,10 @@ connection.getConnectionString = function (mongo) {
var servers = [];
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) {

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

@ -12,7 +12,7 @@ module.exports = function (module) {
return await sortedSetAddBulk(key, score, value);
}
if (!utils.isNumber(score)) {
throw new Error('[[error:invalid-score, ' + score + ']]');
throw new Error(`[[error:invalid-score, ${score}]]`);
}
value = helpers.valueToString(value);
@ -35,7 +35,7 @@ module.exports = function (module) {
}
for (let i = 0; i < scores.length; i += 1) {
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);
@ -54,7 +54,7 @@ module.exports = function (module) {
const isArrayOfScores = Array.isArray(scores);
if ((!isArrayOfScores && !utils.isNumber(scores)) ||
(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) {
@ -77,7 +77,7 @@ module.exports = function (module) {
var bulk = module.client.collection('objects').initializeUnorderedBulkOp();
data.forEach(function (item) {
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]) } });
});

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

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

@ -55,7 +55,7 @@ postgresModule.init = async function () {
try {
await checkUpgrade(client);
} 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;
} finally {
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)`),
], function (err) {
if (err) {
winston.error('Error creating index ' + err.message);
winston.error(`Error creating index ${err.message}`);
return callback(err);
}
winston.info('[database] Checking database indices done!');

@ -48,7 +48,7 @@ SELECT "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);
if (invalid.length) {
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(', '));
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(', ')}`);
}
var missing = keys.filter(function (k) {
@ -93,7 +93,7 @@ SELECT "_key", "type"
});
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) {
let match = params.match;
if (match.startsWith('*')) {
match = '%' + match.substring(1);
match = `%${match.substring(1)}`;
}
if (match.endsWith('*')) {
match = match.substring(0, match.length - 1) + '%';
match = `${match.substring(0, match.length - 1)}%`;
}
const res = await module.pool.query({

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

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

@ -56,10 +56,10 @@ SELECT COUNT(*) c
}
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: `
WITH A AS (SELECT z."value",
` + aggregate + `(z."score" * k."weight") "score",
${aggregate}(z."score" * k."weight") "score",
COUNT(*) c
FROM UNNEST($1::TEXT[], $2::NUMERIC[]) k("_key", "weight")
INNER JOIN "legacy_object_live" o
@ -72,7 +72,7 @@ SELECT A."value",
A."score"
FROM A
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
OFFSET $3::INTEGER`,
values: [sets, weights, start, limit],

@ -50,10 +50,10 @@ SELECT COUNT(DISTINCT z."value") c
}
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: `
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")
INNER JOIN "legacy_object_live" o
ON o."_key" = k."_key"
@ -64,7 +64,7 @@ WITH A AS (SELECT z."value",
SELECT A."value",
A."score"
FROM A
ORDER BY A."score" ` + (params.sort > 0 ? 'ASC' : 'DESC') + `
ORDER BY A."score" ${params.sort > 0 ? 'ASC' : 'DESC'}
LIMIT $4::INTEGER
OFFSET $3::INTEGER`,
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) {
const split = keyInfo.split(',');
redisData.keys = (split[0] || '').replace('keys=', '');
@ -108,7 +108,7 @@ redisModule.socketAdapter = async function () {
const pub = await connection.connect(nconf.get('redis'));
const sub = await connection.connect(nconf.get('redis'));
return redisAdapter({
key: 'db:' + nconf.get('redis:database') + ':adapter_key',
key: `db:${nconf.get('redis:database')}:adapter_key`,
pubClient: pub,
subClient: sub,
});

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

Loading…
Cancel
Save