/** * Code to manage username prefixes that force battles to be public or disable modchat. * @author Annika */ import { FS } from '../../lib'; const PREFIXES_FILE = 'config/chat-plugins/username-prefixes.json'; const PREFIX_DURATION = 10 * 24 * 60 * 60 * 1000; export class PrefixManager { constructor() { // after a restart/newly using the plugin, load prefixes from config.js if (!Chat.oldPlugins['username-prefixes']) this.refreshConfig(true); } save() { FS(PREFIXES_FILE).writeUpdate(() => JSON.stringify(Config.forcedprefixes || [])); } refreshConfig(configJustLoaded = false) { if (!Config.forcedprefixes) Config.forcedprefixes = []; // ensure everything is in the right format if (!Array.isArray(Config.forcedprefixes)) { const convertedPrefixes = []; for (const type in Config.forcedprefixes) { for (const prefix of Config.forcedprefixes[type].map(toID)) { convertedPrefixes.push({ type, prefix, expireAt: Date.now() + PREFIX_DURATION }); } } Config.forcedprefixes = convertedPrefixes; } if (configJustLoaded) { for (const entry of Config.forcedprefixes) { entry.prefix = toID(entry.prefix); } } let data: AnyObject[]; try { data = JSON.parse(FS(PREFIXES_FILE).readSync()); } catch (e: any) { if (e.code !== 'ENOENT') throw e; return; } if (data.length) { for (const entry of data) { if (Config.forcedprefixes.includes(entry)) continue; Config.forcedprefixes.push(entry); } } } addPrefix(prefix: ID, type: 'privacy' | 'modchat') { if (!Config.forcedprefixes) Config.forcedprefixes = []; const entry = Config.forcedprefixes.find((x: AnyObject) => x.prefix === prefix && x.type === type); if (entry) { throw new Chat.ErrorMessage(`Username prefix '${prefix}' is already configured to force ${type}.`); } Config.forcedprefixes.push({ type, prefix, expireAt: Date.now() + PREFIX_DURATION }); this.save(); } removePrefix(prefix: ID, type: 'privacy' | 'modchat') { const entry = Config.forcedprefixes.findIndex((x: AnyObject) => x.prefix === prefix && x.type === type); if (entry < 0) { throw new Chat.ErrorMessage(`Username prefix '${prefix}' is not configured to force ${type}!`); } Config.forcedprefixes.splice(entry, 1); this.save(); } validateType(type: string) { if (type !== 'privacy' && type !== 'modchat') { throw new Chat.ErrorMessage(`'${type}' is not a valid type of forced prefix. Valid types are 'privacy' and 'modchat'.`); } return type; } } export const prefixManager = new PrefixManager(); export const commands: Chat.ChatCommands = { forceprefix: 'usernameprefix', forcedprefix: 'usernameprefix', forcedprefixes: 'usernameprefix', usernameprefixes: 'usernameprefix', usernameprefix: { help: '', ''() { this.parse(`/help forcedprefix`); }, delete: 'add', remove: 'add', add(target, room, user, connection, cmd) { this.checkCan('addhtml'); const isAdding = cmd.includes('add'); const [prefix, type] = target.split(',').map(toID); if (!prefix || !type) return this.parse(`/help usernameprefix`); if (prefix.length > 18) { throw new Chat.ErrorMessage(`Specified prefix '${prefix}' is longer than the maximum user ID length.`); } if (isAdding) { prefixManager.addPrefix(prefix, prefixManager.validateType(type)); } else { prefixManager.removePrefix(prefix, prefixManager.validateType(type)); } this.globalModlog(`FORCEDPREFIX ${isAdding ? 'ADD' : 'REMOVE'}`, null, `'${prefix}' ${isAdding ? 'to' : 'from'} ${type}`); this.addGlobalModAction(`${user.name} set the username prefix ${prefix} to${isAdding ? '' : ' no longer'} disable ${type}.`); }, view(target) { this.checkCan('addhtml'); const types = target ? [prefixManager.validateType(toID(target))] : ['privacy', 'modchat']; const entries = Config.forcedprefixes.filter((x: any) => types.includes(x.type)); return this.sendReplyBox(types.map(type => { const prefixes = entries.filter((x: any) => x.type === type).map((x: any) => x.prefix); const info = prefixes.length ? `${prefixes.join(', ')}` : `none`; return `Username prefixes that disable ${type}: ${info}.`; }).join(`
`)); }, }, usernameprefixhelp() { return this.sendReplyBox( `/usernameprefix add [prefix], [type]: Sets the username prefix [prefix] to disable privacy or modchat on battles where at least one player has the prefix.
` + `/usernameprefix remove [prefix], [type]: Removes a prefix configuration.
` + `/usernameprefix view [optional type]: Displays the currently configured username prefixes.
` + `Valid types are privacy (which forces battles to take place in public rooms) and modchat (which prevents players from setting moderated chat).
` + `Requires: * ~` ); }, };