diff --git a/src/client/music_artist.rs b/src/client/music_artist.rs index 12e79d4..1d21d42 100644 --- a/src/client/music_artist.rs +++ b/src/client/music_artist.rs @@ -34,9 +34,13 @@ impl RustyPipeQuery { artist_id: S, all_albums: bool, ) -> Result { + let artist_id = artist_id.as_ref(); + log::debug!("Getting music artist {}", artist_id); + let res = self._music_artist(artist_id, all_albums).await; if let Err(Error::Extraction(ExtractionError::Redirect(id))) = res { + log::debug!("Music artist {} redirects to {}", artist_id, &id); self._music_artist(&id, all_albums).await.map(|x| *x) } else { res.map(|x| *x) @@ -71,9 +75,17 @@ impl RustyPipeQuery { .await?; let visitor_data = Rc::new(visitor_data); + let n_album_pages = album_page_params.len(); let album_page_results = stream::iter(album_page_params) - .map(|params| { + .enumerate() + .map(|(i, params)| { let visitor_data = visitor_data.clone(); + log::debug!( + "Getting music artist {} section {}/{}", + artist_id, + i + 1, + n_album_pages + ); async move { self.music_artist_album_page(artist_id, ¶ms, &visitor_data) .await @@ -237,14 +249,24 @@ fn map_artist_page( { if let Some(cfg) = bep.browse_endpoint_context_supported_configs { match cfg.browse_endpoint_context_music_config.page_type { + // Music videos PageType::Playlist => { if videos_playlist_id.is_none() { videos_playlist_id = Some(bep.browse_id); } } + // Albums or playlists PageType::Artist => { - album_page_params.push(bep.params); - extendable_albums = true; + // 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.browse_endpoint.as_ref().and_then(|be| { + be.browse_endpoint_context_supported_configs.as_ref().map(|config| { + config.browse_endpoint_context_music_config.page_type + })}) { + album_page_params.push(bep.params); + extendable_albums = true; + } + } } _ => {} } diff --git a/src/client/player.rs b/src/client/player.rs index c646b31..05061cb 100644 --- a/src/client/player.rs +++ b/src/client/player.rs @@ -676,7 +676,7 @@ mod tests { let (url, throttled) = map_res.c.unwrap(); assert_eq!(url, "https://rr5---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=3781277&dur=229.301&ei=vb7nYvH5BMK8gAfBj7ToBQ&expire=1659376413&fexp=24001373%2C24007246&fvip=5&gir=yes&id=o-AB_BABwrXZJN428ZwDxq5ScPn2AbcGODnRlTVhCQ3mj2&initcwndbps=1588750&ip=2003%3Ade%3Aaf06%3A6300%3Ac750%3A1b77%3Ac74a%3A80e3&itag=251&keepalive=yes&lmt=1655510291473933&lsig=AG3C_xAwRQIgCKCGJ1iu4wlaGXy3jcJyU3inh9dr1FIfqYOZEG_MdmACIQCbungkQYFk7EhD6K2YvLaHFMjKOFWjw001_tLb0lPDtg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=hH&mime=audio%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5ednsl&ms=au%2Conr&mt=1659354538&mv=m&mvi=5&n=XzXGSfGusw6OCQ&ns=b_Mq_qlTFcSGlG9RpwpM9xQH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAPIsKd7-xi4xVHEC9gb__dU4hzfzsHEj9ytd3nt0gEceAiACJWBcw-wFEq9qir35bwKHJZxtQ9mOL7SKiVkLQNDa6A%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khi831z8dTejFIRCvCEwx_6romtM&txp=4532434&vprv=1"); - assert_eq!(throttled, false); + assert!(!throttled); assert!( map_res.warnings.is_empty(), "deserialization/mapping warnings: {:?}", diff --git a/src/client/response/url_endpoint.rs b/src/client/response/url_endpoint.rs index 03d9043..0c1493d 100644 --- a/src/client/response/url_endpoint.rs +++ b/src/client/response/url_endpoint.rs @@ -195,38 +195,37 @@ impl From for MusicPageType { impl NavigationEndpoint { pub(crate) fn music_page(self) -> Option<(MusicPageType, String)> { - match self.browse_endpoint { - Some(browse) => match browse.browse_endpoint_context_supported_configs { - Some(config) => Some(( - config.browse_endpoint_context_music_config.page_type.into(), - browse.browse_id, - )), - None => None, - }, - None => None, - } - .or_else(|| { - self.watch_endpoint.map(|watch| { - if watch - .playlist_id - .map(|plid| plid.starts_with("RDQM")) - .unwrap_or_default() - { - // Genre radios (e.g. "pop radio") will be skipped - (MusicPageType::None, watch.video_id) - } else { + self.browse_endpoint + .and_then(|be| { + be.browse_endpoint_context_supported_configs.map(|config| { ( - MusicPageType::Track { - is_video: watch - .watch_endpoint_music_supported_configs - .watch_endpoint_music_config - .music_video_type - == MusicVideoType::Video, - }, - watch.video_id, + config.browse_endpoint_context_music_config.page_type.into(), + be.browse_id, ) - } + }) + }) + .or_else(|| { + self.watch_endpoint.map(|watch| { + if watch + .playlist_id + .map(|plid| plid.starts_with("RDQM")) + .unwrap_or_default() + { + // Genre radios (e.g. "pop radio") will be skipped + (MusicPageType::None, watch.video_id) + } else { + ( + MusicPageType::Track { + is_video: watch + .watch_endpoint_music_supported_configs + .watch_endpoint_music_config + .music_video_type + == MusicVideoType::Video, + }, + watch.video_id, + ) + } + }) }) - }) } } diff --git a/src/serializer/text.rs b/src/serializer/text.rs index 192d790..c682946 100644 --- a/src/serializer/text.rs +++ b/src/serializer/text.rs @@ -538,8 +538,8 @@ mod tests { txt: Vec, } - let res_str = serde_json::from_str::(&test_json).unwrap(); - let res_vec = serde_json::from_str::(&test_json).unwrap(); + let res_str = serde_json::from_str::(test_json).unwrap(); + let res_vec = serde_json::from_str::(test_json).unwrap(); assert_eq!(res_str.txt, exp.join("")); assert_eq!(res_vec.txt, exp); @@ -582,7 +582,7 @@ mod tests { } }"#; - let res = serde_json::from_str::(&test_json).unwrap(); + let res = serde_json::from_str::(test_json).unwrap(); insta::assert_debug_snapshot!(res, @r###" SLink { ln: Video { @@ -617,7 +617,7 @@ mod tests { } }"#; - let res = serde_json::from_str::(&test_json).unwrap(); + let res = serde_json::from_str::(test_json).unwrap(); insta::assert_debug_snapshot!(res, @r###" SLink { ln: Browse { @@ -651,7 +651,7 @@ mod tests { } }"#; - let res = serde_json::from_str::(&test_json).unwrap(); + let res = serde_json::from_str::(test_json).unwrap(); insta::assert_debug_snapshot!(res, @r###" SLink { ln: Browse { @@ -675,7 +675,7 @@ mod tests { } }"#; - let res = serde_json::from_str::(&test_json).unwrap(); + let res = serde_json::from_str::(test_json).unwrap(); insta::assert_debug_snapshot!(res, @r###" SLink { ln: Text { @@ -710,7 +710,7 @@ mod tests { } }"#; - let res = serde_json::from_str::(&test_json).unwrap(); + let res = serde_json::from_str::(test_json).unwrap(); insta::assert_debug_snapshot!(res, @r###" SLink { ln: Web { @@ -759,7 +759,7 @@ mod tests { } }"#; - let res = serde_json::from_str::(&test_json).unwrap(); + let res = serde_json::from_str::(test_json).unwrap(); insta::assert_debug_snapshot!(res, @r###" SLinks { ln: TextComponents( @@ -787,7 +787,7 @@ mod tests { fn t_links_empty() { let test_json = r#"{"ln": {}}"#; - let res = serde_json::from_str::(&test_json).unwrap(); + let res = serde_json::from_str::(test_json).unwrap(); assert!(res.ln.0.is_empty()) } diff --git a/tests/youtube.rs b/tests/youtube.rs index d621194..398a3de 100644 --- a/tests/youtube.rs +++ b/tests/youtube.rs @@ -215,6 +215,7 @@ async fn check_video_stream(s: impl YtStream) { false )] #[tokio::test] +#[allow(clippy::too_many_arguments)] async fn get_player( #[case] id: &str, #[case] name: &str,