Files
HeXi/hexi/plugins/nonebot_plugin_bf_bot/browser_ext
sansenhoshiandClaude Code a31aab00e8 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>
2026-10-13 17:53:06 +08:00
..

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(它是插件目录子目录的一部分,保持纯前端文件)。