Fix #44
This commit is contained in:
@@ -415,7 +415,7 @@ fun SmallSongItem(
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
SongItem(
|
||||
thumbnailModel = song.thumbnail.size(thumbnailSizePx),
|
||||
thumbnailModel = song.thumbnail?.size(thumbnailSizePx),
|
||||
title = song.info.name,
|
||||
authors = song.authors.joinToString("") { it.name },
|
||||
durationText = song.durationText,
|
||||
@@ -436,7 +436,7 @@ fun SmallVideoItem(
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
SongItem(
|
||||
thumbnailModel = video.thumbnail.size(thumbnailSizePx),
|
||||
thumbnailModel = video.thumbnail?.size(thumbnailSizePx),
|
||||
title = video.info.name,
|
||||
authors = video.views.joinToString("") { it.name },
|
||||
durationText = video.durationText,
|
||||
@@ -464,7 +464,7 @@ fun SmallPlaylistItem(
|
||||
modifier = modifier
|
||||
) {
|
||||
AsyncImage(
|
||||
model = playlist.thumbnail.size(thumbnailSizePx),
|
||||
model = playlist.thumbnail?.size(thumbnailSizePx),
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier
|
||||
@@ -513,7 +513,7 @@ fun SmallAlbumItem(
|
||||
modifier = modifier
|
||||
) {
|
||||
AsyncImage(
|
||||
model = album.thumbnail.size(thumbnailSizePx),
|
||||
model = album.thumbnail?.size(thumbnailSizePx),
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier
|
||||
@@ -532,7 +532,7 @@ fun SmallAlbumItem(
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
BasicText(
|
||||
text = "${album.authors.joinToString("") { it.name }} • ${album.year}",
|
||||
text = "${album.authors?.joinToString("") { it.name }} • ${album.year}",
|
||||
style = typography.xs,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
@@ -556,7 +556,7 @@ fun SmallArtistItem(
|
||||
modifier = modifier
|
||||
) {
|
||||
AsyncImage(
|
||||
model = artist.thumbnail.size(thumbnailSizePx),
|
||||
model = artist.thumbnail?.size(thumbnailSizePx),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
|
||||
@@ -95,7 +95,7 @@ fun SongItem(
|
||||
thumbnailModel: Any?,
|
||||
title: String,
|
||||
authors: String,
|
||||
durationText: String,
|
||||
durationText: String?,
|
||||
onClick: () -> Unit,
|
||||
menuContent: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
||||
@@ -86,7 +86,7 @@ val YouTube.Item.Song.asMediaItem: MediaItem
|
||||
.setTitle(info.name)
|
||||
.setArtist(authors.joinToString("") { it.name })
|
||||
.setAlbumTitle(album?.name)
|
||||
.setArtworkUri(thumbnail.url.toUri())
|
||||
.setArtworkUri(thumbnail?.url?.toUri())
|
||||
.setExtras(
|
||||
bundleOf(
|
||||
"videoId" to info.endpoint!!.videoId,
|
||||
@@ -109,7 +109,7 @@ val YouTube.Item.Video.asMediaItem: MediaItem
|
||||
MediaMetadata.Builder()
|
||||
.setTitle(info.name)
|
||||
.setArtist(authors.joinToString("") { it.name })
|
||||
.setArtworkUri(thumbnail.url.toUri())
|
||||
.setArtworkUri(thumbnail?.url?.toUri())
|
||||
.setExtras(
|
||||
bundleOf(
|
||||
"videoId" to info.endpoint!!.videoId,
|
||||
|
||||
@@ -144,14 +144,14 @@ object YouTube {
|
||||
}
|
||||
|
||||
sealed class Item {
|
||||
abstract val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail
|
||||
abstract val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
|
||||
|
||||
data class Song(
|
||||
val info: Info<NavigationEndpoint.Endpoint.Watch>,
|
||||
val authors: List<Info<NavigationEndpoint.Endpoint.Browse>>,
|
||||
val album: Info<NavigationEndpoint.Endpoint.Browse>?,
|
||||
val durationText: String,
|
||||
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail
|
||||
val durationText: String?,
|
||||
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
|
||||
) : Item() {
|
||||
companion object : FromMusicShelfRendererContent<Song> {
|
||||
val Filter = Filter("EgWKAQIIAWoKEAkQBRAKEAMQBA%3D%3D")
|
||||
@@ -161,14 +161,19 @@ object YouTube {
|
||||
|
||||
return Song(
|
||||
info = Info.from(mainRuns.first()),
|
||||
authors = otherRuns.getOrNull(otherRuns.lastIndex - 2)
|
||||
?.map(Info.Companion::from) ?: emptyList(),
|
||||
album = otherRuns.getOrNull(otherRuns.lastIndex - 1)?.firstOrNull()?.let(
|
||||
Info.Companion::from
|
||||
),
|
||||
durationText = otherRuns.getOrNull(otherRuns.lastIndex)?.first()?.text
|
||||
?: "?",
|
||||
thumbnail = content.thumbnail
|
||||
authors = otherRuns
|
||||
.getOrNull(otherRuns.lastIndex - 2)
|
||||
?.map(Info.Companion::from)
|
||||
?: emptyList(),
|
||||
album = otherRuns
|
||||
.getOrNull(otherRuns.lastIndex - 1)
|
||||
?.firstOrNull()
|
||||
?.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 authors: List<Info<NavigationEndpoint.Endpoint.Browse>>,
|
||||
val views: List<Info<NavigationEndpoint.Endpoint.Browse>>,
|
||||
val durationText: String,
|
||||
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail
|
||||
val durationText: String?,
|
||||
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
|
||||
) : Item() {
|
||||
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
|
||||
get() = info.endpoint?.watchEndpointMusicSupportedConfigs?.watchEndpointMusicConfig?.musicVideoType == "MUSIC_VIDEO_TYPE_UGC"
|
||||
get() = info
|
||||
.endpoint
|
||||
?.watchEndpointMusicSupportedConfigs
|
||||
?.watchEndpointMusicConfig
|
||||
?.musicVideoType == "MUSIC_VIDEO_TYPE_UGC"
|
||||
|
||||
companion object : FromMusicShelfRendererContent<Video> {
|
||||
val Filter = Filter("EgWKAQIQAWoKEAkQChAFEAMQBA%3D%3D")
|
||||
@@ -195,13 +208,19 @@ object YouTube {
|
||||
|
||||
return Video(
|
||||
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(),
|
||||
views = otherRuns.getOrNull(otherRuns.lastIndex - 1)
|
||||
?.map(Info.Companion::from) ?: emptyList(),
|
||||
durationText = otherRuns.getOrNull(otherRuns.lastIndex)?.first()?.text
|
||||
?: "?",
|
||||
thumbnail = content.thumbnail
|
||||
durationText = otherRuns
|
||||
.getOrNull(otherRuns.lastIndex)
|
||||
?.first()
|
||||
?.text,
|
||||
thumbnail = content
|
||||
.thumbnail
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -209,9 +228,9 @@ object YouTube {
|
||||
|
||||
data class Album(
|
||||
val info: Info<NavigationEndpoint.Endpoint.Browse>,
|
||||
val authors: List<Info<NavigationEndpoint.Endpoint.Browse>>,
|
||||
val year: String,
|
||||
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail
|
||||
val authors: List<Info<NavigationEndpoint.Endpoint.Browse>>?,
|
||||
val year: String?,
|
||||
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
|
||||
) : Item() {
|
||||
companion object : FromMusicShelfRendererContent<Album> {
|
||||
val Filter = Filter("EgWKAQIYAWoKEAkQChAFEAMQBA%3D%3D")
|
||||
@@ -221,12 +240,23 @@ object YouTube {
|
||||
|
||||
return Album(
|
||||
info = Info(
|
||||
name = mainRuns.first().text,
|
||||
endpoint = content.musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint
|
||||
name = mainRuns
|
||||
.first()
|
||||
.text,
|
||||
endpoint = content
|
||||
.musicResponsiveListItemRenderer
|
||||
.navigationEndpoint
|
||||
?.browseEndpoint
|
||||
),
|
||||
authors = otherRuns[otherRuns.lastIndex - 1].map(Info.Companion::from),
|
||||
year = otherRuns[otherRuns.lastIndex].first().text,
|
||||
thumbnail = content.thumbnail
|
||||
authors = otherRuns
|
||||
.getOrNull(otherRuns.lastIndex - 1)
|
||||
?.map(Info.Companion::from),
|
||||
year = otherRuns
|
||||
.getOrNull(otherRuns.lastIndex)
|
||||
?.firstOrNull()
|
||||
?.text,
|
||||
thumbnail = content
|
||||
.thumbnail
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -234,7 +264,7 @@ object YouTube {
|
||||
|
||||
data class Artist(
|
||||
val info: Info<NavigationEndpoint.Endpoint.Browse>,
|
||||
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail
|
||||
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
|
||||
) : Item() {
|
||||
companion object : FromMusicShelfRendererContent<Artist> {
|
||||
val Filter = Filter("EgWKAQIgAWoKEAkQChAFEAMQBA%3D%3D")
|
||||
@@ -244,10 +274,16 @@ object YouTube {
|
||||
|
||||
return Artist(
|
||||
info = Info(
|
||||
name = mainRuns.first().text,
|
||||
endpoint = content.musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint
|
||||
name = mainRuns
|
||||
.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 channel: Info<NavigationEndpoint.Endpoint.Browse>?,
|
||||
val songCount: Int?,
|
||||
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail,
|
||||
override val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
|
||||
) : Item() {
|
||||
companion object : FromMusicShelfRendererContent<Playlist> {
|
||||
override fun from(content: MusicShelfRenderer.Content): Playlist {
|
||||
@@ -275,9 +311,8 @@ object YouTube {
|
||||
),
|
||||
channel = otherRuns
|
||||
.firstOrNull()
|
||||
?.firstOrNull()?.let {
|
||||
Info.from(it)
|
||||
},
|
||||
?.firstOrNull()
|
||||
?.let { Info.from(it) },
|
||||
songCount = otherRuns
|
||||
.lastOrNull()
|
||||
?.firstOrNull()
|
||||
@@ -285,7 +320,8 @@ object YouTube {
|
||||
?.split(' ')
|
||||
?.firstOrNull()
|
||||
?.toIntOrNull(),
|
||||
thumbnail = content.thumbnail
|
||||
thumbnail = content
|
||||
.thumbnail
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -334,13 +370,13 @@ object YouTube {
|
||||
.contents
|
||||
.tabbedSearchResultsRenderer
|
||||
.tabs
|
||||
.first()
|
||||
.tabRenderer
|
||||
.content!!
|
||||
.sectionListRenderer
|
||||
.contents
|
||||
.first()
|
||||
.musicShelfRenderer
|
||||
.firstOrNull()
|
||||
?.tabRenderer
|
||||
?.content
|
||||
?.sectionListRenderer
|
||||
?.contents
|
||||
?.firstOrNull()
|
||||
?.musicShelfRenderer
|
||||
}
|
||||
} else {
|
||||
response.bodyCatching<ContinuationResponse>().map { body ->
|
||||
@@ -366,7 +402,7 @@ object YouTube {
|
||||
) ?: emptyList(),
|
||||
continuation = musicShelfRenderer
|
||||
?.continuations
|
||||
?.first()
|
||||
?.firstOrNull()
|
||||
?.nextRadioContinuationData
|
||||
?.continuation
|
||||
)
|
||||
@@ -385,10 +421,18 @@ object YouTube {
|
||||
parameter("key", Key)
|
||||
parameter("prettyPrint", false)
|
||||
}.bodyCatching<GetSearchSuggestionsResponse>().map { response ->
|
||||
response.contents?.flatMap { content ->
|
||||
content.searchSuggestionsSectionRenderer.contents.map {
|
||||
it.searchSuggestionRenderer.navigationEndpoint.searchEndpoint!!.query
|
||||
}
|
||||
response
|
||||
.contents
|
||||
?.flatMap { content ->
|
||||
content
|
||||
.searchSuggestionsSectionRenderer
|
||||
.contents.mapNotNull {
|
||||
it
|
||||
.searchSuggestionRenderer
|
||||
.navigationEndpoint
|
||||
.searchEndpoint
|
||||
?.query
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -432,15 +476,21 @@ object YouTube {
|
||||
.longBylineText
|
||||
?.splitBySeparator()
|
||||
?.getOrNull(0)
|
||||
?.map { Info.from(it) } ?: emptyList(),
|
||||
?.map { Info.from(it) }
|
||||
?: emptyList(),
|
||||
album = renderer
|
||||
.longBylineText
|
||||
?.splitBySeparator()
|
||||
?.getOrNull(1)
|
||||
?.get(0)
|
||||
?.getOrNull(0)
|
||||
?.let { Info.from(it) },
|
||||
thumbnail = renderer.thumbnail.thumbnails[0],
|
||||
durationText = renderer.lengthText.text
|
||||
thumbnail = renderer
|
||||
.thumbnail
|
||||
.thumbnails
|
||||
.getOrNull(0),
|
||||
durationText = renderer
|
||||
.lengthText
|
||||
.text
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -511,10 +561,11 @@ object YouTube {
|
||||
?.tabRenderer
|
||||
?.content
|
||||
?.musicQueueRenderer
|
||||
?.content ?: body.continuationContents)
|
||||
?.content
|
||||
?: body.continuationContents)
|
||||
?.playlistPanelRenderer
|
||||
?.continuations
|
||||
?.get(0)
|
||||
?.getOrNull(0)
|
||||
?.nextRadioContinuationData
|
||||
?.continuation,
|
||||
items = (tabs
|
||||
@@ -522,25 +573,37 @@ object YouTube {
|
||||
?.tabRenderer
|
||||
?.content
|
||||
?.musicQueueRenderer
|
||||
?.content ?: body.continuationContents)
|
||||
?.content
|
||||
?: body.continuationContents)
|
||||
?.playlistPanelRenderer
|
||||
?.contents
|
||||
?.mapNotNull { it.playlistPanelVideoRenderer }
|
||||
?.map { renderer ->
|
||||
Item.Song(
|
||||
info = Info(
|
||||
name = renderer.title.text,
|
||||
endpoint = renderer.navigationEndpoint.watchEndpoint
|
||||
name = renderer
|
||||
.title
|
||||
.text,
|
||||
endpoint = renderer
|
||||
.navigationEndpoint
|
||||
.watchEndpoint
|
||||
),
|
||||
authors = renderer.longBylineText?.splitBySeparator()?.get(0)
|
||||
?.map { run ->
|
||||
Info.from(run)
|
||||
} ?: emptyList(),
|
||||
album = renderer.longBylineText?.splitBySeparator()?.get(1)?.get(0)
|
||||
?.let { run ->
|
||||
Info.from(run)
|
||||
},
|
||||
thumbnail = renderer.thumbnail.thumbnails[0],
|
||||
authors = renderer
|
||||
.longBylineText
|
||||
?.splitBySeparator()
|
||||
?.getOrNull(0)
|
||||
?.map { run -> Info.from(run) }
|
||||
?: emptyList(),
|
||||
album = renderer
|
||||
.longBylineText
|
||||
?.splitBySeparator()
|
||||
?.getOrNull(1)
|
||||
?.getOrNull(0)
|
||||
?.let { run -> Info.from(run) },
|
||||
thumbnail = renderer
|
||||
.thumbnail
|
||||
.thumbnails
|
||||
.getOrNull(0),
|
||||
durationText = renderer.lengthText.text
|
||||
)
|
||||
},
|
||||
|
||||
@@ -14,10 +14,28 @@ data class MusicShelfRenderer(
|
||||
val musicResponsiveListItemRenderer: MusicResponsiveListItemRenderer,
|
||||
) {
|
||||
val runs: Pair<List<Runs.Run>, List<List<Runs.Run>>>
|
||||
get() = (musicResponsiveListItemRenderer.flexColumns.first().musicResponsiveListItemFlexColumnRenderer.text?.runs ?: emptyList()) to
|
||||
(musicResponsiveListItemRenderer.flexColumns.last().musicResponsiveListItemFlexColumnRenderer.text?.splitBySeparator() ?: emptyList())
|
||||
get() = (musicResponsiveListItemRenderer
|
||||
.flexColumns
|
||||
.firstOrNull()
|
||||
?.musicResponsiveListItemFlexColumnRenderer
|
||||
?.text
|
||||
?.runs
|
||||
?: emptyList()) to
|
||||
(musicResponsiveListItemRenderer
|
||||
.flexColumns
|
||||
.lastOrNull()
|
||||
?.musicResponsiveListItemFlexColumnRenderer
|
||||
?.text
|
||||
?.splitBySeparator()
|
||||
?: emptyList()
|
||||
)
|
||||
|
||||
val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail
|
||||
get() = musicResponsiveListItemRenderer.thumbnail!!.musicThumbnailRenderer.thumbnail.thumbnails.first()
|
||||
val thumbnail: ThumbnailRenderer.MusicThumbnailRenderer.Thumbnail.Thumbnail?
|
||||
get() = musicResponsiveListItemRenderer
|
||||
.thumbnail
|
||||
?.musicThumbnailRenderer
|
||||
?.thumbnail
|
||||
?.thumbnails
|
||||
?.firstOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user