const { Setting } = require('../../../../interfaces/'); const { Emojis } = require('../../../../../util/'); const { PermissionNames, EmbedLimits } = require('../../../../../util/Constants.js'); const Constants = { Types: { role: [ 'muteRole', 'mutedRole' ], create: [ 'createMute', 'createMuted', 'createMuteRole', 'createMutedRole' ], type: [ 'muteType', 'mutedType' ], permanent: [ 'permaMute', 'permanentMute' ], duration: [ 'defaultMuteDuration', 'muteDuration' ] }, MuteTypes: [0, 1, 2], MaxCharacters: 98, MaxIssues: 6 }; const { stripIndents } = require('common-tags'); class MuteSetting extends Setting { constructor(client) { super(client, { name: 'mute', module: 'moderation', aliases: [ 'muted', 'muteType', 'mutedType', 'muteRole', 'mutedRole', 'createMute', 'createMuteRole', 'createMuted', 'createMutedRole', 'permaMute', 'permanentMute', 'muteDuration', 'defaultMuteDuration' ], // arguments: [ // { // name: 'text', // type: 'BOOLEAN', // types: ['FLAG'], // default: true // }, // { // name: 'voice', // type: 'BOOLEAN', // types: ['FLAG'], // default: true // } // ], usage: "<'create'|'type'|'permanent'|'default'|role> ", examples: [ "mute muted-role", "mute create Muted", "mute type 1", "mute permanent true", "mute default 1 day" ], resolve: 'GUILD', default: { mute: { role: null, type: 0, defaultDuration: 3600, permanent: false } } }); } async handle(message, args) { const { params, parsedArguments } = await this._parseArguments(args, message.guild); if(params.length === 0) { return { msg: message.format('S_MUTE_MISSINGARGUMENTS'), error: true }; } let type = 'role'; let parameters = params.join(' '); if(!['mute', 'muted'].includes(message._settingCaller)) { for(const [ key, values ] of Object.entries(Constants.Types)) { if(values.map((v) => v.toLowerCase()).includes(message._settingCaller.toLowerCase())) { type = key; break; } } } else { const key = params[0].toLowerCase(); if(['create', 'createrole'].includes(key)) type = 'create', parameters = params.splice(1).join(' '); //eslint-disable-line no-unused-expressions, no-sequences if(['type'].includes(key)) type = 'type', parameters = params.splice(1).join(' '); //eslint-disable-line no-unused-expressions, no-sequences if(['duration', 'defaultduration'].includes(key)) type = 'duration', parameters = params.splice(1).join(' '); //eslint-disable-line no-unused-expressions, no-sequences if(['perma', 'permamute', 'permanent'].includes(key)) type = 'permanent', parameters = params.splice(1).join(' '); //eslint-disable-line no-unused-expressions, no-sequences } if(type === 'role') { const role = await this.client.resolver.resolveRole(parameters, true, message.guild); if(!role) return { msg: message.format('S_MUTE_ROLEMISSING'), error: true }; await message.guild._updateSettings({ [this.index]: { ...message.guild._settings[this.index], role: role.id } }); return { msg: message.format('S_MUTE_ROLESUCCESS', { role: role.name }), error: false }; } else if(type === 'create') { const response = await this._createRole(message, parameters, parsedArguments); if(response.error) return response; const { role, issues, created, updatedPermissions } = response; await message.guild._updateSettings({ [this.index]: { ...message.guild._settings[this.index], role: role.id } }); const embed = { author: { name: `${Emojis.warning} Warning` }, color: 0xffe15c, description: message.format('S_MUTE_CREATESUCCESSWARNING'), fields: [] }; const addField = (array, type) => { const field = { name: type === 'text' ? 'Text Channels' : 'Voice Channels', value: '' }; const sorted = array.sort((a, b) => a.position - b.position) || []; for(const i of sorted) { const text = `${Emojis.role} **${i.role}** has ${i.permissions.map((p) => `\`${PermissionNames[p]}\``).join(', ')} in ${Emojis[i.type === 'text' ? 'text-channel' : 'voice-channel']} **${i.channel}**\n`; if(field.value.length+text.length <= EmbedLimits.fieldValue) field.value += text; } return field; }; const textIssues = issues.filter((i) => i.type === 'text'); if(textIssues.length > 0) embed.fields.push(addField(textIssues, 'text')); const voiceIssues = issues.filter((i) => i.type === 'voice'); if(voiceIssues.length > 0) embed.fields.push(addField(voiceIssues, 'voice')); message.respond(message.format(`S_MUTE_CREATESUCCESS${created ? 'ALT' : ''}`, { permissions: message.format(updatedPermissions ? 'S_MUTE_GENERATEDPERMISSIONS' : 'S_MUTE_UNGENERATEDPERMISSIONS'), role: role.name }), { emoji: 'success', embed: issues.length > 0 ? embed : null }); } else if(type === 'type') { const number = parseInt(parameters); if(Number.isNaN(number)) return { msg: message.format('S_MUTE_TYPENAN'), error: true }; if(!Constants.MuteTypes.includes(number)) return { msg: message.format('S_MUTE_TYPEINVALID'), error: true }; await message.guild._updateSettings({ [this.index]: { ...message.guild._settings[this.index], type: number } }); return { msg: `${message.format('S_MUTE_TYPESUCCESS', { type: number })} ${message.format('S_MUTE_TYPESWITCH', { type: number }, true)}`, error: false }; } else if(type === 'duration') { const time = this.client.resolver.resolveTime(parameters); if(!time) { return { msg: message.format('S_MUTE_DEFAULTINVALID'), error: true }; } await message.guild._updateSettings({ [this.index]: { ...message.guild._settings[this.index], defaultDuration: time } }); return { msg: message.format('S_MUTE_DEFAULTSUCCESS', { time }), error: false }; } else if(type === 'permanent') { const boolean = this.client.resolver.resolveBoolean(parameters); if(boolean === null) { return { msg: message.format('S_MUTE_PERMANENTINVALID'), error: true }; } await message.guild._updateSettings({ [this.index]: { ...message.guild._settings[this.index], permanent: boolean } }); return { msg: message.format('S_MUTE_PERMANENTSUCCESS', { boolean }), error: false }; } return { error: false, ignore: true }; } async _createRole(message, name = 'Muted', args) { const createRole = async (name) => { let role = null; if(name.length > Constants.MaxCharacters) name = name.slice(0, Constants.MaxCharacters); try { role = await message.guild.roles.create({ data: { name }, reason: super.reason(message.author) }); } catch(error) { return { msg: message.format('S_MUTE_ROLECREATEERROR'), error: true }; } return role; }; const hasPermission = message.guild.me.hasPermission('MANAGE_ROLES'); if(!hasPermission) return { msg: message.format('S_MUTE_ROLEMISSINGPERMISSION'), error: true }; let role = null; const existing = await this.client.resolver.resolveRole(name, true, message.guild); if(existing) { const prompt = await message.prompt(message.format('S_MUTE_ROLEPROMPT', { name: existing.name, id: existing.id }), { emoji: 'loading' }); const boolean = this.client.resolver.resolveBoolean(prompt.content.toLowerCase()); if(boolean === null) return { msg: message.format('S_MUTE_ROLEPROMPTERROR'), error: true }; if(boolean) { role = existing; } } let created = false; if(!role) { role = await createRole(name); if(role.error) return role; created = true; } const issues = []; let updatedPermissions = false; for(const channel of message.guild.channels.cache.values()) { const configuration = channel.type === 'text' ? { permissions: { SEND_MESSAGES: false, ADD_REACTIONS: false }, bitwise: 0x800 } : { permissions: { CONNECT: false }, bitwise: 0x100000 }; try { if(channel.type === 'text' || channel.type === 'voice') { await channel.createOverwrite(role, configuration.permissions, super.reason(message.author)); for(const permission of channel.permissionOverwrites.values()) { if(permission.type !== 'role') continue; const permissionRole = await this.client.resolver.resolveRole(permission.id, true, message.guild); if((permission.allow & configuration.bitwise) === configuration.bitwise) { //eslint-disable-line no-bitwise const issue = { role: permissionRole.name, permissions: Object.keys(configuration.permissions), channel: channel.name, type: channel.type, position: permissionRole.rawPosition }; issues.push(issue); } } } updatedPermissions = true; } catch(error) {} //eslint-disable-line no-empty } return { error: false, updatedPermissions, created, issues, role }; } fields(guild) { const setting = guild._settings[this.index]; return [ { name: '》 Mute Role', value: setting?.role ? `<@&${guild._settings[this.index].role}>` : '`N/A`', inline: true }, { name: '》 Mute Type', value: `\`${setting?.type || 0}\``, inline: true }, { name: '\u200b', value: '\u200b', inline: true }, //zero width spaces, not necessary, but could make things look nicer. { name: '》 Permanent Mutes', value: guild.format('SETTING_STATUS', { bool: Boolean(setting?.permanent) }, true), inline: true }, { name: '》 Default Duration', value: `\`${setting.defaultDuration ? `${setting.defaultDuration} seconds` : 'N/A'}\``, inline: true }, { name: '\u200b', value: '\u200b', inline: true } //zero width spaces, not necessary, but could make things look nicer. ]; } } module.exports = MuteSetting;