feat: 微信自动化客服(wechatauto-replica) 干净历史导入 - AI 自动回复/语音收发/朋友圈发布

This commit is contained in:
2026-09-16 10:12:49 +08:00
commit c3b98f4c4e
69 changed files with 19828 additions and 0 deletions
+140
View File
@@ -0,0 +1,140 @@
from wechatauto.utils.tools import (
detect_message_direction
)
from wechatauto import uia
from .mattr import (
SystemMessage,
FriendMessage,
SelfMessage
)
from .mtype import *
from . import self as selfmsg
from . import friend as friendmsg
from typing import (
TYPE_CHECKING,
Literal,
Dict,
Any
)
import os
import re
if TYPE_CHECKING:
from wechatauto.ui.chatbox import ChatBox
def parse_msg_attr(
control: uia.Control,
parent: 'ChatBox'
):
msg_direction_hash = {
'left': 'friend',
'right': 'self'
}
if control.AutomationId:
msg_screenshot = control.ScreenShot()
msg_direction, msg_direction_distence = detect_message_direction(msg_screenshot)
msg_attr = msg_direction_hash.get(msg_direction)
os.remove(msg_screenshot)
additonal_attr = {
'direction': msg_direction,
'direction_distence': msg_direction_distence
}
else:
msg_attr = 'system'
if msg_attr == 'system':
return SystemMessage(control, parent)
elif msg_attr == 'friend':
return parse_msg_type(control, parent, 'Friend', additonal_attr)
elif msg_attr == 'self':
return parse_msg_type(control, parent, 'Self', additonal_attr)
def parse_msg_type(
control: uia.Control,
parent,
attr: Literal['Self', 'Friend'],
additonal_attr: Dict[str, Any]
):
"""
多层次消息类型识别算法
基于ClassName、Name等多重验证确保识别准确性
"""
if attr == 'Friend':
msgtype = friendmsg
else:
msgtype = selfmsg
msg_text = control.Name
msg_classname = control.ClassName
msg_automation_id = control.AutomationId
# 第一层:ClassName强特征识别(最可靠)
classname_result = _classify_by_classname(msg_classname)
if classname_result:
return getattr(msgtype, f'{attr}{classname_result}')(control, parent, additonal_attr)
# 第二层:基于ClassName分类后的详细识别
if msg_classname == "mmui::ChatBubbleItemView":
# Name前缀特征识别
prefix_result = _classify_by_name_prefix(msg_text)
if prefix_result:
return getattr(msgtype, f'{attr}{prefix_result}')(control, parent, additonal_attr)
# 图片消息处理
if msg_text == '图片':
return getattr(msgtype, f'{attr}ImageMessage')(control, parent, additonal_attr)
# 如果都不匹配,归类为其他消息
return getattr(msgtype, f'{attr}OtherMessage')(control, parent, additonal_attr)
elif msg_classname == "mmui::ChatTextItemView":
# 第三层:引用消息处理
if _is_quote_message(msg_text):
return getattr(msgtype, f'{attr}QuoteMessage')(control, parent, additonal_attr)
else:
return getattr(msgtype, f'{attr}TextMessage')(control, parent, additonal_attr)
return getattr(msgtype, f'{attr}OtherMessage')(control, parent, additonal_attr)
def _classify_by_classname(classname: str) -> str:
classname_mapping = {
"mmui::ChatVoiceItemView": "VoiceMessage",
"mmui::ChatPersonalCardItemView": "PersonalCardMessage",
}
return classname_mapping.get(classname, "")
def _classify_by_name_prefix(name: str) -> str:
if name.startswith("[动画表情]") or name.startswith("[动画表情"):
return "EmojiMessage"
if name.startswith("[链接]"):
return "LinkMessage"
elif name.startswith("位置"):
return "LocationMessage"
elif name.startswith("文件\n"):
return "FileMessage"
elif name.startswith("视频"):
return "VideoMessage"
return ""
def _is_quote_message(name: str) -> bool:
quote_pattern = r'^(.*?)\s*\n引用\s+(.+?)\s+的消息\s*:\s*(.*)$'
return bool(re.search(quote_pattern, name, re.DOTALL))
def parse_msg(
control: uia.Control,
parent
):
return parse_msg_attr(control, parent)