1use std::fmt::Display;
2
3use derive_builder::UninitializedFieldError;
4use mangadex_api_schema::error::RelationshipConversionError;
5
6#[derive(Debug, thiserror::Error)]
7#[non_exhaustive]
8pub enum Error {
9 #[error("error parsing the URL")]
13 ParseUrlError(#[from] url::ParseError),
14
15 #[error("there was an error from the MangaDex servers (HTTP {0}): {1}")]
16 ServerError(u16, String),
17
18 #[error("failed to send a request to MangaDex: {0:?}")]
19 RequestError(#[from] reqwest::Error),
20
21 #[error("a field is missing when building the request: {0:?}")]
22 UninitializedFieldError(#[from] UninitializedFieldError),
23
24 #[error("failed to build the request: {0:?}")]
26 BuilderError(#[from] BuilderError),
27
28 #[error("missing auth tokens; please log in to MangaDex")]
29 MissingTokens,
30
31 #[error("missing client info; please insert the client_id and client_secret")]
32 MissingClientInfo,
33
34 #[error("missing captcha; please insert it or solve a captcha")]
35 MissingCaptcha,
36
37 #[error("an error occurred while pinging the MangaDex server")]
38 PingError,
39
40 #[error("an error occurred with the MangaDex API request: {0:?}")]
42 Api(#[from] mangadex_api_schema::error::MangaDexErrorResponse_),
43
44 #[error("failed to build a request: {0}")]
46 RequestBuilderError(String),
47
48 #[error("an error occurred while parsing the type: {0}")]
50 ParseError(String),
51
52 #[error("an eccor captured")]
53 Io(#[from] std::io::Error),
54
55 #[error(transparent)]
56 RateLimitParseError(#[from] crate::rate_limit::RateLimitParseError),
57
58 #[error("Rate Limit Excedeed")]
59 RateLimitExcedeed,
60
61 #[error(transparent)]
62 ForumThreadTypeParseError(#[from] mangadex_api_types::forum_thread::ForumThreadTypeParseError),
63
64 #[error(transparent)]
65 RelationshipConversionError(#[from] RelationshipConversionError),
66
67 #[error(transparent)]
68 Types(#[from] mangadex_api_types::error::Error),
69
70 #[error("This file {0} was skipped")]
71 SkippedDownload(String),
72
73 #[error("The API is temporarily anavailable. Reason: {}", if let Some (reason) = .0 {
74 &reason
75 } else {
76 "Unknown"
77 })]
78 ServiceUnavailable(Option<String>),
79
80 #[cfg(feature = "oauth")]
81 #[error("Got Oauth Error response (status: {}, reason: {})", .code, reason.as_ref().map_or("...", |v| v))]
82 OauthError { code: u16, reason: Option<String> },
83
84 #[error("{0}")]
85 UnknowSource(String),
86}
87
88impl Error {
89 pub fn unknow<S>(source: S) -> Self
90 where
91 S: Into<String>,
92 {
93 Self::UnknowSource(source.into())
94 }
95}
96
97impl serde::Serialize for Error {
98 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
99 where
100 S: serde::Serializer,
101 {
102 format!("{self}").serialize(serializer)
103 }
104}
105
106#[derive(Debug)]
107#[non_exhaustive]
108pub enum BuilderError {
109 UninitializedField(String),
111 ValidationError(String),
113}
114
115impl From<String> for BuilderError {
116 fn from(value: String) -> Self {
117 Self::ValidationError(value)
118 }
119}
120
121impl From<UninitializedFieldError> for BuilderError {
122 fn from(value: UninitializedFieldError) -> Self {
123 Self::UninitializedField(value.field_name().to_string())
124 }
125}
126impl Display for BuilderError {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 match self {
129 BuilderError::UninitializedField(s) => {
130 f.write_str(format!("the field {s} must initialized").as_str())
131 }
132 BuilderError::ValidationError(s) => f.write_str(s.as_str()),
133 }
134 }
135}
136impl std::error::Error for BuilderError {}