Files
renjue 82581d2949 Implement full media crawler workflow with Flask backend and Vue frontend.
Add TMDB search and media detail pages, HDHive resource ingestion flow, unified error handling, Docker single-container runtime, and project docs/config updates for local deployment.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-09 16:16:18 +08:00

519 lines
15 KiB
Markdown
Raw Permalink 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.
# 接口列表
OpenAPI 分为两类接口:
- **用户授权接口**:以 `/api/public/openapi/oauth` 为前缀,用于授权预览、确认授权、换取 Token 和撤销 Token。
- **业务接口**:以 `/api/open` 为前缀,请求必须携带 `X-API-Key`。需要代表具体用户执行的接口,还应携带用户 Access Token个人 API Key 或绑定用户的应用可回退到绑定用户。
## 接口总览
### 用户授权接口
| 方法 | 路径 | 认证 | 说明 |
|---|---|---|---|
| GET | `/api/public/openapi/oauth/authorize` | 站内登录 Cookie | 授权页预览信息 |
| POST | `/api/public/openapi/oauth/authorize` | 站内登录 Cookie | 用户确认授权并生成授权码 |
| POST | `/api/public/openapi/oauth/token` | `X-API-Key` 应用 Secret | 授权码或刷新令牌换取用户 Token |
| POST | `/api/public/openapi/oauth/revoke` | `X-API-Key` 应用 Secret | 撤销刷新令牌 |
### 业务接口
| scope | 方法 | 路径 | 说明 |
|---|---|---|---|
| `meta` | GET | `/api/open/ping` | 健康检查 |
| `meta` | GET | `/api/open/quota` | 查询当前凭证配额状态 |
| `meta` | GET | `/api/open/usage` | 查询历史用量 |
| `meta` | GET | `/api/open/usage/today` | 查询今日用量 |
| `query` | GET | `/api/open/resources/:type/:tmdb_id` | 根据 TMDB ID 获取资源列表 |
| `query` | GET | `/api/open/shares/:slug` | 获取分享详情 |
| `query` | POST | `/api/open/check/resource` | 检查资源链接类型 |
| `unlock` | POST | `/api/open/resources/unlock` | 解锁资源 |
| `write` | GET | `/api/open/shares` | 获取我的分享列表 |
| `write` | POST | `/api/open/shares` | 创建分享 |
| `write` | PATCH | `/api/open/shares/:slug` | 更新分享 |
| `write` | DELETE | `/api/open/shares/:slug` | 删除分享 |
| `vip` | GET | `/api/open/me` | 获取当前用户信息 |
| `vip` | POST | `/api/open/checkin` | 每日签到 |
| `vip` | GET | `/api/open/vip/weekly-free-quota` | 获取长期 Premium 每周免费解锁状态 |
---
## 用户授权流程接口
第三方应用的用户授权入口应使用前端页面:
```text
GET /openapi/authorize?client_id=app_xxx&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcallback&scope=query%20unlock&state=opaque-state
```
前端页面会要求用户登录,并调用下面的后端授权接口。
---
## GET /api/public/openapi/oauth/authorize
获取授权页展示信息。该接口需要站内登录 Cookie未登录会返回 `401`,前端授权页会跳转到登录页。
### Query 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `client_id` | string | 是 | OpenAPI 应用公开 Client ID |
| `redirect_uri` | string | 是 | 授权完成回调地址,必须在应用配置中 |
| `scope` | string | 否 | 请求 scope空格分隔例如 `query unlock` |
| `state` | string | 否 | 第三方应用自定义状态 |
### 成功响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| `data.client_id` | string | 应用 Client ID |
| `data.app_name` | string | 应用名称 |
| `data.description` | string | 应用描述 |
| `data.auth_level` | string | 应用授权等级 |
| `data.redirect_uri` | string | 本次授权回调地址 |
| `data.requested_scopes` | string[] | 本次请求 scope |
| `data.allowed_scopes` | string[] | 应用实际允许 scope |
| `data.user` | object | 当前登录用户摘要 |
| `data.expires_in` | integer | 授权码有效期秒数 |
---
## POST /api/public/openapi/oauth/authorize
用户确认授权并生成授权码。该接口需要站内登录 Cookie。
该接口本身返回 JSON 给 HDHive 前端授权页。HDHive 前端收到 `data.code` 后,会重定向到第三方 `redirect_uri`,并追加 `code` 和原始 `state`
```text
https://client.example.com/callback?code=authorization-code&state=opaque-state
```
### Body 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `client_id` | string | 是 | OpenAPI 应用公开 Client ID |
| `redirect_uri` | string | 是 | 授权完成回调地址 |
| `scope` | string | 否 | 请求 scope空格分隔 |
| `state` | string | 否 | 第三方应用自定义状态 |
### 请求示例
```bash
curl -X POST https://hdhive.com/api/public/openapi/oauth/authorize \\
-H "Content-Type: application/json" \\
-d '{
"client_id": "app_xxx",
"redirect_uri": "https://client.example.com/callback",
"scope": "query unlock",
"state": "opaque-state"
}'
```
### 成功响应
```json
{
"success": true,
"code": "200",
"message": "success",
"data": {
"code": "authorization-code",
"redirect_uri": "https://client.example.com/callback",
"expires_in": 600
}
}
```
第三方应用通过自己的回调地址收到授权码后,应在服务端用应用 Secret 换取用户 Token。
---
## POST /api/public/openapi/oauth/token
使用授权码或刷新令牌换取 OpenAPI 用户 Token。该接口必须携带 OpenAPI 应用 Secret。
`redirect_uri` 只在 `authorization_code` 模式下需要。它不是跳转地址,而是授权码校验字段,必须与用户授权阶段传入的 `redirect_uri` 完全一致;后端会同时校验授权码、应用 Secret 和 `redirect_uri` 的绑定关系。
### Header
```http
X-API-Key: app-secret
Content-Type: application/json
```
### authorization_code Body
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `grant_type` | string | 是 | 固定为 `authorization_code` |
| `code` | string | 是 | 用户确认授权后得到的授权码 |
| `redirect_uri` | string | 是 | 安全校验字段,必须与授权码创建时传入的回调地址完全一致;不会触发跳转 |
### refresh_token Body
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `grant_type` | string | 是 | 固定为 `refresh_token` |
| `refresh_token` | string | 是 | 刷新令牌 |
### 请求示例
```bash
curl -X POST https://hdhive.com/api/public/openapi/oauth/token \\
-H "X-API-Key: app-secret" \\
-H "Content-Type: application/json" \\
-d '{
"grant_type": "authorization_code",
"code": "authorization-code",
"redirect_uri": "https://client.example.com/callback"
}'
```
### 成功响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| `data.access_token` | string | OpenAPI 用户 Access Token |
| `data.refresh_token` | string | Refresh Token刷新时可能返回新值 |
| `data.token_type` | string | 固定为 `Bearer` |
| `data.expires_in` | integer | Access Token 有效期秒数 |
| `data.refresh_expires_in` | integer | Refresh Token 有效期秒数 |
| `data.scope` | string | 空格分隔 scope |
| `data.scopes` | string[] | scope 数组 |
---
## POST /api/public/openapi/oauth/revoke
撤销某个 Refresh Token。撤销后该刷新令牌不能再换取新的用户 Access Token。
### Header
```http
X-API-Key: app-secret
Content-Type: application/json
```
### Body 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `refresh_token` | string | 是 | 要撤销的刷新令牌 |
### 请求示例
```bash
curl -X POST https://hdhive.com/api/public/openapi/oauth/revoke \\
-H "X-API-Key: app-secret" \\
-H "Content-Type: application/json" \\
-d '{"refresh_token": "refresh-token"}'
```
---
## GET /api/open/ping
健康检查接口,用于验证 API Key 是否有效。
### 请求示例
```bash
curl -H "X-API-Key: your-api-key" https://hdhive.com/api/open/ping
```
### 成功响应
```json
{
"success": true,
"code": "200",
"message": "success",
"data": {
"message": "pong",
"api_key_id": 1,
"name": "My App"
}
}
```
---
## GET /api/open/quota
查询当前 API Key 的配额状态。该接口用于展示服务端返回的当前状态,不应在客户端写死限制值。
### 请求示例
```bash
curl -H "X-API-Key: your-api-key" https://hdhive.com/api/open/quota
```
### 响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| `data.daily_reset` | integer | 配额重置时间 |
| `data.endpoint_limit` | integer / null | 当前接口限制状态,未配置时为空 |
| `data.endpoint_remaining` | integer / null | 当前接口剩余状态,未配置时为空 |
---
## GET /api/open/usage
查询当前 API Key 的历史用量统计。
### 请求参数
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| `start_date` | query | string | 否 | 开始日期,格式 `YYYY-MM-DD` |
| `end_date` | query | string | 否 | 结束日期,格式 `YYYY-MM-DD` |
### 请求示例
```bash
curl -H "X-API-Key: your-api-key" \\
"https://hdhive.com/api/open/usage?start_date=2026-04-01&end_date=2026-04-25"
```
### 响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| `data.daily_stats` | array | 每日调用统计 |
| `data.endpoint_stats` | array | 按接口聚合的统计 |
| `data.summary` | object | 汇总统计 |
---
## GET /api/open/resources/:type/:tmdb_id
根据媒体类型和 TMDB ID 获取资源列表。
### 请求参数
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| `type` | path | string | 是 | 媒体类型,`movie``tv` |
| `tmdb_id` | path | string | 是 | TMDB ID |
### 请求示例
```bash
curl -H "X-API-Key: your-api-key" \\
-H "Authorization: Bearer user-access-token" \\
https://hdhive.com/api/open/resources/movie/550
```
### 响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| `data[].slug` | string | 资源唯一标识 |
| `data[].title` | string / null | 资源标题 |
| `data[].pan_type` | string / null | 网盘类型 |
| `data[].share_size` | string / null | 分享文件大小 |
| `data[].video_resolution` | string[] | 视频分辨率 |
| `data[].source` | string[] | 片源 |
| `data[].subtitle_language` | string[] | 字幕语言 |
| `data[].subtitle_type` | string[] | 字幕类型 |
| `data[].unlock_points` | integer / null | 解锁所需积分 |
| `data[].is_unlocked` | boolean | 当前用户是否已解锁 |
| `data[].user` | object / null | 分享者信息 |
| `meta.total` | integer | 返回数量 |
---
## POST /api/open/resources/unlock
代表当前用户解锁资源并获取链接。第三方应用调用时应携带用户 Access Token。
### 请求参数
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| `slug` | body | string | 是 | 资源 slug支持带横杠或不带横杠的 UUID |
### 请求示例
```bash
curl -X POST \\
-H "X-API-Key: app-secret" \\
-H "Authorization: Bearer user-access-token" \\
-H "Content-Type: application/json" \\
-d '{"slug": "a1b2c3d4e5f647898765432112345678"}' \\
https://hdhive.com/api/open/resources/unlock
```
### 成功响应
```json
{
"success": true,
"code": "200",
"message": "解锁成功",
"data": {
"url": "https://pan.example.com/s/abc123",
"access_code": "x1y2",
"full_url": "https://pan.example.com/s/abc123?pwd=x1y2",
"already_owned": false
}
}
```
### 错误响应
| 场景 | HTTP 状态码 | 错误码 |
|---|---|---|
| 参数无效 | 400 | `400` |
| 缺少用户身份 | 403 | `OPENAPI_USER_REQUIRED` |
| 资源不存在 | 404 | `404` |
| 积分不足 | 402 | `INSUFFICIENT_POINTS` |
| 用户请求过快 | 429 | `RATE_LIMIT_EXCEEDED` |
> unlock 接口保留用户阶梯风控。第三方应用触发时,处罚对象是当前授权用户,不是整个应用。
---
## POST /api/open/check/resource
检查资源链接所属网盘类型,并尝试解析部分网盘的访问码。
### 请求参数
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| `url` | body | string | 是 | 资源分享链接 |
### 请求示例
```bash
curl -X POST \\
-H "X-API-Key: your-api-key" \\
-H "Authorization: Bearer user-access-token" \\
-H "Content-Type: application/json" \\
-d '{"url": "https://115.com/s/example 访问码:1234"}' \\
https://hdhive.com/api/open/check/resource
```
---
## GET /api/open/me
获取当前用户信息。该接口需要 `vip` scope并要求当前用户满足 Premium 条件。
### 请求示例
```bash
curl -H "X-API-Key: app-secret" \\
-H "Authorization: Bearer user-access-token" \\
https://hdhive.com/api/open/me
```
### 响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| `data.id` | number | 用户 ID |
| `data.nickname` | string | 昵称 |
| `data.username` | string | 用户名 |
| `data.email` | string | 邮箱 |
| `data.avatar_url` | string | 头像 |
| `data.is_vip` | boolean | 是否 Premium |
| `data.user_meta` | object | 用户积分、签到、分享等元信息 |
---
## POST /api/open/checkin
代表当前用户执行每日签到。该接口需要 `vip` scope并要求当前用户满足 Premium 条件。
### 请求参数
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| `is_gambler` | body | boolean | 否 | 是否使用高波动签到模式 |
---
## GET /api/open/vip/weekly-free-quota
获取当前用户长期 Premium 每周免费解锁状态。该接口只返回状态,不建议客户端假设配置固定。
### 响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| `is_forever_vip` | boolean | 是否长期 Premium |
| `limit` | int | 服务端当前配置的基础状态值 |
| `used` | int | 本周已使用次数 |
| `remaining` | int | 当前可用状态 |
| `unlimited` | boolean | 是否不限制 |
| `bonus_quota` | int | 累积状态值 |
| `bonus_quota_max` | int | 累积上限状态值 |
---
## GET /api/open/shares
获取当前用户的分享列表。需要 `write` scope。
### 请求参数
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| `page` | query | integer | 否 | 页码 |
| `page_size` | query | integer | 否 | 每页数量 |
---
## GET /api/open/shares/:slug
获取指定分享详情。该接口不返回资源下载链接和访问码,需要调用 unlock 接口解锁后获取。
---
## POST /api/open/shares
创建新的资源分享。需要 `write` scope。
### 关键参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `url` | string | 是 | 分享链接 |
| `tmdb_id` | string | 条件必填 | TMDB ID需配合 `media_type` |
| `media_type` | string | 条件必填 | `movie``tv` |
| `movie_id` | integer | 条件必填 | 系统电影 ID |
| `tv_id` | integer | 条件必填 | 系统电视剧 ID |
| `collection_id` | integer | 否 | 系统合集 ID |
| `title` | string | 否 | 资源标题 |
| `access_code` | string | 否 | 访问码 |
| `unlock_points` | integer | 否 | 解锁积分,未传或 0 表示免费 |
| `is_anonymous` | boolean | 否 | 是否匿名分享 |
| `hide_link` | boolean | 否 | 是否在通知中隐藏链接 |
> 影视关联至少需要提供 `tmdb_id + media_type`、`movie_id`、`tv_id` 或 `collection_id` 之一。
---
## PATCH /api/open/shares/:slug
部分更新已有分享。需要 `write` scope。只能更新自己创建的分享或当前用户具备对应权限的分享。
---
## DELETE /api/open/shares/:slug
删除分享。需要 `write` scope。只能删除自己创建的分享或当前用户具备对应权限的分享。
---
# 变更日志
| 日期 | 变更内容 |
|---|---|
| 2026-04-25 | 文档更新为新版 OpenAPI 应用授权、用户授权 Token、scope、限制与错误码口径 |