discord.py实现石头剪刀布指令时机器人不响应表情反应的问题
discord.py 反应事件无响应排查与石头剪刀布功能修复
核心问题排查点
- 事件未正确注册:
on_reaction_add是discord.py的内置事件回调,必须通过客户端/机器人实例的事件装饰器(如@bot.event)绑定,否则机器人不会识别该函数为事件处理逻辑,完全不会触发。 - Intent权限未开启:discord.py 2.x+ 版本默认限制事件接收范围,必须手动在客户端初始化时开启
reactions、guilds等相关intent,否则无法收到服务器的反应事件推送。 - 反应对象判断逻辑错误:
on_reaction_add传入的reaction参数是discord.Reaction类实例,不是字符串,直接和emoji字符串对比永远为假,需要读取reaction.emoji属性匹配对应表情。 - 未定义变量引用:代码中直接使用
message变量,但on_reaction_add函数作用域内没有该变量,需从reaction.message获取反应所在的消息对象。 - 拼写错误:
message.chanel存在拼写错误,正确的通道属性为channel,错误拼写会直接抛出属性不存在的异常。 - 随机逻辑不合理:
rpsai被定义为全局变量,仅在程序启动时随机生成1次,后续所有游戏局都会复用同一个随机值,不会随每局游戏重置。 - 未过滤机器人自身反应:未排除
user为机器人的情况,机器人自身添加的表情反应也会触发事件,导致逻辑误触发。
修复后可运行的示例代码
from random import randint import discord from discord.ext import commands # 初始化客户端,开启所需intent intents = discord.Intents.default() intents.reactions = True # 开启反应事件监听 intents.messages = True intents.guilds = True bot = commands.Bot(command_prefix="!", intents=intents) # 石头剪刀布选项映射:1=石头,2=布,3=剪刀 rps_map = { 1: "石头", 2: "布", 3: "剪刀" } rpsai = None @bot.event async def on_ready(): print(f"机器人已登录:{bot.user}") # 新增石头剪刀布发起指令,方便测试 @bot.command(name="rps") async def start_rps(ctx): global rpsai # 每局游戏单独生成随机AI选项,不复用启动时的初始值 rpsai = randint(1,3) msg = await ctx.send("请添加表情选择你的出拳:🧱=石头,📄=布,✂️=剪刀") # 给消息预设三个可选表情 await msg.add_reaction("🧱") await msg.add_reaction("📄") await msg.add_reaction("✂️") @bot.event async def on_reaction_add(reaction, user): # 过滤机器人自身的反应,避免逻辑误触发 if user.bot: return # 仅响应当前机器人发送的游戏消息的反应 if reaction.message.author != bot.user: return # 判断用户添加的表情是否为游戏指定的石头表情 if reaction.emoji == "🧱": ai_choice = rpsai channel = reaction.message.channel if ai_choice == 1: await channel.send(f"我出{rps_map[ai_choice]},平局!") elif ai_choice == 2: await channel.send(f"我出{rps_map[ai_choice]},我赢了!") elif ai_choice == 3: await channel.send(f"我出{rps_map[ai_choice]},你赢了!") # 可自行补充📄、✂️对应的判断逻辑 # 运行机器人,替换为你自己的机器人Token bot.run("你的机器人Token")
额外注意事项
- 若使用discord.py 2.x以上版本,需在Discord开发者后台的机器人设置页面,开启对应特权Intent权限,否则部分事件无法正常接收。
- 若需要监听历史消息的反应事件,需确保机器人对对应服务器、目标消息有读取权限。
- 全局
rpsai变量建议替换为局内存储(如用消息ID绑定对应AI选项),避免多用户同时发起游戏时逻辑混乱。
内容的提问来源于stack exchange,提问作者Minecow 12345
相关产品推荐
相关产品推荐

