修复OCR截历史消息自言自语: 变形命令过滤 + 首次轮询基线\n\n问题: OCR阅读历史帮助文档触发错误回复 + 首次启动时历史消息全部触发回复\n\nFix1: OCR误读斜线为字母(4处过滤)\n /sdfl→Isdfl /import→Jimport 均不被^/[A-Za-z]拦截\n - OCR级+Poll级: 含sdfl关键词的行以字母开头→变形命令跳过\n - OCR级+Poll级: 大写字母+4+小写+含CJK+>10字符→变形命令跳过\n 覆盖Isdfl update更新插件、Jimport导入cdk等所有OCR变形命令行\n\nFix2: 首次成功轮询基线拦截\n 检测_last_new_msg_time[platform]==0判断是否首次见消息\n 首次消息列表全部标记基线→加_seen_messages但skip_on_message\n 不触发KB搜索/自动回复\n 下一轮有真正的增量消息才触发回复

This commit is contained in:
youpaishidifu
2026-07-29 21:23:32 +08:00
parent d72d994db1
commit fae6d5184f
+29
View File
@@ -1704,6 +1704,16 @@ class MessageMonitor:
logger.debug(f"[{platform}] OCR 过滤: 斜线英文命令 line={line!r}")
continue
# —— OCR 误读斜线为 I/J:"/sdfl"→"Isdfl", "/import"→"Jimport" ——
# 特征1:含已知命令关键词(sdfl/sdf1),零误杀
if re.match(r'^[A-Za-z]', line) and ('sdfl' in line.lower() or 'sdf1' in line.lower()):
logger.debug(f"[{platform}] OCR 过滤: 变形命令(sdfl) line={line!r}")
continue
# 特征2:大写字母+4+小写 + CJK + >10 字符 → 非自然对话
if re.match(r'^[A-Z][a-z]{4,}', line) and re.search(r'[\u4e00-\u9fff]', line) and len(line) > 10:
logger.debug(f"[{platform}] OCR 过滤: 变形命令(大写+字母) line={line!r}")
continue
# —— JSON/YAML 碎片兜底:OCR 截屏混入配置面板 ——
# 行首是 "key": value 或 key: value(YAML)→ 配置面板碎片
if re.match(r'^["\']?[a-zA-Z_][\w]*["\']?\s*:\s*["\d\[\{tfn]', line):
@@ -3392,6 +3402,13 @@ class MessageMonitor:
if re.match(r'^/[A-Za-z]', ts):
logger.debug(f"[{platform}] Poll过滤: 斜线英文命令 ts={ts!r}")
continue
# === OCR 误读斜线为 I/J:"/sdfl"→"Isdfl", "/import"→"Jimport" ===
if re.match(r'^[A-Za-z]', ts) and ('sdfl' in ts.lower() or 'sdf1' in ts.lower()):
logger.debug(f"[{platform}] Poll过滤: 变形命令(sdfl) ts={ts!r}")
continue
if re.match(r'^[A-Z][a-z]{4,}', ts) and re.search(r'[\u4e00-\u9fff]', ts) and len(ts) > 10:
logger.debug(f"[{platform}] Poll过滤: 变形命令(大写+字母) ts={ts!r}")
continue
# === 结构化数据面板:QQ/TIM 指令面板(指令:/rtp 权限类型:玩家 图标:标题:)===
colon_kv = re.findall(r'[\u4e00-\u9fff]{1,6}[::](?:[A-Za-z0-9/]|[\u4e00-\u9fff])', ts)
if len(colon_kv) >= 3:
@@ -3535,11 +3552,23 @@ class MessageMonitor:
# 有纯粹的新文本 → 逐一报告(同平台同一 poll 内只处理第一条)
first = True
# ⭐ 首次成功轮询(上次无消息→本次有消息):拦截历史基线
is_baseline = self._last_new_msg_time.get(platform, 0) == 0
if is_baseline:
logger.info(f"[{platform}] 首次消息→基线拦截({len(new_items)}条): {new_items[0][:60]}")
for item in new_items:
if not first:
logger.debug(f"[{platform}] 同poll第条,跳过防多发: {item[:40]}")
continue
first = False # 只处理第一条
if is_baseline:
# 基线轮:日志标记但不触发回复,添加到 seen 防止下次再来
logger.info(f"[{platform}] 基线↺(不回复): {item[:60]}")
seen.add(item)
self._last_new_msg_time[platform] = time.time()
continue
self._last_new_msg_time[platform] = time.time()
self._last_msg[platform] = item
engine_tag = self._last_chosen_engine.get(platform, "")