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', '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 } }); message.respond(message.format('S_MUTE_ROLESUCCESS'), { emoji: 'success' }); } 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 sorted = issues ? issues.sort((a, b) => a.position - b.position) : []; 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: created ? message.format('S_MUTE_CREATESUCCESSALT') : ' ', 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(num); 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') { } else if(type === 'permanent') { } 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 }; } /* async handle(message, args) { let { params, parsedArguments } = await this._parseArguments(args, message.guild); //eslint-disable-line prefer-const if(['mutetype', 'mutedtype'].includes(message._settingCaller) || parsedArguments.type) { if(!params[0]) return { error: true, msg: message.format('S_MUTE_TYPENAN') }; const num = params[0]; const number = parseInt(num); if(Number.isNaN(number)) return { msg: message.format('S_MUTE_TYPENAN'), error: true }; if(![0, 1, 2].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 (['permamute', 'permanentmute'].includes(message._settingCaller) || parsedArguments.permanent) { if(!params[0]) return { error: true, msg: message.format('S_MUTE_PERMANENTINVALID') }; const boolean = this.client.resolver.resolveBoolean(params[0]); 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 }; } else if (['defaultMuteDuration'].includes(message._settingCaller) || parsedArguments.defaultDuration) { if(!params.length) return { error: true, msg: message.format('S_MUTE_PERMANENTINVALID') }; const time = this.client.resolver.resolveTime(params.join(' ')); 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 }; } let role = null, updatedPermissions = false, created = false; const issues = []; if(parsedArguments.create || ['createmute', 'createmuted', 'createmutedrole', 'createmuterole'].includes(message._settingCaller)) { const missing = message.channel.permissionsFor(message.guild.me).missing('MANAGE_ROLES'); if(missing.length > 0) return { msg: message.format('S_MUTE_ROLEMISSINGPERMISSION'), error: true }; const foundRole = await message.guild.resolveRole(params.join(' '), true); if(foundRole) { const prompt = await message.prompt(message.format('S_MUTE_ROLEPROMPT', { name: foundRole.name, id: foundRole.id }), { emoji: 'loading' }); const response = prompt.content.toLowerCase(); const bool = this.client.resolver.resolveBoolean(response); if(bool === null) return { msg: message.format('S_MUTE_ROLEPROMPTERROR'), error: true }; if(!bool) { role = await this._createRole(message, params); if(role.error) return role; created = true; } else { role = foundRole; } } else { role = await this._createRole(message, params); if(role.error) return role; created = true; } const channels = message.guild.channels.cache; for(const channel of channels.values()) { const configuration = channel.type === 'text' ? { permissions: { SEND_MESSAGES: false, ADD_REACTIONS: false }, bitwise: 0x800 } : { permissions: { CONNECT: false }, bitwise: 0x100000 }; try { // console.log(channel.type) if(channel.type === 'text' && !parsedArguments.voice || channel.type === 'voice' && !parsedArguments.text || !parsedArguments.text && !parsedArguments.voice) { if(channel.type === 'category') continue; await channel.createOverwrite(role, configuration.permissions, super.reason(message.author)); for(const permission of channel.permissionOverwrites.values()) { if(permission.type !== 'role') continue; const r = await this.client.resolver.resolveRole(permission.id, true, message.guild); if((permission.allow & configuration.bitwise) === configuration.bitwise) { //eslint-disable-line no-bitwise const info = { role: r.name, permission: channel.type === 'text' ? 'SEND_MESSAGES' : 'CONNECT', channel: channel.name, type: channel.type, emoji: channel.type === 'text' ? emojis['text-channel'] : emojis['voice-channel'] }; issues.push(info); } } } } catch(err) {} //eslint-disable-line no-empty } updatedPermissions = true; } else { if(params.length > 1 && params[0].toLowerCase() === 'role') params = params.splice(1); const search = params.join(' '); role = await this.client.resolver.resolveRole(search, 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: stripIndents`${message.format('S_MUTE_ROLESUCCESS', { role: role.name, type: created ? 'created' : 'set' })} ${updatedPermissions ? message.format('S_MUTE_GENERATEDPERMISSIONS') : message.format('S_MUTE_UNGENERATEDPERMISSIONS')} ${issues.length > 0 ? message.format('S_MUTE_ISSUES', { issues: issues.map((i) => `**\`${i.role}\`:** Has the \`${i.permission}\` permission in **${i.emoji}${i.channel}**.`).join('\n') }) : ''}`, error: false }; } */ /* async _createRole(message, args) { let role = null; let name = args.join(' ') || 'Muted'; if(name.length > maxCharacters) name = name.slice(0, 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; } */ fields(guild) { const setting = guild._settings[this.index]; return [ { name: '》 Muted 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;