添加追番页面的 API

This commit is contained in:
czp3009 2019-02-26 17:49:31 +08:00
parent 7c6297f6d2
commit e33af1de88
7 changed files with 254 additions and 7 deletions

View File

@ -1,6 +1,8 @@
# Bilibili API JVM 调用库
该项目提供 Bilibili API 的 JVM 调用, 协议来自 Bilibili Android APP 的逆向工程以及截包分析.
使用一台虚拟的 `Pixel 2` 设备来截取数据包, 一些固定参数可能与真实设备不一致.
# 技术说明
`BilibiliClient` 类表示一个模拟的客户端, 实例化此类即表示打开了 Bilibili APP.

View File

@ -18,6 +18,9 @@ fun InputStream.readInt(): Int {
(byteArray[3].toInt())
}
/**
* 以大端模式从流中读取一个 unsigned int
*/
@Suppress("EXPERIMENTAL_API_USAGE")
fun InputStream.readUInt() = readInt().toUInt()

View File

@ -33,13 +33,17 @@ interface AppAPI {
/**
* 侧边栏中动态增加的按钮, 返回信息包含 URI 地址(到对应的 activity)
* 侧拉抽屉
*/
@GET("/x/resource/sidebar")
fun sidebar(): Deferred<Sidebar>
/**
* 首页内容(客户端通过解析返回的内容来生成页面内容, 下同)
* API 没有翻页参数, 同样的参数每次请求都会返回不一样的内容. 刷新和下拉只是简单的重新访问此接口.
* 首页 -> 推荐
*
* @param pull 如果是通过滑动到最顶端来刷新页面的, 那么将是 true, 将页面滑动到最底端来获取更多内容将是 false
*/
@Suppress("SpellCheckingInspection")
@GET("/x/v2/feed/index")
@ -65,6 +69,9 @@ interface AppAPI {
/**
* 热门页面
* 首页 -> 热门
*
* @param index 翻页参数, 一开始为 0, 然后每次滑动到底端就会加 10
* @param ver 第一次请求时没有这个参数, 第二次开始这个参数为上一次请求此接口时的返回值中的 `ver`
*/
@GET("/x/v2/show/popular/index")
fun popularPage(
@ -75,7 +82,7 @@ interface AppAPI {
@Query("last_param") lastParam: String? = null,
@Query("login_event") loginEvent: Int = 0,
@Query("qn") qn: Int = 32,
@Query("ver") ver: Long? = null //ver 的值为上一次请求该接口时的 timestamp-1
@Query("ver") ver: Long? = null
): Deferred<PopularPage>
/**

View File

@ -1,9 +1,6 @@
package com.hiczp.bilibili.api.main
import com.hiczp.bilibili.api.main.model.ChildReply
import com.hiczp.bilibili.api.main.model.Recommend
import com.hiczp.bilibili.api.main.model.Reply
import com.hiczp.bilibili.api.main.model.Season
import com.hiczp.bilibili.api.main.model.*
import kotlinx.coroutines.Deferred
import retrofit2.http.GET
import retrofit2.http.Query
@ -52,8 +49,8 @@ interface MainAPI {
): Deferred<ChildReply>
/**
* 获得一个番剧的分季信息, 包含默认季(通常是最新的一季)的分集信息
* seasonId episodeId 必须有一个, 返回的结果是一样的
* 获得一个番剧的分季信息(生成番剧页面所需的信息), 包含当前选择的季的分集信息
* seasonId episodeId 必须有一个, 如果用 episodeId 将跳转到对应的 season 的页面
* 返回值中, 每个 episode 都有 aid cid
*
* @param seasonId 季的唯一标识
@ -74,4 +71,47 @@ interface MainAPI {
*/
@GET("/pgc/season/app/related/recommend")
fun recommend(@Query("season_id") seasonId: Long): Deferred<Recommend>
/**
* 我的追番动态(追番页面上方的那一条 "我的追番")
* 首页 -> 追番 -> 我的追番
*/
@Suppress("SpellCheckingInspection")
@GET("/pgc/app/page/bangumi/mine")
fun myBangumiNews(
@Query("fnval") fnval: Int = 16,
@Query("fnver") fnver: Int = 0
): Deferred<MyBangumiNews>
/**
* 追番页面(客户端用这里面的数据来生成追番页面)
* 每个模块(module)的数据(item)全部超过三个.
* 每个板块下面的 换一换 按钮并不重新请求数据, 而是从每个模块的数据里选出另一批
* 首页 -> 追番
*
* @param pgcHomeTimelineABTest A/B Test 有关, 不明确其值含义, 有可能使得返回内容不一样
*/
@Suppress("SpellCheckingInspection")
@GET("/pgc/app/page/bangumi")
fun bangumiPage(
@Query("fnval") fnval: Int = 16,
@Query("fnver") fnver: Int = 0,
@Query("pgc_home_timeline_abtest") pgcHomeTimelineABTest: Int? = 13
): Deferred<BangumiPage>
/**
* 获得更多 "编辑推荐"
* 首页 -> 追番 -> (下拉)
*
* @param cursor 表示时间(ms), 但是可能是科学计数法. 每次请求所用的 cursor 在上一次的返回值里的最后一个 item . 第一次请求所用的 cursor 在追番页面的返回值的最后.
* @param size 分页大小
* @param wid 不明确, 有可能是一些 padding, margin, 用于计算位置
*
* @see bangumiPage
*/
fun bangumiMore(
@Query("cursor") cursor: String,
@Query("size") size: Int = 10,
@Query("wid") wid: String? = "78,79,80,81,59"
): Deferred<BangumiMore>
}

View File

@ -0,0 +1,43 @@
package com.hiczp.bilibili.api.main.model
import com.google.gson.annotations.SerializedName
data class BangumiMore(
@SerializedName("code")
var code: Int, // 0
@SerializedName("message")
var message: String, // success
@SerializedName("result")
var result: List<Result>
) {
data class Result(
@SerializedName("cover")
var cover: String, // http://i0.hdslb.com/bfs/bangumi/5bac9515a50c880e55a772c194241ff9943e0004.png
/**
* cursor 的值有可能是科学计数法, 例如 1.550210400638E12
* 如果不是最后一个 item 将没有这个字段
*/
@SerializedName("cursor")
var cursor: String?, // 1548172800112.0
@SerializedName("desc")
var desc: String, // 正在就读白凰女学院3年级的加藤茉莉香是个拥有“私掠船免状”的合法宇宙海贼。她不仅是学生、宇宙艇部的部长、咖啡馆的服务员还是宇宙海贼船·弁天丸的船长每天都过着繁忙而充实的生活。某天正在豪华客船上开展工作的茉莉香在乘客名单中发现了拥有银河通行证的少年·无限彼方的名字……。少年与海贼的亚空冒险就此展开
@SerializedName("id")
var id: Int, // 33409
@SerializedName("is_new")
var isNew: Int, // 0
@SerializedName("link")
var link: String, // https://www.bilibili.com/read/cv1831506
@SerializedName("link_type")
var linkType: Int, // 4
@SerializedName("link_value")
var linkValue: Int, // 0
@SerializedName("pub_time")
var pubTime: String, // 2019-01-23 00:00:00
@SerializedName("simg")
var simg: String,
@SerializedName("title")
var title: String, // 化身为刃,除魔四方——《多罗罗》
@SerializedName("wid")
var wid: Int // 81
)
}

View File

@ -0,0 +1,79 @@
package com.hiczp.bilibili.api.main.model
import com.google.gson.annotations.SerializedName
data class BangumiPage(
@SerializedName("code")
var code: Int, // 0
@SerializedName("message")
var message: String, // success
@SerializedName("result")
var result: Result
) {
data class Result(
@SerializedName("modules")
var modules: List<Module>,
@SerializedName("regions")
var regions: List<Region>
) {
data class Module(
@SerializedName("attr")
var attr: Attr,
@SerializedName("headers")
var headers: List<Any>,
@SerializedName("items")
var items: List<Item>,
@SerializedName("module_id")
var moduleId: Int, // 6
@SerializedName("size")
var size: Int, // 10
@SerializedName("style")
var style: String, // fall
@SerializedName("title")
var title: String, // 编辑推荐
@SerializedName("wid")
var wid: List<Int>
) {
data class Item(
@SerializedName("badge")
var badge: String, // NEW
@SerializedName("badge_type")
var badgeType: Int, // 0
@SerializedName("cover")
var cover: String, // http://i0.hdslb.com/bfs/bangumi/57e00f9995459ab0cf40800358ee7f3b392b38a4.jpg
@SerializedName("cursor")
var cursor: String, // 1.55021040036E12
@SerializedName("desc")
var desc: String, // 明明是最差劲的相遇,但雏却不知何时开始无法停止心动。雏被初中时的学长·恋雪所吸引,决定和他进入同所高中而拼命学习。并且,和青梅竹马的虎太朗一同进入了樱丘高中。曾经单调乏味的恋雪,为了自己单相思的对象,而在假日结束后改换了形象,变得受欢迎起来。在这种状况下,雏决定要「告白」,但是——!?
@SerializedName("is_new")
var isNew: Int, // 0
@SerializedName("item_id")
var itemId: Int, // 34265
@SerializedName("link")
var link: String, // https://www.bilibili.com/blackboard/topic/activity-dm4qK4-BI.html
@SerializedName("title")
var title: String, // 【资讯档】2019年第7周
@SerializedName("wid")
var wid: Int // 78
)
data class Attr(
@SerializedName("follow")
var follow: Int, // 0
@SerializedName("header")
var header: Int, // 1
@SerializedName("random")
var random: Int // 0
)
}
data class Region(
@SerializedName("icon")
var icon: String, // http://i0.hdslb.com/bfs/bangumi/3b66adc7339e62d469ea5b89a45c74e14e3ae831.png
@SerializedName("title")
var title: String, // 点评
@SerializedName("url")
var url: String // bilibili://pgc/review/index
)
}
}

View File

@ -0,0 +1,73 @@
package com.hiczp.bilibili.api.main.model
import com.google.gson.annotations.SerializedName
data class MyBangumiNews(
@SerializedName("code")
var code: Int, // 0
@SerializedName("message")
var message: String, // success
@SerializedName("result")
var result: Result
) {
data class Result(
@SerializedName("delay")
var delay: List<Any>,
@SerializedName("follow")
var follow: Int, // 34
@SerializedName("follows")
var follows: List<Follow>,
@SerializedName("follows_type")
var followsType: Int, // 1
@SerializedName("update")
var update: Int // 1
) {
data class Follow(
@SerializedName("badge")
var badge: String, // 会员抢先
@SerializedName("badge_type")
var badgeType: Int, // 0
@SerializedName("cover")
var cover: String, // http://i0.hdslb.com/bfs/bangumi/f34ff3975c39913af936c133ae60a5891babba08.png
@SerializedName("is_finish")
var isFinish: Int, // 0
@SerializedName("is_started")
var isStarted: Int, // 1
@SerializedName("new_ep")
var newEp: NewEp,
/**
* 如果 progress null 说明尚未观看
*/
@SerializedName("progress")
var progress: Progress?,
@SerializedName("season_id")
var seasonId: Int, // 25681
@SerializedName("title")
var title: String, // JOJO的奇妙冒险 黄金之风
@SerializedName("total_count")
var totalCount: Int, // 39
@SerializedName("url")
var url: String // https://www.bilibili.com/bangumi/play/ss25681
) {
data class NewEp(
@SerializedName("cover")
var cover: String, // http://i0.hdslb.com/bfs/archive/c3af18bf85040dfacb081db46e033f056318a8f0.jpg
@SerializedName("id")
var id: Int, // 250631
@SerializedName("index_show")
var indexShow: String // 更新至第20话
)
data class Progress(
@SerializedName("last_ep_desc")
var lastEpDesc: String, // 看到第2话
@SerializedName("last_ep_id")
var lastEpId: Int, // 250837
@SerializedName("last_ep_index")
var lastEpIndex: String, // 2
@SerializedName("last_time")
var lastTime: Int // 1377
)
}
}
}