diff --git a/CHANGELOG.md b/CHANGELOG.md index deae0c9a..23b195d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,15 +10,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `filter_boost_added` and `filter_reply_to_story` filters to `MessageFilterExt` trait - Add `filter_mention_command` filter to `HandlerExt` trait ([issue #494](https://github.com/teloxide/teloxide/issues/494)) +- Add `filter_business_connection`, `filter_business_message`, `filter_edited_business_message`, and `filter_deleted_business_messages` filters to update filters ([PR 1146](https://github.com/teloxide/teloxide/pull/1146)) ## 0.13.0 - 2024-08-16 ### Added - Documentation regarding the way captions work for the official clients on `SendMediaGroup` ([PR 992](https://github.com/teloxide/teloxide/pull/992)) -- Add `MessageToCopyNotFound` error to `teloxide::errors::ApiError` ([PR 917](https://github.com/teloxide/teloxide/pull/917)) +- Add `MessageToCopyNotFound` error to `teloxide::errors::ApiError` ([PR 917](https://github.com/teloxide/teloxide/pull/917)) - `Dispatcher::try_dispatch_with_listener` ([PR 913](https://github.com/teloxide/teloxide/pull/913)) -- Missing Message::filter_* functions ([PR 982](https://github.com/teloxide/teloxide/pull/982)): +- Missing Message::filter_* functions ([PR 982](https://github.com/teloxide/teloxide/pull/982)): - `filter_game` - `filter_venue` - `filter_video` @@ -50,7 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `filter_video_chat_started` - `filter_video_chat_ended` - `filter_video_chat_participants_invited` - - `filter_web_app_data` + - `filter_web_app_data` - Implement `PostgresStorage`, a persistent dialogue storage based on [PostgreSQL](https://www.postgresql.org/)([PR 996](https://github.com/teloxide/teloxide/pull/996)). - Implement `GetChatId` for `teloxide_core::types::{Chat, ChatJoinRequest, ChatMemberUpdated}`. - Use [deadpool-redis](https://crates.io/crates/deadpool-redis) for Redis connection pooling ([PR 1081](https://github.com/teloxide/teloxide/pull/1081)). diff --git a/Cargo.lock b/Cargo.lock index 4d7d2d31..713778fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -441,6 +441,12 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.10.7" @@ -1395,6 +1401,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "pretty_assertions" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "pretty_env_logger" version = "0.5.0" @@ -2216,6 +2232,7 @@ dependencies = [ "mime", "once_cell", "pin-project", + "pretty_assertions", "pretty_env_logger", "rc-box", "reqwest", @@ -2875,6 +2892,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852" +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "zerocopy" version = "0.7.35" diff --git a/README.md b/README.md index 10ed4f93..5ee10261 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ - + diff --git a/crates/teloxide-core/CHANGELOG.md b/crates/teloxide-core/CHANGELOG.md index 525b3455..3198fadc 100644 --- a/crates/teloxide-core/CHANGELOG.md +++ b/crates/teloxide-core/CHANGELOG.md @@ -19,7 +19,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `boost_added` and `reply_to_story` getters to `Message` struct - Add `unrestrict_boost_count` and `custom_emoji_sticker_set_name` getters to `Chat` struct +- Support for TBA 7.2 ([#1146](pr1146)) + - Update documentation of `SendSticker` method + - Add `is_from_offline` field to `MessageCommon` struct + - Add `can_connect_to_business` field to `Me` struct + - Add `personal_chat` field to `ChatPrivate` struct + - Add `ReplaceStickerInSet` and `GetBusinessConnection` methods + - Add `Birthdate` struct and corresponding field `birthdate` in `ChatPrivate` + - Add `request_name`, `request_username` and `request_photo` fields to `KeyboardButtonRequestUsers` struct + - Add `request_title`, `request_username` and `request_photo` fields to `KeyboardButtonRequestChat` struct + - Add `SharedUser` struct + - Add `title`, `username` and `photo` fields to `ChatShared` struct + - Add `format` field to `InputSticker` struct + - Add `format` parameter to `SetStickerSetThumbnail` method + - Add `BusinessConnectionId` struct + - Add `business_connection_id` parameter to `SendMessage`, `SendPhoto`, `SendVideo`, `SendAnimation`, `SendAudio`, `SendDocument`, `SendSticker`, `SendVideoNote`, `SendVoice`, `SendLocation`, `SendVenue`, `SendContact`, `SendPoll`, `SendDice`, `SendGame`, and `SendMediaGroup` methods + - Add `sender_business_bot` and `business_connection_id` fields to `Message` struct + - Add `BusinessIntro` struct and corresponding field `business_intro` to `ChatPrivate` struct + - Add `BusinessLocation` struct and corresponding field `business_location` to `ChatPrivate` struct + - Add `BusinessOpeningHoursInterval` and `BusinessOpeningHours` structs and corresponding field `business_opening_hours` to `ChatPrivate` struct + - Add `BusinessConnection` struct + - Add `BusinessMessagesDeleted` struct + - Add `BusinessConnection`, `BusinessMessage`, `EditedBusinessMessage` and `DeletedBusinessMessages` variants to `UpdateKind` enum + +### Changed + +- `MaybeAnonymousUser` type introduced, which replaced `PollAnswer::voter: Voter` and `MessageReactionUpdated::{user, actor_chat}` in `MessageReactionUpdated`([#1134][pr1134]) + +- Support for TBA 7.2 ([#1146](pr1146)) + - Remove `flags` field from `StickerSet` struct + - Remove `sticker_format` parameter from `CreateNewStickerSet` method + - Wrap `Public` variant of `ChatKind` in `Box` + - Replaced `user_ids` with `users` in `UsersShared` struct + [pr1131]: https://github.com/teloxide/teloxide/pull/1131 +[pr1134]: https://github.com/teloxide/teloxide/pull/1134 +[pr1146]: https://github.com/teloxide/teloxide/pull/1146 ## 0.10.1 - 2024-08-17 @@ -43,7 +78,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ChatId::as_user` ([#905][pr905]) - Implement `PartialEq for UserId` and `PartialEq for ChatId` ([#905][pr905]) - `ChatId::{MIN, MAX}` ([#905][pr905]) -- Missing `Message` getters ([#982][pr982]): +- Missing `Message` getters ([#982][pr982]): - `message_auto_delete_timer_changed` - `write_access_allowed` - `forum_topic_created` @@ -55,7 +90,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `video_chat_scheduled` - `video_chat_started` - `video_chat_ended` - - `web_app_data` + - `web_app_data` - `is_delete_chat_photo`, `is_group_chat_created`, `is_super_group_chat_created`, `is_channel_chat_created` functions to `Message` ([#982][pr982]) - Support for TBA 6.5 ([#954][pr954]) - Add `can_send_audios`, `can_send_documents`, `can_send_photos`, `can_send_videos`, `can_send_video_notes`, and `can_send_voice_notes` to `ChatPermissions` and `Restricted` @@ -85,7 +120,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add parameter `emoji` to the `send_sticker` method to specify an emoji for just uploaded stickers - Add support for the creation of custom emoji sticker sets in `create_new_sticker_set` - Add parameter `needs_repainting` to the `create_new_sticker_set` methodto automatically change the color of emoji based on context (e.g., use text color in messages, accent color in statuses, etc.) - - Add field `needs_repainting` to the `Sticker` struct + - Add field `needs_repainting` to the `Sticker` struct - Add support for the creation of sticker sets with multiple initial stickers in `create_new_sticker_set` by replacing the parameters `sticker`, `emojis` and `mask_position` with the parameters `stickers` and `sticker_format`. - Add support for .WEBP files in `create_new_sticker_set` and `add_sticker_to_set` - Add support for .WEBP, .TGS, and .WEBM files in `upload_sticker_file` by replacing the parameter `png_sticker` with the parameters `sticker` and `sticker_format` @@ -139,7 +174,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Giveaway: - Add `Giveaway`, `GiveawayCreated`, `GiveawayWinners` and `GiveawayCompleted` structs - Add `Giveaway`, `GiveawayCreated`, `GiveawayWinners` and `GiveawayCompleted` variants to `MessageKind` enum - - Add `giveaway`, `giveaway_created`, `giveaway_winners` and `giveaway_completed` getters to `Message` + - Add `giveaway`, `giveaway_created`, `giveaway_winners` and `giveaway_completed` getters to `Message` - Other Changes - Add fields `ChafFullInfo::{has_visible_history, accent_color_id, background_custom_emoji_id, profile_accent_color_id, profile_background_custom_emoji_id}` - Add `RequestId` type @@ -191,7 +226,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `InlineQueryResultLocation::live_period` - `Location::live_period` - `MessageAutoDeleteTimerChanged::message_auto_delete_time` - - `Poll::open_period` + - `Poll::open_period` - `Video::duration` - `VideoNote::duration` - `Voice::duration` @@ -254,12 +289,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Struct `KeyboardButtonRequestUser` was renamed to `KeyboardButtonRequestUsers` + added field `max_quantity` to it - Field `KeyboardButton::request_user` was renamed to `request_users` - `MessageUserShared` was renamed to `MessageUsersShared` - - Other Changes + - Other Changes - `Message::pinned_message` and `CallbackQuery::message` now have `MaybeInaccessibleMessage` type - Field `emoji_status_custom_emoji_id` is allowed in non-private chats (moved to the `ChatFullInfo`) - Struct `Forward` was replaced by `MessageOrigin` in `MessageCommon` - `RequestId` replaces `i32` in `ChatShared` and `KeyboardButtonRequestChat` structs - + [pr852]: https://github.com/teloxide/teloxide/pull/853 [pr859]: https://github.com/teloxide/teloxide/pull/859 @@ -302,7 +337,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.9.1 - 2023-02-15 -### Fixed +### Fixed - `Update::user` now handles channel posts, chat member changes and chat join request updates correctly ([#835][pr835]) - In cases when `teloxide` can't deserialize an update, error now includes the full json value ([#826][pr826]) diff --git a/crates/teloxide-core/Cargo.toml b/crates/teloxide-core/Cargo.toml index 48476554..ef695fe9 100644 --- a/crates/teloxide-core/Cargo.toml +++ b/crates/teloxide-core/Cargo.toml @@ -95,6 +95,7 @@ ron = "0.7" indexmap = { version = "1.9", features = ["serde-1"] } aho-corasick = "0.7" itertools = "0.10" +pretty_assertions = "1.4.0" [package.metadata.docs.rs] diff --git a/crates/teloxide-core/README.md b/crates/teloxide-core/README.md index d4bd5edc..8e8a1ec3 100644 --- a/crates/teloxide-core/README.md +++ b/crates/teloxide-core/README.md @@ -12,7 +12,7 @@ - + diff --git a/crates/teloxide-core/schema.ron b/crates/teloxide-core/schema.ron index f96b7fe2..540cc047 100644 --- a/crates/teloxide-core/schema.ron +++ b/crates/teloxide-core/schema.ron @@ -1,14 +1,14 @@ //! This file is written in [RON] (Rusty Object Notation). -//! -//! This "schema" is a formalized version of the +//! +//! This "schema" is a formalized version of the //! [telegram bot api documentation][tbadoc] which is not machine readable. //! (note: this schema currently covers only API methods and **not** types). -//! +//! //! Also, note that this file is **hand written** and may contain typos, //! deviations from original doc, and other kinds of typical human errors. //! If you found an error please open an issue (or make a PR) on [github]. -//! -//! This schema is targeting code generation for API wrappers in a statically +//! +//! This schema is targeting code generation for API wrappers in a statically //! typed language, though you may use it whatever you want. //! //! This scheme also has some intentional differences from original doc: @@ -20,26 +20,26 @@ //! + `AllowedUpdate` inner type of `allowed_updates` in `getUpdates` and //! `setWebhook` (so type is `ArrayOf(AllowedUpdate)`) //! + `ReplyMarkup` - type of `reply_markup` parameter, in the original -//! documentation written as `InlineKeyboardMarkup or ReplyKeyboardMarkup or +//! documentation written as `InlineKeyboardMarkup or ReplyKeyboardMarkup or //! ReplyKeyboardRemove or ForceReply` //! + `ParseMode` type of `parse_mode` params //! + `PollType` type of poll, either “quiz” or “regular” //! + `DiceEmoji` emoji that can be used in `sendDice` one of “🎲”, “🎯”, or “🏀” //! + `TargetMessage` either `inline_message_id: String` or `chat_id: ChatId` and `message_id: i64` //! * Integers represented with more strict (when possible) types, e.g.: -//! `u8` (unsigned, 8-bit integer), `u32` (unsigned, 32-bit), +//! `u8` (unsigned, 8-bit integer), `u32` (unsigned, 32-bit), //! `i64` (signed, 64-bit), etc //! * Instead of optional parameters `Option(Ty)` is used //! * Instead of `InputFile or String` just `InputFile` is used (assuming that //! `InputFile` is a sum-type or something and it can contain `String`s) //! * `f64` ~= `Float number` -//! +//! //! [tbadoc]: https://core.telegram.org/bots/api //! [RON]: https://github.com/ron-rs/ron //! [github]: https://github.com/WaffleLapkin/tg-methods-schema Schema( - api_version: ApiVersion(ver: "7.1", date: "February 16, 2024"), + api_version: ApiVersion(ver: "7.2", date: "March 31, 2024"), methods: [ Method( names: ("getUpdates", "GetUpdates", "get_updates"), @@ -49,7 +49,7 @@ Schema( md_links: { "wiki": "https://en.wikipedia.org/wiki/Push_technology#Long_polling", "Update": "https://core.telegram.org/bots/api#update", - }, + }, ), tg_doc: "https://core.telegram.org/bots/api#getupdates", tg_category: "Getting updates", @@ -155,7 +155,7 @@ Schema( md_links: {"amazing guide to Webhooks": "https://core.telegram.org/bots/webhooks"} ) ] - ), + ), Method( names: ("deleteWebhook", "DeleteWebhook", "delete_webhook"), return_ty: True, @@ -205,7 +205,7 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#logout", tg_category: "Available methods", params: [], - ), + ), Method( names: ("close", "Close", "close"), return_ty: True, @@ -224,6 +224,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendmessage", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -259,7 +264,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -279,7 +284,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -315,7 +320,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -328,7 +333,7 @@ Schema( ), Param( name: "message_id", - ty: RawTy("MessageId"), + ty: RawTy("MessageId"), descr: Doc(md: "Message identifier in the chat specified in _from\\_chat\\_id_") ), ], @@ -365,7 +370,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -405,7 +410,7 @@ Schema( ), Param( name: "message_id", - ty: RawTy("MessageId"), + ty: RawTy("MessageId"), descr: Doc(md: "Message identifier in the chat specified in _from\\_chat\\_id_") ), Param( @@ -428,7 +433,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -448,7 +453,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -487,12 +492,12 @@ Schema( ), Param( name: "message_ids", - ty: ArrayOf(RawTy("MessageId")), + ty: ArrayOf(RawTy("MessageId")), descr: Doc(md: "Identifiers of 1-100 messages in the chat _from\\_chat\\_id_ to copy. The identifiers must be specified in a strictly increasing order.") ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -520,6 +525,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendphoto", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -555,7 +565,7 @@ Schema( name: "caption_entities", ty: Option(ArrayOf(RawTy("MessageEntity"))), descr: Doc(md: "List of special entities that appear in the photo caption, which can be specified instead of _parse\\_mode_"), - ), + ), Param( name: "has_spoiler", ty: Option(bool), @@ -563,7 +573,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -583,7 +593,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -605,6 +615,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendaudio", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -666,7 +681,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"}, @@ -686,7 +701,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -705,6 +720,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#senddocument", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -756,7 +776,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"}, @@ -776,7 +796,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -798,6 +818,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendvideo", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -869,7 +894,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"}, @@ -889,13 +914,13 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", } ), - + ), ], ), @@ -909,6 +934,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendanimation", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -975,7 +1005,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"}, @@ -995,7 +1025,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -1018,6 +1048,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendvoice", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -1061,7 +1096,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"}, @@ -1076,11 +1111,11 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", - } + } ), ), ], @@ -1098,6 +1133,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendvideonote", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -1136,7 +1176,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"}, @@ -1156,13 +1196,13 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", - } + } ), - + ), ], ), @@ -1176,6 +1216,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendmediagroup", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -1193,7 +1238,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -1221,6 +1266,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendlocation", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -1256,17 +1306,17 @@ Schema( ), Param( name: "heading", - ty: Option(u16), + ty: Option(u16), descr: Doc(md: "For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified.") ), Param( name: "proximity_alert_radius", - ty: Option(u32), + ty: Option(u32), descr: Doc(md: "For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified.") ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -1286,7 +1336,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -1312,7 +1362,7 @@ Schema( ), Param( name: "message_id", - ty: RawTy("MessageId"), + ty: RawTy("MessageId"), descr: Doc(md: "Identifier of the message to edit") ), Param( @@ -1332,19 +1382,19 @@ Schema( ), Param( name: "heading", - ty: Option(u16), + ty: Option(u16), descr: Doc(md: "For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified.") ), Param( name: "proximity_alert_radius", - ty: Option(u32), + ty: Option(u32), descr: Doc(md: "For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified.") ), Param( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -1386,19 +1436,19 @@ Schema( ), Param( name: "heading", - ty: Option(u16), + ty: Option(u16), descr: Doc(md: "For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified.") ), Param( name: "proximity_alert_radius", - ty: Option(u32), + ty: Option(u32), descr: Doc(md: "For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified.") ), Param( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -1428,18 +1478,18 @@ Schema( ), Param( name: "message_id", - ty: RawTy("MessageId"), + ty: RawTy("MessageId"), descr: Doc(md: "Identifier of the message to edit") ), Param( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", - } + } ), ), ], @@ -1464,7 +1514,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -1484,6 +1534,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendvenue", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -1539,7 +1594,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -1559,11 +1614,11 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", - } + } ), ), ], @@ -1578,6 +1633,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendcontact", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -1613,7 +1673,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -1633,7 +1693,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -1652,6 +1712,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendpoll", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -1727,7 +1792,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -1747,11 +1812,11 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", - } + } ), ), ], @@ -1766,6 +1831,11 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#senddice", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -1783,7 +1853,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -1803,7 +1873,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -1822,11 +1892,16 @@ Schema( tg_doc: "https://core.telegram.org/bots/api#sendchataction", tg_category: "Available methods", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the action will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") - ), + ), Param( name: "action", ty: RawTy("ChatAction"), @@ -2189,7 +2264,7 @@ Schema( descr: Doc(md: "Unique identifier of the target sender chat") ), ], - ), + ), Method( names: ("unbanChatSenderChat", "UnbanChatSenderChat", "unban_chat_sender_chat"), return_ty: True, @@ -2246,7 +2321,7 @@ Schema( descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") ), ], - ), + ), Method( names: ("createChatInviteLink", "CreateChatInviteLink", "create_chat_invite_link"), return_ty: RawTy("ChatInviteLink"), @@ -2286,7 +2361,7 @@ Schema( descr: Doc(md: "True, if users joining the chat via the link need to be approved by chat administrators. If True, member_limit can't be specified") ), ], - ), + ), Method( names: ("editChatInviteLink", "EditChatInviteLink", "edit_chat_invite_link"), return_ty: String, @@ -2328,7 +2403,7 @@ Schema( descr: Doc(md: "True, if users joining the chat via the link need to be approved by chat administrators. If True, member_limit can't be specified") ), ], - ), + ), Method( names: ("revokeChatInviteLink", "RevokeChatInviteLink", "revoke_chat_invite_link"), return_ty: String, @@ -2479,7 +2554,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc(md: "Pass True, if it is not necessary to send a notification to all chat members about the new pinned message. Notifications are always disabled in channels.") ), ], @@ -2976,7 +3051,21 @@ Schema( descr: Doc(md: "A two-letter ISO 639-1 language code. If empty, commands will be applied to all users from the given scope, for whose language there are no dedicated commands") ), ], - ), + ), + Method( + names: ("getBusinessConnection", "GetBusinessConnection", "get_business_connection"), + return_ty: RawTy("BusinessConnection"), + doc: Doc(md: "Use this method to get information about the connection of the bot with a business account. Returns a BusinessConnection object on success."), + tg_doc: "https://core.telegram.org/bots/api#getbusinessconnection", + tg_category: "Available methods", + params: [ + Param( + name: "business_connection_id", + ty: RawTy("BusinessConnectionId"), + descr: Doc(md: "Unique identifier of the business connection"), + ), + ], + ), Method( names: ("getMyCommands", "GetMyCommands", "get_my_commands"), return_ty: ArrayOf(RawTy("BotCommand")), @@ -3238,7 +3327,7 @@ Schema( names: ("answerWebAppQuery", "AnswerWebAppQuery", "answer_web_app_query"), return_ty: RawTy("SentWebAppMessage"), doc: Doc( - md: "Use this method to set the result of an interaction with a [Web App] and send a corresponding message on behalf of the user to the chat from which the query originated.", + md: "Use this method to set the result of an interaction with a [Web App] and send a corresponding message on behalf of the user to the chat from which the query originated.", md_links: {"Web App": "https://core.telegram.org/bots/webapps"} ), tg_doc: "https://core.telegram.org/bots/api#answerwebappquery", @@ -3305,7 +3394,7 @@ Schema( ty: Option(RawTy("InlineKeyboardMarkup")), descr: Doc( md: "A JSON-serialized object for an [inline keyboard].", - md_links: {"inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating"}, + md_links: {"inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating"}, ), ), ], @@ -3399,7 +3488,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("InlineKeyboardMarkup")), descr: Doc( - md: "A JSON-serialized object for an [inline keyboard].", + md: "A JSON-serialized object for an [inline keyboard].", md_links: {"inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating",} ), ), @@ -3442,7 +3531,7 @@ Schema( ty: Option(RawTy("InlineKeyboardMarkup")), descr: Doc( md: "A JSON-serialized object for an [inline keyboard].", - md_links: {"inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating"} + md_links: {"inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating"} ), ), ], @@ -3602,7 +3691,7 @@ Schema( name: "message_id", ty: RawTy("MessageId"), descr: Doc(md: "Identifier of the message to delete") - ), + ), ], ), Method( @@ -3624,19 +3713,24 @@ Schema( md: "Identifiers of 1-100 messages to delete. See [deleteMessage] for limitations on which messages can be deleted", md_links: {"deleteMessage": "https://core.telegram.org/bots/api#delete_message"} ) - ), + ), ], ), Method( names: ("sendSticker", "SendSticker", "send_sticker"), return_ty: RawTy("Message"), doc: Doc( - md: "Use this method to send static .WEBP or [animated] .TGS stickers. On success, the sent Message is returned.", + md: "Use this method to send static .WEBP, .TGS or .WEBM stickers. On success, the sent Message is returned.", md_links: {"animated": "https://telegram.org/blog/animated-stickers"} ), tg_doc: "https://core.telegram.org/bots/api#sendsticker", tg_category: "Stickers", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("Recipient"), @@ -3662,7 +3756,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -3682,7 +3776,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user.", + md: "Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account.", md_links: { "inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating", "custom reply keyboard": "https://core.telegram.org/bots#keyboards", @@ -3723,10 +3817,11 @@ Schema( names: ("uploadStickerFile", "UploadStickerFile", "upload_sticker_file"), return_ty: RawTy("FileMeta"), doc: Doc( - md: "Use this method to upload a file with a sticker for later use in the [CreateNewStickerSet] and [AddStickerToSet] methods (the file can be used multiple times). Returns the uploaded [File] on success.", + md: "Use this method to upload a file with a sticker for later use in the [CreateNewStickerSet], [AddStickerToSet] or [ReplaceStickerInSet] methods (the file can be used multiple times). Returns the uploaded [File] on success.", md_links: { "CreateNewStickerSet": "https://docs.rs/teloxide/latest/teloxide/payloads/struct.CreateNewStickerSet.html", "AddStickerToSet": "https://docs.rs/teloxide/latest/teloxide/payloads/struct.AddStickerToSet.html", + "ReplaceStickerInSet": "https://docs.rs/teloxide/latest/teloxide/payloads/struct.ReplaceStickerInSet.html", "File": "https://core.telegram.org/bots/api#file" } ), @@ -3783,11 +3878,6 @@ Schema( ty: ArrayOf(RawTy("InputSticker")), descr: Doc(md: "A JSON-serialized list of 1-50 initial stickers to be added to the sticker set") ), - Param( - name: "sticker_format", - ty: RawTy("StickerFormat"), - descr: Doc(md: "Format of the sticker, must be one of “static”, “animated”, “video”") - ), Param( name: "sticker_type", ty: Option(RawTy("StickerType")), @@ -3859,6 +3949,42 @@ Schema( ), ], ), + Method( + names: ("replaceStickerInSet", "ReplaceStickerInSet", "replace_sticker_in_set"), + return_ty: True, + doc: Doc( + md: "Use this method to replace an existing sticker in a sticker set with a new one. The method is equivalent to calling [DeleteStickerFromSet], then [AddStickerToSet], then [SetStickerPositionInSet]. Returns _True_ on success.", + md_links: { + "DeleteStickerFromSet": "https://docs.rs/teloxide/latest/teloxide/payloads/struct.DeleteStickerFromSet.html", + "AddStickerToSet": "https://docs.rs/teloxide/latest/teloxide/payloads/struct.AddStickerToSet.html", + "SetStickerPositionInSet": "https://docs.rs/teloxide/latest/teloxide/payloads/struct.SetStickerPositionInSet.html", + } + ), + tg_doc: "https://core.telegram.org/bots/api#replacestickerinset", + tg_category: "Stickers", + params: [ + Param( + name: "user_id", + ty: RawTy("UserId"), + descr: Doc(md: "User identifier of the sticker set owner"), + ), + Param( + name: "name", + ty: String, + descr: Doc(md: "Sticker set name"), + ), + Param( + name: "old_sticker", + ty: String, + descr: Doc(md: "File identifier of the replaced sticker"), + ), + Param( + name: "sticker", + ty: RawTy("InputSticker"), + descr: Doc(md: "A JSON-serialized object with information about the added sticker. If exactly the same sticker had already been added to the set, then the set remains unchanged."), + ), + ], + ), Method( names: ("setStickerSetThumbnail", "SetStickerSetThumbnail", "set_sticker_set_thumbnail"), return_ty: True, @@ -3884,6 +4010,11 @@ Schema( md_links: {"More info on Sending Files »": "https://core.telegram.org/bots/api#sending-files"}, ), ), + Param( + name: "format", + ty: RawTy("StickerFormat"), + descr: Doc(md: "Format of the thumbnail, must be one of \"static\" for a .WEBP or .PNG image, \"animated\" for a .TGS animation, or \"video\" for a WEBM video") + ) ], ), Method( @@ -4035,7 +4166,7 @@ Schema( ty: String, descr: Doc( md: "Payments provider token, obtained via [Botfather]", - md_links: {"Botfather":"https://t.me/botfather"} + md_links: {"Botfather":"https://t.me/botfather"} ), ), Param( @@ -4134,7 +4265,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -4187,7 +4318,7 @@ Schema( ty: String, descr: Doc( md: "Payments provider token, obtained via [Botfather]", - md_links: {"Botfather":"https://t.me/botfather"} + md_links: {"Botfather":"https://t.me/botfather"} ), ), Param( @@ -4364,11 +4495,16 @@ Schema( return_ty: RawTy("Message"), doc: Doc( md: "Use this method to send a game. On success, the sent [Message] is returned.", - md_links: {"Message": "https://core.telegram.org/bots/api#message"} + md_links: {"Message": "https://core.telegram.org/bots/api#message"} ), tg_doc: "https://core.telegram.org/bots/api#sendgame", tg_category: "Games", params: [ + Param( + name: "business_connection_id", + ty: Option(RawTy("BusinessConnectionId")), + descr: Doc(md: "Unique identifier of the business connection on behalf of which the message will be sent"), + ), Param( name: "chat_id", ty: RawTy("ChatId"), @@ -4386,7 +4522,7 @@ Schema( ), Param( name: "disable_notification", - ty: Option(bool), + ty: Option(bool), descr: Doc( md: "Sends the message [silently]. Users will receive a notification with no sound.", md_links: {"silently": "https://telegram.org/blog/channels-2-0#silent-messages"} @@ -4406,7 +4542,7 @@ Schema( name: "reply_markup", ty: Option(RawTy("ReplyMarkup")), descr: Doc( - md: "A JSON-serialized object for an [inline keyboard]. If empty, one 'Play game_title' button will be shown. If not empty, the first button must launch the game.", + md: "A JSON-serialized object for an [inline keyboard]. If empty, one 'Play game_title' button will be shown. If not empty, the first button must launch the game. Not supported for messages sent on behalf of a business account.", md_links: {"inline keyboard": "https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating"}, ), ), @@ -4417,7 +4553,7 @@ Schema( return_ty: RawTy("Message"), doc: Doc( md: "Use this method to set the score of the specified user in a game. On success, returns the edited [Message]. Returns an error, if the new score is not greater than the user's current score in the chat and force is False.", - md_links: {"Message": "https://core.telegram.org/bots/api#message"} + md_links: {"Message": "https://core.telegram.org/bots/api#message"} ), tg_doc: "https://core.telegram.org/bots/api#setgamescore", tg_category: "Games", @@ -4449,7 +4585,7 @@ Schema( ), Param( name: "message_id", - ty: RawTy("MessageId"), + ty: RawTy("MessageId"), descr: Doc(md: "Identifier of the message to edit") ), ], @@ -4520,7 +4656,7 @@ Schema( "Updating messages": "https://core.telegram.org/bots/api#updating-messages", "Stickers": "https://core.telegram.org/bots/api#stickers", "Payments": "https://core.telegram.org/bots/api#payments", - "Telegram Passport": "https://core.telegram.org/bots/api#telegram-passport", + "Telegram Passport": "https://core.telegram.org/bots/api#telegram-passport", "Games": "https://core.telegram.org/bots/api#games", } ) diff --git a/crates/teloxide-core/src/adaptors/cache_me.rs b/crates/teloxide-core/src/adaptors/cache_me.rs index aafe2aca..251d7473 100644 --- a/crates/teloxide-core/src/adaptors/cache_me.rs +++ b/crates/teloxide-core/src/adaptors/cache_me.rs @@ -163,6 +163,7 @@ where answer_callback_query, get_user_chat_boosts, set_my_commands, + get_business_connection, get_my_commands, set_my_name, get_my_name, @@ -196,6 +197,7 @@ where add_sticker_to_set, set_sticker_position_in_set, delete_sticker_from_set, + replace_sticker_in_set, set_sticker_set_thumbnail, set_custom_emoji_sticker_set_thumbnail, set_sticker_set_title, diff --git a/crates/teloxide-core/src/adaptors/erased.rs b/crates/teloxide-core/src/adaptors/erased.rs index 7d4eae0f..e813300a 100644 --- a/crates/teloxide-core/src/adaptors/erased.rs +++ b/crates/teloxide-core/src/adaptors/erased.rs @@ -262,6 +262,7 @@ where answer_callback_query, get_user_chat_boosts, set_my_commands, + get_business_connection, get_my_commands, set_my_name, get_my_name, @@ -295,6 +296,7 @@ where add_sticker_to_set, set_sticker_position_in_set, delete_sticker_from_set, + replace_sticker_in_set, set_sticker_set_thumbnail, set_custom_emoji_sticker_set_thumbnail, set_sticker_set_title, @@ -750,6 +752,11 @@ trait ErasableRequester<'a> { commands: Vec, ) -> ErasedRequest<'a, SetMyCommands, Self::Err>; + fn get_business_connection( + &self, + business_connection_id: BusinessConnectionId, + ) -> ErasedRequest<'a, GetBusinessConnection, Self::Err>; + fn get_my_commands(&self) -> ErasedRequest<'a, GetMyCommands, Self::Err>; fn set_my_name(&self) -> ErasedRequest<'a, SetMyName, Self::Err>; @@ -882,7 +889,6 @@ trait ErasableRequester<'a> { name: String, title: String, stickers: Vec, - sticker_format: StickerFormat, ) -> ErasedRequest<'a, CreateNewStickerSet, Self::Err>; fn add_sticker_to_set( @@ -903,10 +909,19 @@ trait ErasableRequester<'a> { sticker: String, ) -> ErasedRequest<'a, DeleteStickerFromSet, Self::Err>; + fn replace_sticker_in_set( + &self, + user_id: UserId, + name: String, + old_sticker: String, + sticker: InputSticker, + ) -> ErasedRequest<'a, ReplaceStickerInSet, Self::Err>; + fn set_sticker_set_thumbnail( &self, name: String, user_id: UserId, + format: StickerFormat, ) -> ErasedRequest<'a, SetStickerSetThumbnail, Self::Err>; fn set_custom_emoji_sticker_set_thumbnail( @@ -1602,6 +1617,13 @@ where Requester::set_my_commands(self, commands).erase() } + fn get_business_connection( + &self, + business_connection_id: BusinessConnectionId, + ) -> ErasedRequest<'a, GetBusinessConnection, Self::Err> { + Requester::get_business_connection(self, business_connection_id).erase() + } + fn get_my_commands(&self) -> ErasedRequest<'a, GetMyCommands, Self::Err> { Requester::get_my_commands(self).erase() } @@ -1792,10 +1814,8 @@ where name: String, title: String, stickers: Vec, - sticker_format: StickerFormat, ) -> ErasedRequest<'a, CreateNewStickerSet, Self::Err> { - Requester::create_new_sticker_set(self, user_id, name, title, stickers, sticker_format) - .erase() + Requester::create_new_sticker_set(self, user_id, name, title, stickers).erase() } fn add_sticker_to_set( @@ -1822,12 +1842,23 @@ where Requester::delete_sticker_from_set(self, sticker).erase() } + fn replace_sticker_in_set( + &self, + user_id: UserId, + name: String, + old_sticker: String, + sticker: InputSticker, + ) -> ErasedRequest<'a, ReplaceStickerInSet, Self::Err> { + Requester::replace_sticker_in_set(self, user_id, name, old_sticker, sticker).erase() + } + fn set_sticker_set_thumbnail( &self, name: String, user_id: UserId, + format: StickerFormat, ) -> ErasedRequest<'a, SetStickerSetThumbnail, Self::Err> { - Requester::set_sticker_set_thumbnail(self, name, user_id).erase() + Requester::set_sticker_set_thumbnail(self, name, user_id, format).erase() } fn set_custom_emoji_sticker_set_thumbnail( diff --git a/crates/teloxide-core/src/adaptors/parse_mode.rs b/crates/teloxide-core/src/adaptors/parse_mode.rs index 2906302e..4bc3f6f4 100644 --- a/crates/teloxide-core/src/adaptors/parse_mode.rs +++ b/crates/teloxide-core/src/adaptors/parse_mode.rs @@ -244,6 +244,7 @@ where answer_callback_query, get_user_chat_boosts, set_my_commands, + get_business_connection, get_my_commands, set_my_name, get_my_name, @@ -269,6 +270,7 @@ where add_sticker_to_set, set_sticker_position_in_set, delete_sticker_from_set, + replace_sticker_in_set, set_sticker_set_thumbnail, set_custom_emoji_sticker_set_thumbnail, set_sticker_set_title, diff --git a/crates/teloxide-core/src/adaptors/throttle/requester_impl.rs b/crates/teloxide-core/src/adaptors/throttle/requester_impl.rs index 9c6fbd28..e12e0de8 100644 --- a/crates/teloxide-core/src/adaptors/throttle/requester_impl.rs +++ b/crates/teloxide-core/src/adaptors/throttle/requester_impl.rs @@ -146,6 +146,7 @@ where answer_callback_query, get_user_chat_boosts, set_my_commands, + get_business_connection, get_my_commands, set_my_name, get_my_name, @@ -178,6 +179,7 @@ where add_sticker_to_set, set_sticker_position_in_set, delete_sticker_from_set, + replace_sticker_in_set, set_sticker_set_thumbnail, set_custom_emoji_sticker_set_thumbnail, set_sticker_set_title, diff --git a/crates/teloxide-core/src/adaptors/trace.rs b/crates/teloxide-core/src/adaptors/trace.rs index 4a865dc3..e675453d 100644 --- a/crates/teloxide-core/src/adaptors/trace.rs +++ b/crates/teloxide-core/src/adaptors/trace.rs @@ -192,6 +192,7 @@ where answer_callback_query, get_user_chat_boosts, set_my_commands, + get_business_connection, get_my_commands, set_my_name, get_my_name, @@ -225,6 +226,7 @@ where add_sticker_to_set, set_sticker_position_in_set, delete_sticker_from_set, + replace_sticker_in_set, set_sticker_set_thumbnail, set_custom_emoji_sticker_set_thumbnail, set_sticker_set_title, diff --git a/crates/teloxide-core/src/bot/api.rs b/crates/teloxide-core/src/bot/api.rs index 2088bbcb..4305505c 100644 --- a/crates/teloxide-core/src/bot/api.rs +++ b/crates/teloxide-core/src/bot/api.rs @@ -5,8 +5,9 @@ use crate::{ prelude::Requester, requests::{JsonRequest, MultipartRequest}, types::{ - BotCommand, ChatId, ChatPermissions, InlineQueryResult, InputFile, InputMedia, - InputSticker, LabeledPrice, MessageId, Recipient, StickerFormat, ThreadId, UserId, + BotCommand, BusinessConnectionId, ChatId, ChatPermissions, InlineQueryResult, InputFile, + InputMedia, InputSticker, LabeledPrice, MessageId, Recipient, StickerFormat, ThreadId, + UserId, }, Bot, }; @@ -881,6 +882,18 @@ impl Requester for Bot { Self::SetMyCommands::new(self.clone(), payloads::SetMyCommands::new(commands)) } + type GetBusinessConnection = JsonRequest; + + fn get_business_connection( + &self, + business_connection_id: BusinessConnectionId, + ) -> Self::GetBusinessConnection { + Self::GetBusinessConnection::new( + self.clone(), + payloads::GetBusinessConnection::new(business_connection_id), + ) + } + type GetMyCommands = JsonRequest; fn get_my_commands(&self) -> Self::GetMyCommands { @@ -1173,7 +1186,7 @@ impl Requester for Bot { &self, user_id: UserId, sticker: InputFile, - sticker_format: crate::types::StickerFormat, + sticker_format: StickerFormat, ) -> Self::UploadStickerFile { Self::UploadStickerFile::new( self.clone(), @@ -1189,7 +1202,6 @@ impl Requester for Bot { name: N, title: T, stickers: S, - sticker_format: StickerFormat, ) -> Self::CreateNewStickerSet where N: Into, @@ -1198,7 +1210,7 @@ impl Requester for Bot { { Self::CreateNewStickerSet::new( self.clone(), - payloads::CreateNewStickerSet::new(user_id, name, title, stickers, sticker_format), + payloads::CreateNewStickerSet::new(user_id, name, title, stickers), ) } @@ -1244,15 +1256,44 @@ impl Requester for Bot { Self::DeleteStickerFromSet::new(self.clone(), payloads::DeleteStickerFromSet::new(sticker)) } + type ReplaceStickerInSet = JsonRequest; + + fn replace_sticker_in_set( + &self, + user_id: UserId, + name: N, + old_sticker: O, + sticker: InputSticker, + ) -> Self::ReplaceStickerInSet + where + N: Into, + O: Into, + { + Self::ReplaceStickerInSet::new( + self.clone(), + payloads::ReplaceStickerInSet { + user_id, + name: name.into(), + old_sticker: old_sticker.into(), + sticker, + }, + ) + } + type SetStickerSetThumbnail = MultipartRequest; - fn set_sticker_set_thumbnail(&self, name: N, user_id: UserId) -> Self::SetStickerSetThumbnail + fn set_sticker_set_thumbnail( + &self, + name: N, + user_id: UserId, + format: StickerFormat, + ) -> Self::SetStickerSetThumbnail where N: Into, { Self::SetStickerSetThumbnail::new( self.clone(), - payloads::SetStickerSetThumbnail::new(name, user_id), + payloads::SetStickerSetThumbnail::new(name, user_id, format), ) } diff --git a/crates/teloxide-core/src/lib.rs b/crates/teloxide-core/src/lib.rs index 84e1a1a2..25f91ec7 100644 --- a/crates/teloxide-core/src/lib.rs +++ b/crates/teloxide-core/src/lib.rs @@ -1,7 +1,7 @@ //! Core part of the [`teloxide`] library. //! //! This library provides tools for making requests to the [Telegram Bot API] -//! (Currently, version `7.1` is supported) with ease. The library is fully +//! (Currently, version `7.2` is supported) with ease. The library is fully //! asynchronous and built using [`tokio`]. //! //!```toml diff --git a/crates/teloxide-core/src/local_macros.rs b/crates/teloxide-core/src/local_macros.rs index 3fd2bbc7..db71eea2 100644 --- a/crates/teloxide-core/src/local_macros.rs +++ b/crates/teloxide-core/src/local_macros.rs @@ -1069,6 +1069,14 @@ macro_rules! requester_forward { $body!(set_my_commands this (commands: C)) } }; + (@method get_business_connection $body:ident $ty:ident) => { + type GetBusinessConnection = $ty![GetBusinessConnection]; + + fn get_business_connection(&self, business_connection_id: BusinessConnectionId) -> Self::GetBusinessConnection { + let this = self; + $body!(get_business_connection this (business_connection_id: BusinessConnectionId)) + } + }; (@method get_my_commands $body:ident $ty:ident) => { type GetMyCommands = $ty![GetMyCommands]; @@ -1308,11 +1316,11 @@ macro_rules! requester_forward { (@method create_new_sticker_set $body:ident $ty:ident) => { type CreateNewStickerSet = $ty![CreateNewStickerSet]; - fn create_new_sticker_set(&self, user_id: UserId, name: N, title: T, stickers: S, sticker_format: StickerFormat) -> Self::CreateNewStickerSet where N: Into, + fn create_new_sticker_set(&self, user_id: UserId, name: N, title: T, stickers: S) -> Self::CreateNewStickerSet where N: Into, T: Into, S: IntoIterator { let this = self; - $body!(create_new_sticker_set this (user_id: UserId, name: N, title: T, stickers: S, sticker_format: StickerFormat)) + $body!(create_new_sticker_set this (user_id: UserId, name: N, title: T, stickers: S)) } }; (@method add_sticker_to_set $body:ident $ty:ident) => { @@ -1339,12 +1347,21 @@ macro_rules! requester_forward { $body!(delete_sticker_from_set this (sticker: S)) } }; + (@method replace_sticker_in_set $body:ident $ty:ident) => { + type ReplaceStickerInSet = $ty![ReplaceStickerInSet]; + + fn replace_sticker_in_set(&self, user_id: UserId, name: N, old_sticker: O, sticker: InputSticker) -> Self::ReplaceStickerInSet where N: Into, + O: Into { + let this = self; + $body!(replace_sticker_in_set this (user_id: UserId, name: N, old_sticker: O, sticker: InputSticker)) + } + }; (@method set_sticker_set_thumbnail $body:ident $ty:ident) => { type SetStickerSetThumbnail = $ty![SetStickerSetThumbnail]; - fn set_sticker_set_thumbnail(&self, name: N, user_id: UserId) -> Self::SetStickerSetThumbnail where N: Into { + fn set_sticker_set_thumbnail(&self, name: N, user_id: UserId, format: StickerFormat) -> Self::SetStickerSetThumbnail where N: Into { let this = self; - $body!(set_sticker_set_thumbnail this (name: N, user_id: UserId)) + $body!(set_sticker_set_thumbnail this (name: N, user_id: UserId, format: StickerFormat)) } }; (@method set_custom_emoji_sticker_set_thumbnail $body:ident $ty:ident) => { @@ -1515,7 +1532,7 @@ fn codegen_requester_forward() { convert_params.sort_unstable(); - let prefixes: IndexMap<_, _> = convert_params + let mut prefixes: IndexMap<_, _> = convert_params .iter() .copied() // Workaround to output the last type as the first letter @@ -1524,6 +1541,18 @@ fn codegen_requester_forward() { .map(|(l, r)| (l, min_prefix(l, r))) .collect(); + // FIXME: This hard-coded value has been set to avoid conflicting generic + // parameter 'B' with impl Requester... in all the adaptors and other places + // + // One fix could be to take full abbrevation for all the parameters instead of + // just the first character. Other fix is to change the generic parameter name + // in all the impl blocks to something like 'Z' because that is very less likely + // to conflict in future. + if prefixes.contains_key("business_connection_id") { + prefixes["business_connection_id"] = "BCI"; + } + let prefixes = prefixes; + let args = m .params .iter() diff --git a/crates/teloxide-core/src/payloads.rs b/crates/teloxide-core/src/payloads.rs index 47fbac31..34e52286 100644 --- a/crates/teloxide-core/src/payloads.rs +++ b/crates/teloxide-core/src/payloads.rs @@ -59,6 +59,7 @@ mod edit_message_text_inline; mod export_chat_invite_link; mod forward_message; mod forward_messages; +mod get_business_connection; mod get_chat; mod get_chat_administrators; mod get_chat_member; @@ -88,6 +89,7 @@ mod pin_chat_message; mod promote_chat_member; mod reopen_forum_topic; mod reopen_general_forum_topic; +mod replace_sticker_in_set; mod restrict_chat_member; mod revoke_chat_invite_link; mod send_animation; @@ -192,6 +194,7 @@ pub use edit_message_text_inline::{EditMessageTextInline, EditMessageTextInlineS pub use export_chat_invite_link::{ExportChatInviteLink, ExportChatInviteLinkSetters}; pub use forward_message::{ForwardMessage, ForwardMessageSetters}; pub use forward_messages::{ForwardMessages, ForwardMessagesSetters}; +pub use get_business_connection::{GetBusinessConnection, GetBusinessConnectionSetters}; pub use get_chat::{GetChat, GetChatSetters}; pub use get_chat_administrators::{GetChatAdministrators, GetChatAdministratorsSetters}; pub use get_chat_member::{GetChatMember, GetChatMemberSetters}; @@ -225,6 +228,7 @@ pub use pin_chat_message::{PinChatMessage, PinChatMessageSetters}; pub use promote_chat_member::{PromoteChatMember, PromoteChatMemberSetters}; pub use reopen_forum_topic::{ReopenForumTopic, ReopenForumTopicSetters}; pub use reopen_general_forum_topic::{ReopenGeneralForumTopic, ReopenGeneralForumTopicSetters}; +pub use replace_sticker_in_set::{ReplaceStickerInSet, ReplaceStickerInSetSetters}; pub use restrict_chat_member::{RestrictChatMember, RestrictChatMemberSetters}; pub use revoke_chat_invite_link::{RevokeChatInviteLink, RevokeChatInviteLinkSetters}; pub use send_animation::{SendAnimation, SendAnimationSetters}; diff --git a/crates/teloxide-core/src/payloads/copy_message.rs b/crates/teloxide-core/src/payloads/copy_message.rs index daa67928..bc7a770a 100644 --- a/crates/teloxide-core/src/payloads/copy_message.rs +++ b/crates/teloxide-core/src/payloads/copy_message.rs @@ -40,7 +40,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/create_new_sticker_set.rs b/crates/teloxide-core/src/payloads/create_new_sticker_set.rs index 9ca7be3d..d3a41491 100644 --- a/crates/teloxide-core/src/payloads/create_new_sticker_set.rs +++ b/crates/teloxide-core/src/payloads/create_new_sticker_set.rs @@ -2,7 +2,7 @@ use serde::Serialize; -use crate::types::{InputSticker, StickerFormat, StickerType, True, UserId}; +use crate::types::{InputSticker, StickerType, True, UserId}; impl_payload! { /// Use this method to create a new sticker set owned by a user. The bot will be able to edit the sticker set thus created. Returns True on success. @@ -17,8 +17,6 @@ impl_payload! { pub title: String [into], /// A JSON-serialized list of 1-50 initial stickers to be added to the sticker set pub stickers: Vec [collect], - /// Format of the sticker, must be one of “static”, “animated”, “video” - pub sticker_format: StickerFormat, } optional { /// Type of stickers in the set, pass “regular”, “mask”, or “custom_emoji”. By default, a regular sticker set is created. diff --git a/crates/teloxide-core/src/payloads/edit_message_live_location.rs b/crates/teloxide-core/src/payloads/edit_message_live_location.rs index b8df0e5a..a3168fe9 100644 --- a/crates/teloxide-core/src/payloads/edit_message_live_location.rs +++ b/crates/teloxide-core/src/payloads/edit_message_live_location.rs @@ -30,7 +30,7 @@ impl_payload! { pub heading: u16, /// For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. pub proximity_alert_radius: u32, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/edit_message_live_location_inline.rs b/crates/teloxide-core/src/payloads/edit_message_live_location_inline.rs index e0f6e5e4..936c8994 100644 --- a/crates/teloxide-core/src/payloads/edit_message_live_location_inline.rs +++ b/crates/teloxide-core/src/payloads/edit_message_live_location_inline.rs @@ -27,7 +27,7 @@ impl_payload! { pub heading: u16, /// For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. pub proximity_alert_radius: u32, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/get_business_connection.rs b/crates/teloxide-core/src/payloads/get_business_connection.rs new file mode 100644 index 00000000..1ae65748 --- /dev/null +++ b/crates/teloxide-core/src/payloads/get_business_connection.rs @@ -0,0 +1,16 @@ +//! Generated by `codegen_payloads`, do not edit by hand. + +use serde::Serialize; + +use crate::types::{BusinessConnection, BusinessConnectionId}; + +impl_payload! { + /// Use this method to get information about the connection of the bot with a business account. Returns a BusinessConnection object on success. + #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)] + pub GetBusinessConnection (GetBusinessConnectionSetters) => BusinessConnection { + required { + /// Unique identifier of the business connection + pub business_connection_id: BusinessConnectionId, + } + } +} diff --git a/crates/teloxide-core/src/payloads/replace_sticker_in_set.rs b/crates/teloxide-core/src/payloads/replace_sticker_in_set.rs new file mode 100644 index 00000000..8e64e9b5 --- /dev/null +++ b/crates/teloxide-core/src/payloads/replace_sticker_in_set.rs @@ -0,0 +1,27 @@ +//! Generated by `codegen_payloads`, do not edit by hand. + +use serde::Serialize; + +use crate::types::{InputSticker, True, UserId}; + +impl_payload! { + @[multipart = sticker] + /// Use this method to replace an existing sticker in a sticker set with a new one. The method is equivalent to calling [DeleteStickerFromSet], then [AddStickerToSet], then [SetStickerPositionInSet]. Returns _True_ on success. + /// + /// [DeleteStickerFromSet]: https://docs.rs/teloxide/latest/teloxide/payloads/struct.DeleteStickerFromSet.html + /// [AddStickerToSet]: https://docs.rs/teloxide/latest/teloxide/payloads/struct.AddStickerToSet.html + /// [SetStickerPositionInSet]: https://docs.rs/teloxide/latest/teloxide/payloads/struct.SetStickerPositionInSet.html + #[derive(Debug, Clone, Serialize)] + pub ReplaceStickerInSet (ReplaceStickerInSetSetters) => True { + required { + /// User identifier of the sticker set owner + pub user_id: UserId, + /// Sticker set name + pub name: String [into], + /// File identifier of the replaced sticker + pub old_sticker: String [into], + /// A JSON-serialized object with information about the added sticker. If exactly the same sticker had already been added to the set, then the set remains unchanged. + pub sticker: InputSticker, + } + } +} diff --git a/crates/teloxide-core/src/payloads/send_animation.rs b/crates/teloxide-core/src/payloads/send_animation.rs index ba2348ee..d1fd7758 100644 --- a/crates/teloxide-core/src/payloads/send_animation.rs +++ b/crates/teloxide-core/src/payloads/send_animation.rs @@ -3,7 +3,8 @@ use serde::Serialize; use crate::types::{ - InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId, + BusinessConnectionId, InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, + ReplyParameters, ThreadId, }; impl_payload! { @@ -22,6 +23,8 @@ impl_payload! { pub animation: InputFile, } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Duration of the animation in seconds @@ -52,7 +55,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_audio.rs b/crates/teloxide-core/src/payloads/send_audio.rs index 2c579ec8..1b0829eb 100644 --- a/crates/teloxide-core/src/payloads/send_audio.rs +++ b/crates/teloxide-core/src/payloads/send_audio.rs @@ -3,7 +3,8 @@ use serde::Serialize; use crate::types::{ - InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId, + BusinessConnectionId, InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, + ReplyParameters, ThreadId, }; impl_payload! { @@ -25,6 +26,8 @@ impl_payload! { pub audio: InputFile, } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Audio caption, 0-1024 characters after entities parsing @@ -53,7 +56,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_chat_action.rs b/crates/teloxide-core/src/payloads/send_chat_action.rs index 46726fba..898a84e3 100644 --- a/crates/teloxide-core/src/payloads/send_chat_action.rs +++ b/crates/teloxide-core/src/payloads/send_chat_action.rs @@ -2,7 +2,7 @@ use serde::Serialize; -use crate::types::{ChatAction, Recipient, ThreadId, True}; +use crate::types::{BusinessConnectionId, ChatAction, Recipient, ThreadId, True}; impl_payload! { /// Use this method when you need to tell the user that something is happening on the bot's side. The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). Returns True on success. @@ -30,6 +30,8 @@ impl_payload! { pub action: ChatAction, } optional { + /// Unique identifier of the business connection on behalf of which the action will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread; supergroups only pub message_thread_id: ThreadId, } diff --git a/crates/teloxide-core/src/payloads/send_contact.rs b/crates/teloxide-core/src/payloads/send_contact.rs index b350b1b5..7f395d5d 100644 --- a/crates/teloxide-core/src/payloads/send_contact.rs +++ b/crates/teloxide-core/src/payloads/send_contact.rs @@ -2,7 +2,9 @@ use serde::Serialize; -use crate::types::{Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId}; +use crate::types::{ + BusinessConnectionId, Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId, +}; impl_payload! { /// Use this method to send phone contacts. On success, the sent [`Message`] is returned. @@ -19,6 +21,8 @@ impl_payload! { pub first_name: String [into], } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Contact's last name @@ -35,7 +39,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_dice.rs b/crates/teloxide-core/src/payloads/send_dice.rs index 2444c39b..069a9507 100644 --- a/crates/teloxide-core/src/payloads/send_dice.rs +++ b/crates/teloxide-core/src/payloads/send_dice.rs @@ -2,7 +2,9 @@ use serde::Serialize; -use crate::types::{DiceEmoji, Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId}; +use crate::types::{ + BusinessConnectionId, DiceEmoji, Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId, +}; impl_payload! { /// Use this method to send an animated emoji that will display a random value. On success, the sent [`Message`] is returned. @@ -15,6 +17,8 @@ impl_payload! { pub chat_id: Recipient [into], } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Emoji on which the dice throw animation is based. Currently, must be one of “🎲”, “🎯”, “🏀”, “⚽”, “🎳”, or “🎰”. Dice can have values 1-6 for “🎲”, “🎯” and “🎳”, values 1-5 for “🏀” and “⚽”, and values 1-64 for “🎰”. Defaults to “🎲” @@ -27,7 +31,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_document.rs b/crates/teloxide-core/src/payloads/send_document.rs index 7f570058..43e6f7d1 100644 --- a/crates/teloxide-core/src/payloads/send_document.rs +++ b/crates/teloxide-core/src/payloads/send_document.rs @@ -3,7 +3,8 @@ use serde::Serialize; use crate::types::{ - InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId, + BusinessConnectionId, InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, + ReplyParameters, ThreadId, }; impl_payload! { @@ -22,6 +23,8 @@ impl_payload! { pub document: InputFile, } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . [More info on Sending Files »] @@ -46,7 +49,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_game.rs b/crates/teloxide-core/src/payloads/send_game.rs index 0b355e1f..413e57ba 100644 --- a/crates/teloxide-core/src/payloads/send_game.rs +++ b/crates/teloxide-core/src/payloads/send_game.rs @@ -2,7 +2,7 @@ use serde::Serialize; -use crate::types::{ChatId, Message, ReplyMarkup, ReplyParameters, ThreadId}; +use crate::types::{BusinessConnectionId, ChatId, Message, ReplyMarkup, ReplyParameters, ThreadId}; impl_payload! { /// Use this method to send a game. On success, the sent [`Message`] is returned. @@ -17,6 +17,8 @@ impl_payload! { pub game_short_name: String [into], } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Sends the message [silently]. Users will receive a notification with no sound. @@ -27,7 +29,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// A JSON-serialized object for an [inline keyboard]. If empty, one 'Play game_title' button will be shown. If not empty, the first button must launch the game. + /// A JSON-serialized object for an [inline keyboard]. If empty, one 'Play game_title' button will be shown. If not empty, the first button must launch the game. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating pub reply_markup: ReplyMarkup [into], diff --git a/crates/teloxide-core/src/payloads/send_location.rs b/crates/teloxide-core/src/payloads/send_location.rs index f1e0f736..03094933 100644 --- a/crates/teloxide-core/src/payloads/send_location.rs +++ b/crates/teloxide-core/src/payloads/send_location.rs @@ -2,7 +2,9 @@ use serde::Serialize; -use crate::types::{Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId}; +use crate::types::{ + BusinessConnectionId, Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId, +}; impl_payload! { /// Use this method to send point on the map. On success, the sent [`Message`] is returned. @@ -19,6 +21,8 @@ impl_payload! { pub longitude: f64, } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// The radius of uncertainty for the location, measured in meters; 0-1500 @@ -39,7 +43,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_media_group.rs b/crates/teloxide-core/src/payloads/send_media_group.rs index 0098ead4..ab5782a1 100644 --- a/crates/teloxide-core/src/payloads/send_media_group.rs +++ b/crates/teloxide-core/src/payloads/send_media_group.rs @@ -2,7 +2,9 @@ use serde::Serialize; -use crate::types::{InputMedia, Message, Recipient, ReplyParameters, ThreadId}; +use crate::types::{ + BusinessConnectionId, InputMedia, Message, Recipient, ReplyParameters, ThreadId, +}; impl_payload! { /// Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of [`Message`]s that were sent is returned. @@ -26,6 +28,8 @@ impl_payload! { pub media: Vec [collect], } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Sends the message [silently]. Users will receive a notification with no sound. diff --git a/crates/teloxide-core/src/payloads/send_message.rs b/crates/teloxide-core/src/payloads/send_message.rs index d7006c4f..46d1c616 100644 --- a/crates/teloxide-core/src/payloads/send_message.rs +++ b/crates/teloxide-core/src/payloads/send_message.rs @@ -3,8 +3,8 @@ use serde::Serialize; use crate::types::{ - LinkPreviewOptions, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, - ThreadId, + BusinessConnectionId, LinkPreviewOptions, Message, MessageEntity, ParseMode, Recipient, + ReplyMarkup, ReplyParameters, ThreadId, }; impl_payload! { @@ -20,6 +20,8 @@ impl_payload! { pub text: String [into], } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Mode for parsing entities in the message text. See [formatting options] for more details. @@ -38,7 +40,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_photo.rs b/crates/teloxide-core/src/payloads/send_photo.rs index 452b16e7..037c3935 100644 --- a/crates/teloxide-core/src/payloads/send_photo.rs +++ b/crates/teloxide-core/src/payloads/send_photo.rs @@ -3,7 +3,8 @@ use serde::Serialize; use crate::types::{ - InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId, + BusinessConnectionId, InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, + ReplyParameters, ThreadId, }; impl_payload! { @@ -22,6 +23,8 @@ impl_payload! { pub photo: InputFile, } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Photo caption (may also be used when resending photos by _file\_id_), 0-1024 characters after entities parsing @@ -42,7 +45,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_poll.rs b/crates/teloxide-core/src/payloads/send_poll.rs index aaa69580..4704cc60 100644 --- a/crates/teloxide-core/src/payloads/send_poll.rs +++ b/crates/teloxide-core/src/payloads/send_poll.rs @@ -4,7 +4,8 @@ use chrono::{DateTime, Utc}; use serde::Serialize; use crate::types::{ - Message, MessageEntity, ParseMode, PollType, Recipient, ReplyMarkup, ReplyParameters, ThreadId, + BusinessConnectionId, Message, MessageEntity, ParseMode, PollType, Recipient, ReplyMarkup, + ReplyParameters, ThreadId, }; impl_payload! { @@ -22,6 +23,8 @@ impl_payload! { pub options: Vec [collect], } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// True, if the poll needs to be anonymous, defaults to True @@ -56,7 +59,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_sticker.rs b/crates/teloxide-core/src/payloads/send_sticker.rs index 13678400..754615e4 100644 --- a/crates/teloxide-core/src/payloads/send_sticker.rs +++ b/crates/teloxide-core/src/payloads/send_sticker.rs @@ -2,11 +2,13 @@ use serde::Serialize; -use crate::types::{InputFile, Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId}; +use crate::types::{ + BusinessConnectionId, InputFile, Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId, +}; impl_payload! { @[multipart = sticker] - /// Use this method to send static .WEBP or [animated] .TGS stickers. On success, the sent Message is returned. + /// Use this method to send static .WEBP, .TGS or .WEBM stickers. On success, the sent Message is returned. /// /// [animated]: https://telegram.org/blog/animated-stickers #[derive(Debug, Clone, Serialize)] @@ -20,6 +22,8 @@ impl_payload! { pub sticker: InputFile, } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Emoji associated with the sticker; only for just uploaded stickers @@ -32,7 +36,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_venue.rs b/crates/teloxide-core/src/payloads/send_venue.rs index 3ccca409..e9629e39 100644 --- a/crates/teloxide-core/src/payloads/send_venue.rs +++ b/crates/teloxide-core/src/payloads/send_venue.rs @@ -2,7 +2,9 @@ use serde::Serialize; -use crate::types::{Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId}; +use crate::types::{ + BusinessConnectionId, Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId, +}; impl_payload! { /// Use this method to send information about a venue. On success, the sent [`Message`] is returned. @@ -23,6 +25,8 @@ impl_payload! { pub address: String [into], } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Foursquare identifier of the venue @@ -43,7 +47,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_video.rs b/crates/teloxide-core/src/payloads/send_video.rs index be52eb1a..c4de05f1 100644 --- a/crates/teloxide-core/src/payloads/send_video.rs +++ b/crates/teloxide-core/src/payloads/send_video.rs @@ -3,7 +3,8 @@ use serde::Serialize; use crate::types::{ - InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId, + BusinessConnectionId, InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, + ReplyParameters, ThreadId, }; impl_payload! { @@ -23,6 +24,8 @@ impl_payload! { pub video: InputFile, } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Duration of the video in seconds @@ -55,7 +58,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_video_note.rs b/crates/teloxide-core/src/payloads/send_video_note.rs index f4387c94..72c1e60b 100644 --- a/crates/teloxide-core/src/payloads/send_video_note.rs +++ b/crates/teloxide-core/src/payloads/send_video_note.rs @@ -2,7 +2,9 @@ use serde::Serialize; -use crate::types::{InputFile, Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId}; +use crate::types::{ + BusinessConnectionId, InputFile, Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId, +}; impl_payload! { @[multipart = video_note, thumbnail] @@ -21,6 +23,8 @@ impl_payload! { pub video_note: InputFile, } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Duration of the video in seconds @@ -39,7 +43,7 @@ impl_payload! { pub protect_content: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/send_voice.rs b/crates/teloxide-core/src/payloads/send_voice.rs index a7d3b139..40b85c42 100644 --- a/crates/teloxide-core/src/payloads/send_voice.rs +++ b/crates/teloxide-core/src/payloads/send_voice.rs @@ -3,7 +3,8 @@ use serde::Serialize; use crate::types::{ - InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId, + BusinessConnectionId, InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, + ReplyParameters, ThreadId, }; impl_payload! { @@ -24,6 +25,8 @@ impl_payload! { pub voice: InputFile, } optional { + /// Unique identifier of the business connection on behalf of which the message will be sent + pub business_connection_id: BusinessConnectionId, /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only pub message_thread_id: ThreadId, /// Voice message caption, 0-1024 characters after entities parsing @@ -42,7 +45,7 @@ impl_payload! { pub disable_notification: bool, /// Description of the message to reply to pub reply_parameters: ReplyParameters, - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/set_sticker_set_thumbnail.rs b/crates/teloxide-core/src/payloads/set_sticker_set_thumbnail.rs index 4c0d6835..0c1d0690 100644 --- a/crates/teloxide-core/src/payloads/set_sticker_set_thumbnail.rs +++ b/crates/teloxide-core/src/payloads/set_sticker_set_thumbnail.rs @@ -2,7 +2,7 @@ use serde::Serialize; -use crate::types::{InputFile, True, UserId}; +use crate::types::{InputFile, StickerFormat, True, UserId}; impl_payload! { @[multipart = thumbnail] @@ -14,6 +14,8 @@ impl_payload! { pub name: String [into], /// User identifier of sticker file owner pub user_id: UserId, + /// Format of the thumbnail, must be one of "static" for a .WEBP or .PNG image, "animated" for a .TGS animation, or "video" for a WEBM video + pub format: StickerFormat, } optional { /// A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail. diff --git a/crates/teloxide-core/src/payloads/setters.rs b/crates/teloxide-core/src/payloads/setters.rs index 06a24b76..e7d3640c 100644 --- a/crates/teloxide-core/src/payloads/setters.rs +++ b/crates/teloxide-core/src/payloads/setters.rs @@ -19,17 +19,18 @@ pub use crate::payloads::{ EditMessageReplyMarkupInlineSetters as _, EditMessageReplyMarkupSetters as _, EditMessageTextInlineSetters as _, EditMessageTextSetters as _, ExportChatInviteLinkSetters as _, ForwardMessageSetters as _, ForwardMessagesSetters as _, - GetChatAdministratorsSetters as _, GetChatMemberCountSetters as _, GetChatMemberSetters as _, - GetChatMembersCountSetters as _, GetChatMenuButtonSetters as _, GetChatSetters as _, - GetCustomEmojiStickersSetters as _, GetFileSetters as _, GetForumTopicIconStickersSetters as _, - GetGameHighScoresSetters as _, GetMeSetters as _, GetMyCommandsSetters as _, - GetMyDefaultAdministratorRightsSetters as _, GetMyDescriptionSetters as _, - GetMyNameSetters as _, GetMyShortDescriptionSetters as _, GetStickerSetSetters as _, - GetUpdatesSetters as _, GetUserChatBoostsSetters as _, GetUserProfilePhotosSetters as _, - GetWebhookInfoSetters as _, HideGeneralForumTopicSetters as _, KickChatMemberSetters as _, - LeaveChatSetters as _, LogOutSetters as _, PinChatMessageSetters as _, - PromoteChatMemberSetters as _, ReopenForumTopicSetters as _, - ReopenGeneralForumTopicSetters as _, RestrictChatMemberSetters as _, + GetBusinessConnectionSetters as _, GetChatAdministratorsSetters as _, + GetChatMemberCountSetters as _, GetChatMemberSetters as _, GetChatMembersCountSetters as _, + GetChatMenuButtonSetters as _, GetChatSetters as _, GetCustomEmojiStickersSetters as _, + GetFileSetters as _, GetForumTopicIconStickersSetters as _, GetGameHighScoresSetters as _, + GetMeSetters as _, GetMyCommandsSetters as _, GetMyDefaultAdministratorRightsSetters as _, + GetMyDescriptionSetters as _, GetMyNameSetters as _, GetMyShortDescriptionSetters as _, + GetStickerSetSetters as _, GetUpdatesSetters as _, GetUserChatBoostsSetters as _, + GetUserProfilePhotosSetters as _, GetWebhookInfoSetters as _, + HideGeneralForumTopicSetters as _, KickChatMemberSetters as _, LeaveChatSetters as _, + LogOutSetters as _, PinChatMessageSetters as _, PromoteChatMemberSetters as _, + ReopenForumTopicSetters as _, ReopenGeneralForumTopicSetters as _, + ReplaceStickerInSetSetters as _, RestrictChatMemberSetters as _, RevokeChatInviteLinkSetters as _, SendAnimationSetters as _, SendAudioSetters as _, SendChatActionSetters as _, SendContactSetters as _, SendDiceSetters as _, SendDocumentSetters as _, SendGameSetters as _, SendInvoiceSetters as _, diff --git a/crates/teloxide-core/src/payloads/stop_message_live_location.rs b/crates/teloxide-core/src/payloads/stop_message_live_location.rs index 7e2a312c..28d5c9b7 100644 --- a/crates/teloxide-core/src/payloads/stop_message_live_location.rs +++ b/crates/teloxide-core/src/payloads/stop_message_live_location.rs @@ -21,7 +21,7 @@ impl_payload! { pub message_id: MessageId, } optional { - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/stop_message_live_location_inline.rs b/crates/teloxide-core/src/payloads/stop_message_live_location_inline.rs index fdc7543c..c932f5f6 100644 --- a/crates/teloxide-core/src/payloads/stop_message_live_location_inline.rs +++ b/crates/teloxide-core/src/payloads/stop_message_live_location_inline.rs @@ -17,7 +17,7 @@ impl_payload! { pub inline_message_id: String [into], } optional { - /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove reply keyboard or to force a reply from the user. + /// Additional interface options. A JSON-serialized object for an [inline keyboard], [custom reply keyboard], instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. /// /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards diff --git a/crates/teloxide-core/src/payloads/upload_sticker_file.rs b/crates/teloxide-core/src/payloads/upload_sticker_file.rs index ef00a015..d3adc35f 100644 --- a/crates/teloxide-core/src/payloads/upload_sticker_file.rs +++ b/crates/teloxide-core/src/payloads/upload_sticker_file.rs @@ -6,10 +6,11 @@ use crate::types::{FileMeta, InputFile, StickerFormat, UserId}; impl_payload! { @[multipart = sticker] - /// Use this method to upload a file with a sticker for later use in the [CreateNewStickerSet] and [AddStickerToSet] methods (the file can be used multiple times). Returns the uploaded [`File`] on success. + /// Use this method to upload a file with a sticker for later use in the [CreateNewStickerSet], [AddStickerToSet] or [ReplaceStickerInSet] methods (the file can be used multiple times). Returns the uploaded [`File`] on success. /// /// [CreateNewStickerSet]: https://docs.rs/teloxide/latest/teloxide/payloads/struct.CreateNewStickerSet.html /// [AddStickerToSet]: https://docs.rs/teloxide/latest/teloxide/payloads/struct.AddStickerToSet.html + /// [ReplaceStickerInSet]: https://docs.rs/teloxide/latest/teloxide/payloads/struct.ReplaceStickerInSet.html /// [`File`]: crate::types::File #[derive(Debug, Clone, Serialize)] pub UploadStickerFile (UploadStickerFileSetters) => FileMeta { diff --git a/crates/teloxide-core/src/requests/requester.rs b/crates/teloxide-core/src/requests/requester.rs index 977e2c19..7e34161a 100644 --- a/crates/teloxide-core/src/requests/requester.rs +++ b/crates/teloxide-core/src/requests/requester.rs @@ -831,6 +831,14 @@ pub trait Requester { where C: IntoIterator; + type GetBusinessConnection: Request; + + /// For Telegram documentation see [`GetBusinessConnection`]. + fn get_business_connection( + &self, + business_connection_id: BusinessConnectionId, + ) -> Self::GetBusinessConnection; + type GetMyCommands: Request; /// For Telegram documentation see [`GetMyCommands`]. @@ -1071,7 +1079,6 @@ pub trait Requester { name: N, title: T, stickers: S, - sticker_format: StickerFormat, ) -> Self::CreateNewStickerSet where N: Into, @@ -1108,6 +1115,20 @@ pub trait Requester { where S: Into; + type ReplaceStickerInSet: Request; + + /// For Telegram documentation see [`ReplaceStickerInSet`]. + fn replace_sticker_in_set( + &self, + user_id: UserId, + name: N, + old_sticker: O, + sticker: InputSticker, + ) -> Self::ReplaceStickerInSet + where + N: Into, + O: Into; + type SetStickerSetThumbnail: Request; /// For Telegram documentation see [`SetStickerSetThumbnail`]. @@ -1115,6 +1136,7 @@ pub trait Requester { &self, name: N, user_id: UserId, + format: StickerFormat, ) -> Self::SetStickerSetThumbnail where N: Into; @@ -1372,6 +1394,7 @@ macro_rules! forward_all { answer_callback_query, get_user_chat_boosts, set_my_commands, + get_business_connection, get_my_commands, set_my_name, get_my_name, @@ -1405,6 +1428,7 @@ macro_rules! forward_all { add_sticker_to_set, set_sticker_position_in_set, delete_sticker_from_set, + replace_sticker_in_set, set_sticker_set_thumbnail, set_custom_emoji_sticker_set_thumbnail, set_sticker_set_title, diff --git a/crates/teloxide-core/src/serde_multipart/mod.rs b/crates/teloxide-core/src/serde_multipart/mod.rs index a83af2b3..d48380e8 100644 --- a/crates/teloxide-core/src/serde_multipart/mod.rs +++ b/crates/teloxide-core/src/serde_multipart/mod.rs @@ -90,7 +90,7 @@ mod tests { types::{ ChatId, InputFile, InputMedia, InputMediaAnimation, InputMediaAudio, InputMediaDocument, InputMediaPhoto, InputMediaVideo, InputSticker, MessageEntity, - MessageEntityKind, ParseMode, UserId, + MessageEntityKind, ParseMode, StickerFormat, UserId, }, }; @@ -157,6 +157,7 @@ mod tests { emoji_list: vec!["✈️⚙️".to_owned()], keywords: vec![], mask_position: None, + format: StickerFormat::Static, }, )) .unwrap() diff --git a/crates/teloxide-core/src/types.rs b/crates/teloxide-core/src/types.rs index 5992e1bc..36b73ac9 100644 --- a/crates/teloxide-core/src/types.rs +++ b/crates/teloxide-core/src/types.rs @@ -3,11 +3,19 @@ pub use allowed_update::*; pub use animation::*; pub use audio::*; +pub use birthdate::*; pub use bot_command::*; pub use bot_command_scope::*; pub use bot_description::*; pub use bot_name::*; pub use bot_short_description::*; +pub use business_connection::*; +pub use business_connection_id::*; +pub use business_intro::*; +pub use business_location::*; +pub use business_messages_deleted::*; +pub use business_opening_hours::*; +pub use business_opening_hours_interval::*; pub use callback_game::*; pub use callback_query::*; pub use chat::*; @@ -91,6 +99,7 @@ pub use link_preview_options::*; pub use location::*; pub use login_url::*; pub use mask_position::*; +pub use maybe_anonymous_user::*; pub use maybe_inaccessible_message::*; pub use me::*; pub use menu_button::*; @@ -120,6 +129,7 @@ pub use reply_parameters::*; pub use request_id::*; pub use response_parameters::*; pub use sent_web_app_message::*; +pub use shared_user::*; pub use shipping_address::*; pub use shipping_option::*; pub use shipping_query::*; @@ -155,11 +165,19 @@ pub use write_access_allowed::*; mod allowed_update; mod animation; mod audio; +mod birthdate; mod bot_command; mod bot_command_scope; mod bot_description; mod bot_name; mod bot_short_description; +mod business_connection; +mod business_connection_id; +mod business_intro; +mod business_location; +mod business_messages_deleted; +mod business_opening_hours; +mod business_opening_hours_interval; mod callback_game; mod callback_query; mod chat; @@ -218,6 +236,7 @@ mod link_preview_options; mod location; mod login_url; mod mask_position; +mod maybe_anonymous_user; mod maybe_inaccessible_message; mod me; mod menu_button; @@ -244,6 +263,7 @@ mod reply_parameters; mod request_id; mod response_parameters; mod sent_web_app_message; +mod shared_user; mod shipping_address; mod shipping_option; mod shipping_query; diff --git a/crates/teloxide-core/src/types/allowed_update.rs b/crates/teloxide-core/src/types/allowed_update.rs index 12949ec5..73f70044 100644 --- a/crates/teloxide-core/src/types/allowed_update.rs +++ b/crates/teloxide-core/src/types/allowed_update.rs @@ -7,6 +7,10 @@ pub enum AllowedUpdate { EditedMessage, ChannelPost, EditedChannelPost, + BusinessConnection, + BusinessMessage, + EditedBusinessMessage, + DeletedBusinessMessages, MessageReaction, MessageReactionCount, InlineQuery, diff --git a/crates/teloxide-core/src/types/birthdate.rs b/crates/teloxide-core/src/types/birthdate.rs new file mode 100644 index 00000000..1c7ba65b --- /dev/null +++ b/crates/teloxide-core/src/types/birthdate.rs @@ -0,0 +1,15 @@ +use serde::{Deserialize, Serialize}; + +/// Describes the birthdate of a user. +#[serde_with::skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Birthdate { + /// Day of the user's birth; 1-31 + pub day: u8, + + /// Month of the user's birth; 1-12 + pub month: u8, + + /// Year of the user's birth + pub year: Option, +} diff --git a/crates/teloxide-core/src/types/business_connection.rs b/crates/teloxide-core/src/types/business_connection.rs new file mode 100644 index 00000000..5b620d9b --- /dev/null +++ b/crates/teloxide-core/src/types/business_connection.rs @@ -0,0 +1,29 @@ +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; + +use crate::types::{BusinessConnectionId, User, UserId}; + +/// Describes the connection of the bot with a business account. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct BusinessConnection { + /// Unique identifier of the business connection + pub id: BusinessConnectionId, + + /// Business account user that created the business connection + pub user: User, + + /// The user id of the private chat with the user who created the business + /// connection + pub user_chat_id: UserId, + + /// Date the connection was established in Unix time + #[serde(with = "crate::types::serde_date_from_unix_timestamp")] + pub date: DateTime, + + /// `true`, if the bot can act on behalf of the business account in chats + /// that were active in the last 24 hours + pub can_reply: bool, + + /// `true`, if the connection is alive + pub is_enabled: bool, +} diff --git a/crates/teloxide-core/src/types/business_connection_id.rs b/crates/teloxide-core/src/types/business_connection_id.rs new file mode 100644 index 00000000..263e2c02 --- /dev/null +++ b/crates/teloxide-core/src/types/business_connection_id.rs @@ -0,0 +1,25 @@ +use serde::{Deserialize, Serialize}; + +/// A unique business connection identifier. +#[derive(Default, Clone, Debug, derive_more::Display, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(transparent)] +pub struct BusinessConnectionId(pub String); + +#[cfg(test)] +mod tests { + use crate::types::BusinessConnectionId; + + #[test] + fn business_connection_id_deser() { + let json = r#""abcd1234""#; + let bcid: BusinessConnectionId = serde_json::from_str(json).unwrap(); + assert_eq!(bcid, BusinessConnectionId(String::from("abcd1234"))); + } + + #[test] + fn business_connection_id_ser() { + let bcid: BusinessConnectionId = BusinessConnectionId(String::from("abcd1234")); + let json = serde_json::to_string(&bcid).unwrap(); + assert_eq!(json, r#""abcd1234""#); + } +} diff --git a/crates/teloxide-core/src/types/business_intro.rs b/crates/teloxide-core/src/types/business_intro.rs new file mode 100644 index 00000000..c4684211 --- /dev/null +++ b/crates/teloxide-core/src/types/business_intro.rs @@ -0,0 +1,16 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::Sticker; + +/// An introduction for a Business. +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +pub struct BusinessIntro { + /// Title text of the business intro + pub title: Option, + + /// Message text of the business intro + pub message: Option, + + /// Sticker of the business intro + pub sticker: Option, +} diff --git a/crates/teloxide-core/src/types/business_location.rs b/crates/teloxide-core/src/types/business_location.rs new file mode 100644 index 00000000..514fe581 --- /dev/null +++ b/crates/teloxide-core/src/types/business_location.rs @@ -0,0 +1,13 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::Location; + +/// Details about the location of a Business +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +pub struct BusinessLocation { + /// Address of the business. + pub address: String, + + /// Location of the business. + pub location: Option, +} diff --git a/crates/teloxide-core/src/types/business_messages_deleted.rs b/crates/teloxide-core/src/types/business_messages_deleted.rs new file mode 100644 index 00000000..3c84daea --- /dev/null +++ b/crates/teloxide-core/src/types/business_messages_deleted.rs @@ -0,0 +1,19 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::{BusinessConnectionId, Chat, MessageId}; + +/// This object is received when messages are deleted from a connected business +/// account. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct BusinessMessagesDeleted { + /// Unique identifier of the business connection. + pub business_connection_id: BusinessConnectionId, + + /// Information about a chat in the business account. The bot may not have + /// access to the chat or the corresponding user. + pub chat: Chat, + + /// The list of identifiers of deleted messages in the chat of the business + /// account. + pub message_ids: Vec, +} diff --git a/crates/teloxide-core/src/types/business_opening_hours.rs b/crates/teloxide-core/src/types/business_opening_hours.rs new file mode 100644 index 00000000..f6bac2b9 --- /dev/null +++ b/crates/teloxide-core/src/types/business_opening_hours.rs @@ -0,0 +1,13 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::BusinessOpeningHoursInterval; + +/// Details about the opening hours of a Business. +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +pub struct BusinessOpeningHours { + /// Unique name of the time zone for which the opening hours are defined. + pub time_zone_name: String, + + /// List of time intervals describing business opening hours. + pub opening_hours: Vec, +} diff --git a/crates/teloxide-core/src/types/business_opening_hours_interval.rs b/crates/teloxide-core/src/types/business_opening_hours_interval.rs new file mode 100644 index 00000000..3c966928 --- /dev/null +++ b/crates/teloxide-core/src/types/business_opening_hours_interval.rs @@ -0,0 +1,15 @@ +use serde::{Deserialize, Serialize}; + +/// Time intervals used to describe the opening hours of a Business. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct BusinessOpeningHoursInterval { + /// The minute's sequence number in a week, starting on Monday, marking the + /// start of the time interval during which the business is open; + /// 0 - 7 * 24* 60 + pub opening_minute: u16, + + /// The minute's sequence number in a week, starting on Monday, marking the + /// end of the time interval during which the business is open; + /// 0 - 8 * 24* 60 + pub closing_minute: u16, +} diff --git a/crates/teloxide-core/src/types/chat.rs b/crates/teloxide-core/src/types/chat.rs index b4adaa5a..f9e94d9c 100644 --- a/crates/teloxide-core/src/types/chat.rs +++ b/crates/teloxide-core/src/types/chat.rs @@ -1,8 +1,8 @@ use serde::{Deserialize, Serialize}; use crate::types::{ - ChatFullInfo, ChatId, ChatLocation, ChatPermissions, ChatPhoto, Message, ReactionType, Seconds, - True, User, + Birthdate, BusinessIntro, BusinessLocation, BusinessOpeningHours, ChatFullInfo, ChatId, + ChatLocation, ChatPermissions, ChatPhoto, Message, ReactionType, Seconds, True, User, }; /// This object represents a chat. @@ -63,7 +63,7 @@ pub struct Chat { #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] pub enum ChatKind { - Public(ChatPublic), + Public(Box), Private(ChatPrivate), } @@ -133,6 +133,36 @@ pub struct ChatPrivate { /// /// [`GetChat`]: crate::payloads::GetChat pub has_restricted_voice_and_video_messages: Option, + + /// For private chats, the personal channel of the user. Returned only in + /// [`GetChat`]. + /// + /// [`GetChat`]: crate::payloads::GetChat + pub personal_chat: Option>, + + /// For private chats, the date of birth of the user. Returned only in + /// [`GetChat`]. + /// + /// [`GetChat`]: crate::payloads::GetChat + pub birthdate: Option, + + /// For private chats with business accounts, the intro of the business. + /// Returned only in [`GetChat`]. + /// + /// [`GetChat`]: crate::payloads::GetChat + pub business_intro: Option, + + /// For private chats with business accounts, the location of the business. + /// Returned only in [`GetChat`]. + /// + /// [`GetChat`]: crate::payloads::GetChat + pub business_location: Option, + + /// For private chats with business accounts, the opening hours of the + /// business. Returned only in [`GetChat`]. + /// + /// [`GetChat`]: crate::payloads::GetChat + pub business_opening_hours: Option, } #[serde_with::skip_serializing_none] @@ -256,20 +286,29 @@ impl Chat { #[must_use] pub fn is_group(&self) -> bool { - matches!(self.kind, ChatKind::Public(ChatPublic { kind: PublicChatKind::Group(_), .. })) + if let ChatKind::Public(chat_pub) = &self.kind { + matches!(**chat_pub, ChatPublic { kind: PublicChatKind::Group(_), .. }) + } else { + false + } } #[must_use] pub fn is_supergroup(&self) -> bool { - matches!( - self.kind, - ChatKind::Public(ChatPublic { kind: PublicChatKind::Supergroup(_), .. }) - ) + if let ChatKind::Public(chat_pub) = &self.kind { + matches!(**chat_pub, ChatPublic { kind: PublicChatKind::Supergroup(_), .. }) + } else { + false + } } #[must_use] pub fn is_channel(&self) -> bool { - matches!(self.kind, ChatKind::Public(ChatPublic { kind: PublicChatKind::Channel(_), .. })) + if let ChatKind::Public(chat_pub) = &self.kind { + matches!(**chat_pub, ChatPublic { kind: PublicChatKind::Channel(_), .. }) + } else { + false + } } #[must_use] @@ -563,7 +602,7 @@ impl Chat { } mod serde_helper { - use crate::types::True; + use crate::types::{Birthdate, BusinessIntro, BusinessLocation, BusinessOpeningHours, True}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] @@ -584,6 +623,11 @@ mod serde_helper { bio: Option, has_private_forwards: Option, has_restricted_voice_and_video_messages: Option, + personal_chat: Option>, + birthdate: Option, + business_intro: Option, + business_location: Option, + business_opening_hours: Option, } impl From for super::ChatPrivate { @@ -596,6 +640,11 @@ mod serde_helper { bio, has_private_forwards, has_restricted_voice_and_video_messages, + personal_chat, + birthdate, + business_intro, + business_location, + business_opening_hours, }: ChatPrivate, ) -> Self { Self { @@ -605,6 +654,11 @@ mod serde_helper { bio, has_private_forwards, has_restricted_voice_and_video_messages, + personal_chat, + birthdate, + business_intro, + business_location, + business_opening_hours, } } } @@ -618,6 +672,11 @@ mod serde_helper { bio, has_private_forwards, has_restricted_voice_and_video_messages, + personal_chat, + birthdate, + business_intro, + business_location, + business_opening_hours, }: super::ChatPrivate, ) -> Self { Self { @@ -628,6 +687,11 @@ mod serde_helper { bio, has_private_forwards, has_restricted_voice_and_video_messages, + personal_chat, + birthdate, + business_intro, + business_location, + business_opening_hours, } } } @@ -643,7 +707,7 @@ mod tests { fn channel_de() { let expected = Chat { id: ChatId(-1), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: None, kind: PublicChatKind::Channel(PublicChatChannel { username: Some("channel_name".into()), @@ -652,7 +716,7 @@ mod tests { description: None, invite_link: None, has_protected_content: None, - }), + })), photo: None, available_reactions: Some(vec![ReactionType::Emoji { emoji: "🌭".to_owned() }]), pinned_message: None, @@ -690,6 +754,11 @@ mod tests { bio: None, has_private_forwards: None, has_restricted_voice_and_video_messages: None, + personal_chat: None, + birthdate: None, + business_intro: None, + business_location: None, + business_opening_hours: None, }), photo: None, available_reactions: Some(vec![ReactionType::Emoji { emoji: "🌭".to_owned() }]), @@ -728,6 +797,11 @@ mod tests { bio: None, has_private_forwards: None, has_restricted_voice_and_video_messages: None, + personal_chat: None, + birthdate: None, + business_intro: None, + business_location: None, + business_opening_hours: None, }), photo: None, available_reactions: None, diff --git a/crates/teloxide-core/src/types/chat_shared.rs b/crates/teloxide-core/src/types/chat_shared.rs index f23c94bb..4616190a 100644 --- a/crates/teloxide-core/src/types/chat_shared.rs +++ b/crates/teloxide-core/src/types/chat_shared.rs @@ -1,8 +1,8 @@ use serde::{Deserialize, Serialize}; -use crate::types::{ChatId, RequestId}; +use crate::types::{ChatId, PhotoSize, RequestId}; -/// Information about the chat whose identifier was shared with the bot using a +/// Information about a chat that was shared with the bot using a /// [`KeyboardButtonRequestChat`] button. /// /// [`KeyboardButtonRequestChat`]: crate::types::KeyboardButtonRequestChat @@ -10,6 +10,16 @@ use crate::types::{ChatId, RequestId}; pub struct ChatShared { /// Identifier of the request. pub request_id: RequestId, + /// Identifier of the shared chat. pub chat_id: ChatId, + + /// Title of the chat, if it was requested. + pub title: Option, + + /// Username of the chat, if it was requested. + pub username: Option, + + /// Available sizes of the chat photo, if it was requested. + pub photo: Option>, } diff --git a/crates/teloxide-core/src/types/force_reply.rs b/crates/teloxide-core/src/types/force_reply.rs index 60f4130d..65ae3be6 100644 --- a/crates/teloxide-core/src/types/force_reply.rs +++ b/crates/teloxide-core/src/types/force_reply.rs @@ -29,7 +29,7 @@ pub struct ForceReply { /// (has reply_to_message_id), sender of the original message. /// /// [`Message`]: crate::types::Message - #[serde(skip_serializing_if = "std::ops::Not::not")] + #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub selective: bool, } @@ -54,3 +54,20 @@ impl ForceReply { Self { selective: true, ..self } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn deserialize() { + let data = r#" + { + "force_reply": true, + "input_field_placeholder": "placeholder", + "selective": false + } + "#; + serde_json::from_str::(data).unwrap(); + } +} diff --git a/crates/teloxide-core/src/types/input_media.rs b/crates/teloxide-core/src/types/input_media.rs index 535d26b6..621678f4 100644 --- a/crates/teloxide-core/src/types/input_media.rs +++ b/crates/teloxide-core/src/types/input_media.rs @@ -43,7 +43,7 @@ pub struct InputMediaPhoto { pub caption_entities: Option>, /// Pass `true` if the photo needs to be covered with a spoiler animation. - #[serde(skip_serializing_if = "std::ops::Not::not")] + #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub has_spoiler: bool, } @@ -131,7 +131,7 @@ pub struct InputMediaVideo { pub supports_streaming: Option, /// Pass `true` if the video needs to be covered with a spoiler animation. - #[serde(skip_serializing_if = "std::ops::Not::not")] + #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub has_spoiler: bool, } @@ -254,7 +254,7 @@ pub struct InputMediaAnimation { /// Pass `true` if the animation needs to be covered with a spoiler /// animation. - #[serde(skip_serializing_if = "std::ops::Not::not")] + #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub has_spoiler: bool, } diff --git a/crates/teloxide-core/src/types/input_sticker.rs b/crates/teloxide-core/src/types/input_sticker.rs index 18fffe7d..fa2677f8 100644 --- a/crates/teloxide-core/src/types/input_sticker.rs +++ b/crates/teloxide-core/src/types/input_sticker.rs @@ -2,6 +2,8 @@ use serde::Serialize; use crate::types::{InputFile, MaskPosition}; +use super::StickerFormat; + /// This object describes a sticker to be added to a sticker set. #[serde_with::skip_serializing_none] #[derive(Clone, Debug, Serialize)] @@ -16,6 +18,10 @@ pub struct InputSticker { /// More information on Sending Files pub sticker: InputFile, + /// Format of the added sticker, must be one of "static" for a .WEBP or .PNG + /// image, "animated" for a .TGS animation, "video" for a WEBM video + pub format: StickerFormat, + /// List of 1-20 emoji associated with the sticker pub emoji_list: Vec, diff --git a/crates/teloxide-core/src/types/keyboard_button_request_chat.rs b/crates/teloxide-core/src/types/keyboard_button_request_chat.rs index 2765aa69..47f9c4a3 100644 --- a/crates/teloxide-core/src/types/keyboard_button_request_chat.rs +++ b/crates/teloxide-core/src/types/keyboard_button_request_chat.rs @@ -2,9 +2,10 @@ use serde::{Deserialize, Serialize}; use crate::types::{ChatAdministratorRights, RequestId}; -/// This object defines the criteria used to request a suitable chat. The -/// identifier of the selected chat will be shared with the bot when the -/// corresponding button is pressed. [More about requesting chats »] +/// This object defines the criteria used to request a suitable chat. +/// Information about the selected chat will be shared with the bot when the +/// corresponding button is pressed. The bot will be granted requested rights in +/// the chat if appropriate. [More about requesting chats »] /// /// [More about requesting chats »]: https://core.telegram.org/bots/features#chat-and-user-selection #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] @@ -53,6 +54,18 @@ pub struct KeyboardButtonRequestChat { /// additional restrictions are applied. #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub bot_is_member: bool, + + /// Pass `true` to request the chat's title. + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + pub request_title: bool, + + /// Pass `true` to request the chat's username. + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + pub request_username: bool, + + /// Pass `true` to request the chat's photo. + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + pub request_photo: bool, } impl KeyboardButtonRequestChat { @@ -67,6 +80,9 @@ impl KeyboardButtonRequestChat { user_administrator_rights: None, bot_administrator_rights: None, bot_is_member: false, + request_title: false, + request_username: false, + request_photo: false, } } @@ -111,4 +127,25 @@ impl KeyboardButtonRequestChat { self.bot_is_member = value; self } + + /// Setter for `request_title` field. + #[must_use] + pub fn request_title(mut self) -> Self { + self.request_title = true; + self + } + + /// Setter for `request_username` field. + #[must_use] + pub fn request_username(mut self) -> Self { + self.request_username = true; + self + } + + /// Setter for `request_photo` field. + #[must_use] + pub fn request_photo(mut self) -> Self { + self.request_photo = true; + self + } } diff --git a/crates/teloxide-core/src/types/keyboard_button_request_users.rs b/crates/teloxide-core/src/types/keyboard_button_request_users.rs index 6f126622..8c38b831 100644 --- a/crates/teloxide-core/src/types/keyboard_button_request_users.rs +++ b/crates/teloxide-core/src/types/keyboard_button_request_users.rs @@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize}; use crate::types::RequestId; -/// This object defines the criteria used to request a suitable users. The -/// identifiers of the selected users will be shared with the bot when the +/// This object defines the criteria used to request a suitable users. +/// Information about the selected users will be shared with the bot when the /// corresponding button is pressed. More about requesting users » /// /// [More about requesting users »]: https://core.telegram.org/bots/features#chat-and-user-selection @@ -30,33 +30,77 @@ pub struct KeyboardButtonRequestUsers { /// The maximum number of users to be selected; 1-10. Defaults to 1. #[serde(default = "one", skip_serializing_if = "is_one")] pub max_quantity: u8, + + /// Pass `true` to request the users' first and last names + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + pub request_name: bool, + + /// Pass `true` to request the users' username + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + pub request_username: bool, + + /// Pass `true` to request the users' photos + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + pub request_photo: bool, } impl KeyboardButtonRequestUsers { /// Creates a new [`KeyboardButtonRequestUsers`]. pub fn new(request_id: RequestId) -> Self { - Self { request_id, user_is_bot: None, user_is_premium: None, max_quantity: 1 } + Self { + request_id, + user_is_bot: None, + user_is_premium: None, + max_quantity: 1, + request_name: false, + request_username: false, + request_photo: false, + } } /// Setter for `user_is_bot` field + #[must_use] pub fn user_is_bot(mut self, value: bool) -> Self { self.user_is_bot = Some(value); self } /// Setter for `user_is_premium` field + #[must_use] pub fn user_is_premium(mut self, value: bool) -> Self { self.user_is_premium = Some(value); self } /// Setter for `max_quantity` field, the value must be in the range 1..=10 + #[must_use] pub fn max_quantity(mut self, value: u8) -> Self { assert!((1..=10).contains(&value)); self.max_quantity = value; self } + + /// Setter for `request_name` field + #[must_use] + pub fn request_name(mut self) -> Self { + self.request_name = true; + self + } + + /// Setter for `request_username` field + #[must_use] + pub fn request_username(mut self) -> Self { + self.request_username = true; + self + } + + /// Setter for `request_photo` field + #[must_use] + pub fn request_photo(mut self) -> Self { + self.request_photo = true; + self + } } fn one() -> u8 { diff --git a/crates/teloxide-core/src/types/maybe_anonymous_user.rs b/crates/teloxide-core/src/types/maybe_anonymous_user.rs new file mode 100644 index 00000000..04b75a96 --- /dev/null +++ b/crates/teloxide-core/src/types/maybe_anonymous_user.rs @@ -0,0 +1,69 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::{Chat, User}; + +/// Represents either [`User`] or anonymous user ([`Chat`]) that acts on behalf +/// of the chat +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum MaybeAnonymousUser { + User(User), + Chat(Chat), +} + +impl MaybeAnonymousUser { + pub fn is_user(&self) -> bool { + self.user().is_some() + } + + pub fn is_chat(&self) -> bool { + self.chat().is_some() + } + + #[must_use] + pub fn chat(&self) -> Option<&Chat> { + match self { + Self::Chat(chat) => Some(chat), + _ => None, + } + } + + #[must_use] + pub fn user(&self) -> Option<&User> { + match self { + Self::User(user) => Some(user), + _ => None, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn user_de() { + let json = r#"{ + "id": 42, + "is_bot": false, + "first_name": "blah" + }"#; + + let user: MaybeAnonymousUser = serde_json::from_str(json).unwrap(); + + assert!(user.user().is_some()); + } + + #[test] + fn chat_de() { + let json = r#"{ + "id": -1001160242915, + "title": "a", + "type": "group" + }"#; + + let chat: MaybeAnonymousUser = serde_json::from_str(json).unwrap(); + + assert!(chat.chat().is_some()); + } +} diff --git a/crates/teloxide-core/src/types/me.rs b/crates/teloxide-core/src/types/me.rs index d5e58a9d..f404d438 100644 --- a/crates/teloxide-core/src/types/me.rs +++ b/crates/teloxide-core/src/types/me.rs @@ -23,6 +23,11 @@ pub struct Me { /// `true`, if the bot supports inline queries. pub supports_inline_queries: bool, + + /// `true`, if the bot can be connected to a Telegram Business account to + /// receive its messages. + #[serde(default)] + pub can_connect_to_business: bool, } impl Me { @@ -73,6 +78,7 @@ mod tests { can_join_groups: false, can_read_all_group_messages: false, supports_inline_queries: false, + can_connect_to_business: false, }; assert_eq!(me.username(), "SomethingSomethingBot"); diff --git a/crates/teloxide-core/src/types/message.rs b/crates/teloxide-core/src/types/message.rs index 9a749ea9..2b2ce6e2 100644 --- a/crates/teloxide-core/src/types/message.rs +++ b/crates/teloxide-core/src/types/message.rs @@ -5,10 +5,10 @@ use serde::{Deserialize, Serialize}; use url::Url; use crate::types::{ - Animation, Audio, BareChatId, Chat, ChatBoostAdded, ChatId, ChatShared, Contact, Dice, - Document, ExternalReplyInfo, ForumTopicClosed, ForumTopicCreated, ForumTopicEdited, - ForumTopicReopened, Game, GeneralForumTopicHidden, GeneralForumTopicUnhidden, Giveaway, - GiveawayCompleted, GiveawayCreated, GiveawayWinners, InlineKeyboardMarkup, Invoice, + Animation, Audio, BareChatId, BusinessConnectionId, Chat, ChatBoostAdded, ChatId, ChatShared, + Contact, Dice, Document, ExternalReplyInfo, ForumTopicClosed, ForumTopicCreated, + ForumTopicEdited, ForumTopicReopened, Game, GeneralForumTopicHidden, GeneralForumTopicUnhidden, + Giveaway, GiveawayCompleted, GiveawayCreated, GiveawayWinners, InlineKeyboardMarkup, Invoice, LinkPreviewOptions, Location, MaybeInaccessibleMessage, MessageAutoDeleteTimerChanged, MessageEntity, MessageEntityRef, MessageId, MessageOrigin, PassportData, PhotoSize, Poll, ProximityAlertTriggered, Sticker, Story, SuccessfulPayment, TextQuote, ThreadId, True, User, @@ -54,6 +54,11 @@ pub struct Message { /// Bot through which the message was sent. pub via_bot: Option, + /// The bot that actually sent the message on behalf of the business + /// account. Available only for outgoing messages sent on behalf of the + /// connected business account. + pub sender_business_bot: Option, + #[serde(flatten)] pub kind: MessageKind, } @@ -154,6 +159,17 @@ pub struct MessageCommon { /// `true`, if the message can't be forwarded. #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub has_protected_content: bool, + + /// `true`, if the message was sent by an implicit action, for example, as + /// an away or a greeting business message, or as a scheduled message + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + pub is_from_offline: bool, + + /// Unique identifier of the business connection from which the message was + /// received. If non-empty, the message belongs to a chat of the + /// corresponding business account that is independent from any potential + /// bot chat which might share the same identifier. + pub business_connection_id: Option, } #[serde_with::skip_serializing_none] @@ -1885,7 +1901,12 @@ mod tests { username: Some("aka_dude".to_string()), bio: None, has_private_forwards: None, - has_restricted_voice_and_video_messages: None + has_restricted_voice_and_video_messages: None, + personal_chat: None, + birthdate: None, + business_intro: None, + business_location: None, + business_opening_hours: None, }), photo: None, available_reactions: None, @@ -1895,10 +1916,14 @@ mod tests { has_hidden_members: false, chat_full_info: ChatFullInfo::default() }, + sender_business_bot: None, kind: MessageKind::ChatShared(MessageChatShared { chat_shared: ChatShared { request_id: RequestId(348349), - chat_id: ChatId(384939) + chat_id: ChatId(384939), + title: None, + username: None, + photo: None, } }), via_bot: None @@ -2108,7 +2133,7 @@ mod tests { let group = Chat { id: ChatId(-1001160242915), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: Some("a".to_owned()), kind: PublicChatKind::Supergroup(PublicChatSupergroup { username: None, @@ -2128,7 +2153,7 @@ mod tests { description: None, invite_link: None, has_protected_content: None, - }), + })), message_auto_delete_time: None, photo: None, available_reactions: None, @@ -2413,7 +2438,7 @@ mod tests { &Giveaway { chats: vec![Chat { id: ChatId(-1002236736395), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: Some("Test".to_owned()), kind: PublicChatKind::Channel(PublicChatChannel { username: None, @@ -2422,7 +2447,7 @@ mod tests { description: None, invite_link: None, has_protected_content: None - }), + })), photo: None, available_reactions: None, pinned_message: None, @@ -2522,7 +2547,7 @@ mod tests { from: None, sender_chat: Some(Chat { id: ChatId(-1002236736395), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: Some("Test".to_owned()), kind: PublicChatKind::Channel(PublicChatChannel { linked_chat_id: None, @@ -2531,7 +2556,7 @@ mod tests { description: None, invite_link: None, has_protected_content: None - }), + })), chat_full_info: ChatFullInfo::default(), available_reactions: None, photo: None, @@ -2544,7 +2569,7 @@ mod tests { date: DateTime::from_timestamp(1721161230, 0).unwrap(), chat: Chat { id: ChatId(-1002236736395), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: Some("Test".to_owned()), kind: PublicChatKind::Channel(PublicChatChannel { username: None, @@ -2553,7 +2578,7 @@ mod tests { description: None, invite_link: None, has_protected_content: None - }), + })), photo: None, available_reactions: None, pinned_message: None, @@ -2563,11 +2588,12 @@ mod tests { chat_full_info: ChatFullInfo::default() }, via_bot: None, + sender_business_bot: None, kind: MessageKind::Giveaway(MessageGiveaway { giveaway: Giveaway { chats: vec![Chat { id: ChatId(-1002236736395), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: Some("Test".to_owned()), kind: PublicChatKind::Channel(PublicChatChannel { username: None, @@ -2576,7 +2602,7 @@ mod tests { description: None, invite_link: None, has_protected_content: None - }), + })), photo: None, available_reactions: None, pinned_message: None, @@ -2668,7 +2694,7 @@ mod tests { &GiveawayWinners { chat: Chat { id: ChatId(-1002236736395), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: Some("Test".to_owned()), kind: PublicChatKind::Channel(PublicChatChannel { username: None, @@ -2677,7 +2703,7 @@ mod tests { description: None, invite_link: None, has_protected_content: None - }), + })), photo: None, available_reactions: None, pinned_message: None, diff --git a/crates/teloxide-core/src/types/message_reaction_updated.rs b/crates/teloxide-core/src/types/message_reaction_updated.rs index 8aeae9e5..5ec884c3 100644 --- a/crates/teloxide-core/src/types/message_reaction_updated.rs +++ b/crates/teloxide-core/src/types/message_reaction_updated.rs @@ -1,7 +1,7 @@ use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; -use crate::types::{Chat, MessageId, ReactionType, User}; +use crate::types::{Chat, MaybeAnonymousUser, MessageId, ReactionType, User}; /// This object represents a change of a reaction on a message performed by a /// user. @@ -15,12 +15,11 @@ pub struct MessageReactionUpdated { #[serde(flatten)] pub message_id: MessageId, - /// The user that changed the reaction, if the user isn't anonymous - pub user: Option, - - /// The chat on behalf of which the reaction was changed, if the user is - /// anonymous - pub actor_chat: Option, + /// The [`MaybeAnonymousUser::User`] that changed the reaction, if the user + /// isn't anonymous or the [`MaybeAnonymousUser::Chat`] on behalf of + /// which the reaction was changed, if the user is anonymous + #[serde(deserialize_with = "deserialize_actor", flatten)] + pub actor: MaybeAnonymousUser, /// Date of the change in Unix time #[serde(with = "crate::types::serde_date_from_unix_timestamp")] @@ -35,22 +34,37 @@ pub struct MessageReactionUpdated { impl MessageReactionUpdated { #[must_use] - pub fn actor_chat(&self) -> Option<&Chat> { - self.actor_chat.as_ref() + pub fn chat(&self) -> Option<&Chat> { + self.actor.chat() } #[must_use] pub fn user(&self) -> Option<&User> { - self.user.as_ref() + self.actor.user() } } +#[derive(Deserialize)] +struct ActorDe { + /// The user that changed the reaction, if the user isn't anonymous + user: Option, + /// The chat on behalf of which the reaction was changed, if the user is + /// anonymous + actor_chat: Option, +} + +fn deserialize_actor<'d, D: Deserializer<'d>>(d: D) -> Result { + let ActorDe { user, actor_chat } = ActorDe::deserialize(d)?; + + Ok(actor_chat.map(MaybeAnonymousUser::Chat).or(user.map(MaybeAnonymousUser::User)).unwrap()) +} + #[cfg(test)] mod tests { use super::*; #[test] - fn deserialize() { + fn deserialize_user() { let data = r#" { "chat": { @@ -77,6 +91,37 @@ mod tests { ] } "#; - serde_json::from_str::(data).unwrap(); + let message_reaction_update = serde_json::from_str::(data).unwrap(); + + assert!(message_reaction_update.actor.is_user()); + } + + #[test] + fn deserialize_chat() { + let data = r#"{ + "chat": { + "id": -1002199793788, + "title": "тест", + "type": "supergroup" + }, + "message_id": 2, + "actor_chat": { + "id": -1002199793788, + "title": "тест", + "type": "supergroup" + }, + "date": 1723798597, + "old_reaction": [ + { + "type": "emoji", + "emoji": "❤" + } + ], + "new_reaction": [] + }"#; + + let message_reaction_update = serde_json::from_str::(data).unwrap(); + + assert!(message_reaction_update.actor.is_chat()) } } diff --git a/crates/teloxide-core/src/types/poll_answer.rs b/crates/teloxide-core/src/types/poll_answer.rs index 5fb670b0..706c4062 100644 --- a/crates/teloxide-core/src/types/poll_answer.rs +++ b/crates/teloxide-core/src/types/poll_answer.rs @@ -1,10 +1,11 @@ use serde::{Deserialize, Deserializer, Serialize}; -use crate::types::{Chat, User}; +use crate::types::{Chat, MaybeAnonymousUser, User}; #[serde_with::skip_serializing_none] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PollAnswer { + // FIXME: PollId /// Unique poll identifier. pub poll_id: String, @@ -14,7 +15,7 @@ pub struct PollAnswer { /// If the voter isn't anonymous, stores the user that changed /// the answer to the poll #[serde(deserialize_with = "deserialize_voter", flatten)] - pub voter: Voter, + pub voter: MaybeAnonymousUser, /// 0-based identifiers of answer options, chosen by the user. /// @@ -22,31 +23,6 @@ pub struct PollAnswer { pub option_ids: Vec, } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(untagged)] -pub enum Voter { - Chat(Chat), - User(User), -} - -impl Voter { - #[must_use] - pub fn chat(&self) -> Option<&Chat> { - match self { - Self::Chat(chat) => Some(chat), - _ => None, - } - } - - #[must_use] - pub fn user(&self) -> Option<&User> { - match self { - Self::User(user) => Some(user), - _ => None, - } - } -} - /// These fields `chat` and `user` from the original [`PollAnswer`] should be /// exclusive, but in cases when the `voter_chat` is presented the `user` isn't /// `None`, but rather actual value for backward compatibility, the field `user` @@ -61,9 +37,9 @@ struct VoterDe { pub user: Option, } -fn deserialize_voter<'d, D: Deserializer<'d>>(d: D) -> Result { +fn deserialize_voter<'d, D: Deserializer<'d>>(d: D) -> Result { let VoterDe { voter_chat, user } = VoterDe::deserialize(d)?; - Ok(voter_chat.map(Voter::Chat).or(user.map(Voter::User)).unwrap()) + Ok(voter_chat.map(MaybeAnonymousUser::Chat).or(user.map(MaybeAnonymousUser::User)).unwrap()) } #[cfg(test)] @@ -71,21 +47,22 @@ mod tests { use super::*; #[test] - fn test_poll_answer_with_user_de() { + fn poll_answer_with_user_de() { let json = r#"{ - "poll_id":"POLL_ID", - "user": {"id":42,"is_bot":false,"first_name":"blah"}, + "poll_id": "POLL_ID", + "user": {"id": 42,"is_bot": false,"first_name": "blah"}, "option_ids": [] }"#; let poll_answer: PollAnswer = serde_json::from_str(json).unwrap(); - assert!(matches!(poll_answer.voter, Voter::User(_))); + + assert!(poll_answer.voter.is_user()); } #[test] - fn test_poll_answer_with_voter_chat_de() { + fn poll_answer_with_voter_chat_de() { let json = r#"{ - "poll_id":"POLL_ID", + "poll_id": "POLL_ID", "voter_chat": { "id": -1001160242915, "title": "a", @@ -95,11 +72,11 @@ mod tests { }"#; let poll_answer: PollAnswer = serde_json::from_str(json).unwrap(); - assert!(matches!(poll_answer.voter, Voter::Chat(_))); + assert!(poll_answer.voter.is_chat()); } #[test] - fn test_poll_answer_with_both_user_and_voter_chat_de() { + fn poll_answer_with_both_user_and_voter_chat_de() { let json = r#"{ "poll_id":"POLL_ID", "voter_chat": { @@ -107,11 +84,11 @@ mod tests { "title": "a", "type": "group" }, - "user": {"id":136817688,"is_bot":true,"first_name":"Channel_Bot"}, + "user": {"id": 136817688,"is_bot": true,"first_name": "Channel_Bot"}, "option_ids": [] }"#; let poll_answer: PollAnswer = serde_json::from_str(json).unwrap(); - assert!(matches!(poll_answer.voter, Voter::Chat(_))); + assert!(poll_answer.voter.is_chat()); } } diff --git a/crates/teloxide-core/src/types/reply_keyboard_markup.rs b/crates/teloxide-core/src/types/reply_keyboard_markup.rs index e409f469..4b38b2df 100644 --- a/crates/teloxide-core/src/types/reply_keyboard_markup.rs +++ b/crates/teloxide-core/src/types/reply_keyboard_markup.rs @@ -22,14 +22,14 @@ pub struct KeyboardMarkup { /// Requests clients to always show the keyboard when the regular keyboard /// is hidden. Defaults to `false`, in which case the custom keyboard /// can be hidden and opened with a keyboard icon. - #[serde(skip_serializing_if = "std::ops::Not::not")] + #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub is_persistent: bool, /// Requests clients to resize the keyboard vertically for optimal fit /// (e.g., make the keyboard smaller if there are just two rows of /// buttons). Defaults to `false`, in which case the custom keyboard is /// always of the same height as the app's standard keyboard. - #[serde(skip_serializing_if = "std::ops::Not::not")] + #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub resize_keyboard: bool, /// Requests clients to hide the keyboard as soon as it's been used. The @@ -37,12 +37,12 @@ pub struct KeyboardMarkup { /// display the usual letter-keyboard in the chat – the user can press a /// special button in the input field to see the custom keyboard again. /// Defaults to `false`. - #[serde(skip_serializing_if = "std::ops::Not::not")] + #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub one_time_keyboard: bool, /// The placeholder to be shown in the input field when the keyboard is /// active; 1-64 characters. - #[serde(skip_serializing_if = "str::is_empty")] + #[serde(default, skip_serializing_if = "str::is_empty")] pub input_field_placeholder: String, /// Use this parameter if you want to show the keyboard to specific users @@ -55,7 +55,7 @@ pub struct KeyboardMarkup { /// in the group don’t see the keyboard. /// /// [`Message`]: crate::types::Message - #[serde(skip_serializing_if = "std::ops::Not::not")] + #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub selective: bool, } @@ -129,3 +129,23 @@ impl KeyboardMarkup { Self { selective: true, ..self } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn deserialize() { + let data = r#" + { + "keyboard": [[{"text": "a"}, {"text": "b"}], [{"text": "c"}, {"text": "d"}]], + "input_field_placeholder": "", + "is_persistent": true, + "one_time_keyboard": false, + "resize_keyboard": true, + "selective": false + } + "#; + serde_json::from_str::(data).unwrap(); + } +} diff --git a/crates/teloxide-core/src/types/reply_keyboard_remove.rs b/crates/teloxide-core/src/types/reply_keyboard_remove.rs index 3c08ad9c..0fe6a6fe 100644 --- a/crates/teloxide-core/src/types/reply_keyboard_remove.rs +++ b/crates/teloxide-core/src/types/reply_keyboard_remove.rs @@ -34,7 +34,7 @@ pub struct KeyboardRemove { /// showing the keyboard with poll options to users who haven't voted yet. /// /// [`Message`]: crate::types::Message - #[serde(skip_serializing_if = "std::ops::Not::not")] + #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub selective: bool, } @@ -52,3 +52,19 @@ impl KeyboardRemove { Self { selective: true, ..self } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn deserialize() { + let data = r#" + { + "remove_keyboard": true, + "selective": false + } + "#; + serde_json::from_str::(data).unwrap(); + } +} diff --git a/crates/teloxide-core/src/types/reply_parameters.rs b/crates/teloxide-core/src/types/reply_parameters.rs index 794c4896..6baa8ed9 100644 --- a/crates/teloxide-core/src/types/reply_parameters.rs +++ b/crates/teloxide-core/src/types/reply_parameters.rs @@ -13,11 +13,14 @@ pub struct ReplyParameters { pub message_id: MessageId, /// If the message to be replied to is from a different chat, unique /// identifier for the chat or username of the channel (in the format - /// `@channelusername`) + /// `@channelusername`). Not supported for messages sent on behalf of a + /// business account. pub chat_id: Option, /// Pass _true_ if the message should be sent even if the specified message /// to be replied to is not found; can be used only for replies in the - /// same chat and forum topic. + /// same chat and forum topic. Always `false` for replies in another chat or + /// forum topic. Always `true` for messages sent on behalf of a business + /// account. pub allow_sending_without_reply: Option, /// Quoted part of the message to be replied to; 0-1024 characters after /// entities parsing. The quote must be an exact substring of the message to diff --git a/crates/teloxide-core/src/types/shared_user.rs b/crates/teloxide-core/src/types/shared_user.rs new file mode 100644 index 00000000..bca2dcb9 --- /dev/null +++ b/crates/teloxide-core/src/types/shared_user.rs @@ -0,0 +1,25 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::{PhotoSize, UserId}; + +/// This object contains information about a user that was shared with the bot +/// using a [`KeyboardButtonRequestUsers`] button. +/// +/// [`KeyboardButtonRequestUsers`]: crate::types::KeyboardButtonRequestUsers +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +pub struct SharedUser { + /// Identifier of the shared user + pub user_id: UserId, + + /// First name of the user, if it was requested by the bot + pub first_name: Option, + + /// Last name of the user, if it was requested by the bot + pub last_name: Option, + + /// Username of the user, if it was requested by the bot + pub username: Option, + + /// Available sizes of the chat photo, if it was requested + pub photo: Option>, +} diff --git a/crates/teloxide-core/src/types/sticker_set.rs b/crates/teloxide-core/src/types/sticker_set.rs index 12c92bb1..32b9f379 100644 --- a/crates/teloxide-core/src/types/sticker_set.rs +++ b/crates/teloxide-core/src/types/sticker_set.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use serde::{Deserialize, Serialize}; -use crate::types::{PhotoSize, Sticker, StickerFormat, StickerFormatFlags, StickerType}; +use crate::types::{PhotoSize, Sticker, StickerType}; /// This object represents a sticker set. /// @@ -20,11 +20,6 @@ pub struct StickerSet { #[serde(flatten)] pub kind: StickerType, - // FIXME: remove it in 7.2 https://core.telegram.org/bots/api#march-31-2024 - /// Sticker format flags shared by all stickers in this set. - #[serde(flatten)] - pub flags: StickerFormatFlags, - /// List of all set stickers. pub stickers: Vec, @@ -50,66 +45,6 @@ impl Deref for StickerSet { } } -impl StickerSet { - // FIXME: remove deprecation, when it will be a way to determine the format of - // the sticker set - /// Returns the format of the stickers in this set - /// - /// Note: this method currently is useless, so the format is always - /// StickerFormat::Static - #[must_use] - #[deprecated(note = "TBA7.2 brought the breaking change: flags 'is_video' and 'is_animated' \ - were removed, so currently there is no way to determine the format of \ - the sticker set in the currently supported version (TBA6.6)")] - pub fn format(&self) -> StickerFormat { - self.flags.format() - } - - /// Returns `true` is this is a "normal" raster sticker. - /// - /// Alias to [`self.format().is_static()`]. - /// - /// [`self.format().is_static()`]: StickerFormat::is_static - #[must_use] - #[deprecated(note = "TBA7.2 brought the breaking change: flags 'is_video' and 'is_animated' \ - were removed, so currently there is no way to determine the format of \ - the sticker set in the currently supported version (TBA6.6)")] - pub fn is_static(&self) -> bool { - #[allow(deprecated)] - self.format().is_static() - } - - /// Returns `true` is this is an [animated] sticker. - /// - /// Alias to [`self.format().is_animated()`]. - /// - /// [`self.format().is_animated()`]: StickerFormat::is_animated - /// [animated]: https://telegram.org/blog/animated-stickers - #[must_use] - #[deprecated(note = "TBA7.2 brought the breaking change: flags 'is_video' and 'is_animated' \ - were removed, so currently there is no way to determine the format of \ - the sticker set in the currently supported version (TBA6.6)")] - pub fn is_animated(&self) -> bool { - #[allow(deprecated)] - self.format().is_animated() - } - - /// Returns `true` is this is a [video] sticker. - /// - /// Alias to [`self.format().is_video()`]. - /// - /// [`self.format().is_video()`]: StickerFormat::is_video - /// [video]: https://telegram.org/blog/video-stickers-better-reactions - #[must_use] - #[deprecated(note = "TBA7.2 brought the breaking change: flags 'is_video' and 'is_animated' \ - were removed, so currently there is no way to determine the format of \ - the sticker set in the currently supported version (TBA6.6)")] - pub fn is_video(&self) -> bool { - #[allow(deprecated)] - self.format().is_video() - } -} - #[cfg(test)] mod tests { use crate::types::StickerSet; diff --git a/crates/teloxide-core/src/types/story.rs b/crates/teloxide-core/src/types/story.rs index 41ac32c5..abe63eac 100644 --- a/crates/teloxide-core/src/types/story.rs +++ b/crates/teloxide-core/src/types/story.rs @@ -44,7 +44,7 @@ mod tests { let story = Story { chat: Chat { id: ChatId(-1001389841361), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: Some("GNOME".to_owned()), kind: PublicChatKind::Supergroup(PublicChatSupergroup { username: Some("gnome_ru".to_owned()), @@ -64,7 +64,7 @@ mod tests { description: None, invite_link: None, has_protected_content: None, - }), + })), photo: None, available_reactions: None, pinned_message: None, diff --git a/crates/teloxide-core/src/types/update.rs b/crates/teloxide-core/src/types/update.rs index 92bebc8f..dd06de27 100644 --- a/crates/teloxide-core/src/types/update.rs +++ b/crates/teloxide-core/src/types/update.rs @@ -3,9 +3,10 @@ use serde::{de::MapAccess, Deserialize, Serialize, Serializer}; use serde_json::Value; use crate::types::{ - CallbackQuery, Chat, ChatBoostRemoved, ChatBoostUpdated, ChatJoinRequest, ChatMemberUpdated, - ChosenInlineResult, InlineQuery, Message, MessageReactionCountUpdated, MessageReactionUpdated, - Poll, PollAnswer, PreCheckoutQuery, ShippingQuery, User, + BusinessConnection, BusinessMessagesDeleted, CallbackQuery, Chat, ChatBoostRemoved, + ChatBoostUpdated, ChatJoinRequest, ChatMemberUpdated, ChosenInlineResult, InlineQuery, Message, + MessageReactionCountUpdated, MessageReactionUpdated, Poll, PollAnswer, PreCheckoutQuery, + ShippingQuery, User, }; /// This [object] represents an incoming update. @@ -60,6 +61,19 @@ pub enum UpdateKind { /// New version of a channel post that is known to the bot and was edited. EditedChannelPost(Message), + /// The bot was connected to or disconnected from a business account, or a + /// user edited an existing connection with the bot + BusinessConnection(BusinessConnection), + + /// New non-service message from a connected business account + BusinessMessage(Message), + + /// New version of a message from a connected business account + EditedBusinessMessage(Message), + + /// Messages were deleted from a connected business account + DeletedBusinessMessages(BusinessMessagesDeleted), + /// A reaction to a message was changed by a user. The bot must be an /// administrator in the chat and must explicitly specify /// [`AllowedUpdate::MessageReaction`] in the list of `allowed_updates` @@ -156,9 +170,14 @@ impl Update { use UpdateKind::*; let from = match &self.kind { - Message(m) | EditedMessage(m) | ChannelPost(m) | EditedChannelPost(m) => { - m.from.as_ref()? - } + Message(m) + | EditedMessage(m) + | ChannelPost(m) + | EditedChannelPost(m) + | BusinessMessage(m) + | EditedBusinessMessage(m) => m.from.as_ref()?, + + BusinessConnection(conn) => &conn.user, CallbackQuery(query) => &query.from, ChosenInlineResult(chosen) => &chosen.from, @@ -173,7 +192,9 @@ impl Update { ChatBoost(b) => return b.boost.source.user(), RemovedChatBoost(b) => return b.source.user(), - MessageReactionCount(_) | Poll(_) | Error(_) => return None, + MessageReactionCount(_) | DeletedBusinessMessages(_) | Poll(_) | Error(_) => { + return None + } }; Some(from) @@ -221,7 +242,9 @@ impl Update { UpdateKind::Message(message) | UpdateKind::EditedMessage(message) | UpdateKind::ChannelPost(message) - | UpdateKind::EditedChannelPost(message) => i0(message.mentioned_users()), + | UpdateKind::EditedChannelPost(message) + | UpdateKind::BusinessMessage(message) + | UpdateKind::EditedBusinessMessage(message) => i0(message.mentioned_users()), UpdateKind::MessageReaction(answer) => { if let Some(user) = answer.user() { @@ -262,7 +285,10 @@ impl Update { i6(empty()) } - UpdateKind::MessageReactionCount(_) | UpdateKind::Error(_) => i6(empty()), + UpdateKind::MessageReactionCount(_) + | UpdateKind::BusinessConnection(_) + | UpdateKind::DeletedBusinessMessages(_) + | UpdateKind::Error(_) => i6(empty()), } } @@ -272,7 +298,12 @@ impl Update { use UpdateKind::*; let chat = match &self.kind { - Message(m) | EditedMessage(m) | ChannelPost(m) | EditedChannelPost(m) => &m.chat, + Message(m) + | EditedMessage(m) + | ChannelPost(m) + | EditedChannelPost(m) + | BusinessMessage(m) + | EditedBusinessMessage(m) => &m.chat, CallbackQuery(q) => q.message.as_ref()?.chat(), ChatMember(m) => &m.chat, MyChatMember(m) => &m.chat, @@ -281,8 +312,10 @@ impl Update { MessageReactionCount(r) => &r.chat, ChatBoost(b) => &b.chat, RemovedChatBoost(b) => &b.chat, + DeletedBusinessMessages(m) => &m.chat, InlineQuery(_) + | BusinessConnection(_) | ChosenInlineResult(_) | ShippingQuery(_) | PreCheckoutQuery(_) @@ -350,6 +383,20 @@ impl<'de> Deserialize<'de> for UpdateKind { "edited_channel_post" => { map.next_value::().ok().map(UpdateKind::EditedChannelPost) } + "business_connection" => map + .next_value::() + .ok() + .map(UpdateKind::BusinessConnection), + "business_message" => { + map.next_value::().ok().map(UpdateKind::BusinessMessage) + } + "edited_business_message" => { + map.next_value::().ok().map(UpdateKind::EditedBusinessMessage) + } + "deleted_business_messages" => map + .next_value::() + .ok() + .map(UpdateKind::DeletedBusinessMessages), "message_reaction" => map .next_value::() .ok() @@ -423,37 +470,49 @@ impl Serialize for UpdateKind { UpdateKind::EditedChannelPost(v) => { s.serialize_newtype_variant(name, 3, "edited_channel_post", v) } + UpdateKind::BusinessConnection(v) => { + s.serialize_newtype_variant(name, 4, "business_connection", v) + } + UpdateKind::BusinessMessage(v) => { + s.serialize_newtype_variant(name, 5, "business_message", v) + } + UpdateKind::EditedBusinessMessage(v) => { + s.serialize_newtype_variant(name, 6, "edited_business_message", v) + } + UpdateKind::DeletedBusinessMessages(v) => { + s.serialize_newtype_variant(name, 7, "deleted_business_messages", v) + } UpdateKind::MessageReaction(v) => { - s.serialize_newtype_variant(name, 4, "message_reaction", v) + s.serialize_newtype_variant(name, 8, "message_reaction", v) } UpdateKind::MessageReactionCount(v) => { - s.serialize_newtype_variant(name, 5, "message_reaction_count", v) + s.serialize_newtype_variant(name, 9, "message_reaction_count", v) } - UpdateKind::InlineQuery(v) => s.serialize_newtype_variant(name, 6, "inline_query", v), + UpdateKind::InlineQuery(v) => s.serialize_newtype_variant(name, 10, "inline_query", v), UpdateKind::ChosenInlineResult(v) => { - s.serialize_newtype_variant(name, 7, "chosen_inline_result", v) + s.serialize_newtype_variant(name, 11, "chosen_inline_result", v) } UpdateKind::CallbackQuery(v) => { - s.serialize_newtype_variant(name, 8, "callback_query", v) + s.serialize_newtype_variant(name, 12, "callback_query", v) } UpdateKind::ShippingQuery(v) => { - s.serialize_newtype_variant(name, 9, "shipping_query", v) + s.serialize_newtype_variant(name, 13, "shipping_query", v) } UpdateKind::PreCheckoutQuery(v) => { - s.serialize_newtype_variant(name, 10, "pre_checkout_query", v) + s.serialize_newtype_variant(name, 14, "pre_checkout_query", v) } - UpdateKind::Poll(v) => s.serialize_newtype_variant(name, 11, "poll", v), - UpdateKind::PollAnswer(v) => s.serialize_newtype_variant(name, 12, "poll_answer", v), + UpdateKind::Poll(v) => s.serialize_newtype_variant(name, 15, "poll", v), + UpdateKind::PollAnswer(v) => s.serialize_newtype_variant(name, 16, "poll_answer", v), UpdateKind::MyChatMember(v) => { - s.serialize_newtype_variant(name, 13, "my_chat_member", v) + s.serialize_newtype_variant(name, 17, "my_chat_member", v) } - UpdateKind::ChatMember(v) => s.serialize_newtype_variant(name, 14, "chat_member", v), + UpdateKind::ChatMember(v) => s.serialize_newtype_variant(name, 18, "chat_member", v), UpdateKind::ChatJoinRequest(v) => { - s.serialize_newtype_variant(name, 15, "chat_join_request", v) + s.serialize_newtype_variant(name, 19, "chat_join_request", v) } - UpdateKind::ChatBoost(v) => s.serialize_newtype_variant(name, 16, "chat_boost", v), + UpdateKind::ChatBoost(v) => s.serialize_newtype_variant(name, 20, "chat_boost", v), UpdateKind::RemovedChatBoost(v) => { - s.serialize_newtype_variant(name, 17, "removed_chat_boost", v) + s.serialize_newtype_variant(name, 21, "removed_chat_boost", v) } UpdateKind::Error(v) => v.serialize(s), } @@ -469,13 +528,14 @@ mod test { use crate::types::{ Chat, ChatBoost, ChatBoostRemoved, ChatBoostSource, ChatBoostSourcePremium, ChatBoostUpdated, ChatFullInfo, ChatId, ChatKind, ChatPrivate, ChatPublic, - LinkPreviewOptions, MediaKind, MediaText, Message, MessageCommon, MessageId, MessageKind, - MessageReactionCountUpdated, MessageReactionUpdated, PublicChatChannel, PublicChatKind, - PublicChatSupergroup, ReactionCount, ReactionType, Update, UpdateId, UpdateKind, User, - UserId, + LinkPreviewOptions, MaybeAnonymousUser, MediaKind, MediaText, Message, MessageCommon, + MessageId, MessageKind, MessageReactionCountUpdated, MessageReactionUpdated, + PublicChatChannel, PublicChatKind, PublicChatSupergroup, ReactionCount, ReactionType, + Update, UpdateId, UpdateKind, User, UserId, }; use chrono::DateTime; + use pretty_assertions::assert_eq; // TODO: more tests for deserialization #[test] @@ -534,6 +594,11 @@ mod test { bio: None, has_private_forwards: None, has_restricted_voice_and_video_messages: None, + personal_chat: None, + birthdate: None, + business_intro: None, + business_location: None, + business_opening_hours: None, }), photo: None, available_reactions: None, @@ -543,6 +608,7 @@ mod test { has_aggressive_anti_spam_enabled: false, chat_full_info: ChatFullInfo::default(), }, + sender_business_bot: None, kind: MessageKind::Common(MessageCommon { reply_to_message: None, forward_origin: None, @@ -566,6 +632,8 @@ mod test { author_signature: None, is_automatic_forward: false, has_protected_content: false, + is_from_offline: false, + business_connection_id: None, }), }), }; @@ -588,7 +656,7 @@ mod test { "from": { "first_name": "Wert", "id": 6962620676, - "is_bot": false, + "is_bot": false, "username": "WertCrypto" }, "message_id": 134545, @@ -630,7 +698,7 @@ mod test { "from": { "first_name": "the Cable Guy", "id": 5964236329, - "is_bot": false, + "is_bot": false, "language_code":"en", "username": "spacewhaleblues" }, @@ -647,7 +715,7 @@ mod test { "from": { "first_name": "Wert", "id": 6962620676, - "is_bot": false, + "is_bot": false, "username": "WertCrypto" }, "message_id": 134545, @@ -862,7 +930,7 @@ mod test { kind: UpdateKind::MessageReaction(MessageReactionUpdated { chat: Chat { id: ChatId(-1002184233434), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: Some("Test".to_owned()), kind: PublicChatKind::Supergroup(PublicChatSupergroup { username: None, @@ -882,7 +950,7 @@ mod test { description: None, invite_link: None, has_protected_content: None, - }), + })), photo: None, available_reactions: None, pinned_message: None, @@ -892,7 +960,7 @@ mod test { chat_full_info: ChatFullInfo::default(), }, message_id: MessageId(35), - user: Some(User { + actor: MaybeAnonymousUser::User(User { id: UserId(1459074222), is_bot: false, first_name: "shadowchain".to_owned(), @@ -902,7 +970,6 @@ mod test { is_premium: true, added_to_attachment_menu: false, }), - actor_chat: None, date: DateTime::from_timestamp(1721306082, 0).unwrap(), old_reaction: vec![], new_reaction: vec![ReactionType::Emoji { emoji: "🌭".to_owned() }], @@ -911,6 +978,78 @@ mod test { let actual = serde_json::from_str::(json).unwrap(); assert_eq!(expected, actual); + + let json = r#" + { + "update_id": 767844136, + "message_reaction": { + "chat": { + "id": -1002199793788, + "title": "тест", + "type": "supergroup" + }, + "message_id": 2, + "actor_chat": { + "id": -1002199793788, + "title": "тест", + "type": "supergroup" + }, + "date": 1723798597, + "old_reaction": [ + { + "type": "emoji", + "emoji": "❤" + } + ], + "new_reaction": [] + } + } + "#; + let chat = Chat { + id: ChatId(-1002199793788), + kind: ChatKind::Public(Box::new(ChatPublic { + title: Some("тест".to_owned()), + kind: PublicChatKind::Supergroup(PublicChatSupergroup { + username: None, + active_usernames: None, + is_forum: false, + sticker_set_name: None, + can_set_sticker_set: None, + permissions: None, + slow_mode_delay: None, + linked_chat_id: None, + location: None, + join_to_send_messages: None, + join_by_request: None, + custom_emoji_sticker_set_name: None, + unrestrict_boost_count: None, + }), + description: None, + invite_link: None, + has_protected_content: None, + })), + photo: None, + available_reactions: None, + pinned_message: None, + message_auto_delete_time: None, + has_hidden_members: false, + has_aggressive_anti_spam_enabled: false, + chat_full_info: ChatFullInfo::default(), + }; + let expected = Update { + id: UpdateId(767844136), + kind: UpdateKind::MessageReaction(MessageReactionUpdated { + chat: chat.clone(), + message_id: MessageId(2), + actor: MaybeAnonymousUser::Chat(chat), + date: DateTime::from_timestamp(1723798597, 0).unwrap(), + old_reaction: vec![ReactionType::Emoji { emoji: "❤".to_owned() }], + new_reaction: vec![], + }), + }; + + let actual = serde_json::from_str::(json).unwrap(); + assert_eq!(expected, actual); } #[test] @@ -951,7 +1090,7 @@ mod test { kind: UpdateKind::MessageReactionCount(MessageReactionCountUpdated { chat: Chat { id: ChatId(-1002236736395), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: Some("Test".to_owned()), kind: PublicChatKind::Channel(PublicChatChannel { username: None, @@ -960,7 +1099,7 @@ mod test { description: None, invite_link: None, has_protected_content: None, - }), + })), photo: None, available_reactions: None, pinned_message: None, @@ -1024,7 +1163,7 @@ mod test { kind: UpdateKind::ChatBoost(ChatBoostUpdated { chat: Chat { id: ChatId(-1002236736395), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: Some("Test".to_owned()), kind: PublicChatKind::Channel(PublicChatChannel { username: None, @@ -1033,7 +1172,7 @@ mod test { description: None, invite_link: None, has_protected_content: None, - }), + })), photo: None, available_reactions: None, pinned_message: None, @@ -1099,7 +1238,7 @@ mod test { kind: UpdateKind::RemovedChatBoost(ChatBoostRemoved { chat: Chat { id: ChatId(-1002236736395), - kind: ChatKind::Public(ChatPublic { + kind: ChatKind::Public(Box::new(ChatPublic { title: Some("Test".to_owned()), kind: PublicChatKind::Channel(PublicChatChannel { username: None, @@ -1108,7 +1247,7 @@ mod test { description: None, invite_link: None, has_protected_content: None, - }), + })), photo: None, available_reactions: None, pinned_message: None, diff --git a/crates/teloxide-core/src/types/users_shared.rs b/crates/teloxide-core/src/types/users_shared.rs index d522fa54..c78c3625 100644 --- a/crates/teloxide-core/src/types/users_shared.rs +++ b/crates/teloxide-core/src/types/users_shared.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -use crate::types::{RequestId, UserId}; +use crate::types::{RequestId, SharedUser}; /// This object contains information about the users whose identifiers were /// shared with the bot using a [KeyboardButtonRequestUsers] button. @@ -11,5 +11,5 @@ pub struct UsersShared { /// Identifier of the request pub request_id: RequestId, /// Identifiers of the shared users - pub user_ids: Vec, + pub users: Vec, } diff --git a/crates/teloxide/src/dispatching/filter_ext.rs b/crates/teloxide/src/dispatching/filter_ext.rs index e9cb3f4c..09b16eb6 100644 --- a/crates/teloxide/src/dispatching/filter_ext.rs +++ b/crates/teloxide/src/dispatching/filter_ext.rs @@ -155,6 +155,10 @@ define_update_ext! { (filter_edited_message, UpdateKind::EditedMessage, EditedMessage), (filter_channel_post, UpdateKind::ChannelPost, ChannelPost), (filter_edited_channel_post, UpdateKind::EditedChannelPost, EditedChannelPost), + (filter_business_connection, UpdateKind::BusinessConnection, BusinessConnection), + (filter_business_message, UpdateKind::BusinessMessage, BusinessMessage), + (filter_edited_business_message, UpdateKind::EditedBusinessMessage, EditedBusinessMessage), + (filter_deleted_business_messages, UpdateKind::DeletedBusinessMessages, DeletedBusinessMessages), (filter_message_reaction_updated, UpdateKind::MessageReaction, MessageReaction), (filter_message_reaction_count_updated, UpdateKind::MessageReactionCount, MessageReactionCount), (filter_inline_query, UpdateKind::InlineQuery, InlineQuery), diff --git a/crates/teloxide/src/dispatching/handler_description.rs b/crates/teloxide/src/dispatching/handler_description.rs index 0398f2df..f798eee3 100644 --- a/crates/teloxide/src/dispatching/handler_description.rs +++ b/crates/teloxide/src/dispatching/handler_description.rs @@ -65,6 +65,10 @@ impl EventKind for Kind { EditedMessage, ChannelPost, EditedChannelPost, + BusinessConnection, + BusinessMessage, + EditedBusinessMessage, + DeletedBusinessMessages, MessageReaction, MessageReactionCount, InlineQuery, @@ -164,10 +168,28 @@ mod tests { for update in allowed_updates_reference { match update { // CAUTION: Don't forget to add new `UpdateKind` to `allowed_updates_reference`! - Message | EditedMessage | ChannelPost | EditedChannelPost | MessageReaction - | MessageReactionCount | InlineQuery | ChosenInlineResult | CallbackQuery - | ShippingQuery | PreCheckoutQuery | Poll | PollAnswer | MyChatMember - | ChatMember | ChatJoinRequest | ChatBoost | RemovedChatBoost => { + Message + | EditedMessage + | ChannelPost + | EditedChannelPost + | MessageReaction + | MessageReactionCount + | InlineQuery + | ChosenInlineResult + | CallbackQuery + | ShippingQuery + | PreCheckoutQuery + | Poll + | PollAnswer + | MyChatMember + | ChatMember + | ChatJoinRequest + | ChatBoost + | RemovedChatBoost + | BusinessMessage + | BusinessConnection + | EditedBusinessMessage + | DeletedBusinessMessages => { assert!(full_set.contains(&Kind(update))) } } diff --git a/crates/teloxide/src/dispatching/handler_ext.rs b/crates/teloxide/src/dispatching/handler_ext.rs index ecda2406..d45c29f1 100644 --- a/crates/teloxide/src/dispatching/handler_ext.rs +++ b/crates/teloxide/src/dispatching/handler_ext.rs @@ -189,6 +189,7 @@ mod tests { }), sender_chat: None, is_topic_message: false, + sender_business_bot: None, date, chat: Chat { id: ChatId(109_998_024), @@ -199,6 +200,11 @@ mod tests { bio: None, has_private_forwards: None, has_restricted_voice_and_video_messages: None, + business_intro: None, + business_location: None, + business_opening_hours: None, + birthdate: None, + personal_chat: None, }), photo: None, available_reactions: None, @@ -231,6 +237,8 @@ mod tests { has_protected_content: false, reply_to_story: None, sender_boost_count: None, + is_from_offline: false, + business_connection_id: None, }), }), } @@ -251,6 +259,7 @@ mod tests { can_join_groups: false, can_read_all_group_messages: false, supports_inline_queries: false, + can_connect_to_business: false, } } diff --git a/crates/teloxide/src/lib.rs b/crates/teloxide/src/lib.rs index 7a789398..bcb901f1 100644 --- a/crates/teloxide/src/lib.rs +++ b/crates/teloxide/src/lib.rs @@ -1,6 +1,6 @@ //! A full-featured framework that empowers you to easily build [Telegram bots] //! using [Rust]. It handles all the difficult stuff so you can focus only on -//! your business logic. Currently, version `7.1` of [Telegram Bot API] is +//! your business logic. Currently, version `7.2` of [Telegram Bot API] is //! supported. //! //! For a high-level overview, see [our GitHub repository](https://github.com/teloxide/teloxide).