From 97492780c6496ca2aac7497984644e7a18fff430 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Sat, 6 May 2023 02:32:42 +0200 Subject: [PATCH] fix: parsing is_ytm for playlists --- codegen/src/util.rs | 4 ++++ src/client/music_playlist.rs | 6 +----- src/client/response/music_item.rs | 9 ++++++--- src/util/dictionary.rs | 15 +++++++++------ src/util/mod.rs | 14 +++++++++++--- testfiles/dict/dictionary.json | 5 ++++- tests/youtube.rs | 8 +++----- 7 files changed, 38 insertions(+), 23 deletions(-) diff --git a/codegen/src/util.rs b/codegen/src/util.rs index 716d54e..16cb7de 100644 --- a/codegen/src/util.rs +++ b/codegen/src/util.rs @@ -52,6 +52,10 @@ pub struct DictEntry { /// /// Format: Parsed token -> decimal power pub number_tokens: BTreeMap, + /// Tokens for parsing number strings with no digits (e.g. "No videos") + /// + /// Format: Parsed token -> value + pub number_nd_tokens: BTreeMap, /// Names of album types (Album, Single, ...) /// /// Format: Parsed text -> Album type diff --git a/src/client/music_playlist.rs b/src/client/music_playlist.rs index 0d126f6..5369e42 100644 --- a/src/client/music_playlist.rs +++ b/src/client/music_playlist.rs @@ -184,11 +184,7 @@ impl MapResponse for response::MusicPlaylist { Some(header) => { let h = header.music_detail_header_renderer; - let from_ytm = h - .subtitle - .0 - .iter() - .any(|c| c.as_str() == util::YT_MUSIC_NAME); + let from_ytm = h.subtitle.0.iter().any(util::is_ytm); let channel = h .subtitle .0 diff --git a/src/client/response/music_item.rs b/src/client/response/music_item.rs index 87d8399..b6bb9b6 100644 --- a/src/client/response/music_item.rs +++ b/src/client/response/music_item.rs @@ -731,7 +731,8 @@ impl MusicListMapper { let from_ytm = channel_p .as_ref() - .map(|p| p.first_str() == util::YT_MUSIC_NAME) + .and_then(|p| p.0.first()) + .map(util::is_ytm) .unwrap_or_default(); let channel = channel_p.and_then(|p| { p.0.into_iter().find_map(|c| ChannelId::try_from(c).ok()) @@ -872,7 +873,8 @@ impl MusicListMapper { // (featured on the startpage or in genres) let from_ytm = subtitle_p2 .as_ref() - .map(|p| p.first_str() == util::YT_MUSIC_NAME) + .and_then(|p| p.0.first()) + .map(util::is_ytm) .unwrap_or(true); let channel = subtitle_p2.and_then(|p| { p.0.into_iter().find_map(|c| ChannelId::try_from(c).ok()) @@ -1007,7 +1009,8 @@ impl MusicListMapper { MusicPageType::Playlist => { let from_ytm = subtitle_p2 .as_ref() - .map(|p| p.first_str() == util::YT_MUSIC_NAME) + .and_then(|p| p.0.first()) + .map(util::is_ytm) .unwrap_or(true); let channel = subtitle_p2 .and_then(|p| p.0.into_iter().find_map(|c| ChannelId::try_from(c).ok())); diff --git a/src/util/dictionary.rs b/src/util/dictionary.rs index 80ab9ab..a0ac898 100644 --- a/src/util/dictionary.rs +++ b/src/util/dictionary.rs @@ -4233,18 +4233,21 @@ pub(crate) fn entry(lang: Language) -> Entry { }, comma_decimal: false, number_tokens: ::phf::Map { - key: 12913932095322966823, + key: 15467950696543387533, disps: &[ - (0, 1), - (0, 0), + (2, 0), + (2, 1), ], entries: &[ - ("ବ\u{b3f}ଜଣ", 9), - ("ହଟ\u{b3f}", 3), ("ନ\u{b3f}ଜଣ", 6), - ("ହଜଣ", 3), + ("ବ\u{b3f}", 9), + ("ନ\u{b3f}", 6), + ("ବ\u{b3f}ଜଣ", 9), ("ବ\u{b3f}ଟ\u{b3f}", 9), + ("ହଜଣ", 3), ("ନ\u{b3f}ଟ\u{b3f}", 6), + ("ହ", 3), + ("ହଟ\u{b3f}", 3), ], }, album_types: ::phf::Map { diff --git a/src/util/mod.rs b/src/util/mod.rs index 2cdc5cd..a2295ed 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -19,7 +19,7 @@ use rand::Rng; use regex::Regex; use url::Url; -use crate::{error::Error, param::Language}; +use crate::{error::Error, param::Language, serializer::text::TextComponent}; pub static VIDEO_ID_REGEX: Lazy = Lazy::new(|| Regex::new(r"^[A-Za-z0-9_-]{11}$").unwrap()); pub static CHANNEL_ID_REGEX: Lazy = @@ -34,8 +34,6 @@ pub static VANITY_PATH_REGEX: Lazy = Lazy::new(|| { /// Separator string for YouTube Music subtitles pub const DOT_SEPARATOR: &str = " • "; -/// YouTube Music name (author of official playlists) -pub const YT_MUSIC_NAME: &str = "YouTube Music"; pub const VARIOUS_ARTISTS: &str = "Various Artists"; pub const PLAYLIST_ID_ALBUM_PREFIX: &str = "OLAK"; @@ -269,6 +267,16 @@ impl TryRemove for Vec { } } +/// Check if a channel name equals "YouTube Music" +/// (the author of original YouTube music playlists) +pub(crate) fn is_ytm(text: &TextComponent) -> bool { + if let TextComponent::Text { text } = text { + text.starts_with("YouTube") + } else { + false + } +} + /// Check if a language should be parsed by character pub fn lang_by_char(lang: Language) -> bool { matches!( diff --git a/testfiles/dict/dictionary.json b/testfiles/dict/dictionary.json index 510cdbb..9a086cb 100644 --- a/testfiles/dict/dictionary.json +++ b/testfiles/dict/dictionary.json @@ -2530,7 +2530,10 @@ "ବିଜଣ": 9, "ବିଟି": 9, "ହଜଣ": 3, - "ହଟି": 3 + "ହଟି": 3, + "ହ": 3, + "ନି": 6, + "ବି": 9 }, "album_types": { "ep": "Ep", diff --git a/tests/youtube.rs b/tests/youtube.rs index 405cb49..1d5abe5 100644 --- a/tests/youtube.rs +++ b/tests/youtube.rs @@ -1242,7 +1242,6 @@ fn music_playlist( let playlist = tokio_test::block_on(rp.query().music_playlist(id)).unwrap(); assert_eq!(playlist.id, id); - assert_eq!(playlist.name, name); assert!(!playlist.tracks.is_empty()); assert_eq!(!playlist.tracks.is_exhausted(), is_long); assert_gte( @@ -1251,6 +1250,7 @@ fn music_playlist( "track count", ); if unlocalized { + assert_eq!(playlist.name, name); assert_eq!(playlist.description, description); } @@ -1600,8 +1600,6 @@ fn music_search_videos(rp: RustyPipe, unlocalized: bool) { assert_next(res.items, rp.query(), 15, 2); } -// This podcast was removed from YouTube Music and I could not find another one -/* #[tokio::test] async fn music_search_episode() { let rp = RustyPipe::builder().strict().build(); @@ -1623,7 +1621,7 @@ async fn music_search_episode() { "Blond - Da muss man dabei gewesen sein: Das Hörspiel - Fall #1" ); assert!(!track.cover.is_empty(), "got no cover"); -}*/ +} #[rstest] #[case::single( @@ -1687,7 +1685,7 @@ fn music_search_albums( assert_eq!(res.corrected_query, None); - if more { + if more && unlocalized { assert_next(res.items, rp.query(), 15, 1); } }