【问题标题】:Asking for Kick Member permission despite having given admin rights to Bot尽管已授予 Bot 管理员权限,但仍要求 Kick Member 许可
【发布时间】:2021-08-08 04:51:51
【问题描述】:

所以我正在设置一个机器人,并对其进行测试。我有一个小功能是踢,禁止和取消禁止用户,设置在一个 cog 中,如下所示:

import discord
from discord.ext import commands

class Moderator(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

#KICK command
@commands.command()
@commands.has_permissions(kick_members=True)
async def kick(self, ctx, member : discord.Member, *, reason=None):
    ('About to kick')
    await member.kick(reason = reason)

@commands.command()
@commands.has_permissions(kick_members=False)
async def kick(self, ctx, member : discord.Member, *, reason=None):
    await ctx.send(f'You do not have permission to kick any member, {ctx.message.author.mention}!')

#BAN command
@commands.command()
@commands.has_permissions(ban_members=True)
async def ban(self, ctx, member : discord.Member, *, reason=None):
    await member.ban(reason = reason)
    await ctx.send(f'Banned {member.mention}')

@commands.command()
@commands.has_permissions(kick_members=False)
async def ban(self, ctx, member : discord.Member, *, reason=None):
    await ctx.send(f'You do not have permission to ban any member, {ctx.message.author.mention}!')

#UNBAN command
@commands.command()
@commands.has_permissions(ban_members=True)
async def unban(self, ctx, *, member):
    banned_users = await ctx.guild.bans()
    member_name, member_discriminator = member.split('#')

    for ban_entry in banned_users:
        user = ban_entry.user

        if (user.name, user.discriminator) == (member_name, member_discriminator):
            await ctx.guild.unban(user)
            await ctx.send(f'Unbanned {user.mention}')
            return

@commands.command()
@commands.has_permissions(kick_members=False)
async def unban(self, ctx, member : discord.Member, *, reason=None):
    await ctx.send(f'You do not have permission to unban any member, {ctx.message.author.mention}!')


#CLEAR MESSAGES
@commands.command()
@commands.has_permissions(manage_messages=True)
async def clear(self, ctx, amount=2):
    await ctx.channel.purge(limit=amount)

@commands.command()
@commands.has_permissions(manage_messages=False)
async def clear(self, ctx, amount=2):
    await ctx.send(f'You do not have permission to delete messages in this way, {ctx.message.author.mention}!')

def setup(bot):
    bot.add_cog(Moderator(bot))

现在我已经用一些空格格式化了上面的代码,以便它适合一个代码块,所以如果你复制粘贴到别处,你可能会遇到缩进错误。

继续前进,机器人本身也具有管理员权限以及单独的踢和禁止权限。它也被放置在角色层次结构的顶部,被视为:

我的机器人的名字是 JunkBot。

现在,每当我作为服务器所有者尝试使用命令 .kick @user 时,都会弹出以下错误:

错误的文本形式是:

Ignoring exception in command kick:
Traceback (most recent call last):
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\bot.py", line 939, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 855, in invoke
    await self.prepare(ctx)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 777, in prepare
    if not await self.can_run(ctx):
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 1087, in can_run
    return await discord.utils.async_all(predicate(ctx) for predicate in predicates)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\utils.py", line 348, in async_all
    for elem in gen:
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 1087, in <genexpr>
    return await discord.utils.async_all(predicate(ctx) for predicate in predicates)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 1790, in predicate
    raise MissingPermissions(missing)
discord.ext.commands.errors.MissingPermissions: You are missing Kick Members permission(s) to run this command.

ban、unban 和 clear messages 命令也出现类似错误。

有趣的是,作为所有者,我得到了这个错误,但假设另一个用户,我的一个朋友,他没有踢、禁止或消息管理角色,完美地运行他们的代码行,其中她从机器人那里得到消息,她无权踢、禁止或清除消息。附上截图。

我不知道我哪里出错了。请帮我调试一下。

【问题讨论】:

  • 您的 kick 命令对我有效(作为我自己服务器的所有者)
  • 您确定您使用的代码与我的完全相同吗?你的机器人层次结构和我的有点相似吗?您会分享这些详细信息,例如您授予机器人的哪些权限以及您作为所有者拥有哪些角色以及角色的层次结构?
  • 我的机器人拥有管理员权限,我复制并粘贴了您的代码(Moderator 类和kick 命令),根据需要修复了缩进。
  • 澄清一下,您,服务器的所有者(具有所有权限)不能调用此命令。但是,没有任何权限的人可以使用命令吗? (我的意思是在机器人中使用 as 实际上确实做了它预期做的事情)
  • 对,我是所有者,拥有所有权限,我无法调用此命令,但如果没有权限的人调用此命令,机器人会按照应有的方式响应。跨度>

标签: discord discord.py


【解决方案1】:

您的问题在于重写函数。我假设您希望制作errorhandler。但是,这不是这样做的方法。

您需要制作正确版本的错误处理程序,而不是使用不同的has_permissions 参数重写函数。

首先,删除所有重复的函数。这些是在 has_permissions 参数上需要 False 的函数。

接下来,创建一个错误处理函数。您可以只为 Cog 命令、所有命令或特定命令创建一个。如果它适用于所有命令,您将使用事件on_command_error,(我建议在主文件中使用它或作为侦听器使用它)。如果是用于 Cog,则必须使用 cog_command_error。如果是针对特定命令,则应制作 Command.error 装饰器。
我将展示 Cog 特定的处理程序,但来回切换不会花费太长时间。

# Indent into Cog level
async def cog_command_error(self, ctx, error):
    # Allows us to check for original exceptions raised and sent to CommandInvokeError.
    # If nothing is found. We keep the exception passed to on_command_error.
    error = getattr(error, 'original', error)
   
    if isinstance(error, commands.BotMissingPermissions): # Check if bot is missing permissions
        await ctx.send(f'I am missing these permissions to do this command:\n{self.lts(error.missing_perms)}')

    elif isinstance(error, commands.MissingPermissions): # Check if user is missing permissions
        await ctx.send(f'You are missing these permissions to do this command:\n{self.lts(error.missing_perms)}')


@staticmethod
def lts(list_: list): # Used to make reading the list of permissions easier.
    """List to string.
        For use in `self.on_command_error`"""
    return ', '.join([obj.name if isinstance(obj, discord.Role) else str(obj).replace('_', ' ') for obj in list_])

以下是您可以在处理程序中使用的异常列表:Exceptions

仅供参考,处理程序不需要我拥有的 lts 函数。它用于使权限列表在一个字符串中可读。您可以随时将其删除或更改为您的需要。

【讨论】:

  • 哦,非常感谢!我是编码新手,所以我不知道错误处理技术。这确实帮助了我的问题,这也适用于其余命令,谢谢!出于好奇,您能解释一下为什么我写的那些函数会导致错误吗?
  • 您正在重写它们,以便只有没有这些权限的人(不是您)才能使用它们。也只能用于同名的一个变量/函数/类(在整个程序的全局范围内)
【解决方案2】:

这不是错误处理的工作方式。您应该查看文档的error handling 部分,了解如何处理缺少的权限。

编辑因为人们提醒我提供更多信息

您不应该通过has_permissions 处理错误。从我从您的代码中可以看出,当调用者没有使用该命令所需的权限时,您希望发送一条消息。这可以通过错误处理程序来实现。错误处理程序将捕获MissingPermissions 异常并基于此执行某些操作。这是一个例子:

@commands.Cog.listener()
async def on_command_error(self, ctx, error): #this is the event that catches errors
    if isinstance(error, commands.MissingPermissions): #seeing if the error is the missing permissions error
        await ctx.send(f"You do not have the permission to do this, {ctx.author.mention}!")

这使用 全局 错误处理程序,这意味着无论何时捕获到错误,这都会捕获它。但是,如果您希望每个命令都有一个错误处理程序,那么您只需更改装饰器和函数名称即可。例如:

@kick.error
async def on_kick_error(self, ctx, error):
    if isinstance(error, commands.MissingPermissions):
        await ctx.send(f"You do not have the permission to kick any member, {ctx.author.mention} ")

这个只会在kick命令错误时触发,其他都不会。

【讨论】:

  • 准确地说,我看不出错误处理文档与我的问题有什么关系。如果您认为这可以通过错误处理文档解决,我请求您使用适当的代码指导我。
  • @RakshitDeshmukh 实际上,这确实回答了这个问题。但这还不足以解释原因。这张海报是在正确的轨道上
  • 你能建议一个适当的错误处理包括代码作为答案吗?如果您贡献它,它将非常有帮助。
  • 致@Ay355,我建议详细说明您的答案并解释您应该做什么。如果您不解释任何内容,大多数人可能不会理解您的答案可能会如何回答问题或如何实施。
  • 是的,很抱歉,当你的消息来的时候,我正在输入编辑。希望我这次解释得更多。
猜你喜欢
  • 2019-09-17
  • 1970-01-01
  • 2020-09-04
  • 2021-08-12
  • 2018-11-12
  • 1970-01-01
  • 2015-06-19
  • 1970-01-01
  • 2020-12-11
相关资源
最近更新 更多