Commit 423e2229b5b66ef52fd095d9ab4702461d45b270

Authored by yibo
1 parent 6470ea10

chore: 清理收尾 — 群昵称查询 + wake-lock 保活 + Frida 残留

#17 群昵称查询:
- android-wechat-tracker-sqlcipher.js:getContactNickname 删掉
  if (wxid.endsWith('@chatroom')) return wxid 的早退分支
- 群(xxxx@chatroom)和私聊都走同一 rcontact 表查询,nickname 就是群名
- A11y 现在可以用群名搜索进入群聊
- 在 Pixel 已部署并重启 auto-reply (PID 18678)

#18 wake-lock + keepalive 重写:
- 通过 am startservice com.termux.service_wake_lock 启用 wake-lock
  (确认 dumpsys power 已持有 'termux:service-wakelock')
- 重写 keepalive.sh 对齐当前部署:
  - 守护 4 项:wake-lock / A11y service / hermes gateway / auto-reply
  - hermes 走 termux native gateway 而不是 proot-distro Ubuntu(已淘汰)
  - 健康检查端口 8642(不再是 3010)
  - A11y 被关掉时自动 settings put secure 重新启用
- 在 Pixel 已部署到 ~/hermes-wechat/keepalive.sh

#16 残留清理(仅 phone 操作,无 git 文件):
- pkill -9 frida-server + rm -rf ~/.frida_queue/
- ~/.hermes/auth.json 删掉 credential_pool['kimi-coding'] 老 sk-kimi 条目
  保留 anthropic + kimi-coding-cn

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
server/services/wechat/android-wechat-tracker-sqlcipher.js
... ... @@ -144,11 +144,7 @@ class AndroidWechatTrackerSQLCipher extends EventEmitter {
144 144 };
145 145 if (builtin[wxid]) return builtin[wxid];
146 146  
147   - // 群聊 ID 走另一个表(chatroom),先简单返回 wxid 让上层处理
148   - if (wxid.endsWith('@chatroom')) {
149   - return wxid;
150   - }
151   -
  147 + // 群(xxxx@chatroom)和私聊都用 rcontact 表 — nickname 就是群名 / 个人昵称
152 148 const safeWxid = String(wxid).replace(/'/g, "''");
153 149 const sql = `SELECT conRemark, nickname FROM rcontact WHERE username='${safeWxid}' LIMIT 1;`;
154 150 try {
... ...
wechat_plain/scripts/local-testkit/keepalive.sh
1   -#!/bin/bash
2   -# keepalive.sh — Termux 保活 + 进程守护脚本
  1 +#!/data/data/com.termux/files/usr/bin/bash
  2 +# keepalive.sh — Pixel 微信自动回复保活脚本
3 3 #
4   -# 功能:
5   -# 1. 获取 wake-lock,防止息屏后 CPU 被冻结
6   -# 2. 检查并启动 hermes server
7   -# 3. 检查并启动 wechat auto-reply plugin
8   -# 4. 进程死了自动重启
  4 +# 守护以下进程,挂了就重启:
  5 +# 1. termux wake-lock — 防 Doze 冻结 Termux:API(通知监听依赖它)
  6 +# 2. HermesAccessibilityService — A11y 易被系统/更新关掉,发现 enabled_accessibility_services=null 就重启
  7 +# 3. hermes-agent gateway — :8642,LLM 网关
  8 +# 4. auto-reply.js — 微信回复主程序
9 9 #
10   -# 用法:
11   -# chmod +x keepalive.sh
12   -# nohup ./keepalive.sh > keepalive.log 2>&1 &
  10 +# 用法(在 Termux 用户 shell 里运行;不要在 root shell 起,wake-lock 拿不住 Termux 进程):
  11 +# nohup bash ~/hermes-wechat/keepalive.sh > ~/hermes-wechat/keepalive.log 2>&1 &
13 12 #
14   -# 前置条件(必须手动设置):
15   -# 1. Android 设置 → 应用 → Termux → 电池优化 → 不优化
16   -# 2. Android 设置 → 应用 → Termux:API → 电池优化 → 不优化
17   -# 3. Android 设置 → 应用 → 微信 → 电池优化 → 不优化
18   -# 4. Android 设置 → 应用 → Termux → 允许自启动
19   -# 5. Termux:API 已安装,并已授予通知访问权限
  13 +# 前置条件(一次性设置):
  14 +# 1. Android 设置 → 应用 → Termux / Termux:API / 微信 → 电池优化 → 不优化
  15 +# 2. Termux:API 已安装,并已授予通知访问权限
  16 +# 3. lsposed-wechat-sendmsg APK 已安装(含 HermesAccessibilityService)
  17 +# 4. ~/hermes-wechat/start-ar.sh 存在并已设置 MY_WXID / MY_NICKNAME
20 18  
21   -set -e
22   -
23   -# 确保 Termux 工具在 PATH 中(su 环境下可能缺失)
24 19 export PATH="/data/data/com.termux/files/usr/bin:$PATH"
25   -
26   -HERMES_DIR="${HERMES_DIR:-/data/data/com.termux/files/home/hermes-wechat}"
27   -HERMES_HOST="${HERMES_HOST:-localhost}"
28   -HERMES_PORT="${HERMES_PORT:-3010}"
29   -MY_WXID="${MY_WXID:-}"
30   -MY_NICKNAME="${MY_NICKNAME:-}"
31   -CHECK_INTERVAL_SEC="${CHECK_INTERVAL_SEC:-10}"
32   -
33   -log() {
34   - echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
35   -}
36   -
37   -# ── 1. Wake lock ─────────────────────────────────────────────────
38   -termux-wake-lock 2>/dev/null || true
39   -log "Wake lock acquired"
40   -
41   -# ── 2. 检查前置条件 ──────────────────────────────────────────────
42   -check_prerequisites() {
43   - _ok=0
44   -
45   - if ! command -v termux-notification-list >/dev/null 2>&1; then
46   - log "[WARN] termux-notification-list not found. Install: pkg install termux-api"
47   - _ok=1
  20 +export HOME="/data/data/com.termux/files/home"
  21 +
  22 +HERMES_DIR="${HERMES_DIR:-$HOME/hermes-wechat}"
  23 +HERMES_PORT="${HERMES_PORT:-8642}"
  24 +GATEWAY_START="${GATEWAY_START:-$HOME/.hermes/scripts/start-gateway.sh}"
  25 +AR_START="${AR_START:-$HERMES_DIR/start-ar.sh}"
  26 +A11Y_SVC="com.hermes.wechat.xposed/com.hermes.wechat.xposed.accessibility.HermesAccessibilityService"
  27 +CHECK_INTERVAL_SEC="${CHECK_INTERVAL_SEC:-15}"
  28 +
  29 +log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
  30 +
  31 +# ── 1. Termux wake-lock ──────────────────────────────────────────
  32 +ensure_wake_lock() {
  33 + # 用命令行 termux-wake-lock(依赖 Termux:API app);am startservice 是备用
  34 + if command -v termux-wake-lock >/dev/null 2>&1; then
  35 + termux-wake-lock 2>/dev/null
  36 + else
  37 + # 后备:用 su 调系统 ServiceManager
  38 + su -c "am startservice --user 0 -a com.termux.service_wake_lock com.termux/.app.TermuxService" 2>/dev/null || true
48 39 fi
  40 +}
49 41  
50   - if [ ! -d "$HERMES_DIR" ]; then
51   - log "[WARN] HERMES_DIR not found: $HERMES_DIR"
52   - _ok=1
53   - fi
  42 +is_wake_lock_held() {
  43 + su -c "dumpsys power 2>/dev/null | grep -q 'termux:service-wakelock'"
  44 +}
54 45  
55   - if [ -z "$MY_WXID" ] || [ -z "$MY_NICKNAME" ]; then
56   - log "[WARN] MY_WXID or MY_NICKNAME not set"
57   - log " export MY_WXID=wxid_xxxxxx"
58   - log " export MY_NICKNAME=你的昵称"
59   - _ok=1
60   - fi
  46 +# ── 2. A11y service ──────────────────────────────────────────────
  47 +is_a11y_enabled() {
  48 + out=$(su -c "settings get secure enabled_accessibility_services" 2>/dev/null)
  49 + case "$out" in
  50 + *com.hermes.wechat.xposed*HermesAccessibilityService*) return 0 ;;
  51 + *) return 1 ;;
  52 + esac
  53 +}
61 54  
62   - return $_ok
  55 +enable_a11y() {
  56 + log "Enabling HermesAccessibilityService..."
  57 + su -c "settings put secure enabled_accessibility_services $A11Y_SVC; settings put secure accessibility_enabled 1" 2>/dev/null
63 58 }
64 59  
65   -# ── 3. 检查 hermes server 是否运行 ───────────────────────────────
66   -is_hermes_running() {
67   - curl -s "http://${HERMES_HOST}:${HERMES_PORT}/api/health" >/dev/null 2>&1
  60 +# ── 3. hermes gateway ────────────────────────────────────────────
  61 +is_gateway_running() {
  62 + # 用 /sys/class/net 风格的端口探测:通过 nc 或 curl,二选一
  63 + if command -v curl >/dev/null 2>&1; then
  64 + # gateway 在 termux 用户下需要 Clash 代理(与本机回环无关);
  65 + # 但 127.0.0.1:8642 走本机,不用代理
  66 + env -u HTTPS_PROXY -u HTTP_PROXY \
  67 + curl -s --max-time 3 "http://127.0.0.1:${HERMES_PORT}/v1/models" >/dev/null 2>&1
  68 + else
  69 + # nc fallback
  70 + echo > /dev/tcp/127.0.0.1/$HERMES_PORT 2>/dev/null
  71 + fi
68 72 }
69 73  
70   -# ── 4. 启动 hermes server ────────────────────────────────────────
71   -# 必须在 proot Ubuntu 内以 ubuntu 用户运行(Claude CLI 拒绝 root + --dangerously-skip-permissions)
72   -start_hermes() {
73   - log "Starting hermes server in proot Ubuntu user=ubuntu..."
74   - cd "$HERMES_DIR"
75   - nohup proot-distro login ubuntu --user ubuntu -- bash -c \
76   - "cd $HERMES_DIR && . .env && node server/index.js" \
77   - > hermes-server.log 2>&1 &
78   - sleep 5
79   - if is_hermes_running; then
80   - log "Hermes server started PID=$!"
  74 +start_gateway() {
  75 + log "Starting hermes gateway..."
  76 + if [ -x "$GATEWAY_START" ]; then
  77 + bash "$GATEWAY_START" >> "$HOME/.hermes/logs/gateway-start.log" 2>&1
81 78 else
82   - log "[WARN] Hermes server may have failed to start, check hermes-server.log"
  79 + log "[ERROR] $GATEWAY_START not found"
83 80 fi
84 81 }
85 82  
86   -# ── 5. 检查 auto-reply 是否运行 ──────────────────────────────────
  83 +# ── 4. auto-reply.js ─────────────────────────────────────────────
87 84 is_auto_reply_running() {
88   - pgrep -f "node auto-reply.js" >/dev/null 2>&1
  85 + pgrep -f "node.*auto-reply.js" >/dev/null 2>&1
89 86 }
90 87  
91   -# ── 6. 启动 auto-reply ───────────────────────────────────────────
92 88 start_auto_reply() {
93 89 log "Starting auto-reply..."
94   - cd "$HERMES_DIR/server/services/wechat"
95   - env MY_WXID="$MY_WXID" MY_NICKNAME="$MY_NICKNAME" \
96   - nohup node auto-reply.js > auto-reply.log 2>&1 &
97   - log "Auto-reply started PID=$!"
  90 + if [ -x "$AR_START" ]; then
  91 + # auto-reply 走 root 才能 input keyevent / am broadcast / 读微信 DB
  92 + su -c "nohup bash $AR_START > /dev/null 2>&1 &"
  93 + else
  94 + log "[ERROR] $AR_START not found"
  95 + fi
98 96 }
99 97  
100   -# ── 7. 主循环 ────────────────────────────────────────────────────
  98 +# ── 5. 主循环 ────────────────────────────────────────────────────
101 99 log "=== Keepalive started ==="
102   -log "HERMES_DIR=$HERMES_DIR"
103   -log "MY_WXID=${MY_WXID:-not-set}"
104   -log "MY_NICKNAME=${MY_NICKNAME:-not-set}"
  100 +log "HERMES_DIR=$HERMES_DIR GATEWAY_START=$GATEWAY_START AR_START=$AR_START"
  101 +log "Check interval: ${CHECK_INTERVAL_SEC}s"
105 102  
106   -if ! check_prerequisites; then
107   - log "[ERROR] Prerequisites check failed, exiting"
108   - exit 1
109   -fi
  103 +# 首次进入:把所有依赖拉到位
  104 +ensure_wake_lock
  105 +is_a11y_enabled || enable_a11y
  106 +is_gateway_running || start_gateway
  107 +sleep 5
  108 +is_auto_reply_running || start_auto_reply
110 109  
111 110 while true; do
112   - # 检查 hermes
113   - if ! is_hermes_running; then
114   - log "Hermes server not responding, restarting..."
115   - start_hermes
  111 + sleep "$CHECK_INTERVAL_SEC"
  112 +
  113 + # wake-lock 偶尔会因 Termux 重启 / 系统重启而丢,保险起见周期性 re-acquire
  114 + if ! is_wake_lock_held; then
  115 + log "Wake lock lost, re-acquiring..."
  116 + ensure_wake_lock
  117 + fi
  118 +
  119 + # A11y 易被系统升级 / 用户在设置中关掉
  120 + if ! is_a11y_enabled; then
  121 + log "A11y service disabled, re-enabling..."
  122 + enable_a11y
  123 + fi
  124 +
  125 + if ! is_gateway_running; then
  126 + log "Gateway not responding on :$HERMES_PORT, restarting..."
  127 + start_gateway
  128 + sleep 6
116 129 fi
117 130  
118   - # 检查 auto-reply
119 131 if ! is_auto_reply_running; then
120   - log "Auto-reply not running, restarting..."
  132 + log "auto-reply.js not running, restarting..."
121 133 start_auto_reply
122 134 fi
123   -
124   - sleep "$CHECK_INTERVAL_SEC"
125 135 done
... ...