From 1682f059d3f237f202628c756a22cc31c5d29754 Mon Sep 17 00:00:00 2001 From: Desiders Date: Mon, 10 Jun 2024 03:34:37 +0300 Subject: [PATCH] Add new types. Change old types and methods --- telers/src/enums/content_type.rs | 6 +- .../src/methods/edit_message_live_location.rs | 19 + telers/src/methods/get_chat.rs | 8 +- telers/src/methods/send_poll.rs | 76 +- telers/src/methods/send_voice.rs | 2 +- telers/src/types.rs | 32 +- telers/src/types/background_fill.rs | 35 + .../background_fill_freeform_gradient.rs | 10 + telers/src/types/background_fill_gradient.rs | 14 + telers/src/types/background_fill_solid.rs | 10 + telers/src/types/background_type.rs | 45 ++ .../src/types/background_type_chat_theme.rs | 11 + telers/src/types/background_type_fill.rs | 14 + telers/src/types/background_type_pattern.rs | 20 + telers/src/types/background_type_wallpaper.rs | 18 + telers/src/types/chat.rs | 367 +-------- telers/src/types/chat_background.rs | 13 + telers/src/types/chat_full_info.rs | 719 ++++++++++++++++++ telers/src/types/chat_member_updated.rs | 2 + telers/src/types/inline_keyboard_button.rs | 12 +- telers/src/types/input_poll_option.rs | 29 + telers/src/types/message.rs | 136 ++++ telers/src/types/poll.rs | 4 + telers/src/types/poll_option.rs | 2 + 24 files changed, 1236 insertions(+), 368 deletions(-) create mode 100644 telers/src/types/background_fill.rs create mode 100644 telers/src/types/background_fill_freeform_gradient.rs create mode 100644 telers/src/types/background_fill_gradient.rs create mode 100644 telers/src/types/background_fill_solid.rs create mode 100644 telers/src/types/background_type.rs create mode 100644 telers/src/types/background_type_chat_theme.rs create mode 100644 telers/src/types/background_type_fill.rs create mode 100644 telers/src/types/background_type_pattern.rs create mode 100644 telers/src/types/background_type_wallpaper.rs create mode 100644 telers/src/types/chat_background.rs create mode 100644 telers/src/types/chat_full_info.rs create mode 100644 telers/src/types/input_poll_option.rs diff --git a/telers/src/enums/content_type.rs b/telers/src/enums/content_type.rs index e479c61b..9ab6c94a 100644 --- a/telers/src/enums/content_type.rs +++ b/telers/src/enums/content_type.rs @@ -81,6 +81,8 @@ pub enum ContentType { ProximityAlertTriggered, #[strum(serialize = "chat_boost_added")] ChatBoostAdded, + #[strum(serialize = "chat_background_set")] + ChatBackgroundSet, #[strum(serialize = "forum_topic_created")] ForumTopicCreated, #[strum(serialize = "forum_topic_edited")] @@ -115,7 +117,7 @@ pub enum ContentType { impl ContentType { #[must_use] - pub const fn all() -> [ContentType; 52] { + pub const fn all() -> [ContentType; 53] { [ ContentType::Text, ContentType::Animation, @@ -154,6 +156,7 @@ impl ContentType { ContentType::PassportData, ContentType::ProximityAlertTriggered, ContentType::ChatBoostAdded, + ContentType::ChatBackgroundSet, ContentType::ForumTopicCreated, ContentType::ForumTopicEdited, ContentType::ForumTopicClosed, @@ -231,6 +234,7 @@ impl From<&Message> for ContentType { Message::PassportData(_) => ContentType::PassportData, Message::ProximityAlertTriggered(_) => ContentType::ProximityAlertTriggered, Message::ChatBoostAdded(_) => ContentType::ChatBoostAdded, + Message::ChatBackgroundSet(_) => ContentType::ChatBackgroundSet, Message::ForumTopicCreated(_) => ContentType::ForumTopicCreated, Message::ForumTopicEdited(_) => ContentType::ForumTopicEdited, Message::ForumTopicClosed(_) => ContentType::ForumTopicClosed, diff --git a/telers/src/methods/edit_message_live_location.rs b/telers/src/methods/edit_message_live_location.rs index a8c0b8ec..7051bfb6 100644 --- a/telers/src/methods/edit_message_live_location.rs +++ b/telers/src/methods/edit_message_live_location.rs @@ -27,6 +27,8 @@ pub struct EditMessageLiveLocation { pub longitude: f64, /// Latitude of new location pub latitude: f64, + /// New period in seconds during which the location can be updated, starting from the message send date. If `0x7FFFFFFF` is specified, then the location can be updated forever. Otherwise, the new value must not exceed the current `live_period` by more than a day, and the live location expiration date must remain within the next 90 days. If not specified, then `live_period` remains unchanged + pub live_period: Option, /// The radius of uncertainty for the location, measured in meters; 0-1500 pub horizontal_accuracy: Option, /// For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified. @@ -46,6 +48,7 @@ impl EditMessageLiveLocation { inline_message_id: None, longitude, latitude, + live_period: None, horizontal_accuracy: None, heading: None, proximity_alert_radius: None, @@ -93,6 +96,14 @@ impl EditMessageLiveLocation { } } + #[must_use] + pub fn live_period(self, val: i64) -> Self { + Self { + live_period: Some(val), + ..self + } + } + #[must_use] pub fn horizontal_accuracy(self, val: f64) -> Self { Self { @@ -151,6 +162,14 @@ impl EditMessageLiveLocation { } } + #[must_use] + pub fn live_period_option(self, val: Option) -> Self { + Self { + live_period: val, + ..self + } + } + #[must_use] pub fn horizontal_accuracy_option(self, val: Option) -> Self { Self { diff --git a/telers/src/methods/get_chat.rs b/telers/src/methods/get_chat.rs index 5ea63243..f90c9da0 100644 --- a/telers/src/methods/get_chat.rs +++ b/telers/src/methods/get_chat.rs @@ -2,16 +2,16 @@ use super::base::{Request, TelegramMethod}; use crate::{ client::Bot, - types::{Chat, ChatIdKind}, + types::{ChatFullInfo, ChatIdKind}, }; use serde::Serialize; -/// Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.). +/// Use this method to get up-to-date information about the chat /// # Documentation /// /// # Returns -/// Returns a [`Chat`] object on success +/// Returns a [`ChatFullInfo`] object on success #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize)] pub struct GetChat { /// Unique identifier for the target chat or username of the target supergroup or channel (in the format `@channelusername`) @@ -36,7 +36,7 @@ impl GetChat { impl TelegramMethod for GetChat { type Method = Self; - type Return = Chat; + type Return = ChatFullInfo; fn build_request(&self, _bot: &Bot) -> Request { Request::new("getChat", self, None) diff --git a/telers/src/methods/send_poll.rs b/telers/src/methods/send_poll.rs index 9562f2b9..78f6d232 100644 --- a/telers/src/methods/send_poll.rs +++ b/telers/src/methods/send_poll.rs @@ -2,7 +2,7 @@ use super::base::{Request, TelegramMethod}; use crate::{ client::Bot, - types::{ChatIdKind, Message, MessageEntity, ReplyMarkup, ReplyParameters}, + types::{ChatIdKind, InputPollOption, Message, MessageEntity, ReplyMarkup, ReplyParameters}, }; use serde::Serialize; @@ -24,8 +24,12 @@ pub struct SendPoll { pub message_thread_id: Option, /// Poll question, 1-300 characters pub question: String, - /// A JSON-serialized list of answer options, 2-10 strings 1-100 characters each - pub options: Vec, + /// Mode for parsing entities in the question. See [formatting options](https://core.telegram.org/bots/api#formatting-options) for more details. Currently, only custom emoji entities are allowed + pub question_parse_mode: Option, + /// A JSON-serialized list of special entities that appear in the poll question. It can be specified instead of `question_parse_mode` + pub question_entities: Option>, + /// A JSON-serialized list of 2-10 answer options + pub options: Vec, /// `true`, if the poll needs to be anonymous, defaults to `true` pub is_anonymous: Option, /// Poll type, `quiz` or `regular`, defaults to `regular` @@ -59,9 +63,13 @@ pub struct SendPoll { impl SendPoll { #[must_use] - pub fn new(chat_id: impl Into, question: T, options: I) -> Self + pub fn new( + chat_id: impl Into, + question: impl Into, + options: I, + ) -> Self where - T: Into, + T: Into, I: IntoIterator, { Self { @@ -69,6 +77,8 @@ impl SendPoll { chat_id: chat_id.into(), message_thread_id: None, question: question.into(), + question_parse_mode: None, + question_entities: None, options: options.into_iter().map(Into::into).collect(), is_anonymous: None, poll_type: None, @@ -120,7 +130,43 @@ impl SendPoll { } #[must_use] - pub fn option(self, val: impl Into) -> Self { + pub fn question_parse_mode(self, val: impl Into) -> Self { + Self { + question_parse_mode: Some(val.into()), + ..self + } + } + + #[must_use] + pub fn question_entity(self, val: MessageEntity) -> Self { + Self { + question_entities: Some( + self.question_entities + .unwrap_or_default() + .into_iter() + .chain(Some(val)) + .collect(), + ), + ..self + } + } + + #[must_use] + pub fn question_entities(self, val: impl IntoIterator) -> Self { + Self { + question_entities: Some( + self.question_entities + .unwrap_or_default() + .into_iter() + .chain(val) + .collect(), + ), + ..self + } + } + + #[must_use] + pub fn option(self, val: impl Into) -> Self { Self { options: self.options.into_iter().chain(Some(val.into())).collect(), ..self @@ -130,7 +176,7 @@ impl SendPoll { #[must_use] pub fn options(self, val: I) -> Self where - T: Into, + T: Into, I: IntoIterator, { Self { @@ -293,6 +339,22 @@ impl SendPoll { } } + #[must_use] + pub fn question_option(self, val: Option>) -> Self { + Self { + question: val.map(Into::into).unwrap_or_default(), + ..self + } + } + + #[must_use] + pub fn question_parse_mode_option(self, val: Option>) -> Self { + Self { + question_parse_mode: val.map(Into::into), + ..self + } + } + #[must_use] pub fn is_anonymous_option(self, val: Option) -> Self { Self { diff --git a/telers/src/methods/send_voice.rs b/telers/src/methods/send_voice.rs index f24a44cf..14d6aabf 100644 --- a/telers/src/methods/send_voice.rs +++ b/telers/src/methods/send_voice.rs @@ -8,7 +8,7 @@ use crate::{ use serde::Serialize; use serde_with::skip_serializing_none; -/// Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as [Audio](crate::types::Audio) or [Document](crate::types::Document)). Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. +/// Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as [Audio](crate::types::Audio) or [Document](crate::types::Document)). Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. /// # Documentation /// /// # Returns diff --git a/telers/src/types.rs b/telers/src/types.rs index 6560aedb..019996f7 100644 --- a/telers/src/types.rs +++ b/telers/src/types.rs @@ -39,6 +39,15 @@ pub mod animation; pub mod audio; +pub mod background_fill; +pub mod background_fill_freeform_gradient; +pub mod background_fill_gradient; +pub mod background_fill_solid; +pub mod background_type; +pub mod background_type_chat_theme; +pub mod background_type_fill; +pub mod background_type_pattern; +pub mod background_type_wallpaper; pub mod birthdate; pub mod bot_command; pub mod bot_command_scope; @@ -62,6 +71,7 @@ pub mod callback_game; pub mod callback_query; pub mod chat; pub mod chat_administrator_rights; +pub mod chat_background; pub mod chat_boost; pub mod chat_boost_added; pub mod chat_boost_removed; @@ -70,6 +80,7 @@ pub mod chat_boost_source_gift_code; pub mod chat_boost_source_giveaway; pub mod chat_boost_source_premium; pub mod chat_boost_updated; +pub mod chat_full_info; pub mod chat_id_kind; pub mod chat_invite_link; pub mod chat_join_request; @@ -144,6 +155,7 @@ pub mod input_media_document; pub mod input_media_photo; pub mod input_media_video; pub mod input_message_content; +pub mod input_poll_option; pub mod input_sticker; pub mod input_text_message_content; pub mod input_venue_message_content; @@ -234,6 +246,15 @@ pub mod write_access_allowed; pub use animation::Animation; pub use audio::Audio; +pub use background_fill::BackgroundFill; +pub use background_fill_freeform_gradient::BackgroundFillFreeformGradient; +pub use background_fill_gradient::BackgroundFillGradient; +pub use background_fill_solid::BackgroundFillSolid; +pub use background_type::BackgroundType; +pub use background_type_chat_theme::BackgroundTypeChatTheme; +pub use background_type_fill::BackgroundTypeFill; +pub use background_type_pattern::BackgroundTypePattern; +pub use background_type_wallpaper::BackgroundTypeWallpaper; pub use birthdate::Birthdate; pub use bot_command::BotCommand; pub use bot_command_scope::BotCommandScope; @@ -255,11 +276,9 @@ pub use business_opening_hours::BusinessOpeningHours; pub use business_opening_hours_interval::BusinessOpeningHoursInterval; pub use callback_game::CallbackGame; pub use callback_query::CallbackQuery; -pub use chat::{ - Channel as ChatChannel, Chat, Group as ChatGroup, Private as ChatPrivate, - Supergroup as ChatSupergroup, -}; +pub use chat::Chat; pub use chat_administrator_rights::ChatAdministratorRights; +pub use chat_background::ChatBackground; pub use chat_boost::ChatBoost; pub use chat_boost_added::ChatBoostAdded; pub use chat_boost_removed::ChatBoostRemoved; @@ -268,6 +287,10 @@ pub use chat_boost_source_gift_code::ChatBoostSourceGiftCode; pub use chat_boost_source_giveaway::ChatBoostSourceGiveaway; pub use chat_boost_source_premium::ChatBoostSourcePremium; pub use chat_boost_updated::ChatBoostUpdated; +pub use chat_full_info::{ + Channel as ChatChannel, ChatFullInfo, Group as ChatGroup, Private as ChatPrivate, + Supergroup as ChatSupergroup, +}; pub use chat_id_kind::ChatIdKind; pub use chat_invite_link::ChatInviteLink; pub use chat_join_request::ChatJoinRequest; @@ -368,6 +391,7 @@ 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_poll_option::InputPollOption; pub use input_sticker::InputSticker; pub use input_text_message_content::InputTextMessageContent; pub use input_venue_message_content::InputVenueMessageContent; diff --git a/telers/src/types/background_fill.rs b/telers/src/types/background_fill.rs new file mode 100644 index 00000000..1b2a0913 --- /dev/null +++ b/telers/src/types/background_fill.rs @@ -0,0 +1,35 @@ +use super::{BackgroundFillFreeformGradient, BackgroundFillGradient, BackgroundFillSolid}; + +use serde::Deserialize; + +/// This object describes the way a background is filled based on the selected colors. Currently, it can be one of +/// - [`BackgroundFillSolid`] +/// - [`BackgroundFillGradient`] +/// - [`BackgroundFillFreeformGradient`] +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum BackgroundFill { + Solid(BackgroundFillSolid), + Gradient(BackgroundFillGradient), + FreeformGradient(BackgroundFillFreeformGradient), +} + +impl From for BackgroundFill { + fn from(fill: BackgroundFillSolid) -> Self { + Self::Solid(fill) + } +} + +impl From for BackgroundFill { + fn from(fill: BackgroundFillGradient) -> Self { + Self::Gradient(fill) + } +} + +impl From for BackgroundFill { + fn from(fill: BackgroundFillFreeformGradient) -> Self { + Self::FreeformGradient(fill) + } +} diff --git a/telers/src/types/background_fill_freeform_gradient.rs b/telers/src/types/background_fill_freeform_gradient.rs new file mode 100644 index 00000000..c2d6f9f2 --- /dev/null +++ b/telers/src/types/background_fill_freeform_gradient.rs @@ -0,0 +1,10 @@ +use serde::Deserialize; + +/// The background is a freeform gradient that rotates after every message in the chat +/// # Documentation +/// +#[derive(Debug, Default, Clone, Hash, PartialEq, Eq, Deserialize)] +pub struct BackgroundFillFreeformGradient { + /// A list of the 3 or 4 base colors that are used to generate the freeform gradient in the RGB24 format + pub colors: Box<[u32]>, +} diff --git a/telers/src/types/background_fill_gradient.rs b/telers/src/types/background_fill_gradient.rs new file mode 100644 index 00000000..0a1ca932 --- /dev/null +++ b/telers/src/types/background_fill_gradient.rs @@ -0,0 +1,14 @@ +use serde::Deserialize; + +/// The background is a gradient fill +/// # Documentation +/// +#[derive(Debug, Default, Clone, Hash, PartialEq, Eq, Deserialize)] +pub struct BackgroundFillGradient { + /// Top color of the gradient in the RGB24 format + pub top_color: u32, + /// Bottom color of the gradient in the RGB24 format + pub bottom_color: u32, + /// Clockwise rotation angle of the background fill in degrees; 0-359 + pub rotation_angle: i32, +} diff --git a/telers/src/types/background_fill_solid.rs b/telers/src/types/background_fill_solid.rs new file mode 100644 index 00000000..ba8841de --- /dev/null +++ b/telers/src/types/background_fill_solid.rs @@ -0,0 +1,10 @@ +use serde::Deserialize; + +/// The background is filled using the selected color +/// # Documentation +/// +#[derive(Debug, Default, Clone, Hash, PartialEq, Eq, Deserialize)] +pub struct BackgroundFillSolid { + /// The color of the background fill in the RGB24 format + pub color: u32, +} diff --git a/telers/src/types/background_type.rs b/telers/src/types/background_type.rs new file mode 100644 index 00000000..9871f1b3 --- /dev/null +++ b/telers/src/types/background_type.rs @@ -0,0 +1,45 @@ +use super::{ + BackgroundTypeChatTheme, BackgroundTypeFill, BackgroundTypePattern, BackgroundTypeWallpaper, +}; + +use serde::Deserialize; + +/// This object describes the type of a background. Currently, it can be one of +/// - [`BackgroundTypeFill`] +/// - [`BackgroundTypeWallpaper`] +/// - [`BackgroundTypePattern`] +/// - [`BackgroundTypeChatTheme`] +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum BackgroundType { + Fill(BackgroundTypeFill), + Wallpaper(BackgroundTypeWallpaper), + Pattern(BackgroundTypePattern), + ChatTheme(BackgroundTypeChatTheme), +} + +impl From for BackgroundType { + fn from(fill: BackgroundTypeFill) -> Self { + Self::Fill(fill) + } +} + +impl From for BackgroundType { + fn from(wallpaper: BackgroundTypeWallpaper) -> Self { + Self::Wallpaper(wallpaper) + } +} + +impl From for BackgroundType { + fn from(pattern: BackgroundTypePattern) -> Self { + Self::Pattern(pattern) + } +} + +impl From for BackgroundType { + fn from(chat_theme: BackgroundTypeChatTheme) -> Self { + Self::ChatTheme(chat_theme) + } +} diff --git a/telers/src/types/background_type_chat_theme.rs b/telers/src/types/background_type_chat_theme.rs new file mode 100644 index 00000000..c127f8b6 --- /dev/null +++ b/telers/src/types/background_type_chat_theme.rs @@ -0,0 +1,11 @@ +use serde::Deserialize; + +/// The background is taken directly from a built-in chat theme. +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize)] +pub struct BackgroundTypeChatTheme { + /// Name of the chat theme, which is usually an emoji + #[serde(rename = "theme_name")] + pub name: String, +} diff --git a/telers/src/types/background_type_fill.rs b/telers/src/types/background_type_fill.rs new file mode 100644 index 00000000..2d51ee16 --- /dev/null +++ b/telers/src/types/background_type_fill.rs @@ -0,0 +1,14 @@ +use super::BackgroundFill; + +use serde::Deserialize; + +/// The background is automatically filled based on the selected colors +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize)] +pub struct BackgroundTypeFill { + /// The background fill + pub fill: BackgroundFill, + /// Dimming of the background in dark themes, as a percentage; 0-100 + pub dark_theme_dimming: u8, +} diff --git a/telers/src/types/background_type_pattern.rs b/telers/src/types/background_type_pattern.rs new file mode 100644 index 00000000..e9534aed --- /dev/null +++ b/telers/src/types/background_type_pattern.rs @@ -0,0 +1,20 @@ +use super::{BackgroundFill, Document}; + +use serde::Deserialize; + +/// The background is a PNG or TGV (gzipped subset of SVG with MIME type “application/x-tgwallpattern”) pattern to be combined with the background fill chosen by the user +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize)] +pub struct BackgroundTypePattern { + /// Document with the wallpaper + pub document: Document, + /// The background fill that is combined with the pattern + pub fill: BackgroundFill, + /// Intensity of the pattern when it is shown above the filled background; 0-100 + pub intensity: u8, + /// `true`, if the background fill must be applied only to the pattern itself. All other pixels are black in this case. For dark themes only + pub is_inverted: Option, + /// `true`, if the background moves slightly when the device is tilted + pub is_moving: Option, +} diff --git a/telers/src/types/background_type_wallpaper.rs b/telers/src/types/background_type_wallpaper.rs new file mode 100644 index 00000000..643bc448 --- /dev/null +++ b/telers/src/types/background_type_wallpaper.rs @@ -0,0 +1,18 @@ +use super::Document; + +use serde::Deserialize; + +/// The background is a wallpaper in the JPEG format +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize)] +pub struct BackgroundTypeWallpaper { + /// Document with the wallpaper + pub document: Document, + /// Dimming of the background in dark themes, as a percentage; 0-100 + pub dark_theme_dimming: u8, + /// `true`, if the wallpaper is downscaled to fit in a 450x450 square and then box-blurred with radius 12 + pub is_blurred: Option, + /// `true`, if the background moves slightly when the device is tilted + pub is_moving: Option, +} diff --git a/telers/src/types/chat.rs b/telers/src/types/chat.rs index e5138d9c..d1fec169 100644 --- a/telers/src/types/chat.rs +++ b/telers/src/types/chat.rs @@ -1,8 +1,3 @@ -use super::{ - Birthdate, BusinessIntro, BusinessLocation, BusinessOpeningHours, ChatLocation, - ChatPermissions, ChatPhoto, Message, -}; - use crate::extractors::FromContext; use serde::Deserialize; @@ -26,7 +21,7 @@ pub enum Chat { #[derive(Debug, Default, Clone, PartialEq, Deserialize)] pub struct Private { - /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in i64erpreting it. But it has at most 52 significant bits, so a signed 64-bit i64eger or double-precision float type are safe for storing this identifier. + /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this identifier. pub id: i64, /// Username pub username: Option>, @@ -34,73 +29,19 @@ pub struct Private { pub first_name: Option>, /// Last name of the other party pub last_name: Option>, - /// Chat photo. Returned only in [`GetChat`](crate::methods::GetChat). - pub photo: Option, - /// If non-empty, the list of all [active chat usernames](https://telegram.org/blog/topics-in-groups-collectible-usernames/ru?ln=a#collectible-usernames). Returned only in [`GetChat`](crate::methods::GetChat). - pub active_usernames: Option]>>, - /// The date of birth of the user. Returned only in [`GetChat`](crate::methods::GetChat). - pub birthdate: Option, - /// The intro of the business. Returned only in [`GetChat`](crate::methods::GetChat). - pub business_intro: Option, - /// The location of the business. Returned only in [`GetChat`](crate::methods::GetChat). - pub business_location: Option, - /// The opening hours of the business. Returned only in [`GetChat`](crate::methods::GetChat). - pub business_opening_hours: Option, - /// The personal channel of the user. Returned only in [`GetChat`](crate::methods::GetChat). - pub personal_chat: Option, - /// Identifier of the accent color for the chat name and backgrounds of the chat photo, reply header, and link preview. See [accent colors](https://core.telegram.org/bots/api#accent-colors) for more details. Returned only in [`GetChat`](crate::methods::GetChat). Always returned in [`GetChat`](crate::methods::GetChat). - pub accent_color_id: Option, - /// Custom emoji identifier of emoji chosen by the chat for the reply header and link preview background. Returned only in [`GetChat`](crate::methods::GetChat). - pub background_custom_emoji_id: Option>, - /// Identifier of the accent color for the chat's profile background. See [profile accent colors](https://core.telegram.org/bots/api#profile-accent-colors) for more details. Returned only in [`GetChat`](crate::methods::GetChat). - pub profile_accent_color_id: Option, - /// Custom emoji identifier of the emoji chosen by the chat for its profile background. Returned only in [`GetChat`](crate::methods::GetChat). - pub profile_background_custom_emoji_id: Option>, - /// Custom emoji identifier of emoji status of the other party. Returned only in [`GetChat`](crate::methods::GetChat). - pub emoji_status_custom_emoji_id: Option>, - /// Expiration date of the emoji status of the other party in Unix time, if any. Returned only in [`GetChat`](crate::methods::GetChat). - pub emoji_status_expiration_date: Option, - /// Bio of the other party. Returned only in [`GetChat`](crate::methods::GetChat). - pub bio: Option>, - /// `true`, if privacy settings of the other party allows to use `tg://user?id=` links only in chats with the user. Returned only in [`GetChat`](crate::methods::GetChat). - pub has_private_forwards: Option, - /// `true`, if the privacy settings of the other party restrict sending voice and video note messages. Returned only in [`GetChat`](crate::methods::GetChat). - pub has_restricted_voice_and_video_messages: Option, - /// The most recent pinned message (by sending date). Returned only in [`GetChat`](crate::methods::GetChat). - pub pinned_message: Option, - /// The time after which all messages sent to the chat will be automatically deleted; in seconds. Returned only in [`GetChat`](crate::methods::GetChat). - pub message_auto_delete_time: Option, } #[derive(Debug, Clone, PartialEq, Deserialize)] pub struct Group { - /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in i64erpreting it. But it has at most 52 significant bits, so a signed 64-bit i64eger or double-precision float type are safe for storing this identifier. + /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this identifier. pub id: i64, /// Title pub title: Box, - /// Chat photo. Returned only in [`GetChat`](crate::methods::GetChat). - pub photo: Option, - /// Description. Returned only in [`GetChat`](crate::methods::GetChat). - pub description: Option>, - /// Primary invite link. Returned only in [`GetChat`](crate::methods::GetChat). - pub invite_link: Option>, - /// The most recent pinned message (by sending date). Returned only in [`GetChat`](crate::methods::GetChat). - pub pinned_message: Option, - /// Default chat member permissions. Returned only in [`GetChat`](crate::methods::GetChat). - pub permissions: Option, - /// The time after which all messages sent to the chat will be automatically deleted; in seconds. Returned only in [`GetChat`](crate::methods::GetChat). - pub message_auto_delete_time: Option, - /// `true`, if non-administrators can only get the list of bots and administrators in the chat. Returned only in [`GetChat`](crate::methods::GetChat). - pub has_hidden_members: Option, - /// `true`, if messages from the chat can't be forwarded to other chats. Returned only in [`GetChat`](crate::methods::GetChat). - pub has_protected_content: Option, - /// `true`, if new chat members will have access to old messages; available only to chat administrators. Returned only in [`GetChat`](crate::methods::GetChat). - pub has_visible_history: Option, } #[derive(Debug, Clone, PartialEq, Deserialize)] pub struct Supergroup { - /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in i64erpreting it. But it has at most 52 significant bits, so a signed 64-bit i64eger or double-precision float type are safe for storing this identifier. + /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this identifier. pub id: i64, /// Title pub title: Box, @@ -108,100 +49,16 @@ pub struct Supergroup { pub username: Option>, /// `true`, if the chat is a forum (has [`topics`](https://telegram.org/blog/topics-in-groups-collectible-usernames#topics-in-groups) enabled) pub is_forum: Option, - /// Chat photo. Returned only in [`GetChat`](crate::methods::GetChat). - pub photo: Option, - /// If non-empty, the list of all [active chat usernames](https://telegram.org/blog/topics-in-groups-collectible-usernames/ru?ln=a#collectible-usernames). Returned only in [`GetChat`](crate::methods::GetChat). - pub active_usernames: Option]>>, - /// List of available reactions allowed in the chat. If omitted, then all [emoji reactions](https://core.telegram.org/bots/api#reactiontypeemoji) are allowed. Returned only in [`GetChat`](crate::methods::GetChat). - pub available_reactions: Option]>>, - /// Identifier of the accent color for the chat name and backgrounds of the chat photo, reply header, and link preview. See [accent colors](https://core.telegram.org/bots/api#accent-colors) for more details. Returned only in [`GetChat`](crate::methods::GetChat). Always returned in [`GetChat`](crate::methods::GetChat). - pub accent_color_id: Option, - /// Custom emoji identifier of emoji chosen by the chat for the reply header and link preview background. Returned only in [`GetChat`](crate::methods::GetChat). - pub background_custom_emoji_id: Option>, - /// Identifier of the accent color for the chat's profile background. See [profile accent colors](https://core.telegram.org/bots/api#profile-accent-colors) for more details. Returned only in [`GetChat`](crate::methods::GetChat). - pub profile_accent_color_id: Option, - /// Custom emoji identifier of the emoji chosen by the chat for its profile background. Returned only in [`GetChat`](crate::methods::GetChat). - pub profile_background_custom_emoji_id: Option>, - /// Custom emoji identifier of the emoji status. Returned only in [`GetChat`](crate::methods::GetChat). - pub emoji_status_custom_emoji_id: Option>, - /// Expiration date of the emoji status in Unix time, if any. Returned only in [`GetChat`](crate::methods::GetChat). - pub emoji_status_expiration_date: Option, - /// `true`, if users need to join the supergroup before they can send messages. Returned only in [`GetChat`](crate::methods::GetChat). - pub join_to_send_messages: Option, - /// `true`, if all users directly joining the supergroup need to be approved by supergroup administrators. Returned only in [`GetChat`](crate::methods::GetChat). - pub join_by_request: Option, - /// Description. Returned only in [`GetChat`](crate::methods::GetChat). - pub description: Option>, - /// Primary invite link. Returned only in [`GetChat`](crate::methods::GetChat). - pub invite_link: Option>, - /// The most recent pinned message (by sending date). Returned only in [`GetChat`](crate::methods::GetChat). - pub pinned_message: Option, - /// Default chat member permissions. Returned only in [`GetChat`](crate::methods::GetChat). - pub permissions: Option, - /// For supergroups, the minimum allowed delay between consecutive messages sent by each unprivileged user; in seconds. Returned only in [`GetChat`](crate::methods::GetChat). - pub slow_mode_delay: Option, - /// The minimum number of boosts that a non-administrator user needs to add in order to ignore slow mode and chat permissions. Returned only in [`GetChat`](crate::methods::GetChat). - pub unrestrict_boost_count: Option, - /// The time after which all messages sent to the chat will be automatically deleted; in seconds. Returned only in [`GetChat`](crate::methods::GetChat). - pub message_auto_delete_time: Option, - /// `true`, if aggressive anti-spam checks are enabled in the supergroup. The field is only available to chat administrators. Returned only in [`GetChat`](crate::methods::GetChat). - pub has_aggressive_anti_spam_enabled: Option, - /// `true`, if non-administrators can only get the list of bots and administrators in the chat. Returned only in [`GetChat`](crate::methods::GetChat). - pub has_hidden_members: Option, - /// `true`, if messages from the chat can't be forwarded to other chats. Returned only in [`GetChat`](crate::methods::GetChat). - pub has_protected_content: Option, - /// `true`, if new chat members will have access to old messages; available only to chat administrators. Returned only in [`GetChat`](crate::methods::GetChat). - pub has_visible_history: Option, - /// Name of group sticker set. Returned only in [`GetChat`](crate::methods::GetChat). - pub sticker_set_name: Option>, - /// `true`, if the bot can change the group sticker set. Returned only in [`GetChat`](crate::methods::GetChat). - pub can_set_sticker_set: Option, - /// The name of the group's custom emoji sticker set. Custom emoji from this set can be used by all users and bots in the group. Returned only in [`GetChat`](crate::methods::GetChat). - pub custom_emoji_sticker_set_name: Option>, - /// Unique identifier for the linked chat, i.e. the discussion group identifier for a channel and vice versa. This identifier may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier. Returned only in [`GetChat`](crate::methods::GetChat). - pub linked_chat_id: Option, - /// The location to which the supergroup is connected. Returned only in [`GetChat`](crate::methods::GetChat). - pub location: Option, } #[derive(Debug, Clone, PartialEq, Deserialize)] pub struct Channel { - /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in i64erpreting it. But it has at most 52 significant bits, so a signed 64-bit i64eger or double-precision float type are safe for storing this identifier. + /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this identifier. pub id: i64, /// Title pub title: Box, /// Username pub username: Option>, - /// Chat photo. Returned only in [`GetChat`](crate::methods::GetChat). - pub photo: Option, - /// If non-empty, the list of all [active chat usernames](https://telegram.org/blog/topics-in-groups-collectible-usernames/ru?ln=a#collectible-usernames). Returned only in [`GetChat`](crate::methods::GetChat). - pub active_usernames: Option]>>, - /// List of available reactions allowed in the chat. If omitted, then all [emoji reactions](https://core.telegram.org/bots/api#reactiontypeemoji) are allowed. Returned only in [`GetChat`](crate::methods::GetChat). - pub available_reactions: Option]>>, - /// Identifier of the accent color for the chat name and backgrounds of the chat photo, reply header, and link preview. See [accent colors](https://core.telegram.org/bots/api#accent-colors) for more details. Returned only in [`GetChat`](crate::methods::GetChat). Always returned in [`GetChat`](crate::methods::GetChat). - pub accent_color_id: Option, - /// Custom emoji identifier of emoji chosen by the chat for the reply header and link preview background. Returned only in [`GetChat`](crate::methods::GetChat). - pub background_custom_emoji_id: Option>, - /// Identifier of the accent color for the chat's profile background. See [profile accent colors](https://core.telegram.org/bots/api#profile-accent-colors) for more details. Returned only in [`GetChat`](crate::methods::GetChat). - pub profile_accent_color_id: Option, - /// Custom emoji identifier of the emoji chosen by the chat for its profile background. Returned only in [`GetChat`](crate::methods::GetChat). - pub profile_background_custom_emoji_id: Option>, - /// Custom emoji identifier of the emoji status. Returned only in [`GetChat`](crate::methods::GetChat). - pub emoji_status_custom_emoji_id: Option>, - /// Expiration date of the emoji status in Unix time, if any. Returned only in [`GetChat`](crate::methods::GetChat). - pub emoji_status_expiration_date: Option, - /// Description. Returned only in [`GetChat`](crate::methods::GetChat). - pub description: Option>, - /// Primary invite link. Returned only in [`GetChat`](crate::methods::GetChat). - pub invite_link: Option>, - /// The most recent pinned message (by sending date). Returned only in [`GetChat`](crate::methods::GetChat). - pub pinned_message: Option, - /// The time after which all messages sent to the chat will be automatically deleted; in seconds. Returned only in [`GetChat`](crate::methods::GetChat). - pub message_auto_delete_time: Option, - /// `true`, if messages from the chat can't be forwarded to other chats. Returned only in [`GetChat`](crate::methods::GetChat). - pub has_protected_content: Option, - /// Unique identifier for the linked chat, i.e. the discussion group identifier for a channel and vice versa. This identifier may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier. Returned only in [`GetChat`](crate::methods::GetChat). - pub linked_chat_id: Option, } impl Chat { @@ -215,36 +72,6 @@ impl Chat { } } - #[allow(clippy::match_as_ref)] - #[must_use] - pub const fn username(&self) -> Option<&str> { - match self { - Self::Group(_) => None, - Self::Private(chat) => match chat.username { - Some(ref username) => Some(username), - None => None, - }, - Self::Supergroup(chat) => match chat.username { - Some(ref username) => Some(username), - None => None, - }, - Self::Channel(chat) => match chat.username { - Some(ref username) => Some(username), - None => None, - }, - } - } - - #[must_use] - pub const fn photo(&self) -> Option<&ChatPhoto> { - match self { - Self::Private(chat) => chat.photo.as_ref(), - Self::Group(chat) => chat.photo.as_ref(), - Self::Supergroup(chat) => chat.photo.as_ref(), - Self::Channel(chat) => chat.photo.as_ref(), - } - } - #[must_use] pub const fn title(&self) -> Option<&str> { match self { @@ -257,203 +84,53 @@ impl Chat { #[allow(clippy::match_as_ref)] #[must_use] - pub const fn active_usernames(&self) -> Option<&[Box]> { + pub const fn username(&self) -> Option<&str> { match self { Self::Group(_) => None, - Self::Private(chat) => match chat.active_usernames { - Some(ref active_usernames) => Some(active_usernames), - None => None, - }, - Self::Supergroup(chat) => match chat.active_usernames { - Some(ref active_usernames) => Some(active_usernames), - None => None, - }, - Self::Channel(chat) => match chat.active_usernames { - Some(ref active_usernames) => Some(active_usernames), - None => None, - }, - } - } - - #[must_use] - pub const fn birthdate(&self) -> Option<&Birthdate> { - match self { - Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, - Self::Private(chat) => chat.birthdate.as_ref(), - } - } - - #[must_use] - pub const fn business_intro(&self) -> Option<&BusinessIntro> { - match self { - Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, - Self::Private(chat) => chat.business_intro.as_ref(), - } - } - - #[allow(clippy::match_as_ref)] - #[must_use] - pub const fn business_location(&self) -> Option<&BusinessLocation> { - match self { - Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, - Self::Private(chat) => match chat.business_location { - Some(ref business_location) => Some(business_location), - None => None, - }, - } - } - - #[must_use] - pub const fn business_opening_hours(&self) -> Option<&BusinessOpeningHours> { - match self { - Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, - Self::Private(chat) => chat.business_opening_hours.as_ref(), - } - } - - #[must_use] - pub const fn personal_chat(&self) -> Option<&Chat> { - match self { - Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, - Self::Private(chat) => chat.personal_chat.as_ref(), - } - } - - #[allow(clippy::match_as_ref)] - #[must_use] - pub const fn available_reactions(&self) -> Option<&[Box]> { - match self { - Self::Group(_) | Self::Private(_) => None, - Self::Supergroup(chat) => match chat.available_reactions { - Some(ref available_reactions) => Some(available_reactions), - None => None, - }, - Self::Channel(chat) => match chat.available_reactions { - Some(ref available_reactions) => Some(available_reactions), - None => None, - }, - } - } - - #[must_use] - pub const fn accent_color_id(&self) -> Option { - match self { - Self::Group(_) | Self::Private(_) => None, - Self::Supergroup(chat) => chat.accent_color_id, - Self::Channel(chat) => chat.accent_color_id, - } - } - - #[allow(clippy::match_as_ref)] - #[must_use] - pub const fn background_custom_emoji_id(&self) -> Option<&str> { - match self { - Self::Group(_) | Self::Private(_) => None, - Self::Supergroup(chat) => match chat.background_custom_emoji_id { - Some(ref background_custom_emoji_id) => Some(background_custom_emoji_id), - None => None, - }, - Self::Channel(chat) => match chat.background_custom_emoji_id { - Some(ref background_custom_emoji_id) => Some(background_custom_emoji_id), + Self::Private(chat) => match chat.username { + Some(ref username) => Some(username), None => None, }, - } - } - - #[must_use] - pub const fn profile_accent_color_id(&self) -> Option { - match self { - Self::Group(_) | Self::Private(_) => None, - Self::Supergroup(chat) => chat.profile_accent_color_id, - Self::Channel(chat) => chat.profile_accent_color_id, - } - } - - #[allow(clippy::match_as_ref)] - #[must_use] - pub const fn profile_background_custom_emoji_id(&self) -> Option<&str> { - match self { - Self::Group(_) | Self::Private(_) => None, - Self::Supergroup(chat) => match chat.profile_background_custom_emoji_id { - Some(ref profile_background_custom_emoji_id) => { - Some(profile_background_custom_emoji_id) - } + Self::Supergroup(chat) => match chat.username { + Some(ref username) => Some(username), None => None, }, - Self::Channel(chat) => match chat.profile_background_custom_emoji_id { - Some(ref profile_background_custom_emoji_id) => { - Some(profile_background_custom_emoji_id) - } + Self::Channel(chat) => match chat.username { + Some(ref username) => Some(username), None => None, }, } } - #[must_use] - pub const fn has_visible_history(&self) -> Option { - match self { - Self::Private(_) | Self::Channel(_) => None, - Self::Group(chat) => chat.has_visible_history, - Self::Supergroup(chat) => chat.has_visible_history, - } - } - #[allow(clippy::match_as_ref)] #[must_use] - pub const fn description(&self) -> Option<&str> { + pub const fn first_name(&self) -> Option<&str> { match self { - Self::Private(_) => None, - Self::Group(chat) => match chat.description { - Some(ref description) => Some(description), - None => None, - }, - Self::Supergroup(chat) => match chat.description { - Some(ref description) => Some(description), - None => None, - }, - Self::Channel(chat) => match chat.description { - Some(ref description) => Some(description), + Self::Private(chat) => match chat.first_name { + Some(ref first_name) => Some(first_name), None => None, }, + _ => None, } } #[allow(clippy::match_as_ref)] #[must_use] - pub const fn invite_link(&self) -> Option<&str> { + pub const fn last_name(&self) -> Option<&str> { match self { - Self::Private(_) => None, - Self::Group(chat) => match chat.invite_link { - Some(ref invite_link) => Some(invite_link), - None => None, - }, - Self::Supergroup(chat) => match chat.invite_link { - Some(ref invite_link) => Some(invite_link), + Self::Private(chat) => match chat.last_name { + Some(ref last_name) => Some(last_name), None => None, }, - Self::Channel(chat) => match chat.invite_link { - Some(ref invite_link) => Some(invite_link), - None => None, - }, - } - } - - #[must_use] - pub const fn has_protected_content(&self) -> Option { - match self { - Self::Private(_) => None, - Self::Group(chat) => chat.has_protected_content, - Self::Supergroup(chat) => chat.has_protected_content, - Self::Channel(chat) => chat.has_protected_content, + _ => None, } } #[must_use] - pub const fn linked_chat_id(&self) -> Option { + pub const fn is_forum(&self) -> Option { match self { - Self::Private(_) | Self::Group(_) => None, - Self::Supergroup(chat) => chat.linked_chat_id, - Self::Channel(chat) => chat.linked_chat_id, + Self::Supergroup(chat) => chat.is_forum, + _ => None, } } } diff --git a/telers/src/types/chat_background.rs b/telers/src/types/chat_background.rs new file mode 100644 index 00000000..995f0545 --- /dev/null +++ b/telers/src/types/chat_background.rs @@ -0,0 +1,13 @@ +use super::BackgroundType; + +use serde::Deserialize; + +/// This object represents a chat background +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize)] +pub struct ChatBackground { + /// Type of the background + #[serde(rename = "type")] + pub background_type: BackgroundType, +} diff --git a/telers/src/types/chat_full_info.rs b/telers/src/types/chat_full_info.rs new file mode 100644 index 00000000..78c70dbe --- /dev/null +++ b/telers/src/types/chat_full_info.rs @@ -0,0 +1,719 @@ +use super::{ + Birthdate, BusinessIntro, BusinessLocation, BusinessOpeningHours, Chat, ChatLocation, + ChatPermissions, ChatPhoto, Message, ReactionType, +}; + +use serde::Deserialize; + +/// This object contains full information about a chat. +/// # Documentation +/// +#[derive(Debug, Clone, PartialEq, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum ChatFullInfo { + Private(Box), + Group(Box), + Supergroup(Box), + Channel(Box), +} + +#[derive(Debug, Default, Clone, PartialEq, Deserialize)] +pub struct Private { + /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in i64erpreting it. But it has at most 52 significant bits, so a signed 64-bit i64eger or double-precision float type are safe for storing this identifier. + pub id: i64, + /// Username + pub username: Option>, + /// First name of the other party + pub first_name: Option>, + /// Last name of the other party + pub last_name: Option>, + /// Identifier of the accent color for the chat name and backgrounds of the chat photo, reply header, and link preview. See [accent colors](https://core.telegram.org/bots/api#accent-colors) for more details. + pub accent_color_id: i64, + /// Chat photo. + pub photo: Option, + /// If non-empty, the list of all [active chat usernames](https://telegram.org/blog/topics-in-groups-collectible-usernames/ru?ln=a#collectible-usernames). + pub active_usernames: Option]>>, + /// The date of birth of the user. + pub birthdate: Option, + /// The intro of the business. + pub business_intro: Option, + /// The location of the business. + pub business_location: Option, + /// The opening hours of the business. + pub business_opening_hours: Option, + /// The personal channel of the user. + pub personal_chat: Option, + /// Custom emoji identifier of emoji chosen by the chat for the reply header and link preview background. + pub background_custom_emoji_id: Option>, + /// Identifier of the accent color for the chat's profile background. See [profile accent colors](https://core.telegram.org/bots/api#profile-accent-colors) for more details. + pub profile_accent_color_id: Option, + /// Custom emoji identifier of the emoji chosen by the chat for its profile background. + pub profile_background_custom_emoji_id: Option>, + /// Custom emoji identifier of emoji status of the other party. + pub emoji_status_custom_emoji_id: Option>, + /// Expiration date of the emoji status of the other party in Unix time, if any. + pub emoji_status_expiration_date: Option, + /// Bio of the other party. + pub bio: Option>, + /// `true`, if privacy settings of the other party allows to use `tg://user?id=` links only in chats with the user. + pub has_private_forwards: Option, + /// `true`, if the privacy settings of the other party restrict sending voice and video note messages. + pub has_restricted_voice_and_video_messages: Option, + /// The most recent pinned message (by sending date). + pub pinned_message: 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 + pub has_protected_content: Option, +} + +#[derive(Debug, Clone, PartialEq, Deserialize)] +pub struct Group { + /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in i64erpreting it. But it has at most 52 significant bits, so a signed 64-bit i64eger or double-precision float type are safe for storing this identifier. + pub id: i64, + /// Title + pub title: Box, + /// Chat photo. + pub photo: Option, + /// Description. + pub description: Option>, + /// Primary invite link. + pub invite_link: Option>, + /// The most recent pinned message (by sending date). + pub pinned_message: Option, + /// Default chat member permissions. + pub permissions: 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 non-administrators can only get the list of bots and administrators in the chat. + pub has_hidden_members: Option, + /// `true`, if messages from the chat can't be forwarded to other chats. + pub has_protected_content: Option, + /// `true`, if new chat members will have access to old messages; available only to chat administrators. + pub has_visible_history: Option, +} + +#[derive(Debug, Clone, PartialEq, Deserialize)] +pub struct Supergroup { + /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in i64erpreting it. But it has at most 52 significant bits, so a signed 64-bit i64eger or double-precision float type are safe for storing this identifier. + pub id: i64, + /// Title + pub title: Box, + /// Username + pub username: Option>, + /// `true`, if the chat is a forum (has [`topics`](https://telegram.org/blog/topics-in-groups-collectible-usernames#topics-in-groups) enabled) + pub is_forum: Option, + /// Identifier of the accent color for the chat name and backgrounds of the chat photo, reply header, and link preview. See [accent colors](https://core.telegram.org/bots/api#accent-colors) for more details. + pub accent_color_id: i64, + /// The maximum number of reactions that can be set on a message in the chat + pub max_reaction_count: Option, + /// Chat photo. + pub photo: Option, + /// If non-empty, the list of all [active chat usernames](https://telegram.org/blog/topics-in-groups-collectible-usernames/ru?ln=a#collectible-usernames). + pub active_usernames: Option]>>, + /// List of available reactions allowed in the chat. If omitted, then all [emoji reactions](https://core.telegram.org/bots/api#reactiontypeemoji) are allowed. + pub available_reactions: Option>, + /// Custom emoji identifier of emoji chosen by the chat for the reply header and link preview background. + pub background_custom_emoji_id: Option>, + /// Identifier of the accent color for the chat's profile background. See [profile accent colors](https://core.telegram.org/bots/api#profile-accent-colors) for more details. + pub profile_accent_color_id: Option, + /// Custom emoji identifier of the emoji chosen by the chat for its profile background. + pub profile_background_custom_emoji_id: Option>, + /// Custom emoji identifier of the emoji status. + pub emoji_status_custom_emoji_id: Option>, + /// Expiration date of the emoji status in Unix time, if any. + pub emoji_status_expiration_date: Option, + /// `true`, if users need to join the supergroup before they can send messages. + pub join_to_send_messages: Option, + /// `true`, if all users directly joining the supergroup need to be approved by supergroup administrators. + pub join_by_request: Option, + /// Description. + pub description: Option>, + /// Primary invite link. + pub invite_link: Option>, + /// The most recent pinned message (by sending date). + pub pinned_message: Option, + /// Default chat member permissions. + pub permissions: Option, + /// For supergroups, the minimum allowed delay between consecutive messages sent by each unprivileged user; in seconds. + pub slow_mode_delay: Option, + /// The minimum number of boosts that a non-administrator user needs to add in order to ignore slow mode and chat permissions. + pub unrestrict_boost_count: 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 aggressive anti-spam checks are enabled in the supergroup. The field is only available to chat administrators. + pub has_aggressive_anti_spam_enabled: Option, + /// `true`, if non-administrators can only get the list of bots and administrators in the chat. + pub has_hidden_members: Option, + /// `true`, if messages from the chat can't be forwarded to other chats. + pub has_protected_content: Option, + /// `true`, if new chat members will have access to old messages; available only to chat administrators. + pub has_visible_history: Option, + /// Name of group sticker set. + pub sticker_set_name: Option>, + /// `true`, if the bot can change the group sticker set. + pub can_set_sticker_set: Option, + /// The name of the group's custom emoji sticker set. Custom emoji from this set can be used by all users and bots in the group. + pub custom_emoji_sticker_set_name: Option>, + /// Unique identifier for the linked chat, i.e. the discussion group identifier for a channel and vice versa. This identifier may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier. + pub linked_chat_id: Option, + /// The location to which the supergroup is connected. + pub location: Option, +} + +#[derive(Debug, Clone, PartialEq, Deserialize)] +pub struct Channel { + /// Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in i64erpreting it. But it has at most 52 significant bits, so a signed 64-bit i64eger or double-precision float type are safe for storing this identifier. + pub id: i64, + /// Title + pub title: Box, + /// Username + pub username: Option>, + /// Identifier of the accent color for the chat name and backgrounds of the chat photo, reply header, and link preview. See [accent colors](https://core.telegram.org/bots/api#accent-colors) for more details. + pub accent_color_id: i64, + /// The maximum number of reactions that can be set on a message in the chat + pub max_reaction_count: Option, + /// Chat photo. + pub photo: Option, + /// If non-empty, the list of all [active chat usernames](https://telegram.org/blog/topics-in-groups-collectible-usernames/ru?ln=a#collectible-usernames). + pub active_usernames: Option]>>, + /// List of available reactions allowed in the chat. If omitted, then all [emoji reactions](https://core.telegram.org/bots/api#reactiontypeemoji) are allowed. + pub available_reactions: Option>, + /// Custom emoji identifier of emoji chosen by the chat for the reply header and link preview background. + pub background_custom_emoji_id: Option>, + /// Identifier of the accent color for the chat's profile background. See [profile accent colors](https://core.telegram.org/bots/api#profile-accent-colors) for more details. + pub profile_accent_color_id: Option, + /// Custom emoji identifier of the emoji chosen by the chat for its profile background. + pub profile_background_custom_emoji_id: Option>, + /// Custom emoji identifier of the emoji status. + pub emoji_status_custom_emoji_id: Option>, + /// Expiration date of the emoji status in Unix time, if any. + pub emoji_status_expiration_date: Option, + /// Description. + pub description: Option>, + /// Primary invite link. + pub invite_link: Option>, + /// The most recent pinned message (by sending date). + pub pinned_message: 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. + pub has_protected_content: Option, + /// Unique identifier for the linked chat, i.e. the discussion group identifier for a channel and vice versa. This identifier may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier. + pub linked_chat_id: Option, +} + +impl ChatFullInfo { + #[must_use] + pub const fn id(&self) -> i64 { + match self { + Self::Private(chat) => chat.id, + Self::Group(chat) => chat.id, + Self::Supergroup(chat) => chat.id, + Self::Channel(chat) => chat.id, + } + } + + #[must_use] + pub const fn title(&self) -> Option<&str> { + match self { + Self::Private(_) => None, + Self::Group(chat) => Some(&chat.title), + Self::Supergroup(chat) => Some(&chat.title), + Self::Channel(chat) => Some(&chat.title), + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn username(&self) -> Option<&str> { + match self { + Self::Group(_) => None, + Self::Private(chat) => match chat.username { + Some(ref username) => Some(username), + None => None, + }, + Self::Supergroup(chat) => match chat.username { + Some(ref username) => Some(username), + None => None, + }, + Self::Channel(chat) => match chat.username { + Some(ref username) => Some(username), + None => None, + }, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn first_name(&self) -> Option<&str> { + match self { + Self::Private(chat) => match chat.first_name { + Some(ref first_name) => Some(first_name), + None => None, + }, + _ => None, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn last_name(&self) -> Option<&str> { + match self { + Self::Private(chat) => match chat.last_name { + Some(ref last_name) => Some(last_name), + None => None, + }, + _ => None, + } + } + + #[must_use] + pub const fn is_forum(&self) -> Option { + match self { + Self::Supergroup(chat) => chat.is_forum, + _ => None, + } + } + + #[must_use] + pub const fn accent_color_id(&self) -> Option { + match self { + Self::Group(_) | Self::Private(_) => None, + Self::Supergroup(chat) => Some(chat.accent_color_id), + Self::Channel(chat) => Some(chat.accent_color_id), + } + } + + #[must_use] + pub const fn max_reaction_count(&self) -> Option { + match self { + Self::Group(_) | Self::Private(_) => None, + Self::Supergroup(chat) => chat.max_reaction_count, + Self::Channel(chat) => chat.max_reaction_count, + } + } + + #[must_use] + pub const fn photo(&self) -> Option<&ChatPhoto> { + match self { + Self::Private(chat) => chat.photo.as_ref(), + Self::Group(chat) => chat.photo.as_ref(), + Self::Supergroup(chat) => chat.photo.as_ref(), + Self::Channel(chat) => chat.photo.as_ref(), + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn active_usernames(&self) -> Option<&[Box]> { + match self { + Self::Group(_) => None, + Self::Private(chat) => match chat.active_usernames { + Some(ref active_usernames) => Some(active_usernames), + None => None, + }, + Self::Supergroup(chat) => match chat.active_usernames { + Some(ref active_usernames) => Some(active_usernames), + None => None, + }, + Self::Channel(chat) => match chat.active_usernames { + Some(ref active_usernames) => Some(active_usernames), + None => None, + }, + } + } + + #[must_use] + pub const fn birthdate(&self) -> Option<&Birthdate> { + match self { + Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, + Self::Private(chat) => chat.birthdate.as_ref(), + } + } + + #[must_use] + pub const fn business_intro(&self) -> Option<&BusinessIntro> { + match self { + Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, + Self::Private(chat) => chat.business_intro.as_ref(), + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn business_location(&self) -> Option<&BusinessLocation> { + match self { + Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, + Self::Private(chat) => match chat.business_location { + Some(ref business_location) => Some(business_location), + None => None, + }, + } + } + + #[must_use] + pub const fn business_opening_hours(&self) -> Option<&BusinessOpeningHours> { + match self { + Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, + Self::Private(chat) => chat.business_opening_hours.as_ref(), + } + } + + #[must_use] + pub const fn personal_chat(&self) -> Option<&Chat> { + match self { + Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, + Self::Private(chat) => chat.personal_chat.as_ref(), + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn available_reactions(&self) -> Option<&[ReactionType]> { + match self { + Self::Group(_) | Self::Private(_) => None, + Self::Supergroup(chat) => match chat.available_reactions { + Some(ref available_reactions) => Some(available_reactions), + None => None, + }, + Self::Channel(chat) => match chat.available_reactions { + Some(ref available_reactions) => Some(available_reactions), + None => None, + }, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn background_custom_emoji_id(&self) -> Option<&str> { + match self { + Self::Group(_) => None, + Self::Private(_) => match self { + Self::Private(chat) => match chat.background_custom_emoji_id { + Some(ref background_custom_emoji_id) => Some(background_custom_emoji_id), + None => None, + }, + _ => None, + }, + Self::Supergroup(chat) => match chat.background_custom_emoji_id { + Some(ref background_custom_emoji_id) => Some(background_custom_emoji_id), + None => None, + }, + Self::Channel(chat) => match chat.background_custom_emoji_id { + Some(ref background_custom_emoji_id) => Some(background_custom_emoji_id), + None => None, + }, + } + } + + #[must_use] + pub const fn profile_accent_color_id(&self) -> Option { + match self { + Self::Group(_) => None, + Self::Private(chat) => chat.profile_accent_color_id, + Self::Supergroup(chat) => chat.profile_accent_color_id, + Self::Channel(chat) => chat.profile_accent_color_id, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn profile_background_custom_emoji_id(&self) -> Option<&str> { + match self { + Self::Group(_) => None, + Self::Private(chat) => match chat.profile_background_custom_emoji_id { + Some(ref profile_background_custom_emoji_id) => { + Some(profile_background_custom_emoji_id) + } + None => None, + }, + Self::Supergroup(chat) => match chat.profile_background_custom_emoji_id { + Some(ref profile_background_custom_emoji_id) => { + Some(profile_background_custom_emoji_id) + } + None => None, + }, + Self::Channel(chat) => match chat.profile_background_custom_emoji_id { + Some(ref profile_background_custom_emoji_id) => { + Some(profile_background_custom_emoji_id) + } + None => None, + }, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn emoji_status_custom_emoji_id(&self) -> Option<&str> { + match self { + Self::Group(_) => None, + Self::Private(chat) => match chat.emoji_status_custom_emoji_id { + Some(ref emoji_status_custom_emoji_id) => Some(emoji_status_custom_emoji_id), + None => None, + }, + Self::Supergroup(chat) => match chat.emoji_status_custom_emoji_id { + Some(ref emoji_status_custom_emoji_id) => Some(emoji_status_custom_emoji_id), + None => None, + }, + Self::Channel(chat) => match chat.emoji_status_custom_emoji_id { + Some(ref emoji_status_custom_emoji_id) => Some(emoji_status_custom_emoji_id), + None => None, + }, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn emoji_status_expiration_date(&self) -> Option { + match self { + Self::Group(_) => None, + Self::Private(chat) => match chat.emoji_status_expiration_date { + Some(emoji_status_expiration_date) => Some(emoji_status_expiration_date), + None => None, + }, + Self::Supergroup(chat) => match chat.emoji_status_expiration_date { + Some(emoji_status_expiration_date) => Some(emoji_status_expiration_date), + None => None, + }, + Self::Channel(chat) => match chat.emoji_status_expiration_date { + Some(emoji_status_expiration_date) => Some(emoji_status_expiration_date), + None => None, + }, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn bio(&self) -> Option<&str> { + match self { + Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, + Self::Private(chat) => match chat.bio { + Some(ref bio) => Some(bio), + None => None, + }, + } + } + + #[must_use] + pub const fn has_private_forwards(&self) -> Option { + match self { + Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, + Self::Private(chat) => chat.has_private_forwards, + } + } + + #[must_use] + pub const fn has_restricted_voice_and_video_messages(&self) -> Option { + match self { + Self::Group(_) | Self::Supergroup(_) | Self::Channel(_) => None, + Self::Private(chat) => chat.has_restricted_voice_and_video_messages, + } + } + + #[must_use] + pub const fn join_to_send_messages(&self) -> Option { + match self { + Self::Private(_) | Self::Group(_) | Self::Channel(_) => None, + Self::Supergroup(chat) => chat.join_to_send_messages, + } + } + + #[must_use] + pub const fn join_by_request(&self) -> Option { + match self { + Self::Private(_) | Self::Group(_) | Self::Channel(_) => None, + Self::Supergroup(chat) => chat.join_by_request, + } + } + + #[must_use] + pub const fn has_visible_history(&self) -> Option { + match self { + Self::Private(_) | Self::Channel(_) => None, + Self::Group(chat) => chat.has_visible_history, + Self::Supergroup(chat) => chat.has_visible_history, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn sticker_set_name(&self) -> Option<&str> { + match self { + Self::Private(_) | Self::Group(_) | Self::Channel(_) => None, + Self::Supergroup(chat) => match chat.sticker_set_name { + Some(ref sticker_set_name) => Some(sticker_set_name), + None => None, + }, + } + } + + #[must_use] + pub const fn can_set_sticker_set(&self) -> Option { + match self { + Self::Private(_) | Self::Group(_) | Self::Channel(_) => None, + Self::Supergroup(chat) => chat.can_set_sticker_set, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn custom_emoji_sticker_set_name(&self) -> Option<&str> { + match self { + Self::Private(_) | Self::Group(_) | Self::Channel(_) => None, + Self::Supergroup(chat) => match chat.custom_emoji_sticker_set_name { + Some(ref custom_emoji_sticker_set_name) => Some(custom_emoji_sticker_set_name), + None => None, + }, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn description(&self) -> Option<&str> { + match self { + Self::Private(_) => None, + Self::Group(chat) => match chat.description { + Some(ref description) => Some(description), + None => None, + }, + Self::Supergroup(chat) => match chat.description { + Some(ref description) => Some(description), + None => None, + }, + Self::Channel(chat) => match chat.description { + Some(ref description) => Some(description), + None => None, + }, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn invite_link(&self) -> Option<&str> { + match self { + Self::Private(_) => None, + Self::Group(chat) => match chat.invite_link { + Some(ref invite_link) => Some(invite_link), + None => None, + }, + Self::Supergroup(chat) => match chat.invite_link { + Some(ref invite_link) => Some(invite_link), + None => None, + }, + Self::Channel(chat) => match chat.invite_link { + Some(ref invite_link) => Some(invite_link), + None => None, + }, + } + } + + #[allow(clippy::match_as_ref)] + #[must_use] + pub const fn pinned_message(&self) -> Option<&Message> { + match self { + Self::Private(chat) => match chat.pinned_message { + Some(ref pinned_message) => Some(pinned_message), + None => None, + }, + Self::Group(chat) => match chat.pinned_message { + Some(ref pinned_message) => Some(pinned_message), + None => None, + }, + Self::Supergroup(chat) => match chat.pinned_message { + Some(ref pinned_message) => Some(pinned_message), + None => None, + }, + Self::Channel(chat) => match chat.pinned_message { + Some(ref pinned_message) => Some(pinned_message), + None => None, + }, + } + } + + #[must_use] + pub const fn permissions(&self) -> Option<&ChatPermissions> { + match self { + Self::Private(_) | Self::Channel(_) => None, + Self::Group(chat) => chat.permissions.as_ref(), + Self::Supergroup(chat) => chat.permissions.as_ref(), + } + } + + #[must_use] + pub const fn slow_mode_delay(&self) -> Option { + match self { + Self::Private(_) | Self::Group(_) | Self::Channel(_) => None, + Self::Supergroup(chat) => chat.slow_mode_delay, + } + } + + #[must_use] + pub const fn unrestrict_boost_count(&self) -> Option { + match self { + Self::Private(_) | Self::Group(_) | Self::Channel(_) => None, + Self::Supergroup(chat) => chat.unrestrict_boost_count, + } + } + + #[must_use] + pub const fn message_auto_delete_time(&self) -> Option { + match self { + Self::Private(chat) => chat.message_auto_delete_time, + Self::Group(chat) => chat.message_auto_delete_time, + Self::Supergroup(chat) => chat.message_auto_delete_time, + Self::Channel(chat) => chat.message_auto_delete_time, + } + } + + #[must_use] + pub const fn has_aggressive_anti_spam_enabled(&self) -> Option { + match self { + Self::Private(_) | Self::Group(_) | Self::Channel(_) => None, + Self::Supergroup(chat) => chat.has_aggressive_anti_spam_enabled, + } + } + + #[must_use] + pub const fn has_hidden_members(&self) -> Option { + match self { + Self::Private(_) | Self::Channel(_) => None, + Self::Supergroup(chat) => chat.has_hidden_members, + Self::Group(chat) => chat.has_hidden_members, + } + } + + #[must_use] + pub const fn has_protected_content(&self) -> Option { + match self { + Self::Private(chat) => chat.has_protected_content, + Self::Group(chat) => chat.has_protected_content, + Self::Supergroup(chat) => chat.has_protected_content, + Self::Channel(chat) => chat.has_protected_content, + } + } + + #[must_use] + pub const fn linked_chat_id(&self) -> Option { + match self { + Self::Private(_) | Self::Group(_) => None, + Self::Supergroup(chat) => chat.linked_chat_id, + Self::Channel(chat) => chat.linked_chat_id, + } + } + + #[must_use] + pub const fn location(&self) -> Option<&ChatLocation> { + match self { + Self::Private(_) | Self::Group(_) | Self::Channel(_) => None, + Self::Supergroup(chat) => chat.location.as_ref(), + } + } +} + +impl Default for ChatFullInfo { + #[must_use] + fn default() -> Self { + Self::Private(Box::default()) + } +} diff --git a/telers/src/types/chat_member_updated.rs b/telers/src/types/chat_member_updated.rs index badb7408..49eb0e40 100644 --- a/telers/src/types/chat_member_updated.rs +++ b/telers/src/types/chat_member_updated.rs @@ -22,6 +22,8 @@ pub struct ChatMemberUpdated { pub new_chat_member: ChatMember, /// Chat invite link, which was used by the user to join the chat; for joining by invite link events only. pub invite_link: Option, + /// `true`, if the user joined the chat after sending a direct join request without using an invite link and being approved by an administrator + pub via_join_request: Option, /// `true`, if the user joined the chat via a chat folder invite link pub via_chat_folder_invite_link: Option, } diff --git a/telers/src/types/inline_keyboard_button.rs b/telers/src/types/inline_keyboard_button.rs index 5697d262..11cb880f 100644 --- a/telers/src/types/inline_keyboard_button.rs +++ b/telers/src/types/inline_keyboard_button.rs @@ -13,19 +13,19 @@ pub struct InlineKeyboardButton { pub text: String, /// HTTP or tg:// URL to be opened when the button is pressed. Links `tg://user?id=` can be used to mention a user by their identifier without using a username, if this is allowed by their privacy settings. pub url: Option, - /// Data to be sent in a [`callback query`](https://core.telegram.org/bots/api#callbackquery) to the bot when button is pressed, 1-64 bytes + /// Data to be sent in a [`callback query`](https://core.telegram.org/bots/api#callbackquery) to the bot when button is pressed, 1-64 bytes. Not supported for messages sent on behalf of a Telegram Business account. pub callback_data: Option, - /// Description of the [`Web App`](https://core.telegram.org/bots/webapps) that will be launched when the user presses the button. The Web App will be able to send an arbitrary message on behalf of the user using the method [`AnswerWebAppQuery`](crate::methods::AnswerWebAppQuery). Available only in private chats between a user and the bot. + /// Description of the [`Web App`](https://core.telegram.org/bots/webapps) that will be launched when the user presses the button. The Web App will be able to send an arbitrary message on behalf of the user using the method [`AnswerWebAppQuery`](crate::methods::AnswerWebAppQuery). Available only in private chats between a user and the bot. Not supported for messages sent on behalf of a Telegram Business account. pub web_app: Option, /// An HTTPS URL used to automatically authorize the user. Can be used as a replacement for the [`Telegram Login Widget`](https://core.telegram.org/widgets/login). pub login_url: Option, - /// If set, pressing the button will prompt the user to select one of their chats, open that chat and insert the bot's username and the specified inline query in the input field. May be empty, in which case just the bot's username will be inserted. + /// If set, pressing the button will prompt the user to select one of their chats, open that chat and insert the bot's username and the specified inline query in the input field. May be empty, in which case just the bot's username will be inserted. Not supported for messages sent on behalf of a Telegram Business account. pub switch_inline_query: Option, - /// If set, pressing the button will insert the bot's username and the specified inline query in the current chat's input field. May be empty, in which case only the bot's username will be inserted. + /// If set, pressing the button will insert the bot's username and the specified inline query in the current chat's input field. May be empty, in which case only the bot's username will be inserted. This offers a quick way for the user to open your bot in inline mode in the same chat - good for selecting something from multiple options. Not supported in channels and for messages sent on behalf of a Telegram Business account. pub switch_inline_query_current_chat: Option, - /// If set, pressing the button will prompt the user to select one of their chats of the specified type, open that chat and insert the bot's username and the specified inline query in the input field + /// If set, pressing the button will prompt the user to select one of their chats of the specified type, open that chat and insert the bot's username and the specified inline query in the input field. Not supported for messages sent on behalf of a Telegram Business account. pub switch_inline_query_chosen_chat: Option, - /// Description of the game that will be launched when the user presses the button. + /// Description of the game that will be launched when the user presses the button. This type of button **must** always be the first button in the first row. pub callback_game: Option, /// Specify `true`, to send a [`Pay button`](https://core.telegram.org/bots/api#payments). pub pay: Option, diff --git a/telers/src/types/input_poll_option.rs b/telers/src/types/input_poll_option.rs new file mode 100644 index 00000000..1920ea3d --- /dev/null +++ b/telers/src/types/input_poll_option.rs @@ -0,0 +1,29 @@ +use super::MessageEntity; + +use serde::Serialize; + +/// This object contains information about one answer option in a poll to send. +/// # Documentation +/// +#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize)] +pub struct InputPollOption { + /// Option text, 1-100 characters + pub text: String, + /// Mode for parsing entities in the text. See [formatting options](https://core.telegram.org/bots/api#formatting-options) for more details. Currently, only custom emoji entities are allowed + pub text_parse_mode: Option, + /// A JSON-serialized list of special entities that appear in the poll option text. It can be specified instead of `text_parse_mode` + pub text_entities: Option>, +} + +impl From for InputPollOption +where + T: Into, +{ + fn from(val: T) -> Self { + Self { + text: val.into(), + text_parse_mode: None, + text_entities: None, + } + } +} diff --git a/telers/src/types/message.rs b/telers/src/types/message.rs index 3b4db35e..e511b86f 100644 --- a/telers/src/types/message.rs +++ b/telers/src/types/message.rs @@ -58,6 +58,7 @@ pub enum Message { PassportData(Box), ProximityAlertTriggered(Box), ChatBoostAdded(Box), + ChatBackgroundSet(Box), ForumTopicCreated(Box), ForumTopicEdited(Box), ForumTopicClosed(Box), @@ -1367,6 +1368,28 @@ pub struct ChatBoostAdded { pub added: types::ChatBoostAdded, } +#[derive(Debug, Clone, PartialEq, Deserialize, FromEvent)] +#[event(try_from = Update)] +pub struct ChatBackgroundSet { + /// Unique message identifier inside this chat + #[serde(rename = "message_id")] + pub id: i64, + /// Unique identifier of a message thread to which the message belongs; for supergroups only + #[serde(rename = "message_thread_id")] + pub thread_id: Option, + /// Sender of the message; empty for messages sent to channels. For backward compatibility, the field contains a fake sender user in non-channel chats, if the message was sent on behalf of a chat. + pub from: Option, + /// Sender of the message, sent on behalf of a chat. For example, the channel itself for channel posts, the supergroup itself for messages from anonymous group administrators, the linked channel for messages automatically forwarded to the discussion group. For backward compatibility, the field *from* contains a fake sender user in non-channel chats, if the message was sent on behalf of a chat. + pub sender_chat: Option, + /// Date the message was sent in Unix time + pub date: i64, + /// Conversation the message belongs to + pub chat: Chat, + /// Service message: forum topic created + #[serde(rename = "chat_background_set")] + pub background: types::ChatBackground, +} + #[derive(Debug, Clone, PartialEq, Deserialize, FromEvent)] #[event(try_from = Update)] pub struct ForumTopicCreated { @@ -1758,6 +1781,7 @@ impl Message { Message::PassportData(message) => message.id, Message::ProximityAlertTriggered(message) => message.id, Message::ChatBoostAdded(message) => message.id, + Message::ChatBackgroundSet(message) => message.id, Message::ForumTopicCreated(message) => message.id, Message::ForumTopicEdited(message) => message.id, Message::ForumTopicClosed(message) => message.id, @@ -1852,6 +1876,7 @@ impl Message { Message::PassportData(message) => message.date, Message::ProximityAlertTriggered(message) => message.date, Message::ChatBoostAdded(message) => message.date, + Message::ChatBackgroundSet(message) => message.date, Message::ForumTopicCreated(message) => message.date, Message::ForumTopicEdited(message) => message.date, Message::ForumTopicClosed(message) => message.date, @@ -2013,6 +2038,7 @@ impl Message { Message::PassportData(message) => &message.chat, Message::ProximityAlertTriggered(message) => &message.chat, Message::ChatBoostAdded(message) => &message.chat, + Message::ChatBackgroundSet(message) => &message.chat, Message::ForumTopicCreated(message) => &message.chat, Message::ForumTopicEdited(message) => &message.chat, Message::ForumTopicClosed(message) => &message.chat, @@ -2134,6 +2160,7 @@ impl Message { Message::UsersShared(message) => message.from.as_ref(), Message::ChatShared(message) => message.from.as_ref(), Message::PassportData(message) => message.from.as_ref(), + Message::ChatBackgroundSet(message) => message.from.as_ref(), Message::ForumTopicCreated(message) => message.from.as_ref(), Message::ForumTopicEdited(message) => message.from.as_ref(), Message::ForumTopicClosed(message) => message.from.as_ref(), @@ -2218,6 +2245,7 @@ impl Message { Message::Invoice(message) => message.sender_chat.as_ref(), Message::SuccessfulPayment(message) => message.sender_chat.as_ref(), Message::PassportData(message) => message.sender_chat.as_ref(), + Message::ChatBackgroundSet(message) => message.sender_chat.as_ref(), Message::ForumTopicCreated(message) => message.sender_chat.as_ref(), Message::ForumTopicEdited(message) => message.sender_chat.as_ref(), Message::ForumTopicClosed(message) => message.sender_chat.as_ref(), @@ -2760,6 +2788,14 @@ impl Message { } } + #[must_use] + pub const fn chat_background(&self) -> Option<&types::ChatBackground> { + match self { + Message::ChatBackgroundSet(message) => Some(&message.background), + _ => None, + } + } + #[must_use] pub const fn forum_topic_closed(&self) -> Option<&types::ForumTopicClosed> { match self { @@ -3015,6 +3051,7 @@ impl_try_from_message!(ConnectedWebsite, ConnectedWebsite); impl_try_from_message!(PassportData, PassportData); impl_try_from_message!(ProximityAlertTriggered, ProximityAlertTriggered); impl_try_from_message!(ChatBoostAdded, ChatBoostAdded); +impl_try_from_message!(ChatBackgroundSet, ChatBackgroundSet); impl_try_from_message!(ForumTopicCreated, ForumTopicCreated); impl_try_from_message!(ForumTopicEdited, ForumTopicEdited); impl_try_from_message!(ForumTopicClosed, ForumTopicClosed); @@ -3096,6 +3133,7 @@ impl_try_from_update!(ConnectedWebsite); impl_try_from_update!(PassportData); impl_try_from_update!(ProximityAlertTriggered); impl_try_from_update!(ChatBoostAdded); +impl_try_from_update!(ChatBackgroundSet); impl_try_from_update!(ForumTopicCreated); impl_try_from_update!(ForumTopicEdited); impl_try_from_update!(ForumTopicClosed); @@ -4360,6 +4398,104 @@ mod tests { } } + #[test] + fn deserialize_chat_background_set() { + let jsons = [ + serde_json::json!({ + "message_id": 1, + "date": 0, + "chat": { + "id": -1, + "title": "test", + "type": "channel", + }, + "chat_background_set": { + "type": { + "type": "pattern", + "document": { + "file_id": "test", + "file_unique_id": "test", + }, + "fill": { + "type": "gradient", + "top_color": 123, + "bottom_color": 123, + "rotation_angle": 1, + }, + "intensity": 1, + }, + }, + }), + serde_json::json!({ + "message_id": 1, + "date": 0, + "chat": { + "id": -1, + "title": "test", + "type": "channel", + }, + "chat_background_set": { + "type": { + "type": "fill", + "fill": { + "type": "gradient", + "top_color": 123, + "bottom_color": 123, + "rotation_angle": 1, + }, + "dark_theme_dimming": 1, + }, + }, + }), + serde_json::json!({ + "message_id": 1, + "date": 0, + "chat": { + "id": -1, + "title": "test", + "type": "channel", + }, + "chat_background_set": { + "type": { + "type": "wallpaper", + "document": { + "file_id": "test", + "file_unique_id": "test", + }, + "dark_theme_dimming": 1, + }, + }, + }), + serde_json::json!({ + "message_id": 1, + "date": 0, + "chat": { + "id": -1, + "title": "test", + "type": "channel", + }, + "chat_background_set": { + "type": { + "type": "chat_theme", + "theme_name": "test", + }, + }, + }), + ]; + + for json in jsons { + let message_kind = serde_json::from_value(json.clone()).unwrap(); + let message: Message = serde_json::from_value(json).unwrap(); + + match message { + Message::ChatBackgroundSet(message) => { + assert_eq!(message, message_kind); + } + _ => panic!("Unexpected message type: {message:?}"), + } + } + } + #[test] fn deserialize_forum_topic_created() { let jsons = [serde_json::json!({ diff --git a/telers/src/types/poll.rs b/telers/src/types/poll.rs index a8d9fec0..a873f8ce 100644 --- a/telers/src/types/poll.rs +++ b/telers/src/types/poll.rs @@ -22,6 +22,8 @@ pub struct Regular { pub id: Box, /// Poll question, 1-300 characters pub question: Box, + /// Special entities that appear in the question. Currently, only custom emoji entities are allowed in poll questions + pub question_entities: Option>, /// List of poll options pub options: Box<[PollOption]>, /// Total number of users that voted in the poll @@ -45,6 +47,8 @@ pub struct Quiz { pub id: Box, /// Poll question, 1-300 characters pub question: Box, + /// Special entities that appear in the question. Currently, only custom emoji entities are allowed in poll questions + pub question_entities: Option>, /// List of poll options pub options: Box<[PollOption]>, /// Total number of users that voted in the poll diff --git a/telers/src/types/poll_option.rs b/telers/src/types/poll_option.rs index 9fc1a5e1..95647d5c 100644 --- a/telers/src/types/poll_option.rs +++ b/telers/src/types/poll_option.rs @@ -7,6 +7,8 @@ use serde::Deserialize; pub struct PollOption { /// Option text, 1-100 characters pub text: Box, + /// Special entities that appear in the option text. Currently, only custom emoji entities are allowed in poll option texts + pub entities: Option>, /// Number of users that voted for this option pub voter_count: i64, }