From 8fbd6b95b6f01108b46f53fe60a56b0c561e40c1 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Thu, 18 Apr 2024 19:50:06 +0200 Subject: [PATCH] fix: parsing error when no `music_related` content available --- src/client/music_details.rs | 76 ++++++++++++++-------------- src/client/response/music_details.rs | 21 +++++--- 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/src/client/music_details.rs b/src/client/music_details.rs index 36d5ddd..0459389 100644 --- a/src/client/music_details.rs +++ b/src/client/music_details.rs @@ -306,19 +306,14 @@ impl MapResponse for response::MusicLyrics { ) -> Result, ExtractionError> { let lyrics = self .contents - .section_list_renderer - .and_then(|sl| { - sl.contents - .into_iter() - .find_map(|item| item.music_description_shelf_renderer) - }) - .ok_or(match self.contents.message_renderer { - Some(msg) => ExtractionError::NotFound { - id: id.to_owned(), - msg: msg.text.into(), - }, - None => ExtractionError::InvalidData(Cow::Borrowed("no content")), - })?; + .into_res() + .map_err(|msg| ExtractionError::NotFound { + id: id.to_owned(), + msg: msg.into(), + })? + .into_iter() + .find_map(|item| item.music_description_shelf_renderer) + .ok_or(ExtractionError::InvalidData(Cow::Borrowed("no content")))?; Ok(MapResult { c: Lyrics { @@ -333,36 +328,39 @@ impl MapResponse for response::MusicLyrics { impl MapResponse for response::MusicRelated { fn map_response( self, - _id: &str, + id: &str, lang: Language, _deobf: Option<&crate::deobfuscate::DeobfData>, _vdata: Option<&str>, ) -> Result, ExtractionError> { + let contents = self + .contents + .into_res() + .map_err(|msg| ExtractionError::NotFound { + id: id.to_owned(), + msg: msg.into(), + })?; + // Find artist - let artist_id = self - .contents - .section_list_renderer - .contents - .iter() - .find_map(|section| match section { - response::music_item::ItemSection::MusicCarouselShelfRenderer(shelf) => { - shelf.header.as_ref().and_then(|h| { - h.music_carousel_shelf_basic_header_renderer - .title - .0 - .iter() - .find_map(|c| { - let artist = ArtistId::from(c.clone()); - if artist.id.is_some() { - Some(artist) - } else { - None - } - }) - }) - } - _ => None, - }); + let artist_id = contents.iter().find_map(|section| match section { + response::music_item::ItemSection::MusicCarouselShelfRenderer(shelf) => { + shelf.header.as_ref().and_then(|h| { + h.music_carousel_shelf_basic_header_renderer + .title + .0 + .iter() + .find_map(|c| { + let artist = ArtistId::from(c.clone()); + if artist.id.is_some() { + Some(artist) + } else { + None + } + }) + }) + } + _ => None, + }); let mut mapper_tracks = MusicListMapper::new(lang); let mut mapper = match artist_id { @@ -370,7 +368,7 @@ impl MapResponse for response::MusicRelated { None => MusicListMapper::new(lang), }; - let mut sections = self.contents.section_list_renderer.contents.into_iter(); + let mut sections = contents.into_iter(); if let Some(response::music_item::ItemSection::MusicCarouselShelfRenderer(shelf)) = sections.next() { diff --git a/src/client/response/music_details.rs b/src/client/response/music_details.rs index 387f041..4254b00 100644 --- a/src/client/response/music_details.rs +++ b/src/client/response/music_details.rs @@ -7,7 +7,7 @@ use super::AlertRenderer; use super::ContentsRenderer; use super::{ music_item::{ItemSection, PlaylistPanelRenderer}, - ContentRenderer, SectionList, + ContentRenderer, }; /// Response model for YouTube Music track details @@ -108,14 +108,14 @@ pub(crate) struct PlaylistPanel { #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub(crate) struct MusicLyrics { - pub contents: LyricsContents, + pub contents: ListOrMessage, } #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] -pub(crate) struct LyricsContents { - pub message_renderer: Option, - pub section_list_renderer: Option>, +pub(crate) enum ListOrMessage { + SectionListRenderer(ContentsRenderer), + MessageRenderer(AlertRenderer), } #[derive(Debug, Deserialize)] @@ -137,5 +137,14 @@ pub(crate) struct LyricsRenderer { #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub(crate) struct MusicRelated { - pub contents: SectionList, + pub contents: ListOrMessage, +} + +impl ListOrMessage { + pub fn into_res(self) -> Result, String> { + match self { + ListOrMessage::SectionListRenderer(c) => Ok(c.contents), + ListOrMessage::MessageRenderer(msg) => Err(msg.text), + } + } }