const { Setting } = require('../../../../interfaces/'); const CONSTANTS = { INFRACTIONS: ['WARN', 'MUTE', 'KICK', 'SOFTBAN', 'BAN', 'VCMUTE', 'VCKICK', 'VCBAN'], TIMED: ['MUTE', 'BAN', 'VCMUTE', 'VCBAN'] }; class AutoModerationSetting extends Setting { constructor(client) { super(client, { name: 'autoModeration', module: 'moderation', aliases: ['automod'], resolve: 'GUILD', usage: ` [time]`, examples: [ 'automod on', 'automod threshold 10 mute 3 hours', 'automod length 10 2 hours', 'automod useprevious on' ], default: { autoModeration: { enabled: false, thresholds: { }, usePrevious: false // use previous threshold if no new threshold is exceeded } }, archivable: true }); } async handle(message, args) { const setting = message.guild._settings[this.index]; const [method, ...params] = args; let index = null, langParams = {}; const { resolver } = this.client; if (resolver.resolveBoolean(method)) { setting.enabled = true; index = 'S_AUTOMOD_TOGGLE'; langParams = { toggle: message.format('ON_OFF_TOGGLE', { toggle: true }, true) }; } else if (resolver.resolveBoolean(method) === false) { setting.enabled = false; index = 'S_AUTOMOD_TOGGLE'; langParams = { toggle: message.format('ON_OFF_TOGGLE', { toggle: false }, true) }; } else if (method.toLowerCase() === 'threshold') { const points = parseInt(params.shift()); if (isNaN(points) || points < 0 || points > 100) return { error: true, msg: message.format('S_AUTOMOD_INVALID_POINTS', {}) }; const action = params.shift()?.toLowerCase(); if (!action) return { error: true, msg: message.format('S_AUTOMOD_NOARG') }; if (['delete', 'remove'].includes(action)) { const old = setting.thresholds[points]; if (old) { index = 'S_AUTOMOD_REMOVE_POINTS'; langParams = { type: old.type, points }; delete setting.thresholds[points]; } else { return { error: true, msg: message.format('S_AUTOMOD_REMOVE_NOPOINTS', { points }) }; } } else { const infraction = resolver.resolveInfraction(action); if (!CONSTANTS.INFRACTIONS.includes(infraction)) return { error: true, msg: message.format('S_AUTOMOD_INVALID_TYPE', { infraction }) }; const old = setting.thresholds[points]; const timed = CONSTANTS.TIMED.includes(infraction); const _time = params.join(' '); const time = resolver.resolveTime(_time); if (old) { index = timed && time ? 'S_AUTOMOD_OVERWRITE_POINTS_TIMED' : 'S_AUTOMOD_OVERWRITE_POINTS'; langParams = { type: infraction, points, oldType: old.type, time: resolver.timeAgo(time, true, true, true) }; } else { index = timed && time ? 'S_AUTOMOD_ADD_POINTS_TIMED' : 'S_AUTOMOD_ADD_POINTS'; langParams = { type: infraction, points, time: resolver.timeAgo(time, true, true, true) }; } setting.thresholds[points] = { type: infraction }; if (timed && time) setting.thresholds[points].length = time; } } else if (method.toLowerCase() === 'length') { const points = parseInt(params.shift()); if (isNaN(points) || points < 0 || points > 100) return { error: true, msg: message.format('S_AUTOMOD_INVALID_POINTS', {}) }; const action = params.shift()?.toLowerCase(); if (!action) return { error: true, msg: message.format('S_AUTOMOD_NOARG') }; if (!setting.thresholds[points]) return { error: true, msg: message.format('S_AUTOMOD_NOACTION') }; if (['delete', 'remove'].includes(action)) { delete setting.thresholds[points].length; index = 'S_AUTOMOD_REMOVE_LENGTH'; langParams = { type: setting.thresholds[points].type, points }; } else { const [, , ..._time] = args; const time = resolver.resolveTime(_time.join(' ')); if (!time) return { error: true, msg: message.format('ERR_INVALID_TIMESTRING') }; setting.thresholds[points].length = time; index = 'S_AUTOMOD_LENGTH_SUCCESS'; } } else if (['useprev', 'useprevious', 'previous'].includes(method.toLowerCase())) { const bool = resolver.resolveBoolean(params[0]); if (bool) setting.usePrevious = bool; else if (bool === false) setting.usePrevious = bool; else return { error: true, msg: message.format('ERR_BOOLEAN_RESOLVE', { resolveable: params[0] }) }; index = 'S_AUTOMOD_USEPREV_TOGGLE'; langParams = { toggle: message.format('ON_OFF_TOGGLE', { toggle: bool }, true) }; } await message.guild._updateSettings({ [this.index]: setting }); return { msg: message.format(index, langParams), error: false }; } fields(guild) { const setting = guild._settings[this.index]; const { resolver } = this.client; return [ { name: "》 Status", value: guild.format('SETTING_STATUS', { bool: Boolean(setting.enabled) }, true), inline: true }, { name: '》 Use previous threshold', value: guild.format('SETTING_STATUS', { bool: Boolean(setting.usePrevious) }, true), inline: true }, { name: '》 Thresholds', value: Object.entries(setting.thresholds).reduce((acc, [points, action]) => { acc.push(`**${points}:** \`${action.type}\`${action.length ? ', ' + resolver.timeAgo(action.length) : ''}`); return acc; }, []).join('\n') || '`N/A`' } ]; } } module.exports = AutoModerationSetting;