From b2c63ede06e94319e1dbae67e094d1c1b691e0fe Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Sun, 12 Mar 2023 12:45:40 +0200 Subject: [PATCH] Bot API 6.6 (#102) * Bot API 6.6 * modify logic for create new sticker set * new functions * fix * fix * new functions * thumbnail changes * more thumbnail changes * more thumbnail changes * fix test * bump version * fix tests * update the supported version in the readme file * address comments * fix async trait * fix * fix bugs --- CHANGELOG.md | 4 + Cargo.toml | 2 +- README.md | 12 +- src/api/telegram_api_impl.rs | 6 +- src/api_params.rs | 178 ++++++++++++++++---------- src/api_traits/async_telegram_api.rs | 182 ++++++++++++++++++++------ src/api_traits/telegram_api.rs | 183 ++++++++++++++++++++------- src/objects.rs | 114 ++++++++++------- 8 files changed, 479 insertions(+), 202 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 236bb31..7ef7bd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.24.0 (2023-03-12) + +### [Bot API 6.6](https://core.telegram.org/bots/api#march-9-2023) - [#102](https://github.com/ayrat555/frankenstein/pull/102) + ## 0.23.0 (2023-02-04) ### [Bot API 6.5](https://core.telegram.org/bots/api#february-3-2023) - [#97](https://github.com/ayrat555/frankenstein/pull/97) diff --git a/Cargo.toml b/Cargo.toml index 321007d..5026b3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "frankenstein" -version = "0.23.0" +version = "0.24.0" authors = ["Ayrat Badykov "] description = "Telegram bot API client for Rust" edition = "2018" diff --git a/README.md b/README.md index a4fbb5a..59a1614 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Telegram bot API client for Rust. -It's a complete wrapper for Telegram bot API and it's up to date with version 6.5 of the API. +It's a complete wrapper for Telegram bot API and it's up to date with version 6.6 of the API. Frankenstein data structures (rust structs and enums) are mapped one-to-one from Telegram bot API objects and method params. @@ -17,7 +17,7 @@ Add this to your Cargo.toml ```toml [dependencies] -frankenstein = "0.23" +frankenstein = "0.24" ``` ## Features @@ -35,13 +35,13 @@ frankenstein = "0.23" To use the async client add the following line to your `Cargo.toml` file: ```toml -frankenstein = { version = "0.23", default-features = false, features = ["async-http-client"] } +frankenstein = { version = "0.24", default-features = false, features = ["async-http-client"] } ``` You can also disable all features: ```toml -frankenstein = { version = "0.23", default-features = false } +frankenstein = { version = "0.24", default-features = false } ``` In this case the crate will ship only with telegram types @@ -195,7 +195,7 @@ AsyncApi::builder().api_url(api_url).client(client).build() ### Documentation -Frankenstein implements all telegram bot api methods. To see which parameters you should pass, check [docs.rs](https://docs.rs/frankenstein/0.23.0/frankenstein/api_traits/telegram_api/trait.TelegramApi.html#provided-methods) +Frankenstein implements all telegram bot api methods. To see which parameters you should pass, check [docs.rs](https://docs.rs/frankenstein/0.24.0/frankenstein/api_traits/telegram_api/trait.TelegramApi.html#provided-methods) You can check out real-world bots created using this library: @@ -213,7 +213,7 @@ The library uses `ureq` http client by default, but it can be easily replaced wi 1. `ureq` comes with a default feature (`impl`). So the feature should be disabled: ```toml -frankenstein = { version = "0.23", default-features = false, features = ["telegram-trait"] } +frankenstein = { version = "0.24", default-features = false, features = ["telegram-trait"] } ``` 2. Implement `TelegramApi` trait which requires two functions: diff --git a/src/api/telegram_api_impl.rs b/src/api/telegram_api_impl.rs index c95b73e..fad41bd 100644 --- a/src/api/telegram_api_impl.rs +++ b/src/api/telegram_api_impl.rs @@ -1034,7 +1034,7 @@ mod tests { let params = SendAudioParams::builder() .chat_id(275808073) .audio(file.clone()) - .thumb(file) + .thumbnail(file) .build(); let mut server = mockito::Server::new(); let _m = server @@ -1726,7 +1726,7 @@ mod tests { #[test] fn send_sticker_success() { - let response_string = "{\"ok\":true,\"result\":{\"message_id\":2788,\"from\":{\"id\":1276618370,\"is_bot\":true,\"first_name\":\"test_el_bot\",\"username\":\"el_mon_test_bot\"},\"date\":1619245784,\"chat\":{\"id\":275808073,\"type\":\"private\",\"username\":\"Ayrat555\",\"first_name\":\"Ayrat\",\"last_name\":\"Badykov\"},\"sticker\":{\"file_id\":\"CAACAgIAAxkDAAIK5GCDutgNxc07rqqtjkGWrGskbHfQAAIMEAACRx8ZSKJ6Z5GkdVHcHwQ\",\"file_unique_id\":\"AgADDBAAAkcfGUg\",\"type\":\"regular\",\"width\":512,\"height\":512,\"is_animated\":false,\"is_video\":false,\"thumb\":{\"file_id\":\"AAMCAgADGQMAAgrkYIO62A3FzTuuqq2OQZasayRsd9AAAgwQAAJHHxlIonpnkaR1Udz29bujLgADAQAHbQADzR4AAh8E\",\"file_unique_id\":\"AQAD9vW7oy4AA80eAAI\",\"width\":320,\"height\":320,\"file_size\":19264},\"file_size\":36596}}}"; + let response_string = "{\"ok\":true,\"result\":{\"message_id\":2788,\"from\":{\"id\":1276618370,\"is_bot\":true,\"first_name\":\"test_el_bot\",\"username\":\"el_mon_test_bot\"},\"date\":1619245784,\"chat\":{\"id\":275808073,\"type\":\"private\",\"username\":\"Ayrat555\",\"first_name\":\"Ayrat\",\"last_name\":\"Badykov\"},\"sticker\":{\"file_id\":\"CAACAgIAAxkDAAIK5GCDutgNxc07rqqtjkGWrGskbHfQAAIMEAACRx8ZSKJ6Z5GkdVHcHwQ\",\"file_unique_id\":\"AgADDBAAAkcfGUg\",\"type\":\"regular\",\"width\":512,\"height\":512,\"is_animated\":false,\"is_video\":false,\"thumbnail\":{\"file_id\":\"AAMCAgADGQMAAgrkYIO62A3FzTuuqq2OQZasayRsd9AAAgwQAAJHHxlIonpnkaR1Udz29bujLgADAQAHbQADzR4AAh8E\",\"file_unique_id\":\"AQAD9vW7oy4AA80eAAI\",\"width\":320,\"height\":320,\"file_size\":19264},\"file_size\":36596}}}"; let file = std::path::PathBuf::from("./frankenstein_logo.png"); let params = SendStickerParams::builder() @@ -1750,7 +1750,7 @@ mod tests { #[test] fn get_sticker_set_success() { - let response_string = "{\"ok\":true,\"result\":{\"name\":\"unocards\",\"title\":\"UNO Bot\",\"sticker_type\":\"regular\",\"is_animated\":false,\"is_video\":false,\"contains_masks\":false,\"stickers\":[{\"file_id\":\"CAACAgQAAxUAAWCDxAQVJ6X7FGiBD5NyjN5DDvgfAALZAQACX1eZAAEqnpNt3SpG_x8E\",\"file_unique_id\":\"AgAD2QEAAl9XmQAB\",\"type\":\"regular\",\"width\":342,\"height\":512,\"is_animated\":false,\"is_video\":false,\"thumb\":{\"file_id\":\"AAMCBAADFQABYIPEBBUnpfsUaIEPk3KM3kMO-B8AAtkBAAJfV5kAASqek23dKkb_P75BGQAEAQAHbQADBBEAAh8E\",\"file_unique_id\":\"AQADP75BGQAEBBEAAg\",\"width\":85,\"height\":128,\"file_size\":2452},\"emoji\":\"dd\",\"set_name\":\"unocards\",\"file_size\":8898}]}}"; + let response_string = "{\"ok\":true,\"result\":{\"name\":\"unocards\",\"title\":\"UNO Bot\",\"sticker_type\":\"regular\",\"is_animated\":false,\"is_video\":false,\"contains_masks\":false,\"stickers\":[{\"file_id\":\"CAACAgQAAxUAAWCDxAQVJ6X7FGiBD5NyjN5DDvgfAALZAQACX1eZAAEqnpNt3SpG_x8E\",\"file_unique_id\":\"AgAD2QEAAl9XmQAB\",\"type\":\"regular\",\"width\":342,\"height\":512,\"is_animated\":false,\"is_video\":false,\"thumbnail\":{\"file_id\":\"AAMCBAADFQABYIPEBBUnpfsUaIEPk3KM3kMO-B8AAtkBAAJfV5kAASqek23dKkb_P75BGQAEAQAHbQADBBEAAh8E\",\"file_unique_id\":\"AQADP75BGQAEBBEAAg\",\"width\":85,\"height\":128,\"file_size\":2452},\"emoji\":\"dd\",\"set_name\":\"unocards\",\"file_size\":8898}]}}"; let params = GetStickerSetParams::builder().name("unocards").build(); let mut server = mockito::Server::new(); diff --git a/src/api_params.rs b/src/api_params.rs index aac1aba..4af8dcc 100644 --- a/src/api_params.rs +++ b/src/api_params.rs @@ -7,12 +7,12 @@ use crate::objects::{ InlineQueryResultCachedVoice, InlineQueryResultContact, InlineQueryResultDocument, InlineQueryResultGame, InlineQueryResultGif, InlineQueryResultLocation, InlineQueryResultMpeg4Gif, InlineQueryResultPhoto, InlineQueryResultVenue, - InlineQueryResultVideo, InlineQueryResultVoice, LabeledPrice, MaskPosition, MenuButton, - MessageEntity, PassportElementErrorDataField, PassportElementErrorFile, + InlineQueryResultVideo, InlineQueryResultVoice, InputSticker, LabeledPrice, MaskPosition, + MenuButton, MessageEntity, PassportElementErrorDataField, PassportElementErrorFile, PassportElementErrorFiles, PassportElementErrorFrontSide, PassportElementErrorReverseSide, PassportElementErrorSelfie, PassportElementErrorTranslationFile, PassportElementErrorTranslationFiles, PassportElementErrorUnspecified, PollType, - ReplyKeyboardMarkup, ReplyKeyboardRemove, ShippingOption, StickerType, + ReplyKeyboardMarkup, ReplyKeyboardRemove, ShippingOption, StickerFormat, StickerType, }; use crate::{AllowedUpdate, ParseMode}; use serde::Deserialize; @@ -175,34 +175,23 @@ pub enum ChatAction { } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -#[serde(tag = "type")] +#[serde(tag = "type", rename_all = "lowercase")] pub enum Media { - #[serde(rename = "audio")] Audio(InputMediaAudio), - #[serde(rename = "document")] Document(InputMediaDocument), - #[serde(rename = "photo")] Photo(InputMediaPhoto), - #[serde(rename = "video")] Video(InputMediaVideo), } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -#[serde(tag = "type")] +#[serde(tag = "type", rename_all = "snake_case")] pub enum BotCommandScope { - #[serde(rename = "default")] Default, - #[serde(rename = "all_private_chats")] AllPrivateChats, - #[serde(rename = "all_group_chats")] AllGroupChats, - #[serde(rename = "all_chat_administrators")] AllChatAdministrators, - #[serde(rename = "chat")] Chat(BotCommandScopeChat), - #[serde(rename = "chat_administrators")] ChatAdministrators(BotCommandScopeChatAdministrators), - #[serde(rename = "chat_member")] ChatMember(BotCommandScopeChatMember), } @@ -488,7 +477,7 @@ pub struct SendAudioParams { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -525,7 +514,7 @@ pub struct SendDocumentParams { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -590,7 +579,7 @@ pub struct SendVideoParams { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -659,7 +648,7 @@ pub struct SendAnimationParams { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -769,7 +758,7 @@ pub struct SendVideoNoteParams { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -1629,6 +1618,42 @@ pub struct SetMyCommandsParams { pub language_code: Option, } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] +pub struct SetMyDescriptionParams { + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into, strip_option), default)] + pub description: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into, strip_option), default)] + pub language_code: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] +pub struct GetMyDescriptionParams { + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into, strip_option), default)] + pub language_code: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] +pub struct SetMyShortDescriptionParams { + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into, strip_option), default)] + pub short_description: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into, strip_option), default)] + pub language_code: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] +pub struct GetMyShortDescriptionParams { + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into, strip_option), default)] + pub language_code: Option, +} + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] pub struct GetMyCommandsParams { #[serde(skip_serializing_if = "Option::is_none")] @@ -1789,6 +1814,10 @@ pub struct SendStickerParams { #[builder(setter(into))] pub sticker: File, + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into, strip_option), default)] + pub emoji: Option, + #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] pub disable_notification: Option, @@ -1820,7 +1849,9 @@ pub struct GetStickerSetParams { pub struct UploadStickerFileParams { pub user_id: u64, - pub png_sticker: InputFile, + pub sticker: InputFile, + + pub sticker_format: StickerFormat, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Builder)] @@ -1833,34 +1864,17 @@ pub struct CreateNewStickerSetParams { #[builder(setter(into))] pub title: String, - #[serde(skip_serializing_if = "Option::is_none")] - #[builder(setter(into, strip_option), default)] - pub png_sticker: Option, + pub stickers: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - #[builder(setter(into, strip_option), default)] - pub tgs_sticker: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - #[builder(setter(into, strip_option), default)] - pub webm_sticker: Option, + pub sticker_format: StickerFormat, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option))] pub sticker_type: Option, - #[builder(setter(into))] - pub emojis: String, - - #[doc(hidden)] - #[deprecated(since = "0.19.2", note = "Please use `sticker_type` instead")] - #[serde(skip_serializing_if = "Option::is_none")] - #[builder(setter(into, strip_option), default)] - pub contains_masks: Option, - #[serde(skip_serializing_if = "Option::is_none")] - #[builder(setter(into, strip_option), default)] - pub mask_position: Option, + #[builder(setter(into, strip_option))] + pub needs_repainting: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] @@ -1876,20 +1890,45 @@ pub struct AddStickerToSetParams { #[builder(setter(into))] pub name: String, - #[serde(skip_serializing_if = "Option::is_none")] - #[builder(setter(into, strip_option), default)] - pub png_sticker: Option, + pub sticker: InputSticker, +} - #[serde(skip_serializing_if = "Option::is_none")] - #[builder(setter(into, strip_option), default)] - pub tgs_sticker: Option, +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] +pub struct SetStickerPositionInSetParams { + #[builder(setter(into))] + pub sticker: String, + + pub position: u32, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] +pub struct DeleteStickerFromSetParams { + #[builder(setter(into))] + pub sticker: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] +pub struct SetStickerEmojiListParams { + #[builder(setter(into))] + pub sticker: String, + + pub emoji_list: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] +pub struct SetStickerKeywordsParams { + #[builder(setter(into))] + pub sticker: String, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub webm_sticker: Option, + pub keywords: Option>, +} +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Builder)] +pub struct SetStickerMaskPositionParams { #[builder(setter(into))] - pub emojis: String, + pub sticker: String, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -1897,29 +1936,40 @@ pub struct AddStickerToSetParams { } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] -pub struct SetStickerPositionInSetParams { +pub struct SetStickerSetTitleParams { #[builder(setter(into))] - pub sticker: String, + pub name: String, - pub position: u32, + #[builder(setter(into))] + pub title: String, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] -pub struct DeleteStickerFromSetParams { +pub struct SetStickerSetThumbnailParams { #[builder(setter(into))] - pub sticker: String, + pub name: String, + + pub user_id: u64, + + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into, strip_option), default)] + pub thumbnail: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] -pub struct SetStickerSetThumbParams { +pub struct SetCustomEmojiStickerSetThumbnailParams { #[builder(setter(into))] pub name: String, - pub user_id: u64, - #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub custom_emoji_id: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] +pub struct DeleteStickerSetParams { + #[builder(setter(into))] + pub name: String, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Builder)] @@ -2272,7 +2322,7 @@ pub struct InputMediaVideo { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -2314,7 +2364,7 @@ pub struct InputMediaAnimation { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -2352,7 +2402,7 @@ pub struct InputMediaAudio { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -2386,7 +2436,7 @@ pub struct InputMediaDocument { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] diff --git a/src/api_traits/async_telegram_api.rs b/src/api_traits/async_telegram_api.rs index 47f292c..a431918 100644 --- a/src/api_traits/async_telegram_api.rs +++ b/src/api_traits/async_telegram_api.rs @@ -23,6 +23,7 @@ use crate::api_params::DeleteForumTopicParams; use crate::api_params::DeleteMessageParams; use crate::api_params::DeleteMyCommandsParams; use crate::api_params::DeleteStickerFromSetParams; +use crate::api_params::DeleteStickerSetParams; use crate::api_params::DeleteWebhookParams; use crate::api_params::EditChatInviteLinkParams; use crate::api_params::EditForumTopicParams; @@ -45,6 +46,8 @@ use crate::api_params::GetFileParams; use crate::api_params::GetGameHighScoresParams; use crate::api_params::GetMyCommandsParams; use crate::api_params::GetMyDefaultAdministratorRightsParams; +use crate::api_params::GetMyDescriptionParams; +use crate::api_params::GetMyShortDescriptionParams; use crate::api_params::GetStickerSetParams; use crate::api_params::GetUpdatesParams; use crate::api_params::GetUserProfilePhotosParams; @@ -83,11 +86,18 @@ use crate::api_params::SetChatPermissionsParams; use crate::api_params::SetChatPhotoParams; use crate::api_params::SetChatStickerSetParams; use crate::api_params::SetChatTitleParams; +use crate::api_params::SetCustomEmojiStickerSetThumbnailParams; use crate::api_params::SetGameScoreParams; use crate::api_params::SetMyCommandsParams; use crate::api_params::SetMyDefaultAdministratorRightsParams; +use crate::api_params::SetMyDescriptionParams; +use crate::api_params::SetMyShortDescriptionParams; +use crate::api_params::SetStickerEmojiListParams; +use crate::api_params::SetStickerKeywordsParams; +use crate::api_params::SetStickerMaskPositionParams; use crate::api_params::SetStickerPositionInSetParams; -use crate::api_params::SetStickerSetThumbParams; +use crate::api_params::SetStickerSetThumbnailParams; +use crate::api_params::SetStickerSetTitleParams; use crate::api_params::SetWebhookParams; use crate::api_params::StopMessageLiveLocationParams; use crate::api_params::StopPollParams; @@ -98,6 +108,8 @@ use crate::api_params::UnpinAllForumTopicMessagesParams; use crate::api_params::UnpinChatMessageParams; use crate::api_params::UploadStickerFileParams; use crate::objects::BotCommand; +use crate::objects::BotDescription; +use crate::objects::BotShortDescription; use crate::objects::Chat; use crate::objects::ChatAdministratorRights; use crate::objects::ChatInviteLink; @@ -105,6 +117,7 @@ use crate::objects::ChatMember; use crate::objects::File as FileObject; use crate::objects::ForumTopic; use crate::objects::GameHighScore; +use crate::objects::InputSticker; use crate::objects::MenuButton; use crate::objects::Message; use crate::objects::MessageId; @@ -207,8 +220,8 @@ pub trait AsyncTelegramApi { files.push(("audio", input_file.path.clone())); } - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -239,12 +252,12 @@ pub trait AsyncTelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &audio.thumb { + if let Some(File::InputFile(input_file)) = &audio.thumbnail { let name = format!("file{file_idx}"); let attach_name = format!("attach://{name}"); file_idx += 1; - new_audio.thumb = Some(File::String(attach_name)); + new_audio.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -296,12 +309,12 @@ pub trait AsyncTelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &video.thumb { + if let Some(File::InputFile(input_file)) = &video.thumbnail { let name = format!("file{file_idx}"); let attach_name = format!("attach://{name}"); file_idx += 1; - new_video.thumb = Some(File::String(attach_name)); + new_video.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -334,8 +347,8 @@ pub trait AsyncTelegramApi { files.push(("document", input_file.path.clone())); } - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -353,8 +366,8 @@ pub trait AsyncTelegramApi { files.push(("video", input_file.path.clone())); } - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -372,8 +385,8 @@ pub trait AsyncTelegramApi { files.push(("animation", input_file.path.clone())); } - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -406,8 +419,8 @@ pub trait AsyncTelegramApi { files.push(("video_note", input_file.path.clone())); } - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -779,6 +792,34 @@ pub trait AsyncTelegramApi { self.request("getMyCommands", Some(params)).await } + async fn set_my_description( + &self, + params: &SetMyDescriptionParams, + ) -> Result, Self::Error> { + self.request("setMyDescription", Some(params)).await + } + + async fn get_my_description( + &self, + params: &GetMyDescriptionParams, + ) -> Result, Self::Error> { + self.request("getMyDescription", Some(params)).await + } + + async fn set_my_short_description( + &self, + params: &SetMyShortDescriptionParams, + ) -> Result, Self::Error> { + self.request("setMyShortDescription", Some(params)).await + } + + async fn get_my_short_description( + &self, + params: &GetMyShortDescriptionParams, + ) -> Result, Self::Error> { + self.request("getMyShortDescription", Some(params)).await + } + async fn delete_my_commands( &self, params: &DeleteMyCommandsParams, @@ -827,11 +868,11 @@ pub trait AsyncTelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &animation.thumb { + if let Some(File::InputFile(input_file)) = &animation.thumbnail { let name = "animation_thumb".to_string(); let attach_name = format!("attach://{name}"); - new_animation.thumb = Some(File::String(attach_name)); + new_animation.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -850,11 +891,11 @@ pub trait AsyncTelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &document.thumb { + if let Some(File::InputFile(input_file)) = &document.thumbnail { let name = "document_thumb".to_string(); let attach_name = format!("attach://{name}"); - new_document.thumb = Some(File::String(attach_name)); + new_document.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -873,11 +914,11 @@ pub trait AsyncTelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &audio.thumb { + if let Some(File::InputFile(input_file)) = &audio.thumbnail { let name = "audio_thumb".to_string(); let attach_name = format!("attach://{name}"); - new_audio.thumb = Some(File::String(attach_name)); + new_audio.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -910,11 +951,11 @@ pub trait AsyncTelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &video.thumb { + if let Some(File::InputFile(input_file)) = &video.thumbnail { let name = "video_thumb".to_string(); let attach_name = format!("attach://{name}"); - new_video.thumb = Some(File::String(attach_name)); + new_video.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -982,12 +1023,12 @@ pub trait AsyncTelegramApi { &self, params: &UploadStickerFileParams, ) -> Result, Self::Error> { - let sticker = ¶ms.png_sticker; + let sticker = ¶ms.sticker; self.request_with_form_data( "uploadStickerFile", params, - vec![("png_sticker", sticker.path.clone())], + vec![("sticker", sticker.path.clone())], ) .await } @@ -997,17 +1038,35 @@ pub trait AsyncTelegramApi { params: &CreateNewStickerSetParams, ) -> Result, Self::Error> { let method_name = "createNewStickerSet"; - let mut files: Vec<(&str, PathBuf)> = vec![]; + let mut new_stickers: Vec = vec![]; + let mut files: Vec<(String, PathBuf)> = vec![]; + let mut file_idx = 0; - if let Some(File::InputFile(input_file)) = ¶ms.png_sticker { - files.push(("png_sticker", input_file.path.clone())); - } + for sticker in ¶ms.stickers { + let mut new_sticker = sticker.clone(); + + if let File::InputFile(input_file) = &sticker.sticker { + let name = format!("file{file_idx}"); + let attach_name = format!("attach://{name}"); + file_idx += 1; - if let Some(input_file) = ¶ms.tgs_sticker { - files.push(("tgs_sticker", input_file.path.clone())); + new_sticker.sticker = File::String(attach_name); + + files.push((name, input_file.path.clone())); + }; + + new_stickers.push(new_sticker); } - self.request_with_possible_form_data(method_name, params, files) + let mut new_params = params.clone(); + new_params.stickers = new_stickers; + + let files_with_str_names: Vec<(&str, PathBuf)> = files + .iter() + .map(|(key, path)| (key.as_str(), path.clone())) + .collect(); + + self.request_with_possible_form_data(method_name, &new_params, files_with_str_names) .await } @@ -1024,12 +1083,8 @@ pub trait AsyncTelegramApi { let method_name = "addStickerToSet"; let mut files: Vec<(&str, PathBuf)> = vec![]; - if let Some(File::InputFile(input_file)) = ¶ms.png_sticker { - files.push(("png_sticker", input_file.path.clone())); - } - - if let Some(input_file) = ¶ms.tgs_sticker { - files.push(("tgs_sticker", input_file.path.clone())); + if let File::InputFile(input_file) = ¶ms.sticker.sticker { + files.push(("sticker", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -1050,21 +1105,64 @@ pub trait AsyncTelegramApi { self.request("deleteStickerFromSet", Some(params)).await } + async fn set_sticker_emoji_list( + &self, + params: &SetStickerEmojiListParams, + ) -> Result, Self::Error> { + self.request("setStickerEmojiList", Some(params)).await + } + + async fn set_sticker_keywords( + &self, + params: &SetStickerKeywordsParams, + ) -> Result, Self::Error> { + self.request("setStickerKeywords", Some(params)).await + } + + async fn set_sticker_mask_position( + &self, + params: &SetStickerMaskPositionParams, + ) -> Result, Self::Error> { + self.request("setStickerMaskPosition", Some(params)).await + } + + async fn set_sticker_set_title( + &self, + params: &SetStickerSetTitleParams, + ) -> Result, Self::Error> { + self.request("setStickerSetTitle", Some(params)).await + } + async fn set_sticker_set_thumb( &self, - params: &SetStickerSetThumbParams, + params: &SetStickerSetThumbnailParams, ) -> Result, Self::Error> { - let method_name = "setStickerSetThumb"; + let method_name = "setStickerSetThumbnail"; let mut files: Vec<(&str, PathBuf)> = vec![]; - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) .await } + async fn set_custom_emoji_sticker_set_thumbnail( + &self, + params: &SetCustomEmojiStickerSetThumbnailParams, + ) -> Result, Self::Error> { + self.request("setCustomEmojiStickerSetThumbnail", Some(params)) + .await + } + + async fn delete_sticker_set( + &self, + params: &DeleteStickerSetParams, + ) -> Result, Self::Error> { + self.request("deleteStickerSet", Some(params)).await + } + async fn send_invoice( &self, params: &SendInvoiceParams, diff --git a/src/api_traits/telegram_api.rs b/src/api_traits/telegram_api.rs index c92533c..9cbed7b 100644 --- a/src/api_traits/telegram_api.rs +++ b/src/api_traits/telegram_api.rs @@ -23,6 +23,7 @@ use crate::api_params::DeleteForumTopicParams; use crate::api_params::DeleteMessageParams; use crate::api_params::DeleteMyCommandsParams; use crate::api_params::DeleteStickerFromSetParams; +use crate::api_params::DeleteStickerSetParams; use crate::api_params::DeleteWebhookParams; use crate::api_params::EditChatInviteLinkParams; use crate::api_params::EditForumTopicParams; @@ -44,6 +45,8 @@ use crate::api_params::GetFileParams; use crate::api_params::GetGameHighScoresParams; use crate::api_params::GetMyCommandsParams; use crate::api_params::GetMyDefaultAdministratorRightsParams; +use crate::api_params::GetMyDescriptionParams; +use crate::api_params::GetMyShortDescriptionParams; use crate::api_params::GetStickerSetParams; use crate::api_params::GetUpdatesParams; use crate::api_params::GetUserProfilePhotosParams; @@ -82,11 +85,18 @@ use crate::api_params::SetChatPermissionsParams; use crate::api_params::SetChatPhotoParams; use crate::api_params::SetChatStickerSetParams; use crate::api_params::SetChatTitleParams; +use crate::api_params::SetCustomEmojiStickerSetThumbnailParams; use crate::api_params::SetGameScoreParams; use crate::api_params::SetMyCommandsParams; use crate::api_params::SetMyDefaultAdministratorRightsParams; +use crate::api_params::SetMyDescriptionParams; +use crate::api_params::SetMyShortDescriptionParams; +use crate::api_params::SetStickerEmojiListParams; +use crate::api_params::SetStickerKeywordsParams; +use crate::api_params::SetStickerMaskPositionParams; use crate::api_params::SetStickerPositionInSetParams; -use crate::api_params::SetStickerSetThumbParams; +use crate::api_params::SetStickerSetThumbnailParams; +use crate::api_params::SetStickerSetTitleParams; use crate::api_params::SetWebhookParams; use crate::api_params::StopMessageLiveLocationParams; use crate::api_params::StopPollParams; @@ -97,6 +107,8 @@ use crate::api_params::UnpinAllForumTopicMessagesParams; use crate::api_params::UnpinChatMessageParams; use crate::api_params::UploadStickerFileParams; use crate::objects::BotCommand; +use crate::objects::BotDescription; +use crate::objects::BotShortDescription; use crate::objects::Chat; use crate::objects::ChatAdministratorRights; use crate::objects::ChatInviteLink; @@ -104,6 +116,7 @@ use crate::objects::ChatMember; use crate::objects::File as FileObject; use crate::objects::ForumTopic; use crate::objects::GameHighScore; +use crate::objects::InputSticker; use crate::objects::MenuButton; use crate::objects::Message; use crate::objects::MessageId; @@ -195,8 +208,8 @@ pub trait TelegramApi { files.push(("audio", input_file.path.clone())); } - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -226,12 +239,12 @@ pub trait TelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &audio.thumb { + if let Some(File::InputFile(input_file)) = &audio.thumbnail { let name = format!("file{file_idx}"); let attach_name = format!("attach://{name}"); file_idx += 1; - new_audio.thumb = Some(File::String(attach_name)); + new_audio.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -283,12 +296,12 @@ pub trait TelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &video.thumb { + if let Some(File::InputFile(input_file)) = &video.thumbnail { let name = format!("file{file_idx}"); let attach_name = format!("attach://{name}"); file_idx += 1; - new_video.thumb = Some(File::String(attach_name)); + new_video.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -320,8 +333,8 @@ pub trait TelegramApi { files.push(("document", input_file.path.clone())); } - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -335,8 +348,8 @@ pub trait TelegramApi { files.push(("video", input_file.path.clone())); } - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -353,8 +366,8 @@ pub trait TelegramApi { files.push(("animation", input_file.path.clone())); } - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -382,8 +395,8 @@ pub trait TelegramApi { files.push(("video_note", input_file.path.clone())); } - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -734,6 +747,34 @@ pub trait TelegramApi { self.request("getMyCommands", Some(params)) } + fn set_my_description( + &self, + params: &SetMyDescriptionParams, + ) -> Result, Self::Error> { + self.request("setMyDescription", Some(params)) + } + + fn get_my_description( + &self, + params: &GetMyDescriptionParams, + ) -> Result, Self::Error> { + self.request("getMyDescription", Some(params)) + } + + fn set_my_short_description( + &self, + params: &SetMyShortDescriptionParams, + ) -> Result, Self::Error> { + self.request("setMyShortDescription", Some(params)) + } + + fn get_my_short_description( + &self, + params: &GetMyShortDescriptionParams, + ) -> Result, Self::Error> { + self.request("getMyShortDescription", Some(params)) + } + fn delete_my_commands( &self, params: &DeleteMyCommandsParams, @@ -782,11 +823,11 @@ pub trait TelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &animation.thumb { + if let Some(File::InputFile(input_file)) = &animation.thumbnail { let name = "animation_thumb".to_string(); let attach_name = format!("attach://{name}"); - new_animation.thumb = Some(File::String(attach_name)); + new_animation.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -805,11 +846,11 @@ pub trait TelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &document.thumb { + if let Some(File::InputFile(input_file)) = &document.thumbnail { let name = "document_thumb".to_string(); let attach_name = format!("attach://{name}"); - new_document.thumb = Some(File::String(attach_name)); + new_document.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -828,11 +869,11 @@ pub trait TelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &audio.thumb { + if let Some(File::InputFile(input_file)) = &audio.thumbnail { let name = "audio_thumb".to_string(); let attach_name = format!("attach://{name}"); - new_audio.thumb = Some(File::String(attach_name)); + new_audio.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -865,11 +906,11 @@ pub trait TelegramApi { files.push((name, input_file.path.clone())); }; - if let Some(File::InputFile(input_file)) = &video.thumb { + if let Some(File::InputFile(input_file)) = &video.thumbnail { let name = "video_thumb".to_string(); let attach_name = format!("attach://{name}"); - new_video.thumb = Some(File::String(attach_name)); + new_video.thumbnail = Some(File::String(attach_name)); files.push((name, input_file.path.clone())); }; @@ -932,12 +973,12 @@ pub trait TelegramApi { &self, params: &UploadStickerFileParams, ) -> Result, Self::Error> { - let sticker = ¶ms.png_sticker; + let sticker = ¶ms.sticker; self.request_with_form_data( "uploadStickerFile", params, - vec![("png_sticker", sticker.path.clone())], + vec![("sticker", sticker.path.clone())], ) } @@ -946,17 +987,35 @@ pub trait TelegramApi { params: &CreateNewStickerSetParams, ) -> Result, Self::Error> { let method_name = "createNewStickerSet"; - let mut files: Vec<(&str, PathBuf)> = vec![]; + let mut new_stickers: Vec = vec![]; + let mut files: Vec<(String, PathBuf)> = vec![]; + let mut file_idx = 0; - if let Some(File::InputFile(input_file)) = ¶ms.png_sticker { - files.push(("png_sticker", input_file.path.clone())); - } + for sticker in ¶ms.stickers { + let mut new_sticker = sticker.clone(); + + if let File::InputFile(input_file) = &sticker.sticker { + let name = format!("file{file_idx}"); + let attach_name = format!("attach://{name}"); + file_idx += 1; + + new_sticker.sticker = File::String(attach_name); + + files.push((name, input_file.path.clone())); + }; - if let Some(input_file) = ¶ms.tgs_sticker { - files.push(("tgs_sticker", input_file.path.clone())); + new_stickers.push(new_sticker); } - self.request_with_possible_form_data(method_name, params, files) + let mut new_params = params.clone(); + new_params.stickers = new_stickers; + + let files_with_str_names: Vec<(&str, PathBuf)> = files + .iter() + .map(|(key, path)| (key.as_str(), path.clone())) + .collect(); + + self.request_with_possible_form_data(method_name, &new_params, files_with_str_names) } fn get_custom_emoji_stickers( @@ -973,12 +1032,8 @@ pub trait TelegramApi { let method_name = "addStickerToSet"; let mut files: Vec<(&str, PathBuf)> = vec![]; - if let Some(File::InputFile(input_file)) = ¶ms.png_sticker { - files.push(("png_sticker", input_file.path.clone())); - } - - if let Some(input_file) = ¶ms.tgs_sticker { - files.push(("tgs_sticker", input_file.path.clone())); + if let File::InputFile(input_file) = ¶ms.sticker.sticker { + files.push(("sticker", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) @@ -998,20 +1053,62 @@ pub trait TelegramApi { self.request("deleteStickerFromSet", Some(params)) } - fn set_sticker_set_thumb( + fn set_sticker_emoji_list( &self, - params: &SetStickerSetThumbParams, + params: &SetStickerEmojiListParams, ) -> Result, Self::Error> { - let method_name = "setStickerSetThumb"; + self.request("setStickerEmojiList", Some(params)) + } + + fn set_sticker_keywords( + &self, + params: &SetStickerKeywordsParams, + ) -> Result, Self::Error> { + self.request("setStickerKeywords", Some(params)) + } + + fn set_sticker_mask_position( + &self, + params: &SetStickerMaskPositionParams, + ) -> Result, Self::Error> { + self.request("setStickerMaskPosition", Some(params)) + } + + fn set_sticker_set_title( + &self, + params: &SetStickerSetTitleParams, + ) -> Result, Self::Error> { + self.request("setStickerSetTitle", Some(params)) + } + + fn set_sticker_set_thumbnail( + &self, + params: &SetStickerSetThumbnailParams, + ) -> Result, Self::Error> { + let method_name = "setStickerSetThumbnail"; let mut files: Vec<(&str, PathBuf)> = vec![]; - if let Some(File::InputFile(input_file)) = ¶ms.thumb { - files.push(("thumb", input_file.path.clone())); + if let Some(File::InputFile(input_file)) = ¶ms.thumbnail { + files.push(("thumbnail", input_file.path.clone())); } self.request_with_possible_form_data(method_name, params, files) } + fn set_custom_emoji_sticker_set_thumbnail( + &self, + params: &SetCustomEmojiStickerSetThumbnailParams, + ) -> Result, Self::Error> { + self.request("setCustomEmojiStickerSetThumbnail", Some(params)) + } + + fn delete_sticker_set( + &self, + params: &DeleteStickerSetParams, + ) -> Result, Self::Error> { + self.request("deleteStickerSet", Some(params)) + } + fn send_invoice( &self, params: &SendInvoiceParams, diff --git a/src/objects.rs b/src/objects.rs index 63e9890..645feaa 100644 --- a/src/objects.rs +++ b/src/objects.rs @@ -1,19 +1,26 @@ #![allow(deprecated)] +use super::api_params::File as InputFile; use serde::{Deserialize, Serialize}; use typed_builder::TypedBuilder as Builder; use crate::ParseMode; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] pub enum StickerType { - #[serde(rename = "regular")] Regular, - #[serde(rename = "mask")] Mask, - #[serde(rename = "custom_emoji")] CustomEmoji, } +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum StickerFormat { + Static, + Animated, + Video, +} + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(untagged)] pub enum InputMessageContent { @@ -25,19 +32,13 @@ pub enum InputMessageContent { } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -#[serde(tag = "status")] +#[serde(tag = "status", rename_all = "lowercase")] pub enum ChatMember { - #[serde(rename = "creator")] - Owner(ChatMemberOwner), - #[serde(rename = "administrator")] + Creator(ChatMemberOwner), Administrator(ChatMemberAdministrator), - #[serde(rename = "member")] Member(ChatMemberMember), - #[serde(rename = "restricted")] Restricted(ChatMemberRestricted), - #[serde(rename = "left")] Left(ChatMemberLeft), - #[serde(rename = "kicked")] Banned(ChatMemberBanned), } @@ -158,13 +159,10 @@ pub enum PassportElementErrorTranslationFileType { } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -#[serde(tag = "type")] +#[serde(tag = "type", rename_all = "snake_case")] pub enum MenuButton { - #[serde(rename = "commands")] Commands, - #[serde(rename = "web_app")] WebApp(MenuButtonWebApp), - #[serde(rename = "default")] Default, } @@ -297,6 +295,18 @@ pub struct VideoChatScheduled { #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Builder)] pub struct CallbackGame {} +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] +pub struct BotDescription { + #[builder(setter(into))] + pub description: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] +pub struct BotShortDescription { + #[builder(setter(into))] + pub short_description: String, +} + /// Represents an incoming update from telegram. /// [Official documentation.](https://core.telegram.org/bots/api#update) #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] @@ -885,7 +895,7 @@ pub struct Animation { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -932,7 +942,7 @@ pub struct Audio { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)] @@ -945,7 +955,7 @@ pub struct Document { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -976,7 +986,7 @@ pub struct Video { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -1005,7 +1015,7 @@ pub struct VideoNote { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -1691,7 +1701,7 @@ pub struct Sticker { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -1713,11 +1723,29 @@ pub struct Sticker { #[builder(setter(into, strip_option), default)] pub custom_emoji_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into, strip_option), default)] + pub needs_repainting: Option, + #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] pub file_size: Option, } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Builder)] +pub struct InputSticker { + pub sticker: InputFile, + pub emoji_list: Vec, + + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into, strip_option), default)] + pub mask_position: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[builder(setter(into, strip_option), default)] + pub keywords: Option>, +} + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Builder)] pub struct StickerSet { #[builder(setter(into))] @@ -1741,7 +1769,7 @@ pub struct StickerSet { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb: Option, + pub thumbnail: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Builder)] @@ -1806,15 +1834,15 @@ pub struct InlineQueryResultArticle { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_url: Option, + pub thumbnail_url: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_width: Option, + pub thumbnail_width: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_height: Option, + pub thumbnail_height: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Builder)] @@ -1826,7 +1854,7 @@ pub struct InlineQueryResultPhoto { pub photo_url: String, #[builder(setter(into))] - pub thumb_url: String, + pub thumbnail_url: String, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -1886,11 +1914,11 @@ pub struct InlineQueryResultGif { pub gif_duration: Option, #[builder(setter(into))] - pub thumb_url: String, + pub thumbnail_url: String, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_mime_type: Option, + pub thumbnail_mime_type: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -1938,11 +1966,11 @@ pub struct InlineQueryResultMpeg4Gif { pub mpeg4_duration: Option, #[builder(setter(into))] - pub thumb_url: String, + pub thumbnail_url: String, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_mime_type: Option, + pub thumbnail_mime_type: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] @@ -1981,7 +2009,7 @@ pub struct InlineQueryResultVideo { pub mime_type: String, #[builder(setter(into))] - pub thumb_url: String, + pub thumbnail_url: String, #[builder(setter(into))] pub title: String, @@ -2139,15 +2167,15 @@ pub struct InlineQueryResultDocument { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_url: Option, + pub thumbnail_url: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_width: Option, + pub thumbnail_width: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_height: Option, + pub thumbnail_height: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Builder)] @@ -2188,15 +2216,15 @@ pub struct InlineQueryResultLocation { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_url: Option, + pub thumbnail_url: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_width: Option, + pub thumbnail_width: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_height: Option, + pub thumbnail_height: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Builder)] @@ -2240,15 +2268,15 @@ pub struct InlineQueryResultVenue { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_url: Option, + pub thumbnail_url: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_width: Option, + pub thumbnail_width: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_height: Option, + pub thumbnail_height: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Builder)] @@ -2280,15 +2308,15 @@ pub struct InlineQueryResultContact { #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_url: Option, + pub thumbnail_url: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_width: Option, + pub thumbnail_width: Option, #[serde(skip_serializing_if = "Option::is_none")] #[builder(setter(into, strip_option), default)] - pub thumb_height: Option, + pub thumbnail_height: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Builder)]