你如何扩展client.command的功能?

问题描述 投票:0回答:1

我试图添加到client.command的错误,args,kwargs和函数的处理(clientdiscord.ext.commands.Bot实例)。基本上我试图让我的所有命令都有一些共同的自定义行为。

我最初的想法是创建一个函数,返回一个装饰器,用client.command装饰它的包装器。

然而,我遇到的最大问题是client.command(...)返回的装饰器的参数处理完全取决于装饰函数的参数和注释的排列方式,这意味着包含其参数的包装器

async def wrapper(*args, **kwargs):

将接受原始论点。这意味着我必须自己处理包装内的所有东西,这首先打败了使用discord.ext.commands的全部意义。

PEP 3107,我试图想出一个解决方法。这是代码草图,其中与问题无关的部分:

from discord.ext import commands as c
import discord as d
client = c.Bot(command_prefix = "insert_prefix_here$")



def command(*args, **kwargs):
    def decorator(func):
        command_name = kwargs.setdefault("name", func.__name__)

        async def wrapper(ctx, *args, **kwargs):
            # do stuff with func and command_name

        # ...eh? this down here is the dirtiest thing i've ever seen
        wrapper.__defaults__ = func.__defaults__
        wrapper.__annotations__ = func.__annotations__

        wrapper = client.command(*args, **kwargs)(wrapper)


        @wrapper.error
        async def wrapper_error(ctx, error):
            # do stuff with ctx, error, command_name, ... etc

        return wrapper

    return decorator

# insert commands with @command(...) decorator here

我简单地想到“欺骗”client.command(...)返回的装饰器,认为包装器的参数结构与装饰函数的参数结构相同,方法是将包装器的__default____annotations__属性设置为装饰函数的属性。

是的,我完全意识到这是一个可怕而且没有那么深思熟虑的想法(它甚至不起作用)。这就是我发布这个的原因,这意味着我的方向并不好。

有什么建议?

有没有更简单的方法做这样的事情,我完全没有意识到?

我应该从头开始自己构建一个command装饰器并坚持使用discord.Client而不是试图添加到client.command

python discord.py discord.py-rewrite
1个回答
1
投票

我认为你根本不需要扩展Command的功能。相反,您可以使用机器人范围的on_command_erroron_command_completion事件来提供您正在寻找的功能。

唯一的问题是返回值。最简单的方法可能是分配ctx的未使用属性,而不是尝试捕获返回值(您还可以使用返回值引发自定义错误)

from discord.commands.ext import Bot, BadArgument, MissingRequiredArgument
import sys

bot = Bot("!")

@bot.command()
async def some_command(ctx):
    ctx.return_value = 1

@bot.event
async def on_command_error(ctx, error):
    if isinstance(error, BadArgument):
        await ctx.send("That's a bad argument")
    elif isinstance(error, MissingRequiredArgument):
        await ctx.send("You're missing an argument")
    else:
        # This is what the standard on_command_error does
        print('Ignoring exception in command {}:'.format(context.command), file=sys.stderr)
        traceback.print_exception(type(exception), exception, exception.__traceback__, file=sys.stderr)

@bot.event
async def on_command_completion(ctx):
    await ctx.send(str(ctx.return_value))

bot.run("TOKEN")
© www.soinside.com 2019 - 2024. All rights reserved.