Skip to main content

rustigram_api/
error.rs

1use thiserror::Error;
2
3/// Errors that can occur when interacting with the Telegram Bot API.
4#[derive(Debug, Error)]
5pub enum Error {
6    /// The Telegram API returned `ok: false`.
7    #[error("Telegram API error {error_code}: {description}")]
8    Api {
9        /// The HTTP error code returned by Telegram.
10        error_code: u16,
11        /// Human-readable description of the error.
12        description: String,
13        /// If set, the group was migrated to a supergroup with this ID.
14        migrate_to_chat_id: Option<i64>,
15        /// If set, retry the request after this many seconds.
16        retry_after: Option<u32>,
17    },
18
19    /// HTTP transport or network error.
20    #[error("HTTP error: {0}")]
21    Http(#[from] reqwest::Error),
22
23    /// Failed to serialise the request body.
24    #[error("Serialization error: {0}")]
25    Serialization(#[from] serde_json::Error),
26
27    /// The response body could not be decoded.
28    #[error("Response decode error: {0}")]
29    Decode(String),
30
31    /// Rate limit hit — caller should wait `retry_after` seconds before retrying.
32    #[error("Rate limited: retry after {retry_after}s")]
33    RateLimit {
34        /// Number of seconds to wait before retrying.
35        retry_after: u32,
36    },
37
38    /// The provided token format is invalid.
39    #[error("Invalid bot token format")]
40    InvalidToken,
41
42    /// A required parameter was missing.
43    #[error("Missing required parameter: {0}")]
44    MissingParam(&'static str),
45}
46
47impl Error {
48    /// Returns `true` if this is a flood-control error (429).
49    #[must_use]
50    pub fn is_rate_limit(&self) -> bool {
51        matches!(
52            self,
53            Self::RateLimit { .. }
54                | Self::Api {
55                    error_code: 429,
56                    ..
57                }
58        )
59    }
60
61    /// Extracts the `retry_after` value if available.
62    #[must_use]
63    pub fn retry_after(&self) -> Option<u32> {
64        match self {
65            Self::RateLimit { retry_after } => Some(*retry_after),
66            Self::Api { retry_after, .. } => *retry_after,
67            _ => None,
68        }
69    }
70
71    /// Returns `true` if the bot is blocked by the user.
72    #[must_use]
73    pub fn is_blocked(&self) -> bool {
74        matches!(self, Self::Api { error_code: 403, description, .. }
75            if description.contains("bot was blocked"))
76    }
77
78    /// Returns `true` if the chat was not found.
79    #[must_use]
80    pub fn is_chat_not_found(&self) -> bool {
81        matches!(self, Self::Api { error_code: 400, description, .. }
82            if description.contains("chat not found"))
83    }
84}
85
86/// A specialised `Result` type for rustigram API operations.
87pub type Result<T> = std::result::Result<T, Error>;