tgbot/types/definitions/
response.rs1use std::{error::Error, fmt};
2
3use serde::Deserialize;
4
5use crate::types::Integer;
6
7#[derive(Clone, Debug, Deserialize)]
9#[serde(from = "RawResponse<T>")]
10pub enum Response<T> {
11 Success(T),
13 Error(ResponseError),
15}
16
17impl<T> Response<T> {
18 pub fn retry_after(&self) -> Option<u64> {
20 match self {
21 Response::Success(_) => None,
22 Response::Error(err) => err.retry_after(),
23 }
24 }
25
26 pub fn into_result(self) -> Result<T, ResponseError> {
28 match self {
29 Response::Success(obj) => Ok(obj),
30 Response::Error(err) => Err(err),
31 }
32 }
33}
34
35impl<T> From<RawResponse<T>> for Response<T> {
36 fn from(raw: RawResponse<T>) -> Self {
37 if raw.ok {
38 if let Some(result) = raw.result {
39 Response::Success(result)
40 } else {
41 Response::Error(ResponseError {
42 description: String::from("response is ok, but result is not provided"),
43 error_code: None,
44 migrate_to_chat_id: None,
45 retry_after: None,
46 })
47 }
48 } else {
49 Response::Error(ResponseError {
50 description: raw.description.unwrap_or_else(|| String::from("no description")),
51 error_code: raw.error_code,
52 migrate_to_chat_id: raw.parameters.and_then(|x| x.migrate_to_chat_id),
53 retry_after: raw.parameters.and_then(|x| x.retry_after),
54 })
55 }
56 }
57}
58
59#[derive(Clone, Debug)]
61pub struct ResponseError {
62 description: String,
63 error_code: Option<Integer>,
64 migrate_to_chat_id: Option<Integer>,
65 retry_after: Option<Integer>,
66}
67
68impl ResponseError {
69 pub fn description(&self) -> &str {
71 &self.description
72 }
73
74 pub fn error_code(&self) -> Option<Integer> {
76 self.error_code
77 }
78
79 pub fn can_retry(&self) -> bool {
81 self.retry_after.is_some()
82 }
83
84 pub fn retry_after(&self) -> Option<u64> {
86 self.retry_after.and_then(|x| x.try_into().ok())
87 }
88
89 pub fn migrate_to_chat_id(&self) -> Option<Integer> {
91 self.migrate_to_chat_id
92 }
93}
94
95impl Error for ResponseError {}
96
97impl fmt::Display for ResponseError {
98 fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
99 write!(out, "a telegram error has occurred: description={}", self.description)?;
100 if let Some(code) = self.error_code {
101 write!(out, "; error_code={code}")?;
102 }
103 if let Some(chat_id) = self.migrate_to_chat_id {
104 write!(out, "; migrate_to_chat_id={chat_id}")?;
105 }
106 if let Some(retry_after) = self.retry_after {
107 write!(out, "; retry_after={retry_after}")?;
108 }
109 Ok(())
110 }
111}
112
113#[derive(Clone, Debug, Deserialize)]
114struct RawResponse<T> {
115 ok: bool,
116 result: Option<T>,
117 description: Option<String>,
118 error_code: Option<Integer>,
119 parameters: Option<RawResponseParameters>,
120}
121
122#[derive(Clone, Copy, Debug, Deserialize)]
123struct RawResponseParameters {
124 migrate_to_chat_id: Option<Integer>,
125 retry_after: Option<Integer>,
126}