diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dbdb17f..e246e8b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,11 @@ 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] +## unreleased + +### Changed + +- Require that `AsUpdateStream::Stream` is `Send` ## 0.5.3 - 2021-10-25 @@ -12,19 +16,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Compilation when the `ctrlc_handler` feature is disabled ([issue 462](https://github.com/teloxide/teloxide/issues/462)) -## [0.5.2] - 2021-08-25 +## 0.5.2 - 2021-08-25 ### Fixed - Depend on a correct `futures` version (v0.3.15). -## [0.5.1] - 2021-08-05 +## 0.5.1 - 2021-08-05 ### Changed - Improved log messages when `^C` is received with `^C` handler set up -## [0.5.0] - 2021-07-08 +## 0.5.0 - 2021-07-08 ### Added @@ -70,7 +74,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Log errors from `Storage::{remove_dialogue, update_dialogue}` in `DialogueDispatcher` ([issue 302](https://github.com/teloxide/teloxide/issues/302)). - Mark all the functions of `Storage` as `#[must_use]`. -## [0.4.0] - 2021-03-22 +## 0.4.0 - 2021-03-22 ### Added - Integrate [teloxide-core]. @@ -107,28 +111,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [issue 253]: https://github.com/teloxide/teloxide/issues/253 [pr 257]: https://github.com/teloxide/teloxide/pull/257 -## [0.3.4] - 2020-01-13 +## 0.3.4 - 2020-01-13 ### Fixed - Failing compilation with `serde::export` ([issue 328](https://github.com/teloxide/teloxide/issues/328)). -## [0.3.3] - 2020-10-30 +## 0.3.3 - 2020-10-30 ### Fixed - The `dice` field from `MessageDice` is public now ([issue 306](https://github.com/teloxide/teloxide/issues/306)) -## [0.3.2] - 2020-10-23 +## 0.3.2 - 2020-10-23 ### Added - `LoginUrl::new` ([issue 298](https://github.com/teloxide/teloxide/issues/298)) -## [0.3.1] - 2020-08-25 +## 0.3.1 - 2020-08-25 ### Added - `Bot::builder` method ([PR 269](https://github.com/teloxide/teloxide/pull/269)). -## [0.3.0] - 2020-07-31 +## 0.3.0 - 2020-07-31 ### Added - Support for typed bot commands ([issue 152](https://github.com/teloxide/teloxide/issues/152)). - `BotBuilder`, which allows setting a default `ParseMode`. @@ -165,7 +169,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Now methods which can send file to Telegram returns `tokio::io::Result`. Early its could panic ([issue 216](https://github.com/teloxide/teloxide/issues/216)). - If a bot wasn't triggered for several days, it stops responding ([issue 223](https://github.com/teloxide/teloxide/issues/223)). -## [0.2.0] - 2020-02-25 +## 0.2.0 - 2020-02-25 ### Added - The functionality to parse commands only with a correct bot's name (breaks backwards compatibility) ([Issue 168](https://github.com/teloxide/teloxide/issues/168)). - This `CHANGELOG.md`. @@ -180,6 +184,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [either](https://crates.io/crates/either) from the dependencies in `Cargo.toml`. - `teloxide-macros` migrated into [the separate repository](https://github.com/teloxide/teloxide-macros) to easier releases and testing. -## [0.1.0] - 2020-02-19 +## 0.1.0 - 2020-02-19 ### Added - This project. diff --git a/Cargo.toml b/Cargo.toml index cbb0272b..9ac1a193 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ authors = [ maintenance = { status = "actively-developed" } [features] -default = ["native-tls", "ctrlc_handler", "teloxide-core/default"] +default = ["native-tls", "ctrlc_handler", "teloxide-core/default", "auto-send"] sqlite-storage = ["sqlx"] redis-storage = ["redis"] diff --git a/README.md b/README.md index 919500f9..f78ffa16 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,12 @@ # Unix-like $ export TELOXIDE_TOKEN= -# Windows +# Windows command line $ set TELOXIDE_TOKEN= + +# Windows PowerShell +$ $env:TELOXIDE_TOKEN= + ``` 4. Make sure that your Rust compiler is up to date: ```bash @@ -68,10 +72,10 @@ $ rustup override set nightly 5. Run `cargo new my_bot`, enter the directory and put these lines into your `Cargo.toml`: ```toml [dependencies] -teloxide = { version = "0.4", features = ["auto-send", "macros"] } -log = "0.4.8" +teloxide = { version = "0.5", features = ["macros"] } +log = "0.4" pretty_env_logger = "0.4.0" -tokio = { version = "1.3", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] } ``` ## API overview @@ -412,21 +416,21 @@ A: Yes. You can setup any logger, for example, [fern], e.g. teloxide has no spec Feel free to propose your own bot to our collection! - [WaffleLapkin/crate_upd_bot](https://github.com/WaffleLapkin/crate_upd_bot) -- A bot that notifies about crate updates. - - [dracarys18/grpmr-rs](https://github.com/dracarys18/grpmr-rs) -- A telegram group manager bot with variety of extra features. + - [mxseev/logram](https://github.com/mxseev/logram) -- Utility that takes logs from anywhere and sends them to Telegram. + - [Hermitter/tepe](https://github.com/Hermitter/tepe) -- A CLI to command a bot to send messages and files over Telegram. + - [dracarys18/grpmr-rs](https://github.com/dracarys18/grpmr-rs) -- A Telegram group manager bot with variety of extra features. - [steadylearner/subreddit_reader](https://github.com/steadylearner/Rust-Full-Stack/tree/master/commits/teloxide/subreddit_reader) -- A bot that shows the latest posts at Rust subreddit. + - [myblackbeard/basketball-betting-bot](https://github.com/myblackbeard/basketball-betting-bot) -- The bot lets you bet on NBA games against your buddies. - [ArtHome12/vzmuinebot](https://github.com/ArtHome12/vzmuinebot) -- Telegram bot for food menu navigate. - [ArtHome12/cognito_bot](https://github.com/ArtHome12/cognito_bot) -- The bot is designed to anonymize messages to a group. - - [Hermitter/tepe](https://github.com/Hermitter/tepe) -- A CLI to command a bot to send messages and files over Telegram. - [pro-vim/tg-vimhelpbot](https://github.com/pro-vim/tg-vimhelpbot) -- Link `:help` for Vim in Telegram. - [sschiz/janitor-bot](https://github.com/sschiz/janitor-bot) -- A bot that removes users trying to join to a chat that is designed for comments. - - [myblackbeard/basketball-betting-bot](https://github.com/myblackbeard/basketball-betting-bot) -- The bot lets you bet on NBA games against your buddies. - [slondr/BeerHolderBot](https://gitlab.com/slondr/BeerHolderBot) -- A bot that holds your beer. - - [mxseev/logram](https://github.com/mxseev/logram) -- Utility that takes logs from anywhere and sends them to Telegram. - - [msfjarvis/walls-bot-rs](https://github.com/msfjarvis/walls-bot-rs) -- Telegram bot for my wallpapers collection, in Rust. - - [MustafaSalih1993/Miss-Vodka-Telegram-Bot](https://github.com/MustafaSalih1993/Miss-Vodka-Telegram-Bot) -- A telegram bot written in rust using "Teloxide" library. + - [MustafaSalih1993/Miss-Vodka-Telegram-Bot](https://github.com/MustafaSalih1993/Miss-Vodka-Telegram-Bot) -- A Telegram bot written in rust using "Teloxide" library. - [x13a/tg-prompt](https://github.com/x13a/tg-prompt) -- Telegram prompt. - [magnickolas/remindee-bot](https://github.com/magnickolas/remindee-bot) -- Telegram bot for managing reminders. - - [cyberknight777/knight-bot](https://gitlab.com/cyberknight777/knight-bot) -- A telegram bot with variety of fun features. - + - [cyberknight777/knight-bot](https://gitlab.com/cyberknight777/knight-bot) -- A Telegram bot with variety of fun features. + - [wa7sa34cx/the-black-box-bot](https://github.com/wa7sa34cx/the-black-box-bot) -- This is the Black Box Telegram bot. You can hold any items in it. + ## Contributing See [CONRIBUTING.md](https://github.com/teloxide/teloxide/blob/master/CONTRIBUTING.md). diff --git a/examples/admin_bot/Cargo.toml b/examples/admin_bot/Cargo.toml index 52c6f017..4ee67f87 100644 --- a/examples/admin_bot/Cargo.toml +++ b/examples/admin_bot/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -teloxide = { path = "../../", features = ["macros", "auto-send"] } +teloxide = { path = "../../", features = ["macros"] } log = "0.4.8" pretty_env_logger = "0.4.0" tokio = { version = "1.3.0", features = ["rt-multi-thread", "macros"] } diff --git a/examples/buttons/Cargo.toml b/examples/buttons/Cargo.toml new file mode 100644 index 00000000..9922e0ae --- /dev/null +++ b/examples/buttons/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "buttons" +version = "0.1.0" +edition = "2018" + +[dependencies] +teloxide = { path = "../../", features = ["macros"] } + +tokio = { version = "1.3", features = ["rt-multi-thread", "macros"] } +log = "0.4.8" +pretty_env_logger = "0.4.0" +tokio-stream = "0.1.6" diff --git a/examples/buttons/src/main.rs b/examples/buttons/src/main.rs new file mode 100644 index 00000000..97bde1ed --- /dev/null +++ b/examples/buttons/src/main.rs @@ -0,0 +1,147 @@ +use std::error::Error; +use teloxide::{ + payloads::SendMessageSetters, + prelude::*, + types::{ + InlineKeyboardButton, InlineKeyboardMarkup, InlineQueryResultArticle, InputMessageContent, + InputMessageContentText, + }, + utils::command::BotCommand, +}; + +use tokio_stream::wrappers::UnboundedReceiverStream; + +#[derive(BotCommand)] +#[command(rename = "lowercase", description = "These commands are supported:")] +enum Command { + #[command(description = "Display this text")] + Help, + #[command(description = "Start")] + Start, +} + +/// Creates a keyboard made by buttons in a big column. +fn make_keyboard() -> InlineKeyboardMarkup { + let mut keyboard: Vec> = vec![]; + + let debian_versions = [ + "Buzz", "Rex", "Bo", "Hamm", "Slink", "Potato", "Woody", "Sarge", "Etch", "Lenny", + "Squeeze", "Wheezy", "Jessie", "Stretch", "Buster", "Bullseye", + ]; + + for versions in debian_versions.chunks(3) { + let row = versions + .iter() + .map(|&version| InlineKeyboardButton::callback(version.to_owned(), version.to_owned())) + .collect(); + + keyboard.push(row); + } + + InlineKeyboardMarkup::new(keyboard) +} + +/// Parse the text wrote on Telegram and check if that text is a valid command +/// or not, then match the command. If the command is `/start` it writes a +/// markup with the `InlineKeyboardMarkup`. +async fn message_handler( + cx: UpdateWithCx, Message>, +) -> Result<(), Box> { + match cx.update.text() { + Some(text) => { + match BotCommand::parse(text, "buttons") { + Ok(Command::Help) => { + // Just send the description of all commands. + cx.answer(Command::descriptions()).await?; + } + Ok(Command::Start) => { + // Create a list of buttons and send them. + let keyboard = make_keyboard(); + cx.answer("Debian versions:").reply_markup(keyboard).await?; + } + + Err(_) => { + cx.reply_to("Command not found!").await?; + } + } + } + None => {} + } + + Ok(()) +} + +async fn inline_query_handler( + cx: UpdateWithCx, InlineQuery>, +) -> Result<(), Box> { + let UpdateWithCx { requester: bot, update: query } = cx; + + let choose_debian_version = InlineQueryResultArticle::new( + "0", + "Chose debian version", + InputMessageContent::Text(InputMessageContentText::new("Debian versions:")), + ) + .reply_markup(make_keyboard()); + + bot.answer_inline_query(query.id, vec![choose_debian_version.into()]).await?; + + Ok(()) +} + +/// When it receives a callback from a button it edits the message with all +/// those buttons writing a text with the selected Debian version. +async fn callback_handler( + cx: UpdateWithCx, CallbackQuery>, +) -> Result<(), Box> { + let UpdateWithCx { requester: bot, update: query } = cx; + + if let Some(version) = query.data { + let text = format!("You chose: {}", version); + + match query.message { + Some(Message { id, chat, .. }) => { + bot.edit_message_text(chat.id, id, text).await?; + } + None => { + if let Some(id) = query.inline_message_id { + bot.edit_message_text_inline(dbg!(id), text).await?; + } + } + } + + log::info!("You chose: {}", version); + } + + Ok(()) +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + teloxide::enable_logging!(); + log::info!("Starting bot..."); + + let bot = Bot::from_env().auto_send(); + + Dispatcher::new(bot) + .messages_handler(|rx: DispatcherHandlerRx, Message>| { + UnboundedReceiverStream::new(rx).for_each_concurrent(None, |cx| async move { + message_handler(cx).await.log_on_error().await; + }) + }) + .callback_queries_handler(|rx: DispatcherHandlerRx, CallbackQuery>| { + UnboundedReceiverStream::new(rx).for_each_concurrent(None, |cx| async move { + callback_handler(cx).await.log_on_error().await; + }) + }) + .inline_queries_handler(|rx: DispatcherHandlerRx, InlineQuery>| { + UnboundedReceiverStream::new(rx).for_each_concurrent(None, |cx| async move { + inline_query_handler(cx).await.log_on_error().await; + }) + }) + .dispatch() + .await; + + log::info!("Closing bot... Goodbye!"); + + Ok(()) +} diff --git a/examples/dialogue_bot/Cargo.toml b/examples/dialogue_bot/Cargo.toml index 8d2ea09a..be8d5085 100644 --- a/examples/dialogue_bot/Cargo.toml +++ b/examples/dialogue_bot/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -teloxide = { path = "../../", features = ["frunk", "macros", "auto-send"] } +teloxide = { path = "../../", features = ["frunk", "macros"] } futures = "0.3.5" tokio = { version = "1.3.0", features = ["rt-multi-thread", "macros"] } diff --git a/examples/dices_bot/Cargo.toml b/examples/dices_bot/Cargo.toml index 763f2c8b..b6feb4b2 100644 --- a/examples/dices_bot/Cargo.toml +++ b/examples/dices_bot/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -teloxide = { path = "../../", features = ["auto-send"] } +teloxide = { path = "../../" } log = "0.4.8" pretty_env_logger = "0.4.0" tokio = { version = "1.3.0", features = ["rt-multi-thread", "macros"] } diff --git a/examples/heroku_ping_pong_bot/Cargo.toml b/examples/heroku_ping_pong_bot/Cargo.toml index edcc76f5..713b4fd4 100644 --- a/examples/heroku_ping_pong_bot/Cargo.toml +++ b/examples/heroku_ping_pong_bot/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -teloxide = { path = "../../", features = ["auto-send"] } +teloxide = { path = "../../" } log = "0.4.8" pretty_env_logger = "0.4.0" tokio = { version = "1.3.0", features = ["rt-multi-thread", "macros"] } diff --git a/examples/inline_bot/Cargo.toml b/examples/inline_bot/Cargo.toml index 40e7281d..913b25c8 100644 --- a/examples/inline_bot/Cargo.toml +++ b/examples/inline_bot/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -teloxide = { path = "../../", features = ["macros", "auto-send"] } +teloxide = { path = "../../", features = ["macros"] } log = "0.4.8" pretty_env_logger = "0.4.0" tokio = { version = "1.3.0", features = ["rt-multi-thread", "macros"] } diff --git a/examples/ngrok_ping_pong_bot/Cargo.toml b/examples/ngrok_ping_pong_bot/Cargo.toml index 571fe1ff..5f05b0d7 100644 --- a/examples/ngrok_ping_pong_bot/Cargo.toml +++ b/examples/ngrok_ping_pong_bot/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -teloxide = { path = "../../", features = ["auto-send"] } +teloxide = { path = "../../" } log = "0.4.8" pretty_env_logger = "0.4.0" tokio = { version = "1.3.0", features = ["rt-multi-thread", "macros"] } diff --git a/examples/redis_remember_bot/Cargo.toml b/examples/redis_remember_bot/Cargo.toml index c134f0a4..57d7b547 100644 --- a/examples/redis_remember_bot/Cargo.toml +++ b/examples/redis_remember_bot/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] # You can also choose "cbor-serializer" or built-in JSON serializer -teloxide = { path = "../../", features = ["redis-storage", "bincode-serializer", "macros", "auto-send"] } +teloxide = { path = "../../", features = ["redis-storage", "bincode-serializer", "macros"] } log = "0.4.8" pretty_env_logger = "0.4.0" diff --git a/examples/shared_state_bot/Cargo.toml b/examples/shared_state_bot/Cargo.toml index eb613ba1..dbaacc86 100644 --- a/examples/shared_state_bot/Cargo.toml +++ b/examples/shared_state_bot/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -teloxide = { path = "../../", features = ["auto-send"] } +teloxide = { path = "../../" } log = "0.4.8" pretty_env_logger = "0.4.0" tokio = { version = "1.3.0", features = ["rt-multi-thread", "macros"] } diff --git a/examples/simple_commands_bot/Cargo.toml b/examples/simple_commands_bot/Cargo.toml index 7aef1030..d5368de3 100644 --- a/examples/simple_commands_bot/Cargo.toml +++ b/examples/simple_commands_bot/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -teloxide = { path = "../../", features = ["macros", "auto-send"] } +teloxide = { path = "../../", features = ["macros"] } log = "0.4.8" pretty_env_logger = "0.4.0" tokio = { version = "1.3.0", features = ["rt-multi-thread", "macros"] } diff --git a/examples/sqlite_remember_bot/Cargo.toml b/examples/sqlite_remember_bot/Cargo.toml index d224d528..74b1d23a 100644 --- a/examples/sqlite_remember_bot/Cargo.toml +++ b/examples/sqlite_remember_bot/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] # You can also choose "cbor-serializer" or built-in JSON serializer -teloxide = { path = "../../", features = ["sqlite-storage", "bincode-serializer", "redis-storage", "macros", "auto-send"] } +teloxide = { path = "../../", features = ["sqlite-storage", "bincode-serializer", "redis-storage", "macros"] } log = "0.4.8" pretty_env_logger = "0.4.0" diff --git a/src/dispatching/dispatcher.rs b/src/dispatching/dispatcher.rs index 77133764..f486c46a 100644 --- a/src/dispatching/dispatcher.rs +++ b/src/dispatching/dispatcher.rs @@ -106,7 +106,7 @@ where /// /// [`shutdown`]: ShutdownToken::shutdown #[cfg(feature = "ctrlc_handler")] - #[cfg_attr(docsrs, doc(cfg(feature = "ctrlc_handler")))] + #[cfg_attr(all(docsrs, feature = "nightly"), doc(cfg(feature = "ctrlc_handler")))] pub fn setup_ctrlc_handler(self) -> Self { let state = Arc::clone(&self.state); tokio::spawn(async move { diff --git a/src/dispatching/update_listeners.rs b/src/dispatching/update_listeners.rs index a0d9edca..078f52a2 100644 --- a/src/dispatching/update_listeners.rs +++ b/src/dispatching/update_listeners.rs @@ -188,7 +188,14 @@ pub trait UpdateListener: for<'a> AsUpdateStream<'a, E> { /// This trait is a workaround to not require GAT. pub trait AsUpdateStream<'a, E> { /// The stream of updates from Telegram. - type Stream: Stream> + 'a; + // HACK: There is currently no way to write something like + // `-> impl for<'a> AsUpdateStream<'a, E, Stream: Send>`. Since we return + // `impl UpdateListener` from `polling`, we need to have `Send` bound here, + // to make the stream `Send`. + // + // Without this it's, for example, impossible to spawn a tokio task with + // teloxide polling. + type Stream: Stream> + Send + 'a; /// Creates the update [`Stream`]. /// diff --git a/src/dispatching/update_listeners/polling.rs b/src/dispatching/update_listeners/polling.rs index 5440fd6a..f7050bff 100644 --- a/src/dispatching/update_listeners/polling.rs +++ b/src/dispatching/update_listeners/polling.rs @@ -24,7 +24,7 @@ use crate::{ /// This function will automatically delete a webhook if it was set up. pub async fn polling_default(requester: R) -> impl UpdateListener where - R: Requester + 'static, + R: Requester + Send + 'static, ::GetUpdatesFaultTolerant: Send, { delete_webhook_if_setup(&requester).await; @@ -50,7 +50,7 @@ pub fn polling( allowed_updates: Option>, ) -> impl UpdateListener where - R: Requester + 'static, + R: Requester + Send + 'static, ::GetUpdatesFaultTolerant: Send, { struct State { @@ -63,9 +63,10 @@ where token: AsyncStopToken, } - fn stream(st: &mut State) -> impl Stream> + '_ + fn stream(st: &mut State) -> impl Stream> + Send + '_ where - B: Requester, + B: Requester + Send, + ::GetUpdatesFaultTolerant: Send, { stream::unfold(st, move |state| async move { let State { timeout, limit, allowed_updates, bot, offset, flag, .. } = &mut *state; @@ -177,3 +178,16 @@ where } } } + +#[test] +fn polling_is_send() { + use crate::dispatching::update_listeners::AsUpdateStream; + + let bot = crate::Bot::new("TOKEN"); + let mut polling = polling(bot, None, None, None); + + assert_send(&polling); + assert_send(&polling.as_stream()); + + fn assert_send(_: &impl Send) {} +} diff --git a/src/dispatching/update_listeners/stateful_listener.rs b/src/dispatching/update_listeners/stateful_listener.rs index a9c26576..2b36baa5 100644 --- a/src/dispatching/update_listeners/stateful_listener.rs +++ b/src/dispatching/update_listeners/stateful_listener.rs @@ -79,7 +79,7 @@ impl Thfn, > where - S: Stream> + Unpin + 'static, + S: Stream> + Unpin + Send + 'static, { /// Creates a new update listener from a stream of updates which ignores /// stop signals. @@ -109,6 +109,7 @@ impl<'a, St, Assf, Sf, Hauf, Thf, Strm, E> AsUpdateStream<'a, E> for StatefulListener where (St, Strm): 'a, + Strm: Send, Assf: FnMut(&'a mut St) -> Strm, Strm: Stream>, { diff --git a/src/features.txt b/src/features.txt index f6ef21ba..7edd2f39 100644 --- a/src/features.txt +++ b/src/features.txt @@ -10,8 +10,11 @@ | `native-tls` | Enables the [`native-tls`] TLS implementation (enabled by default). | | `rustls` | Enables the [`rustls`] TLS implementation. | | `ctrlc_handler` | Enables the [`Dispatcher::setup_ctrlc_handler`](dispatching::Dispatcher::setup_ctrlc_handler) function. | -| `auto-send` | Enables the `AutoSend` bot adaptor. | -| `cache-me` | Enables the `CacheMe` bot adaptor. | +| `auto-send` | Enables the [`AutoSend`](adaptors::AutoSend) bot adaptor. | +| `throttle` | Enables the [`Throttle`](adaptors::Throttle) bot adaptor. | +| `cache-me` | Enables the [`CacheMe`](adaptors::CacheMe) bot adaptor. | +| `trace-adaptor` | Enables the [`Trace`](adaptors::Trace) bot adaptor. | +| `erased` | Enables the [`ErasedRequester`](adaptors::ErasedRequester) bot adaptor. | | `frunk` | Enables [`teloxide::utils::UpState`]. | | `full` | Enables all the features except `nightly`. | | `nightly` | Enables nightly-only features (see the [teloxide-core features]). |