Commit 7eff166684cd58d29afd7216640bbaefba5e834e

Authored by yibo
1 parent b47aed62

feat(xhshook): add POST /xhs_params to event_server + update STATUS

- event_server.py: POST /xhs_params receives forwarded XHS edith requests from
  xhshook v3 (Hook.java background thread), stores as type='xhs_request' in events DB;
  GET /xhs_params returns latest N captures for Hermes to query
- Pushed to device ~/.hermes/event_bus/event_server.py
- STATUS.md: reflect v3 state (mid=4, DEX=6328B, HTTP forwarding live), mark task C done,
  add Hermes startup instructions for event_server + xhs_params query

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
phoneuse/event_server.py
@@ -213,3 +213,33 @@ def clear_events(): @@ -213,3 +213,33 @@ def clear_events():
213 @app.get("/health") 213 @app.get("/health")
214 def health(): 214 def health():
215 return {"status": "ok", "ts": time.time()} 215 return {"status": "ok", "ts": time.time()}
  216 +
  217 +
  218 +class XhsParams(BaseModel):
  219 + method: str
  220 + url: str
  221 + headers: dict[str, str] = {}
  222 +
  223 +
  224 +@app.post("/xhs_params", status_code=200)
  225 +def post_xhs_params(params: XhsParams):
  226 + """Receive forwarded XHS request from xhshook (Hook.java).
  227 + Stored in events table as type='xhs_request' so Hermes can poll via GET /events?type=xhs_request."""
  228 + with get_db() as conn:
  229 + cursor = conn.execute(
  230 + "INSERT INTO events (type, app, data, ts, source) VALUES (?, ?, ?, ?, ?)",
  231 + ("xhs_request", "com.xingin.xhs", json.dumps({"method": params.method, "url": params.url, "headers": params.headers}), time.time(), "xhshook")
  232 + )
  233 + conn.commit()
  234 + return {"id": cursor.lastrowid}
  235 +
  236 +
  237 +@app.get("/xhs_params")
  238 +def get_xhs_params(limit: int = Query(default=10, le=100)):
  239 + """Latest XHS requests captured by xhshook. Convenience wrapper over GET /events?type=xhs_request."""
  240 + with get_db() as conn:
  241 + rows = conn.execute(
  242 + "SELECT id, data, ts FROM events WHERE type='xhs_request' ORDER BY id DESC LIMIT ?",
  243 + (limit,)
  244 + ).fetchall()
  245 + return [{"id": r["id"], "ts": r["ts"], **json.loads(r["data"])} for r in reversed(rows)]
xhs_lsposed_a16_fix/STATUS.md
@@ -13,16 +13,18 @@ @@ -13,16 +13,18 @@
13 13
14 --- 14 ---
15 15
16 -## 当前设备状态(2026-06-30 00:33 验证通过) 16 +## 当前设备状态(2026-06-30 01:17 验证通过)
17 17
18 ``` 18 ```
19 设备:Pixel 10 Pro Fold 19 设备:Pixel 10 Pro Fold
20 Android:16 (API 36) 20 Android:16 (API 36)
21 Magisk:30.7 21 Magisk:30.7
22 LSPosed (Vector fork):正常运行,lspd 进程存活 22 LSPosed (Vector fork):正常运行,lspd 进程存活
23 -xhshook:注入 com.xingin.xhs 成功 23 +xhshook v3:注入 com.xingin.xhs 成功(mid=4,APK=16863 字节,DEX=6328 字节)
24 xy-common-params:已捕获(见下方样本) 24 xy-common-params:已捕获(见下方样本)
25 curl HTTP 200:已用捕获参数成功复现 API 调用 25 curl HTTP 200:已用捕获参数成功复现 API 调用
  26 +xhshook HTTP 转发:POST /xhs_params 已实现,event_server.py 已更新
  27 +event_server.py:已推送到设备 ~/.hermes/event_bus/event_server.py
26 ``` 28 ```
27 29
28 ### 模块布局 30 ### 模块布局
@@ -47,8 +49,9 @@ curl HTTP 200:已用捕获参数成功复现 API 调用 @@ -47,8 +49,9 @@ curl HTTP 200:已用捕获参数成功复现 API 调用
47 ``` 49 ```
48 已安装:com.hermes.xhshook(streamed install --no-incremental) 50 已安装:com.hermes.xhshook(streamed install --no-incremental)
49 APK 含:assets/xposed_init → com.hermes.xhshook.Hook 51 APK 含:assets/xposed_init → com.hermes.xhshook.Hook
50 -modules_config.db:mid=1, enabled=1, scope=com.xingin.xhs  
51 -APK 路径:/data/app/~~1V3kNj_Xru_4IO7Ixo56Wg==/com.hermes.xhshook-5c7zNdRgh3RtSyoqISuL_A==/base.apk 52 +modules_config.db:mid=4, enabled=1, scope=(4, com.xingin.xhs, 0)
  53 +APK 路径:/data/app/~~F2OUnKKEvaoaCC4wwrGOsg==/com.hermes.xhshook-NAAljEo_GRPgf6S_5pp7kw==/base.apk
  54 +xhshook v3 新增:HTTP POST 转发到 127.0.0.1:8765/xhs_params(后台线程,1s 超时,静默失败)
52 ``` 55 ```
53 56
54 --- 57 ---
@@ -242,10 +245,30 @@ Hook.java 里已经打印了 `Headers.toString()` 的完整内容——重新抓 @@ -242,10 +245,30 @@ Hook.java 里已经打印了 `Headers.toString()` 的完整内容——重新抓
242 su -c "logcat -d -b all | grep 'VectorLegacyBridge'" | grep -v '\[XHSHook\]' | head -30 245 su -c "logcat -d -b all | grep 'VectorLegacyBridge'" | grep -v '\[XHSHook\]' | head -30
243 ``` 246 ```
244 247
245 -### C. 修改 xhshook 做实时转发(高级,需要 Mac 改 Hook.java) 248 +### C. 实时转发 → Hermes event_server ✅ 已完成(2026-06-30 01:17)
246 249
247 -改 hook 在 `beforeHookedMethod` 里把完整 header 通过 HTTP POST 转到 Hermes 的本地 server  
248 -(如 `localhost:8765`),让 Hermes 实时处理每条请求的签名参数。 250 +xhshook v3(Hook.java)已在 `beforeHookedMethod` 里启动后台线程 HTTP POST 到 `127.0.0.1:8765/xhs_params`。
  251 +event_server.py 已新增两个端点(已推送到设备 `~/.hermes/event_bus/event_server.py`):
  252 +
  253 +```bash
  254 +# Hermes 启动 event_server 后(uvicorn event_server:app --host 127.0.0.1 --port 8765),
  255 +# 打开 XHS,hook 自动转发 edith 请求,Hermes 可以查询:
  256 +
  257 +# 查最近捕获的 XHS 请求(含完整 headers)
  258 +curl http://127.0.0.1:8765/xhs_params
  259 +
  260 +# 或通过通用 events 接口
  261 +curl "http://127.0.0.1:8765/events/latest?type=xhs_request&app=com.xingin.xhs"
  262 +```
  263 +
  264 +转发的 JSON 格式:`{"method":"GET","url":"https://edith.xiaohongshu.com/...","headers":{"xy-common-params":"...","x-mini-sig":"...",...}}`
  265 +
  266 +**启动 event_server 步骤(Termux 里):**
  267 +```bash
  268 +cd ~/.hermes/event_bus
  269 +uvicorn event_server:app --host 127.0.0.1 --port 8765
  270 +# 然后打开 XHS,xhshook 会自动 POST 每条 edith 请求过来
  271 +```
249 272
250 --- 273 ---
251 274