76 lines
2.8 KiB
Python
76 lines
2.8 KiB
Python
"""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
|