feat: 播放地址优先使用 playlist 并补充接口清单

This commit is contained in:
Nixevol
2026-09-25 23:49:19 +08:00
parent 1a26efd994
commit 00bf1361d3
2 changed files with 505 additions and 7 deletions
+470
View File
@@ -0,0 +1,470 @@
# RaptDrama 接口清单
基址使用 `https://apis.raptdrama.com`。`https://app.raptdrama.com` 上部分路径也能通,脚本以 `apis` 为准。
本文只记录已经实际调用过的返回结构。安装包里还有一批路径,返回格式没有核对,放在最后一节,不要把它们当成已确认的协议。
## 通用约定
业务响应外面都有同一层包装。HTTP 状态经常仍是 200,成功与否看 `code`。
```json
{
"code": 200,
"msg": "ok",
"data": {}
}
```
已见到的业务码:
| code | 含义 |
| --- | --- |
| 200 | 成功。`msg` 可能是 `ok`、`成功` 或 `Login success` |
| 299 | 未登录,`msg` 为 `Please login first`。用 `Authorization: Bearer` 调播放接口时会出现 |
| 500 | 参数错误,例如 `Invalid email format`、`Password cannot be empty`、`Error Type` |
请求头:
| 头 | 值 |
| --- | --- |
| Content-Type | `application/json`。播放和登录都用 JSON,不要用表单 |
| Accept | `application/json` |
| User-Agent | `RaptDrama/1.1.81 (Android 12; 23113RKC6C; Redmi)` |
| apasstk | 登录后拿到的 `token`。游客 `autologin` 本身不带这个头 |
| x-app-build | `139` |
| x-app-version | `1.1.81` |
| x-device-type | `phone` |
| x-device-brand | `Redmi` |
| x-device-model | `23113RKC6C` |
| x-device-id | 设备号,例如 `rd_` 开头的字符串 |
| x-device-fingerprint | 设备指纹 |
| x-device-physical | `true` |
| x-os-name | `Android` |
| x-os-version | `12` |
| accept-language | `en-US` |
| accept-language-custom | `en-US` |
登录凭证只放在 `apasstk`。不要再使用 `Authorization: Bearer`。
## 登录
### POST /app/open/autologin
每次调用都新建一个游客,不会沿用上一次的账号。不需要 `apasstk`。
请求体:`{}`
`data`:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| id | string | 新游客 id |
| nickname | string | 随机昵称 |
| token | string | 后续请求的 `apasstk` |
| score | int | |
| vipday | int | |
| badge | string | 例如 `BRONZE` |
| watched | int | |
| rewards | int | |
| avatarNum | int | |
| avatarNumUrl | string | 头像地址 |
### POST /app/open/emailLogin
同一邮箱重复登录返回同一个用户。不需要先带 `apasstk`。
请求体:
```json
{"email": "邮箱", "password": "密码"}
```
`email` 或 `password` 用错字段名时,`code` 为 500。
`data`:
| 字段 | 类型 |
| --- | --- |
| id | int |
| nickname | string |
| email | string |
| email_bind | int |
| score | int |
| tgid | int |
| isguanzhu | int |
| sxid | int |
| os | string |
| channel | string |
| token | string |
| google_bind | int |
`/auth/login` 在这个基址上没有返回上述 JSON 包装,邮箱登录以 `/app/open/emailLogin` 为准。
### POST /app/user/getUserInfo
需要 `apasstk`。游客 token 也可以调用。
请求体:`{}`
`data`:
| 字段 | 类型 |
| --- | --- |
| id | int |
| nickname | string |
| email_bind | int |
| mobile_bind | int |
| score | int |
| tgid | int |
| isguanzhu | int |
| sxid | int |
| os | string |
| channel | string |
| google_bind | int |
| apple_bind | int |
| login_day | int |
| vipday | int |
| badge | string |
| watched | int |
| rewards | int |
| avatarNum | int |
| avatarNumUrl | string |
这里的 `id` 是数字。`autologin` 返回的 `id` 是字符串。
## 分类和剧列表
剧对象在多个接口里重复出现,下面称它为剧目:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| id | int | 剧 id,播放接口的 `vid` 用这个值 |
| title | string | |
| update_time | int | Unix 时间 |
| view | int | |
| image | string | 封面 |
| tstype | string | 分类 id,Passion 为 `"20"` |
| desc | string | |
| forstaus | string | |
| forstausen | string | 连载状态文案,例如完结 |
| author | string | |
| classify | string[] | 题材标签 |
| score | string | 评分,是字符串 |
### POST /app/open/classifyv2
请求体:`{}`
`data` 是分类数组:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| id | int | 传给分类视频接口的 `type` |
| label | string | 英文名 |
| label_origin | string | |
| image | string 或 null | |
已见到的分类:`18` Comedy,`20` Passion,`21` Newest,`22` Western,`23` Comic drama。
### POST /app/open/classify_video
按分类分页。`type` 才是分类 id。传 `tstype`、`classify` 或 `id` 会返回 `code` 500、`Error Type`。
请求体:
```json
{"page": 1, "limit": 10, "type": 20}
```
`page` 从 1 开始。每页 10 条,空页表示结束。`limit` 增大也不会一次返回超过 10 条。
`data` 是剧目数组。
### POST /app/open/recommend
请求体:`{}`
`data` 是剧目数组。空对象也只返回约 10 条,不是全站列表。
### POST /app/open/foryou
请求体:`{}`
`data` 是剧目数组,并多一个 `firstchapter`:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| firstchapter.id | int | 集 id |
| firstchapter.title | string | |
| firstchapter.idx | int | 集序号 |
| firstchapter.playurl | string | 这一集的播放地址 |
### POST /app/open/extra_broadcast
请求体:`{}`
`data` 是剧目数组。
### GET /app/open/orgin
无请求体。`data` 是剧目数组。
### POST /app/open/search
请求体:
```json
{"keyword": "love", "page": 1, "limit": 10}
```
`data` 是剧目数组,并多一个 `totalvideo`(int,集数)。
### POST /app/open/bank
请求体:`{}`
`data` 不是剧目数组,而是观看或片库记录:
| 字段 | 类型 |
| --- | --- |
| id | int |
| vid | int |
| cid | int |
| create_time | int |
| video.id | int |
| video.title | string |
| video.image | string |
| video.desc | string |
| video.forstaus | string |
| video.author | string |
| video.forstausen | string |
## 剧集和播放地址
### GET /app/video/getchapters
查询参数:
| 参数 | 说明 |
| --- | --- |
| vid | 剧 id |
| start | 起始偏移,从 0 开始 |
| limit | 每页条数,可用 200 |
示例:`/app/video/getchapters?vid=1942&start=0&limit=200`
`data`:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| count | int | 总集数 |
| list[].id | int | 集 id,对应播放列表里的 `cid` |
| list[].title | string | |
| list[].idx | int | 集序号 |
| list[].isvip | string | `"0"` 免费,`"1"` 锁定。这是字符串,不是布尔值 |
### POST /app/video/playlist
安装包里没有这个路径,但服务端仍接受,GET 和 POST 都可以。请求体与 `playlistv2` 相同。
`data` 的字段和 `playlistv2` 一样。区别是它一次返回该剧全部集,不再按每页 10 条分页。剧 1942 一次返回 `count` 30、`list` 30 条,其中免费的 3 集有 `src`,其余为空。第一集的 `src` 与 `playlistv2` 第一页相同。脚本优先调用这个接口,结果为空、条数少于 `count` 或请求失败时,再按页调用 `playlistv2`。
`playlistv1` 和 `playlistv3` 返回 nginx 404。
### POST /app/video/playlistv2
这是播放地址接口。`vid` 是剧 id,不是集 id。
请求体:
```json
{"vid": 1942, "page": 1, "before": 1}
```
第一页 `before` 为 `1`,后面的页为 `0`。每页 10 集。`data.count` 到齐后停止。
`data`:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| count | int | 总集数 |
| list[].cid | int | 集 id |
| list[].idx | int | 集序号 |
| list[].msg | string | 例如 `EP.1` |
| list[].src | string | 主 m3u8。未解锁时是空字符串 |
| list[].state | string | 例如 `pause` |
| list[].like | int | |
| list[].like_n | int | |
| list[].playNumber | int | |
| list[].fufei | int | |
| list[].playIng | bool | |
| list[].isShowimage | bool | |
| list[].needScore | string | |
| list[].isplay | bool | |
游客和未购买账号只能拿到免费集的 `src`。锁定集的 `src` 为空,接口不会因为换了登录方式就返回地址。
`src` 是 BunnyCDN 签名地址,形如:
```text
https://vz-<编号>.b-cdn.net/bcdn_token=<签名>&token_path=%2F<视频uuid>%2F&expires=<unix时间>/<视频uuid>/playlist.m3u8
```
签名写在路径里,不是查询字符串。主列表里有一行相对路径 `1080p/video.m3u8`。子列表是点播,分片名为 `video0.ts`、`video1.ts`。同一段签名前缀可以访问该视频目录下的子列表和 ts。签名会过期,需要时重新请求 `playlistv2`。
### POST /app/video/videoinfo
请求体:
```json
{"vid": 1942}
```
`data`:
| 字段 | 类型 |
| --- | --- |
| moshi | int |
| video.id | int |
| video.title | string |
| video.view | int |
| video.desc | string |
| video.ishot | string |
| video.like | int |
| video.is_on | int |
| video.poster | string |
| video.forstaus | string |
| video.author | string |
| video.forstausen | string |
带已登录账号时,`data` 里还出现过 `history`。
### POST /app/video/addreadlog
App 播放时发出的请求体如下,返回格式没有单独保存:
```json
{"vid": 2286, "del": 0, "cid": 26125}
```
`vid` 是剧 id,`cid` 是集 id。
## 其他已核对接口
### POST /app/open/contact
请求体:`{}`
`data`:
| 字段 | 类型 |
| --- | --- |
| techniacl_email | string |
| business_email | string |
字段名在服务端就是 `techniacl_email`。
### POST /app/appopen/getAuthConfig
请求体:`{}`
`data`:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| platform | string | |
| google.enabled | bool | |
| google.android_client_id | string | |
| google.ios_client_id | string | |
| google.web_client_id | string | |
| google.client_id | string | |
| google.server_client_id | string | |
| apple.enabled | bool | |
| apple.service_id | string | |
| apple.team_id | string | |
| apple.key_id | string | |
| supported_platforms | string[] | |
## 安装包中的路径
这些路径从 `libapp.so` 提取。除上面已写明的接口外,访问方式和返回格式都还没有核对。
认证:
- POST /app/user/appleLogin
- POST /app/user/googleLogin
- POST /app/user/bindEmail
- POST /auth/register
- POST /auth/refresh
- POST /auth/bind-email
用户:
- /app/user/accountBindingStatus
- /app/user/editProfile
- /app/user/changePassword
- /app/user/deleteAccount
- /app/user/activate
- /app/user/activationSubOverview
- /app/user/getPlatformBinds
- /app/user/getSensorsProfile
- /app/user/recordAttribution
- /app/user/readhistory
- /app/user/delhistory
视频:
- /app/video/overview
- /app/video/addToWishlist
- /app/video/markvideo
- /app/video/exitRecommendm
- /app/video/screening
- /app/User/checkViewTime
支付和订阅:
- /app/pay/google_iap_create_order
- /app/pay/google_iap_verify
- /app/pay/google_iap_status
- /app/pay/google_iap_recovery
- /app/pay/apple_iap_create_order
- /app/pay/apple_iap_verify
- /app/pay/apple_iap_recovery
- /app/pay/paylmpay_create_order
- /app/pay/paypal_return
- /app/pay/paypal_cancel
- /app/pay/paystatus
- /app/pay/paysuccess
- /app/pay/initiateCheckout
- /app/pay/report_payment_panel_context
- /app/pay_center/create_order
- /app/pay_center/paylist
- /app/pay_center/third_party_qualification
- /app/user/paylist
- /app/user/paylistv2
- /app/user/paylistv3
- /app/subscription/list
- /app/subscription/cancel
签到、反馈、通知:
- /app/checkin/config
- /app/checkin/status
- /app/checkin/perform
- /app/checkin/history
- /app/checkin/statistics
- /app/checkin/tasks
- /app/feedback/submit
- /app/feedback/list
- /app/feedback/detail
- /app/feedback/read
- /app/feedback/categories
- /app/feedback/unreadCount
- /app/feedback/upload
- /app/notification/getList
- /app/notification/getDetail
- /app/notification/device
- /app/notification/settings
- /app/notification/action
- /app/notification/clear