refactor(bf-bot): 插件重构为 handlers/services/utils 分层,资源归入 res/

- 旧平铺模块(data/data_utils/database_op/image_builder*/get_bf6_data/
  gametools_bf6/bf6_data/img_utils)拆分为 handlers(绑定/查询)、
  services(fetchers/processing/query)、utils(渲染/参数)分层;
  新增 repository.py / config.py / paths.py
- 字体/图片/模板资源迁入 res/,新增 BF2042 卡面素材(bg/object_icon 等)
- browser_ext/:BF2042 扩展捕获桥(WS 直连兜底通道)源码入库
- 新增 hexi/web/src/plugins/bf_bot 前端管理页
- 新增 tests:test_bf_bot_helpers / repository / tracker_api

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
sansenhoshiandClaude Code committed 2026-10-13 17:53:06 +08:00
1 parent 614e1d7e00
commit a31aab00e8
752 files changed
+6241 -2506

No files matched your search

@@ -0,0 +1,80 @@
# HeXi BF2042 捕获桥(浏览器扩展)
被动捕获 tracker.gg 的 BF2042 API 响应,经 WebSocket 转发给本机 bot。
服务端有两个等价实现:bot 插件内的 `services/fetchers/tracker_bridge.py`(正式,
随 bot 启停,端口/token 是 /hub 插件配置页里的 `bf_ext_ws_port`/`bf_ext_ws_token`),
以及 `debug/bf2042_bridge_server.py`(独立联调用,不启 bot)。两侧默认
`ws://127.0.0.1:39272/?token=hexi-bf2042`。
## 原理
历史通道要走 `--remote-debugging-port` + Playwright `connect_over_cdp`。本扩展把捕获
搬进浏览器内部,参照 FetchV / 猫抓一类捕获扩展的通行模式:
- `inject.js`(主世界,document_start)用 Proxy 包住 `fetch` / `XMLHttpRequest`,
被动观察**页面自己发出**的请求(不改写、不重放,只读 clone 的响应体);
- `content.js`(隔离世界)把捕获经 `chrome.runtime` 转给 SW
(内容脚本连 `ws://127.0.0.1` 会被页面 CSP 的 connect-src 拦掉,所以 WS 必须放 SW);
- `background.js`(SW)持有到 bot 的 WebSocket,转发捕获、执行取数任务:
找/开 tracker.gg 标签页 → 回首页落稳 → 站内跳转进 profile 页 → 等页面发 XHR。
- **失败重试**:单轮 22s 内关键响应没齐(多半撞了 CF 挑战/403,页面 XHR 拿不到
数据),自动重走"首页→站内跳转"刷新,最多 3 轮;每轮结束做页面健康检查
(挑战页/封禁页/登录过期)并打日志。
**不需要任何调试端口**,浏览器就是个普通 Edge 实例,可以常驻不关。
## 安装(一次性)
1. 用专用配置开 Edge(登录态 + CF 信任都在里面):
```
msedge.exe --user-data-dir="<repo>\hexi\data\nonebot_plugin_bf_bot\edge_profile"
```
2. 地址栏开 `edge://extensions` → 打开"开发人员模式" → "加载解压缩的扩展" → 选本目录。
3. 若有"开发者模式扩展"启动提示,保留即可(纯提醒,不影响)。
代码改动后在 `edge://extensions` 点该扩展的"刷新"按钮生效;SW 日志在扩展详情页点
"Service Worker" 检查。
## 联调(不启 bot)
```
.venv\Scripts\python.exe debug\bf2042_bridge_server.py # 手动浏览观察
.venv\Scripts\python.exe debug\bf2042_bridge_server.py --job EAID # 自动取数全流程
```
预期输出:先 "扩展已连接";手动打开任意 BF2042 profile 页会打印被动捕获;
`--job` 时扩展自动完成首页→站内跳转,打印 4 个响应,最后 "任务完成 keys=..."。
注意:bot 在跑时 39272 已被 bot 自己的扩展桥占用——要跑独立联调服务端得先停
bot(或临时改扩展 `background.js` 的端口常量)。bot 在跑时直接看 bot 日志里
"BF2042 扩展桥" 相关行即可,不用另起服务端。
## WebSocket 协议(v0)
服务端:`ws://127.0.0.1:39272/?token=hexi-bf2042`(仅回环 + 共享 token;
常量在 `background.js` 顶部,bot 侧对应配置项为 `bf_ext_ws_port`/`bf_ext_ws_token`,
两边保持一致)。
| 方向 | 消息 |
|---|---|
| ext→bot | `{"type":"hello","name":"hexi-bf2042-bridge","version":"0.1.0"}` |
| bot→ext | `{"type":"fetch","id":"...","player":"X","platform":"origin","profileUrl":"https://tracker.gg/bf2042/profile/origin/X/overview","apiBase":"https://api.tracker.gg/api/v2/bf2042/standard/profile/origin/X"}` |
| ext→bot | `{"type":"capture","id":null 或任务id,"key":"profile\|weapon\|vehicle\|soldier","url":"...","status":200,"body":{...}}` |
| ext→bot | `{"type":"job_done","id":"...","keys":["profile","weapon","vehicle"]}` |
| ext→bot | `{"type":"job_error","id":"...","keys":[...],"detail":"..."}` |
| 双向 | `{"type":"ping"}` |
- 无任务时的捕获以 `id: null` 被动转发。
- 任务的 URL 匹配"两遍 decode 再比",消除 python `quote()` 与 JS
`encodeURIComponent` 的转义差异。
- 任务期间只认自己驱动的标签页(`tabId` 过滤)。
## 注意
- 导航定律保留:首页 bootstrap → 站内跳转(`location.href`);深链直开会被挑战。
- MV3 SW 保活:活跃 WebSocket(Chromium 116+)+ `chrome.alarms`(30s)双保险,
bot 重启后扩展自动重连。
- 若手动浏览时页面有数据、扩展却捕获不到 → 该请求可能不经过页面 `fetch`/`XHR`
(如 Worker 发起)。届时把捕获后端换成 `chrome.debugger`(只开 Network 域),
管道其余部分不用动。
- 本目录不要放 `.py`(它是插件目录子目录的一部分,保持纯前端文件)。