diff --git a/src/structure/components/inhibitors/Permissions.js b/src/structure/components/inhibitors/Permissions.js index 74b7894..38b7f85 100644 --- a/src/structure/components/inhibitors/Permissions.js +++ b/src/structure/components/inhibitors/Permissions.js @@ -1,5 +1,7 @@ const { Inhibitor } = require('../../interfaces'); +const safeCommands = ['command:settings', 'command:grant', 'command:revoke']; + class Permissions extends Inhibitor { constructor(client) { @@ -13,6 +15,62 @@ class Permissions extends Inhibitor { } + async execute(interaction, command, override = null) { + + const { guild, member } = interaction; + const { permissions: { type } } = await guild.settings(); + const permissions = override ?? command.memberPermissions; + const memberPerms = interaction.channel.permissionsFor(member); + + let missing = []; + if (type === 'discord') { + missing = memberPerms.missing(permissions); + if (missing.length === permissions.length && permissions.length > 0) + return super._fail({ missing: missing.join(', ') }); + } else if (type === 'grant' && permissions.length) { + if (safeCommands.includes(command.resolveable) && memberPerms.has(['MANAGE_GUILD'])) + return super._succeed(); + missing = await this._checkGrants(interaction, command.resolveable); + } else if (type === 'both') { + const disc = memberPerms.missing(permissions); + const grants = await this._checkGrants(interaction, command.resolveable); + if (disc.length === permissions.length && permissions.length && grants.length) + return super._fail({ missing: [...disc, ...grants].join(', ') }); + } + + if (missing.length > 0) { + return super._fail({ missing: missing.join(', ') }); + } + return super._succeed(); + + } + + async _checkGrants(interaction, permission) { + const perms = await interaction.guild.permissions(); + const roles = interaction.member.roles.cache.map((r) => r.id); + const channelId = interaction.channel.id; + const user = interaction.author.id; + + let canRun = false; + for (const [id, perm] of Object.entries(perms)) { + if (id === user || roles.includes(id)) { + if (perm.global.includes(id)) { + canRun = true; + break; + } + const channel = perm.channels[channelId]; + if (!channel) continue; + if (channel.includes(permission)) { + canRun = true; + break; + } + } + } + + return canRun ? [] : [permission]; + + } + } module.exports = Permissions; \ No newline at end of file