1use core::fmt::{Debug, Display};
3pub use json_crawler::CrawlerError as JsonError;
4use std::{
5 hash::{Hash, Hasher},
6 io,
7 time::SystemTimeError,
8};
9
10pub type Result<T> = core::result::Result<T, Error>;
12
13pub struct Error {
15 inner: Box<ErrorKind>,
18}
19
20#[non_exhaustive]
24pub enum ErrorKind {
25 JsonParsing(JsonError),
27 Web { message: String },
29 Io(io::Error),
32 InvalidResponse { response: String },
35 Header,
37 UnableToSerializeGoogleOAuthToken {
38 response: String,
39 err: serde_json::Error,
40 },
41 InvalidUserAgent(String),
43 BrowserAuthenticationFailed,
46 OAuthTokenExpired { token_hash: u64 },
49 OtherErrorCodeInResponse { code: u64, message: String },
53 ApiStatusFailed,
55 SystemTimeError { message: String },
57}
58#[derive(Debug, Clone)]
60pub enum ParseTarget {
61 Array,
62 Other(String),
63}
64impl Error {
65 pub fn into_kind(self) -> ErrorKind {
67 *self.inner
68 }
69 pub(crate) fn invalid_user_agent<S: Into<String>>(user_agent: S) -> Self {
70 Self {
71 inner: Box::new(ErrorKind::InvalidUserAgent(user_agent.into())),
72 }
73 }
74 pub(crate) fn oauth_token_expired(token: &crate::auth::OAuthToken) -> Self {
75 let mut h = std::hash::DefaultHasher::new();
76 token.hash(&mut h);
77 let token_hash = h.finish();
78 Self {
79 inner: Box::new(ErrorKind::OAuthTokenExpired { token_hash }),
80 }
81 }
82 pub(crate) fn browser_authentication_failed() -> Self {
83 Self {
84 inner: Box::new(ErrorKind::BrowserAuthenticationFailed),
85 }
86 }
87 pub(crate) fn header() -> Self {
88 Self {
89 inner: Box::new(ErrorKind::Header),
90 }
91 }
92 pub(crate) fn response<S: Into<String>>(response: S) -> Self {
93 let response = response.into();
94 Self {
95 inner: Box::new(ErrorKind::InvalidResponse { response }),
96 }
97 }
98 pub(crate) fn unable_to_serialize_oauth<S: Into<String>>(
99 response: S,
100 err: serde_json::Error,
101 ) -> Self {
102 let response = response.into();
103 Self {
104 inner: Box::new(ErrorKind::UnableToSerializeGoogleOAuthToken { response, err }),
105 }
106 }
107 pub(crate) fn other_code(code: u64, message: String) -> Self {
108 Self {
109 inner: Box::new(ErrorKind::OtherErrorCodeInResponse { code, message }),
110 }
111 }
112 pub(crate) fn status_failed() -> Self {
113 Self {
114 inner: Box::new(ErrorKind::ApiStatusFailed),
115 }
116 }
117 pub(crate) fn web(message: impl Into<String>) -> Self {
118 Self {
119 inner: Box::new(ErrorKind::Web {
120 message: message.into(),
121 }),
122 }
123 }
124}
125
126impl std::error::Error for Error {}
127impl Display for ErrorKind {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 match self {
130 ErrorKind::Web { message } => write!(f, "Web error <{message}> received."),
131 ErrorKind::Io(e) => write!(f, "IO error {e} recieved."),
132 ErrorKind::Header => write!(f, "Error parsing header."),
133 ErrorKind::InvalidResponse { response } => {
134 write!(
135 f,
136 "Response is invalid json - unable to deserialize. <{response}>"
137 )
138 }
139 ErrorKind::OtherErrorCodeInResponse { code, message } => {
140 write!(
141 f,
142 "Http error code {code} recieved in response. Message: <{message}>."
143 )
144 }
145 ErrorKind::ApiStatusFailed => write!(f, "Api returned STATUS_FAILED for the query"),
146 ErrorKind::OAuthTokenExpired { token_hash: _ } => write!(f, "OAuth token has expired"),
147 ErrorKind::InvalidUserAgent(u) => write!(f, "InnerTube rejected User Agent {u}"),
148 ErrorKind::BrowserAuthenticationFailed => write!(f, "Browser authentication failed"),
149 ErrorKind::UnableToSerializeGoogleOAuthToken { response, err } => write!(
150 f,
151 "Unable to serialize Google auth token {}, received error {}",
152 response, err
153 ),
154 ErrorKind::SystemTimeError { message } => write!(
155 f,
156 "Error obtaining system time to use in API query. <{message}>"
157 ),
158 ErrorKind::JsonParsing(e) => write!(f, "{e}"),
159 }
160 }
161}
162impl Debug for Error {
165 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166 Display::fmt(&*self.inner, f)
168 }
169}
170impl Display for Error {
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 Display::fmt(&*self.inner, f)
173 }
174}
175impl From<reqwest::Error> for Error {
176 fn from(err: reqwest::Error) -> Self {
177 let message = err.to_string();
178 Self {
179 inner: Box::new(ErrorKind::Web { message }),
180 }
181 }
182}
183impl From<io::Error> for Error {
184 fn from(err: io::Error) -> Self {
185 Self {
186 inner: Box::new(ErrorKind::Io(err)),
187 }
188 }
189}
190impl From<SystemTimeError> for Error {
191 fn from(err: SystemTimeError) -> Self {
192 let message = err.to_string();
193 Self {
194 inner: Box::new(ErrorKind::SystemTimeError { message }),
195 }
196 }
197}
198impl From<ErrorKind> for Error {
199 fn from(value: ErrorKind) -> Self {
200 Self {
201 inner: Box::new(value),
202 }
203 }
204}
205impl From<JsonError> for Error {
206 fn from(value: JsonError) -> Self {
207 let e = ErrorKind::JsonParsing(value);
208 Self { inner: Box::new(e) }
209 }
210}