From eb588f57989e1f7b34aeaf55ef20d31ea98370d9 Mon Sep 17 00:00:00 2001 From: czp3009 Date: Wed, 20 Feb 2019 18:24:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=99=BB=E9=99=86=E8=BF=87?= =?UTF-8?q?=E7=A8=8B=E4=B8=AD=E4=BC=9A=E8=AE=BF=E9=97=AE=E7=9A=84=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 +- .../kotlin/com/hiczp/bilibili/api/BaseUrl.kt | 14 +- .../com/hiczp/bilibili/api/BilibiliClient.kt | 101 +++-- .../com/hiczp/bilibili/api/app/AppAPI.kt | 48 +++ .../hiczp/bilibili/api/app/model/IndexPage.kt | 374 ++++++++++++++++++ .../com/hiczp/bilibili/api/app/model/Mine.kt | 60 +++ .../hiczp/bilibili/api/app/model/Sidebar.kt | 33 ++ .../hiczp/bilibili/api/message/MessageAPI.kt | 26 ++ .../bilibili/api/message/model/NotifyCount.kt | 38 ++ .../bilibili/api/message/model/UplmList.kt | 27 ++ .../bilibili/api/passport/PassportAPI.kt | 3 + .../kotlin/com/hiczp/bilibili/api/vc/VcAPI.kt | 30 ++ .../bilibili/api/vc/model/AttentionList.kt | 19 + .../bilibili/api/vc/model/DynamicNumber.kt | 25 ++ 14 files changed, 783 insertions(+), 35 deletions(-) create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/app/model/IndexPage.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/app/model/Mine.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/app/model/Sidebar.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/message/MessageAPI.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/message/model/NotifyCount.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/message/model/UplmList.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/vc/VcAPI.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/vc/model/AttentionList.kt create mode 100644 src/main/kotlin/com/hiczp/bilibili/api/vc/model/DynamicNumber.kt diff --git a/README.md b/README.md index 683b72e..aedac95 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,17 @@ https://passport.bilibili.com 登陆后, 可以访问全部 API. +# message +https://message.bilibili.com + + BilibiliClient().messageAPI + +消息通知有关的接口. + # app https://app.bilibili.com - BilibiliClient().appAPI() + BilibiliClient().appAPI 为 app 提供通用接口, 例如获取个人信息. 完整示例如下 @@ -54,15 +61,16 @@ https://app.bilibili.com val bilibiliClient = BilibiliClient().apply { login(username, password) } - val myInfo = bilibiliClient.appAPI().myInfo().await() + val myInfo = bilibiliClient.appAPI.myInfo().await() println(myInfo) } -# 主站 -//TODO +# av +https://api.vc.bilibili.com -# 直播站 -//TODO + BilibiliClient().vcAPI + +小视频有关的接口. # License GPL V3 diff --git a/src/main/kotlin/com/hiczp/bilibili/api/BaseUrl.kt b/src/main/kotlin/com/hiczp/bilibili/api/BaseUrl.kt index f109983..f9badc7 100644 --- a/src/main/kotlin/com/hiczp/bilibili/api/BaseUrl.kt +++ b/src/main/kotlin/com/hiczp/bilibili/api/BaseUrl.kt @@ -5,17 +5,27 @@ package com.hiczp.bilibili.api */ object BaseUrl { /** - * passport 站, 用于登录 + * 用户鉴权 */ const val passport = "https://passport.bilibili.com" + /** + * 消息 + */ + const val message = "https://message.bilibili.com" + /** * 提供通用功能, 例如获取用户信息 */ const val app = "https://app.bilibili.com" /** - * 直播站 + * 小视频 + */ + const val vc = "https://api.vc.bilibili.com" + + /** + * 直播 */ const val live = "https://api.live.bilibili.com" } diff --git a/src/main/kotlin/com/hiczp/bilibili/api/BilibiliClient.kt b/src/main/kotlin/com/hiczp/bilibili/api/BilibiliClient.kt index a1a000d..6d6afe0 100644 --- a/src/main/kotlin/com/hiczp/bilibili/api/BilibiliClient.kt +++ b/src/main/kotlin/com/hiczp/bilibili/api/BilibiliClient.kt @@ -1,6 +1,7 @@ package com.hiczp.bilibili.api import com.hiczp.bilibili.api.app.AppAPI +import com.hiczp.bilibili.api.message.MessageAPI import com.hiczp.bilibili.api.passport.PassportAPI import com.hiczp.bilibili.api.passport.model.LoginResponse import com.hiczp.bilibili.api.retrofit.ParamType @@ -9,8 +10,8 @@ import com.hiczp.bilibili.api.retrofit.interceptor.CommonHeaderInterceptor import com.hiczp.bilibili.api.retrofit.interceptor.CommonParamInterceptor import com.hiczp.bilibili.api.retrofit.interceptor.FailureResponseInterceptor import com.hiczp.bilibili.api.retrofit.interceptor.SortAndSignInterceptor +import com.hiczp.bilibili.api.vc.VcAPI import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory -import mu.KotlinLogging import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor @@ -18,12 +19,11 @@ import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import java.security.KeyFactory import java.security.spec.X509EncodedKeySpec +import java.text.SimpleDateFormat import java.time.Instant import java.util.* import javax.crypto.Cipher -private val logger = KotlinLogging.logger {} - /** * 此类表示一个模拟的 Bilibili 客户端(Android), 所有调用由此开始. * 多个 BilibiliClient 实例之间不共享登陆状态. @@ -58,8 +58,34 @@ class BilibiliClient( get() = loginResponse != null //快捷方式 - val userId get() = loginResponse?.userId - val token get() = loginResponse?.token + @Suppress("MemberVisibilityCanBePrivate") + val userId + get() = loginResponse?.userId + @Suppress("MemberVisibilityCanBePrivate") + val token + get() = loginResponse?.token + + @Suppress("SpellCheckingInspection") + private val defaultCommonHeaderInterceptor = CommonHeaderInterceptor( + "Display-ID" to { "${billingClientProperties.buildVersionId}-$initTime" }, + "Buvid" to { billingClientProperties.buildVersionId }, + "User-Agent" to { "Mozilla/5.0 BiliDroid/5.37.0 (bbcallen@gmail.com)" }, + "Device-ID" to { billingClientProperties.hardwareId } + ) + + @Suppress("SpellCheckingInspection") + private val defaultCommonParamArray = arrayOf( + "access_key" to { token }, + "appkey" to { billingClientProperties.appKey }, + "build" to { billingClientProperties.build }, + "channel" to { billingClientProperties.channel }, + "mobi_app" to { billingClientProperties.platform }, + "platform" to { billingClientProperties.platform }, + "ts" to { Instant.now().epochSecond.toString() } + ) + + private val defaultQuerySignInterceptor = SortAndSignInterceptor(ParamType.QUERY, billingClientProperties.appSecret) + private val defaultFormSignInterceptor = SortAndSignInterceptor(ParamType.FORM_URL_ENCODED, billingClientProperties.appSecret) /** * 用户鉴权相关的接口 @@ -67,12 +93,7 @@ class BilibiliClient( @Suppress("SpellCheckingInspection") val passportAPI by lazy { createAPI(BaseUrl.passport, logLevel, - CommonHeaderInterceptor( - "Display-ID" to { "${billingClientProperties.buildVersionId}-$initTime" }, - "Buvid" to { billingClientProperties.buildVersionId }, - "User-Agent" to { "Mozilla/5.0 BiliDroid/5.37.0 (bbcallen@gmail.com)" }, - "Device-ID" to { billingClientProperties.hardwareId } - ), + defaultCommonHeaderInterceptor, CommonParamInterceptor(ParamType.FORM_URL_ENCODED, "appkey" to { billingClientProperties.appKey }, "build" to { billingClientProperties.build }, @@ -81,7 +102,22 @@ class BilibiliClient( "platform" to { billingClientProperties.platform }, "ts" to { Instant.now().epochSecond.toString() } ), - SortAndSignInterceptor(ParamType.FORM_URL_ENCODED, billingClientProperties.appSecret) + defaultFormSignInterceptor + ) + } + + /** + * 消息通知有关的接口 + */ + @Suppress("SpellCheckingInspection") + val messageAPI by lazy { + createAPI(BaseUrl.message, logLevel, + defaultCommonHeaderInterceptor, + CommonParamInterceptor(ParamType.QUERY, *defaultCommonParamArray, + "actionKey" to { "appkey" }, + "has_up" to { "1" } + ), + defaultQuerySignInterceptor ) } @@ -91,22 +127,28 @@ class BilibiliClient( @Suppress("SpellCheckingInspection") val appAPI by lazy { createAPI(BaseUrl.app, logLevel, - CommonHeaderInterceptor( - "Display-ID" to { "${billingClientProperties.buildVersionId}-$initTime" }, - "Buvid" to { billingClientProperties.buildVersionId }, - "User-Agent" to { "Mozilla/5.0 BiliDroid/5.37.0 (bbcallen@gmail.com)" }, - "Device-ID" to { billingClientProperties.hardwareId } + defaultCommonHeaderInterceptor, + CommonParamInterceptor(ParamType.QUERY, *defaultCommonParamArray), + defaultQuerySignInterceptor + ) + } + + /** + * 小视频相关接口 + */ + @Suppress("SpellCheckingInspection") + val vcAPI by lazy { + createAPI(BaseUrl.vc, logLevel, + defaultCommonHeaderInterceptor, + CommonParamInterceptor(ParamType.QUERY, *defaultCommonParamArray, + "_device" to { billingClientProperties.platform }, + "_hwid" to { billingClientProperties.hardwareId }, + "src" to { billingClientProperties.channel }, + "trace_id" to { generateTraceId() }, + "uid" to { userId?.toString() }, + "version" to { billingClientProperties.version } ), - CommonParamInterceptor(ParamType.QUERY, - "access_key" to { token }, - "appkey" to { billingClientProperties.appKey }, - "build" to { billingClientProperties.build }, - "channel" to { billingClientProperties.channel }, - "mobi_app" to { billingClientProperties.platform }, - "platform" to { billingClientProperties.platform }, - "ts" to { Instant.now().epochSecond.toString() } - ), - SortAndSignInterceptor(ParamType.QUERY, billingClientProperties.appSecret) + defaultQuerySignInterceptor ) } @@ -164,6 +206,11 @@ class BilibiliClient( passportAPI.revoke(cookieMap, response.token).await() loginResponse = null } + + companion object { + private val traceIdFormat = SimpleDateFormat("yyyyMMddHHmm000ss") + private fun generateTraceId() = traceIdFormat.format(Date()) + } } @Suppress("SpellCheckingInspection") diff --git a/src/main/kotlin/com/hiczp/bilibili/api/app/AppAPI.kt b/src/main/kotlin/com/hiczp/bilibili/api/app/AppAPI.kt index 318c81a..b73f449 100644 --- a/src/main/kotlin/com/hiczp/bilibili/api/app/AppAPI.kt +++ b/src/main/kotlin/com/hiczp/bilibili/api/app/AppAPI.kt @@ -1,12 +1,60 @@ package com.hiczp.bilibili.api.app +import com.hiczp.bilibili.api.app.model.IndexPage +import com.hiczp.bilibili.api.app.model.Mine import com.hiczp.bilibili.api.app.model.MyInfo +import com.hiczp.bilibili.api.app.model.Sidebar import kotlinx.coroutines.Deferred import retrofit2.http.GET +import retrofit2.http.Query +import java.time.Instant +/** + * 提供通用信息的接口 + */ @Suppress("DeferredIsResult") interface AppAPI { + /** + * 登陆完成后将请求一次此接口以获得个人资料 + */ @Suppress("SpellCheckingInspection") @GET("/x/v2/account/myinfo") fun myInfo(): Deferred + + /** + * 登陆后也会访问此接口, 返回内容大致与 myInfo() 相同 + */ + @GET("/x/v2/account/mine") + fun mine(): Deferred + + /** + * 侧边栏中动态增加的按钮, 返回信息包含 URI 地址(到对应的 activity) + */ + @GET("/x/resource/sidebar") + fun sidebar(): Deferred + + /** + * 首页内容 + * 首页 -> 推荐 + */ + @Suppress("SpellCheckingInspection") + @GET("/x/v2/feed/index") + fun index( + @Query("ad_extra") adExtra: String? = null, + @Query("autoplay_card") autoplayCard: Int = 0, + @Query("banner_hash") bannerHash: String? = null, + @Query("column") column: Int = 2, + @Query("device_type") deviceType: Int = 0, + @Query("flush") flush: Int = 0, + @Query("fnval") fnVal: Int = 16, + @Query("fnver") fnVer: Int = 0, + @Query("force_host") forceHost: Int = 0, + @Query("idx") index: Long = Instant.now().epochSecond, + @Query("login_event") loginEvent: Int = 2, + @Query("network") network: String = "mobile", + @Query("open_event") openEvent: String? = null, + @Query("pull") pull: Boolean = true, + @Query("qn") qn: Int = 32, + @Query("recsys_mode") recsysMode: Int = 0 + ): Deferred } diff --git a/src/main/kotlin/com/hiczp/bilibili/api/app/model/IndexPage.kt b/src/main/kotlin/com/hiczp/bilibili/api/app/model/IndexPage.kt new file mode 100644 index 0000000..7bd8645 --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/app/model/IndexPage.kt @@ -0,0 +1,374 @@ +package com.hiczp.bilibili.api.app.model + +import com.google.gson.annotations.SerializedName + +data class IndexPage( + @SerializedName("code") + var code: Int, // 0 + @SerializedName("data") + var `data`: Data, + @SerializedName("message") + var message: String, // 0 + @SerializedName("ttl") + var ttl: Int // 1 +) { + data class Data( + @SerializedName("config") + var config: Config, + @SerializedName("items") + var items: List + ) { + data class Item( + @SerializedName("ad_info") + var adInfo: AdInfo, + @SerializedName("args") + var args: Args, + @SerializedName("badge") + var badge: String, // 直播 + @SerializedName("banner_item") + var bannerItem: List, + @SerializedName("can_play") + var canPlay: Int, // 1 + @SerializedName("card_goto") + var cardGoto: String, // av + @SerializedName("card_type") + var cardType: String, // small_cover_v2 + @SerializedName("cover") + var cover: String, // http://i0.hdslb.com/bfs/archive/884e982379b32ef1dc3281e0da1864e62cf74cc3.jpg + @SerializedName("cover_left_icon_1") + var coverLeftIcon1: Int, // 1 + @SerializedName("cover_left_icon_2") + var coverLeftIcon2: Int, // 3 + @SerializedName("cover_left_text_1") + var coverLeftText1: String, // 2.9万 + @SerializedName("cover_left_text_2") + var coverLeftText2: String, // 471 + @SerializedName("cover_right_text") + var coverRightText: String, // 33:33 + @SerializedName("desc") + var desc: String, // 少年歌行11 + @SerializedName("desc_button") + var descButton: DescButton, + @SerializedName("goto") + var goto: String, // av + @SerializedName("hash") + var hash: String, // 674069931701357536 + @SerializedName("idx") + var idx: Int, // 1550559507 + @SerializedName("official_icon") + var officialIcon: Int, // 17 + @SerializedName("param") + var `param`: String, // 43804922 + @SerializedName("player_args") + var playerArgs: PlayerArgs, + @SerializedName("rcmd_reason") + var rcmdReason: String, // 已关注 + @SerializedName("rcmd_reason_style") + var rcmdReasonStyle: RcmdReasonStyle, + @SerializedName("three_point") + var threePoint: ThreePoint, + @SerializedName("three_point_v2") + var threePointV2: List, + @SerializedName("title") + var title: String, // 宇宙沙盘2娱乐,给地球加1000个月亮,先要准备好灭火器 + @SerializedName("title_right_pic") + var titleRightPic: Int, // 14 + @SerializedName("title_right_text") + var titleRightText: String, // 1 + @SerializedName("uri") + var uri: String // bilibili://video/43804922?page=1&player_preload=%7B%22cid%22%3A76731390%2C%22expire_time%22%3A1550649542%2C%22file_info%22%3A%7B%22112%22%3A%5B%7B%22timelength%22%3A2012565%2C%22filesize%22%3A1416010611%7D%5D%2C%2216%22%3A%5B%7B%22timelength%22%3A2012565%2C%22filesize%22%3A72842412%7D%5D%2C%2232%22%3A%5B%7B%22timelength%22%3A2012565%2C%22filesize%22%3A163018544%7D%5D%2C%2264%22%3A%5B%7B%22timelength%22%3A2012565%2C%22filesize%22%3A360516756%7D%5D%2C%2280%22%3A%5B%7B%22timelength%22%3A2012565%2C%22filesize%22%3A540132030%7D%5D%7D%2C%22support_quality%22%3A%5B112%2C80%2C64%2C32%2C16%5D%2C%22support_formats%22%3A%5B%22hdflv2%22%2C%22flv%22%2C%22flv720%22%2C%22flv480%22%2C%22flv360%22%5D%2C%22support_description%22%3A%5B%22%E9%AB%98%E6%B8%85%201080P%2B%22%2C%22%E9%AB%98%E6%B8%85%201080P%22%2C%22%E9%AB%98%E6%B8%85%20720P%22%2C%22%E6%B8%85%E6%99%B0%20480P%22%2C%22%E6%B5%81%E7%95%85%20360P%22%5D%2C%22quality%22%3A32%2C%22video_codecid%22%3A7%2C%22video_project%22%3Atrue%2C%22fnver%22%3A0%2C%22fnval%22%3A16%2C%22dash%22%3A%7B%22video%22%3A%5B%7B%22id%22%3A16%2C%22base_url%22%3A%22http%3A%2F%2F58.243.177.135%2Fupgcxcode%2F90%2F13%2F76731390%2F76731390-1-30015.m4s%3Fexpires%3D1550652900%5Cu0026platform%3Dandroid%5Cu0026ssig%3D42OA30l6zhf_btPLBI8CGw%5Cu0026oi%3D1699214834%5Cu0026hfa%3D2120103141%5Cu0026hfb%3DNzUxMjI5MWJlMDBjMDY0YTQxNjFjMTJiYWE0MjEwYmQ%3D%5Cu0026trid%3D8fae8885111d4e9bacbcdf70a3021572%5Cu0026nfc%3D1%22%2C%22bandwidth%22%3A391965%2C%22codecid%22%3A7%7D%2C%7B%22id%22%3A32%2C%22base_url%22%3A%22http%3A%2F%2F60.12.119.69%2Fupgcxcode%2F90%2F13%2F76731390%2F76731390-1-30032.m4s%3Fexpires%3D1550652900%5Cu0026platform%3Dandroid%5Cu0026ssig%3Dx1acEg918HekzZ7feezBAA%5Cu0026oi%3D1699214834%5Cu0026hfa%3D2120103141%5Cu0026hfb%3DNzUxMjI5MWJlMDBjMDY0YTQxNjFjMTJiYWE0MjEwYmQ%3D%5Cu0026trid%3D8fae8885111d4e9bacbcdf70a3021572%5Cu0026nfc%3D1%22%2C%22bandwidth%22%3A878269%2C%22codecid%22%3A7%7D%2C%7B%22id%22%3A64%2C%22base_url%22%3A%22http%3A%2F%2F58.243.177.134%2Fupgcxcode%2F90%2F13%2F76731390%2F76731390-1-30064.m4s%3Fexpires%3D1550652900%5Cu0026platform%3Dandroid%5Cu0026ssig%3Dg2Ryt0_xwF-bQop6Bers1g%5Cu0026oi%3D1699214834%5Cu0026hfa%3D2120103141%5Cu0026hfb%3DNzUxMjI5MWJlMDBjMDY0YTQxNjFjMTJiYWE0MjEwYmQ%3D%5Cu0026trid%3D8fae8885111d4e9bacbcdf70a3021572%5Cu0026nfc%3D1%22%2C%22bandwidth%22%3A1947512%2C%22codecid%22%3A7%7D%2C%7B%22id%22%3A80%2C%22base_url%22%3A%22http%3A%2F%2F58.243.177.135%2Fupgcxcode%2F90%2F13%2F76731390%2F76731390-1-30080.m4s%3Fexpires%3D1550652900%5Cu0026platform%3Dandroid%5Cu0026ssig%3DCe4MJYd4Q8tb1zDiPZ2NPw%5Cu0026oi%3D1699214834%5Cu0026hfa%3D2120103141%5Cu0026hfb%3DNzUxMjI5MWJlMDBjMDY0YTQxNjFjMTJiYWE0MjEwYmQ%3D%5Cu0026trid%3D8fae8885111d4e9bacbcdf70a3021572%5Cu0026nfc%3D1%22%2C%22bandwidth%22%3A2920113%2C%22codecid%22%3A7%7D%2C%7B%22id%22%3A16%2C%22base_url%22%3A%22http%3A%2F%2F60.12.119.71%2Fupgcxcode%2F90%2F13%2F76731390%2F76731390-1-30011.m4s%3Fexpires%3D1550652900%5Cu0026platform%3Dandroid%5Cu0026ssig%3DtVLJ9Xy56D8zBIHQpeHnOA%5Cu0026oi%3D1699214834%5Cu0026hfa%3D2120103141%5Cu0026hfb%3DNzUxMjI5MWJlMDBjMDY0YTQxNjFjMTJiYWE0MjEwYmQ%3D%5Cu0026trid%3D8fae8885111d4e9bacbcdf70a3021572%5Cu0026nfc%3D1%22%2C%22bandwidth%22%3A289550%2C%22codecid%22%3A12%7D%2C%7B%22id%22%3A32%2C%22base_url%22%3A%22http%3A%2F%2F60.12.119.68%2Fupgcxcode%2F90%2F13%2F76731390%2F76731390-1-30033.m4s%3Fexpires%3D1550652900%5Cu0026platform%3Dandroid%5Cu0026ssig%3DU3bKyOYXHxJDPDsFyTSYRw%5Cu0026oi%3D1699214834%5Cu0026hfa%3D2120103141%5Cu0026hfb%3DNzUxMjI5MWJlMDBjMDY0YTQxNjFjMTJiYWE0MjEwYmQ%3D%5Cu0026trid%3D8fae8885111d4e9bacbcdf70a3021572%5Cu0026nfc%3D1%22%2C%22bandwidth%22%3A648003%2C%22codecid%22%3A12%7D%2C%7B%22id%22%3A64%2C%22base_url%22%3A%22http%3A%2F%2F60.12.119.69%2Fupgcxcode%2F90%2F13%2F76731390%2F76731390-1-30066.m4s%3Fexpires%3D1550652900%5Cu0026platform%3Dandroid%5Cu0026ssig%3DQmia_xv_261EEanMCMDLBg%5Cu0026oi%3D1699214834%5Cu0026hfa%3D2120103141%5Cu0026hfb%3DNzUxMjI5MWJlMDBjMDY0YTQxNjFjMTJiYWE0MjEwYmQ%3D%5Cu0026trid%3D8fae8885111d4e9bacbcdf70a3021572%5Cu0026nfc%3D1%22%2C%22bandwidth%22%3A1433063%2C%22codecid%22%3A12%7D%2C%7B%22id%22%3A80%2C%22base_url%22%3A%22http%3A%2F%2F60.12.119.70%2Fupgcxcode%2F90%2F13%2F76731390%2F76731390-1-30077.m4s%3Fexpires%3D1550652900%5Cu0026platform%3Dandroid%5Cu0026ssig%3D7KKLcfPoYOtggLt2B8OpSw%5Cu0026oi%3D1699214834%5Cu0026hfa%3D2120103141%5Cu0026hfb%3DNzUxMjI5MWJlMDBjMDY0YTQxNjFjMTJiYWE0MjEwYmQ%3D%5Cu0026trid%3D8fae8885111d4e9bacbcdf70a3021572%5Cu0026nfc%3D1%22%2C%22bandwidth%22%3A2147039%2C%22codecid%22%3A12%7D%2C%7B%22id%22%3A112%2C%22base_url%22%3A%22http%3A%2F%2Fupos-hz-mirrorwcsu.acgvideo.com%2Fupgcxcode%2F90%2F13%2F76731390%2F76731390-1-30112.m4s%3Fe%3Dig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEuENvNC8aNEVEtEvE9IMvXBvE2ENvNCImNEVEIj0Y2J_aug859r1qXg8xNEVE5XREto8GuFGv2U7SuxI72X6fTr859IB_%5Cu0026trid%3D8fae8885111d4e9bacbcdf70a3021572%5Cu0026oi%3D1699214834%5Cu0026platform%3Dandroid%5Cu0026gen%3Dplayurl%5Cu0026uipk%3D5%5Cu0026os%3Dwcsu%5Cu0026nbs%3D1%5Cu0026deadline%3D1550653142%5Cu0026upsig%3Db1a2c5c4587c9d62c62328fd5fbf5e5d%22%2C%22bandwidth%22%3A5628680%2C%22codecid%22%3A7%7D%5D%2C%22audio%22%3A%5B%7B%22id%22%3A30280%2C%22base_url%22%3A%22http%3A%2F%2F58.243.177.131%2Fupgcxcode%2F90%2F13%2F76731390%2F76731390-1-30280.m4s%3Fexpires%3D1550652900%5Cu0026platform%3Dandroid%5Cu0026ssig%3DfoKPdZpezm90iRFrxXyj5A%5Cu0026oi%3D1699214834%5Cu0026hfa%3D2120103141%5Cu0026hfb%3DNzUxMjI5MWJlMDBjMDY0YTQxNjFjMTJiYWE0MjEwYmQ%3D%5Cu0026trid%3D8fae8885111d4e9bacbcdf70a3021572%5Cu0026nfc%3D1%22%2C%22bandwidth%22%3A167107%2C%22codecid%22%3A0%7D%2C%7B%22id%22%3A30216%2C%22base_url%22%3A%22http%3A%2F%2F222.161.224.6%2Fupgcxcode%2F90%2F13%2F76731390%2F76731390-1-30216.m4s%3Fexpires%3D1550652900%5Cu0026platform%3Dandroid%5Cu0026ssig%3Dfd9cXg9GDLF8Ci-EvSTuXQ%5Cu0026oi%3D1699214834%5Cu0026hfa%3D2120103141%5Cu0026hfb%3DNzUxMjI5MWJlMDBjMDY0YTQxNjFjMTJiYWE0MjEwYmQ%3D%5Cu0026trid%3D8fae8885111d4e9bacbcdf70a3021572%5Cu0026nfc%3D1%22%2C%22bandwidth%22%3A67216%2C%22codecid%22%3A0%7D%5D%7D%7D&player_width=1920&player_height=1080&player_rotate=0&trackid=all_3.shylf-ai-recsys-120.1550645942519.77 + ) { + data class ThreePoint( + @SerializedName("dislike_reasons") + var dislikeReasons: List, + @SerializedName("feedbacks") + var feedbacks: List, + @SerializedName("watch_later") + var watchLater: Int // 1 + ) { + data class DislikeReason( + @SerializedName("id") + var id: Int, // 1 + @SerializedName("name") + var name: String // 不感兴趣 + ) + + data class Feedback( + @SerializedName("id") + var id: Int, // 4 + @SerializedName("name") + var name: String // 标题党/封面党 + ) + } + + data class PlayerArgs( + @SerializedName("aid") + var aid: Int, // 43804922 + @SerializedName("cid") + var cid: Int // 76731390 + ) + + data class Args( + @SerializedName("rid") + var rid: Int, // 17 + @SerializedName("rname") + var rname: String, // 单机游戏 + @SerializedName("tid") + var tid: Int, // 9264 + @SerializedName("tname") + var tname: String, // 宇宙 + @SerializedName("up_id") + var upId: Int, // 131565338 + @SerializedName("up_name") + var upName: String // 的夏游戏模拟 + ) + + data class AdInfo( + @SerializedName("ad_cb") + var adCb: String, // CMyzBBDInQwYl7+RAyAeKAEw6Ro46w5CHzE1NTA2NDU5NDI1MTlxMTcyYTIzYTU2YTE0NXE1NjFI97HNzZAtUgbmna3lt55aBua1meaxn2IG5Lit5Zu9aAFwAHiAgICA4ASAAQOIAQCSAQ4xMDEuNzEuMjQ1LjI0MpoBiwNhbGw6Y3BjX2Nyb3dkX3RhcmdldCxlY3BtOmRlZmF1bHQsY3BjVGFnRmlsdGVyOnVuZGVmaW5lZCxlbmhhbmNlQ3RyUUZhY3RvcjpkZWZhdWx0LGFkTWVjaGFuaXNtTW9uaXRvcjpvdGhlcixwbGF5cGFnZWN0cjpkaXNhYmxlLHVwX3JlY19mbG93X2NvbnRyb2w6dW5kZWZpbmVkLGJydXNoX2R1cGxpY2F0ZTpkZWZhdWx0LHBjdHJfY3BtOmNwbSxkZnhfc3BlY2lmaWNfcmF0aW86dW5kZWZpbmVkLHBjdHJfdjI6a2Fma2EsZHluYW1pY19mbG93X2NvbnRyb2w6c3BsaXQgdGhlIGZsb3cgYnkgbWlkLHBjdnI6ZGxkLGZyZXFMaW1pdDpkZWZhdWx0LHNtYWxsQ29uc3VtZVVuaXQ6ZnJlcUxpbWl0TG9vc2Usb3V0ZXJCZWF0SW5uZXI6ZW5hYmxlLG91dGVyUXVpdDpkZWZhdWx0LGZkc19ydHQ6ZGVmYXVsdKABHqgB4QSyASBXbHnmbpOszwTXdVHn7Ki/qhzsnkZKkYFNZgfpS815cLoBLmh0dHBzOi8vbS53ZWliby5jbi82MTkyODc3MjQyLzQzMzM1NDIxMjI4NzM3MTLCAYUBMzA3Ml8xNDI3Xzg0Nl83MjRfNDU3XzQ1MV80MzRfMzg1XzE3NF8xNTBfMTQ4XzE0OF8xNDhfMTQ4XzE0OF8xNDdfMTQ3XzE0N18xNDdfMTQ3XzE0N18xNDdfMTM5XzEzOV8xMzlfMTM5XzEzOV8xMzlfMTM5XzEzOV8xMzlfMTM5XzEzOMoBANIBANgBJuABgIyNngLoAYCMjZ4C8AEA+AEegAICiAIAkgLlAjE4MDIyNl8xNTUwNTM0OTIxLDE5NjEzNV8xNTUwNTM0OTMxLDc3NzA3XzE1NTA1MzQ5MzgsMjAwMzkyXzE1NTA1MzUxNDUsMTc2NzgwXzE1NTA1MzUxNTMsMTgwMjI1XzE1NTA1MzUxNjYsMjA0MDMzXzE1NTA1MzUyMzMsMjAyNDQ5XzE1NTA1MzUyMzMsNzc3MjNfMTU1MDUzNTIzNywyMDA0MTNfMTU1MDUzNTI0MywxMDE3MDNfMTU1MDUzNTczOCwyMDAxNDFfMTU1MDU5MTE1MSwxOTU3MzlfMTU1MDU5MTE1NywxNzY3NDhfMTU1MDYwMTU5OSwyMDA0MTFfMTU1MDYwMTYwMCwxNTE2NTJfMTU1MDYwMTYxMCwxNTE2NTBfMTU1MDYwMTczNiwyMDI0NDVfMTU1MDYwMTc1MCwyMDUyNjBfMTU1MDYxOTAyNiwyMDUyNjNfMTU1MDYxOTAyN5gCrqCjBqAC8qUHqALu/gSwAp8EuAIAwAIAyAIA0AIA2AIA4gISLCzmna3lt54t5LiK5Z+O5Yy6 + @SerializedName("card_index") + var cardIndex: Int, // 5 + @SerializedName("card_type") + var cardType: Int, // 3 + @SerializedName("client_ip") + var clientIp: String, // 101.71.245.242 + @SerializedName("cm_mark") + var cmMark: Int, // 1 + @SerializedName("creative_content") + var creativeContent: CreativeContent, + @SerializedName("creative_id") + var creativeId: Int, // 6578071 + @SerializedName("creative_type") + var creativeType: Int, // 2 + @SerializedName("extra") + var extra: Extra, + @SerializedName("index") + var index: Int, // 2 + @SerializedName("is_ad") + var isAd: Boolean, // true + @SerializedName("is_ad_loc") + var isAdLoc: Boolean, // true + @SerializedName("request_id") + var requestId: String, // 1550645942519q172a23a56a145q561 + @SerializedName("resource") + var resource: Int, // 1897 + @SerializedName("source") + var source: Int // 1899 + ) { + data class CreativeContent( + @SerializedName("description") + var description: String, // 恶搞·剪辑 + @SerializedName("image_md5") + var imageMd5: String, // 23f4d623b4348e86890411f29688fb58 + @SerializedName("image_url") + var imageUrl: String, // https://i0.hdslb.com/bfs/sycp/creative_img/201902/9097a17ff77a3dc03ea4b8841f46078f.jpg_640x400.jpg + @SerializedName("title") + var title: String, // 往老鼠洞里打氢气和氧气,场面瞬间失控 + @SerializedName("url") + var url: String // https://cm.bilibili.com/cm/api/fees/wise/redirect?ad_cb=CMyzBBDInQwYl7%2BRAyAeKAEw6Ro46w5CHzE1NTA2NDU5NDI1MTlxMTcyYTIzYTU2YTE0NXE1NjFI97HNzZAtUgbmna3lt55aBua1meaxn2IG5Lit5Zu9aAFwAHiAgICA4ASAAQOIAQCSAQ4xMDEuNzEuMjQ1LjI0MpoBiwNhbGw6Y3BjX2Nyb3dkX3RhcmdldCxlY3BtOmRlZmF1bHQsY3BjVGFnRmlsdGVyOnVuZGVmaW5lZCxlbmhhbmNlQ3RyUUZhY3RvcjpkZWZhdWx0LGFkTWVjaGFuaXNtTW9uaXRvcjpvdGhlcixwbGF5cGFnZWN0cjpkaXNhYmxlLHVwX3JlY19mbG93X2NvbnRyb2w6dW5kZWZpbmVkLGJydXNoX2R1cGxpY2F0ZTpkZWZhdWx0LHBjdHJfY3BtOmNwbSxkZnhfc3BlY2lmaWNfcmF0aW86dW5kZWZpbmVkLHBjdHJfdjI6a2Fma2EsZHluYW1pY19mbG93X2NvbnRyb2w6c3BsaXQgdGhlIGZsb3cgYnkgbWlkLHBjdnI6ZGxkLGZyZXFMaW1pdDpkZWZhdWx0LHNtYWxsQ29uc3VtZVVuaXQ6ZnJlcUxpbWl0TG9vc2Usb3V0ZXJCZWF0SW5uZXI6ZW5hYmxlLG91dGVyUXVpdDpkZWZhdWx0LGZkc19ydHQ6ZGVmYXVsdKABHqgB4QSyASBXbHnmbpOszwTXdVHn7Ki%2FqhzsnkZKkYFNZgfpS815cLoBLmh0dHBzOi8vbS53ZWliby5jbi82MTkyODc3MjQyLzQzMzM1NDIxMjI4NzM3MTLCAYUBMzA3Ml8xNDI3Xzg0Nl83MjRfNDU3XzQ1MV80MzRfMzg1XzE3NF8xNTBfMTQ4XzE0OF8xNDhfMTQ4XzE0OF8xNDdfMTQ3XzE0N18xNDdfMTQ3XzE0N18xNDdfMTM5XzEzOV8xMzlfMTM5XzEzOV8xMzlfMTM5XzEzOV8xMzlfMTM5XzEzOMoBANIBANgBJuABgIyNngLoAYCMjZ4C8AEA%2BAEegAICiAIAkgLlAjE4MDIyNl8xNTUwNTM0OTIxLDE5NjEzNV8xNTUwNTM0OTMxLDc3NzA3XzE1NTA1MzQ5MzgsMjAwMzkyXzE1NTA1MzUxNDUsMTc2NzgwXzE1NTA1MzUxNTMsMTgwMjI1XzE1NTA1MzUxNjYsMjA0MDMzXzE1NTA1MzUyMzMsMjAyNDQ5XzE1NTA1MzUyMzMsNzc3MjNfMTU1MDUzNTIzNywyMDA0MTNfMTU1MDUzNTI0MywxMDE3MDNfMTU1MDUzNTczOCwyMDAxNDFfMTU1MDU5MTE1MSwxOTU3MzlfMTU1MDU5MTE1NywxNzY3NDhfMTU1MDYwMTU5OSwyMDA0MTFfMTU1MDYwMTYwMCwxNTE2NTJfMTU1MDYwMTYxMCwxNTE2NTBfMTU1MDYwMTczNiwyMDI0NDVfMTU1MDYwMTc1MCwyMDUyNjBfMTU1MDYxOTAyNiwyMDUyNjNfMTU1MDYxOTAyN5gCrqCjBqAC8qUHqALu%2FgSwAp8EuAIAwAIAyAIA0AIA2AIA4gISLCzmna3lt54t5LiK5Z%2BO5Yy6 + ) + + data class Extra( + @SerializedName("card") + var card: Card, + @SerializedName("click_urls") + var clickUrls: List, + @SerializedName("download_whitelist") + var downloadWhitelist: List, + @SerializedName("open_whitelist") + var openWhitelist: List, + @SerializedName("preload_landingpage") + var preloadLandingpage: Int, // 0 + @SerializedName("report_time") + var reportTime: Int, // 2000 + @SerializedName("sales_type") + var salesType: Int, // 12 + @SerializedName("show_urls") + var showUrls: List, + @SerializedName("special_industry") + var specialIndustry: Boolean, // false + @SerializedName("special_industry_tips") + var specialIndustryTips: String, + @SerializedName("use_ad_web_v2") + var useAdWebV2: Boolean // true + ) { + data class Card( + @SerializedName("ad_tag") + var adTag: String, + @SerializedName("callup_url") + var callupUrl: String, // sinaweibo://cardlist?containerid=102803&luicode=10000404&lfid=jixinshengbo_9999_001 + @SerializedName("card_type") + var cardType: Int, // 3 + @SerializedName("covers") + var covers: List, + @SerializedName("desc") + var desc: String, // 恶搞·剪辑 + @SerializedName("jump_url") + var jumpUrl: String, // https://cm.bilibili.com/cm/api/fees/wise/redirect?ad_cb=CMyzBBDInQwYl7%2BRAyAeKAEw6Ro46w5CHzE1NTA2NDU5NDI1MTlxMTcyYTIzYTU2YTE0NXE1NjFI97HNzZAtUgbmna3lt55aBua1meaxn2IG5Lit5Zu9aAFwAHiAgICA4ASAAQOIAQCSAQ4xMDEuNzEuMjQ1LjI0MpoBiwNhbGw6Y3BjX2Nyb3dkX3RhcmdldCxlY3BtOmRlZmF1bHQsY3BjVGFnRmlsdGVyOnVuZGVmaW5lZCxlbmhhbmNlQ3RyUUZhY3RvcjpkZWZhdWx0LGFkTWVjaGFuaXNtTW9uaXRvcjpvdGhlcixwbGF5cGFnZWN0cjpkaXNhYmxlLHVwX3JlY19mbG93X2NvbnRyb2w6dW5kZWZpbmVkLGJydXNoX2R1cGxpY2F0ZTpkZWZhdWx0LHBjdHJfY3BtOmNwbSxkZnhfc3BlY2lmaWNfcmF0aW86dW5kZWZpbmVkLHBjdHJfdjI6a2Fma2EsZHluYW1pY19mbG93X2NvbnRyb2w6c3BsaXQgdGhlIGZsb3cgYnkgbWlkLHBjdnI6ZGxkLGZyZXFMaW1pdDpkZWZhdWx0LHNtYWxsQ29uc3VtZVVuaXQ6ZnJlcUxpbWl0TG9vc2Usb3V0ZXJCZWF0SW5uZXI6ZW5hYmxlLG91dGVyUXVpdDpkZWZhdWx0LGZkc19ydHQ6ZGVmYXVsdKABHqgB4QSyASBXbHnmbpOszwTXdVHn7Ki%2FqhzsnkZKkYFNZgfpS815cLoBLmh0dHBzOi8vbS53ZWliby5jbi82MTkyODc3MjQyLzQzMzM1NDIxMjI4NzM3MTLCAYUBMzA3Ml8xNDI3Xzg0Nl83MjRfNDU3XzQ1MV80MzRfMzg1XzE3NF8xNTBfMTQ4XzE0OF8xNDhfMTQ4XzE0OF8xNDdfMTQ3XzE0N18xNDdfMTQ3XzE0N18xNDdfMTM5XzEzOV8xMzlfMTM5XzEzOV8xMzlfMTM5XzEzOV8xMzlfMTM5XzEzOMoBANIBANgBJuABgIyNngLoAYCMjZ4C8AEA%2BAEegAICiAIAkgLlAjE4MDIyNl8xNTUwNTM0OTIxLDE5NjEzNV8xNTUwNTM0OTMxLDc3NzA3XzE1NTA1MzQ5MzgsMjAwMzkyXzE1NTA1MzUxNDUsMTc2NzgwXzE1NTA1MzUxNTMsMTgwMjI1XzE1NTA1MzUxNjYsMjA0MDMzXzE1NTA1MzUyMzMsMjAyNDQ5XzE1NTA1MzUyMzMsNzc3MjNfMTU1MDUzNTIzNywyMDA0MTNfMTU1MDUzNTI0MywxMDE3MDNfMTU1MDUzNTczOCwyMDAxNDFfMTU1MDU5MTE1MSwxOTU3MzlfMTU1MDU5MTE1NywxNzY3NDhfMTU1MDYwMTU5OSwyMDA0MTFfMTU1MDYwMTYwMCwxNTE2NTJfMTU1MDYwMTYxMCwxNTE2NTBfMTU1MDYwMTczNiwyMDI0NDVfMTU1MDYwMTc1MCwyMDUyNjBfMTU1MDYxOTAyNiwyMDUyNjNfMTU1MDYxOTAyN5gCrqCjBqAC8qUHqALu%2FgSwAp8EuAIAwAIAyAIA0AIA2AIA4gISLCzmna3lt54t5LiK5Z%2BO5Yy6 + @SerializedName("long_desc") + var longDesc: String, + @SerializedName("title") + var title: String // 往老鼠洞里打氢气和氧气,场面瞬间失控 + ) { + data class Cover( + @SerializedName("url") + var url: String // https://i0.hdslb.com/bfs/sycp/creative_img/201902/9097a17ff77a3dc03ea4b8841f46078f.jpg_640x400.jpg + ) + } + } + } + + data class ThreePointV2( + @SerializedName("reasons") + var reasons: List, + @SerializedName("subtitle") + var subtitle: String, // (选择后将减少相似内容推荐) + @SerializedName("title") + var title: String, // 不感兴趣 + @SerializedName("type") + var type: String // dislike + ) { + data class Reason( + @SerializedName("id") + var id: Int, // 1 + @SerializedName("name") + var name: String // 不感兴趣 + ) + } + + data class BannerItem( + @SerializedName("ad_cb") + var adCb: String, // CMDeARAAGOChASAAKAAwAzjABUIfMTU1MDY0NTk0MjUxNHExNzJhMjJhNTZhMTU5cTcxNkjysc3NkC1SBuadreW3nloG5rWZ5rGfYgbkuK3lm71oAXAAeICAgIAQgAEAiAGCJJIBDjEwMS43MS4yNDUuMjQymgGKA2FsbDpjcGNfY3Jvd2RfdGFyZ2V0LGVjcG06ZGVmYXVsdCxjcGNUYWdGaWx0ZXI6dW5kZWZpbmVkLGVuaGFuY2VDdHJRRmFjdG9yOmRlZmF1bHQsYWRNZWNoYW5pc21Nb25pdG9yOm90aGVyLHBsYXlwYWdlY3RyOmRpc2FibGUsdXBfcmVjX2Zsb3dfY29udHJvbDp1bmRlZmluZWQsYnJ1c2hfZHVwbGljYXRlOmRlZmF1bHQscGN0cl9jcG06Y3BtLGRmeF9zcGVjaWZpY19yYXRpbzp1bmRlZmluZWQscGN0cl92MjpkZnQsZHluYW1pY19mbG93X2NvbnRyb2w6c3BsaXQgdGhlIGZsb3cgYnkgbWlkLHBjdnI6ZGxkLGZyZXFMaW1pdDpkZWZhdWx0LHNtYWxsQ29uc3VtZVVuaXQ6ZnJlcUxpbWl0TG9vc2Usb3V0ZXJCZWF0SW5uZXI6ZGVmYXVsdCxvdXRlclF1aXQ6ZGVmYXVsdCxmZHNfcnR0OmRlZmF1bHSgAQCoAQCyASBzEMEnoPF8mLhSbbL8kmKEYNtD/f3W63yJX7yJ/ZmpN7oBQ2JpbGliaWxpOi8vZ2FtZV9jZW50ZXIvZGV0YWlsP2lkPTgwJnNvdXJjZUZyb209NzgyJnNvdXJjZVR5cGU9YWRQdXTCAQDKAQDSAQDYAQHgAQDoAQDwAQD4AQCAAgCIAgC4AgDAAqCsT8gCANACANgCAOICEiws5p2t5beeLeS4iuWfjuWMug== + @SerializedName("click_url") + var clickUrl: String, // https://ad-bili-data.biligame.com/api/mobile/clickBili?ad_plan_id=1670&mid=__MID__&os=0&idfa=__IDFA__&buvid=__BUVID__&android_id=43d7a1ebb6669597650e3ee417d9e7f5&imei=__IMEI__&mac=1035d532877200d6598f96118c2821e8&duid=__DUID__&ip=101.71.245.242&request_id=1550645942514q172a22a56a159q716&ts=__TS__&ua=Dalvik%252F2.1.0%2B%2528Linux%253B%2BU%253B%2BAndroid%2B6.0%253B%2BAndroid%2BSDK%2Bbuilt%2Bfor%2Bx86%2BBuild%252FMASTER%2529 + @SerializedName("client_ip") + var clientIp: String, // 101.71.245.242 + @SerializedName("cm_mark") + var cmMark: Int, // 0 + @SerializedName("creative_id") + var creativeId: Int, // 20704 + @SerializedName("extra") + var extra: Extra, + @SerializedName("hash") + var hash: String, // 036073dcc265f595ce2a0d331fe404c0 + @SerializedName("id") + var id: Int, // 229421 + @SerializedName("image") + var image: String, // http://i0.hdslb.com/bfs/archive/91318bfd6076f4c5fd59b945120f346eda43cc59.jpg + @SerializedName("index") + var index: Int, // 5 + @SerializedName("is_ad") + var isAd: Boolean, // true + @SerializedName("is_ad_loc") + var isAdLoc: Boolean, // true + @SerializedName("request_id") + var requestId: String, // 1550645942462 + @SerializedName("resource_id") + var resourceId: Int, // 631 + @SerializedName("server_type") + var serverType: Int, // 0 + @SerializedName("src_id") + var srcId: Int, // 704 + @SerializedName("title") + var title: String, // 还有哪些特别的过年习俗呢? + @SerializedName("uri") + var uri: String // https://www.bilibili.com/blackboard/topic/activity-Dp6imaUka.html + ) { + data class Extra( + @SerializedName("card") + var card: Card, + @SerializedName("click_urls") + var clickUrls: List, + @SerializedName("open_whitelist") + var openWhitelist: List, + @SerializedName("preload_landingpage") + var preloadLandingpage: Int, // 0 + @SerializedName("report_time") + var reportTime: Int, // 2000 + @SerializedName("sales_type") + var salesType: Int, // 31 + @SerializedName("show_urls") + var showUrls: List, + @SerializedName("special_industry") + var specialIndustry: Boolean, // false + @SerializedName("special_industry_tips") + var specialIndustryTips: String, + @SerializedName("use_ad_web_v2") + var useAdWebV2: Boolean // false + ) { + data class Card( + @SerializedName("ad_tag") + var adTag: String, + @SerializedName("button") + var button: Button, + @SerializedName("callup_url") + var callupUrl: String, + @SerializedName("card_type") + var cardType: Int, // 0 + @SerializedName("covers") + var covers: List, + @SerializedName("desc") + var desc: String, + @SerializedName("jump_url") + var jumpUrl: String, // bilibili://game_center/detail?id=80&sourceFrom=782&sourceType=adPut + @SerializedName("long_desc") + var longDesc: String, + @SerializedName("title") + var title: String + ) { + data class Cover( + @SerializedName("url") + var url: String // https://i0.hdslb.com/bfs/sycp/creative_img/201902/abd37b988b7f043a8aba3f173ef5c220.jpg + ) + + data class Button( + @SerializedName("dlsuc_callup_url") + var dlsucCallupUrl: String, + @SerializedName("jump_url") + var jumpUrl: String, // bilibili://game_center/detail?id=80&sourceFrom=782&sourceType=adPut + @SerializedName("report_urls") + var reportUrls: List, + @SerializedName("text") + var text: String, + @SerializedName("type") + var type: Int // 1 + ) + } + } + } + + data class RcmdReasonStyle( + @SerializedName("bg_color") + var bgColor: String, // #FFFB9E60 + @SerializedName("bg_style") + var bgStyle: Int, // 1 + @SerializedName("border_color") + var borderColor: String, // #FFFB9E60 + @SerializedName("text") + var text: String, // 已关注 + @SerializedName("text_color") + var textColor: String // #FFFFFFFF + ) + + data class DescButton( + @SerializedName("event") + var event: String, // channel_click + @SerializedName("text") + var text: String, // 单机游戏 · 宇宙 + @SerializedName("type") + var type: Int, // 1 + @SerializedName("uri") + var uri: String // bilibili://pegasus/channel/9264 + ) + } + + data class Config( + @SerializedName("autoplay_card") + var autoplayCard: Int, // 2 + @SerializedName("column") + var column: Int, // 2 + @SerializedName("feed_clean_abtest") + var feedCleanAbtest: Int // 0 + ) + } +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/app/model/Mine.kt b/src/main/kotlin/com/hiczp/bilibili/api/app/model/Mine.kt new file mode 100644 index 0000000..3e7bcf7 --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/app/model/Mine.kt @@ -0,0 +1,60 @@ +package com.hiczp.bilibili.api.app.model + +import com.google.gson.annotations.SerializedName + +data class Mine( + @SerializedName("code") + var code: Int, // 0 + @SerializedName("data") + var `data`: Data, + @SerializedName("message") + var message: String, // 0 + @SerializedName("ttl") + var ttl: Int // 1 +) { + data class Data( + @SerializedName("audio_type") + var audioType: Int, // 0 + @SerializedName("bcoin") + var bcoin: Int, // 5 + @SerializedName("coin") + var coin: Double, // 892.7 + @SerializedName("dynamic") + var `dynamic`: Int, // 8 + @SerializedName("face") + var face: String, // http://i0.hdslb.com/bfs/face/0434dccc0ec4de223e8ca374dea06a6e1e8eb471.jpg + @SerializedName("follower") + var follower: Int, // 512 + @SerializedName("following") + var following: Int, // 106 + @SerializedName("level") + var level: Int, // 5 + @SerializedName("mid") + var mid: Int, // 2866663 + @SerializedName("name") + var name: String, // hyx5020 + @SerializedName("new_followers") + var newFollowers: Int, // 0 + @SerializedName("official_verify") + var officialVerify: OfficialVerify, + @SerializedName("rank") + var rank: Int, // 10000 + @SerializedName("sex") + var sex: Int, // 0 + @SerializedName("show_creative") + var showCreative: Int, // 1 + @SerializedName("show_videoup") + var showVideoup: Int, // 1 + @SerializedName("silence") + var silence: Int, // 0 + @SerializedName("vip_type") + var vipType: Int // 2 + ) { + data class OfficialVerify( + @SerializedName("desc") + var desc: String, + @SerializedName("type") + var type: Int // -1 + ) + } +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/app/model/Sidebar.kt b/src/main/kotlin/com/hiczp/bilibili/api/app/model/Sidebar.kt new file mode 100644 index 0000000..bbc5bd8 --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/app/model/Sidebar.kt @@ -0,0 +1,33 @@ +package com.hiczp.bilibili.api.app.model + +import com.google.gson.annotations.SerializedName + +data class Sidebar( + @SerializedName("code") + var code: Int, // 0 + @SerializedName("data") + var `data`: List, + @SerializedName("message") + var message: String, // 0 + @SerializedName("ttl") + var ttl: Int // 1 +) { + data class SidebarElement( + @SerializedName("id") + var id: Int, // 13 + @SerializedName("logo") + var logo: String, // http://i0.hdslb.com/bfs/archive/91f7ba40e54502f7479c8d355e4298989bb8ebce.png + @SerializedName("module") + var module: Int, // 1 + @SerializedName("name") + var name: String, // 会员购中心 + @SerializedName("online_time") + var onlineTime: Int, // 0 + @SerializedName("param") + var `param`: String, // bilibili://mall/mine?msource=mine + @SerializedName("rank") + var rank: Int, // 300 + @SerializedName("tip") + var tip: Int // 1 + ) +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/message/MessageAPI.kt b/src/main/kotlin/com/hiczp/bilibili/api/message/MessageAPI.kt new file mode 100644 index 0000000..6f6ab83 --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/message/MessageAPI.kt @@ -0,0 +1,26 @@ +package com.hiczp.bilibili.api.message + +import com.hiczp.bilibili.api.message.model.NotifyCount +import com.hiczp.bilibili.api.message.model.UplmList +import kotlinx.coroutines.Deferred +import retrofit2.http.GET + +/** + * 消息推送有关的接口 + */ +@Suppress("DeferredIsResult") +interface MessageAPI { + /** + * 获取消息数量 + * 首页 -> 右上角 talk 图标 + */ + @GET("/api/notify/query.notify.count.do") + fun queryNotifyCount(): Deferred + + /** + * 荣誉周报 + */ + @Suppress("SpellCheckingInspection") + @GET("/api/notify/get.uplm.list.do") + fun getUplmList(): Deferred +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/message/model/NotifyCount.kt b/src/main/kotlin/com/hiczp/bilibili/api/message/model/NotifyCount.kt new file mode 100644 index 0000000..cafcd65 --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/message/model/NotifyCount.kt @@ -0,0 +1,38 @@ +package com.hiczp.bilibili.api.message.model + +import com.google.gson.annotations.SerializedName + +data class NotifyCount( + @SerializedName("code") + var code: Int, // 0 + @SerializedName("data") + var `data`: Data, + @SerializedName("message") + var message: String, + @SerializedName("msg") + var msg: String +) { + data class Data( + @SerializedName("_gt_") + var gt: Int, // 0 + /** + * \@我 + */ + @SerializedName("at_me") + var atMe: Int, // 0 + @SerializedName("notify_me") + var notifyMe: Int, // 9 + /** + * 收到的赞 + */ + @SerializedName("praise_me") + var praiseMe: Int, // 0 + /** + * 回复我的 + */ + @SerializedName("reply_me") + var replyMe: Int, // 0 + @SerializedName("up") + var up: Int // 0 + ) +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/message/model/UplmList.kt b/src/main/kotlin/com/hiczp/bilibili/api/message/model/UplmList.kt new file mode 100644 index 0000000..59a0675 --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/message/model/UplmList.kt @@ -0,0 +1,27 @@ +package com.hiczp.bilibili.api.message.model + +import com.google.gson.annotations.SerializedName + +data class UplmList( + @SerializedName("code") + var code: Int, // 0 + @SerializedName("data") + var `data`: Data, + @SerializedName("message") + var message: String, + @SerializedName("msg") + var msg: String +) { + data class Data( + @SerializedName("_gt_") + var gt: Int, // 0 + @SerializedName("id") + var id: Int, // 2429173 + @SerializedName("time") + var time: String, // 2018-11-25 19:29:22 + @SerializedName("title") + var title: String, // 叮!你有一份荣誉周报待查收! + @SerializedName("unread") + var unread: Int // 0 + ) +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/passport/PassportAPI.kt b/src/main/kotlin/com/hiczp/bilibili/api/passport/PassportAPI.kt index f50d191..608a1cd 100644 --- a/src/main/kotlin/com/hiczp/bilibili/api/passport/PassportAPI.kt +++ b/src/main/kotlin/com/hiczp/bilibili/api/passport/PassportAPI.kt @@ -9,6 +9,9 @@ import retrofit2.http.FieldMap import retrofit2.http.FormUrlEncoded import retrofit2.http.POST +/** + * 用户鉴权相关的接口 + */ @Suppress("DeferredIsResult") interface PassportAPI { @POST("/api/oauth2/getKey") diff --git a/src/main/kotlin/com/hiczp/bilibili/api/vc/VcAPI.kt b/src/main/kotlin/com/hiczp/bilibili/api/vc/VcAPI.kt new file mode 100644 index 0000000..b1042ee --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/vc/VcAPI.kt @@ -0,0 +1,30 @@ +package com.hiczp.bilibili.api.vc + +import com.hiczp.bilibili.api.vc.model.AttentionList +import com.hiczp.bilibili.api.vc.model.DynamicNumber +import kotlinx.coroutines.Deferred +import retrofit2.http.GET +import retrofit2.http.Query + +/** + * 小视频 + */ +@Suppress("DeferredIsResult") +interface VcAPI { + /** + * //TODO 接口意义不明 + * 可能是一个通知接口 + */ + @GET("/dynamic_svr/v1/dynamic_svr/dynamic_num") + fun dynamicNumber( + @Query("rsp_type") rspType: Int, + @Query("type_list") typeList: Long? = null, + @Query("update_num_dy_id") updateNumberDynamicId: Int = 0 + ): Deferred + + /** + * 关注列表 + */ + @GET("/feed/v1/feed/get_attention_list") + fun getAttentionList(): Deferred +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/vc/model/AttentionList.kt b/src/main/kotlin/com/hiczp/bilibili/api/vc/model/AttentionList.kt new file mode 100644 index 0000000..2b13589 --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/vc/model/AttentionList.kt @@ -0,0 +1,19 @@ +package com.hiczp.bilibili.api.vc.model + +import com.google.gson.annotations.SerializedName + +data class AttentionList( + @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("list") + var list: List + ) +} diff --git a/src/main/kotlin/com/hiczp/bilibili/api/vc/model/DynamicNumber.kt b/src/main/kotlin/com/hiczp/bilibili/api/vc/model/DynamicNumber.kt new file mode 100644 index 0000000..9c70126 --- /dev/null +++ b/src/main/kotlin/com/hiczp/bilibili/api/vc/model/DynamicNumber.kt @@ -0,0 +1,25 @@ +package com.hiczp.bilibili.api.vc.model + +import com.google.gson.annotations.SerializedName + +data class DynamicNumber( + @SerializedName("code") + var code: Int, // 0 + @SerializedName("data") + var `data`: Data, + @SerializedName("message") + var message: String, + @SerializedName("msg") + var msg: String +) { + data class Data( + @SerializedName("_gt_") + var gt: Int, // 0 + @SerializedName("exist_gap") + var existGap: Int, // 1 + @SerializedName("new_num") + var newNum: Int, // 30 + @SerializedName("update_num") + var updateNum: Int // 100 + ) +}