Files
gameno-api/utils/notificationSettings.js
T

103 lines
2.9 KiB
JavaScript

'use strict';
const config = require('../config/config');
const { Setting, SETTINGS_KEY } = require('../components/settings/settingModel');
const {
NOTIFICATION_ACTION_DEFS,
mergeNotificationSettings,
toPublicNotificationSettings,
normalizeStoredActionEntry,
findActionDef
} = require('../components/settings/notificationActions');
const {
isEnvChannelEnabled,
isDbChannelEnabled,
CHANNELS
} = require('./messagingChannels');
const { getDbMessagingFlags, invalidateMessagingCache } = require('../components/settings/messagingFlags');
let settingsCache = null;
let settingsCacheAt = 0;
const CACHE_TTL_MS = 10000;
const readStoredMap = (doc) => {
const stored = doc?.notificationSettings || {};
if (stored instanceof Map) {
return Object.fromEntries(stored.entries());
}
return { ...stored };
};
const getMergedSettingsMap = (doc) => mergeNotificationSettings(readStoredMap(doc));
const loadNotificationSettingsDoc = async () => {
const now = Date.now();
if (settingsCache && (now - settingsCacheAt) < CACHE_TTL_MS) {
return settingsCache;
}
const doc = await Setting.findOne({ key: SETTINGS_KEY })
.select('notificationSettings smsEnabled emailEnabled botEnabled')
.lean();
settingsCache = {
map: getMergedSettingsMap(doc),
dbMessaging: {
smsEnabled: doc?.smsEnabled,
emailEnabled: doc?.emailEnabled,
botEnabled: doc?.botEnabled
}
};
settingsCacheAt = now;
return settingsCache;
};
const invalidateNotificationSettingsCache = () => {
settingsCache = null;
settingsCacheAt = 0;
invalidateMessagingCache();
};
const isGlobalChannelEnabled = async (channel) => {
if (!CHANNELS.includes(channel)) return false;
if (!isEnvChannelEnabled(channel, config)) return false;
const db = await getDbMessagingFlags();
return isDbChannelEnabled(channel, db);
};
const isActionChannelEnabled = async (actionKey, channel) => {
if (!CHANNELS.includes(channel)) return false;
if (!(await isGlobalChannelEnabled(channel))) return false;
const cached = await loadNotificationSettingsDoc();
const def = findActionDef(actionKey);
if (!def) return true;
const entry = normalizeStoredActionEntry(cached.map[actionKey], def);
return entry[channel] === true;
};
const getActionChannelFlags = async (actionKey) => {
const result = { sms: false, email: false, bot: false };
await Promise.all(
CHANNELS.map(async (channel) => {
result[channel] = await isActionChannelEnabled(actionKey, channel);
})
);
return result;
};
const getPublicNotificationSettings = async (doc = null) => {
const resolved = doc || await Setting.findOne({ key: SETTINGS_KEY }).lean();
return toPublicNotificationSettings(getMergedSettingsMap(resolved));
};
module.exports = {
getMergedSettingsMap,
isActionChannelEnabled,
getActionChannelFlags,
getPublicNotificationSettings,
invalidateNotificationSettingsCache,
readStoredMap
};