1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use serde::Deserialize;
use crate::{
requests::ResponseResult,
types::{False, ResponseParameters, True},
ApiError, RequestError,
};
#[derive(Deserialize)]
#[serde(untagged)]
pub(crate) enum TelegramResponse<R> {
Ok {
#[allow(dead_code)]
ok: True,
#[serde(rename = "result")]
response: R,
},
Err {
#[allow(dead_code)]
ok: False,
#[serde(rename = "description")]
error: ApiError,
#[serde(rename = "parameters")]
response_parameters: Option<ResponseParameters>,
},
}
impl<R> From<TelegramResponse<R>> for ResponseResult<R> {
fn from(this: TelegramResponse<R>) -> ResponseResult<R> {
match this {
TelegramResponse::Ok { response, .. } => Ok(response),
TelegramResponse::Err {
response_parameters: Some(params),
..
} => Err(match params {
ResponseParameters::RetryAfter(i) => RequestError::RetryAfter(i),
ResponseParameters::MigrateToChatId(to) => RequestError::MigrateToChatId(to),
}),
TelegramResponse::Err { error, .. } => Err(RequestError::Api(error)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{errors::ApiError, types::Update};
#[test]
fn parse_terminated_by_other_get_updates() {
let s = r#"{"ok":false,"error_code":409,"description":"Conflict: terminated by other getUpdates request; make sure that only one bot instance is running"}"#;
let val = serde_json::from_str::<TelegramResponse<Update>>(s).unwrap();
assert!(matches!(
val,
TelegramResponse::Err {
error: ApiError::TerminatedByOtherGetUpdates,
..
}
));
}
#[test]
fn parse_unknown() {
let s = r#"{"ok":false,"error_code":111,"description":"Unknown description that won't match anything"}"#;
let val = serde_json::from_str::<TelegramResponse<Update>>(s).unwrap();
assert!(
matches!(val, TelegramResponse::Err { error: ApiError::Unknown(s), .. } if s == "Unknown description that won't match anything")
);
}
}