diff --git a/notes/video_ids.txt b/notes/video_ids.txt index 53f9d7b..35096d4 100644 --- a/notes/video_ids.txt +++ b/notes/video_ids.txt @@ -63,3 +63,10 @@ Dec PL1J-6JOckZtHo91uApeb10Qlf2XhkfM-9 24.12.2021 10e3: 5K UC0QEucPrn0-Ddi3JBTcs5Kw 10e2: 388 UCllyEQfcoiPN68zHv6mGHDQ 10e1: 37 UCGiJh0NZ52wRhYKYnuZI08Q + +# Album types +Album: MPREb_nlBWQROfvjo +Single: MPREb_bHfHGoy7vuv +EP: MPREb_u1I69lSAe5v +Show: MPREb_cwzk8EUwypZ +Audiobook: MPREb_gaoNzsQHedo diff --git a/src/client/pagination.rs b/src/client/pagination.rs index b85df14..0d4baf3 100644 --- a/src/client/pagination.rs +++ b/src/client/pagination.rs @@ -128,7 +128,7 @@ impl MapResponse> for response::MusicContinuation { _deobf: Option<&crate::deobfuscate::Deobfuscator>, ) -> Result>, ExtractionError> { let mut mapper = MusicListMapper::new(lang); - let mut shelf = self.continuation_contents.music_playlist_shelf_continuation; + let mut shelf = self.continuation_contents.music_shelf_continuation; mapper.map_response(shelf.contents); let map_res = mapper.items(); diff --git a/src/client/response/music_item.rs b/src/client/response/music_item.rs index 4561ce9..46bbf99 100644 --- a/src/client/response/music_item.rs +++ b/src/client/response/music_item.rs @@ -183,7 +183,8 @@ pub(crate) struct MusicContinuation { #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub(crate) struct ContinuationContents { - pub music_playlist_shelf_continuation: MusicShelf, + #[serde(alias = "musicPlaylistShelfContinuation")] + pub music_shelf_continuation: MusicShelf, } /* diff --git a/src/client/response/url_endpoint.rs b/src/client/response/url_endpoint.rs index 23b8b3c..004270c 100644 --- a/src/client/response/url_endpoint.rs +++ b/src/client/response/url_endpoint.rs @@ -36,13 +36,47 @@ pub(crate) struct WatchEndpoint { pub start_time_seconds: u32, } -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] +#[derive(Debug)] pub(crate) struct BrowseEndpoint { pub browse_id: String, pub browse_endpoint_context_supported_configs: Option, } +impl<'de> Deserialize<'de> for BrowseEndpoint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + #[derive(Debug, Deserialize)] + #[serde(rename_all = "camelCase")] + struct BEp { + pub browse_id: String, + pub browse_endpoint_context_supported_configs: Option, + } + + let bep = BEp::deserialize(deserializer)?; + + // Remove the VL prefix from the playlist id + let browse_id = bep + .browse_endpoint_context_supported_configs + .as_ref() + .and_then( + |cfg| match cfg.browse_endpoint_context_music_config.page_type { + PageType::Playlist => bep.browse_id.strip_prefix("VL"), + _ => None, + }, + ) + .map(str::to_owned) + .unwrap_or(bep.browse_id); + + Ok(Self { + browse_id, + browse_endpoint_context_supported_configs: bep + .browse_endpoint_context_supported_configs, + }) + } +} + #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub(crate) struct UrlEndpoint { @@ -75,9 +109,12 @@ pub(crate) struct WebCommandMetadata { #[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)] pub(crate) enum PageType { - #[serde(rename = "MUSIC_PAGE_TYPE_ARTIST")] + #[serde( + rename = "MUSIC_PAGE_TYPE_ARTIST", + alias = "MUSIC_PAGE_TYPE_AUDIOBOOK_ARTIST" + )] Artist, - #[serde(rename = "MUSIC_PAGE_TYPE_ALBUM")] + #[serde(rename = "MUSIC_PAGE_TYPE_ALBUM", alias = "MUSIC_PAGE_TYPE_AUDIOBOOK")] Album, #[serde( rename = "WEB_PAGE_TYPE_CHANNEL", diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_default.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_default.snap index 7051978..2a46a44 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_default.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_default.snap @@ -356,7 +356,7 @@ MusicSearchResult( ], playlists: [ MusicPlaylistItem( - id: "VLPLk76iSbFqNJsu_Gozn9SkEXxQ7t-bpXid", + id: "PLk76iSbFqNJsu_Gozn9SkEXxQ7t-bpXid", name: "IRMA MIRTILLA Black Mamba", thumbnail: [ Thumbnail( @@ -383,7 +383,7 @@ MusicSearchResult( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLIL9Q2jz6euDEJZKHd4QaG4iic944_vKY", + id: "PLIL9Q2jz6euDEJZKHd4QaG4iic944_vKY", name: "Black Mamba", thumbnail: [ Thumbnail( @@ -410,7 +410,7 @@ MusicSearchResult( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLinm7-cvTdN7RqadpfNrncUGqkdyKNpn6", + id: "PLinm7-cvTdN7RqadpfNrncUGqkdyKNpn6", name: "Black Mamba", thumbnail: [ Thumbnail( diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_playlists_community.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_playlists_community.snap index 2fb6d9b..f3381e8 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_playlists_community.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_playlists_community.snap @@ -7,7 +7,7 @@ MusicSearchFiltered( count: None, items: [ MusicPlaylistItem( - id: "VLPLDIoUOhQQPlVr3qepMVRsDe4T8vNQsvno", + id: "PLDIoUOhQQPlVr3qepMVRsDe4T8vNQsvno", name: "Türkçe Pop Şarkılar 2022 - Yeni Hit Şarkılar 2022", thumbnail: [ Thumbnail( @@ -34,7 +34,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLI_7Mg2Z_-4Lf7IYeiTEOV8HBn-nMqz5N", + id: "PLI_7Mg2Z_-4Lf7IYeiTEOV8HBn-nMqz5N", name: "Pop 2022 ♫ Mix Pop En Ingles (English Pop Songs 2022)", thumbnail: [ Thumbnail( @@ -61,7 +61,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLTC7VQ12-9raqhLCx1S1E_ic35t94dj28", + id: "PLTC7VQ12-9raqhLCx1S1E_ic35t94dj28", name: "Pop & Pop Rock Hits 🔥 2012 - 2022", thumbnail: [ Thumbnail( @@ -88,7 +88,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLPssMy7y6ygl-Kzi9Mc7TVFFPWwyAXIwW", + id: "PLPssMy7y6ygl-Kzi9Mc7TVFFPWwyAXIwW", name: "Bester deutscher Pop/Best of German Pop music", thumbnail: [ Thumbnail( @@ -115,7 +115,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLMC9KNkIncKtPzgY-5rmhvj7fax8fdxoj", + id: "PLMC9KNkIncKtPzgY-5rmhvj7fax8fdxoj", name: "Pop Music Playlist - Timeless Pop Songs (Updated Weekly 2022)", thumbnail: [ Thumbnail( @@ -142,7 +142,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLX6L4t7t6ZanfCJ1wBxRdGZ_mk9ygmKqo", + id: "PLX6L4t7t6ZanfCJ1wBxRdGZ_mk9ygmKqo", name: "Deutsch Pop Hits NEU 2022", thumbnail: [ Thumbnail( @@ -169,7 +169,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPL1jMjCxDqxLvomtUMbqa_4pAjMmzpfgUy", + id: "PL1jMjCxDqxLvomtUMbqa_4pAjMmzpfgUy", name: "Top 100 Músicas Internacionais Pop 2022", thumbnail: [ Thumbnail( @@ -196,7 +196,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLgRdph0qPLy53IhYrQLPpATDDA2TpFey5", + id: "PLgRdph0qPLy53IhYrQLPpATDDA2TpFey5", name: "Teen-Pop 90-2000", thumbnail: [ Thumbnail( @@ -223,7 +223,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLV9Y77TQ4I9dXpIF-r54ZTLM5T7C4k5jf", + id: "PLV9Y77TQ4I9dXpIF-r54ZTLM5T7C4k5jf", name: "Most Popular Soft Pop Songs of 2022 Playlist - Best Soft Pop Music Hits of the Year 2022", thumbnail: [ Thumbnail( @@ -250,7 +250,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLlYKDqBVDxX2TXAf8ruuF3FVZgzF3wCTx", + id: "PLlYKDqBVDxX2TXAf8ruuF3FVZgzF3wCTx", name: "Pop 2022 ♫ Best Pop Songs Playlist 2022", thumbnail: [ Thumbnail( @@ -277,7 +277,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLMC9KNkIncKvYin_USF1qoJQnIyMAfRxl", + id: "PLMC9KNkIncKvYin_USF1qoJQnIyMAfRxl", name: "Best Pop Songs of All Time: Playlist of Good Songs (Throwback Hits & Pop Music 2022)", thumbnail: [ Thumbnail( @@ -304,7 +304,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLKUA473MWUv2jmkqIxzQR3YL4kuPArj4G", + id: "PLKUA473MWUv2jmkqIxzQR3YL4kuPArj4G", name: "Best Pop Music for Office – Good Songs for Work: Pop Hits Collection (Playlist Updated in 2022)", thumbnail: [ Thumbnail( @@ -331,7 +331,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLkqz3S84Tw-RfPS9HHi3MRmrinOBKxIr8", + id: "PLkqz3S84Tw-RfPS9HHi3MRmrinOBKxIr8", name: "Top POP Hits 2022 – Biggest Pop Music Videos - Vevo", thumbnail: [ Thumbnail( @@ -358,7 +358,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLEBX04z4REEaHbC7ghEqFwwL4ptIw8qaZ", + id: "PLEBX04z4REEaHbC7ghEqFwwL4ptIw8qaZ", name: "Playlist Pop Rock 2022 ♫ Musique Pop Rock 2022 Nouveauté", thumbnail: [ Thumbnail( @@ -385,7 +385,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLMC9KNkIncKtGvr2kFRuXBVmBev6cAJ2u", + id: "PLMC9KNkIncKtGvr2kFRuXBVmBev6cAJ2u", name: "Best Pop Music Videos - Top Pop Hits Playlist", thumbnail: [ Thumbnail( @@ -412,7 +412,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPL9NY5axt700FjL6HlEhqlMFT1gjMGVBgy", + id: "PL9NY5axt700FjL6HlEhqlMFT1gjMGVBgy", name: "Pop Music Songs 2022", thumbnail: [ Thumbnail( @@ -439,7 +439,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLTariUrSxayvzHkCnEiX5-NSeFgLTqzHE", + id: "PLTariUrSxayvzHkCnEiX5-NSeFgLTqzHE", name: "Pop Music Playlist 2022", thumbnail: [ Thumbnail( @@ -466,7 +466,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLB8HqqmpyIBcPirb5lDm-ol01trE6dOuM", + id: "PLB8HqqmpyIBcPirb5lDm-ol01trE6dOuM", name: "Mix Internacional 2022 ♫ As Mais Tocadas 2022 Internacionais (Playlist Musicas Pop As Melhores)", thumbnail: [ Thumbnail( @@ -493,7 +493,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLkqz3S84Tw-Qlth8bNBpXGO7L4J1PkCW7", + id: "PLkqz3S84Tw-Qlth8bNBpXGO7L4J1PkCW7", name: "POP INTERNATIONAL HOTLIST - Pop Hits 2022- Brandneue Pop Videos | Vevo Playlist", thumbnail: [ Thumbnail( @@ -520,7 +520,7 @@ MusicSearchFiltered( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLkqz3S84Tw-SvUSUY5Ov8LTP3KWuWxFab", + id: "PLkqz3S84Tw-SvUSUY5Ov8LTP3KWuWxFab", name: "Cheesy Sing-Along Pop Hits!", thumbnail: [ Thumbnail( diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_playlists_ytm.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_playlists_ytm.snap index 3ff8844..1773035 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_playlists_ytm.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_playlists_ytm.snap @@ -7,7 +7,7 @@ MusicSearchFiltered( count: None, items: [ MusicPlaylistItem( - id: "VLRDCLAK5uy_nmS3YoxSwVVQk9lEQJ0UX4ZCjXsW_psU8", + id: "RDCLAK5uy_nmS3YoxSwVVQk9lEQJ0UX4ZCjXsW_psU8", name: "Pop\'s Biggest Hits", thumbnail: [ Thumbnail( @@ -36,7 +36,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_nfs_t4FUu00E5ED6lveEBBX1VMYe1mFjk", + id: "RDCLAK5uy_nfs_t4FUu00E5ED6lveEBBX1VMYe1mFjk", name: "Dance-Pop Bangers", thumbnail: [ Thumbnail( @@ -65,7 +65,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_nH_fdBVCcbNaVwi_tmZajZRq-ekddiuFY", + id: "RDCLAK5uy_nH_fdBVCcbNaVwi_tmZajZRq-ekddiuFY", name: "Pop Meets Country", thumbnail: [ Thumbnail( @@ -94,7 +94,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_lb6CVU6S4uVugLVNTU9WhqfaomWAgnho4", + id: "RDCLAK5uy_lb6CVU6S4uVugLVNTU9WhqfaomWAgnho4", name: "Shout-Out Pop Hits", thumbnail: [ Thumbnail( @@ -123,7 +123,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_mfdqvCAl8wodlx2P2_Ai2gNkiRDAufkkI", + id: "RDCLAK5uy_mfdqvCAl8wodlx2P2_Ai2gNkiRDAufkkI", name: "Happy Pop Hits", thumbnail: [ Thumbnail( @@ -152,7 +152,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_nHSqCJjDrW9HBhCNdF6tWPdnOMngOv0wA", + id: "RDCLAK5uy_nHSqCJjDrW9HBhCNdF6tWPdnOMngOv0wA", name: "Pop Gold", thumbnail: [ Thumbnail( @@ -181,7 +181,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_kLB769E3eFSzgy4fbpu6-1YPLh90b0JAY", + id: "RDCLAK5uy_kLB769E3eFSzgy4fbpu6-1YPLh90b0JAY", name: "Pop Hotlist", thumbnail: [ Thumbnail( @@ -210,7 +210,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_m_0U5VQNyyzwwH1lRi7cPAAGXqNQnAOqY", + id: "RDCLAK5uy_m_0U5VQNyyzwwH1lRi7cPAAGXqNQnAOqY", name: "Laid-Back Sofa Pop", thumbnail: [ Thumbnail( @@ -239,7 +239,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_mHW5bcduhjB-PkTePAe6EoRMj1xNT8gzY", + id: "RDCLAK5uy_mHW5bcduhjB-PkTePAe6EoRMj1xNT8gzY", name: "K-Pop Girl Crush", thumbnail: [ Thumbnail( @@ -268,7 +268,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_nWFLXjO1mIJnP4wAmxjfDS40Zmu6nF9DU", + id: "RDCLAK5uy_nWFLXjO1mIJnP4wAmxjfDS40Zmu6nF9DU", name: "Se Habla Pop", thumbnail: [ Thumbnail( @@ -297,7 +297,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_lHu_HYAQ0A-OfCwhuky240HOdM1UduuyA", + id: "RDCLAK5uy_lHu_HYAQ0A-OfCwhuky240HOdM1UduuyA", name: "Presenting Pop Smoke", thumbnail: [ Thumbnail( @@ -326,7 +326,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_lw21MuKaqFsDBIPZSbRmZcoDrHmV_c6uY", + id: "RDCLAK5uy_lw21MuKaqFsDBIPZSbRmZcoDrHmV_c6uY", name: "Happy latin pop", thumbnail: [ Thumbnail( @@ -355,7 +355,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_lY6JFrs7W9yIhFjUN_yxQ_ubkjcrqQaVs", + id: "RDCLAK5uy_lY6JFrs7W9yIhFjUN_yxQ_ubkjcrqQaVs", name: "Bedroom Pop", thumbnail: [ Thumbnail( @@ -384,7 +384,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_nbK9qSkqYZvtMXH1fLCMmC1yn8HEm0W90", + id: "RDCLAK5uy_nbK9qSkqYZvtMXH1fLCMmC1yn8HEm0W90", name: "J-Hits!", thumbnail: [ Thumbnail( @@ -413,7 +413,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_kIcfhFcnJ9fdkKHw96Gvr6Q0_bAyWiZbM", + id: "RDCLAK5uy_kIcfhFcnJ9fdkKHw96Gvr6Q0_bAyWiZbM", name: "Reiwa Era J-Pop", thumbnail: [ Thumbnail( @@ -442,7 +442,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_nDL8KeBrUagwyISwNmyEiSfYgz1gVCesg", + id: "RDCLAK5uy_nDL8KeBrUagwyISwNmyEiSfYgz1gVCesg", name: "Mellow Pop Classics", thumbnail: [ Thumbnail( @@ -471,7 +471,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_l7K78k4EkjcFojhd1617rmUjY-aet6-t0", + id: "RDCLAK5uy_l7K78k4EkjcFojhd1617rmUjY-aet6-t0", name: "K-Pop Party Hits", thumbnail: [ Thumbnail( @@ -500,7 +500,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_nCVF_zUZizzRcojIUuYmaXxMoPgg2WMDo", + id: "RDCLAK5uy_nCVF_zUZizzRcojIUuYmaXxMoPgg2WMDo", name: "Klangfarbe: German Pop Hits", thumbnail: [ Thumbnail( @@ -529,7 +529,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_nGKsW16ocmP8l8wL1oMIyR53cu4N5fyKI", + id: "RDCLAK5uy_nGKsW16ocmP8l8wL1oMIyR53cu4N5fyKI", name: "GIF Pop BR", thumbnail: [ Thumbnail( @@ -558,7 +558,7 @@ MusicSearchFiltered( from_ytm: true, ), MusicPlaylistItem( - id: "VLRDCLAK5uy_mVJ3RRi_YBfUJnZnQxLAedQQcXHujbUcg", + id: "RDCLAK5uy_mVJ3RRi_YBfUJnZnQxLAedQQcXHujbUcg", name: "Pump-Up Pop", thumbnail: [ Thumbnail( diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_typo.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_typo.snap index 2fb52a5..5e76805 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_typo.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_typo.snap @@ -364,7 +364,7 @@ MusicSearchResult( ], playlists: [ MusicPlaylistItem( - id: "VLPL46jG0sBz4EabjYqv0tVEd1RvrZRjfJ8m", + id: "PL46jG0sBz4EabjYqv0tVEd1RvrZRjfJ8m", name: "Lieblingsmensch", thumbnail: [ Thumbnail( @@ -391,7 +391,7 @@ MusicSearchResult( from_ytm: false, ), MusicPlaylistItem( - id: "VLPL-2Z-8cOvEixQ2EKumbXXW8XivJG6U7-D", + id: "PL-2Z-8cOvEixQ2EKumbXXW8XivJG6U7-D", name: "Namika - Lieblingsmensch", thumbnail: [ Thumbnail( @@ -418,7 +418,7 @@ MusicSearchResult( from_ytm: false, ), MusicPlaylistItem( - id: "VLPLDnJKuRrOR5sx_jZ8-dsweq1OdayL_kpz", + id: "PLDnJKuRrOR5sx_jZ8-dsweq1OdayL_kpz", name: "Lieblingsmensch", thumbnail: [ Thumbnail( diff --git a/src/model/mod.rs b/src/model/mod.rs index 49bc156..e40e105 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -5,7 +5,7 @@ mod ordering; mod paginator; pub mod richtext; -pub(crate) use convert::FromYtItem; +pub use convert::FromYtItem; pub use paginator::Paginator; use serde_with::serde_as; @@ -955,6 +955,7 @@ pub struct MusicPlaylistItem { /// YouTube Music album type #[derive(Default, Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[non_exhaustive] pub enum AlbumType { /// Regular album (default) #[default] @@ -1031,9 +1032,13 @@ pub struct MusicAlbum { /// YouTube Music search result #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct MusicSearchResult { + /// Found tracks pub tracks: Vec, + /// Found albums pub albums: Vec, + /// Found artists pub artists: Vec, + /// Found playlists pub playlists: Vec, /// Corrected search query /// @@ -1041,6 +1046,8 @@ pub struct MusicSearchResult { /// for the corrected search term and displays it on top of the /// search results page. pub corrected_query: Option, + /// Order of the item sections of the search page, starting with + /// the most relevant. pub order: Vec, } diff --git a/tests/snapshots/youtube__music_album_audiobook.snap b/tests/snapshots/youtube__music_album_audiobook.snap new file mode 100644 index 0000000..6d73252 --- /dev/null +++ b/tests/snapshots/youtube__music_album_audiobook.snap @@ -0,0 +1,2418 @@ +--- +source: tests/youtube.rs +expression: album +--- +MusicAlbum( + id: "MPREb_gaoNzsQHedo", + playlist_id: Some("OLAK5uy_k7u7GK3VF2l5tCdMEyksYRibZvTxLDcVY"), + name: "1984", + cover: "[cover]", + artists: [], + artists_txt: "George Orwell & Dirk Jacobs", + album_type: Album, + year: Some(2022), + by_va: false, + tracks: [ + TrackItem( + id: "F28BV_Y-970", + title: "Kapitel 1.1 - 1984", + duration: 131, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(1), + ), + TrackItem( + id: "B12pddzDBAs", + title: "Kapitel 1.2 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(2), + ), + TrackItem( + id: "J4jGyX1f998", + title: "Kapitel 1.3 - 1984", + duration: 129, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(3), + ), + TrackItem( + id: "xSwgv3_59Jg", + title: "Kapitel 1.4 - 1984", + duration: 141, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(4), + ), + TrackItem( + id: "WzmdYCTH-ZI", + title: "Kapitel 1.5 - 1984", + duration: 134, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(5), + ), + TrackItem( + id: "5OQfpOqbaY8", + title: "Kapitel 1.6 - 1984", + duration: 135, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(6), + ), + TrackItem( + id: "7UeTt_0QS1M", + title: "Kapitel 1.7 - 1984", + duration: 129, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(7), + ), + TrackItem( + id: "2RP6xm9TWPA", + title: "Kapitel 1.8 - 1984", + duration: 140, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(8), + ), + TrackItem( + id: "4EiyZzC98vA", + title: "Kapitel 1.9 - 1984", + duration: 178, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(9), + ), + TrackItem( + id: "d7c18oVKGuw", + title: "Kapitel 1.10 - 1984", + duration: 138, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(10), + ), + TrackItem( + id: "bKCEe30O-9E", + title: "Kapitel 1.11 - 1984", + duration: 126, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(11), + ), + TrackItem( + id: "jzZVXzd-IgI", + title: "Kapitel 1.12 - 1984", + duration: 133, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(12), + ), + TrackItem( + id: "A5GNL_YP6rc", + title: "Kapitel 1.13 - 1984", + duration: 134, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(13), + ), + TrackItem( + id: "TihFSZ8IZHo", + title: "Kapitel 1.14 - 1984", + duration: 154, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(14), + ), + TrackItem( + id: "1QfMUYC9BR8", + title: "Kapitel 1.15 - 1984", + duration: 139, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(15), + ), + TrackItem( + id: "AhuZlNLGQK0", + title: "Kapitel 1.16 - 1984", + duration: 127, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(16), + ), + TrackItem( + id: "Twrr-ReUadg", + title: "Kapitel 1.17 - 1984", + duration: 140, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(17), + ), + TrackItem( + id: "F6JJmeRk3NY", + title: "Kapitel 1.18 - 1984", + duration: 141, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(18), + ), + TrackItem( + id: "bERcihhazVQ", + title: "Kapitel 1.19 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(19), + ), + TrackItem( + id: "zmsB0ixj4L8", + title: "Kapitel 1.20 - 1984", + duration: 138, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(20), + ), + TrackItem( + id: "_AeZoRyNZ0Q", + title: "Kapitel 1.21 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(21), + ), + TrackItem( + id: "iX_GlsDkgSs", + title: "Kapitel 1.22 & Kapitel 2.1 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(22), + ), + TrackItem( + id: "TdR76HsPNZI", + title: "Kapitel 2.2 - 1984", + duration: 153, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(23), + ), + TrackItem( + id: "gz6e4SE3L_8", + title: "Kapitel 2.3 - 1984", + duration: 144, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(24), + ), + TrackItem( + id: "jrZYEoLg1lY", + title: "Kapitel 2.4 - 1984", + duration: 136, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(25), + ), + TrackItem( + id: "z4CRs-_heos", + title: "Kapitel 2.5 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(26), + ), + TrackItem( + id: "RM8Jk0AhLNY", + title: "Kapitel 2.6 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(27), + ), + TrackItem( + id: "mICWuD7UbpE", + title: "Kapitel 2.7 - 1984", + duration: 153, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(28), + ), + TrackItem( + id: "ieJk5E2FrTQ", + title: "Kapitel 2.8 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(29), + ), + TrackItem( + id: "DWa2LY_SXyQ", + title: "Kapitel 2.9 - 1984", + duration: 139, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(30), + ), + TrackItem( + id: "vBzgEusfeIU", + title: "Kapitel 2.10 - 1984", + duration: 151, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(31), + ), + TrackItem( + id: "t3U95rPrFrY", + title: "Kapitel 2.11 & Kapitel 3.1 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(32), + ), + TrackItem( + id: "F0HVKbHFXOA", + title: "Kapitel 3.2 - 1984", + duration: 125, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(33), + ), + TrackItem( + id: "VB6RraDXSEM", + title: "Kapitel 3.3 - 1984", + duration: 133, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(34), + ), + TrackItem( + id: "tqi9j41-xhU", + title: "Kapitel 3.4 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(35), + ), + TrackItem( + id: "tyCtChD9gNY", + title: "Kapitel 3.5 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(36), + ), + TrackItem( + id: "fn2pYeEM288", + title: "Kapitel 3.6 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(37), + ), + TrackItem( + id: "1hphnoWnbFM", + title: "Kapitel 3.7 - 1984", + duration: 141, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(38), + ), + TrackItem( + id: "cnige70U6nw", + title: "Kapitel 3.8 - 1984", + duration: 188, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(39), + ), + TrackItem( + id: "N_DmWGxuDg8", + title: "Kapitel 3.9 - 1984", + duration: 135, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(40), + ), + TrackItem( + id: "v536-IdXIqc", + title: "Kapitel 3.10 - 1984", + duration: 133, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(41), + ), + TrackItem( + id: "ZkFmAt8MS90", + title: "Kapitel 3.11 & Kapitel 4.1 - 1984", + duration: 129, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(42), + ), + TrackItem( + id: "tzCu8HlkxDE", + title: "Kapitel 4.2 - 1984", + duration: 152, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(43), + ), + TrackItem( + id: "mJGIaHm03Tc", + title: "Kapitel 4.3 - 1984", + duration: 136, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(44), + ), + TrackItem( + id: "qsZee8A6QB0", + title: "Kapitel 4.4 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(45), + ), + TrackItem( + id: "8Wpxs6QRqu4", + title: "Kapitel 4.5 - 1984", + duration: 129, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(46), + ), + TrackItem( + id: "82eUY70WLqE", + title: "Kapitel 4.6 - 1984", + duration: 134, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(47), + ), + TrackItem( + id: "03KktUmXdMg", + title: "Kapitel 4.7 - 1984", + duration: 127, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(48), + ), + TrackItem( + id: "ki5f2zgRAjI", + title: "Kapitel 4.8 - 1984", + duration: 137, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(49), + ), + TrackItem( + id: "O05G6kmQW2g", + title: "Kapitel 4.9 - 1984", + duration: 143, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(50), + ), + TrackItem( + id: "Dayba7Kf90U", + title: "Kapitel 4.10 - 1984", + duration: 144, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(51), + ), + TrackItem( + id: "V1G2tVnsyfU", + title: "Kapitel 4.11 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(52), + ), + TrackItem( + id: "ugegWLyUGjg", + title: "Kapitel 4.12 - 1984", + duration: 146, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(53), + ), + TrackItem( + id: "o0OY_x2Sb1E", + title: "Kapitel 4.13 & Kapitel 5.1 - 1984", + duration: 137, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(54), + ), + TrackItem( + id: "aefFzoIlJZY", + title: "Kapitel 5.2 - 1984", + duration: 142, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(55), + ), + TrackItem( + id: "Wp6E3VPS2mM", + title: "Kapitel 5.3 - 1984", + duration: 151, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(56), + ), + TrackItem( + id: "tLuYgcr6Dpg", + title: "Kapitel 5.4 - 1984", + duration: 161, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(57), + ), + TrackItem( + id: "375_yqG6YbI", + title: "Kapitel 5.5 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(58), + ), + TrackItem( + id: "ANqW0THg1Pw", + title: "Kapitel 5.6 - 1984", + duration: 131, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(59), + ), + TrackItem( + id: "3qfEL7ZCgL8", + title: "Kapitel 5.7 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(60), + ), + TrackItem( + id: "_G8r-gk0msY", + title: "Kapitel 5.8 - 1984", + duration: 154, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(61), + ), + TrackItem( + id: "whI1u7a_rSU", + title: "Kapitel 5.9 - 1984", + duration: 129, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(62), + ), + TrackItem( + id: "X2swFoUEp30", + title: "Kapitel 5.10 - 1984", + duration: 148, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(63), + ), + TrackItem( + id: "5nXXHqVDIqY", + title: "Kapitel 5.11 - 1984", + duration: 133, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(64), + ), + TrackItem( + id: "AgT-3d32lkQ", + title: "Kapitel 5.12 - 1984", + duration: 129, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(65), + ), + TrackItem( + id: "NvR28TRH1Kc", + title: "Kapitel 5.13 - 1984", + duration: 143, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(66), + ), + TrackItem( + id: "218UZATQgwY", + title: "Kapitel 5.14 - 1984", + duration: 152, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(67), + ), + TrackItem( + id: "rCUpwhyh7ag", + title: "Kapitel 5.15 - 1984", + duration: 141, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(68), + ), + TrackItem( + id: "FseNJJS42Wk", + title: "Kapitel 5.16 - 1984", + duration: 133, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(69), + ), + TrackItem( + id: "ahufTwdimiY", + title: "Kapitel 5.17 & Kapitel 6.1 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(70), + ), + TrackItem( + id: "w_hYzT2BSz0", + title: "Kapitel 6.2 - 1984", + duration: 129, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(71), + ), + TrackItem( + id: "L8bxsR6xR8Y", + title: "Kapitel 6.3 - 1984", + duration: 135, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(72), + ), + TrackItem( + id: "StCyrfSVKRA", + title: "Kapitel 6.4 - 1984", + duration: 135, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(73), + ), + TrackItem( + id: "bfb0z96jjDw", + title: "Kapitel 6.5 - 1984", + duration: 149, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(74), + ), + TrackItem( + id: "_Cs_HEjIxE4", + title: "Kapitel 6.6 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(75), + ), + TrackItem( + id: "rlZTCrB9DUY", + title: "Kapitel 6.7 & Kapitel 7.1 - 1984", + duration: 136, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(76), + ), + TrackItem( + id: "0gXRizztpCE", + title: "Kapitel 7.2 - 1984", + duration: 153, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(77), + ), + TrackItem( + id: "U3gNQeexaFA", + title: "Kapitel 7.3 - 1984", + duration: 146, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(78), + ), + TrackItem( + id: "SDVj1LdZAWs", + title: "Kapitel 7.4 - 1984", + duration: 144, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(79), + ), + TrackItem( + id: "aStx8DVBL4w", + title: "Kapitel 7.5 - 1984", + duration: 150, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(80), + ), + TrackItem( + id: "39HPvtWzT5w", + title: "Kapitel 7.6 - 1984", + duration: 139, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(81), + ), + TrackItem( + id: "KDpAcnRvf98", + title: "Kapitel 7.7 - 1984", + duration: 136, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(82), + ), + TrackItem( + id: "Qg7M-RQatI8", + title: "Kapitel 7.8 - 1984", + duration: 143, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(83), + ), + TrackItem( + id: "V35JMnicqpE", + title: "Kapitel 7.9 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(84), + ), + TrackItem( + id: "fqVlv9bXo38", + title: "Kapitel 7.10 - 1984", + duration: 126, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(85), + ), + TrackItem( + id: "zcv2WC4ccCM", + title: "Kapitel 7.11 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(86), + ), + TrackItem( + id: "Em3S3CXYgsc", + title: "Kapitel 7.12 - 1984", + duration: 147, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(87), + ), + TrackItem( + id: "Pru_NJ16FX8", + title: "Kapitel 7.13 - 1984", + duration: 139, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(88), + ), + TrackItem( + id: "qePq7ltD6j4", + title: "Kapitel 7.15 & Kapitel 8.1 - 1984", + duration: 138, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(90), + ), + TrackItem( + id: "oBiS9b_v4wM", + title: "Kapitel 8.2 - 1984", + duration: 138, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(91), + ), + TrackItem( + id: "g2_3XksRrek", + title: "Kapitel 8.3 - 1984", + duration: 167, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(92), + ), + TrackItem( + id: "-eW-lGQghx8", + title: "Kapitel 8.4 - 1984", + duration: 131, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(93), + ), + TrackItem( + id: "adRnRqIr19Q", + title: "Kapitel 8.5 - 1984", + duration: 155, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(94), + ), + TrackItem( + id: "C1fvUpxJ8G0", + title: "Kapitel 8.6 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(95), + ), + TrackItem( + id: "MgkJ7uW13hM", + title: "Kapitel 8.7 - 1984", + duration: 129, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(96), + ), + TrackItem( + id: "pB22pN3oudY", + title: "Kapitel 8.8 - 1984", + duration: 137, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(97), + ), + TrackItem( + id: "d4JvNP7oR4g", + title: "Kapitel 8.9 - 1984", + duration: 152, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(98), + ), + TrackItem( + id: "FfUZhLb3L1A", + title: "Kapitel 8.10 - 1984", + duration: 152, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(99), + ), + TrackItem( + id: "pGdz8B_V9vs", + title: "Kapitel 8.11 - 1984", + duration: 160, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(100), + ), + TrackItem( + id: "wWzLLDr7VZY", + title: "Kapitel 8.12 - 1984", + duration: 140, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(101), + ), + TrackItem( + id: "sjwsqR7A-nI", + title: "Kapitel 8.13 - 1984", + duration: 137, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(102), + ), + TrackItem( + id: "ZBxtouT9Rpo", + title: "Kapitel 8.14 - 1984", + duration: 131, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(103), + ), + TrackItem( + id: "Ym_pEJYSd1Y", + title: "Kapitel 8.15 - 1984", + duration: 140, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(104), + ), + TrackItem( + id: "48rzTOM0u5g", + title: "Kapitel 8.16 - 1984", + duration: 141, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(105), + ), + TrackItem( + id: "KGN_cz6acJg", + title: "Kapitel 8.17 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(106), + ), + TrackItem( + id: "JPYOtU69FBI", + title: "Kapitel 8.18 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(107), + ), + TrackItem( + id: "UKJsludf1ME", + title: "Kapitel 8.19 - 1984", + duration: 142, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(108), + ), + TrackItem( + id: "aO0GCv90tok", + title: "Kapitel 8.20 - 1984", + duration: 136, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(109), + ), + TrackItem( + id: "yqLiNPBAIF4", + title: "Kapitel 8.21 - 1984", + duration: 135, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(110), + ), + TrackItem( + id: "Wm71AIJ08ss", + title: "Kapitel 8.22 - 1984", + duration: 127, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(111), + ), + TrackItem( + id: "LxSyUI2fjzM", + title: "Kapitel 8.23 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(112), + ), + TrackItem( + id: "4SVHRTay_PU", + title: "Kapitel 8.24 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(113), + ), + TrackItem( + id: "zhrqkGwyk4o", + title: "Kapitel 8.25 - 1984", + duration: 133, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(114), + ), + TrackItem( + id: "2YuvSWutjbY", + title: "Kapitel 8.26 & Kapitel 9.1 - 1984", + duration: 137, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(115), + ), + TrackItem( + id: "QT-BvFEO3ho", + title: "Kapitel 9.2 - 1984", + duration: 154, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(116), + ), + TrackItem( + id: "27rrlVQ7D4M", + title: "Kapitel 9.3 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(117), + ), + TrackItem( + id: "7m0EEXEBRo4", + title: "Kapitel 9.4 - 1984", + duration: 126, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(118), + ), + TrackItem( + id: "34H2shrx38w", + title: "Kapitel 9.5 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(119), + ), + TrackItem( + id: "yCuI-ii6dLA", + title: "Kapitel 9.6 - 1984", + duration: 136, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(120), + ), + TrackItem( + id: "E6Uzcr7zwoQ", + title: "Kapitel 9.7 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(121), + ), + TrackItem( + id: "gpL45b1fugI", + title: "Kapitel 9.8 - 1984", + duration: 142, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(122), + ), + TrackItem( + id: "ZHGQcDZ2lDo", + title: "Kapitel 9.9 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(123), + ), + TrackItem( + id: "EkVfn3H1YNw", + title: "Kapitel 9.10 - 1984", + duration: 131, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(124), + ), + TrackItem( + id: "iqh3t9ScmdM", + title: "Kapitel 9.11 - 1984", + duration: 138, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(125), + ), + TrackItem( + id: "lfdocX0dHjo", + title: "Kapitel 9.12 - 1984", + duration: 151, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(126), + ), + TrackItem( + id: "LBz5HWuwICc", + title: "Kapitel 9.13 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(127), + ), + TrackItem( + id: "DLiAozDSkn4", + title: "Kapitel 9.14 & Kapitel 10.1 - 1984", + duration: 151, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(128), + ), + TrackItem( + id: "1oAe6NOWODM", + title: "Kapitel 10.2 - 1984", + duration: 134, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(129), + ), + TrackItem( + id: "CpEo9pBL9cw", + title: "Kapitel 10.3 - 1984", + duration: 127, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(130), + ), + TrackItem( + id: "DioQU4tkLZQ", + title: "Kapitel 10.4 - 1984", + duration: 138, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(131), + ), + TrackItem( + id: "aShFQKy3Z8M", + title: "Kapitel 10.5 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(132), + ), + TrackItem( + id: "RgZACT1rJ4A", + title: "Kapitel 10.6 - 1984", + duration: 140, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(133), + ), + TrackItem( + id: "Vqg-K1lFtf4", + title: "Kapitel 10.7 - 1984", + duration: 135, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(134), + ), + TrackItem( + id: "FgzKDQ-KvkQ", + title: "Kapitel 10.8 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(135), + ), + TrackItem( + id: "q6qGmT7z_mk", + title: "Kapitel 10.9 - 1984", + duration: 136, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(136), + ), + TrackItem( + id: "BSEUTCp4JzQ", + title: "Kapitel 10.10 - 1984", + duration: 131, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(137), + ), + TrackItem( + id: "GorIwpkX6bk", + title: "Kapitel 10.11 - 1984", + duration: 142, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(138), + ), + TrackItem( + id: "NYiNrt7VMzA", + title: "Kapitel 10.12 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(139), + ), + TrackItem( + id: "9pPalZZsIlQ", + title: "Kapitel 10.13 & Kapitel 11.1 - 1984", + duration: 126, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(140), + ), + TrackItem( + id: "GUPplhf2Wts", + title: "Kapitel 11.2 - 1984", + duration: 136, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(141), + ), + TrackItem( + id: "sUc4pA09dMA", + title: "Kapitel 11.3 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(142), + ), + TrackItem( + id: "ykieQtMZjgI", + title: "Kapitel 11.4 - 1984", + duration: 149, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(143), + ), + TrackItem( + id: "P_aAJjwygaA", + title: "Kapitel 11.5 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(144), + ), + TrackItem( + id: "d2QMPdcl7YM", + title: "Kapitel 11.6 - 1984", + duration: 125, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(145), + ), + TrackItem( + id: "V0gQO8dH6b4", + title: "Kapitel 11.7 - 1984", + duration: 140, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(146), + ), + TrackItem( + id: "cgOzxcg52v8", + title: "Kapitel 11.8 - 1984", + duration: 126, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(147), + ), + TrackItem( + id: "rjTEyuRGrYY", + title: "Kapitel 11.9 - 1984", + duration: 137, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(148), + ), + TrackItem( + id: "6DwpgjU82ww", + title: "Kapitel 11.10 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(149), + ), + TrackItem( + id: "dwk9eQZse6E", + title: "Kapitel 11.11 - 1984", + duration: 148, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(150), + ), + TrackItem( + id: "zmM1aeBv_mo", + title: "Kapitel 11.12 & Kapitel 12.1 - 1984", + duration: 126, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(151), + ), + TrackItem( + id: "QL1HMAEp21k", + title: "Kapitel 12.2 - 1984", + duration: 134, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(152), + ), + TrackItem( + id: "rtzG_mr5q-c", + title: "Kapitel 12.3 - 1984", + duration: 133, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(153), + ), + TrackItem( + id: "Eg2WlrlzO8Y", + title: "Kapitel 12.4 - 1984", + duration: 134, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(154), + ), + TrackItem( + id: "QMXkBa6exqA", + title: "Kapitel 12.5 - 1984", + duration: 133, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(155), + ), + TrackItem( + id: "n0dStgWvR08", + title: "Kapitel 12.6 - 1984", + duration: 161, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(156), + ), + TrackItem( + id: "FxslNrm_3jU", + title: "Kapitel 12.7 - 1984", + duration: 127, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(157), + ), + TrackItem( + id: "rlJXZLKXjyM", + title: "Kapitel 12.8 - 1984", + duration: 131, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(158), + ), + TrackItem( + id: "RQ6lvrVddyk", + title: "Kapitel 12.9 - 1984", + duration: 136, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(159), + ), + TrackItem( + id: "LCLBV5T8s5k", + title: "Kapitel 12.10 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(160), + ), + TrackItem( + id: "bNigSN7siMU", + title: "Kapitel 12.11 - 1984", + duration: 139, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(161), + ), + TrackItem( + id: "KFBydJkaTD4", + title: "Kapitel 12.12 & Kapitel 13.1 - 1984", + duration: 133, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(162), + ), + TrackItem( + id: "1PUlvwOASBw", + title: "Kapitel 13.2 - 1984", + duration: 147, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(163), + ), + TrackItem( + id: "pyvOIiyn5JY", + title: "Kapitel 13.3 - 1984", + duration: 161, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(164), + ), + TrackItem( + id: "eQKlU7pzFRw", + title: "Kapitel 13.4 - 1984", + duration: 147, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(165), + ), + TrackItem( + id: "pbROCT8IwDs", + title: "Kapitel 13.5 - 1984", + duration: 149, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(166), + ), + TrackItem( + id: "6eklRsup2Cg", + title: "Kapitel 13.6 - 1984", + duration: 139, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(167), + ), + TrackItem( + id: "Sx047sHMOV8", + title: "Kapitel 13.7 - 1984", + duration: 161, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(168), + ), + TrackItem( + id: "uIhFD_Y1RM8", + title: "Kapitel 13.8 - 1984", + duration: 142, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(169), + ), + TrackItem( + id: "OdiW4u-MJWk", + title: "Kapitel 13.9 - 1984", + duration: 126, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(170), + ), + TrackItem( + id: "IQQ4H5wKhqw", + title: "Kapitel 13.10 - 1984", + duration: 135, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(171), + ), + TrackItem( + id: "heJoxdCFgXE", + title: "Kapitel 13.11 & Kapitel 14.1 - 1984", + duration: 135, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(172), + ), + TrackItem( + id: "k7Vhuh9N7hg", + title: "Kapitel 14.2 - 1984", + duration: 129, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(173), + ), + TrackItem( + id: "0Aeaczuom_0", + title: "Kapitel 14.3 - 1984", + duration: 126, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(174), + ), + TrackItem( + id: "5sJd3YkpnNg", + title: "Kapitel 14.4 & Kapitel 15.1 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(175), + ), + TrackItem( + id: "K3xED9BLZ0g", + title: "Kapitel 15.2 - 1984", + duration: 161, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(176), + ), + TrackItem( + id: "wxBk25H3Zw4", + title: "Kapitel 15.3 - 1984", + duration: 154, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(177), + ), + TrackItem( + id: "Gxdv90qTiBA", + title: "Kapitel 15.4 - 1984", + duration: 134, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(178), + ), + TrackItem( + id: "ewUX4G705t0", + title: "Kapitel 15.5 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(179), + ), + TrackItem( + id: "fIAs-O1seGs", + title: "Kapitel 15.6 - 1984", + duration: 134, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(180), + ), + TrackItem( + id: "CLmbiozyb3g", + title: "Kapitel 15.7 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(181), + ), + TrackItem( + id: "cZqX4kRFrls", + title: "Kapitel 15.8 - 1984", + duration: 126, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(182), + ), + TrackItem( + id: "GzKlXy_klc0", + title: "Kapitel 15.9 - 1984", + duration: 130, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(183), + ), + TrackItem( + id: "N9TK0-c90NQ", + title: "Kapitel 15.10 & Kapitel 16.1 - 1984", + duration: 145, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(184), + ), + TrackItem( + id: "AdmAEn7yJBg", + title: "Kapitel 16.2 - 1984", + duration: 136, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(185), + ), + TrackItem( + id: "goV3qAE4nDo", + title: "Kapitel 16.3 - 1984", + duration: 143, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(186), + ), + TrackItem( + id: "HpX-bfM-z8c", + title: "Kapitel 16.4 - 1984", + duration: 138, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(187), + ), + TrackItem( + id: "GT5EGpOqAeM", + title: "Kapitel 16.5 - 1984", + duration: 143, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(188), + ), + TrackItem( + id: "M8cQ5zntKks", + title: "Kapitel 16.6 - 1984", + duration: 135, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(189), + ), + TrackItem( + id: "EDdwfxA88RQ", + title: "Kapitel 16.7 - 1984", + duration: 127, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(190), + ), + TrackItem( + id: "deQx4nzAHvI", + title: "Kapitel 16.8 - 1984", + duration: 144, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(191), + ), + TrackItem( + id: "-TYmP5BWkZA", + title: "Kapitel 16.9 - 1984", + duration: 134, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(192), + ), + TrackItem( + id: "NKWffyEyvvQ", + title: "Kapitel 16.10 - 1984", + duration: 126, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(193), + ), + TrackItem( + id: "5SQgoPx88Xk", + title: "Kapitel 16.11 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(194), + ), + TrackItem( + id: "8MmcjOWCXcI", + title: "Kapitel 16.12 - 1984", + duration: 129, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(195), + ), + TrackItem( + id: "Cs8eNJJsOwg", + title: "Kapitel 16.13 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(196), + ), + TrackItem( + id: "u9ulcct7UW8", + title: "Kapitel 16.14 & Kapitel 17.1 - 1984", + duration: 193, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(197), + ), + TrackItem( + id: "_Q3Ybt6A0A4", + title: "Kapitel 17.2 - 1984", + duration: 129, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(198), + ), + TrackItem( + id: "OwLevpAaw50", + title: "Kapitel 17.3 - 1984", + duration: 157, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(199), + ), + TrackItem( + id: "wKg1h1i_pLk", + title: "Kapitel 17.4 - 1984", + duration: 132, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(200), + ), + TrackItem( + id: "svY6h_e3LYI", + title: "Kapitel 17.5 - 1984", + duration: 128, + cover: [], + artists: [], + artists_txt: Some("George Orwell & Dirk Jacobs"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(201), + ), + ], + variants: [], +) diff --git a/tests/snapshots/youtube__music_album_ep.snap b/tests/snapshots/youtube__music_album_ep.snap new file mode 100644 index 0000000..2bb50ec --- /dev/null +++ b/tests/snapshots/youtube__music_album_ep.snap @@ -0,0 +1,108 @@ +--- +source: tests/youtube.rs +expression: album +--- +MusicAlbum( + id: "MPREb_u1I69lSAe5v", + playlist_id: Some("OLAK5uy_lGP_zv0vJDUlecQDzugUJmjcF7pvyVNyY"), + name: "Waldbrand", + cover: "[cover]", + artists: [ + ChannelId( + id: "UCpJyCbFbdTrx0M90HCNBHFQ", + name: "Madeline Juno", + ), + ], + artists_txt: "Madeline Juno", + album_type: Ep, + year: Some(2016), + by_va: false, + tracks: [ + TrackItem( + id: "aGd3VKSOTxY", + title: "Ich wache auf", + duration: 221, + cover: [], + artists: [ + ChannelId( + id: "UCpJyCbFbdTrx0M90HCNBHFQ", + name: "Madeline Juno", + ), + ], + artists_txt: Some("Madeline Juno"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(1), + ), + TrackItem( + id: "lhPOMUjV4rE", + title: "Waldbrand", + duration: 208, + cover: [], + artists: [ + ChannelId( + id: "UCpJyCbFbdTrx0M90HCNBHFQ", + name: "Madeline Juno", + ), + ], + artists_txt: Some("Madeline Juno"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(2), + ), + TrackItem( + id: "Bu26uFtpt58", + title: "Verlernt", + duration: 223, + cover: [], + artists: [ + ChannelId( + id: "UCpJyCbFbdTrx0M90HCNBHFQ", + name: "Madeline Juno", + ), + ], + artists_txt: Some("Madeline Juno"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(3), + ), + TrackItem( + id: "RgwNqqiVqdY", + title: "In Farbe", + duration: 221, + cover: [], + artists: [ + ChannelId( + id: "UCpJyCbFbdTrx0M90HCNBHFQ", + name: "Madeline Juno", + ), + ], + artists_txt: Some("Madeline Juno"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(4), + ), + TrackItem( + id: "2TuOh30XbCI", + title: "Stadt im Hinterland", + duration: 197, + cover: [], + artists: [ + ChannelId( + id: "UCpJyCbFbdTrx0M90HCNBHFQ", + name: "Madeline Juno", + ), + ], + artists_txt: Some("Madeline Juno"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(5), + ), + ], + variants: [], +) diff --git a/tests/snapshots/youtube__music_album_one_artist.snap b/tests/snapshots/youtube__music_album_one_artist.snap new file mode 100644 index 0000000..3bd35ea --- /dev/null +++ b/tests/snapshots/youtube__music_album_one_artist.snap @@ -0,0 +1,355 @@ +--- +source: tests/youtube.rs +expression: album +--- +MusicAlbum( + id: "MPREb_nlBWQROfvjo", + playlist_id: Some("OLAK5uy_myZkBX2d2TzcrlQhIwLy3hCj2MkAMaPR4"), + name: "Märchen enden gut", + cover: "[cover]", + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: "Oonagh", + album_type: Album, + year: Some(2016), + by_va: false, + tracks: [ + TrackItem( + id: "g0iRiJ_ck48", + title: "Aulë und Yavanna", + duration: 216, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(1), + ), + TrackItem( + id: "rREEBXp0y9s", + title: "Numenor", + duration: 224, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(2), + ), + TrackItem( + id: "zvU5Y8Q19hU", + title: "Das Mädchen und die Liebe (feat. Santiano)", + duration: 176, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(3), + ), + TrackItem( + id: "ARKLrzzTQA0", + title: "Niënna", + duration: 215, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(4), + ), + TrackItem( + id: "tstLgN8A_Ng", + title: "Der fahle Mond", + duration: 268, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(5), + ), + TrackItem( + id: "k2DjgQOY3Ts", + title: "Weise den Weg", + duration: 202, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(6), + ), + TrackItem( + id: "azHwhecxEsI", + title: "Zeit der Sommernächte", + duration: 185, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(7), + ), + TrackItem( + id: "_FcsdYIQ2co", + title: "Märchen enden gut", + duration: 226, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(8), + ), + TrackItem( + id: "27bOWEbshyE", + title: "Das Mädchen und der Tod", + duration: 207, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(9), + ), + TrackItem( + id: "riD_3oZwt8w", + title: "Wir sehn uns wieder", + duration: 211, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(10), + ), + TrackItem( + id: "8GNvjF3no9s", + title: "Tanz mit mir", + duration: 179, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(11), + ), + TrackItem( + id: "YHMFzf1uN2U", + title: "Nachtigall", + duration: 218, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(12), + ), + TrackItem( + id: "jvV-z5F3oAo", + title: "Gayatri Mantra", + duration: 277, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(13), + ), + TrackItem( + id: "u8_9cxlrh8k", + title: "Sing mir deine Lieder", + duration: 204, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(14), + ), + TrackItem( + id: "gSvKcvM1Wk0", + title: "Laurië lantar", + duration: 202, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(15), + ), + TrackItem( + id: "wQHgKRJ0pDQ", + title: "Wächter vor dem Tor", + duration: 222, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(16), + ), + TrackItem( + id: "Ckz5i6-hzf0", + title: "Stroh zu Gold", + duration: 177, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(17), + ), + TrackItem( + id: "y5zuUgyFqrc", + title: "Sonnenwendnacht", + duration: 220, + cover: [], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: Some("Oonagh"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(18), + ), + ], + variants: [ + AlbumItem( + id: "MPREb_jk6Msw8izou", + name: "Märchen enden gut (Nyáre Ranta (Märchenedition))", + cover: [ + Thumbnail( + url: "https://lh3.googleusercontent.com/BKgnW_-hapCHk599AtRfTYZGdXVIo0C4bJp1Bh7qUpGK7fNAXGW8Bhv2x-ukeFM8cuxKbGqqGaTo8fZASA=w226-h226-l90-rj", + width: 226, + height: 226, + ), + Thumbnail( + url: "https://lh3.googleusercontent.com/BKgnW_-hapCHk599AtRfTYZGdXVIo0C4bJp1Bh7qUpGK7fNAXGW8Bhv2x-ukeFM8cuxKbGqqGaTo8fZASA=w544-h544-l90-rj", + width: 544, + height: 544, + ), + ], + artists: [ + ChannelId( + id: "UC_vmjW5e1xEHhYjY2a0kK1A", + name: "Oonagh", + ), + ], + artists_txt: "Oonagh", + album_type: Album, + year: None, + ), + ], +) diff --git a/tests/snapshots/youtube__music_album_show.snap b/tests/snapshots/youtube__music_album_show.snap new file mode 100644 index 0000000..ed2a5c5 --- /dev/null +++ b/tests/snapshots/youtube__music_album_show.snap @@ -0,0 +1,261 @@ +--- +source: tests/youtube.rs +expression: album +--- +MusicAlbum( + id: "MPREb_cwzk8EUwypZ", + playlist_id: Some("OLAK5uy_kODvYZ5CEpYdtd4VPsmg0eRTlpazG0dvA"), + name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)", + cover: "[cover]", + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: "Kingdom Force", + album_type: Album, + year: Some(2022), + by_va: false, + tracks: [ + TrackItem( + id: "lSbKz5LWvKE", + title: "Achtung, Waldbrand - Teil 1", + duration: 229, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(1), + ), + TrackItem( + id: "fdO6gu4qjRw", + title: "Achtung, Waldbrand - Teil 2", + duration: 235, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(2), + ), + TrackItem( + id: "muCxstXirvY", + title: "Achtung, Waldbrand - Teil 3", + duration: 197, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(3), + ), + TrackItem( + id: "aG1N0vo__Ng", + title: "Eiszeit - Teil 1", + duration: 186, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(4), + ), + TrackItem( + id: "roHhLNYS9yo", + title: "Eiszeit - Teil 2", + duration: 188, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(5), + ), + TrackItem( + id: "nJ49NuLvcAw", + title: "Eiszeit - Teil 3", + duration: 205, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(6), + ), + TrackItem( + id: "Me119D570h0", + title: "Eiszeit - Teil 4", + duration: 219, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(7), + ), + TrackItem( + id: "YXnRLK-qKG8", + title: "Im Sinkloch - Teil 1", + duration: 240, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(8), + ), + TrackItem( + id: "A61wz1jz9X0", + title: "Im Sinkloch - Teil 2", + duration: 239, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(9), + ), + TrackItem( + id: "u_S08EJOTUg", + title: "Im Sinkloch - Teil 3", + duration: 197, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(10), + ), + TrackItem( + id: "0qwYJihV1EU", + title: "Vorsicht, heiß - Teil 1", + duration: 201, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(11), + ), + TrackItem( + id: "zjhoyTnEzuQ", + title: "Vorsicht, heiß - Teil 2", + duration: 187, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(12), + ), + TrackItem( + id: "oDjDd0UBzAY", + title: "Vorsicht, heiß - Teil 3", + duration: 183, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(13), + ), + TrackItem( + id: "_3-WVmqgi-Q", + title: "Vorsicht, heiß - Teil 4", + duration: 193, + cover: [], + artists: [ + ChannelId( + id: "UCNoyEM0e2A7WlsBmP2w3avg", + name: "Kingdom Force", + ), + ], + artists_txt: Some("Kingdom Force"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(14), + ), + ], + variants: [], +) diff --git a/tests/snapshots/youtube__music_album_single.snap b/tests/snapshots/youtube__music_album_single.snap new file mode 100644 index 0000000..fb88438 --- /dev/null +++ b/tests/snapshots/youtube__music_album_single.snap @@ -0,0 +1,48 @@ +--- +source: tests/youtube.rs +expression: album +--- +MusicAlbum( + id: "MPREb_bHfHGoy7vuv", + playlist_id: Some("OLAK5uy_kdSWBZ-9AZDkYkuy0QCc3p0KO9DEHVNH0"), + name: "Der Himmel reißt auf", + cover: "[cover]", + artists: [ + ChannelId( + id: "UCXGYZ-OhdOpPBamHX3K9YRg", + name: "Joel Brandenstein", + ), + ChannelId( + id: "UCFTcSVPYRWlDoHisR-ZKwgw", + name: "Vanessa Mai", + ), + ], + artists_txt: "Joel Brandenstein & Vanessa Mai", + album_type: Single, + year: Some(2020), + by_va: false, + tracks: [ + TrackItem( + id: "XX0epju-YvY", + title: "Der Himmel reißt auf", + duration: 183, + cover: [], + artists: [ + ChannelId( + id: "UCXGYZ-OhdOpPBamHX3K9YRg", + name: "Joel Brandenstein", + ), + ChannelId( + id: "UCFTcSVPYRWlDoHisR-ZKwgw", + name: "Vanessa Mai", + ), + ], + artists_txt: Some("Joel Brandenstein & Vanessa Mai"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(1), + ), + ], + variants: [], +) diff --git a/tests/snapshots/youtube__music_album_various_artists.snap b/tests/snapshots/youtube__music_album_various_artists.snap new file mode 100644 index 0000000..26d7572 --- /dev/null +++ b/tests/snapshots/youtube__music_album_various_artists.snap @@ -0,0 +1,95 @@ +--- +source: tests/youtube.rs +expression: album +--- +MusicAlbum( + id: "MPREb_8QkDeEIawvX", + playlist_id: Some("OLAK5uy_mEX9ljZeeEWgTM1xLL1isyiGaWXoPyoOk"), + name: "<Queendom2> FINAL", + cover: "[cover]", + artists: [], + artists_txt: "Various Artists", + album_type: Single, + year: Some(2022), + by_va: true, + tracks: [ + TrackItem( + id: "8IqLxg0GqXc", + title: "Waka Boom (My Way) (feat. Lee Young Ji)", + duration: 274, + cover: [], + artists: [], + artists_txt: Some("HYOLYN"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(1), + ), + TrackItem( + id: "9WYpLYAEub0", + title: "AURA", + duration: 216, + cover: [], + artists: [], + artists_txt: Some("WJSN"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(2), + ), + TrackItem( + id: "R48tE237bW4", + title: "THE GIRLS (Can’t turn me down)", + duration: 239, + cover: [], + artists: [ + ChannelId( + id: "UCAKvDuIX3m1AUdPpDSqV_3w", + name: "Kep1er", + ), + ], + artists_txt: Some("Kep1er"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(3), + ), + TrackItem( + id: "-UzsoR6z-vg", + title: "Red Sun!", + duration: 254, + cover: [], + artists: [], + artists_txt: Some("VIVIZ"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(4), + ), + TrackItem( + id: "kbNVyn8Ex28", + title: "POSE", + duration: 187, + cover: [], + artists: [], + artists_txt: Some("LOONA"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(5), + ), + TrackItem( + id: "NJrQZUzWP5Y", + title: "Whistle", + duration: 224, + cover: [], + artists: [], + artists_txt: Some("Brave Girls"), + album: None, + view_count: None, + is_video: true, + track_nr: Some(6), + ), + ], + variants: [], +) diff --git a/tests/youtube.rs b/tests/youtube.rs index cd58b5e..e132a14 100644 --- a/tests/youtube.rs +++ b/tests/youtube.rs @@ -1,14 +1,16 @@ use std::collections::HashSet; +use std::fmt::Display; use rstest::rstest; use time::macros::date; use time::OffsetDateTime; -use rustypipe::client::{ClientType, RustyPipe}; +use rustypipe::client::{ClientType, RustyPipe, RustyPipeQuery}; use rustypipe::error::{Error, ExtractionError}; use rustypipe::model::richtext::ToPlaintext; use rustypipe::model::{ - AudioCodec, AudioFormat, Channel, UrlTarget, Verification, VideoCodec, VideoFormat, YouTubeItem, + AlbumType, AudioCodec, AudioFormat, Channel, FromYtItem, MusicEntityType, Paginator, UrlTarget, + Verification, VideoCodec, VideoFormat, YouTubeItem, }; use rustypipe::param::search_filter::{self, SearchFilter}; @@ -45,7 +47,7 @@ async fn get_player_from_client(#[case] client_type: ClientType) { assert!(!player_data.details.thumbnail.is_empty()); assert_eq!(player_data.details.channel.id, "UC_aEa8K-EOJ3D6gOs7HcyNg"); assert_eq!(player_data.details.channel.name, "NoCopyrightSounds"); - assert!(player_data.details.view_count > 146_818_808); + assert_gte(player_data.details.view_count, 146_818_808, "view count"); assert_eq!(player_data.details.keywords[0], "spektrem"); assert_eq!(player_data.details.is_live_content, false); @@ -76,7 +78,7 @@ async fn get_player_from_client(#[case] client_type: ClientType) { assert_approx(audio.bitrate as f64, 130685.0); assert_approx(audio.average_bitrate as f64, 129496.0); - assert_eq!(audio.size, 4193863); + assert_approx(audio.size as f64, 4193863.0); assert_eq!(audio.mime, "audio/mp4; codecs=\"mp4a.40.2\""); assert_eq!(audio.format, AudioFormat::M4a); assert_eq!(audio.codec, AudioCodec::Mp4a); @@ -207,12 +209,7 @@ async fn get_player( assert_eq!(details.length, length); assert_eq!(details.channel.id, channel_id); assert_eq!(details.channel.name, channel_name); - assert!( - details.view_count > views, - "expected > {} views, got {}", - views, - details.view_count - ); + assert_gte(details.view_count, views, "views"); assert_eq!(details.is_live, is_live); assert_eq!(details.is_live_content, is_live_content); @@ -255,7 +252,7 @@ async fn get_player( _ => {} }; - assert!(player_data.expires_in_seconds > 10000); + assert_gte(player_data.expires_in_seconds, 10_000, "expiry time"); } #[rstest] @@ -425,22 +422,13 @@ async fn get_video_details() { assert_eq!(details.channel.name, "SMTOWN"); assert!(!details.channel.avatar.is_empty(), "no channel avatars"); assert_eq!(details.channel.verification, Verification::Verified); - assert!( - details.channel.subscriber_count.unwrap() > 30000000, - "expected >30M subs, got {}", - details.channel.subscriber_count.unwrap() - ); - - assert!( - details.view_count > 232000000, - "expected > 232M views, got {}", - details.view_count - ); - assert!( - details.like_count.unwrap() > 4000000, - "expected > 4M likes, got {}", - details.like_count.unwrap() + assert_gte( + details.channel.subscriber_count.unwrap(), + 30_000_000, + "subscribers", ); + assert_gte(details.view_count, 232_000_000, "views"); + assert_gte(details.like_count.unwrap(), 4_000_000, "likes"); let date = details.publish_date.unwrap(); assert_eq!(date.date(), date!(2020 - 11 - 17)); @@ -448,14 +436,9 @@ async fn get_video_details() { assert!(!details.is_live); assert!(!details.is_ccommons); - assert!(!details.recommended.items.is_empty()); - assert!(!details.recommended.is_exhausted()); + assert_next(details.recommended, &rp.query(), 10, 2).await; - assert!( - details.top_comments.count.unwrap() > 700000, - "expected > 700K comments, got {}", - details.top_comments.count.unwrap() - ); + assert_gte(details.top_comments.count.unwrap(), 700_000, "comments"); assert!(!details.top_comments.is_exhausted()); assert!(!details.latest_comments.is_exhausted()); } @@ -476,22 +459,13 @@ async fn get_video_details_music() { assert_eq!(details.channel.name, "Sentamusic"); assert!(!details.channel.avatar.is_empty(), "no channel avatars"); assert_eq!(details.channel.verification, Verification::Artist); - assert!( - details.channel.subscriber_count.unwrap() > 33000, - "expected >33K subs, got {}", - details.channel.subscriber_count.unwrap() - ); - - assert!( - details.view_count > 20309, - "expected > 20309 views, got {}", - details.view_count - ); - assert!( - details.like_count.unwrap() > 145, - "expected > 145 likes, got {}", - details.like_count.unwrap() + assert_gte( + details.channel.subscriber_count.unwrap(), + 33_000, + "subscribers", ); + assert_gte(details.view_count, 20_309, "views"); + assert_gte(details.like_count.unwrap(), 145, "likes"); let date = details.publish_date.unwrap(); assert_eq!(date.date(), date!(2020 - 8 - 6)); @@ -499,8 +473,7 @@ async fn get_video_details_music() { assert!(!details.is_live); assert!(!details.is_ccommons); - assert!(!details.recommended.items.is_empty()); - assert!(!details.recommended.is_exhausted()); + assert_next(details.recommended, &rp.query(), 10, 2).await; // Update(01.11.2022): comments are sometimes enabled /* @@ -534,22 +507,13 @@ async fn get_video_details_ccommons() { assert_eq!(details.channel.name, "media.ccc.de"); assert!(!details.channel.avatar.is_empty(), "no channel avatars"); assert_eq!(details.channel.verification, Verification::None); - assert!( - details.channel.subscriber_count.unwrap() > 170000, - "expected >170K subs, got {}", - details.channel.subscriber_count.unwrap() - ); - - assert!( - details.view_count > 2517358, - "expected > 2517358 views, got {}", - details.view_count - ); - assert!( - details.like_count.unwrap() > 52330, - "expected > 52330 likes, got {}", - details.like_count.unwrap() + assert_gte( + details.channel.subscriber_count.unwrap(), + 170_000, + "subscribers", ); + assert_gte(details.view_count, 2_517_358, "views"); + assert_gte(details.like_count.unwrap(), 52_330, "likes"); let date = details.publish_date.unwrap(); assert_eq!(date.date(), date!(2019 - 12 - 29)); @@ -557,14 +521,9 @@ async fn get_video_details_ccommons() { assert!(!details.is_live); assert!(details.is_ccommons); - assert!(!details.recommended.items.is_empty()); - assert!(!details.recommended.is_exhausted()); + assert_next(details.recommended, &rp.query(), 10, 2).await; - assert!( - details.top_comments.count.unwrap() > 2199, - "expected > 2199 comments, got {}", - details.top_comments.count.unwrap() - ); + assert_gte(details.top_comments.count.unwrap(), 2199, "comments"); assert!(!details.top_comments.is_exhausted()); assert!(!details.latest_comments.is_exhausted()); } @@ -589,22 +548,13 @@ async fn get_video_details_chapters() { assert_eq!(details.channel.name, "Linus Tech Tips"); assert!(!details.channel.avatar.is_empty(), "no channel avatars"); assert_eq!(details.channel.verification, Verification::Verified); - assert!( - details.channel.subscriber_count.unwrap() > 14700000, - "expected >14.7M subs, got {}", - details.channel.subscriber_count.unwrap() - ); - - assert!( - details.view_count > 1157262, - "expected > 1157262 views, got {}", - details.view_count - ); - assert!( - details.like_count.unwrap() > 54670, - "expected > 54670 likes, got {}", - details.like_count.unwrap() + assert_gte( + details.channel.subscriber_count.unwrap(), + 14_700_000, + "subscribers", ); + assert_gte(details.view_count, 1_157_262, "views"); + assert_gte(details.like_count.unwrap(), 54_670, "likes"); let date = details.publish_date.unwrap(); assert_eq!(date.date(), date!(2022 - 9 - 15)); @@ -695,14 +645,9 @@ async fn get_video_details_chapters() { "###); } - assert!(!details.recommended.items.is_empty()); - assert!(!details.recommended.is_exhausted()); + assert_next(details.recommended, &rp.query(), 10, 2).await; - assert!( - details.top_comments.count.unwrap() > 3199, - "expected > 3199 comments, got {}", - details.top_comments.count.unwrap() - ); + assert_gte(details.top_comments.count.unwrap(), 3200, "comments"); assert!(!details.top_comments.is_exhausted()); assert!(!details.latest_comments.is_exhausted()); } @@ -730,22 +675,13 @@ async fn get_video_details_live() { assert_eq!(details.channel.name, "Space Videos"); assert!(!details.channel.avatar.is_empty(), "no channel avatars"); assert_eq!(details.channel.verification, Verification::Verified); - assert!( - details.channel.subscriber_count.unwrap() > 5500000, - "expected >5.5M subs, got {}", - details.channel.subscriber_count.unwrap() - ); - - assert!( - details.view_count > 10, - "expected > 10 views, got {}", - details.view_count - ); - assert!( - details.like_count.unwrap() > 872290, - "expected > 872290 likes, got {}", - details.like_count.unwrap() + assert_gte( + details.channel.subscriber_count.unwrap(), + 5_500_000, + "subscribers", ); + assert_gte(details.view_count, 10, "views"); + assert_gte(details.like_count.unwrap(), 872_290, "likes"); let date = details.publish_date.unwrap(); assert_eq!(date.date(), date!(2021 - 9 - 23)); @@ -753,8 +689,7 @@ async fn get_video_details_live() { assert!(details.is_live); assert!(!details.is_ccommons); - assert!(!details.recommended.items.is_empty()); - assert!(!details.recommended.is_exhausted()); + assert_next(details.recommended, &rp.query(), 10, 2).await; // No comments because livestream assert_eq!(details.top_comments.count, Some(0)); @@ -781,17 +716,12 @@ async fn get_video_details_agegate() { assert_eq!(details.channel.name, "PrinceOfFALLEN"); assert!(!details.channel.avatar.is_empty(), "no channel avatars"); assert_eq!(details.channel.verification, Verification::None); - assert!( - details.channel.subscriber_count.unwrap() > 1400, - "expected >1400 subs, got {}", - details.channel.subscriber_count.unwrap() - ); - - assert!( - details.view_count > 200, - "expected > 200 views, got {}", - details.view_count + assert_gte( + details.channel.subscriber_count.unwrap(), + 1400, + "subscribers", ); + assert_gte(details.view_count, 200, "views"); assert!(details.like_count.is_none(), "like count not hidden"); let date = details.publish_date.unwrap(); @@ -820,26 +750,6 @@ async fn get_video_details_not_found() { ) } -#[tokio::test] -async fn get_video_recommendations() { - let rp = RustyPipe::builder().strict().build(); - let details = rp.query().video_details("ZeerrnuLi5E").await.unwrap(); - let next_recommendations = details - .recommended - .next(&rp.query()) - .await - .unwrap() - .unwrap(); - // dbg!(&next_recommendations); - - assert!( - next_recommendations.items.len() > 10, - "expected > 10 next recommendations, got {}", - next_recommendations.items.len() - ); - assert!(!next_recommendations.is_exhausted()); -} - #[tokio::test] async fn get_video_comments() { let rp = RustyPipe::builder().strict().build(); @@ -851,21 +761,17 @@ async fn get_video_comments() { .await .unwrap() .unwrap(); - assert!( - top_comments.items.len() > 10, - "expected > 10 next comments, got {}", - top_comments.items.len() - ); + assert_gte(top_comments.items.len(), 10, "comments"); assert!(!top_comments.is_exhausted()); let n_comments = top_comments.count.unwrap(); + assert_gte(n_comments, 700_000, "comments"); + // Comment count should be exact after fetching first page assert!( - n_comments > 700000, - "expected > 700k comments, got {}", + n_comments % 1000 != 0, + "estimated comment count: {}", n_comments ); - // Comment count should be exact after fetching first page - assert!(n_comments % 1000 != 0); let latest_comments = details .latest_comments @@ -873,11 +779,7 @@ async fn get_video_comments() { .await .unwrap() .unwrap(); - assert!( - latest_comments.items.len() > 10, - "expected > 10 next comments, got {}", - latest_comments.items.len() - ); + assert_gte(latest_comments.items.len(), 10, "next comments"); assert!(!latest_comments.is_exhausted()); } @@ -906,11 +808,7 @@ async fn channel_videos() { assert!(age_days < 60, "latest video older than 60 days"); - let next = channel.content.next(&rp.query()).await.unwrap().unwrap(); - assert!( - !next.is_exhausted() && !next.items.is_empty(), - "no more videos" - ); + assert_next(channel.content, &rp.query(), 15, 2).await; } #[tokio::test] @@ -928,11 +826,7 @@ async fn channel_shorts() { // dbg!(&channel); assert_eq!(channel.id, "UCh8gHdtzO2tXd593_bjErWg"); assert_eq!(channel.name, "Doobydobap"); - assert!( - channel.subscriber_count.unwrap() > 2800000, - "expected >2.8M subscribers, got {}", - channel.subscriber_count.unwrap() - ); + assert_gte(channel.subscriber_count.unwrap(), 2_800_000, "subscribers"); assert!(!channel.avatar.is_empty(), "got no thumbnails"); assert_eq!(channel.verification, Verification::Verified); assert!(channel @@ -951,11 +845,7 @@ async fn channel_shorts() { "got no shorts" ); - let next = channel.content.next(&rp.query()).await.unwrap().unwrap(); - assert!( - !next.is_exhausted() && !next.items.is_empty(), - "no more shorts" - ); + assert_next(channel.content, &rp.query(), 15, 1).await; } #[tokio::test] @@ -978,8 +868,7 @@ async fn channel_livestreams() { "got no streams" ); - let next = channel.content.next(&rp.query()).await.unwrap().unwrap(); - assert!(!next.items.is_empty(), "no more streams"); + assert_next(channel.content, &rp.query(), 5, 1).await; } #[tokio::test] @@ -998,11 +887,7 @@ async fn channel_playlists() { "got no playlists" ); - let next = channel.content.next(&rp.query()).await.unwrap().unwrap(); - assert!( - !next.is_exhausted() && !next.items.is_empty(), - "no more playlists" - ); + assert_next(channel.content, &rp.query(), 15, 1).await; } #[tokio::test] @@ -1020,10 +905,10 @@ async fn channel_info() { let created = channel.content.create_date.unwrap(); assert_eq!(created, date!(2009 - 4 - 4)); - assert!( - channel.content.view_count.unwrap() > 186854340, - "exp >186M views, got {}", - channel.content.view_count.unwrap() + assert_gte( + channel.content.view_count.unwrap(), + 186854340, + "channel views", ); insta::assert_ron_snapshot!(channel.content.links, @r###" @@ -1048,11 +933,7 @@ async fn channel_info() { fn assert_channel_eevblog(channel: &Channel) { assert_eq!(channel.id, "UC2DjFE7Xf11URZqWBigcVOQ"); assert_eq!(channel.name, "EEVblog"); - assert!( - channel.subscriber_count.unwrap() > 880000, - "exp >880K subscribers, got {}", - channel.subscriber_count.unwrap() - ); + assert_gte(channel.subscriber_count.unwrap(), 880_000, "subscribers"); assert!(!channel.avatar.is_empty(), "got no thumbnails"); assert_eq!(channel.verification, Verification::Verified); assert_eq!(channel.description, "NO SCRIPT, NO FEAR, ALL OPINION\nAn off-the-cuff Video Blog about Electronics Engineering, for engineers, hobbyists, enthusiasts, hackers and Makers\nHosted by Dave Jones from Sydney Australia\n\nDONATIONS:\nBitcoin: 3KqyH1U3qrMPnkLufM2oHDU7YB4zVZeFyZ\nEthereum: 0x99ccc4d2654ba40744a1f678d9868ecb15e91206\nPayPal: david@alternatezone.com\n\nPatreon: https://www.patreon.com/eevblog\n\nEEVblog2: http://www.youtube.com/EEVblog2\nEEVdiscover: https://www.youtube.com/channel/UCkGvUEt8iQLmq3aJIMjT2qQ\n\nEMAIL:\nAdvertising/Commercial: eevblog+business@gmail.com\nFan mail: eevblog+fan@gmail.com\nHate Mail: eevblog+hate@gmail.com\n\nI DON'T DO PAID VIDEO SPONSORSHIPS, DON'T ASK!\n\nPLEASE:\nDo NOT ask for personal advice on something, post it in the EEVblog forum.\nI read ALL email, but please don't be offended if I don't have time to reply, I get a LOT of email.\n\nMailbag\nPO Box 7949\nBaulkham Hills NSW 2153\nAUSTRALIA"); @@ -1191,22 +1072,9 @@ async fn search() { "expected > 7000 total results, got {}", result.items.count.unwrap() ); - assert!( - result.items.items.len() > 10, - "expected > 10 search results, got {}", - result.items.items.len() - ); - assert!(!result.items.is_exhausted()); - assert_eq!(result.corrected_query.unwrap(), "doobydobap"); - let next = result.items.next(&rp.query()).await.unwrap().unwrap(); - assert!( - next.items.len() > 10, - "expected > 10 continuation results, got {}", - next.items.len() - ); - assert!(!next.is_exhausted()); + assert_next(result.items, &rp.query(), 10, 2).await; } #[rstest] @@ -1216,18 +1084,14 @@ async fn search() { #[tokio::test] async fn search_filter_entity(#[case] entity: search_filter::Entity) { let rp = RustyPipe::builder().strict().build(); - let result = rp + let mut result = rp .query() .search_filter("music", &SearchFilter::new().entity(entity)) .await .unwrap(); - assert!( - result.items.items.len() > 10, - "expected > 10 search results, got {}", - result.items.items.len() - ); - assert!(!result.items.is_exhausted()); + result.items.extend(&rp.query()).await.unwrap(); + assert_gte(result.items.items.len(), 20, "items"); result.items.items.iter().for_each(|item| match item { YouTubeItem::Video(_) => { @@ -1343,30 +1207,10 @@ async fn resolve_channel_not_found() { #[tokio::test] async fn startpage() { - let rp = RustyPipe::builder().strict().build(); - let result = rp.query().startpage().await.unwrap(); - - assert!( - result.items.len() >= 20, - "expected >= 20 items, got {}", - result.items.len() - ); - assert!(!result.is_exhausted()); -} - -#[tokio::test] -async fn startpage_cont() { let rp = RustyPipe::builder().strict().build(); let startpage = rp.query().startpage().await.unwrap(); - let next = startpage.next(&rp.query()).await.unwrap().unwrap(); - - assert!( - next.items.len() >= 20, - "expected >= 20 items, got {}", - next.items.len() - ); - assert!(!next.is_exhausted()); + assert_next(startpage, &rp.query(), 20, 2).await; } #[tokio::test] @@ -1374,11 +1218,7 @@ async fn trending() { let rp = RustyPipe::builder().strict().build(); let result = rp.query().trending().await.unwrap(); - assert!( - result.len() >= 50, - "expected >= 50 items, got {}", - result.len() - ); + assert_gte(result.len(), 50, "items"); } //#MUSIC @@ -1474,6 +1314,263 @@ async fn music_playlist_not_found() { ); } +#[rstest] +#[case::one_artist("one_artist", "MPREb_nlBWQROfvjo")] +#[case::various_artists("various_artists", "MPREb_8QkDeEIawvX")] +#[case::single("single", "MPREb_bHfHGoy7vuv")] +#[case::ep("ep", "MPREb_u1I69lSAe5v")] +#[case::audiobook("audiobook", "MPREb_gaoNzsQHedo")] +#[case::show("show", "MPREb_cwzk8EUwypZ")] +#[tokio::test] +async fn music_album(#[case] name: &str, #[case] id: &str) { + let rp = RustyPipe::builder().strict().build(); + let album = rp.query().music_album(id).await.unwrap(); + + assert!(!album.cover.is_empty(), "got no cover"); + + insta::assert_ron_snapshot!(format!("music_album_{}", name), album, + {".cover" => "[cover]"} + ); +} + +#[tokio::test] +async fn music_album_not_found() { + let rp = RustyPipe::builder().strict().build(); + let err = rp + .query() + .music_album("MPREb_nlBWQROfvjoz") + .await + .unwrap_err(); + + assert!( + matches!( + err, + Error::Extraction(ExtractionError::ContentUnavailable(_)) + ), + "got: {}", + err + ); +} + +#[rstest] +#[case::default(false)] +#[case::typo(true)] +#[tokio::test] +async fn music_search(#[case] typo: bool) { + let rp = RustyPipe::builder().strict().build(); + let res = rp + .query() + .music_search(match typo { + false => "black mamba", + true => "blck mamba", + }) + .await + .unwrap(); + + assert!(!res.tracks.is_empty(), "no tracks"); + assert!(!res.albums.is_empty(), "no albums"); + assert!(!res.artists.is_empty(), "no artists"); + assert!(!res.playlists.is_empty(), "no playlists"); + assert_eq!(res.order[0], MusicEntityType::Track); + + if typo { + assert_eq!(res.corrected_query.unwrap(), "black mamba"); + } else { + assert_eq!(res.corrected_query, None); + } + + let track = &res.tracks[0]; + dbg!(&track); + assert_eq!(track.id, "ZeerrnuLi5E"); + assert_eq!(track.title, "Black Mamba"); + assert_eq!(track.duration, 230); + assert!(!track.cover.is_empty(), "got no cover"); + + let track_artist = &track.artists[0]; + assert_eq!(track_artist.id, "UCEdZAdnnKqbaHOlv8nM6OtA"); + assert_eq!(track_artist.name, "aespa"); + assert_eq!(track.artists_txt.as_ref().unwrap(), "aespa"); + assert_eq!(track.album, None); + assert_gte(track.view_count.unwrap(), 230_000_000, "views"); + assert!(track.is_video, "got no video"); + assert_eq!(track.track_nr, None); +} + +#[rstest] +#[case::tracks(false)] +#[case::videos(true)] +#[tokio::test] +async fn music_search_tracks(#[case] videos: bool) { + let rp = RustyPipe::builder().strict().build(); + let res = rp + .query() + .music_search_tracks("black mamba", videos) + .await + .unwrap(); + + let track = &res.items.items[0]; + assert_eq!(track.title, "Black Mamba"); + assert!(!track.cover.is_empty(), "got no cover"); + assert_eq!(track.is_video, videos); + assert_eq!(track.track_nr, None); + + let track_artist = &track.artists[0]; + assert_eq!(track_artist.id, "UCEdZAdnnKqbaHOlv8nM6OtA"); + assert_eq!(track_artist.name, "aespa"); + assert_eq!(track.artists_txt.as_ref().unwrap(), "aespa"); + + if videos { + assert_eq!(track.id, "ZeerrnuLi5E"); + assert_eq!(track.duration, 230); + assert_eq!(track.album, None); + assert_gte(track.view_count.unwrap(), 230_000_000, "views"); + } else { + assert_eq!(track.id, "BL-aIpCLWnU"); + assert_eq!(track.duration, 175); + + let album = track.album.as_ref().unwrap(); + assert_eq!(album.id, "MPREb_OpHWHwyNOuY"); + assert_eq!(album.name, "Black Mamba"); + } + + assert_next(res.items, &rp.query(), 15, 2).await; +} + +#[rstest] +#[case::single( + "black mamba", + "Black Mamba", + "MPREb_OpHWHwyNOuY", + "aespa", + "UCEdZAdnnKqbaHOlv8nM6OtA", + 2020, + AlbumType::Single, + 2 +)] +#[case::ep( + "waldbrand", + "Waldbrand", + "MPREb_u1I69lSAe5v", + "Madeline Juno", + "UCpJyCbFbdTrx0M90HCNBHFQ", + 2016, + AlbumType::Ep, + 1 +)] +#[case::album( + "märchen enden gut", + "Märchen enden gut", + "MPREb_nlBWQROfvjo", + "Oonagh", + "UC_vmjW5e1xEHhYjY2a0kK1A", + 2016, + AlbumType::Album, + 1 +)] +#[tokio::test] +async fn music_search_albums( + #[case] query: &str, + #[case] name: &str, + #[case] id: &str, + #[case] artist: &str, + #[case] artist_id: &str, + #[case] year: u16, + #[case] album_type: AlbumType, + #[case] n_pages: usize, +) { + let rp = RustyPipe::builder().strict().build(); + let res = rp.query().music_search_albums(query).await.unwrap(); + + let album = &res.items.items[0]; + assert_eq!(album.name, name); + assert_eq!(album.id, id); + assert_eq!(album.artists_txt, artist); + + let album_artist = &album.artists[0]; + assert_eq!(album_artist.id, artist_id); + assert_eq!(album_artist.name, artist); + + assert!(!album.cover.is_empty(), "got no cover"); + assert_eq!(album.year.as_ref().unwrap(), &year); + assert_eq!(album.album_type, album_type); + + assert_eq!(res.corrected_query, None); + + assert_next(res.items, &rp.query(), 15, n_pages).await; +} + +#[tokio::test] +async fn music_search_artists() { + let rp = RustyPipe::builder().strict().build(); + let res = rp.query().music_search_artists("namika").await.unwrap(); + + let artist = &res.items.items[0]; + assert_eq!(artist.id, "UCIh4j8fXWf2U0ro0qnGU8Mg"); + assert_eq!(artist.name, "Namika"); + assert!(!artist.avatar.is_empty(), "got no avatar"); + assert!( + artist.subscriber_count.unwrap() > 735_000, + "expected >735K subscribers, got {}", + artist.subscriber_count.unwrap() + ); + assert_eq!(res.corrected_query, None); +} + +#[tokio::test] +async fn music_search_artists_cont() { + let rp = RustyPipe::builder().strict().build(); + 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; +} + +#[tokio::test] +async fn music_search_playlists() { + let rp = RustyPipe::builder().strict().build(); + let res = rp + .query() + .music_search_playlists("easy pop", false) + .await + .unwrap(); + + assert_eq!(res.corrected_query, None); + let playlist = &res.items.items[0]; + + assert_eq!(playlist.id, "RDCLAK5uy_kFQXdnqMaQCVx2wpUM4ZfbsGCDibZtkJk"); + assert_eq!(playlist.name, "Easy Pop"); + assert!(!playlist.thumbnail.is_empty(), "got no thumbnail"); + assert_gte(playlist.track_count.unwrap(), 80, "tracks"); + assert_eq!(playlist.channel, None); + assert!(playlist.from_ytm); +} + +#[tokio::test] +async fn music_search_playlists_community() { + let rp = RustyPipe::builder().strict().build(); + let res = rp + .query() + .music_search_playlists("Best Pop Music Videos - Top Pop Hits Playlist", true) + .await + .unwrap(); + + assert_eq!(res.corrected_query, None); + let playlist = &res.items.items[0]; + + assert_eq!(playlist.id, "PLMC9KNkIncKtGvr2kFRuXBVmBev6cAJ2u"); + assert_eq!( + playlist.name, + "Best Pop Music Videos - Top Pop Hits Playlist" + ); + assert!(!playlist.thumbnail.is_empty(), "got no thumbnail"); + assert_gte(playlist.track_count.unwrap(), 250, "tracks"); + + let channel = playlist.channel.as_ref().unwrap(); + assert_eq!(channel.id, "UCs72iRpTEuwV3y6pdWYLgiw"); + assert_eq!(channel.name, "Redlist - Just Hits"); + assert!(!playlist.from_ytm); +} + //#TESTUTIL /// Assert equality within 10% margin @@ -1488,3 +1585,26 @@ fn assert_approx(left: f64, right: f64) { ); } } + +fn assert_gte(a: T, b: T, msg: &str) { + assert!(a >= b, "expected {} {}, got {}", b, msg, a); +} + +async fn assert_next( + paginator: Paginator, + query: &RustyPipeQuery, + min_items: usize, + n_pages: usize, +) { + let mut p = paginator; + assert_gte(p.items.len(), min_items, "items on page 0"); + + for i in 0..n_pages { + p = p.next(query).await.unwrap().expect("paginator exhausted"); + assert_gte( + p.items.len(), + min_items, + &format!("items on page {}", i + 1), + ); + } +}