You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nodebb/src/user/settings.js

155 lines
6.7 KiB
JavaScript

'use strict';
const validator = require('validator');
const meta = require('../meta');
const db = require('../database');
const plugins = require('../plugins');
const notifications = require('../notifications');
const languages = require('../languages');
module.exports = function (User) {
User.getSettings = async function (uid) {
if (parseInt(uid, 10) <= 0) {
return await onSettingsLoaded(0, {});
}
let settings = await db.getObject('user:' + uid + ':settings');
settings = settings || {};
settings.uid = uid;
return await onSettingsLoaded(uid, settings);
};
User.getMultipleUserSettings = async function (uids) {
if (!Array.isArray(uids) || !uids.length) {
return [];
}
const keys = uids.map(uid => 'user:' + uid + ':settings');
let settings = await db.getObjects(keys);
settings = settings.map(function (userSettings, index) {
userSettings = userSettings || {};
userSettings.uid = uids[index];
return userSettings;
});
return await Promise.all(settings.map(s => onSettingsLoaded(s.uid, s)));
};
async function onSettingsLoaded(uid, settings) {
const data = await plugins.fireHook('filter:user.getSettings', { uid: uid, settings: settings });
settings = data.settings;
const defaultTopicsPerPage = meta.config.topicsPerPage;
const defaultPostsPerPage = meta.config.postsPerPage;
settings.showemail = parseInt(getSetting(settings, 'showemail', 0), 10) === 1;
settings.showfullname = parseInt(getSetting(settings, 'showfullname', 0), 10) === 1;
settings.openOutgoingLinksInNewTab = parseInt(getSetting(settings, 'openOutgoingLinksInNewTab', 0), 10) === 1;
settings.dailyDigestFreq = getSetting(settings, 'dailyDigestFreq', 'off');
settings.usePagination = parseInt(getSetting(settings, 'usePagination', 0), 10) === 1;
settings.topicsPerPage = Math.min(settings.topicsPerPage ? parseInt(settings.topicsPerPage, 10) : defaultTopicsPerPage, defaultTopicsPerPage);
settings.postsPerPage = Math.min(settings.postsPerPage ? parseInt(settings.postsPerPage, 10) : defaultPostsPerPage, defaultPostsPerPage);
settings.userLang = settings.userLang || meta.config.defaultLang || 'en-GB';
settings.acpLang = settings.acpLang || settings.userLang;
settings.topicPostSort = getSetting(settings, 'topicPostSort', 'oldest_to_newest');
settings.categoryTopicSort = getSetting(settings, 'categoryTopicSort', 'newest_to_oldest');
settings.followTopicsOnCreate = parseInt(getSetting(settings, 'followTopicsOnCreate', 1), 10) === 1;
settings.followTopicsOnReply = parseInt(getSetting(settings, 'followTopicsOnReply', 0), 10) === 1;
settings.upvoteNotifFreq = getSetting(settings, 'upvoteNotifFreq', 'all');
settings.restrictChat = parseInt(getSetting(settings, 'restrictChat', 0), 10) === 1;
settings.topicSearchEnabled = parseInt(getSetting(settings, 'topicSearchEnabled', 0), 10) === 1;
settings.bootswatchSkin = validator.escape(String(settings.bootswatchSkin || ''));
settings.homePageRoute = validator.escape(String(settings.homePageRoute || '')).replace('&#x2F;', '/');
settings.scrollToMyPost = parseInt(getSetting(settings, 'scrollToMyPost', 1), 10) === 1;
settings.categoryWatchState = getSetting(settings, 'categoryWatchState', 'notwatching');
const notificationTypes = await notifications.getAllNotificationTypes();
notificationTypes.forEach(function (notificationType) {
settings[notificationType] = getSetting(settings, notificationType, 'notification');
});
return settings;
}
function getSetting(settings, key, defaultValue) {
if (settings[key] || settings[key] === 0) {
return settings[key];
} else if (meta.config[key] || meta.config[key] === 0) {
return meta.config[key];
}
return defaultValue;
}
User.saveSettings = async function (uid, data) {
const maxPostsPerPage = meta.config.maxPostsPerPage || 20;
if (!data.postsPerPage || parseInt(data.postsPerPage, 10) <= 1 || parseInt(data.postsPerPage, 10) > maxPostsPerPage) {
throw new Error('[[error:invalid-pagination-value, 2, ' + maxPostsPerPage + ']]');
}
const maxTopicsPerPage = meta.config.maxTopicsPerPage || 20;
if (!data.topicsPerPage || parseInt(data.topicsPerPage, 10) <= 1 || parseInt(data.topicsPerPage, 10) > maxTopicsPerPage) {
throw new Error('[[error:invalid-pagination-value, 2, ' + maxTopicsPerPage + ']]');
}
const languageCodes = await languages.listCodes();
if (data.userLang && !languageCodes.includes(data.userLang)) {
throw new Error('[[error:invalid-language]]');
}
if (data.acpLang && !languageCodes.includes(data.acpLang)) {
throw new Error('[[error:invalid-language]]');
}
data.userLang = data.userLang || meta.config.defaultLang;
plugins.fireHook('action:user.saveSettings', { uid: uid, settings: data });
const settings = {
showemail: data.showemail,
showfullname: data.showfullname,
openOutgoingLinksInNewTab: data.openOutgoingLinksInNewTab,
dailyDigestFreq: data.dailyDigestFreq || 'off',
usePagination: data.usePagination,
topicsPerPage: Math.min(data.topicsPerPage, parseInt(maxTopicsPerPage, 10) || 20),
postsPerPage: Math.min(data.postsPerPage, parseInt(maxPostsPerPage, 10) || 20),
userLang: data.userLang || meta.config.defaultLang,
acpLang: data.acpLang || meta.config.defaultLang,
followTopicsOnCreate: data.followTopicsOnCreate,
followTopicsOnReply: data.followTopicsOnReply,
restrictChat: data.restrictChat,
topicSearchEnabled: data.topicSearchEnabled,
homePageRoute: ((data.homePageRoute === 'custom' ? data.homePageCustom : data.homePageRoute) || '').replace(/^\//, ''),
scrollToMyPost: data.scrollToMyPost,
notificationSound: data.notificationSound,
incomingChatSound: data.incomingChatSound,
outgoingChatSound: data.outgoingChatSound,
upvoteNotifFreq: data.upvoteNotifFreq,
bootswatchSkin: data.bootswatchSkin,
categoryWatchState: data.categoryWatchState,
};
const notificationTypes = await notifications.getAllNotificationTypes();
notificationTypes.forEach(function (notificationType) {
if (data[notificationType]) {
settings[notificationType] = data[notificationType];
}
});
const result = await plugins.fireHook('filter:user.saveSettings', { settings: settings, data: data });
await db.setObject('user:' + uid + ':settings', result.settings);
await User.updateDigestSetting(uid, data.dailyDigestFreq);
return await User.getSettings(uid);
};
User.updateDigestSetting = async function (uid, dailyDigestFreq) {
await db.sortedSetsRemove(['digest:day:uids', 'digest:week:uids', 'digest:month:uids'], uid);
if (['day', 'week', 'month'].includes(dailyDigestFreq)) {
await db.sortedSetAdd('digest:' + dailyDigestFreq + ':uids', Date.now(), uid);
}
};
User.setSetting = async function (uid, key, value) {
if (parseInt(uid, 10) <= 0) {
return;
}
await db.setObjectField('user:' + uid + ':settings', key, value);
};
};