fix: handle playlist not found
This commit is contained in:
parent
de9e3c6ed9
commit
79b7fcf92c
5 changed files with 49 additions and 23 deletions
|
|
@ -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())),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
Reference in a new issue