This commit is contained in:
vfsfitvnm
2022-06-16 12:57:38 +02:00
parent 4ed7268970
commit abf2be6c9a
5 changed files with 162 additions and 81 deletions

View File

@@ -415,7 +415,7 @@ fun SmallSongItem(
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
SongItem( SongItem(
thumbnailModel = song.thumbnail.size(thumbnailSizePx), thumbnailModel = song.thumbnail?.size(thumbnailSizePx),
title = song.info.name, title = song.info.name,
authors = song.authors.joinToString("") { it.name }, authors = song.authors.joinToString("") { it.name },
durationText = song.durationText, durationText = song.durationText,
@@ -436,7 +436,7 @@ fun SmallVideoItem(
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
SongItem( SongItem(
thumbnailModel = video.thumbnail.size(thumbnailSizePx), thumbnailModel = video.thumbnail?.size(thumbnailSizePx),
title = video.info.name, title = video.info.name,
authors = video.views.joinToString("") { it.name }, authors = video.views.joinToString("") { it.name },
durationText = video.durationText, durationText = video.durationText,
@@ -464,7 +464,7 @@ fun SmallPlaylistItem(
modifier = modifier modifier = modifier
) { ) {
AsyncImage( AsyncImage(
model = playlist.thumbnail.size(thumbnailSizePx), model = playlist.thumbnail?.size(thumbnailSizePx),
contentDescription = null, contentDescription = null,
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = Modifier modifier = Modifier
@@ -513,7 +513,7 @@ fun SmallAlbumItem(
modifier = modifier modifier = modifier
) { ) {
AsyncImage( AsyncImage(
model = album.thumbnail.size(thumbnailSizePx), model = album.thumbnail?.size(thumbnailSizePx),
contentDescription = null, contentDescription = null,
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = Modifier modifier = Modifier
@@ -532,7 +532,7 @@ fun SmallAlbumItem(
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
BasicText( BasicText(
text = "${album.authors.joinToString("") { it.name }} • ${album.year}", text = "${album.authors?.joinToString("") { it.name }} • ${album.year}",
style = typography.xs, style = typography.xs,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
@@ -556,7 +556,7 @@ fun SmallArtistItem(
modifier = modifier modifier = modifier
) { ) {
AsyncImage( AsyncImage(
model = artist.thumbnail.size(thumbnailSizePx), model = artist.thumbnail?.size(thumbnailSizePx),
contentDescription = null, contentDescription = null,
modifier = Modifier modifier = Modifier
.clip(CircleShape) .clip(CircleShape)

View File

@@ -95,7 +95,7 @@ fun SongItem(
thumbnailModel: Any?, thumbnailModel: Any?,
title: String, title: String,
authors: String, authors: String,
durationText: String, durationText: String?,
onClick: () -> Unit, onClick: () -> Unit,
menuContent: @Composable () -> Unit, menuContent: @Composable () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,

View File

@@ -86,7 +86,7 @@ val YouTube.Item.Song.asMediaItem: MediaItem
.setTitle(info.name) .setTitle(info.name)
.setArtist(authors.joinToString("") { it.name }) .setArtist(authors.joinToString("") { it.name })
.setAlbumTitle(album?.name) .setAlbumTitle(album?.name)
.setArtworkUri(thumbnail.url.toUri()) .setArtworkUri(thumbnail?.url?.toUri())
.setExtras( .setExtras(
bundleOf( bundleOf(
"videoId" to info.endpoint!!.videoId, "videoId" to info.endpoint!!.videoId,
@@ -109,7 +109,7 @@ val YouTube.Item.Video.asMediaItem: MediaItem
MediaMetadata.Builder() MediaMetadata.Builder()
.setTitle(info.name) .setTitle(info.name)
.setArtist(authors.joinToString("") { it.name }) .setArtist(authors.joinToString("") { it.name })
.setArtworkUri(thumbnail.url.toUri()) .setArtworkUri(thumbnail?.url?.toUri())
.setExtras( .setExtras(
bundleOf( bundleOf(
"videoId" to info.endpoint!!.videoId, "videoId" to info.endpoint!!.videoId,

View File

@@ -144,14 +144,14 @@ object YouTube {
} }
sealed class Item { sealed class Item {
abstract val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail abstract val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
data class Song( data class Song(
val info: Info<NavigationEndpoint.Endpoint.Watch>, val info: Info<NavigationEndpoint.Endpoint.Watch>,
val authors: List<Info<NavigationEndpoint.Endpoint.Browse>>, val authors: List<Info<NavigationEndpoint.Endpoint.Browse>>,
val album: Info<NavigationEndpoint.Endpoint.Browse>?, val album: Info<NavigationEndpoint.Endpoint.Browse>?,
val durationText: String, val durationText: String?,
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
) : Item() { ) : Item() {
companion object : FromMusicShelfRendererContent<Song> { companion object : FromMusicShelfRendererContent<Song> {
val Filter = Filter("EgWKAQIIAWoKEAkQBRAKEAMQBA%3D%3D") val Filter = Filter("EgWKAQIIAWoKEAkQBRAKEAMQBA%3D%3D")
@@ -161,14 +161,19 @@ object YouTube {
return Song( return Song(
info = Info.from(mainRuns.first()), info = Info.from(mainRuns.first()),
authors = otherRuns.getOrNull(otherRuns.lastIndex - 2) authors = otherRuns
?.map(Info.Companion::from) ?: emptyList(), .getOrNull(otherRuns.lastIndex - 2)
album = otherRuns.getOrNull(otherRuns.lastIndex - 1)?.firstOrNull()?.let( ?.map(Info.Companion::from)
Info.Companion::from ?: emptyList(),
), album = otherRuns
durationText = otherRuns.getOrNull(otherRuns.lastIndex)?.first()?.text .getOrNull(otherRuns.lastIndex - 1)
?: "?", ?.firstOrNull()
thumbnail = content.thumbnail ?.let(Info.Companion::from),
durationText = otherRuns
.getOrNull(otherRuns.lastIndex)
?.firstOrNull()?.text,
thumbnail = content
.thumbnail
) )
} }
} }
@@ -178,14 +183,22 @@ object YouTube {
val info: Info<NavigationEndpoint.Endpoint.Watch>, val info: Info<NavigationEndpoint.Endpoint.Watch>,
val authors: List<Info<NavigationEndpoint.Endpoint.Browse>>, val authors: List<Info<NavigationEndpoint.Endpoint.Browse>>,
val views: List<Info<NavigationEndpoint.Endpoint.Browse>>, val views: List<Info<NavigationEndpoint.Endpoint.Browse>>,
val durationText: String, val durationText: String?,
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
) : Item() { ) : Item() {
val isOfficialMusicVideo: Boolean val isOfficialMusicVideo: Boolean
get() = info.endpoint?.watchEndpointMusicSupportedConfigs?.watchEndpointMusicConfig?.musicVideoType == "MUSIC_VIDEO_TYPE_OMV" get() = info
.endpoint
?.watchEndpointMusicSupportedConfigs
?.watchEndpointMusicConfig
?.musicVideoType == "MUSIC_VIDEO_TYPE_OMV"
val isUserGeneratedContent: Boolean val isUserGeneratedContent: Boolean
get() = info.endpoint?.watchEndpointMusicSupportedConfigs?.watchEndpointMusicConfig?.musicVideoType == "MUSIC_VIDEO_TYPE_UGC" get() = info
.endpoint
?.watchEndpointMusicSupportedConfigs
?.watchEndpointMusicConfig
?.musicVideoType == "MUSIC_VIDEO_TYPE_UGC"
companion object : FromMusicShelfRendererContent<Video> { companion object : FromMusicShelfRendererContent<Video> {
val Filter = Filter("EgWKAQIQAWoKEAkQChAFEAMQBA%3D%3D") val Filter = Filter("EgWKAQIQAWoKEAkQChAFEAMQBA%3D%3D")
@@ -195,13 +208,19 @@ object YouTube {
return Video( return Video(
info = Info.from(mainRuns.first()), info = Info.from(mainRuns.first()),
authors = otherRuns.getOrNull(otherRuns.lastIndex - 2) authors = otherRuns
.getOrNull(otherRuns.lastIndex - 2)
?.map(Info.Companion::from)
?: emptyList(),
views = otherRuns
.getOrNull(otherRuns.lastIndex - 1)
?.map(Info.Companion::from) ?: emptyList(), ?.map(Info.Companion::from) ?: emptyList(),
views = otherRuns.getOrNull(otherRuns.lastIndex - 1) durationText = otherRuns
?.map(Info.Companion::from) ?: emptyList(), .getOrNull(otherRuns.lastIndex)
durationText = otherRuns.getOrNull(otherRuns.lastIndex)?.first()?.text ?.first()
?: "?", ?.text,
thumbnail = content.thumbnail thumbnail = content
.thumbnail
) )
} }
} }
@@ -209,9 +228,9 @@ object YouTube {
data class Album( data class Album(
val info: Info<NavigationEndpoint.Endpoint.Browse>, val info: Info<NavigationEndpoint.Endpoint.Browse>,
val authors: List<Info<NavigationEndpoint.Endpoint.Browse>>, val authors: List<Info<NavigationEndpoint.Endpoint.Browse>>?,
val year: String, val year: String?,
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
) : Item() { ) : Item() {
companion object : FromMusicShelfRendererContent<Album> { companion object : FromMusicShelfRendererContent<Album> {
val Filter = Filter("EgWKAQIYAWoKEAkQChAFEAMQBA%3D%3D") val Filter = Filter("EgWKAQIYAWoKEAkQChAFEAMQBA%3D%3D")
@@ -221,12 +240,23 @@ object YouTube {
return Album( return Album(
info = Info( info = Info(
name = mainRuns.first().text, name = mainRuns
endpoint = content.musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint .first()
.text,
endpoint = content
.musicResponsiveListItemRenderer
.navigationEndpoint
?.browseEndpoint
), ),
authors = otherRuns[otherRuns.lastIndex - 1].map(Info.Companion::from), authors = otherRuns
year = otherRuns[otherRuns.lastIndex].first().text, .getOrNull(otherRuns.lastIndex - 1)
thumbnail = content.thumbnail ?.map(Info.Companion::from),
year = otherRuns
.getOrNull(otherRuns.lastIndex)
?.firstOrNull()
?.text,
thumbnail = content
.thumbnail
) )
} }
} }
@@ -234,7 +264,7 @@ object YouTube {
data class Artist( data class Artist(
val info: Info<NavigationEndpoint.Endpoint.Browse>, val info: Info<NavigationEndpoint.Endpoint.Browse>,
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
) : Item() { ) : Item() {
companion object : FromMusicShelfRendererContent<Artist> { companion object : FromMusicShelfRendererContent<Artist> {
val Filter = Filter("EgWKAQIgAWoKEAkQChAFEAMQBA%3D%3D") val Filter = Filter("EgWKAQIgAWoKEAkQChAFEAMQBA%3D%3D")
@@ -244,10 +274,16 @@ object YouTube {
return Artist( return Artist(
info = Info( info = Info(
name = mainRuns.first().text, name = mainRuns
endpoint = content.musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint .first()
.text,
endpoint = content
.musicResponsiveListItemRenderer
.navigationEndpoint
?.browseEndpoint
), ),
thumbnail = content.thumbnail thumbnail = content
.thumbnail
) )
} }
} }
@@ -257,7 +293,7 @@ object YouTube {
val info: Info<NavigationEndpoint.Endpoint.Browse>, val info: Info<NavigationEndpoint.Endpoint.Browse>,
val channel: Info<NavigationEndpoint.Endpoint.Browse>?, val channel: Info<NavigationEndpoint.Endpoint.Browse>?,
val songCount: Int?, val songCount: Int?,
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail, override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
) : Item() { ) : Item() {
companion object : FromMusicShelfRendererContent<Playlist> { companion object : FromMusicShelfRendererContent<Playlist> {
override fun from(content: MusicShelfRenderer.Content): Playlist { override fun from(content: MusicShelfRenderer.Content): Playlist {
@@ -275,9 +311,8 @@ object YouTube {
), ),
channel = otherRuns channel = otherRuns
.firstOrNull() .firstOrNull()
?.firstOrNull()?.let { ?.firstOrNull()
Info.from(it) ?.let { Info.from(it) },
},
songCount = otherRuns songCount = otherRuns
.lastOrNull() .lastOrNull()
?.firstOrNull() ?.firstOrNull()
@@ -285,7 +320,8 @@ object YouTube {
?.split(' ') ?.split(' ')
?.firstOrNull() ?.firstOrNull()
?.toIntOrNull(), ?.toIntOrNull(),
thumbnail = content.thumbnail thumbnail = content
.thumbnail
) )
} }
} }
@@ -334,13 +370,13 @@ object YouTube {
.contents .contents
.tabbedSearchResultsRenderer .tabbedSearchResultsRenderer
.tabs .tabs
.first() .firstOrNull()
.tabRenderer ?.tabRenderer
.content!! ?.content
.sectionListRenderer ?.sectionListRenderer
.contents ?.contents
.first() ?.firstOrNull()
.musicShelfRenderer ?.musicShelfRenderer
} }
} else { } else {
response.bodyCatching<ContinuationResponse>().map { body -> response.bodyCatching<ContinuationResponse>().map { body ->
@@ -366,7 +402,7 @@ object YouTube {
) ?: emptyList(), ) ?: emptyList(),
continuation = musicShelfRenderer continuation = musicShelfRenderer
?.continuations ?.continuations
?.first() ?.firstOrNull()
?.nextRadioContinuationData ?.nextRadioContinuationData
?.continuation ?.continuation
) )
@@ -385,10 +421,18 @@ object YouTube {
parameter("key", Key) parameter("key", Key)
parameter("prettyPrint", false) parameter("prettyPrint", false)
}.bodyCatching<GetSearchSuggestionsResponse>().map { response -> }.bodyCatching<GetSearchSuggestionsResponse>().map { response ->
response.contents?.flatMap { content -> response
content.searchSuggestionsSectionRenderer.contents.map { .contents
it.searchSuggestionRenderer.navigationEndpoint.searchEndpoint!!.query ?.flatMap { content ->
} content
.searchSuggestionsSectionRenderer
.contents.mapNotNull {
it
.searchSuggestionRenderer
.navigationEndpoint
.searchEndpoint
?.query
}
} }
} }
} }
@@ -432,15 +476,21 @@ object YouTube {
.longBylineText .longBylineText
?.splitBySeparator() ?.splitBySeparator()
?.getOrNull(0) ?.getOrNull(0)
?.map { Info.from(it) } ?: emptyList(), ?.map { Info.from(it) }
?: emptyList(),
album = renderer album = renderer
.longBylineText .longBylineText
?.splitBySeparator() ?.splitBySeparator()
?.getOrNull(1) ?.getOrNull(1)
?.get(0) ?.getOrNull(0)
?.let { Info.from(it) }, ?.let { Info.from(it) },
thumbnail = renderer.thumbnail.thumbnails[0], thumbnail = renderer
durationText = renderer.lengthText.text .thumbnail
.thumbnails
.getOrNull(0),
durationText = renderer
.lengthText
.text
) )
} }
} }
@@ -511,10 +561,11 @@ object YouTube {
?.tabRenderer ?.tabRenderer
?.content ?.content
?.musicQueueRenderer ?.musicQueueRenderer
?.content ?: body.continuationContents) ?.content
?: body.continuationContents)
?.playlistPanelRenderer ?.playlistPanelRenderer
?.continuations ?.continuations
?.get(0) ?.getOrNull(0)
?.nextRadioContinuationData ?.nextRadioContinuationData
?.continuation, ?.continuation,
items = (tabs items = (tabs
@@ -522,25 +573,37 @@ object YouTube {
?.tabRenderer ?.tabRenderer
?.content ?.content
?.musicQueueRenderer ?.musicQueueRenderer
?.content ?: body.continuationContents) ?.content
?: body.continuationContents)
?.playlistPanelRenderer ?.playlistPanelRenderer
?.contents ?.contents
?.mapNotNull { it.playlistPanelVideoRenderer } ?.mapNotNull { it.playlistPanelVideoRenderer }
?.map { renderer -> ?.map { renderer ->
Item.Song( Item.Song(
info = Info( info = Info(
name = renderer.title.text, name = renderer
endpoint = renderer.navigationEndpoint.watchEndpoint .title
.text,
endpoint = renderer
.navigationEndpoint
.watchEndpoint
), ),
authors = renderer.longBylineText?.splitBySeparator()?.get(0) authors = renderer
?.map { run -> .longBylineText
Info.from(run) ?.splitBySeparator()
} ?: emptyList(), ?.getOrNull(0)
album = renderer.longBylineText?.splitBySeparator()?.get(1)?.get(0) ?.map { run -> Info.from(run) }
?.let { run -> ?: emptyList(),
Info.from(run) album = renderer
}, .longBylineText
thumbnail = renderer.thumbnail.thumbnails[0], ?.splitBySeparator()
?.getOrNull(1)
?.getOrNull(0)
?.let { run -> Info.from(run) },
thumbnail = renderer
.thumbnail
.thumbnails
.getOrNull(0),
durationText = renderer.lengthText.text durationText = renderer.lengthText.text
) )
}, },

View File

@@ -14,10 +14,28 @@ data class MusicShelfRenderer(
val musicResponsiveListItemRenderer: MusicResponsiveListItemRenderer, val musicResponsiveListItemRenderer: MusicResponsiveListItemRenderer,
) { ) {
val runs: Pair<List<Runs.Run>, List<List<Runs.Run>>> val runs: Pair<List<Runs.Run>, List<List<Runs.Run>>>
get() = (musicResponsiveListItemRenderer.flexColumns.first().musicResponsiveListItemFlexColumnRenderer.text?.runs ?: emptyList()) to get() = (musicResponsiveListItemRenderer
(musicResponsiveListItemRenderer.flexColumns.last().musicResponsiveListItemFlexColumnRenderer.text?.splitBySeparator() ?: emptyList()) .flexColumns
.firstOrNull()
?.musicResponsiveListItemFlexColumnRenderer
?.text
?.runs
?: emptyList()) to
(musicResponsiveListItemRenderer
.flexColumns
.lastOrNull()
?.musicResponsiveListItemFlexColumnRenderer
?.text
?.splitBySeparator()
?: emptyList()
)
val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
get() = musicResponsiveListItemRenderer.thumbnail!!.musicThumbnailRenderer.thumbnail.thumbnails.first() get() = musicResponsiveListItemRenderer
.thumbnail
?.musicThumbnailRenderer
?.thumbnail
?.thumbnails
?.firstOrNull()
} }
} }