fix: handle music artist not found

This commit is contained in:
ThetaDev 2025-03-31 18:11:14 +02:00
parent 187bf1c9a0
commit daf3d035be
No known key found for this signature in database
GPG key ID: E319D3C5148D65B6
5 changed files with 48 additions and 35 deletions

View file

@ -154,7 +154,24 @@ fn map_artist_page(
ctx: &MapRespCtx<'_>, ctx: &MapRespCtx<'_>,
skip_extendables: bool, skip_extendables: bool,
) -> Result<MapResult<(MusicArtist, bool)>, ExtractionError> { ) -> Result<MapResult<(MusicArtist, bool)>, ExtractionError> {
let header = res.header.music_immersive_header_renderer; let contents = match res.contents {
Some(c) => c,
None => {
if res.microformat.microformat_data_renderer.noindex {
return Err(ExtractionError::NotFound {
id: ctx.id.to_owned(),
msg: "no contents".into(),
});
} else {
return Err(ExtractionError::InvalidData("no contents".into()));
}
}
};
let header = res
.header
.ok_or(ExtractionError::InvalidData("no header".into()))?
.music_immersive_header_renderer;
if let Some(share) = header.share_endpoint { if let Some(share) = header.share_endpoint {
let pb = share.share_entity_endpoint.serialized_share_entity; let pb = share.share_entity_endpoint.serialized_share_entity;
@ -171,8 +188,7 @@ fn map_artist_page(
} }
} }
let sections = res let sections = contents
.contents
.single_column_browse_results_renderer .single_column_browse_results_renderer
.contents .contents
.into_iter() .into_iter()

View file

@ -154,11 +154,7 @@ impl MapResponse<MusicPlaylist> for response::MusicPlaylist {
let contents = match self.contents { let contents = match self.contents {
Some(c) => c, Some(c) => c,
None => { None => {
if self if self.microformat.microformat_data_renderer.noindex {
.microformat
.map(|m| m.microformat_data_renderer.noindex)
.unwrap_or_default()
{
return Err(ExtractionError::NotFound { return Err(ExtractionError::NotFound {
id: ctx.id.to_owned(), id: ctx.id.to_owned(),
msg: "no contents".into(), msg: "no contents".into(),
@ -359,11 +355,7 @@ impl MapResponse<MusicAlbum> for response::MusicPlaylist {
let contents = match self.contents { let contents = match self.contents {
Some(c) => c, Some(c) => c,
None => { None => {
if self if self.microformat.microformat_data_renderer.noindex {
.microformat
.map(|m| m.microformat_data_renderer.noindex)
.unwrap_or_default()
{
return Err(ExtractionError::NotFound { return Err(ExtractionError::NotFound {
id: ctx.id.to_owned(), id: ctx.id.to_owned(),
msg: "no contents".into(), msg: "no contents".into(),
@ -492,7 +484,8 @@ impl MapResponse<MusicAlbum> for response::MusicPlaylist {
let playlist_id = self let playlist_id = self
.microformat .microformat
.and_then(|mf| mf.microformat_data_renderer.url_canonical) .microformat_data_renderer
.url_canonical
.and_then(|x| { .and_then(|x| {
x.strip_prefix("https://music.youtube.com/playlist?list=") x.strip_prefix("https://music.youtube.com/playlist?list=")
.map(str::to_owned) .map(str::to_owned)

View file

@ -5,7 +5,8 @@ use crate::serializer::text::Text;
use super::{ use super::{
music_item::{ music_item::{
Button, Grid, ItemSection, MusicThumbnailRenderer, SimpleHeader, SingleColumnBrowseResult, Button, Grid, ItemSection, MusicMicroformat, MusicThumbnailRenderer, SimpleHeader,
SingleColumnBrowseResult,
}, },
SectionList, Tab, SectionList, Tab,
}; };
@ -14,8 +15,10 @@ use super::{
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub(crate) struct MusicArtist { pub(crate) struct MusicArtist {
pub contents: SingleColumnBrowseResult<Tab<SectionList<ItemSection>>>, pub contents: Option<SingleColumnBrowseResult<Tab<SectionList<ItemSection>>>>,
pub header: Header, pub header: Option<Header>,
#[serde(default)]
pub microformat: MusicMicroformat,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]

View file

@ -433,6 +433,22 @@ pub(crate) enum TrackBadge {
LiveBadgeRenderer {}, LiveBadgeRenderer {},
} }
#[serde_as]
#[derive(Default, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct MusicMicroformat {
#[serde_as(as = "DefaultOnError")]
pub microformat_data_renderer: MicroformatData,
}
#[derive(Default, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct MicroformatData {
pub url_canonical: Option<String>,
#[serde(default)]
pub noindex: bool,
}
/* /*
#MAPPER #MAPPER
*/ */

View file

@ -5,22 +5,21 @@ use crate::serializer::text::{AttributedText, Text, TextComponents};
use super::{ use super::{
music_item::{ music_item::{
Button, ItemSection, MusicContentsRenderer, MusicItemMenuEntry, MusicThumbnailRenderer, Button, ItemSection, MusicContentsRenderer, MusicItemMenuEntry, MusicMicroformat,
MusicThumbnailRenderer,
}, },
url_endpoint::OnTapWrap, url_endpoint::OnTapWrap,
ContentsRenderer, SectionList, Tab, ContentsRenderer, SectionList, Tab,
}; };
/// Response model for YouTube Music playlists and albums /// Response model for YouTube Music playlists and albums
#[serde_as]
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub(crate) struct MusicPlaylist { pub(crate) struct MusicPlaylist {
pub contents: Option<Contents>, pub contents: Option<Contents>,
pub header: Option<Header>, pub header: Option<Header>,
#[serde(default)] #[serde(default)]
#[serde_as(as = "DefaultOnError")] pub microformat: MusicMicroformat,
pub microformat: Option<Microformat>,
} }
#[serde_as] #[serde_as]
@ -162,17 +161,3 @@ pub(crate) struct AvatarStackViewModel {
pub(crate) struct AvatarStackRendererContext { pub(crate) struct AvatarStackRendererContext {
pub command_context: Option<OnTapWrap>, pub command_context: Option<OnTapWrap>,
} }
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct Microformat {
pub microformat_data_renderer: MicroformatData,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct MicroformatData {
pub url_canonical: Option<String>,
#[serde(default)]
pub noindex: bool,
}