1use serde::{Deserialize, Serialize};
4use thiserror::Error;
5
6pub type Result<T> = std::result::Result<T, Error>;
8
9#[derive(Error, Debug)]
11pub enum Error {
12 #[error("HTTP request failed: {0}")]
14 Request(#[from] reqwest::Error),
15
16 #[error("JSON error: {0}")]
18 Json(#[from] serde_json::Error),
19
20 #[error("URL parse error: {0}")]
22 UrlParse(#[from] url::ParseError),
23
24 #[error("API error: {message} (code: {code})")]
26 Api {
27 code: i32,
28 message: String,
29 error_subcode: Option<i32>,
30 error_data: Option<ApiErrorData>,
31 },
32
33 #[error("Rate limit exceeded. Retry after {retry_after:?} seconds")]
35 RateLimited { retry_after: Option<u64> },
36
37 #[error("Invalid or expired access token")]
39 InvalidToken,
40
41 #[error("Media upload failed: {0}")]
43 MediaUpload(String),
44
45 #[error("Invalid phone number format: {0}")]
47 InvalidPhoneNumber(String),
48
49 #[error("Message not sent: {0}")]
51 MessageNotSent(String),
52
53 #[error("IO error: {0}")]
55 Io(#[from] std::io::Error),
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct ApiErrorData {
61 pub messaging_product: Option<String>,
63 pub details: Option<String>,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct ApiErrorResponse {
70 pub error: ApiError,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct ApiError {
77 pub message: String,
79 #[serde(rename = "type")]
81 pub error_type: Option<String>,
82 pub code: i32,
84 pub error_subcode: Option<i32>,
86 pub error_user_title: Option<String>,
88 pub error_user_msg: Option<String>,
90 pub fbtrace_id: Option<String>,
92 pub error_data: Option<ApiErrorData>,
94}
95
96impl From<ApiErrorResponse> for Error {
97 fn from(response: ApiErrorResponse) -> Self {
98 let err = response.error;
99
100 match err.code {
102 190 => Error::InvalidToken,
103 4 | 17 | 32 | 613 => Error::RateLimited { retry_after: None },
104 _ => Error::Api {
105 code: err.code,
106 message: err.message,
107 error_subcode: err.error_subcode,
108 error_data: err.error_data,
109 },
110 }
111 }
112}