diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c6a7fdb..2d43546e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -157,6 +157,13 @@ jobs: command: check args: --examples --features full + # TODO: prolly move it to a separate step? + - name: Check with no default features + uses: actions-rs/cargo@v1 + with: + command: check + args: --no-default-features + clippy: name: Run linter runs-on: ubuntu-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 11e2543c..f5748e0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## unreleased -## Removed +### Changed + +- Updated `axum` to v0.6.0. + +### Removed - `rocksdb-storage` feature and associated items (See [PR #761](https://github.com/teloxide/teloxide/pull/761) for reasoning) [**BC**] @@ -16,7 +20,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The following functions were made `#[must_use]`: - `DispatcherBuilder::{enable_ctrlc_handler, distribution_function}` -## 0.11.1 - 2022-10-31 +## 0.11.3 - 2022-11-28 + +### Fixed + +- Add another missing feature gate for `dispatching::repls` import ([issue #770](https://github.com/teloxide/teloxide/issues/770)) + +## 0.11.2 - 2022-11-18 + +### Fixed + +- Add missing feature gate for `dispatching::repls` import ([issue #770](https://github.com/teloxide/teloxide/issues/770)) + +## 0.11.1 - 2022-10-31 [yanked] + +This release was yanked because it accidentally [breaks backwards compatibility](https://github.com/teloxide/teloxide/issues/770). ### Added diff --git a/Cargo.toml b/Cargo.toml index c66a4d73..09124e33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,13 @@ [workspace] members = ["crates/*"] + + +# The settings below will be applied to all crates in the workspace +[workspace.package] +# MSRV (minimal supported Rust version). +rust-version = "1.64" +edition = "2021" + +license = "MIT" +homepage = "https://github.com/teloxide/teloxide" +repository = "https://github.com/teloxide/teloxide" diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index fd75050f..acbf9301 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -9,7 +9,7 @@ Note that the list of required changes is not fully exhaustive and it may lack s If you are using rocksdb storage, you'll need to either write `Storage` impl yourself, or use a third party crate. -## 0.11 -> 0.11.1 +## 0.11 -> 0.11.3 ### teloxide diff --git a/README.md b/README.md index ad1b7565..f5c23baf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -> [v0.11 -> v0.11.1 migration guide >>](MIGRATION_GUIDE.md#011---0111) +> [v0.11 -> v0.11.3 migration guide >>](MIGRATION_GUIDE.md#011---0113)
diff --git a/crates/teloxide-core/Cargo.toml b/crates/teloxide-core/Cargo.toml index fb1cfcb1..ea8f2931 100644 --- a/crates/teloxide-core/Cargo.toml +++ b/crates/teloxide-core/Cargo.toml @@ -1,64 +1,20 @@ [package] name = "teloxide-core" -description = "Core part of the `teloxide` library - telegram bot API client" version = "0.8.0" -edition = "2021" +description = "Core part of the `teloxide` library - telegram bot API client" + +rust-version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true -license = "MIT" -repository = "https://github.com/teloxide/teloxide-core/" -homepage = "https://github.com/teloxide/teloxide-core/" documentation = "https://docs.rs/teloxide-core/" readme = "README.md" -keywords = ["telegram", "bot", "tba"] +keywords = ["teloxide", "telegram", "telegram-bot", "telegram-bot-api", "bot", "TBA"] categories = ["api-bindings", "asynchronous"] -exclude = [ - ".github/*", - "netlify.toml", -] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -futures = "0.3.5" -tokio = { version = "1.12.0", features = ["fs"] } -tokio-util = { version = "0.7.0", features = ["codec"] } -pin-project = "1.0.12" -bytes = "1.0.0" -reqwest = { version = "0.11.10", features = ["json", "stream", "multipart"], default-features = false } -url = { version = "2", features = ["serde"] } -log = "0.4" - -serde = { version = "1.0.114", features = ["derive"] } -serde_json = "1.0.55" -serde_with_macros = "1.5.2" -uuid = { version = "1.1.0", features = ["v4"] } # for attaching input files - -derive_more = "0.99.9" -mime = "0.3.16" -thiserror = "1.0.20" -once_cell = "1.5.0" -takecell = "0.1" -take_mut = "0.2" -rc-box = "1.1.1" -never = "0.1.0" -chrono = { version = "0.4.19", default-features = false } -either = "1.6.1" -bitflags = { version = "1.2" } - -vecrem = { version = "0.1", optional = true } - -[dev-dependencies] -pretty_env_logger = "0.4" -tokio = { version = "1.8.0", features = ["fs", "macros", "macros", "rt-multi-thread"] } -cool_asserts = "2.0.3" - -xshell = "0.2" -ron = "0.7" -indexmap = { version = "1.9", features = ["serde-1"] } -aho-corasick = "0.7" -itertools = "0.10" [features] default = ["native-tls"] @@ -90,6 +46,49 @@ auto_send = [] # All features except nightly and tls-related full = ["throttle", "trace_adaptor", "erased", "cache_me", "auto_send"] + +[dependencies] +futures = "0.3.5" +tokio = { version = "1.12.0", features = ["fs"] } +tokio-util = { version = "0.7.0", features = ["codec"] } +pin-project = "1.0.12" +bytes = "1.0.0" +reqwest = { version = "0.11.10", features = ["json", "stream", "multipart"], default-features = false } +url = { version = "2", features = ["serde"] } +log = "0.4" + +serde = { version = "1.0.114", features = ["derive"] } +serde_json = "1.0.55" +serde_with_macros = "1.5.2" +uuid = { version = "1.1.0", features = ["v4"] } # for attaching input files + +derive_more = "0.99.9" +mime = "0.3.16" +thiserror = "1.0.20" +once_cell = "1.5.0" +takecell = "0.1" +take_mut = "0.2" +rc-box = "1.1.1" +never = "0.1.0" +chrono = { version = "0.4.19", default-features = false } +either = "1.6.1" +bitflags = { version = "1.2" } + +vecrem = { version = "0.1", optional = true } + + +[dev-dependencies] +pretty_env_logger = "0.4" +tokio = { version = "1.8.0", features = ["fs", "macros", "macros", "rt-multi-thread"] } +cool_asserts = "2.0.3" + +xshell = "0.2" +ron = "0.7" +indexmap = { version = "1.9", features = ["serde-1"] } +aho-corasick = "0.7" +itertools = "0.10" + + [package.metadata.docs.rs] features = ["full", "nightly", "tokio/macros", "tokio/rt-multi-thread"] rustdoc-args = ["--cfg", "docsrs", "-Znormalize-docs"] @@ -97,6 +96,7 @@ rustdoc-args = ["--cfg", "docsrs", "-Znormalize-docs"] # https://github.com/rust-lang/rust/issues/88791 cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples=examples"] + [[example]] name = "self_info" required-features = ["tokio/macros", "tokio/rt-multi-thread"] diff --git a/crates/teloxide-core/src/requests/requester.rs b/crates/teloxide-core/src/requests/requester.rs index 3fc819bb..f4a29663 100644 --- a/crates/teloxide-core/src/requests/requester.rs +++ b/crates/teloxide-core/src/requests/requester.rs @@ -90,8 +90,8 @@ use crate::{ /// /// Because of this it's oftentimes more convinient to have a type alias: /// -/// ```rust -/// # async { +/// ```rust,no_run +/// # #[cfg(feature = "throttle")] { /// # use teloxide_core::{adaptors::{DefaultParseMode, Throttle}, requests::RequesterExt, types::ParseMode}; /// type Bot = DefaultParseMode>; /// diff --git a/crates/teloxide-macros/Cargo.toml b/crates/teloxide-macros/Cargo.toml index c6ea1d39..7f18287b 100644 --- a/crates/teloxide-macros/Cargo.toml +++ b/crates/teloxide-macros/Cargo.toml @@ -2,14 +2,22 @@ name = "teloxide-macros" version = "0.7.0" description = "The teloxide's procedural macros" -license = "MIT" -edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +rust-version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +documentation = "https://docs.rs/teloxide-core/" +# FIXME: add a simple readme for teloxide-macros +#readme = "README.md" + [lib] proc-macro = true + [dependencies] quote = "1.0.7" proc-macro2 = "1.0.19" diff --git a/crates/teloxide/Cargo.toml b/crates/teloxide/Cargo.toml index 455f13a9..760b14ad 100644 --- a/crates/teloxide/Cargo.toml +++ b/crates/teloxide/Cargo.toml @@ -1,15 +1,20 @@ [package] name = "teloxide" -version = "0.11.1" -edition = "2021" +version = "0.11.3" description = "An elegant Telegram bots framework for Rust" -repository = "https://github.com/teloxide/teloxide" + +rust-version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + documentation = "https://docs.rs/teloxide/" readme = "../../README.md" -keywords = ["teloxide", "telegram", "telegram-bot", "telegram-bot-api"] + +keywords = ["teloxide", "telegram", "telegram-bot", "telegram-bot-api", "bot", "TBA"] categories = ["web-programming", "api-bindings", "asynchronous"] -license = "MIT" -exclude = ["media", "README.md"] + [features] default = ["native-tls", "ctrlc_handler", "teloxide-core/default", "auto-send"] @@ -56,6 +61,7 @@ full = [ "erased", ] + [dependencies] teloxide-core = { version = "0.8.0", default-features = false } teloxide-macros = { version = "0.7.0", optional = true } @@ -94,11 +100,12 @@ sqlx = { version = "0.6", optional = true, default-features = false, features = redis = { version = "0.21", features = ["tokio-comp"], optional = true } serde_cbor = { version = "0.11", optional = true } bincode = { version = "1.3", optional = true } -axum = { version = "0.5.13", optional = true } +axum = { version = "0.6.0", optional = true } tower = { version = "0.4.12", optional = true } tower-http = { version = "0.3.4", features = ["trace"], optional = true } rand = { version = "0.8.5", optional = true } + [dev-dependencies] rand = "0.8.3" pretty_env_logger = "0.4.0" @@ -109,6 +116,7 @@ reqwest = "0.11.11" chrono = "0.4" tokio-stream = "0.1" + [package.metadata.docs.rs] all-features = true # FIXME: Add back "-Znormalize-docs" when https://github.com/rust-lang/rust/issues/93703 is fixed @@ -116,6 +124,7 @@ rustdoc-args = ["--cfg", "docsrs"] rustc-args = ["--cfg", "dep_docsrs"] cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples=examples"] + [[test]] name = "redis" path = "tests/redis.rs" @@ -126,42 +135,51 @@ name = "sqlite" path = "tests/sqlite.rs" required-features = ["sqlite-storage", "cbor-serializer", "bincode-serializer"] + [[example]] -name = "dialogue" -required-features = ["macros"] +name = "admin" +required-features = ["macros", "ctrlc_handler"] + +[[example]] +name = "buttons" +required-features = ["macros", "ctrlc_handler"] [[example]] name = "command" -required-features = ["macros"] +required-features = ["macros", "ctrlc_handler"] [[example]] name = "db_remember" required-features = ["sqlite-storage", "redis-storage", "bincode-serializer", "macros"] [[example]] -name = "inline" -required-features = ["macros"] - -[[example]] -name = "buttons" -required-features = ["macros"] - -[[example]] -name = "admin" -required-features = ["macros"] +name = "dialogue" +required-features = ["macros", "ctrlc_handler"] [[example]] name = "dispatching_features" -required-features = ["macros"] - -[[example]] -name = "ngrok_ping_pong" -required-features = ["webhooks-axum"] +required-features = ["macros", "ctrlc_handler"] [[example]] name = "heroku_ping_pong" -required-features = ["webhooks-axum"] +required-features = ["webhooks-axum", "ctrlc_handler"] + +[[example]] +name = "inline" +required-features = ["macros", "ctrlc_handler"] + +[[example]] +name = "ngrok_ping_pong" +required-features = ["webhooks-axum", "ctrlc_handler"] [[example]] name = "purchase" -required-features = ["macros"] +required-features = ["macros", "ctrlc_handler"] + +[[example]] +name = "shared_state" +required-features = ["ctrlc_handler"] + +[[example]] +name = "throw_dice" +required-features = ["ctrlc_handler"] diff --git a/crates/teloxide/src/dispatching.rs b/crates/teloxide/src/dispatching.rs index e65eca20..3d64ef8e 100644 --- a/crates/teloxide/src/dispatching.rs +++ b/crates/teloxide/src/dispatching.rs @@ -1,6 +1,6 @@ //! An update dispatching model based on [`dptree`]. //! -//! In teloxide, update dispatching is declarative: it takes the form of a +//! In `teloxide`, update dispatching is declarative: it takes the form of a //! [chain of responsibility] pattern enriched with a number of combinator //! functions, which together form an instance of the [`dptree::Handler`] type. //! @@ -23,6 +23,7 @@ //! `/start` or `/help`: //! //! ```no_run +//! # #[cfg(feature = "macros")] { //! # use teloxide::utils::command::BotCommands; //! #[derive(BotCommands, Clone)] //! #[command(rename_rule = "lowercase", description = "These commands are supported:")] @@ -34,6 +35,7 @@ //! #[command(description = "cancel the purchase procedure.")] //! Cancel, //! } +//! # } //! ``` //! //! Now the key question: how to elegantly dispatch on different combinations of @@ -43,6 +45,7 @@ //! solution is to use [`dptree`]: //! //! ```no_run +//! # #[cfg(feature = "macros")] { //! # // That's a lot of context needed to compile this, oof //! # use teloxide::dispatching::{UpdateHandler, UpdateFilterExt, dialogue, dialogue::InMemStorage}; //! # use teloxide::utils::command::BotCommands; @@ -81,6 +84,7 @@ //! .branch(message_handler) //! .branch(callback_query_handler) //! } +//! # } //! ``` //! //! The overall logic should be clear. Throughout the above example, we use @@ -149,6 +153,7 @@ //! Inside `main`, we plug the schema into [`Dispatcher`] like this: //! //! ```no_run +//! # #[cfg(feature = "ctrlc_handler")] { //! # use teloxide::Bot; //! # use teloxide::requests::RequesterExt; //! # use teloxide::dispatching::{Dispatcher, dialogue::InMemStorage}; @@ -165,6 +170,7 @@ //! .dispatch() //! .await; //! } +//! # } //! ``` //! //! In a call to [`DispatcherBuilder::dependencies`], we specify a list of diff --git a/crates/teloxide/src/dispatching/dispatcher.rs b/crates/teloxide/src/dispatching/dispatcher.rs index 1d062c85..954a6ecd 100644 --- a/crates/teloxide/src/dispatching/dispatcher.rs +++ b/crates/teloxide/src/dispatching/dispatcher.rs @@ -146,6 +146,9 @@ where ctrlc_handler, } = self; + // If the `ctrlc_handler` feature is not enabled, don't emit a warning. + let _ = ctrlc_handler; + let dp = Dispatcher { bot, dependencies, diff --git a/crates/teloxide/src/dispatching/handler_description.rs b/crates/teloxide/src/dispatching/handler_description.rs index 92bbda38..55b4146d 100644 --- a/crates/teloxide/src/dispatching/handler_description.rs +++ b/crates/teloxide/src/dispatching/handler_description.rs @@ -77,14 +77,15 @@ impl EventKind for Kind { #[cfg(test)] mod tests { + #[cfg(feature = "macros")] use crate::{ + self as teloxide, // fixup for the `BotCommands` macro dispatching::{HandlerExt, UpdateFilterExt}, types::{AllowedUpdate::*, Update}, utils::command::BotCommands, }; - use crate as teloxide; // fixup for the `BotCommands` macro - + #[cfg(feature = "macros")] #[derive(BotCommands, Clone)] #[command(rename_rule = "lowercase")] enum Cmd { @@ -93,6 +94,7 @@ mod tests { // #[test] + #[cfg(feature = "macros")] fn discussion_648() { let h = dptree::entry().branch(Update::filter_my_chat_member().endpoint(|| async {})).branch( @@ -108,4 +110,11 @@ mod tests { assert_eq!(v, [Message, MyChatMember]) } + + #[test] + #[ignore = "this test requires `macros` feature"] + #[cfg(not(feature = "macros"))] + fn discussion_648() { + panic!("this test requires `macros` feature") + } } diff --git a/crates/teloxide/src/dispatching/update_listeners/webhooks/axum.rs b/crates/teloxide/src/dispatching/update_listeners/webhooks/axum.rs index 7bbe03ba..45cb5e79 100644 --- a/crates/teloxide/src/dispatching/update_listeners/webhooks/axum.rs +++ b/crates/teloxide/src/dispatching/update_listeners/webhooks/axum.rs @@ -1,14 +1,16 @@ use std::{convert::Infallible, future::Future, pin::Pin}; use axum::{ - extract::{FromRequest, RequestParts}, - http::status::StatusCode, + extract::{FromRequestParts, State}, + http::{request::Parts, status::StatusCode}, }; +use tokio::sync::mpsc; use crate::{ dispatching::update_listeners::{webhooks::Options, UpdateListener}, requests::Requester, stop::StopFlag, + types::Update, }; /// Webhook implementation based on the [mod@axum] framework. @@ -156,25 +158,17 @@ pub fn axum_no_setup( use crate::{ dispatching::update_listeners::{self, webhooks::tuple_first_mut}, stop::{mk_stop_token, StopToken}, - types::Update, }; - use axum::{extract::Extension, response::IntoResponse, routing::post}; - use tokio::sync::mpsc; + use axum::{response::IntoResponse, routing::post}; use tokio_stream::wrappers::UnboundedReceiverStream; - use tower::ServiceBuilder; use tower_http::trace::TraceLayer; - type Sender = mpsc::UnboundedSender>; - type CSender = ClosableSender>; - - let (tx, rx): (Sender, _) = mpsc::unbounded_channel(); + let (tx, rx): (UpdateSender, _) = mpsc::unbounded_channel(); async fn telegram_request( - input: String, + State(WebhookState { secret, flag, mut tx }): State, secret_header: XTelegramBotApiSecretToken, - secret: Extension>, - tx: Extension, - flag: Extension, + input: String, ) -> impl IntoResponse { // FIXME: use constant time comparison here if secret_header.0.as_deref() != secret.as_deref().map(str::as_bytes) { @@ -186,7 +180,7 @@ pub fn axum_no_setup( // Do not process updates after `.stop()` is called even if the server is still // running (useful for when you need to stop the bot but can't stop the server). _ if flag.is_stopped() => { - { tx.0 }.close(); + tx.close(); return StatusCode::SERVICE_UNAVAILABLE; } Some(tx) => tx, @@ -212,14 +206,14 @@ pub fn axum_no_setup( let (stop_token, stop_flag) = mk_stop_token(); - let app = axum::Router::new().route(options.url.path(), post(telegram_request)).layer( - ServiceBuilder::new() - .layer(TraceLayer::new_for_http()) - .layer(Extension(ClosableSender::new(tx))) - .layer(Extension(stop_flag.clone())) - .layer(Extension(options.secret_token)) - .into_inner(), - ); + let app = axum::Router::new() + .route(options.url.path(), post(telegram_request)) + .layer(TraceLayer::new_for_http()) + .with_state(WebhookState { + tx: ClosableSender::new(tx), + flag: stop_flag.clone(), + secret: options.secret_token, + }); let stream = UnboundedReceiverStream::new(rx); @@ -233,9 +227,19 @@ pub fn axum_no_setup( (listener, stop_flag, app) } +type UpdateSender = mpsc::UnboundedSender>; +type UpdateCSender = ClosableSender>; + +#[derive(Clone)] +struct WebhookState { + tx: UpdateCSender, + flag: StopFlag, + secret: Option, +} + /// A terrible workaround to drop axum extension struct ClosableSender { - origin: std::sync::Arc>>>, + origin: std::sync::Arc>>>, } impl Clone for ClosableSender { @@ -245,11 +249,11 @@ impl Clone for ClosableSender { } impl ClosableSender { - fn new(sender: tokio::sync::mpsc::UnboundedSender) -> Self { + fn new(sender: mpsc::UnboundedSender) -> Self { Self { origin: std::sync::Arc::new(std::sync::RwLock::new(Some(sender))) } } - fn get(&self) -> Option> { + fn get(&self) -> Option> { self.origin.read().unwrap().clone() } @@ -260,20 +264,22 @@ impl ClosableSender { struct XTelegramBotApiSecretToken(Option>); -impl FromRequest for XTelegramBotApiSecretToken { +impl FromRequestParts for XTelegramBotApiSecretToken { type Rejection = StatusCode; - fn from_request<'l0, 'at>( - req: &'l0 mut RequestParts, + fn from_request_parts<'l0, 'l1, 'at>( + req: &'l0 mut Parts, + _state: &'l1 S, ) -> Pin> + Send + 'at>> where 'l0: 'at, + 'l1: 'at, Self: 'at, { use crate::dispatching::update_listeners::webhooks::check_secret; let res = req - .headers_mut() + .headers .remove("x-telegram-bot-api-secret-token") .map(|header| { check_secret(header.as_bytes()) diff --git a/crates/teloxide/src/lib.rs b/crates/teloxide/src/lib.rs index afb01109..77a67781 100644 --- a/crates/teloxide/src/lib.rs +++ b/crates/teloxide/src/lib.rs @@ -6,8 +6,10 @@ //! //! [[`examples/throw_dice.rs`](https://github.com/teloxide/teloxide/blob/master/examples/throw_dice.rs)] //! ```no_run +//! # #[cfg(feature = "ctrlc_handler")] //! use teloxide::prelude::*; //! +//! # #[cfg(feature = "ctrlc_handler")] //! # #[tokio::main] //! # async fn main() { //! pretty_env_logger::init(); @@ -20,7 +22,7 @@ //! Ok(()) //! }) //! .await; -//! # } +//! # } #[cfg(not(feature = "ctrlc_handler"))] fn main(){} //! ``` //! //!
@@ -60,6 +62,7 @@ #[cfg(feature = "ctrlc_handler")] pub use dispatching::repls::{repl, repl_with_listener}; +#[cfg(feature = "ctrlc_handler")] #[allow(deprecated)] pub use dispatching::repls::{commands_repl, commands_repl_with_listener}; diff --git a/crates/teloxide/src/prelude.rs b/crates/teloxide/src/prelude.rs index ca6afa90..27336320 100644 --- a/crates/teloxide/src/prelude.rs +++ b/crates/teloxide/src/prelude.rs @@ -6,10 +6,12 @@ pub use crate::error_handlers::{LoggingErrorHandler, OnError}; pub use crate::respond; pub use crate::dispatching::{ - dialogue::Dialogue, repls::CommandReplExt as _, Dispatcher, HandlerExt as _, - MessageFilterExt as _, UpdateFilterExt as _, + dialogue::Dialogue, Dispatcher, HandlerExt as _, MessageFilterExt as _, UpdateFilterExt as _, }; +#[cfg(feature = "ctrlc_handler")] +pub use crate::dispatching::repls::CommandReplExt as _; + pub use teloxide_core::{ requests::ResponseResult, types::{