You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.py如何实现支持异步操作的自定义权限校验装饰器

问题解决方法

你原有代码的核心问题如下:

  • 你之前误以为外层装饰器需要异步才能支持异步发送消息,实际上只需要内部的校验函数(predicate)为异步即可,discord.py的commands.check原生支持异步predicate,完全可以正常执行异步逻辑发送Embed,外层仅作为接收权限参数的工厂函数,不需要定义为异步
  • 你错误地直接执行了predicate(ctx, permission)并把返回值传给commands.check,实际上应该直接把predicate函数本身传给commands.check,由discord.py在命令触发时自动传入ctx参数执行
  • predicate不需要额外接收permission参数,直接通过闭包捕获外层传入的permission值即可
  • 大量重复的Embed生成逻辑可以抽离复用,减少冗余代码
  • 原有代码中部分权限属性名写错,discord.py原生踢出成员权限为kick_members、封禁成员权限为ban_members,直接写kick、ban会取不到正确权限值

修改后完整代码

def custom_permission(permission):
    async def predicate(ctx):
        # 所有者直接放行
        if ctx.author.id in config.owners:
            return True
        
        # 权限校验
        has_perm = False
        if permission == "administrator":
            has_perm = ctx.author.guild_permissions.administrator
        elif permission == "manage_messages":
            has_perm = ctx.author.guild_permissions.manage_messages
        elif permission == "kick":
            has_perm = ctx.author.guild_permissions.kick_members
        elif permission == "ban":
            has_perm = ctx.author.guild_permissions.ban_members
        elif permission == "manage_guild":
            has_perm = ctx.author.guild_permissions.manage_guild
        
        if has_perm:
            return True
        
        # 权限不足发送提示Embed
        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 False
    
    # 直接将predicate函数传给commands.check,不要提前执行
    return commands.check(predicate)

使用方式

和你原有写法完全一致,不需要调整命令上的装饰器代码:

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

内容的提问来源于stack exchange,提问作者BenitzCoding

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 08:48:02