mirror of
https://github.com/lifegpc/pixiv_downloader.git
synced 2026-07-08 01:32:41 +08:00
Update Error handle
This commit is contained in:
@@ -259,6 +259,9 @@ pub async fn download_artwork(
|
||||
let app_ok = helper.refresh_token().is_some();
|
||||
if app_ok && helper.use_app_api() {
|
||||
if let Err(e) = download_artwork_app(ac, pw.clone(), id).await {
|
||||
if e.is_not_found() {
|
||||
return Err(e);
|
||||
}
|
||||
println!("{}{}", gettext("Warning: Failed to download artwork with app api, trying to download with web api: "), e);
|
||||
download_artwork_web(pw.clone(), id).await?;
|
||||
}
|
||||
|
||||
10
src/error.rs
10
src/error.rs
@@ -28,6 +28,7 @@ pub enum PixivDownloaderError {
|
||||
OpenSSLError(openssl::error::ErrorStack),
|
||||
ParseIntError(std::num::ParseIntError),
|
||||
ReqwestError(reqwest::Error),
|
||||
PixivAppError(crate::pixivapp::error::PixivAppError),
|
||||
}
|
||||
|
||||
impl std::error::Error for PixivDownloaderError {}
|
||||
@@ -44,6 +45,15 @@ impl From<http::header::InvalidHeaderValue> for PixivDownloaderError {
|
||||
}
|
||||
}
|
||||
|
||||
impl PixivDownloaderError {
|
||||
pub fn is_not_found(&self) -> bool {
|
||||
match self {
|
||||
Self::PixivAppError(e) => e.is_not_found(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! concat_pixiv_downloader_error {
|
||||
($exp1:expr, $exp2:expr) => {
|
||||
|
||||
@@ -41,6 +41,7 @@ mod parser;
|
||||
mod pixiv_app;
|
||||
mod pixiv_link;
|
||||
mod pixiv_web;
|
||||
mod pixivapp;
|
||||
mod push;
|
||||
mod retry_interval;
|
||||
#[cfg(feature = "server")]
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::ext::atomic::AtomicQuick;
|
||||
use crate::ext::replace::ReplaceWith2;
|
||||
use crate::ext::rw_lock::GetRwLock;
|
||||
use crate::opthelper::OptHelper;
|
||||
use crate::pixivapp::error::handle_error;
|
||||
use crate::webclient::{ReqMiddleware, WebClient};
|
||||
use crate::{get_helper, gettext};
|
||||
use chrono::{DateTime, Local, SecondsFormat, Utc};
|
||||
@@ -69,6 +70,7 @@ pub struct PixivAppClientInternal {
|
||||
}
|
||||
|
||||
impl PixivAppClientInternal {
|
||||
#[cfg(not(feature = "db"))]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
client: WebClient::default(),
|
||||
@@ -247,8 +249,7 @@ impl PixivAppClientInternal {
|
||||
)
|
||||
.await
|
||||
.ok_or(gettext("Failed to get illust details."))?;
|
||||
let status = re.status();
|
||||
let obj = json::parse(&re.text().await?)?;
|
||||
let obj = handle_error(re).await?;
|
||||
if get_helper().verbose() {
|
||||
println!("{}{}", gettext("Illust details:"), obj.pretty(2).as_str());
|
||||
}
|
||||
@@ -264,6 +265,7 @@ pub struct PixivAppClient {
|
||||
}
|
||||
|
||||
impl PixivAppClient {
|
||||
#[cfg(not(feature = "db"))]
|
||||
pub fn new() -> Self {
|
||||
let r = Self {
|
||||
internal: Arc::new(PixivAppClientInternal::new()),
|
||||
|
||||
4
src/pixivapp/check.rs
Normal file
4
src/pixivapp/check.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
/// Check if have data that we don't handle
|
||||
pub trait CheckUnknown {
|
||||
fn check_unknown(&self) -> Result<(), String>;
|
||||
}
|
||||
150
src/pixivapp/error.rs
Normal file
150
src/pixivapp/error.rs
Normal file
@@ -0,0 +1,150 @@
|
||||
use super::check::CheckUnknown;
|
||||
use crate::error::PixivDownloaderError;
|
||||
use json::JsonValue;
|
||||
use proc_macros::check_json_keys;
|
||||
use reqwest::{Response, StatusCode};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PixivAppHTTPError {
|
||||
status: StatusCode,
|
||||
}
|
||||
|
||||
impl PixivAppHTTPError {
|
||||
pub fn new(status: StatusCode) -> Self {
|
||||
Self { status }
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for PixivAppHTTPError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{} {}",
|
||||
self.status.as_u16(),
|
||||
self.status.canonical_reason().unwrap_or("")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PixivAppAPIError {
|
||||
data: JsonValue,
|
||||
status: StatusCode,
|
||||
}
|
||||
|
||||
impl CheckUnknown for PixivAppAPIError {
|
||||
fn check_unknown(&self) -> Result<(), String> {
|
||||
check_json_keys!(
|
||||
"user_message"+,
|
||||
"message"+,
|
||||
"reason"+,
|
||||
"user_message_details"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl PixivAppAPIError {
|
||||
pub fn new(data: JsonValue, status: StatusCode) -> Self {
|
||||
Self { data, status }
|
||||
}
|
||||
|
||||
pub fn user_message(&self) -> Option<&str> {
|
||||
self.data["user_message"].as_str()
|
||||
}
|
||||
|
||||
pub fn message(&self) -> Option<&str> {
|
||||
self.data["message"].as_str()
|
||||
}
|
||||
|
||||
pub fn reason(&self) -> Option<&str> {
|
||||
self.data["reason"].as_str()
|
||||
}
|
||||
|
||||
pub fn user_message_details(&self) -> &JsonValue {
|
||||
&self.data["user_message_details"]
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for PixivAppAPIError {}
|
||||
|
||||
impl std::fmt::Debug for PixivAppAPIError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("PixivAppAPIError")
|
||||
.field("user_message", &self.user_message())
|
||||
.field("message", &self.message())
|
||||
.field("reason", &self.reason())
|
||||
.field("user_message_details", &self.user_message_details())
|
||||
.field("status", &self.status)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for PixivAppAPIError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if let Some(user_message) = self.user_message() {
|
||||
write!(
|
||||
f,
|
||||
"{} ({} {})",
|
||||
user_message,
|
||||
self.status.as_u16(),
|
||||
self.status.canonical_reason().unwrap_or("")
|
||||
)
|
||||
} else if let Some(message) = self.message() {
|
||||
write!(f, "{} (", message)?;
|
||||
if let Some(reason) = self.reason() {
|
||||
write!(f, "{}, ", reason)?;
|
||||
}
|
||||
write!(
|
||||
f,
|
||||
"{} {})",
|
||||
self.status.as_u16(),
|
||||
self.status.canonical_reason().unwrap_or("")
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"{} {}: ",
|
||||
self.status.as_u16(),
|
||||
self.status.canonical_reason().unwrap_or("")
|
||||
)?;
|
||||
write!(f, "{}", self.data.pretty(2).as_str())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, derive_more::From, derive_more::Display)]
|
||||
pub enum PixivAppError {
|
||||
HTTP(PixivAppHTTPError),
|
||||
API(PixivAppAPIError),
|
||||
}
|
||||
|
||||
impl PixivAppError {
|
||||
pub fn is_not_found(&self) -> bool {
|
||||
match self {
|
||||
Self::HTTP(err) => err.status.as_u16() == 404,
|
||||
Self::API(err) => err.status.as_u16() == 404,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_error(res: Response) -> Result<JsonValue, PixivDownloaderError> {
|
||||
let status = res.status();
|
||||
if let Ok(obj) = json::parse(&res.text().await?) {
|
||||
let err = &obj["error"];
|
||||
if status.is_success() && err.is_null() {
|
||||
Ok(obj)
|
||||
} else if !err.is_null() {
|
||||
Err(PixivDownloaderError::from(PixivAppError::from(
|
||||
PixivAppAPIError::new(err.clone(), status),
|
||||
)))
|
||||
} else {
|
||||
Err(PixivDownloaderError::from(PixivAppError::from(
|
||||
PixivAppHTTPError::new(status),
|
||||
)))
|
||||
}
|
||||
} else {
|
||||
Err(PixivDownloaderError::from(PixivAppError::from(
|
||||
PixivAppHTTPError::new(status),
|
||||
)))
|
||||
}
|
||||
}
|
||||
3
src/pixivapp/mod.rs
Normal file
3
src/pixivapp/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod check;
|
||||
/// Error handling for pixiv app api
|
||||
pub mod error;
|
||||
Reference in New Issue
Block a user