基于Rust的Phigros后端服务,提供绑定、存档解析、RKS计算以及单曲成绩查询等功能。
- 绑定Phigros的sessionToken
- 获取并解析Phigros存档
- 计算玩家RKS及其构成成绩 (B30, Best N)
- 查询单曲成绩
- 统一查询歌曲信息(支持ID、名称、别名)
- 生成B30/BN成绩图片
- 生成单曲成绩图片
- 生成RKS排行榜图片
- 统计图片生成次数并提供查询接口
该服务需要使用phi-plugin的数据文件,包括:
info.csv
(歌曲信息)difficulty.csv
(歌曲难度定数)nicklist.yaml
(歌曲别名)
这些文件默认位于项目根目录下的 info
文件夹内。路径可以在.env
中配置。
-
克隆仓库
git clone <repository-url> cd phi-backend-rust
-
创建
.env
文件 (可选, 用于自定义配置) 参考.env.example
文件创建.env
文件,可以配置数据库URL、服务器地址、端口和数据文件路径等。# 复制示例配置文件 cp .env.example .env # 然后按需修改 .env 中的配置
配置说明:
# 数据库URL,默认使用项目根目录的SQLite文件 DATABASE_URL=sqlite:phigros_bindings.db # 服务器配置 (可选,有默认值) # HOST=127.0.0.1 # PORT=8080 # 数据文件路径 (可选,默认使用项目根目录下的info文件夹) # INFO_DATA_PATH=info # --- 维护模式配置 (可选) --- # 手动开启维护模式 (true/false) # MAINTENANCE_MODE=false # 维护时返回的自定义信息 # MAINTENANCE_MESSAGE="服务器正在维护中,请稍后再试。" # 基于时间的维护窗口 (使用 RFC3339 格式, UTC 时区) # MAINTENANCE_START_TIME="2025-08-15T02:00:00Z" # MAINTENANCE_END_TIME="2025-08-15T04:00:00Z" # 基于 Cron 表达式的维护 (UTC 时区, 格式: 秒 分 时 日 月 周) # 例如,每天凌晨 2:00 (UTC) 开始的维护窗口 # MAINTENANCE_CRON="0 0 2 * * *"
注意:
.env
文件用于本地开发环境,不应提交到Git仓库。 -
编译项目
cargo build --release
-
运行服务
cargo run --release
服务将在配置的地址和端口启动(默认
127.0.0.1:8080
)。
所有接口均使用JSON格式进行数据交换。
GET /status
- 描述: 检查后端服务的健康状况。可用于监控、负载均衡和容器健康检查。
- 成功响应 (
200 OK
):{ "status": "ok" }
- 维护中响应 (
503 Service Unavailable
):{ "message": "服务器正在维护中,请稍后再试。" }
通用请求体:
IdentifierRequest
(用于需要用户身份的接口)- 请求体中必须包含
token
或 (platform
和platform_id
) 中的至少一组。 - 如果都提供,优先使用
token
。 platform
字段大小写不敏感。
// 方式一:使用 SessionToken { "token": "用户的Phigros SessionToken" } // 方式二:使用平台和平台ID (如果已绑定) { "platform": "qq", // 平台名称 (大小写不敏感) "platform_id": "用户的QQ号" }
- 请求体中必须包含
-
GET /auth/qrcode
或POST /auth/qrcode
- 描述: 生成用于TapTap账号登录的二维码图片(Base64编码)。
- 成功响应 (
200 OK
):{ "qrId": "唯一的二维码ID,用于查询状态", "qrCodeImage": "data:image/png;base64,xxxxxxxxxx..." // Base64编码的PNG图片数据 }
- 失败响应:
500 Internal Server Error
(二维码生成失败)。
-
GET /auth/qrcode/{qrId}/status
- 描述: 查询指定二维码的登录状态。
- 路径参数:
qrId
(通过/auth/qrcode
获取的二维码ID) - 成功响应 (
200 OK
):status: "pending"
: 等待用户扫描二维码。status: "scanned"
: 用户已扫描二维码,等待授权。status: "success"
: 用户已授权登录成功。{ "status": "success", "sessionToken": "用户的TapTap SessionToken" }
status: "expired"
: 二维码已过期(通常5分钟)。status: "error"
: 发生其他错误。
- 失败响应:
404 Not Found
:qrId
无效或已过期。500 Internal Server Error
: 其他内部错误。
-
POST /bind
- 描述: 绑定平台ID和Phigros SessionToken。
- 请求体:
{ "platform": "qq", // 平台名称 (大小写不敏感) "platform_id": "用户的QQ号", "token": "用户的Phigros SessionToken" }
- 成功响应 (
200 OK
):
{ "code": 200, "status": "success", "message": "绑定成功", // 或 "已更新...的Token", 或 "已绑定到现有内部用户" "data": { "internal_id": "生成的或已有的内部用户ID" } }
- 失败响应:
400 Bad Request
(参数错误),500 Internal Server Error
。
-
POST /token/list
- 描述: 获取用户关联的所有平台ID和Token列表。
- 请求体:
IdentifierRequest
- 成功响应 (
200 OK
):
{ "code": 200, "status": "success", "message": "获取Token列表成功", "data": { "internal_id": "用户内部ID", "bindings": [ { "platform": "qq", "platform_id": "123456", "session_token": "token_for_qq", "bind_time": "2025-01-01T12:00:00Z" } ] } }
- 失败响应:
400 Bad Request
,404 Not Found
,500 Internal Server Error
。
-
POST /unbind
- 描述: 解除指定平台账号的绑定。支持Token验证或简介验证。
- 请求体:
IdentifierRequest
(必须包含platform
,platform_id
; 可选token
或verification_code
) - 成功响应:
- Token验证成功:
200 OK
{ "code": 200, "status": "success", "message": "解绑成功 (平台ID+Token验证)" }
- 简介验证 - 获取验证码:
200 OK
{ "code": 200, "status": "verification_initiated", "message": "请在 xxx 秒内将您的 Phigros 简介修改为此验证码...", "data": { "verification_code": "ABCDEF12", "expires_in_seconds": "xxx" } }
- 简介验证 - 提交验证码成功:
200 OK
{ "code": 200, "status": "success", "message": "解绑成功 (简介验证)" }
- Token验证成功:
- 失败响应:
400 Bad Request
,401 Unauthorized
,404 Not Found
,500 Internal Server Error
。
-
POST /get/cloud/saves
- 描述: 获取并解析用户的Phigros云存档(不含难度定数和RKS)。
- 请求体:
IdentifierRequest
- 成功响应 (
200 OK
): 返回基础GameSave
结构。 - 失败响应:
401 Unauthorized
,404 Not Found
,500 Internal Server Error
。
-
POST /get/cloud/saves/with_difficulty
- 描述: 获取并解析用户的Phigros云存档,包含难度定数和计算出的RKS值。
- 请求体:
IdentifierRequest
- 成功响应 (
200 OK
): 返回包含difficulty
和rks
的GameSave
结构。 - 失败响应:
401 Unauthorized
,404 Not Found
,500 Internal Server Error
。
-
POST /get/cloud/saveInfo
- 描述: 获取原始的云存档元数据 (
saveInfo
)。这个JSON对象包含了存档文件的URL、校验和、更新时间等,但不包含游戏存档本身的内容。 - 请求体:
IdentifierRequest
- 成功响应 (
200 OK
): 返回原始的saveInfo
JSON对象。 - 失败响应:
401 Unauthorized
,404 Not Found
,500 Internal Server Error
。
- 描述: 获取原始的云存档元数据 (
-
POST /rks
- 描述: 计算并返回用户所有歌曲的RKS分数,按分数由高到低排序。
- 请求体:
IdentifierRequest
- 成功响应 (
200 OK
):
{ "code": 200, "status": "OK", "data": { "records": [ { "song_id": "...", "song_name": "...", "difficulty": "IN", "difficulty_value": ..., "acc": ..., "score": ..., "rks": ... } ] } }
- 失败响应:
401 Unauthorized
,404 Not Found
,500 Internal Server Error
。
-
POST /b30
- 描述: 计算并返回用户的B30成绩。
- 请求体:
IdentifierRequest
- 成功响应 (
200 OK
): 返回B30Result
结构。 - 失败响应:
401 Unauthorized
,404 Not Found
,500 Internal Server Error
。
-
POST /bn/{n}
- 描述: 计算并返回用户的 Best N 成绩。
- 路径参数:
n
(整数, 必须大于0) - 请求体:
IdentifierRequest
- 成功响应 (
200 OK
): 返回BnResult
结构。 - 失败响应:
400 Bad Request
,401 Unauthorized
,404 Not Found
,500 Internal Server Error
。
-
GET /song/search
(推荐)- 描述: 统一搜索歌曲信息。
- 查询参数:
q
(必需) - 搜索关键词 - 成功响应 (
200 OK
): 返回SongInfo
。 - 失败响应:
400 Bad Request
,404 Not Found
,409 Conflict
。
-
POST /song/search/record
(推荐)- 描述: 查询指定歌曲的成绩记录。
- 查询参数:
q
: (必需) 歌曲ID、名称或别名。difficulty
: (可选) 难度级别 (EZ, HD, IN, AT)。
- 请求体:
IdentifierRequest
- 成功响应 (
200 OK
): 返回该歌曲的SongRecord
。 - 失败响应:
400 Bad Request
,401 Unauthorized
,404 Not Found
,409 Conflict
。
-
GET /song/search/predictions
- 描述: 查询歌曲的预测常数信息。(待废弃)
- 查询参数:
q
(必需) - 搜索关键词difficulty
(可选) - 指定难度,如不提供则返回所有难度。
- 成功响应 (
200 OK
): 返回预测常数列表。 - 失败响应:
400 Bad Request
,404 Not Found
,409 Conflict
。
-
旧版兼容接口:
GET /song/info
和POST /song/record
依然可用,但推荐使用新的/song/search/*
接口。
-
POST /image/bn/{n}
- 描述: 生成用户的Best N成绩图片。
- 路径参数:
n
(整数, 必须大于0) - 请求体:
IdentifierRequest
- 成功响应 (
200 OK
): 返回二进制PNG格式的图片数据。 - 失败响应:
400 Bad Request
,401 Unauthorized
,404 Not Found
,500 Internal Server Error
。
-
POST /image/song
- 描述: 生成指定歌曲的成绩图片。
- 查询参数:
q
(必需) - 歌曲关键词。 - 请求体:
IdentifierRequest
- 成功响应 (
200 OK
): 返回二进制PNG格式的图片数据。 - 失败响应:
400 Bad Request
,401 Unauthorized
,404 Not Found
,409 Conflict
。
-
GET /image/leaderboard/rks
- 描述: 生成RKS排行榜图片。
- 查询参数:
limit
(可选) - 显示的玩家数量,默认为20。 - 成功响应 (
200 OK
): 返回二进制PNG格式的图片数据。 - 失败响应:
500 Internal Server Error
。
-
GET /image/stats
- 描述: 获取所有类型图片的生成统计信息。
- 成功响应 (
200 OK
): 返回包含各类型图片生成次数和最后更新时间的JSON对象。 - 失败响应:
500 Internal Server Error
。
-
GET /image/stats/{image_type}
- 描述: 获取指定类型图片的生成统计信息。
- 路径参数:
image_type
(字符串, 可选值:bn
,song
,leaderboard
) - 成功响应 (
200 OK
): 返回指定类型图片的生成次数和最后更新时间。 - 失败响应:
400 Bad Request
,500 Internal Server Error
。
-
GET /image/cache/stats
- 描述: 获取图片缓存的统计信息,包括命中率等。
- 成功响应 (
200 OK
): 返回包含各图片缓存命中率和统计信息的JSON对象。 - 失败响应:
500 Internal Server Error
。
系统使用以下主要数据模型:
-
内部用户 (InternalUser)
- 每个用户都有一个系统生成的内部ID (
internal_id
)。 - 包含可选的昵称和用户相关信息。
- 每个用户都有一个系统生成的内部ID (
-
平台绑定 (PlatformBinding)
- 关联内部用户ID与各平台账号。
- 一个内部用户可以关联多个平台账号。
- 每个平台账号绑定一个SessionToken。
- 平台名称 (
platform
) 大小写不敏感。
-
验证码 (UnbindVerificationCode)
- 用于验证解绑请求。
- 通过平台名称和平台ID关联到特定绑定。
-
存档 (GameSave)
- 包含玩家游戏进度、设置和成绩记录 (
game_record
)。 game_record
是一个嵌套的HashMap
,结构为Map<SongId, Map<DifficultyString, SongRecord>>
。SongRecord
包含score
,acc
,fc
,difficulty
(定数),rks
等字段。
- 包含玩家游戏进度、设置和成绩记录 (
-
RKS记录 (RksRecord)
- 用于计算和展示RKS相关的成绩,通常按RKS值排序。
-
图片计数器 (ImageCounter)
- 用于统计各类型图片的生成次数。
- 包含图片类型、生成次数和最后更新时间。
如果你想使用 Docker 运行 Phi-Backend,本项目提供了 Dockerfile 和 docker-compose.yml 文件。
-
使用 Docker Compose (推荐)
使用 Docker Compose 可以更简单地管理容器、数据卷和环境变量。
# 确保Docker和Docker Compose已安装 # 启动服务 docker-compose up -d # 查看日志 docker-compose logs -f
服务将在
http://<your-host>:8080
启动。 -
手动使用 Docker
你也可以手动构建和运行Docker镜像。
# 构建镜像 docker build -t phi-backend . # 创建数据目录 mkdir -p data info # 运行容器 docker run -d --name phi-backend \ -p 8080:8080 \ -v $(pwd)/data:/app/data \ -v $(pwd)/info:/app/info \ -e DATABASE_URL=sqlite:/app/data/phigros_bindings.db \ -e INFO_DATA_PATH=/app/info \ -e HOST=0.0.0.0 \ phi-backend
在 Docker 环境中,你可以通过环境变量设置配置,无需使用 .env
文件。关键的环境变量有:
DATABASE_URL
: 数据库连接URL (例如sqlite:/app/data/phigros_bindings.db
)INFO_DATA_PATH
: 数据文件目录 (例如/app/info
)HOST
: 绑定的主机地址,在容器中通常为0.0.0.0
PORT
: 服务端口号RUST_LOG
: 日志级别
这些环境变量可以在 docker-compose.yml
的 environment
部分进行配置,或在 docker run
命令中通过 -e
参数设置。
Docker 配置使用卷映射来持久化数据:
./data:/app/data
: 存储数据库文件./info:/app/info
: 存储歌曲信息文件
确保这些目录在宿主机上存在并且包含必要的文件。
在使用 Phi-Backend 之前,请确保 info
目录中包含必要的数据文件 (info.csv
, difficulty.csv
, nicklist.yaml
),这些可以从 phi-plugin 获取。
该项目的大部分代码由LLM生成,
设计和部分数据处理逻辑参考了 phi-plugin , 扫码登录参考了PhiLogin
在此一并表示感谢awa