From 5a96d4403b8acb6fe93ed70cbed39a2f08a178f4 Mon Sep 17 00:00:00 2001 From: Goh Wei Wen Date: Mon, 21 Oct 2019 13:15:36 +0800 Subject: [PATCH 1/7] Add ChosenInlineResult type --- raw/src/types/chosen_inline_result.rs | 20 ++++++++++++++++++++ raw/src/types/mod.rs | 2 ++ raw/src/types/update.rs | 21 ++++++++++++++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 raw/src/types/chosen_inline_result.rs diff --git a/raw/src/types/chosen_inline_result.rs b/raw/src/types/chosen_inline_result.rs new file mode 100644 index 0000000000..f44b87aa71 --- /dev/null +++ b/raw/src/types/chosen_inline_result.rs @@ -0,0 +1,20 @@ +use crate::types::*; + +/// This object represents the result of an inline query that was chosen by a +/// user and sent to their chat partner. It is only sent if inline feedback is +/// enabled for the bot. +#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)] +pub struct ChosenInlineResult { + /// Unique identifier for the result that was chosen + pub result_id: String, + /// The user that chose the result + pub from: User, + /// Sender location, only for bots that require user location + pub location: Option, + /// Identifier of the sent inline message. Available only if there is an + /// inline keyboard attached to the message. Will be also received in + /// callback queries and can be used to edit the message + pub inline_message_id: Option, + /// The query that was used to obtain the result + pub query: String, +} diff --git a/raw/src/types/mod.rs b/raw/src/types/mod.rs index 293baa4256..0a4a4fbfe1 100644 --- a/raw/src/types/mod.rs +++ b/raw/src/types/mod.rs @@ -1,6 +1,7 @@ pub mod callback_query; pub mod chat; pub mod chat_member; +pub mod chosen_inline_result; pub mod inline_query; pub mod inline_query_result; pub mod input_file; @@ -15,6 +16,7 @@ pub mod update; pub use self::callback_query::*; pub use self::chat::*; pub use self::chat_member::*; +pub use self::chosen_inline_result::*; pub use self::inline_query::*; pub use self::inline_query_result::*; pub use self::input_file::*; diff --git a/raw/src/types/update.rs b/raw/src/types/update.rs index ed84146039..ab2076a595 100644 --- a/raw/src/types/update.rs +++ b/raw/src/types/update.rs @@ -29,11 +29,30 @@ pub enum UpdateKind { EditedChannelPost(ChannelPost), #[serde(rename = "inline_query")] InlineQuery(InlineQuery), - // ChosenInlineResult(ChosenInlineResult), + #[serde(rename = "chosen_inline_result")] + ChosenInlineResult(ChosenInlineResult), #[serde(rename = "callback_query")] CallbackQuery(CallbackQuery), + #[serde(rename = "shipping_query")] + ShippingQuery(ShippingQuery), + #[serde(rename = "pre_checkout_query")] + PreCheckoutQuery(PreCheckoutQuery), + #[serde(rename = "poll")] + Poll(Poll), #[doc(hidden)] Error(String), #[doc(hidden)] Unknown, } + +// TODO +#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)] +pub struct ShippingQuery {} + +// TODO +#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)] +pub struct PreCheckoutQuery {} + +// TODO +#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)] +pub struct Poll {} From 12b06846e4fb45408d53af68745d86e03b34b074 Mon Sep 17 00:00:00 2001 From: Goh Wei Wen Date: Mon, 21 Oct 2019 18:41:01 +0800 Subject: [PATCH 2/7] Add InlineKeyboardButton variants (SwitchInlineQuery, SwitchInlineQueryCurrentChat) --- raw/src/types/reply_markup.rs | 53 ++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/raw/src/types/reply_markup.rs b/raw/src/types/reply_markup.rs index cba683cdc0..85cbad9025 100644 --- a/raw/src/types/reply_markup.rs +++ b/raw/src/types/reply_markup.rs @@ -241,12 +241,38 @@ impl InlineKeyboardButton { } } + /// HTTP or tg:// url to be opened when button is pressed pub fn url, U: AsRef>(text: T, url: U) -> Self { Self { text: text.as_ref().to_string(), kind: InlineKeyboardButtonKind::Url(url.as_ref().to_string()), } } + + /// Pressing the button will prompt the user to select one of their chats, open that chat and + /// insert the bot‘s username and the specified inline query in the input field. Can be empty, + /// in which case just the bot’s username will be inserted. + pub fn switch_inline_query, Q: AsRef>(text: T, query: Q) -> Self { + Self { + text: text.as_ref().to_string(), + kind: InlineKeyboardButtonKind::SwitchInlineQuery(query.as_ref().to_string()), + } + } + + /// Pressing the button will insert the bot‘s username and the specified inline query in the + /// current chat's input field. Can be empty, in which case just the bot’s username will be + /// inserted. + pub fn switch_inline_query_current_chat, Q: AsRef>( + text: T, + query: Q, + ) -> Self { + Self { + text: text.as_ref().to_string(), + kind: InlineKeyboardButtonKind::SwitchInlineQueryCurrentChat( + query.as_ref().to_string(), + ), + } + } } #[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)] @@ -255,23 +281,16 @@ pub enum InlineKeyboardButtonKind { Url(String), // TODO(knsd): Url? #[serde(rename = "callback_data")] CallbackData(String), // TODO(knsd) Validate size? - // SwitchInlineQuery(String), - // SwitchInlineQueryCurrentChat(String), - // CallbackGame(CallbackGame), -} - -#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)] -struct InlineKeyboardButtonRaw<'a> { - text: &'a str, - #[serde(skip_serializing_if = "Option::is_none")] - url: Option<&'a str>, // TODO(knsd): Url? - #[serde(skip_serializing_if = "Option::is_none")] - callback_data: Option<&'a str>, //TODO(knsd) Validate size? - #[serde(skip_serializing_if = "Option::is_none")] - switch_inline_query: Option<&'a str>, - #[serde(skip_serializing_if = "Option::is_none")] - switch_inline_query_current_chat: Option<&'a str>, - // callback_game: Option, + #[serde(rename = "switch_inline_query")] + SwitchInlineQuery(String), + #[serde(rename = "switch_inline_query_current_chat")] + SwitchInlineQueryCurrentChat(String), + // #[serde(rename = "callback_game")] + // CallbackGame(CallbackGame), + // #[serde(rename = "pay")] + // Pay, + // #[serde(rename = "login_url")] + // LoginUrl(LoginUrl), } /// Upon receiving a message with this object, Telegram clients will From ffbcee4c00eef3f9ccf3d895ba1396a1b7821c08 Mon Sep 17 00:00:00 2001 From: Goh Wei Wen Date: Mon, 16 Dec 2019 16:42:41 +0800 Subject: [PATCH 3/7] Add missing fields to AnswerInlineQuery --- raw/src/requests/answer_inline_query.rs | 43 ++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/raw/src/requests/answer_inline_query.rs b/raw/src/requests/answer_inline_query.rs index 8b0f7cb156..68facca627 100644 --- a/raw/src/requests/answer_inline_query.rs +++ b/raw/src/requests/answer_inline_query.rs @@ -1,3 +1,5 @@ +use std::ops::Not; + use crate::requests::*; use crate::types::*; @@ -5,7 +7,16 @@ use crate::types::*; pub struct AnswerInlineQuery { inline_query_id: InlineQueryId, results: Vec, - // TODO: Rest of the fields + #[serde(skip_serializing_if = "Option::is_none")] + cache_time: Option, + #[serde(skip_serializing_if = "Not::not")] + is_personal: bool, + #[serde(skip_serializing_if = "Option::is_none")] + next_offset: Option, + #[serde(skip_serializing_if = "Option::is_none")] + switch_pm_text: Option, + #[serde(skip_serializing_if = "Option::is_none")] + switch_pm_parameter: Option, } impl Request for AnswerInlineQuery { @@ -38,10 +49,40 @@ impl AnswerInlineQuery { AnswerInlineQuery { inline_query_id, results, + cache_time: None, + is_personal: false, + next_offset: None, + switch_pm_text: None, + switch_pm_parameter: None, } } pub fn add_inline_result>(&mut self, result: T) { self.results.push(result.into()); } + + pub fn cache_time(&mut self, cache_time: Integer) -> &mut Self { + self.cache_time = Some(cache_time); + self + } + + pub fn is_personal(&mut self) -> &mut Self { + self.is_personal = true; + self + } + + pub fn next_offset(&mut self, next_offset: String) -> &mut Self { + self.next_offset = Some(next_offset); + self + } + + pub fn switch_pm_text(&mut self, switch_pm_text: String) -> &mut Self { + self.switch_pm_text = Some(switch_pm_text); + self + } + + pub fn switch_pm_parameter(&mut self, switch_pm_parameter: String) -> &mut Self { + self.switch_pm_parameter = Some(switch_pm_parameter); + self + } } From 29c5e6f881019f0879bfec070d4c07dc774cd24a Mon Sep 17 00:00:00 2001 From: Goh Wei Wen Date: Mon, 6 Jan 2020 13:00:59 +0800 Subject: [PATCH 4/7] Fix foursquare_id typo --- raw/src/types/inline_query_result.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/raw/src/types/inline_query_result.rs b/raw/src/types/inline_query_result.rs index 1fbc4e5f6e..8794e936f3 100644 --- a/raw/src/types/inline_query_result.rs +++ b/raw/src/types/inline_query_result.rs @@ -874,11 +874,11 @@ pub struct InputVenueMessageContent { pub address: String, /// Foursquare identifier of the venue, if known #[serde(skip_serializing_if = "Option::is_none")] - pub foursqure_id: Option, + pub foursquare_id: Option, /// Foursquare type of the venue, if known. (For example, “arts_entertainment/default”, /// “arts_entertainment/aquarium” or “food/icecream”.) #[serde(skip_serializing_if = "Option::is_none")] - pub foursqure_type: Option, + pub foursquare_type: Option, } #[derive(Serialize, Debug)] From c8cca564d36f835feff3eb1e0994d4771ac7c3c3 Mon Sep 17 00:00:00 2001 From: Goh Wei Wen Date: Tue, 14 Jan 2020 16:18:47 +0800 Subject: [PATCH 5/7] Replace ReplyMarkup to InlineKeyboardMarkup in InlineQueryResult* structs --- raw/src/types/inline_query_result.rs | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/raw/src/types/inline_query_result.rs b/raw/src/types/inline_query_result.rs index 8794e936f3..f1853a2c6b 100644 --- a/raw/src/types/inline_query_result.rs +++ b/raw/src/types/inline_query_result.rs @@ -134,7 +134,7 @@ pub struct InlineQueryResultArticle { pub input_message_content: InputMessageContent, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// URL of the result #[serde(skip_serializing_if = "Option::is_none")] pub url: Option, @@ -183,7 +183,7 @@ pub struct InlineQueryResultPhoto { pub parse_mode: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -217,7 +217,7 @@ pub struct InlineQueryResultGif { pub parse_mode: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -250,7 +250,7 @@ pub struct InlineQueryResultMpeg4Gif { pub parse_mode: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -288,7 +288,7 @@ pub struct InlineQueryResultVideo { pub description: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -315,7 +315,7 @@ pub struct InlineQueryResultAudio { pub audio_duration: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -339,7 +339,7 @@ pub struct InlineQueryResultVoice { pub audio_duration: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -366,7 +366,7 @@ pub struct InlineQueryResultDocument { pub description: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -396,7 +396,7 @@ pub struct InlineQueryResultLocation { pub live_period: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -432,7 +432,7 @@ pub struct InlineQueryResultVenue { pub foursquare_type: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -461,7 +461,7 @@ pub struct InlineQueryResultContact { pub vcard: String, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -484,7 +484,7 @@ pub struct InlineQueryResultGame { pub game_short_name: String, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, } #[derive(Serialize, Debug)] @@ -507,7 +507,7 @@ pub struct InlineQueryResultCachedPhoto { pub parse_mode: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -530,7 +530,7 @@ pub struct InlineQueryResultCachedGif { pub parse_mode: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -553,7 +553,7 @@ pub struct InlineQueryResultCachedMpeg4Gif { pub parse_mode: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -567,7 +567,7 @@ pub struct InlineQueryResultCachedSticker { pub sticker_file_id: String, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -592,7 +592,7 @@ pub struct InlineQueryResultCachedDocument { pub parse_mode: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -617,7 +617,7 @@ pub struct InlineQueryResultCachedVideo { pub parse_mode: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -639,7 +639,7 @@ pub struct InlineQueryResultCachedVoice { pub parse_mode: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -659,7 +659,7 @@ pub struct InlineQueryResultCachedAudio { pub parse_mode: Option, /// Inline keyboard attached to the message #[serde(skip_serializing_if = "Option::is_none")] - pub reply_markup: Option, + pub reply_markup: Option, /// Content of the message to be sent #[serde(skip_serializing_if = "Option::is_none")] pub input_message_content: Option, @@ -685,7 +685,7 @@ impl InlineQueryResultArticle { } } - pub fn reply_markup>(&mut self, reply_markup: T) -> &mut Self { + pub fn reply_markup>(&mut self, reply_markup: T) -> &mut Self { self.reply_markup = Some(reply_markup.into()); self } From 62d3adc0793b9e67350db95a75eef2b0c707a9d4 Mon Sep 17 00:00:00 2001 From: Goh Wei Wen Date: Tue, 14 Jan 2020 16:35:32 +0800 Subject: [PATCH 6/7] Run cargo fmt --- lib/src/api.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/src/api.rs b/lib/src/api.rs index b63e915198..07c2207664 100644 --- a/lib/src/api.rs +++ b/lib/src/api.rs @@ -193,13 +193,13 @@ impl Api { tracing::trace!("response deserialized"); Ok(response) } - .map(|result| { - if let Err(ref error) = result { - tracing::error!(error = %error); - } - result - }) - .instrument(span) - .await + .map(|result| { + if let Err(ref error) = result { + tracing::error!(error = %error); + } + result + }) + .instrument(span) + .await } } From dfc5c9372933ca23892eed282484835553351ca6 Mon Sep 17 00:00:00 2001 From: Goh Wei Wen Date: Mon, 3 Feb 2020 14:36:48 +0800 Subject: [PATCH 7/7] Add MarkdownV2 parse mode --- raw/src/types/message.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/raw/src/types/message.rs b/raw/src/types/message.rs index ba65ec721f..3ead9a1912 100644 --- a/raw/src/types/message.rs +++ b/raw/src/types/message.rs @@ -875,8 +875,10 @@ impl File { /// See [documentation](https://core.telegram.org/bots/api#formatting-options) for details. #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize)] pub enum ParseMode { - /// Use markdown formatting. + /// Use legacy markdown formatting. Markdown, + /// Use MarkdownV2 formatting. + MarkdownV2, /// Use HTML formatting. #[serde(rename = "HTML")] Html, @@ -886,6 +888,7 @@ impl ::std::fmt::Display for ParseMode { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match *self { ParseMode::Markdown => write!(f, "Markdown"), + ParseMode::MarkdownV2 => write!(f, "MarkdownV2"), ParseMode::Html => write!(f, "HTML"), } }