From 7ba2737a13a6857e94398d9d10827400ca60fe50 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 21 Sep 2019 05:03:37 +0600 Subject: [PATCH 01/30] Add the Telegram Passport API Types --- src/network/download.rs | 3 +- src/types/encrypted_credintials.rs | 35 ++++++++++++ src/types/encrypted_passport_element.rs | 73 +++++++++++++++++++++++++ src/types/mod.rs | 10 ++++ src/types/passport_data.rs | 73 +++++++++++++++++++++++++ src/types/passport_file.rs | 6 ++ 6 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 src/types/encrypted_credintials.rs create mode 100644 src/types/encrypted_passport_element.rs create mode 100644 src/types/passport_data.rs create mode 100644 src/types/passport_file.rs diff --git a/src/network/download.rs b/src/network/download.rs index a57d3fff..31cbbb36 100644 --- a/src/network/download.rs +++ b/src/network/download.rs @@ -23,7 +23,8 @@ where let mut stream = download_file_stream(client, token, path).await?; while let Some(chunk) = stream.next().await { - destination.write_all(chunk?.bytes()).await?; + let chunk = chunk?; + destination.write_all(chunk.bytes()).await?; } Ok(()) diff --git a/src/types/encrypted_credintials.rs b/src/types/encrypted_credintials.rs new file mode 100644 index 00000000..184993cf --- /dev/null +++ b/src/types/encrypted_credintials.rs @@ -0,0 +1,35 @@ +#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Clone, Serialize)] +pub struct EncryptedCredentials { + // TODO: check base64 type + pub data: String, + pub hash: String, + pub secret: String, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn must_serialize_encrypted_credentials_to_json() { + // given + let expected_json = r#" + { + "data":"someData", + "hash":"1122", + "secret":"secret" + }"# + .replace("\n", "") + .replace(" ", ""); + let encrypted_credentials = EncryptedCredentials { + data: "someData".to_string(), + hash: "1122".to_string(), + secret: "secret".to_string(), + }; + // when + let actual_json = + serde_json::to_string(&encrypted_credentials).unwrap(); + //then + assert_eq!(actual_json, expected_json) + } +} diff --git a/src/types/encrypted_passport_element.rs b/src/types/encrypted_passport_element.rs new file mode 100644 index 00000000..54bcbbc4 --- /dev/null +++ b/src/types/encrypted_passport_element.rs @@ -0,0 +1,73 @@ +use super::passport_file::PassportFile; + +#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Clone, Serialize)] +pub struct EncryptedPassportElement { + #[serde(rename = "type")] + pub element_type: ElementType, + pub data: String, + pub phone_number: String, + pub email: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub files: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub front_size: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub reverse_side: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub selfie: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub translation: Option>, +} + +#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Clone, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum ElementType { + PersonalData, + Passport, + DriverLicense, + IdentityCard, + Address, + UtilityBill, + BankStatement, + RentalAgreement, + PassportRegistration, + TemporaryRegistration, + PhoneNumber, + Email, +} + +mod tests { + #[test] + fn must_serialize_encrypted_passport_element_to_json() { + // given + let expected_json = r#" + { + "type":"passport_registration", + "data":"somedata", + "phone_number":"1313", + "email":"someemail", + "files":null, + "front_size":{"file_id":"someId","file_size":13,"file_date":13}, + "reverse_side":null, + "selfie":null, + "translation":null + }"# + .replace("\n", "") + .replace(" ", ""); + + let passport_element = EncryptedPassportElement { + element_type: ElementType::PassportRegistration, + data: "somedata".to_string(), + phone_number: "1313".to_string(), + email: "someemail".to_string(), + files: None, + front_size: Some(create_passport_file()), + reverse_side: None, + selfie: None, + translation: None, + }; + + let actual_json = serde_json::to_string(&passport_element).unwrap(); + assert_eq!(actual_json, expected_json) + } +} diff --git a/src/types/mod.rs b/src/types/mod.rs index 1533e3bb..b2b70abb 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -76,6 +76,11 @@ pub use self::{ video_note::VideoNote, voice::Voice, webhook_info::WebhookInfo, + + encrypted_passport_element::{ElementType, EncryptedPassportElement}, + passport_data::PassportData, + encrypted_credintials::EncryptedCredentials, + passport_file::PassportFile, }; mod animation; @@ -154,3 +159,8 @@ mod inline_query_result_photo; mod inline_query_result_venue; mod inline_query_result_video; mod inline_query_result_voice; + +mod encrypted_passport_element; +mod passport_data; +mod encrypted_credintials; +mod passport_file; \ No newline at end of file diff --git a/src/types/passport_data.rs b/src/types/passport_data.rs new file mode 100644 index 00000000..8214b679 --- /dev/null +++ b/src/types/passport_data.rs @@ -0,0 +1,73 @@ +use super::encrypted_credintials::EncryptedCredentials; +use super::encrypted_passport_element::EncryptedPassportElement; + +#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Clone, Serialize)] +pub struct PassportData { + pub data: Vec, + pub credentials: EncryptedCredentials, +} + +#[cfg(test)] +mod tests { + use super::super::{ElementType, PassportFile}; + use super::*; + + #[test] + fn should_serialize_passport_data_to_json() { + // given + let expected_json = r#"{ + "data": + [ + { + "type":"passport_registration", + "data":"somedata", + "phone_number":"1313", + "email":"someemail", + "files":null, + "front_size": + { + "file_id":"someId", + "file_size":13, + "file_date":13 + }, + "reverse_side":null, + "selfie":null, + "translation":null + } + ], + "credential": + { + "data":"someData", + "hash":"1122", + "secret":"secret" + } + }"# + .replace("\n", "") + .replace(" ", ""); + let passport_data = PassportData { + data: vec![EncryptedPassportElement { + element_type: ElementType::PassportRegistration, + data: "somedata".to_string(), + phone_number: "1313".to_string(), + email: "someemail".to_string(), + files: None, + front_size: Some(PassportFile { + file_id: "someId".to_string(), + file_size: 13, + file_date: 13, + }), + reverse_side: None, + selfie: None, + translation: None, + }], + credentials: EncryptedCredentials { + data: "someData".to_string(), + hash: "1122".to_string(), + secret: "secret".to_string(), + }, + }; + + let actual_json = serde_json::to_string(&passport_data).unwrap(); + assert_eq!(actual_json, expected_json) + } +} diff --git a/src/types/passport_file.rs b/src/types/passport_file.rs new file mode 100644 index 00000000..116f3685 --- /dev/null +++ b/src/types/passport_file.rs @@ -0,0 +1,6 @@ +#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Clone, Serialize)] +pub struct PassportFile { + pub file_id: String, + pub file_size: u64, + pub file_date: u64, +} \ No newline at end of file From 788006f4277e6baab6e60fd47932dd8a1c65d720 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 21 Sep 2019 05:05:39 +0600 Subject: [PATCH 02/30] Fix the errors --- src/types/encrypted_passport_element.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/types/encrypted_passport_element.rs b/src/types/encrypted_passport_element.rs index 54bcbbc4..95503532 100644 --- a/src/types/encrypted_passport_element.rs +++ b/src/types/encrypted_passport_element.rs @@ -36,7 +36,9 @@ pub enum ElementType { Email, } +#[cfg(test)] mod tests { + use super::super::{ElementType, EncryptedPassportElement, PassportFile}; #[test] fn must_serialize_encrypted_passport_element_to_json() { // given @@ -61,7 +63,11 @@ mod tests { phone_number: "1313".to_string(), email: "someemail".to_string(), files: None, - front_size: Some(create_passport_file()), + front_size: Some(PassportFile { + file_id: "someId".to_string(), + file_size: 13, + file_date: 13, + }), reverse_side: None, selfie: None, translation: None, From 6b0e05cdf74795b9ede7e9ed9325302f946040ca Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 21 Sep 2019 05:05:48 +0600 Subject: [PATCH 03/30] Format the code --- src/network/download.rs | 2 +- src/network/request.rs | 2 +- src/types/mod.rs | 13 ++++++------- src/types/passport_file.rs | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/network/download.rs b/src/network/download.rs index 31cbbb36..96bc646e 100644 --- a/src/network/download.rs +++ b/src/network/download.rs @@ -1,10 +1,10 @@ +use bytes::Buf; use futures::StreamExt; use reqwest::r#async::{Chunk, Client}; use tokio::{ io::{AsyncWrite, AsyncWriteExt}, stream::Stream, }; -use bytes::Buf; use crate::{ network::{file_url, TELEGRAM_API_URL}, diff --git a/src/network/request.rs b/src/network/request.rs index 0faf04c0..b068a5a0 100644 --- a/src/network/request.rs +++ b/src/network/request.rs @@ -3,7 +3,7 @@ use reqwest::r#async::{multipart::Form, Client, Response}; use serde::{de::DeserializeOwned, Serialize}; use crate::{ - network::{method_url, TELEGRAM_API_URL, TelegramResponse}, + network::{method_url, TelegramResponse, TELEGRAM_API_URL}, requests::ResponseResult, RequestError, }; diff --git a/src/types/mod.rs b/src/types/mod.rs index b2b70abb..893d492f 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -11,6 +11,8 @@ pub use self::{ chosen_inline_result::ChosenInlineResult, contact::Contact, document::Document, + encrypted_credintials::EncryptedCredentials, + encrypted_passport_element::{ElementType, EncryptedPassportElement}, file::File, force_reply::ForceReply, game::Game, @@ -54,6 +56,8 @@ pub use self::{ message_entity::MessageEntity, order_info::OrderInfo, parse_mode::ParseMode, + passport_data::PassportData, + passport_file::PassportFile, photo_size::PhotoSize, poll::{Poll, PollOption}, pre_checkout_query::PreCheckoutQuery, @@ -76,11 +80,6 @@ pub use self::{ video_note::VideoNote, voice::Voice, webhook_info::WebhookInfo, - - encrypted_passport_element::{ElementType, EncryptedPassportElement}, - passport_data::PassportData, - encrypted_credintials::EncryptedCredentials, - passport_file::PassportFile, }; mod animation; @@ -160,7 +159,7 @@ mod inline_query_result_venue; mod inline_query_result_video; mod inline_query_result_voice; +mod encrypted_credintials; mod encrypted_passport_element; mod passport_data; -mod encrypted_credintials; -mod passport_file; \ No newline at end of file +mod passport_file; diff --git a/src/types/passport_file.rs b/src/types/passport_file.rs index 116f3685..1aee85a7 100644 --- a/src/types/passport_file.rs +++ b/src/types/passport_file.rs @@ -3,4 +3,4 @@ pub struct PassportFile { pub file_id: String, pub file_size: u64, pub file_date: u64, -} \ No newline at end of file +} From 5ea1673903f4ce03c72b2556a0e3341a45d14376 Mon Sep 17 00:00:00 2001 From: Waffle Date: Sat, 21 Sep 2019 02:07:05 +0300 Subject: [PATCH 04/30] Fix `request::` imports (&cargo fmt) --- src/bot/api.rs | 9 ++-- src/network/download.rs | 2 +- src/network/request.rs | 2 +- src/requests/get_user_profile_photos.rs | 2 +- src/requests/kick_chat_member.rs | 2 +- src/requests/mod.rs | 60 ++++++++++++++++--------- src/requests/restrict_chat_member.rs | 2 +- src/requests/unban_chat_member.rs | 2 +- 8 files changed, 47 insertions(+), 34 deletions(-) diff --git a/src/bot/api.rs b/src/bot/api.rs index 37efa01f..d10d83b1 100644 --- a/src/bot/api.rs +++ b/src/bot/api.rs @@ -1,12 +1,9 @@ use crate::{ bot::Bot, requests::{ - edit_message_live_location::EditMessageLiveLocation, - forward_message::ForwardMessage, get_file::GetFile, get_me::GetMe, - send_audio::SendAudio, send_location::SendLocation, - send_media_group::SendMediaGroup, send_message::SendMessage, - send_photo::SendPhoto, - stop_message_live_location::StopMessageLiveLocation, ChatId, + ChatId, EditMessageLiveLocation, ForwardMessage, GetFile, GetMe, + SendAudio, SendLocation, SendMediaGroup, SendMessage, SendPhoto, + StopMessageLiveLocation, }, types::{InputFile, InputMedia}, }; diff --git a/src/network/download.rs b/src/network/download.rs index a57d3fff..c50d7f44 100644 --- a/src/network/download.rs +++ b/src/network/download.rs @@ -1,10 +1,10 @@ +use bytes::Buf; use futures::StreamExt; use reqwest::r#async::{Chunk, Client}; use tokio::{ io::{AsyncWrite, AsyncWriteExt}, stream::Stream, }; -use bytes::Buf; use crate::{ network::{file_url, TELEGRAM_API_URL}, diff --git a/src/network/request.rs b/src/network/request.rs index 0faf04c0..b068a5a0 100644 --- a/src/network/request.rs +++ b/src/network/request.rs @@ -3,7 +3,7 @@ use reqwest::r#async::{multipart::Form, Client, Response}; use serde::{de::DeserializeOwned, Serialize}; use crate::{ - network::{method_url, TELEGRAM_API_URL, TelegramResponse}, + network::{method_url, TelegramResponse, TELEGRAM_API_URL}, requests::ResponseResult, RequestError, }; diff --git a/src/requests/get_user_profile_photos.rs b/src/requests/get_user_profile_photos.rs index 7123151b..5feca84e 100644 --- a/src/requests/get_user_profile_photos.rs +++ b/src/requests/get_user_profile_photos.rs @@ -5,7 +5,7 @@ use crate::requests::RequestContext; ///Use this method to get a list of profile pictures for a user. Returns a /// UserProfilePhotos object. #[derive(Debug, Clone, Serialize)] -struct GetUserProfilePhotos<'a> { +pub struct GetUserProfilePhotos<'a> { #[serde(skip_serializing)] ctx: RequestContext<'a>, /// Unique identifier of the target user diff --git a/src/requests/kick_chat_member.rs b/src/requests/kick_chat_member.rs index b33616ce..baabe494 100644 --- a/src/requests/kick_chat_member.rs +++ b/src/requests/kick_chat_member.rs @@ -6,7 +6,7 @@ use crate::requests::RequestContext; /// bot must be an administrator in the chat for this to work and must have the /// appropriate admin rights. Returns True on success. #[derive(Debug, Clone, Serialize)] -struct KickChatMember<'a> { +pub struct KickChatMember<'a> { #[serde(skip_serializing)] ctx: RequestContext<'a>, } diff --git a/src/requests/mod.rs b/src/requests/mod.rs index 0c793a52..3eef8f34 100644 --- a/src/requests/mod.rs +++ b/src/requests/mod.rs @@ -7,6 +7,22 @@ use std::{future::Future, pin::Pin}; use crate::RequestError; +pub use self::{ + answer_pre_checkout_query::AnswerPreCheckoutQuery, + answer_shipping_query::AnswerShippingQuery, + edit_message_live_location::EditMessageLiveLocation, + forward_message::ForwardMessage, get_chat::GetChat, get_file::GetFile, + get_me::GetMe, get_updates::GetUpdates, + get_user_profile_photos::GetUserProfilePhotos, + kick_chat_member::KickChatMember, restrict_chat_member::RestrictChatMember, + send_audio::SendAudio, send_chat_action::SendChatAction, + send_contact::SendContact, send_location::SendLocation, + send_media_group::SendMediaGroup, send_message::SendMessage, + send_photo::SendPhoto, send_poll::SendPoll, send_venue::SendVenue, + stop_message_live_location::StopMessageLiveLocation, + unban_chat_member::UnbanChatMember, +}; + pub type ResponseResult = Result; /// Request that can be sent to telegram. @@ -63,25 +79,25 @@ mod tests { } } -pub mod answer_pre_checkout_query; -pub mod answer_shipping_query; -pub mod edit_message_live_location; -pub mod forward_message; -pub mod get_chat; -pub mod get_file; -pub mod get_me; -pub mod get_updates; -pub mod get_user_profile_photos; -pub mod kick_chat_member; -pub mod restrict_chat_member; -pub mod send_audio; -pub mod send_chat_action; -pub mod send_contact; -pub mod send_location; -pub mod send_media_group; -pub mod send_message; -pub mod send_photo; -pub mod send_poll; -pub mod send_venue; -pub mod stop_message_live_location; -pub mod unban_chat_member; +mod answer_pre_checkout_query; +mod answer_shipping_query; +mod edit_message_live_location; +mod forward_message; +mod get_chat; +mod get_file; +mod get_me; +mod get_updates; +mod get_user_profile_photos; +mod kick_chat_member; +mod restrict_chat_member; +mod send_audio; +mod send_chat_action; +mod send_contact; +mod send_location; +mod send_media_group; +mod send_message; +mod send_photo; +mod send_poll; +mod send_venue; +mod stop_message_live_location; +mod unban_chat_member; diff --git a/src/requests/restrict_chat_member.rs b/src/requests/restrict_chat_member.rs index 6957922b..781dead6 100644 --- a/src/requests/restrict_chat_member.rs +++ b/src/requests/restrict_chat_member.rs @@ -2,7 +2,7 @@ use crate::requests::RequestContext; //TODO:: need implementation #[derive(Debug, Clone, Serialize)] -struct RestrictChatMember<'a> { +pub struct RestrictChatMember<'a> { #[serde(skip_serializing)] ctx: RequestContext<'a>, } diff --git a/src/requests/unban_chat_member.rs b/src/requests/unban_chat_member.rs index d7a9b436..ffaace92 100644 --- a/src/requests/unban_chat_member.rs +++ b/src/requests/unban_chat_member.rs @@ -2,7 +2,7 @@ use crate::requests::RequestContext; //TODO:: need implementation #[derive(Debug, Clone, Serialize)] -struct UnbanChatMember<'a> { +pub struct UnbanChatMember<'a> { #[serde(skip_serializing)] ctx: RequestContext<'a>, } From ed1d3cd56ed4ba627a791aa281ce12a5d4ac248f Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 21 Sep 2019 05:25:15 +0600 Subject: [PATCH 05/30] Fix a few tests --- src/types/encrypted_passport_element.rs | 6 +----- src/types/passport_data.rs | 7 +------ 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/types/encrypted_passport_element.rs b/src/types/encrypted_passport_element.rs index 95503532..0a013bf1 100644 --- a/src/types/encrypted_passport_element.rs +++ b/src/types/encrypted_passport_element.rs @@ -48,11 +48,7 @@ mod tests { "data":"somedata", "phone_number":"1313", "email":"someemail", - "files":null, - "front_size":{"file_id":"someId","file_size":13,"file_date":13}, - "reverse_side":null, - "selfie":null, - "translation":null + "front_size":{"file_id":"someId","file_size":13,"file_date":13} }"# .replace("\n", "") .replace(" ", ""); diff --git a/src/types/passport_data.rs b/src/types/passport_data.rs index 8214b679..8bcad91b 100644 --- a/src/types/passport_data.rs +++ b/src/types/passport_data.rs @@ -13,8 +13,7 @@ mod tests { use super::*; #[test] - fn should_serialize_passport_data_to_json() { - // given + fn must_serialize_passport_data_to_json() { let expected_json = r#"{ "data": [ @@ -23,16 +22,12 @@ mod tests { "data":"somedata", "phone_number":"1313", "email":"someemail", - "files":null, "front_size": { "file_id":"someId", "file_size":13, "file_date":13 }, - "reverse_side":null, - "selfie":null, - "translation":null } ], "credential": From 74f816c616734d4e23d7547fa19a83bec1c9c17f Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 21 Sep 2019 05:34:26 +0600 Subject: [PATCH 06/30] Fix the tests --- src/types/passport_data.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types/passport_data.rs b/src/types/passport_data.rs index 8bcad91b..9c7ffc89 100644 --- a/src/types/passport_data.rs +++ b/src/types/passport_data.rs @@ -27,10 +27,10 @@ mod tests { "file_id":"someId", "file_size":13, "file_date":13 - }, + } } ], - "credential": + "credentials": { "data":"someData", "hash":"1122", From a447c26837e1a8096e94491f657a0e4bf1d151c9 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 21 Sep 2019 05:39:27 +0600 Subject: [PATCH 07/30] 'mod errors' + 'pub use errors' (src/lib.rs) --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index d35d2e98..34052315 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,9 +4,9 @@ extern crate derive_more; extern crate serde; mod network; +mod errors; pub mod bot; -pub mod errors; pub mod requests; pub mod types; From 8211838fe92f0f5d9f6a4f97b387a93ccf1acfc9 Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Sat, 21 Sep 2019 10:48:34 +0300 Subject: [PATCH 08/30] +PinChatMessage --- src/core/requests/mod.rs | 1 + src/core/requests/pin_chat_message.rs | 32 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/core/requests/pin_chat_message.rs diff --git a/src/core/requests/mod.rs b/src/core/requests/mod.rs index a1dfa82f..d04e113a 100644 --- a/src/core/requests/mod.rs +++ b/src/core/requests/mod.rs @@ -97,6 +97,7 @@ pub mod get_file; pub mod get_me; pub mod get_user_profile_photos; pub mod kick_chat_member; +pub mod pin_chat_message; pub mod restrict_chat_member; pub mod send_audio; pub mod send_chat_action; diff --git a/src/core/requests/pin_chat_message.rs b/src/core/requests/pin_chat_message.rs new file mode 100644 index 00000000..c1481d38 --- /dev/null +++ b/src/core/requests/pin_chat_message.rs @@ -0,0 +1,32 @@ +use crate::core::requests::{ChatId, RequestContext, RequestFuture, ResponseResult, Request}; +use crate::core::network; + +/// Use this method to get up to date information about the chat +/// (current name of the user for one-on-one conversations, +/// current username of a user, group or channel, etc.). +/// Returns a Chat object on success. +#[derive(Debug, Clone, Serialize)] +pub struct PinChatMessage<'a> { + #[serde(skip_serializing)] + ctx: RequestContext<'a>, + /// Unique identifier for the target chat or username + /// of the target supergroup or channel (in the format @channelusername) + chat_id: ChatId, + message_id: i32, + disable_notification: bool +} + +impl<'a> Request<'a> for PinChatMessage<'a> { + type ReturnValue = bool; + + fn send(self) -> RequestFuture<'a, ResponseResult> { + Box::pin(async move { + network::request_json( + &self.ctx.client, + &self.ctx.token, + "pinChatMessage", + &self, + ).await + }) + } +} From fc68705d71b67cc6b96f1737626f2c252f36cdfd Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Sat, 21 Sep 2019 11:38:58 +0300 Subject: [PATCH 09/30] +EncryptedPassportElement --- src/requests/pin_chat_message.rs | 17 +++- src/types/encrypted_passport_element.rs | 128 +++++++++++------------- src/types/message.rs | 2 +- src/types/mod.rs | 2 +- 4 files changed, 77 insertions(+), 72 deletions(-) diff --git a/src/requests/pin_chat_message.rs b/src/requests/pin_chat_message.rs index c1481d38..6f5db2a6 100644 --- a/src/requests/pin_chat_message.rs +++ b/src/requests/pin_chat_message.rs @@ -1,5 +1,5 @@ -use crate::core::requests::{ChatId, RequestContext, RequestFuture, ResponseResult, Request}; -use crate::core::network; +use crate::requests::{ChatId, RequestContext, RequestFuture, ResponseResult, Request}; +use crate::network; /// Use this method to get up to date information about the chat /// (current name of the user for one-on-one conversations, @@ -16,6 +16,19 @@ pub struct PinChatMessage<'a> { disable_notification: bool } +impl<'a> PinChatMessage<'a> { + pub(crate) fn new( + ctx: RequestContext<'a>, chat_id: ChatId, message_id: i32 + ) -> Self { + Self { ctx, chat_id, message_id, disable_notification: false } + } + + pub fn disable_notification(mut self) -> Self { + self.disable_notification = true; + self + } +} + impl<'a> Request<'a> for PinChatMessage<'a> { type ReturnValue = bool; diff --git a/src/types/encrypted_passport_element.rs b/src/types/encrypted_passport_element.rs index 0a013bf1..dbb3a6de 100644 --- a/src/types/encrypted_passport_element.rs +++ b/src/types/encrypted_passport_element.rs @@ -1,75 +1,67 @@ use super::passport_file::PassportFile; -#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Clone, Serialize)] +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct EncryptedPassportElement { - #[serde(rename = "type")] - pub element_type: ElementType, - pub data: String, - pub phone_number: String, - pub email: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub files: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub front_size: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub reverse_side: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub selfie: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub translation: Option>, + pub hash: String, + #[serde(flatten)] + pub kind: EncryptedPassportElementKind } -#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Clone, Serialize)] +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] #[serde(rename_all = "snake_case")] -pub enum ElementType { - PersonalData, - Passport, - DriverLicense, - IdentityCard, - Address, - UtilityBill, - BankStatement, - RentalAgreement, - PassportRegistration, - TemporaryRegistration, - PhoneNumber, - Email, -} - -#[cfg(test)] -mod tests { - use super::super::{ElementType, EncryptedPassportElement, PassportFile}; - #[test] - fn must_serialize_encrypted_passport_element_to_json() { - // given - let expected_json = r#" - { - "type":"passport_registration", - "data":"somedata", - "phone_number":"1313", - "email":"someemail", - "front_size":{"file_id":"someId","file_size":13,"file_date":13} - }"# - .replace("\n", "") - .replace(" ", ""); - - let passport_element = EncryptedPassportElement { - element_type: ElementType::PassportRegistration, - data: "somedata".to_string(), - phone_number: "1313".to_string(), - email: "someemail".to_string(), - files: None, - front_size: Some(PassportFile { - file_id: "someId".to_string(), - file_size: 13, - file_date: 13, - }), - reverse_side: None, - selfie: None, - translation: None, - }; - - let actual_json = serde_json::to_string(&passport_element).unwrap(); - assert_eq!(actual_json, expected_json) - } +pub enum EncryptedPassportElementKind { + PersonalDetails { + data: String + }, + Passport { + data: String, + front_side: PassportFile, + selfie: PassportFile, + translation: Vec + }, + DriverLicense { + data: String, + front_side: PassportFile, + reverse_side: PassportFile, + selfie: PassportFile, + translation: Vec + }, + IdentityCard { + data: String, + front_side: PassportFile, + reverse_side: PassportFile, + selfie: PassportFile, + translation: Vec + }, + InternalPassport { + data: String, + front_side: PassportFile, + selfie: PassportFile, + translation: Vec + }, + Address { + data: String + }, + UtilityBill { + files: Vec, + translation: Vec + }, + BankStatement { + files: Vec, + translation: Vec + }, + RentalAgreement { + files: Vec, + translation: Vec + }, + PassportRegistration { + files: Vec, + translation: Vec + }, + TemporaryRegistration { + files: Vec, + translation: Vec + }, + PhoneNumber { phone_number: String }, + Email { email: String } } diff --git a/src/types/message.rs b/src/types/message.rs index 905d79d4..2bc8a102 100644 --- a/src/types/message.rs +++ b/src/types/message.rs @@ -15,7 +15,7 @@ pub struct Message { } impl Message { - fn text(&self) -> Option<&str> { + pub fn text(&self) -> Option<&str> { if let MessageKind::Common { media_kind: MediaKind::Text { ref text, .. }, .. diff --git a/src/types/mod.rs b/src/types/mod.rs index 893d492f..2c1c221b 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -12,7 +12,7 @@ pub use self::{ contact::Contact, document::Document, encrypted_credintials::EncryptedCredentials, - encrypted_passport_element::{ElementType, EncryptedPassportElement}, + encrypted_passport_element::{EncryptedPassportElement, EncryptedPassportElementKind}, file::File, force_reply::ForceReply, game::Game, From b7e0a1c7d1849b6f30e3793b6527248fcfafe721 Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Sat, 21 Sep 2019 11:52:59 +0300 Subject: [PATCH 10/30] In EncryptedMessageElementKind::translation: Vec<_> -> Option> --- src/types/encrypted_passport_element.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/types/encrypted_passport_element.rs b/src/types/encrypted_passport_element.rs index dbb3a6de..61b1fa47 100644 --- a/src/types/encrypted_passport_element.rs +++ b/src/types/encrypted_passport_element.rs @@ -17,50 +17,50 @@ pub enum EncryptedPassportElementKind { data: String, front_side: PassportFile, selfie: PassportFile, - translation: Vec + translation: Option> }, DriverLicense { data: String, front_side: PassportFile, reverse_side: PassportFile, selfie: PassportFile, - translation: Vec + translation: Option> }, IdentityCard { data: String, front_side: PassportFile, reverse_side: PassportFile, selfie: PassportFile, - translation: Vec + translation: Option> }, InternalPassport { data: String, front_side: PassportFile, selfie: PassportFile, - translation: Vec + translation: Option> }, Address { data: String }, UtilityBill { files: Vec, - translation: Vec + translation: Option> }, BankStatement { files: Vec, - translation: Vec + translation: Option> }, RentalAgreement { files: Vec, - translation: Vec + translation: Option> }, PassportRegistration { files: Vec, - translation: Vec + translation: Option> }, TemporaryRegistration { files: Vec, - translation: Vec + translation: Option> }, PhoneNumber { phone_number: String }, Email { email: String } From 02d97966676bc3770285609202e1d3f905e4d4a9 Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Sat, 21 Sep 2019 12:05:13 +0300 Subject: [PATCH 11/30] request/PinChatMessage pub fixes --- src/requests/pin_chat_message.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/requests/pin_chat_message.rs b/src/requests/pin_chat_message.rs index 6f5db2a6..8f8a955c 100644 --- a/src/requests/pin_chat_message.rs +++ b/src/requests/pin_chat_message.rs @@ -11,9 +11,9 @@ pub struct PinChatMessage<'a> { ctx: RequestContext<'a>, /// Unique identifier for the target chat or username /// of the target supergroup or channel (in the format @channelusername) - chat_id: ChatId, - message_id: i32, - disable_notification: bool + pub chat_id: ChatId, + pub message_id: i32, + pub disable_notification: bool } impl<'a> PinChatMessage<'a> { From b0aff65f71b2517a11ca5115270316c765181248 Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Sat, 21 Sep 2019 12:08:19 +0300 Subject: [PATCH 12/30] request/PinChatMessage added TODO --- src/requests/pin_chat_message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/requests/pin_chat_message.rs b/src/requests/pin_chat_message.rs index 8f8a955c..5b9ddfde 100644 --- a/src/requests/pin_chat_message.rs +++ b/src/requests/pin_chat_message.rs @@ -30,7 +30,7 @@ impl<'a> PinChatMessage<'a> { } impl<'a> Request<'a> for PinChatMessage<'a> { - type ReturnValue = bool; + type ReturnValue = bool; // TODO: change to unit type True fn send(self) -> RequestFuture<'a, ResponseResult> { Box::pin(async move { From b500296ed60501297af82288cfaaf1e792db03b7 Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Sat, 21 Sep 2019 12:18:42 +0300 Subject: [PATCH 13/30] `pub use`d requests/PinChatMessage in requests/mod --- src/requests/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/requests/mod.rs b/src/requests/mod.rs index ede9b45a..04c2251b 100644 --- a/src/requests/mod.rs +++ b/src/requests/mod.rs @@ -14,7 +14,8 @@ pub use self::{ forward_message::ForwardMessage, get_chat::GetChat, get_file::GetFile, get_me::GetMe, get_updates::GetUpdates, get_user_profile_photos::GetUserProfilePhotos, - kick_chat_member::KickChatMember, restrict_chat_member::RestrictChatMember, + kick_chat_member::KickChatMember, pin_chat_message::PinChatMessage, + restrict_chat_member::RestrictChatMember, send_audio::SendAudio, send_chat_action::SendChatAction, send_contact::SendContact, send_location::SendLocation, send_media_group::SendMediaGroup, send_message::SendMessage, From c3f543786d35495e141751189ef69a0b0bd2ba31 Mon Sep 17 00:00:00 2001 From: nextel Date: Sat, 21 Sep 2019 20:03:57 +0300 Subject: [PATCH 14/30] add get user profile photos action --- src/requests/get_user_profile_photos.rs | 49 +++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/requests/get_user_profile_photos.rs b/src/requests/get_user_profile_photos.rs index 5feca84e..619dde88 100644 --- a/src/requests/get_user_profile_photos.rs +++ b/src/requests/get_user_profile_photos.rs @@ -1,7 +1,7 @@ -use crate::requests::RequestContext; +use crate::network; +use crate::requests::{Request, RequestContext, RequestFuture, ResponseResult}; +use crate::types::UserProfilePhotos; -//TODO: complete implementation after user_profile_fotos will be added to -// types/mod.rs ///Use this method to get a list of profile pictures for a user. Returns a /// UserProfilePhotos object. #[derive(Debug, Clone, Serialize)] @@ -17,3 +17,46 @@ pub struct GetUserProfilePhotos<'a> { /// accepted. Defaults to 100. limit: Option, } + +impl<'a> Request<'a> for GetUserProfilePhotos<'a> { + type ReturnValue = UserProfilePhotos; + + fn send(self) -> RequestFuture<'a, ResponseResult> { + Box::pin(async move { + network::request_json( + &self.ctx.client, + &self.ctx.token, + "getUserProfilePhotos", + &self, + ) + .await + }) + } +} + +impl<'a> GetUserProfilePhotos<'a> { + pub fn new(ctx: RequestContext<'a>, user_id: i32) -> Self { + Self { + ctx, + user_id, + offset: None, + limit: None, + } + } + + pub fn user_id(mut self, user_id: T) -> Self + where + T: Into, + { + self.user_id = user_id.into(); + self + } + + pub fn offset(mut self, offset: T) -> Self + where + T: Into, + { + self.offset = Some(offset.into()); + self + } +} From 23f2b9494d58ad963b3335427bbfe4e086ff6cfd Mon Sep 17 00:00:00 2001 From: nextel Date: Sat, 21 Sep 2019 20:08:06 +0300 Subject: [PATCH 15/30] add action template --- src/requests/kick_chat_member.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/requests/kick_chat_member.rs b/src/requests/kick_chat_member.rs index baabe494..a07f2252 100644 --- a/src/requests/kick_chat_member.rs +++ b/src/requests/kick_chat_member.rs @@ -9,4 +9,8 @@ use crate::requests::RequestContext; pub struct KickChatMember<'a> { #[serde(skip_serializing)] ctx: RequestContext<'a>, + + chat_id Integer or String Yes Unique identifier for the target group or username of the target supergroup or channel (in the format @channelusername) + user_id Integer Yes Unique identifier of the target user + until_date Integer Optional Date when the user will be unbanned, unix time. If user is banned for more than 366 days or less than 30 seconds from the current time they are considered to be banned forever } From 3443942cf9b5e9d8999fc7749b67a06886e9f447 Mon Sep 17 00:00:00 2001 From: nextel Date: Sat, 21 Sep 2019 20:09:35 +0300 Subject: [PATCH 16/30] fix optional value --- src/requests/get_user_profile_photos.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/requests/get_user_profile_photos.rs b/src/requests/get_user_profile_photos.rs index 619dde88..9e84d935 100644 --- a/src/requests/get_user_profile_photos.rs +++ b/src/requests/get_user_profile_photos.rs @@ -12,9 +12,11 @@ pub struct GetUserProfilePhotos<'a> { user_id: i32, /// Sequential number of the first photo to be returned. By default, all /// photos are returned. + #[serde(skip_serializing_if = "Option::is_none")] offset: Option, ///Limits the number of photos to be retrieved. Values between 1—100 are /// accepted. Defaults to 100. + #[serde(skip_serializing_if = "Option::is_none")] limit: Option, } @@ -59,4 +61,13 @@ impl<'a> GetUserProfilePhotos<'a> { self.offset = Some(offset.into()); self } + + pub fn limit(mut self, limit: T) -> Self + where + T: Into, + { + self.limit = Some(limit.into()); + self + } + } From 57e3b217786a8513419dfe2e861d9555a305de35 Mon Sep 17 00:00:00 2001 From: nextel Date: Sat, 21 Sep 2019 20:10:25 +0300 Subject: [PATCH 17/30] add pub modifcators for filds --- src/requests/get_user_profile_photos.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/requests/get_user_profile_photos.rs b/src/requests/get_user_profile_photos.rs index 9e84d935..722b919a 100644 --- a/src/requests/get_user_profile_photos.rs +++ b/src/requests/get_user_profile_photos.rs @@ -9,15 +9,15 @@ pub struct GetUserProfilePhotos<'a> { #[serde(skip_serializing)] ctx: RequestContext<'a>, /// Unique identifier of the target user - user_id: i32, + pub user_id: i32, /// Sequential number of the first photo to be returned. By default, all /// photos are returned. #[serde(skip_serializing_if = "Option::is_none")] - offset: Option, + pub offset: Option, ///Limits the number of photos to be retrieved. Values between 1—100 are /// accepted. Defaults to 100. #[serde(skip_serializing_if = "Option::is_none")] - limit: Option, + pub limit: Option, } impl<'a> Request<'a> for GetUserProfilePhotos<'a> { From 62b26fe14f96719b0a34477b3426d37821fb6d2d Mon Sep 17 00:00:00 2001 From: nextel Date: Sat, 21 Sep 2019 20:20:14 +0300 Subject: [PATCH 18/30] add kickChatMember action --- src/requests/kick_chat_member.rs | 66 +++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/src/requests/kick_chat_member.rs b/src/requests/kick_chat_member.rs index a07f2252..fe762ab4 100644 --- a/src/requests/kick_chat_member.rs +++ b/src/requests/kick_chat_member.rs @@ -1,5 +1,8 @@ -use crate::requests::RequestContext; -//TODO:: need implementation +use crate::network; +use crate::requests::{ + ChatId, Request, RequestContext, RequestFuture, ResponseResult, +}; + /// Use this method to kick a user from a group, a supergroup or a channel. In /// the case of supergroups and channels, the user will not be able to return to /// the group on their own using invite links, etc., unless unbanned first. The @@ -9,8 +12,59 @@ use crate::requests::RequestContext; pub struct KickChatMember<'a> { #[serde(skip_serializing)] ctx: RequestContext<'a>, - - chat_id Integer or String Yes Unique identifier for the target group or username of the target supergroup or channel (in the format @channelusername) - user_id Integer Yes Unique identifier of the target user - until_date Integer Optional Date when the user will be unbanned, unix time. If user is banned for more than 366 days or less than 30 seconds from the current time they are considered to be banned forever + ///Unique identifier for the target group or username of the target + /// supergroup or channel (in the format @channelusername) + pub chat_id: ChatId, + /// Unique identifier of the target user + pub user_id: i32, + ///Date when the user will be unbanned, unix time. If user is banned for + /// more than 366 days or less than 30 seconds from the current time they + /// are considered to be banned forever + pub until_date: Option, +} + +impl<'a> Request<'a> for KickChatMember<'a> { + type ReturnValue = bool; + + fn send(self) -> RequestFuture<'a, ResponseResult> { + Box::pin(async move { + network::request_json( + self.ctx.client, + self.ctx.token, + "kickChatMember", + &self, + ) + .await + }) + } +} + +impl<'a> KickChatMember<'a> { + pub(crate) fn new( + ctx: RequestContext<'a>, + chat_id: ChatId, + user_id: i32, + ) -> Self { + Self { + ctx, + chat_id, + user_id, + until_date: None, + } + } + + pub fn chat_id>(mut self, chat_id: T) -> Self { + self.chat_id = chat_id.into(); + self + } + + pub fn user_id>(mut self, user_id: T) -> Self { + self.user_id = user_id.into(); + self + } + + pub fn until_date>(mut self, until_date: T) -> Self { + self.until_date = Some(user_id.into()); + self + } } From a777b3a8055385a67f28e5ce31c6ea46c2743b67 Mon Sep 17 00:00:00 2001 From: nextel Date: Sat, 21 Sep 2019 20:39:58 +0300 Subject: [PATCH 19/30] add action template --- src/requests/restrict_chat_member.rs | 87 +++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 2 deletions(-) diff --git a/src/requests/restrict_chat_member.rs b/src/requests/restrict_chat_member.rs index 781dead6..62bf8f29 100644 --- a/src/requests/restrict_chat_member.rs +++ b/src/requests/restrict_chat_member.rs @@ -1,8 +1,91 @@ -use crate::requests::RequestContext; -//TODO:: need implementation +use crate::network; +use crate::requests::{ + ChatId, Request, RequestContext, RequestFuture, ResponseResult, +}; +use crate::types::ChatPermissions; +/// Use this method to restrict a user in a supergroup. The bot must be an +/// administrator in the supergroup for this to work and must have the +/// appropriate admin rights. Pass True for all permissions to lift restrictions +/// from a user. Returns True on success. #[derive(Debug, Clone, Serialize)] pub struct RestrictChatMember<'a> { #[serde(skip_serializing)] ctx: RequestContext<'a>, + ///Unique identifier for the target chat or username of the target + /// supergroup (in the format @supergroupusername) + pub chat_id: ChatId, + ///Unique identifier of the target user + pub user_id: i32, + ///New user permissions + pub permissions: ChatPermissions, + ///Date when restrictions will be lifted for the user, unix time. If user + /// is restricted for more than 366 days or less than 30 seconds from the + /// current time, they are considered to be restricted forever + pub until_date: Option, +} + +impl<'a> Request<'a> for RestrictChatMember<'a> { + type ReturnValue = bool; + + fn send(self) -> RequestFuture<'a, ResponseResult> { + Box::pin(async move { + network::request_json( + &self.ctx.client, + &self.ctx.token, + "restrictChatMember", + &self, + ) + .await + }) + } +} + +impl<'a> RestrictChatMember<'a> { + pub(crate) fn new( + ctx: RequestContext<'a>, + chat_id: ChatId, + user_id: i32, + permissions: ChatPermissions, + ) -> Self { + Self { + ctx, + chat_id, + user_id, + permissions, + until_date: None, + } + } + + pub fn chat_id(mut self, chat_id: T) -> Self + where + T: Into, + { + self.chat_id = chat_id.into(); + self + } + + pub fn user_id(mut self, user_id: T) -> Self + where + T: Into, + { + self.user_id = user_id.into(); + self + } + + pub fn permissions(mut self, permissions: T) -> Self + where + T: Into, + { + self.permissions = permissions.into(); + self + } + + pub fn until_date(mut self, until_date: T) -> Self + where + T: Into, + { + self.until_date = Some(until_date.into()); + self + } } From 774c481faf4fdb400e3cfc36e83e7819273435be Mon Sep 17 00:00:00 2001 From: nextel Date: Sat, 21 Sep 2019 20:41:31 +0300 Subject: [PATCH 20/30] fix build error --- src/requests/kick_chat_member.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/requests/kick_chat_member.rs b/src/requests/kick_chat_member.rs index fe762ab4..ea590d59 100644 --- a/src/requests/kick_chat_member.rs +++ b/src/requests/kick_chat_member.rs @@ -64,7 +64,7 @@ impl<'a> KickChatMember<'a> { } pub fn until_date>(mut self, until_date: T) -> Self { - self.until_date = Some(user_id.into()); + self.until_date = Some(until_date.into()); self } } From 7736ba3ca8ad33ee4044867fbf45d6a6adc9f0b6 Mon Sep 17 00:00:00 2001 From: nextel Date: Sun, 22 Sep 2019 17:03:12 +0300 Subject: [PATCH 21/30] add serde derive for optional field --- src/requests/kick_chat_member.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/requests/kick_chat_member.rs b/src/requests/kick_chat_member.rs index ea590d59..2ed54f0a 100644 --- a/src/requests/kick_chat_member.rs +++ b/src/requests/kick_chat_member.rs @@ -20,6 +20,7 @@ pub struct KickChatMember<'a> { ///Date when the user will be unbanned, unix time. If user is banned for /// more than 366 days or less than 30 seconds from the current time they /// are considered to be banned forever + #[serde(skip_serializing_if = "Option::is_none")] pub until_date: Option, } From a63fe51171b490ada49c2649f468a220a9a832d6 Mon Sep 17 00:00:00 2001 From: nextel Date: Sun, 22 Sep 2019 17:05:30 +0300 Subject: [PATCH 22/30] add skip serialization for opt value --- src/requests/restrict_chat_member.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/requests/restrict_chat_member.rs b/src/requests/restrict_chat_member.rs index 62bf8f29..dabfb9c1 100644 --- a/src/requests/restrict_chat_member.rs +++ b/src/requests/restrict_chat_member.rs @@ -22,6 +22,7 @@ pub struct RestrictChatMember<'a> { ///Date when restrictions will be lifted for the user, unix time. If user /// is restricted for more than 366 days or less than 30 seconds from the /// current time, they are considered to be restricted forever + #[serde(skip_serializing_if = "Option::is_none")] pub until_date: Option, } From 695ea93e067a7d47a7f753fc20aec98a214784e0 Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Tue, 24 Sep 2019 19:32:57 +0300 Subject: [PATCH 23/30] bool -> Option --- src/requests/pin_chat_message.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/requests/pin_chat_message.rs b/src/requests/pin_chat_message.rs index 5b9ddfde..f50110b2 100644 --- a/src/requests/pin_chat_message.rs +++ b/src/requests/pin_chat_message.rs @@ -13,18 +13,20 @@ pub struct PinChatMessage<'a> { /// of the target supergroup or channel (in the format @channelusername) pub chat_id: ChatId, pub message_id: i32, - pub disable_notification: bool + pub disable_notification: Option } impl<'a> PinChatMessage<'a> { pub(crate) fn new( ctx: RequestContext<'a>, chat_id: ChatId, message_id: i32 ) -> Self { - Self { ctx, chat_id, message_id, disable_notification: false } + Self { ctx, chat_id, message_id, disable_notification: None } } - pub fn disable_notification(mut self) -> Self { - self.disable_notification = true; + pub fn disable_notification(mut self, val: T) -> Self + where T: Into + { + self.disable_notification = Some(val.into()); self } } From e813953b00c802c6d11ec31136cbc76f8fd6fa4e Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Tue, 24 Sep 2019 19:56:57 +0300 Subject: [PATCH 24/30] Deleted test --- src/types/passport_data.rs | 60 -------------------------------------- 1 file changed, 60 deletions(-) diff --git a/src/types/passport_data.rs b/src/types/passport_data.rs index 9c7ffc89..8ca8e20c 100644 --- a/src/types/passport_data.rs +++ b/src/types/passport_data.rs @@ -6,63 +6,3 @@ pub struct PassportData { pub data: Vec, pub credentials: EncryptedCredentials, } - -#[cfg(test)] -mod tests { - use super::super::{ElementType, PassportFile}; - use super::*; - - #[test] - fn must_serialize_passport_data_to_json() { - let expected_json = r#"{ - "data": - [ - { - "type":"passport_registration", - "data":"somedata", - "phone_number":"1313", - "email":"someemail", - "front_size": - { - "file_id":"someId", - "file_size":13, - "file_date":13 - } - } - ], - "credentials": - { - "data":"someData", - "hash":"1122", - "secret":"secret" - } - }"# - .replace("\n", "") - .replace(" ", ""); - let passport_data = PassportData { - data: vec![EncryptedPassportElement { - element_type: ElementType::PassportRegistration, - data: "somedata".to_string(), - phone_number: "1313".to_string(), - email: "someemail".to_string(), - files: None, - front_size: Some(PassportFile { - file_id: "someId".to_string(), - file_size: 13, - file_date: 13, - }), - reverse_side: None, - selfie: None, - translation: None, - }], - credentials: EncryptedCredentials { - data: "someData".to_string(), - hash: "1122".to_string(), - secret: "secret".to_string(), - }, - }; - - let actual_json = serde_json::to_string(&passport_data).unwrap(); - assert_eq!(actual_json, expected_json) - } -} From 20925e82fb22968b7b4e624e04998457af4bb916 Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Wed, 25 Sep 2019 17:51:32 +0300 Subject: [PATCH 25/30] Added True unit type --- src/types/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/types/mod.rs b/src/types/mod.rs index 2c1c221b..041001cd 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -72,6 +72,7 @@ pub use self::{ sticker::Sticker, sticker_set::StickerSet, successful_payment::SuccessfulPayment, + unit_true::True, update::{Update, UpdateKind}, user::User, user_profile_photos::UserProfilePhotos, @@ -127,6 +128,7 @@ mod shipping_query; mod sticker; mod sticker_set; mod successful_payment; +mod unit_true; mod update; mod user; mod user_profile_photos; From ce8420354e9a3406370d29ee4ffad2014a854f84 Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Wed, 25 Sep 2019 17:56:52 +0300 Subject: [PATCH 26/30] Fixed test name --- src/types/unit_true.rs | 64 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/types/unit_true.rs diff --git a/src/types/unit_true.rs b/src/types/unit_true.rs new file mode 100644 index 00000000..c9c44e46 --- /dev/null +++ b/src/types/unit_true.rs @@ -0,0 +1,64 @@ +use serde::de::{self, Deserialize, Deserializer, Visitor}; +use serde::ser::{Serialize, Serializer}; + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct True; + +impl<'de> Deserialize<'de> for True { + fn deserialize(des: D) -> Result + where + D: Deserializer<'de> + { + des.deserialize_bool(TrueVisitor) + } +} + +struct TrueVisitor; + +impl<'de> Visitor<'de> for TrueVisitor { + type Value = True; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("bool, equal to `true`") + } + + fn visit_bool(self, value: bool) -> Result + where + E: de::Error + { + match value { + true => Ok(True), + _ => Err(E::custom("expected `true`, found other")) + } + } +} + +impl Serialize for True { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bool(true) + } +} + +#[cfg(test)] +mod tests { + use super::True; + use serde_json::{from_str, to_string}; + + #[test] + fn unit_true_de() { + let json = "true"; + let expected = True; + let actual = from_str(json).unwrap(); + assert_eq!(expected, actual); + } + + #[test] + fn unit_true_se() { + let actual = to_string(&True).unwrap(); + let expected = "true"; + assert_eq!(expected, actual); + } +} From dbc07a1a0c04104d71155a83b8375f9c50feb201 Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Wed, 25 Sep 2019 19:49:37 +0300 Subject: [PATCH 27/30] "other" -> "`false`" --- src/types/unit_true.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/unit_true.rs b/src/types/unit_true.rs index c9c44e46..24a04153 100644 --- a/src/types/unit_true.rs +++ b/src/types/unit_true.rs @@ -28,7 +28,7 @@ impl<'de> Visitor<'de> for TrueVisitor { { match value { true => Ok(True), - _ => Err(E::custom("expected `true`, found other")) + _ => Err(E::custom("expected `true`, found `false`")) } } } From fc4dc0636022a5d5775f74bb009f7218fb30851e Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Wed, 25 Sep 2019 20:14:08 +0300 Subject: [PATCH 28/30] impl {Termination,Default,Hash,{Partial,}Ord} for True --- Cargo.toml | 3 ++- src/lib.rs | 2 ++ src/types/unit_true.rs | 12 +++++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b928b697..5ec3559a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,5 @@ apply = "0.2.2" derive_more = "0.15.0" tokio = "0.2.0-alpha.4" bytes = "0.4.12" -futures-preview = "0.3.0-alpha.18" \ No newline at end of file +futures-preview = "0.3.0-alpha.18" +libc = "0.2.62" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 34052315..34962237 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(termination_trait_lib)] + #[macro_use] extern crate derive_more; #[macro_use] diff --git a/src/types/unit_true.rs b/src/types/unit_true.rs index 24a04153..e838df1f 100644 --- a/src/types/unit_true.rs +++ b/src/types/unit_true.rs @@ -1,9 +1,15 @@ use serde::de::{self, Deserialize, Deserializer, Visitor}; use serde::ser::{Serialize, Serializer}; -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)] pub struct True; +impl std::process::Termination for True { + fn report(self) -> i32 { + libc::EXIT_SUCCESS + } +} + impl<'de> Deserialize<'de> for True { fn deserialize(des: D) -> Result where @@ -18,8 +24,8 @@ struct TrueVisitor; impl<'de> Visitor<'de> for TrueVisitor { type Value = True; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("bool, equal to `true`") + fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "bool, equal to `true`") } fn visit_bool(self, value: bool) -> Result From 7493a448a638a097e02591309365a1cf66bafafa Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Wed, 25 Sep 2019 20:14:52 +0300 Subject: [PATCH 29/30] _ -> false --- src/types/unit_true.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/unit_true.rs b/src/types/unit_true.rs index e838df1f..dc20f839 100644 --- a/src/types/unit_true.rs +++ b/src/types/unit_true.rs @@ -34,7 +34,7 @@ impl<'de> Visitor<'de> for TrueVisitor { { match value { true => Ok(True), - _ => Err(E::custom("expected `true`, found `false`")) + false => Err(E::custom("expected `true`, found `false`")) } } } From dc0c7bbb77c44faf5fda830181604d69b65b9ff6 Mon Sep 17 00:00:00 2001 From: Mr-Andersen Date: Wed, 25 Sep 2019 20:38:14 +0300 Subject: [PATCH 30/30] `type ReturnType = bool;` -> `... = True` --- src/requests/answer_pre_checkout_query.rs | 3 ++- src/requests/answer_shipping_query.rs | 4 ++-- src/requests/kick_chat_member.rs | 3 ++- src/requests/pin_chat_message.rs | 7 +++++-- src/requests/restrict_chat_member.rs | 4 ++-- src/requests/send_chat_action.rs | 3 ++- src/types/unit_true.rs | 11 +++++++++++ 7 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/requests/answer_pre_checkout_query.rs b/src/requests/answer_pre_checkout_query.rs index 03a26263..3e76814c 100644 --- a/src/requests/answer_pre_checkout_query.rs +++ b/src/requests/answer_pre_checkout_query.rs @@ -1,6 +1,7 @@ use crate::{ network, requests::{Request, RequestContext, RequestFuture, ResponseResult}, + types::True }; #[derive(Debug, Serialize, Clone)] @@ -32,7 +33,7 @@ pub struct AnswerPreCheckoutQuery<'a> { } impl<'a> Request<'a> for AnswerPreCheckoutQuery<'a> { - type ReturnValue = bool; + type ReturnValue = True; fn send(self) -> RequestFuture<'a, ResponseResult> { Box::pin(async move { diff --git a/src/requests/answer_shipping_query.rs b/src/requests/answer_shipping_query.rs index c28fffd4..3858f392 100644 --- a/src/requests/answer_shipping_query.rs +++ b/src/requests/answer_shipping_query.rs @@ -1,7 +1,7 @@ use crate::{ network, requests::{Request, RequestContext, RequestFuture, ResponseResult}, - types::ShippingOption, + types::{ShippingOption, True}, }; #[derive(Debug, Clone, Serialize)] @@ -34,7 +34,7 @@ pub struct AnswerShippingQuery<'a> { } impl<'a> Request<'a> for AnswerShippingQuery<'a> { - type ReturnValue = bool; + type ReturnValue = True; fn send(self) -> RequestFuture<'a, ResponseResult> { Box::pin(async move { diff --git a/src/requests/kick_chat_member.rs b/src/requests/kick_chat_member.rs index 2ed54f0a..ae417f90 100644 --- a/src/requests/kick_chat_member.rs +++ b/src/requests/kick_chat_member.rs @@ -2,6 +2,7 @@ use crate::network; use crate::requests::{ ChatId, Request, RequestContext, RequestFuture, ResponseResult, }; +use crate::types::True; /// Use this method to kick a user from a group, a supergroup or a channel. In /// the case of supergroups and channels, the user will not be able to return to @@ -25,7 +26,7 @@ pub struct KickChatMember<'a> { } impl<'a> Request<'a> for KickChatMember<'a> { - type ReturnValue = bool; + type ReturnValue = True; fn send(self) -> RequestFuture<'a, ResponseResult> { Box::pin(async move { diff --git a/src/requests/pin_chat_message.rs b/src/requests/pin_chat_message.rs index f50110b2..d6b9f8ef 100644 --- a/src/requests/pin_chat_message.rs +++ b/src/requests/pin_chat_message.rs @@ -1,4 +1,7 @@ -use crate::requests::{ChatId, RequestContext, RequestFuture, ResponseResult, Request}; +use crate::{ + requests::{ChatId, RequestContext, RequestFuture, ResponseResult, Request}, + types::True +}; use crate::network; /// Use this method to get up to date information about the chat @@ -32,7 +35,7 @@ impl<'a> PinChatMessage<'a> { } impl<'a> Request<'a> for PinChatMessage<'a> { - type ReturnValue = bool; // TODO: change to unit type True + type ReturnValue = True; fn send(self) -> RequestFuture<'a, ResponseResult> { Box::pin(async move { diff --git a/src/requests/restrict_chat_member.rs b/src/requests/restrict_chat_member.rs index dabfb9c1..697dcdeb 100644 --- a/src/requests/restrict_chat_member.rs +++ b/src/requests/restrict_chat_member.rs @@ -2,7 +2,7 @@ use crate::network; use crate::requests::{ ChatId, Request, RequestContext, RequestFuture, ResponseResult, }; -use crate::types::ChatPermissions; +use crate::types::{ChatPermissions, True}; /// Use this method to restrict a user in a supergroup. The bot must be an /// administrator in the supergroup for this to work and must have the @@ -27,7 +27,7 @@ pub struct RestrictChatMember<'a> { } impl<'a> Request<'a> for RestrictChatMember<'a> { - type ReturnValue = bool; + type ReturnValue = True; fn send(self) -> RequestFuture<'a, ResponseResult> { Box::pin(async move { diff --git a/src/requests/send_chat_action.rs b/src/requests/send_chat_action.rs index 639307cc..f6fc41e4 100644 --- a/src/requests/send_chat_action.rs +++ b/src/requests/send_chat_action.rs @@ -3,6 +3,7 @@ use crate::{ requests::{ ChatId, Request, RequestContext, RequestFuture, ResponseResult, }, + types::True }; ///Use this method when you need to tell the user that something is happening @@ -40,7 +41,7 @@ pub enum ChatAction { } impl<'a> Request<'a> for SendChatAction<'a> { - type ReturnValue = bool; + type ReturnValue = True; fn send(self) -> RequestFuture<'a, ResponseResult> { Box::pin(async move { diff --git a/src/types/unit_true.rs b/src/types/unit_true.rs index dc20f839..85db581a 100644 --- a/src/types/unit_true.rs +++ b/src/types/unit_true.rs @@ -10,6 +10,17 @@ impl std::process::Termination for True { } } +impl std::convert::TryFrom for True { + type Error = (); + + fn try_from(value: bool) -> Result { + match value { + true => Ok(True), + false => Err(()) + } + } +} + impl<'de> Deserialize<'de> for True { fn deserialize(des: D) -> Result where