diff --git a/crates/teloxide-core/src/types/message.rs b/crates/teloxide-core/src/types/message.rs index 93411078..36fec591 100644 --- a/crates/teloxide-core/src/types/message.rs +++ b/crates/teloxide-core/src/types/message.rs @@ -1826,6 +1826,14 @@ impl IntoIterator for Message { } } +/// Implemented for syntax sugar, see issue +#[allow(clippy::from_over_into)] +impl Into for Message { + fn into(self) -> MessageId { + self.id + } +} + #[cfg(test)] mod tests { use chrono::DateTime; diff --git a/crates/teloxide/src/sugar/bot.rs b/crates/teloxide/src/sugar/bot.rs index 1d69380d..4c8781a2 100644 --- a/crates/teloxide/src/sugar/bot.rs +++ b/crates/teloxide/src/sugar/bot.rs @@ -2,15 +2,19 @@ //! //! [`Bot`]: crate::Bot use crate::{prelude::*, types::*}; +use teloxide_core::{payloads::*, requests::JsonRequest}; use std::collections::HashSet; +/// Adds useful manipulations with [`Message`] structs +/// +/// [`Message`]: crate::types::Message pub trait BotMessagesExt { /// This function is the same as [`Bot::forward_messages`], /// but can take in [`Message`], including just one. /// /// [`Bot::forward_messages`]: crate::Bot::forward_messages /// [`Message`]: crate::types::Message - fn forward(&self, to_chat_id: C, messages: M) -> ::ForwardMessages + fn forward(&self, to_chat_id: C, messages: M) -> JsonRequest where C: Into, M: IntoIterator; @@ -20,7 +24,7 @@ pub trait BotMessagesExt { /// /// [`Bot::copy_messages`]: crate::Bot::copy_messages /// [`Message`]: crate::types::Message - fn copy(&self, to_chat_id: C, messages: M) -> ::CopyMessages + fn copy(&self, to_chat_id: C, messages: M) -> JsonRequest where C: Into, M: IntoIterator; @@ -30,7 +34,7 @@ pub trait BotMessagesExt { /// /// [`Bot::delete_messages`]: crate::Bot::delete_messages /// [`Message`]: crate::types::Message - fn delete(&self, messages: M) -> ::DeleteMessages + fn delete(&self, messages: M) -> JsonRequest where M: IntoIterator; } @@ -58,7 +62,7 @@ where } impl BotMessagesExt for Bot { - fn forward(&self, to_chat_id: C, messages: M) -> ::ForwardMessages + fn forward(&self, to_chat_id: C, messages: M) -> JsonRequest where C: Into, M: IntoIterator, @@ -67,7 +71,7 @@ impl BotMessagesExt for Bot { self.forward_messages(to_chat_id, from_chat_id, message_ids) } - fn copy(&self, to_chat_id: C, messages: M) -> ::CopyMessages + fn copy(&self, to_chat_id: C, messages: M) -> JsonRequest where C: Into, M: IntoIterator, @@ -76,7 +80,7 @@ impl BotMessagesExt for Bot { self.copy_messages(to_chat_id, from_chat_id, message_ids) } - fn delete(&self, messages: M) -> ::DeleteMessages + fn delete(&self, messages: M) -> JsonRequest where M: IntoIterator, { @@ -86,14 +90,14 @@ impl BotMessagesExt for Bot { } #[cfg(test)] -mod tests { +pub(crate) mod tests { use std::ops::Deref; use chrono::DateTime; use super::*; - fn make_message(chat_id: ChatId, message_id: MessageId) -> Message { + pub(crate) fn make_message(chat_id: ChatId, message_id: MessageId) -> Message { let timestamp = 1_569_518_829; let date = DateTime::from_timestamp(timestamp, 0).unwrap(); Message { @@ -241,4 +245,12 @@ mod tests { let message = make_message(ChatId(1), MessageId(1)); assert_eq!(message.clone().into_iter().next(), Some(message)); } + + #[test] + fn message_to_message_id() { + // Just to make sure message still can be in Into + let message = make_message(ChatId(1), MessageId(1)); + let message_id: MessageId = message.into(); + assert_eq!(message_id, MessageId(1)); + } } diff --git a/crates/teloxide/src/sugar/request.rs b/crates/teloxide/src/sugar/request.rs index dc31ae50..6c2d4f3d 100644 --- a/crates/teloxide/src/sugar/request.rs +++ b/crates/teloxide/src/sugar/request.rs @@ -1,8 +1,13 @@ -//! Additions to [`JsonRequest`]. +//! Additions to [`JsonRequest`] and [`MultipartRequest`]. //! //! [`JsonRequest`]: teloxide_core::requests::JsonRequest +//! [`MultipartRequest`]: teloxide_core::requests::MultipartRequest -use teloxide_core::{payloads::*, prelude::Requester, types::*, Bot}; +use teloxide_core::{ + payloads::*, + requests::{JsonRequest, MultipartRequest}, + types::*, +}; macro_rules! impl_request_reply_ext { ($($t:ty),*) => { @@ -24,12 +29,12 @@ macro_rules! impl_request_link_preview_ext { ($($t:ty),*) => { $( impl RequestLinkPreviewExt for $t { - fn disable_link_preview(self) -> Self + fn disable_link_preview(self, is_disabled: bool) -> Self where Self: Sized { let link_preview_options = LinkPreviewOptions { - is_disabled: true, + is_disabled, url: None, prefer_small_media: false, prefer_large_media: false, @@ -42,25 +47,57 @@ macro_rules! impl_request_link_preview_ext { }; } +/// Adds `.reply_to(message_id)` to requests pub trait RequestReplyExt { + /// Replaces `.reply_parameters(ReplyParameters::new(msg.id))` + /// with `.reply_to(msg.id)` or `.reply_to(msg)` fn reply_to(self, message_id: M) -> Self where M: Into, Self: Sized; } +/// Adds `.disable_link_preview(is_disabled)` to requests pub trait RequestLinkPreviewExt { - fn disable_link_preview(self) -> Self + /// Replaces + /// `.link_preview_options(LinkPreviewOptions { + /// is_disabled: true, + /// url: None, + /// prefer_small_media: false, + /// prefer_large_media: false, + /// show_above_text: false + /// };)` + /// + /// With `.disable_link_preview(true)` + fn disable_link_preview(self, is_disabled: bool) -> Self where Self: Sized; } impl_request_reply_ext! { - ::SendMessage + JsonRequest, + JsonRequest, + JsonRequest, + JsonRequest, + JsonRequest, + JsonRequest, + JsonRequest, + JsonRequest, + JsonRequest, + MultipartRequest, + MultipartRequest, + MultipartRequest, + MultipartRequest, + MultipartRequest, + MultipartRequest, + MultipartRequest, + MultipartRequest, + MultipartRequest } impl_request_link_preview_ext! { - ::SendMessage + JsonRequest, + JsonRequest } #[cfg(test)] @@ -73,6 +110,7 @@ mod tests { #[test] fn test_reply_to() { let bot = Bot::new("TOKEN"); + let real_reply_req = bot .send_message(ChatId(1234), "test") .reply_parameters(ReplyParameters::new(MessageId(1))); @@ -81,6 +119,22 @@ mod tests { assert_eq!(real_reply_req.deref(), sugar_reply_req.deref()) } + #[test] + fn test_reply_to_multipart() { + let bot = Bot::new("TOKEN"); + let document = InputFile::memory("hello world!"); + + let real_reply_req = bot + .send_document(ChatId(1234), document.clone()) + .reply_parameters(ReplyParameters::new(MessageId(1))); + let sugar_reply_req = bot.send_document(ChatId(1234), document).reply_to(MessageId(1)); + + assert_eq!( + real_reply_req.deref().reply_parameters, + sugar_reply_req.deref().reply_parameters + ) + } + #[test] fn test_disable_link_preview() { let link_preview_options = LinkPreviewOptions { @@ -91,9 +145,10 @@ mod tests { show_above_text: false, }; let bot = Bot::new("TOKEN"); + let real_link_req = bot.send_message(ChatId(1234), "test").link_preview_options(link_preview_options); - let sugar_link_req = bot.send_message(ChatId(1234), "test").disable_link_preview(); + let sugar_link_req = bot.send_message(ChatId(1234), "test").disable_link_preview(true); assert_eq!(real_link_req.deref(), sugar_link_req.deref()) }