Discord.py on_reaction_add()报错:缺少必填参数'user'求助
解决Discord.py中
on_reaction_add()的TypeError错误并理解user参数 错误根源
你碰到的TypeError: on_reaction_add() missing 1 required positional argument: 'user'问题,本质是事件监听器的参数签名不符合Discord.py的规范。
Discord.py的on_reaction_add事件回调函数的正确参数顺序是self, reaction, user,不需要额外的ctx参数。你在定义时多加了ctx,导致Discord.py调用这个函数时,只会传入reaction和user两个参数,而函数期望接收三个参数(self, ctx, reaction, user),自然就会报参数缺失的错误。
user参数的作用
user是Discord.py传递给这个事件的核心参数之一:
- 它代表添加该表情反应的用户对象,包含了这个用户的所有信息(比如ID、昵称、头像、所在服务器的权限等)
- 你可以通过它做很多判断:比如代码里的
if user.bot: return,就是用来忽略机器人自己的反应,避免机器人处理自身触发的反应导致逻辑混乱 - 还可以基于这个用户对象进行互动,比如给用户发送私信、检查用户权限等
修正后的代码
下面是修正了on_reaction_add部分的完整代码(重点看监听器的参数和消息发送的部分):
class Changelog(commands.Cog): def __init__(self, client): self.client = client @commands.Cog.listener() async def on_ready(self): print('Application is loaded') @commands.group(invoke_without_command=True) async def application(self, ctx): embed = discord.Embed(title="Application Commands", description="Channel: <#channel>", color=0) await ctx.send(embed=embed) @application.command() async def channel(self, ctx, channel: discord.TextChannel): if ctx.message.author.guild_permissions.administrator: db = sqlite3.connect('main.sqlite') cursor = db.cursor() cursor.execute( f'SELECT channel_id FROM application WHERE guild_id = {ctx.guild.id}') result = cursor.fetchone() if result is None: sql = ('INSERT INTO application(guild_id, channel_id) VALUES(?,?)') val = (ctx.guild.id, channel.id) await ctx.send(f'Message has been sent and channel has been set to {channel.mention}') elif result is not None: sql = ('UPDATE application SET channel_id = ? WHERE guild_id = ?') val = (channel.id, ctx.guild.id) await ctx.send(f'Message has been sent and channel has been updated to {channel.mention}') youtube = ':play_pause:' staff = ':envelope_with_arrow:' embed = discord.Embed(title="ReefCraft Applications", color=0) embed.add_field( name="** **", value=f"{youtube} YouTube Application\n\n{staff} Staff Application", inline=False) embed.add_field(name="\n\nInformation", value="Reacting to one of the emotes will create a new text-channel, where you will write your applicaiton!") reaction_message = await channel.send(embed=embed) # 提前定义emojis变量,对应你要添加的反应表情 emojis = ["⏯️", "📩"] for emoji in emojis: await reaction_message.add_reaction(emoji) cursor.execute(sql, val) db.commit() cursor.close() db.close() @commands.Cog.listener() async def on_reaction_add(self, reaction, user): # 移除了多余的ctx参数 emoji = reaction.emoji if user.bot: return # 改用reaction关联的频道发送消息,同时@触发反应的用户 if emoji == "\U0001F4E9": # 📩的Unicode编码 await reaction.message.channel.send(f"{user.mention} You clicked the Staff Application") elif emoji == "\U000023EF": # ⏯️的Unicode编码 await reaction.message.channel.send(f"{user.mention} You clicked the Youtube Application") else: return def setup(client): client.add_cog(Changelog(client))
另外补充两个小细节:
- 代码里新增了
emojis变量的定义,对应你要添加的反应表情,避免出现变量未定义的错误 - 原来的
ctx.send在on_reaction_add里无法使用,因为这个事件不会传递ctx,所以改用reaction.message.channel.send来发送消息,同时通过user.mention@触发反应的用户,提升交互体验
内容的提问来源于stack exchange,提问作者simon sjöö
相关产品推荐
相关产品推荐

