Merge pull request #10 from Mr-Andersen/dev

Dev
This commit is contained in:
Temirkhan Myrzamadi 2019-09-04 23:27:06 +06:00 committed by GitHub
commit 8ec055b0f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 155 additions and 79 deletions

View file

@ -1,33 +1,83 @@
use crate::core::types::{ChatPermissions, ChatPhoto, Message};
#[derive(Debug, Deserialize, Eq, Hash, PartialEq)]
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct Chat {
#[serde(rename = "chat_id")]
pub id: i32,
#[serde(flatten)]
pub type_: ChatType,
#[serde(skip_serializing_if = "Option::is_none")]
pub photo: Option<ChatPhoto>,
}
#[derive(Debug, Deserialize, Eq, Hash, PartialEq)]
struct PrivateChatTypeVisitor;
impl<'de> serde::de::Visitor<'de> for PrivateChatTypeVisitor {
type Value = ();
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, r#"field equal to "private""#)
}
fn visit_borrowed_str<E: serde::de::Error>(
self,
v: &'de str,
) -> Result<Self::Value, E> {
match v {
"private" => Ok(()),
_ => Err(E::invalid_value(
serde::de::Unexpected::Str(v),
&r#""private""#,
)),
}
}
}
fn assert_private_field<'de, D: serde::Deserializer<'de>>(
des: D,
) -> Result<(), D::Error> {
des.deserialize_str(PrivateChatTypeVisitor)
}
fn serialize_private_field<S: serde::Serializer>(
_: &(),
ser: S,
) -> Result<S::Ok, S::Error> {
ser.serialize_str("private")
}
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
#[serde(untagged)]
pub enum ChatType {
NotPrivate {
#[serde(skip_serializing_if = "Option::is_none")]
title: Option<String>,
#[serde(flatten)]
type_: NotPrivateChatType,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
invite_link: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pinned_message: Option<Box<Message>>,
},
Private {
/// Dummy field. Used to ensure that "type" field is equal to "private"
#[serde(rename = "type")]
#[serde(deserialize_with = "assert_private_field")]
#[serde(serialize_with = "serialize_private_field")]
type_: (),
#[serde(skip_serializing_if = "Option::is_none")]
username: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
first_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
last_name: Option<String>,
},
}
#[derive(Debug, Deserialize, Eq, Hash, PartialEq)]
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "type")]
pub enum NotPrivateChatType {
@ -45,25 +95,72 @@ pub enum NotPrivateChatType {
},
}
#[test]
fn test_chat_de() {
use serde_json::from_str;
#[cfg(test)]
mod tests {
use crate::core::types::*;
use serde_json::{from_str, to_string};
assert_eq!(
Chat {
id: 0,
type_: ChatType::NotPrivate {
title: None,
type_: NotPrivateChatType::Channel {
username: Some("channelname".into())
#[test]
fn channel_de() {
assert_eq!(
Chat {
id: -1,
type_: ChatType::NotPrivate {
title: None,
type_: NotPrivateChatType::Channel {
username: Some("channelname".into())
},
description: None,
invite_link: None,
pinned_message: None
},
description: None,
invite_link: None,
pinned_message: None,
photo: None,
},
photo: None,
},
from_str(r#"{"id":0,"type":"channel","username":"channelname"}"#)
from_str(
r#"{"chat_id":-1,"type":"channel","username":"channelname"}"#
)
.unwrap()
);
);
}
#[test]
fn private_chat_de() {
assert_eq!(
Chat {
id: 0,
type_: ChatType::Private {
type_: (),
username: Some("username".into()),
first_name: Some("Anon".into()),
last_name: None
},
photo: None
},
from_str(
r#"{"chat_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());
}
#[test]
fn private_chat_ser() {
assert_eq!(
to_string(&Chat {
id: 0,
type_: ChatType::Private {
type_: (),
username: None,
first_name: None,
last_name: None
},
photo: None
})
.unwrap(),
r#"{"chat_id":0,"type":"private"}"#.to_owned()
);
}
}

View file

@ -1,4 +1,4 @@
#[derive(Debug, Deserialize, Hash, PartialEq, Eq)]
#[derive(Debug, Deserialize, Hash, PartialEq, Eq, Serialize)]
pub struct ChatPermissions {
pub can_send_messages: Option<bool>,
pub can_send_media_messages: Option<bool>,

View file

@ -1,4 +1,4 @@
#[derive(Debug, Deserialize, Hash, PartialEq, Eq)]
#[derive(Debug, Deserialize, Hash, PartialEq, Eq, Serialize)]
pub struct ChatPhoto {
pub small_file_id: String,
pub big_file_id: String,

View file

@ -4,53 +4,17 @@ use crate::core::types::{
SuccessfulPayment, User, Venue, Video, VideoNote, Voice,
};
#[derive(Debug, Deserialize, Eq, Hash, PartialEq)]
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct Message {
pub message_id: i64,
pub from: Option<Box<User>>,
pub date: i64,
#[serde(rename = "message_id")]
pub id: i32,
pub date: i32,
pub chat: Chat,
pub forward_from: Option<User>,
pub forward_from_chat: Option<Chat>,
pub forward_from_message_id: Option<i64>,
pub forward_signature: Option<String>,
pub forward_sender_name: Option<String>,
pub forward_date: Option<i64>,
pub reply_to_message: Option<Box<Message>>,
pub edit_date: Option<i64>,
pub media_group_id: Option<String>,
pub author_signature: Option<String>,
pub text: Option<String>,
pub entities: Option<Vec<MessageEntity>>,
pub caption_entities: Option<Vec<MessageEntity>>,
pub audio: Option<Audio>,
pub document: Option<Document>,
pub animation: Option<Animation>,
pub game: Option<Game>,
pub photo: Option<Vec<PhotoSize>>,
pub sticker: Option<Sticker>,
pub video: Option<Video>,
pub voice: Option<Voice>,
pub video_note: Option<VideoNote>,
pub caption: Option<String>,
pub contact: Option<Contact>,
pub location: Option<Location>,
pub venue: Option<Venue>,
pub poll: Option<Poll>,
pub new_chat_members: Option<Vec<User>>,
pub left_chat_member: Option<User>,
pub new_chat_title: Option<String>,
pub new_chat_photo: Option<Vec<PhotoSize>>,
pub delete_chat_photo: Option<bool>,
pub group_chat_created: Option<bool>,
pub supergroup_chat_created: Option<bool>,
pub channel_chat_created: Option<bool>,
pub migrate_to_chat_id: Option<i64>,
pub migrate_from_chat_id: Option<i64>,
pub pinned_message: Option<Box<Message>>,
pub invoice: Option<Invoice>,
pub successful_payment: Option<SuccessfulPayment>,
pub connected_website: Option<String>,
pub passport_data: Option<PassportData>,
pub reply_markup: Option<InlineKeyboardMarkup>,
#[serde(flatten)]
pub type_: MessageType,
}
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
#[serde(untagged)]
pub enum MessageType {}

View file

@ -1,16 +1,31 @@
use self::not_implemented_types::*;
pub use self::{
answer_pre_checkout_query::AnswerPreCheckoutQuery,
answer_shipping_query::AnswerShippingQuery, audio::Audio, chat::Chat,
chat_member::ChatMember, chat_permissions::ChatPermissions,
chat_photo::ChatPhoto, document::Document, input_file::InputFile,
input_media::InputMedia, invoice::Invoice, label_price::LabeledPrice,
message::Message, message_entity::MessageEntity, order_info::OrderInfo,
parse_mode::ParseMode, photo_size::PhotoSize,
pre_checkout_query::PreCheckoutQuery, send_invoice::SendInvoice,
shipping_address::ShippingAddress, shipping_option::ShippingOption,
shipping_query::ShippingQuery, sticker::Sticker,
successful_payment::SuccessfulPayment, user::User, video::Video,
answer_shipping_query::AnswerShippingQuery,
audio::Audio,
chat::{Chat, ChatType, NotPrivateChatType},
chat_member::ChatMember,
chat_permissions::ChatPermissions,
chat_photo::ChatPhoto,
document::Document,
input_file::InputFile,
input_media::InputMedia,
invoice::Invoice,
label_price::LabeledPrice,
message::Message,
message_entity::MessageEntity,
order_info::OrderInfo,
parse_mode::ParseMode,
photo_size::PhotoSize,
pre_checkout_query::PreCheckoutQuery,
send_invoice::SendInvoice,
shipping_address::ShippingAddress,
shipping_option::ShippingOption,
shipping_query::ShippingQuery,
sticker::Sticker,
successful_payment::SuccessfulPayment,
user::User,
video::Video,
};
mod answer_pre_checkout_query;