const { stripIndents } = require('common-tags'); const { Collection, Util } = require('../../util/'); const Constants = { MaxTargets: 10 //10+(10*premium-tier), theoretical max = 40 }; class ModerationManager { constructor(client) { this.client = client; this.expirations = new Collection(); } async handleInfraction(Infraction, message, { targets, reason, duration }) { const maxTargets = Constants.MaxTargets + message.guild.premium*Constants.MaxTargets; if(targets.length > maxTargets) { return message.respond(stripIndents`${message.format('MODERATIONMANAGER_INFRACTION_MAXTARGETS', { maxTargets, type: Infraction.targetType })} ${maxTargets < 40 ? message.format('MODERATIONMANAGER_INFRACTION_MAXTARGETSALT') : ''}`, { emoji: 'failure' }); } const silent = Boolean(message.guild._settings.silent || message.arguments.silent); this.client.logger.debug(`Silent infraction: ${silent}`); const promises = []; for(const target of targets) { promises.push(new Infraction(this.client, { executor: message.member, guild: message.guild, channel: message.channel, arguments: message.arguments, message, target, reason, duration, silent }).execute()); } const responses = await Promise.all(promises); let success = Boolean(responses.some((r) => !r.error)); const succeeded = responses.filter((r) => !r.error); const failed = responses.filter((r) => r.error); const succeededTargets = succeeded.map((s) => s.infraction.target); const actions = await this._handleArguments(message, succeededTargets); //Handle prune arguments, etc. ONLY IF INFRACTION SUCCEEDS. //NOTE: I'm not translating: infraction types (KICK, MUTE, ETC.), infraction target types (channel(s), user(s)), /* Message Handling */ const { dictionary, targetType } = responses[0].infraction; let string = ""; if(success && !silent) { string = message.format('MODERATIONMANAGER_INFRACTION_SUCCESS', { infraction: dictionary.past, targetType: `${targetType}${succeeded.length > 1 ? 's' : ''}`, target: succeeded.map((s) => `**${Util.escapeMarkdown(s.infraction.targetName)}**`).join(', '), action: actions.prune ? ` and pruned \`${actions.prune}\` message${actions.prune > 1 ? 's' : ''}` : '' }); } else if((silent && failed.length > 0)) { if(silent) success = false; const format = failed.length === 1 ? "MODERATIONMANAGER_INFRACTION_SINGULARFAIL" : "MODERATIONMANAGER_INFRACTION_MULTIPLEFAIL"; string = message.format(format, { infraction: dictionary.present, targetType: `${targetType}${failed.length > 1 ? 's' : ''}`, target: failed.length === 1 ? `**${Util.escapeMarkdown(failed[0].infraction.targetName)}**` : failed.map((f) => `**${f.infraction.targetName}**`).join(', '), reason: failed[0].reason }); } if((success && failed.length > 0) || (!success && failed.length > 1)) { for(const fail of failed) { string += `\n${message.format('MODERATIONMANAGER_INFRACTION_FAIL', { infraction: dictionary.present, target: Util.escapeMarkdown(fail.infraction.targetName), reason: fail.reason })}`; } } if(string) message.respond(string, { emoji: success ? 'success' : 'failure' }); return succeeded; } async _handleArguments(message, targets) { const actions = { prune: async (message, argument, targets) => { const users = targets.map((t) => t.id); let messages = await message.channel.messages.fetch({ limit: argument.value }); messages = messages.filter((m) => users.includes(m.author.id)); try { await message.channel.bulkDelete(messages, true); } catch(err) {} //eslint-disable-line no-empty return messages.size; } }; const responses = {}; for(const arg of Object.values(message.arguments)) { if(actions[arg.name]) { let action = actions[arg.name](message, arg, targets); if(action instanceof Promise) action = await action; responses[arg.name] = action; } } return responses; } } module.exports = ModerationManager;