WechatOnCloud/bridge/woc_bridge/messaging/friend_parser.py
Kris 31953eedf4 feat: 新增好友申请自动通过功能
- 新增好友申请XML解析器,支持解析微信4.x Linux的fmessage系统消息
- 新增好友申请自动通过规则引擎,支持黑白名单、关键词、场景过滤
- 新增xdotool驱动的好友申请UI自动化流程
- 新增后台好友申请监听器,支持增量轮询与状态统计
- 新增配套API接口,支持查询申请列表、手动/自动通过、配置管理
- 新增多分辨率UI定位配置,适配1280x720和1920x1080分辨率
- 新增配置项支持自动通过功能的开关与规则配置
2026-07-16 13:03:58 +08:00

85 lines
2.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""fmessage 系统消息 XML 解析器。
解析微信 4.x Linux 的 fmessage sysmsg XML提取好友申请信息。
无状态函数,便于单测。
XML 格式(推断,需环境验证):
<sysmsg type="verifyUser" ...>
<Link ...>
<UserName>xxx@stranger</UserName>
<NickName>申请人昵称</NickName>
<Content>验证消息内容</Content>
<Scene>...</Scene>
</Link>
</sysmsg>
"""
from __future__ import annotations
import logging
import xml.etree.ElementTree as ET
from typing import TYPE_CHECKING, Optional
if TYPE_CHECKING:
# 仅类型注解用,避免与 friend_watcher.py 形成运行时循环 import
from woc_bridge.messaging.friend_watcher import FriendRequestInfo
logger = logging.getLogger("woc-bridge")
def parse_friend_request(
content: str, create_time: int, msg_local_id: int
) -> Optional[FriendRequestInfo]:
"""解析 fmessage 系统消息 XML提取好友申请信息。
Args:
content: message_content 原始文本XML
create_time: 消息时间戳
msg_local_id: 消息 local_id
Returns:
FriendRequestInfo 或 None解析失败 / 非 verifyUser 类型)
"""
if not content or not content.strip():
return None
try:
root = ET.fromstring(content)
except ET.ParseError:
# 部分消息可能不是合法 XML如纯文本通知跳过
return None
# 检查是否为 verifyUser 类型 sysmsg
msg_type = root.get("type", "")
if msg_type != "verifyUser":
return None
# 提取 Link 节点中的申请人信息
link = root.find(".//Link")
if link is None:
return None
stranger_wxid = _text(link, "UserName")
nickname = _text(link, "NickName")
verify_message = _text(link, "Content")
scene = _text(link, "Scene")
if not stranger_wxid:
return None
return FriendRequestInfo(
stranger_wxid=stranger_wxid,
nickname=nickname,
verify_message=verify_message,
scene=scene,
raw_xml=content,
create_time=create_time,
msg_local_id=msg_local_id,
)
def _text(parent: ET.Element, tag: str) -> str:
"""安全提取子元素文本None 安全)。"""
el = parent.find(tag)
return el.text.strip() if el is not None and el.text else ""