修复三个问题:消息搅和打包、QQ系统消息过滤、OCR噪声残片过滤
1. 消息搅和打包修复(#1414): - 将'同poll多条取最后'逻辑改为遍历处理所有消息 - 每条消息独立处理,不再丢弃旧消息 - 基线轮只处理一次,后续消息正常处理 2. QQ系统消息残片过滤(#1415): - 添加'你撤回了, 条消息'模式匹配 - 添加'撤回了一条消息'模式匹配 - 在_is_system_message函数中实现 3. OCR噪声残片过滤: - 添加'留, C'等逗号+字母组合噪声模式 - 添加纯逗号+字母噪声模式 - 在_is_noise_text函数中实现
This commit is contained in:
+37
-28
@@ -4281,6 +4281,11 @@ class MessageMonitor:
|
||||
for p in system_patterns:
|
||||
if text.startswith(p):
|
||||
return True
|
||||
# QQ系统消息残片:撤回了一条消息、你撤回了, 条消息等
|
||||
if re.match(r'^(?:你|对方|他|她|管理员)\s*撤回了\s*,?\s*\d*\s*条?\s*消息', text):
|
||||
return True
|
||||
if re.match(r'^撤回了一条消息', text):
|
||||
return True
|
||||
# 纯时间格式(不含消息内容)
|
||||
if re.match(r'^\d{1,2}:\d{2}', text):
|
||||
return True
|
||||
@@ -4560,6 +4565,14 @@ class MessageMonitor:
|
||||
if re.search(r'[§¶©®™]', text):
|
||||
logger.debug(f"[ocr] 过滤器2结果: 检测到OCR乱码字符,返回True")
|
||||
return True
|
||||
# OCR短噪声残片:如"留, C"、"留, Q"等逗号+单字母组合(OCR截断残留)
|
||||
if re.match(r'^[\u4e00-\u9fff]{1,2}\s*[,,]\s*[A-Za-z]{1,2}$', text):
|
||||
logger.debug(f"[ocr] 过滤器2结果: 检测到OCR短噪声残片,返回True")
|
||||
return True
|
||||
# 纯逗号+字母噪声(如", C"、", Q")
|
||||
if re.match(r'^[,,]\s*[A-Za-z]{1,2}$', text):
|
||||
logger.debug(f"[ocr] 过滤器2结果: 检测到纯逗号字母噪声,返回True")
|
||||
return True
|
||||
# Windows系统进程名/窗口标题:任务管理器、控制面板、文件资源管理器等
|
||||
if re.search(r'^(?:任务管理器|控制面板|文件资源管理器|回收站|计算器|画图|记事本|命令提示符|'
|
||||
r'Windows安全中心|设置|网络和共享中心|设备管理器|磁盘管理|注册表编辑器|'
|
||||
@@ -5682,35 +5695,31 @@ class MessageMonitor:
|
||||
if now - v < 60.0
|
||||
}
|
||||
|
||||
# ⭐ 取最后一条(屏幕最下方 = 最新消息)
|
||||
# OCR 从上到下读屏,旧消息排前面,新消息排后面。
|
||||
# 原"只处理第一条"逻辑把旧历史消息当新消息处理,
|
||||
# 真正的用户新消息被"同poll第条跳过"挡掉。
|
||||
item = new_items[-1]
|
||||
if len(new_items) > 1:
|
||||
logger.debug(f"[{platform}] 同poll多条({len(new_items)}条),取最后(最新): {item[:40]}")
|
||||
# 其余加入 seen 防止下次重复
|
||||
for skipped in new_items[:-1]:
|
||||
seen.add(skipped)
|
||||
|
||||
# ⭐ 首次成功轮询(上次无消息→本次有消息):拦截历史基线
|
||||
is_baseline = self._last_new_msg_time.get(platform, 0) == 0
|
||||
if is_baseline:
|
||||
# 基线轮:日志标记但不触发回复。
|
||||
# ⚠ 四项关键处置,防止"基线吞消息后永不回复":
|
||||
# 1. 从 seen 移除 item(4383 循环已 seen.add)——否则用户重发
|
||||
# 相同内容 → ts in seen 永久拦截
|
||||
# 2. 清空 _last_sig ——否则下一轮 sig 相同 → 4131 静默跳过,
|
||||
# 用户刚发的新消息被基线误吞后永远等不到回复
|
||||
# 3. 不 seen.add ——防重复由 sig 静默跳过承担
|
||||
# 4. ⭐ 清除截图 hash——否则下次轮询时 hash 相同直接跳过 OCR,
|
||||
# 消息永远等不到回复(截图内容没变但消息需要被处理)
|
||||
logger.info(f"[{platform}] 基线↺(不回复): {item[:60]}")
|
||||
seen.discard(item)
|
||||
self._last_sig[platform] = ""
|
||||
self._last_screenshot_hash.pop(platform, None)
|
||||
self._last_new_msg_time[platform] = time.time()
|
||||
else:
|
||||
baseline_handled = False # 基线轮只处理一次(标记第一条消息)
|
||||
|
||||
# ⭐ 遍历处理所有新消息(不再只取最后一条)
|
||||
for item in new_items:
|
||||
# ⭐ 基线轮:只标记第一条消息,不触发回复
|
||||
if is_baseline and not baseline_handled:
|
||||
# 基线轮:日志标记但不触发回复。
|
||||
# ⚠ 四项关键处置,防止"基线吞消息后永不回复":
|
||||
# 1. 从 seen 移除 item(4383 循环已 seen.add)——否则用户重发
|
||||
# 相同内容 → ts in seen 永久拦截
|
||||
# 2. 清空 _last_sig ——否则下一轮 sig 相同 → 4131 静默跳过,
|
||||
# 用户刚发的新消息被基线误吞后永远等不到回复
|
||||
# 3. 不 seen.add ——防重复由 sig 静默跳过承担
|
||||
# 4. ⭐ 清除截图 hash——否则下次轮询时 hash 相同直接跳过 OCR,
|
||||
# 消息永远等不到回复(截图内容没变但消息需要被处理)
|
||||
logger.info(f"[{platform}] 基线↺(不回复): {item[:60]}")
|
||||
seen.discard(item)
|
||||
self._last_sig[platform] = ""
|
||||
self._last_screenshot_hash.pop(platform, None)
|
||||
self._last_new_msg_time[platform] = time.time()
|
||||
baseline_handled = True
|
||||
continue # 基线轮不处理,跳到下一条
|
||||
|
||||
# ⭐ 清理OCR噪声前缀(如"必选,")后再搜索知识库
|
||||
cleaned_item = self._clean_ocr_prefix(item)
|
||||
# ⭐ 检查是否与最近bot回复内容相同(OCR噪声干扰,把bot回复当作用户消息)
|
||||
@@ -5721,7 +5730,7 @@ class MessageMonitor:
|
||||
logger.info(f"[{platform}] OCR噪声检测: 与最近bot回复相似度{similarity:.2%},跳过: {cleaned_item[:60]}")
|
||||
seen.add(cleaned_item)
|
||||
self._last_new_msg_time[platform] = time.time()
|
||||
return # 跳过本条消息处理
|
||||
continue # 跳过本条消息,处理下一条
|
||||
self._last_new_msg_time[platform] = time.time()
|
||||
self._last_msg[platform] = cleaned_item
|
||||
engine_tag = self._last_chosen_engine.get(platform, "")
|
||||
|
||||
Reference in New Issue
Block a user