fix(monitor): 修复全局昵称匹配正则边界过严问题,改用简单子串匹配
原正则要求前后必须是空格/标点/字符串边界,导致常见OCR格式无法匹配: - "你好草原探险服务器备用号,我想问" → 未剥离(失败) - "=>草原探险服务器备用号游戏专用有问题" → 未剥离(失败) 新方案:统一使用最长优先的子串匹配 - 按昵称长度降序排序,优先匹配长昵称(避免短前缀误匹配) - 直接字符串查找并移除,简单高效 - 不会误删部分匹配的文本(如"服务器备用电源"不会误删"备用") 测试验证: ✓ 纯昵称剥离 ✓ 箭头前缀剥离 ✓ 汉字前缀+逗号剥离 ✓ 连续多个昵称剥离 ✓ 短昵称剥离 ✓ 防误删(部分匹配不误删)
This commit is contained in:
+9
-23
@@ -4890,29 +4890,15 @@ class MessageMonitor:
|
||||
# 例:"=>草原探险服务器备用号游戏专用有问题" → 前缀匹配后剩"游戏专用有问题"
|
||||
# 但有时前缀匹配失败,需要全局扫描
|
||||
if not changed: # 前缀匹配无变化时才进行全局匹配
|
||||
for nick in nicknames:
|
||||
# 使用正则进行全局匹配,需要前后边界检查
|
||||
# 避免误删正文中的正常文本(如"服务器备用"不应被误删)
|
||||
pattern = re.compile(rf'(?:^|[^\w\u4e00-\u9fff]){re.escape(nick)}(?:$|[^а-яА-Яa-zA-Z0-9\u4e00-\u9fff])', re.UNICODE)
|
||||
m_global = pattern.search(ts)
|
||||
if m_global:
|
||||
# 计算实际匹配范围(去除边界字符)
|
||||
match_start = m_global.start()
|
||||
match_end = m_global.end()
|
||||
# 跳过开头的非单词字符
|
||||
while match_start < len(ts) and not ts[match_start].isalnum() and ts[match_start] not in '\u4e00-\u9fff':
|
||||
match_start += 1
|
||||
# 跳过结尾的非单词字符
|
||||
while match_end > match_start and not ts[match_end-1].isalnum() and ts[match_end-1] not in '\u4e00-\u9fff':
|
||||
match_end -= 1
|
||||
|
||||
if match_start < match_end and match_start > 0: # 不在开头(已处理过)
|
||||
before = ts[:match_start]
|
||||
after = ts[match_end:]
|
||||
ts = (before + after).lstrip()
|
||||
logger.debug(f"[qq] 全局匹配剥除昵称 {nick!r}: {m_global.group()!r}")
|
||||
changed = True
|
||||
break
|
||||
# 按长度降序排序,优先匹配长昵称(避免短前缀误匹配)
|
||||
for nick in sorted(nicknames, key=len, reverse=True):
|
||||
if nick in ts:
|
||||
start = ts.find(nick)
|
||||
end = start + len(nick)
|
||||
ts = (ts[:start] + ts[end:]).lstrip()
|
||||
logger.debug(f"[qq] 全局匹配剥除昵称 {nick!r} @ [{start}:{end}]")
|
||||
changed = True
|
||||
break
|
||||
|
||||
# ⭐ 群聊多消息拆分:OCR多条消息拼接时,[头衔]用户名 或 裸昵称 作为分隔符出现在文本中间
|
||||
# 如 "C4炸弹起来准备测试了,[专业皮肤定制] C4炸弹,[专业皮肤定制] C4炸弹,youpaishidifu关于我们"
|
||||
|
||||
Reference in New Issue
Block a user