use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("Telegram API error {error_code}: {description}")]
Api {
error_code: u16,
description: String,
migrate_to_chat_id: Option<i64>,
retry_after: Option<u32>,
},
#[error("HTTP error: {0}")]
Http(#[from] reqwest::Error),
#[error("Serialization error: {0}")]
Serialization(#[from] serde_json::Error),
#[error("Response decode error: {0}")]
Decode(String),
#[error("Rate limited: retry after {retry_after}s")]
RateLimit {
retry_after: u32,
},
#[error("Invalid bot token format")]
InvalidToken,
#[error("Missing required parameter: {0}")]
MissingParam(&'static str),
}
impl Error {
#[must_use]
pub fn is_rate_limit(&self) -> bool {
matches!(
self,
Self::RateLimit { .. }
| Self::Api {
error_code: 429,
..
}
)
}
#[must_use]
pub fn retry_after(&self) -> Option<u32> {
match self {
Self::RateLimit { retry_after } => Some(*retry_after),
Self::Api { retry_after, .. } => *retry_after,
_ => None,
}
}
#[must_use]
pub fn is_blocked(&self) -> bool {
matches!(self, Self::Api { error_code: 403, description, .. }
if description.contains("bot was blocked"))
}
#[must_use]
pub fn is_chat_not_found(&self) -> bool {
matches!(self, Self::Api { error_code: 400, description, .. }
if description.contains("chat not found"))
}
}
pub type Result<T> = std::result::Result<T, Error>;