fix: handle playlist not found

This commit is contained in:
ThetaDev 2022-10-11 19:50:43 +02:00
parent de9e3c6ed9
commit 79b7fcf92c
5 changed files with 49 additions and 23 deletions

View file

@ -533,16 +533,7 @@ fn map_channel_content(
Ok(MapResult::ok(content)) Ok(MapResult::ok(content))
} }
None => match alerts { None => Err(response::alerts_to_err(alerts)),
Some(alerts) => Err(ExtractionError::ContentUnavailable(
alerts
.into_iter()
.map(|a| a.alert_renderer.text)
.collect::<Vec<_>>()
.join(" "),
)),
None => Err(ExtractionError::InvalidData("no contents".into())),
},
} }
} }

View file

@ -68,8 +68,12 @@ impl MapResponse<Playlist> for response::Playlist {
lang: Language, lang: Language,
_deobf: Option<&Deobfuscator>, _deobf: Option<&Deobfuscator>,
) -> Result<MapResult<Playlist>, ExtractionError> { ) -> Result<MapResult<Playlist>, ExtractionError> {
// TODO: think about a deserializer that deserializes only first list item let (contents, header) = match (self.contents, self.header) {
let mut tcbr_contents = self.contents.two_column_browse_results_renderer.contents; (Some(contents), Some(header)) => (contents, header),
_ => return Err(response::alerts_to_err(self.alerts)),
};
let mut tcbr_contents = contents.two_column_browse_results_renderer.contents;
let video_items = some_or_bail!( let video_items = some_or_bail!(
some_or_bail!( some_or_bail!(
some_or_bail!( some_or_bail!(
@ -121,11 +125,11 @@ impl MapResponse<Playlist> for response::Playlist {
} }
None => { None => {
let header_banner = some_or_bail!( let header_banner = some_or_bail!(
self.header.playlist_header_renderer.playlist_header_banner, header.playlist_header_renderer.playlist_header_banner,
Err(ExtractionError::InvalidData("no thumbnail found".into())) Err(ExtractionError::InvalidData("no thumbnail found".into()))
); );
let mut byline = self.header.playlist_header_renderer.byline; let mut byline = header.playlist_header_renderer.byline;
let last_update_txt = byline let last_update_txt = byline
.try_swap_remove(1) .try_swap_remove(1)
.map(|b| b.playlist_byline_renderer.text); .map(|b| b.playlist_byline_renderer.text);
@ -140,14 +144,14 @@ impl MapResponse<Playlist> for response::Playlist {
let n_videos = match ctoken { let n_videos = match ctoken {
Some(_) => { Some(_) => {
ok_or_bail!( ok_or_bail!(
util::parse_numeric(&self.header.playlist_header_renderer.num_videos_text), util::parse_numeric(&header.playlist_header_renderer.num_videos_text),
Err(ExtractionError::InvalidData("no video count".into())) Err(ExtractionError::InvalidData("no video count".into()))
) )
} }
None => videos.len() as u64, None => videos.len() as u64,
}; };
let playlist_id = self.header.playlist_header_renderer.playlist_id; let playlist_id = header.playlist_header_renderer.playlist_id;
if playlist_id != id { if playlist_id != id {
return Err(ExtractionError::WrongResult(format!( return Err(ExtractionError::WrongResult(format!(
"got wrong playlist id {}, expected {}", "got wrong playlist id {}, expected {}",
@ -155,10 +159,9 @@ impl MapResponse<Playlist> for response::Playlist {
))); )));
} }
let name = self.header.playlist_header_renderer.title; let name = header.playlist_header_renderer.title;
let description = self.header.playlist_header_renderer.description_text; let description = header.playlist_header_renderer.description_text;
let channel = self let channel = header
.header
.playlist_header_renderer .playlist_header_renderer
.owner_text .owner_text
.and_then(|link| ChannelId::try_from(link).ok()); .and_then(|link| ChannelId::try_from(link).ok());

View file

@ -25,6 +25,7 @@ pub use channel_rss::ChannelRss;
use serde::Deserialize; use serde::Deserialize;
use serde_with::{json::JsonString, serde_as, DefaultOnError, VecSkipError}; use serde_with::{json::JsonString, serde_as, DefaultOnError, VecSkipError};
use crate::error::ExtractionError;
use crate::serializer::{ use crate::serializer::{
ignore_any, ignore_any,
text::{Text, TextComponent}, text::{Text, TextComponent},
@ -471,3 +472,16 @@ impl IsShort for Vec<TimeOverlay> {
}) })
} }
} }
pub fn alerts_to_err(alerts: Option<Vec<Alert>>) -> ExtractionError {
match alerts {
Some(alerts) => ExtractionError::ContentUnavailable(
alerts
.into_iter()
.map(|a| a.alert_renderer.text)
.collect::<Vec<_>>()
.join(" "),
),
None => ExtractionError::InvalidData("no contents".into()),
}
}

View file

@ -5,14 +5,17 @@ use serde_with::{DefaultOnError, VecSkipError};
use crate::serializer::text::{Text, TextComponent}; use crate::serializer::text::{Text, TextComponent};
use crate::serializer::{MapResult, VecLogError}; use crate::serializer::{MapResult, VecLogError};
use super::{ContentRenderer, ContentsRenderer, ThumbnailsWrap, VideoListItem}; use super::{Alert, ContentRenderer, ContentsRenderer, ThumbnailsWrap, VideoListItem};
#[serde_as]
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Playlist { pub struct Playlist {
pub contents: Contents, pub contents: Option<Contents>,
pub header: Header, pub header: Option<Header>,
pub sidebar: Option<Sidebar>, pub sidebar: Option<Sidebar>,
#[serde_as(as = "Option<DefaultOnError>")]
pub alerts: Option<Vec<Alert>>,
} }
#[serde_as] #[serde_as]

View file

@ -211,6 +211,21 @@ async fn playlist_cont2() {
assert!(playlist.videos.count.unwrap() > 100); assert!(playlist.videos.count.unwrap() > 100);
} }
#[tokio::test]
async fn playlist_not_found() {
let rp = RustyPipe::builder().strict().build();
let err = rp
.query()
.playlist("PLbZIPy20-1pN7mqjckepWF78ndb6ci_qz")
.await
.unwrap_err();
assert!(matches!(
err,
Error::Extraction(ExtractionError::ContentUnavailable(_))
));
}
//#VIDEO DETAILS //#VIDEO DETAILS
#[tokio::test] #[tokio::test]