fix: 修复OCR捕捉含年月日消息导致后续消息丢失的问题 (Task #1652/#1653)
问题:当上面一条消息有年月日时,下面的消息会丢失目标定位,需通过表情包/图片才能重新加入消息队列 根因:_ocr_text_has_fresh_timestamp对整个文本块检查,任何部分含历史日期都会导致整段文本被丢弃 修复: 1. 新增_strip_historical_date_lines辅助方法,按行分割文本并智能剥离历史日期行 2. 修改_process_ocr_output中的时间戳新鲜性检查逻辑 3. 当检测到历史日期时,先尝试剥离旧消息行,保留新鲜消息继续处理 4. 仅含日期无时间的表格日期:剥离日期但保留行内容 5. 含日期+时间的历史消息行:完全剥离 6. 无日期的行:完整保留
This commit is contained in:
+67
-12
@@ -3773,10 +3773,24 @@ class MessageMonitor:
|
||||
if not raw_text:
|
||||
return []
|
||||
if not self._ocr_text_has_fresh_timestamp(raw_text, platform):
|
||||
# ⭐ 2026-08-24 新逻辑:_ocr_text_has_fresh_timestamp 返回 False 表示
|
||||
# 检测到清晰年月日(历史消息),应丢弃整段文本
|
||||
logger.debug(f"[{platform}] OCR 有清晰年月日(历史消息),丢弃整段: {raw_text[:80]!r}")
|
||||
return []
|
||||
# ⭐ 2026-08-30 Task #1652 修复:尝试剥离历史日期行,保留新鲜消息
|
||||
# 根因:_ocr_text_has_fresh_timestamp 对整个文本块检查,任何部分含历史日期都会
|
||||
# 导致整段文本被丢弃,即使其中包含新鲜消息(如"2026/8/30 23:29:35"下方的新查询)
|
||||
# 解决:按行分割,剥离含日期+时间的行(历史消息),保留无日期或仅含表格日期的行
|
||||
logger.debug(f"[{platform}] OCR 时间戳新鲜性检查失败,尝试剥离历史日期行...")
|
||||
salvaged_text = self._strip_historical_date_lines(raw_text, platform)
|
||||
if not salvaged_text:
|
||||
logger.debug(f"[{platform}] 剥离历史日期行后无剩余文本,丢弃整段: {raw_text[:80]!r}")
|
||||
return []
|
||||
|
||||
# 对剥离后的文本重新检查新鲜性
|
||||
if not self._ocr_text_has_fresh_timestamp(salvaged_text, platform):
|
||||
logger.debug(f"[{platform}] 剥离历史日期行后仍无新鲜消息,丢弃: {salvaged_text[:80]!r}")
|
||||
return []
|
||||
|
||||
# 使用剥离后的文本继续处理
|
||||
logger.debug(f"[{platform}] 剥离历史日期行后有新鲜消息,继续处理: {salvaged_text[:80]!r}")
|
||||
raw_text = salvaged_text
|
||||
|
||||
# —— 行切割 + 尾标清理 ——
|
||||
ocr_lines = []
|
||||
@@ -6994,9 +7008,10 @@ class MessageMonitor:
|
||||
# 纯英文/数字/符号,可能是UI噪声,丢弃
|
||||
logger.debug(f"[ocr] 过滤器1结果: 无时间戳且无中文字符,丢弃: {stripped[:80]!r}")
|
||||
return False
|
||||
# 用户消息挨着bot消息判断:最近一次bot回复在60秒内(放宽窗口)
|
||||
last_bot_time = self._msg_history.last_bot_reply_time(platform)
|
||||
if last_bot_time > 0 and time.time() - last_bot_time <= 60:
|
||||
|
||||
# 用户消息挨着bot消息判断:最近一次bot回复在60秒内(放宽窗口)
|
||||
last_bot_time = self._msg_history.last_bot_reply_time(platform)
|
||||
if last_bot_time > 0 and time.time() - last_bot_time <= 60:
|
||||
# 用户消息挨着bot消息
|
||||
if not self._msg_history.is_user_message_replied(platform, stripped, time.time()):
|
||||
# 数据库无记录,无条件放行
|
||||
@@ -7006,11 +7021,11 @@ class MessageMonitor:
|
||||
# 数据库有记录,整段丢弃
|
||||
logger.debug(f"[ocr] 过滤器1结果: 无时间戳且用户消息挨着bot消息但有记录,丢弃: {stripped[:80]!r}")
|
||||
return False
|
||||
# ⭐ 无时间戳消息:放行交给DB查重处理(避免连续聊天时时间戳被覆盖误杀用户消息)
|
||||
# 无论消息长短,只要包含中文字符且非噪声,都放行
|
||||
# DB查重会自动过滤掉已经回复过的消息
|
||||
logger.info(f"[ocr] 过滤器1结果: 无时间戳但为中文消息,交由DB查重: {stripped[:80]!r}")
|
||||
return True
|
||||
# ⭐ 无时间戳消息:放行交给DB查重处理(避免连续聊天时时间戳被覆盖误杀用户消息)
|
||||
# 无论消息长短,只要包含中文字符且非噪声,都放行
|
||||
# DB查重会自动过滤掉已经回复过的消息
|
||||
logger.info(f"[ocr] 过滤器1结果: 无时间戳但为中文消息,交由DB查重: {stripped[:80]!r}")
|
||||
return True
|
||||
# 有新鲜时间戳 → 确定有新消息
|
||||
for ts in timestamps:
|
||||
try:
|
||||
@@ -7034,6 +7049,46 @@ class MessageMonitor:
|
||||
logger.debug(f"[ocr] 过滤器1结果: 无新鲜时间戳(全部>300s){_age_info},丢弃: {text[:80]!r}")
|
||||
return False
|
||||
|
||||
def _strip_historical_date_lines(self, text: str, platform: str = "unknown") -> str:
|
||||
"""剥离含历史日期的行,保留可能的新鲜消息。
|
||||
|
||||
当 _ocr_text_has_fresh_timestamp 返回 False 时调用,尝试按行分割文本,
|
||||
识别并剥离含过去日期(年月日+时分)的行,保留其余部分。
|
||||
|
||||
返回剥离后的文本;若无剩余内容则返回空字符串。
|
||||
"""
|
||||
if not text:
|
||||
return ""
|
||||
|
||||
lines = text.split('\n')
|
||||
salvaged = []
|
||||
for line in lines:
|
||||
# 检查行是否包含日期模式
|
||||
date_pattern = r'\d{4}[/-]\d{1,2}[/-]\d{1,2}|\d{4}年\d{1,2}月\d{1,2}日'
|
||||
if re.search(date_pattern, line):
|
||||
# 检查日期是否附带时间(年月日+时分 = 真消息)
|
||||
time_pattern = r'(\d{4}[/-]\d{1,2}[/-]\d{1,2}|\d{4}年\d{1,2}月\d{1,2}日)\s*\d{1,2}:\d{1,2}'
|
||||
if re.search(time_pattern, line):
|
||||
# 含日期+时间 = 历史消息行,剥离
|
||||
logger.debug(f"[{platform}] 剥离含过去日期+时间行: {line[:60]!r}")
|
||||
continue
|
||||
else:
|
||||
# 仅有日期无时间 = 表格日期,剥离日期但保留行其余部分
|
||||
cleaned = re.sub(date_pattern, '', line).strip()
|
||||
if cleaned:
|
||||
logger.debug(f"[{platform}] 剥离表格日期后保留: {cleaned[:60]!r}")
|
||||
salvaged.append(cleaned)
|
||||
else:
|
||||
logger.debug(f"[{platform}] 表格日期行为空,丢弃: {line[:60]!r}")
|
||||
continue
|
||||
# 无日期模式,保留整行
|
||||
salvaged.append(line)
|
||||
|
||||
if not salvaged:
|
||||
return ""
|
||||
|
||||
return '\n'.join(salvaged)
|
||||
|
||||
# 未来时间戳容忍偏差(秒):同日内时间戳比系统时间晚超过此值 = 未到来,直接丢弃。
|
||||
# 容忍偏差与 max_age 持平(300s):OCR/聊天服务器时钟与系统时钟存在秒级差异,
|
||||
# 刚到的消息时间戳可能比系统时间晚几秒(如 14:41:00 消息在 14:40:58 被捕获),
|
||||
|
||||
Reference in New Issue
Block a user