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

Discord.py 继承类中自定义命令无法运行问题求助

问题分析与修复方案

你的!info命令无法响应,主要存在两个关键问题:

1. on_raw_reaction_add方法中的错误

在on_raw_reaction_add里,你使用了self.client.get_guild(payload.guild_id),但self.client并不存在——你的MyClient类直接继承自commands.Bot,自身就拥有get_guild方法,这个错误会引发AttributeError,导致Bot运行异常,进而无法处理命令。

2. 命令注册时机不当

你在__init__方法中调用add_my_commands()注册命令,但此时Bot的初始化流程尚未完成,装饰器可能无法正确将命令注册到Bot实例中。


修复步骤

步骤1:修复on_raw_reaction_add的错误

将guild = self.client.get_guild(payload.guild_id)改为:

guild = self.get_guild(payload.guild_id)

步骤2:调整命令注册方式

推荐两种方式来正确注册命令:

方式一:手动添加命令(替代装饰器)

修改add_my_commands方法,直接使用self.add_command()手动注册,避免装饰器嵌套的问题:

def add_my_commands(self):
    async def info(ctx):
        """显示命令执行上下文信息"""
        await ctx.send("Hello X")
        await ctx.send(ctx.guild)
        await ctx.send(ctx.author)
        await ctx.send(str(ctx.message.id))  # 转为字符串避免发送对象报错
    
    # 手动创建Command对象并添加到Bot
    self.add_command(commands.Command(info, name="info"))
方式二:延迟命令注册到on_ready事件

如果坚持使用装饰器,将add_my_commands()的调用从__init__移到on_ready中,确保Bot完全初始化后再注册命令:

async def on_ready(self):
    print("We have logged in as {0.user}".format(self))
    print("---------------------------------------------")
    self.add_my_commands()  # 初始化完成后注册命令

同时保留原来的add_my_commands装饰器写法,但移除过时的pass_context=True参数(discord.py v1.0+已自动传递上下文):

def add_my_commands(self):
    @self.command(name="info")
    async def info(ctx):
        """显示命令执行上下文信息"""
        await ctx.send("Hello X")
        await ctx.send(ctx.guild)
        await ctx.send(ctx.author)
        await ctx.send(str(ctx.message.id))

步骤3:验证其他逻辑

确保on_message方法末尾的await self.process_commands(message)存在,这是Bot处理命令的必要步骤(你的代码中已经包含,无需修改)。


修改后的完整MyClient类示例

import discord
from discord.ext import commands

class MyClient(commands.Bot):
    def __init__(self, *args, command_prefix, **kwargs):
        super().__init__(
            *args, command_prefix=command_prefix, case_insensitive=True, **kwargs
        )
        self.target_message_id = XXXX
        # 这里不再调用add_my_commands(),移到on_ready中

    async def on_ready(self):
        print("We have logged in as {0.user}".format(self))
        print("---------------------------------------------")
        self.add_my_commands()  # 初始化完成后注册命令

    async def on_member_remove(self, member):
        channel = self.get_channel(XXXX)
        await channel.send("Goodbye")

    async def on_raw_reaction_add(self, payload):
        """根据表情反应分配角色"""
        if payload.message_id != self.target_message_id:
            return

        guild = self.get_guild(payload.guild_id)  # 修复此处的self.client错误
        if not guild:
            return
        
        print(payload.emoji.name)
        print("Hello")

    async def on_message(self, message):
        if message.author == self.user:
            return

        if message.content == "Test":
            await message.channel.send("Hey hey chill")

        if message.content == "cool":
            await message.add_reaction("\U0001F60E")

        if message.content == "give me our prefix":
            await message.channel.send(str(self.command_prefix))

        await self.process_commands(message)

    async def on_reaction_add(self, reaction, user):
        await reaction.message.channel.send(f"{user} reacted with {reaction.emoji}")

    def add_my_commands(self):
        @self.command(name="info")
        async def info(ctx):
            """显示命令执行上下文信息"""
            await ctx.send("Hello X")
            await ctx.send(ctx.guild)
            await ctx.send(ctx.author)
            await ctx.send(str(ctx.message.id))  # 转为字符串发送

完成以上修改后,重启Bot,!info命令应该就能正常响应并输出预期信息了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 01:25:37