async def _voice_perm_check(ctx: commands.Context, user_voice_state: Optional[discord.VoiceState], **perms: bool) -> bool: """Check if the bot and user have sufficient permissions for voicebans. This also verifies that the user's voice state and connected channel are not ``None``. Returns ------- bool ``True`` if the permissions are sufficient and the user has a valid voice state. """ if user_voice_state is None or user_voice_state.channel is None: await ctx.send(_("That user is not in a voice channel.")) return False voice_channel: discord.VoiceChannel = user_voice_state.channel required_perms = discord.Permissions() required_perms.update(**perms) if not voice_channel.permissions_for(ctx.me) >= required_perms: await ctx.send( _("I require the {perms} permission(s) in that user's channel to do that." ).format(perms=format_perms_list(required_perms))) return False if (ctx.permission_state is commands.PermState.NORMAL and not voice_channel.permissions_for( ctx.author) >= required_perms): await ctx.send( _("You must have the {perms} permission(s) in that user's channel to use this " "command.").format(perms=format_perms_list(required_perms))) return False return True
async def chanperms(self, ctx, member: discord.Member, *, channel: Union[discord.TextChannel, discord.VoiceChannel, discord.CategoryChannel, str] = None): """Check user's permission for current or provided channel""" if isinstance(channel, str): await ctx.send_help() return perms = channel.permissions_for(member) await ctx.send("{}\n{}".format( chat.inline(str(member.guild_permissions.value)), chat.box(chat.format_perms_list(perms), lang="py")))
async def chanperms( self, ctx, member: Optional[discord.Member], *, channel: Union[discord.TextChannel, discord.VoiceChannel, discord.CategoryChannel] = None, ): """Check user's permission for current or provided channel""" if not member: member = ctx.author if not channel: channel = ctx.channel perms = channel.permissions_for(member) await ctx.send("{}\n{}".format( chat.inline(str(perms.value)), chat.box( chat.format_perms_list(perms) if perms.value else _("No permissions"), lang="py", ), ))
async def _check_requires_user_perms_and_privilege_level( self, cog_or_command: commands.CogCommandMixin) -> CheckResult: label = _("User's discord permissions and privilege level") requires = cog_or_command.requires if await requires._verify_user(self.ctx): print("HI!") return CheckResult(True, label) resolutions = [] if requires.user_perms is not None: permissions = format_perms_list(requires.user_perms) resolutions.append( _("grant the required permissions to the user through role settings" " or channel overrides")) details = (_( "The user is missing some of the channel permissions ({permissions})" " required by the {cog} cog." ).format( permissions=permissions, cog=inline(cog_or_command.qualified_name) ) if cog_or_command is self.ctx.cog else _( "The user is missing some of the channel permissions ({permissions})" " required by the {command} command.").format( permissions=permissions, command=self._format_command_name(cog_or_command))) if requires.privilege_level is not None: if requires.privilege_level is commands.PrivilegeLevel.GUILD_OWNER: privilege_level = _("the guild owner") else: if requires.privilege_level is commands.PrivilegeLevel.MOD: privilege_level = _("the mod role") elif requires.privilege_level is commands.PrivilegeLevel.ADMIN: privilege_level = _("the admin role") else: raise RuntimeError("Ran into unexpected privilege level.") resolutions.append(_("assign appropriate role to the user")) details = ( _("The user is missing the privilege level ({privilege_level})" " required by the {cog} cog.").format( privilege_level=privilege_level, cog=inline(cog_or_command.qualified_name)) if cog_or_command is self.ctx.cog else _("The user is missing the privilege level ({privilege_level})" " required by the {command} command.").format( privilege_level=privilege_level, command=self._format_command_name(cog_or_command), )) if not resolutions: # Neither `user_perms` nor `privilege_level` are responsible for the issue. return CheckResult(True, label) resolutions.append(_("add appropriate rule in the Permissions cog")) if requires.user_perms is not None and requires.privilege_level is not None: details = (_( "The user has neither the channel permissions ({permissions}) nor" " the privilege level ({privilege_level}) required by the {cog} cog." ).format( permissions=permissions, privilege_level=privilege_level, cog=inline(cog_or_command.qualified_name), ) if cog_or_command is self.ctx.cog else _( "The user has neither the channel permissions ({permissions}) nor" " the privilege level ({privilege_level}) required by the {command} command." ).format( permissions=permissions, privilege_level=privilege_level, command=self._format_command_name(cog_or_command), )) return CheckResult( False, label, details, self._format_multiple_resolutions(resolutions), )
async def _check_requires( self, label: str, cog_or_command: commands.CogCommandMixin) -> CheckResult: original_perm_state = self.ctx.permission_state try: allowed = await cog_or_command.requires.verify(self.ctx) except commands.DisabledCommand: return CheckResult( False, label, _("The cog of the given command is disabled in this guild."), _("To fix this issue, you can run {command}" " which will enable the {affected_cog} cog in this guild."). format( command=self._format_command_name( f"command enablecog {self.ctx.cog.qualified_name}"), affected_cog=inline(self.ctx.cog.qualified_name), ), ) except commands.BotMissingPermissions as e: # No, go away, "some" can refer to a single permission so plurals are just fine here! # Seriously. They are. Don't even question it. details = (_( "Bot is missing some of the channel permissions ({permissions})" " required by the {cog} cog." ).format( permissions=format_perms_list(e.missing), cog=inline(cog_or_command.qualified_name), ) if cog_or_command is self.ctx.cog else _( "Bot is missing some of the channel permissions ({permissions})" " required by the {command} command.").format( permissions=format_perms_list(e.missing), command=self._format_command_name(cog_or_command), )) return CheckResult( False, label, details, _("To fix this issue, grant the required permissions to the bot" " through role settings or channel overrides."), ) if allowed: return CheckResult(True, label) self.ctx.permission_state = original_perm_state return await self._check_until_fail( label, ( partial(self._check_requires_bot_owner, cog_or_command), partial(self._check_requires_permission_hooks, cog_or_command), partial(self._check_requires_permission_rules, cog_or_command), ), # unless there's some bug here, we should probably never run into this final_check_result=CheckResult( False, _("Other issues related to the permissions."), _("Fatal error: There's an issue related to the permissions for the" " {cog} cog but we're not able to determine the exact cause." ) if cog_or_command is self.ctx.cog else _("Fatal error: There's an issue related to the permissions for the" " {command} command but we're not able to determine the exact cause." ), _("This is an unexpected error, please report it on Red's issue tracker." ), ), )
async def _check_requires( self, label: str, cog_or_command: commands.CogCommandMixin) -> CheckResult: original_perm_state = self.ctx.permission_state try: allowed = await cog_or_command.requires.verify(self.ctx) except commands.DisabledCommand: return CheckResult( False, label, _("The cog of the given command is disabled in this guild."), _("To fix this issue, you can run {command}" " which will enable the {affected_cog} cog in this guild."). format( command=self._format_command_name( f"command enablecog {self.ctx.cog.qualified_name}"), affected_cog=inline(self.ctx.cog.qualified_name), ), ) except commands.BotMissingPermissions as e: # No, go away, "some" can refer to a single permission so plurals are just fine here! # Seriously. They are. Don't even question it. details = (_( "Bot is missing some of the channel permissions ({permissions})" " required by the {cog} cog." ).format( permissions=format_perms_list(e.missing), cog=inline(cog_or_command.qualified_name), ) if cog_or_command is self.ctx.cog else _( "Bot is missing some of the channel permissions ({permissions})" " required by the {command} command.").format( permissions=format_perms_list(e.missing), command=self._format_command_name(cog_or_command), )) return CheckResult( False, label, details, _("To fix this issue, grant the required permissions to the bot" " through role settings or channel overrides."), ) if allowed: return CheckResult(True, label) self.ctx.permission_state = original_perm_state return await self._check_until_fail( label, ( partial(self._check_requires_bot_owner, cog_or_command), partial(self._check_requires_permission_hooks, cog_or_command), ), # TODO: Split the `final_check_result` into parts to be ran by this function final_check_result=CheckResult( False, _("User's discord permissions, privilege level and rules from Permissions cog" ), _("One of the above is the issue."), _("To fix this issue, verify each of these" " and determine which part is the issue."), ), )