diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d890843..4ea743ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,7 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add the `Key: Clone` requirement for `impl Dispatcher` [**BC**]. - `dispatching::update_listeners::{polling_default, polling}` now return a named, `Polling<_>` type. -- Update teloxide-core to v0.7.0 with Bot API 6.1 support, see [its changelog][core07c] for more information [**BC**]. +- Update `teloxide-core` to v0.7.0 with Bot API 6.1 support, see [its changelog][core07c] for more information [**BC**]. [core07c]: https://github.com/teloxide/teloxide-core/blob/master/CHANGELOG.md#070---2022-07-19 @@ -92,7 +92,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Update teloxide-core to v0.6.0 with [Bot API 6.0] support [**BC**]. +- Update `teloxide-core` to v0.6.0 with [Bot API 6.0] support [**BC**]. [Bot API 6.0]: https://core.telegram.org/bots/api#april-16-2022 diff --git a/CODE_STYLE.md b/CODE_STYLE.md index 77803ce3..40b65d86 100644 --- a/CODE_STYLE.md +++ b/CODE_STYLE.md @@ -83,6 +83,7 @@ impl Trait for Wrap { ... } /// [`tokio::fs::File`]: tokio::fs::File /// [`Bot::download_file`]: crate::Bot::download_file ``` +4. Write `teloxide`, `teloxide-macros`, and `teloxide-core`, not "teloxide", "Teloxide", "teloxide-macros" or any other variant. ## Use `Self` where possible diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 78003f48..83ea0829 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,6 +1,108 @@ This document describes breaking changes of `teloxide` crate, as well as the ways to update code. Note that the list of required changes is not fully exhaustive and it may lack something in rare cases. +## 0.10 -> 0.11 + +### core + +Requests can now be `.await`ed directly, without need of `.send()` or `AutoSend`. +If you previously used `AutoSend` adaptor, you can safely remove it: + +```diff,rust +-let bot = Bot::from_env().auto_send(); ++let bot = Bot::from_env(); +``` + +```diff,rust +-async fn start(bot: AutoSend, dialogue: MyDialogue, msg: Message) -> HandlerResult { ++async fn start(bot: Bot, dialogue: MyDialogue, msg: Message) -> HandlerResult { +``` + +`File`'s and `FileMeta`'s fields now don't have `file_` prefix. +If you previously accessed the fields, you'll need to change remove the prefix: + +```diff +-_ = file.file_size; ++_ = file.size; +``` + +`Animation`, `Audio`, `Document`, `PassportFile`, `PhotoSize`, `Video`, `VideoNote` and `Voice` now contain `FileMeta` instead of its fields. +Together with rename of `FileMeta`'s fields, you'll need to change `_` to `.`: + +```diff +-_ = animation.file_size; ++_ = animation.file.size; +``` + +Message id fields and parameters now use `MessageId` type, instead of `i32`. +You may need to change code accordingly: + +```diff +-let id: i32 = message.id; ++let id: MessageId = message.id; +``` +```diff,rust +let (cid, mid): (ChatId, i32) = get_message_to_delete_from_db(); +-bot.delete_message(cid, mid).await?; ++bot.delete_message(cid, MessageId(mid)).await?; +``` + +Note that at the same time `MessageId` is now a tuple struct. +If you've accessed its only field you'll need to change it too: + +```diff,rust +-let MessageId { message_id } = bot.copy_message(dst_chat, src_chat, mid).await?; ++let MessageId(message_id) = bot.copy_message(dst_chat, src_chat, mid).await?; +save_to_db(message_id); +``` + +Because of API updates `Sticker` type was refactored again. +You may need to change code accordingly. +See `Sticker` documentation for more information about the new structure. + +### teloxide + +You can now write `Ok(())` instead of `respond(())` at the end of closures provided to RELPs: + +```diff,rust +teloxide::repl(bot, |bot: Bot, msg: Message| async move { + bot.send_dice(msg.chat.id).await?; +- respond(()) ++ Ok(()) +}) +.await; +``` + +This is because REPLs now require the closure to return `RequestError` instead of a generic error type, so type inference works perfectly for a return value. If you use something other than `RequestError`, you can transfer your code to `teloxide::dispatching`, which still permits a generic error type. + +### macros + +`parse_with` now accepts a Rust _path_ to a custom parser function instead of a string: + +```diff,rust +fn custom_parser(input: String) -> Result<(u8,), ParseError> { + todo!() +} + +#[derive(BotCommands)] +enum Command { +- #[command(parse_with = "custom_parser")] ++ #[command(parse_with = custom_parser)] + Num(u8), +} +``` + +`rename` now only renames a command literally; use `rename_rule` to change the case of a command: + +```diff,rust +#[derive(BotCommands)] +- #[command(rename = "lowercase", description = "These commands are supported:")] ++ #[command(rename_rule = "lowercase", description = "These commands are supported:")] +enum Command { + // ... +} +``` + ## 0.9 -> 0.10 ### core diff --git a/README.md b/README.md index f3fae40d..2fb0010a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@
-

teloxide

+

teloxide

@@ -24,18 +24,20 @@ ## Highlights - - **Declarative design.** teloxide is based upon [`dptree`], a functional [chain of responsibility] pattern that allows you to express pipelines of message processing in a highly declarative and extensible style. + - **Declarative design.** `teloxide` is based upon [`dptree`], a functional [chain of responsibility] pattern that allows you to express pipelines of message processing in a highly declarative and extensible style. [`dptree`]: https://github.com/teloxide/dptree [chain of responsibility]: https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern - - **Dialogues management subsystem.** Our dialogues management subsystem is simple and easy-to-use, and, furthermore, is agnostic of how/where dialogues are stored. For example, you can just replace a one line to achieve [persistence]. Out-of-the-box storages include [Redis] and [Sqlite]. + - **Feature-rich.** You can use both long polling and webhooks, configure an underlying HTTPS client, set a custom URL of a Telegram API server, and much more. + + - **Simple dialogues.** Our dialogues subsystem is simple and easy-to-use, and, furthermore, is agnostic of how/where dialogues are stored. For example, you can just replace a one line to achieve [persistence]. Out-of-the-box storages include [Redis] and [Sqlite]. [persistence]: https://en.wikipedia.org/wiki/Persistence_(computer_science) [Redis]: https://redis.io/ [Sqlite]: https://www.sqlite.org - - **Strongly typed 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 commands.** Define bot commands as an `enum` and teloxide will parse them automatically — 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 @@ -54,9 +56,9 @@ $ set TELOXIDE_TOKEN= # Windows PowerShell $ $env:TELOXIDE_TOKEN= - ``` - 4. Make sure that your Rust compiler is up to date (teloxide currently requires rustc at least version 1.64): + + 4. Make sure that your Rust compiler is up to date (`teloxide` currently requires rustc at least version 1.64): ```bash # If you're using stable $ rustup update stable @@ -304,7 +306,7 @@ A: No, only the bots API. **Q: Can I use webhooks?** -A: You can! Teloxide has a built-in support for webhooks in `dispatching::update_listeners::webhooks` module. See how it's used in [`examples/ngrok_ping_pong_bot`](examples/ngrok_ping_pong.rs) and [`examples/heroku_ping_pong_bot`](examples/heroku_ping_pong.rs). +A: You can! `teloxide` has a built-in support for webhooks in `dispatching::update_listeners::webhooks` module. See how it's used in [`examples/ngrok_ping_pong_bot`](examples/ngrok_ping_pong.rs) and [`examples/heroku_ping_pong_bot`](examples/heroku_ping_pong.rs). **Q: Can I handle both callback queries and messages within a single dialogue?** @@ -328,7 +330,7 @@ Feel free to propose your own bot to our collection! - [`zamazan4ik/npaperbot-telegram`](https://github.com/zamazan4ik/npaperbot-telegram) — Telegram bot for searching via C++ proposals.
-Show bots using teloxide older than v0.6.0 +Show bots using `teloxide` older than v0.6.0 - [`mxseev/logram`](https://github.com/mxseev/logram) — Utility that takes logs from anywhere and sends them to Telegram. - [`alexkonovalov/PedigreeBot`](https://github.com/alexkonovalov/PedigreeBot) — A Telegram bot for building family trees. @@ -340,7 +342,7 @@ Feel free to propose your own bot to our collection!
-See [700+ other public repositories using teloxide >>](https://github.com/teloxide/teloxide/network/dependents) +See [700+ other public repositories using `teloxide` >>](https://github.com/teloxide/teloxide/network/dependents) ## Contributing diff --git a/src/dispatching/dialogue.rs b/src/dispatching/dialogue.rs index c8d27896..89d16326 100644 --- a/src/dispatching/dialogue.rs +++ b/src/dispatching/dialogue.rs @@ -220,18 +220,17 @@ where Upd: GetChatId + Clone + Send + Sync + 'static, Output: Send + Sync + 'static, { - dptree::entry() - .chain(dptree::filter_map(|storage: Arc, upd: Upd| { - let chat_id = upd.chat_id()?; - Some(Dialogue::new(storage, chat_id)) - })) - .chain(dptree::filter_map_async(|dialogue: Dialogue| async move { - match dialogue.get_or_default().await { - Ok(dialogue) => Some(dialogue), - Err(err) => { - log::error!("dialogue.get_or_default() failed: {:?}", err); - None - } + dptree::filter_map(|storage: Arc, upd: Upd| { + let chat_id = upd.chat_id()?; + Some(Dialogue::new(storage, chat_id)) + }) + .filter_map_async(|dialogue: Dialogue| async move { + match dialogue.get_or_default().await { + Ok(dialogue) => Some(dialogue), + Err(err) => { + log::error!("dialogue.get_or_default() failed: {:?}", err); + None } - })) + } + }) } diff --git a/src/dispatching/handler_ext.rs b/src/dispatching/handler_ext.rs index 932d5079..0013acb4 100644 --- a/src/dispatching/handler_ext.rs +++ b/src/dispatching/handler_ext.rs @@ -88,8 +88,8 @@ where C: BotCommands + Send + Sync + 'static, Output: Send + Sync + 'static, { - dptree::entry().chain(dptree::filter_map(move |message: Message, me: Me| { + dptree::filter_map(move |message: Message, me: Me| { let bot_name = me.user.username.expect("Bots must have a username"); message.text().and_then(|text| C::parse(text, &bot_name).ok()) - })) + }) } diff --git a/src/dispatching/repls/commands_repl.rs b/src/dispatching/repls/commands_repl.rs index d4e82954..fe9d9fb7 100644 --- a/src/dispatching/repls/commands_repl.rs +++ b/src/dispatching/repls/commands_repl.rs @@ -37,7 +37,7 @@ use std::{fmt::Debug, marker::PhantomData}; /// /// ## Handler arguments /// -/// Teloxide provides the following types to the `handler`: +/// `teloxide` provides the following types to the `handler`: /// - [`Message`] /// - `R` (type of the `bot`) /// - `Cmd` (type of the parsed command) @@ -105,7 +105,7 @@ where /// /// ## Handler arguments /// -/// Teloxide provides the following types to the `handler`: +/// `teloxide` provides the following types to the `handler`: /// - [`Message`] /// - `R` (type of the `bot`) /// - `Cmd` (type of the parsed command) diff --git a/src/dispatching/repls/repl.rs b/src/dispatching/repls/repl.rs index fd26e6e2..b352d8e3 100644 --- a/src/dispatching/repls/repl.rs +++ b/src/dispatching/repls/repl.rs @@ -27,7 +27,7 @@ use std::fmt::Debug; /// /// ## Handler arguments /// -/// Teloxide provides the following types to the `handler`: +/// `teloxide` provides the following types to the `handler`: /// - [`Message`] /// - `R` (type of the `bot`) /// - [`Me`] @@ -81,7 +81,7 @@ where /// /// ## Handler arguments /// -/// Teloxide provides the following types to the `handler`: +/// `teloxide` provides the following types to the `handler`: /// - [`Message`] /// - `R` (type of the `bot`) /// - [`Me`] diff --git a/src/dispatching/update_listeners/polling.rs b/src/dispatching/update_listeners/polling.rs index 1543b322..5fb863f0 100644 --- a/src/dispatching/update_listeners/polling.rs +++ b/src/dispatching/update_listeners/polling.rs @@ -67,7 +67,7 @@ where /// /// ## Note /// - /// Teloxide normally (when using [`Dispatcher`] or [`repl`]s) sets this + /// `teloxide` normally (when using [`Dispatcher`] or [`repl`]s) sets this /// automatically via [`hint_allowed_updates`], so you rarely need to use /// `allowed_updates` explicitly. /// diff --git a/src/dispatching/update_listeners/webhooks.rs b/src/dispatching/update_listeners/webhooks.rs index ef94fec4..e327016b 100644 --- a/src/dispatching/update_listeners/webhooks.rs +++ b/src/dispatching/update_listeners/webhooks.rs @@ -49,7 +49,7 @@ pub struct Options { /// `a-z`, `0-9`, `_` and `-` are allowed. The header is useful to ensure /// that the request comes from a webhook set by you. /// - /// Default - teloxide will generate a random token. + /// Default - `teloxide` will generate a random token. pub secret_token: Option, } diff --git a/src/features.md b/src/features.md index c7aa4e6a..1545af78 100644 --- a/src/features.md +++ b/src/features.md @@ -12,7 +12,7 @@ | `trace-adaptor` | Enables the [`Trace`](adaptors::Trace) bot adaptor. | | `erased` | Enables the [`ErasedRequester`](adaptors::ErasedRequester) bot adaptor. | | `full` | Enables all the features except `nightly`. | -| `nightly` | Enables nightly-only features (see the [teloxide-core features]). | +| `nightly` | Enables nightly-only features (see the [`teloxide-core` features]). | | `native-tls` | Enables the [`native-tls`] TLS implementation (**enabled by default**). | | `rustls` | Enables the [`rustls`] TLS implementation. | | `redis-storage` | Enables the [Redis] storage support for dialogues. | @@ -29,6 +29,6 @@ [`native-tls`]: https://docs.rs/native-tls [`rustls`]: https://docs.rs/rustls [`teloxide::utils::UpState`]: utils::UpState -[teloxide-core features]: https://docs.rs/teloxide-core/latest/teloxide_core/#cargo-features +[`teloxide-core` features]: https://docs.rs/teloxide-core/latest/teloxide_core/#cargo-features [`DispatcherBuilder::enable_ctrlc_handler`]: dispatching::DispatcherBuilder::enable_ctrlc_handler \ No newline at end of file