简体   繁体   English

异步 function 作为 Discord.py 上的装饰器

[英]Async function as Decorator on Discord.py

I have a Discord.py Command, I want to make a custom permission handler.我有一个 Discord.py 命令,我想制作一个自定义权限处理程序。

My Command:我的命令:

@commands.command()
@custom_permission("administrator")
async def example(self, ctx, args):
    ...

In this case, @custom_permission() is the Permission handler, now how do I make it work for a decorator that in async def?在这种情况下, @custom_permission()是权限处理程序,现在我如何让它适用于异步定义中的装饰器?

The Decorator Function:装饰师Function:

async def custom_permission(permission):
    
    async def predicate(ctx, permission):
        if ctx.author.id in config.owners:
            return True

        elif permission == "administrator":
            if ctx.author.guild_permissions.administrator:
                return True

            else:
                embed = discord.Embed(timestamp=ctx.message.created_at, description=f"You do not meet the required guild permissions the command \"`{ctx.command.name}`\" requires to be executed.\n\nYou need `{permission.upper()}` Permission in this Guild to be able to execute/run/use this command.", color=242424)
                embed.set_author(name="Insufficient Permissions", icon_url=config.forbidden_img)
                embed.set_footer(text="Numix", icon_url=config.logo)
                await ctx.send(embed=embed)

        elif permission == "manage_messages":
            if ctx.author.guild_permissions.manage_messages:
                return True

            else:
                embed = discord.Embed(timestamp=ctx.message.created_at, description=f"You do not meet the required guild permissions the command \"`{ctx.command.name}`\" requires to be executed.\n\nYou need `{permission.upper()}` Permission in this Guild to be able to execute/run/use this command.", color=242424)
                embed.set_author(name="Insufficient Permissions", icon_url=config.forbidden_img)
                embed.set_footer(text="Numix", icon_url=config.logo)
                await ctx.send(embed=embed)

        elif permission == "kick":
            if ctx.author.guild_permissions.kick:
                return True

            else:
                embed = discord.Embed(timestamp=ctx.message.created_at, description=f"You do not meet the required guild permissions the command \"`{ctx.command.name}`\" requires to be executed.\n\nYou need `{permission.upper()}` Permission in this Guild to be able to execute/run/use this command.", color=242424)
                embed.set_author(name="Insufficient Permissions", icon_url=config.forbidden_img)
                embed.set_footer(text="Numix", icon_url=config.logo)
                await ctx.send(embed=embed)

        elif permission == "ban":
            if ctx.author.guild_permissions.ban:
                return True
                
            else:
                embed = discord.Embed(timestamp=ctx.message.created_at, description=f"You do not meet the required guild permissions the command \"`{ctx.command.name}`\" requires to be executed.\n\nYou need `{permission.upper()}` Permission in this Guild to be able to execute/run/use this command.", color=242424)
                embed.set_author(name="Insufficient Permissions", icon_url=config.forbidden_img)
                embed.set_footer(text="Numix", icon_url=config.logo)
                await ctx.send(embed=embed)

        elif permission == "manage_guild":
            if ctx.author.guild_permissions.manage_guild:
                return True

            else:
                embed = discord.Embed(timestamp=ctx.message.created_at, description=f"You do not meet the required guild permissions the command \"`{ctx.command.name}`\" requires to be executed.\n\nYou need `{permission.upper()}` Permission in this Guild to be able to execute/run/use this command.", color=242424)
                embed.set_author(name="Insufficient Permissions", icon_url=config.forbidden_img)
                embed.set_footer(text="Numix", icon_url=config.logo)
                await ctx.send(embed=embed)
        

    return commands.check(predicate(ctx, permission))

Now, how do I make this work?现在,我该如何进行这项工作? I can't change it to a normal function, because If I did that, then I can't send the embed message when the permission requirement is met.我无法将其更改为正常的 function,因为如果我这样做,则在满足权限要求时我无法发送嵌入消息。

  1. Decorator syntax:装饰器语法:
@decorator
def function():
    ...

is just syntax sugar for this:只是语法糖:

def function():
    ...
function = decorator(function)
  1. An async function is a function that returns a coroutine.异步 function 是返回协程的 function。

In [1]: async def foo():
   ...:     return 42
   ...: 

In [2]: await foo()
Out[2]: 42

In [3]: foo()
Out[3]: <coroutine object foo at 0x7f7ca626da40>

So when you do所以当你这样做

@an_async_function("argument")
async def foo():
    ...

an_async_function("argument") will be a coroutine object, which you are trying to call. an_async_function("argument")将是您尝试调用的协程 object。

  1. commands.check expects an async function, while you're passing in the call to that function. commands.check需要异步 function,而您正在传递对 function 的调用。

What you can do is:你可以做的是:

a) use functools.partial to partially apply the predicate function to the permissions argument: a) 使用functools.partialpredicate function 部分应用于permissions参数:

async def _check_permission(ctx, permission):
    ...

def custom_permission(permission):

    return commands.check(partial(_check_permission, permission=permission))

b) Just use the permission that you pass in the decorator inside predicate . b) 只需使用您在predicate内的装饰器中传递的permission

def custom_permission(permission):
    
    async def predicate(ctx):
        ...  # use `permission` here

    return commands.check(predicate)

You don't need to make the outer-most function asynchronous, however the predicate function can be a coroutine您不需要使最外层的 function 异步,但是predicate function可以是协程

def custom_permission(permission):
    async def predicate(ctx):
        ...
    return commands.check(predicate)

Keep in mind that the predicate coroutine can only take one argument, ctx (the arguments are passed internally in the commands.check method, you do not pass them yourself) If you want to access the other arguments use ctx.args .请记住, predicate协程只能采用一个参数, ctx (arguments 在commands.check方法中内部传递,您自己传递它们)如果您想访问另一个 arguments,请使用ctx.args

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM