From 51fcc5151c3e2dabd00dab5c5ddc7438ad9390fc Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 16 Oct 2021 10:12:21 +0300 Subject: [PATCH 1/4] Buttons: use message.chat.id, instead of passing it via callback data --- examples/buttons/src/main.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/examples/buttons/src/main.rs b/examples/buttons/src/main.rs index 0112a173..794c3688 100644 --- a/examples/buttons/src/main.rs +++ b/examples/buttons/src/main.rs @@ -18,7 +18,7 @@ enum Command { } /// Creates a keyboard made by buttons in a big column. -fn make_keyboard(chat_id: i64) -> InlineKeyboardMarkup { +fn make_keyboard() -> InlineKeyboardMarkup { let mut keyboard_array: Vec> = vec![]; // The column is made by the list of Debian versions. let debian_versions = vec![ @@ -29,8 +29,8 @@ fn make_keyboard(chat_id: i64) -> InlineKeyboardMarkup { for version in debian_versions { // Match each button with the chat id and the Debian version. keyboard_array.push(vec![InlineKeyboardButton::callback( - version.into(), - format!("{}_{}", chat_id, version), + version.to_owned(), + version.to_owned(), )]); } @@ -52,7 +52,7 @@ async fn message_handler( cx.answer(Command::descriptions()).await?; } Command::Start => { - let keyboard = make_keyboard(cx.chat_id()); + let keyboard = make_keyboard(); // Create a list of buttons using callbacks to receive the response. cx.answer("Debian versions:").reply_markup(keyboard).await?; } @@ -70,15 +70,11 @@ async fn callback_handler( cx: UpdateWithCx, CallbackQuery>, ) -> Result<(), Box> { let data = &cx.update.data; - if let Some(text) = data { - let callback: Vec<&str> = text.split('_').collect(); - let chat_id = callback[0]; - let version = callback[1]; - - let message_id = cx.update.message.clone().unwrap().id; + if let Some(version) = data { + let message = cx.update.message.clone().unwrap(); let _ = cx .requester - .edit_message_text(chat_id.to_string(), message_id, format!("You chose: {}", version)) + .edit_message_text(message.chat.id, message.id, format!("You chose: {}", version)) .await; log::info!("You chose: {}", version); } From 7ae2d7efbadad5ad497139b2b2a11f8b20c28a2e Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 16 Oct 2021 10:24:06 +0300 Subject: [PATCH 2/4] Buttons: use better layout for buttons Allow multiple buttons in a row, ie use ```text a | b | c d | e | f g ``` instead of ```text a b c d e f g ``` --- examples/buttons/src/main.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/buttons/src/main.rs b/examples/buttons/src/main.rs index 794c3688..7b93b220 100644 --- a/examples/buttons/src/main.rs +++ b/examples/buttons/src/main.rs @@ -19,22 +19,23 @@ enum Command { /// Creates a keyboard made by buttons in a big column. fn make_keyboard() -> InlineKeyboardMarkup { - let mut keyboard_array: Vec> = vec![]; + let mut keyboard: Vec> = vec![]; // The column is made by the list of Debian versions. - let debian_versions = vec![ + let debian_versions = [ "Buzz", "Rex", "Bo", "Hamm", "Slink", "Potato", "Woody", "Sarge", "Etch", "Lenny", "Squeeze", "Wheezy", "Jessie", "Stretch", "Buster", "Bullseye", ]; - for version in debian_versions { - // Match each button with the chat id and the Debian version. - keyboard_array.push(vec![InlineKeyboardButton::callback( - version.to_owned(), - version.to_owned(), - )]); + for versions in debian_versions.chunks(3) { + let row = versions + .iter() + .map(|&version| InlineKeyboardButton::callback(version.to_owned(), version.to_owned())) + .collect(); + + keyboard.push(row); } - InlineKeyboardMarkup::new(keyboard_array) + InlineKeyboardMarkup::new(keyboard) } /// Parse the text wrote on Telegram and check if that text is a valid command From 776e8be073852b73a3a64cf7d983040dd99abcae Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 16 Oct 2021 10:33:39 +0300 Subject: [PATCH 3/4] Buttons: propagete errors in callback_handler, handle messages without text ...and also remove needless copying --- examples/buttons/src/main.rs | 47 +++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/examples/buttons/src/main.rs b/examples/buttons/src/main.rs index 7b93b220..0124167a 100644 --- a/examples/buttons/src/main.rs +++ b/examples/buttons/src/main.rs @@ -20,7 +20,7 @@ enum Command { /// Creates a keyboard made by buttons in a big column. fn make_keyboard() -> InlineKeyboardMarkup { let mut keyboard: Vec> = vec![]; - // The column is made by the list of Debian versions. + let debian_versions = [ "Buzz", "Rex", "Bo", "Hamm", "Slink", "Potato", "Woody", "Sarge", "Etch", "Lenny", "Squeeze", "Wheezy", "Jessie", "Stretch", "Buster", "Bullseye", @@ -44,22 +44,25 @@ fn make_keyboard() -> InlineKeyboardMarkup { async fn message_handler( cx: UpdateWithCx, Message>, ) -> Result<(), Box> { - if let Ok(command) = - BotCommand::parse(cx.update.text().expect("Error with the text"), "buttons") - { - match command { - Command::Help => { - // Just send the description of all commands. - cx.answer(Command::descriptions()).await?; - } - Command::Start => { - let keyboard = make_keyboard(); - // Create a list of buttons using callbacks to receive the response. - cx.answer("Debian versions:").reply_markup(keyboard).await?; + match cx.update.text() { + Some(text) => { + match BotCommand::parse(text, "buttons") { + Ok(Command::Help) => { + // Just send the description of all commands. + cx.answer(Command::descriptions()).await?; + } + Ok(Command::Start) => { + // Create a list of buttons and send them. + let keyboard = make_keyboard(); + cx.answer("Debian versions:").reply_markup(keyboard).await?; + } + + Err(_) => { + cx.reply_to("Command not found!").await?; + } } } - } else { - cx.reply_to("Command not found!").await?; + None => {} } Ok(()) @@ -70,13 +73,13 @@ async fn message_handler( async fn callback_handler( cx: UpdateWithCx, CallbackQuery>, ) -> Result<(), Box> { - let data = &cx.update.data; - if let Some(version) = data { - let message = cx.update.message.clone().unwrap(); - let _ = cx - .requester - .edit_message_text(message.chat.id, message.id, format!("You chose: {}", version)) - .await; + let UpdateWithCx { requester: bot, update: query } = cx; + if let Some(version) = query.data { + let message = query.message.unwrap(); + + bot.edit_message_text(message.chat.id, message.id, format!("You chose: {}", version)) + .await?; + log::info!("You chose: {}", version); } From 31e133493b8115182ece828eb1ee044c860a12de Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 16 Oct 2021 11:07:55 +0300 Subject: [PATCH 4/4] Buttons: add inline support --- examples/buttons/src/main.rs | 44 ++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/examples/buttons/src/main.rs b/examples/buttons/src/main.rs index 0124167a..97bde1ed 100644 --- a/examples/buttons/src/main.rs +++ b/examples/buttons/src/main.rs @@ -2,7 +2,10 @@ use std::error::Error; use teloxide::{ payloads::SendMessageSetters, prelude::*, - types::{InlineKeyboardButton, InlineKeyboardMarkup}, + types::{ + InlineKeyboardButton, InlineKeyboardMarkup, InlineQueryResultArticle, InputMessageContent, + InputMessageContentText, + }, utils::command::BotCommand, }; @@ -68,17 +71,43 @@ async fn message_handler( Ok(()) } +async fn inline_query_handler( + cx: UpdateWithCx, InlineQuery>, +) -> Result<(), Box> { + let UpdateWithCx { requester: bot, update: query } = cx; + + let choose_debian_version = InlineQueryResultArticle::new( + "0", + "Chose debian version", + InputMessageContent::Text(InputMessageContentText::new("Debian versions:")), + ) + .reply_markup(make_keyboard()); + + bot.answer_inline_query(query.id, vec![choose_debian_version.into()]).await?; + + Ok(()) +} + /// When it receives a callback from a button it edits the message with all /// those buttons writing a text with the selected Debian version. async fn callback_handler( cx: UpdateWithCx, CallbackQuery>, ) -> Result<(), Box> { let UpdateWithCx { requester: bot, update: query } = cx; - if let Some(version) = query.data { - let message = query.message.unwrap(); - bot.edit_message_text(message.chat.id, message.id, format!("You chose: {}", version)) - .await?; + if let Some(version) = query.data { + let text = format!("You chose: {}", version); + + match query.message { + Some(Message { id, chat, .. }) => { + bot.edit_message_text(chat.id, id, text).await?; + } + None => { + if let Some(id) = query.inline_message_id { + bot.edit_message_text_inline(dbg!(id), text).await?; + } + } + } log::info!("You chose: {}", version); } @@ -104,6 +133,11 @@ async fn main() -> Result<(), Box> { callback_handler(cx).await.log_on_error().await; }) }) + .inline_queries_handler(|rx: DispatcherHandlerRx, InlineQuery>| { + UnboundedReceiverStream::new(rx).for_each_concurrent(None, |cx| async move { + inline_query_handler(cx).await.log_on_error().await; + }) + }) .dispatch() .await;