Discord.py中如何避免误判消息未收到回复的问题?
解决Discord Bot无法识别Reply回复的问题
问题根源
原is_response_received函数的逻辑方向错误:它检查的是Bot发送的原消息自身是否带有reference或反应,但用户通过Discord Reply功能回复时,是用户的回复消息的reference指向原消息,原消息本身不会有reference字段,因此函数无法识别这类回复。
解决方案
需要调整逻辑,从「检查原消息的属性」改为「跟踪原消息ID,检测是否有消息的reference指向它」,同时保留反应检测逻辑。以下是具体实现步骤:
1. 维护待检测消息的跟踪集合
存储Bot发送的、需要等待回复的消息关键信息(消息ID、所在频道ID、发送时间),推荐用字典存储:
import asyncio from datetime import datetime import discord # 全局字典:key=消息ID,value=(频道ID, 发送时间) pending_messages = {}
2. 发送消息时记录跟踪信息
当Bot发送需要等待回复的消息时,将其信息加入跟踪字典:
async def send_tracked_message(channel, content): sent_msg = await channel.send(content) pending_messages[sent_msg.id] = (sent_msg.channel.id, datetime.now()) return sent_msg
3. 实时监听回复消息
通过on_message事件监听所有消息,一旦发现有回复指向跟踪中的消息,立即将其从跟踪集合中移除:
@bot.event async def on_message(message): # 跳过Bot自身消息 if message.author.bot: await bot.process_commands(message) return # 检查当前消息是否是回复,且回复的是跟踪中的消息 if message.reference and message.reference.message_id in pending_messages: del pending_messages[message.reference.message_id] await bot.process_commands(message)
4. 定时检查未回复消息
创建定时任务,定期检查跟踪集合中的消息,超过设定时间未收到回复则发送提示:
async def check_unreplied_messages(): await bot.wait_until_ready() # 每60秒检查一次 while not bot.is_closed(): current_time = datetime.now() # 遍历副本避免删除时引发异常 for msg_id, (channel_id, send_time) in list(pending_messages.items()): # 此处设置超时时间,示例为1小时(3600秒) if (current_time - send_time).total_seconds() > 3600: channel = bot.get_channel(channel_id) if channel: # 获取原消息的跳转链接 original_msg = await channel.fetch_message(msg_id) await channel.send(f"您错过消息:{original_msg.jump_url}") # 无论是否发送成功,都移除跟踪 del pending_messages[msg_id] await asyncio.sleep(60) # 启动定时任务 bot.loop.create_task(check_unreplied_messages())
5. 保留反应检测逻辑
如果需要保留「用户添加反应即视为已读」的逻辑,可以在定时检查中补充:
# 在check_unreplied_messages的循环内 original_msg = await channel.fetch_message(msg_id) if len(original_msg.reactions) > 0: del pending_messages[msg_id] continue
替代优化方案
如果你的Bot只在特定频道内运行,可以缩小消息历史的查询范围,避免遍历所有频道:
# 针对特定频道的回复检查(替代on_message监听) async def has_replies(channel, original_msg_id): async for msg in channel.history(limit=200): # 只查最近200条消息 if msg.reference and msg.reference.message_id == original_msg_id: return True return False
内容的提问来源于stack exchange,提问作者nullclarity
相关产品推荐
相关产品推荐

