pub type Result<T> = std::result::Result<T, SlackError>;
#[derive(Debug, thiserror::Error)]
pub enum SlackError {
#[error("HTTP request failed: {0}")]
HttpError(#[from] reqwest::Error),
#[error("Slack API error: {code} - {message}")]
ApiError { code: String, message: String },
#[error("JSON error: {0}")]
JsonError(#[from] serde_json::Error),
#[error("WebSocket error: {0}")]
WebSocketError(String),
#[error("Authentication error: {0}")]
AuthError(String),
#[error("Configuration error: {0}")]
ConfigError(String),
#[error("Invalid parameter: {0}")]
InvalidParameter(String),
#[error("Rate limit exceeded. Retry after {retry_after} seconds")]
RateLimitExceeded { retry_after: u64 },
#[error("Resource not found: {0}")]
NotFound(String),
#[error("Permission denied: {0}")]
PermissionDenied(String),
#[error("{0}")]
Other(String),
}
impl SlackError {
pub fn api_error(code: impl Into<String>, message: impl Into<String>) -> Self {
Self::ApiError {
code: code.into(),
message: message.into(),
}
}
pub fn websocket_error(msg: impl Into<String>) -> Self {
Self::WebSocketError(msg.into())
}
pub fn auth_error(msg: impl Into<String>) -> Self {
Self::AuthError(msg.into())
}
pub fn config_error(msg: impl Into<String>) -> Self {
Self::ConfigError(msg.into())
}
pub fn is_rate_limit(&self) -> bool {
matches!(self, SlackError::RateLimitExceeded { .. })
}
pub fn is_auth_error(&self) -> bool {
matches!(self, SlackError::AuthError(_))
}
}
impl From<tokio_tungstenite::tungstenite::Error> for SlackError {
fn from(err: tokio_tungstenite::tungstenite::Error) -> Self {
SlackError::WebSocketError(err.to_string())
}
}