feat: add more extraction errors
This commit is contained in:
parent
f748b98ccc
commit
68342cecab
4 changed files with 78 additions and 25 deletions
|
|
@ -1075,11 +1075,8 @@ impl RustyPipeQuery {
|
||||||
Ok(mapres.c)
|
Ok(mapres.c)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
match e {
|
if e.should_report() {
|
||||||
ExtractionError::VideoUnavailable(_, _)
|
create_report(Level::ERR, Some(e.to_string()), Vec::new());
|
||||||
| ExtractionError::VideoAgeRestricted
|
|
||||||
| ExtractionError::ContentUnavailable(_) => (),
|
|
||||||
_ => create_report(Level::ERR, Some(e.to_string()), Vec::new()),
|
|
||||||
}
|
}
|
||||||
Err(e.into())
|
Err(e.into())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,22 @@ impl RustyPipeQuery {
|
||||||
|
|
||||||
match android_res {
|
match android_res {
|
||||||
Ok(res) => Ok(res),
|
Ok(res) => Ok(res),
|
||||||
Err(Error::Extraction(
|
Err(Error::Extraction(e)) => {
|
||||||
ExtractionError::VideoAgeRestricted | ExtractionError::WrongResult(_),
|
if e.switch_client() {
|
||||||
)) => {
|
let tv_res = self
|
||||||
self.player_from_client(video_id, ClientType::TvHtml5Embed)
|
.player_from_client(video_id, ClientType::TvHtml5Embed)
|
||||||
.await
|
.await;
|
||||||
|
|
||||||
|
match tv_res {
|
||||||
|
// Output android client error if the tv client is unsupported
|
||||||
|
Err(Error::Extraction(ExtractionError::VideoClientUnsupported(_))) => {
|
||||||
|
Err(Error::Extraction(e))
|
||||||
|
}
|
||||||
|
_ => tv_res,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(Error::Extraction(e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
|
|
@ -138,11 +149,29 @@ impl MapResponse<VideoPlayer> for response::Player {
|
||||||
live_streamability.is_some()
|
live_streamability.is_some()
|
||||||
}
|
}
|
||||||
response::player::PlayabilityStatus::Unplayable { reason } => {
|
response::player::PlayabilityStatus::Unplayable { reason } => {
|
||||||
return Err(ExtractionError::VideoUnavailable("DRM/Geoblock", reason))
|
for word in reason.split_whitespace() {
|
||||||
|
match word {
|
||||||
|
// reason: "This video requires payment to watch."
|
||||||
|
"payment" => return Err(ExtractionError::VideoUnavailable("DRM", reason)),
|
||||||
|
// reason: "The uploader has not made this video available in your country."
|
||||||
|
"country" => return Err(ExtractionError::VideoGeoblock),
|
||||||
|
// reason (Android): "This video can only be played on newer versions of Android or other supported devices."
|
||||||
|
// reason (TV client): "Playback on other websites has been disabled by the video owner."
|
||||||
|
"Android" | "websites" => {
|
||||||
|
return Err(ExtractionError::VideoClientUnsupported(reason))
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Err(ExtractionError::VideoUnavailable(
|
||||||
|
"being unplayable",
|
||||||
|
reason,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
response::player::PlayabilityStatus::LoginRequired { reason } => {
|
response::player::PlayabilityStatus::LoginRequired { reason } => {
|
||||||
// reason: "Sign in to confirm your age"
|
// reason (age restriction): "Sign in to confirm your age"
|
||||||
// or: "This video may be inappropriate for some users."
|
// or: "This video may be inappropriate for some users."
|
||||||
|
// reason (private): "This video is private"
|
||||||
if reason
|
if reason
|
||||||
.split_whitespace()
|
.split_whitespace()
|
||||||
.any(|word| word == "age" || word == "inappropriate")
|
.any(|word| word == "age" || word == "inappropriate")
|
||||||
|
|
@ -158,10 +187,12 @@ impl MapResponse<VideoPlayer> for response::Player {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
response::player::PlayabilityStatus::Error { reason } => {
|
response::player::PlayabilityStatus::Error { reason } => {
|
||||||
|
// reason (censored): "This video has been removed for violating YouTube's policy on hate speech. Learn more about combating hate speech in your country."
|
||||||
|
// reason: "This video is unavailable"
|
||||||
return Err(ExtractionError::VideoUnavailable(
|
return Err(ExtractionError::VideoUnavailable(
|
||||||
"deletion/censorship",
|
"deletion/censorship",
|
||||||
reason,
|
reason,
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
24
src/error.rs
24
src/error.rs
|
|
@ -73,6 +73,10 @@ pub enum ExtractionError {
|
||||||
VideoUnavailable(&'static str, String),
|
VideoUnavailable(&'static str, String),
|
||||||
#[error("Video is age restricted")]
|
#[error("Video is age restricted")]
|
||||||
VideoAgeRestricted,
|
VideoAgeRestricted,
|
||||||
|
#[error("Video is not available in your country")]
|
||||||
|
VideoGeoblock,
|
||||||
|
#[error("Video cant be played with this client. Reason (from YT): {0}")]
|
||||||
|
VideoClientUnsupported(String),
|
||||||
#[error("Content is not available. Reason: {0}")]
|
#[error("Content is not available. Reason: {0}")]
|
||||||
ContentUnavailable(Cow<'static, str>),
|
ContentUnavailable(Cow<'static, str>),
|
||||||
#[error("deserialization error: {0}")]
|
#[error("deserialization error: {0}")]
|
||||||
|
|
@ -84,3 +88,23 @@ pub enum ExtractionError {
|
||||||
#[error("Warnings during deserialization/mapping")]
|
#[error("Warnings during deserialization/mapping")]
|
||||||
DeserializationWarnings,
|
DeserializationWarnings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ExtractionError {
|
||||||
|
pub(crate) fn should_report(&self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self,
|
||||||
|
ExtractionError::Deserialization(_)
|
||||||
|
| ExtractionError::InvalidData(_)
|
||||||
|
| ExtractionError::WrongResult(_)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn switch_client(&self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self,
|
||||||
|
ExtractionError::VideoClientUnsupported(_)
|
||||||
|
| ExtractionError::VideoAgeRestricted
|
||||||
|
| ExtractionError::WrongResult(_)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -271,27 +271,28 @@ async fn get_player(
|
||||||
// This video is geoblocked outside of Japan, so expect this test case to fail when using a Japanese IP address.
|
// This video is geoblocked outside of Japan, so expect this test case to fail when using a Japanese IP address.
|
||||||
#[case::geoblock(
|
#[case::geoblock(
|
||||||
"sJL6WA-aGkQ",
|
"sJL6WA-aGkQ",
|
||||||
"extraction error: Video cant be played because of DRM/Geoblock. Reason (from YT): "
|
"extraction error: Video is not available in your country"
|
||||||
)]
|
)]
|
||||||
#[case::drm(
|
#[case::drm(
|
||||||
"1bfOsni7EgI",
|
"1bfOsni7EgI",
|
||||||
"extraction error: Video cant be played because of DRM/Geoblock. Reason (from YT): "
|
"extraction error: Video cant be played because of DRM. Reason (from YT): "
|
||||||
)]
|
)]
|
||||||
// YouTube sometimes returns "Video unavailable" for this video
|
#[case::private(
|
||||||
// #[case::private(
|
"s7_qI6_mIXc",
|
||||||
// "s7_qI6_mIXc",
|
"extraction error: Video cant be played because of being private. Reason (from YT): "
|
||||||
// "extraction error: Video cant be played because of being private. Reason (from YT): "
|
|
||||||
// )]
|
|
||||||
#[case::t1(
|
|
||||||
"CUO8secmc0g",
|
|
||||||
"extraction error: Video cant be played because of DRM/Geoblock. Reason (from YT): "
|
|
||||||
)]
|
)]
|
||||||
|
#[case::age_restricted("CUO8secmc0g", "extraction error: Video is age restricted")]
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn get_player_error(#[case] id: &str, #[case] msg: &str) {
|
async fn get_player_error(#[case] id: &str, #[case] msg: &str) {
|
||||||
let rp = RustyPipe::builder().strict().build();
|
let rp = RustyPipe::builder().strict().build();
|
||||||
let err = rp.query().player(id).await.unwrap_err();
|
let err = rp.query().player(id).await.unwrap_err().to_string();
|
||||||
|
|
||||||
assert!(err.to_string().starts_with(msg), "got error msg: {}", err);
|
assert!(
|
||||||
|
err.starts_with(msg),
|
||||||
|
"got error msg: `{}`, expected: `{}`",
|
||||||
|
err,
|
||||||
|
msg
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#PLAYLIST
|
//#PLAYLIST
|
||||||
|
|
|
||||||
Reference in a new issue