fix: parsing error when no music_related content available

This commit is contained in:
ThetaDev 2024-04-18 19:50:06 +02:00
parent 77ee923778
commit 8fbd6b95b6
No known key found for this signature in database
GPG key ID: E319D3C5148D65B6
2 changed files with 52 additions and 45 deletions

View file

@ -306,19 +306,14 @@ impl MapResponse<Lyrics> for response::MusicLyrics {
) -> Result<MapResult<Lyrics>, 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<Lyrics> for response::MusicLyrics {
impl MapResponse<MusicRelated> for response::MusicRelated {
fn map_response(
self,
_id: &str,
id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::DeobfData>,
_vdata: Option<&str>,
) -> Result<MapResult<MusicRelated>, 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<MusicRelated> 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()
{

View file

@ -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<LyricsSection>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct LyricsContents {
pub message_renderer: Option<AlertRenderer>,
pub section_list_renderer: Option<ContentsRenderer<LyricsSection>>,
pub(crate) enum ListOrMessage<T> {
SectionListRenderer(ContentsRenderer<T>),
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<ItemSection>,
pub contents: ListOrMessage<ItemSection>,
}
impl<T> ListOrMessage<T> {
pub fn into_res(self) -> Result<Vec<T>, String> {
match self {
ListOrMessage::SectionListRenderer(c) => Ok(c.contents),
ListOrMessage::MessageRenderer(msg) => Err(msg.text),
}
}
}