This commit is contained in:
vfsfitvnm
2022-10-13 19:48:27 +02:00
parent 7ed138ea51
commit 92141f4f49
4 changed files with 99 additions and 88 deletions

View File

@@ -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?,

View File

@@ -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
} }
} }

View File

@@ -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

View File

@@ -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,
)
}