为了账号安全,请及时绑定邮箱和手机立即绑定

如何扩展 client.command 的功能?

如何扩展 client.command 的功能?

德玛西亚99 2022-01-18 17:28:37
我正在尝试添加对client.command(client作为discord.ext.commands.Bot实例)的错误、args、kwargs 和函数内容的处理。基本上,我试图让我的所有命令具有某些共同的自定义行为。我最初的想法是创建一个返回装饰器的函数,该装饰器用client.command.但是,我遇到的最大问题是,返回的装饰器的参数处理client.command(...)完全取决于被装饰函数的参数和注解的排列方式,也就是说,像这样带有参数的包装器async def wrapper(*args, **kwargs):将收到原始参数。这意味着我必须自己处理包装器内的所有内容,这discord.ext.commands首先破坏了使用的全部意义。阅读PEP 3107,我试图想出一个解决方法。这是代码的草图,与问题无关的部分被删掉了:from discord.ext import commands as cimport discord as dclient = 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吗?
查看完整描述

1 回答

?
湖上湖

TA贡献2003条经验 获得超2个赞

我认为您根本不需要扩展的功能Command。相反,您可以拥有提供您正在寻找的功能的机器人范围on_command_error和 事件。on_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")


查看完整回答
反对 回复 2022-01-18
  • 1 回答
  • 0 关注
  • 185 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号