如何解决Discord.py机器人因用户反应重复发送消息的问题?
问题分析与解决方案
你的机器人重复发送消息的核心原因是:每次收到用户消息时都会启动一个独立的wait_for('reaction_add')监听,而这些监听的判断条件没有限定对应消息。当用户对某条消息添加反应时,所有正在等待的wait_for都会触发,导致多次发送结果Embed。
另外代码里还有几个细节问题会引发异常或逻辑错误,一起修复:
修复步骤
限定反应对应的目标消息
在check函数中添加判断,确保只响应刚才机器人添加反应的那条消息的反应,避免所有等待中的监听同时触发。修正频道ID类型
bot.get_channel()需要传入整数类型的频道ID,不能是字符串,否则会获取不到频道。避免变量名冲突
历史消息列表推导式里的变量名不要和on_message的参数message重名,否则会覆盖外部变量。规范异步调用写法
add_reaction是异步方法,需要正确await,不要直接把协程对象赋值后再await。
修复后的代码
import asyncio import random import discord @bot.listen('on_message') async def on_message(message): if message.author == bot.user: return # 频道ID改为整数 channel = bot.get_channel(CHANNEL_ID) # 替换成你的数字ID if not channel: return # 防止获取不到频道引发后续错误 # 变量名改为msg,避免和外部message冲突 messages = [msg async for msg in channel.history(limit=15)] if len(messages) < 1: return # 确保有消息可选择 await asyncio.sleep(random.randint(0, 3)) # 随机选一条消息并添加反应 target_msg = messages[random.randint(0, len(messages)-1)] await target_msg.add_reaction("\N{Snowman}") def check(reaction, user): # 限定反应的消息是刚才添加反应的那条,同时判断表情和用户 return (str(reaction.emoji) == '\N{Snowman}' and user != bot.user and reaction.message == target_msg) try: reaction, user = await bot.wait_for('reaction_add', timeout=30, check=check) embed = discord.Embed(description=f'{user.mention} 抢到雪人啦!', color=discord.Color.random()) await channel.send(embed=embed) except asyncio.TimeoutError: pass
额外说明
- 新增了
if not channel:和if len(messages) <1:的判断,避免因为频道不存在或频道无消息导致的运行时错误。 - 随机选消息时用
len(messages)-1代替固定的14,防止频道历史消息不足15条时引发索引越界异常。
内容的提问来源于stack exchange,提问作者Chex Rex
相关产品推荐
相关产品推荐

