Fix #423
This commit is contained in:
@@ -16,7 +16,7 @@ object ArtistSaver : Saver<Artist, List<Any?>> {
|
|||||||
|
|
||||||
override fun restore(value: List<Any?>): Artist = Artist(
|
override fun restore(value: List<Any?>): Artist = Artist(
|
||||||
id = value[0] as String,
|
id = value[0] as String,
|
||||||
name = value[1] as String,
|
name = value[1] as String?,
|
||||||
thumbnailUrl = value[2] as String?,
|
thumbnailUrl = value[2] as String?,
|
||||||
info = value[3] as String?,
|
info = value[3] as String?,
|
||||||
timestamp = value[4] as Long?,
|
timestamp = value[4] as Long?,
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ val DetailedSong.asMediaItem: MediaItem
|
|||||||
fun String?.thumbnail(size: Int): String? {
|
fun String?.thumbnail(size: Int): String? {
|
||||||
return when {
|
return when {
|
||||||
this?.startsWith("https://lh3.googleusercontent.com") == true -> "$this-w$size-h$size"
|
this?.startsWith("https://lh3.googleusercontent.com") == true -> "$this-w$size-h$size"
|
||||||
this?.startsWith("https://yt3.ggpht.com") == true -> "$this-s$size"
|
this?.startsWith("https://yt3.ggpht.com") == true -> "$this-w$size-h$size-s$size"
|
||||||
else -> this
|
else -> this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package it.vfsfitvnm.youtubemusic.models
|
package it.vfsfitvnm.youtubemusic.models
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.JsonNames
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class BrowseResponse(
|
data class BrowseResponse(
|
||||||
@@ -15,7 +17,8 @@ data class BrowseResponse(
|
|||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Header(
|
data class Header @OptIn(ExperimentalSerializationApi::class) constructor(
|
||||||
|
@JsonNames("musicVisualHeaderRenderer")
|
||||||
val musicImmersiveHeaderRenderer: MusicImmersiveHeaderRenderer?,
|
val musicImmersiveHeaderRenderer: MusicImmersiveHeaderRenderer?,
|
||||||
val musicDetailHeaderRenderer: MusicDetailHeaderRenderer?,
|
val musicDetailHeaderRenderer: MusicDetailHeaderRenderer?,
|
||||||
) {
|
) {
|
||||||
@@ -33,6 +36,7 @@ data class BrowseResponse(
|
|||||||
val playButton: PlayButton?,
|
val playButton: PlayButton?,
|
||||||
val startRadioButton: StartRadioButton?,
|
val startRadioButton: StartRadioButton?,
|
||||||
val thumbnail: ThumbnailRenderer?,
|
val thumbnail: ThumbnailRenderer?,
|
||||||
|
val foregroundThumbnail: ThumbnailRenderer?,
|
||||||
val title: Runs?
|
val title: Runs?
|
||||||
) {
|
) {
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|||||||
@@ -13,90 +13,97 @@ import it.vfsfitvnm.youtubemusic.utils.findSectionByTitle
|
|||||||
import it.vfsfitvnm.youtubemusic.utils.from
|
import it.vfsfitvnm.youtubemusic.utils.from
|
||||||
import it.vfsfitvnm.youtubemusic.utils.runCatchingNonCancellable
|
import it.vfsfitvnm.youtubemusic.utils.runCatchingNonCancellable
|
||||||
|
|
||||||
suspend fun Innertube.artistPage(body: BrowseBody): Result<Innertube.ArtistPage>? = runCatchingNonCancellable {
|
suspend fun Innertube.artistPage(body: BrowseBody): Result<Innertube.ArtistPage>? =
|
||||||
val response = client.post(browse) {
|
runCatchingNonCancellable {
|
||||||
setBody(body)
|
val response = client.post(browse) {
|
||||||
mask("contents,header")
|
setBody(body)
|
||||||
}.body<BrowseResponse>()
|
mask("contents,header")
|
||||||
|
}.body<BrowseResponse>()
|
||||||
|
|
||||||
fun findSectionByTitle(text: String): SectionListRenderer.Content? {
|
println(response)
|
||||||
return response
|
|
||||||
.contents
|
fun findSectionByTitle(text: String): SectionListRenderer.Content? {
|
||||||
?.singleColumnBrowseResultsRenderer
|
return response
|
||||||
?.tabs
|
.contents
|
||||||
?.get(0)
|
?.singleColumnBrowseResultsRenderer
|
||||||
?.tabRenderer
|
?.tabs
|
||||||
?.content
|
?.get(0)
|
||||||
?.sectionListRenderer
|
?.tabRenderer
|
||||||
?.findSectionByTitle(text)
|
?.content
|
||||||
|
?.sectionListRenderer
|
||||||
|
?.findSectionByTitle(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
val songsSection = findSectionByTitle("Songs")?.musicShelfRenderer
|
||||||
|
val albumsSection = findSectionByTitle("Albums")?.musicCarouselShelfRenderer
|
||||||
|
val singlesSection = findSectionByTitle("Singles")?.musicCarouselShelfRenderer
|
||||||
|
|
||||||
|
Innertube.ArtistPage(
|
||||||
|
name = response
|
||||||
|
.header
|
||||||
|
?.musicImmersiveHeaderRenderer
|
||||||
|
?.title
|
||||||
|
?.text,
|
||||||
|
description = response
|
||||||
|
.header
|
||||||
|
?.musicImmersiveHeaderRenderer
|
||||||
|
?.description
|
||||||
|
?.text
|
||||||
|
?.substringBeforeLast("\n\nFrom Wikipedia"),
|
||||||
|
thumbnail = (response
|
||||||
|
.header
|
||||||
|
?.musicImmersiveHeaderRenderer
|
||||||
|
?.foregroundThumbnail
|
||||||
|
?: response
|
||||||
|
.header
|
||||||
|
?.musicImmersiveHeaderRenderer
|
||||||
|
?.thumbnail)
|
||||||
|
?.musicThumbnailRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.thumbnails
|
||||||
|
?.getOrNull(0),
|
||||||
|
shuffleEndpoint = response
|
||||||
|
.header
|
||||||
|
?.musicImmersiveHeaderRenderer
|
||||||
|
?.playButton
|
||||||
|
?.buttonRenderer
|
||||||
|
?.navigationEndpoint
|
||||||
|
?.watchEndpoint,
|
||||||
|
radioEndpoint = response
|
||||||
|
.header
|
||||||
|
?.musicImmersiveHeaderRenderer
|
||||||
|
?.startRadioButton
|
||||||
|
?.buttonRenderer
|
||||||
|
?.navigationEndpoint
|
||||||
|
?.watchEndpoint,
|
||||||
|
songs = songsSection
|
||||||
|
?.contents
|
||||||
|
?.mapNotNull(MusicShelfRenderer.Content::musicResponsiveListItemRenderer)
|
||||||
|
?.mapNotNull(Innertube.SongItem::from),
|
||||||
|
songsEndpoint = songsSection
|
||||||
|
?.bottomEndpoint
|
||||||
|
?.browseEndpoint,
|
||||||
|
albums = albumsSection
|
||||||
|
?.contents
|
||||||
|
?.mapNotNull(MusicCarouselShelfRenderer.Content::musicTwoRowItemRenderer)
|
||||||
|
?.mapNotNull(Innertube.AlbumItem::from),
|
||||||
|
albumsEndpoint = albumsSection
|
||||||
|
?.header
|
||||||
|
?.musicCarouselShelfBasicHeaderRenderer
|
||||||
|
?.moreContentButton
|
||||||
|
?.buttonRenderer
|
||||||
|
?.navigationEndpoint
|
||||||
|
?.browseEndpoint,
|
||||||
|
singles = singlesSection
|
||||||
|
?.contents
|
||||||
|
?.mapNotNull(MusicCarouselShelfRenderer.Content::musicTwoRowItemRenderer)
|
||||||
|
?.mapNotNull(Innertube.AlbumItem::from),
|
||||||
|
singlesEndpoint = singlesSection
|
||||||
|
?.header
|
||||||
|
?.musicCarouselShelfBasicHeaderRenderer
|
||||||
|
?.moreContentButton
|
||||||
|
?.buttonRenderer
|
||||||
|
?.navigationEndpoint
|
||||||
|
?.browseEndpoint,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val songsSection = findSectionByTitle("Songs")?.musicShelfRenderer
|
|
||||||
val albumsSection = findSectionByTitle("Albums")?.musicCarouselShelfRenderer
|
|
||||||
val singlesSection = findSectionByTitle("Singles")?.musicCarouselShelfRenderer
|
|
||||||
|
|
||||||
Innertube.ArtistPage(
|
|
||||||
name = response
|
|
||||||
.header
|
|
||||||
?.musicImmersiveHeaderRenderer
|
|
||||||
?.title
|
|
||||||
?.text,
|
|
||||||
description = response
|
|
||||||
.header
|
|
||||||
?.musicImmersiveHeaderRenderer
|
|
||||||
?.description
|
|
||||||
?.text
|
|
||||||
?.substringBeforeLast("\n\nFrom Wikipedia"),
|
|
||||||
thumbnail = response
|
|
||||||
.header
|
|
||||||
?.musicImmersiveHeaderRenderer
|
|
||||||
?.thumbnail
|
|
||||||
?.musicThumbnailRenderer
|
|
||||||
?.thumbnail
|
|
||||||
?.thumbnails
|
|
||||||
?.getOrNull(0),
|
|
||||||
shuffleEndpoint = response
|
|
||||||
.header
|
|
||||||
?.musicImmersiveHeaderRenderer
|
|
||||||
?.playButton
|
|
||||||
?.buttonRenderer
|
|
||||||
?.navigationEndpoint
|
|
||||||
?.watchEndpoint,
|
|
||||||
radioEndpoint = response
|
|
||||||
.header
|
|
||||||
?.musicImmersiveHeaderRenderer
|
|
||||||
?.startRadioButton
|
|
||||||
?.buttonRenderer
|
|
||||||
?.navigationEndpoint
|
|
||||||
?.watchEndpoint,
|
|
||||||
songs = songsSection
|
|
||||||
?.contents
|
|
||||||
?.mapNotNull(MusicShelfRenderer.Content::musicResponsiveListItemRenderer)
|
|
||||||
?.mapNotNull(Innertube.SongItem::from),
|
|
||||||
songsEndpoint = songsSection
|
|
||||||
?.bottomEndpoint
|
|
||||||
?.browseEndpoint,
|
|
||||||
albums = albumsSection
|
|
||||||
?.contents
|
|
||||||
?.mapNotNull(MusicCarouselShelfRenderer.Content::musicTwoRowItemRenderer)
|
|
||||||
?.mapNotNull(Innertube.AlbumItem::from),
|
|
||||||
albumsEndpoint = albumsSection
|
|
||||||
?.header
|
|
||||||
?.musicCarouselShelfBasicHeaderRenderer
|
|
||||||
?.moreContentButton
|
|
||||||
?.buttonRenderer
|
|
||||||
?.navigationEndpoint
|
|
||||||
?.browseEndpoint,
|
|
||||||
singles = singlesSection
|
|
||||||
?.contents
|
|
||||||
?.mapNotNull(MusicCarouselShelfRenderer.Content::musicTwoRowItemRenderer)
|
|
||||||
?.mapNotNull(Innertube.AlbumItem::from),
|
|
||||||
singlesEndpoint = singlesSection
|
|
||||||
?.header
|
|
||||||
?.musicCarouselShelfBasicHeaderRenderer
|
|
||||||
?.moreContentButton
|
|
||||||
?.buttonRenderer
|
|
||||||
?.navigationEndpoint
|
|
||||||
?.browseEndpoint,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user