teloxide/src/net/telegram_response.rs
2021-01-07 16:01:46 +03:00

88 lines
2.7 KiB
Rust

use reqwest::StatusCode;
use serde::Deserialize;
use crate::{
requests::ResponseResult,
types::{False, ResponseParameters, True},
ApiError, RequestError,
};
#[derive(Deserialize)]
#[serde(untagged)]
pub(crate) enum TelegramResponse<R> {
Ok {
/// A dummy field. Used only for deserialization.
#[allow(dead_code)]
ok: True,
#[serde(rename = "result")]
response: R,
},
Err {
/// A dummy field. Used only for deserialization.
#[allow(dead_code)]
ok: False,
#[serde(rename = "description")]
error: ApiError,
error_code: u16,
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 {
error,
error_code,
response_parameters,
..
} => {
if let Some(params) = response_parameters {
match params {
ResponseParameters::RetryAfter(i) => Err(RequestError::RetryAfter(i)),
ResponseParameters::MigrateToChatId(to) => {
Err(RequestError::MigrateToChatId(to))
}
}
} else {
Err(RequestError::ApiError {
kind: error,
status_code: StatusCode::from_u16(error_code).unwrap(),
})
}
}
}
}
}
#[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")
);
}
}