From 451276cc2054832a36801f03f15dd0715ee79e1a Mon Sep 17 00:00:00 2001 From: Desiders Date: Wed, 14 Aug 2024 16:52:14 +0300 Subject: [PATCH 01/11] Add `PaidMedia`, `PaidMediaInfo`, `PaidMediaPreview`, `PaidMediaPhoto` and `PaidMediaVideo` types --- telers/src/types.rs | 10 ++++++++ telers/src/types/paid_media.rs | 35 ++++++++++++++++++++++++++ telers/src/types/paid_media_info.rs | 14 +++++++++++ telers/src/types/paid_media_photo.rs | 12 +++++++++ telers/src/types/paid_media_preview.rs | 14 +++++++++++ telers/src/types/paid_media_video.rs | 12 +++++++++ 6 files changed, 97 insertions(+) create mode 100644 telers/src/types/paid_media.rs create mode 100644 telers/src/types/paid_media_info.rs create mode 100644 telers/src/types/paid_media_photo.rs create mode 100644 telers/src/types/paid_media_preview.rs create mode 100644 telers/src/types/paid_media_video.rs diff --git a/telers/src/types.rs b/telers/src/types.rs index 50d0819..13812f7 100644 --- a/telers/src/types.rs +++ b/telers/src/types.rs @@ -187,6 +187,11 @@ pub mod message_origin_user; pub mod message_reaction_count_updated; pub mod message_reaction_updated; pub mod order_info; +pub mod paid_media; +pub mod paid_media_info; +pub mod paid_media_photo; +pub mod paid_media_preview; +pub mod paid_media_video; pub mod passport_data; pub mod passport_element_error; pub mod passport_element_error_data_field; @@ -464,6 +469,11 @@ pub use message_origin_user::MessageOriginUser; pub use message_reaction_count_updated::MessageReactionCountUpdated; pub use message_reaction_updated::MessageReactionUpdated; pub use order_info::OrderInfo; +pub use paid_media::PaidMedia; +pub use paid_media_info::PaidMediaInfo; +pub use paid_media_photo::PaidMediaPhoto; +pub use paid_media_preview::PaidMediaPreview; +pub use paid_media_video::PaidMediaVideo; pub use passport_data::PassportData; pub use passport_element_error::PassportElementError; pub use passport_element_error_data_field::{ diff --git a/telers/src/types/paid_media.rs b/telers/src/types/paid_media.rs new file mode 100644 index 0000000..fd04e54 --- /dev/null +++ b/telers/src/types/paid_media.rs @@ -0,0 +1,35 @@ +use super::{PaidMediaPhoto, PaidMediaPreview, PaidMediaVideo}; + +use serde::{Deserialize, Serialize}; + +/// This object describes paid media. Currently, it can be one of +/// - [`PaidMediaPreview`] +/// - [`PaidMediaPhoto`] +/// - [`PaidMediaVideo`] +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum PaidMedia { + Preview(PaidMediaPreview), + Photo(PaidMediaPhoto), + Video(PaidMediaVideo), +} + +impl From for PaidMedia { + fn from(fill: PaidMediaPreview) -> Self { + Self::Preview(fill) + } +} + +impl From for PaidMedia { + fn from(fill: PaidMediaPhoto) -> Self { + Self::Photo(fill) + } +} + +impl From for PaidMedia { + fn from(fill: PaidMediaVideo) -> Self { + Self::Video(fill) + } +} diff --git a/telers/src/types/paid_media_info.rs b/telers/src/types/paid_media_info.rs new file mode 100644 index 0000000..8e24ae2 --- /dev/null +++ b/telers/src/types/paid_media_info.rs @@ -0,0 +1,14 @@ +use super::PaidMedia; + +use serde::{Deserialize, Serialize}; + +/// Describes the paid media added to a message. +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] +pub struct PaidMediaInfo { + /// The number of Telegram Stars that must be paid to buy access to the media + pub star_count: i64, + /// Information about the paid media + pub paid_media: Box<[PaidMedia]>, +} diff --git a/telers/src/types/paid_media_photo.rs b/telers/src/types/paid_media_photo.rs new file mode 100644 index 0000000..ac839ed --- /dev/null +++ b/telers/src/types/paid_media_photo.rs @@ -0,0 +1,12 @@ +use super::PhotoSize; + +use serde::{Deserialize, Serialize}; + +/// The paid media is a photo. +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] +pub struct PaidMediaPhoto { + /// The photo + pub photo: Box<[PhotoSize]>, +} diff --git a/telers/src/types/paid_media_preview.rs b/telers/src/types/paid_media_preview.rs new file mode 100644 index 0000000..d470a57 --- /dev/null +++ b/telers/src/types/paid_media_preview.rs @@ -0,0 +1,14 @@ +use serde::{Deserialize, Serialize}; + +/// The paid media isn't available before the payment. +/// # Documentation +/// +#[derive(Debug, Default, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] +pub struct PaidMediaPreview { + /// Media width as defined by the sender + pub width: Option, + /// Media height as defined by the sender + pub height: Option, + /// Duration of the media in seconds as defined by the sender + pub duration: Option, +} diff --git a/telers/src/types/paid_media_video.rs b/telers/src/types/paid_media_video.rs new file mode 100644 index 0000000..1686bd1 --- /dev/null +++ b/telers/src/types/paid_media_video.rs @@ -0,0 +1,12 @@ +use super::Video; + +use serde::{Deserialize, Serialize}; + +/// The paid media is a video. +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] +pub struct PaidMediaVideo { + /// The video + pub video: Video, +} From ad6fd2e46d071a52c27729b8f65e45864855ea09 Mon Sep 17 00:00:00 2001 From: Desiders Date: Wed, 14 Aug 2024 17:16:45 +0300 Subject: [PATCH 02/11] Add `InputPaidMedia`, `InputPaidMediaPhoto` and `InputPaidMediaVideo` types --- telers/src/types.rs | 6 + telers/src/types/input_paid_media.rs | 27 +++++ telers/src/types/input_paid_media_photo.rs | 29 +++++ telers/src/types/input_paid_media_video.rs | 123 +++++++++++++++++++++ 4 files changed, 185 insertions(+) create mode 100644 telers/src/types/input_paid_media.rs create mode 100644 telers/src/types/input_paid_media_photo.rs create mode 100644 telers/src/types/input_paid_media_video.rs diff --git a/telers/src/types.rs b/telers/src/types.rs index 13812f7..66aef6e 100644 --- a/telers/src/types.rs +++ b/telers/src/types.rs @@ -155,6 +155,9 @@ pub mod input_media_document; pub mod input_media_photo; pub mod input_media_video; pub mod input_message_content; +pub mod input_paid_media; +pub mod input_paid_media_photo; +pub mod input_paid_media_video; pub mod input_poll_option; pub mod input_sticker; pub mod input_text_message_content; @@ -406,6 +409,9 @@ pub use input_media_document::InputMediaDocument; pub use input_media_photo::InputMediaPhoto; pub use input_media_video::InputMediaVideo; pub use input_message_content::InputMessageContent; +pub use input_paid_media::InputPaidMedia; +pub use input_paid_media_photo::InputPaidMediaPhoto; +pub use input_paid_media_video::InputPaidMediaVideo; pub use input_poll_option::InputPollOption; pub use input_sticker::InputSticker; pub use input_text_message_content::InputTextMessageContent; diff --git a/telers/src/types/input_paid_media.rs b/telers/src/types/input_paid_media.rs new file mode 100644 index 0000000..ff9d943 --- /dev/null +++ b/telers/src/types/input_paid_media.rs @@ -0,0 +1,27 @@ +use super::{InputPaidMediaPhoto, InputPaidMediaVideo}; + +use serde::Serialize; + +/// This object describes the paid media to be sent. Currently, it can be one of +/// - [`InputPaidMediaPhoto`] +/// - [`InputPaidMediaVideo`] +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Serialize)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum InputPaidMedia<'a> { + Photo(InputPaidMediaPhoto<'a>), + Video(InputPaidMediaVideo<'a>), +} + +impl<'a> From> for InputPaidMedia<'a> { + fn from(fill: InputPaidMediaPhoto<'a>) -> Self { + Self::Photo(fill) + } +} + +impl<'a> From> for InputPaidMedia<'a> { + fn from(fill: InputPaidMediaVideo<'a>) -> Self { + Self::Video(fill) + } +} diff --git a/telers/src/types/input_paid_media_photo.rs b/telers/src/types/input_paid_media_photo.rs new file mode 100644 index 0000000..cce40b0 --- /dev/null +++ b/telers/src/types/input_paid_media_photo.rs @@ -0,0 +1,29 @@ +use super::InputFile; + +use serde::Serialize; + +/// The paid media to send is a photo. +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Serialize)] +pub struct InputPaidMediaPhoto<'a> { + /// File to send. Pass a `file_id` to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass `attach://` to upload a new one using `multipart/form-data` under `` name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + pub media: InputFile<'a>, +} + +impl<'a> InputPaidMediaPhoto<'a> { + #[must_use] + pub fn new(media: impl Into>) -> Self { + Self { + media: media.into(), + } + } + + #[must_use] + pub fn media(self, val: impl Into>) -> Self { + Self { + media: val.into(), + ..self + } + } +} diff --git a/telers/src/types/input_paid_media_video.rs b/telers/src/types/input_paid_media_video.rs new file mode 100644 index 0000000..beaf95b --- /dev/null +++ b/telers/src/types/input_paid_media_video.rs @@ -0,0 +1,123 @@ +use super::InputFile; + +use serde::Serialize; + +/// The paid media to send is a video. +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Serialize)] +pub struct InputPaidMediaVideo<'a> { + /// File to send. Pass a `file_id` to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass `attach://` to upload a new one using `multipart/form-data` under `` name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + pub media: InputFile<'a>, + /// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using `multipart/form-data`. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass `attach://` if the thumbnail was uploaded using `multipart/form-data` under ``. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + pub thumbnail: Option>, + /// Video width + pub width: Option, + /// Video height" + pub height: Option, + /// Video duration in seconds + pub duration: Option, + /// Pass `true` if the uploaded video is suitable for streaming + pub supports_streaming: Option, +} + +impl<'a> InputPaidMediaVideo<'a> { + #[must_use] + pub fn new(media: impl Into>) -> Self { + Self { + media: media.into(), + thumbnail: None, + width: None, + height: None, + duration: None, + supports_streaming: None, + } + } + + #[must_use] + pub fn media(self, val: impl Into>) -> Self { + Self { + media: val.into(), + ..self + } + } + + #[must_use] + pub fn thumbnail(self, val: impl Into>) -> Self { + Self { + thumbnail: Some(val.into()), + ..self + } + } + + #[must_use] + pub fn width(self, val: i64) -> Self { + Self { + width: Some(val), + ..self + } + } + + #[must_use] + pub fn height(self, val: i64) -> Self { + Self { + height: Some(val), + ..self + } + } + + #[must_use] + pub fn duration(self, val: i64) -> Self { + Self { + duration: Some(val), + ..self + } + } + + #[must_use] + pub fn supports_streaming(self, val: bool) -> Self { + Self { + supports_streaming: Some(val), + ..self + } + } +} + +impl<'a> InputPaidMediaVideo<'a> { + #[must_use] + pub fn thumbnail_option(self, val: Option>>) -> Self { + Self { + thumbnail: val.map(Into::into), + ..self + } + } + + #[must_use] + pub fn width_option(self, val: Option) -> Self { + Self { width: val, ..self } + } + + #[must_use] + pub fn height_option(self, val: Option) -> Self { + Self { + height: val, + ..self + } + } + + #[must_use] + pub fn duration_option(self, val: Option) -> Self { + Self { + duration: val, + ..self + } + } + + #[must_use] + pub fn supports_streaming_option(self, val: Option) -> Self { + Self { + supports_streaming: val, + ..self + } + } +} From 907e463030e2bb55b9d599c8c15f79dcefedf56a Mon Sep 17 00:00:00 2001 From: Desiders Date: Wed, 14 Aug 2024 17:17:09 +0300 Subject: [PATCH 03/11] Small docs changes --- telers/src/types/input_media_animation.rs | 4 ++-- telers/src/types/input_media_audio.rs | 4 ++-- telers/src/types/input_media_document.rs | 4 ++-- telers/src/types/input_media_photo.rs | 2 +- telers/src/types/input_media_video.rs | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/telers/src/types/input_media_animation.rs b/telers/src/types/input_media_animation.rs index 8fddc9a..2eb50bc 100644 --- a/telers/src/types/input_media_animation.rs +++ b/telers/src/types/input_media_animation.rs @@ -9,9 +9,9 @@ use serde_with::skip_serializing_none; #[skip_serializing_none] #[derive(Debug, Clone, Hash, PartialEq, Serialize)] pub struct InputMediaAnimation<'a> { - /// File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://' to upload a new one using `multipart/form-data` under name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + /// File to send. Pass a `file_id` to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass `attach://` to upload a new one using `multipart/form-data` under `` name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). pub media: InputFile<'a>, - /// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using `multipart/form-data`. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using `multipart/form-data` under . [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + /// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using `multipart/form-data`. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass `attach://` if the thumbnail was uploaded using `multipart/form-data` under ``. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). pub thumbnail: Option>, /// Caption of the video to be sent, 0-1024 characters after entities parsing pub caption: Option, diff --git a/telers/src/types/input_media_audio.rs b/telers/src/types/input_media_audio.rs index f70c83c..b5eb060 100644 --- a/telers/src/types/input_media_audio.rs +++ b/telers/src/types/input_media_audio.rs @@ -9,9 +9,9 @@ use serde_with::skip_serializing_none; #[skip_serializing_none] #[derive(Debug, Clone, Hash, PartialEq, Serialize)] pub struct InputMediaAudio<'a> { - /// File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://' to upload a new one using `multipart/form-data` under name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + /// File to send. Pass a `file_id` to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass `attach://` to upload a new one using `multipart/form-data` under `` name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). pub media: InputFile<'a>, - /// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using `multipart/form-data`. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using `multipart/form-data` under . [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + /// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using `multipart/form-data`. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass `attach://` if the thumbnail was uploaded using `multipart/form-data` under ``. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). pub thumbnail: Option>, /// Caption of the audio to be sent, 0-1024 characters after entities parsing pub caption: Option, diff --git a/telers/src/types/input_media_document.rs b/telers/src/types/input_media_document.rs index efc56a1..ff139ad 100644 --- a/telers/src/types/input_media_document.rs +++ b/telers/src/types/input_media_document.rs @@ -9,9 +9,9 @@ use serde_with::skip_serializing_none; #[skip_serializing_none] #[derive(Debug, Clone, Hash, PartialEq, Serialize)] pub struct InputMediaDocument<'a> { - /// File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://' to upload a new one using `multipart/form-data` under name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + /// File to send. Pass a `file_id` to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass `attach://` to upload a new one using `multipart/form-data` under `` name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). pub media: InputFile<'a>, - /// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using `multipart/form-data`. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using `multipart/form-data` under . [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + /// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using `multipart/form-data`. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass `attach://` if the thumbnail was uploaded using `multipart/form-data` under ``. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). pub thumbnail: Option>, /// Caption of the document to be sent, 0-1024 characters after entities parsing pub caption: Option, diff --git a/telers/src/types/input_media_photo.rs b/telers/src/types/input_media_photo.rs index f97ac58..caaa248 100644 --- a/telers/src/types/input_media_photo.rs +++ b/telers/src/types/input_media_photo.rs @@ -9,7 +9,7 @@ use serde_with::skip_serializing_none; #[skip_serializing_none] #[derive(Debug, Clone, Hash, PartialEq, Serialize)] pub struct InputMediaPhoto<'a> { - /// File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://' to upload a new one using `multipart/form-data` under name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + /// File to send. Pass a `file_id` to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass `attach://` to upload a new one using `multipart/form-data` under `` name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). pub media: InputFile<'a>, /// Caption of the photo to be sent, 0-1024 characters after entities parsing pub caption: Option, diff --git a/telers/src/types/input_media_video.rs b/telers/src/types/input_media_video.rs index 6c2ff17..d555b9c 100644 --- a/telers/src/types/input_media_video.rs +++ b/telers/src/types/input_media_video.rs @@ -9,9 +9,9 @@ use serde_with::skip_serializing_none; #[skip_serializing_none] #[derive(Debug, Clone, Hash, PartialEq, Serialize)] pub struct InputMediaVideo<'a> { - /// File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://' to upload a new one using `multipart/form-data` under name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + /// File to send. Pass a `file_id` to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass `attach://` to upload a new one using `multipart/form-data` under `` name. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). pub media: InputFile<'a>, - /// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using `multipart/form-data`. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass 'attach://' if the thumbnail was uploaded using `multipart/form-data` under . [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). + /// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using `multipart/form-data`. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass `attach://` if the thumbnail was uploaded using `multipart/form-data` under ``. [`More information on Sending Files`](https://core.telegram.org/bots/api#sending-files). pub thumbnail: Option>, /// Caption of the video to be sent, 0-1024 characters after entities parsing pub caption: Option, From 6b257dd4e24ab71ce8e3cc8a20af196d51ca6caa Mon Sep 17 00:00:00 2001 From: Desiders Date: Wed, 14 Aug 2024 17:44:28 +0300 Subject: [PATCH 04/11] Add `SendPaidMedia` method --- telers/src/methods.rs | 2 + telers/src/methods/base.rs | 25 ++- telers/src/methods/send_paid_media.rs | 300 ++++++++++++++++++++++++++ 3 files changed, 326 insertions(+), 1 deletion(-) create mode 100644 telers/src/methods/send_paid_media.rs diff --git a/telers/src/methods.rs b/telers/src/methods.rs index 6116a12..0261a2e 100644 --- a/telers/src/methods.rs +++ b/telers/src/methods.rs @@ -105,6 +105,7 @@ pub mod send_invoice; pub mod send_location; pub mod send_media_group; pub mod send_message; +pub mod send_paid_media; pub mod send_photo; pub mod send_poll; pub mod send_sticker; @@ -225,6 +226,7 @@ pub use send_invoice::SendInvoice; pub use send_location::SendLocation; pub use send_media_group::SendMediaGroup; pub use send_message::SendMessage; +pub use send_paid_media::SendPaidMedia; pub use send_photo::SendPhoto; pub use send_poll::SendPoll; pub use send_sticker::SendSticker; diff --git a/telers/src/methods/base.rs b/telers/src/methods/base.rs index 71e5c64..5d6c1c4 100644 --- a/telers/src/methods/base.rs +++ b/telers/src/methods/base.rs @@ -1,6 +1,6 @@ use crate::{ client::Bot, - types::{InputFile, InputMedia, InputSticker, ResponseParameters}, + types::{InputFile, InputMedia, InputPaidMedia, InputSticker, ResponseParameters}, }; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -131,3 +131,26 @@ pub(super) fn prepare_input_stickers<'a>( prepare_input_sticker(files, input_sticker); } } + +pub(super) fn prepare_input_paid_media<'a>( + files: &mut Vec<&'a InputFile<'a>>, + input_paid_media: &'a InputPaidMedia<'a>, +) { + match input_paid_media { + InputPaidMedia::Photo(inner) => { + prepare_file(files, &inner.media); + } + InputPaidMedia::Video(inner) => { + prepare_file(files, &inner.media); + } + } +} + +pub(super) fn prepare_input_paid_media_group<'a>( + files: &mut Vec<&'a InputFile<'a>>, + input_paid_media_group: &'a [InputPaidMedia<'a>], +) { + for input_paid_media in input_paid_media_group { + prepare_input_paid_media(files, input_paid_media); + } +} diff --git a/telers/src/methods/send_paid_media.rs b/telers/src/methods/send_paid_media.rs new file mode 100644 index 0000000..881142e --- /dev/null +++ b/telers/src/methods/send_paid_media.rs @@ -0,0 +1,300 @@ +use super::base::{prepare_input_paid_media_group, Request, TelegramMethod}; + +use crate::{ + client::Bot, + types::{ChatIdKind, InputPaidMedia, Message, MessageEntity, ReplyMarkup, ReplyParameters}, +}; + +use serde::Serialize; +use serde_with::skip_serializing_none; + +/// Use this method to send paid media. +/// # Documentation +/// +/// # Returns +/// On success, the sent [`Message`] is returned +#[skip_serializing_none] +#[derive(Debug, Clone, Hash, PartialEq, Serialize)] +pub struct SendPaidMedia<'a> { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: Option, + /// Unique identifier for the target chat or username of the target channel (in the format `@channelusername`). If the chat is a channel, all Telegram Star proceeds from this media will be credited to the chat's balance. Otherwise, they will be credited to the bot's balance. + pub chat_id: ChatIdKind, + /// The number of Telegram Stars that must be paid to buy access to the media + pub star_count: i64, + /// A JSON-serialized array describing the media to be sent; up to 10 items + pub media: Vec>, + /// Media caption, 0-1024 characters after entities parsing + pub caption: Option, + /// Mode for parsing entities in the media caption. See [`formatting options`](https://core.telegram.org/bots/api#formatting-options) for more details. + pub parse_mode: Option, + /// A JSON-serialized list of special entities that appear in the caption, which can be specified instead of `parse_mode` + pub caption_entities: Option>, + /// Pass `true`, if the caption must be shown above the message media + pub show_caption_above_media: Option, + /// Sends the message [silently](https://telegram.org/blog/channels-2-0#silent-messages). Users will receive a notification with no sound + pub disable_notification: Option, + /// Protects the contents of the sent message from forwarding and saving + pub protect_content: Option, + /// Description of the message to reply to + pub reply_parameters: Option, + /// Additional interface options. A JSON-serialized object for an [inline keyboard](https://core.telegram.org/bots/features#inline-keyboards), [custom reply keyboard](https://core.telegram.org/bots/features#keyboards), instructions to remove reply keyboard or to force a reply from the user. + pub reply_markup: Option, +} + +impl<'a> SendPaidMedia<'a> { + #[must_use] + pub fn new(chat_id: impl Into, star_count: i64, media: I) -> Self + where + T: Into>, + I: IntoIterator, + { + Self { + business_connection_id: None, + chat_id: chat_id.into(), + star_count, + media: media.into_iter().map(Into::into).collect(), + caption: None, + parse_mode: None, + caption_entities: None, + show_caption_above_media: None, + disable_notification: None, + protect_content: None, + reply_parameters: None, + reply_markup: None, + } + } + + #[must_use] + pub fn business_connection_id(self, val: impl Into) -> Self { + Self { + business_connection_id: Some(val.into()), + ..self + } + } + + #[must_use] + pub fn chat_id(self, val: impl Into) -> Self { + Self { + chat_id: val.into(), + ..self + } + } + + #[must_use] + pub fn star_count(self, val: i64) -> Self { + Self { + star_count: val, + ..self + } + } + + #[must_use] + pub fn media_single(self, val: impl Into>) -> Self { + Self { + media: self.media.into_iter().chain(Some(val.into())).collect(), + ..self + } + } + + #[must_use] + pub fn media(self, val: I) -> Self + where + T: Into>, + I: IntoIterator, + { + Self { + media: self + .media + .into_iter() + .chain(val.into_iter().map(Into::into)) + .collect(), + ..self + } + } + + #[must_use] + pub fn caption(self, val: impl Into) -> Self { + Self { + caption: Some(val.into()), + ..self + } + } + + #[must_use] + pub fn parse_mode(self, val: impl Into) -> Self { + Self { + parse_mode: Some(val.into()), + ..self + } + } + + #[must_use] + pub fn caption_entity(self, val: MessageEntity) -> Self { + Self { + caption_entities: Some( + self.caption_entities + .unwrap_or_default() + .into_iter() + .chain(Some(val)) + .collect(), + ), + ..self + } + } + + #[must_use] + pub fn caption_entities(self, val: impl IntoIterator) -> Self { + Self { + caption_entities: Some( + self.caption_entities + .unwrap_or_default() + .into_iter() + .chain(val) + .collect(), + ), + ..self + } + } + + #[must_use] + pub fn show_caption_above_media(self, val: bool) -> Self { + Self { + show_caption_above_media: Some(val), + ..self + } + } + + #[must_use] + pub fn disable_notification(self, val: bool) -> Self { + Self { + disable_notification: Some(val), + ..self + } + } + + #[must_use] + pub fn protect_content(self, val: bool) -> Self { + Self { + protect_content: Some(val), + ..self + } + } + + #[must_use] + pub fn reply_parameters(self, val: ReplyParameters) -> Self { + Self { + reply_parameters: Some(val), + ..self + } + } + + #[must_use] + pub fn reply_markup(self, val: impl Into) -> Self { + Self { + reply_markup: Some(val.into()), + ..self + } + } +} + +impl<'a> SendPaidMedia<'a> { + #[must_use] + pub fn business_connection_id_option(self, val: Option>) -> Self { + Self { + business_connection_id: val.map(Into::into), + ..self + } + } + + #[must_use] + pub fn caption_option(self, val: Option>) -> Self { + Self { + caption: val.map(Into::into), + ..self + } + } + + #[must_use] + pub fn parse_mode_option(self, val: Option>) -> Self { + Self { + parse_mode: val.map(Into::into), + ..self + } + } + + #[must_use] + pub fn caption_entities_option( + self, + val: Option>, + ) -> Self { + Self { + caption_entities: val.map(|val| { + self.caption_entities + .unwrap_or_default() + .into_iter() + .chain(val) + .collect() + }), + ..self + } + } + + #[must_use] + pub fn show_caption_above_media_option(self, val: Option) -> Self { + Self { + show_caption_above_media: val, + ..self + } + } + + #[must_use] + pub fn disable_notification_option(self, val: Option) -> Self { + Self { + disable_notification: val, + ..self + } + } + + #[must_use] + pub fn protect_content_option(self, val: Option) -> Self { + Self { + protect_content: val, + ..self + } + } + + #[must_use] + pub fn reply_parameters_option(self, val: Option) -> Self { + Self { + reply_parameters: val, + ..self + } + } + + #[must_use] + pub fn reply_markup_option(self, val: Option>) -> Self { + Self { + reply_markup: val.map(Into::into), + ..self + } + } +} + +impl<'a> TelegramMethod for SendPaidMedia<'a> { + type Method = Self; + type Return = Message; + + fn build_request(&self, _bot: &Bot) -> Request { + let mut files = vec![]; + prepare_input_paid_media_group(&mut files, &self.media); + + Request::new("sendPaidMedia", self, Some(files.into())) + } +} + +impl<'a> AsRef> for SendPaidMedia<'a> { + fn as_ref(&self) -> &Self { + self + } +} From 0bedfffb2dffa450fdc168c9e9fd3337c09d444d Mon Sep 17 00:00:00 2001 From: Desiders Date: Wed, 14 Aug 2024 17:52:06 +0300 Subject: [PATCH 05/11] Update docks for `CopyMessage` and `CopyMessages` about paid --- telers/src/methods/copy_message.rs | 2 +- telers/src/methods/copy_messages.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telers/src/methods/copy_message.rs b/telers/src/methods/copy_message.rs index 88e02a1..2c5e153 100644 --- a/telers/src/methods/copy_message.rs +++ b/telers/src/methods/copy_message.rs @@ -8,7 +8,7 @@ use crate::{ use serde::Serialize; use serde_with::skip_serializing_none; -/// Use this method to copy messages of any kind. Service messages and invoice messages can't be copied. A quiz [`poll`](crate::types::Poll) can be copied only if the value of the field `correct_option_id` is known to the bot. The method is analogous to the method [`ForwardMessage`](crate::methods::ForwardMessage), but the copied message doesn't have a link to the original message. +/// Use this method to copy messages of any kind. Service messages, paid media messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. A quiz [`poll`](crate::types::Poll) can be copied only if the value of the field `correct_option_id` is known to the bot. The method is analogous to the method [`ForwardMessage`](crate::methods::ForwardMessage), but the copied message doesn't have a link to the original message. /// # Documentation /// /// # Returns diff --git a/telers/src/methods/copy_messages.rs b/telers/src/methods/copy_messages.rs index 83d604d..9a3650e 100644 --- a/telers/src/methods/copy_messages.rs +++ b/telers/src/methods/copy_messages.rs @@ -8,7 +8,7 @@ use crate::{ use serde::Serialize; use serde_with::skip_serializing_none; -/// Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. Service messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. A quiz [`poll`](crate::types::Poll) can be copied only if the value of the field `correct_option_id` is known to the bot. The method is analogous to the method [`ForwardMessages`](crate::methods::ForwardMessages), but the copied messages don't have a link to the original message. Album grouping is kept for copied messages. +/// Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. Service messages, paid media messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. A quiz [`poll`](crate::types::Poll) can be copied only if the value of the field `correct_option_id` is known to the bot. The method is analogous to the method [`ForwardMessages`](crate::methods::ForwardMessages), but the copied messages don't have a link to the original message. Album grouping is kept for copied messages. /// # Documentation /// /// # Returns From e464d5ed05c35070e2442b3049a1e5df9ffaebb3 Mon Sep 17 00:00:00 2001 From: Desiders Date: Wed, 14 Aug 2024 17:55:47 +0300 Subject: [PATCH 06/11] Add `can_send_paid_media` to `ChannelFullInfo` --- telers/src/types/chat_full_info.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/telers/src/types/chat_full_info.rs b/telers/src/types/chat_full_info.rs index 469311c..bcbac0a 100644 --- a/telers/src/types/chat_full_info.rs +++ b/telers/src/types/chat_full_info.rs @@ -200,6 +200,8 @@ pub struct ChannelFullInfo { pub invite_link: Option>, /// The most recent pinned message (by sending date). pub pinned_message: Option, + /// `true`, if paid media messages can be sent or forwarded to the channel chat + pub can_send_paid_media: Option, /// The time after which all messages sent to the chat will be automatically deleted; in seconds. pub message_auto_delete_time: Option, /// `true`, if messages from the chat can't be forwarded to other chats. @@ -645,6 +647,14 @@ impl ChatFullInfo { } } + #[must_use] + pub const fn can_send_paid_media(&self) -> Option { + match self { + Self::Private(_) | Self::Group(_) | Self::Supergroup(_) => None, + Self::Channel(chat) => chat.can_send_paid_media, + } + } + #[must_use] pub const fn slow_mode_delay(&self) -> Option { match self { From 90fc53923eb09b7b4dcbb4e915670122b6981492 Mon Sep 17 00:00:00 2001 From: Desiders Date: Wed, 14 Aug 2024 18:38:52 +0300 Subject: [PATCH 07/11] Add `MessagePaidMedia` --- telers/src/enums/content_type.rs | 6 +- telers/src/types.rs | 9 ++- telers/src/types/message.rs | 134 +++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 5 deletions(-) diff --git a/telers/src/enums/content_type.rs b/telers/src/enums/content_type.rs index 9ab6c94..315bf6e 100644 --- a/telers/src/enums/content_type.rs +++ b/telers/src/enums/content_type.rs @@ -15,6 +15,8 @@ pub enum ContentType { Audio, #[strum(serialize = "document")] Document, + #[strum(serialize = "paid_media")] + PaidMedia, #[strum(serialize = "photo")] Photo, #[strum(serialize = "sticker")] @@ -117,12 +119,13 @@ pub enum ContentType { impl ContentType { #[must_use] - pub const fn all() -> [ContentType; 53] { + pub const fn all() -> [ContentType; 54] { [ ContentType::Text, ContentType::Animation, ContentType::Audio, ContentType::Document, + ContentType::PaidMedia, ContentType::Photo, ContentType::Sticker, ContentType::Story, @@ -201,6 +204,7 @@ impl From<&Message> for ContentType { Message::Animation(_) => ContentType::Animation, Message::Audio(_) => ContentType::Audio, Message::Document(_) => ContentType::Document, + Message::PaidMedia(_) => ContentType::PaidMedia, Message::Photo(_) => ContentType::Photo, Message::Sticker(_) => ContentType::Sticker, Message::Story(_) => ContentType::Story, diff --git a/telers/src/types.rs b/telers/src/types.rs index 66aef6e..e7f8272 100644 --- a/telers/src/types.rs +++ b/telers/src/types.rs @@ -447,10 +447,11 @@ pub use message::{ MessageAutoDeleteTimerChanged as MessageMessageAutoDeleteTimerChanged, MigrateFromChat as MessageMigrateFromChat, MigrateToChat as MessageMigrateToChat, NewChatMembers as MessageNewChatMembers, NewChatPhoto as MessageNewChatPhoto, - NewChatTitle as MessageNewChatTitle, PassportData as MessagePassportData, - Photo as MessagePhoto, Pinned as MessagePinned, Poll as MessagePoll, - ProximityAlertTriggered as MessageProximityAlertTriggered, Sticker as MessageSticker, - Story as MessageStory, SuccessfulPayment as MessageSuccessfulPayment, + NewChatTitle as MessageNewChatTitle, PaidMedia as MessagePaidMedia, + PassportData as MessagePassportData, Photo as MessagePhoto, Pinned as MessagePinned, + Poll as MessagePoll, ProximityAlertTriggered as MessageProximityAlertTriggered, + Sticker as MessageSticker, Story as MessageStory, + SuccessfulPayment as MessageSuccessfulPayment, SupergroupChatCreated as MessageSupergroupChatCreated, Text as MessageText, UsersShared as MessageUsersShared, Venue as MessageVenue, Video as MessageVideo, VideoChatEnded as MessageVideoChatEnded, diff --git a/telers/src/types/message.rs b/telers/src/types/message.rs index fb497a6..f5046d5 100644 --- a/telers/src/types/message.rs +++ b/telers/src/types/message.rs @@ -26,6 +26,7 @@ pub enum Message { Animation(Box), Audio(Box