mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-22 14:35:36 +01:00
Properly parse telegram answer
This commit is contained in:
parent
c3052ed036
commit
dc755b6ec0
8 changed files with 82 additions and 46 deletions
|
@ -1,10 +1,19 @@
|
|||
use apply::Apply;
|
||||
use reqwest::r#async::{multipart::Form, Client};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde_json::Value;
|
||||
use crate::core::{
|
||||
requests::{RequestError, ResponseResult},
|
||||
types::ResponseParameters,
|
||||
};
|
||||
|
||||
use apply::Apply;
|
||||
use serde_json::Value;
|
||||
use serde::{
|
||||
Serialize,
|
||||
de::DeserializeOwned
|
||||
};
|
||||
use reqwest::{
|
||||
StatusCode,
|
||||
r#async::{Client, multipart::Form},
|
||||
};
|
||||
|
||||
use crate::core::requests::{RequestError, ResponseResult};
|
||||
use serde::Serialize;
|
||||
|
||||
const TELEGRAM_API_URL: &str = "https://api.telegram.org";
|
||||
|
||||
|
@ -48,7 +57,7 @@ pub async fn request_multipart<T: DeserializeOwned>(
|
|||
.await
|
||||
.map_err(RequestError::NetworkError)?;
|
||||
|
||||
let response_json = serde_json::from_str::<Value>(
|
||||
let response = serde_json::from_str::<TelegramResponse<T>>(
|
||||
&response
|
||||
.text()
|
||||
.await
|
||||
|
@ -56,13 +65,14 @@ pub async fn request_multipart<T: DeserializeOwned>(
|
|||
)
|
||||
.map_err(RequestError::InvalidJson)?;
|
||||
|
||||
if response_json["ok"] == "false" {
|
||||
Err(RequestError::ApiError {
|
||||
status_code: response.status(),
|
||||
description: response_json["description"].to_string(),
|
||||
})
|
||||
} else {
|
||||
Ok(serde_json::from_value(response_json["result"].clone()).unwrap())
|
||||
match response {
|
||||
TelegramResponse::Ok { result, .. } => Ok(result),
|
||||
TelegramResponse::Err {
|
||||
description,
|
||||
error_code,
|
||||
response_parameters,
|
||||
..
|
||||
} => Err(RequestError::ApiError { description, status_code: StatusCode::from_u16(error_code).unwrap() })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +89,7 @@ pub async fn request_json<T: DeserializeOwned, P: Serialize>(
|
|||
.await
|
||||
.map_err(RequestError::NetworkError)?;
|
||||
|
||||
let response_json = serde_json::from_str::<Value>(
|
||||
let response = serde_json::from_str::<TelegramResponse<T>>(
|
||||
&response
|
||||
.text()
|
||||
.await
|
||||
|
@ -87,16 +97,32 @@ pub async fn request_json<T: DeserializeOwned, P: Serialize>(
|
|||
)
|
||||
.map_err(RequestError::InvalidJson)?;
|
||||
|
||||
if response_json["ok"] == "false" {
|
||||
Err(RequestError::ApiError {
|
||||
status_code: response.status(),
|
||||
description: response_json["description"].to_string(),
|
||||
})
|
||||
} else {
|
||||
Ok(serde_json::from_value(response_json["result"].clone()).unwrap())
|
||||
match response {
|
||||
TelegramResponse::Ok { result, .. } => Ok(result),
|
||||
TelegramResponse::Err {
|
||||
description,
|
||||
error_code,
|
||||
response_parameters,
|
||||
..
|
||||
} => Err(RequestError::ApiError { description, status_code: StatusCode::from_u16(error_code).unwrap() })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum TelegramResponse<R> {
|
||||
Ok {
|
||||
ok: bool, // true
|
||||
result: R,
|
||||
},
|
||||
Err {
|
||||
ok: bool, // false
|
||||
description: String,
|
||||
error_code: u16,
|
||||
response_parameters: Option<ResponseParameters>,
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -37,14 +37,14 @@ impl<'a> Request<'a> for ForwardMessage<'a> {
|
|||
type ReturnValue = Message;
|
||||
|
||||
fn send(self) -> RequestFuture<'a, ResponseResult<Self::ReturnValue>> {
|
||||
Box::pin(
|
||||
Box::pin(async move {
|
||||
network::request_json(
|
||||
self.ctx.client,
|
||||
self.ctx.token,
|
||||
"forwardMessage",
|
||||
&self,
|
||||
)
|
||||
)
|
||||
).await
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ mod utils;
|
|||
#[derive(Debug, Display)]
|
||||
pub enum RequestError {
|
||||
#[display(fmt = "Telegram error #{}: {}", status_code, description)]
|
||||
ApiError {
|
||||
ApiError { // TODO: add response parameters
|
||||
status_code: StatusCode,
|
||||
description: String,
|
||||
},
|
||||
|
|
|
@ -52,25 +52,25 @@ impl<'a> Request<'a> for SendMessage<'a> {
|
|||
type ReturnValue = Message;
|
||||
|
||||
fn send(self) -> RequestFuture<'a, ResponseResult<Self::ReturnValue>> {
|
||||
Box::pin(
|
||||
Box::pin(async move {
|
||||
network::request_json(
|
||||
self.ctx.client,
|
||||
self.ctx.token,
|
||||
"sendMessage",
|
||||
&self,
|
||||
)
|
||||
)
|
||||
).await
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SendMessage<'a> {
|
||||
pub(crate) fn new(
|
||||
info: RequestContext<'a>,
|
||||
ctx: RequestContext<'a>,
|
||||
chat_id: ChatId,
|
||||
text: String,
|
||||
) -> Self {
|
||||
SendMessage {
|
||||
ctx: info,
|
||||
ctx,
|
||||
chat_id,
|
||||
text,
|
||||
parse_mode: None,
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::core::types::{ChatPermissions, ChatPhoto, Message};
|
|||
|
||||
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Clone)]
|
||||
pub struct Chat {
|
||||
#[serde(rename = "chat_id")]
|
||||
pub id: i64,
|
||||
#[serde(flatten)]
|
||||
pub kind: ChatKind,
|
||||
|
@ -103,7 +102,7 @@ mod tests {
|
|||
photo: None,
|
||||
};
|
||||
let actual = from_str(
|
||||
r#"{"chat_id":-1,"type":"channel","username":"channelname"}"#,
|
||||
r#"{"id":-1,"type":"channel","username":"channelname"}"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(expected, actual);
|
||||
|
@ -123,12 +122,12 @@ mod tests {
|
|||
photo: None
|
||||
},
|
||||
from_str(
|
||||
r#"{"chat_id":0,"type":"private","username":"username","first_name":"Anon"}"#
|
||||
r#"{"id":0,"type":"private","username":"username","first_name":"Anon"}"#
|
||||
).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn private_chat_de_wrong_type_field() {
|
||||
assert!(from_str::<Chat>(r#"{"chat_id":0,"type":"WRONG"}"#).is_err());
|
||||
assert!(from_str::<Chat>(r#"{"id":0,"type":"WRONG"}"#).is_err());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ mod tests {
|
|||
reply_markup: None,
|
||||
},
|
||||
};
|
||||
let actual = from_str::<Message>(r#"{"message_id":0,"date":0,"chat":{"chat_id":0,"type":"private"},"text":"Hello","entities":[]}"#).unwrap();
|
||||
let actual = from_str::<Message>(r#"{"message_id":0,"date":0,"chat":{"id":0,"type":"private"},"text":"Hello","entities":[]}"#).unwrap();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
|
@ -230,9 +230,17 @@ mod tests {
|
|||
},
|
||||
};
|
||||
let actual = from_str::<Message>(
|
||||
r#"{"message_id":1,"date":1,"chat":{"chat_id":1,"type":"private"},"forward_date":1,"forward_from":{"id":123,"is_bot":false,"first_name":"Name"},"text":"Message","entities":[]}"#,
|
||||
r#"{"message_id":1,"date":1,"chat":{"id":1,"type":"private"},"forward_date":1,"forward_from":{"id":123,"is_bot":false,"first_name":"Name"},"text":"Message","entities":[]}"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sent_message_de() {
|
||||
// actual message from telegram
|
||||
let json = "{\"message_id\":6534,\"from\":{\"id\":457569668,\"is_bot\":true,\"first_name\":\"\\u0424\\u044b\\u0440\\u044c\\u043a\",\"username\":\"BloodyTestBot\"},\"chat\":{\"id\":218485655,\"first_name\":\"\\u0412\\u0430\\u0444\\u0435\\u043b\\u044c\",\"username\":\"WaffleLapkin\",\"type\":\"private\"},\"date\":1567898953,\"text\":\"text\"}";
|
||||
let actual: Result<Message, _>= from_str(json);
|
||||
assert!(actual.is_ok());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ pub use self::{
|
|||
successful_payment::SuccessfulPayment,
|
||||
user::User,
|
||||
video::Video,
|
||||
response_parameters::ResponseParameters
|
||||
};
|
||||
|
||||
mod answer_pre_checkout_query;
|
||||
|
@ -55,3 +56,4 @@ mod sticker;
|
|||
mod successful_payment;
|
||||
mod user;
|
||||
mod video;
|
||||
mod response_parameters;
|
|
@ -1,5 +1,4 @@
|
|||
#[derive(Debug, Deserialize, Hash, PartialEq, Eq, Clone)]
|
||||
#[serde(tag = "type")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ResponseParameters {
|
||||
MigrateToChatId(i64),
|
||||
|
@ -8,23 +7,25 @@ pub enum ResponseParameters {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn migrate_to_chat_id_deserialization() {
|
||||
let expected_struct = ResponseParameters::MigrateToChatId(123456);
|
||||
let actual_json: ResponseParameters = serde_json::from_str(
|
||||
let expected = ResponseParameters::MigrateToChatId(123456);
|
||||
let actual: ResponseParameters = serde_json::from_str(
|
||||
r#"{"migrate_to_chat_id":123456}"#
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn retry_after_deserialization() {
|
||||
let expected_struct = ResponseParameters::RetryAfter(123456);
|
||||
let actual_json: ResponseParameters = serde_json::from_str(
|
||||
let expected = ResponseParameters::RetryAfter(123456);
|
||||
let actual: ResponseParameters = serde_json::from_str(
|
||||
r#"{"retry_after":123456}"#
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue