From 2f4006f5ea16551d49cca36f6ee7f4b97de80fc4 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Fri, 31 Jul 2020 23:18:13 +0600 Subject: [PATCH 01/41] Update the API coverage badge to 0.4.9 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2c09106e..19fa1b36 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ - + A full-featured framework that empowers you to easily build [Telegram bots](https://telegram.org/blog/bot-revolution) using the [`async`/`.await`](https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html) syntax in [Rust](https://www.rust-lang.org/). It handles all the difficult stuff so you can focus only on your business logic. From f2618ad7ed7f42f7b7bc9fde4b6bbb70ff5ca035 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Fri, 31 Jul 2020 23:49:43 +0600 Subject: [PATCH 02/41] Fix wrong documentation about TELOXIDE_PROXY --- src/bot/mod.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/bot/mod.rs b/src/bot/mod.rs index 65a024bf..1c205a21 100644 --- a/src/bot/mod.rs +++ b/src/bot/mod.rs @@ -33,8 +33,7 @@ impl Bot { /// client. /// /// # Panics - /// - If cannot get the `TELOXIDE_TOKEN` and `TELOXIDE_PROXY` environmental - /// variables. + /// - If cannot get the `TELOXIDE_TOKEN` environmental variable. /// - If it cannot create [`reqwest::Client`]. /// /// [`reqwest::Client`]: https://docs.rs/reqwest/0.10.1/reqwest/struct.Client.html @@ -221,11 +220,11 @@ impl BotBuilder { /// /// This method will attempt to build a new client with a proxy, specified /// in the `TELOXIDE_PROXY` (passed into [`reqwest::Proxy::all`]) - /// environmental variable, if a client haven't been specified. + /// environmental variable, if a client haven't been specified. If + /// `TELOXIDE_PROXY` is unspecified, it'll use no proxy. /// /// # Panics - /// - If cannot get the `TELOXIDE_TOKEN` and `TELOXIDE_PROXY` environmental - /// variables. + /// - If cannot get the `TELOXIDE_TOKEN` environmental variable. /// - If it cannot create [`reqwest::Client`]. /// /// [`reqwest::Client`]: https://docs.rs/reqwest/0.10.1/reqwest/struct.Client.html From 08d0d7f2f4e7ac58a3d845999d003ddb57b3834f Mon Sep 17 00:00:00 2001 From: Kirill Mironov Date: Fri, 31 Jul 2020 21:10:18 +0300 Subject: [PATCH 03/41] Unpair TransitionOut from concrete Error type resolves #242 --- src/dispatching/dialogue/transition.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/dispatching/dialogue/transition.rs b/src/dispatching/dialogue/transition.rs index d15ce303..5a53a004 100644 --- a/src/dispatching/dialogue/transition.rs +++ b/src/dispatching/dialogue/transition.rs @@ -1,6 +1,5 @@ use crate::{ dispatching::{dialogue::DialogueStage, UpdateWithCx}, - requests::ResponseResult, types::Message, }; use futures::future::BoxFuture; @@ -51,4 +50,4 @@ impl SubtransitionOutputType for TransitionOut { pub type TransitionIn = UpdateWithCx; /// A type returned from a FSM (sub)transition function. -pub type TransitionOut = ResponseResult>; +pub type TransitionOut = Result, E>; From ffb5f2936212309a313d0016c7e8f64051b77fbd Mon Sep 17 00:00:00 2001 From: Kirill Mironov Date: Sat, 1 Aug 2020 00:18:52 +0300 Subject: [PATCH 04/41] Allow for custom error types in TransitionOut --- Cargo.toml | 2 +- src/dispatching/dialogue/dialogue_stage.rs | 4 ++-- src/dispatching/dialogue/mod.rs | 2 +- src/dispatching/dialogue/transition.rs | 16 ++++++++++++---- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a8661289..d1db35be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ serde_cbor = { version = "0.11.1", optional = true } bincode = { version = "1.3.1", optional = true } frunk = { version = "0.3.1", optional = true } -teloxide-macros = "0.3.2" +teloxide-macros = { git = "https://github.com/teloxide/teloxide-macros", branch = "feature/arbitrary-transition-result-types" } [dev-dependencies] smart-default = "0.6.0" diff --git a/src/dispatching/dialogue/dialogue_stage.rs b/src/dispatching/dialogue/dialogue_stage.rs index 7dcafec3..ad731e74 100644 --- a/src/dispatching/dialogue/dialogue_stage.rs +++ b/src/dispatching/dialogue/dialogue_stage.rs @@ -21,7 +21,7 @@ pub enum DialogueStage { /// /// [`From`]: std::convert::From /// [derive-more]: https://crates.io/crates/derive_more -pub fn next(new_state: State) -> TransitionOut +pub fn next(new_state: State) -> TransitionOut where Dialogue: From, { @@ -32,6 +32,6 @@ where /// /// See [the module-level documentation for the design /// overview](crate::dispatching::dialogue). -pub fn exit() -> TransitionOut { +pub fn exit() -> TransitionOut { Ok(DialogueStage::Exit) } diff --git a/src/dispatching/dialogue/mod.rs b/src/dispatching/dialogue/mod.rs index 420a755b..5030fd4b 100644 --- a/src/dispatching/dialogue/mod.rs +++ b/src/dispatching/dialogue/mod.rs @@ -39,7 +39,7 @@ //! struct _2State; //! struct _3State; //! -//! type Out = TransitionOut; +//! type Out = TransitionOut; //! //! #[teloxide(subtransition)] //! async fn _1_transition(_state: _1State, _cx: TransitionIn) -> Out { diff --git a/src/dispatching/dialogue/transition.rs b/src/dispatching/dialogue/transition.rs index 5a53a004..a811db4c 100644 --- a/src/dispatching/dialogue/transition.rs +++ b/src/dispatching/dialogue/transition.rs @@ -7,11 +7,16 @@ use futures::future::BoxFuture; /// Represents a transition function of a dialogue FSM. pub trait Transition: Sized { type Aux; + type Error; /// Turns itself into another state, depending on the input message. /// /// `aux` will be passed to each subtransition function. - fn react(self, cx: TransitionIn, aux: Self::Aux) -> BoxFuture<'static, TransitionOut>; + fn react( + self, + cx: TransitionIn, + aux: Self::Aux, + ) -> BoxFuture<'static, TransitionOut>; } /// Like [`Transition`], but from `StateN` -> `Dialogue`. @@ -23,6 +28,7 @@ where { type Aux; type Dialogue; + type Error; /// Turns itself into another state, depending on the input message. /// @@ -32,7 +38,7 @@ where self, cx: TransitionIn, aux: Self::Aux, - ) -> BoxFuture<'static, TransitionOut>; + ) -> BoxFuture<'static, TransitionOut>; } /// A type returned from a FSM subtransition function. @@ -40,14 +46,16 @@ where /// Now it is used only inside `#[teloxide(subtransition)]` for type inference. pub trait SubtransitionOutputType { type Output; + type Error; } -impl SubtransitionOutputType for TransitionOut { +impl SubtransitionOutputType for TransitionOut { type Output = D; + type Error = E; } /// An input passed into a FSM (sub)transition function. pub type TransitionIn = UpdateWithCx; /// A type returned from a FSM (sub)transition function. -pub type TransitionOut = Result, E>; +pub type TransitionOut = Result, E>; From 245355ea3e025a5054d13c99d406cdeca47d58b0 Mon Sep 17 00:00:00 2001 From: Kirill Mironov Date: Sat, 1 Aug 2020 11:58:24 +0300 Subject: [PATCH 05/41] set default error type --- src/dispatching/dialogue/transition.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dispatching/dialogue/transition.rs b/src/dispatching/dialogue/transition.rs index a811db4c..3150db98 100644 --- a/src/dispatching/dialogue/transition.rs +++ b/src/dispatching/dialogue/transition.rs @@ -58,4 +58,4 @@ impl SubtransitionOutputType for TransitionOut { pub type TransitionIn = UpdateWithCx; /// A type returned from a FSM (sub)transition function. -pub type TransitionOut = Result, E>; +pub type TransitionOut = Result, E>; From 90a65c0f9e8f07bd9209e8c932a04cd0ae030be2 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 1 Aug 2020 15:15:45 +0600 Subject: [PATCH 06/41] Update examples/README.md --- examples/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/README.md b/examples/README.md index db492ce7..6a41c295 100644 --- a/examples/README.md +++ b/examples/README.md @@ -2,11 +2,11 @@ Just enter the directory (for example, `cd dialogue_bot`) and execute `cargo run` to run an example. Don't forget to initialise the `TELOXIDE_TOKEN` environmental variable. | Bot | Description | |---|-----------| -| [dices_bot](dices_bot) | This bot throws a dice on each incoming message. | +| [dices_bot](dices_bot) | Throws a dice on each incoming message. | | [ngrok_ping_pong_bot](ngrok_ping_pong_bot) | The ngrok version of ping-pong-bot that uses webhooks. | | [heroku_ping_pong_bot](heroku_ping_pong_bot) | The Heroku version of ping-pong-bot that uses webhooks. | | [simple_commands_bot](simple_commands_bot) | Shows how to deal with bot's commands. | -| [guess_a_number_bot](guess_a_number_bot) | The "guess a number" game. | -| [dialogue_bot](dialogue_bot) | Drive a dialogue with a user using a type-safe finite automaton. | -| [admin_bot](admin_bot) | A bot, which can ban, kick, and mute on a command. | -| [shared_state_bot](shared_state_bot) | A bot that shows how to deal with shared state. | +| [redis_remember_bot](redis_remember) | Uses `RedisStorage` instead of `InMemStorage`. | +| [dialogue_bot](dialogue_bot) | How to deal with dialogues. | +| [admin_bot](admin_bot) | Ban, kick, and mute on a command. | +| [shared_state_bot](shared_state_bot) | How to deal with shared state. | From 71414b812f1c1363495d8d36c607d8bb221c9b69 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 1 Aug 2020 15:16:28 +0600 Subject: [PATCH 07/41] Update examples/README.md --- examples/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/README.md b/examples/README.md index 6a41c295..21515200 100644 --- a/examples/README.md +++ b/examples/README.md @@ -6,7 +6,7 @@ Just enter the directory (for example, `cd dialogue_bot`) and execute `cargo run | [ngrok_ping_pong_bot](ngrok_ping_pong_bot) | The ngrok version of ping-pong-bot that uses webhooks. | | [heroku_ping_pong_bot](heroku_ping_pong_bot) | The Heroku version of ping-pong-bot that uses webhooks. | | [simple_commands_bot](simple_commands_bot) | Shows how to deal with bot's commands. | -| [redis_remember_bot](redis_remember) | Uses `RedisStorage` instead of `InMemStorage`. | +| [redis_remember_bot](redis_remember_bot) | Uses `RedisStorage` instead of `InMemStorage`. | | [dialogue_bot](dialogue_bot) | How to deal with dialogues. | | [admin_bot](admin_bot) | Ban, kick, and mute on a command. | | [shared_state_bot](shared_state_bot) | How to deal with shared state. | From 8b14fb5122581e19c2827bfd287174a4aa720f96 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 1 Aug 2020 16:07:01 +0600 Subject: [PATCH 08/41] Download teloxide-macros from git in the examples --- examples/dialogue_bot/Cargo.toml | 2 +- examples/redis_remember_bot/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/dialogue_bot/Cargo.toml b/examples/dialogue_bot/Cargo.toml index 1f08c16a..c5dc6c01 100644 --- a/examples/dialogue_bot/Cargo.toml +++ b/examples/dialogue_bot/Cargo.toml @@ -17,7 +17,7 @@ futures = "0.3.5" tokio = { version = "0.2.11", features = ["rt-threaded", "macros"] } teloxide = { path = "../../", features = ["frunk"] } -teloxide-macros = "0.3.2" +teloxide-macros = { git = "https://github.com/teloxide/teloxide-macros", branch = "feature/arbitrary-transition-result-types" } derive_more = "0.99.9" diff --git a/examples/redis_remember_bot/Cargo.toml b/examples/redis_remember_bot/Cargo.toml index 6927b9d8..992b2a2d 100644 --- a/examples/redis_remember_bot/Cargo.toml +++ b/examples/redis_remember_bot/Cargo.toml @@ -11,7 +11,7 @@ tokio = { version = "0.2.11", features = ["rt-threaded", "macros"] } # You can also choose "cbor-serializer" or built-in JSON serializer teloxide = { path = "../../", features = ["redis-storage", "bincode-serializer"] } -teloxide-macros = "0.3.2" +teloxide-macros = { git = "https://github.com/teloxide/teloxide-macros", branch = "feature/arbitrary-transition-result-types" } serde = "1.0.104" futures = "0.3.5" From b3aa539c4d989057c5f81ec6c4aa85e70ddbd80e Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 1 Aug 2020 17:52:50 +0600 Subject: [PATCH 09/41] Download the master branch of teloxide-macros --- Cargo.toml | 2 +- examples/dialogue_bot/Cargo.toml | 2 +- examples/redis_remember_bot/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d1db35be..2497c1c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ serde_cbor = { version = "0.11.1", optional = true } bincode = { version = "1.3.1", optional = true } frunk = { version = "0.3.1", optional = true } -teloxide-macros = { git = "https://github.com/teloxide/teloxide-macros", branch = "feature/arbitrary-transition-result-types" } +teloxide-macros = { git = "https://github.com/teloxide/teloxide-macros", branch = "master" } [dev-dependencies] smart-default = "0.6.0" diff --git a/examples/dialogue_bot/Cargo.toml b/examples/dialogue_bot/Cargo.toml index c5dc6c01..3d36bb3c 100644 --- a/examples/dialogue_bot/Cargo.toml +++ b/examples/dialogue_bot/Cargo.toml @@ -17,7 +17,7 @@ futures = "0.3.5" tokio = { version = "0.2.11", features = ["rt-threaded", "macros"] } teloxide = { path = "../../", features = ["frunk"] } -teloxide-macros = { git = "https://github.com/teloxide/teloxide-macros", branch = "feature/arbitrary-transition-result-types" } +teloxide-macros = { git = "https://github.com/teloxide/teloxide-macros", branch = "master" } derive_more = "0.99.9" diff --git a/examples/redis_remember_bot/Cargo.toml b/examples/redis_remember_bot/Cargo.toml index 992b2a2d..f7843219 100644 --- a/examples/redis_remember_bot/Cargo.toml +++ b/examples/redis_remember_bot/Cargo.toml @@ -11,7 +11,7 @@ tokio = { version = "0.2.11", features = ["rt-threaded", "macros"] } # You can also choose "cbor-serializer" or built-in JSON serializer teloxide = { path = "../../", features = ["redis-storage", "bincode-serializer"] } -teloxide-macros = { git = "https://github.com/teloxide/teloxide-macros", branch = "feature/arbitrary-transition-result-types" } +teloxide-macros = { git = "https://github.com/teloxide/teloxide-macros", branch = "master" } serde = "1.0.104" futures = "0.3.5" From 6f13d38812c0b92f5a34e628844bba0b0a7fae9e Mon Sep 17 00:00:00 2001 From: DCjanus Date: Sun, 2 Aug 2020 02:43:30 +0800 Subject: [PATCH 10/41] remove unnecessary type bound --- src/dispatching/repls/commands_repl.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/dispatching/repls/commands_repl.rs b/src/dispatching/repls/commands_repl.rs index c842fd7a..d80138ca 100644 --- a/src/dispatching/repls/commands_repl.rs +++ b/src/dispatching/repls/commands_repl.rs @@ -22,13 +22,14 @@ use std::{fmt::Debug, future::Future, sync::Arc}; /// /// [REPL]: https://en.wikipedia.org/wiki/Read-eval-print_loop /// [`Dispatcher`]: crate::dispatching::Dispatcher -pub async fn commands_repl(bot: Bot, bot_name: &'static str, handler: H) +pub async fn commands_repl(bot: Bot, bot_name: N, handler: H) where Cmd: BotCommand + Send + 'static, H: Fn(UpdateWithCx, Cmd) -> Fut + Send + Sync + 'static, Fut: Future> + Send + 'static, Result<(), HandlerE>: OnError, HandlerE: Debug + Send, + N: Into + Send + 'static, { let cloned_bot = bot.clone(); @@ -53,9 +54,9 @@ where /// [`Dispatcher`]: crate::dispatching::Dispatcher /// [`commands_repl`]: crate::dispatching::repls::commands_repl() /// [`UpdateListener`]: crate::dispatching::update_listeners::UpdateListener -pub async fn commands_repl_with_listener<'a, Cmd, H, Fut, L, ListenerE, HandlerE>( +pub async fn commands_repl_with_listener<'a, Cmd, H, Fut, L, ListenerE, HandlerE, N>( bot: Bot, - bot_name: &'static str, + bot_name: N, handler: H, listener: L, ) where @@ -66,21 +67,19 @@ pub async fn commands_repl_with_listener<'a, Cmd, H, Fut, L, ListenerE, HandlerE ListenerE: Debug + Send + 'a, Result<(), HandlerE>: OnError, HandlerE: Debug + Send, + N: Into + Send + 'static, { let handler = Arc::new(handler); Dispatcher::new(bot) .messages_handler(move |rx: DispatcherHandlerRx| { - rx.commands::(bot_name).for_each_concurrent( - None, - move |(cx, cmd)| { - let handler = Arc::clone(&handler); + rx.commands::(bot_name).for_each_concurrent(None, move |(cx, cmd)| { + let handler = Arc::clone(&handler); - async move { - handler(cx, cmd).await.log_on_error().await; - } - }, - ) + async move { + handler(cx, cmd).await.log_on_error().await; + } + }) }) .dispatch_with_listener( listener, From 7b9f7e869030f90fcfe22df1dec0d1e4ae88408d Mon Sep 17 00:00:00 2001 From: DCjanus Date: Sun, 2 Aug 2020 12:11:09 +0800 Subject: [PATCH 11/41] fix example code --- README.md | 3 ++- examples/admin_bot/src/main.rs | 3 ++- examples/simple_commands_bot/src/main.rs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 19fa1b36..5a30bab9 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,8 @@ async fn main() { let bot = Bot::from_env(); - teloxide::commands_repl(bot, panic!("Your bot's name here"), answer).await; + let bot_name: String = panic!("Your bot's name here"); + teloxide::commands_repl(bot, bot_name, action).await; } ``` diff --git a/examples/admin_bot/src/main.rs b/examples/admin_bot/src/main.rs index ea4f9078..ee239fa0 100644 --- a/examples/admin_bot/src/main.rs +++ b/examples/admin_bot/src/main.rs @@ -139,5 +139,6 @@ async fn run() { let bot = Bot::from_env(); - teloxide::commands_repl(bot, panic!("Your bot's name here"), action).await; + let bot_name: String = panic!("Your bot's name here"); + teloxide::commands_repl(bot, bot_name, action).await; } diff --git a/examples/simple_commands_bot/src/main.rs b/examples/simple_commands_bot/src/main.rs index 24b88345..86a61bb6 100644 --- a/examples/simple_commands_bot/src/main.rs +++ b/examples/simple_commands_bot/src/main.rs @@ -36,5 +36,6 @@ async fn run() { let bot = Bot::from_env(); - teloxide::commands_repl(bot, panic!("Your bot's name here"), answer).await; + let bot_name: String = panic!("Your bot's name here"); + teloxide::commands_repl(bot, bot_name, answer).await; } From 05e32336faa7cd3bd824fb4c62647fbf484ee55e Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sun, 2 Aug 2020 13:08:43 +0600 Subject: [PATCH 12/41] Add requests::respond --- README.md | 2 +- examples/dices_bot/src/main.rs | 2 +- src/prelude.rs | 2 +- src/requests/mod.rs | 5 +++++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5a30bab9..427b78d3 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ async fn main() { teloxide::repl(bot, |message| async move { message.answer_dice().send().await?; - ResponseResult::<()>::Ok(()) + respond(()) }) .await; } diff --git a/examples/dices_bot/src/main.rs b/examples/dices_bot/src/main.rs index ea7f4424..0f5e46bd 100644 --- a/examples/dices_bot/src/main.rs +++ b/examples/dices_bot/src/main.rs @@ -15,7 +15,7 @@ async fn run() { teloxide::repl(bot, |message| async move { message.answer_dice().send().await?; - ResponseResult::<()>::Ok(()) + respond(()) }) .await; } diff --git a/src/prelude.rs b/src/prelude.rs index 3b2032d9..a7ce757e 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -9,7 +9,7 @@ pub use crate::{ Dispatcher, DispatcherHandlerRx, DispatcherHandlerRxExt, UpdateWithCx, }, error_handlers::{LoggingErrorHandler, OnError}, - requests::{Request, ResponseResult}, + requests::{respond, Request, ResponseResult}, types::{Message, Update}, Bot, RequestError, }; diff --git a/src/requests/mod.rs b/src/requests/mod.rs index 09f2af6c..bb104ddf 100644 --- a/src/requests/mod.rs +++ b/src/requests/mod.rs @@ -9,6 +9,11 @@ pub use all::*; /// A type that is returned after making a request to Telegram. pub type ResponseResult = Result; +/// A shortcut for `ResponseResult::Ok(val)`. +pub fn respond(val: T) -> ResponseResult { + ResponseResult::Ok(val) +} + /// Designates an API request. #[async_trait::async_trait] pub trait Request { From d7ad1f26ed3c0a6ab2ae0fda2b1c8824c3ea819f Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sun, 2 Aug 2020 13:16:53 +0600 Subject: [PATCH 13/41] Update CHANGELOG.md --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd3cf8cd..db431426 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [unreleased] + +### Added + - Allow arbitrary error types to be returned from (sub)transitions ([issue 242](https://github.com/teloxide/teloxide/issues/242)). + - The `respond` function, a shortcut for `ResponseResult::Ok(())`. + +### Changed + - Allow `bot_name` be `N`, where `N: Into + ...` in `commands_repl` & `commands_repl_with_listener`. + ## [0.3.0] - 2020-07-31 ### Added - Support for typed bot commands ([issue 152](https://github.com/teloxide/teloxide/issues/152)). From 817f492223332295bbd8f426822bac7c85e98844 Mon Sep 17 00:00:00 2001 From: PatriotRossii Date: Fri, 7 Aug 2020 05:55:06 +0500 Subject: [PATCH 14/41] Un Arc<_> Bot::parse_mode --- src/bot/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bot/mod.rs b/src/bot/mod.rs index 1c205a21..bb008ef0 100644 --- a/src/bot/mod.rs +++ b/src/bot/mod.rs @@ -20,7 +20,7 @@ pub(crate) const TELOXIDE_PROXY: &str = "TELOXIDE_PROXY"; pub struct Bot { token: Arc, client: Client, - parse_mode: Arc>, + parse_mode: Option, } impl Bot { @@ -95,7 +95,7 @@ impl Bot { Self { token: Into::>::into(Into::::into(token)), client, - parse_mode: Arc::new(None), + parse_mode: None, } } } @@ -236,7 +236,7 @@ impl BotBuilder { Bot { client: self.client.unwrap_or_else(crate::utils::client_from_env), token: self.token.unwrap_or_else(|| get_env(TELOXIDE_TOKEN)).into(), - parse_mode: Arc::new(self.parse_mode), + parse_mode: self.parse_mode, } } } From 517afc0cfe80d8982835f330a28e8267b1fc3693 Mon Sep 17 00:00:00 2001 From: PatriotRossii Date: Fri, 7 Aug 2020 06:08:22 +0500 Subject: [PATCH 15/41] Remove unnecessary derefs --- src/bot/api.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bot/api.rs b/src/bot/api.rs index 619d0777..a4d0c2db 100644 --- a/src/bot/api.rs +++ b/src/bot/api.rs @@ -1007,10 +1007,10 @@ impl Bot { where T: Into, { - match self.parse_mode.deref() { + match self.parse_mode { None => EditMessageText::new(self.clone(), chat_or_inline_message, text), Some(parse_mode) => EditMessageText::new(self.clone(), chat_or_inline_message, text) - .parse_mode(*parse_mode.deref()), + .parse_mode(parse_mode), } } @@ -1033,10 +1033,10 @@ impl Bot { &self, chat_or_inline_message: ChatOrInlineMessage, ) -> EditMessageCaption { - match self.parse_mode.deref() { + match self.parse_mode { None => EditMessageCaption::new(self.clone(), chat_or_inline_message), Some(parse_mode) => EditMessageCaption::new(self.clone(), chat_or_inline_message) - .parse_mode(*parse_mode.deref()), + .parse_mode(parse_mode), } } @@ -1530,9 +1530,9 @@ impl Bot { builder: Builder, f: fn(Builder, ParseMode) -> Builder, ) -> Builder { - match self.parse_mode.deref() { + match self.parse_mode { None => builder, - Some(parse_mode) => f(builder, *parse_mode.deref()), + Some(parse_mode) => f(builder, parse_mode), } } } From b1ac80e244bc29943e1253238fb0f7577cb87a9b Mon Sep 17 00:00:00 2001 From: Eoan Ermine Date: Fri, 7 Aug 2020 12:02:30 +0500 Subject: [PATCH 16/41] Fix code formatting, remove unused import --- src/bot/api.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bot/api.rs b/src/bot/api.rs index a4d0c2db..f90c5123 100644 --- a/src/bot/api.rs +++ b/src/bot/api.rs @@ -21,7 +21,6 @@ use crate::{ }, Bot, }; -use std::ops::Deref; impl Bot { /// Use this method to receive incoming updates using long polling ([wiki]). @@ -1035,8 +1034,9 @@ impl Bot { ) -> EditMessageCaption { match self.parse_mode { None => EditMessageCaption::new(self.clone(), chat_or_inline_message), - Some(parse_mode) => EditMessageCaption::new(self.clone(), chat_or_inline_message) - .parse_mode(parse_mode), + Some(parse_mode) => { + EditMessageCaption::new(self.clone(), chat_or_inline_message).parse_mode(parse_mode) + } } } From 503f406eddedb701df2a7276ce451a519f835816 Mon Sep 17 00:00:00 2001 From: Waffle Date: Fri, 7 Aug 2020 00:48:17 +0300 Subject: [PATCH 17/41] Fix `edit_*` and `stop_inline_message_live_location` methods Previously they have been broken because of the wrong type of `ChatOrInlineMessage::Inline::inline_message_id` (`i32` instead of `String`), and wrong return type in case of inline editing messages (`Message` instead of `True`). This commit splits the methods into inline and non-inline versions, fixing the issue. --- src/bot/api.rs | 292 +++++++++++++----- src/dispatching/update_with_cx.rs | 15 +- .../all/edit_inline_message_caption.rs | 83 +++++ .../all/edit_inline_message_live_location.rs | 77 +++++ src/requests/all/edit_inline_message_media.rs | 78 +++++ .../all/edit_inline_message_reply_markup.rs | 62 ++++ src/requests/all/edit_inline_message_text.rs | 98 ++++++ src/requests/all/edit_message_caption.rs | 35 ++- .../all/edit_message_live_location.rs | 40 ++- src/requests/all/edit_message_media.rs | 55 ++-- src/requests/all/edit_message_reply_markup.rs | 33 +- src/requests/all/edit_message_text.rs | 35 ++- src/requests/all/mod.rs | 12 + .../all/stop_inline_message_live_location.rs | 62 ++++ .../all/stop_message_live_location.rs | 33 +- 15 files changed, 844 insertions(+), 166 deletions(-) create mode 100644 src/requests/all/edit_inline_message_caption.rs create mode 100644 src/requests/all/edit_inline_message_live_location.rs create mode 100644 src/requests/all/edit_inline_message_media.rs create mode 100644 src/requests/all/edit_inline_message_reply_markup.rs create mode 100644 src/requests/all/edit_inline_message_text.rs create mode 100644 src/requests/all/stop_inline_message_live_location.rs diff --git a/src/bot/api.rs b/src/bot/api.rs index f90c5123..3f3fb8c7 100644 --- a/src/bot/api.rs +++ b/src/bot/api.rs @@ -2,22 +2,24 @@ use crate::{ requests::{ AddStickerToSet, AnswerCallbackQuery, AnswerInlineQuery, AnswerPreCheckoutQuery, AnswerShippingQuery, CreateNewStickerSet, DeleteChatPhoto, DeleteChatStickerSet, - DeleteMessage, DeleteStickerFromSet, DeleteWebhook, EditMessageCaption, - EditMessageLiveLocation, EditMessageMedia, EditMessageReplyMarkup, EditMessageText, - ExportChatInviteLink, ForwardMessage, GetChat, GetChatAdministrators, GetChatMember, - GetChatMembersCount, GetFile, GetGameHighScores, GetMe, GetMyCommands, GetStickerSet, - GetUpdates, GetUserProfilePhotos, GetWebhookInfo, KickChatMember, LeaveChat, - PinChatMessage, PromoteChatMember, RestrictChatMember, SendAnimation, SendAudio, - SendChatAction, SendChatActionKind, SendContact, SendDice, SendDocument, SendGame, - SendInvoice, SendLocation, SendMediaGroup, SendMessage, SendPhoto, SendPoll, SendSticker, - SendVenue, SendVideo, SendVideoNote, SendVoice, SetChatAdministratorCustomTitle, - SetChatDescription, SetChatPermissions, SetChatPhoto, SetChatStickerSet, SetChatTitle, - SetGameScore, SetMyCommands, SetStickerPositionInSet, SetStickerSetThumb, SetWebhook, - StopMessageLiveLocation, StopPoll, UnbanChatMember, UnpinChatMessage, UploadStickerFile, + DeleteMessage, DeleteStickerFromSet, DeleteWebhook, EditInlineMessageCaption, + EditInlineMessageLiveLocation, EditInlineMessageMedia, EditInlineMessageReplyMarkup, + EditInlineMessageText, EditMessageCaption, EditMessageLiveLocation, EditMessageMedia, + EditMessageReplyMarkup, EditMessageText, ExportChatInviteLink, ForwardMessage, GetChat, + GetChatAdministrators, GetChatMember, GetChatMembersCount, GetFile, GetGameHighScores, + GetMe, GetMyCommands, GetStickerSet, GetUpdates, GetUserProfilePhotos, GetWebhookInfo, + KickChatMember, LeaveChat, PinChatMessage, PromoteChatMember, RestrictChatMember, + SendAnimation, SendAudio, SendChatAction, SendChatActionKind, SendContact, SendDice, + SendDocument, SendGame, SendInvoice, SendLocation, SendMediaGroup, SendMessage, SendPhoto, + SendPoll, SendSticker, SendVenue, SendVideo, SendVideoNote, SendVoice, + SetChatAdministratorCustomTitle, SetChatDescription, SetChatPermissions, SetChatPhoto, + SetChatStickerSet, SetChatTitle, SetGameScore, SetMyCommands, SetStickerPositionInSet, + SetStickerSetThumb, SetWebhook, StopInlineMessageLiveLocation, StopMessageLiveLocation, + StopPoll, UnbanChatMember, UnpinChatMessage, UploadStickerFile, }, types::{ - BotCommand, ChatId, ChatOrInlineMessage, ChatPermissions, InlineQueryResult, InputFile, - InputMedia, LabeledPrice, ParseMode, StickerType, + BotCommand, ChatId, ChatPermissions, InlineQueryResult, InputFile, InputMedia, + LabeledPrice, ParseMode, StickerType, TargetMessage, }, Bot, }; @@ -409,42 +411,89 @@ impl Bot { /// Use this method to edit live location messages. /// /// A location can be edited until its live_period expires or editing is - /// explicitly disabled by a call to stopMessageLiveLocation. On success, if - /// the edited message was sent by the bot, the edited [`Message`] is - /// returned, otherwise [`True`] is returned. + /// explicitly disabled by a call to stopMessageLiveLocation. On success, + /// the edited [`Message`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#editmessagelivelocation). /// + /// [`Message`]: crate::types::Message + /// /// # Params /// - `latitude`: Latitude of new location. /// - `longitude`: Longitude of new location. - /// - /// [`Message`]: crate::types::Message - /// [`True`]: crate::types::True - pub fn edit_message_live_location( + pub fn edit_message_live_location( &self, - chat_or_inline_message: ChatOrInlineMessage, + chat_id: C, + message_id: i32, latitude: f32, longitude: f32, - ) -> EditMessageLiveLocation { - EditMessageLiveLocation::new(self.clone(), chat_or_inline_message, latitude, longitude) + ) -> EditMessageLiveLocation + where + C: Into, + { + EditMessageLiveLocation::new(self.clone(), chat_id, message_id, latitude, longitude) + } + + /// Use this method to edit live location messages sent via the bot. + /// + /// A location can be edited until its live_period expires or editing is + /// explicitly disabled by a call to stopMessageLiveLocation. On success, + /// [`True`] is returned. + /// + /// [The official docs](https://core.telegram.org/bots/api#editmessagelivelocation). + /// + /// [`True`]: crate::types::True + /// + /// # Params + /// - `latitude`: Latitude of new location. + /// - `longitude`: Longitude of new location. + pub fn edit_inline_message_live_location( + &self, + inline_message_id: I, + latitude: f32, + longitude: f32, + ) -> EditInlineMessageLiveLocation + where + I: Into, + { + EditInlineMessageLiveLocation::new(self.clone(), inline_message_id, latitude, longitude) } /// Use this method to stop updating a live location message before /// `live_period` expires. /// - /// On success, if the message was sent by the bot, the sent [`Message`] is - /// returned, otherwise [`True`] is returned. + /// On success, the sent [`Message`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#stopmessagelivelocation). /// /// [`Message`]: crate::types::Message - /// [`True`]: crate::types::True - pub fn stop_message_live_location( + pub fn stop_message_live_location( &self, - chat_or_inline_message: ChatOrInlineMessage, - ) -> StopMessageLiveLocation { - StopMessageLiveLocation::new(self.clone(), chat_or_inline_message) + chat_id: C, + message_id: i32, + ) -> StopMessageLiveLocation + where + C: Into, + { + StopMessageLiveLocation::new(self.clone(), chat_id, message_id) + } + + /// Use this method to stop updating a live location message (sent via the + /// bot) before `live_period` expires. + /// + /// On success, [`True`] is returned. + /// + /// [The official docs](https://core.telegram.org/bots/api#stopmessagelivelocation). + /// + /// [`True`]: crate::types::True + pub fn stop_inline_message_live_location( + &self, + inline_message_id: I, + ) -> StopInlineMessageLiveLocation + where + I: Into, + { + StopInlineMessageLiveLocation::new(self.clone(), inline_message_id) } /// Use this method to send information about a venue. @@ -982,45 +1031,103 @@ impl Bot { /// Use this method to edit text and game messages. /// - /// On success, if edited message is sent by the bot, the edited [`Message`] - /// is returned, otherwise [`True`] is returned. + /// On success, the edited [`Message`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#editmessagetext). /// - /// # Params - /// - New text of the message. - /// /// [`Message`]: crate::types::Message - /// [`True`]: crate::types::True + /// + /// # Params + /// + /// - `chat_id`: Unique identifier for the target chat or username of the + /// target channel (in the format `@channelusername`). + /// - `message_id`: Identifier of the message to edit. + /// - `text`: New text of the message. /// /// # Notes + /// /// Uses [a default parse mode] if specified in [`BotBuilder`]. /// /// [a default parse mode]: crate::BotBuilder::parse_mode /// [`BotBuilder`]: crate::BotBuilder - pub fn edit_message_text( - &self, - chat_or_inline_message: ChatOrInlineMessage, - text: T, - ) -> EditMessageText + pub fn edit_message_text(&self, chat_id: C, message_id: i32, text: T) -> EditMessageText where + C: Into, T: Into, { match self.parse_mode { - None => EditMessageText::new(self.clone(), chat_or_inline_message, text), - Some(parse_mode) => EditMessageText::new(self.clone(), chat_or_inline_message, text) + None => EditMessageText::new(self.clone(), chat_id, message_id, text), + Some(parse_mode) => EditMessageText::new(self.clone(), chat_id, message_id, text) .parse_mode(parse_mode), } } - /// Use this method to edit captions of messages. + /// Use this method to edit text and game messages sent via the bot. /// - /// On success, if edited message is sent by the bot, the edited [`Message`] - /// is returned, otherwise [`True`] is returned. + /// On success, [`True`] is returned. + /// + /// [The official docs](https://core.telegram.org/bots/api#editmessagetext). + /// + /// [`True`]: crate::types::True + /// + /// # Params + /// + /// - `inline_message_id`: Identifier of the inline message. + /// - `text`: New text of the message. + /// + /// # Notes + /// + /// Uses [a default parse mode] if specified in [`BotBuilder`]. + /// + /// [a default parse mode]: crate::BotBuilder::parse_mode + /// [`BotBuilder`]: crate::BotBuilder + pub fn edit_inline_message_text( + &self, + inline_message_id: I, + text: T, + ) -> EditInlineMessageText + where + I: Into, + T: Into, + { + match self.parse_mode { + None => EditInlineMessageText::new(self.clone(), inline_message_id, text), + Some(parse_mode) => EditInlineMessageText::new(self.clone(), inline_message_id, text) + .parse_mode(parse_mode), + } + } + + /// Use this method to edit captions of messages sent via the bot. + /// + /// On success, [`True`] is returned. + /// + /// [The official docs](https://core.telegram.org/bots/api#editmessagecaption). + /// + /// [`True`]: crate::types::True + /// + /// # Notes + /// + /// Uses [a default parse mode] if specified in [`BotBuilder`]. + /// + /// [a default parse mode]: crate::BotBuilder::parse_mode + /// [`BotBuilder`]: crate::BotBuilder + pub fn edit_message_caption(&self, chat_id: C, message_id: i32) -> EditMessageCaption + where + C: Into, + { + match self.parse_mode { + None => EditMessageCaption::new(self.clone(), chat_id, message_id), + Some(parse_mode) => EditMessageCaption::new(self.clone(), chat_id, message_id) + .parse_mode(parse_mode), + } + } + + /// Use this method to edit captions of messages sent via the bot. + /// + /// On success, [`True`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#editmessagecaption). /// - /// [`Message`]: crate::types::Message /// [`True`]: crate::types::True /// /// # Notes @@ -1028,15 +1135,14 @@ impl Bot { /// /// [a default parse mode]: crate::BotBuilder::parse_mode /// [`BotBuilder`]: crate::BotBuilder - pub fn edit_message_caption( - &self, - chat_or_inline_message: ChatOrInlineMessage, - ) -> EditMessageCaption { + pub fn edit_inline_message_caption(&self, inline_message_id: I) -> EditInlineMessageCaption + where + I: Into, + { match self.parse_mode { - None => EditMessageCaption::new(self.clone(), chat_or_inline_message), - Some(parse_mode) => { - EditMessageCaption::new(self.clone(), chat_or_inline_message).parse_mode(parse_mode) - } + None => EditInlineMessageCaption::new(self.clone(), inline_message_id), + Some(parse_mode) => EditInlineMessageCaption::new(self.clone(), inline_message_id) + .parse_mode(parse_mode), } } @@ -1045,37 +1151,81 @@ impl Bot { /// /// If a message is a part of a message album, then it can be edited only to /// a photo or a video. Otherwise, message type can be changed - /// arbitrarily. When inline message is edited, new file can't be - /// uploaded. Use previously uploaded file via its `file_id` or specify - /// a URL. On success, if the edited message was sent by the bot, the - /// edited [`Message`] is returned, otherwise [`True`] is returned. + /// arbitrarily. On success, the edited [`Message`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#editmessagemedia). /// /// [`Message`]: crate::types::Message - /// [`True`]: crate::types::True - pub fn edit_message_media( + pub fn edit_message_media( &self, - chat_or_inline_message: ChatOrInlineMessage, + chat_id: C, + message_id: i32, media: InputMedia, - ) -> EditMessageMedia { - EditMessageMedia::new(self.clone(), chat_or_inline_message, media) + ) -> EditMessageMedia + where + C: Into, + { + EditMessageMedia::new(self.clone(), chat_id, message_id, media) + } + + /// Use this method to edit animation, audio, document, photo, or video + /// messages sent via the bot. + /// + /// If a message is a part of a message album, then it can be edited only to + /// a photo or a video. Otherwise, message type can be changed + /// arbitrarily. When this method is used, new file can't be uploaded. + /// Use previously uploaded file via its `file_id` or specify a URL. On + /// success, [`True`] is returned. + /// + /// [The official docs](https://core.telegram.org/bots/api#editmessagemedia). + /// + /// [`True`]: crate::types::True + pub fn edit_inline_message_media( + &self, + inline_message_id: I, + media: InputMedia, + ) -> EditInlineMessageMedia + where + I: Into, + { + EditInlineMessageMedia::new(self.clone(), inline_message_id, media) } /// Use this method to edit only the reply markup of messages. /// - /// On success, if edited message is sent by the bot, the edited [`Message`] - /// is returned, otherwise [`True`] is returned. + /// On success, the edited [`Message`] is returned. + /// + /// [The official docs](https://core.telegram.org/bots/api#editmessagereplymarkup). + /// + /// [`Message`]: crate::types::Message + pub fn edit_message_reply_markup( + &self, + chat_id: C, + message_id: i32, + ) -> EditMessageReplyMarkup + where + C: Into, + { + EditMessageReplyMarkup::new(self.clone(), chat_id, message_id) + } + + /// Use this method to edit only the reply markup of messages sent via the + /// bot. + /// + /// On success, [`True`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#editmessagereplymarkup). /// /// [`Message`]: crate::types::Message /// [`True`]: crate::types::True - pub fn edit_message_reply_markup( + pub fn edit_inline_message_reply_markup( &self, - chat_or_inline_message: ChatOrInlineMessage, - ) -> EditMessageReplyMarkup { - EditMessageReplyMarkup::new(self.clone(), chat_or_inline_message) + inline_message_id: I, + ) -> EditInlineMessageReplyMarkup + where + I: Into, + { + EditInlineMessageReplyMarkup::new(self.clone(), inline_message_id) } /// Use this method to stop a poll which was sent by the bot. diff --git a/src/dispatching/update_with_cx.rs b/src/dispatching/update_with_cx.rs index 66c0beec..f3fa74e1 100644 --- a/src/dispatching/update_with_cx.rs +++ b/src/dispatching/update_with_cx.rs @@ -6,7 +6,7 @@ use crate::{ SendLocation, SendMediaGroup, SendMessage, SendPhoto, SendSticker, SendVenue, SendVideo, SendVideoNote, SendVoice, }, - types::{ChatId, ChatOrInlineMessage, InputFile, InputMedia, Message}, + types::{ChatId, InputFile, InputMedia, Message}, Bot, }; @@ -130,20 +130,11 @@ impl UpdateWithCx { where T: Into, { - self.bot.edit_message_text( - ChatOrInlineMessage::Chat { - chat_id: self.update.chat.id.into(), - message_id: self.update.id, - }, - text, - ) + self.bot.edit_message_text(self.update.chat.id, self.update.id, text) } pub fn edit_message_caption(&self) -> EditMessageCaption { - self.bot.edit_message_caption(ChatOrInlineMessage::Chat { - chat_id: self.update.chat.id.into(), - message_id: self.update.id, - }) + self.bot.edit_message_caption(self.update.chat.id, self.update.id) } pub fn delete_message(&self) -> DeleteMessage { diff --git a/src/requests/all/edit_inline_message_caption.rs b/src/requests/all/edit_inline_message_caption.rs new file mode 100644 index 00000000..e777f17c --- /dev/null +++ b/src/requests/all/edit_inline_message_caption.rs @@ -0,0 +1,83 @@ +use serde::Serialize; + +use crate::{ + net, + requests::{Request, ResponseResult}, + types::{InlineKeyboardMarkup, ParseMode, True}, + Bot, +}; + +/// Use this method to edit captions of messages sent via the bot. +/// +/// On success, [`True`] is returned. +/// +/// [The official docs](https://core.telegram.org/bots/api#editmessagecaption). +/// +/// [`True`]: crate::types::True +#[serde_with_macros::skip_serializing_none] +#[derive(Debug, Clone, Serialize)] +pub struct EditInlineMessageCaption { + #[serde(skip_serializing)] + bot: Bot, + inline_message_id: String, + caption: Option, + parse_mode: Option, + reply_markup: Option, +} + +#[async_trait::async_trait] +impl Request for EditInlineMessageCaption { + type Output = True; + + async fn send(&self) -> ResponseResult { + net::request_json(self.bot.client(), self.bot.token(), "editMessageCaption", &self).await + } +} + +impl EditInlineMessageCaption { + pub(crate) fn new(bot: Bot, inline_message_id: I) -> Self + where + I: Into, + { + let inline_message_id = inline_message_id.into(); + Self { bot, inline_message_id, caption: None, parse_mode: None, reply_markup: None } + } + + /// Identifier of the inline message. + pub fn inline_message_id(mut self, val: T) -> Self + where + T: Into, + { + self.inline_message_id = val.into(); + self + } + + /// New caption of the message. + pub fn caption(mut self, val: T) -> Self + where + T: Into, + { + self.caption = Some(val.into()); + self + } + + /// Send [Markdown] or [HTML], if you want Telegram apps to show + /// [bold, italic, fixed-width text or inline URLs] in the media caption. + /// + /// [Markdown]: crate::types::ParseMode::Markdown + /// [HTML]: crate::types::ParseMode::HTML + /// [bold, italic, fixed-width text or inline URLs]: + /// crate::types::ParseMode + pub fn parse_mode(mut self, val: ParseMode) -> Self { + self.parse_mode = Some(val); + self + } + + /// A JSON-serialized object for an [inline keyboard]. + /// + /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating + pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { + self.reply_markup = Some(val); + self + } +} diff --git a/src/requests/all/edit_inline_message_live_location.rs b/src/requests/all/edit_inline_message_live_location.rs new file mode 100644 index 00000000..4b267427 --- /dev/null +++ b/src/requests/all/edit_inline_message_live_location.rs @@ -0,0 +1,77 @@ +use serde::Serialize; + +use crate::{ + net, + requests::{Request, ResponseResult}, + types::{InlineKeyboardMarkup, True}, + Bot, +}; + +/// Use this method to edit live location messages sent via the bot. +/// +/// A location can be edited until its live_period expires or editing is +/// explicitly disabled by a call to stopMessageLiveLocation. On success, +/// [`True`] is returned. +/// +/// [The official docs](https://core.telegram.org/bots/api#editmessagelivelocation). +/// +/// [`True`]: crate::types::True +#[serde_with_macros::skip_serializing_none] +#[derive(Debug, Clone, Serialize)] +pub struct EditInlineMessageLiveLocation { + #[serde(skip_serializing)] + bot: Bot, + inline_message_id: String, + latitude: f32, + longitude: f32, + reply_markup: Option, +} + +#[async_trait::async_trait] +impl Request for EditInlineMessageLiveLocation { + type Output = True; + + async fn send(&self) -> ResponseResult { + net::request_json(self.bot.client(), self.bot.token(), "editMessageLiveLocation", &self) + .await + } +} + +impl EditInlineMessageLiveLocation { + pub(crate) fn new(bot: Bot, inline_message_id: I, latitude: f32, longitude: f32) -> Self + where + I: Into, + { + let inline_message_id = inline_message_id.into(); + Self { bot, inline_message_id, latitude, longitude, reply_markup: None } + } + + /// Identifier of the inline message. + pub fn inline_message_id(mut self, val: T) -> Self + where + T: Into, + { + self.inline_message_id = val.into(); + self + } + + /// Latitude of new location. + pub fn latitude(mut self, val: f32) -> Self { + self.latitude = val; + self + } + + /// Longitude of new location. + pub fn longitude(mut self, val: f32) -> Self { + self.longitude = val; + self + } + + /// A JSON-serialized object for a new [inline keyboard]. + /// + /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating + pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { + self.reply_markup = Some(val); + self + } +} diff --git a/src/requests/all/edit_inline_message_media.rs b/src/requests/all/edit_inline_message_media.rs new file mode 100644 index 00000000..9a11f126 --- /dev/null +++ b/src/requests/all/edit_inline_message_media.rs @@ -0,0 +1,78 @@ +use crate::{ + net, + requests::{form_builder::FormBuilder, Request, ResponseResult}, + types::{InlineKeyboardMarkup, InputMedia, True}, + Bot, +}; + +/// Use this method to edit animation, audio, document, photo, or video +/// messages sent via the bot. +/// +/// If a message is a part of a message album, then it can be edited only to a +/// photo or a video. Otherwise, message type can be changed arbitrarily. When +/// this method is used, new file can't be uploaded. Use previously +/// uploaded file via its `file_id` or specify a URL. On success, [`True`] is +/// returned. +/// +/// [The official docs](https://core.telegram.org/bots/api#editmessagemedia). +/// +/// [`True`]: crate::types::True +#[derive(Debug, Clone)] +pub struct EditInlineMessageMedia { + bot: Bot, + inline_message_id: String, + media: InputMedia, + reply_markup: Option, +} + +#[async_trait::async_trait] +impl Request for EditInlineMessageMedia { + type Output = True; + + async fn send(&self) -> ResponseResult { + net::request_multipart( + self.bot.client(), + self.bot.token(), + "editMessageMedia", + FormBuilder::new() + .add_text("media", &self.media) + .add_text("reply_markup", &self.reply_markup) + .add_text("inline_message_id", &self.inline_message_id) + .build(), + ) + .await + } +} + +impl EditInlineMessageMedia { + pub(crate) fn new(bot: Bot, inline_message_id: I, media: InputMedia) -> Self + where + I: Into, + { + let inline_message_id = inline_message_id.into(); + Self { bot, inline_message_id, media, reply_markup: None } + } + + /// Identifier of the inline message. + pub fn inline_message_id(mut self, val: T) -> Self + where + T: Into, + { + self.inline_message_id = val.into(); + self + } + + /// A JSON-serialized object for a new media content of the message. + pub fn media(mut self, val: InputMedia) -> Self { + self.media = val; + self + } + + /// A JSON-serialized object for a new [inline keyboard]. + /// + /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating + pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { + self.reply_markup = Some(val); + self + } +} diff --git a/src/requests/all/edit_inline_message_reply_markup.rs b/src/requests/all/edit_inline_message_reply_markup.rs new file mode 100644 index 00000000..cd96c686 --- /dev/null +++ b/src/requests/all/edit_inline_message_reply_markup.rs @@ -0,0 +1,62 @@ +use serde::Serialize; + +use crate::{ + net, + requests::{Request, ResponseResult}, + types::{InlineKeyboardMarkup, True}, + Bot, +}; + +/// Use this method to edit only the reply markup of messages sent via the bot. +/// +/// On success, [`True`] is returned. +/// +/// [The official docs](https://core.telegram.org/bots/api#editmessagereplymarkup). +/// +/// [`Message`]: crate::types::Message +/// [`True`]: crate::types::True +#[serde_with_macros::skip_serializing_none] +#[derive(Debug, Clone, Serialize)] +pub struct EditInlineMessageReplyMarkup { + #[serde(skip_serializing)] + bot: Bot, + inline_message_id: String, + reply_markup: Option, +} + +#[async_trait::async_trait] +impl Request for EditInlineMessageReplyMarkup { + type Output = True; + + async fn send(&self) -> ResponseResult { + net::request_json(self.bot.client(), self.bot.token(), "editMessageReplyMarkup", &self) + .await + } +} + +impl EditInlineMessageReplyMarkup { + pub(crate) fn new(bot: Bot, inline_message_id: I) -> Self + where + I: Into, + { + let inline_message_id = inline_message_id.into(); + Self { bot, inline_message_id, reply_markup: None } + } + + /// Identifier of the inline message. + pub fn inline_message_id(mut self, val: T) -> Self + where + T: Into, + { + self.inline_message_id = val.into(); + self + } + + /// A JSON-serialized object for an [inline keyboard]. + /// + /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating + pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { + self.reply_markup = Some(val); + self + } +} diff --git a/src/requests/all/edit_inline_message_text.rs b/src/requests/all/edit_inline_message_text.rs new file mode 100644 index 00000000..2b266314 --- /dev/null +++ b/src/requests/all/edit_inline_message_text.rs @@ -0,0 +1,98 @@ +use serde::Serialize; + +use crate::{ + net, + requests::{Request, ResponseResult}, + types::{InlineKeyboardMarkup, Message, ParseMode}, + Bot, +}; + +/// Use this method to edit text and game messages sent via the bot. +/// +/// On success, [`True`] is returned. +/// +/// [The official docs](https://core.telegram.org/bots/api#editmessagetext). +/// +/// [`True`]: crate::types::True +#[serde_with_macros::skip_serializing_none] +#[derive(Debug, Clone, Serialize)] +pub struct EditInlineMessageText { + #[serde(skip_serializing)] + bot: Bot, + inline_message_id: String, + text: String, + parse_mode: Option, + disable_web_page_preview: Option, + reply_markup: Option, +} + +#[async_trait::async_trait] +impl Request for EditInlineMessageText { + type Output = Message; + + async fn send(&self) -> ResponseResult { + net::request_json(self.bot.client(), self.bot.token(), "editMessageText", &self).await + } +} + +impl EditInlineMessageText { + pub(crate) fn new(bot: Bot, inline_message_id: I, text: T) -> Self + where + I: Into, + T: Into, + { + let inline_message_id = inline_message_id.into(); + let text = text.into(); + Self { + bot, + inline_message_id, + text, + parse_mode: None, + disable_web_page_preview: None, + reply_markup: None, + } + } + + /// Identifier of the inline message. + pub fn inline_message_id(mut self, val: T) -> Self + where + T: Into, + { + self.inline_message_id = val.into(); + self + } + + /// New text of the message. + pub fn text(mut self, val: T) -> Self + where + T: Into, + { + self.text = val.into(); + self + } + + /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, + /// italic, fixed-width text or inline URLs] in your bot's message. + /// + /// [Markdown]: https://core.telegram.org/bots/api#markdown-style + /// [HTML]: https://core.telegram.org/bots/api#html-style + /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options + pub fn parse_mode(mut self, val: ParseMode) -> Self { + self.parse_mode = Some(val); + self + } + + /// Disables link previews for links in this message. + pub fn disable_web_page_preview(mut self, val: bool) -> Self { + self.disable_web_page_preview = Some(val); + self + } + + /// A JSON-serialized object for an [inline keyboard]. + /// + /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating + pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { + self.reply_markup = Some(val); + self + } +} diff --git a/src/requests/all/edit_message_caption.rs b/src/requests/all/edit_message_caption.rs index 2b9f2839..9294af93 100644 --- a/src/requests/all/edit_message_caption.rs +++ b/src/requests/all/edit_message_caption.rs @@ -3,26 +3,24 @@ use serde::Serialize; use crate::{ net, requests::{Request, ResponseResult}, - types::{ChatOrInlineMessage, InlineKeyboardMarkup, Message, ParseMode}, + types::{ChatId, InlineKeyboardMarkup, Message, ParseMode}, Bot, }; -/// Use this method to edit captions of messages. +/// Use this method to edit captions of messages sent by the bot. /// -/// On success, if edited message is sent by the bot, the edited [`Message`] is -/// returned, otherwise [`True`] is returned. +/// On success, the edited [`Message`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#editmessagecaption). /// /// [`Message`]: crate::types::Message -/// [`True`]: crate::types::True #[serde_with_macros::skip_serializing_none] #[derive(Debug, Clone, Serialize)] pub struct EditMessageCaption { #[serde(skip_serializing)] bot: Bot, - #[serde(flatten)] - chat_or_inline_message: ChatOrInlineMessage, + chat_id: ChatId, + message_id: i32, caption: Option, parse_mode: Option, reply_markup: Option, @@ -38,12 +36,27 @@ impl Request for EditMessageCaption { } impl EditMessageCaption { - pub(crate) fn new(bot: Bot, chat_or_inline_message: ChatOrInlineMessage) -> Self { - Self { bot, chat_or_inline_message, caption: None, parse_mode: None, reply_markup: None } + pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32) -> Self + where + C: Into, + { + let chat_id = chat_id.into(); + Self { bot, chat_id, message_id, caption: None, parse_mode: None, reply_markup: None } } - pub fn chat_or_inline_message(mut self, val: ChatOrInlineMessage) -> Self { - self.chat_or_inline_message = val; + /// Unique identifier for the target chat or username of the target channel + /// (in the format `@channelusername`) + pub fn chat_id(mut self, val: T) -> Self + where + T: Into, + { + self.chat_id = val.into(); + self + } + + /// Identifier of the message to edit + pub fn message_id(mut self, val: i32) -> Self { + self.message_id = val; self } diff --git a/src/requests/all/edit_message_live_location.rs b/src/requests/all/edit_message_live_location.rs index 78fd163e..c5afd295 100644 --- a/src/requests/all/edit_message_live_location.rs +++ b/src/requests/all/edit_message_live_location.rs @@ -3,28 +3,26 @@ use serde::Serialize; use crate::{ net, requests::{Request, ResponseResult}, - types::{ChatOrInlineMessage, InlineKeyboardMarkup, Message}, + types::{ChatId, InlineKeyboardMarkup, Message}, Bot, }; /// Use this method to edit live location messages. /// /// A location can be edited until its live_period expires or editing is -/// explicitly disabled by a call to stopMessageLiveLocation. On success, if the -/// edited message was sent by the bot, the edited [`Message`] is returned, -/// otherwise [`True`] is returned. +/// explicitly disabled by a call to stopMessageLiveLocation. On success, the +/// edited [`Message`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#editmessagelivelocation). /// /// [`Message`]: crate::types::Message -/// [`True`]: crate::types::True #[serde_with_macros::skip_serializing_none] #[derive(Debug, Clone, Serialize)] pub struct EditMessageLiveLocation { #[serde(skip_serializing)] bot: Bot, - #[serde(flatten)] - chat_or_inline_message: ChatOrInlineMessage, + chat_id: ChatId, + message_id: i32, latitude: f32, longitude: f32, reply_markup: Option, @@ -41,17 +39,33 @@ impl Request for EditMessageLiveLocation { } impl EditMessageLiveLocation { - pub(crate) fn new( + pub(crate) fn new( bot: Bot, - chat_or_inline_message: ChatOrInlineMessage, + chat_id: C, + message_id: i32, latitude: f32, longitude: f32, - ) -> Self { - Self { bot, chat_or_inline_message, latitude, longitude, reply_markup: None } + ) -> Self + where + C: Into, + { + let chat_id = chat_id.into(); + Self { bot, chat_id, message_id, latitude, longitude, reply_markup: None } } - pub fn chat_or_inline_message(mut self, val: ChatOrInlineMessage) -> Self { - self.chat_or_inline_message = val; + /// Unique identifier for the target chat or username of the target channel + /// (in the format `@channelusername`) + pub fn chat_id(mut self, val: T) -> Self + where + T: Into, + { + self.chat_id = val.into(); + self + } + + /// Identifier of the message to edit + pub fn message_id(mut self, val: i32) -> Self { + self.message_id = val; self } diff --git a/src/requests/all/edit_message_media.rs b/src/requests/all/edit_message_media.rs index fd49c5c0..7f15ed5f 100644 --- a/src/requests/all/edit_message_media.rs +++ b/src/requests/all/edit_message_media.rs @@ -1,7 +1,7 @@ use crate::{ net, requests::{form_builder::FormBuilder, Request, ResponseResult}, - types::{ChatOrInlineMessage, InlineKeyboardMarkup, InputMedia, Message}, + types::{ChatId, InlineKeyboardMarkup, InputMedia, Message}, Bot, }; @@ -9,20 +9,17 @@ use crate::{ /// messages. /// /// If a message is a part of a message album, then it can be edited only to a -/// photo or a video. Otherwise, message type can be changed arbitrarily. When -/// inline message is edited, new file can't be uploaded. Use previously -/// uploaded file via its `file_id` or specify a URL. On success, if the edited -/// message was sent by the bot, the edited [`Message`] is returned, -/// otherwise [`True`] is returned. +/// photo or a video. Otherwise, message type can be changed arbitrarily. On +/// success, the edited [`Message`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#editmessagemedia). /// /// [`Message`]: crate::types::Message -/// [`True`]: crate::types::True #[derive(Debug, Clone)] pub struct EditMessageMedia { bot: Bot, - chat_or_inline_message: ChatOrInlineMessage, + chat_id: ChatId, + message_id: i32, media: InputMedia, reply_markup: Option, } @@ -32,22 +29,13 @@ impl Request for EditMessageMedia { type Output = Message; async fn send(&self) -> ResponseResult { - let mut params = FormBuilder::new(); - - match &self.chat_or_inline_message { - ChatOrInlineMessage::Chat { chat_id, message_id } => { - params = params.add_text("chat_id", chat_id).add_text("message_id", message_id); - } - ChatOrInlineMessage::Inline { inline_message_id } => { - params = params.add_text("inline_message_id", inline_message_id); - } - } - net::request_multipart( self.bot.client(), self.bot.token(), "editMessageMedia", - params + FormBuilder::new() + .add_text("chat_id", &self.chat_id) + .add_text("message_id", &self.message_id) .add_text("media", &self.media) .add_text("reply_markup", &self.reply_markup) .build(), @@ -57,16 +45,27 @@ impl Request for EditMessageMedia { } impl EditMessageMedia { - pub(crate) fn new( - bot: Bot, - chat_or_inline_message: ChatOrInlineMessage, - media: InputMedia, - ) -> Self { - Self { bot, chat_or_inline_message, media, reply_markup: None } + pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32, media: InputMedia) -> Self + where + C: Into, + { + let chat_id = chat_id.into(); + Self { bot, chat_id, message_id, media, reply_markup: None } } - pub fn chat_or_inline_message(mut self, val: ChatOrInlineMessage) -> Self { - self.chat_or_inline_message = val; + /// Unique identifier for the target chat or username of the target channel + /// (in the format `@channelusername`) + pub fn chat_id(mut self, val: T) -> Self + where + T: Into, + { + self.chat_id = val.into(); + self + } + + /// Identifier of the message to edit + pub fn message_id(mut self, val: i32) -> Self { + self.message_id = val; self } diff --git a/src/requests/all/edit_message_reply_markup.rs b/src/requests/all/edit_message_reply_markup.rs index cdfd9e67..66aab5bf 100644 --- a/src/requests/all/edit_message_reply_markup.rs +++ b/src/requests/all/edit_message_reply_markup.rs @@ -3,26 +3,24 @@ use serde::Serialize; use crate::{ net, requests::{Request, ResponseResult}, - types::{ChatOrInlineMessage, InlineKeyboardMarkup, Message}, + types::{ChatId, InlineKeyboardMarkup, Message}, Bot, }; /// Use this method to edit only the reply markup of messages. /// -/// On success, if edited message is sent by the bot, the edited [`Message`] is -/// returned, otherwise [`True`] is returned. +/// On success, the edited [`Message`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#editmessagereplymarkup). /// /// [`Message`]: crate::types::Message -/// [`True`]: crate::types::True #[serde_with_macros::skip_serializing_none] #[derive(Debug, Clone, Serialize)] pub struct EditMessageReplyMarkup { #[serde(skip_serializing)] bot: Bot, - #[serde(flatten)] - chat_or_inline_message: ChatOrInlineMessage, + chat_id: ChatId, + message_id: i32, reply_markup: Option, } @@ -37,12 +35,27 @@ impl Request for EditMessageReplyMarkup { } impl EditMessageReplyMarkup { - pub(crate) fn new(bot: Bot, chat_or_inline_message: ChatOrInlineMessage) -> Self { - Self { bot, chat_or_inline_message, reply_markup: None } + pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32) -> Self + where + C: Into, + { + let chat_id = chat_id.into(); + Self { bot, chat_id, message_id, reply_markup: None } } - pub fn chat_or_inline_message(mut self, val: ChatOrInlineMessage) -> Self { - self.chat_or_inline_message = val; + /// Unique identifier for the target chat or username of the target channel + /// (in the format `@channelusername`) + pub fn chat_id(mut self, val: T) -> Self + where + T: Into, + { + self.chat_id = val.into(); + self + } + + /// Identifier of the message to edit + pub fn message_id(mut self, val: i32) -> Self { + self.message_id = val; self } diff --git a/src/requests/all/edit_message_text.rs b/src/requests/all/edit_message_text.rs index 71c7aeed..12251313 100644 --- a/src/requests/all/edit_message_text.rs +++ b/src/requests/all/edit_message_text.rs @@ -3,26 +3,24 @@ use serde::Serialize; use crate::{ net, requests::{Request, ResponseResult}, - types::{ChatOrInlineMessage, InlineKeyboardMarkup, Message, ParseMode}, + types::{ChatId, InlineKeyboardMarkup, Message, ParseMode}, Bot, }; /// Use this method to edit text and game messages. /// -/// On success, if edited message is sent by the bot, the edited [`Message`] is -/// returned, otherwise [`True`] is returned. +/// On success, the edited [`Message`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#editmessagetext). /// /// [`Message`]: crate::types::Message -/// [`True`]: crate::types::True #[serde_with_macros::skip_serializing_none] #[derive(Debug, Clone, Serialize)] pub struct EditMessageText { #[serde(skip_serializing)] bot: Bot, - #[serde(flatten)] - chat_or_inline_message: ChatOrInlineMessage, + chat_id: ChatId, + message_id: i32, text: String, parse_mode: Option, disable_web_page_preview: Option, @@ -39,22 +37,37 @@ impl Request for EditMessageText { } impl EditMessageText { - pub(crate) fn new(bot: Bot, chat_or_inline_message: ChatOrInlineMessage, text: T) -> Self + pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32, text: T) -> Self where + C: Into, T: Into, { + let chat_id = chat_id.into(); + let text = text.into(); Self { bot, - chat_or_inline_message, - text: text.into(), + chat_id, + message_id, + text, parse_mode: None, disable_web_page_preview: None, reply_markup: None, } } - pub fn chat_or_inline_message(mut self, val: ChatOrInlineMessage) -> Self { - self.chat_or_inline_message = val; + /// Unique identifier for the target chat or username of the target channel + /// (in the format `@channelusername`) + pub fn chat_id(mut self, val: T) -> Self + where + T: Into, + { + self.chat_id = val.into(); + self + } + + /// Identifier of the message to edit + pub fn message_id(mut self, val: i32) -> Self { + self.message_id = val; self } diff --git a/src/requests/all/mod.rs b/src/requests/all/mod.rs index 9a754103..3de4d87a 100644 --- a/src/requests/all/mod.rs +++ b/src/requests/all/mod.rs @@ -9,6 +9,11 @@ mod delete_chat_sticker_set; mod delete_message; mod delete_sticker_from_set; mod delete_webhook; +mod edit_inline_message_caption; +mod edit_inline_message_live_location; +mod edit_inline_message_media; +mod edit_inline_message_reply_markup; +mod edit_inline_message_text; mod edit_message_caption; mod edit_message_live_location; mod edit_message_media; @@ -62,6 +67,7 @@ mod set_my_commands; mod set_sticker_position_in_set; mod set_sticker_set_thumb; mod set_webhook; +mod stop_inline_message_live_location; mod stop_message_live_location; mod stop_poll; mod unban_chat_member; @@ -79,6 +85,11 @@ pub use delete_chat_sticker_set::*; pub use delete_message::*; pub use delete_sticker_from_set::*; pub use delete_webhook::*; +pub use edit_inline_message_caption::*; +pub use edit_inline_message_live_location::*; +pub use edit_inline_message_media::*; +pub use edit_inline_message_reply_markup::*; +pub use edit_inline_message_text::*; pub use edit_message_caption::*; pub use edit_message_live_location::*; pub use edit_message_media::*; @@ -133,6 +144,7 @@ pub use set_sticker_position_in_set::*; pub use set_sticker_set_thumb::*; pub use set_webhook::*; pub use std::pin::Pin; +pub use stop_inline_message_live_location::*; pub use stop_message_live_location::*; pub use stop_poll::*; pub use unban_chat_member::*; diff --git a/src/requests/all/stop_inline_message_live_location.rs b/src/requests/all/stop_inline_message_live_location.rs new file mode 100644 index 00000000..40fb5604 --- /dev/null +++ b/src/requests/all/stop_inline_message_live_location.rs @@ -0,0 +1,62 @@ +use serde::Serialize; + +use crate::{ + net, + requests::{Request, ResponseResult}, + types::{InlineKeyboardMarkup, Message}, + Bot, +}; + +/// Use this method to stop updating a live location message (sent via the bot) +/// before `live_period` expires. +/// +/// On success, [`True`] is returned. +/// +/// [The official docs](https://core.telegram.org/bots/api#stopmessagelivelocation). +/// +/// [`True`]: crate::types::True +#[serde_with_macros::skip_serializing_none] +#[derive(Debug, Clone, Serialize)] +pub struct StopInlineMessageLiveLocation { + #[serde(skip_serializing)] + bot: Bot, + inline_message_id: String, + reply_markup: Option, +} + +#[async_trait::async_trait] +impl Request for StopInlineMessageLiveLocation { + type Output = Message; + + async fn send(&self) -> ResponseResult { + net::request_json(self.bot.client(), self.bot.token(), "stopMessageLiveLocation", &self) + .await + } +} + +impl StopInlineMessageLiveLocation { + pub(crate) fn new(bot: Bot, inline_message_id: I) -> Self + where + I: Into, + { + let inline_message_id = inline_message_id.into(); + Self { bot, inline_message_id, reply_markup: None } + } + + /// Identifier of the inline message. + pub fn inline_message_id(mut self, val: T) -> Self + where + T: Into, + { + self.inline_message_id = val.into(); + self + } + + /// A JSON-serialized object for a new [inline keyboard]. + /// + /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating + pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { + self.reply_markup = Some(val); + self + } +} diff --git a/src/requests/all/stop_message_live_location.rs b/src/requests/all/stop_message_live_location.rs index a0692ec8..892492ea 100644 --- a/src/requests/all/stop_message_live_location.rs +++ b/src/requests/all/stop_message_live_location.rs @@ -3,27 +3,25 @@ use serde::Serialize; use crate::{ net, requests::{Request, ResponseResult}, - types::{ChatOrInlineMessage, InlineKeyboardMarkup, Message}, + types::{ChatId, InlineKeyboardMarkup, Message}, Bot, }; /// Use this method to stop updating a live location message before /// `live_period` expires. /// -/// On success, if the message was sent by the bot, the sent [`Message`] is -/// returned, otherwise [`True`] is returned. +/// On success, the sent [`Message`] is returned. /// /// [The official docs](https://core.telegram.org/bots/api#stopmessagelivelocation). /// /// [`Message`]: crate::types::Message -/// [`True`]: crate::types::True #[serde_with_macros::skip_serializing_none] #[derive(Debug, Clone, Serialize)] pub struct StopMessageLiveLocation { #[serde(skip_serializing)] bot: Bot, - #[serde(flatten)] - chat_or_inline_message: ChatOrInlineMessage, + chat_id: ChatId, + message_id: i32, reply_markup: Option, } @@ -38,12 +36,27 @@ impl Request for StopMessageLiveLocation { } impl StopMessageLiveLocation { - pub(crate) fn new(bot: Bot, chat_or_inline_message: ChatOrInlineMessage) -> Self { - Self { bot, chat_or_inline_message, reply_markup: None } + pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32) -> Self + where + C: Into, + { + let chat_id = chat_id.into(); + Self { bot, chat_id, message_id, reply_markup: None } } - pub fn chat_or_inline_message(mut self, val: ChatOrInlineMessage) -> Self { - self.chat_or_inline_message = val; + /// Unique identifier for the target chat or username of the target channel + /// (in the format `@channelusername`) + pub fn chat_id(mut self, val: T) -> Self + where + T: Into, + { + self.chat_id = val.into(); + self + } + + /// Identifier of the message to edit + pub fn message_id(mut self, val: i32) -> Self { + self.message_id = val; self } From 851e4c6bc6dc6c998113b9fda29a491180e22ab3 Mon Sep 17 00:00:00 2001 From: Waffle Date: Fri, 7 Aug 2020 00:49:47 +0300 Subject: [PATCH 18/41] refactor `ChatOrInlineMessage` - Rename `ChatOrInlineMessage` => `TargetMessage` - Change type of `TargetMessage::inline_message_id` `i32` => `String` - Remove `#[non_exhaustive]` annotation as this enum is unlikely to be changed in future - Implement `From` - Use `From` impl in `get_game_high_scores` and `set_game_score` methods - Leave a deprecated pub use as `ChatOrInlineMessage` for a bit of backward compat --- src/bot/api.rs | 27 ++++++++++---------- src/requests/all/get_game_high_scores.rs | 23 +++++++++++------ src/requests/all/set_game_score.rs | 32 +++++++++++------------- src/types/chat_or_inline_message.rs | 12 --------- src/types/mod.rs | 4 +-- src/types/target_message.rs | 20 +++++++++++++++ 6 files changed, 65 insertions(+), 53 deletions(-) delete mode 100644 src/types/chat_or_inline_message.rs create mode 100644 src/types/target_message.rs diff --git a/src/bot/api.rs b/src/bot/api.rs index 3f3fb8c7..5278d357 100644 --- a/src/bot/api.rs +++ b/src/bot/api.rs @@ -1563,18 +1563,18 @@ impl Bot { /// [The official docs](https://core.telegram.org/bots/api#setgamescore). /// /// # Params + /// - `target`: Target message, either chat id and message id or inline + /// message id. /// - `user_id`: User identifier. /// - `score`: New score, must be non-negative. /// /// [`Message`]: crate::types::Message /// [`True`]: crate::types::True - pub fn set_game_score( - &self, - chat_or_inline_message: ChatOrInlineMessage, - user_id: i32, - score: i32, - ) -> SetGameScore { - SetGameScore::new(self.clone(), chat_or_inline_message, user_id, score) + pub fn set_game_score(&self, target: T, user_id: i32, score: i32) -> SetGameScore + where + T: Into, + { + SetGameScore::new(self.clone(), target, user_id, score) } /// Use this method to get data for high score tables. @@ -1591,13 +1591,14 @@ impl Bot { /// [The official docs](https://core.telegram.org/bots/api#getgamehighscores). /// /// # Params + /// - `target`: Target message, either chat id and message id or inline + /// message id. /// - `user_id`: Target user id. - pub fn get_game_high_scores( - &self, - chat_or_inline_message: ChatOrInlineMessage, - user_id: i32, - ) -> GetGameHighScores { - GetGameHighScores::new(self.clone(), chat_or_inline_message, user_id) + pub fn get_game_high_scores(&self, target: T, user_id: i32) -> GetGameHighScores + where + T: Into, + { + GetGameHighScores::new(self.clone(), target, user_id) } /// Use this method to set a custom title for an administrator in a diff --git a/src/requests/all/get_game_high_scores.rs b/src/requests/all/get_game_high_scores.rs index 260098c7..1a43d63e 100644 --- a/src/requests/all/get_game_high_scores.rs +++ b/src/requests/all/get_game_high_scores.rs @@ -3,7 +3,7 @@ use serde::Serialize; use crate::{ net, requests::{Request, ResponseResult}, - types::{ChatOrInlineMessage, GameHighScore}, + types::{GameHighScore, TargetMessage}, Bot, }; @@ -18,14 +18,13 @@ use crate::{ /// the user and his neighbors are not among them. Please note that this /// behavior is subject to change. /// -/// [The official docs](https://core.telegram.org/bots/api#getgamehighscores). -#[serde_with_macros::skip_serializing_none] +/// [The official docs](https://core.telegram.org/bots/api#getgamehighscores) #[derive(Debug, Clone, Serialize)] pub struct GetGameHighScores { #[serde(skip_serializing)] bot: Bot, #[serde(flatten)] - chat_or_inline_message: ChatOrInlineMessage, + target: TargetMessage, user_id: i32, } @@ -39,12 +38,20 @@ impl Request for GetGameHighScores { } impl GetGameHighScores { - pub(crate) fn new(bot: Bot, chat_or_inline_message: ChatOrInlineMessage, user_id: i32) -> Self { - Self { bot, chat_or_inline_message, user_id } + pub(crate) fn new(bot: Bot, target: T, user_id: i32) -> Self + where + T: Into, + { + let target = target.into(); + Self { bot, target, user_id } } - pub fn chat_or_inline_message(mut self, val: ChatOrInlineMessage) -> Self { - self.chat_or_inline_message = val; + /// Target message, either chat id and message id or inline message id. + pub fn target(mut self, val: T) -> Self + where + T: Into, + { + self.target = val.into(); self } diff --git a/src/requests/all/set_game_score.rs b/src/requests/all/set_game_score.rs index e3271a77..8e429e3a 100644 --- a/src/requests/all/set_game_score.rs +++ b/src/requests/all/set_game_score.rs @@ -3,7 +3,7 @@ use serde::Serialize; use crate::{ net, requests::{Request, ResponseResult}, - types::{ChatOrInlineMessage, Message}, + types::{Message, TargetMessage}, Bot, }; @@ -24,7 +24,7 @@ pub struct SetGameScore { #[serde(skip_serializing)] bot: Bot, #[serde(flatten)] - chat_or_inline_message: ChatOrInlineMessage, + target: TargetMessage, user_id: i32, score: i32, force: Option, @@ -41,24 +41,20 @@ impl Request for SetGameScore { } impl SetGameScore { - pub(crate) fn new( - bot: Bot, - chat_or_inline_message: ChatOrInlineMessage, - user_id: i32, - score: i32, - ) -> Self { - Self { - bot, - chat_or_inline_message, - user_id, - score, - force: None, - disable_edit_message: None, - } + pub(crate) fn new(bot: Bot, target: T, user_id: i32, score: i32) -> Self + where + T: Into, + { + let target = target.into(); + Self { bot, target, user_id, score, force: None, disable_edit_message: None } } - pub fn chat_or_inline_message(mut self, val: ChatOrInlineMessage) -> Self { - self.chat_or_inline_message = val; + /// Target message, either chat id and message id or inline message id. + pub fn target(mut self, val: T) -> Self + where + T: Into, + { + self.target = val.into(); self } diff --git a/src/types/chat_or_inline_message.rs b/src/types/chat_or_inline_message.rs deleted file mode 100644 index d02a522b..00000000 --- a/src/types/chat_or_inline_message.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::types::ChatId; - -use serde::{Deserialize, Serialize}; - -/// A chat message or inline message. -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[serde(untagged)] -#[non_exhaustive] -pub enum ChatOrInlineMessage { - Chat { chat_id: ChatId, message_id: i32 }, - Inline { inline_message_id: i32 }, -} diff --git a/src/types/mod.rs b/src/types/mod.rs index a8f01b30..e6f7e5fa 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -10,7 +10,6 @@ pub use chat::*; pub use chat_action::*; pub use chat_id::*; pub use chat_member::*; -pub use chat_or_inline_message::*; pub use chat_permissions::*; pub use chat_photo::*; pub use chosen_inline_result::*; @@ -83,6 +82,7 @@ pub use sticker::*; pub use sticker_set::*; pub use sticker_type::*; pub use successful_payment::*; +pub use target_message::*; pub use unit_false::*; pub use unit_true::*; pub use update::*; @@ -104,7 +104,6 @@ mod chat; mod chat_action; mod chat_id; mod chat_member; -mod chat_or_inline_message; mod chat_permissions; mod chat_photo; mod chosen_inline_result; @@ -150,6 +149,7 @@ mod sticker; mod sticker_set; mod sticker_type; mod successful_payment; +mod target_message; mod unit_false; mod unit_true; mod update; diff --git a/src/types/target_message.rs b/src/types/target_message.rs new file mode 100644 index 00000000..aff9a0b6 --- /dev/null +++ b/src/types/target_message.rs @@ -0,0 +1,20 @@ +use crate::types::ChatId; + +use serde::{Deserialize, Serialize}; + +/// A message in chat or inline message. +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum TargetMessage { + Chat { chat_id: ChatId, message_id: i32 }, + Inline { inline_message_id: String }, +} + +#[deprecated = "Was renamed to `TargetMessage`, please use renamed version"] +pub use TargetMessage as ChatOrInlineMessage; + +impl From for TargetMessage { + fn from(inline_message_id: String) -> Self { + Self::Inline { inline_message_id } + } +} From 02400b18ab3c0a091c60909a8664d431be8b4c68 Mon Sep 17 00:00:00 2001 From: Waffle Date: Mon, 10 Aug 2020 18:14:52 +0300 Subject: [PATCH 19/41] remove TargetMessage as ChatOrInlineMessage reexport as it couldn't be deprecated Also rename `TargetMessage::{Chat => Common}` variant. (anyway `ChatOrInlineMessage`/`TargetMessage` refactoring is not backward compatible) --- src/types/target_message.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/types/target_message.rs b/src/types/target_message.rs index aff9a0b6..0c0d8cc1 100644 --- a/src/types/target_message.rs +++ b/src/types/target_message.rs @@ -6,13 +6,10 @@ use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(untagged)] pub enum TargetMessage { - Chat { chat_id: ChatId, message_id: i32 }, + Common { chat_id: ChatId, message_id: i32 }, Inline { inline_message_id: String }, } -#[deprecated = "Was renamed to `TargetMessage`, please use renamed version"] -pub use TargetMessage as ChatOrInlineMessage; - impl From for TargetMessage { fn from(inline_message_id: String) -> Self { Self::Inline { inline_message_id } From b06d3e7b7e96c70d4acd0cfd78a504156bc2793d Mon Sep 17 00:00:00 2001 From: Waffle Date: Mon, 10 Aug 2020 18:36:43 +0300 Subject: [PATCH 20/41] add edit-methods and `TargetMessage` refactoring changes to CHANGELOG.md --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db431426..7ef4a38f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Allow `bot_name` be `N`, where `N: Into + ...` in `commands_repl` & `commands_repl_with_listener`. + - 'Edit methods' (namely `edit_message_live_location`, `stop_message_live_location`, `edit_message_text`, + `edit_message_caption`, `edit_message_media` and `edit_message_reply_markup`) are split into common and inline + versions (e.g.: `edit_message_text` and `edit_inline_message_text`). Instead of `ChatOrInlineMessage` common versions + accept `chat_id: impl Into` and `message_id: i32` whereas inline versions accept + `inline_message_id: impl Into`. Also note that return type of inline versions is `True` ([issue 253], [pr 257]) + - `ChatOrInlineMessage` is renamed to `TargetMessage`, it's `::Chat` variant is renamed to `::Common`, + `#[non_exhaustive]` annotation is removed from the enum, type of `TargetMessage::Inline::inline_message_id` changed + `i32` => `String`. `TargetMessage` now implements `From`, `get_game_high_scores` and `set_game_score` use + `Into` to accept `String`s. ([issue 253], [pr 257]) + +[issue 253]: https://github.com/teloxide/teloxide/issues/253 +[pr 257]: https://github.com/teloxide/teloxide/pull/257 ## [0.3.0] - 2020-07-31 ### Added From b81bfd3b2ad1b9d9061d36581e9ab3dfab49a1f3 Mon Sep 17 00:00:00 2001 From: Waffle Date: Mon, 10 Aug 2020 18:39:30 +0300 Subject: [PATCH 21/41] fix fmt --- src/bot/api.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/bot/api.rs b/src/bot/api.rs index 5278d357..8fe0fc80 100644 --- a/src/bot/api.rs +++ b/src/bot/api.rs @@ -1057,8 +1057,9 @@ impl Bot { { match self.parse_mode { None => EditMessageText::new(self.clone(), chat_id, message_id, text), - Some(parse_mode) => EditMessageText::new(self.clone(), chat_id, message_id, text) - .parse_mode(parse_mode), + Some(parse_mode) => { + EditMessageText::new(self.clone(), chat_id, message_id, text).parse_mode(parse_mode) + } } } @@ -1117,8 +1118,9 @@ impl Bot { { match self.parse_mode { None => EditMessageCaption::new(self.clone(), chat_id, message_id), - Some(parse_mode) => EditMessageCaption::new(self.clone(), chat_id, message_id) - .parse_mode(parse_mode), + Some(parse_mode) => { + EditMessageCaption::new(self.clone(), chat_id, message_id).parse_mode(parse_mode) + } } } From f521f08470ebc955ced1317957e58c9fb2f634b5 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Wed, 12 Aug 2020 22:31:35 +0300 Subject: [PATCH 22/41] Use local ./ paths instead of github links in README --- README.md | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 427b78d3..81a54c1f 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ ## Table of contents - - [Highlights](https://github.com/teloxide/teloxide#highlights) - - [Setting up your environment](https://github.com/teloxide/teloxide#setting-up-your-environment) - - [API overview](https://github.com/teloxide/teloxide#api-overview) - - [The dices bot](https://github.com/teloxide/teloxide#the-dices-bot) - - [Commands](https://github.com/teloxide/teloxide#commands) - - [Dialogues management](https://github.com/teloxide/teloxide#dialogues-management) - - [Recommendations](https://github.com/teloxide/teloxide#recommendations) - - [Cargo features](https://github.com/teloxide/teloxide#cargo-features) - - [FAQ](https://github.com/teloxide/teloxide#faq) - - [Community bots](https://github.com/teloxide/teloxide#community-bots) - - [Contributing](https://github.com/teloxide/teloxide#contributing) + - [Highlights](#highlights) + - [Setting up your environment](#setting-up-your-environment) + - [API overview](#api-overview) + - [The dices bot](#the-dices-bot) + - [Commands](#commands) + - [Dialogues management](#dialogues-management) + - [Recommendations](#recommendations) + - [Cargo features](#cargo-features) + - [FAQ](#faq) + - [Community bots](#community-bots) + - [Contributing](#contributing) ## Highlights @@ -90,7 +90,7 @@ tokio = { version = "0.2.11", features = ["rt-threaded", "macros"] } ### The dices bot This bot throws a dice on each incoming message: -([Full](https://github.com/teloxide/teloxide/blob/master/examples/dices_bot/src/main.rs)) +([Full](./examples/dices_bot/src/main.rs)) ```rust use teloxide::prelude::*; @@ -112,7 +112,7 @@ async fn main() {
- +
@@ -126,7 +126,7 @@ Commands are strongly typed and defined declaratively, similar to how we define [structopt]: https://docs.rs/structopt/0.3.9/structopt/ [serde-json]: https://github.com/serde-rs/json -([Full](https://github.com/teloxide/teloxide/blob/master/examples/simple_commands_bot/src/main.rs)) +([Full](./examples/simple_commands_bot/src/main.rs)) ```rust // Imports are omitted... @@ -169,7 +169,7 @@ async fn main() {
- +
@@ -180,7 +180,7 @@ A dialogue is described by an enumeration, where each variant is one of possible Below is a bot, which asks you three questions and then sends the answers back to you. First, let's start with an enumeration (a collection of our dialogue's states): -([dialogue_bot/src/dialogue/mod.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/dialogue/mod.rs)) +([dialogue_bot/src/dialogue/mod.rs](./examples/dialogue_bot/src/dialogue/mod.rs)) ```rust // Imports are omitted... @@ -204,7 +204,7 @@ When a user sends a message to our bot, and such a dialogue does not yet exist,
Dialogue::Start -([dialogue_bot/src/dialogue/states/start.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/dialogue/states/start.rs)) +([dialogue_bot/src/dialogue/states/start.rs](./examples/dialogue_bot/src/dialogue/states/start.rs)) ```rust // Imports are omitted... @@ -222,7 +222,7 @@ async fn start(_state: StartState, cx: TransitionIn, _ans: String) -> Transition
Dialogue::ReceiveFullName -([dialogue_bot/src/dialogue/states/receive_full_name.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/dialogue/states/receive_full_name.rs)) +([dialogue_bot/src/dialogue/states/receive_full_name.rs](./examples/dialogue_bot/src/dialogue/states/receive_full_name.rs)) ```rust // Imports are omitted... @@ -245,7 +245,7 @@ async fn receive_full_name(
Dialogue::ReceiveAge -([dialogue_bot/src/dialogue/states/receive_age.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/dialogue/states/receive_age.rs)) +([dialogue_bot/src/dialogue/states/receive_age.rs](./examples/dialogue_bot/src/dialogue/states/receive_age.rs)) ```rust // Imports are omitted... @@ -278,7 +278,7 @@ async fn receive_age_state(
Dialogue::ReceiveLocation -([dialogue_bot/src/dialogue/states/receive_location.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/dialogue/states/receive_location.rs)) +([dialogue_bot/src/dialogue/states/receive_location.rs](./examples/dialogue_bot/src/dialogue/states/receive_location.rs)) ```rust // Imports are omitted... @@ -306,7 +306,7 @@ All these subtransitions accept a corresponding state (one of the many variants Finally, the `main` function looks like this: -([dialogue_bot/src/main.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/main.rs)) +([dialogue_bot/src/main.rs](./examples/dialogue_bot/src/main.rs)) ```rust // Imports are omitted... @@ -336,11 +336,11 @@ async fn handle_message(cx: UpdateWithCx, dialogue: Dialogue) -> Transi
- +
-[More examples!](https://github.com/teloxide/teloxide/tree/master/examples) +[More examples!](./examples) ## Recommendations - Use this pattern: @@ -404,7 +404,7 @@ UPD: The current design spreads wide and deep trait bounds, thereby increasing c Q: Can I use webhooks? -A: teloxide doesn't provide special API for working with webhooks due to their nature with lots of subtle settings. Instead, you setup your webhook by yourself, as shown in [`examples/ngrok_ping_pong_bot`](examples/ngrok_ping_pong_bot/src/main.rs) and [`examples/heroku_ping_pong_bot`](examples/heroku_ping_pong_bot/src/main.rs). +A: teloxide doesn't provide special API for working with webhooks due to their nature with lots of subtle settings. Instead, you setup your webhook by yourself, as shown in [`examples/ngrok_ping_pong_bot`](./examples/ngrok_ping_pong_bot/src/main.rs) and [`examples/heroku_ping_pong_bot`](./examples/heroku_ping_pong_bot/src/main.rs). Associated links: - [Marvin's Marvellous Guide to All Things Webhook](https://core.telegram.org/bots/webhooks) From 7a3ce7f05c0b9e57a8d2d79f5774c5a61e130038 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Wed, 12 Aug 2020 22:44:56 +0300 Subject: [PATCH 23/41] Remove confusing use of `respond` from README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 81a54c1f..b1b0a584 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ async fn main() { teloxide::repl(bot, |message| async move { message.answer_dice().send().await?; - respond(()) + ResponseResult::<()>::Ok(()) }) .await; } From 00e39e8d35c3ad279f81e31acce2f1c74e2c0312 Mon Sep 17 00:00:00 2001 From: Waffle Date: Wed, 12 Aug 2020 22:48:36 +0300 Subject: [PATCH 24/41] enable all features for `docs.rs` doc build --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 2497c1c4..d4475692 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,3 +63,6 @@ rand = "0.7.3" pretty_env_logger = "0.4.0" lazy_static = "1.4.0" tokio = { version = "0.2.21", features = ["fs", "stream", "rt-threaded", "macros"] } + +[package.metadata."docs.rs"] +all-features = true From f765278c6892a4e0e5c87b6556d02089287b9342 Mon Sep 17 00:00:00 2001 From: Waffle Date: Wed, 12 Aug 2020 22:49:58 +0300 Subject: [PATCH 25/41] add docs|master badge and netlify config --- README.md | 15 +++++++++------ netlify.toml | 12 ++++++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 netlify.toml diff --git a/README.md b/README.md index 427b78d3..ca7ad4c6 100644 --- a/README.md +++ b/README.md @@ -2,21 +2,24 @@

teloxide

- - - + + + + + + - - - + + + A full-featured framework that empowers you to easily build [Telegram bots](https://telegram.org/blog/bot-revolution) using the [`async`/`.await`](https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html) syntax in [Rust](https://www.rust-lang.org/). It handles all the difficult stuff so you can focus only on your business logic. diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 00000000..27cffb2f --- /dev/null +++ b/netlify.toml @@ -0,0 +1,12 @@ +[build] +# Directory (relative to root of your repo) that contains the deploy-ready +# HTML files and assets generated by the build. If a base directory has +# been specified, include it in the publish directory path. +publish = "target/doc" + +# Default build command. +command = 'curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly --profile minimal && source $HOME/.cargo/env && RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --no-deps --all-features' + +[[redirects]] + from = "/*" + to = "/teloxide" From 3157305105dae855529d092173fab8ee54d15234 Mon Sep 17 00:00:00 2001 From: Waffle Date: Wed, 12 Aug 2020 23:21:13 +0300 Subject: [PATCH 26/41] add automatic test of code blocks from readme --- Cargo.toml | 2 ++ README.md | 20 ++++++++++---------- src/lib.rs | 5 +++++ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d4475692..37109156 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,8 @@ bincode-serializer = ["bincode"] frunk- = ["frunk"] +nightly = [] # currently used only for `README.md` tests + [dependencies] serde_json = "1.0.55" serde = { version = "1.0.114", features = ["derive"] } diff --git a/README.md b/README.md index ca7ad4c6..4cdc75c3 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ tokio = { version = "0.2.11", features = ["rt-threaded", "macros"] } This bot throws a dice on each incoming message: ([Full](https://github.com/teloxide/teloxide/blob/master/examples/dices_bot/src/main.rs)) -```rust +```rust,no_run use teloxide::prelude::*; #[tokio::main] @@ -130,8 +130,8 @@ Commands are strongly typed and defined declaratively, similar to how we define [serde-json]: https://github.com/serde-rs/json ([Full](https://github.com/teloxide/teloxide/blob/master/examples/simple_commands_bot/src/main.rs)) -```rust -// Imports are omitted... +```rust,no_run +use teloxide::{utils::command::BotCommand, prelude::*}; #[derive(BotCommand)] #[command(rename = "lowercase", description = "These commands are supported:")] @@ -166,7 +166,7 @@ async fn main() { let bot = Bot::from_env(); let bot_name: String = panic!("Your bot's name here"); - teloxide::commands_repl(bot, bot_name, action).await; + teloxide::commands_repl(bot, bot_name, answer).await; } ``` @@ -184,7 +184,7 @@ A dialogue is described by an enumeration, where each variant is one of possible Below is a bot, which asks you three questions and then sends the answers back to you. First, let's start with an enumeration (a collection of our dialogue's states): ([dialogue_bot/src/dialogue/mod.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/dialogue/mod.rs)) -```rust +```rust,ignore // Imports are omitted... #[derive(Transition, From)] @@ -208,7 +208,7 @@ When a user sends a message to our bot, and such a dialogue does not yet exist, Dialogue::Start ([dialogue_bot/src/dialogue/states/start.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/dialogue/states/start.rs)) -```rust +```rust,ignore // Imports are omitted... pub struct StartState; @@ -226,7 +226,7 @@ async fn start(_state: StartState, cx: TransitionIn, _ans: String) -> Transition Dialogue::ReceiveFullName ([dialogue_bot/src/dialogue/states/receive_full_name.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/dialogue/states/receive_full_name.rs)) -```rust +```rust,ignore // Imports are omitted... #[derive(Generic)] @@ -249,7 +249,7 @@ async fn receive_full_name( Dialogue::ReceiveAge ([dialogue_bot/src/dialogue/states/receive_age.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/dialogue/states/receive_age.rs)) -```rust +```rust,ignore // Imports are omitted... #[derive(Generic)] @@ -282,7 +282,7 @@ async fn receive_age_state( Dialogue::ReceiveLocation ([dialogue_bot/src/dialogue/states/receive_location.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/dialogue/states/receive_location.rs)) -```rust +```rust,ignore // Imports are omitted... #[derive(Generic)] @@ -310,7 +310,7 @@ All these subtransitions accept a corresponding state (one of the many variants Finally, the `main` function looks like this: ([dialogue_bot/src/main.rs](https://github.com/teloxide/teloxide/blob/master/examples/dialogue_bot/src/main.rs)) -```rust +```rust,ignore // Imports are omitted... #[tokio::main] diff --git a/src/lib.rs b/src/lib.rs index c3116be2..7ffb1775 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,6 +40,7 @@ )] #![allow(clippy::match_bool)] #![forbid(unsafe_code)] +#![cfg_attr(all(feature = "nightly", doctest), feature(external_doc))] pub use bot::{Bot, BotBuilder}; pub use dispatching::repls::{ @@ -61,3 +62,7 @@ pub mod types; pub mod utils; extern crate teloxide_macros; + +#[cfg(all(feature = "nightly", doctest))] +#[doc(include = "../README.md")] +enum ReadmeDocTests {} From 981ba237c9917f9315f192daf7b82d4d5b2940fb Mon Sep 17 00:00:00 2001 From: Waffle Date: Wed, 12 Aug 2020 23:53:58 +0300 Subject: [PATCH 27/41] redis test fix & beta/nightly ci This commit fixes redis storage test, those were not ran before. Also, introduces beta&nightly tests to CI --- .github/workflows/ci.yml | 42 ++++++++++++++++++++++++++++++---------- Cargo.toml | 5 +++++ tests/redis.rs | 5 ----- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c7b3cda1..588ea79a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,23 +27,45 @@ jobs: override: true - name: Cargo clippy run: cargo clippy --all --all-targets --all-features -- -D warnings - stable-test: + + test: runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + - beta + - nightly + + include: + - rust: stable + features: "--features \"redis-storage cbor-serializer bincode-serializer frunk-\"" + - rust: beta + features: "--features \"redis-storage cbor-serializer bincode-serializer frunk-\"" + - rust: nightly + features: "--all-features" + steps: - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: stable + toolchain: ${{ matrix.rust }} override: true - - name: Setup redis - run: | - sudo apt install redis-server - redis-server --port 7777 > /dev/null & - redis-server --port 7778 > /dev/null & - redis-server --port 7779 > /dev/null & - - name: Cargo test - run: cargo test --all --all-features + + - name: build + uses: actions-rs/cargo@v1 + with: + command: build + args: --verbose ${{ matrix.features }} + + - name: test + uses: actions-rs/cargo@v1 + with: + command: test + args: --verbose ${{ matrix.features }} + build-example: runs-on: ubuntu-latest strategy: diff --git a/Cargo.toml b/Cargo.toml index 37109156..9e85b94f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,3 +68,8 @@ tokio = { version = "0.2.21", features = ["fs", "stream", "rt-threaded", "macros [package.metadata."docs.rs"] all-features = true + +[[test]] +name = "redis" +path = "tests/redis.rs" +required-features = ["redis-storage", "cbor-serializer", "bincode-serializer"] diff --git a/tests/redis.rs b/tests/redis.rs index 3d9da600..0a06c06e 100644 --- a/tests/redis.rs +++ b/tests/redis.rs @@ -1,5 +1,3 @@ -#![cfg(feature = "redis_storage")] - use std::{ fmt::{Debug, Display}, future::Future, @@ -8,7 +6,6 @@ use std::{ use teloxide::dispatching::dialogue::{RedisStorage, Serializer, Storage}; #[tokio::test] -#[cfg(feature = "redis_storage")] async fn test_redis_json() { let storage = RedisStorage::open( "redis://127.0.0.1:7777", @@ -19,7 +16,6 @@ async fn test_redis_json() { test_redis(storage).await; } -#[cfg(feature = "bincode_serializer")] #[tokio::test] async fn test_redis_bincode() { let storage = RedisStorage::open( @@ -31,7 +27,6 @@ async fn test_redis_bincode() { test_redis(storage).await; } -#[cfg(feature = "cbor_serializer")] #[tokio::test] async fn test_redis_cbor() { let storage = RedisStorage::open( From 94bc8504a514df2e1941cf2e594144c0559bdfe7 Mon Sep 17 00:00:00 2001 From: Waffle Date: Thu, 13 Aug 2020 00:07:16 +0300 Subject: [PATCH 28/41] oops, i've accidentally removed redis setup from ci --- .github/workflows/ci.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 588ea79a..d2dfc583 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,13 +54,20 @@ jobs: toolchain: ${{ matrix.rust }} override: true - - name: build + - name: Build uses: actions-rs/cargo@v1 with: command: build args: --verbose ${{ matrix.features }} - - name: test + - name: Setup redis + run: | + sudo apt install redis-server + redis-server --port 7777 > /dev/null & + redis-server --port 7778 > /dev/null & + redis-server --port 7779 > /dev/null & + + - name: Test uses: actions-rs/cargo@v1 with: command: test @@ -87,5 +94,5 @@ jobs: profile: minimal toolchain: stable override: true - - name: Test the example + - name: Check the example run: cd examples && cd ${{ matrix.example }} && cargo check From d88f92d26c03126bfeb15643670fe6bd983b3a58 Mon Sep 17 00:00:00 2001 From: Waffle Date: Mon, 17 Aug 2020 18:10:03 +0300 Subject: [PATCH 29/41] make 'dev' default branch in docs --- CONTRIBUTING.md | 3 ++- README.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b81f9695..4587993e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,8 @@ # Contributing + Before contributing, please read [our code style](https://github.com/teloxide/teloxide/blob/master/CODE_STYLE.md) and [the license](https://github.com/teloxide/teloxide/blob/master/LICENSE). -To change the source code, fork the `master` branch of this repository and work inside your own branch. Then send us a PR into `master` branch and wait for the CI to check everything. However, you'd better check changes first locally: +To change the source code, fork the `dev` branch of this repository and work inside your own branch. Then send us a PR into `dev` branch and wait for the CI to check everything. However, you'd better check changes first locally: ``` cargo clippy --all --all-features --all-targets diff --git a/README.md b/README.md index 76c90ea8..9bafee33 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ - + From 7cbbf4396611441ac877095d1562a547ee75d0ab Mon Sep 17 00:00:00 2001 From: Waffle Date: Mon, 17 Aug 2020 18:30:19 +0300 Subject: [PATCH 30/41] run CI for pull requests against dev --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2dfc583..a9a4c47a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ on: push: branches: [ master ] pull_request: - branches: [ master ] + branches: [ master, dev ] name: Continuous integration From 060dd5f6b4733ac8a2fa5d89ceac34617a388ecd Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Tue, 18 Aug 2020 09:23:18 +0600 Subject: [PATCH 31/41] Add cognito_bot to README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 76c90ea8..7ae679f3 100644 --- a/README.md +++ b/README.md @@ -428,6 +428,7 @@ Feel free to push your own bot into our collection! - [_Rust subreddit reader_](https://github.com/steadylearner/Rust-Full-Stack/tree/master/commits/teloxide/subreddit_reader) - [_vzmuinebot -- Telegram bot for food menu navigate_](https://github.com/ArtHome12/vzmuinebot) - [_Tepe -- A CLI to command a bot to send messages and files over Telegram_](https://lib.rs/crates/tepe) + - [_cognito_bot -- The bot is designed to anonymize messages to a group_](https://github.com/ArtHome12/cognito_bot) ## Contributing See [CONRIBUTING.md](https://github.com/teloxide/teloxide/blob/master/CONTRIBUTING.md). From fc4324b91f0b553a8d1e7f52c311a0d0ef56db8e Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Fri, 21 Aug 2020 16:24:09 +0600 Subject: [PATCH 32/41] Remove useless spaces from README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7ae679f3..44cc99d4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

teloxide

- +
@@ -20,7 +20,7 @@ - + A full-featured framework that empowers you to easily build [Telegram bots](https://telegram.org/blog/bot-revolution) using the [`async`/`.await`](https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html) syntax in [Rust](https://www.rust-lang.org/). It handles all the difficult stuff so you can focus only on your business logic.
@@ -110,7 +110,6 @@ async fn main() { }) .await; } - ```
From e4449e49f3fa9deed2e904fdcbeaf53e4d19114c Mon Sep 17 00:00:00 2001 From: Robin Hundt <24554122+robinhundt@users.noreply.github.com> Date: Fri, 28 Aug 2020 23:33:16 +0200 Subject: [PATCH 33/41] Added failing test case for command with single non-String arg --- tests/command.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/command.rs b/tests/command.rs index 82bba9aa..a8bd02da 100644 --- a/tests/command.rs +++ b/tests/command.rs @@ -18,6 +18,22 @@ fn parse_command_with_args() { assert_eq!(actual, expected) } +#[test] +fn parse_command_with_non_string_arg() { + #[command(rename = "lowercase")] + #[derive(BotCommand, Debug, PartialEq)] + enum DefaultCommands { + Start(i32), + Help, + } + + let data = "/start -50"; + let expected = DefaultCommands::Start("-50".parse().unwrap()); + let actual = DefaultCommands::parse(data, "").unwrap(); + assert_eq!(actual, expected) +} + + #[test] fn attribute_prefix() { #[command(rename = "lowercase")] From abb7b9335ed5a789e9d9cc62d8bc7ca28933a3cc Mon Sep 17 00:00:00 2001 From: Robin Hundt <24554122+robinhundt@users.noreply.github.com> Date: Wed, 2 Sep 2020 16:12:59 +0200 Subject: [PATCH 34/41] Removed whitespace --- tests/command.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/command.rs b/tests/command.rs index a8bd02da..d7badef0 100644 --- a/tests/command.rs +++ b/tests/command.rs @@ -33,7 +33,6 @@ fn parse_command_with_non_string_arg() { assert_eq!(actual, expected) } - #[test] fn attribute_prefix() { #[command(rename = "lowercase")] From 4fabc083b8a7f773f01e05feb8147b67f01040ba Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sun, 6 Sep 2020 00:48:26 +0600 Subject: [PATCH 35/41] Add tg-vimhelpbot to README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8fe657e8..42ff8600 100644 --- a/README.md +++ b/README.md @@ -428,6 +428,7 @@ Feel free to push your own bot into our collection! - [_vzmuinebot -- Telegram bot for food menu navigate_](https://github.com/ArtHome12/vzmuinebot) - [_Tepe -- A CLI to command a bot to send messages and files over Telegram_](https://lib.rs/crates/tepe) - [_cognito_bot -- The bot is designed to anonymize messages to a group_](https://github.com/ArtHome12/cognito_bot) + - [_tg-vimhelpbot -- Link `:help` for Vim in Telegram_](https://github.com/GoldsteinE/tg-vimhelpbot) ## Contributing See [CONRIBUTING.md](https://github.com/teloxide/teloxide/blob/master/CONTRIBUTING.md). From b2126162570512f9925e34415bc6586005139276 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 12 Sep 2020 21:23:50 +0600 Subject: [PATCH 36/41] Add authors of bots to README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 42ff8600..3b8da7da 100644 --- a/README.md +++ b/README.md @@ -424,11 +424,11 @@ A: Yes. You can setup any logger, for example, [fern], e.g. teloxide has no spec ## Community bots Feel free to push your own bot into our collection! - - [_Rust subreddit reader_](https://github.com/steadylearner/Rust-Full-Stack/tree/master/commits/teloxide/subreddit_reader) - - [_vzmuinebot -- Telegram bot for food menu navigate_](https://github.com/ArtHome12/vzmuinebot) - - [_Tepe -- A CLI to command a bot to send messages and files over Telegram_](https://lib.rs/crates/tepe) - - [_cognito_bot -- The bot is designed to anonymize messages to a group_](https://github.com/ArtHome12/cognito_bot) - - [_tg-vimhelpbot -- Link `:help` for Vim in Telegram_](https://github.com/GoldsteinE/tg-vimhelpbot) + - [_steadylearner/subreddit_reader_](https://github.com/steadylearner/Rust-Full-Stack/tree/master/commits/teloxide/subreddit_reader) + - [_ArtHome12/vzmuinebot -- Telegram bot for food menu navigate_](https://github.com/ArtHome12/vzmuinebot) + - [_Hermitter/tepe -- A CLI to command a bot to send messages and files over Telegram_](https://github.com/Hermitter/tepe) + - [_ArtHome12/cognito_bot -- The bot is designed to anonymize messages to a group_](https://github.com/ArtHome12/cognito_bot) + - [_GoldsteinE/tg-vimhelpbot -- Link `:help` for Vim in Telegram_](https://github.com/GoldsteinE/tg-vimhelpbot) ## Contributing See [CONRIBUTING.md](https://github.com/teloxide/teloxide/blob/master/CONTRIBUTING.md). From 4db66eaa83e62d117c6f1b3c4079ede57556ae42 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 26 Sep 2020 21:27:13 +0600 Subject: [PATCH 37/41] Highlight dialogues management (README.md) --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3b8da7da..91f20a81 100644 --- a/README.md +++ b/README.md @@ -39,17 +39,18 @@ ## Highlights - - **Functional reactive design.** teloxide has [functional reactive design], allowing you to declaratively manipulate streams of updates from Telegram using filters, maps, folds, zips, and a lot of [other adaptors]. + - **Functional reactive design.** teloxide follows [functional reactive design], allowing you to declaratively manipulate streams of updates from Telegram using filters, maps, folds, zips, and a lot of [other adaptors]. [functional reactive design]: https://en.wikipedia.org/wiki/Functional_reactive_programming [other adaptors]: https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html - - **Persistence.** Dialogues management is independent of how/where dialogues are stored: you can just replace one line and make them [persistent]. Out-of-the-box storages include [Redis]. + - **Dialogues management subsystem.** Dialogues are represented as [finite-state machines] augmented with some syntax sugar, thanks to attribute macros. We have designed our dialogues management subsystem to be easy-to-use, and, furthermore, to be independent of how/where dialogues are stored; for example, you can just replace one line to achieve [persistence]. Out-of-the-box storages include [Redis]. -[persistent]: https://en.wikipedia.org/wiki/Persistence_(computer_science) +[persistence]: https://en.wikipedia.org/wiki/Persistence_(computer_science) +[finite-state machines]: https://en.wikipedia.org/wiki/Finite-state_machine [Redis]: https://redis.io/ - - **Strongly typed bot commands.** You can describe bot commands as enumerations, and then they'll be automatically constructed from strings. Just like you describe JSON structures in [serde-json] and command-line arguments in [structopt]. + - **Strongly typed bot commands.** You can describe bot commands as enumerations, and then they'll be automatically constructed from strings -- just like JSON structures in [serde-json] and command-line arguments in [structopt]. [structopt]: https://github.com/TeXitoi/structopt [serde-json]: https://github.com/serde-rs/json From 1c6b97ae392ba4de7708efceb2fe011893d41325 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 26 Sep 2020 21:29:32 +0600 Subject: [PATCH 38/41] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 91f20a81..f4d2a521 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ [functional reactive design]: https://en.wikipedia.org/wiki/Functional_reactive_programming [other adaptors]: https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html - - **Dialogues management subsystem.** Dialogues are represented as [finite-state machines] augmented with some syntax sugar, thanks to attribute macros. We have designed our dialogues management subsystem to be easy-to-use, and, furthermore, to be independent of how/where dialogues are stored; for example, you can just replace one line to achieve [persistence]. Out-of-the-box storages include [Redis]. + - **Dialogues management subsystem.** We have designed our dialogues management subsystem to be easy-to-use, and, furthermore, to be independent of how/where dialogues are stored; for example, you can just replace one line to achieve [persistence]. Out-of-the-box storages include [Redis]. [persistence]: https://en.wikipedia.org/wiki/Persistence_(computer_science) [finite-state machines]: https://en.wikipedia.org/wiki/Finite-state_machine From 4a1ba8d9b45becf556cd887f08cceeb6fb1d6e78 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 26 Sep 2020 21:30:08 +0600 Subject: [PATCH 39/41] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f4d2a521..a87cd5bf 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ [functional reactive design]: https://en.wikipedia.org/wiki/Functional_reactive_programming [other adaptors]: https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html - - **Dialogues management subsystem.** We have designed our dialogues management subsystem to be easy-to-use, and, furthermore, to be independent of how/where dialogues are stored; for example, you can just replace one line to achieve [persistence]. Out-of-the-box storages include [Redis]. + - **Dialogues management subsystem.** We have designed our dialogues management subsystem to be easy-to-use, and, furthermore, to be independent of how/where dialogues are stored. For example, you can just replace one line to achieve [persistence]. Out-of-the-box storages include [Redis]. [persistence]: https://en.wikipedia.org/wiki/Persistence_(computer_science) [finite-state machines]: https://en.wikipedia.org/wiki/Finite-state_machine From e894ae868e3a53b0d73a7c1e7ee881d998d422fb Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 26 Sep 2020 21:42:36 +0600 Subject: [PATCH 40/41] Update README.md Co-authored-by: Waffle Lapkin --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a87cd5bf..d511ece9 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ [finite-state machines]: https://en.wikipedia.org/wiki/Finite-state_machine [Redis]: https://redis.io/ - - **Strongly typed bot commands.** You can describe bot commands as enumerations, and then they'll be automatically constructed from strings -- just like JSON structures in [serde-json] and command-line arguments in [structopt]. + - **Strongly typed bot commands.** You can describe bot commands as enumerations, and then they'll be automatically constructed from strings — just like JSON structures in [serde-json] and command-line arguments in [structopt]. [structopt]: https://github.com/TeXitoi/structopt [serde-json]: https://github.com/serde-rs/json From eb79c7099da20e19c25ff79ee6ee65310799322e Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 26 Sep 2020 21:50:22 +0600 Subject: [PATCH 41/41] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index d511ece9..6740c43d 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,6 @@ - **Dialogues management subsystem.** We have designed our dialogues management subsystem to be easy-to-use, and, furthermore, to be independent of how/where dialogues are stored. For example, you can just replace one line to achieve [persistence]. Out-of-the-box storages include [Redis]. [persistence]: https://en.wikipedia.org/wiki/Persistence_(computer_science) -[finite-state machines]: https://en.wikipedia.org/wiki/Finite-state_machine [Redis]: https://redis.io/ - **Strongly typed bot commands.** You can describe bot commands as enumerations, and then they'll be automatically constructed from strings — just like JSON structures in [serde-json] and command-line arguments in [structopt].