Discord.py 上作为装饰器的异步函数
Async function as Decorator on Discord.py
我有一个 Discord.py 命令,我想制作一个自定义权限处理程序。
我的命令:
@commands.command()
@custom_permission("administrator")
async def example(self, ctx, args):
...
在这种情况下,@custom_permission()
是权限处理程序,现在我如何让它适用于异步定义中的装饰器?
装饰函数:
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))
现在,我该怎么做呢?
我无法将其更改为普通功能,因为如果我那样做,则在满足权限要求时我无法发送嵌入消息。
你不需要让最外层的函数异步,但是 predicate
函数 可以 是协程
def custom_permission(permission):
async def predicate(ctx):
...
return commands.check(predicate)
记住predicate
协程只能接受一个参数,ctx
(参数在commands.check
方法内部传递,你不 自己传递)如果您想访问其他参数,请使用 ctx.args
.
- 装饰器语法:
@decorator
def function():
...
只是语法糖:
def function():
...
function = decorator(function)
- 异步函数是 returns 协程的函数。
In [1]: async def foo():
...: return 42
...:
In [2]: await foo()
Out[2]: 42
In [3]: foo()
Out[3]: <coroutine object foo at 0x7f7ca626da40>
所以当你这样做时
@an_async_function("argument")
async def foo():
...
an_async_function("argument")
将是您尝试调用的协程对象。
commands.check
需要一个异步函数,而您正在传递对该函数的调用。
您可以做的是:
a) 使用 functools.partial
将 predicate
函数部分应用到 permissions
参数:
async def _check_permission(ctx, permission):
...
def custom_permission(permission):
return commands.check(partial(_check_permission, permission=permission))
b) 只需在 predicate
.
中使用您在装饰器中传递的 permission
def custom_permission(permission):
async def predicate(ctx):
... # use `permission` here
return commands.check(predicate)
我有一个 Discord.py 命令,我想制作一个自定义权限处理程序。
我的命令:
@commands.command()
@custom_permission("administrator")
async def example(self, ctx, args):
...
在这种情况下,@custom_permission()
是权限处理程序,现在我如何让它适用于异步定义中的装饰器?
装饰函数:
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))
现在,我该怎么做呢? 我无法将其更改为普通功能,因为如果我那样做,则在满足权限要求时我无法发送嵌入消息。
你不需要让最外层的函数异步,但是 predicate
函数 可以 是协程
def custom_permission(permission):
async def predicate(ctx):
...
return commands.check(predicate)
记住predicate
协程只能接受一个参数,ctx
(参数在commands.check
方法内部传递,你不 自己传递)如果您想访问其他参数,请使用 ctx.args
.
- 装饰器语法:
@decorator
def function():
...
只是语法糖:
def function():
...
function = decorator(function)
- 异步函数是 returns 协程的函数。
In [1]: async def foo():
...: return 42
...:
In [2]: await foo()
Out[2]: 42
In [3]: foo()
Out[3]: <coroutine object foo at 0x7f7ca626da40>
所以当你这样做时
@an_async_function("argument")
async def foo():
...
an_async_function("argument")
将是您尝试调用的协程对象。
commands.check
需要一个异步函数,而您正在传递对该函数的调用。
您可以做的是:
a) 使用 functools.partial
将 predicate
函数部分应用到 permissions
参数:
async def _check_permission(ctx, permission):
...
def custom_permission(permission):
return commands.check(partial(_check_permission, permission=permission))
b) 只需在 predicate
.
permission
def custom_permission(permission):
async def predicate(ctx):
... # use `permission` here
return commands.check(predicate)