mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-22 14:35:36 +01:00
Merge pull request #1162 from LasterAlex/add-syntactic-sugar
Added syntactic sugar
This commit is contained in:
commit
cfedb585d3
8 changed files with 373 additions and 14 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -8,13 +8,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Add `filter_boost_added` and `filter_reply_to_story` filters to `MessageFilterExt` trait
|
- `filter_boost_added` and `filter_reply_to_story` filters to the `MessageFilterExt` trait ([PR 1131](https://github.com/teloxide/teloxide/pull/1131))
|
||||||
- Add `filter_mention_command` filter to `HandlerExt` trait ([issue #494](https://github.com/teloxide/teloxide/issues/494))
|
- `filter_mention_command` filter to the `HandlerExt` trait ([issue 494](https://github.com/teloxide/teloxide/issues/494))
|
||||||
- Add `filter_business_connection`, `filter_business_message`, `filter_edited_business_message`, and `filter_deleted_business_messages` filters to update filters ([PR 1146](https://github.com/teloxide/teloxide/pull/1146))
|
- `filter_business_connection`, `filter_business_message`, `filter_edited_business_message`, and `filter_deleted_business_messages` filters to the `UpdateFilterExt` trait ([PR 1146](https://github.com/teloxide/teloxide/pull/1146))
|
||||||
|
- Syntax sugar for making requests ([issue 1143](https://github.com/teloxide/teloxide/issues/1143)):
|
||||||
|
- `bot.forward`, `bot.edit_live_location`, `bot.stop_live_location`, `bot.set_reaction`, `bot.pin`, `bot.unpin`, `bot.edit_text`, `bot.edit_caption`, `bot.edit_media`, `bot.edit_reply_markup`, `bot.stop_poll_message`, `bot.delete` and `bot.copy` methods to the new `crate::sugar::bot::BotMessagesExt` trait
|
||||||
|
- `req.reply_to` method to the new `crate::sugar::request::RequestReplyExt` trait
|
||||||
|
- `req.disable_link_preview` method to the new `crate::sugar::request::RequestLinkPreviewExt` trait
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Environment bumps: ([#1147][pr1147])
|
- Environment bumps: ([PR 1147](https://github.com/teloxide/teloxide/pull/1147))
|
||||||
- MSRV (Minimal Supported Rust Version) was bumped from `1.70.0` to `1.80.0`
|
- MSRV (Minimal Supported Rust Version) was bumped from `1.70.0` to `1.80.0`
|
||||||
- Some dependencies was bumped: `sqlx` to `0.8.1`, `tower` to `0.5.0`, `reqwest` to `0.12.7`
|
- Some dependencies was bumped: `sqlx` to `0.8.1`, `tower` to `0.5.0`, `reqwest` to `0.12.7`
|
||||||
- `tokio` version was explicitly specified as `1.39`
|
- `tokio` version was explicitly specified as `1.39`
|
||||||
|
@ -23,8 +27,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
- Now Vec<MessageId> in requests serializes into [number] instead of [ {message_id: number} ], `forward_messages`, `copy_messages` and `delete_messages` now work properly
|
- Now Vec<MessageId> in requests serializes into [number] instead of [ {message_id: number} ], `forward_messages`, `copy_messages` and `delete_messages` now work properly
|
||||||
|
|
||||||
[pr1147]: https://github.com/teloxide/teloxide/pull/1147
|
|
||||||
|
|
||||||
## 0.13.0 - 2024-08-16
|
## 0.13.0 - 2024-08-16
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -1816,6 +1816,13 @@ impl Message {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implemented for syntax sugar, see issue <https://github.com/teloxide/teloxide/issues/1143>
|
||||||
|
impl From<Message> for MessageId {
|
||||||
|
fn from(message: Message) -> MessageId {
|
||||||
|
message.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::error::Error;
|
||||||
use teloxide::{
|
use teloxide::{
|
||||||
payloads::SendMessageSetters,
|
payloads::SendMessageSetters,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
sugar::bot::BotMessagesExt,
|
||||||
types::{
|
types::{
|
||||||
InlineKeyboardButton, InlineKeyboardMarkup, InlineQueryResultArticle, InputMessageContent,
|
InlineKeyboardButton, InlineKeyboardMarkup, InlineQueryResultArticle, InputMessageContent,
|
||||||
InputMessageContentText, Me,
|
InputMessageContentText, Me,
|
||||||
|
@ -107,17 +108,17 @@ async fn inline_query_handler(
|
||||||
/// **IMPORTANT**: do not send privacy-sensitive data this way!!!
|
/// **IMPORTANT**: do not send privacy-sensitive data this way!!!
|
||||||
/// Anyone can read data stored in the callback button.
|
/// Anyone can read data stored in the callback button.
|
||||||
async fn callback_handler(bot: Bot, q: CallbackQuery) -> Result<(), Box<dyn Error + Send + Sync>> {
|
async fn callback_handler(bot: Bot, q: CallbackQuery) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
if let Some(version) = q.data {
|
if let Some(ref version) = q.data {
|
||||||
let text = format!("You chose: {version}");
|
let text = format!("You chose: {version}");
|
||||||
|
|
||||||
// Tell telegram that we've seen this query, to remove 🕑 icons from the
|
// Tell telegram that we've seen this query, to remove 🕑 icons from the
|
||||||
// clients. You could also use `answer_callback_query`'s optional
|
// clients. You could also use `answer_callback_query`'s optional
|
||||||
// parameters to tweak what happens on the client side.
|
// parameters to tweak what happens on the client side.
|
||||||
bot.answer_callback_query(q.id).await?;
|
bot.answer_callback_query(&q.id).await?;
|
||||||
|
|
||||||
// Edit text of the message to which the buttons were attached
|
// Edit text of the message to which the buttons were attached
|
||||||
if let Some(message) = q.message {
|
if let Some(message) = q.regular_message() {
|
||||||
bot.edit_message_text(message.chat().id, message.id(), text).await?;
|
bot.edit_text(message, text).await?;
|
||||||
} else if let Some(id) = q.inline_message_id {
|
} else if let Some(id) = q.inline_message_id {
|
||||||
bot.edit_message_text_inline(id, text).await?;
|
bot.edit_message_text_inline(id, text).await?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,7 @@
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use teloxide::{
|
use teloxide::{
|
||||||
dispatching::HandlerExt,
|
dispatching::HandlerExt, prelude::*, sugar::request::RequestReplyExt, types::Dice,
|
||||||
prelude::*,
|
|
||||||
types::{Dice, ReplyParameters},
|
|
||||||
utils::command::BotCommands,
|
utils::command::BotCommands,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,7 +82,7 @@ async fn main() {
|
||||||
// filter only messages with dices.
|
// filter only messages with dices.
|
||||||
Message::filter_dice().endpoint(|bot: Bot, msg: Message, dice: Dice| async move {
|
Message::filter_dice().endpoint(|bot: Bot, msg: Message, dice: Dice| async move {
|
||||||
bot.send_message(msg.chat.id, format!("Dice value: {}", dice.value))
|
bot.send_message(msg.chat.id, format!("Dice value: {}", dice.value))
|
||||||
.reply_parameters(ReplyParameters::new(msg.id))
|
.reply_to(msg)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -140,6 +140,7 @@ pub mod prelude;
|
||||||
#[cfg(feature = "ctrlc_handler")]
|
#[cfg(feature = "ctrlc_handler")]
|
||||||
pub mod repls;
|
pub mod repls;
|
||||||
pub mod stop;
|
pub mod stop;
|
||||||
|
pub mod sugar;
|
||||||
pub mod update_listeners;
|
pub mod update_listeners;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
|
|
4
crates/teloxide/src/sugar.rs
Normal file
4
crates/teloxide/src/sugar.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
//! Some syntax sugar support for TBA functionality.
|
||||||
|
|
||||||
|
pub mod bot;
|
||||||
|
pub mod request;
|
191
crates/teloxide/src/sugar/bot.rs
Normal file
191
crates/teloxide/src/sugar/bot.rs
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
//! Additions to [`Bot`].
|
||||||
|
//!
|
||||||
|
//! [`Bot`]: crate::Bot
|
||||||
|
use crate::{prelude::*, types::*};
|
||||||
|
use teloxide_core::{
|
||||||
|
payloads::*,
|
||||||
|
requests::{JsonRequest, MultipartRequest},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Syntax sugar for [`Message`] manipulations.
|
||||||
|
///
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
pub trait BotMessagesExt {
|
||||||
|
/// This function is the same as [`Bot::forward_message`],
|
||||||
|
/// but can take in [`Message`] to forward it.
|
||||||
|
///
|
||||||
|
/// [`Bot::forward_message`]: crate::Bot::forward_message
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn forward<C>(&self, to_chat_id: C, message: &Message) -> JsonRequest<ForwardMessage>
|
||||||
|
where
|
||||||
|
C: Into<Recipient>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::edit_message_live_location`],
|
||||||
|
/// but can take in [`Message`] to edit it.
|
||||||
|
///
|
||||||
|
/// [`Bot::edit_message_live_location`]: crate::Bot::edit_message_live_location
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn edit_live_location(
|
||||||
|
&self,
|
||||||
|
message: &Message,
|
||||||
|
latitude: f64,
|
||||||
|
longitude: f64,
|
||||||
|
) -> JsonRequest<EditMessageLiveLocation>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::stop_message_live_location`],
|
||||||
|
/// but can take in [`Message`] to stop the live location in it.
|
||||||
|
///
|
||||||
|
/// [`Bot::stop_message_live_location`]: crate::Bot::stop_message_live_location
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn stop_live_location(&self, message: &Message) -> JsonRequest<StopMessageLiveLocation>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::set_message_reaction`],
|
||||||
|
/// but can take in [`Message`] to set a reaction on it.
|
||||||
|
///
|
||||||
|
/// [`Bot::set_message_reaction`]: crate::Bot::set_message_reaction
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn set_reaction(&self, message: &Message) -> JsonRequest<SetMessageReaction>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::pin_chat_message`],
|
||||||
|
/// but can take in [`Message`] to pin it.
|
||||||
|
///
|
||||||
|
/// [`Bot::pin_chat_message`]: crate::Bot::pin_chat_message
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn pin(&self, message: &Message) -> JsonRequest<PinChatMessage>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::unpin_chat_message`],
|
||||||
|
/// but can take in [`Message`] to unpin it.
|
||||||
|
///
|
||||||
|
/// [`Bot::unpin_chat_message`]: crate::Bot::unpin_chat_message
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn unpin(&self, message: &Message) -> JsonRequest<UnpinChatMessage>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::edit_message_text`],
|
||||||
|
/// but can take in [`Message`] to edit it.
|
||||||
|
///
|
||||||
|
/// [`Bot::edit_message_text`]: crate::Bot::edit_message_text
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn edit_text<T>(&self, message: &Message, text: T) -> JsonRequest<EditMessageText>
|
||||||
|
where
|
||||||
|
T: Into<String>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::edit_message_caption`],
|
||||||
|
/// but can take in [`Message`] to edit it.
|
||||||
|
///
|
||||||
|
/// [`Bot::edit_message_caption`]: crate::Bot::edit_message_caption
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn edit_caption(&self, message: &Message) -> JsonRequest<EditMessageCaption>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::edit_message_media`],
|
||||||
|
/// but can take in [`Message`] to edit it.
|
||||||
|
///
|
||||||
|
/// [`Bot::edit_message_media`]: crate::Bot::edit_message_media
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn edit_media(
|
||||||
|
&self,
|
||||||
|
message: &Message,
|
||||||
|
media: InputMedia,
|
||||||
|
) -> MultipartRequest<EditMessageMedia>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::edit_message_reply_markup`],
|
||||||
|
/// but can take in [`Message`] to edit it.
|
||||||
|
///
|
||||||
|
/// [`Bot::edit_message_reply_markup`]: crate::Bot::edit_message_reply_markup
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn edit_reply_markup(&self, message: &Message) -> JsonRequest<EditMessageReplyMarkup>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::stop_poll`],
|
||||||
|
/// but can take in [`Message`] to stop the poll in it.
|
||||||
|
///
|
||||||
|
/// [`Bot::stop_poll`]: crate::Bot::stop_poll
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn stop_poll_message(&self, message: &Message) -> JsonRequest<StopPoll>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::delete_message`],
|
||||||
|
/// but can take in [`Message`] to delete it.
|
||||||
|
///
|
||||||
|
/// [`Bot::delete_message`]: crate::Bot::delete_message
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn delete(&self, message: &Message) -> JsonRequest<DeleteMessage>;
|
||||||
|
|
||||||
|
/// This function is the same as [`Bot::copy_message`],
|
||||||
|
/// but can take in [`Message`] to copy it.
|
||||||
|
///
|
||||||
|
/// [`Bot::copy_messages`]: crate::Bot::copy_message
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
fn copy<C>(&self, to_chat_id: C, message: &Message) -> JsonRequest<CopyMessage>
|
||||||
|
where
|
||||||
|
C: Into<Recipient>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BotMessagesExt for Bot {
|
||||||
|
fn forward<C>(&self, to_chat_id: C, message: &Message) -> JsonRequest<ForwardMessage>
|
||||||
|
where
|
||||||
|
C: Into<Recipient>,
|
||||||
|
{
|
||||||
|
self.forward_message(to_chat_id, message.chat.id, message.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn edit_live_location(
|
||||||
|
&self,
|
||||||
|
message: &Message,
|
||||||
|
latitude: f64,
|
||||||
|
longitude: f64,
|
||||||
|
) -> JsonRequest<EditMessageLiveLocation> {
|
||||||
|
self.edit_message_live_location(message.chat.id, message.id, latitude, longitude)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stop_live_location(&self, message: &Message) -> JsonRequest<StopMessageLiveLocation> {
|
||||||
|
self.stop_message_live_location(message.chat.id, message.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_reaction(&self, message: &Message) -> JsonRequest<SetMessageReaction> {
|
||||||
|
self.set_message_reaction(message.chat.id, message.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pin(&self, message: &Message) -> JsonRequest<PinChatMessage> {
|
||||||
|
self.pin_chat_message(message.chat.id, message.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unpin(&self, message: &Message) -> JsonRequest<UnpinChatMessage> {
|
||||||
|
self.unpin_chat_message(message.chat.id).message_id(message.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn edit_text<T>(&self, message: &Message, text: T) -> JsonRequest<EditMessageText>
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.edit_message_text(message.chat.id, message.id, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn edit_caption(&self, message: &Message) -> JsonRequest<EditMessageCaption> {
|
||||||
|
self.edit_message_caption(message.chat.id, message.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn edit_media(
|
||||||
|
&self,
|
||||||
|
message: &Message,
|
||||||
|
media: InputMedia,
|
||||||
|
) -> MultipartRequest<EditMessageMedia> {
|
||||||
|
self.edit_message_media(message.chat.id, message.id, media)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn edit_reply_markup(&self, message: &Message) -> JsonRequest<EditMessageReplyMarkup> {
|
||||||
|
self.edit_message_reply_markup(message.chat.id, message.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stop_poll_message(&self, message: &Message) -> JsonRequest<StopPoll> {
|
||||||
|
self.stop_poll(message.chat.id, message.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete(&self, message: &Message) -> JsonRequest<DeleteMessage> {
|
||||||
|
self.delete_message(message.chat.id, message.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy<C>(&self, to_chat_id: C, message: &Message) -> JsonRequest<CopyMessage>
|
||||||
|
where
|
||||||
|
C: Into<Recipient>,
|
||||||
|
{
|
||||||
|
self.copy_message(to_chat_id, message.chat.id, message.id)
|
||||||
|
}
|
||||||
|
}
|
155
crates/teloxide/src/sugar/request.rs
Normal file
155
crates/teloxide/src/sugar/request.rs
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
//! Additions to [`JsonRequest`] and [`MultipartRequest`].
|
||||||
|
//!
|
||||||
|
//! [`JsonRequest`]: teloxide_core::requests::JsonRequest
|
||||||
|
//! [`MultipartRequest`]: teloxide_core::requests::MultipartRequest
|
||||||
|
|
||||||
|
use teloxide_core::{
|
||||||
|
payloads::*,
|
||||||
|
requests::{JsonRequest, MultipartRequest},
|
||||||
|
types::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! impl_request_reply_ext {
|
||||||
|
($($t:ty),*) => {
|
||||||
|
$(
|
||||||
|
impl RequestReplyExt for $t {
|
||||||
|
fn reply_to<M>(self, message_id: M) -> Self
|
||||||
|
where
|
||||||
|
M: Into<MessageId>,
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.reply_parameters(ReplyParameters::new(message_id.into()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_request_link_preview_ext {
|
||||||
|
($($t:ty),*) => {
|
||||||
|
$(
|
||||||
|
impl RequestLinkPreviewExt for $t {
|
||||||
|
fn disable_link_preview(self, is_disabled: bool) -> Self
|
||||||
|
where
|
||||||
|
Self: Sized
|
||||||
|
{
|
||||||
|
let link_preview_options = LinkPreviewOptions {
|
||||||
|
is_disabled,
|
||||||
|
url: None,
|
||||||
|
prefer_small_media: false,
|
||||||
|
prefer_large_media: false,
|
||||||
|
show_above_text: false,
|
||||||
|
};
|
||||||
|
self.link_preview_options(link_preview_options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `.reply_to(msg)` syntax sugar for requests.
|
||||||
|
pub trait RequestReplyExt {
|
||||||
|
/// Replaces `.reply_parameters(ReplyParameters::new(msg.id))`
|
||||||
|
/// with `.reply_to(msg.id)` or `.reply_to(msg)`
|
||||||
|
fn reply_to<M>(self, message_id: M) -> Self
|
||||||
|
where
|
||||||
|
M: Into<MessageId>,
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `.disable_link_preview(is_disabled)` syntax sugar for requests.
|
||||||
|
pub trait RequestLinkPreviewExt {
|
||||||
|
/// 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! {
|
||||||
|
JsonRequest<SendDice>,
|
||||||
|
JsonRequest<SendInvoice>,
|
||||||
|
JsonRequest<SendPoll>,
|
||||||
|
JsonRequest<SendContact>,
|
||||||
|
JsonRequest<SendGame>,
|
||||||
|
JsonRequest<SendVenue>,
|
||||||
|
JsonRequest<SendLocation>,
|
||||||
|
JsonRequest<CopyMessage>,
|
||||||
|
JsonRequest<SendMessage>,
|
||||||
|
MultipartRequest<SendSticker>,
|
||||||
|
MultipartRequest<SendMediaGroup>,
|
||||||
|
MultipartRequest<SendAnimation>,
|
||||||
|
MultipartRequest<SendVideoNote>,
|
||||||
|
MultipartRequest<SendVideo>,
|
||||||
|
MultipartRequest<SendDocument>,
|
||||||
|
MultipartRequest<SendAudio>,
|
||||||
|
MultipartRequest<SendVoice>,
|
||||||
|
MultipartRequest<SendPhoto>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_request_link_preview_ext! {
|
||||||
|
JsonRequest<SendMessage>,
|
||||||
|
JsonRequest<EditMessageText>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use teloxide_core::{prelude::Requester, Bot};
|
||||||
|
|
||||||
|
#[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)));
|
||||||
|
let sugar_reply_req = bot.send_message(ChatId(1234), "test").reply_to(MessageId(1));
|
||||||
|
|
||||||
|
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 {
|
||||||
|
is_disabled: true,
|
||||||
|
url: None,
|
||||||
|
prefer_small_media: false,
|
||||||
|
prefer_large_media: false,
|
||||||
|
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(true);
|
||||||
|
|
||||||
|
assert_eq!(real_link_req.deref(), sugar_link_req.deref())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue