diff --git a/src/client/music_artist.rs b/src/client/music_artist.rs index 75dafb5..66d7261 100644 --- a/src/client/music_artist.rs +++ b/src/client/music_artist.rs @@ -4,7 +4,7 @@ use once_cell::sync::Lazy; use regex::Regex; use crate::{ - client::response::url_endpoint::{MusicPageType, NavigationEndpoint}, + client::response::url_endpoint::NavigationEndpoint, error::{Error, ExtractionError}, model::{AlbumItem, ArtistId, MusicArtist}, serializer::MapResult, @@ -191,20 +191,29 @@ fn map_artist_page( .music_carousel_shelf_basic_header_renderer .more_content_button { - match button.button_renderer.navigation_endpoint.music_page() { + if let NavigationEndpoint::Browse { + browse_endpoint, .. + } = button.button_renderer.navigation_endpoint + { // Music videos - Some((MusicPageType::Playlist, id)) => { + if browse_endpoint + .browse_endpoint_context_supported_configs + .map(|cfg| { + cfg.browse_endpoint_context_music_config.page_type + == PageType::Playlist + }) + .unwrap_or_default() + { if videos_playlist_id.is_none() { - videos_playlist_id = Some(id); + videos_playlist_id = Some(browse_endpoint.browse_id); } - } - // Albums - Some((MusicPageType::ArtistDiscography, _)) => { + } else if browse_endpoint + .browse_id + .starts_with(util::ARTIST_DISCOGRAPHY_PREFIX) + { can_fetch_more = true; extendable_albums = true; - } - // Albums or playlists - Some((MusicPageType::Artist, _)) => { + } else { // Peek at the first item to determine type if let Some(response::music_item::MusicResponseItem::MusicTwoRowItemRenderer(item)) = shelf.contents.c.first() { if let Some(PageType::Album) = item.navigation_endpoint.page_type() { @@ -213,7 +222,6 @@ fn map_artist_page( } } } - _ => {} } } } diff --git a/src/client/response/music_item.rs b/src/client/response/music_item.rs index bee91c9..6bbfdff 100644 --- a/src/client/response/music_item.rs +++ b/src/client/response/music_item.rs @@ -759,7 +759,7 @@ impl MusicListMapper { })); Ok(Some(MusicItemType::Playlist)) } - MusicPageType::None | MusicPageType::ArtistDiscography => { + MusicPageType::None => { // There may be broken YT channels from the artist search. They can be skipped. Ok(None) } @@ -901,7 +901,7 @@ impl MusicListMapper { })); Ok(Some(MusicItemType::Playlist)) } - MusicPageType::None | MusicPageType::ArtistDiscography => Ok(None), + MusicPageType::None => Ok(None), MusicPageType::Unknown => { self.has_unknown = true; Ok(None) @@ -1039,7 +1039,7 @@ impl MusicListMapper { })); Some(MusicItemType::Playlist) } - MusicPageType::None | MusicPageType::ArtistDiscography => None, + MusicPageType::None => None, MusicPageType::Unknown => { self.has_unknown = true; None diff --git a/src/client/response/url_endpoint.rs b/src/client/response/url_endpoint.rs index 1b9b225..01a9374 100644 --- a/src/client/response/url_endpoint.rs +++ b/src/client/response/url_endpoint.rs @@ -102,9 +102,12 @@ pub(crate) struct BrowseEndpointConfig { pub browse_endpoint_context_music_config: BrowseEndpointMusicConfig, } +#[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub(crate) struct BrowseEndpointMusicConfig { + #[serde(default)] + #[serde_as(as = "DefaultOnError")] pub page_type: PageType, } @@ -114,9 +117,12 @@ pub(crate) struct CommandMetadata { pub web_command_metadata: WebCommandMetadata, } +#[serde_as] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub(crate) struct WebCommandMetadata { + #[serde(default)] + #[serde_as(as = "DefaultOnError")] pub web_page_type: PageType, } @@ -144,15 +150,13 @@ pub(crate) enum MusicVideoType { Track, } -#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)] +#[derive(Default, Debug, Clone, Copy, Deserialize, PartialEq, Eq)] pub(crate) enum PageType { #[serde( rename = "MUSIC_PAGE_TYPE_ARTIST", alias = "MUSIC_PAGE_TYPE_AUDIOBOOK_ARTIST" )] Artist, - #[serde(rename = "MUSIC_PAGE_TYPE_ARTIST_DISCOGRAPHY")] - ArtistDiscography, #[serde(rename = "MUSIC_PAGE_TYPE_ALBUM", alias = "MUSIC_PAGE_TYPE_AUDIOBOOK")] Album, #[serde( @@ -162,7 +166,7 @@ pub(crate) enum PageType { Channel, #[serde(rename = "MUSIC_PAGE_TYPE_PLAYLIST", alias = "WEB_PAGE_TYPE_PLAYLIST")] Playlist, - #[serde(rename = "MUSIC_PAGE_TYPE_UNKNOWN")] + #[default] Unknown, } @@ -170,9 +174,6 @@ impl PageType { pub(crate) fn to_url_target(self, id: String) -> Option { match self { PageType::Artist | PageType::Channel => Some(UrlTarget::Channel { id }), - PageType::ArtistDiscography => id - .strip_prefix(util::ARTIST_DISCOGRAPHY_PREFIX) - .map(|id| UrlTarget::Channel { id: id.to_owned() }), PageType::Album => Some(UrlTarget::Album { id }), PageType::Playlist => Some(UrlTarget::Playlist { id }), PageType::Unknown => None, @@ -183,7 +184,6 @@ impl PageType { #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub(crate) enum MusicPageType { Artist, - ArtistDiscography, Album, Playlist, Track { is_video: bool }, @@ -195,7 +195,6 @@ impl From for MusicPageType { fn from(t: PageType) -> Self { match t { PageType::Artist => MusicPageType::Artist, - PageType::ArtistDiscography => MusicPageType::ArtistDiscography, PageType::Album => MusicPageType::Album, PageType::Playlist => MusicPageType::Playlist, PageType::Channel => MusicPageType::None, diff --git a/src/serializer/snapshots/rustypipe__serializer__text__tests__t_attributed_description.snap b/src/serializer/snapshots/rustypipe__serializer__text__tests__t_attributed_description.snap index e937bcc..4966a2f 100644 --- a/src/serializer/snapshots/rustypipe__serializer__text__tests__t_attributed_description.snap +++ b/src/serializer/snapshots/rustypipe__serializer__text__tests__t_attributed_description.snap @@ -80,32 +80,42 @@ SAttributed { Text { text: "\n\n", }, - Text { + Browse { text: "#aespa", + page_type: Unknown, + browse_id: "FEhashtag", }, Text { text: " ", }, - Text { + Browse { text: "#æspa", + page_type: Unknown, + browse_id: "FEhashtag", }, Text { text: " ", }, - Text { + Browse { text: "#BlackMamba", + page_type: Unknown, + browse_id: "FEhashtag", }, Text { text: " ", }, - Text { + Browse { text: "#블랙맘바", + page_type: Unknown, + browse_id: "FEhashtag", }, Text { text: " ", }, - Text { + Browse { text: "#에스파", + page_type: Unknown, + browse_id: "FEhashtag", }, Text { text: "\naespa 에스파 'Black Mamba' MV ℗ SM Entertainment",