Files
wechat_crawler/wxauto/msgs/msg.py
李顺东 b66bac7ca8 feat: Initialize wxauto WeChat automation project with job extraction tools
- Add wxauto package with WeChat UI automation and message handling capabilities
- Implement job_extractor.py for automated job posting extraction from WeChat groups
- Add job_extractor_gui.py providing graphical interface for job extraction tool
- Create comprehensive documentation in Chinese covering GUI usage, multi-group support, and quick start guides
- Add build configuration files (build_exe.py, build_exe.spec) for packaging as standalone executable
- Include utility scripts for WeChat interaction (auto_send_msg.py, get_history.py, receive_file_transfer.py)
- Add project configuration files (pyproject.toml, setup.cfg, requirements.txt)
- Include test files (test_api.py, test_com_fix.py) for API and compatibility validation
- Add Apache 2.0 LICENSE and comprehensive README documentation
- Configure .gitignore to exclude build artifacts, logs, and temporary files
2026-02-11 14:49:38 +08:00

133 lines
4.3 KiB
Python

from .attr import *
from .type import OtherMessage
from . import self as selfmsg
from . import friend as friendmsg
from wxauto.languages import *
from wxauto.param import WxParam
from wxauto import uiautomation as uia
from typing import Literal
import re
class MESSAGE_ATTRS:
SYS_TEXT_HEIGHT = 33
TIME_TEXT_HEIGHT = 34
CHAT_TEXT_HEIGHT = 52
FILE_MSG_HEIGHT = 115
LINK_MSG_HEIGHT = 115
VOICE_MSG_HEIGHT = 55
TEXT_MSG_CONTROL_NUM = (8, 9, 10, 11)
TIME_MSG_CONTROL_NUM = (1,)
SYS_MSG_CONTROL_NUM = (4,5,6)
IMG_MSG_CONTROL_NUM = (9, 10, 11, 12)
FILE_MSG_CONTROL_NUM = tuple(i for i in range(15, 30))
LINK_MSG_CONTROL_NUM = tuple(i for i in range(15, 30))
VOICE_MSG_CONTROL_NUM = tuple(i for i in range(10, 30))
VIDEO_MSG_CONTROL_NUM = (13, 14, 15, 16)
QUOTE_MSG_CONTROL_NUM = tuple(i for i in range(16, 30))
LINK_MSG_CONTROL_NUM = tuple(i for i in range(15, 30))
def _lang(text: str) -> str:
return MESSAGES.get(text, {WxParam.LANGUAGE: text}).get(WxParam.LANGUAGE)
SEPICIAL_MSGS = [
_lang(i)
for i in [
'[图片]', # ImageMessage
'[视频]', # VideoMessage
'[语音]', # VoiceMessage
'[文件]', # FileMessage
'[链接]', # LinkMessage
]
]
def parse_msg_attr(
control: uia.Control,
parent,
):
msg_rect = control.BoundingRectangle
height = msg_rect.height()
mid = (msg_rect.left + msg_rect.right) / 2
for length, _ in enumerate(uia.WalkControl(control)):length += 1
# TimeMessage
if (
length in MESSAGE_ATTRS.TIME_MSG_CONTROL_NUM
):
return TimeMessage(control, parent)
# FriendMessage or SelfMessage
if (head_control := control.ButtonControl(searchDepth=2)).Exists(0):
head_rect = head_control.BoundingRectangle
if head_rect.left < mid:
return parse_msg_type(control, parent, 'Friend')
else:
return parse_msg_type(control, parent, 'Self')
# SystemMessage or TickleMessage
else:
if length in MESSAGE_ATTRS.SYS_MSG_CONTROL_NUM:
return SystemMessage(control, parent)
elif control.ListItemControl(RegexName=_lang('re_拍一拍')).Exists(0):
return TickleMessage(control, parent)
else:
return OtherMessage(control, parent)
def parse_msg_type(
control: uia.Control,
parent,
attr: Literal['Self', 'Friend']
):
for length, _ in enumerate(uia.WalkControl(control)):length += 1
content = control.Name
wxlog.debug(f'content: {content}, length: {length}')
if attr == 'Friend':
msgtype = friendmsg
else:
msgtype = selfmsg
# Special Message Type
if content in SEPICIAL_MSGS:
# ImageMessage
if content == _lang('[图片]') and length in MESSAGE_ATTRS.IMG_MSG_CONTROL_NUM:
return getattr(msgtype, f'{attr}ImageMessage')(control, parent)
# VideoMessage
elif content == _lang('[视频]') and length in MESSAGE_ATTRS.VIDEO_MSG_CONTROL_NUM:
return getattr(msgtype, f'{attr}VideoMessage')(control, parent)
# FileMessage
elif content == _lang('[文件]') and length in MESSAGE_ATTRS.FILE_MSG_CONTROL_NUM:
return getattr(msgtype, f'{attr}FileMessage')(control, parent)
# LinkMessage
elif content == _lang('[链接]') and length in MESSAGE_ATTRS.LINK_MSG_CONTROL_NUM:
return getattr(msgtype, f'{attr}LinkMessage')(control, parent)
# TextMessage
if length in MESSAGE_ATTRS.TEXT_MSG_CONTROL_NUM:
return getattr(msgtype, f'{attr}TextMessage')(control, parent)
# QuoteMessage
elif (
rematch := re.compile(_lang('re_引用消息'), re.DOTALL).match(content)
and length in MESSAGE_ATTRS.QUOTE_MSG_CONTROL_NUM
):
return getattr(msgtype, f'{attr}QuoteMessage')(control, parent)
# VoiceMessage
elif (
rematch := re.compile(_lang('re_语音')).match(content)
and length in MESSAGE_ATTRS.VOICE_MSG_CONTROL_NUM
):
return getattr(msgtype, f'{attr}VoiceMessage')(control, parent)
return getattr(msgtype, f'{attr}OtherMessage')(control, parent)
def parse_msg(
control: uia.Control,
parent
):
result = parse_msg_attr(control, parent)
return result