feat: 支持大湾区球场监控
This commit is contained in:
152
skills/tennis-booking/references/operations.md
Normal file
152
skills/tennis-booking/references/operations.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# agent 调用方式
|
||||
|
||||
## 必备工具
|
||||
|
||||
- HTTP 客户端:agent 自带 `web_fetch` / `curl` / Node 22 `fetch` 任一
|
||||
- Node 22:执行 `scripts/pospal.mjs`(Linux / macOS 自带 `node` 或 NVM)
|
||||
- 隐藏式输入:Linux/macOS `bash read -rs`、或 Node `readline` 关闭回显
|
||||
- 单次请求硬性超时:`AbortSignal.timeout(12000)`(12 秒)
|
||||
|
||||
## 凭证管理
|
||||
|
||||
### 首次获取(agent 主动询问)
|
||||
|
||||
```bash
|
||||
printf "PSPLVISITORID: " >&2
|
||||
IFS= read -rs PSPAL_VISITOR_ID
|
||||
printf "\n" >&2
|
||||
```
|
||||
|
||||
旧版 `bash` 不支持 `-s` 时:
|
||||
|
||||
```bash
|
||||
stty -echo
|
||||
printf "PSPLVISITORID: " >&2
|
||||
read PSPAL_VISITOR_ID
|
||||
stty echo
|
||||
printf "\n" >&2
|
||||
```
|
||||
|
||||
### 注入到 helper 调用
|
||||
|
||||
```bash
|
||||
export POSPAL_VISITOR_ID="$PSPAL_VISITOR_ID"
|
||||
node scripts/pospal.mjs build-booking-body < continuous-slots.json
|
||||
```
|
||||
|
||||
helper 也支持 `--visitor <value>`,但**优先用 env**——避免值出现在进程列表 (`ps aux`)。
|
||||
|
||||
### Session 结束
|
||||
|
||||
```bash
|
||||
unset POSPAL_VISITOR_ID
|
||||
```
|
||||
|
||||
新 session 必须重新索取,不允许持久化。
|
||||
|
||||
## helper 子命令
|
||||
|
||||
| 子命令 | 作用 | 何时用 |
|
||||
|---|---|---|
|
||||
| `parse-availability` | 把 list 端点原始 JSON 转结构化 slots(含状态判定、活动合并) | 每次拿到 list 响应后必跑 |
|
||||
| `find-continuous` | 从 slots 中找符合 `--start HH --end HH` 的完整连续组合 | 拿到结构化 slots 后 |
|
||||
| `build-booking-body` | 从连续组合生成锁场请求体 | 锁场前 |
|
||||
| `parse-booking-response` | 解析锁场响应,**剥离 `script.paySign`** | 锁场后 |
|
||||
| `fingerprint` | 访客凭证 → 12 字符 hex 指纹 | 日志关联 |
|
||||
| `redact` | 任意 JSON → 移除敏感字段 | 落盘或汇报前 |
|
||||
|
||||
所有子命令从 stdin 读 JSON(除 `fingerprint`),都支持 `--help`。
|
||||
|
||||
## 工作流示例
|
||||
|
||||
### 单次查询
|
||||
|
||||
```bash
|
||||
# 1. 调 list 端点
|
||||
RAW=$(curl -sS -X POST 'https://wxservice-stg48.pospal.cn/wxapi/AppointmentVenue/LoadValidClassRoomApptSettingV2' \
|
||||
-H 'Accept: */*' \
|
||||
-H 'APPTYPE: 1' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'PSPLVISITORAUTO: API' \
|
||||
-H 'Referer: https://servicewechat.com/wx2088ca46b47d8be7/11/page-frame.html' \
|
||||
-H 'STOREID: 6038652' \
|
||||
-H 'VERSIONINFO: NC|2026.07.03' \
|
||||
-d '{"dateTime":"2026-07-16","userId":6038652,"projectUid":"1775556129325750199"}')
|
||||
|
||||
# 2. 解析
|
||||
echo "$RAW" | node scripts/pospal.mjs parse-availability --date 2026-07-16
|
||||
|
||||
# 3. 找连续组合
|
||||
echo "$RAW" | node scripts/pospal.mjs parse-availability --date 2026-07-16 \
|
||||
| node scripts/pospal.mjs find-continuous --start 19 --end 21
|
||||
```
|
||||
|
||||
### 锁场
|
||||
|
||||
```bash
|
||||
# 1. 重新查一次(不复用旧缓存)
|
||||
RAW=$(curl -sS -X POST '...' -d '...')
|
||||
|
||||
# 2. 解析 + 找连续 + 构造请求体
|
||||
BODY=$(echo "$RAW" | node scripts/pospal.mjs parse-availability --date 2026-07-16 \
|
||||
| node scripts/pospal.mjs find-continuous --start 19 --end 21 \
|
||||
| node scripts/pospal.mjs build-booking-body)
|
||||
|
||||
# 3. 调锁场
|
||||
RESP=$(curl -sS -X POST 'https://wxservice-stg48.pospal.cn/wxapi/AppointmentVenue/SaveVenueAppointmentV2' \
|
||||
-H "PSPLVISITORID: $POSPAL_VISITOR_ID" \
|
||||
-H @write-headers.txt \
|
||||
-d "$BODY")
|
||||
|
||||
# 4. 解析并脱敏
|
||||
echo "$RESP" | node scripts/pospal.mjs parse-booking-response --slots continuous-slots.json
|
||||
```
|
||||
|
||||
`write-headers.txt` 模板见 `references/protocol.md` 末尾。
|
||||
|
||||
### 监控循环(agent 自行实现)
|
||||
|
||||
```
|
||||
for date in today, today+1, ..., today+6:
|
||||
slots = curl list(date) → parse-availability
|
||||
cont = find-continuous(slots, target_start, target_end)
|
||||
key = (date, cont.txtClassroomUid, cont.startTime, cont.endTime, sum_price)
|
||||
if cont and key not in seen:
|
||||
notify(cont)
|
||||
seen.add(key)
|
||||
elif not cont and key in seen:
|
||||
notify("removed: {key}")
|
||||
seen.discard(key)
|
||||
sleep 10
|
||||
```
|
||||
|
||||
整点(如 `19:00:00.000`)agent 主动绕过冷却立即查一次。同一 date 的并发查询只允许一个在飞。
|
||||
|
||||
## 失败处理速查
|
||||
|
||||
| 现象 | agent 动作 |
|
||||
|---|---|
|
||||
| 列表返回 `successed: false` | 视为该日无可订数据,不重试 |
|
||||
| 列表返回缺字段 | 视为接口变更,停止对该球场所有操作,告诉用户"接口字段变化,暂停服务" |
|
||||
| 锁场 `successed: false` | 换时段最多重试 1 次,仍失败则停下 |
|
||||
| 锁场 HTTP 5xx / 网络错误 | 不重试,告诉用户"结果不确定,请去小程序核实" |
|
||||
| 锁场后 `script.expireTime` 已过 | 锁场已失效,告知用户 |
|
||||
| `enrollSlots` 含目标时段 | 该时段按已订处理,不计入连续组合 |
|
||||
| `PSPLVISITORID` 未索取 | 写操作前必须先向用户隐藏式索取;缺则停下 |
|
||||
|
||||
## 调试与脱敏
|
||||
|
||||
```bash
|
||||
# 任何写操作前,确认 visitor 指纹
|
||||
node scripts/pospal.mjs fingerprint "$POSPAL_VISITOR_ID"
|
||||
# → "a3f9b21c0e4d" (12 字符)
|
||||
|
||||
# 落盘任何响应前必须 redact
|
||||
curl ...list... | node scripts/pospal.mjs redact > list-redacted.json
|
||||
|
||||
# 看 helper 自检
|
||||
node scripts/pospal.mjs parse-availability --date 2026-07-16 \
|
||||
< evals/fixtures/availability-sample.json
|
||||
```
|
||||
|
||||
完整 `list-headers.txt` / `write-headers.txt` 模板见 `references/protocol.md` 末尾的 curl 示例。
|
||||
Reference in New Issue
Block a user