Compare commits
	
		
			2 commits
		
	
	
		
			
				64d009615e
			
			...
			
				94b55711cb
			
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 94b55711cb | |||
| 85cac83070 | 
					 7 changed files with 94 additions and 88 deletions
				
			
		|  | @ -61,4 +61,3 @@ rstest = "0.16.0" | |||
| temp_testdir = "0.2.3" | ||||
| insta = { version = "1.17.1", features = ["ron", "redactions"] } | ||||
| path_macro = "1.0.0" | ||||
| velcro = "0.5.3" | ||||
|  |  | |||
|  | @ -208,7 +208,7 @@ async fn playlist_cont(testfiles: &Path) { | |||
|         .unwrap(); | ||||
| 
 | ||||
|     let rp = rp_testfile(&json_path); | ||||
|     playlist.videos.next(&rp.query()).await.unwrap().unwrap(); | ||||
|     playlist.videos.next(rp.query()).await.unwrap().unwrap(); | ||||
| } | ||||
| 
 | ||||
| async fn video_details(testfiles: &Path) { | ||||
|  | @ -246,7 +246,7 @@ async fn comments_top(testfiles: &Path) { | |||
|     let rp = rp_testfile(&json_path); | ||||
|     details | ||||
|         .top_comments | ||||
|         .next(&rp.query()) | ||||
|         .next(rp.query()) | ||||
|         .await | ||||
|         .unwrap() | ||||
|         .unwrap(); | ||||
|  | @ -266,7 +266,7 @@ async fn comments_latest(testfiles: &Path) { | |||
|     let rp = rp_testfile(&json_path); | ||||
|     details | ||||
|         .latest_comments | ||||
|         .next(&rp.query()) | ||||
|         .next(rp.query()) | ||||
|         .await | ||||
|         .unwrap() | ||||
|         .unwrap(); | ||||
|  | @ -284,7 +284,7 @@ async fn recommendations(testfiles: &Path) { | |||
|     let details = rp.query().video_details("ZeerrnuLi5E").await.unwrap(); | ||||
| 
 | ||||
|     let rp = rp_testfile(&json_path); | ||||
|     details.recommended.next(&rp.query()).await.unwrap(); | ||||
|     details.recommended.next(rp.query()).await.unwrap(); | ||||
| } | ||||
| 
 | ||||
| async fn channel_videos(testfiles: &Path) { | ||||
|  | @ -384,7 +384,7 @@ async fn channel_videos_cont(testfiles: &Path) { | |||
|         .unwrap(); | ||||
| 
 | ||||
|     let rp = rp_testfile(&json_path); | ||||
|     videos.content.next(&rp.query()).await.unwrap().unwrap(); | ||||
|     videos.content.next(rp.query()).await.unwrap().unwrap(); | ||||
| } | ||||
| 
 | ||||
| async fn channel_playlists_cont(testfiles: &Path) { | ||||
|  | @ -403,7 +403,7 @@ async fn channel_playlists_cont(testfiles: &Path) { | |||
|         .unwrap(); | ||||
| 
 | ||||
|     let rp = rp_testfile(&json_path); | ||||
|     playlists.content.next(&rp.query()).await.unwrap().unwrap(); | ||||
|     playlists.content.next(rp.query()).await.unwrap().unwrap(); | ||||
| } | ||||
| 
 | ||||
| async fn search(testfiles: &Path) { | ||||
|  | @ -430,7 +430,7 @@ async fn search_cont(testfiles: &Path) { | |||
|     let search = rp.query().search("doobydoobap").await.unwrap(); | ||||
| 
 | ||||
|     let rp = rp_testfile(&json_path); | ||||
|     search.items.next(&rp.query()).await.unwrap().unwrap(); | ||||
|     search.items.next(rp.query()).await.unwrap().unwrap(); | ||||
| } | ||||
| 
 | ||||
| async fn search_playlists(testfiles: &Path) { | ||||
|  | @ -492,7 +492,7 @@ async fn startpage_cont(testfiles: &Path) { | |||
|     let startpage = rp.query().startpage().await.unwrap(); | ||||
| 
 | ||||
|     let rp = rp_testfile(&json_path); | ||||
|     startpage.next(&rp.query()).await.unwrap(); | ||||
|     startpage.next(rp.query()).await.unwrap(); | ||||
| } | ||||
| 
 | ||||
| async fn trending(testfiles: &Path) { | ||||
|  | @ -541,7 +541,7 @@ async fn music_playlist_cont(testfiles: &Path) { | |||
|         .unwrap(); | ||||
| 
 | ||||
|     let rp = rp_testfile(&json_path); | ||||
|     playlist.tracks.next(&rp.query()).await.unwrap().unwrap(); | ||||
|     playlist.tracks.next(rp.query()).await.unwrap().unwrap(); | ||||
| } | ||||
| 
 | ||||
| async fn music_playlist_related(testfiles: &Path) { | ||||
|  | @ -562,7 +562,7 @@ async fn music_playlist_related(testfiles: &Path) { | |||
|     let rp = rp_testfile(&json_path); | ||||
|     playlist | ||||
|         .related_playlists | ||||
|         .next(&rp.query()) | ||||
|         .next(rp.query()) | ||||
|         .await | ||||
|         .unwrap() | ||||
|         .unwrap(); | ||||
|  | @ -688,7 +688,7 @@ async fn music_search_cont(testfiles: &Path) { | |||
|     let res = rp.query().music_search_tracks("black mamba").await.unwrap(); | ||||
| 
 | ||||
|     let rp = rp_testfile(&json_path); | ||||
|     res.items.next(&rp.query()).await.unwrap().unwrap(); | ||||
|     res.items.next(rp.query()).await.unwrap().unwrap(); | ||||
| } | ||||
| 
 | ||||
| async fn music_search_suggestion(testfiles: &Path) { | ||||
|  | @ -801,7 +801,7 @@ async fn music_radio_cont(testfiles: &Path) { | |||
|     let res = rp.query().music_radio("RDAMVM7nigXQS1Xb0").await.unwrap(); | ||||
| 
 | ||||
|     let rp = rp_testfile(&json_path); | ||||
|     res.next(&rp.query()).await.unwrap().unwrap(); | ||||
|     res.next(rp.query()).await.unwrap().unwrap(); | ||||
| } | ||||
| 
 | ||||
| async fn music_new_albums(testfiles: &Path) { | ||||
|  |  | |||
|  | @ -1164,6 +1164,12 @@ impl RustyPipeQuery { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsRef<RustyPipeQuery> for RustyPipeQuery { | ||||
|     fn as_ref(&self) -> &RustyPipeQuery { | ||||
|         self | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Implement this for YouTube API response structs that need to be mapped to
 | ||||
| /// RustyPipe models.
 | ||||
| trait MapResponse<T> { | ||||
|  |  | |||
|  | @ -176,10 +176,11 @@ impl MapResponse<Paginator<MusicItem>> for response::MusicContinuation { | |||
| } | ||||
| 
 | ||||
| impl<T: FromYtItem> Paginator<T> { | ||||
|     pub async fn next(&self, query: &RustyPipeQuery) -> Result<Option<Self>, Error> { | ||||
|     pub async fn next<Q: AsRef<RustyPipeQuery>>(&self, query: Q) -> Result<Option<Self>, Error> { | ||||
|         Ok(match &self.ctoken { | ||||
|             Some(ctoken) => Some( | ||||
|                 query | ||||
|                     .as_ref() | ||||
|                     .continuation(ctoken, self.endpoint, self.visitor_data.as_deref()) | ||||
|                     .await?, | ||||
|             ), | ||||
|  | @ -187,7 +188,7 @@ impl<T: FromYtItem> Paginator<T> { | |||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     pub async fn extend(&mut self, query: &RustyPipeQuery) -> Result<bool, Error> { | ||||
|     pub async fn extend<Q: AsRef<RustyPipeQuery>>(&mut self, query: Q) -> Result<bool, Error> { | ||||
|         match self.next(query).await { | ||||
|             Ok(Some(paginator)) => { | ||||
|                 let mut items = paginator.items; | ||||
|  | @ -200,11 +201,12 @@ impl<T: FromYtItem> Paginator<T> { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub async fn extend_pages( | ||||
|     pub async fn extend_pages<Q: AsRef<RustyPipeQuery>>( | ||||
|         &mut self, | ||||
|         query: &RustyPipeQuery, | ||||
|         query: Q, | ||||
|         n_pages: usize, | ||||
|     ) -> Result<(), Error> { | ||||
|         let query = query.as_ref(); | ||||
|         for _ in 0..n_pages { | ||||
|             match self.extend(query).await { | ||||
|                 Ok(false) => break, | ||||
|  | @ -215,11 +217,12 @@ impl<T: FromYtItem> Paginator<T> { | |||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     pub async fn extend_limit( | ||||
|     pub async fn extend_limit<Q: AsRef<RustyPipeQuery>>( | ||||
|         &mut self, | ||||
|         query: &RustyPipeQuery, | ||||
|         query: Q, | ||||
|         n_items: usize, | ||||
|     ) -> Result<(), Error> { | ||||
|         let query = query.as_ref(); | ||||
|         while self.items.len() < n_items { | ||||
|             match self.extend(query).await { | ||||
|                 Ok(false) => break, | ||||
|  | @ -232,10 +235,11 @@ impl<T: FromYtItem> Paginator<T> { | |||
| } | ||||
| 
 | ||||
| impl Paginator<Comment> { | ||||
|     pub async fn next(&self, query: &RustyPipeQuery) -> Result<Option<Self>, Error> { | ||||
|     pub async fn next<Q: AsRef<RustyPipeQuery>>(&self, query: Q) -> Result<Option<Self>, Error> { | ||||
|         Ok(match &self.ctoken { | ||||
|             Some(ctoken) => Some( | ||||
|                 query | ||||
|                     .as_ref() | ||||
|                     .video_comments(ctoken, self.visitor_data.as_deref()) | ||||
|                     .await?, | ||||
|             ), | ||||
|  | @ -245,9 +249,9 @@ impl Paginator<Comment> { | |||
| } | ||||
| 
 | ||||
| impl Paginator<PlaylistVideo> { | ||||
|     pub async fn next(&self, query: &RustyPipeQuery) -> Result<Option<Self>, Error> { | ||||
|     pub async fn next<Q: AsRef<RustyPipeQuery>>(&self, query: Q) -> Result<Option<Self>, Error> { | ||||
|         Ok(match &self.ctoken { | ||||
|             Some(ctoken) => Some(query.playlist_continuation(ctoken).await?), | ||||
|             Some(ctoken) => Some(query.as_ref().playlist_continuation(ctoken).await?), | ||||
|             None => None, | ||||
|         }) | ||||
|     } | ||||
|  | @ -256,7 +260,10 @@ impl Paginator<PlaylistVideo> { | |||
| macro_rules! paginator { | ||||
|     ($entity_type:ty) => { | ||||
|         impl Paginator<$entity_type> { | ||||
|             pub async fn extend(&mut self, query: &RustyPipeQuery) -> Result<bool, Error> { | ||||
|             pub async fn extend<Q: AsRef<RustyPipeQuery>>( | ||||
|                 &mut self, | ||||
|                 query: Q, | ||||
|             ) -> Result<bool, Error> { | ||||
|                 match self.next(query).await { | ||||
|                     Ok(Some(paginator)) => { | ||||
|                         let mut items = paginator.items; | ||||
|  | @ -269,11 +276,12 @@ macro_rules! paginator { | |||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             pub async fn extend_pages( | ||||
|             pub async fn extend_pages<Q: AsRef<RustyPipeQuery>>( | ||||
|                 &mut self, | ||||
|                 query: &RustyPipeQuery, | ||||
|                 query: Q, | ||||
|                 n_pages: usize, | ||||
|             ) -> Result<(), Error> { | ||||
|                 let query = query.as_ref(); | ||||
|                 for _ in 0..n_pages { | ||||
|                     match self.extend(query).await { | ||||
|                         Ok(false) => break, | ||||
|  | @ -284,11 +292,12 @@ macro_rules! paginator { | |||
|                 Ok(()) | ||||
|             } | ||||
| 
 | ||||
|             pub async fn extend_limit( | ||||
|             pub async fn extend_limit<Q: AsRef<RustyPipeQuery>>( | ||||
|                 &mut self, | ||||
|                 query: &RustyPipeQuery, | ||||
|                 query: Q, | ||||
|                 n_items: usize, | ||||
|             ) -> Result<(), Error> { | ||||
|                 let query = query.as_ref(); | ||||
|                 while self.items.len() < n_items { | ||||
|                     match self.extend(query).await { | ||||
|                         Ok(false) => break, | ||||
|  |  | |||
|  | @ -292,7 +292,7 @@ pub async fn download_video( | |||
|     output_dir: &str, | ||||
|     output_fname: Option<String>, | ||||
|     output_format: Option<String>, | ||||
|     filter: &StreamFilter, | ||||
|     filter: &StreamFilter<'_>, | ||||
|     ffmpeg: &str, | ||||
|     http: Client, | ||||
|     pb: ProgressBar, | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| //! Filters for selecting audio/video streams
 | ||||
| 
 | ||||
| use std::{cmp::Ordering, collections::HashSet}; | ||||
| use std::cmp::Ordering; | ||||
| 
 | ||||
| use crate::model::{ | ||||
|     AudioCodec, AudioFormat, AudioStream, QualityOrd, VideoCodec, VideoFormat, VideoPlayer, | ||||
|  | @ -8,15 +8,15 @@ use crate::model::{ | |||
| }; | ||||
| 
 | ||||
| #[derive(Debug, Default, Clone)] | ||||
| pub struct StreamFilter { | ||||
| pub struct StreamFilter<'a> { | ||||
|     audio_max_bitrate: Option<u32>, | ||||
|     audio_formats: Option<HashSet<AudioFormat>>, | ||||
|     audio_codecs: Option<HashSet<AudioCodec>>, | ||||
|     audio_language: Option<String>, | ||||
|     audio_formats: Option<&'a [AudioFormat]>, | ||||
|     audio_codecs: Option<&'a [AudioCodec]>, | ||||
|     audio_language: Option<&'a str>, | ||||
|     video_max_res: Option<u32>, | ||||
|     video_max_fps: Option<u8>, | ||||
|     video_formats: Option<HashSet<VideoFormat>>, | ||||
|     video_codecs: Option<HashSet<VideoCodec>>, | ||||
|     video_formats: Option<&'a [VideoFormat]>, | ||||
|     video_codecs: Option<&'a [VideoCodec]>, | ||||
|     video_hdr: bool, | ||||
|     video_none: bool, | ||||
| } | ||||
|  | @ -59,7 +59,7 @@ impl FilterResult { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl StreamFilter { | ||||
| impl<'a> StreamFilter<'a> { | ||||
|     /// Set the maximum audio bitrate in bits per second.
 | ||||
|     ///
 | ||||
|     /// This is a soft filter, so if there is no stream with a bitrate
 | ||||
|  | @ -77,7 +77,7 @@ impl StreamFilter { | |||
|     } | ||||
| 
 | ||||
|     /// Set the supported audio container formats
 | ||||
|     pub fn audio_formats(&mut self, formats: HashSet<AudioFormat>) -> &mut Self { | ||||
|     pub fn audio_formats(&mut self, formats: &'a [AudioFormat]) -> &mut Self { | ||||
|         self.audio_formats = Some(formats); | ||||
|         self | ||||
|     } | ||||
|  | @ -90,7 +90,7 @@ impl StreamFilter { | |||
|     } | ||||
| 
 | ||||
|     /// Set the supported audio codecs
 | ||||
|     pub fn audio_codecs(&mut self, codecs: HashSet<AudioCodec>) -> &mut Self { | ||||
|     pub fn audio_codecs(&mut self, codecs: &'a [AudioCodec]) -> &mut Self { | ||||
|         self.audio_codecs = Some(codecs); | ||||
|         self | ||||
|     } | ||||
|  | @ -108,8 +108,8 @@ impl StreamFilter { | |||
|     ///
 | ||||
|     /// If this filter is unset or no stream matches,
 | ||||
|     /// the filter returns the default audio stream.
 | ||||
|     pub fn audio_language(&mut self, language: &str) -> &mut Self { | ||||
|         self.audio_language = Some(language.to_owned()); | ||||
|     pub fn audio_language(&mut self, language: &'a str) -> &mut Self { | ||||
|         self.audio_language = Some(language); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|  | @ -163,7 +163,7 @@ impl StreamFilter { | |||
|     } | ||||
| 
 | ||||
|     /// Set the supported video container formats
 | ||||
|     pub fn video_formats(&mut self, formats: HashSet<VideoFormat>) -> &mut Self { | ||||
|     pub fn video_formats(&mut self, formats: &'a [VideoFormat]) -> &mut Self { | ||||
|         self.video_formats = Some(formats); | ||||
|         self | ||||
|     } | ||||
|  | @ -176,7 +176,7 @@ impl StreamFilter { | |||
|     } | ||||
| 
 | ||||
|     /// Set the supported video codecs
 | ||||
|     pub fn video_codecs(&mut self, codecs: HashSet<VideoCodec>) -> &mut Self { | ||||
|     pub fn video_codecs(&mut self, codecs: &'a [VideoCodec]) -> &mut Self { | ||||
|         self.video_codecs = Some(codecs); | ||||
|         self | ||||
|     } | ||||
|  | @ -324,7 +324,6 @@ mod tests { | |||
|     use once_cell::sync::Lazy; | ||||
|     use path_macro::path; | ||||
|     use rstest::rstest; | ||||
|     use velcro::hash_set; | ||||
| 
 | ||||
|     static PLAYER_ML: Lazy<VideoPlayer> = Lazy::new(|| { | ||||
|         let json_path = path!("testfiles" / "player_model" / "multilanguage.json"); | ||||
|  | @ -343,13 +342,13 @@ mod tests { | |||
|     #[rstest] | ||||
|     #[case::default(StreamFilter::default(), Some("https://rr4---sn-h0jeener.googlevideo.com/videoplayback?c=WEB&clen=16104134&dur=1012.661&ei=498HY6KvArqM6dsPiN6QgAE&expire=1661482051&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AK8GbbQovVxldcBz4pkXu4EA9N2sU-4yPPa5hFT3bXta&initcwndbps=1392500&ip=2003%3Ade%3Aaf1e%3A8a00%3A84c6%3A28f3%3A9de2%3A464&itag=251&keepalive=yes&lmt=1659767097097120&lsig=AG3C_xAwRAIgLFPuLqOoHoNQax15AE9Q2YIZ7pM7-olbGWgYGv1MDccCIADKSc_HeOdmD7CDs4AkY5ZtWF4gdZd4rw99Cqlzakbk&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=wB&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeener%2Csn-h0jeln7l&ms=au%2Crdu&mt=1661460078&mv=m&mvi=4&n=LwUYrFgbIVPzmA&ns=bBqoZtLH6lsaX8ke0xgRMM8H&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgW4IxGJJFRAwZefvDdDkJfjhN7y3bPmh96BCFuyFn6pwCIQDW6pVnk_DwMC3FcZy5rXNUULMNWLdadScxwuhFTFR84g%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cxtags%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khmjdu08WYG7DxAg_8xq0R2u5a6w&txp=4532434&vprv=1&xtags=lang%3Den"))] | ||||
|     #[case::bitrate(StreamFilter::default().audio_max_bitrate(100000).to_owned(), Some("https://rr4---sn-h0jeener.googlevideo.com/videoplayback?c=WEB&clen=8217507&dur=1012.661&ei=498HY6KvArqM6dsPiN6QgAE&expire=1661482051&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AK8GbbQovVxldcBz4pkXu4EA9N2sU-4yPPa5hFT3bXta&initcwndbps=1392500&ip=2003%3Ade%3Aaf1e%3A8a00%3A84c6%3A28f3%3A9de2%3A464&itag=250&keepalive=yes&lmt=1659767073159859&lsig=AG3C_xAwRAIgLFPuLqOoHoNQax15AE9Q2YIZ7pM7-olbGWgYGv1MDccCIADKSc_HeOdmD7CDs4AkY5ZtWF4gdZd4rw99Cqlzakbk&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=wB&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeener%2Csn-h0jeln7l&ms=au%2Crdu&mt=1661460078&mv=m&mvi=4&n=LwUYrFgbIVPzmA&ns=bBqoZtLH6lsaX8ke0xgRMM8H&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgM9loLjlUtgwrALqSek4vO8KljcCltFjLw1TGX0d9lZ4CICRiTJ8a_KgdafXVo2vKwgLPuH2B7t0hF-ln2k_MI3ds&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cxtags%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khmjdu08WYG7DxAg_8xq0R2u5a6w&txp=4532434&vprv=1&xtags=lang%3Den"))] | ||||
|     #[case::m4a_format(StreamFilter::default().audio_formats(hash_set!(AudioFormat::M4a)).to_owned(), Some("https://rr4---sn-h0jeener.googlevideo.com/videoplayback?c=WEB&clen=16390628&dur=1012.691&ei=498HY6KvArqM6dsPiN6QgAE&expire=1661482051&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AK8GbbQovVxldcBz4pkXu4EA9N2sU-4yPPa5hFT3bXta&initcwndbps=1392500&ip=2003%3Ade%3Aaf1e%3A8a00%3A84c6%3A28f3%3A9de2%3A464&itag=140&keepalive=yes&lmt=1659766154827884&lsig=AG3C_xAwRAIgLFPuLqOoHoNQax15AE9Q2YIZ7pM7-olbGWgYGv1MDccCIADKSc_HeOdmD7CDs4AkY5ZtWF4gdZd4rw99Cqlzakbk&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=wB&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jeener%2Csn-h0jeln7l&ms=au%2Crdu&mt=1661460078&mv=m&mvi=4&n=LwUYrFgbIVPzmA&ns=bBqoZtLH6lsaX8ke0xgRMM8H&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgc8oxPEHDO0cgO3ZcbPmv3nrkzfy52WchpV0HcBcUw24CIEFxLKBcM4vVqGeRkt581dFL2tetvHd93SHCTVEUnIn_&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cxtags%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khmjdu08WYG7DxAg_8xq0R2u5a6w&txp=4532434&vprv=1&xtags=lang%3Den"))] | ||||
|     #[case::m4a_codec(StreamFilter::default().audio_codecs(hash_set!(AudioCodec::Mp4a)).to_owned(), Some("https://rr4---sn-h0jeener.googlevideo.com/videoplayback?c=WEB&clen=16390628&dur=1012.691&ei=498HY6KvArqM6dsPiN6QgAE&expire=1661482051&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AK8GbbQovVxldcBz4pkXu4EA9N2sU-4yPPa5hFT3bXta&initcwndbps=1392500&ip=2003%3Ade%3Aaf1e%3A8a00%3A84c6%3A28f3%3A9de2%3A464&itag=140&keepalive=yes&lmt=1659766154827884&lsig=AG3C_xAwRAIgLFPuLqOoHoNQax15AE9Q2YIZ7pM7-olbGWgYGv1MDccCIADKSc_HeOdmD7CDs4AkY5ZtWF4gdZd4rw99Cqlzakbk&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=wB&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jeener%2Csn-h0jeln7l&ms=au%2Crdu&mt=1661460078&mv=m&mvi=4&n=LwUYrFgbIVPzmA&ns=bBqoZtLH6lsaX8ke0xgRMM8H&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgc8oxPEHDO0cgO3ZcbPmv3nrkzfy52WchpV0HcBcUw24CIEFxLKBcM4vVqGeRkt581dFL2tetvHd93SHCTVEUnIn_&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cxtags%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khmjdu08WYG7DxAg_8xq0R2u5a6w&txp=4532434&vprv=1&xtags=lang%3Den"))] | ||||
|     #[case::m4a_format(StreamFilter::default().audio_formats(&[AudioFormat::M4a]).to_owned(), Some("https://rr4---sn-h0jeener.googlevideo.com/videoplayback?c=WEB&clen=16390628&dur=1012.691&ei=498HY6KvArqM6dsPiN6QgAE&expire=1661482051&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AK8GbbQovVxldcBz4pkXu4EA9N2sU-4yPPa5hFT3bXta&initcwndbps=1392500&ip=2003%3Ade%3Aaf1e%3A8a00%3A84c6%3A28f3%3A9de2%3A464&itag=140&keepalive=yes&lmt=1659766154827884&lsig=AG3C_xAwRAIgLFPuLqOoHoNQax15AE9Q2YIZ7pM7-olbGWgYGv1MDccCIADKSc_HeOdmD7CDs4AkY5ZtWF4gdZd4rw99Cqlzakbk&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=wB&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jeener%2Csn-h0jeln7l&ms=au%2Crdu&mt=1661460078&mv=m&mvi=4&n=LwUYrFgbIVPzmA&ns=bBqoZtLH6lsaX8ke0xgRMM8H&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgc8oxPEHDO0cgO3ZcbPmv3nrkzfy52WchpV0HcBcUw24CIEFxLKBcM4vVqGeRkt581dFL2tetvHd93SHCTVEUnIn_&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cxtags%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khmjdu08WYG7DxAg_8xq0R2u5a6w&txp=4532434&vprv=1&xtags=lang%3Den"))] | ||||
|     #[case::m4a_codec(StreamFilter::default().audio_codecs(&[AudioCodec::Mp4a]).to_owned(), Some("https://rr4---sn-h0jeener.googlevideo.com/videoplayback?c=WEB&clen=16390628&dur=1012.691&ei=498HY6KvArqM6dsPiN6QgAE&expire=1661482051&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AK8GbbQovVxldcBz4pkXu4EA9N2sU-4yPPa5hFT3bXta&initcwndbps=1392500&ip=2003%3Ade%3Aaf1e%3A8a00%3A84c6%3A28f3%3A9de2%3A464&itag=140&keepalive=yes&lmt=1659766154827884&lsig=AG3C_xAwRAIgLFPuLqOoHoNQax15AE9Q2YIZ7pM7-olbGWgYGv1MDccCIADKSc_HeOdmD7CDs4AkY5ZtWF4gdZd4rw99Cqlzakbk&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=wB&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jeener%2Csn-h0jeln7l&ms=au%2Crdu&mt=1661460078&mv=m&mvi=4&n=LwUYrFgbIVPzmA&ns=bBqoZtLH6lsaX8ke0xgRMM8H&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgc8oxPEHDO0cgO3ZcbPmv3nrkzfy52WchpV0HcBcUw24CIEFxLKBcM4vVqGeRkt581dFL2tetvHd93SHCTVEUnIn_&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cxtags%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khmjdu08WYG7DxAg_8xq0R2u5a6w&txp=4532434&vprv=1&xtags=lang%3Den"))] | ||||
|     #[case::french(StreamFilter::default().audio_language("fr").to_owned(), Some("https://rr4---sn-h0jeener.googlevideo.com/videoplayback?c=WEB&clen=16357630&dur=1012.721&ei=498HY6KvArqM6dsPiN6QgAE&expire=1661482051&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AK8GbbQovVxldcBz4pkXu4EA9N2sU-4yPPa5hFT3bXta&initcwndbps=1392500&ip=2003%3Ade%3Aaf1e%3A8a00%3A84c6%3A28f3%3A9de2%3A464&itag=251&keepalive=yes&lmt=1659767033119964&lsig=AG3C_xAwRAIgLFPuLqOoHoNQax15AE9Q2YIZ7pM7-olbGWgYGv1MDccCIADKSc_HeOdmD7CDs4AkY5ZtWF4gdZd4rw99Cqlzakbk&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=wB&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeener%2Csn-h0jeln7l&ms=au%2Crdu&mt=1661460078&mv=m&mvi=4&n=LwUYrFgbIVPzmA&ns=bBqoZtLH6lsaX8ke0xgRMM8H&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAKtzVVyoS46hkuKX31EyUE6X6Q5wotcToOCnYKswX3x_AiB0G2SUdVoso39bYgewd3zT8Pf77DrVtahXh4kVb46T9g%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cxtags%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khmjdu08WYG7DxAg_8xq0R2u5a6w&txp=4532434&vprv=1&xtags=lang%3Dfr"))] | ||||
|     #[case::br_fallback(StreamFilter::default().audio_max_bitrate(0).to_owned(), Some("https://rr4---sn-h0jeener.googlevideo.com/videoplayback?c=WEB&clen=6297404&dur=1012.661&ei=498HY6KvArqM6dsPiN6QgAE&expire=1661482051&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AK8GbbQovVxldcBz4pkXu4EA9N2sU-4yPPa5hFT3bXta&initcwndbps=1392500&ip=2003%3Ade%3Aaf1e%3A8a00%3A84c6%3A28f3%3A9de2%3A464&itag=249&keepalive=yes&lmt=1659767062297621&lsig=AG3C_xAwRAIgLFPuLqOoHoNQax15AE9Q2YIZ7pM7-olbGWgYGv1MDccCIADKSc_HeOdmD7CDs4AkY5ZtWF4gdZd4rw99Cqlzakbk&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=wB&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeener%2Csn-h0jeln7l&ms=au%2Crdu&mt=1661460078&mv=m&mvi=4&n=LwUYrFgbIVPzmA&ns=bBqoZtLH6lsaX8ke0xgRMM8H&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAPm10DeIvOt5Oc7e36cfhPC0ej2PslQqF3-CFVUl5TNfAiEAlgvwjlQK14e_-6j3W_hMvk9KHax8zd5shSVlYSR1P34%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cxtags%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khmjdu08WYG7DxAg_8xq0R2u5a6w&txp=4532434&vprv=1&xtags=lang%3Den"))] | ||||
|     #[case::lang_fallback(StreamFilter::default().audio_language("xx").to_owned(), Some("https://rr4---sn-h0jeener.googlevideo.com/videoplayback?c=WEB&clen=16104134&dur=1012.661&ei=498HY6KvArqM6dsPiN6QgAE&expire=1661482051&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AK8GbbQovVxldcBz4pkXu4EA9N2sU-4yPPa5hFT3bXta&initcwndbps=1392500&ip=2003%3Ade%3Aaf1e%3A8a00%3A84c6%3A28f3%3A9de2%3A464&itag=251&keepalive=yes&lmt=1659767097097120&lsig=AG3C_xAwRAIgLFPuLqOoHoNQax15AE9Q2YIZ7pM7-olbGWgYGv1MDccCIADKSc_HeOdmD7CDs4AkY5ZtWF4gdZd4rw99Cqlzakbk&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=wB&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeener%2Csn-h0jeln7l&ms=au%2Crdu&mt=1661460078&mv=m&mvi=4&n=LwUYrFgbIVPzmA&ns=bBqoZtLH6lsaX8ke0xgRMM8H&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgW4IxGJJFRAwZefvDdDkJfjhN7y3bPmh96BCFuyFn6pwCIQDW6pVnk_DwMC3FcZy5rXNUULMNWLdadScxwuhFTFR84g%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cxtags%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khmjdu08WYG7DxAg_8xq0R2u5a6w&txp=4532434&vprv=1&xtags=lang%3Den"))] | ||||
|     #[case::noformat(StreamFilter::default().audio_formats(hash_set!()).to_owned(), None)] | ||||
|     #[case::nocodec(StreamFilter::default().audio_codecs(hash_set!()).to_owned(), None)] | ||||
|     #[case::noformat(StreamFilter::default().audio_formats(&[]).to_owned(), None)] | ||||
|     #[case::nocodec(StreamFilter::default().audio_codecs(&[]).to_owned(), None)] | ||||
|     fn t_select_audio_stream(#[case] filter: StreamFilter, #[case] expect_url: Option<&str>) { | ||||
|         let selection = PLAYER_ML.select_audio_stream(&filter); | ||||
| 
 | ||||
|  | @ -365,10 +364,10 @@ mod tests { | |||
|     #[case::resolution(StreamFilter::default().video_max_res(720).to_owned(), Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C308%2C315%2C330%2C331%2C332%2C333%2C334%2C335%2C336%2C337%2C394%2C395%2C396%2C397%2C398%2C399%2C400%2C401%2C694%2C695%2C696%2C697%2C698%2C699%2C700%2C701&c=WEB&clen=76313586&dur=313.780&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=302&keepalive=yes&lmt=1647455155369524&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=Zd7nrOM1B2C6PA&ns=426LxLap5MonJD_YWdS4lSYH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgW0H1434eh9Axw6zw95qezJB0D2aVd2bxEIs4T5bcfFACIDOjha9WLycp0L188FZyFGa1RBkLPoGrrJOppsaXqwDR&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4532434&vprv=1"))] | ||||
|     #[case::resolution_fps(StreamFilter::default().video_max_res(720).video_max_fps(30).to_owned(), Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C308%2C315%2C330%2C331%2C332%2C333%2C334%2C335%2C336%2C337%2C394%2C395%2C396%2C397%2C398%2C399%2C400%2C401%2C694%2C695%2C696%2C697%2C698%2C699%2C700%2C701&c=WEB&clen=47531179&dur=313.780&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=247&keepalive=yes&lmt=1647458657499381&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=Zd7nrOM1B2C6PA&ns=426LxLap5MonJD_YWdS4lSYH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAMUsmcl1zgbr3YQranPWNV1kcxT5IdEoLL7FTFEDdHHPAiEAhQnrfYMU0A9xZ69MfBujWA4pXtCOQCg2Jn6ve9J_vBQ%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4532434&vprv=1"))] | ||||
|     #[case::res_fallback(StreamFilter::default().video_max_res(100).to_owned(), Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C308%2C315%2C330%2C331%2C332%2C333%2C334%2C335%2C336%2C337%2C394%2C395%2C396%2C397%2C398%2C399%2C400%2C401%2C694%2C695%2C696%2C697%2C698%2C699%2C700%2C701&c=WEB&clen=2763284&dur=313.780&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=160&keepalive=yes&lmt=1647456833049253&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=video%2Fmp4&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=Zd7nrOM1B2C6PA&ns=426LxLap5MonJD_YWdS4lSYH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgLPNxzLxppSSpnDEHxVblrQ38890NMbGnLXlmxljprfQCIQDn4Ir_sjYh7S3ms-Rynm-K0nJpHpQGYsz1nv4TiqeELQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4532434&vprv=1"))] | ||||
|     #[case::webm_format(StreamFilter::default().video_formats(hash_set!(VideoFormat::Webm)).to_owned(), Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C308%2C315%2C330%2C331%2C332%2C333%2C334%2C335%2C336%2C337%2C394%2C395%2C396%2C397%2C398%2C399%2C400%2C401%2C694%2C695%2C696%2C697%2C698%2C699%2C700%2C701&c=WEB&clen=998696577&dur=313.780&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=315&keepalive=yes&lmt=1647476955807851&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=Zd7nrOM1B2C6PA&ns=426LxLap5MonJD_YWdS4lSYH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIfP4IVSo-00_kq_JIkuh032hcLoJzNEhYjvwgLiDpEzQIhALPVrvDBjRwiFddXiAyADmRtYygte4HvlJ3XOrkOf_TR&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4532434&vprv=1"))] | ||||
|     #[case::vp9_codec(StreamFilter::default().video_codecs(hash_set!(VideoCodec::Vp9)).to_owned(), Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C308%2C315%2C330%2C331%2C332%2C333%2C334%2C335%2C336%2C337%2C394%2C395%2C396%2C397%2C398%2C399%2C400%2C401%2C694%2C695%2C696%2C697%2C698%2C699%2C700%2C701&c=WEB&clen=998696577&dur=313.780&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=315&keepalive=yes&lmt=1647476955807851&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=Zd7nrOM1B2C6PA&ns=426LxLap5MonJD_YWdS4lSYH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIfP4IVSo-00_kq_JIkuh032hcLoJzNEhYjvwgLiDpEzQIhALPVrvDBjRwiFddXiAyADmRtYygte4HvlJ3XOrkOf_TR&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4532434&vprv=1"))] | ||||
|     #[case::noformat(StreamFilter::default().video_formats(hash_set!()).to_owned(), None)] | ||||
|     #[case::nocodec(StreamFilter::default().video_codecs(hash_set!()).to_owned(), None)] | ||||
|     #[case::webm_format(StreamFilter::default().video_formats(&[VideoFormat::Webm]).to_owned(), Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C308%2C315%2C330%2C331%2C332%2C333%2C334%2C335%2C336%2C337%2C394%2C395%2C396%2C397%2C398%2C399%2C400%2C401%2C694%2C695%2C696%2C697%2C698%2C699%2C700%2C701&c=WEB&clen=998696577&dur=313.780&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=315&keepalive=yes&lmt=1647476955807851&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=Zd7nrOM1B2C6PA&ns=426LxLap5MonJD_YWdS4lSYH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIfP4IVSo-00_kq_JIkuh032hcLoJzNEhYjvwgLiDpEzQIhALPVrvDBjRwiFddXiAyADmRtYygte4HvlJ3XOrkOf_TR&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4532434&vprv=1"))] | ||||
|     #[case::vp9_codec(StreamFilter::default().video_codecs(&[VideoCodec::Vp9]).to_owned(), Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C308%2C315%2C330%2C331%2C332%2C333%2C334%2C335%2C336%2C337%2C394%2C395%2C396%2C397%2C398%2C399%2C400%2C401%2C694%2C695%2C696%2C697%2C698%2C699%2C700%2C701&c=WEB&clen=998696577&dur=313.780&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=315&keepalive=yes&lmt=1647476955807851&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=Zd7nrOM1B2C6PA&ns=426LxLap5MonJD_YWdS4lSYH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIfP4IVSo-00_kq_JIkuh032hcLoJzNEhYjvwgLiDpEzQIhALPVrvDBjRwiFddXiAyADmRtYygte4HvlJ3XOrkOf_TR&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4532434&vprv=1"))] | ||||
|     #[case::noformat(StreamFilter::default().video_formats(&[]).to_owned(), None)] | ||||
|     #[case::nocodec(StreamFilter::default().video_codecs(&[]).to_owned(), None)] | ||||
|     fn t_select_video_only_stream(#[case] filter: StreamFilter, #[case] expect_url: Option<&str>) { | ||||
|         let selection = PLAYER_HDR.select_video_only_stream(&filter); | ||||
| 
 | ||||
|  | @ -385,12 +384,12 @@ mod tests { | |||
|         Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?c=WEB&clen=5199784&dur=313.801&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=251&keepalive=yes&lmt=1647453650291076&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=Zd7nrOM1B2C6PA&ns=426LxLap5MonJD_YWdS4lSYH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhALtI3j8ZChpNb0LcyDZ3yosbWnSpqaO0-jKAe_UM_RQyAiAMwrpdeNbJEnQn3q1eveaAcRcNIwy5iJ4fIjeBW_MUfg%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4532434&vprv=1") | ||||
|     )] | ||||
|     #[case::webm(
 | ||||
|         StreamFilter::default().video_formats(hash_set!(VideoFormat::Webm)).to_owned(), | ||||
|         StreamFilter::default().video_formats(&[VideoFormat::Webm]).to_owned(), | ||||
|         Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C308%2C315%2C330%2C331%2C332%2C333%2C334%2C335%2C336%2C337%2C394%2C395%2C396%2C397%2C398%2C399%2C400%2C401%2C694%2C695%2C696%2C697%2C698%2C699%2C700%2C701&c=WEB&clen=998696577&dur=313.780&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=315&keepalive=yes&lmt=1647476955807851&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=Zd7nrOM1B2C6PA&ns=426LxLap5MonJD_YWdS4lSYH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIfP4IVSo-00_kq_JIkuh032hcLoJzNEhYjvwgLiDpEzQIhALPVrvDBjRwiFddXiAyADmRtYygte4HvlJ3XOrkOf_TR&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4532434&vprv=1"), | ||||
|         Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?c=WEB&clen=5199784&dur=313.801&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=251&keepalive=yes&lmt=1647453650291076&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=Zd7nrOM1B2C6PA&ns=426LxLap5MonJD_YWdS4lSYH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhALtI3j8ZChpNb0LcyDZ3yosbWnSpqaO0-jKAe_UM_RQyAiAMwrpdeNbJEnQn3q1eveaAcRcNIwy5iJ4fIjeBW_MUfg%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4532434&vprv=1") | ||||
|     )] | ||||
|     #[case::noaudio(
 | ||||
|         StreamFilter::default().audio_formats(hash_set!()).to_owned(), | ||||
|         StreamFilter::default().audio_formats(&[]).to_owned(), | ||||
|         Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?c=WEB&clen=23544588&dur=313.834&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=18&lmt=1647456546485912&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=video%2Fmp4&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=HWZNhARNT_nJgg&ns=pLFQxzhiCbZ9F2HJmDLveKoH&pl=37&ratebypass=yes&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgeCEjusAq6p33rH0NHyTAbPIRaaEkjDE32AXBFzDvR-ICIQD0LI8hQVH8oCMWu6OuADzc1FSQhIqYs5RLkxBmObIdsw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4530434&vprv=1"), | ||||
|         None | ||||
|     )] | ||||
|  | @ -399,7 +398,7 @@ mod tests { | |||
|         None, | ||||
|         Some("https://rr5---sn-h0jelne7.googlevideo.com/videoplayback?c=WEB&clen=5199784&dur=313.801&ei=eckIY72IKcGZ8gOMt6CwDg&expire=1661541849&fexp=24001373%2C24007246&fvip=2&gir=yes&id=o-AOqXE9lVS424yszv6LN5V_gaevdHxenJl-tYNy3Drs6g&initcwndbps=1428750&ip=2003%3Ade%3Aaf05%3A2500%3A5dad%3A319b%3Aca30%3Ae212&itag=251&keepalive=yes&lmt=1647453650291076&lsig=AG3C_xAwRQIhAMioKyc-dqs-6uvAwLViCcCTXKHn9sIbo0cbSSBXGG4kAiBQNsRBAvQrbWdOjZIsQXYrfPEb1KDpE_AlSEGQZXB9uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=NH&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jelne7%2Csn-h0jeenl6&ms=au%2Crdu&mt=1661519833&mv=m&mvi=5&n=Zd7nrOM1B2C6PA&ns=426LxLap5MonJD_YWdS4lSYH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhALtI3j8ZChpNb0LcyDZ3yosbWnSpqaO0-jKAe_UM_RQyAiAMwrpdeNbJEnQn3q1eveaAcRcNIwy5iJ4fIjeBW_MUfg%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-KhuPtxVzL5-QbZ7S9zNeOHsWTdms&txp=4532434&vprv=1") | ||||
|     )] | ||||
|     #[case::noformat(StreamFilter::default().audio_formats(hash_set!()).video_formats(hash_set!()).to_owned(), None, None)] | ||||
|     #[case::noformat(StreamFilter::default().audio_formats(&[]).video_formats(&[]).to_owned(), None, None)] | ||||
|     fn t_select_video_audio_stream( | ||||
|         #[case] filter: StreamFilter, | ||||
|         #[case] expect_video_url: Option<&str>, | ||||
|  |  | |||
|  | @ -380,7 +380,7 @@ async fn playlist_cont() { | |||
| 
 | ||||
|     playlist | ||||
|         .videos | ||||
|         .extend_pages(&rp.query(), usize::MAX) | ||||
|         .extend_pages(rp.query(), usize::MAX) | ||||
|         .await | ||||
|         .unwrap(); | ||||
|     assert!(playlist.videos.items.len() > 100); | ||||
|  | @ -396,11 +396,7 @@ async fn playlist_cont2() { | |||
|         .await | ||||
|         .unwrap(); | ||||
| 
 | ||||
|     playlist | ||||
|         .videos | ||||
|         .extend_limit(&rp.query(), 101) | ||||
|         .await | ||||
|         .unwrap(); | ||||
|     playlist.videos.extend_limit(rp.query(), 101).await.unwrap(); | ||||
|     assert!(playlist.videos.items.len() > 100); | ||||
|     assert!(playlist.videos.count.unwrap() > 100); | ||||
| } | ||||
|  | @ -461,7 +457,7 @@ async fn get_video_details() { | |||
|     assert!(!details.is_ccommons); | ||||
| 
 | ||||
|     assert!(details.recommended.visitor_data.is_some()); | ||||
|     assert_next(details.recommended, &rp.query(), 10, 2).await; | ||||
|     assert_next(details.recommended, rp.query(), 10, 2).await; | ||||
| 
 | ||||
|     assert_gte(details.top_comments.count.unwrap(), 700_000, "comments"); | ||||
|     assert!(!details.top_comments.is_exhausted()); | ||||
|  | @ -499,7 +495,7 @@ async fn get_video_details_music() { | |||
|     assert!(!details.is_ccommons); | ||||
| 
 | ||||
|     assert!(details.recommended.visitor_data.is_some()); | ||||
|     assert_next(details.recommended, &rp.query(), 10, 2).await; | ||||
|     assert_next(details.recommended, rp.query(), 10, 2).await; | ||||
| 
 | ||||
|     // Update(01.11.2022): comments are sometimes enabled
 | ||||
|     /* | ||||
|  | @ -548,7 +544,7 @@ async fn get_video_details_ccommons() { | |||
|     assert!(details.is_ccommons); | ||||
| 
 | ||||
|     assert!(details.recommended.visitor_data.is_some()); | ||||
|     assert_next(details.recommended, &rp.query(), 10, 2).await; | ||||
|     assert_next(details.recommended, rp.query(), 10, 2).await; | ||||
| 
 | ||||
|     assert_gte(details.top_comments.count.unwrap(), 2199, "comments"); | ||||
|     assert!(!details.top_comments.is_exhausted()); | ||||
|  | @ -673,7 +669,7 @@ async fn get_video_details_chapters() { | |||
|     } | ||||
| 
 | ||||
|     assert!(details.recommended.visitor_data.is_some()); | ||||
|     assert_next(details.recommended, &rp.query(), 10, 2).await; | ||||
|     assert_next(details.recommended, rp.query(), 10, 2).await; | ||||
| 
 | ||||
|     assert_gte(details.top_comments.count.unwrap(), 3200, "comments"); | ||||
|     assert!(!details.top_comments.is_exhausted()); | ||||
|  | @ -718,7 +714,7 @@ async fn get_video_details_live() { | |||
|     assert!(!details.is_ccommons); | ||||
| 
 | ||||
|     assert!(details.recommended.visitor_data.is_some()); | ||||
|     assert_next(details.recommended, &rp.query(), 10, 2).await; | ||||
|     assert_next(details.recommended, rp.query(), 10, 2).await; | ||||
| 
 | ||||
|     // No comments because livestream
 | ||||
|     assert_eq!(details.top_comments.count, Some(0)); | ||||
|  | @ -786,7 +782,7 @@ async fn get_video_comments() { | |||
| 
 | ||||
|     let top_comments = details | ||||
|         .top_comments | ||||
|         .next(&rp.query()) | ||||
|         .next(rp.query()) | ||||
|         .await | ||||
|         .unwrap() | ||||
|         .unwrap(); | ||||
|  | @ -805,7 +801,7 @@ async fn get_video_comments() { | |||
| 
 | ||||
|     let latest_comments = details | ||||
|         .latest_comments | ||||
|         .next(&rp.query()) | ||||
|         .next(rp.query()) | ||||
|         .await | ||||
|         .unwrap() | ||||
|         .unwrap(); | ||||
|  | @ -839,7 +835,7 @@ async fn channel_videos() { | |||
| 
 | ||||
|     assert!(age_days < 60, "latest video older than 60 days"); | ||||
| 
 | ||||
|     assert_next(channel.content, &rp.query(), 15, 2).await; | ||||
|     assert_next(channel.content, rp.query(), 15, 2).await; | ||||
| } | ||||
| 
 | ||||
| #[tokio::test] | ||||
|  | @ -873,7 +869,7 @@ async fn channel_shorts() { | |||
|         "got no shorts" | ||||
|     ); | ||||
| 
 | ||||
|     assert_next(channel.content, &rp.query(), 15, 1).await; | ||||
|     assert_next(channel.content, rp.query(), 15, 1).await; | ||||
| } | ||||
| 
 | ||||
| #[tokio::test] | ||||
|  | @ -893,7 +889,7 @@ async fn channel_livestreams() { | |||
|         "got no streams" | ||||
|     ); | ||||
| 
 | ||||
|     assert_next(channel.content, &rp.query(), 5, 1).await; | ||||
|     assert_next(channel.content, rp.query(), 5, 1).await; | ||||
| } | ||||
| 
 | ||||
| #[tokio::test] | ||||
|  | @ -912,7 +908,7 @@ async fn channel_playlists() { | |||
|         "got no playlists" | ||||
|     ); | ||||
| 
 | ||||
|     assert_next(channel.content, &rp.query(), 15, 1).await; | ||||
|     assert_next(channel.content, rp.query(), 15, 1).await; | ||||
| } | ||||
| 
 | ||||
| #[tokio::test] | ||||
|  | @ -1099,7 +1095,7 @@ async fn search() { | |||
|     ); | ||||
|     assert_eq!(result.corrected_query.unwrap(), "doobydobap"); | ||||
| 
 | ||||
|     assert_next(result.items, &rp.query(), 10, 2).await; | ||||
|     assert_next(result.items, rp.query(), 10, 2).await; | ||||
| } | ||||
| 
 | ||||
| #[rstest] | ||||
|  | @ -1115,7 +1111,7 @@ async fn search_filter_entity(#[case] entity: search_filter::Entity) { | |||
|         .await | ||||
|         .unwrap(); | ||||
| 
 | ||||
|     result.items.extend(&rp.query()).await.unwrap(); | ||||
|     result.items.extend(rp.query()).await.unwrap(); | ||||
|     assert_gte(result.items.items.len(), 20, "items"); | ||||
| 
 | ||||
|     result.items.items.iter().for_each(|item| match item { | ||||
|  | @ -1243,7 +1239,7 @@ async fn startpage() { | |||
|     // The startpage requires visitor data to fetch continuations
 | ||||
|     assert!(startpage.visitor_data.is_some()); | ||||
| 
 | ||||
|     assert_next(startpage, &rp.query(), 20, 2).await; | ||||
|     assert_next(startpage, rp.query(), 20, 2).await; | ||||
| } | ||||
| 
 | ||||
| #[tokio::test] | ||||
|  | @ -1321,7 +1317,7 @@ async fn music_playlist_cont() { | |||
| 
 | ||||
|     playlist | ||||
|         .tracks | ||||
|         .extend_pages(&rp.query(), usize::MAX) | ||||
|         .extend_pages(rp.query(), usize::MAX) | ||||
|         .await | ||||
|         .unwrap(); | ||||
| 
 | ||||
|  | @ -1338,11 +1334,7 @@ async fn music_playlist_related() { | |||
|         .await | ||||
|         .unwrap(); | ||||
| 
 | ||||
|     playlist | ||||
|         .related_playlists | ||||
|         .extend(&rp.query()) | ||||
|         .await | ||||
|         .unwrap(); | ||||
|     playlist.related_playlists.extend(rp.query()).await.unwrap(); | ||||
| 
 | ||||
|     assert_gte( | ||||
|         playlist.related_playlists.items.len(), | ||||
|  | @ -1571,7 +1563,7 @@ async fn music_search_tracks() { | |||
|     assert_eq!(album.id, "MPREb_OpHWHwyNOuY"); | ||||
|     assert_eq!(album.name, "Black Mamba"); | ||||
| 
 | ||||
|     assert_next(res.items, &rp.query(), 15, 2).await; | ||||
|     assert_next(res.items, rp.query(), 15, 2).await; | ||||
| } | ||||
| 
 | ||||
| #[tokio::test] | ||||
|  | @ -1605,7 +1597,7 @@ async fn music_search_videos() { | |||
|     assert_eq!(track.album, None); | ||||
|     assert_gte(track.view_count.unwrap(), 230_000_000, "views"); | ||||
| 
 | ||||
|     assert_next(res.items, &rp.query(), 15, 2).await; | ||||
|     assert_next(res.items, rp.query(), 15, 2).await; | ||||
| } | ||||
| 
 | ||||
| #[tokio::test] | ||||
|  | @ -1692,7 +1684,7 @@ async fn music_search_albums( | |||
| 
 | ||||
|     assert_eq!(res.corrected_query, None); | ||||
| 
 | ||||
|     assert_next(res.items, &rp.query(), 15, n_pages).await; | ||||
|     assert_next(res.items, rp.query(), 15, n_pages).await; | ||||
| } | ||||
| 
 | ||||
| #[tokio::test] | ||||
|  | @ -1724,7 +1716,7 @@ async fn music_search_artists_cont() { | |||
|     let res = rp.query().music_search_artists("band").await.unwrap(); | ||||
| 
 | ||||
|     assert_eq!(res.corrected_query, None); | ||||
|     assert_next(res.items, &rp.query(), 15, 2).await; | ||||
|     assert_next(res.items, rp.query(), 15, 2).await; | ||||
| } | ||||
| 
 | ||||
| #[rstest] | ||||
|  | @ -2000,7 +1992,7 @@ async fn music_details_not_found() { | |||
| async fn music_radio_track() { | ||||
|     let rp = RustyPipe::builder().strict().build(); | ||||
|     let tracks = rp.query().music_radio_track("ZeerrnuLi5E").await.unwrap(); | ||||
|     assert_next(tracks, &rp.query(), 20, 3).await; | ||||
|     assert_next(tracks, rp.query(), 20, 3).await; | ||||
| } | ||||
| 
 | ||||
| #[tokio::test] | ||||
|  | @ -2030,7 +2022,7 @@ async fn music_radio_playlist() { | |||
|         .music_radio_playlist("PL5dDx681T4bR7ZF1IuWzOv1omlRbE7PiJ") | ||||
|         .await | ||||
|         .unwrap(); | ||||
|     assert_next(tracks, &rp.query(), 10, 1).await; | ||||
|     assert_next(tracks, rp.query(), 10, 1).await; | ||||
| } | ||||
| 
 | ||||
| #[tokio::test] | ||||
|  | @ -2121,13 +2113,14 @@ fn assert_gte<T: PartialOrd + Display>(a: T, b: T, msg: &str) { | |||
|     assert!(a >= b, "expected {} {}, got {}", b, msg, a); | ||||
| } | ||||
| 
 | ||||
| async fn assert_next<T: FromYtItem>( | ||||
| async fn assert_next<T: FromYtItem, Q: AsRef<RustyPipeQuery>>( | ||||
|     paginator: Paginator<T>, | ||||
|     query: &RustyPipeQuery, | ||||
|     query: Q, | ||||
|     min_items: usize, | ||||
|     n_pages: usize, | ||||
| ) { | ||||
|     let mut p = paginator; | ||||
|     let query = query.as_ref(); | ||||
|     assert_gte(p.items.len(), min_items, "items on page 0"); | ||||
| 
 | ||||
|     for i in 0..n_pages { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue