From dce45203c943b187f2251f01beceba6fa0bda765 Mon Sep 17 00:00:00 2001 From: czp3009 Date: Tue, 12 Mar 2019 18:39:00 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9B=B4=E6=92=AD=E7=AB=99=20API=20=E5=BC=80?= =?UTF-8?q?=E5=B7=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/hiczp/bilibili/api/BilibiliClient.kt | 20 ++++ .../com/hiczp/bilibili/api/live/LiveAPI.kt | 67 ++++++++++++ .../bilibili/api/live/model/AnchorInRoom.kt | 103 ++++++++++++++++++ .../bilibili/api/live/model/DanmakuConfig.kt | 49 +++++++++ .../bilibili/api/live/model/MobileRoom.kt | 58 ++++++++++ .../hiczp/bilibili/api/live/model/RoomInfo.kt | 99 +++++++++++++++++ .../com/hiczp/bilibili/api/live/model/User.kt | 54 +++++++++ .../bilibili/api/retrofit/HttpConstant.kt | 5 +- .../hiczp/bilibili/api/test/EnterRoomTest.kt | 15 +++ 9 files changed, 468 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/live/LiveAPI.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/live/model/AnchorInRoom.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/live/model/DanmakuConfig.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/live/model/MobileRoom.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/live/model/RoomInfo.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/live/model/User.kt create mode 100644 src/test/kotlin/com/hiczp/bilibili/api/test/EnterRoomTest.kt diff --git a/src/main/kotlin/com/hiczp/bilibili/api/BilibiliClient.kt b/src/main/kotlin/com/hiczp/bilibili/api/BilibiliClient.kt index 2d25d6f..f5f0afb 100644 --- a/src/main/kotlin/com/hiczp/bilibili/api/BilibiliClient.kt +++ b/src/main/kotlin/com/hiczp/bilibili/api/BilibiliClient.kt @@ -2,6 +2,7 @@ package com.hiczp.bilibili.api import com.hiczp.bilibili.api.app.AppAPI import com.hiczp.bilibili.api.danmaku.DanmakuAPI +import com.hiczp.bilibili.api.live.LiveAPI import com.hiczp.bilibili.api.main.MainAPI import com.hiczp.bilibili.api.member.MemberAPI import com.hiczp.bilibili.api.message.MessageAPI @@ -217,6 +218,25 @@ class BilibiliClient( .create(DanmakuAPI::class.java) } + /** + * 直播站 + */ + val liveAPI by lazy { + createAPI(BaseUrl.live, + CommonHeaderInterceptor( + //如果未登陆则没有 Display-ID + Header.DISPLAY_ID to { userId?.let { "$it-$initTime" } }, + Header.BUILD_VERSION_ID to { billingClientProperties.buildVersionId }, + Header.USER_AGENT to { billingClientProperties.defaultUserAgent }, + Header.DEVICE_ID to { billingClientProperties.hardwareId } + ), + CommonParamInterceptor(*defaultCommonParamArray, + Param.ACTION_KEY to { Param.APP_KEY }, + Param.DEVICE to { billingClientProperties.platform } + ) + ) + } + /** * 登陆 * v3 登陆接口会同时返回 cookies 和 token diff --git a/src/main/kotlin/com/hiczp/bilibili/api/live/LiveAPI.kt b/src/main/kotlin/com/hiczp/bilibili/api/live/LiveAPI.kt new file mode 100644 index 0000000..a2e27ce --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/live/LiveAPI.kt @@ -0,0 +1,67 @@ +package com.hiczp.bilibili.api.live + +import com.hiczp.bilibili.api.live.model.* +import com.hiczp.bilibili.api.retrofit.CommonResponse +import kotlinx.coroutines.Deferred +import retrofit2.http.* + +/** + * 直播站 API + */ +@Suppress("DeferredIsResult") +interface LiveAPI { + /** + * 获取一个房间的基本信息 + * + * @param id 房间号或房间短号 + */ + @GET("/room/v1/Room/mobileRoomInit") + fun mobileRoomInit(@Query("id") id: Long): Deferred + + /** + * 进入房间时客户端将访问该接口 + * 访问该接口将在自己的账户中产生一条观看直播的历史记录 + * + * @param roomId 房间号(没试过能不能用短号, 下同) + */ + @POST("/room/v1/Room/room_entry_action") + @FormUrlEncoded + fun roomEntryAction( + @Field("room_id") roomId: Long, + @Field("jumpFrom") jumpFrom: Int? = 0 + ): Deferred + + /** + * 获取一个房间的详细信息 + * + * @param id 房间号 + */ + @GET("/room/v1/Room/get_info") + fun getInfo(@Query("id") id: Long): Deferred + + /** + * 获取弹幕服务器 + * + * @param roomId 房间号 + */ + @GET("/room/v1/Danmu/getConf") + fun getDanmakuConfig( + @Field("room_id") roomId: Long + ): Deferred + + + /** + * 获取该房间的主播的头像和等级一类的信息 + * + * @param roomId 房间号 + */ + @Suppress("SpellCheckingInspection") + @GET("/live_user/v1/UserInfo/get_anchor_in_room") + fun getAnchorInRoom(@Query("roomid") roomId: Long): Deferred + + /** + * 获取自己在直播间的基本信息, 包括自己的直播间号, 银瓜子, 金瓜子数量等 + */ + @GET("/mobile/getUser") + fun getUser(): Deferred +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/live/model/AnchorInRoom.kt b/src/main/kotlin/com/hiczp/bilibili/api/live/model/AnchorInRoom.kt new file mode 100644 index 0000000..f4a3643 --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/live/model/AnchorInRoom.kt @@ -0,0 +1,103 @@ +package com.hiczp.bilibili.api.live.model + +import com.google.gson.annotations.SerializedName + +data class AnchorInRoom( + @SerializedName("code") + var code: Int, // 0 + @SerializedName("data") + var `data`: Data, + @SerializedName("message") + var message: String, // success + @SerializedName("msg") + var msg: String // success +) { + data class Data( + @SerializedName("info") + var info: Info, + @SerializedName("level") + var level: Level, + @SerializedName("san") + var san: String // 12 + ) { + data class Info( + @SerializedName("face") + var face: String, // https://i1.hdslb.com/bfs/face/4f65e79399ad5a1bf3f877851b2f819d5870b494.jpg + @SerializedName("gender") + var gender: Int, // 0 + @SerializedName("identification") + var identification: Int, // 1 + @SerializedName("mobile_verify") + var mobileVerify: Int, // 1 + @SerializedName("official_verify") + var officialVerify: OfficialVerify, + @SerializedName("platform_user_level") + var platformUserLevel: Int, // 4 + @SerializedName("rank") + var rank: String, // 10000 + @SerializedName("uid") + var uid: Long, // 20293030 + @SerializedName("uname") + var uname: String, // czp3009 + @SerializedName("vip_type") + var vipType: Int // 0 + ) { + data class OfficialVerify( + @SerializedName("desc") + var desc: String, + @SerializedName("role") + var role: Int, // 0 + @SerializedName("type") + var type: Int // -1 + ) + } + + data class Level( + @SerializedName("anchor_score") + var anchorScore: Int, // 27376 + @SerializedName("color") + var color: Int, // 5805790 + @SerializedName("cost") + var cost: Int, // 52187800 + @SerializedName("master_level") + var masterLevel: MasterLevel, + @SerializedName("rcost") + var rcost: Int, // 2737665 + @SerializedName("svip") + var svip: Int, // 0 + @SerializedName("svip_time") + var svipTime: String, // 0000-00-00 00:00:00 + @SerializedName("uid") + var uid: Int, // 20293030 + @SerializedName("update_time") + var updateTime: String, // 2019-03-12 16:00:48 + @SerializedName("user_level") + var userLevel: Int, // 25 + @SerializedName("user_score") + var userScore: String, // 0 + @SerializedName("vip") + var vip: Int, // 0 + @SerializedName("vip_time") + var vipTime: String // 2018-05-15 12:00:50 + ) { + data class MasterLevel( + @SerializedName("anchor_score") + var anchorScore: Int, // 27376 + @SerializedName("color") + var color: Int, // 5805790 + @SerializedName("current") + var current: List, + @SerializedName("level") + var level: Int, // 11 + @SerializedName("master_level_color") + var masterLevelColor: Int, // 5805790 + @SerializedName("next") + var next: List, + @SerializedName("sort") + var sort: String, // >10000 + @SerializedName("upgrade_score") + var upgradeScore: Int // 12234 + ) + } + } +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/live/model/DanmakuConfig.kt b/src/main/kotlin/com/hiczp/bilibili/api/live/model/DanmakuConfig.kt new file mode 100644 index 0000000..bf734a1 --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/live/model/DanmakuConfig.kt @@ -0,0 +1,49 @@ +package com.hiczp.bilibili.api.live.model + +import com.google.gson.annotations.SerializedName + +data class DanmakuConfig( + @SerializedName("code") + var code: Int, // 0 + @SerializedName("data") + var `data`: Data, + @SerializedName("message") + var message: String, // ok + @SerializedName("msg") + var msg: String // ok +) { + data class Data( + @SerializedName("host") + var host: String, // broadcastlv.chat.bilibili.com + @SerializedName("host_server_list") + var hostServerList: List, + @SerializedName("max_delay") + var maxDelay: Int, // 5000 + @SerializedName("port") + var port: Int, // 2243 + @SerializedName("refresh_rate") + var refreshRate: Int, // 100 + @SerializedName("refresh_row_factor") + var refreshRowFactor: Double, // 0.125 + @SerializedName("server_list") + var serverList: List + ) { + data class Server( + @SerializedName("host") + var host: String, // broadcastlv.chat.bilibili.com + @SerializedName("port") + var port: Int // 80 + ) + + data class HostServer( + @SerializedName("host") + var host: String, // broadcastlv.chat.bilibili.com + @SerializedName("port") + var port: Int, // 2243 + @SerializedName("ws_port") + var wsPort: Int, // 2244 + @SerializedName("wss_port") + var wssPort: Int // 443 + ) + } +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/live/model/MobileRoom.kt b/src/main/kotlin/com/hiczp/bilibili/api/live/model/MobileRoom.kt new file mode 100644 index 0000000..a46a9c0 --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/live/model/MobileRoom.kt @@ -0,0 +1,58 @@ +package com.hiczp.bilibili.api.live.model + +import com.google.gson.annotations.SerializedName + +data class MobileRoom( + @SerializedName("code") + var code: Int, // 0 + @SerializedName("data") + var `data`: Data, + @SerializedName("message") + var message: String, // ok + @SerializedName("msg") + var msg: String // ok +) { + data class Data( + @SerializedName("encrypted") + var encrypted: Boolean, // false + @SerializedName("hidden_till") + var hiddenTill: Int, // 0 + @SerializedName("is_hidden") + var isHidden: Boolean, // false + @SerializedName("is_locked") + var isLocked: Boolean, // false + @SerializedName("is_portrait") + var isPortrait: Boolean, // false + @SerializedName("is_sp") + var isSp: Int, // 0 + @SerializedName("live_status") + var liveStatus: Int, // 0 + @SerializedName("live_time") + var liveTime: Long, // -62170012800 + @SerializedName("lock_till") + var lockTill: Int, // 0 + @SerializedName("need_p2p") + var needP2p: Int, // 0 + @SerializedName("pwd_verified") + var pwdVerified: Boolean, // true + /** + * 实际房间号 + */ + @SerializedName("room_id") + var roomId: Long, // 1110317 + /** + * 如果房间有短号则 roomShield 为 1 + */ + @SerializedName("room_shield") + var roomShield: Int, // 0 + /** + * 短房间号 + */ + @SerializedName("short_id") + var shortId: Int, // 0 + @SerializedName("special_type") + var specialType: Int, // 0 + @SerializedName("uid") + var uid: Long // 20293030 + ) +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/live/model/RoomInfo.kt b/src/main/kotlin/com/hiczp/bilibili/api/live/model/RoomInfo.kt new file mode 100644 index 0000000..3beb1cd --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/live/model/RoomInfo.kt @@ -0,0 +1,99 @@ +package com.hiczp.bilibili.api.live.model + +import com.google.gson.JsonElement +import com.google.gson.annotations.SerializedName + +data class RoomInfo( + @SerializedName("code") + var code: Int, // 0 + @SerializedName("data") + var `data`: Data, + @SerializedName("message") + var message: String, // ok + @SerializedName("msg") + var msg: String // ok +) { + data class Data( + @SerializedName("allow_change_area_time") + var allowChangeAreaTime: Int, // 0 + @SerializedName("allow_upload_cover_time") + var allowUploadCoverTime: Int, // 0 + @SerializedName("area_id") + var areaId: Int, // 107 + @SerializedName("area_name") + var areaName: String, // 其他游戏 + @SerializedName("area_pendants") + var areaPendants: String, + @SerializedName("attention") + var attention: Int, // 62 + @SerializedName("background") + var background: String, + @SerializedName("description") + var description: String, //

立即安装Jetbrains, 享受精彩人生!

+ @SerializedName("hot_words") + var hotWords: List, + @SerializedName("hot_words_status") + var hotWordsStatus: Int, // 0 + @SerializedName("is_anchor") + var isAnchor: Int, // 1 + @SerializedName("is_portrait") + var isPortrait: Boolean, // false + @SerializedName("is_strict_room") + var isStrictRoom: Boolean, // false + @SerializedName("keyframe") + var keyframe: String, // https://i0.hdslb.com/bfs/live/1110317.jpg?03092037 + @SerializedName("live_status") + var liveStatus: Int, // 0 + @SerializedName("live_time") + var liveTime: String, // 0000-00-00 00:00:00 + @SerializedName("new_pendants") + var newPendants: NewPendants, + @SerializedName("old_area_id") + var oldAreaId: Int, // 1 + @SerializedName("online") + var online: Int, // 18 + @SerializedName("parent_area_id") + var parentAreaId: Int, // 2 + @SerializedName("parent_area_name") + var parentAreaName: String, // 网游 + @SerializedName("pendants") + var pendants: String, + @SerializedName("pk_id") + var pkId: Int, // 0 + @SerializedName("pk_status") + var pkStatus: Int, // 0 + @SerializedName("room_id") + var roomId: Long, // 1110317 + @SerializedName("room_silent_level") + var roomSilentLevel: Int, // 0 + @SerializedName("room_silent_second") + var roomSilentSecond: Int, // 0 + @SerializedName("room_silent_type") + var roomSilentType: String, + @SerializedName("short_id") + var shortId: Int, // 0 + @SerializedName("tags") + var tags: String, // 编程 + @SerializedName("title") + var title: String, // 太空程序员 + @SerializedName("uid") + var uid: Long, // 20293030 + @SerializedName("up_session") + var upSession: String, + @SerializedName("user_cover") + var userCover: String, // https://i0.hdslb.com/bfs/live/b4d4dbf35f7a30fb6b0a2ea4077514235262797e.jpg + @SerializedName("verify") + var verify: String + ) { + data class NewPendants( + @SerializedName("badge") + var badge: JsonElement?, // null + @SerializedName("frame") + var frame: JsonElement?, // null + @SerializedName("mobile_badge") + var mobileBadge: JsonElement?, // null + @SerializedName("mobile_frame") + var mobileFrame: JsonElement? // null + ) + } +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/live/model/User.kt b/src/main/kotlin/com/hiczp/bilibili/api/live/model/User.kt new file mode 100644 index 0000000..d0df28b --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/live/model/User.kt @@ -0,0 +1,54 @@ +package com.hiczp.bilibili.api.live.model + +import com.google.gson.annotations.SerializedName + +data class User( + @SerializedName("code") + var code: Int, // 0 + @SerializedName("data") + var `data`: Data, + @SerializedName("message") + var message: String, // OK + @SerializedName("msg") + var msg: String // OK +) { + data class Data( + @SerializedName("gold") + var gold: Int, // 0 + @SerializedName("isSign") + var isSign: Int, // 0 + @SerializedName("medal") + var medal: Any?, // null + @SerializedName("new") + var new: Int, // 1 + @SerializedName("room_id") + var roomId: Long, // 1110317 + @SerializedName("silver") + var silver: Int, // 140258 + @SerializedName("svip") + var svip: Int, // 0 + @SerializedName("svip_time") + var svipTime: String, // 0000-00-00 00:00:00 + @SerializedName("use_count") + var useCount: Int, // 0 + @SerializedName("user_level") + var userLevel: Int, // 25 + @SerializedName("user_level_color") + var userLevelColor: Int, // 5805790 + @SerializedName("vip") + var vip: Int, // 0 + @SerializedName("vip_time") + var vipTime: String, // 2018-05-15 12:00:50 + @SerializedName("vip_view_status") + var vipViewStatus: Int, // 1 + @SerializedName("wearTitle") + var wearTitle: WearTitle + ) { + data class WearTitle( + @SerializedName("activity") + var activity: String, // 0 + @SerializedName("title") + var title: String // 0 + ) + } +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/retrofit/HttpConstant.kt b/src/main/kotlin/com/hiczp/bilibili/api/retrofit/HttpConstant.kt index 7cc73f8..1b66957 100644 --- a/src/main/kotlin/com/hiczp/bilibili/api/retrofit/HttpConstant.kt +++ b/src/main/kotlin/com/hiczp/bilibili/api/retrofit/HttpConstant.kt @@ -24,9 +24,10 @@ object Header { //强制公共参数添加位置 const val FORCE_PARAM = "Retrofit-Force-Param" const val FORCE_PARAM_QUERY = "query" - const val FORCE_PARAM_FORMBODY = "formBody" + @Suppress("MemberVisibilityCanBePrivate") + const val FORCE_PARAM_FORM_BODY = "formBody" const val FORCE_QUERY = "$FORCE_PARAM: $FORCE_PARAM_QUERY" - const val FORCE_FORMBODY = "$FORCE_PARAM: $FORCE_PARAM_FORMBODY" + const val FORCE_FORM_BODY = "$FORCE_PARAM: $FORCE_PARAM_FORM_BODY" } object Param { diff --git a/src/test/kotlin/com/hiczp/bilibili/api/test/EnterRoomTest.kt b/src/test/kotlin/com/hiczp/bilibili/api/test/EnterRoomTest.kt new file mode 100644 index 0000000..4ac7808 --- /dev/null +++ b/src/test/kotlin/com/hiczp/bilibili/api/test/EnterRoomTest.kt @@ -0,0 +1,15 @@ +package com.hiczp.bilibili.api.test + +import kotlinx.coroutines.runBlocking +import org.junit.jupiter.api.Test + +class EnterRoomTest { + @Test + fun enterRoom() { + runBlocking { + val roomId = bilibiliClient.liveAPI.mobileRoomInit(3).await().data.roomId + bilibiliClient.liveAPI.roomEntryAction(roomId).await() + bilibiliClient.liveAPI.getInfo(roomId).await() + } + } +}