"""CLI:python -m jiangchang_desktop_wake """ from __future__ import annotations import argparse import json import sys def _print_json(obj) -> None: print(json.dumps(obj, ensure_ascii=False, indent=2)) def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser( prog="python -m jiangchang_desktop_wake", description="桌面 UIA Provider 暖树(probe / inject / wake / ensure)", ) sub = parser.add_subparsers(dest="cmd", required=True) p_profiles = sub.add_parser("profiles", help="列出内置 profile") p_profiles.set_defaults(func=_cmd_profiles) p_probe = sub.add_parser("probe", help="探测冷/暖") p_probe.add_argument("--profile", default="wecom") p_probe.add_argument("--hwnd", type=lambda s: int(s, 0), default=None) p_probe.set_defaults(func=_cmd_probe) p_inject = sub.add_parser( "inject", help="阶段 B:安全注入探针(不挂钩;成功看 inject_ok + ui_responsive)", ) p_inject.add_argument("--profile", default="wecom") p_inject.add_argument("--hwnd", type=lambda s: int(s, 0), default=None) p_inject.set_defaults(func=_cmd_inject) p_c2 = sub.add_parser( "c2", help="阶段 C2:SPI + 注入 + WakeProvider,再 probe(冲暖树)", ) p_c2.add_argument("--profile", default="wecom") p_c2.add_argument("--hwnd", type=lambda s: int(s, 0), default=None) p_c2.set_defaults(func=_cmd_c2) p_wake = sub.add_parser("wake", help="仅跑唤醒策略(不强制成功)") p_wake.add_argument("--profile", default="wecom") p_wake.add_argument("--hwnd", type=lambda s: int(s, 0), default=None) p_wake.set_defaults(func=_cmd_wake) p_ensure = sub.add_parser( "ensure", help="probe→wake→probe;wecom 主路径为 n2-wake(DuiLib 暖树)", ) p_ensure.add_argument("--profile", default="wecom") p_ensure.add_argument("--hwnd", type=lambda s: int(s, 0), default=None) p_ensure.add_argument( "--no-raise", action="store_true", help="仍冷也 exit 0,只打印 JSON", ) p_ensure.set_defaults(func=_cmd_ensure) args = parser.parse_args(argv) try: return int(args.func(args)) except Exception as exc: print(str(exc), file=sys.stderr) return 1 def _cmd_profiles(_args) -> int: from .profiles import list_profiles, load_profile out = [] for pid in list_profiles(): p = load_profile(pid) out.append( { "id": p.id, "description": p.description, "window_class": p.window_class, "warm_min_findall": p.warm_min_findall, "warm_markers": p.warm_markers, "wake_strategies": p.wake_strategies, } ) _print_json(out) return 0 def _cmd_probe(args) -> int: from .probe import probe r = probe(args.profile, hwnd=args.hwnd) _print_json(r.to_dict()) return 0 if r.warm else 2 def _cmd_inject(args) -> int: from .inject import inject_probe r = inject_probe(args.profile, hwnd=args.hwnd) _print_json(r) if r.get("inject_ok") and r.get("ui_responsive"): return 0 if r.get("inject_ok") and not r.get("ui_responsive"): return 6 return 5 def _cmd_c2(args) -> int: from .c2 import wake_c2 r = wake_c2(args.profile, hwnd=args.hwnd) _print_json(r) if r.get("warm"): return 0 if r.get("ui_responsive") is False: return 6 return 4 def _cmd_wake(args) -> int: from .probe import probe from .wake import wake steps = wake(args.profile, hwnd=args.hwnd) after = probe(args.profile, hwnd=args.hwnd) _print_json( { "steps": [s.to_dict() for s in steps], "probe_after": after.to_dict(), } ) return 0 if after.warm else 2 def _cmd_ensure(args) -> int: from .ensure import ensure_ui_ready from .errors import DesktopWakeError try: r = ensure_ui_ready( args.profile, hwnd=args.hwnd, raise_on_cold=not args.no_raise, ) except DesktopWakeError as exc: print(str(exc), file=sys.stderr) return 1 _print_json(r.to_dict()) return 0 if r.warm else 2 if __name__ == "__main__": raise SystemExit(main())