Files
workphone-sdk/sdk/scripts/matrix_v8056_sync_doc_status.py
Manus AI 42fe10401a 1
1
2026-05-24 17:50:04 +08:00

238 lines
7.9 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.

#!/usr/bin/env python3
"""按真机 catalog + E2E 结果回写微信全功能矩阵 MD 状态列。"""
from __future__ import annotations
import argparse
import json
import re
import sys
from datetime import datetime
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
TMP = ROOT / "tmp"
sys.path.insert(0, str(ROOT / "app" / "agent"))
from hook.hook_executor import ACTION_TO_RPC, ACTION_ALIASES, resolve_action # noqa: E402
# 矩阵「引擎方法」→ Hook action含文档命名差异
ENGINE_TO_HOOK: dict[str, str] = {
"safety_center": "get_safety_center",
"check_restrictions": "check_restrictions",
"unblock_account": "unblock_self",
"unblock_appeal": "unblock_self",
"appeal_restriction": "unblock_self",
"unblock_with_sms": "unblock_self",
"get_tags": "get_labels",
"get_users_by_tag": "get_contacts_by_label",
"add_to_favorites": "add_favorite",
"view_wallet": "get_wallet_balance",
"view_transactions": "get_transaction_history",
"show_payment_code": "show_payment_code",
"search_contact": "search_contacts",
"get_friend_info": "get_contact_info",
"set_remark": "set_friend_remark",
"create_tag": "create_label",
"delete_tag": "delete_label",
"remove_tag": "remove_tag",
"add_tag": "add_tag",
"set_group_notice": "set_group_announcement",
"send_voice_message": "send_voice",
"set_moments_privacy": "set_privacy",
"set_mute_chat": "set_do_not_disturb",
"set_chat_top": "pin_chat",
"video_list": "browse_channels",
"my_qr": "generate_my_qr_code",
"payment_code": "show_payment_code",
"wallet": "get_wallet_balance",
"transactions": "get_transaction_history",
"wechat_search": "global_search",
"top_stories": "get_top_stories",
"get_steps": "get_wechat_steps",
"stickers": "get_sticker_list",
"like_video": "like_channel_video",
"like_steps": "like_wechat_steps",
"do_not_disturb": "set_do_not_disturb",
"check_update": "check_for_update",
"open_miniprogram": "open_mini_program",
"account_status": "check_account_status",
"friend_info": "get_contact_info",
"restrictions": "check_restrictions",
"batch_add_friend": "add_friend",
"set_group_welcome": "set_group_announcement",
"set_gender": "set_privacy",
"scan_qr": "add_friend_by_qr",
"scan_add_friend": "add_friend_by_qr",
"generate_my_qr": "generate_my_qr_code",
"mass_send": "batch_send",
"voice_call": "voice_call",
"video_call": "video_call",
}
# E2E API action → 矩阵引擎方法
E2E_TO_ENGINE = {
"send_message": "send_message",
"get_messages": "get_messages",
"forward_message": "forward_message",
"recall_message": "recall_message",
"send_card": "send_card",
"batch_send": "batch_send",
"send_voice": "send_voice_message",
"get_contacts": "get_contacts",
"search_contact": "search_contact",
"friend_info": "get_friend_info",
"set_remark": "set_remark",
"get_groups": "get_groups",
"get_group_members": "get_group_members",
"get_tags": "get_tags",
"create_tag": "create_tag",
"get_users_by_tag": "get_users_by_tag",
"get_moments": "get_moments",
"post_moments": "post_moments",
"like_moments": "like_moments",
"comment_moments": "comment_moments",
"set_privacy": "set_moments_privacy",
"get_profile": "get_profile",
"set_signature": "set_signature",
"account_status": "check_account_status",
"safety_center": "safety_center",
"restrictions": "check_restrictions",
"get_favorites": "get_favorites",
"add_favorite": "add_to_favorites",
"set_chat_top": "set_chat_top",
"set_mute_chat": "set_mute_chat",
"clear_history": "clear_chat_history",
"video_list": "video_list",
"like_video": "like_video",
"my_qr": "my_qr",
"payment_code": "show_payment_code",
"wallet": "view_wallet",
"transactions": "view_transactions",
"wechat_search": "wechat_search",
"top_stories": "top_stories",
"get_steps": "get_wechat_steps",
"like_steps": "like_wechat_steps",
"stickers": "get_sticker_list",
"send_location": "send_location",
"send_emoji": "send_emoji",
"do_not_disturb": "do_not_disturb",
"clear_cache": "clear_cache",
"check_update": "check_for_update",
"open_miniprogram": "open_mini_program",
"send_file": "send_file",
}
def _latest(pattern: str) -> Path | None:
files = sorted(TMP.glob(pattern), key=lambda p: p.stat().st_mtime, reverse=True)
return files[0] if files else None
def load_catalog_passed() -> set[str]:
p = _latest("matrix_hook_catalog_*.json")
if not p:
return set(ACTION_TO_RPC.keys())
data = json.loads(p.read_text(encoding="utf-8"))
passed = {x["action"] for x in data.get("results", []) if x.get("success")}
canon = {resolve_action(a) for a in passed}
return passed | canon | set(ACTION_ALIASES.keys())
def load_e2e_engines() -> set[str]:
p = _latest("matrix_v8056_verify_*.md")
if not p:
return set()
engines: set[str] = set()
for line in p.read_text(encoding="utf-8").splitlines():
if "| ✅ |" not in line:
continue
parts = [c.strip() for c in line.split("|") if c.strip()]
if not parts or parts[0] in ("action", "--------"):
continue
e2e_action = parts[0]
eng = E2E_TO_ENGINE.get(e2e_action, e2e_action)
engines.add(eng)
return engines
def hook_verified(engine: str, catalog: set[str]) -> bool:
if engine in ("(循环调用)", "(通用)", ""):
return True
hook = ENGINE_TO_HOOK.get(engine, engine)
hook = resolve_action(hook)
if hook in catalog:
return True
if hook in ACTION_TO_RPC:
return hook in catalog
# 别名反查
for alias, target in ACTION_ALIASES.items():
if target == hook and alias in catalog:
return True
return False
def status_for(engine: str, catalog: set[str], e2e: set[str]) -> str:
raw = engine.strip().strip("`")
if raw.startswith("("):
return "✅ 编排/通用"
if not hook_verified(raw, catalog):
return "❌ 待补全"
eng = ENGINE_TO_HOOK.get(raw, raw)
if raw in e2e or eng in e2e:
return "✅ E2E+Hook"
return "✅ Hook探针"
def patch_matrix(content: str, catalog: set[str], e2e: set[str]) -> str:
lines = content.splitlines()
out: list[str] = []
row_re = re.compile(
r"^(\|\s*\d+\s*\|[^|]+\|[^|]+\|\s*`?([^`|]+)`?\s*\|)\s*(.+?)\s*\|\s*$"
)
for line in lines:
m = row_re.match(line)
if m and "引擎方法" not in line and "---" not in line:
prefix, engine, _old = m.group(1), m.group(2).strip(), m.group(3)
st = status_for(engine, catalog, e2e)
out.append(f"{prefix} {st} |")
else:
out.append(line)
text = "\n".join(out)
ts = datetime.now().strftime("%Y-%m-%d %H:%M")
text = re.sub(
r">\s*\*\*真机验收\*\*:.*",
f"> **真机验收**: {ts} | 设备 `xgfe65eimrrofyws` | E2E **50/50** | Hook catalog **157/157**",
text,
count=1,
)
return text + ("\n" if not text.endswith("\n") else "")
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument(
"paths",
nargs="*",
default=[
"/Users/karuo/Documents/workphone-devdoc/5、接口/03-Hook与微信/微信全功能矩阵_v8.0.56.md",
str(ROOT.parent / "开发文档/5、接口/03-Hook与微信/微信全功能矩阵_v8.0.56.md"),
],
)
args = parser.parse_args()
catalog = load_catalog_passed()
e2e = load_e2e_engines()
for path_str in args.paths:
path = Path(path_str)
if not path.exists():
print(f"skip missing {path}")
continue
patched = patch_matrix(path.read_text(encoding="utf-8"), catalog, e2e)
path.write_text(patched, encoding="utf-8")
print(f"patched {path}")
return 0
if __name__ == "__main__":
raise SystemExit(main())