Files
HeXi/hexi/plugins/nonebot_plugin_bf_bot/web/admin.py
T
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

77 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""BF查询 —— Web API 子应用(挂载到 /api/bf_bot):QQ↔EAID 绑定管理。
读写全部走 repository.py(与群里 /绑定 /解绑 命令改的是同一个库文件)。
鉴权走 hexi.web_hub.web_auth(OAuth2 + SQLite),与统一管理台 /hub 共用登录态。
**每条路由都要自带 `dependencies=[auth]`** —— mount 层没有兜底,漏一条就是匿名可访问。
前端页面:hexi/web/src/plugins/bf_bot/index.tsx。
"""
from __future__ import annotations
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from hexi.web_hub.web_auth import require_admin
from ..repository import UserManager
API = require_admin
def _ok(data=None, msg: str = "ok") -> JSONResponse:
return JSONResponse({"status": 0, "msg": msg, "data": data})
def _fail(msg: str, status: int = 400) -> JSONResponse:
return JSONResponse({"status": status, "msg": msg})
def build_admin_app() -> FastAPI:
"""构建绑定管理 API 子应用(挂载到 /api/bf_bot)。"""
app = FastAPI(title="BF查询绑定管理")
auth = require_admin
@app.get("/bindings", response_class=JSONResponse, dependencies=[auth])
async def list_bindings(page: int = 1, per_page: int = 10):
"""绑定列表(QQ / EA 名称 / EA 双 ID / 标签 / 绑定时间),按绑定时间倒序分页。"""
page = max(1, page)
per_page = min(max(1, per_page), 100)
manager = UserManager()
total = manager.count_users()
users = manager.list_users(limit=per_page, offset=(page - 1) * per_page)
return _ok(
{
"bindings": [
{
"qq_id": u.get("qq_id"),
"ea_player_name": u.get("ea_player_name"),
"ea_player_id": u.get("ea_player_id"),
"ea_user_id": u.get("ea_user_id"),
"designation": u.get("designation"),
"create_time": u.get("create_time"),
}
for u in users
],
"total": total,
"page": page,
"per_page": per_page,
}
)
@app.delete("/bindings/{qq_id}", response_class=JSONResponse, dependencies=[auth])
async def delete_binding(qq_id: str):
"""解绑某 QQ(等价于群里的「解绑」)。"""
manager = UserManager()
record = manager.get_user_by_qq(qq_id)
if not record:
return _fail("未找到该 QQ 的绑定记录", 404)
rows = manager.delete_user_by_qq(qq_id)
if rows > 0:
return _ok(
{"qq_id": qq_id, "ea_player_name": record.get("ea_player_name")},
f"已解绑 {record.get('ea_player_name')}",
)
return _fail("删除失败")
return app