wd21 commited on
Commit
faabffb
·
verified ·
1 Parent(s): 7e51849

Upload README.md

Browse files
Files changed (1) hide show
  1. README.md +1004 -13
README.md CHANGED
@@ -1,19 +1,1010 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
- title: "hdapi"
3
- emoji: "🐝"
4
- colorFrom: "blue"
5
- colorTo: "purple"
6
- sdk: "docker"
7
- app_port: 8890
8
- pinned: false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  ---
10
 
11
- # HDHive API Test Client
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- 这是一个 HDHive Open API 的测试客户端,提供 Web 控制台和代理接口。
 
 
 
 
 
 
14
 
15
- - 本地 HTTP 服务监听 8890 端口
16
- - 支持 TMDB 搜索、资源查询、解锁、分享管理
17
- - 内置 Web 控制台(`/`)
18
 
19
- 详细文档参考项目 README。
 
 
 
1
+ # HDHive API Test Client
2
+
3
+ 独立的 HDHive Open API 测试客户端
4
+
5
+ 目标:
6
+
7
+ - 直接封装 `HDHive Open API` 文档中的接口
8
+ - 对上游 JSON 响应尽量原样透传
9
+ - 独立暴露本地 HTTP API,方便先验证查询、解锁、分享管理链路
10
+ - 提供一个内置 Web 控制台,方便可视化查看配额、响应头、原始 JSON 和调试请求
11
+ - 在内置 Web 控制台里额外提供一个“封装搜索”工作流,方便先用 TMDB 搜索,再批量处理 HDHive 资源
12
+
13
+ ## 启动
14
+
15
+ 在仓库根目录执行:
16
+
17
+ ```bash
18
+ go run ./hdhive-api
19
+ ```
20
+
21
+ 或先构建:
22
+
23
+ ```bash
24
+ go build -o ./bin/hdhive-test ./hdhive-api
25
+ ./bin/hdhive-test
26
+ ```
27
+
28
+ ## 环境变量
29
+
30
+ - `HDHIVE_LISTEN_ADDR`
31
+ 默认 `:8890`
32
+ - `HDHIVE_BASE_URL`
33
+ 默认 `https://hdhive.com`
34
+ - `HDHIVE_API_KEY`
35
+ 默认空。若请求头未传 `X-API-Key`,则使用这里的默认值
36
+ - `TMDB_API_KEY`
37
+ 默认空。若请求头未传 `X-TMDB-API-Key`,则使用这里的默认值
38
+ - `TMDB_BASE_URL`
39
+ 默认 `https://api.tmdb.org`,本地服务会自动按 v3 路径拼成 `https://api.tmdb.org/3`
40
+ - `HDHIVE_TIMEOUT_SECONDS`
41
+ 默认 `20`
42
+ - `GIN_MODE`
43
+ 默认 `release`
44
+
45
+ ## API 总览
46
+
47
+ 本地服务默认监听 `http://localhost:8890`。
48
+
49
+ Web 控制台入口:
50
+
51
+ - [`GET /`](#get-)
52
+ 打开内置测试页面,统一操作所有已实现接口
53
+
54
+ ### 本地辅助接口
55
+
56
+ - [`GET /healthz`](#get-healthz)
57
+ 本地健康检查,不请求上游
58
+
59
+ ### 通用接口
60
+
61
+ - [`GET /api/open/ping`](#get-apiopenping)
62
+ 验证 API Key 是否有效
63
+ - [`GET /api/open/quota`](#get-apiopenquota)
64
+ 查询当前 API Key 配额
65
+ - [`GET /api/open/usage`](#get-apiopenusage)
66
+ 查询用量统计
67
+ - [`GET /api/open/usage/today`](#get-apiopenusagetoday)
68
+ 查询今日用量
69
+
70
+ ### TMDB 接口
71
+
72
+ - [`GET /api/tmdb/configuration`](#get-apitmdbconfiguration)
73
+ 获取 TMDB 配置,例如图片基础地址
74
+ - [`GET /api/tmdb/configuration/primary_translations`](#get-apitmdbconfigurationprimary_translations)
75
+ 获取 TMDB 官方支持的 primary translation code 列表
76
+ - [`GET /api/tmdb/search/:media_type`](#get-apitmdbsearchmedia_type)
77
+ 按 `movie`、`tv` 或 `multi` 搜索 TMDB 原始结果
78
+ - [`GET /api/tmdb/:media_type/:media_id`](#get-apitmdbmedia_typemedia_id)
79
+ 获取指定 `movie` 或 `tv` 的 TMDB 原始详情
80
+
81
+ ### 资源接口
82
+
83
+ - [`GET /api/open/resources/:type/:tmdb_id`](#get-apiopenresourcestypetmdb_id)
84
+ 根据媒体类型和 TMDB ID 获取资源列表
85
+ - [`POST /api/open/resources/unlock`](#post-apiopenresourcesunlock)
86
+ 解锁资源,返回链接或访问码
87
+ - [`POST /api/open/check/resource`](#post-apiopencheckresource)
88
+ 检查分享链接所属网盘类型
89
+
90
+ ### 分享管理接口
91
+
92
+ - [`GET /api/open/shares`](#get-apiopenshares)
93
+ 获取我的分享列表
94
+ - [`GET /api/open/shares/:slug`](#get-apiopensharesslug)
95
+ 获取指定分享详情
96
+ - [`POST /api/open/shares`](#post-apiopenshares)
97
+ 创建分享
98
+ - [`PATCH /api/open/shares/:slug`](#patch-apiopensharesslug)
99
+ 更新分享
100
+ - [`DELETE /api/open/shares/:slug`](#delete-apiopensharesslug)
101
+ 删除分享
102
+
103
+ ## 通用说明
104
+
105
+ ### 认证方式
106
+
107
+ 所有 `/api/open/*` 接口都需要 API Key。
108
+
109
+ 优先级:
110
+
111
+ 1. 请求头 `X-API-Key`
112
+ 2. 环境变量 `HDHIVE_API_KEY`
113
+
114
+ 请求头示例:
115
+
116
+ ```http
117
+ X-API-Key: your-api-key-here
118
+ ```
119
+
120
+ ### 响应行为
121
+
122
+ - 所有已实现的 `/api/open/*` 接口都尽量原样透传上游响应
123
+ - 所有已实现的 `/api/tmdb/*` 接口都尽量原样透传 TMDB 原始响应
124
+ - 会保留关键响应头:
125
+ - `Content-Type`
126
+ - `X-RateLimit-Reset`
127
+ - `X-Endpoint-Limit`
128
+ - `X-Endpoint-Remaining`
129
+ - `Retry-After`
130
+
131
+ ### 内置 Web 控制台补充说明
132
+
133
+ `GET /` 返回的控制台除了原始 API 调试外,还内置了一个“封装搜索”页面,行为如下:
134
+
135
+ - 按关键词同时搜索 `movie + tv`
136
+ - 通过 TMDB 搜索结果选择具体媒体后,再调用 `GET /api/open/resources/:type/:tmdb_id`
137
+ - 默认仅自动处理当前用户可直接获取的资源
138
+ - 可选显示收费资源;收费资源默认仅展示,不会自动扣积分
139
+ - 收费资源需要用户手动逐个点击解锁
140
+ - 解锁得到的链接支持直接点击复制
141
+ - 资源解锁结果会显示 `pan_type`,并支持按网盘类型筛选免费 / 收费资源列表
142
+
143
+ 该页面还做了两层本地优化:
144
+
145
+ 1. 失效资源预过滤
146
+ - 若 `GET /api/open/resources/:type/:tmdb_id` 返回的某条资源同时满足:
147
+ - `validate_status == "invalid"`
148
+ - 且 `validate_message` 包含 `链接无效` 或 `链接已失效`
149
+ - 则该资源会在前端封装搜索流程中直接忽略,不再继续请求详情和解锁接口
150
+
151
+ 2. 解锁结果缓存
152
+ - 对成功解锁得到的结果按 `服务端地址 + API Key + slug` 进行本地缓存
153
+ - 自动解锁免费资源时会优先读取缓存
154
+ - 收费资源手动解锁时也会优先读取缓存
155
+ - 当前缓存有效期为 24 小时
156
+ - 缓存仅影响 `GET /` 返回的内置控制台,不会改变服务端 API 本身的返回
157
+
158
+ ## 接口详情
159
+
160
+ ### `GET /`
161
+
162
+ 本地 Web 控制台入口,不请求上游。
163
+
164
+ 功能:
165
+
166
+ - 可视化填写 API Key
167
+ - 直接测试所有已实现的 Open API 接口
168
+ - 在页面右侧查看状态码、关键响应头、原始 JSON、请求摘要和 cURL
169
+ - 提供一个封装搜索界面,串联 TMDB 搜索与 HDHive 资源处理
170
+ - 封装搜索界面支持免费/收费资源分栏查看、网盘类型筛选、分页、手动解锁和链接复制
171
+ - 封装搜索界面内置失效资源过滤与解锁缓存
172
+
173
+ 请求示例:
174
+
175
+ 直接在浏览器打开:
176
+
177
+ ```text
178
+ http://localhost:8890/
179
+ ```
180
+
181
+ 返回:
182
+
183
+ - `text/html`
184
+ - 一个内置的单页测试控制台
185
+
186
  ---
187
+
188
+ ### `GET /healthz`
189
+
190
+ 本地健康检查接口,不请求上游。
191
+
192
+ 功能:
193
+
194
+ - 用于确认测试客户端进程是否已启动
195
+ - 返回当前配置的上游地址
196
+
197
+ 请求示例:
198
+
199
+ ```bash
200
+ curl http://localhost:8890/healthz
201
+ ```
202
+
203
+ 返回示例:
204
+
205
+ ```json
206
+ {
207
+ "success": true,
208
+ "message": "ok",
209
+ "upstream": "https://hdhive.com/api/open"
210
+ }
211
+ ```
212
+
213
+ 返回字段:
214
+
215
+ | 字段 | 类型 | 说明 |
216
+ |------|------|------|
217
+ | `success` | boolean | 固定为 `true` |
218
+ | `message` | string | 固定为 `ok` |
219
+ | `upstream` | string | 当前上游 Open API 地址 |
220
+
221
  ---
222
 
223
+ ### `GET /api/open/ping`
224
+
225
+ 功能:
226
+
227
+ - 健康检查
228
+ - 验证 API 密钥是否有效
229
+
230
+ 请求示例:
231
+
232
+ ```bash
233
+ curl -H "X-API-Key: your-api-key" \
234
+ http://localhost:8890/api/open/ping
235
+ ```
236
+
237
+ 成功响应:
238
+
239
+ ```json
240
+ {
241
+ "success": true,
242
+ "code": "200",
243
+ "message": "success",
244
+ "data": {
245
+ "message": "pong",
246
+ "api_key_id": 1,
247
+ "name": "My App"
248
+ }
249
+ }
250
+ ```
251
+
252
+ 响应字段:
253
+
254
+ | 字段 | 类型 | 说明 |
255
+ |------|------|------|
256
+ | `data.message` | string | 固定返回 `pong` |
257
+ | `data.api_key_id` | integer | 当前 API Key ID |
258
+ | `data.name` | string | 当前 API Key 名称 |
259
+
260
+ ---
261
+
262
+ ### `GET /api/open/quota`
263
+
264
+ 功能:
265
+
266
+ - 获取当前 API Key 的配额信息
267
+
268
+ 请求示例:
269
+
270
+ ```bash
271
+ curl -H "X-API-Key: your-api-key" \
272
+ http://localhost:8890/api/open/quota
273
+ ```
274
+
275
+ 成功响应:
276
+
277
+ ```json
278
+ {
279
+ "success": true,
280
+ "code": "200",
281
+ "message": "success",
282
+ "data": {
283
+ "daily_reset": 1707494400,
284
+ "endpoint_limit": 1000,
285
+ "endpoint_remaining": 850
286
+ }
287
+ }
288
+ ```
289
+
290
+ 响应字段:
291
+
292
+ | 字段 | 类型 | 说明 |
293
+ |------|------|------|
294
+ | `data.daily_reset` | integer | 配额重置时间(Unix 时间戳,北京时间次日 00:00) |
295
+ | `data.endpoint_limit` | integer / null | 当前接口每日配额上限 |
296
+ | `data.endpoint_remaining` | integer / null | 当前接口今日剩余配额 |
297
+
298
+ ---
299
+
300
+ ### `GET /api/open/usage`
301
+
302
+ 功能:
303
+
304
+ - 获取当前 API Key 的用量统计
305
+ - 包含每日统计、接口统计、汇总数据
306
+
307
+ 请求参数:
308
+
309
+ | 参数 | 位置 | 类型 | 必填 | 说明 |
310
+ |------|------|------|------|------|
311
+ | `start_date` | query | string | 否 | 开始日期,格式 `YYYY-MM-DD` |
312
+ | `end_date` | query | string | 否 | 结束日期,格式 `YYYY-MM-DD` |
313
+
314
+ 请求示例:
315
+
316
+ ```bash
317
+ curl -H "X-API-Key: your-api-key" \
318
+ "http://localhost:8890/api/open/usage?start_date=2025-01-01&end_date=2025-01-31"
319
+ ```
320
+
321
+ 成功响应:
322
+
323
+ ```json
324
+ {
325
+ "success": true,
326
+ "code": "200",
327
+ "message": "success",
328
+ "data": {
329
+ "daily_stats": [
330
+ { "date": "2025-01-01", "total_calls": 120 },
331
+ { "date": "2025-01-02", "total_calls": 85 }
332
+ ],
333
+ "endpoint_stats": [
334
+ { "endpoint": "/api/open/resources/:type/:tmdb_id", "total_calls": 150 },
335
+ { "endpoint": "/api/open/resources/unlock", "total_calls": 55 }
336
+ ],
337
+ "summary": {
338
+ "total_calls": 205,
339
+ "success_calls": 200,
340
+ "failed_calls": 5,
341
+ "avg_latency": 123.45
342
+ }
343
+ }
344
+ }
345
+ ```
346
+
347
+ 响应字段:
348
+
349
+ | 字段 | 类型 | 说明 |
350
+ |------|------|------|
351
+ | `data.daily_stats` | array | 每日调用统计 |
352
+ | `data.daily_stats[].date` | string | 日期 |
353
+ | `data.daily_stats[].total_calls` | integer | 当日总调用次数 |
354
+ | `data.endpoint_stats` | array | 按接口分组统计 |
355
+ | `data.endpoint_stats[].endpoint` | string | 接口路径 |
356
+ | `data.endpoint_stats[].total_calls` | integer | 该接口总调用次数 |
357
+ | `data.summary.total_calls` | integer | 总调用次数 |
358
+ | `data.summary.success_calls` | integer | 成功调用次数 |
359
+ | `data.summary.failed_calls` | integer | 失败调用次数 |
360
+ | `data.summary.avg_latency` | number | 平均响应延迟(毫秒) |
361
+
362
+ ---
363
+
364
+ ### `GET /api/open/usage/today`
365
+
366
+ 功能:
367
+
368
+ - 获取当前 API Key 的今日用量统计
369
+
370
+ 请求示例:
371
+
372
+ ```bash
373
+ curl -H "X-API-Key: your-api-key" \
374
+ http://localhost:8890/api/open/usage/today
375
+ ```
376
+
377
+ 成功响应:
378
+
379
+ ```json
380
+ {
381
+ "success": true,
382
+ "code": "200",
383
+ "message": "success",
384
+ "data": {
385
+ "total_calls": 50,
386
+ "success_calls": 48,
387
+ "failed_calls": 2,
388
+ "avg_latency": 98.76
389
+ }
390
+ }
391
+ ```
392
+
393
+ 响应字段:
394
+
395
+ | 字段 | 类型 | 说明 |
396
+ |------|------|------|
397
+ | `data.total_calls` | integer | 今日总调用次数 |
398
+ | `data.success_calls` | integer | 今日成功调用次数 |
399
+ | `data.failed_calls` | integer | 今日失败调用次数 |
400
+ | `data.avg_latency` | number | 今日平均响应延迟(毫秒) |
401
+
402
+ ---
403
+
404
+ ### `GET /api/open/resources/:type/:tmdb_id`
405
+
406
+ 功能:
407
+
408
+ - 根据媒体类型和 TMDB ID 获取资源列表
409
+
410
+ 请求参数:
411
+
412
+ | 参数 | 位置 | 类型 | 必填 | 说明 |
413
+ |------|------|------|------|------|
414
+ | `type` | path | string | 是 | 媒体类型,可选 `movie`、`tv` |
415
+ | `tmdb_id` | path | string | 是 | TMDB ID |
416
+
417
+ 请求示例:
418
+
419
+ ```bash
420
+ curl -H "X-API-Key: your-api-key" \
421
+ http://localhost:8890/api/open/resources/movie/550
422
+ ```
423
+
424
+ 成功响应:
425
+
426
+ ```json
427
+ {
428
+ "success": true,
429
+ "code": "200",
430
+ "message": "success",
431
+ "data": [
432
+ {
433
+ "slug": "a1b2c3d4e5f647898765432112345678",
434
+ "title": "Fight Club 4K REMUX",
435
+ "share_size": "58.3 GB",
436
+ "video_resolution": ["2160p"],
437
+ "source": ["REMUX"],
438
+ "subtitle_language": ["中文", "英文"],
439
+ "subtitle_type": ["内嵌"],
440
+ "remark": "杜比视界",
441
+ "unlock_points": 10,
442
+ "unlocked_users_count": 42,
443
+ "validate_status": "valid",
444
+ "validate_message": null,
445
+ "last_validated_at": "2025-01-08 12:00:00",
446
+ "is_official": true,
447
+ "is_unlocked": false,
448
+ "user": {
449
+ "id": 1,
450
+ "nickname": "HDHive",
451
+ "avatar_url": "https://example.com/avatar.jpg"
452
+ },
453
+ "created_at": "2025-01-01 10:00:00"
454
+ }
455
+ ],
456
+ "meta": {
457
+ "total": 1
458
+ }
459
+ }
460
+ ```
461
+
462
+ 响应字段:
463
+
464
+ | 字段 | 类型 | 说明 |
465
+ |------|------|------|
466
+ | `data[].slug` | string | 资源唯一标识 |
467
+ | `data[].title` | string / null | 资源标题 |
468
+ | `data[].share_size` | string / null | 分享文件大小 |
469
+ | `data[].video_resolution` | string[] | 视频分辨率列表 |
470
+ | `data[].source` | string[] | 来源列表 |
471
+ | `data[].subtitle_language` | string[] | 字幕语言列表 |
472
+ | `data[].subtitle_type` | string[] | 字幕类型列表 |
473
+ | `data[].remark` | string / null | 备注 |
474
+ | `data[].unlock_points` | integer / null | 解锁所需积分 |
475
+ | `data[].unlocked_users_count` | integer / null | 已解锁用户数 |
476
+ | `data[].validate_status` | string / null | 资源验证状态 |
477
+ | `data[].validate_message` | string / null | 验证信息 |
478
+ | `data[].last_validated_at` | string / null | 最后验证时间 |
479
+ | `data[].is_official` | boolean / null | 是否官方资源 |
480
+ | `data[].is_unlocked` | boolean | 当前用户是否已解锁 |
481
+ | `data[].user` | object / null | 分享者信息 |
482
+ | `data[].created_at` | string | 创建时间 |
483
+ | `meta.total` | integer | 资源总数 |
484
+
485
+ 说明:
486
+
487
+ - 若对应电影/电视剧不存在,返回空列表而不是 `404`
488
+ - 对于内置 Web 控制台里的封装搜索流程,本地前端会额外忽略以下资源:
489
+ - `validate_status == "invalid"`
490
+ - 且 `validate_message` 包含 `链接无效` 或 `链接已失效`
491
+ - 上述过滤仅发生在 `GET /` 返回的前端工作流中;接口本身仍原样返回上游数据
492
+
493
+ ---
494
+
495
+ ### `GET /api/tmdb/configuration`
496
+
497
+ 功能:
498
+
499
+ - 获取 TMDB 官方 `configuration` 响应
500
+ - 可用于拼接图片地址、查看图片尺寸配置
501
+
502
+ 请求示例:
503
+
504
+ ```bash
505
+ curl -H "X-TMDB-API-Key: your-tmdb-api-key" \
506
+ http://localhost:8890/api/tmdb/configuration
507
+ ```
508
+
509
+ 说明:
510
+
511
+ - 本接口为 TMDB 官方原始响应代理
512
+ - 若未传 `X-TMDB-API-Key`,会尝试使用环境变量 `TMDB_API_KEY`
513
+
514
+ ---
515
+
516
+ ### `GET /api/tmdb/configuration/primary_translations`
517
+
518
+ 功能:
519
+
520
+ - 获取 TMDB 官方支持的 primary translation code 列表
521
+ - 可直接用于前端语言下拉选择,例如 `zh-CN`、`en-US`、`ja-JP`
522
+
523
+ 请求示例:
524
+
525
+ ```bash
526
+ curl -H "X-TMDB-API-Key: your-tmdb-api-key" \
527
+ http://localhost:8890/api/tmdb/configuration/primary_translations
528
+ ```
529
+
530
+ 说明:
531
+
532
+ - 本接口为 TMDB 官方原始响应代理
533
+ - 返回为字符串数组
534
+
535
+ ---
536
+
537
+ ### `GET /api/tmdb/search/:media_type`
538
+
539
+ 功能:
540
+
541
+ - 调用 TMDB 官方搜索接口
542
+ - 支持 `movie`、`tv`、`multi`
543
+ - 适合根据关键词获取 `tmdb_id`、`poster_path`、`overview`
544
+
545
+ 请求参数:
546
+
547
+ | 参数 | 位置 | 类型 | 必填 | 说明 |
548
+ |------|------|------|------|------|
549
+ | `media_type` | path | string | 是 | `movie`、`tv` 或 `multi` |
550
+ | `query` | query | string | 是 | 搜索关键词 |
551
+ | `page` | query | integer | 否 | 页码 |
552
+ | `language` | query | string | 否 | 语言,如 `zh-CN`、`en-US` |
553
+
554
+ 请求示例:
555
+
556
+ ```bash
557
+ curl -H "X-TMDB-API-Key: your-tmdb-api-key" \
558
+ "http://localhost:8890/api/tmdb/search/movie?query=Fight%20Club&language=zh-CN&page=1"
559
+ ```
560
+
561
+ 说明:
562
+
563
+ - 本接口为 TMDB 官方原始响应代理
564
+ - 返回字段取决于 TMDB 官方当前响应
565
+
566
+ ---
567
+
568
+ ### `GET /api/tmdb/:media_type/:media_id`
569
+
570
+ 功能:
571
+
572
+ - 获取指定电影或剧集的 TMDB 原始详情
573
+ - 可配合 `append_to_response=images` 取回海报、剧照等数据
574
+
575
+ 请求参数:
576
+
577
+ | 参数 | 位置 | 类型 | 必填 | 说明 |
578
+ |------|------|------|------|------|
579
+ | `media_type` | path | string | 是 | `movie` 或 `tv` |
580
+ | `media_id` | path | string | 是 | TMDB 媒体 ID |
581
+ | `language` | query | string | 否 | 语言,如 `zh-CN` |
582
+ | `append_to_response` | query | string | 否 | 例如 `images`、`credits`、`videos` |
583
+
584
+ 请求示例:
585
+
586
+ ```bash
587
+ curl -H "X-TMDB-API-Key: your-tmdb-api-key" \
588
+ "http://localhost:8890/api/tmdb/movie/550?language=zh-CN&append_to_response=images"
589
+ ```
590
+
591
+ 说明:
592
+
593
+ - 本接口为 TMDB 官方原始响应代理
594
+
595
+ ---
596
+
597
+ ### `POST /api/open/resources/unlock`
598
+
599
+ 功能:
600
+
601
+ - 使用积分解锁资源
602
+ - 获取下载链接或访问码
603
+ - 本地保留安全开关,默认不允许扣积分
604
+
605
+ 请求参数:
606
+
607
+ | 参数 | 位置 | 类型 | 必填 | 说明 |
608
+ |------|------|------|------|------|
609
+ | `slug` | body | string | 是 | 资源 slug |
610
+ | `allow_points` | body | boolean | 否 | 本地安全开关。默认 `false`,即默认不允许扣积分解锁 |
611
+
612
+ 请求示例:
613
+
614
+ ```bash
615
+ curl -X POST \
616
+ -H "X-API-Key: your-api-key" \
617
+ -H "Content-Type: application/json" \
618
+ -d '{
619
+ "slug": "a1b2c3d4e5f647898765432112345678",
620
+ "allow_points": false
621
+ }' \
622
+ http://localhost:8890/api/open/resources/unlock
623
+ ```
624
+
625
+ 说明:
626
+
627
+ - 当 `allow_points=false` 或未传时,本地会先查询 `GET /api/open/shares/:slug`
628
+ - 若当前资源对该用户可免费获取,或已解锁,或 `actual_unlock_points <= 0`,则继续调用上游解锁
629
+ - 若当前资源需要真实扣积分,则本地直接返回 `POINTS_REQUIRED`
630
+ - 当 `allow_points=true` 时,直接透传到上游解锁接口
631
+ - `GET /` 返回的内置控制台会对成功解锁结果做本地缓存,避免重复调用该接口
632
+ - 该缓存只存在于浏览器本地存储中,不会改变服务端接口行为
633
+
634
+ 成功响应:
635
+
636
+ ```json
637
+ {
638
+ "success": true,
639
+ "code": "200",
640
+ "message": "解锁成功",
641
+ "data": {
642
+ "url": "https://pan.example.com/s/abc123",
643
+ "access_code": "x1y2",
644
+ "full_url": "https://pan.example.com/s/abc123?pwd=x1y2",
645
+ "already_owned": false
646
+ }
647
+ }
648
+ ```
649
+
650
+ 响应字段:
651
+
652
+ | 字段 | 类型 | 说明 |
653
+ |------|------|------|
654
+ | `data.url` | string | 资源链接 |
655
+ | `data.access_code` | string | 访问码/提取码 |
656
+ | `data.full_url` | string | 完整链接(含访问码) |
657
+ | `data.already_owned` | boolean | 是否之前已解锁 |
658
+
659
+ ---
660
+
661
+ ### `POST /api/open/check/resource`
662
+
663
+ 功能:
664
+
665
+ - 检查资源链接的网盘类型
666
+ - 在创建分享前预判网盘平台
667
+ - 自动解析 115 / 123 网盘访问码
668
+
669
+ 请求参数:
670
+
671
+ | 参数 | 位置 | 类型 | 必填 | 说明 |
672
+ |------|------|------|------|------|
673
+ | `url` | body | string | 是 | 资源分享链接 |
674
+
675
+ 请求示例:
676
+
677
+ ```bash
678
+ curl -X POST \
679
+ -H "X-API-Key: your-api-key" \
680
+ -H "Content-Type: application/json" \
681
+ -d '{"url": "https://115.com/s/abc123#xxxx 访问码:1234"}' \
682
+ http://localhost:8890/api/open/check/resource
683
+ ```
684
+
685
+ 成功响应:
686
+
687
+ ```json
688
+ {
689
+ "success": true,
690
+ "code": "200",
691
+ "message": "success",
692
+ "data": {
693
+ "website": "115",
694
+ "url": "https://115.com/s/abc123",
695
+ "base_link": "https://115.com/s/abc123",
696
+ "access_code": "1234",
697
+ "default_unlock_points": 10
698
+ }
699
+ }
700
+ ```
701
+
702
+ 响应字段:
703
+
704
+ | 字段 | 类型 | 说明 |
705
+ |------|------|------|
706
+ | `data.website` | string | 网盘类型,如 `115`、`123`、`quark`、`baidu`、`ed2k` |
707
+ | `data.url` | string | 提取后的干净链接 |
708
+ | `data.base_link` | string | 基础链接,仅 115 / 123 返回 |
709
+ | `data.access_code` | string | 访问码,仅 115 / 123 自动解析 |
710
+ | `data.default_unlock_points` | integer / null | 用户默认解锁积分 |
711
+
712
+ ---
713
+
714
+ ### `GET /api/open/shares`
715
+
716
+ 功能:
717
+
718
+ - 获取当前 API Key 关联用户的分享列表
719
+
720
+ 请求参数:
721
+
722
+ | 参数 | 位置 | 类型 | 必填 | 说明 |
723
+ |------|------|------|------|------|
724
+ | `page` | query | integer | 否 | 页码,默认 `1` |
725
+ | `page_size` | query | integer | 否 | 每页条数,默认 `20`,最大 `100` |
726
+
727
+ 请求示例:
728
+
729
+ ```bash
730
+ curl -H "X-API-Key: your-api-key" \
731
+ "http://localhost:8890/api/open/shares?page=1&page_size=10"
732
+ ```
733
+
734
+ 成功响应:
735
+
736
+ ```json
737
+ {
738
+ "success": true,
739
+ "code": "200",
740
+ "message": "success",
741
+ "data": [
742
+ {
743
+ "slug": "a1b2c3d4e5f647898765432112345678",
744
+ "title": "Fight Club 4K REMUX",
745
+ "share_size": "58.3 GB",
746
+ "video_resolution": ["4K"],
747
+ "source": ["蓝光原盘/REMUX"],
748
+ "subtitle_language": ["简中"],
749
+ "subtitle_type": ["内封"],
750
+ "remark": "杜比视界",
751
+ "unlock_points": 10,
752
+ "unlocked_users_count": 8,
753
+ "validate_status": "valid",
754
+ "validate_message": null,
755
+ "last_validated_at": "2025-01-08 12:00:00",
756
+ "is_official": false,
757
+ "is_unlocked": false,
758
+ "user": {
759
+ "id": 1,
760
+ "nickname": "用户A",
761
+ "avatar_url": "https://example.com/avatar.jpg"
762
+ },
763
+ "created_at": "2025-01-01 10:00:00"
764
+ }
765
+ ],
766
+ "meta": {
767
+ "total": 1,
768
+ "page": 1,
769
+ "page_size": 10
770
+ }
771
+ }
772
+ ```
773
+
774
+ 响应字段:
775
+
776
+ | 字段 | 类型 | 说明 |
777
+ |------|------|------|
778
+ | `data` | array | 分享列表 |
779
+ | `meta.total` | integer | 分享总数 |
780
+ | `meta.page` | integer | 当前页码 |
781
+ | `meta.page_size` | integer | 每页条数 |
782
+
783
+ ---
784
+
785
+ ### `GET /api/open/shares/:slug`
786
+
787
+ 功能:
788
+
789
+ - 获取指定分享详情
790
+ - 包含媒体关联和用户信息
791
+
792
+ 请求参数:
793
+
794
+ | 参数 | 位置 | 类型 | 必填 | 说明 |
795
+ |------|------|------|------|------|
796
+ | `slug` | path | string | 是 | 资源 slug |
797
+
798
+ 请求示例:
799
+
800
+ ```bash
801
+ curl -H "X-API-Key: your-api-key" \
802
+ http://localhost:8890/api/open/shares/a1b2c3d4e5f647898765432112345678
803
+ ```
804
+
805
+ 成功响应核心字段:
806
+
807
+ | 字段 | 类型 | 说明 |
808
+ |------|------|------|
809
+ | `data.slug` | string | 资源唯一标识 |
810
+ | `data.title` | string / null | 资源标题 |
811
+ | `data.pan_type` | string / null | 网盘类型 |
812
+ | `data.share_size` | string / null | 分享大小 |
813
+ | `data.video_resolution` | string[] | 分辨率列表 |
814
+ | `data.source` | string[] | 来源列表 |
815
+ | `data.subtitle_language` | string[] | 字幕语言列表 |
816
+ | `data.subtitle_type` | string[] | 字幕类型列表 |
817
+ | `data.unlock_points` | integer / null | 设定解锁积分 |
818
+ | `data.actual_unlock_points` | integer | 当前用户实际需要支付的积分 |
819
+ | `data.is_unlocked` | boolean | 当前用户是否已解锁 |
820
+ | `data.is_free_for_user` | boolean | 当前用户是否可免费获取 |
821
+ | `data.unlock_message` | string | 解锁状态描述 |
822
+ | `data.media` | object / null | 媒体关联信息 |
823
+ | `data.media.type` | string | `movie`、`tv` 或 `collection` |
824
+ | `data.media.tmdb_id` | string / null | TMDB ID |
825
+ | `data.media.title` | string / null | 媒体标题 |
826
+ | `data.user` | object / null | 分享者信息 |
827
+
828
+ 说明:
829
+
830
+ - 此接口不返回真实下载链接和访问码
831
+ - 需要通过 `/api/open/resources/unlock` 才能拿到实际链接
832
+
833
+ ---
834
+
835
+ ### `POST /api/open/shares`
836
+
837
+ 功能:
838
+
839
+ - 创建新的资源分享
840
+ - 支持通过 TMDB ID 或系统内部 ID 关联影视内容
841
+
842
+ 请求参数:
843
+
844
+ | 参数 | 位置 | 类型 | 必填 | 说明 |
845
+ |------|------|------|------|------|
846
+ | `tmdb_id` | body | string | 条件必填 | TMDB ID |
847
+ | `media_type` | body | string | 条件必填 | 使用 `tmdb_id` 时必填,取值 `movie` 或 `tv` |
848
+ | `movie_id` | body | integer | 条件必填 | 系统电影 ID,与 `tmdb_id` 二选一 |
849
+ | `tv_id` | body | integer | 条件必填 | 系统电视剧 ID,与 `tmdb_id` 二选一 |
850
+ | `collection_id` | body | integer | 否 | 系统合集 ID |
851
+ | `title` | body | string | 否 | 资源标题 |
852
+ | `url` | body | string | 是 | 分享链接 |
853
+ | `share_size` | body | string | 否 | 资源大小 |
854
+ | `video_resolution` | body | string[] | 否 | 分辨率列表 |
855
+ | `source` | body | string[] | 否 | 片源列表 |
856
+ | `subtitle_language` | body | string[] | 否 | 字幕语言列表 |
857
+ | `subtitle_type` | body | string[] | 否 | 字幕类型列表 |
858
+ | `remark` | body | string | 否 | 备注 |
859
+ | `access_code` | body | string | 否 | 访问码/提取码 |
860
+ | `unlock_points` | body | integer | 否 | 解锁所需积分 |
861
+ | `is_anonymous` | body | boolean | 否 | 是否匿名分享 |
862
+ | `hide_link` | body | boolean | 否 | 是否在 Telegram 通知中隐藏原始链接 |
863
+
864
+ 关联影视必填规则:
865
+
866
+ - 需提供 `tmdb_id + media_type`
867
+ - 或 `movie_id / tv_id / collection_id` 至少其一
868
+
869
+ 请求示例:
870
+
871
+ ```bash
872
+ curl -X POST \
873
+ -H "X-API-Key: your-api-key" \
874
+ -H "Content-Type: application/json" \
875
+ -d '{
876
+ "tmdb_id": "550",
877
+ "media_type": "movie",
878
+ "title": "Fight Club 4K REMUX",
879
+ "url": "https://pan.example.com/s/abc123",
880
+ "access_code": "x1y2",
881
+ "share_size": "58.3 GB",
882
+ "video_resolution": ["4K"],
883
+ "source": ["蓝光原盘/REMUX"],
884
+ "subtitle_language": ["简中"],
885
+ "subtitle_type": ["内封"],
886
+ "unlock_points": 10,
887
+ "is_anonymous": false
888
+ }' \
889
+ http://localhost:8890/api/open/shares
890
+ ```
891
+
892
+ 成功响应:
893
+
894
+ - 返回新建分享对象,字段结构与资源列表项基本一致
895
+
896
+ ---
897
+
898
+ ### `PATCH /api/open/shares/:slug`
899
+
900
+ 功能:
901
+
902
+ - 部分更新已有分享
903
+ - 传什么更新什么,未传字段保持不变
904
+
905
+ 请求参数:
906
+
907
+ | 参数 | 位置 | 类型 | 必填 | 说明 |
908
+ |------|------|------|------|------|
909
+ | `slug` | path | string | 是 | 资源 slug |
910
+ | `title` | body | string | 否 | 资源标题 |
911
+ | `url` | body | string | 否 | 分享链接 |
912
+ | `share_size` | body | string | 否 | 资源大小 |
913
+ | `video_resolution` | body | string[] | 否 | 分辨率列表 |
914
+ | `source` | body | string[] | 否 | 片源列表 |
915
+ | `subtitle_language` | body | string[] | 否 | 字幕语言列表 |
916
+ | `subtitle_type` | body | string[] | 否 | 字幕类型列表 |
917
+ | `remark` | body | string | 否 | 备注 |
918
+ | `access_code` | body | string | 否 | 访问码 |
919
+ | `unlock_points` | body | integer | 否 | 解锁所需积分 |
920
+ | `is_anonymous` | body | boolean | ��� | 是否匿名分享 |
921
+ | `hide_link` | body | boolean | 否 | 是否隐藏链接 |
922
+ | `notify` | body | boolean | 否 | 是否发送 Telegram 通知 |
923
+
924
+ 说明:
925
+
926
+ - 至少需要提供一个更新字段
927
+
928
+ 请求示例:
929
+
930
+ ```bash
931
+ curl -X PATCH \
932
+ -H "X-API-Key: your-api-key" \
933
+ -H "Content-Type: application/json" \
934
+ -d '{
935
+ "title": "Fight Club 4K REMUX (更新)",
936
+ "video_resolution": ["4K", "1080P"],
937
+ "subtitle_language": ["简中", "繁中"]
938
+ }' \
939
+ http://localhost:8890/api/open/shares/a1b2c3d4e5f647898765432112345678
940
+ ```
941
+
942
+ 成功响应:
943
+
944
+ - 返回更新后的分享对象
945
+
946
+ ---
947
+
948
+ ### `DELETE /api/open/shares/:slug`
949
+
950
+ 功能:
951
+
952
+ - 删除分享资源
953
+
954
+ 请求参数:
955
+
956
+ | 参数 | 位置 | 类型 | 必填 | 说明 |
957
+ |------|------|------|------|------|
958
+ | `slug` | path | string | 是 | 资源 slug |
959
+
960
+ 请求示例:
961
+
962
+ ```bash
963
+ curl -X DELETE \
964
+ -H "X-API-Key: your-api-key" \
965
+ http://localhost:8890/api/open/shares/a1b2c3d4e5f647898765432112345678
966
+ ```
967
+
968
+ 成功响应:
969
+
970
+ ```json
971
+ {
972
+ "success": true,
973
+ "code": "200",
974
+ "message": "删除成功",
975
+ "data": null
976
+ }
977
+ ```
978
+
979
+ ---
980
+
981
+ ## 错误码说明
982
+
983
+ 常见上游错误码:
984
+
985
+ | 错误码 | HTTP 状态码 | 说明 |
986
+ |--------|-------------|------|
987
+ | `MISSING_API_KEY` | 401 | 缺少 API Key |
988
+ | `INVALID_API_KEY` | 401 | API Key 无效 |
989
+ | `DISABLED_API_KEY` | 401 | API Key 已被禁用 |
990
+ | `EXPIRED_API_KEY` | 401 | API Key 已过期 |
991
+ | `ENDPOINT_DISABLED` | 403 | 接口已禁用 |
992
+ | `ENDPOINT_QUOTA_EXCEEDED` | 429 | 接口配额已用尽 |
993
+ | `RATE_LIMIT_EXCEEDED` | 429 | 请求频率过高 |
994
+ | `INSUFFICIENT_POINTS` | 402 | 积分不足 |
995
+
996
+ 本地附加错误码:
997
 
998
+ | 错误码 | HTTP 状态码 | 说明 |
999
+ |--------|-------------|------|
1000
+ | `UPSTREAM_REQUEST_FAILED` | 502 | 请求上游失败 |
1001
+ | `UPSTREAM_RESPONSE_INVALID` | 502 | 上游返回结构无法解析 |
1002
+ | `POINTS_REQUIRED` | 409 | 资源需要积分,但本地安全开关未允许扣积分 |
1003
+ | `MISSING_TMDB_API_KEY` | 401 | 缺少 TMDB API Key |
1004
+ | `TMDB_REQUEST_FAILED` | 502 | 请求 TMDB 失败 |
1005
 
1006
+ ## 说明
 
 
1007
 
1008
+ - 如果求头里传了 `X-API-Key`,优先使用请求头
1009
+ - 如果请求头没传,则尝试使用环境变量 `HDHIVE_API_KEY`
1010
+ - 默认控制台访问地址通常为 `http://127.0.0.1:8890/` 或 `http://localhost:8890/`