Discord.py机器人用户表情反应无法触发角色分配问题排查
问题原因
代码卡在wait_for没有任何输出,核心是两个错误导致的,没有抛出异常是因为wait_for会持续等待符合校验规则的事件,你写的校验规则永远不可能成立,所以程序会一直阻塞在等待阶段,不会执行后续代码。
错误1:wait_for的校验lambda逻辑完全错误
你写的校验逻辑:
lambda reaction, user: user == reaction.message.id == msg.id
链式比较a == b == c的实际执行逻辑是a == b and b == c,这里存在两个常识错误:
reaction_add事件返回的第二个参数user是触发反应的成员对象,reaction.message.id是整数类型的消息ID,两者类型完全不同,相等判断永远返回False- 你需要校验的是「反应是加在你刚发送的那条embed消息上」,而不是把用户对象和消息ID做比较
正确的校验逻辑需要同时满足三个条件: - 反应对应的消息是你发送的embed消息:
reaction.message.id == msg.id - 触发反应的不是机器人自身,避免机器人自己加预设反应的时候误触发逻辑:
not user.bot - 反应的表情在你预设的表情列表里,过滤无关表情
错误2:添加角色的API调用方式完全错误
就算你修复了校验逻辑,后面的加角色代码也会直接报错:
add_roles是discord.Member对象的实例方法,既不是bot对象的方法,也不是ctx上下文对象的方法- 你之前的写法
await bot.add_roles(CSGO)、await ctx.add_roles(WF)全是错的,调用这个方法需要指定给哪个用户加什么角色,参数应该是角色对象,调用方是要加角色的成员对象。
修正后可运行代码
desc1 = ("React with the corresponding emoji to game specific channels you want\n" "\n👍 - Counter Strike\n" "😀 - Warframe\n" "🤓 - Lost Ark\n" "😆 - Chiller\n" "💪 - Warhammer") @bot.command() async def embed(ctx: commands.Context): embed = discord.Embed(title="Create Your Profile", description=desc1) embed.set_footer(text="Jammys Bot") msg = await ctx.send(embed=embed) # 预设表情和对应角色ID的映射表,省略冗余的if判断 role_config = { '👍': 780182144747569193, '😀': 780244861130768395, '🤓': 947231964753170473, '😆': 896853904384458772, '💪': 896882687816630293 } # 批量添加预设反应 for emoji in role_config.keys(): await msg.add_reaction(emoji) while True: # 修正wait_for校验逻辑 reaction, user = await bot.wait_for( "reaction_add", check=lambda reaction, user: reaction.message.id == msg.id and not user.bot and str(reaction.emoji) in role_config ) # 获取对应角色 target_role = ctx.guild.get_role(role_config[str(reaction.emoji)]) if target_role: # 正确调用加角色方法:给触发反应的用户添加对应角色 await user.add_roles(target_role)
补充说明:如果你使用discord.py 2.0及以上版本,需要在机器人开发者后台开启Presence Intent、Server Members Intent、Message Content Intent,同时在代码初始化bot的时候声明开启对应intents,否则会收不到反应事件。另外命令里写死无限while循环的写法在多人同时调用命令时会出现阻塞,个人小体量服务器使用足够,生产环境建议替换为全局
on_reaction_add事件监听实现。
内容的提问来源于stack exchange,提问作者JammyShaw
相关产品推荐
相关产品推荐

