add_command discord.py 不工作 "The command passed must be a subclass of Command"

add_command discord.py not working "The command passed must be a subclass of Command"

我目前正在更新我的 discord 机器人,并希望添加新功能,允许我通过 discord 添加和删除命令,而无需直接修改代码。

我发现已经存在一些方法(即“Bot.add_command”和“Bot.remove_command”,它们完全符合我的要求。

“remove_command”部分工作得很好,但我在使用 add_command 函数添加回命令时遇到了问题。我已阅读文档,但我似乎不明白是什么导致了我的错误(如下所述)。

代码:

    @client.command()
    @commands.has_permissions(administrator = True)
    async def removecommand(ctx, command):
        try:
            client.remove_command(command)
        except Exception as err:
            print(err) 
        await ctx.message.add_reaction('✅')
    
    @client.command()
    @commands.has_permissions(administrator = True)
    async def addcommand(ctx, command):
        command = client.get_command(command)
        await client.add_command(command)
        await ctx.message.add_reaction('✅')

错误: discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: The command passed must be a subclass of Command

有人可以帮助我吗?我似乎不明白这是什么意思。谢谢。

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "/Users/name/Desktop/discord mj market/1 mainmarketplace.py", line 121, in addcommand
    await client.add_command(command)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 1132, in add_command
    raise TypeError('The command passed must be a subclass of Command')
TypeError: The command passed must be a subclass of Command

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 903, in invoke
    await ctx.command.invoke(ctx)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 859, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: The command passed must be a subclass of Command

传递给 add_commandremove_command 的参数 command 必须是 discord.ext.commands.Command 对象。当您的公会成员调用命令时,他们会将字符串传递给参数(因此出现错误消息)。

获取命令名对应的Command对象有两种方式:

  1. (推荐)使用Bot.get_command()方法。如果找不到命令,这将 return 对应于命令名称(或别名)或 NoneCommand 对象。 注意:命令名称区分大小写
  2. 使用Bot.walk_commands()方法。这将 return 生成器生成每个 Command 连接到 Bot 对象的对象。

至于add_command()方法,参数也必须是Command对象。因此,您必须创建自己的 Command 对象(这需要一个函数 func 和一个名称 name,等等)。最好将函数定义为 Command 对象(使用 Bot.command() 装饰器)。如果是这样,那么以上两种方法也可以。


Bot.get_command()

@client.command()
@commands.has_permissions(administrator = True)
async def removecommand(ctx, command):
    cmd = client.get_command(command)
    if cmd is None:
        await ctx.channel.send(f"Command `{command}` does not exist")
    client.remove_command(cmd)
    await ctx.message.add_reaction('✅')

Bot.walk_commands()

@client.command()
@commands.has_permissions(administrator = True)
async def removecommand(ctx, command):
    for cmd in client.walk_commands():
        if cmd.name.lower() == command.lower():
            client.remove_command(cmd)
            await ctx.message.add_reaction('✅')
            return
    await ctx.channel.send(f"Command `{command}` does not exist")

discord.utils.find(lambda cmd: str(cmd) == "yourcmdname", client.commands)

这将找到您的机器人的命令(如果存在),否则 returns None。另外,如果您要再次使用删除的命令,可以将其禁用。

@client.command()
async def toggle(ctx, cmd):
    command = discord.utils.find(lambda c: str(c) == cmd, client.commands)
    if command:
        command.enabled = not command.enabled
        if command.enabled:
            await ctx.send(f"{cmd} enabled.")
        else:
            await ctx.send(f"{cmd} disabled.")
    else:
        await ctx.send("Command not found")