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

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))

另外补充两个小细节:

  1. 代码里新增了emojis变量的定义,对应你要添加的反应表情,避免出现变量未定义的错误
  2. 原来的ctx.send在on_reaction_add里无法使用,因为这个事件不会传递ctx,所以改用reaction.message.channel.send来发送消息,同时通过user.mention@触发反应的用户,提升交互体验

内容的提问来源于stack exchange,提问作者simon sjöö

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 09:37:45