From 94ae11f9d0937c22166b94a4d8ccd668ceebf7a9 Mon Sep 17 00:00:00 2001 From: ZRunner Date: Thu, 29 Aug 2024 19:22:12 +0200 Subject: [PATCH] refact(moderation): better staff check --- core/bot_classes/axobot.py | 23 +++++++++++++++++++++++ modules/moderation/moderation.py | 32 ++++++-------------------------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/core/bot_classes/axobot.py b/core/bot_classes/axobot.py index 634c2bd10..08b96f8f6 100644 --- a/core/bot_classes/axobot.py +++ b/core/bot_classes/axobot.py @@ -305,3 +305,26 @@ async def get_command_mention(self, command_name: str): return f"`{command.qualified_name}`" self.log.error("Trying to mention invalid command: %s", command_name) return f"`{command_name}`" + + async def can_use_command(self, interaction: discord.Interaction, member: discord.Member): + "Check if a given user can use a slash command" + if member.bot: + return False + if member.guild_permissions.administrator: + return True + command_name = interaction.data["name"] + command = await self.fetch_app_command_by_name(command_name) + if command is None: + raise RuntimeError(f"Global command '{command_name}' not found") + try: + command_perms = await command.fetch_permissions(interaction.guild) + except discord.NotFound: + return member.guild_permissions <= interaction.command.default_permissions + can_use = False + user_roles = set(role.id for role in member.roles) + for perm in command_perms.permissions: + if perm.type == discord.AppCommandPermissionType.user and perm.id == member.id: + return perm.permission + if perm.type == discord.AppCommandPermissionType.role and perm.id in user_roles: + can_use = can_use or perm.permission + return can_use diff --git a/modules/moderation/moderation.py b/modules/moderation/moderation.py index 5d9896a5e..271eac393 100644 --- a/modules/moderation/moderation.py +++ b/modules/moderation/moderation.py @@ -172,13 +172,7 @@ async def kick(self, interaction: discord.Interaction, user: discord.Member, rea return await interaction.response.defer(ephemeral=True) - async def user_can_kick(user: discord.Member): - return user.guild_permissions.kick_members - - if user == interaction.guild.me or (self.bot.database_online and await user_can_kick(user)): - await interaction.followup.send(await self.bot._(interaction, "moderation.kick.cant-staff")) - return - if not self.bot.database_online and interaction.channel.permissions_for(user).kick_members: + if user == interaction.guild.me or await self.bot.can_use_command(interaction, user): await interaction.followup.send(await self.bot._(interaction, "moderation.kick.cant-staff")) return if user.roles[-1].position >= interaction.guild.me.roles[-1].position: @@ -217,14 +211,8 @@ async def warn(self, interaction: discord.Interaction, user: discord.Member, mes ..Example warn @someone Please just stop, next one is a mute duh ..Doc moderator.html#warn""" - async def user_can_warn(user: discord.Member): - return user.guild_permissions.moderate_members - await interaction.response.defer(ephemeral=True) - if user == interaction.guild.me or (self.bot.database_online and await user_can_warn(user)): - await interaction.followup.send(await self.bot._(interaction, "moderation.warn.cant-staff")) - return - if not self.bot.database_online and interaction.channel.permissions_for(user).manage_roles: + if user == interaction.guild.me or await self.bot.can_use_command(interaction, user): await interaction.followup.send(await self.bot._(interaction, "moderation.warn.cant-staff")) return if user.bot and not user.id==423928230840500254: @@ -335,7 +323,7 @@ async def user_can_mute(user: discord.Member): ]) await interaction.followup.send((await self.bot._(interaction, "moderation.mute.staff-mute")) + " " + emoji) return - if not self.bot.database_online and interaction.channel.permissions_for(user).manage_roles: + if await self.bot.can_use_command(interaction, user): await interaction.followup.send(await self.bot._(interaction, "moderation.warn.cant-staff")) return role = await self.get_muted_role(interaction.guild) @@ -533,9 +521,8 @@ async def ban(self, interaction: discord.Interaction, user: discord.User, durati if not interaction.guild.me.guild_permissions.ban_members: await interaction.followup.send(await self.bot._(interaction, "moderation.ban.cant-ban")) return - if user in interaction.guild.members: - member = interaction.guild.get_member(user.id) - if user == interaction.guild.me or member.guild_permissions.ban_members: + if member := interaction.guild.get_member(user.id): + if member == interaction.guild.me or await self.bot.can_use_command(interaction, member): await interaction.followup.send(await self.bot._(interaction, "moderation.ban.staff-ban")) return if member.roles[-1].position >= interaction.guild.me.roles[-1].position: @@ -616,15 +603,8 @@ async def softban(self, interaction: discord.Interaction, user: discord.Member, if not interaction.guild.me.guild_permissions.ban_members: await interaction.response.send_message(await self.bot._(interaction, "moderation.ban.cant-ban"), ephemeral=True) return - async def user_can_kick(user: discord.Member): - return user.guild_permissions.kick_members - if user == interaction.guild.me or (self.bot.database_online and await user_can_kick(user)): - await interaction.response.send_message( - await self.bot._(interaction, "moderation.kick.cant-staff"), ephemeral=True - ) - return - if not self.bot.database_online and user.guild_permissions.kick_members: + if user == interaction.guild.me or await self.bot.can_use_command(interaction, user): await interaction.response.send_message( await self.bot._(interaction, "moderation.kick.cant-staff"), ephemeral=True )