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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 08:24:53