126 lines
5.2 KiB
Bash
Executable File
126 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# ==============================================================================
|
||
# run_extended_acceptance.sh — 微信 P0 + 四端 E2E + friend-add/AI chat 编排
|
||
#
|
||
# 真源:工作手机_微信全量控机与私域_20260529.md · 工作手机_存客宝四端对接_20260529.md
|
||
# 用法:bash sdk/scripts/run_extended_acceptance.sh [device_id]
|
||
# 环境:CUNKEBAO_API_KEY=xxx 可自动启用 CKB(须重启 SDK 后生效)
|
||
# ==============================================================================
|
||
set -o pipefail
|
||
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||
DEVICE="${1:-${SDK_DEVICE_ID:-xgfe65eimrrofyws}}"
|
||
BASE="${SDK_BASE_URL:-http://127.0.0.1:8899}"
|
||
TS="$(date +%Y%m%d-%H%M%S)"
|
||
EVID="$ROOT/开发文档/8、部署/05-测试验收/$(date +%Y%m%d)_扩展验收"
|
||
mkdir -p "$EVID"
|
||
REPORT="$EVID/extended_acceptance_${TS}.json"
|
||
|
||
PASS=0; BLOCKED=0; FAIL=0
|
||
declare -a ROWS
|
||
|
||
note() { echo "$1"; ROWS+=("$2"); }
|
||
|
||
echo "=== 扩展验收 $TS === device=$DEVICE"
|
||
|
||
# 0. 设备 / Hook
|
||
HOOK=$(curl -s --max-time 20 "$BASE/api/v3/hook/probe/$DEVICE" 2>/dev/null || echo '{}')
|
||
SUPPORTS=$(echo "$HOOK" | python3 -c "import sys,json;print(json.load(sys.stdin).get('supports_hook'))" 2>/dev/null)
|
||
if [ "$SUPPORTS" = "True" ]; then
|
||
note " [PASS] hook probe supports_hook=true" "hook:PASS"
|
||
PASS=$((PASS+1))
|
||
else
|
||
note " [BLOCKED] hook offline(手机 Termux 跑 termux_frida_up_onphone.sh)" "hook:BLOCKED"
|
||
BLOCKED=$((BLOCKED+1))
|
||
fi
|
||
|
||
# 1. 微信三项 P0
|
||
if bash "$ROOT/sdk/scripts/run_three_acceptance.sh" "$DEVICE" 2>&1 | tee "$EVID/three_${TS}.log" | tail -3 | grep -q '三项验收全绿'; then
|
||
note " [PASS] 微信三项 P0 全绿" "three:PASS"
|
||
PASS=$((PASS+1))
|
||
elif [ "$SUPPORTS" != "True" ]; then
|
||
note " [BLOCKED] 三项跳过(hook 离线)" "three:BLOCKED"
|
||
BLOCKED=$((BLOCKED+1))
|
||
else
|
||
note " [FAIL] 微信三项未全绿" "three:FAIL"
|
||
FAIL=$((FAIL+1))
|
||
fi
|
||
|
||
sleep 5
|
||
|
||
# 2. 四端 E2E(含写消息)
|
||
FOUR_LOG="$EVID/4end_${TS}.log"
|
||
if WP_WRITE=1 bash "$ROOT/开发文档/8、部署/05-测试验收/scripts/workphone_4end_e2e.sh" "$DEVICE" 2>&1 | tee "$FOUR_LOG" | grep -qE 'FAIL=0'; then
|
||
note " [PASS] 四端 E2E FAIL=0" "4end:PASS"
|
||
PASS=$((PASS+1))
|
||
else
|
||
note " [FAIL] 四端 E2E 有失败项" "4end:FAIL"
|
||
FAIL=$((FAIL+1))
|
||
fi
|
||
|
||
# 3. friend-add ingest
|
||
R=$(curl -s --max-time 30 -X POST "$BASE/api/v3/cunke-bao/hook/friend-add" -H 'Content-Type: application/json' \
|
||
-d "{\"device_id\":\"$DEVICE\",\"wechat_id\":\"wxid_e2e_${TS}\",\"nickname\":\"E2E\",\"source\":\"extended_acceptance\"}")
|
||
[ -z "$R" ] && sleep 2 && R=$(curl -s --max-time 30 -X POST "$BASE/api/v3/cunke-bao/hook/friend-add" -H 'Content-Type: application/json' \
|
||
-d "{\"device_id\":\"$DEVICE\",\"wechat_id\":\"wxid_e2e_${TS}\",\"nickname\":\"E2E\",\"source\":\"extended_acceptance\"}")
|
||
echo "$R" > "$EVID/friend_add_${TS}.json"
|
||
CODE=$(echo "$R" | python3 -c "import sys,json;print(json.load(sys.stdin).get('code',''))" 2>/dev/null)
|
||
if [ "$CODE" = "200" ]; then
|
||
note " [PASS] friend-add → CKB code=200" "friend_add:PASS"
|
||
PASS=$((PASS+1))
|
||
elif echo "$R" | grep -qE '未启用|未配置|API Key'; then
|
||
note " [BLOCKED] CKB 未启用(设 CUNKEBAO_API_KEY 并重启 SDK)" "friend_add:BLOCKED"
|
||
BLOCKED=$((BLOCKED+1))
|
||
else
|
||
note " [FAIL] friend-add code=$CODE" "friend_add:FAIL"
|
||
FAIL=$((FAIL+1))
|
||
fi
|
||
|
||
# 4. AI chat(需卡若网关 + hook)
|
||
AI=$(curl -s --max-time 90 -X POST "$BASE/api/v3/devices/$DEVICE/ai/chat" -H 'Content-Type: application/json' \
|
||
-d "{\"instruction\":\"向文件传输助手发:AI扩展验收-$TS\",\"timeout\":60}" 2>/dev/null || echo '{}')
|
||
echo "$AI" > "$EVID/ai_chat_${TS}.json"
|
||
AI_STATUS=$(echo "$AI" | python3 -c "
|
||
import sys,json,re
|
||
raw=sys.stdin.read()
|
||
try:
|
||
d=json.loads(raw)
|
||
except Exception:
|
||
print('FAIL'); sys.exit(0)
|
||
if d.get('code')==200 and (d.get('data') or {}).get('acted'):
|
||
print('PASS')
|
||
elif d.get('code')==200 and not (d.get('data') or {}).get('acted'):
|
||
print('BLOCKED')
|
||
else:
|
||
blob=json.dumps(d,ensure_ascii=False)
|
||
if re.search(r'429|502|503|401|无响应|RATE_LIMIT|Too Many|余额不足|gateway|Bad Gateway|Unauthorized|insufficient', blob, re.I):
|
||
print('BLOCKED')
|
||
else:
|
||
print('FAIL')
|
||
" 2>/dev/null)
|
||
case "$AI_STATUS" in
|
||
PASS) note " [PASS] AI chat 决策并执行" "ai_chat:PASS"; PASS=$((PASS+1)) ;;
|
||
BLOCKED) note " [BLOCKED] AI 网关限流/502/余额不足" "ai_chat:BLOCKED"; BLOCKED=$((BLOCKED+1)) ;;
|
||
*) note " [FAIL] AI chat 未执行" "ai_chat:FAIL"; FAIL=$((FAIL+1)) ;;
|
||
esac
|
||
|
||
# 5. 静态审计
|
||
if python3 "$ROOT/sdk/scripts/wechat_interface_audit.py" >/dev/null 2>&1; then
|
||
note " [PASS] 128/174 静态对齐" "audit:PASS"
|
||
PASS=$((PASS+1))
|
||
else
|
||
note " [FAIL] 静态审计失败" "audit:FAIL"
|
||
FAIL=$((FAIL+1))
|
||
fi
|
||
|
||
python3 - "$REPORT" "$DEVICE" "$TS" "$PASS" "$BLOCKED" "$FAIL" "${ROWS[@]}" <<'PY'
|
||
import json,sys
|
||
report,device,ts,p,b,f,*rows=sys.argv[1:]
|
||
data={"timestamp":ts,"device_id":device,"pass":int(p),"blocked":int(b),"fail":int(f),
|
||
"results":[dict(zip(("item","status"),r.split(":",1))) for r in rows]}
|
||
open(report,"w").write(json.dumps(data,ensure_ascii=False,indent=2))
|
||
print(f"\n汇总 PASS={p} BLOCKED={b} FAIL={f} 报告 {report}")
|
||
PY
|
||
|
||
echo "证据: $EVID"
|
||
exit $([ "$FAIL" -eq 0 ] && echo 0 || echo 1)
|