Archived
## uv 环境管理 - pyproject.toml 声明 dependencies + [dependency-groups].dev,uv.lock 精确锁定 - 删除 requirements.txt / requirements-fastapi.txt / requirements-dev.txt - .python-version = 3.12;Dockerfile 改用 uv sync --frozen(可复现构建) - 新增 jinja2(首页渲染) ## 删除 Flask 技术债 - 从 main.py 用 ast 精确剥离 56 个 Flask 节点(路由/中间件/错误处理/启动), 框架无关的服务层落为 services/runtime.py(MusicAPIService、下载/打包 worker、 任务监控、缓存清扫),零 Flask 依赖 - 删除 main.py(4527 行)与 auth_routes.py(1050 行) - auth_system.py 移除会话/请求上下文层(login_session/current_user/login_required/ admin_required/_client_ip 等),保留数据与业务层 - 新增 core/net.py(IP 解析)、web/auth_state.py(登录锁定/2FA 票据/发码限流) - FastAPI 侧改直接依赖 services.runtime,不再 import main - web/app.py 去掉 Flask fallback;入口默认根路径模式(API_PREFIX 可选) ## 删除 requests 技术债 - 新增 core/sync_http.py:requests 风格的同步门面(底层 aiohttp 连接池, 流式读取经有界队列背压),含 Session/headers/(connect,read) 元组超时兼容 - core/utils、auth_system、podcast_api、music_downloader、services 全部切换 - 实测真实下载 5.2MB 音频完整成功 ## 质量门禁归零 - ruff:0 错误(B904 全部修复,不再忽略) - pyright:0 错误(类型收窄修复) - pytest:140/140(含 golden 契约回归、root 模式 66 项路径覆盖) - 真实 uvicorn 启动:/health、/、/static、受保护端鉴权全部正确 新增 tests/golden/responses.json:删除 Flask 前捕获的 32 例响应快照, FastAPI 逐字段复现——删除巨石后行为回归仍有硬证据。
540 lines
10 KiB
JSON
540 lines
10 KiB
JSON
[
|
||
{
|
||
"name": "health",
|
||
"auth": "none",
|
||
"method": "GET",
|
||
"path": "/health",
|
||
"payload": null,
|
||
"status": 200,
|
||
"body": {
|
||
"data": {
|
||
"cookie_count": 3,
|
||
"cookie_status": "valid",
|
||
"downloads_dir": "configured",
|
||
"service": "running",
|
||
"timestamp": 1790391125,
|
||
"version": "2.4.0"
|
||
},
|
||
"message": "API服务运行正常",
|
||
"status": 200,
|
||
"success": true
|
||
}
|
||
},
|
||
{
|
||
"name": "api_info",
|
||
"auth": "none",
|
||
"method": "GET",
|
||
"path": "/api/info",
|
||
"payload": null,
|
||
"status": 200,
|
||
"body": {
|
||
"data": {
|
||
"config": {
|
||
"downloads_dir": "configured",
|
||
"max_body_bytes": "2MB(备份上传 200MB)"
|
||
},
|
||
"description": "云村小助手 · 网易云音乐解析/下载服务",
|
||
"endpoints": {
|
||
"/album": "GET/POST - 获取专辑详情",
|
||
"/api/info": "GET - API信息",
|
||
"/api/playlist/play": "GET/POST - 公开歌单播放API(id/level/limit)",
|
||
"/download": "POST - 下载音乐(付费动作仅接受 POST)",
|
||
"/global/playlist": "GET/POST - 全局账号歌单详情",
|
||
"/global/playlists": "GET/POST - 全局账号歌单列表",
|
||
"/health": "GET - 健康检查",
|
||
"/playlist": "GET/POST - 获取歌单详情",
|
||
"/podcast/download": "POST - 播客单集下载",
|
||
"/podcast/download/batch_zip": "POST - 整台播客打包ZIP",
|
||
"/podcast/hot": "GET/POST - 热门播客与分类",
|
||
"/podcast/parse": "GET/POST - 播客解析(电台/单集)",
|
||
"/podcast/programs": "GET/POST - 播客单集列表(分页)",
|
||
"/podcast/search": "GET/POST - 播客搜索",
|
||
"/search": "GET/POST - 搜索音乐",
|
||
"/song": "GET/POST - 获取歌曲信息"
|
||
},
|
||
"name": "云村小助手API服务",
|
||
"supported_qualities": [
|
||
"standard",
|
||
"exhigh",
|
||
"lossless",
|
||
"hires",
|
||
"sky",
|
||
"jyeffect",
|
||
"jymaster",
|
||
"dolby"
|
||
],
|
||
"version": "2.4.0"
|
||
},
|
||
"message": "API信息获取成功",
|
||
"status": 200,
|
||
"success": true
|
||
}
|
||
},
|
||
{
|
||
"name": "toplist_unauth",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/toplist",
|
||
"payload": {},
|
||
"status": 401,
|
||
"body": {
|
||
"error_code": "unauthorized",
|
||
"message": "请先登录后再使用解析功能",
|
||
"status": 401,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "user_status_unauth",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/user/status",
|
||
"payload": {},
|
||
"status": 200,
|
||
"body": {
|
||
"data": {
|
||
"cookie": {
|
||
"is_valid": false
|
||
},
|
||
"user": null
|
||
},
|
||
"message": "个人账号未登录",
|
||
"status": 200,
|
||
"success": true
|
||
}
|
||
},
|
||
{
|
||
"name": "user_logout",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/user/logout",
|
||
"payload": {},
|
||
"status": 200,
|
||
"body": {
|
||
"data": {
|
||
"is_valid": false
|
||
},
|
||
"message": "已退出登录",
|
||
"status": 200,
|
||
"success": true
|
||
}
|
||
},
|
||
{
|
||
"name": "auth_trial",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/auth/trial",
|
||
"payload": {},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "注册即送 3 次免费下载次数,请直接注册账号",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "auth_sendcode_badpurpose",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/auth/send_code",
|
||
"payload": {
|
||
"email": "x@y.com",
|
||
"purpose": "bad"
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "验证码用途不正确",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "auth_register_shortuser",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/auth/register",
|
||
"payload": {
|
||
"username": "ab",
|
||
"password": "12345678",
|
||
"email": "a@b.com",
|
||
"code": "x",
|
||
"agree": "1"
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "用户名需 3-20 位,仅支持中文、字母、数字、下划线,且不能纯下划线",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "auth_register_noagree",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/auth/register",
|
||
"payload": {
|
||
"username": "abcdef",
|
||
"password": "12345678",
|
||
"email": "a@b.com",
|
||
"code": "x",
|
||
"agree": "0"
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "请先阅读并同意《用户协议》与《隐私政策》",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "auth_register_badcode",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/auth/register",
|
||
"payload": {
|
||
"username": "abcdef",
|
||
"password": "12345678",
|
||
"email": "a@b.com",
|
||
"code": "zz",
|
||
"agree": "1"
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "邮箱验证码错误或已过期",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "auth_redeem_unauth",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/auth/redeem",
|
||
"payload": {
|
||
"code": "X"
|
||
},
|
||
"status": 401,
|
||
"body": {
|
||
"error_code": "unauthorized",
|
||
"message": "请先登录",
|
||
"status": 401,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "auth_forgot_shortpwd",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/auth/forgot_password",
|
||
"payload": {
|
||
"email": "a@b.com",
|
||
"code": "x",
|
||
"password": "short"
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "新密码长度需在 8-128 位之间",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "admin_logs_forbidden",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/admin/logs",
|
||
"payload": {},
|
||
"status": 403,
|
||
"body": {
|
||
"message": "需要管理员权限,请使用管理员账号登录",
|
||
"status": 403,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "admin_site_users_forbidden",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/admin/site/users",
|
||
"payload": {},
|
||
"status": 403,
|
||
"body": {
|
||
"error_code": "forbidden",
|
||
"message": "需要管理员权限",
|
||
"status": 403,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "admin_qr_forbidden",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/admin/qr/create",
|
||
"payload": {},
|
||
"status": 403,
|
||
"body": {
|
||
"message": "需要管理员权限,请使用管理员账号登录",
|
||
"status": 403,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "global_playlists_forbidden",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/global/playlists",
|
||
"payload": {},
|
||
"status": 403,
|
||
"body": {
|
||
"error_code": "forbidden",
|
||
"message": "需要管理员权限",
|
||
"status": 403,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "download_unauth",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/download",
|
||
"payload": {
|
||
"id": "1"
|
||
},
|
||
"status": 401,
|
||
"body": {
|
||
"error_code": "unauthorized",
|
||
"message": "请先登录后再使用解析功能",
|
||
"status": 401,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "download_badid",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/download",
|
||
"payload": {
|
||
"id": "abc"
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "无效的歌曲 ID",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "download_badquality",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/download",
|
||
"payload": {
|
||
"id": "347230",
|
||
"quality": "nope"
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "无效的音质参数,支持: standard, exhigh, lossless, hires, sky, jyeffect, jymaster, dolby",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "task_list_unauth",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/api/task/list",
|
||
"payload": {
|
||
"device_id": "x"
|
||
},
|
||
"status": 401,
|
||
"body": {
|
||
"error_code": "unauthorized",
|
||
"message": "请先登录后再使用解析功能",
|
||
"status": 401,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "task_cancel_unauth",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/api/task/cancel",
|
||
"payload": {
|
||
"task_id": "x"
|
||
},
|
||
"status": 401,
|
||
"body": {
|
||
"error_code": "unauthorized",
|
||
"message": "请先登录后再使用解析功能",
|
||
"status": 401,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "queue",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/api/queue",
|
||
"payload": {},
|
||
"status": 200,
|
||
"body": {
|
||
"data": {
|
||
"avg_batch_seconds": null,
|
||
"batch_active": 0,
|
||
"batch_capacity": 3,
|
||
"batch_waiting": 0,
|
||
"download_active": 0,
|
||
"download_capacity": 10,
|
||
"download_waiting": 0
|
||
},
|
||
"message": "获取排队状态成功",
|
||
"status": 200,
|
||
"success": true
|
||
}
|
||
},
|
||
{
|
||
"name": "delivery_404",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/download/result",
|
||
"payload": {
|
||
"task_id": "nope"
|
||
},
|
||
"status": 404,
|
||
"body": {
|
||
"message": "任务不存在或已过期",
|
||
"status": 404,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "delivery_batch_404",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/download/batch_zip/result",
|
||
"payload": {
|
||
"task_id": "nope"
|
||
},
|
||
"status": 404,
|
||
"body": {
|
||
"message": "任务不存在或已过期",
|
||
"status": 404,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "fe_error_nomsg",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/api/fe_error",
|
||
"payload": {},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "缺少 msg 参数",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "play_badkey",
|
||
"auth": "none",
|
||
"method": "POST",
|
||
"path": "/api/playlist/play",
|
||
"payload": {
|
||
"id": 3778678
|
||
},
|
||
"status": 401,
|
||
"body": {
|
||
"message": "需要有效的 API 密钥(请联系站点管理员获取)",
|
||
"status": 401,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "podcast_programs_badid",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/podcast/programs",
|
||
"payload": {
|
||
"radio_id": "abc"
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "无效的电台 ID",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "song_badid",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/song",
|
||
"payload": {
|
||
"id": "abc"
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "无效的歌曲ID,请输入数字ID或分享链接",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "comments_badid",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/comments",
|
||
"payload": {
|
||
"id": "abc"
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "无效的歌曲ID,请输入数字ID或分享链接",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "playlist_badid",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/playlist",
|
||
"payload": {
|
||
"id": ""
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "参数 'playlist_id' 不能为空",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "album_badid",
|
||
"auth": "user",
|
||
"method": "POST",
|
||
"path": "/album",
|
||
"payload": {
|
||
"id": "abc"
|
||
},
|
||
"status": 400,
|
||
"body": {
|
||
"message": "无效的专辑ID,请输入数字ID或分享链接",
|
||
"status": 400,
|
||
"success": false
|
||
}
|
||
},
|
||
{
|
||
"name": "index",
|
||
"auth": "none",
|
||
"method": "GET",
|
||
"path": "/",
|
||
"payload": null,
|
||
"status": 200,
|
||
"body": null,
|
||
"html_len": 466261,
|
||
"html_sha256": "5ba897c2f07b43b6c34e998505fea385cb6a6c8bfd5115d014f80044a38c6200"
|
||
}
|
||
] |