fix(monitor): 扩展联系方式匹配规则

修复_sanatize_message中的手机号匹配遗漏:
1. 固话:以0开头的区号+号码(如010-12345678、07311234567)
2. 400电话:以400开头的7-8位数字
3. 急救电话:110、119、120、122

确保所有联系方式都能被正确识别和剥离,防止误触回复。
This commit is contained in:
youpaishidifu
2026-08-15 21:06:50 +08:00
parent 79b1beabef
commit e01249dcc1
+95
View File
@@ -3386,6 +3386,8 @@ class MessageMonitor:
if msg:
# ⭐ 剥离QQ用户昵称,防止昵称拼凑进消息文本导致查库关键词被压住
msg = self._strip_qq_nickname(msg)
# ⭐ 2026-08-15 消息全身检查:剥离所有昵称和联系方式,防止误触回复
msg = self._sanitize_message(msg)
# ⭐ 2026-08-15 修复:OCR合并多条消息时,拆分所有消息段
# 如 "公告信息呀@游戏专用,草原探险服务器备用号,嘿啊。服务器地址"
# 不应只取最后一段,而应提取所有独立消息
@@ -3461,6 +3463,8 @@ class MessageMonitor:
if msg:
# ⭐ 剥离QQ用户昵称,防止昵称拼凑进消息文本导致查库关键词被压住
msg = self._strip_qq_nickname(msg)
# ⭐ 2026-08-15 消息全身检查:剥离所有昵称和联系方式,防止误触回复
msg = self._sanitize_message(msg)
# ⭐ 2026-08-15 修复:OCR合并多条消息时,拆分所有消息段
if '@' in msg or any(n + ',' in msg for n in nicknames):
_multi_msgs = self._split_by_nick_sep(msg)
@@ -4898,6 +4902,97 @@ class MessageMonitor:
return text.strip()
return ts.strip()
def _sanitize_message(self, text: str) -> str:
"""消息入队前的全身检查:剥离昵称和联系方式,防止误触回复。
从消息中移除:
1. config.json中已注册的所有QQ昵称(无论出现在何处)
2. 联系方式:Email、QQ号、手机号、固话、400电话、急救电话等
确保敏感信息不进入知识库搜索和回复流程。
"""
if not text or not text.strip():
return text
# 加载昵称列表
try:
from config import load_config
cfg = load_config()
nicks = cfg.get('qq_nicknames', [])
except Exception:
nicks = []
if not nicks:
nicks = ["草原探险服务器备用号", "游戏专用"]
result = text
removed_items = []
# 1. 移除已注册的昵称(全局,不分位置)
for nick in nicks:
if nick in result:
result = result.replace(nick, '')
removed_items.append(f"昵称:{nick}")
# 2. 移除联系方式
# Email: 匹配 xxx@xxx.xxx 格式
email_pattern = re.compile(r'[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}')
emails = email_pattern.findall(result)
if emails:
for email in emails:
result = result.replace(email, '')
removed_items.append(f"邮箱:{email}")
# QQ号: 匹配纯数字,长度5-12位(常见QQ号范围)
# 注意:需要避免匹配时间戳(如16:28:40)
qq_pattern = re.compile(r'(?<![.\d:/@])\b(\d{5,12})\b(?![.\d:/@])')
qq_numbers = qq_pattern.findall(result)
if qq_numbers:
for qq in qq_numbers:
result = result.replace(qq, '', 1) # 只替换第一个匹配
removed_items.append(f"QQ号:{qq}")
# 手机号: 匹配11位手机号(1开头,13-19中间)
phone_pattern = re.compile(r'(?<![.\d:/@])\b(1[3-9]\d{9})\b(?![.\d:/@])')
phones = phone_pattern.findall(result)
if phones:
for phone in phones:
result = result.replace(phone, '', 1)
removed_items.append(f"手机号:{phone}")
# 固话: 匹配以0开头的区号+号码(如010-12345678、07311234567)
# 格式:0\d{2,3}[-\s]?\d{6,8} 或 0\d{2,3}\d{6,8}
landline_pattern = re.compile(r'(?<![.\d:/@])\b(0\d{2,3}[-\s]?\d{6,8})\b(?![.\d:/@])')
landlines = landline_pattern.findall(result)
if landlines:
for landline in landlines:
result = result.replace(landline, '', 1)
removed_items.append(f"固话:{landline}")
# 400电话: 匹配以400开头的7-8位数字
# 格式:400-\d{7} 或 400-\d{8} 或 400\d{7} 或 400\d{8}
phone400_pattern = re.compile(r'(?<![.\d:/@])\b(400[-\s]?\d{7,8})\b(?![.\d:/@])')
phone400s = phone400_pattern.findall(result)
if phone400s:
for p in phone400s:
result = result.replace(p, '', 1)
removed_items.append(f"400电话:{p}")
# 急救电话: 110、119、120、122
emergency_phones = ['110', '119', '120', '122']
for emp in emergency_phones:
if emp in result:
result = result.replace(emp, '', 1)
removed_items.append(f"急救电话:{emp}")
# 清理多余的空格和标点
result = re.sub(r'\s+', ' ', result).strip()
result = re.sub(r'[,,。::;;]+\s*[,,。::;;]+', '', result).strip()
if removed_items:
logger.info(f"[qq] 消息清理: 移除{removed_items}, 原文={text[:60]!r}, 清理后={result[:60]!r}")
return result.strip() if result.strip() else text
def _split_by_nick_sep(self, text: str) -> list:
"""将OCR合并的多条消息按昵称分隔符拆分,提取所有消息段。