From fae6d5184fbee4132795346a41125555fc6e0910 Mon Sep 17 00:00:00 2001 From: youpaishidifu Date: Wed, 29 Jul 2026 21:23:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DOCR=E6=88=AA=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E6=B6=88=E6=81=AF=E8=87=AA=E8=A8=80=E8=87=AA=E8=AF=AD?= =?UTF-8?q?:=20=E5=8F=98=E5=BD=A2=E5=91=BD=E4=BB=A4=E8=BF=87=E6=BB=A4=20+?= =?UTF-8?q?=20=E9=A6=96=E6=AC=A1=E8=BD=AE=E8=AF=A2=E5=9F=BA=E7=BA=BF\n\n?= =?UTF-8?q?=E9=97=AE=E9=A2=98:=20OCR=E9=98=85=E8=AF=BB=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E5=B8=AE=E5=8A=A9=E6=96=87=E6=A1=A3=E8=A7=A6=E5=8F=91=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E5=9B=9E=E5=A4=8D=20+=20=E9=A6=96=E6=AC=A1=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E6=97=B6=E5=8E=86=E5=8F=B2=E6=B6=88=E6=81=AF=E5=85=A8?= =?UTF-8?q?=E9=83=A8=E8=A7=A6=E5=8F=91=E5=9B=9E=E5=A4=8D\n\nFix1:=20OCR?= =?UTF-8?q?=E8=AF=AF=E8=AF=BB=E6=96=9C=E7=BA=BF=E4=B8=BA=E5=AD=97=E6=AF=8D?= =?UTF-8?q?(4=E5=A4=84=E8=BF=87=E6=BB=A4)\n=20=20/sdfl=E2=86=92Isdfl=20/im?= =?UTF-8?q?port=E2=86=92Jimport=20=E5=9D=87=E4=B8=8D=E8=A2=AB^/[A-Za-z]?= =?UTF-8?q?=E6=8B=A6=E6=88=AA\n=20=20-=20OCR=E7=BA=A7+Poll=E7=BA=A7:=20?= =?UTF-8?q?=E5=90=ABsdfl=E5=85=B3=E9=94=AE=E8=AF=8D=E7=9A=84=E8=A1=8C?= =?UTF-8?q?=E4=BB=A5=E5=AD=97=E6=AF=8D=E5=BC=80=E5=A4=B4=E2=86=92=E5=8F=98?= =?UTF-8?q?=E5=BD=A2=E5=91=BD=E4=BB=A4=E8=B7=B3=E8=BF=87\n=20=20-=20OCR?= =?UTF-8?q?=E7=BA=A7+Poll=E7=BA=A7:=20=E5=A4=A7=E5=86=99=E5=AD=97=E6=AF=8D?= =?UTF-8?q?+4+=E5=B0=8F=E5=86=99+=E5=90=ABCJK+>10=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E2=86=92=E5=8F=98=E5=BD=A2=E5=91=BD=E4=BB=A4=E8=B7=B3=E8=BF=87?= =?UTF-8?q?\n=20=20=E8=A6=86=E7=9B=96Isdfl=20update=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E3=80=81Jimport=E5=AF=BC=E5=85=A5cdk?= =?UTF-8?q?=E7=AD=89=E6=89=80=E6=9C=89OCR=E5=8F=98=E5=BD=A2=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E8=A1=8C\n\nFix2:=20=E9=A6=96=E6=AC=A1=E6=88=90?= =?UTF-8?q?=E5=8A=9F=E8=BD=AE=E8=AF=A2=E5=9F=BA=E7=BA=BF=E6=8B=A6=E6=88=AA?= =?UTF-8?q?\n=20=20=E6=A3=80=E6=B5=8B=5Flast=5Fnew=5Fmsg=5Ftime[platform]?= =?UTF-8?q?=3D=3D0=E5=88=A4=E6=96=AD=E6=98=AF=E5=90=A6=E9=A6=96=E6=AC=A1?= =?UTF-8?q?=E8=A7=81=E6=B6=88=E6=81=AF\n=20=20=E9=A6=96=E6=AC=A1=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E5=88=97=E8=A1=A8=E5=85=A8=E9=83=A8=E6=A0=87=E8=AE=B0?= =?UTF-8?q?=E5=9F=BA=E7=BA=BF=E2=86=92=E5=8A=A0=5Fseen=5Fmessages=E4=BD=86?= =?UTF-8?q?skip=5Fon=5Fmessage\n=20=20=E4=B8=8D=E8=A7=A6=E5=8F=91KB?= =?UTF-8?q?=E6=90=9C=E7=B4=A2/=E8=87=AA=E5=8A=A8=E5=9B=9E=E5=A4=8D\n=20=20?= =?UTF-8?q?=E4=B8=8B=E4=B8=80=E8=BD=AE=E6=9C=89=E7=9C=9F=E6=AD=A3=E7=9A=84?= =?UTF-8?q?=E5=A2=9E=E9=87=8F=E6=B6=88=E6=81=AF=E6=89=8D=E8=A7=A6=E5=8F=91?= =?UTF-8?q?=E5=9B=9E=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- monitor.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/monitor.py b/monitor.py index 093fd25..4ce4098 100644 --- a/monitor.py +++ b/monitor.py @@ -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, "")