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

