修复过滤器4误判用户名@提及为回复残片:公共子串为用户名时豁免
This commit is contained in:
+58
-2
@@ -3755,8 +3755,33 @@ class MessageMonitor:
|
||||
if _is_ask and not _is_full_sub:
|
||||
logger.debug(f"[{platform}] OCR 过滤: 疑似回复片段但为问句且非完全子串,视为用户提问放行 line={line[:60]!r}")
|
||||
else:
|
||||
logger.debug(f"[{platform}] OCR 过滤: 回复内容片段 line={line[:60]!r}")
|
||||
continue
|
||||
# ⭐ 用户名@提及豁免(2026-08-12):公共子串主要是用户名/昵称时,
|
||||
# 且用户消息含中文内容,视为用户提问而非回复残片。
|
||||
# 例:youpaishidifu关于我们 vs @youpaishidifu 你好 → 公共子串youpaishidifu是用户名
|
||||
_cjk_line = ''.join(c for c in line if '\u4e00' <= c <= '\u9fff')
|
||||
_has_cjk = len(_cjk_line) >= 2
|
||||
if _has_cjk and not _is_full_sub:
|
||||
_pub_is_username = False
|
||||
for r in self._replied_texts:
|
||||
if len(r) < 5:
|
||||
continue
|
||||
sm = difflib.SequenceMatcher(None, line, r)
|
||||
lm = sm.find_longest_match(0, len(line), 0, len(r)).size
|
||||
if lm >= 8:
|
||||
match = sm.find_longest_match(0, len(line), 0, len(r))
|
||||
pub_str = line[match.a:match.a + match.size]
|
||||
pub_cjk = sum(1 for c in pub_str if '\u4e00' <= c <= '\u9fff')
|
||||
if pub_cjk == 0:
|
||||
_pub_is_username = True
|
||||
break
|
||||
if _pub_is_username:
|
||||
logger.debug(f"[{platform}] OCR 过滤: 疑似回复片段但公共子串为用户名且消息含中文,视为用户提问放行 line={line[:60]!r}")
|
||||
else:
|
||||
logger.debug(f"[{platform}] OCR 过滤: 回复内容片段 line={line[:60]!r}")
|
||||
continue
|
||||
else:
|
||||
logger.debug(f"[{platform}] OCR 过滤: 回复内容片段 line={line[:60]!r}")
|
||||
continue
|
||||
|
||||
# ⭐ Task #1441: bot自身消息查库过滤
|
||||
# 检查OCR读到的内容是否与数据库中bot回复的消息重合率≥90%
|
||||
@@ -4748,6 +4773,37 @@ class MessageMonitor:
|
||||
if _is_ask and not _is_full_sub:
|
||||
logger.debug(f"[ocr] 过滤器4结果: 匹配成功但为问句且非完全子串,视为用户提问返回False")
|
||||
return False
|
||||
|
||||
# ⭐ 用户名@提及豁免(2026-08-12):当公共子串主要是用户名/昵称(不含中文),
|
||||
# 且用户消息的其余部分包含中文内容时,视为用户提问而非回复残片。
|
||||
# 例:youpaishidifu关于我们 vs @youpaishidifu 你好 → 公共子串youpaishidifu是用户名,
|
||||
# 剩余"关于我们"是用户实际提问,不应判为残片。
|
||||
_has_cjk_in_text = len(t_cjk) >= 2 # 用户消息至少2个中文字符
|
||||
if _has_cjk_in_text and not _is_full_sub:
|
||||
# 检查公共子串是否主要是非中文(用户名/昵称)
|
||||
# 找最长公共子串对应的r_norm片段
|
||||
_pub_is_username = False
|
||||
for r in self._replied_texts:
|
||||
if len(r) < 5:
|
||||
continue
|
||||
r_norm = self._norm_frag(r)
|
||||
if not r_norm:
|
||||
continue
|
||||
sm = difflib.SequenceMatcher(None, t_norm, r_norm)
|
||||
lm = sm.find_longest_match(0, len(t_norm), 0, len(r_norm)).size
|
||||
if lm >= 8:
|
||||
# 提取公共子串在t_norm中的位置
|
||||
match = sm.find_longest_match(0, len(t_norm), 0, len(r_norm))
|
||||
pub_str = t_norm[match.a:match.a + match.size]
|
||||
# 检查公共子串是否不含中文(即主要是用户名/昵称)
|
||||
pub_cjk = sum(1 for c in pub_str if '\u4e00' <= c <= '\u9fff')
|
||||
if pub_cjk == 0 and lm >= 8:
|
||||
_pub_is_username = True
|
||||
break
|
||||
if _pub_is_username:
|
||||
logger.debug(f"[ocr] 过滤器4结果: 匹配成功但公共子串为用户名且消息含中文,视为用户提问返回False")
|
||||
return False
|
||||
|
||||
logger.debug(f"[ocr] 过滤器4结果: 文本匹配成功,返回True")
|
||||
return True
|
||||
logger.debug(f"[ocr] 过滤器4结果: 未匹配到已回复文本,返回False")
|
||||
|
||||
Reference in New Issue
Block a user