Skip to main content

archivist_core/
error.rs

1//! Error types for the bot.
2
3use thiserror::Error;
4
5/// Bot-wide error type. Every variant is platform-neutral.
6#[derive(Debug, Error)]
7pub enum BotError {
8    /// Outgoing HTTP request failed.
9    #[error("HTTP request failed: {0}")]
10    Http(#[from] reqwest::Error),
11    /// The API returned an explicit error code + message.
12    #[error("API returned error {err}: {msg}")]
13    Api {
14        /// FicHub API error code.
15        err: i32,
16        /// Human-readable error message.
17        msg: String,
18    },
19    /// The API returned a non-200 status with a raw body.
20    #[error("API returned non-200 status {status}: {body}")]
21    Status {
22        /// HTTP status code.
23        status: u16,
24        /// Raw response body.
25        body: String,
26    },
27    /// JSON deserialization failed.
28    #[error("JSON parse failed: {0}")]
29    Json(#[from] serde_json::Error),
30    /// Redis operation failed.
31    #[error("Redis error: {0}")]
32    Redis(#[from] redis::RedisError),
33    /// The user has no linked FicHub account.
34    #[error("Not linked: run /link to connect your FicHub account")]
35    NotLinked,
36    /// Bad or missing configuration.
37    #[error("Configuration error: {0}")]
38    Config(String),
39    /// Invalid command usage.
40    #[error("Command error: {0}")]
41    Command(String),
42    /// Rate limited by a shared Redis bucket.
43    #[error("Rate limited — retry in {retry_after_secs}s")]
44    RateLimited {
45        /// Seconds to wait before retrying.
46        retry_after_secs: u64,
47    },
48    /// Anything else.
49    #[error("Internal error: {0}")]
50    Other(String),
51}
52
53/// Convenience alias.
54pub type Result<T> = std::result::Result<T, BotError>;