use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[non_exhaustive]
#[derive(Debug, Error)]
pub enum Error {
#[cfg(feature = "reqwest")]
#[error("http transport error: {0}")]
Http(#[from] reqwest::Error),
#[error("matomo api error in {method}: {message}")]
Api {
message: String,
method: &'static str,
kind: ApiErrorKind,
},
#[error("failed to decode {method} response: {source}")]
Decode {
#[source]
source: serde_json::Error,
method: &'static str,
},
#[error("non-json body from {method}: {body}")]
NonJsonBody { method: &'static str, body: String },
#[error("configuration error: {0}")]
Config(String),
#[error("preflight failed: {0}")]
Preflight(String),
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ApiErrorKind {
Auth,
UnknownMethod,
InvalidParam,
RateLimited,
NoData,
Other,
}
impl ApiErrorKind {
pub(crate) fn classify(message: &str) -> Self {
let m = message.to_ascii_lowercase();
if m.contains("token_auth")
|| m.contains("authentication")
|| m.contains("not allowed")
|| m.contains("permission")
{
ApiErrorKind::Auth
} else if m.contains("method") && (m.contains("not exist") || m.contains("not found")) {
ApiErrorKind::UnknownMethod
} else if m.contains("requires") || m.contains("parameter") || m.contains("invalid") {
ApiErrorKind::InvalidParam
} else if m.contains("rate") && m.contains("limit") {
ApiErrorKind::RateLimited
} else if m.contains("no data") {
ApiErrorKind::NoData
} else {
ApiErrorKind::Other
}
}
}