Rename youtube-music module to innertube and rewrite it
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class BrowseResponse(
|
||||
val contents: Contents?,
|
||||
val header: Header?,
|
||||
val microformat: Microformat?
|
||||
) {
|
||||
@Serializable
|
||||
data class Contents(
|
||||
val singleColumnBrowseResultsRenderer: Tabs?,
|
||||
val sectionListRenderer: SectionListRenderer?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Header(
|
||||
val musicImmersiveHeaderRenderer: MusicImmersiveHeaderRenderer?,
|
||||
val musicDetailHeaderRenderer: MusicDetailHeaderRenderer?,
|
||||
) {
|
||||
@Serializable
|
||||
data class MusicDetailHeaderRenderer(
|
||||
val title: Runs?,
|
||||
val subtitle: Runs?,
|
||||
val secondSubtitle: Runs?,
|
||||
val thumbnail: ThumbnailRenderer?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MusicImmersiveHeaderRenderer(
|
||||
val description: Runs?,
|
||||
val playButton: PlayButton?,
|
||||
val startRadioButton: StartRadioButton?,
|
||||
val thumbnail: ThumbnailRenderer?,
|
||||
val title: Runs?
|
||||
) {
|
||||
@Serializable
|
||||
data class PlayButton(
|
||||
val buttonRenderer: ButtonRenderer?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class StartRadioButton(
|
||||
val buttonRenderer: ButtonRenderer?
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class Microformat(
|
||||
val microformatDataRenderer: MicroformatDataRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class MicroformatDataRenderer(
|
||||
val urlCanonical: String?
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class ButtonRenderer(
|
||||
val navigationEndpoint: NavigationEndpoint?
|
||||
)
|
||||
@@ -0,0 +1,48 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Context(
|
||||
val client: Client,
|
||||
val thirdParty: ThirdParty? = null,
|
||||
) {
|
||||
@Serializable
|
||||
data class Client(
|
||||
val clientName: String,
|
||||
val clientVersion: String,
|
||||
val visitorData: String?,
|
||||
val hl: String = "en",
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ThirdParty(
|
||||
val embedUrl: String,
|
||||
)
|
||||
|
||||
companion object {
|
||||
val DefaultWeb = Context(
|
||||
client = Client(
|
||||
clientName = "WEB_REMIX",
|
||||
clientVersion = "1.20220328.01.00",
|
||||
visitorData = "CgtsZG1ySnZiQWtSbyiMjuGSBg%3D%3D"
|
||||
)
|
||||
)
|
||||
|
||||
val DefaultAndroid = Context(
|
||||
client = Client(
|
||||
clientName = "ANDROID",
|
||||
clientVersion = "16.50",
|
||||
visitorData = null,
|
||||
)
|
||||
)
|
||||
|
||||
val DefaultAgeRestrictionBypass = Context(
|
||||
client = Client(
|
||||
clientName = "TVHTML5_SIMPLY_EMBEDDED_PLAYER",
|
||||
clientVersion = "2.0",
|
||||
visitorData = null,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonNames
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@Serializable
|
||||
data class Continuation(
|
||||
@JsonNames("nextContinuationData", "nextRadioContinuationData")
|
||||
val nextContinuationData: Data?
|
||||
) {
|
||||
@Serializable
|
||||
data class Data(
|
||||
val continuation: String?
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonNames
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@Serializable
|
||||
data class ContinuationResponse(
|
||||
val continuationContents: ContinuationContents?,
|
||||
) {
|
||||
@Serializable
|
||||
data class ContinuationContents(
|
||||
@JsonNames("musicPlaylistShelfContinuation")
|
||||
val musicShelfContinuation: MusicShelfRenderer?,
|
||||
val playlistPanelContinuation: NextResponse.MusicQueueRenderer.Content.PlaylistPanelRenderer?,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class GetQueueResponse(
|
||||
val queueDatas: List<QueueData>?,
|
||||
) {
|
||||
@Serializable
|
||||
data class QueueData(
|
||||
val content: NextResponse.MusicQueueRenderer.Content.PlaylistPanelRenderer.Content?
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class GridRenderer(
|
||||
val items: List<Item>?,
|
||||
) {
|
||||
@Serializable
|
||||
data class Item(
|
||||
val musicTwoRowItemRenderer: MusicTwoRowItemRenderer?
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class MusicCarouselShelfRenderer(
|
||||
val header: Header?,
|
||||
val contents: List<Content>,
|
||||
) {
|
||||
@Serializable
|
||||
data class Content(
|
||||
val musicTwoRowItemRenderer: MusicTwoRowItemRenderer?,
|
||||
val musicResponsiveListItemRenderer: MusicResponsiveListItemRenderer?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Header(
|
||||
val musicTwoRowItemRenderer: MusicTwoRowItemRenderer?,
|
||||
val musicResponsiveListItemRenderer: MusicResponsiveListItemRenderer?,
|
||||
val musicCarouselShelfBasicHeaderRenderer: MusicCarouselShelfBasicHeaderRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class MusicCarouselShelfBasicHeaderRenderer(
|
||||
val moreContentButton: MoreContentButton?,
|
||||
val title: Runs?,
|
||||
val strapline: Runs?,
|
||||
) {
|
||||
@Serializable
|
||||
data class MoreContentButton(
|
||||
val buttonRenderer: ButtonRenderer?
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonNames
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@Serializable
|
||||
data class MusicResponsiveListItemRenderer(
|
||||
val fixedColumns: List<FlexColumn>?,
|
||||
val flexColumns: List<FlexColumn>,
|
||||
val thumbnail: ThumbnailRenderer?,
|
||||
val navigationEndpoint: NavigationEndpoint?,
|
||||
) {
|
||||
@Serializable
|
||||
data class FlexColumn(
|
||||
@JsonNames("musicResponsiveListItemFixedColumnRenderer")
|
||||
val musicResponsiveListItemFlexColumnRenderer: MusicResponsiveListItemFlexColumnRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class MusicResponsiveListItemFlexColumnRenderer(
|
||||
val text: Runs?
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class MusicShelfRenderer(
|
||||
val bottomEndpoint: NavigationEndpoint?,
|
||||
val contents: List<Content>?,
|
||||
val continuations: List<Continuation>?,
|
||||
val title: Runs?
|
||||
) {
|
||||
@Serializable
|
||||
data class Content(
|
||||
val musicResponsiveListItemRenderer: MusicResponsiveListItemRenderer?,
|
||||
) {
|
||||
val runs: Pair<List<Runs.Run>, List<List<Runs.Run>>>
|
||||
get() = (musicResponsiveListItemRenderer
|
||||
?.flexColumns
|
||||
?.firstOrNull()
|
||||
?.musicResponsiveListItemFlexColumnRenderer
|
||||
?.text
|
||||
?.runs
|
||||
?: emptyList()) to
|
||||
(musicResponsiveListItemRenderer
|
||||
?.flexColumns
|
||||
?.lastOrNull()
|
||||
?.musicResponsiveListItemFlexColumnRenderer
|
||||
?.text
|
||||
?.splitBySeparator()
|
||||
?: emptyList()
|
||||
)
|
||||
|
||||
val thumbnail: Thumbnail?
|
||||
get() = musicResponsiveListItemRenderer
|
||||
?.thumbnail
|
||||
?.musicThumbnailRenderer
|
||||
?.thumbnail
|
||||
?.thumbnails
|
||||
?.firstOrNull()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class MusicTwoRowItemRenderer(
|
||||
val navigationEndpoint: NavigationEndpoint?,
|
||||
val thumbnailRenderer: ThumbnailRenderer?,
|
||||
val title: Runs?,
|
||||
val subtitle: Runs?,
|
||||
)
|
||||
@@ -0,0 +1,203 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* watchPlaylistEndpoint: params, playlistId
|
||||
* watchEndpoint: params, playlistId, videoId, index
|
||||
* browseEndpoint: params, browseId
|
||||
* searchEndpoint: params, query
|
||||
*/
|
||||
//@Serializable
|
||||
//data class NavigationEndpoint(
|
||||
// @JsonNames("watchEndpoint", "watchPlaylistEndpoint", "navigationEndpoint", "browseEndpoint", "searchEndpoint")
|
||||
// val endpoint: Endpoint
|
||||
//) {
|
||||
// @Serializable
|
||||
// data class Endpoint(
|
||||
// val params: String?,
|
||||
// val playlistId: String?,
|
||||
// val videoId: String?,
|
||||
// val index: Int?,
|
||||
// val browseId: String?,
|
||||
// val query: String?,
|
||||
// val watchEndpointMusicSupportedConfigs: WatchEndpointMusicSupportedConfigs?,
|
||||
// val browseEndpointContextSupportedConfigs: BrowseEndpointContextSupportedConfigs?,
|
||||
// ) {
|
||||
// @Serializable
|
||||
// data class WatchEndpointMusicSupportedConfigs(
|
||||
// val watchEndpointMusicConfig: WatchEndpointMusicConfig
|
||||
// ) {
|
||||
// @Serializable
|
||||
// data class WatchEndpointMusicConfig(
|
||||
// val musicVideoType: String
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// @Serializable
|
||||
// data class BrowseEndpointContextSupportedConfigs(
|
||||
// val browseEndpointContextMusicConfig: BrowseEndpointContextMusicConfig
|
||||
// ) {
|
||||
// @Serializable
|
||||
// data class BrowseEndpointContextMusicConfig(
|
||||
// val pageType: String
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
@Serializable
|
||||
data class NavigationEndpoint(
|
||||
val watchEndpoint: Endpoint.Watch?,
|
||||
val watchPlaylistEndpoint: Endpoint.WatchPlaylist?,
|
||||
val browseEndpoint: Endpoint.Browse?,
|
||||
val searchEndpoint: Endpoint.Search?,
|
||||
) {
|
||||
val endpoint: Endpoint?
|
||||
get() = watchEndpoint ?: browseEndpoint ?: watchPlaylistEndpoint ?: searchEndpoint
|
||||
|
||||
@Serializable
|
||||
sealed class Endpoint {
|
||||
@Serializable
|
||||
data class Watch(
|
||||
val params: String? = null,
|
||||
val playlistId: String? = null,
|
||||
val videoId: String? = null,
|
||||
val index: Int? = null,
|
||||
val playlistSetVideoId: String? = null,
|
||||
val watchEndpointMusicSupportedConfigs: WatchEndpointMusicSupportedConfigs? = null,
|
||||
) : Endpoint() {
|
||||
val type: String?
|
||||
get() = watchEndpointMusicSupportedConfigs
|
||||
?.watchEndpointMusicConfig
|
||||
?.musicVideoType
|
||||
|
||||
@Serializable
|
||||
data class WatchEndpointMusicSupportedConfigs(
|
||||
val watchEndpointMusicConfig: WatchEndpointMusicConfig?
|
||||
) {
|
||||
|
||||
@Serializable
|
||||
data class WatchEndpointMusicConfig(
|
||||
val musicVideoType: String?
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class WatchPlaylist(
|
||||
val params: String?,
|
||||
val playlistId: String?,
|
||||
) : Endpoint()
|
||||
|
||||
@Serializable
|
||||
data class Browse(
|
||||
val params: String? = null,
|
||||
val browseId: String? = null,
|
||||
val browseEndpointContextSupportedConfigs: BrowseEndpointContextSupportedConfigs? = null,
|
||||
) : Endpoint() {
|
||||
val type: String?
|
||||
get() = browseEndpointContextSupportedConfigs
|
||||
?.browseEndpointContextMusicConfig
|
||||
?.pageType
|
||||
|
||||
@Serializable
|
||||
data class BrowseEndpointContextSupportedConfigs(
|
||||
val browseEndpointContextMusicConfig: BrowseEndpointContextMusicConfig
|
||||
) {
|
||||
|
||||
@Serializable
|
||||
data class BrowseEndpointContextMusicConfig(
|
||||
val pageType: String
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class Search(
|
||||
val params: String?,
|
||||
val query: String,
|
||||
) : Endpoint()
|
||||
}
|
||||
}
|
||||
|
||||
//@Serializable(with = NavigationEndpoint.Serializer::class)
|
||||
//sealed class NavigationEndpoint {
|
||||
// @Serializable
|
||||
// data class Watch(
|
||||
// val watchEndpoint: Data
|
||||
// ) : NavigationEndpoint() {
|
||||
// @Serializable
|
||||
// data class Data(
|
||||
// val params: String?,
|
||||
// val playlistId: String,
|
||||
// val videoId: String,
|
||||
//// val index: Int?
|
||||
// val watchEndpointMusicSupportedConfigs: WatchEndpointMusicSupportedConfigs,
|
||||
// )
|
||||
//
|
||||
// @Serializable
|
||||
// data class WatchEndpointMusicSupportedConfigs(
|
||||
// val watchEndpointMusicConfig: WatchEndpointMusicConfig
|
||||
// ) {
|
||||
// @Serializable
|
||||
// data class WatchEndpointMusicConfig(
|
||||
// val musicVideoType: String
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Serializable
|
||||
// data class WatchPlaylist(
|
||||
// val watchPlaylistEndpoint: Data
|
||||
// ) : NavigationEndpoint() {
|
||||
// @Serializable
|
||||
// data class Data(
|
||||
// val params: String?,
|
||||
// val playlistId: String,
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// @Serializable
|
||||
// data class Browse(
|
||||
// val browseEndpoint: Data
|
||||
// ) : NavigationEndpoint() {
|
||||
// @Serializable
|
||||
// data class Data(
|
||||
// val params: String?,
|
||||
// val browseId: String,
|
||||
// val browseEndpointContextSupportedConfigs: BrowseEndpointContextSupportedConfigs,
|
||||
// )
|
||||
//
|
||||
// @Serializable
|
||||
// data class BrowseEndpointContextSupportedConfigs(
|
||||
// val browseEndpointContextMusicConfig: BrowseEndpointContextMusicConfig
|
||||
// ) {
|
||||
// @Serializable
|
||||
// data class BrowseEndpointContextMusicConfig(
|
||||
// val pageType: String
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Serializable
|
||||
// data class Search(
|
||||
// val searchEndpoint: Data
|
||||
// ) : NavigationEndpoint() {
|
||||
// @Serializable
|
||||
// data class Data(
|
||||
// val params: String?,
|
||||
// val query: String,
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// object Serializer : JsonContentPolymorphicSerializer<NavigationEndpoint>(NavigationEndpoint::class) {
|
||||
// override fun selectDeserializer(element: JsonElement) = when {
|
||||
// "watchEndpoint" in element.jsonObject -> Watch.serializer()
|
||||
// "watchPlaylistEndpoint" in element.jsonObject -> WatchPlaylist.serializer()
|
||||
// "browseEndpoint" in element.jsonObject -> Browse.serializer()
|
||||
// "searchEndpoint" in element.jsonObject -> Search.serializer()
|
||||
// else -> TODO()
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,87 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonNames
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@Serializable
|
||||
data class NextResponse(
|
||||
val contents: Contents?
|
||||
) {
|
||||
@Serializable
|
||||
data class MusicQueueRenderer(
|
||||
val content: Content?
|
||||
) {
|
||||
@Serializable
|
||||
data class Content(
|
||||
@JsonNames("playlistPanelContinuation")
|
||||
val playlistPanelRenderer: PlaylistPanelRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class PlaylistPanelRenderer(
|
||||
val contents: List<Content>?,
|
||||
val continuations: List<Continuation>?,
|
||||
) {
|
||||
@Serializable
|
||||
data class Content(
|
||||
val playlistPanelVideoRenderer: PlaylistPanelVideoRenderer?,
|
||||
val automixPreviewVideoRenderer: AutomixPreviewVideoRenderer?,
|
||||
) {
|
||||
|
||||
@Serializable
|
||||
data class AutomixPreviewVideoRenderer(
|
||||
val content: Content?
|
||||
) {
|
||||
@Serializable
|
||||
data class Content(
|
||||
val automixPlaylistVideoRenderer: AutomixPlaylistVideoRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class AutomixPlaylistVideoRenderer(
|
||||
val navigationEndpoint: NavigationEndpoint?
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class Contents(
|
||||
val singleColumnMusicWatchNextResultsRenderer: SingleColumnMusicWatchNextResultsRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class SingleColumnMusicWatchNextResultsRenderer(
|
||||
val tabbedRenderer: TabbedRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class TabbedRenderer(
|
||||
val watchNextTabbedResultsRenderer: WatchNextTabbedResultsRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class WatchNextTabbedResultsRenderer(
|
||||
val tabs: List<Tab>?
|
||||
) {
|
||||
@Serializable
|
||||
data class Tab(
|
||||
val tabRenderer: TabRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class TabRenderer(
|
||||
val content: Content?,
|
||||
val endpoint: NavigationEndpoint?,
|
||||
val title: String?
|
||||
) {
|
||||
@Serializable
|
||||
data class Content(
|
||||
val musicQueueRenderer: MusicQueueRenderer?
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class PlayerResponse(
|
||||
val playabilityStatus: PlayabilityStatus?,
|
||||
val playerConfig: PlayerConfig?,
|
||||
val streamingData: StreamingData?,
|
||||
) {
|
||||
@Serializable
|
||||
data class PlayabilityStatus(
|
||||
val status: String?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class PlayerConfig(
|
||||
val audioConfig: AudioConfig?
|
||||
) {
|
||||
@Serializable
|
||||
data class AudioConfig(
|
||||
val loudnessDb: Double?,
|
||||
val perceptualLoudnessDb: Double?
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class StreamingData(
|
||||
val adaptiveFormats: List<AdaptiveFormat>?
|
||||
) {
|
||||
@Serializable
|
||||
data class AdaptiveFormat(
|
||||
val itag: Int,
|
||||
val mimeType: String,
|
||||
val bitrate: Long?,
|
||||
val averageBitrate: Long?,
|
||||
val contentLength: Long?,
|
||||
val audioQuality: String?,
|
||||
val approxDurationMs: Long?,
|
||||
val lastModified: Long?,
|
||||
val loudnessDb: Double?,
|
||||
val audioSampleRate: Int?,
|
||||
val url: String?,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class PlaylistPanelVideoRenderer(
|
||||
val title: Runs?,
|
||||
val longBylineText: Runs?,
|
||||
val shortBylineText: Runs?,
|
||||
val lengthText: Runs?,
|
||||
val navigationEndpoint: NavigationEndpoint?,
|
||||
val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail?,
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Runs(
|
||||
val runs: List<Run> = listOf()
|
||||
) {
|
||||
val text: String
|
||||
get() = runs.joinToString("") { it.text ?: "" }
|
||||
|
||||
fun splitBySeparator(): List<List<Run>> {
|
||||
return runs.flatMapIndexed { index, run ->
|
||||
when {
|
||||
index == 0 || index == runs.lastIndex -> listOf(index)
|
||||
run.text == " • " -> listOf(index - 1, index + 1)
|
||||
else -> emptyList()
|
||||
}
|
||||
}.windowed(size = 2, step = 2) { (from, to) -> runs.slice(from..to) }.let {
|
||||
it.ifEmpty {
|
||||
listOf(runs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class Run(
|
||||
val text: String?,
|
||||
val navigationEndpoint: NavigationEndpoint?,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class SearchResponse(
|
||||
val contents: Contents?,
|
||||
) {
|
||||
@Serializable
|
||||
data class Contents(
|
||||
val tabbedSearchResultsRenderer: Tabs?
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class SearchSuggestionsResponse(
|
||||
val contents: List<Content>?
|
||||
) {
|
||||
@Serializable
|
||||
data class Content(
|
||||
val searchSuggestionsSectionRenderer: SearchSuggestionsSectionRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class SearchSuggestionsSectionRenderer(
|
||||
val contents: List<Content>?
|
||||
) {
|
||||
@Serializable
|
||||
data class Content(
|
||||
val searchSuggestionRenderer: SearchSuggestionRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class SearchSuggestionRenderer(
|
||||
val navigationEndpoint: NavigationEndpoint?,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonNames
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@Serializable
|
||||
data class SectionListRenderer(
|
||||
val contents: List<Content>?,
|
||||
val continuations: List<Continuation>?
|
||||
) {
|
||||
@Serializable
|
||||
data class Content(
|
||||
@JsonNames("musicImmersiveCarouselShelfRenderer")
|
||||
val musicCarouselShelfRenderer: MusicCarouselShelfRenderer?,
|
||||
@JsonNames("musicPlaylistShelfRenderer")
|
||||
val musicShelfRenderer: MusicShelfRenderer?,
|
||||
val gridRenderer: GridRenderer?,
|
||||
val musicDescriptionShelfRenderer: MusicDescriptionShelfRenderer?,
|
||||
) {
|
||||
|
||||
@Serializable
|
||||
data class MusicDescriptionShelfRenderer(
|
||||
val description: Runs?,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Tabs(
|
||||
val tabs: List<Tab>?
|
||||
) {
|
||||
@Serializable
|
||||
data class Tab(
|
||||
val tabRenderer: TabRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class TabRenderer(
|
||||
val content: Content?,
|
||||
val title: String?,
|
||||
val tabIdentifier: String?,
|
||||
) {
|
||||
@Serializable
|
||||
data class Content(
|
||||
val sectionListRenderer: SectionListRenderer?,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Thumbnail(
|
||||
val url: String,
|
||||
val height: Int?,
|
||||
val width: Int?
|
||||
) {
|
||||
val isResizable: Boolean
|
||||
get() = !url.startsWith("https://i.ytimg.com")
|
||||
|
||||
fun size(size: Int): String {
|
||||
return when {
|
||||
url.startsWith("https://lh3.googleusercontent.com") -> "$url-w$size-h$size"
|
||||
url.startsWith("https://yt3.ggpht.com") -> "$url-s$size"
|
||||
else -> url
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package it.vfsfitvnm.youtubemusic.models
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonNames
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@Serializable
|
||||
data class ThumbnailRenderer(
|
||||
@JsonNames("croppedSquareThumbnailRenderer")
|
||||
val musicThumbnailRenderer: MusicThumbnailRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class MusicThumbnailRenderer(
|
||||
val thumbnail: Thumbnail?
|
||||
) {
|
||||
@Serializable
|
||||
data class Thumbnail(
|
||||
val thumbnails: List<it.vfsfitvnm.youtubemusic.models.Thumbnail>?
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package it.vfsfitvnm.youtubemusic.models.bodies
|
||||
|
||||
import it.vfsfitvnm.youtubemusic.models.Context
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class BrowseBody(
|
||||
val context: Context = Context.DefaultWeb,
|
||||
val browseId: String,
|
||||
val params: String? = null
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package it.vfsfitvnm.youtubemusic.models.bodies
|
||||
|
||||
import it.vfsfitvnm.youtubemusic.models.Context
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class ContinuationBody(
|
||||
val context: Context = Context.DefaultWeb,
|
||||
val continuation: String,
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
package it.vfsfitvnm.youtubemusic.models.bodies
|
||||
|
||||
import it.vfsfitvnm.youtubemusic.models.Context
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class NextBody(
|
||||
val context: Context = Context.DefaultWeb,
|
||||
val videoId: String?,
|
||||
val isAudioOnly: Boolean = true,
|
||||
val playlistId: String? = null,
|
||||
val tunerSettingValue: String = "AUTOMIX_SETTING_NORMAL",
|
||||
val index: Int? = null,
|
||||
val params: String? = null,
|
||||
val playlistSetVideoId: String? = null,
|
||||
val watchEndpointMusicSupportedConfigs: WatchEndpointMusicSupportedConfigs = WatchEndpointMusicSupportedConfigs(
|
||||
musicVideoType = "MUSIC_VIDEO_TYPE_ATV"
|
||||
)
|
||||
) {
|
||||
@Serializable
|
||||
data class WatchEndpointMusicSupportedConfigs(
|
||||
val musicVideoType: String
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package it.vfsfitvnm.youtubemusic.models.bodies
|
||||
|
||||
import it.vfsfitvnm.youtubemusic.models.Context
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class PlayerBody(
|
||||
val context: Context = Context.DefaultAndroid,
|
||||
val videoId: String,
|
||||
val playlistId: String? = null
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package it.vfsfitvnm.youtubemusic.models.bodies
|
||||
|
||||
import it.vfsfitvnm.youtubemusic.models.Context
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class QueueBody(
|
||||
val context: Context = Context.DefaultWeb,
|
||||
val videoIds: List<String>? = null,
|
||||
val playlistId: String? = null,
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package it.vfsfitvnm.youtubemusic.models.bodies
|
||||
|
||||
import it.vfsfitvnm.youtubemusic.models.Context
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class SearchBody(
|
||||
val context: Context = Context.DefaultWeb,
|
||||
val query: String,
|
||||
val params: String
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package it.vfsfitvnm.youtubemusic.models.bodies
|
||||
|
||||
import it.vfsfitvnm.youtubemusic.models.Context
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class SearchSuggestionsBody(
|
||||
val context: Context = Context.DefaultWeb,
|
||||
val input: String
|
||||
)
|
||||
Reference in New Issue
Block a user