From 7df2b673ac9b95a567896ecc42755d70e9169114 Mon Sep 17 00:00:00 2001 From: MUEDSA <7676275+muedsa@users.noreply.github.com> Date: Wed, 19 Feb 2025 16:23:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BC=98=E9=85=B7?= =?UTF-8?q?=E5=BC=B9=E5=B9=95=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/muedsa/tvbox/AppModule.kt | 35 +++- .../tvbox/danmaku/youku/YoukuApiService.kt | 52 ++++++ .../danmaku/youku/YoukuDanmakuProvider.kt | 160 ++++++++++++++++++ .../muedsa/tvbox/model/youku/YoukuDanmaku.kt | 12 ++ .../model/youku/YoukuDanmakuProperties.kt | 11 ++ .../tvbox/model/youku/YoukuDanmakuReqMsg.kt | 18 ++ .../model/youku/YoukuDanmakuReqSignedMsg.kt | 41 +++++ .../tvbox/model/youku/YoukuDanmakuResp.kt | 11 ++ .../tvbox/model/youku/YoukuDanmakuResult.kt | 9 + .../tvbox/model/youku/YoukuPageComponent.kt | 10 ++ .../youku/YoukuPageComponentCommonData.kt | 21 +++ .../muedsa/tvbox/model/youku/YoukuRpcResp.kt | 12 ++ .../tvbox/model/youku/YoukuRpcRespData.kt | 8 + .../tvbox/model/youku/YoukuSearchResp.kt | 11 ++ .../muedsa/tvbox/model/youku/YoukuTitleDTO.kt | 9 + .../tvbox/model/youku/YoukuVideoInfo.kt | 18 ++ .../muedsa/tvbox/model/youku/YoukuVideos.kt | 10 ++ 17 files changed, 442 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/com/muedsa/tvbox/danmaku/youku/YoukuApiService.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/danmaku/youku/YoukuDanmakuProvider.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmaku.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuProperties.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuReqMsg.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuReqSignedMsg.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuResp.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuResult.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuPageComponent.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuPageComponentCommonData.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuRpcResp.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuRpcRespData.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuSearchResp.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuTitleDTO.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuVideoInfo.kt create mode 100644 app/src/main/java/com/muedsa/tvbox/model/youku/YoukuVideos.kt diff --git a/app/src/main/java/com/muedsa/tvbox/AppModule.kt b/app/src/main/java/com/muedsa/tvbox/AppModule.kt index eee8018..7286367 100644 --- a/app/src/main/java/com/muedsa/tvbox/AppModule.kt +++ b/app/src/main/java/com/muedsa/tvbox/AppModule.kt @@ -8,6 +8,8 @@ import com.muedsa.tvbox.danmaku.dandanplay.DanDanPlayAuthInterceptor import com.muedsa.tvbox.danmaku.dandanplay.DanDanPlayDanmakuProvider import com.muedsa.tvbox.danmaku.iqiyi.IqiyiDanmakuProvider import com.muedsa.tvbox.danmaku.iqiyi.IqiyiSearchApiService +import com.muedsa.tvbox.danmaku.youku.YoukuApiService +import com.muedsa.tvbox.danmaku.youku.YoukuDanmakuProvider import com.muedsa.tvbox.room.AppDatabase import com.muedsa.tvbox.store.DataStoreRepo import com.muedsa.tvbox.store.PluginPerfStore @@ -61,15 +63,19 @@ internal object AppModule { @Provides @Singleton - fun provideOkhttpCookieJar(dataStoreRepo: DataStoreRepo) = PluginCookieJar( - saver = SharedCookieSaver( - store = PluginPerfStore( - pluginPackage = BuildConfig.APPLICATION_ID, - pluginDataStore = dataStoreRepo.dataStore, - ), + fun provideSharedCookieSaver(dataStoreRepo: DataStoreRepo) = SharedCookieSaver( + store = PluginPerfStore( + pluginPackage = BuildConfig.APPLICATION_ID, + pluginDataStore = dataStoreRepo.dataStore, ), ) + @Provides + @Singleton + fun provideOkhttpCookieJar(cookieSaver: SharedCookieSaver) = PluginCookieJar( + saver = cookieSaver, + ) + @Provides @Singleton fun provideOkHttpClient( @@ -110,11 +116,27 @@ internal object AppModule { ), ) + @Provides + @Singleton + fun provideYoukuDanmakuProvider( + cookieSaver: SharedCookieSaver, + okHttpClient: OkHttpClient, + ) = YoukuDanmakuProvider( + cookieSaver = cookieSaver, + okHttpClient = okHttpClient, + youkuApiService = createJsonRetrofit( + baseUrl = "https://openapi.youku.com/", + service = YoukuApiService::class.java, + okHttpClient = okHttpClient, + ), + ) + @Provides @Singleton fun provideDanmakuService( danDanPlayDanmakuProvider: DanDanPlayDanmakuProvider, iqiyiDanmakuProvider: IqiyiDanmakuProvider, + youkuDanmakuProvider: YoukuDanmakuProvider ) = DanmakuService().also { if (BuildConfig.DANDANPLAY_APP_ID.isNotEmpty() && BuildConfig.DANDANPLAY_APP_SECRET.isNotEmpty() @@ -122,5 +144,6 @@ internal object AppModule { it.register(danDanPlayDanmakuProvider) } it.register(iqiyiDanmakuProvider) + it.register(youkuDanmakuProvider) } } \ No newline at end of file diff --git a/app/src/main/java/com/muedsa/tvbox/danmaku/youku/YoukuApiService.kt b/app/src/main/java/com/muedsa/tvbox/danmaku/youku/YoukuApiService.kt new file mode 100644 index 0000000..cfce311 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/danmaku/youku/YoukuApiService.kt @@ -0,0 +1,52 @@ +package com.muedsa.tvbox.danmaku.youku + + +import com.muedsa.tvbox.model.youku.YoukuRpcResp +import com.muedsa.tvbox.model.youku.YoukuSearchResp +import com.muedsa.tvbox.model.youku.YoukuVideos +import com.muedsa.tvbox.tool.ChromeUserAgent +import retrofit2.http.Field +import retrofit2.http.FormUrlEncoded +import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.POST +import retrofit2.http.Query + +interface YoukuApiService { + + @GET("https://search.youku.com/api/search") + suspend fun search( + @Query("keyword") keyword: String, + @Query("userAgent") userAgent: String = ChromeUserAgent, + @Query("site") site: Int = 1, + @Query("categories") categories: Int = 0, + @Query("ftype") fType: Int = 0, + @Query("ob") ob: Int = 0, + @Query("pg") pg: Int = 1, + ): YoukuSearchResp + + @GET("v2/shows/videos.json") + suspend fun videos( + @Query("client_id") clientId: String = "53e6cc67237fc59a", + @Query("package") clientPackage: String = "com.huawei.hwvplayer.youku", + @Query("ext") ext: String = "show", + @Query("show_id") showId: String, + ): YoukuVideos + + @POST("https://acs.youku.com/h5/mopen.youku.danmu.list/1.0/") + @FormUrlEncoded + suspend fun danmuList( + @Field("data") data: String, + @Query("jsv") jsv: String = "2.7.0", + @Query("appKey") appKey: String, + @Query("t") t: Long, + @Query("sign") sign: String, + @Query("api") api: String = "mopen.youku.danmu.list", + @Query("v") v: String = "1.0", + @Query("type") type: String = "originaljson", + @Query("dataType") dataType: String = "jsonp", + @Query("timeout") timeout: Int = 20000, + @Query("jsonpIncPrefix") jsonpIncPrefix: String = "utility", + @Header("Referer") referer: String = "https://v.youku.com" + ): YoukuRpcResp +} \ No newline at end of file diff --git a/app/src/main/java/com/muedsa/tvbox/danmaku/youku/YoukuDanmakuProvider.kt b/app/src/main/java/com/muedsa/tvbox/danmaku/youku/YoukuDanmakuProvider.kt new file mode 100644 index 0000000..fde2536 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/danmaku/youku/YoukuDanmakuProvider.kt @@ -0,0 +1,160 @@ +package com.muedsa.tvbox.danmaku.youku + +import com.kuaishou.akdanmaku.data.DanmakuItemData +import com.muedsa.tvbox.danmaku.DanmakuProvider +import com.muedsa.tvbox.model.DanmakuEpisode +import com.muedsa.tvbox.model.DanmakuMedia +import com.muedsa.tvbox.model.youku.YoukuDanmakuProperties +import com.muedsa.tvbox.model.youku.YoukuDanmakuReqMsg +import com.muedsa.tvbox.model.youku.YoukuDanmakuReqSignedMsg +import com.muedsa.tvbox.model.youku.YoukuDanmakuResp +import com.muedsa.tvbox.tool.LenientJson +import com.muedsa.tvbox.tool.SharedCookieSaver +import com.muedsa.tvbox.tool.encodeBase64 +import com.muedsa.tvbox.tool.feignChrome +import com.muedsa.tvbox.tool.get +import com.muedsa.tvbox.tool.md5 +import com.muedsa.tvbox.tool.toRequestBuild +import kotlinx.coroutines.delay +import okhttp3.OkHttpClient +import kotlin.math.ceil +import kotlin.time.Duration.Companion.milliseconds + +class YoukuDanmakuProvider( + private val cookieSaver: SharedCookieSaver, + private val okHttpClient: OkHttpClient, + private val youkuApiService: YoukuApiService, +) : DanmakuProvider { + + init { + cookieSaver.load().filter { it.domain == "youku.com" || it.domain == "mmstat.com" } + .forEach { cookieSaver.remove(it) } + } + + override val name: String = "优酷" + + var cna: String? = null + var token: String? = null + var tokenEnc: String? = null + + override suspend fun searchMedia(keyword: String): List { + val resp = youkuApiService.search(keyword = keyword) + return resp.pageComponentList + .mapNotNull { it.commonData } + .filter { it.isYouku == 1 && it.hasYouku == 1 && it.ugcSupply == 0 } + .map { + val feats = it.feature.split(" ") + DanmakuMedia( + provider = name, + mediaId = it.showId, + mediaName = it.titleDTO.displayName, + publishDate = if (feats.size > 2) "${feats[0]} ${feats[1]}" else feats[0], + episodes = emptyList(), + ) + } + } + + override suspend fun getMediaEpisodes(media: DanmakuMedia): DanmakuMedia? { + val resp = youkuApiService.videos(showId = media.mediaId) + return resp.videos?.let { + DanmakuMedia( + provider = name, + mediaId = media.mediaId, + mediaName = media.mediaName, + publishDate = media.publishDate, + episodes = it.map { + DanmakuEpisode( + provider = name, + mediaId = media.mediaId, + mediaName = media.mediaName, + episodeId = it.id, + episodeName = it.title, + extendData = it.duration + ) + } + ) + } + } + + override suspend fun getEpisodeDanmakuList(episode: DanmakuEpisode): List { + ensureToken() + var mat = 0 + val maxMat = ceil(episode.extendData!!.toDouble() / 60).toInt() + val list = mutableListOf() + while (mat < maxMat) { + val t = System.currentTimeMillis() + val msg = YoukuDanmakuReqMsg( + ctime = t, + guid = cna!!, + vid = episode.episodeId, + mat = mat + ) + val msgJson = LenientJson.encodeToString(msg) + val msgEnc = msgJson.toByteArray(Charsets.UTF_8).encodeBase64() + val msgSign = generateMsgSign(msgEnc) + val signedMsg = YoukuDanmakuReqSignedMsg.from(msg = msg, msgEnc = msgEnc, msgSign = msgSign) + val appKey = "24679788" + val data = LenientJson.encodeToString(signedMsg) + val resp = youkuApiService.danmuList( + data = data, + appKey = appKey, + t = t, + sign = generateTokenSign("$t", appKey, data) + ) + if (!resp.data?.result.isNullOrBlank()) { + val danmakuResp = LenientJson.decodeFromString(resp.data.result) + danmakuResp.data?.result?.forEach { + val props = LenientJson.decodeFromString(it.properties) + list.add( + DanmakuItemData( + danmakuId = it.id, + position = it.playAt, + content = it.content, + mode = DanmakuItemData.DANMAKU_MODE_ROLLING, + textSize = 25, + textColor = props.color, + score = 9, + danmakuStyle = DanmakuItemData.DANMAKU_STYLE_NONE + ) + ) + } + } + mat++ + delay(100.milliseconds) + } + return list + } + + fun ensureToken() { + var cookies = cookieSaver.load() + cna = cookies.find { it.name == "cna" && (it.domain == "youku.com" || it.domain == "mmstat.com") }?.value + if (cna.isNullOrBlank()) { + "https://log.mmstat.com/eg.js" + .toRequestBuild() + .feignChrome(referer = "https://youku.com/") + .get(okHttpClient) + cookies = cookieSaver.load() + cna = cookies.find { it.name == "cna" && (it.domain == "youku.com" || it.domain == "mmstat.com") }?.value + } + + token = cookies.find { it.name == "_m_h5_tk" && it.domain == "youku.com" }?.value + tokenEnc = cookies.find { it.name == "_m_h5_tk_enc" && it.domain == "youku.com" }?.value + if (token.isNullOrBlank() || tokenEnc.isNullOrBlank()) { + "https://acs.youku.com/h5/mtop.com.youku.aplatform.weakget/1.0/?jsv=2.5.1&appKey=24679788" + .toRequestBuild() + .feignChrome(referer = "https://youku.com/") + .get(okHttpClient) + cookies = cookieSaver.load() + token = cookies.find { it.name == "_m_h5_tk" && it.domain == "youku.com" }?.value + tokenEnc = cookies.find { it.name == "_m_h5_tk_enc" && it.domain == "youku.com" }?.value + } + } + + @OptIn(ExperimentalStdlibApi::class) + fun generateMsgSign(msgEnc: String): String = + "${msgEnc}MkmC9SoIw6xCkSKHhJ7b5D2r51kBiREr".md5().toHexString() + + @OptIn(ExperimentalStdlibApi::class) + fun generateTokenSign(t: String, appKey: String, data: String): String = + listOf(token!!.substring(0, 32), t, appKey, data).joinToString("&").md5().toHexString() +} \ No newline at end of file diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmaku.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmaku.kt new file mode 100644 index 0000000..5856766 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmaku.kt @@ -0,0 +1,12 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuDanmaku( + @SerialName("id") val id: Long = 0, + @SerialName("content") val content: String, + @SerialName("propertis") val properties: String, + @SerialName("playat") val playAt: Long, //ms +) diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuProperties.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuProperties.kt new file mode 100644 index 0000000..b074299 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuProperties.kt @@ -0,0 +1,11 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuDanmakuProperties( + @SerialName("size") val size: Int, + @SerialName("color") val color: Int, + @SerialName("pos") val pos: Int, +) diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuReqMsg.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuReqMsg.kt new file mode 100644 index 0000000..f8a4b5d --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuReqMsg.kt @@ -0,0 +1,18 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuDanmakuReqMsg( + @SerialName("pid") val pid: Int = 0, + @SerialName("ctype") val ctype: Int = 10004, + @SerialName("sver") val sver: String = "3.1.0", + @SerialName("cver") val cver: String = "v1.0", + @SerialName("ctime") val ctime: Long, + @SerialName("guid") val guid: String, + @SerialName("vid") val vid: String, + @SerialName("mat") val mat: Int, + @SerialName("mcount") val mcount: Int = 1, + @SerialName("type") val type: Int = 1, +) \ No newline at end of file diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuReqSignedMsg.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuReqSignedMsg.kt new file mode 100644 index 0000000..ba34cb7 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuReqSignedMsg.kt @@ -0,0 +1,41 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuDanmakuReqSignedMsg( + @SerialName("pid") val pid: Int = 0, + @SerialName("ctype") val ctype: Int = 10004, + @SerialName("sver") val sver: String = "3.1.0", + @SerialName("cver") val cver: String = "v1.0", + @SerialName("ctime") val ctime: Long, + @SerialName("guid") val guid: String, + @SerialName("vid") val vid: String, + @SerialName("mat") val mat: Int, + @SerialName("mcount") val mcount: Int = 1, + @SerialName("type") val type: Int = 1, + @SerialName("msg") val msg: String, + @SerialName("sign") val sign: String, +) { + companion object { + fun from( + msg: YoukuDanmakuReqMsg, + msgEnc: String, + msgSign: String + ): YoukuDanmakuReqSignedMsg = YoukuDanmakuReqSignedMsg( + pid = msg.pid, + ctype = msg.ctype, + sver = msg.sver, + cver = msg.cver, + ctime = msg.ctime, + guid = msg.guid, + vid = msg.vid, + mat = msg.mat, + mcount = msg.mcount, + type = msg.type, + msg = msgEnc, + sign = msgSign, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuResp.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuResp.kt new file mode 100644 index 0000000..b421ca9 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuResp.kt @@ -0,0 +1,11 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuDanmakuResp( + // code + // cost + @SerialName("data") val data: YoukuDanmakuResult? = null, +) diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuResult.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuResult.kt new file mode 100644 index 0000000..0407435 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuDanmakuResult.kt @@ -0,0 +1,9 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuDanmakuResult( + @SerialName("result") val result: List = emptyList(), +) diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuPageComponent.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuPageComponent.kt new file mode 100644 index 0000000..7c0f761 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuPageComponent.kt @@ -0,0 +1,10 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuPageComponent( + @SerialName("commonData") val commonData: YoukuPageComponentCommonData? = null, + @SerialName("id") val id: String, +) diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuPageComponentCommonData.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuPageComponentCommonData.kt new file mode 100644 index 0000000..1bbd4b0 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuPageComponentCommonData.kt @@ -0,0 +1,21 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuPageComponentCommonData( + @SerialName("showId") val showId: String, + @SerialName("episodeTotal") val episodeTotal: Int, + @SerialName("episodeType") val episodeType: Int? = null, + @SerialName("realShowId") val realShowId: String, + @SerialName("feature") val feature: String, +// @SerialName("director") val director: String, +// @SerialName("stripeBottom") val stripeBottom: String, +// @SerialName("sourceImg") val sourceImg: String, +// @SerialName("sourceName") val sourceName: String, + @SerialName("isYouku") val isYouku: Int, + @SerialName("hasYouku") val hasYouku: Int, + @SerialName("ugcSupply") val ugcSupply: Int, + @SerialName("titleDTO") val titleDTO: YoukuTitleDTO, +) diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuRpcResp.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuRpcResp.kt new file mode 100644 index 0000000..6dc89ff --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuRpcResp.kt @@ -0,0 +1,12 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuRpcResp( + //val api: String, + @SerialName("data") val data: YoukuRpcRespData? = null, + // ret + // v +) \ No newline at end of file diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuRpcRespData.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuRpcRespData.kt new file mode 100644 index 0000000..496cba6 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuRpcRespData.kt @@ -0,0 +1,8 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuRpcRespData( + val result: String? = null +) diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuSearchResp.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuSearchResp.kt new file mode 100644 index 0000000..2a6ad69 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuSearchResp.kt @@ -0,0 +1,11 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuSearchResp( + @SerialName("message") val message: String, + @SerialName("more") val more: Boolean, + @SerialName("pageComponentList") val pageComponentList: List = emptyList(), +) \ No newline at end of file diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuTitleDTO.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuTitleDTO.kt new file mode 100644 index 0000000..1107bbf --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuTitleDTO.kt @@ -0,0 +1,9 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuTitleDTO( + @SerialName("displayName") val displayName: String, +) diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuVideoInfo.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuVideoInfo.kt new file mode 100644 index 0000000..6db3f4d --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuVideoInfo.kt @@ -0,0 +1,18 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuVideoInfo( + @SerialName("id") val id: String, + @SerialName("stage") val stage: String, + @SerialName("seq") val seq: String, + @SerialName("title") val title: String, + @SerialName("link") val link: String, + + @SerialName("duration") val duration: String, + @SerialName("category") val category: String, + + @SerialName("published") val published: String, +) diff --git a/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuVideos.kt b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuVideos.kt new file mode 100644 index 0000000..6081ab1 --- /dev/null +++ b/app/src/main/java/com/muedsa/tvbox/model/youku/YoukuVideos.kt @@ -0,0 +1,10 @@ +package com.muedsa.tvbox.model.youku + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class YoukuVideos( + @SerialName("total") val total: Int? = null, + @SerialName("videos") val videos: List? = null +)