From 3d74587c93e3f978ba79e90f679979fc64a8aaec Mon Sep 17 00:00:00 2001 From: Andrey Brusnik Date: Fri, 19 Jul 2024 00:19:17 +0400 Subject: [PATCH] Add `LinkPreviewOptions` struct and `link_preview_options` field to `InputMessageContentText`, `Message`, `sendMessage` and `editMessageText` --- crates/teloxide-core/schema.ron | 10 ++ .../src/payloads/edit_message_text.rs | 7 +- .../src/payloads/send_message.rs | 5 +- crates/teloxide-core/src/types.rs | 2 + .../src/types/inline_query_result.rs | 146 ++++++++++++++++-- .../src/types/input_message_content.rs | 28 +++- .../src/types/link_preview_options.rs | 46 ++++++ crates/teloxide-core/src/types/message.rs | 6 +- crates/teloxide-core/src/types/update.rs | 19 ++- 9 files changed, 241 insertions(+), 28 deletions(-) create mode 100644 crates/teloxide-core/src/types/link_preview_options.rs diff --git a/crates/teloxide-core/schema.ron b/crates/teloxide-core/schema.ron index dd2bdad2..2169a8a7 100644 --- a/crates/teloxide-core/schema.ron +++ b/crates/teloxide-core/schema.ron @@ -252,6 +252,11 @@ Schema( ty: Option(ArrayOf(RawTy("MessageEntity"))), descr: Doc(md: "List of special entities that appear in the message text, which can be specified instead of _parse\\_mode_"), ), + Param( + name: "link_preview_options", + ty: Option(RawTy("LinkPreviewOptions")), + descr: Doc(md: "Link preview generation options for the message"), + ), Param( name: "disable_notification", ty: Option(bool), @@ -3268,6 +3273,11 @@ Schema( ty: Option(ArrayOf(RawTy("MessageEntity"))), descr: Doc(md: "List of special entities that appear in message text, which can be specified instead of _parse\\_mode_"), ), + Param( + name: "link_preview_options", + ty: Option(RawTy("LinkPreviewOptions")), + descr: Doc(md: "Link preview generation options for the message"), + ), Param( name: "reply_markup", ty: Option(RawTy("InlineKeyboardMarkup")), diff --git a/crates/teloxide-core/src/payloads/edit_message_text.rs b/crates/teloxide-core/src/payloads/edit_message_text.rs index 9d0b9fbd..833b3175 100644 --- a/crates/teloxide-core/src/payloads/edit_message_text.rs +++ b/crates/teloxide-core/src/payloads/edit_message_text.rs @@ -2,7 +2,10 @@ use serde::Serialize; -use crate::types::{InlineKeyboardMarkup, Message, MessageEntity, MessageId, ParseMode, Recipient}; +use crate::types::{ + InlineKeyboardMarkup, LinkPreviewOptions, Message, MessageEntity, MessageId, ParseMode, + Recipient, +}; impl_payload! { /// Use this method to edit text and [games] messages. On success, the edited Message is returned. @@ -28,6 +31,8 @@ impl_payload! { pub parse_mode: ParseMode, /// List of special entities that appear in message text, which can be specified instead of _parse\_mode_ pub entities: Vec [collect], + /// Link preview generation options for the message + pub link_preview_options: LinkPreviewOptions, /// A JSON-serialized object for an [inline keyboard]. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating diff --git a/crates/teloxide-core/src/payloads/send_message.rs b/crates/teloxide-core/src/payloads/send_message.rs index f168f5c5..d7006c4f 100644 --- a/crates/teloxide-core/src/payloads/send_message.rs +++ b/crates/teloxide-core/src/payloads/send_message.rs @@ -3,7 +3,8 @@ use serde::Serialize; use crate::types::{ - Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId, + LinkPreviewOptions, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, + ThreadId, }; impl_payload! { @@ -27,6 +28,8 @@ impl_payload! { pub parse_mode: ParseMode, /// List of special entities that appear in the message text, which can be specified instead of _parse\_mode_ pub entities: Vec [collect], + /// Link preview generation options for the message + pub link_preview_options: LinkPreviewOptions, /// Sends the message [silently]. Users will receive a notification with no sound. /// /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages diff --git a/crates/teloxide-core/src/types.rs b/crates/teloxide-core/src/types.rs index cd7cf0a8..643fe086 100644 --- a/crates/teloxide-core/src/types.rs +++ b/crates/teloxide-core/src/types.rs @@ -81,6 +81,7 @@ pub use keyboard_button_poll_type::*; pub use keyboard_button_request_chat::*; pub use keyboard_button_request_user::*; pub use label_price::*; +pub use link_preview_options::*; pub use location::*; pub use login_url::*; pub use mask_position::*; @@ -199,6 +200,7 @@ mod keyboard_button_poll_type; mod keyboard_button_request_chat; mod keyboard_button_request_user; mod label_price; +mod link_preview_options; mod location; mod login_url; mod mask_position; diff --git a/crates/teloxide-core/src/types/inline_query_result.rs b/crates/teloxide-core/src/types/inline_query_result.rs index d8ad8df2..1d58fd56 100644 --- a/crates/teloxide-core/src/types/inline_query_result.rs +++ b/crates/teloxide-core/src/types/inline_query_result.rs @@ -266,7 +266,7 @@ mod tests { InlineQueryResultGif, InlineQueryResultLocation, InlineQueryResultMpeg4Gif, InlineQueryResultPhoto, InlineQueryResultVenue, InlineQueryResultVideo, InlineQueryResultVoice, InputMessageContent, InputMessageContentLocation, - InputMessageContentText, Seconds, + InputMessageContentText, LinkPreviewOptions, Seconds, }; use mime::Mime; @@ -304,11 +304,18 @@ mod tests { message_text: String::from("message_text"), parse_mode: Some(ParseMode::MarkdownV2), entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), caption_entities: None, }); - let expected_json = r#"{"type":"audio","id":"id","audio_file_id":"audio_file_id","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2"}}"#; + let expected_json = r#"{"type":"audio","id":"id","audio_file_id":"audio_file_id","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -351,13 +358,20 @@ mod tests { message_text: String::from("message_text"), parse_mode: Some(ParseMode::MarkdownV2), entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), caption_entities: None, performer: Some(String::from("performer")), audio_duration: Some(Seconds::from_seconds(1)), }); - let expected_json = r#"{"type":"audio","id":"id","audio_url":"http://audio_url/","title":"title","caption":"caption","parse_mode":"HTML","performer":"performer","audio_duration":1,"reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2"}}"#; + let expected_json = r#"{"type":"audio","id":"id","audio_url":"http://audio_url/","title":"title","caption":"caption","parse_mode":"HTML","performer":"performer","audio_duration":1,"reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -399,11 +413,18 @@ mod tests { message_text: String::from("message_text"), parse_mode: Some(ParseMode::MarkdownV2), entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), caption_entities: None, }); - let expected_json = r#"{"type":"document","id":"id","title":"title","document_file_id":"document_file_id","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2"}}"#; + let expected_json = r#"{"type":"document","id":"id","title":"title","document_file_id":"document_file_id","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -451,13 +472,20 @@ mod tests { message_text: String::from("message_text"), parse_mode: Some(ParseMode::MarkdownV2), entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), thumbnail_url: Some(reqwest::Url::parse("http://thumb_url/").unwrap()), thumbnail_width: Some(1), thumbnail_height: Some(1), }); - let expected_json = r#"{"type":"document","id":"id","title":"title","caption":"caption","parse_mode":"HTML","document_url":"http://document_url/","mime_type":"application/pdf","description":"description","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2"},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#; + let expected_json = r#"{"type":"document","id":"id","title":"title","caption":"caption","parse_mode":"HTML","document_url":"http://document_url/","mime_type":"application/pdf","description":"description","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -498,10 +526,17 @@ mod tests { message_text: String::from("message_text"), parse_mode: Some(ParseMode::MarkdownV2), entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), }); - let expected_json = r#"{"type":"gif","id":"id","gif_file_id":"gif_file_id","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2"}}"#; + let expected_json = r#"{"type":"gif","id":"id","gif_file_id":"gif_file_id","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -552,10 +587,17 @@ mod tests { message_text: String::from("message_text"), parse_mode: Some(ParseMode::MarkdownV2), entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), }); - let expected_json = r#"{"type":"gif","id":"id","gif_url":"http://gif_url/","gif_width":1,"gif_height":1,"gif_duration":1,"thumbnail_url":"http://thumb_url/","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2"}}"#; + let expected_json = r#"{"type":"gif","id":"id","gif_url":"http://gif_url/","gif_width":1,"gif_height":1,"gif_duration":1,"thumbnail_url":"http://thumb_url/","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -596,10 +638,17 @@ mod tests { message_text: String::from("message_text"), parse_mode: Some(ParseMode::MarkdownV2), entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), }); - let expected_json = r#"{"type":"mpeg4_gif","id":"id","mpeg4_file_id":"mpeg4_file_id","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2"}}"#; + let expected_json = r#"{"type":"mpeg4_gif","id":"id","mpeg4_file_id":"mpeg4_file_id","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -650,10 +699,17 @@ mod tests { message_text: String::from("message_text"), parse_mode: Some(ParseMode::MarkdownV2), entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), }); - let expected_json = r#"{"type":"mpeg4_gif","id":"id","mpeg4_url":"http://mpeg4_url/","mpeg4_width":1,"mpeg4_height":1,"mpeg4_duration":1,"thumbnail_url":"http://thumb_url/","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2"}}"#; + let expected_json = r#"{"type":"mpeg4_gif","id":"id","mpeg4_url":"http://mpeg4_url/","mpeg4_width":1,"mpeg4_height":1,"mpeg4_duration":1,"thumbnail_url":"http://thumb_url/","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -696,10 +752,17 @@ mod tests { message_text: String::from("message_text"), parse_mode: Some(ParseMode::MarkdownV2), entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), }); - let expected_json = r#"{"type":"photo","id":"id","photo_file_id":"photo_file_id","title":"title","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2"}}"#; + let expected_json = r#"{"type":"photo","id":"id","photo_file_id":"photo_file_id","title":"title","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -748,10 +811,17 @@ mod tests { message_text: String::from("message_text"), parse_mode: Some(ParseMode::MarkdownV2), entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), }); - let expected_json = r#"{"type":"photo","id":"id","photo_url":"http://photo_url/","thumbnail_url":"http://thumb_url/","photo_width":1,"photo_height":1,"title":"title","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2"}}"#; + let expected_json = r#"{"type":"photo","id":"id","photo_url":"http://photo_url/","thumbnail_url":"http://thumb_url/","photo_width":1,"photo_height":1,"title":"title","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -784,10 +854,17 @@ mod tests { message_text: String::from("message_text"), entities: None, parse_mode: Some(ParseMode::MarkdownV2), + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), }); - let expected_json = r#"{"type":"sticker","id":"id","sticker_file_id":"sticker_file_id","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2"}}"#; + let expected_json = r#"{"type":"sticker","id":"id","sticker_file_id":"sticker_file_id","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -1017,6 +1094,13 @@ mod tests { input_message_content: InputMessageContent::Text(InputMessageContentText { message_text: String::from("message_text"), entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), parse_mode: None, }), reply_markup: None, @@ -1028,7 +1112,7 @@ mod tests { thumbnail_height: None, }); - let expected_json = r#"{"type":"article","id":"id","title":"title","input_message_content":{"message_text":"message_text"}}"#; + let expected_json = r#"{"type":"article","id":"id","title":"title","input_message_content":{"message_text":"message_text","link_preview_options":{"is_disabled":true}}}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -1044,6 +1128,13 @@ mod tests { message_text: String::from("message_text"), entities: None, parse_mode: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), }), reply_markup: Some(InlineKeyboardMarkup::default()), url: Some(Url::parse("http://url/").unwrap()), @@ -1054,7 +1145,7 @@ mod tests { thumbnail_height: Some(1), }); - let expected_json = r#"{"type":"article","id":"id","title":"title","input_message_content":{"message_text":"message_text"},"reply_markup":{"inline_keyboard":[]},"url":"http://url/","hide_url":true,"description":"description","thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#; + let expected_json = r#"{"type":"article","id":"id","title":"title","input_message_content":{"message_text":"message_text","link_preview_options":{"is_disabled":true}},"reply_markup":{"inline_keyboard":[]},"url":"http://url/","hide_url":true,"description":"description","thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -1096,13 +1187,20 @@ mod tests { message_text: String::from("message_text"), entities: None, parse_mode: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), thumbnail_url: Some(Url::parse("http://thumb_url/").unwrap()), thumbnail_width: Some(1), thumbnail_height: Some(1), }); - let expected_json = r#"{"type":"contact","id":"id","phone_number":"phone_number","first_name":"first_name","last_name":"last_name","vcard":"vcard","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text"},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#; + let expected_json = r#"{"type":"contact","id":"id","phone_number":"phone_number","first_name":"first_name","last_name":"last_name","vcard":"vcard","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","link_preview_options":{"is_disabled":true}},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -1181,13 +1279,20 @@ mod tests { message_text: String::from("message_text"), entities: None, parse_mode: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), thumbnail_url: Some(Url::parse("http://thumb_url/").unwrap()), thumbnail_width: Some(1), thumbnail_height: Some(1), }); - let expected_json = r#"{"type":"location","id":"id","latitude":1.0,"longitude":1.0,"title":"title","horizontal_accuracy":1.0,"live_period":1,"heading":1,"proximity_alert_radius":1,"reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text"},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#; + let expected_json = r#"{"type":"location","id":"id","latitude":1.0,"longitude":1.0,"title":"title","horizontal_accuracy":1.0,"live_period":1,"heading":1,"proximity_alert_radius":1,"reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","link_preview_options":{"is_disabled":true}},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); @@ -1237,13 +1342,20 @@ mod tests { message_text: String::from("message_text"), entities: None, parse_mode: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), })), thumbnail_url: Some(Url::parse("http://thumb_url/").unwrap()), thumbnail_width: Some(1), thumbnail_height: Some(1), }); - let expected_json = r#"{"type":"venue","id":"id","latitude":1.0,"longitude":1.0,"title":"title","address":"address","foursquare_id":"foursquare_id","foursquare_type":"foursquare_type","google_place_id":"google_place_id","google_place_type":"google_place_type","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text"},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#; + let expected_json = r#"{"type":"venue","id":"id","latitude":1.0,"longitude":1.0,"title":"title","address":"address","foursquare_id":"foursquare_id","foursquare_type":"foursquare_type","google_place_id":"google_place_id","google_place_type":"google_place_type","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","link_preview_options":{"is_disabled":true}},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#; let actual_json = serde_json::to_string(&structure).unwrap(); assert_eq!(expected_json, actual_json); diff --git a/crates/teloxide-core/src/types/input_message_content.rs b/crates/teloxide-core/src/types/input_message_content.rs index 3cb54fe7..ed517b7a 100644 --- a/crates/teloxide-core/src/types/input_message_content.rs +++ b/crates/teloxide-core/src/types/input_message_content.rs @@ -1,7 +1,7 @@ use reqwest::Url; use serde::{Deserialize, Serialize}; -use crate::types::{Currency, LabeledPrice, MessageEntity, ParseMode}; +use crate::types::{Currency, LabeledPrice, LinkPreviewOptions, MessageEntity, ParseMode}; /// This object represents the content of a message to be sent as a result of an /// inline query. @@ -35,6 +35,9 @@ pub struct InputMessageContentText { /// List of special entities that appear in message text, which can be /// specified instead of `parse_mode`. pub entities: Option>, + + /// Link preview generation options for the message + pub link_preview_options: Option, } impl InputMessageContentText { @@ -42,7 +45,12 @@ impl InputMessageContentText { where S: Into, { - Self { message_text: message_text.into(), parse_mode: None, entities: None } + Self { + message_text: message_text.into(), + parse_mode: None, + entities: None, + link_preview_options: None, + } } pub fn message_text(mut self, val: S) -> Self @@ -66,6 +74,12 @@ impl InputMessageContentText { self.entities = Some(val.into_iter().collect()); self } + + #[must_use] + pub fn link_preview_options(mut self, val: LinkPreviewOptions) -> Self { + self.link_preview_options = Some(val); + self + } } /// Represents the content of a location message to be sent as the result of an @@ -569,11 +583,19 @@ mod tests { #[test] fn text_serialize() { - let expected_json = r#"{"message_text":"text"}"#; + let expected_json = + r#"{"message_text":"text","link_preview_options":{"is_disabled":true}}"#; let text_content = InputMessageContent::Text(InputMessageContentText { message_text: String::from("text"), parse_mode: None, entities: None, + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), }); let actual_json = serde_json::to_string(&text_content).unwrap(); diff --git a/crates/teloxide-core/src/types/link_preview_options.rs b/crates/teloxide-core/src/types/link_preview_options.rs new file mode 100644 index 00000000..4f56d8b0 --- /dev/null +++ b/crates/teloxide-core/src/types/link_preview_options.rs @@ -0,0 +1,46 @@ +use serde::{Deserialize, Serialize}; + +/// Describes the options used for link preview generation. +#[serde_with::skip_serializing_none] +#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] +pub struct LinkPreviewOptions { + /// `true`, if the link preview is disabled + pub is_disabled: Option, + + /// URL to use for the link preview. If empty, then the first URL found in + /// the message text will be used + pub url: Option, + + /// `true`, if the media in the link preview is suppposed to be shrunk; + /// ignored if the URL isn't explicitly specified or media size change isn't + /// supported for the preview + pub prefer_small_media: Option, + + /// `true`, if the media in the link preview is suppposed to be enlarged; + /// ignored if the URL isn't explicitly specified or media size change isn't + /// supported for the preview + pub prefer_large_media: Option, + + /// `true`, if the link preview must be shown above the message text; + /// otherwise, the link preview will be shown below the message text + pub show_above_text: Option, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn deserialize() { + let data = r#" + { + "is_disabled": true, + "url": "https://kernel.org/", + "prefer_small_media": false, + "prefer_large_media": true, + "show_above_text": true + } + "#; + serde_json::from_str::(data).unwrap(); + } +} diff --git a/crates/teloxide-core/src/types/message.rs b/crates/teloxide-core/src/types/message.rs index 24eff7cb..a4b4372f 100644 --- a/crates/teloxide-core/src/types/message.rs +++ b/crates/teloxide-core/src/types/message.rs @@ -8,7 +8,7 @@ use crate::types::{ Animation, Audio, BareChatId, Chat, ChatId, ChatShared, Contact, Dice, Document, ForumTopicClosed, ForumTopicCreated, ForumTopicEdited, ForumTopicReopened, Game, GeneralForumTopicHidden, GeneralForumTopicUnhidden, Giveaway, GiveawayCompleted, - GiveawayCreated, GiveawayWinners, InlineKeyboardMarkup, Invoice, Location, + GiveawayCreated, GiveawayWinners, InlineKeyboardMarkup, Invoice, LinkPreviewOptions, Location, MaybeInaccessibleMessage, MessageAutoDeleteTimerChanged, MessageEntity, MessageEntityRef, MessageId, MessageOrigin, PassportData, PhotoSize, Poll, ProximityAlertTriggered, Sticker, Story, SuccessfulPayment, TextQuote, ThreadId, True, User, UsersShared, Venue, Video, @@ -476,6 +476,10 @@ pub struct MediaText { /// commands, etc. that appear in the text. #[serde(default, skip_serializing_if = "Vec::is_empty")] pub entities: Vec, + + /// Options used for link preview generation for the message, if it is a + /// text message and link preview options were changed + pub link_preview_options: Option, } #[serde_with::skip_serializing_none] diff --git a/crates/teloxide-core/src/types/update.rs b/crates/teloxide-core/src/types/update.rs index 18a37ad3..2d7fa7b6 100644 --- a/crates/teloxide-core/src/types/update.rs +++ b/crates/teloxide-core/src/types/update.rs @@ -428,10 +428,11 @@ fn empty_error() -> UpdateKind { #[cfg(test)] mod test { use crate::types::{ - Chat, ChatFullInfo, ChatId, ChatKind, ChatPrivate, ChatPublic, MediaKind, MediaText, - Message, MessageCommon, MessageId, MessageKind, MessageReactionCountUpdated, - MessageReactionUpdated, PublicChatChannel, PublicChatKind, PublicChatSupergroup, - ReactionCount, ReactionType, ReactionTypeKind, Update, UpdateId, UpdateKind, User, UserId, + Chat, ChatFullInfo, ChatId, ChatKind, ChatPrivate, ChatPublic, LinkPreviewOptions, + MediaKind, MediaText, Message, MessageCommon, MessageId, MessageKind, + MessageReactionCountUpdated, MessageReactionUpdated, PublicChatChannel, PublicChatKind, + PublicChatSupergroup, ReactionCount, ReactionType, ReactionTypeKind, Update, UpdateId, + UpdateKind, User, UserId, }; use chrono::DateTime; @@ -460,7 +461,8 @@ mod test { "type":"private" }, "date":1569518342, - "text":"hello there" + "text":"hello there", + "link_preview_options":{"is_disabled":true} } }"#; @@ -507,6 +509,13 @@ mod test { media_kind: MediaKind::Text(MediaText { text: String::from("hello there"), entities: vec![], + link_preview_options: Some(LinkPreviewOptions { + is_disabled: Some(true), + url: None, + prefer_small_media: None, + prefer_large_media: None, + show_above_text: None, + }), }), reply_markup: None, sender_chat: None,