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

discord.py 2.0自定义装饰器导致命令无法注册求助

问题:discord.py 2.0自定义装饰器导致命令无法被机器人识别

我基于discord.py 2.0开发机器人,为了避免在每个新命令中重复编写用户注册检查逻辑,把该逻辑封装成了自定义装饰器command_author_check。但给命令添加这个装饰器后,命令完全无法被机器人识别。

命令类代码

from discord.ext import commands

from main import db

from scr.phrases_func import dict_to_str
from scr.cfg import phrases
from scr.command_author_check import command_author_check


class GeneralCommands(commands.Cog):
    def __init__(self, bot: commands.Bot):
        self.bot = bot

    @commands.command()
    async def info(self, ctx):
        auth = ctx.message.author
        if db.check_user(auth):
            if db.get_user(auth).permissions_level >= 20:
                await auth.send(ctx.message.author.mention + phrases.master_greeting + dict_to_str(phrases.master_commands))
            else:
                await auth.send(ctx.message.author.mention + phrases.slaves_greeting + dict_to_str(phrases.slaves_commands))
        else:
            await auth.send(ctx.message.author.mention + phrases.general_greeting + dict_to_str(phrases.slaves_commands))

    @commands.command()
    @command_author_check()
    async def test(self, ctx):
        await ctx.send("ПОЛУЧИЛОСЬ")


async def setup(bot: commands.Bot):
    await bot.add_cog(GeneralCommands(bot))

装饰器代码

from main import db
from scr.cfg import phrases
from scr import phrases_func


def command_author_check(permissions_level: int = 1):
    print("command_author_check")

    def decorator(func):
        print("decorator")
        
        async def wrapper(ctx, *args, **kwargs):
            print("wrapper")
            auth = ctx.message.author
            if db.check_user(auth):
                if db.get_user(auth).permissions_level >= permissions_level:
                    return await func(ctx, *args, **kwargs)
                else:
                    await auth.send(ctx.message.author.mention + phrases.slaves_greeting + phrases_func.dict_to_str(phrases.slaves_commands))
            else:
                await auth.send(ctx.message.author.mention + phrases.general_greeting + phrases_func.dict_to_str(phrases.slaves_commands))
        return wrapper
    return decorator

解决方法

问题出在两个核心点:装饰器顺序错误,以及自定义装饰器未保留原函数元数据。

1. 调整装饰器顺序

discord.py的@commands.command()装饰器必须最后应用(即放在最靠近函数定义的位置)。它的作用是将函数注册为机器人命令,如果先使用它再用自定义装饰器,机器人只会注册未被包装的原函数,包装后的逻辑不会被关联到命令上,自然无法被识别。

修正后的命令装饰顺序:

@command_author_check()
@commands.command()
async def test(self, ctx):
    await ctx.send("ПОЛУЧИЛОСЬ")

2. 保留原函数元数据

自定义装饰器的wrapper函数会覆盖原函数的名称等元数据,而discord.py依赖这些元数据确定命令名称。需要用functools.wraps装饰wrapper,把原函数的元数据复制过来,确保机器人能正确识别命令名。

修正后的装饰器代码:

from functools import wraps
from main import db
from scr.cfg import phrases
from scr import phrases_func


def command_author_check(permissions_level: int = 1):
    print("command_author_check")

    def decorator(func):
        print("decorator")
        
        @wraps(func)  # 保留原函数元数据,确保命令名正确识别
        async def wrapper(ctx, *args, **kwargs):
            print("wrapper")
            auth = ctx.message.author
            if db.check_user(auth):
                if db.get_user(auth).permissions_level >= permissions_level:
                    return await func(ctx, *args, **kwargs)
                else:
                    await auth.send(ctx.message.author.mention + phrases.slaves_greeting + phrases_func.dict_to_str(phrases.slaves_commands))
            else:
                await auth.send(ctx.message.author.mention + phrases.general_greeting + phrases_func.dict_to_str(phrases.slaves_commands))
        return wrapper
    return decorator

完成以上两处修改后,test命令就能被机器人正常识别并执行了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 18:57:23