From 2c4102e2b35dab14d25da06718f659167cdbc3f2 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Mon, 3 Feb 2020 00:54:11 +0600 Subject: [PATCH] Simplify building ReplyKeyboardMarkup --- examples/simple_fsm/src/main.rs | 57 ++++++++--------------------- src/types/inline_keyboard_markup.rs | 4 -- src/types/keyboard_button.rs | 22 +++++++++++ src/types/reply_keyboard_markup.rs | 45 ++++++++++++++++++++++- 4 files changed, 81 insertions(+), 47 deletions(-) diff --git a/examples/simple_fsm/src/main.rs b/examples/simple_fsm/src/main.rs index 743f781a..3b7853c9 100644 --- a/examples/simple_fsm/src/main.rs +++ b/examples/simple_fsm/src/main.rs @@ -21,29 +21,12 @@ enum FavouriteMusic { impl FavouriteMusic { fn markup() -> ReplyKeyboardMarkup { - ReplyKeyboardMarkup { - keyboard: vec![vec![ - KeyboardButton { - text: "Rock".to_owned(), - request: None, - }, - KeyboardButton { - text: "Metal".to_owned(), - request: None, - }, - KeyboardButton { - text: "Pop".to_owned(), - request: None, - }, - KeyboardButton { - text: "Other".to_owned(), - request: None, - }, - ]], - resize_keyboard: None, - one_time_keyboard: None, - selective: None, - } + ReplyKeyboardMarkup::default().append_row(vec![ + KeyboardButton::new("Rock"), + KeyboardButton::new("Metal"), + KeyboardButton::new("Pop"), + KeyboardButton::new("Other"), + ]) } } @@ -70,21 +53,13 @@ impl Display for User { } } -// ============================================================================ -// [Some macros] -// ============================================================================ - -#[macro_export] -macro_rules! reply { - ($ctx:ident, $text:expr) => { - $ctx.reply($text).await?; - }; -} - // ============================================================================ // [Control our FSM] // ============================================================================ +type Ctx = SessionHandlerCtx; +type Res = Result, RequestError>; + async fn send_favourite_music_types(ctx: &Ctx) -> Result<(), RequestError> { ctx.bot .send_message(ctx.chat_id(), "Good. Now choose your favourite music:") @@ -94,16 +69,14 @@ async fn send_favourite_music_types(ctx: &Ctx) -> Result<(), RequestError> { Ok(()) } -type Ctx = SessionHandlerCtx; -type Res = Result, RequestError>; - async fn start(ctx: Ctx) -> Res { - reply!(ctx, "Let's start! First, what's your full name?"); + ctx.reply("Let's start! First, what's your full name?") + .await?; Ok(SessionState::Next(ctx.session)) } async fn full_name(mut ctx: Ctx) -> Res { - reply!(ctx, "What a wonderful name! Your age?"); + ctx.reply("What a wonderful name! Your age?").await?; ctx.session.full_name = Some(ctx.update.text().unwrap().to_owned()); Ok(SessionState::Next(ctx.session)) } @@ -114,7 +87,7 @@ async fn age(mut ctx: Ctx) -> Res { send_favourite_music_types(&ctx).await?; ctx.session.age = Some(ok); } - Err(_) => reply!(ctx, "Oh, please, enter a number!"), + Err(_) => ctx.reply("Oh, please, enter a number!").await?, } Ok(SessionState::Next(ctx.session)) @@ -124,11 +97,11 @@ async fn favourite_music(mut ctx: Ctx) -> Res { match ctx.update.text().unwrap().parse() { Ok(ok) => { ctx.session.favourite_music = Some(ok); - reply!(ctx, format!("Fine. {}", ctx.session)); + ctx.reply(format!("Fine. {}", ctx.session)).await?; Ok(SessionState::Exit) } Err(_) => { - reply!(ctx, "Oh, please, enter from the keyboard!"); + ctx.reply("Oh, please, enter from the keyboard!").await?; Ok(SessionState::Next(ctx.session)) } } diff --git a/src/types/inline_keyboard_markup.rs b/src/types/inline_keyboard_markup.rs index 0a35e799..8361509d 100644 --- a/src/types/inline_keyboard_markup.rs +++ b/src/types/inline_keyboard_markup.rs @@ -33,10 +33,6 @@ pub struct InlineKeyboardMarkup { /// let keyboard = InlineKeyboardMarkup::new().append_row(vec![url_button]); /// ``` impl InlineKeyboardMarkup { - pub fn new() -> Self { - <_>::default() - } - pub fn append_row(mut self, buttons: Vec) -> Self { self.inline_keyboard.push(buttons); self diff --git a/src/types/keyboard_button.rs b/src/types/keyboard_button.rs index 5e428201..ee68c4d1 100644 --- a/src/types/keyboard_button.rs +++ b/src/types/keyboard_button.rs @@ -24,6 +24,28 @@ pub struct KeyboardButton { pub request: Option, } +impl KeyboardButton { + /// Creates `KeyboardButton` with the provided `text` and all the other + /// fields set to `None`. + pub fn new(text: T) -> Self + where + T: Into, + { + Self { + text: text.into(), + request: None, + } + } + + pub fn request(mut self, val: T) -> Self + where + T: Into>, + { + self.request = val.into(); + self + } +} + // Serialize + Deserialize are implemented by hand #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] pub enum ButtonRequest { diff --git a/src/types/reply_keyboard_markup.rs b/src/types/reply_keyboard_markup.rs index f2cd674e..59707764 100644 --- a/src/types/reply_keyboard_markup.rs +++ b/src/types/reply_keyboard_markup.rs @@ -10,7 +10,7 @@ use crate::types::KeyboardButton; /// [custom keyboard]: https://core.telegram.org/bots#keyboards /// [Introduction to bots]: https://core.telegram.org/bots#keyboards #[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, Default)] pub struct ReplyKeyboardMarkup { /// Array of button rows, each represented by an Array of /// [`KeyboardButton`] objects @@ -43,3 +43,46 @@ pub struct ReplyKeyboardMarkup { /// [`Message`]: crate::types::Message pub selective: Option, } + +impl ReplyKeyboardMarkup { + pub fn append_row(mut self, buttons: Vec) -> Self { + self.keyboard.push(buttons); + self + } + + pub fn append_to_row( + mut self, + button: KeyboardButton, + index: usize, + ) -> Self { + match self.keyboard.get_mut(index) { + Some(buttons) => buttons.push(button), + None => self.keyboard.push(vec![button]), + }; + self + } + + pub fn resize_keyboard(mut self, val: T) -> Self + where + T: Into>, + { + self.resize_keyboard = val.into(); + self + } + + pub fn one_time_keyboard(mut self, val: T) -> Self + where + T: Into>, + { + self.one_time_keyboard = val.into(); + self + } + + pub fn selective(mut self, val: T) -> Self + where + T: Into>, + { + self.selective = val.into(); + self + } +}