mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-22 14:35:36 +01:00
Merge pull request #1101 from syrtcevvi/feature/support-tba-7.0
Feature/support tba 7.0
This commit is contained in:
commit
cdd7d485bb
89 changed files with 3454 additions and 612 deletions
|
@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Use [deadpool-redis](https://crates.io/crates/deadpool-redis) for Redis connection pooling ([PR 1081](https://github.com/teloxide/teloxide/pull/1081)).
|
||||
- Add `MessageExt::filter_story` method for the corresponding `MediaKind::Story` variant ([PR 1087](https://github.com/teloxide/teloxide/pull/1087)).
|
||||
- Add `update_listeners::webhooks::Options::path`, an option to make the webhook server listen on a different path, which can be useful behind a reverse proxy.
|
||||
- Add `filter_giveaway`, `filter_giveaway_completed`, `filter_giveaway_created` and `filter_giveaway_winners` filters to `MessageFilterExt` trait ([PR 1101](https://github.com/teloxide/teloxide/pull/1101))
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -69,6 +70,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- MSRV (Minimal Supported Rust Version) was bumped from `1.68.0` to `1.70.0` ([PR 996][https://github.com/teloxide/teloxide/pull/996])
|
||||
- `axum` was bumped to `0.7`, along with related libraries used for webhooks ([PR 1093][https://github.com/teloxide/teloxide/pull/1093])
|
||||
- `Polling`'s exponential backoff now results in 64 seconds maximum delay instead of 17 minutes ([PR 1113][https://github.com/teloxide/teloxide/pull/1113])
|
||||
- `filter_forward_from` was renamed to `filter_forward_origin` and now returns `MessageOrigin` instead of `ForwardFrom` ([PR 1101](https://github.com/teloxide/teloxide/pull/1101))
|
||||
|
||||
### Removed
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<img src="https://img.shields.io/crates/v/teloxide.svg">
|
||||
</a>
|
||||
<a href="https://core.telegram.org/bots/api">
|
||||
<img src="https://img.shields.io/badge/API%20coverage-Up%20to%206.9%20(inclusively)-green.svg">
|
||||
<img src="https://img.shields.io/badge/API%20coverage-Up%20to%207.0%20(inclusively)-green.svg">
|
||||
</a>
|
||||
<a href="https://t.me/teloxide">
|
||||
<img src="https://img.shields.io/badge/support-t.me%2Fteloxide-blueviolet">
|
||||
|
|
|
@ -43,7 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Add `shared_chat` method to `Message`
|
||||
- Add `KeyboardButtonRequestUser` and `UserShared` types
|
||||
- Add `RequestUser` variant to `ButtonRequest`
|
||||
- Add `UserShared` variant to `MessageKind`
|
||||
- Add `UserShared` variant to `MessageKind`
|
||||
- Add `shared_user` method to `Message`
|
||||
- Support for TBA 6.6 ([#1040](pr1040))
|
||||
- Add methods for working with bot's description:
|
||||
|
@ -88,6 +88,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Support for TBA 6.9 ([#1095](pr1095))
|
||||
- Add `can_post_stories`, `can_edit_stories` and `can_delete_stories` fields to `ChatMemberKind::Administrator`, `ChatAdministratorRights` and `PromoteChatMember`
|
||||
- Add `from_request` and `from_attachment_menu` fields to `WriteAccessAllowed`
|
||||
- Support for TBA 7.0 ([#1101](pr1101))
|
||||
- Reactions:
|
||||
- Add `ReactionType` enum
|
||||
- Add `MessageReactionUpdated` and `MessageReactionCountUpdated` structs
|
||||
- Add `MessageReaction` and `MessageReactionCount` variants to `UpdateKind` enum
|
||||
- Add `filter_message_reaction_updated` and `filter_message_reaction_count_updated` filters to `UpdateFilterExt` trait
|
||||
- Add `set_message_reaction` TBA method to `Requester` trait
|
||||
- Add `available_reactions` field to `Chat` struct
|
||||
- Replies 2.0
|
||||
- Add the fields `MessageCommon::{external_reply, quote}` of types `ExternalReplyInfo` and `TextQuote` respectively
|
||||
- Link Preview Customization
|
||||
- `disable_web_page_preview` replaced with `link_preview_options`:
|
||||
- Remove `disable_web_page_preview` field from `send_message` and `send_message` TBA methods and `InputMessageContentText` struct
|
||||
- Add `LinkPreviewOptions` struct
|
||||
- Add `link_preview_options` field to `InputMessageContentText` and `Message` structs
|
||||
- Add `link_preview_options` field to `send_message` and `send_message` TBA methods
|
||||
- Multiple Message Actions
|
||||
- Add TBA methods `delete_messages`, `forward_messages` and `copy_messages` to `Requester` trait
|
||||
- Chat Boost
|
||||
- Add `ChatBoostSource` enum
|
||||
- Add `ChatBoost`, `ChatBoostUpdated`, `ChatBoostRemoved` and `UserChatBoosts` structs
|
||||
- Add `ChatBoost` and `RemovedChatBoost` variants to `UpdateKind` enum
|
||||
- Add `filter_chat_boost` and `filter_removed_chat_boost` filters to `UpdateFilterExt` trait
|
||||
- Add `get_user_chat_boosts` TBA method to `Requester` trait
|
||||
- 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`
|
||||
- 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
|
||||
- Add `CallbackQuery::regular_message` getter
|
||||
|
||||
[pr851]: https://github.com/teloxide/teloxide/pull/851
|
||||
[pr887]: https://github.com/teloxide/teloxide/pull/887
|
||||
|
@ -97,6 +129,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
[pr1086]: https://github.com/teloxide/teloxide/pull/1086
|
||||
[pr1087]: https://github.com/teloxide/teloxide/pull/1087
|
||||
[pr1095]: https://github.com/teloxide/teloxide/pull/1095
|
||||
[pr1101]: https://github.com/teloxide/teloxide/pull/1101
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -108,6 +141,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Deserialization of empty (content-less) messages that can sometimes appear as a part of callback query ([#850][pr850], issue [#873][issue873])
|
||||
- Type of `chat_id` in `send_game`: `u32` => `ChatId` ([#1066][pr1066])
|
||||
- `Requester::Err` was bounded to the `AsResponseParameters`. In case of `RetryAfter(..)` errors the polling is paused for the specified delay instead of falling into the backoff strategy ([#1113][pr1113])
|
||||
- `SendPoll` documentation ([#1101][pr1101], issue [#1058][issue1058])
|
||||
- `from`, `sender_chat` and `is_topic_message` are moved into the `Message` from the `MessageCommon` ([#1101][pr1101], issue [#945][issue945]). Initially [#946][pr946]
|
||||
- Add support for `blockquote` entity in received messages + in `MarkdownV2` and `HTML` ([#1101][pr1101], issue [#1062][issue1062])
|
||||
|
||||
[pr839]: https://github.com/teloxide/teloxide/pull/839
|
||||
[pr879]: https://github.com/teloxide/teloxide/pull/879
|
||||
|
@ -169,6 +205,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Method `set_sticker_set_thumb` and it's parameter `thumb` have been renamed to `set_sticker_set_thumbnail` and `thumbnail` respectively
|
||||
- Fields `{InlineQueryResultArticle, InlineQueryResultContact, InlineQueryResultDocument, InlineQueryResultLocation, InlineQueryResultVenue}::{thumb_url, thumb_width, thumb_height}` have been renamed to `{thumbnail_url, thumbnail_width, thumbnail_height}` respectively
|
||||
- Field `{InlineQueryResultPhoto, InlineQueryResultVideo, InlineQueryResultGif, InlineQueryResultMpeg4Gif}::thumb_url` has been renamed to `thumbnail_url`
|
||||
- Support for TBA 7.0 ([#1101](pr1101))
|
||||
- Replies 2.0
|
||||
- Parameter `reply_parameters` of type `ReplyParameters` replaces parameters `reply_to_message_id` and `allow_sending_without_reply` in the methods:
|
||||
- `copy_message`
|
||||
- `send_message`
|
||||
- `send_photo`
|
||||
- `send_video`
|
||||
- `send_animation`
|
||||
- `send_audio`
|
||||
- `send_document`
|
||||
- `send_sticker`
|
||||
- `send_video_note`
|
||||
- `send_voice`
|
||||
- `send_location`
|
||||
- `send_venue`
|
||||
- `send_contact`
|
||||
- `send_poll`
|
||||
- `send_dice`
|
||||
- `send_invoice`
|
||||
- `send_game`
|
||||
- `send_media_group`
|
||||
- Request for multiple users
|
||||
- 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
|
||||
- `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
|
||||
|
@ -182,8 +249,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Deprecated
|
||||
|
||||
- `Update::user`, use `Update::from` instead ([#850][pr850])
|
||||
- `Message::from()` and `Message::sender_chat()` in favour of fields with the same name([initially #946][pr946][#1101][pr1101])
|
||||
|
||||
[pr850]: https://github.com/teloxide/teloxide/pull/850
|
||||
[pr946]: https://github.com/teloxide/teloxide/pull/946
|
||||
|
||||
### Removed
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<img src="https://img.shields.io/badge/license-MIT-blue.svg">
|
||||
</a>
|
||||
<a href="https://core.telegram.org/bots/api">
|
||||
<img src="https://img.shields.io/badge/API%20coverage-Up%20to%206.9%20(inclusively)-green.svg">
|
||||
<img src="https://img.shields.io/badge/API%20coverage-Up%20to%207.0%20(inclusively)-green.svg">
|
||||
</a>
|
||||
<a href="https://crates.io/crates/teloxide_core">
|
||||
<img src="https://img.shields.io/crates/v/teloxide_core.svg">
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
//! [github]: https://github.com/WaffleLapkin/tg-methods-schema
|
||||
|
||||
Schema(
|
||||
api_version: ApiVersion(ver: "6.9", date: "September 22, 2023"),
|
||||
api_version: ApiVersion(ver: "7.0", date: "December 29, 2023"),
|
||||
methods: [
|
||||
Method(
|
||||
names: ("getUpdates", "GetUpdates", "get_updates"),
|
||||
|
@ -253,9 +253,9 @@ Schema(
|
|||
descr: Doc(md: "List of special entities that appear in the message text, which can be specified instead of _parse\\_mode_"),
|
||||
),
|
||||
Param(
|
||||
name: "disable_web_page_preview",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Disables link previews for links in this message")
|
||||
name: "link_preview_options",
|
||||
ty: Option(RawTy("LinkPreviewOptions")),
|
||||
descr: Doc(md: "Link preview generation options for the message"),
|
||||
),
|
||||
Param(
|
||||
name: "disable_notification",
|
||||
|
@ -271,14 +271,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -338,6 +333,51 @@ Schema(
|
|||
),
|
||||
],
|
||||
),
|
||||
Method(
|
||||
names: ("forwardMessages", "ForwardMessages", "forward_messages"),
|
||||
return_ty: ArrayOf(RawTy("MessageId")),
|
||||
doc: Doc(
|
||||
md: "Use this method to forward multiple messages of any kind. If some of the specified messages can't be found or forwarded, they are skipped. Service messages and messages with protected content can't be forwarded. Album grouping is kept for forwarded messages. On success, an array of [MessageId] of the sent messages is returned.",
|
||||
md_links: {"MessageId": "https://core.telegram.org/bots/api#messageid"},
|
||||
),
|
||||
tg_doc: "https://core.telegram.org/bots/api#forwardmessages",
|
||||
tg_category: "Available methods",
|
||||
params: [
|
||||
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: "message_thread_id",
|
||||
ty: Option(RawTy("ThreadId")),
|
||||
descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"),
|
||||
),
|
||||
Param(
|
||||
name: "from_chat_id",
|
||||
ty: RawTy("Recipient"),
|
||||
descr: Doc(md: "Unique identifier for the chat where the original message was sent (or channel username in the format `@channelusername`)"),
|
||||
),
|
||||
Param(
|
||||
name: "message_ids",
|
||||
ty: ArrayOf(RawTy("MessageId")),
|
||||
descr: Doc(md: "A JSON-serialized list of 1-100 identifiers of messages in the chat _from\\_chat\\_id_ to forward. The identifiers must be specified in a strictly increasing order.")
|
||||
),
|
||||
Param(
|
||||
name: "disable_notification",
|
||||
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"}
|
||||
)
|
||||
),
|
||||
Param(
|
||||
name: "protect_content",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
],
|
||||
),
|
||||
Method(
|
||||
names: ("copyMessage", "CopyMessage", "copy_message"),
|
||||
return_ty: RawTy("MessageId"),
|
||||
|
@ -400,14 +440,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -422,6 +457,59 @@ Schema(
|
|||
),
|
||||
],
|
||||
),
|
||||
Method(
|
||||
names: ("copyMessages", "CopyMessages", "copy_messages"),
|
||||
return_ty: ArrayOf(RawTy("MessageId")),
|
||||
doc: Doc(
|
||||
md: "Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. Service messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. A quiz poll can be copied only if the value of the field _correct\\_option\\_id_ is known to the bot. The method is analogous to the method [forwardMessages], but the copied messages don't have a link to the original message. Album grouping is kept for copied messages. On success, an array of [MessageId] of the sent messages is returned.",
|
||||
md_links: {
|
||||
"forwardMessages": "https://core.telegram.org/bots/api#forwardmessages",
|
||||
"MessageId": "https://core.telegram.org/bots/api#messageid"
|
||||
},
|
||||
),
|
||||
tg_doc: "https://core.telegram.org/bots/api#copymessages",
|
||||
tg_category: "Available methods",
|
||||
params: [
|
||||
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: "message_thread_id",
|
||||
ty: Option(RawTy("ThreadId")),
|
||||
descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"),
|
||||
),
|
||||
Param(
|
||||
name: "from_chat_id",
|
||||
ty: RawTy("Recipient"),
|
||||
descr: Doc(md: "Unique identifier for the chat where the original message was sent (or channel username in the format `@channelusername`)"),
|
||||
),
|
||||
Param(
|
||||
name: "message_ids",
|
||||
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),
|
||||
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"}
|
||||
)
|
||||
),
|
||||
Param(
|
||||
name: "protect_content",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "remove_caption",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_ to copy the messages without their captions")
|
||||
)
|
||||
],
|
||||
),
|
||||
Method(
|
||||
names: ("sendPhoto", "SendPhoto", "send_photo"),
|
||||
return_ty: RawTy("Message"),
|
||||
|
@ -487,14 +575,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -595,14 +678,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -690,14 +768,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -808,14 +881,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -919,14 +987,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -1005,14 +1068,9 @@ Schema(
|
|||
)
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -1090,14 +1148,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -1152,14 +1205,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -1230,14 +1278,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -1508,14 +1551,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -1587,14 +1625,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -1613,7 +1646,7 @@ Schema(
|
|||
names: ("sendPoll", "SendPoll", "send_poll"),
|
||||
return_ty: RawTy("Message"),
|
||||
doc: Doc(
|
||||
md: "Use this method to send phone contacts. On success, the sent [Message] is returned.",
|
||||
md: "Use this method to send a native poll. On success, the sent [Message] is returned.",
|
||||
md_links: {"Message": "https://core.telegram.org/bots/api#message"},
|
||||
),
|
||||
tg_doc: "https://core.telegram.org/bots/api#sendpoll",
|
||||
|
@ -1706,14 +1739,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -1767,14 +1795,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -1828,6 +1851,37 @@ Schema(
|
|||
),
|
||||
],
|
||||
),
|
||||
Method(
|
||||
names: ("setMessageReaction", "SetMessageReaction", "set_message_reaction"),
|
||||
return_ty: True,
|
||||
doc: Doc(
|
||||
md: "Use this method to change the chosen reactions on a message. Service messages can't be reacted to. Automatically forwarded messages from a channel to its discussion group have the same available reactions as messages in the channel. Returns True on success."
|
||||
),
|
||||
tg_doc: "https://core.telegram.org/bots/api#setmessagereaction",
|
||||
tg_category: "Available methods",
|
||||
params: [
|
||||
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: "message_id",
|
||||
ty: RawTy("MessageId"),
|
||||
descr: Doc(md: "Identifier of the target message. If the message belongs to a media group, the reaction is set to the first non-deleted message in the group instead.")
|
||||
),
|
||||
Param(
|
||||
name: "reaction",
|
||||
ty: Option(ArrayOf(RawTy("ReactionType"))),
|
||||
descr: Doc(md: "New list of reaction types to set on the message. Currently, as non-premium users, bots can set up to one reaction per message. A custom emoji reaction can be used if it is either already present on the message or explicitly allowed by chat administrators.")
|
||||
),
|
||||
Param(
|
||||
name: "is_big",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass True to set the reaction with a big animation")
|
||||
),
|
||||
],
|
||||
),
|
||||
Method(
|
||||
names: ("getUserProfilePhotos", "GetUserProfilePhotos", "get_user_profile_photos"),
|
||||
return_ty: RawTy("UserProfilePhotos"),
|
||||
|
@ -2877,6 +2931,28 @@ Schema(
|
|||
),
|
||||
],
|
||||
),
|
||||
Method(
|
||||
names: ("getUserChatBoosts", "GetUserChatBoosts", "get_user_chat_boosts"),
|
||||
return_ty: RawTy("UserChatBoosts"),
|
||||
doc: Doc(
|
||||
md: "Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a [UserChatBoosts] object.",
|
||||
md_links: {"UserChatBoosts": "https://core.telegram.org/bots/api#userchatboosts"},
|
||||
),
|
||||
tg_doc: "https://core.telegram.org/bots/api#getuserchatboosts",
|
||||
tg_category: "Available methods",
|
||||
params: [
|
||||
Param(
|
||||
name: "chat_id",
|
||||
ty: RawTy("Recipient"),
|
||||
descr: Doc(md: "Unique identifier for the chat or username of the channel (in the format @channelusername)"),
|
||||
),
|
||||
Param(
|
||||
name: "user_id",
|
||||
ty: RawTy("UserId"),
|
||||
descr: Doc(md: "Unique identifier of the target user"),
|
||||
),
|
||||
],
|
||||
),
|
||||
Method(
|
||||
names: ("setMyCommands", "SetMyCommands", "set_my_commands"),
|
||||
return_ty: True,
|
||||
|
@ -3220,9 +3296,9 @@ Schema(
|
|||
descr: Doc(md: "List of special entities that appear in message text, which can be specified instead of _parse\\_mode_"),
|
||||
),
|
||||
Param(
|
||||
name: "disable_web_page_preview",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Disables link previews for links in this message")
|
||||
name: "link_preview_options",
|
||||
ty: Option(RawTy("LinkPreviewOptions")),
|
||||
descr: Doc(md: "Link preview generation options for the message"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -3529,6 +3605,28 @@ Schema(
|
|||
),
|
||||
],
|
||||
),
|
||||
Method(
|
||||
names: ("deleteMessages", "DeleteMessages", "delete_messages"),
|
||||
return_ty: True,
|
||||
doc: Doc(md: "Use this method to delete multiple messages simultaneously. If some of the specified messages can't be found, they are skipped. Returns _True_ on success."),
|
||||
tg_doc: "https://core.telegram.org/bots/api#delete_messages",
|
||||
tg_category: "Updating messages",
|
||||
params: [
|
||||
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: "message_ids",
|
||||
ty: ArrayOf(RawTy("MessageId")),
|
||||
descr: Doc(
|
||||
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"),
|
||||
|
@ -3576,14 +3674,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -4047,14 +4140,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
@ -4298,14 +4386,9 @@ Schema(
|
|||
descr: Doc(md: "Protects the contents of sent messages from forwarding and saving"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_to_message_id",
|
||||
ty: Option(RawTy("MessageId")),
|
||||
descr: Doc(md: "If the message is a reply, ID of the original message")
|
||||
),
|
||||
Param(
|
||||
name: "allow_sending_without_reply",
|
||||
ty: Option(bool),
|
||||
descr: Doc(md: "Pass _True_, if the message should be sent even if the specified replied-to message is not found")
|
||||
name: "reply_parameters",
|
||||
ty: Option(RawTy("ReplyParameters")),
|
||||
descr: Doc(md: "Description of the message to reply to"),
|
||||
),
|
||||
Param(
|
||||
name: "reply_markup",
|
||||
|
|
|
@ -94,7 +94,9 @@ where
|
|||
delete_webhook,
|
||||
get_webhook_info,
|
||||
forward_message,
|
||||
forward_messages,
|
||||
copy_message,
|
||||
copy_messages,
|
||||
send_message,
|
||||
send_photo,
|
||||
send_audio,
|
||||
|
@ -114,6 +116,7 @@ where
|
|||
send_poll,
|
||||
send_dice,
|
||||
send_chat_action,
|
||||
set_message_reaction,
|
||||
get_user_profile_photos,
|
||||
get_file,
|
||||
kick_chat_member,
|
||||
|
@ -158,6 +161,7 @@ where
|
|||
unhide_general_forum_topic,
|
||||
unpin_all_general_forum_topic_messages,
|
||||
answer_callback_query,
|
||||
get_user_chat_boosts,
|
||||
set_my_commands,
|
||||
get_my_commands,
|
||||
set_my_name,
|
||||
|
@ -183,6 +187,7 @@ where
|
|||
edit_message_reply_markup_inline,
|
||||
stop_poll,
|
||||
delete_message,
|
||||
delete_messages,
|
||||
send_sticker,
|
||||
get_sticker_set,
|
||||
get_custom_emoji_stickers,
|
||||
|
|
|
@ -170,6 +170,9 @@ macro_rules! fwd_erased {
|
|||
(@convert $m:ident, $arg:ident, emoji_list: $T:ty) => {
|
||||
$arg.into_iter().collect()
|
||||
};
|
||||
(@convert $m:ident, $arg:ident, message_ids: $T:ty) => {
|
||||
$arg.into_iter().collect()
|
||||
};
|
||||
(@convert $m:ident, $arg:ident, $arg_:ident : $T:ty) => {
|
||||
$arg.into()
|
||||
};
|
||||
|
@ -190,7 +193,9 @@ where
|
|||
delete_webhook,
|
||||
get_webhook_info,
|
||||
forward_message,
|
||||
forward_messages,
|
||||
copy_message,
|
||||
copy_messages,
|
||||
send_message,
|
||||
send_photo,
|
||||
send_audio,
|
||||
|
@ -210,6 +215,7 @@ where
|
|||
send_poll,
|
||||
send_dice,
|
||||
send_chat_action,
|
||||
set_message_reaction,
|
||||
get_user_profile_photos,
|
||||
get_file,
|
||||
kick_chat_member,
|
||||
|
@ -254,6 +260,7 @@ where
|
|||
unhide_general_forum_topic,
|
||||
unpin_all_general_forum_topic_messages,
|
||||
answer_callback_query,
|
||||
get_user_chat_boosts,
|
||||
set_my_commands,
|
||||
get_my_commands,
|
||||
set_my_name,
|
||||
|
@ -279,6 +286,7 @@ where
|
|||
edit_message_reply_markup_inline,
|
||||
stop_poll,
|
||||
delete_message,
|
||||
delete_messages,
|
||||
send_sticker,
|
||||
get_sticker_set,
|
||||
get_custom_emoji_stickers,
|
||||
|
@ -341,6 +349,13 @@ trait ErasableRequester<'a> {
|
|||
message_id: MessageId,
|
||||
) -> ErasedRequest<'a, ForwardMessage, Self::Err>;
|
||||
|
||||
fn forward_messages(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
from_chat_id: Recipient,
|
||||
message_ids: Vec<MessageId>,
|
||||
) -> ErasedRequest<'a, ForwardMessages, Self::Err>;
|
||||
|
||||
fn copy_message(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
|
@ -348,6 +363,13 @@ trait ErasableRequester<'a> {
|
|||
message_id: MessageId,
|
||||
) -> ErasedRequest<'a, CopyMessage, Self::Err>;
|
||||
|
||||
fn copy_messages(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
from_chat_id: Recipient,
|
||||
message_ids: Vec<MessageId>,
|
||||
) -> ErasedRequest<'a, CopyMessages, Self::Err>;
|
||||
|
||||
fn send_photo(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
|
@ -460,6 +482,12 @@ trait ErasableRequester<'a> {
|
|||
action: ChatAction,
|
||||
) -> ErasedRequest<'a, SendChatAction, Self::Err>;
|
||||
|
||||
fn set_message_reaction(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
message_id: MessageId,
|
||||
) -> ErasedRequest<'a, SetMessageReaction, Self::Err>;
|
||||
|
||||
fn get_user_profile_photos(
|
||||
&self,
|
||||
user_id: UserId,
|
||||
|
@ -711,6 +739,12 @@ trait ErasableRequester<'a> {
|
|||
callback_query_id: String,
|
||||
) -> ErasedRequest<'a, AnswerCallbackQuery, Self::Err>;
|
||||
|
||||
fn get_user_chat_boosts(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
user_id: UserId,
|
||||
) -> ErasedRequest<'a, GetUserChatBoosts, Self::Err>;
|
||||
|
||||
fn set_my_commands(
|
||||
&self,
|
||||
commands: Vec<BotCommand>,
|
||||
|
@ -816,6 +850,12 @@ trait ErasableRequester<'a> {
|
|||
message_id: MessageId,
|
||||
) -> ErasedRequest<'a, DeleteMessage, Self::Err>;
|
||||
|
||||
fn delete_messages(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
message_ids: Vec<MessageId>,
|
||||
) -> ErasedRequest<'a, DeleteMessages, Self::Err>;
|
||||
|
||||
fn send_sticker(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
|
@ -1019,6 +1059,15 @@ where
|
|||
Requester::forward_message(self, chat_id, from_chat_id, message_id).erase()
|
||||
}
|
||||
|
||||
fn forward_messages(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
from_chat_id: Recipient,
|
||||
message_ids: Vec<MessageId>,
|
||||
) -> ErasedRequest<'a, ForwardMessages, Self::Err> {
|
||||
Requester::forward_messages(self, chat_id, from_chat_id, message_ids).erase()
|
||||
}
|
||||
|
||||
fn copy_message(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
|
@ -1028,6 +1077,15 @@ where
|
|||
Requester::copy_message(self, chat_id, from_chat_id, message_id).erase()
|
||||
}
|
||||
|
||||
fn copy_messages(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
from_chat_id: Recipient,
|
||||
message_ids: Vec<MessageId>,
|
||||
) -> ErasedRequest<'a, CopyMessages, Self::Err> {
|
||||
Requester::copy_messages(self, chat_id, from_chat_id, message_ids).erase()
|
||||
}
|
||||
|
||||
fn send_photo(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
|
@ -1178,6 +1236,14 @@ where
|
|||
Requester::send_chat_action(self, chat_id, action).erase()
|
||||
}
|
||||
|
||||
fn set_message_reaction(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
message_id: MessageId,
|
||||
) -> ErasedRequest<'a, SetMessageReaction, Self::Err> {
|
||||
Requester::set_message_reaction(self, chat_id, message_id).erase()
|
||||
}
|
||||
|
||||
fn get_user_profile_photos(
|
||||
&self,
|
||||
user_id: UserId,
|
||||
|
@ -1521,6 +1587,14 @@ where
|
|||
Requester::answer_callback_query(self, callback_query_id).erase()
|
||||
}
|
||||
|
||||
fn get_user_chat_boosts(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
user_id: UserId,
|
||||
) -> ErasedRequest<'a, GetUserChatBoosts, Self::Err> {
|
||||
Requester::get_user_chat_boosts(self, chat_id, user_id).erase()
|
||||
}
|
||||
|
||||
fn set_my_commands(
|
||||
&self,
|
||||
commands: Vec<BotCommand>,
|
||||
|
@ -1676,6 +1750,14 @@ where
|
|||
Requester::delete_message(self, chat_id, message_id).erase()
|
||||
}
|
||||
|
||||
fn delete_messages(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
message_ids: Vec<MessageId>,
|
||||
) -> ErasedRequest<'a, DeleteMessages, Self::Err> {
|
||||
Requester::delete_messages(self, chat_id, message_ids).erase()
|
||||
}
|
||||
|
||||
fn send_sticker(
|
||||
&self,
|
||||
chat_id: Recipient,
|
||||
|
|
|
@ -185,6 +185,8 @@ where
|
|||
delete_webhook,
|
||||
get_webhook_info,
|
||||
forward_message,
|
||||
forward_messages,
|
||||
copy_messages,
|
||||
send_video_note,
|
||||
send_location,
|
||||
edit_message_live_location,
|
||||
|
@ -195,6 +197,7 @@ where
|
|||
send_contact,
|
||||
send_dice,
|
||||
send_chat_action,
|
||||
set_message_reaction,
|
||||
get_user_profile_photos,
|
||||
get_file,
|
||||
kick_chat_member,
|
||||
|
@ -239,6 +242,7 @@ where
|
|||
unhide_general_forum_topic,
|
||||
unpin_all_general_forum_topic_messages,
|
||||
answer_callback_query,
|
||||
get_user_chat_boosts,
|
||||
set_my_commands,
|
||||
get_my_commands,
|
||||
set_my_name,
|
||||
|
@ -256,6 +260,7 @@ where
|
|||
edit_message_reply_markup_inline,
|
||||
stop_poll,
|
||||
delete_message,
|
||||
delete_messages,
|
||||
send_sticker,
|
||||
get_sticker_set,
|
||||
get_custom_emoji_stickers,
|
||||
|
|
|
@ -92,11 +92,14 @@ where
|
|||
set_webhook,
|
||||
delete_webhook,
|
||||
get_webhook_info,
|
||||
forward_messages,
|
||||
copy_messages,
|
||||
edit_message_live_location,
|
||||
edit_message_live_location_inline,
|
||||
stop_message_live_location,
|
||||
stop_message_live_location_inline,
|
||||
send_chat_action,
|
||||
set_message_reaction,
|
||||
get_user_profile_photos,
|
||||
get_file,
|
||||
kick_chat_member,
|
||||
|
@ -141,6 +144,7 @@ where
|
|||
unhide_general_forum_topic,
|
||||
unpin_all_general_forum_topic_messages,
|
||||
answer_callback_query,
|
||||
get_user_chat_boosts,
|
||||
set_my_commands,
|
||||
get_my_commands,
|
||||
set_my_name,
|
||||
|
@ -166,6 +170,7 @@ where
|
|||
edit_message_reply_markup_inline,
|
||||
stop_poll,
|
||||
delete_message,
|
||||
delete_messages,
|
||||
get_sticker_set,
|
||||
get_custom_emoji_stickers,
|
||||
upload_sticker_file,
|
||||
|
|
|
@ -123,7 +123,9 @@ where
|
|||
delete_webhook,
|
||||
get_webhook_info,
|
||||
forward_message,
|
||||
forward_messages,
|
||||
copy_message,
|
||||
copy_messages,
|
||||
send_message,
|
||||
send_photo,
|
||||
send_audio,
|
||||
|
@ -143,6 +145,7 @@ where
|
|||
send_poll,
|
||||
send_dice,
|
||||
send_chat_action,
|
||||
set_message_reaction,
|
||||
get_user_profile_photos,
|
||||
get_file,
|
||||
kick_chat_member,
|
||||
|
@ -187,6 +190,7 @@ where
|
|||
unhide_general_forum_topic,
|
||||
unpin_all_general_forum_topic_messages,
|
||||
answer_callback_query,
|
||||
get_user_chat_boosts,
|
||||
set_my_commands,
|
||||
get_my_commands,
|
||||
set_my_name,
|
||||
|
@ -212,6 +216,7 @@ where
|
|||
edit_message_reply_markup_inline,
|
||||
stop_poll,
|
||||
delete_message,
|
||||
delete_messages,
|
||||
send_sticker,
|
||||
get_sticker_set,
|
||||
get_custom_emoji_stickers,
|
||||
|
|
|
@ -72,6 +72,24 @@ impl Requester for Bot {
|
|||
)
|
||||
}
|
||||
|
||||
type ForwardMessages = JsonRequest<payloads::ForwardMessages>;
|
||||
fn forward_messages<C, F, M>(
|
||||
&self,
|
||||
chat_id: C,
|
||||
from_chat_id: F,
|
||||
message_ids: M,
|
||||
) -> Self::ForwardMessages
|
||||
where
|
||||
C: Into<Recipient>,
|
||||
F: Into<Recipient>,
|
||||
M: IntoIterator<Item = MessageId>,
|
||||
{
|
||||
Self::ForwardMessages::new(
|
||||
self.clone(),
|
||||
payloads::ForwardMessages::new(chat_id, from_chat_id, message_ids),
|
||||
)
|
||||
}
|
||||
|
||||
type SendPhoto = MultipartRequest<payloads::SendPhoto>;
|
||||
|
||||
fn send_photo<C>(&self, chat_id: C, photo: InputFile) -> Self::SendPhoto
|
||||
|
@ -291,6 +309,18 @@ impl Requester for Bot {
|
|||
Self::SendChatAction::new(self.clone(), payloads::SendChatAction::new(chat_id, action))
|
||||
}
|
||||
|
||||
type SetMessageReaction = JsonRequest<payloads::SetMessageReaction>;
|
||||
|
||||
fn set_message_reaction<C>(&self, chat_id: C, message_id: MessageId) -> Self::SetMessageReaction
|
||||
where
|
||||
C: Into<Recipient>,
|
||||
{
|
||||
Self::SetMessageReaction::new(
|
||||
self.clone(),
|
||||
payloads::SetMessageReaction::new(chat_id, message_id),
|
||||
)
|
||||
}
|
||||
|
||||
type GetUserProfilePhotos = JsonRequest<payloads::GetUserProfilePhotos>;
|
||||
|
||||
fn get_user_profile_photos(&self, user_id: UserId) -> Self::GetUserProfilePhotos {
|
||||
|
@ -830,6 +860,18 @@ impl Requester for Bot {
|
|||
)
|
||||
}
|
||||
|
||||
type GetUserChatBoosts = JsonRequest<payloads::GetUserChatBoosts>;
|
||||
|
||||
fn get_user_chat_boosts<C>(&self, chat_id: C, user_id: UserId) -> Self::GetUserChatBoosts
|
||||
where
|
||||
C: Into<Recipient>,
|
||||
{
|
||||
Self::GetUserChatBoosts::new(
|
||||
self.clone(),
|
||||
payloads::GetUserChatBoosts::new(chat_id, user_id),
|
||||
)
|
||||
}
|
||||
|
||||
type SetMyCommands = JsonRequest<payloads::SetMyCommands>;
|
||||
|
||||
fn set_my_commands<C>(&self, commands: C) -> Self::SetMyCommands
|
||||
|
@ -1086,6 +1128,15 @@ impl Requester for Bot {
|
|||
Self::DeleteMessage::new(self.clone(), payloads::DeleteMessage::new(chat_id, message_id))
|
||||
}
|
||||
|
||||
type DeleteMessages = JsonRequest<payloads::DeleteMessages>;
|
||||
fn delete_messages<C, M>(&self, chat_id: C, message_ids: M) -> Self::DeleteMessages
|
||||
where
|
||||
C: Into<Recipient>,
|
||||
M: IntoIterator<Item = MessageId>,
|
||||
{
|
||||
Self::DeleteMessages::new(self.clone(), payloads::DeleteMessages::new(chat_id, message_ids))
|
||||
}
|
||||
|
||||
type SendSticker = MultipartRequest<payloads::SendSticker>;
|
||||
|
||||
fn send_sticker<C>(&self, chat_id: C, sticker: InputFile) -> Self::SendSticker
|
||||
|
@ -1465,6 +1516,24 @@ impl Requester for Bot {
|
|||
)
|
||||
}
|
||||
|
||||
type CopyMessages = JsonRequest<payloads::CopyMessages>;
|
||||
fn copy_messages<C, F, M>(
|
||||
&self,
|
||||
chat_id: C,
|
||||
from_chat_id: F,
|
||||
message_ids: M,
|
||||
) -> Self::CopyMessages
|
||||
where
|
||||
C: Into<Recipient>,
|
||||
F: Into<Recipient>,
|
||||
M: IntoIterator<Item = MessageId>,
|
||||
{
|
||||
Self::CopyMessages::new(
|
||||
self.clone(),
|
||||
payloads::CopyMessages::new(chat_id, from_chat_id, message_ids),
|
||||
)
|
||||
}
|
||||
|
||||
type UnpinAllChatMessages = JsonRequest<payloads::UnpinAllChatMessages>;
|
||||
|
||||
fn unpin_all_chat_messages<C>(&self, chat_id: C) -> Self::UnpinAllChatMessages
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Core part of the [`teloxide`] library.
|
||||
//!
|
||||
//! This library provides tools for making requests to the [Telegram Bot API]
|
||||
//! (Currently, version `6.9` is supported) with ease. The library is fully
|
||||
//! (Currently, version `7.0` is supported) with ease. The library is fully
|
||||
//! asynchronous and built using [`tokio`].
|
||||
//!
|
||||
//!```toml
|
||||
|
|
|
@ -487,6 +487,16 @@ macro_rules! requester_forward {
|
|||
$body!(forward_message this (chat_id: C, from_chat_id: F, message_id: MessageId))
|
||||
}
|
||||
};
|
||||
(@method forward_messages $body:ident $ty:ident) => {
|
||||
type ForwardMessages = $ty![ForwardMessages];
|
||||
|
||||
fn forward_messages<C, F, M>(&self, chat_id: C, from_chat_id: F, message_ids: M) -> Self::ForwardMessages where C: Into<Recipient>,
|
||||
F: Into<Recipient>,
|
||||
M: IntoIterator<Item = MessageId> {
|
||||
let this = self;
|
||||
$body!(forward_messages this (chat_id: C, from_chat_id: F, message_ids: M))
|
||||
}
|
||||
};
|
||||
(@method copy_message $body:ident $ty:ident) => {
|
||||
type CopyMessage = $ty![CopyMessage];
|
||||
|
||||
|
@ -496,6 +506,16 @@ macro_rules! requester_forward {
|
|||
$body!(copy_message this (chat_id: C, from_chat_id: F, message_id: MessageId))
|
||||
}
|
||||
};
|
||||
(@method copy_messages $body:ident $ty:ident) => {
|
||||
type CopyMessages = $ty![CopyMessages];
|
||||
|
||||
fn copy_messages<C, F, M>(&self, chat_id: C, from_chat_id: F, message_ids: M) -> Self::CopyMessages where C: Into<Recipient>,
|
||||
F: Into<Recipient>,
|
||||
M: IntoIterator<Item = MessageId> {
|
||||
let this = self;
|
||||
$body!(copy_messages this (chat_id: C, from_chat_id: F, message_ids: M))
|
||||
}
|
||||
};
|
||||
(@method send_photo $body:ident $ty:ident) => {
|
||||
type SendPhoto = $ty![SendPhoto];
|
||||
|
||||
|
@ -647,6 +667,14 @@ macro_rules! requester_forward {
|
|||
$body!(send_chat_action this (chat_id: C, action: ChatAction))
|
||||
}
|
||||
};
|
||||
(@method set_message_reaction $body:ident $ty:ident) => {
|
||||
type SetMessageReaction = $ty![SetMessageReaction];
|
||||
|
||||
fn set_message_reaction<C>(&self, chat_id: C, message_id: MessageId) -> Self::SetMessageReaction where C: Into<Recipient> {
|
||||
let this = self;
|
||||
$body!(set_message_reaction this (chat_id: C, message_id: MessageId))
|
||||
}
|
||||
};
|
||||
(@method get_user_profile_photos $body:ident $ty:ident) => {
|
||||
type GetUserProfilePhotos = $ty![GetUserProfilePhotos];
|
||||
|
||||
|
@ -1025,6 +1053,14 @@ macro_rules! requester_forward {
|
|||
$body!(answer_callback_query this (callback_query_id: C))
|
||||
}
|
||||
};
|
||||
(@method get_user_chat_boosts $body:ident $ty:ident) => {
|
||||
type GetUserChatBoosts = $ty![GetUserChatBoosts];
|
||||
|
||||
fn get_user_chat_boosts<C>(&self, chat_id: C, user_id: UserId) -> Self::GetUserChatBoosts where C: Into<Recipient> {
|
||||
let this = self;
|
||||
$body!(get_user_chat_boosts this (chat_id: C, user_id: UserId))
|
||||
}
|
||||
};
|
||||
(@method set_my_commands $body:ident $ty:ident) => {
|
||||
type SetMyCommands = $ty![SetMyCommands];
|
||||
|
||||
|
@ -1228,6 +1264,15 @@ macro_rules! requester_forward {
|
|||
$body!(delete_message this (chat_id: C, message_id: MessageId))
|
||||
}
|
||||
};
|
||||
(@method delete_messages $body:ident $ty:ident) => {
|
||||
type DeleteMessages = $ty![DeleteMessages];
|
||||
|
||||
fn delete_messages<C, M>(&self, chat_id: C, message_ids: M) -> Self::DeleteMessages where C: Into<Recipient>,
|
||||
M: IntoIterator<Item = MessageId> {
|
||||
let this = self;
|
||||
$body!(delete_messages this (chat_id: C, message_ids: M))
|
||||
}
|
||||
};
|
||||
(@method send_sticker $body:ident $ty:ident) => {
|
||||
type SendSticker = $ty![SendSticker];
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ mod close;
|
|||
mod close_forum_topic;
|
||||
mod close_general_forum_topic;
|
||||
mod copy_message;
|
||||
mod copy_messages;
|
||||
mod create_chat_invite_link;
|
||||
mod create_forum_topic;
|
||||
mod create_invoice_link;
|
||||
|
@ -37,6 +38,7 @@ mod delete_chat_photo;
|
|||
mod delete_chat_sticker_set;
|
||||
mod delete_forum_topic;
|
||||
mod delete_message;
|
||||
mod delete_messages;
|
||||
mod delete_my_commands;
|
||||
mod delete_sticker_from_set;
|
||||
mod delete_sticker_set;
|
||||
|
@ -56,6 +58,7 @@ mod edit_message_text;
|
|||
mod edit_message_text_inline;
|
||||
mod export_chat_invite_link;
|
||||
mod forward_message;
|
||||
mod forward_messages;
|
||||
mod get_chat;
|
||||
mod get_chat_administrators;
|
||||
mod get_chat_member;
|
||||
|
@ -74,6 +77,7 @@ mod get_my_name;
|
|||
mod get_my_short_description;
|
||||
mod get_sticker_set;
|
||||
mod get_updates;
|
||||
mod get_user_chat_boosts;
|
||||
mod get_user_profile_photos;
|
||||
mod get_webhook_info;
|
||||
mod hide_general_forum_topic;
|
||||
|
@ -114,6 +118,7 @@ mod set_chat_title;
|
|||
mod set_custom_emoji_sticker_set_thumbnail;
|
||||
mod set_game_score;
|
||||
mod set_game_score_inline;
|
||||
mod set_message_reaction;
|
||||
mod set_my_commands;
|
||||
mod set_my_default_administrator_rights;
|
||||
mod set_my_description;
|
||||
|
@ -152,6 +157,7 @@ pub use close::{Close, CloseSetters};
|
|||
pub use close_forum_topic::{CloseForumTopic, CloseForumTopicSetters};
|
||||
pub use close_general_forum_topic::{CloseGeneralForumTopic, CloseGeneralForumTopicSetters};
|
||||
pub use copy_message::{CopyMessage, CopyMessageSetters};
|
||||
pub use copy_messages::{CopyMessages, CopyMessagesSetters};
|
||||
pub use create_chat_invite_link::{CreateChatInviteLink, CreateChatInviteLinkSetters};
|
||||
pub use create_forum_topic::{CreateForumTopic, CreateForumTopicSetters};
|
||||
pub use create_invoice_link::{CreateInvoiceLink, CreateInvoiceLinkSetters};
|
||||
|
@ -161,6 +167,7 @@ pub use delete_chat_photo::{DeleteChatPhoto, DeleteChatPhotoSetters};
|
|||
pub use delete_chat_sticker_set::{DeleteChatStickerSet, DeleteChatStickerSetSetters};
|
||||
pub use delete_forum_topic::{DeleteForumTopic, DeleteForumTopicSetters};
|
||||
pub use delete_message::{DeleteMessage, DeleteMessageSetters};
|
||||
pub use delete_messages::{DeleteMessages, DeleteMessagesSetters};
|
||||
pub use delete_my_commands::{DeleteMyCommands, DeleteMyCommandsSetters};
|
||||
pub use delete_sticker_from_set::{DeleteStickerFromSet, DeleteStickerFromSetSetters};
|
||||
pub use delete_sticker_set::{DeleteStickerSet, DeleteStickerSetSetters};
|
||||
|
@ -184,6 +191,7 @@ pub use edit_message_text::{EditMessageText, EditMessageTextSetters};
|
|||
pub use edit_message_text_inline::{EditMessageTextInline, EditMessageTextInlineSetters};
|
||||
pub use export_chat_invite_link::{ExportChatInviteLink, ExportChatInviteLinkSetters};
|
||||
pub use forward_message::{ForwardMessage, ForwardMessageSetters};
|
||||
pub use forward_messages::{ForwardMessages, ForwardMessagesSetters};
|
||||
pub use get_chat::{GetChat, GetChatSetters};
|
||||
pub use get_chat_administrators::{GetChatAdministrators, GetChatAdministratorsSetters};
|
||||
pub use get_chat_member::{GetChatMember, GetChatMemberSetters};
|
||||
|
@ -206,6 +214,7 @@ pub use get_my_name::{GetMyName, GetMyNameSetters};
|
|||
pub use get_my_short_description::{GetMyShortDescription, GetMyShortDescriptionSetters};
|
||||
pub use get_sticker_set::{GetStickerSet, GetStickerSetSetters};
|
||||
pub use get_updates::{GetUpdates, GetUpdatesSetters};
|
||||
pub use get_user_chat_boosts::{GetUserChatBoosts, GetUserChatBoostsSetters};
|
||||
pub use get_user_profile_photos::{GetUserProfilePhotos, GetUserProfilePhotosSetters};
|
||||
pub use get_webhook_info::{GetWebhookInfo, GetWebhookInfoSetters};
|
||||
pub use hide_general_forum_topic::{HideGeneralForumTopic, HideGeneralForumTopicSetters};
|
||||
|
@ -250,6 +259,7 @@ pub use set_custom_emoji_sticker_set_thumbnail::{
|
|||
};
|
||||
pub use set_game_score::{SetGameScore, SetGameScoreSetters};
|
||||
pub use set_game_score_inline::{SetGameScoreInline, SetGameScoreInlineSetters};
|
||||
pub use set_message_reaction::{SetMessageReaction, SetMessageReactionSetters};
|
||||
pub use set_my_commands::{SetMyCommands, SetMyCommandsSetters};
|
||||
pub use set_my_default_administrator_rights::{
|
||||
SetMyDefaultAdministratorRights, SetMyDefaultAdministratorRightsSetters,
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{MessageEntity, MessageId, ParseMode, Recipient, ReplyMarkup, ThreadId};
|
||||
use crate::types::{
|
||||
MessageEntity, MessageId, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId,
|
||||
};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to copy messages of any kind. The method is analogous to the method forwardMessage, but the copied message doesn't have a link to the original message. Returns the [`MessageId`] of the sent message on success.
|
||||
|
@ -36,11 +38,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
35
crates/teloxide-core/src/payloads/copy_messages.rs
Normal file
35
crates/teloxide-core/src/payloads/copy_messages.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
//! Generated by `codegen_payloads`, do not edit by hand.
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{MessageId, Recipient, ThreadId};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. Service messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. A quiz poll can be copied only if the value of the field _correct\_option\_id_ is known to the bot. The method is analogous to the method [`ForwardMessages`], but the copied messages don't have a link to the original message. Album grouping is kept for copied messages. On success, an array of [`MessageId`] of the sent messages is returned.
|
||||
///
|
||||
/// [`MessageId`]: crate::types::MessageId
|
||||
/// [`ForwardMessages`]: crate::payloads::ForwardMessages
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)]
|
||||
pub CopyMessages (CopyMessagesSetters) => Vec<MessageId> {
|
||||
required {
|
||||
/// Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)
|
||||
pub chat_id: Recipient [into],
|
||||
/// Unique identifier for the chat where the original message was sent (or channel username in the format `@channelusername`)
|
||||
pub from_chat_id: Recipient [into],
|
||||
/// Identifiers of 1-100 messages in the chat _from\_chat\_id_ to copy. The identifiers must be specified in a strictly increasing order.
|
||||
pub message_ids: Vec<MessageId> [collect],
|
||||
}
|
||||
optional {
|
||||
/// 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.
|
||||
///
|
||||
/// [silently]: https://telegram.org/blog/channels-2-0#silent-messages
|
||||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// Pass _True_ to copy the messages without their captions
|
||||
pub remove_caption: bool,
|
||||
}
|
||||
}
|
||||
}
|
20
crates/teloxide-core/src/payloads/delete_messages.rs
Normal file
20
crates/teloxide-core/src/payloads/delete_messages.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
//! Generated by `codegen_payloads`, do not edit by hand.
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{MessageId, Recipient, True};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to delete multiple messages simultaneously. If some of the specified messages can't be found, they are skipped. Returns _True_ on success.
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)]
|
||||
pub DeleteMessages (DeleteMessagesSetters) => True {
|
||||
required {
|
||||
/// Unique identifier for the target chat or username of the target channel (in the format `@channelusername`).
|
||||
pub chat_id: Recipient [into],
|
||||
/// Identifiers of 1-100 messages to delete. See [`DeleteMessage`] for limitations on which messages can be deleted
|
||||
///
|
||||
/// [`DeleteMessage`]: crate::payloads::DeleteMessage
|
||||
pub message_ids: Vec<MessageId> [collect],
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{InlineKeyboardMarkup, Message, MessageEntity, MessageId, ParseMode, Recipient};
|
||||
use crate::types::{
|
||||
InlineKeyboardMarkup, LinkPreviewOptions, Message, MessageEntity, MessageId, ParseMode,
|
||||
Recipient,
|
||||
};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to edit text and [games] messages. On success, the edited Message is returned.
|
||||
|
@ -28,8 +31,8 @@ impl_payload! {
|
|||
pub parse_mode: ParseMode,
|
||||
/// List of special entities that appear in message text, which can be specified instead of _parse\_mode_
|
||||
pub entities: Vec<MessageEntity> [collect],
|
||||
/// Disables link previews for links in this message
|
||||
pub disable_web_page_preview: bool,
|
||||
/// Link preview generation options for the message
|
||||
pub link_preview_options: LinkPreviewOptions,
|
||||
/// A JSON-serialized object for an [inline keyboard].
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
32
crates/teloxide-core/src/payloads/forward_messages.rs
Normal file
32
crates/teloxide-core/src/payloads/forward_messages.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
//! Generated by `codegen_payloads`, do not edit by hand.
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{MessageId, Recipient, ThreadId};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to forward multiple messages of any kind. If some of the specified messages can't be found or forwarded, they are skipped. Service messages and messages with protected content can't be forwarded. Album grouping is kept for forwarded messages. On success, an array of [`MessageId`] of the sent messages is returned.
|
||||
///
|
||||
/// [`MessageId`]: crate::types::MessageId
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)]
|
||||
pub ForwardMessages (ForwardMessagesSetters) => Vec<MessageId> {
|
||||
required {
|
||||
/// Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)
|
||||
pub chat_id: Recipient [into],
|
||||
/// Unique identifier for the chat where the original message was sent (or channel username in the format `@channelusername`)
|
||||
pub from_chat_id: Recipient [into],
|
||||
/// A JSON-serialized list of 1-100 identifiers of messages in the chat _from\_chat\_id_ to forward. The identifiers must be specified in a strictly increasing order.
|
||||
pub message_ids: Vec<MessageId> [collect],
|
||||
}
|
||||
optional {
|
||||
/// 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.
|
||||
///
|
||||
/// [silently]: https://telegram.org/blog/channels-2-0#silent-messages
|
||||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
}
|
||||
}
|
||||
}
|
20
crates/teloxide-core/src/payloads/get_user_chat_boosts.rs
Normal file
20
crates/teloxide-core/src/payloads/get_user_chat_boosts.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
//! Generated by `codegen_payloads`, do not edit by hand.
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{Recipient, UserChatBoosts, UserId};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a [`UserChatBoosts`] object.
|
||||
///
|
||||
/// [`UserChatBoosts`]: crate::types::UserChatBoosts
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)]
|
||||
pub GetUserChatBoosts (GetUserChatBoostsSetters) => UserChatBoosts {
|
||||
required {
|
||||
/// Unique identifier for the chat or username of the channel (in the format @channelusername)
|
||||
pub chat_id: Recipient [into],
|
||||
/// Unique identifier of the target user
|
||||
pub user_id: UserId,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::types::{
|
||||
InputFile, Message, MessageEntity, MessageId, ParseMode, Recipient, ReplyMarkup, ThreadId,
|
||||
InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId,
|
||||
};
|
||||
|
||||
impl_payload! {
|
||||
|
@ -50,11 +50,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::types::{
|
||||
InputFile, Message, MessageEntity, MessageId, ParseMode, Recipient, ReplyMarkup, ThreadId,
|
||||
InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId,
|
||||
};
|
||||
|
||||
impl_payload! {
|
||||
|
@ -51,11 +51,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{Message, MessageId, Recipient, ReplyMarkup, ThreadId};
|
||||
use crate::types::{Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to send phone contacts. On success, the sent [`Message`] is returned.
|
||||
|
@ -33,11 +33,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{DiceEmoji, Message, MessageId, Recipient, ReplyMarkup, ThreadId};
|
||||
use crate::types::{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.
|
||||
|
@ -25,11 +25,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::types::{
|
||||
InputFile, Message, MessageEntity, MessageId, ParseMode, Recipient, ReplyMarkup, ThreadId,
|
||||
InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId,
|
||||
};
|
||||
|
||||
impl_payload! {
|
||||
|
@ -44,11 +44,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{ChatId, Message, MessageId, ReplyMarkup, ThreadId};
|
||||
use crate::types::{ChatId, Message, ReplyMarkup, ReplyParameters, ThreadId};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to send a game. On success, the sent [`Message`] is returned.
|
||||
|
@ -25,11 +25,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
use serde::Serialize;
|
||||
use url::Url;
|
||||
|
||||
use crate::types::{InlineKeyboardMarkup, LabeledPrice, Message, MessageId, Recipient, ThreadId};
|
||||
use crate::types::{
|
||||
InlineKeyboardMarkup, LabeledPrice, Message, Recipient, ReplyParameters, ThreadId,
|
||||
};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to send invoices. On success, the sent [`Message`] is returned.
|
||||
|
@ -70,11 +72,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: bool,
|
||||
/// Description of the message to reply to
|
||||
pub reply_parameters: ReplyParameters,
|
||||
/// A JSON-serialized object for an [inline keyboard]. If empty, one 'Pay `total price`' button will be shown. If not empty, the first button must be a Pay button.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{Message, MessageId, Recipient, ReplyMarkup, ThreadId};
|
||||
use crate::types::{Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to send point on the map. On success, the sent [`Message`] is returned.
|
||||
|
@ -37,11 +37,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{InputMedia, Message, MessageId, Recipient, ThreadId};
|
||||
use crate::types::{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.
|
||||
|
@ -34,11 +34,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: bool,
|
||||
/// Description of the message to reply to
|
||||
pub reply_parameters: ReplyParameters,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::types::{
|
||||
Message, MessageEntity, MessageId, ParseMode, Recipient, ReplyMarkup, ThreadId,
|
||||
LinkPreviewOptions, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters,
|
||||
ThreadId,
|
||||
};
|
||||
|
||||
impl_payload! {
|
||||
|
@ -27,19 +28,16 @@ impl_payload! {
|
|||
pub parse_mode: ParseMode,
|
||||
/// List of special entities that appear in the message text, which can be specified instead of _parse\_mode_
|
||||
pub entities: Vec<MessageEntity> [collect],
|
||||
/// Disables link previews for links in this message
|
||||
pub disable_web_page_preview: bool,
|
||||
/// Link preview generation options for the message
|
||||
pub link_preview_options: LinkPreviewOptions,
|
||||
/// Sends the message [silently]. Users will receive a notification with no sound.
|
||||
///
|
||||
/// [silently]: https://telegram.org/blog/channels-2-0#silent-messages
|
||||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::types::{
|
||||
InputFile, Message, MessageEntity, MessageId, ParseMode, Recipient, ReplyMarkup, ThreadId,
|
||||
InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId,
|
||||
};
|
||||
|
||||
impl_payload! {
|
||||
|
@ -40,11 +40,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -4,11 +4,11 @@ use chrono::{DateTime, Utc};
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::types::{
|
||||
Message, MessageEntity, MessageId, ParseMode, PollType, Recipient, ReplyMarkup, ThreadId,
|
||||
Message, MessageEntity, ParseMode, PollType, Recipient, ReplyMarkup, ReplyParameters, ThreadId,
|
||||
};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to send phone contacts. On success, the sent [`Message`] is returned.
|
||||
/// Use this method to send a native poll. On success, the sent [`Message`] is returned.
|
||||
///
|
||||
/// [`Message`]: crate::types::Message
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)]
|
||||
|
@ -54,11 +54,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{InputFile, Message, MessageId, Recipient, ReplyMarkup, ThreadId};
|
||||
use crate::types::{InputFile, Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId};
|
||||
|
||||
impl_payload! {
|
||||
@[multipart = sticker]
|
||||
|
@ -30,11 +30,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{Message, MessageId, Recipient, ReplyMarkup, ThreadId};
|
||||
use crate::types::{Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to send information about a venue. On success, the sent [`Message`] is returned.
|
||||
|
@ -41,11 +41,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::types::{
|
||||
InputFile, Message, MessageEntity, MessageId, ParseMode, Recipient, ReplyMarkup, ThreadId,
|
||||
InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId,
|
||||
};
|
||||
|
||||
impl_payload! {
|
||||
|
@ -53,11 +53,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{InputFile, Message, MessageId, Recipient, ReplyMarkup, ThreadId};
|
||||
use crate::types::{InputFile, Message, Recipient, ReplyMarkup, ReplyParameters, ThreadId};
|
||||
|
||||
impl_payload! {
|
||||
@[multipart = video_note, thumbnail]
|
||||
|
@ -37,11 +37,8 @@ impl_payload! {
|
|||
pub disable_notification: bool,
|
||||
/// Protects the contents of sent messages from forwarding and saving
|
||||
pub protect_content: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::types::{
|
||||
InputFile, Message, MessageEntity, MessageId, ParseMode, Recipient, ReplyMarkup, ThreadId,
|
||||
InputFile, Message, MessageEntity, ParseMode, Recipient, ReplyMarkup, ReplyParameters, ThreadId,
|
||||
};
|
||||
|
||||
impl_payload! {
|
||||
|
@ -40,11 +40,8 @@ impl_payload! {
|
|||
///
|
||||
/// [silently]: https://telegram.org/blog/channels-2-0#silent-messages
|
||||
pub disable_notification: bool,
|
||||
/// If the message is a reply, ID of the original message
|
||||
#[serde(serialize_with = "crate::types::serialize_reply_to_message_id")]
|
||||
pub reply_to_message_id: MessageId,
|
||||
/// Pass _True_, if the message should be sent even if the specified replied-to message is not found
|
||||
pub allow_sending_without_reply: 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.
|
||||
///
|
||||
/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
|
||||
|
|
25
crates/teloxide-core/src/payloads/set_message_reaction.rs
Normal file
25
crates/teloxide-core/src/payloads/set_message_reaction.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
//! Generated by `codegen_payloads`, do not edit by hand.
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::{MessageId, ReactionType, Recipient, True};
|
||||
|
||||
impl_payload! {
|
||||
/// Use this method to change the chosen reactions on a message. Service messages can't be reacted to. Automatically forwarded messages from a channel to its discussion group have the same available reactions as messages in the channel. Returns True on success.
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)]
|
||||
pub SetMessageReaction (SetMessageReactionSetters) => True {
|
||||
required {
|
||||
/// Unique identifier for the target chat or username of the target channel (in the format @channelusername)
|
||||
pub chat_id: Recipient [into],
|
||||
/// Identifier of the target message. If the message belongs to a media group, the reaction is set to the first non-deleted message in the group instead.
|
||||
#[serde(flatten)]
|
||||
pub message_id: MessageId,
|
||||
}
|
||||
optional {
|
||||
/// New list of reaction types to set on the message. Currently, as non-premium users, bots can set up to one reaction per message. A custom emoji reaction can be used if it is either already present on the message or explicitly allowed by chat administrators.
|
||||
pub reaction: Vec<ReactionType> [collect],
|
||||
/// Pass True to set the reaction with a big animation
|
||||
pub is_big: bool,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,31 +6,33 @@ pub use crate::payloads::{
|
|||
AnswerPreCheckoutQuerySetters as _, AnswerShippingQuerySetters as _,
|
||||
AnswerWebAppQuerySetters as _, ApproveChatJoinRequestSetters as _, BanChatMemberSetters as _,
|
||||
BanChatSenderChatSetters as _, CloseForumTopicSetters as _, CloseGeneralForumTopicSetters as _,
|
||||
CloseSetters as _, CopyMessageSetters as _, CreateChatInviteLinkSetters as _,
|
||||
CreateForumTopicSetters as _, CreateInvoiceLinkSetters as _, CreateNewStickerSetSetters as _,
|
||||
DeclineChatJoinRequestSetters as _, DeleteChatPhotoSetters as _,
|
||||
DeleteChatStickerSetSetters as _, DeleteForumTopicSetters as _, DeleteMessageSetters as _,
|
||||
DeleteMyCommandsSetters as _, DeleteStickerFromSetSetters as _, DeleteStickerSetSetters as _,
|
||||
DeleteWebhookSetters as _, EditChatInviteLinkSetters as _, EditForumTopicSetters as _,
|
||||
EditGeneralForumTopicSetters as _, EditMessageCaptionInlineSetters as _,
|
||||
EditMessageCaptionSetters as _, EditMessageLiveLocationInlineSetters as _,
|
||||
EditMessageLiveLocationSetters as _, EditMessageMediaInlineSetters as _,
|
||||
EditMessageMediaSetters as _, EditMessageReplyMarkupInlineSetters as _,
|
||||
EditMessageReplyMarkupSetters as _, EditMessageTextInlineSetters as _,
|
||||
EditMessageTextSetters as _, ExportChatInviteLinkSetters as _, ForwardMessageSetters as _,
|
||||
CloseSetters as _, CopyMessageSetters as _, CopyMessagesSetters as _,
|
||||
CreateChatInviteLinkSetters as _, CreateForumTopicSetters as _, CreateInvoiceLinkSetters as _,
|
||||
CreateNewStickerSetSetters as _, DeclineChatJoinRequestSetters as _,
|
||||
DeleteChatPhotoSetters as _, DeleteChatStickerSetSetters as _, DeleteForumTopicSetters as _,
|
||||
DeleteMessageSetters as _, DeleteMessagesSetters as _, DeleteMyCommandsSetters as _,
|
||||
DeleteStickerFromSetSetters as _, DeleteStickerSetSetters as _, DeleteWebhookSetters as _,
|
||||
EditChatInviteLinkSetters as _, EditForumTopicSetters as _, EditGeneralForumTopicSetters as _,
|
||||
EditMessageCaptionInlineSetters as _, EditMessageCaptionSetters as _,
|
||||
EditMessageLiveLocationInlineSetters as _, EditMessageLiveLocationSetters as _,
|
||||
EditMessageMediaInlineSetters as _, EditMessageMediaSetters as _,
|
||||
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 _, GetUserProfilePhotosSetters as _, GetWebhookInfoSetters as _,
|
||||
HideGeneralForumTopicSetters as _, KickChatMemberSetters as _, LeaveChatSetters as _,
|
||||
LogOutSetters as _, PinChatMessageSetters as _, PromoteChatMemberSetters as _,
|
||||
ReopenForumTopicSetters as _, ReopenGeneralForumTopicSetters as _,
|
||||
RestrictChatMemberSetters as _, RevokeChatInviteLinkSetters as _, SendAnimationSetters as _,
|
||||
SendAudioSetters as _, SendChatActionSetters as _, SendContactSetters as _,
|
||||
SendDiceSetters as _, SendDocumentSetters as _, SendGameSetters as _, SendInvoiceSetters 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 _,
|
||||
RevokeChatInviteLinkSetters as _, SendAnimationSetters as _, SendAudioSetters as _,
|
||||
SendChatActionSetters as _, SendContactSetters as _, SendDiceSetters as _,
|
||||
SendDocumentSetters as _, SendGameSetters as _, SendInvoiceSetters as _,
|
||||
SendLocationSetters as _, SendMediaGroupSetters as _, SendMessageSetters as _,
|
||||
SendPhotoSetters as _, SendPollSetters as _, SendStickerSetters as _, SendVenueSetters as _,
|
||||
SendVideoNoteSetters as _, SendVideoSetters as _, SendVoiceSetters as _,
|
||||
|
@ -38,7 +40,7 @@ pub use crate::payloads::{
|
|||
SetChatMenuButtonSetters as _, SetChatPermissionsSetters as _, SetChatPhotoSetters as _,
|
||||
SetChatStickerSetSetters as _, SetChatTitleSetters as _,
|
||||
SetCustomEmojiStickerSetThumbnailSetters as _, SetGameScoreInlineSetters as _,
|
||||
SetGameScoreSetters as _, SetMyCommandsSetters as _,
|
||||
SetGameScoreSetters as _, SetMessageReactionSetters as _, SetMyCommandsSetters as _,
|
||||
SetMyDefaultAdministratorRightsSetters as _, SetMyDescriptionSetters as _,
|
||||
SetMyNameSetters as _, SetMyShortDescriptionSetters as _, SetPassportDataErrorsSetters as _,
|
||||
SetStickerEmojiListSetters as _, SetStickerKeywordsSetters as _,
|
||||
|
|
|
@ -203,6 +203,20 @@ pub trait Requester {
|
|||
C: Into<Recipient>,
|
||||
F: Into<Recipient>;
|
||||
|
||||
type ForwardMessages: Request<Payload = ForwardMessages, Err = Self::Err>;
|
||||
|
||||
/// For Telegram documentation see [`ForwardMessages`].
|
||||
fn forward_messages<C, F, M>(
|
||||
&self,
|
||||
chat_id: C,
|
||||
from_chat_id: F,
|
||||
message_ids: M,
|
||||
) -> Self::ForwardMessages
|
||||
where
|
||||
C: Into<Recipient>,
|
||||
F: Into<Recipient>,
|
||||
M: IntoIterator<Item = MessageId>;
|
||||
|
||||
type CopyMessage: Request<Payload = CopyMessage, Err = Self::Err>;
|
||||
|
||||
/// For Telegram documentation see [`CopyMessage`].
|
||||
|
@ -216,6 +230,20 @@ pub trait Requester {
|
|||
C: Into<Recipient>,
|
||||
F: Into<Recipient>;
|
||||
|
||||
type CopyMessages: Request<Payload = CopyMessages, Err = Self::Err>;
|
||||
|
||||
/// For Telegram documentation see [`CopyMessages`].
|
||||
fn copy_messages<C, F, M>(
|
||||
&self,
|
||||
chat_id: C,
|
||||
from_chat_id: F,
|
||||
message_ids: M,
|
||||
) -> Self::CopyMessages
|
||||
where
|
||||
C: Into<Recipient>,
|
||||
F: Into<Recipient>,
|
||||
M: IntoIterator<Item = MessageId>;
|
||||
|
||||
type SendPhoto: Request<Payload = SendPhoto, Err = Self::Err>;
|
||||
|
||||
/// For Telegram documentation see [`SendPhoto`].
|
||||
|
@ -385,6 +413,17 @@ pub trait Requester {
|
|||
where
|
||||
C: Into<Recipient>;
|
||||
|
||||
type SetMessageReaction: Request<Payload = SetMessageReaction, Err = Self::Err>;
|
||||
|
||||
/// For Telegram documentation see [`SetMessageReaction`].
|
||||
fn set_message_reaction<C>(
|
||||
&self,
|
||||
chat_id: C,
|
||||
message_id: MessageId,
|
||||
) -> Self::SetMessageReaction
|
||||
where
|
||||
C: Into<Recipient>;
|
||||
|
||||
type GetUserProfilePhotos: Request<Payload = GetUserProfilePhotos, Err = Self::Err>;
|
||||
|
||||
/// For Telegram documentation see [`GetUserProfilePhotos`].
|
||||
|
@ -778,6 +817,13 @@ pub trait Requester {
|
|||
where
|
||||
C: Into<String>;
|
||||
|
||||
type GetUserChatBoosts: Request<Payload = GetUserChatBoosts, Err = Self::Err>;
|
||||
|
||||
/// For Telegram documentation see [`GetUserChatBoosts`].
|
||||
fn get_user_chat_boosts<C>(&self, chat_id: C, user_id: UserId) -> Self::GetUserChatBoosts
|
||||
where
|
||||
C: Into<Recipient>;
|
||||
|
||||
type SetMyCommands: Request<Payload = SetMyCommands, Err = Self::Err>;
|
||||
|
||||
/// For Telegram documentation see [`SetMyCommands`].
|
||||
|
@ -977,6 +1023,14 @@ pub trait Requester {
|
|||
where
|
||||
C: Into<Recipient>;
|
||||
|
||||
type DeleteMessages: Request<Payload = DeleteMessages, Err = Self::Err>;
|
||||
|
||||
/// For Telegram documentation see [`DeleteMessages`].
|
||||
fn delete_messages<C, M>(&self, chat_id: C, message_ids: M) -> Self::DeleteMessages
|
||||
where
|
||||
C: Into<Recipient>,
|
||||
M: IntoIterator<Item = MessageId>;
|
||||
|
||||
type SendSticker: Request<Payload = SendSticker, Err = Self::Err>;
|
||||
|
||||
/// For Telegram documentation see [`SendSticker`].
|
||||
|
@ -1249,7 +1303,9 @@ macro_rules! forward_all {
|
|||
delete_webhook,
|
||||
get_webhook_info,
|
||||
forward_message,
|
||||
forward_messages,
|
||||
copy_message,
|
||||
copy_messages,
|
||||
send_message,
|
||||
send_photo,
|
||||
send_audio,
|
||||
|
@ -1269,6 +1325,7 @@ macro_rules! forward_all {
|
|||
send_poll,
|
||||
send_dice,
|
||||
send_chat_action,
|
||||
set_message_reaction,
|
||||
get_user_profile_photos,
|
||||
get_file,
|
||||
kick_chat_member,
|
||||
|
@ -1313,6 +1370,7 @@ macro_rules! forward_all {
|
|||
unhide_general_forum_topic,
|
||||
unpin_all_general_forum_topic_messages,
|
||||
answer_callback_query,
|
||||
get_user_chat_boosts,
|
||||
set_my_commands,
|
||||
get_my_commands,
|
||||
set_my_name,
|
||||
|
@ -1338,6 +1396,7 @@ macro_rules! forward_all {
|
|||
edit_message_reply_markup_inline,
|
||||
stop_poll,
|
||||
delete_message,
|
||||
delete_messages,
|
||||
send_sticker,
|
||||
get_sticker_set,
|
||||
get_custom_emoji_stickers,
|
||||
|
|
|
@ -173,8 +173,7 @@ mod tests {
|
|||
.caption_entities(entities())
|
||||
.thumbnail(InputFile::read(
|
||||
File::open("../../media/teloxide-core-logo.png").await.unwrap(),
|
||||
))
|
||||
.allow_sending_without_reply(true),
|
||||
)),
|
||||
)
|
||||
.unwrap()
|
||||
.await;
|
||||
|
|
|
@ -13,6 +13,10 @@ pub use callback_query::*;
|
|||
pub use chat::*;
|
||||
pub use chat_action::*;
|
||||
pub use chat_administrator_rights::*;
|
||||
pub use chat_boost::*;
|
||||
pub use chat_boost_removed::*;
|
||||
pub use chat_boost_source::*;
|
||||
pub use chat_boost_updated::*;
|
||||
pub use chat_full_info::*;
|
||||
pub use chat_invite_link::*;
|
||||
pub use chat_join_request::*;
|
||||
|
@ -30,6 +34,7 @@ pub use dice_emoji::*;
|
|||
pub use document::*;
|
||||
pub use encrypted_credentials::*;
|
||||
pub use encrypted_passport_element::*;
|
||||
pub use external_reply_info::*;
|
||||
pub use file::*;
|
||||
pub use force_reply::*;
|
||||
pub use forum_topic::*;
|
||||
|
@ -41,6 +46,11 @@ pub use game::*;
|
|||
pub use game_high_score::*;
|
||||
pub use general_forum_topic_hidden::*;
|
||||
pub use general_forum_topic_unhidden::*;
|
||||
pub use giveaway::*;
|
||||
pub use giveaway_completed::*;
|
||||
pub use giveaway_created::*;
|
||||
pub use giveaway_winners::*;
|
||||
pub use inaccessible_message::*;
|
||||
pub use inline_keyboard_button::*;
|
||||
pub use inline_keyboard_markup::*;
|
||||
pub use inline_query::*;
|
||||
|
@ -74,17 +84,22 @@ pub use invoice::*;
|
|||
pub use keyboard_button::*;
|
||||
pub use keyboard_button_poll_type::*;
|
||||
pub use keyboard_button_request_chat::*;
|
||||
pub use keyboard_button_request_user::*;
|
||||
pub use keyboard_button_request_users::*;
|
||||
pub use label_price::*;
|
||||
pub use link_preview_options::*;
|
||||
pub use location::*;
|
||||
pub use login_url::*;
|
||||
pub use mask_position::*;
|
||||
pub use maybe_inaccessible_message::*;
|
||||
pub use me::*;
|
||||
pub use menu_button::*;
|
||||
pub use message::*;
|
||||
pub use message_auto_delete_timer_changed::*;
|
||||
pub use message_entity::*;
|
||||
pub use message_id::*;
|
||||
pub use message_origin::*;
|
||||
pub use message_reaction_count_updated::*;
|
||||
pub use message_reaction_updated::*;
|
||||
pub use order_info::*;
|
||||
pub use parse_mode::*;
|
||||
pub use passport_data::*;
|
||||
|
@ -96,9 +111,12 @@ pub use poll_answer::*;
|
|||
pub use poll_type::*;
|
||||
pub use pre_checkout_query::*;
|
||||
pub use proximity_alert_triggered::*;
|
||||
pub use reaction_type::*;
|
||||
pub use reply_keyboard_markup::*;
|
||||
pub use reply_keyboard_remove::*;
|
||||
pub use reply_markup::*;
|
||||
pub use reply_parameters::*;
|
||||
pub use request_id::*;
|
||||
pub use response_parameters::*;
|
||||
pub use sent_web_app_message::*;
|
||||
pub use shipping_address::*;
|
||||
|
@ -110,13 +128,15 @@ pub use story::*;
|
|||
pub use successful_payment::*;
|
||||
pub use switch_inline_query_chosen_chat::*;
|
||||
pub use target_message::*;
|
||||
pub use text_quote::*;
|
||||
pub use thread_id::*;
|
||||
pub use unit_false::*;
|
||||
pub use unit_true::*;
|
||||
pub use update::*;
|
||||
pub use user::*;
|
||||
pub use user_chat_boosts::*;
|
||||
pub use user_profile_photos::*;
|
||||
pub use user_shared::*;
|
||||
pub use users_shared::*;
|
||||
pub use venue::*;
|
||||
pub use video::*;
|
||||
pub use video_chat_ended::*;
|
||||
|
@ -143,6 +163,10 @@ mod callback_query;
|
|||
mod chat;
|
||||
mod chat_action;
|
||||
mod chat_administrator_rights;
|
||||
mod chat_boost;
|
||||
mod chat_boost_removed;
|
||||
mod chat_boost_source;
|
||||
mod chat_boost_updated;
|
||||
mod chat_full_info;
|
||||
mod chat_invite_link;
|
||||
mod chat_join_request;
|
||||
|
@ -158,6 +182,7 @@ mod contact;
|
|||
mod dice;
|
||||
mod dice_emoji;
|
||||
mod document;
|
||||
mod external_reply_info;
|
||||
mod file;
|
||||
mod force_reply;
|
||||
mod forum_topic;
|
||||
|
@ -169,6 +194,11 @@ mod game;
|
|||
mod game_high_score;
|
||||
mod general_forum_topic_hidden;
|
||||
mod general_forum_topic_unhidden;
|
||||
mod giveaway;
|
||||
mod giveaway_completed;
|
||||
mod giveaway_created;
|
||||
mod giveaway_winners;
|
||||
mod inaccessible_message;
|
||||
mod inline_keyboard_button;
|
||||
mod inline_keyboard_markup;
|
||||
mod inline_query_results_button;
|
||||
|
@ -180,17 +210,22 @@ mod invoice;
|
|||
mod keyboard_button;
|
||||
mod keyboard_button_poll_type;
|
||||
mod keyboard_button_request_chat;
|
||||
mod keyboard_button_request_user;
|
||||
mod keyboard_button_request_users;
|
||||
mod label_price;
|
||||
mod link_preview_options;
|
||||
mod location;
|
||||
mod login_url;
|
||||
mod mask_position;
|
||||
mod maybe_inaccessible_message;
|
||||
mod me;
|
||||
mod menu_button;
|
||||
mod message;
|
||||
mod message_auto_delete_timer_changed;
|
||||
mod message_entity;
|
||||
mod message_id;
|
||||
mod message_origin;
|
||||
mod message_reaction_count_updated;
|
||||
mod message_reaction_updated;
|
||||
mod order_info;
|
||||
mod parse_mode;
|
||||
mod photo_size;
|
||||
|
@ -199,9 +234,12 @@ mod poll_answer;
|
|||
mod poll_type;
|
||||
mod pre_checkout_query;
|
||||
mod proximity_alert_triggered;
|
||||
mod reaction_type;
|
||||
mod reply_keyboard_markup;
|
||||
mod reply_keyboard_remove;
|
||||
mod reply_markup;
|
||||
mod reply_parameters;
|
||||
mod request_id;
|
||||
mod response_parameters;
|
||||
mod sent_web_app_message;
|
||||
mod shipping_address;
|
||||
|
@ -213,13 +251,15 @@ mod story;
|
|||
mod successful_payment;
|
||||
mod switch_inline_query_chosen_chat;
|
||||
mod target_message;
|
||||
mod text_quote;
|
||||
mod thread_id;
|
||||
mod unit_false;
|
||||
mod unit_true;
|
||||
mod update;
|
||||
mod user;
|
||||
mod user_chat_boosts;
|
||||
mod user_profile_photos;
|
||||
mod user_shared;
|
||||
mod users_shared;
|
||||
mod venue;
|
||||
mod video;
|
||||
mod video_chat_ended;
|
||||
|
@ -280,7 +320,11 @@ pub use recipient::*;
|
|||
pub use seconds::*;
|
||||
pub use user_id::*;
|
||||
|
||||
use serde::Serialize;
|
||||
use serde_with::with_prefix;
|
||||
|
||||
// Deserialization prefix for giveaway_message_id field used in GiveawayWinners
|
||||
// and ChatBoostSourceGiveaway
|
||||
with_prefix!(prefix_giveaway_message_id "giveaway_");
|
||||
|
||||
/// Converts an `i64` timestamp to a `choro::DateTime`, producing serde error
|
||||
/// for invalid timestamps
|
||||
|
@ -439,16 +483,6 @@ pub(crate) mod option_msg_id_as_int {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn serialize_reply_to_message_id<S>(
|
||||
this: &Option<MessageId>,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
this.map(|MessageId(id)| id).serialize(serializer)
|
||||
}
|
||||
|
||||
pub(crate) mod serde_rgb {
|
||||
use serde::{de::Visitor, Deserializer, Serializer};
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ pub enum AllowedUpdate {
|
|||
EditedMessage,
|
||||
ChannelPost,
|
||||
EditedChannelPost,
|
||||
MessageReaction,
|
||||
MessageReactionCount,
|
||||
InlineQuery,
|
||||
ChosenInlineResult,
|
||||
CallbackQuery,
|
||||
|
@ -17,4 +19,6 @@ pub enum AllowedUpdate {
|
|||
MyChatMember,
|
||||
ChatMember,
|
||||
ChatJoinRequest,
|
||||
ChatBoost,
|
||||
RemovedChatBoost,
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Message, User};
|
||||
use crate::types::{MaybeInaccessibleMessage, Message, User};
|
||||
|
||||
/// This object represents an incoming callback query from a callback button in
|
||||
/// an [inline keyboard].
|
||||
|
@ -24,10 +24,12 @@ pub struct CallbackQuery {
|
|||
/// A sender.
|
||||
pub from: User,
|
||||
|
||||
/// A message with the callback button that originated the query. Note that
|
||||
/// message content and message date will not be available if the message
|
||||
/// is too old.
|
||||
pub message: Option<Message>,
|
||||
/// Message sent by the bot with the callback button that originated the
|
||||
/// query.
|
||||
///
|
||||
/// Note: if the message is too old, it will be
|
||||
/// [`MaybeInaccessibleMessage::Inaccessible`].
|
||||
pub message: Option<MaybeInaccessibleMessage>,
|
||||
|
||||
/// An identifier of the message sent via the bot in inline mode, that
|
||||
/// originated the query.
|
||||
|
@ -58,7 +60,15 @@ impl CallbackQuery {
|
|||
use crate::util::flatten;
|
||||
use std::iter::once;
|
||||
|
||||
once(&self.from).chain(flatten(self.message.as_ref().map(Message::mentioned_users)))
|
||||
once(&self.from).chain(flatten(self.regular_message().map(Message::mentioned_users)))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn regular_message(&self) -> Option<&Message> {
|
||||
self.message
|
||||
.as_ref()
|
||||
// If we can access the message
|
||||
.and_then(|maybe| maybe.regular_message())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{
|
||||
ChatFullInfo, ChatId, ChatLocation, ChatPermissions, ChatPhoto, Message, Seconds, True, User,
|
||||
ChatFullInfo, ChatId, ChatLocation, ChatPermissions, ChatPhoto, Message, ReactionType, Seconds,
|
||||
True, User,
|
||||
};
|
||||
|
||||
/// This object represents a chat.
|
||||
|
@ -21,6 +22,12 @@ pub struct Chat {
|
|||
/// [`GetChat`]: crate::payloads::GetChat
|
||||
pub photo: Option<ChatPhoto>,
|
||||
|
||||
/// List of available reactions allowed in the chat. If omitted, then all
|
||||
/// emoji reactions are allowed. Returned only from [`GetChat`].
|
||||
///
|
||||
/// [`GetChat`]: crate::payloads::GetChat
|
||||
pub available_reactions: Option<Vec<ReactionType>>,
|
||||
|
||||
/// The most recent pinned message (by sending date). Returned only in
|
||||
/// [`GetChat`].
|
||||
///
|
||||
|
@ -108,13 +115,6 @@ pub struct ChatPrivate {
|
|||
/// A last name of the other party in a private chat.
|
||||
pub last_name: Option<String>,
|
||||
|
||||
/// Custom emoji identifier of emoji status of the other party in a private
|
||||
/// chat. Returned only in [`GetChat`].
|
||||
///
|
||||
/// [`GetChat`]: crate::payloads::GetChat
|
||||
// FIXME: CustomEmojiId
|
||||
pub emoji_status_custom_emoji_id: Option<String>,
|
||||
|
||||
/// Bio of the other party in a private chat. Returned only in [`GetChat`].
|
||||
///
|
||||
/// [`GetChat`]: crate::payloads::GetChat
|
||||
|
@ -539,7 +539,6 @@ mod serde_helper {
|
|||
bio: Option<String>,
|
||||
has_private_forwards: Option<True>,
|
||||
has_restricted_voice_and_video_messages: Option<True>,
|
||||
emoji_status_custom_emoji_id: Option<String>,
|
||||
}
|
||||
|
||||
impl From<ChatPrivate> for super::ChatPrivate {
|
||||
|
@ -552,7 +551,6 @@ mod serde_helper {
|
|||
bio,
|
||||
has_private_forwards,
|
||||
has_restricted_voice_and_video_messages,
|
||||
emoji_status_custom_emoji_id,
|
||||
}: ChatPrivate,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
@ -562,7 +560,6 @@ mod serde_helper {
|
|||
bio,
|
||||
has_private_forwards,
|
||||
has_restricted_voice_and_video_messages,
|
||||
emoji_status_custom_emoji_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -576,7 +573,6 @@ mod serde_helper {
|
|||
bio,
|
||||
has_private_forwards,
|
||||
has_restricted_voice_and_video_messages,
|
||||
emoji_status_custom_emoji_id,
|
||||
}: super::ChatPrivate,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
@ -587,7 +583,6 @@ mod serde_helper {
|
|||
bio,
|
||||
has_private_forwards,
|
||||
has_restricted_voice_and_video_messages,
|
||||
emoji_status_custom_emoji_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -614,13 +609,27 @@ mod tests {
|
|||
has_protected_content: None,
|
||||
}),
|
||||
photo: None,
|
||||
available_reactions: Some(vec![ReactionType::Emoji { emoji: "🌭".to_owned() }]),
|
||||
pinned_message: None,
|
||||
message_auto_delete_time: None,
|
||||
has_hidden_members: false,
|
||||
has_aggressive_anti_spam_enabled: false,
|
||||
chat_full_info: ChatFullInfo { emoji_status_expiration_date: None },
|
||||
chat_full_info: ChatFullInfo::default(),
|
||||
};
|
||||
let actual = from_str(r#"{"id":-1,"type":"channel","username":"channel_name"}"#).unwrap();
|
||||
let actual = from_str(
|
||||
r#"{
|
||||
"id": -1,
|
||||
"type": "channel",
|
||||
"username": "channel_name",
|
||||
"available_reactions": [
|
||||
{
|
||||
"type": "emoji",
|
||||
"emoji": "🌭"
|
||||
}
|
||||
]
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
|
@ -636,17 +645,30 @@ mod tests {
|
|||
bio: None,
|
||||
has_private_forwards: None,
|
||||
has_restricted_voice_and_video_messages: None,
|
||||
emoji_status_custom_emoji_id: None
|
||||
}),
|
||||
photo: None,
|
||||
available_reactions: Some(vec![ReactionType::Emoji { emoji: "🌭".to_owned() }]),
|
||||
pinned_message: None,
|
||||
message_auto_delete_time: None,
|
||||
has_hidden_members: false,
|
||||
has_aggressive_anti_spam_enabled: false,
|
||||
chat_full_info: ChatFullInfo { emoji_status_expiration_date: None }
|
||||
chat_full_info: ChatFullInfo::default()
|
||||
},
|
||||
from_str(r#"{"id":0,"type":"private","username":"username","first_name":"Anon"}"#)
|
||||
.unwrap()
|
||||
from_str(
|
||||
r#"{
|
||||
"id": 0,
|
||||
"type": "private",
|
||||
"username": "username",
|
||||
"first_name": "Anon",
|
||||
"available_reactions": [
|
||||
{
|
||||
"type": "emoji",
|
||||
"emoji": "🌭"
|
||||
}
|
||||
]
|
||||
}"#
|
||||
)
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -661,14 +683,14 @@ mod tests {
|
|||
bio: None,
|
||||
has_private_forwards: None,
|
||||
has_restricted_voice_and_video_messages: None,
|
||||
emoji_status_custom_emoji_id: 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 { emoji_status_expiration_date: None },
|
||||
chat_full_info: ChatFullInfo::default(),
|
||||
};
|
||||
|
||||
let json = to_string(&chat).unwrap();
|
||||
|
|
52
crates/teloxide-core/src/types/chat_boost.rs
Normal file
52
crates/teloxide-core/src/types/chat_boost.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::ChatBoostSource;
|
||||
|
||||
/// This object contains information about a chat boost.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ChatBoost {
|
||||
/// Unique identifier of the boost.
|
||||
pub boost_id: String,
|
||||
|
||||
/// Point in time (Unix timestamp) when the chat was boosted.
|
||||
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
pub add_date: DateTime<Utc>,
|
||||
|
||||
/// Point in time (Unix timestamp) when the boost will automatically expire,
|
||||
/// unless the booster's Telegram Premium subscription is prolonged.
|
||||
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
pub expiration_date: DateTime<Utc>,
|
||||
|
||||
/// Source of the added boost.
|
||||
pub source: ChatBoostSource,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let data = r#"
|
||||
{
|
||||
"boost_id": "4506e1b7e866e33fcbde78fe1746ec3a",
|
||||
"add_date": 1721399621,
|
||||
"expiration_date": 1745088963,
|
||||
"source": {
|
||||
"source": "premium",
|
||||
"user": {
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10",
|
||||
"language_code": "en",
|
||||
"is_premium": true
|
||||
}
|
||||
}
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<ChatBoost>(data).unwrap();
|
||||
}
|
||||
}
|
55
crates/teloxide-core/src/types/chat_boost_removed.rs
Normal file
55
crates/teloxide-core/src/types/chat_boost_removed.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Chat, ChatBoostSource};
|
||||
|
||||
/// This object represents a boost removed from a chat.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ChatBoostRemoved {
|
||||
/// Chat which was boosted
|
||||
pub chat: Chat,
|
||||
|
||||
// FIXME: BoostId
|
||||
/// Unique identifier of the boost
|
||||
pub boost_id: String,
|
||||
|
||||
/// Point in time (Unix timestamp) when the boost was removed
|
||||
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
pub remove_date: DateTime<Utc>,
|
||||
|
||||
/// Source of the removed boost
|
||||
pub source: ChatBoostSource,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let data = r#"
|
||||
{
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"boost_id": "4506e1b7e866e33fcbde78fe1746ec3a",
|
||||
"remove_date": 1745089963,
|
||||
"source": {
|
||||
"source": "premium",
|
||||
"user": {
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10",
|
||||
"language_code": "en",
|
||||
"is_premium": true
|
||||
}
|
||||
}
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<ChatBoostRemoved>(data).unwrap();
|
||||
}
|
||||
}
|
124
crates/teloxide-core/src/types/chat_boost_source.rs
Normal file
124
crates/teloxide-core/src/types/chat_boost_source.rs
Normal file
|
@ -0,0 +1,124 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{MessageId, User};
|
||||
|
||||
/// This object describes the source of a chat boost.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[serde(tag = "source")]
|
||||
pub enum ChatBoostSource {
|
||||
Premium(ChatBoostSourcePremium),
|
||||
GiftCode(ChatBoostSourceGiftCode),
|
||||
Giveaway(ChatBoostSourceGiveaway),
|
||||
}
|
||||
|
||||
/// The boost was obtained by subscribing to Telegram Premium or by gifting a
|
||||
/// Telegram Premium subscription to another user.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ChatBoostSourcePremium {
|
||||
/// User that boosted the chat.
|
||||
pub user: User,
|
||||
}
|
||||
|
||||
/// The boost was obtained by the creation of Telegram Premium gift codes to
|
||||
/// boost a chat. Each such code boosts the chat 4 times for the duration of the
|
||||
/// corresponding Telegram Premium subscription.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ChatBoostSourceGiftCode {
|
||||
/// User for which the gift code was created.
|
||||
pub user: User,
|
||||
}
|
||||
|
||||
/// The boost was obtained by the creation of a Telegram Premium giveaway. This
|
||||
/// boosts the chat 4 times for the duration of the corresponding Telegram
|
||||
/// Premium subscription.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ChatBoostSourceGiveaway {
|
||||
/// Identifier of a message in the chat with the giveaway; the message could
|
||||
/// have been deleted already. May be 0 if the message isn't sent yet.
|
||||
#[serde(flatten, with = "crate::types::prefix_giveaway_message_id")]
|
||||
pub giveaway_message_id: MessageId,
|
||||
|
||||
/// User that won the prize in the giveaway if any.
|
||||
pub user: Option<User>,
|
||||
|
||||
/// `true`, if the giveaway was completed, but there was no user to win the
|
||||
/// prize.
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub is_unclaimed: bool,
|
||||
}
|
||||
|
||||
impl ChatBoostSource {
|
||||
#[must_use]
|
||||
pub fn user(&self) -> Option<&User> {
|
||||
Some(match &self {
|
||||
Self::Premium(premium) => &premium.user,
|
||||
Self::GiftCode(gift_code) => &gift_code.user,
|
||||
Self::Giveaway(giveaway) => return giveaway.user.as_ref(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize_premium() {
|
||||
let data = r#"
|
||||
{
|
||||
"source": "premium",
|
||||
"user": {
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10",
|
||||
"language_code": "en",
|
||||
"is_premium": true
|
||||
}
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<ChatBoostSource>(data).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_gift_code() {
|
||||
let data = r#"
|
||||
{
|
||||
"source": "gift_code",
|
||||
"user": {
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10",
|
||||
"language_code": "en",
|
||||
"is_premium": false
|
||||
}
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<ChatBoostSource>(data).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_giveaway() {
|
||||
let data = r#"
|
||||
{
|
||||
"source": "giveaway",
|
||||
"giveaway_message_id": 420,
|
||||
"user": {
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10",
|
||||
"language_code": "en",
|
||||
"is_premium": false
|
||||
}
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<ChatBoostSource>(data).unwrap();
|
||||
}
|
||||
}
|
49
crates/teloxide-core/src/types/chat_boost_updated.rs
Normal file
49
crates/teloxide-core/src/types/chat_boost_updated.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Chat, ChatBoost};
|
||||
|
||||
/// This object represents a boost added to a chat or changed.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ChatBoostUpdated {
|
||||
/// Chat which was boosted
|
||||
pub chat: Chat,
|
||||
|
||||
/// Infomation about the chat boost
|
||||
pub boost: ChatBoost,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let data = r#"
|
||||
{
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"boost": {
|
||||
"boost_id": "4506e1b7e866e33fcbde78fe1746ec3a",
|
||||
"add_date": 1721399621,
|
||||
"expiration_date": 1745088963,
|
||||
"source": {
|
||||
"source": "premium",
|
||||
"user": {
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10",
|
||||
"language_code": "en",
|
||||
"is_premium": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<ChatBoostUpdated>(data).unwrap();
|
||||
}
|
||||
}
|
|
@ -4,12 +4,43 @@ use serde::{Deserialize, Serialize};
|
|||
// TODO: in the TBA7.3 the Chat will be splitted into Chat and ChatInfo
|
||||
// Currently it's just a container for the some fields of the Chat struct
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ChatFullInfo {
|
||||
/// Identifier of the accent color for the chat name and backgrounds of the
|
||||
/// chat photo, reply header, and link preview. See [accent colors] for more
|
||||
/// details.
|
||||
///
|
||||
/// [accent colors]: https://core.telegram.org/bots/api#accent-colors
|
||||
pub accent_color_id: Option<u8>,
|
||||
/// Custom emoji identifier of the emoji chosen by the chat for the reply
|
||||
/// header and link preview background
|
||||
// FIXME: CustomEmojiId
|
||||
pub background_custom_emoji_id: Option<String>,
|
||||
/// Identifier of the accent color for the chat's profile background. See
|
||||
/// [profile accent colors] for more details.
|
||||
///
|
||||
/// [profile accent colors]: https://core.telegram.org/bots/api#profile-accent-colors
|
||||
pub profile_accent_color_id: Option<u8>,
|
||||
/// Custom emoji identifier of the emoji chosen by the chat for its profile
|
||||
/// background
|
||||
// FIXME: CustomEmojiId
|
||||
pub profile_background_custom_emoji_id: Option<String>,
|
||||
/// Custom emoji identifier of emoji status of the other party in a private
|
||||
/// chat. Returned only in [`GetChat`].
|
||||
///
|
||||
/// [`GetChat`]: crate::payloads::GetChat
|
||||
// FIXME: CustomEmojiId
|
||||
pub emoji_status_custom_emoji_id: Option<String>,
|
||||
/// Expiration date of the emoji status of the chat or the other party in a
|
||||
/// private chat, in Unix time, if any
|
||||
#[serde(default, with = "crate::types::serde_opt_date_from_unix_timestamp")]
|
||||
pub emoji_status_expiration_date: Option<DateTime<Utc>>,
|
||||
/// True, if new chat members will have access to old messages; available
|
||||
/// only to chat administrators. Returned only in [`GetChat`].
|
||||
///
|
||||
/// [`GetChat`]: crate::payloads::GetChat
|
||||
#[serde(default)]
|
||||
pub has_visible_history: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -18,18 +49,18 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_chat_full_info_de() {
|
||||
assert_eq!(
|
||||
serde_json::from_str::<ChatFullInfo>("{}").unwrap(),
|
||||
ChatFullInfo { emoji_status_expiration_date: None }
|
||||
);
|
||||
assert_eq!(serde_json::from_str::<ChatFullInfo>("{}").unwrap(), ChatFullInfo::default());
|
||||
assert_eq!(
|
||||
serde_json::from_str::<ChatFullInfo>(
|
||||
r#"{
|
||||
"emoji_status_expiration_date": 1720708004
|
||||
}"#
|
||||
"emoji_status_expiration_date": 1720708004
|
||||
}"#
|
||||
)
|
||||
.unwrap(),
|
||||
ChatFullInfo { emoji_status_expiration_date: DateTime::from_timestamp(1720708004, 0) }
|
||||
ChatFullInfo {
|
||||
emoji_status_expiration_date: DateTime::from_timestamp(1720708004, 0),
|
||||
..ChatFullInfo::default()
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::ChatId;
|
||||
use crate::types::{ChatId, RequestId};
|
||||
|
||||
/// Information about the chat whose identifier was shared with the bot using a
|
||||
/// [`KeyboardButtonRequestChat`] button.
|
||||
|
@ -9,7 +9,7 @@ use crate::types::ChatId;
|
|||
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ChatShared {
|
||||
/// Identifier of the request.
|
||||
pub request_id: i32,
|
||||
pub request_id: RequestId,
|
||||
/// Identifier of the shared chat.
|
||||
pub chat_id: ChatId,
|
||||
}
|
||||
|
|
62
crates/teloxide-core/src/types/external_reply_info.rs
Normal file
62
crates/teloxide-core/src/types/external_reply_info.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{
|
||||
Animation, Audio, Chat, Contact, Dice, Document, Game, Giveaway, GiveawayWinners, Invoice,
|
||||
LinkPreviewOptions, Location, MessageId, MessageOrigin, PhotoSize, Poll, Sticker, Story, Venue,
|
||||
Video, VideoNote, Voice,
|
||||
};
|
||||
|
||||
/// This object contains information about a message that is being replied to,
|
||||
/// which may come from another chat or forum topic.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ExternalReplyInfo {
|
||||
/// Origin of the message replied to by the given message.
|
||||
pub origin: MessageOrigin,
|
||||
/// Chat the original message belongs to. Available only if the chat is a
|
||||
/// supergroup or a channel.
|
||||
pub chat: Option<Chat>,
|
||||
/// Unique message identifier inside the original chat. Available only if
|
||||
/// the original chat is a supergroup or a channel.
|
||||
#[serde(with = "crate::types::option_msg_id_as_int")]
|
||||
pub message_id: Option<MessageId>,
|
||||
/// Options used for link preview generation for the original message, if it
|
||||
/// is a text message.
|
||||
pub link_preview_options: Option<LinkPreviewOptions>,
|
||||
/// _true_, if the message media is covered by a spoiler animation.
|
||||
#[serde(default)]
|
||||
pub has_media_spoiler: bool,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub kind: ExternalReplyInfoKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ExternalReplyInfoKind {
|
||||
// Note:
|
||||
// - `Venue` must be in front of `Location`
|
||||
// - `Animation` must be in front of `Document`
|
||||
//
|
||||
// This is needed so serde doesn't parse `Venue` as `Location` or `Animation` as `Document`
|
||||
// (for backward compatability telegram duplicates some fields).
|
||||
//
|
||||
// See <https://github.com/teloxide/teloxide/issues/481>
|
||||
Animation(Animation),
|
||||
Audio(Audio),
|
||||
Contact(Contact),
|
||||
Dice(Dice),
|
||||
Document(Document),
|
||||
Game(Game),
|
||||
Venue(Venue),
|
||||
Location(Location),
|
||||
Photo(Vec<PhotoSize>),
|
||||
Poll(Poll),
|
||||
Sticker(Sticker),
|
||||
Story(Story),
|
||||
Giveaway(Giveaway),
|
||||
GiveawayWinners(GiveawayWinners),
|
||||
Video(Video),
|
||||
VideoNote(VideoNote),
|
||||
Voice(Voice),
|
||||
Invoice(Invoice),
|
||||
}
|
70
crates/teloxide-core/src/types/giveaway.rs
Normal file
70
crates/teloxide-core/src/types/giveaway.rs
Normal file
|
@ -0,0 +1,70 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Chat, CountryCode};
|
||||
|
||||
/// This object represents a message about a scheduled giveaway.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Giveaway {
|
||||
/// The list of chats which the user must join to participate in the
|
||||
/// giveaway.
|
||||
pub chats: Vec<Chat>,
|
||||
|
||||
/// Point in time (Unix timestamp) when winners of the giveaway will be
|
||||
/// selected
|
||||
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
pub winners_selection_date: DateTime<Utc>,
|
||||
|
||||
/// The number of users which are supposed to be selected as winners of the
|
||||
/// giveaway
|
||||
pub winner_count: u32,
|
||||
|
||||
/// `true`, if only users who join the chats after the giveaway started
|
||||
/// should be eligible to win
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub only_new_members: bool,
|
||||
|
||||
/// `true`, if the list of giveaway winners will be visible to everyone
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub has_public_winners: bool,
|
||||
|
||||
/// Description of additional giveaway prize
|
||||
pub prize_description: Option<String>,
|
||||
|
||||
/// A list of two-letter [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country codes indicating the
|
||||
/// countries from which eligible users for the giveaway must come. If
|
||||
/// empty, then all users can participate in the giveaway. Users with a
|
||||
/// phone number that was bought on Fragment can always participate in
|
||||
/// giveaways.
|
||||
pub country_codes: Option<Vec<CountryCode>>,
|
||||
|
||||
/// The number of months the Telegram Premium subscription won from the
|
||||
/// giveaway will be active for
|
||||
pub premium_subscription_month_count: Option<u8>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let data = r#"
|
||||
{
|
||||
"chats": [
|
||||
{
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
}
|
||||
],
|
||||
"winners_selection_date": 1721162701,
|
||||
"winner_count": 1,
|
||||
"has_public_winners": true,
|
||||
"premium_subscription_month_count": 6
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<Giveaway>(data).unwrap();
|
||||
}
|
||||
}
|
61
crates/teloxide-core/src/types/giveaway_completed.rs
Normal file
61
crates/teloxide-core/src/types/giveaway_completed.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::Message;
|
||||
|
||||
/// This object represents a service message about the completion of a giveaway
|
||||
/// without public winners.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct GiveawayCompleted {
|
||||
/// Number of winners in the giveaway
|
||||
pub winner_count: u32,
|
||||
|
||||
/// Number of undistributed prizes
|
||||
pub unclaimed_prize_count: Option<u32>,
|
||||
|
||||
/// Message with the giveaway that was completed, if it wasn't deleted
|
||||
pub giveaway_message: Option<Box<Message>>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let data = r#"
|
||||
{
|
||||
"winner_count": 0,
|
||||
"unclaimed_prize_count": 1,
|
||||
"giveaway_message": {
|
||||
"message_id": 24,
|
||||
"sender_chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"date": 1721161230,
|
||||
"giveaway": {
|
||||
"chats": [
|
||||
{
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
}
|
||||
],
|
||||
"winners_selection_date": 1721162701,
|
||||
"winner_count": 1,
|
||||
"has_public_winners": true,
|
||||
"premium_subscription_month_count": 6
|
||||
}
|
||||
}
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<GiveawayCompleted>(data).unwrap();
|
||||
}
|
||||
}
|
18
crates/teloxide-core/src/types/giveaway_created.rs
Normal file
18
crates/teloxide-core/src/types/giveaway_created.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// This object represents a service message about the creation of a scheduled
|
||||
/// giveaway. Currently holds no information.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub struct GiveawayCreated {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let data = r#"{}"#;
|
||||
serde_json::from_str::<GiveawayCreated>(data).unwrap();
|
||||
}
|
||||
}
|
83
crates/teloxide-core/src/types/giveaway_winners.rs
Normal file
83
crates/teloxide-core/src/types/giveaway_winners.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Chat, MessageId, User};
|
||||
|
||||
/// This object represents a message about the completion of a giveaway with
|
||||
/// public winners.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct GiveawayWinners {
|
||||
/// The chat that created the giveaway
|
||||
pub chat: Chat,
|
||||
|
||||
/// Identifier of the messsage with the giveaway in the chat
|
||||
#[serde(flatten, with = "crate::types::prefix_giveaway_message_id")]
|
||||
pub giveaway_message_id: MessageId,
|
||||
|
||||
/// Point in time (Unix timestamp) when winners of the giveaway were
|
||||
/// selected
|
||||
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
pub winners_selection_date: DateTime<Utc>,
|
||||
|
||||
/// Total number of winners in the giveaway
|
||||
pub winner_count: u32,
|
||||
|
||||
/// List of up to 100 winners of the giveaway
|
||||
pub winners: Vec<User>,
|
||||
|
||||
/// The number of other chats the user had to join in order to be eligible
|
||||
/// for the giveaway
|
||||
pub additional_chat_count: Option<u16>,
|
||||
|
||||
/// The number of months the Telegram Premium subscription won from the
|
||||
/// giveaway will be active for
|
||||
pub premium_subscription_month_count: Option<u8>,
|
||||
|
||||
/// Number of undistributed prizes
|
||||
pub unclaimed_prize_count: Option<u32>,
|
||||
|
||||
/// `true`, if only users who had joined the chats after the giveaway
|
||||
/// started were eligible to win
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub only_new_members: bool,
|
||||
|
||||
/// `true`, if the giveaway was canceled because the payment for it was
|
||||
/// refunded
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub was_refunded: bool,
|
||||
|
||||
/// Description of additional giveaway prize
|
||||
pub prize_description: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let data = r#"
|
||||
{
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"giveaway_message_id": 27,
|
||||
"winners_selection_date": 1721162701,
|
||||
"premium_subscription_month_count": 6,
|
||||
"winner_count": 1,
|
||||
"winners": [
|
||||
{
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10"
|
||||
}
|
||||
]
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<GiveawayWinners>(data).unwrap();
|
||||
}
|
||||
}
|
14
crates/teloxide-core/src/types/inaccessible_message.rs
Normal file
14
crates/teloxide-core/src/types/inaccessible_message.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Chat, MessageId};
|
||||
|
||||
/// This object describes a message that was deleted or is otherwise
|
||||
/// inaccessible to the bot.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct InaccessibleMessage {
|
||||
/// Chat the message belonged to
|
||||
pub chat: Chat,
|
||||
/// Unique message identifier inside the chat
|
||||
#[serde(flatten)]
|
||||
pub message_id: MessageId,
|
||||
}
|
|
@ -266,7 +266,7 @@ mod tests {
|
|||
InlineQueryResultGif, InlineQueryResultLocation, InlineQueryResultMpeg4Gif,
|
||||
InlineQueryResultPhoto, InlineQueryResultVenue, InlineQueryResultVideo,
|
||||
InlineQueryResultVoice, InputMessageContent, InputMessageContentLocation,
|
||||
InputMessageContentText, Seconds,
|
||||
InputMessageContentText, LinkPreviewOptions, Seconds,
|
||||
};
|
||||
|
||||
use mime::Mime;
|
||||
|
@ -303,13 +303,19 @@ mod tests {
|
|||
input_message_content: Some(InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("message_text"),
|
||||
parse_mode: Some(ParseMode::MarkdownV2),
|
||||
disable_web_page_preview: Some(true),
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
caption_entities: None,
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"audio","id":"id","audio_file_id":"audio_file_id","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#;
|
||||
let expected_json = r#"{"type":"audio","id":"id","audio_file_id":"audio_file_id","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -351,15 +357,21 @@ mod tests {
|
|||
input_message_content: Some(InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("message_text"),
|
||||
parse_mode: Some(ParseMode::MarkdownV2),
|
||||
disable_web_page_preview: Some(true),
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
caption_entities: None,
|
||||
performer: Some(String::from("performer")),
|
||||
audio_duration: Some(Seconds::from_seconds(1)),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"audio","id":"id","audio_url":"http://audio_url/","title":"title","caption":"caption","parse_mode":"HTML","performer":"performer","audio_duration":1,"reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#;
|
||||
let expected_json = r#"{"type":"audio","id":"id","audio_url":"http://audio_url/","title":"title","caption":"caption","parse_mode":"HTML","performer":"performer","audio_duration":1,"reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -400,13 +412,19 @@ mod tests {
|
|||
input_message_content: Some(InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("message_text"),
|
||||
parse_mode: Some(ParseMode::MarkdownV2),
|
||||
disable_web_page_preview: Some(true),
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
caption_entities: None,
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"document","id":"id","title":"title","document_file_id":"document_file_id","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#;
|
||||
let expected_json = r#"{"type":"document","id":"id","title":"title","document_file_id":"document_file_id","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -453,15 +471,21 @@ mod tests {
|
|||
input_message_content: Some(InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("message_text"),
|
||||
parse_mode: Some(ParseMode::MarkdownV2),
|
||||
disable_web_page_preview: Some(true),
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
thumbnail_url: Some(reqwest::Url::parse("http://thumb_url/").unwrap()),
|
||||
thumbnail_width: Some(1),
|
||||
thumbnail_height: Some(1),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"document","id":"id","title":"title","caption":"caption","parse_mode":"HTML","document_url":"http://document_url/","mime_type":"application/pdf","description":"description","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#;
|
||||
let expected_json = r#"{"type":"document","id":"id","title":"title","caption":"caption","parse_mode":"HTML","document_url":"http://document_url/","mime_type":"application/pdf","description":"description","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -501,12 +525,18 @@ mod tests {
|
|||
input_message_content: Some(InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("message_text"),
|
||||
parse_mode: Some(ParseMode::MarkdownV2),
|
||||
disable_web_page_preview: Some(true),
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"gif","id":"id","gif_file_id":"gif_file_id","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#;
|
||||
let expected_json = r#"{"type":"gif","id":"id","gif_file_id":"gif_file_id","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -556,12 +586,18 @@ mod tests {
|
|||
input_message_content: Some(InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("message_text"),
|
||||
parse_mode: Some(ParseMode::MarkdownV2),
|
||||
disable_web_page_preview: Some(true),
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"gif","id":"id","gif_url":"http://gif_url/","gif_width":1,"gif_height":1,"gif_duration":1,"thumbnail_url":"http://thumb_url/","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#;
|
||||
let expected_json = r#"{"type":"gif","id":"id","gif_url":"http://gif_url/","gif_width":1,"gif_height":1,"gif_duration":1,"thumbnail_url":"http://thumb_url/","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -601,12 +637,18 @@ mod tests {
|
|||
input_message_content: Some(InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("message_text"),
|
||||
parse_mode: Some(ParseMode::MarkdownV2),
|
||||
disable_web_page_preview: Some(true),
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"mpeg4_gif","id":"id","mpeg4_file_id":"mpeg4_file_id","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#;
|
||||
let expected_json = r#"{"type":"mpeg4_gif","id":"id","mpeg4_file_id":"mpeg4_file_id","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -656,12 +698,18 @@ mod tests {
|
|||
input_message_content: Some(InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("message_text"),
|
||||
parse_mode: Some(ParseMode::MarkdownV2),
|
||||
disable_web_page_preview: Some(true),
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"mpeg4_gif","id":"id","mpeg4_url":"http://mpeg4_url/","mpeg4_width":1,"mpeg4_height":1,"mpeg4_duration":1,"thumbnail_url":"http://thumb_url/","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#;
|
||||
let expected_json = r#"{"type":"mpeg4_gif","id":"id","mpeg4_url":"http://mpeg4_url/","mpeg4_width":1,"mpeg4_height":1,"mpeg4_duration":1,"thumbnail_url":"http://thumb_url/","title":"title","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -703,12 +751,18 @@ mod tests {
|
|||
input_message_content: Some(InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("message_text"),
|
||||
parse_mode: Some(ParseMode::MarkdownV2),
|
||||
disable_web_page_preview: Some(true),
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"photo","id":"id","photo_file_id":"photo_file_id","title":"title","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#;
|
||||
let expected_json = r#"{"type":"photo","id":"id","photo_file_id":"photo_file_id","title":"title","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -756,12 +810,18 @@ mod tests {
|
|||
input_message_content: Some(InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("message_text"),
|
||||
parse_mode: Some(ParseMode::MarkdownV2),
|
||||
disable_web_page_preview: Some(true),
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"photo","id":"id","photo_url":"http://photo_url/","thumbnail_url":"http://thumb_url/","photo_width":1,"photo_height":1,"title":"title","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#;
|
||||
let expected_json = r#"{"type":"photo","id":"id","photo_url":"http://photo_url/","thumbnail_url":"http://thumb_url/","photo_width":1,"photo_height":1,"title":"title","description":"description","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -794,11 +854,17 @@ mod tests {
|
|||
message_text: String::from("message_text"),
|
||||
entities: None,
|
||||
parse_mode: Some(ParseMode::MarkdownV2),
|
||||
disable_web_page_preview: Some(true),
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"sticker","id":"id","sticker_file_id":"sticker_file_id","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#;
|
||||
let expected_json = r#"{"type":"sticker","id":"id","sticker_file_id":"sticker_file_id","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","link_preview_options":{"is_disabled":true}}}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -1028,8 +1094,14 @@ mod tests {
|
|||
input_message_content: InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("message_text"),
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
parse_mode: None,
|
||||
disable_web_page_preview: None,
|
||||
}),
|
||||
reply_markup: None,
|
||||
url: None,
|
||||
|
@ -1040,7 +1112,7 @@ mod tests {
|
|||
thumbnail_height: None,
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"article","id":"id","title":"title","input_message_content":{"message_text":"message_text"}}"#;
|
||||
let expected_json = r#"{"type":"article","id":"id","title":"title","input_message_content":{"message_text":"message_text","link_preview_options":{"is_disabled":true}}}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -1056,7 +1128,13 @@ mod tests {
|
|||
message_text: String::from("message_text"),
|
||||
entities: None,
|
||||
parse_mode: None,
|
||||
disable_web_page_preview: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
}),
|
||||
reply_markup: Some(InlineKeyboardMarkup::default()),
|
||||
url: Some(Url::parse("http://url/").unwrap()),
|
||||
|
@ -1067,7 +1145,7 @@ mod tests {
|
|||
thumbnail_height: Some(1),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"article","id":"id","title":"title","input_message_content":{"message_text":"message_text"},"reply_markup":{"inline_keyboard":[]},"url":"http://url/","hide_url":true,"description":"description","thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#;
|
||||
let expected_json = r#"{"type":"article","id":"id","title":"title","input_message_content":{"message_text":"message_text","link_preview_options":{"is_disabled":true}},"reply_markup":{"inline_keyboard":[]},"url":"http://url/","hide_url":true,"description":"description","thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -1109,14 +1187,20 @@ mod tests {
|
|||
message_text: String::from("message_text"),
|
||||
entities: None,
|
||||
parse_mode: None,
|
||||
disable_web_page_preview: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
thumbnail_url: Some(Url::parse("http://thumb_url/").unwrap()),
|
||||
thumbnail_width: Some(1),
|
||||
thumbnail_height: Some(1),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"contact","id":"id","phone_number":"phone_number","first_name":"first_name","last_name":"last_name","vcard":"vcard","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text"},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#;
|
||||
let expected_json = r#"{"type":"contact","id":"id","phone_number":"phone_number","first_name":"first_name","last_name":"last_name","vcard":"vcard","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","link_preview_options":{"is_disabled":true}},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -1195,14 +1279,20 @@ mod tests {
|
|||
message_text: String::from("message_text"),
|
||||
entities: None,
|
||||
parse_mode: None,
|
||||
disable_web_page_preview: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
thumbnail_url: Some(Url::parse("http://thumb_url/").unwrap()),
|
||||
thumbnail_width: Some(1),
|
||||
thumbnail_height: Some(1),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"location","id":"id","latitude":1.0,"longitude":1.0,"title":"title","horizontal_accuracy":1.0,"live_period":1,"heading":1,"proximity_alert_radius":1,"reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text"},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#;
|
||||
let expected_json = r#"{"type":"location","id":"id","latitude":1.0,"longitude":1.0,"title":"title","horizontal_accuracy":1.0,"live_period":1,"heading":1,"proximity_alert_radius":1,"reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","link_preview_options":{"is_disabled":true}},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
@ -1252,14 +1342,20 @@ mod tests {
|
|||
message_text: String::from("message_text"),
|
||||
entities: None,
|
||||
parse_mode: None,
|
||||
disable_web_page_preview: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
})),
|
||||
thumbnail_url: Some(Url::parse("http://thumb_url/").unwrap()),
|
||||
thumbnail_width: Some(1),
|
||||
thumbnail_height: Some(1),
|
||||
});
|
||||
|
||||
let expected_json = r#"{"type":"venue","id":"id","latitude":1.0,"longitude":1.0,"title":"title","address":"address","foursquare_id":"foursquare_id","foursquare_type":"foursquare_type","google_place_id":"google_place_id","google_place_type":"google_place_type","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text"},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#;
|
||||
let expected_json = r#"{"type":"venue","id":"id","latitude":1.0,"longitude":1.0,"title":"title","address":"address","foursquare_id":"foursquare_id","foursquare_type":"foursquare_type","google_place_id":"google_place_id","google_place_type":"google_place_type","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","link_preview_options":{"is_disabled":true}},"thumbnail_url":"http://thumb_url/","thumbnail_width":1,"thumbnail_height":1}"#;
|
||||
let actual_json = serde_json::to_string(&structure).unwrap();
|
||||
|
||||
assert_eq!(expected_json, actual_json);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use reqwest::Url;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Currency, LabeledPrice, MessageEntity, ParseMode};
|
||||
use crate::types::{Currency, LabeledPrice, LinkPreviewOptions, MessageEntity, ParseMode};
|
||||
|
||||
/// This object represents the content of a message to be sent as a result of an
|
||||
/// inline query.
|
||||
|
@ -36,8 +36,8 @@ pub struct InputMessageContentText {
|
|||
/// specified instead of `parse_mode`.
|
||||
pub entities: Option<Vec<MessageEntity>>,
|
||||
|
||||
/// Disables link previews for links in the sent message.
|
||||
pub disable_web_page_preview: Option<bool>,
|
||||
/// Link preview generation options for the message
|
||||
pub link_preview_options: Option<LinkPreviewOptions>,
|
||||
}
|
||||
|
||||
impl InputMessageContentText {
|
||||
|
@ -48,8 +48,8 @@ impl InputMessageContentText {
|
|||
Self {
|
||||
message_text: message_text.into(),
|
||||
parse_mode: None,
|
||||
disable_web_page_preview: None,
|
||||
entities: None,
|
||||
link_preview_options: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,8 +76,8 @@ impl InputMessageContentText {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn disable_web_page_preview(mut self, val: bool) -> Self {
|
||||
self.disable_web_page_preview = Some(val);
|
||||
pub fn link_preview_options(mut self, val: LinkPreviewOptions) -> Self {
|
||||
self.link_preview_options = Some(val);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -583,12 +583,19 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn text_serialize() {
|
||||
let expected_json = r#"{"message_text":"text"}"#;
|
||||
let expected_json =
|
||||
r#"{"message_text":"text","link_preview_options":{"is_disabled":true}}"#;
|
||||
let text_content = InputMessageContent::Text(InputMessageContentText {
|
||||
message_text: String::from("text"),
|
||||
parse_mode: None,
|
||||
disable_web_page_preview: None,
|
||||
entities: None,
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
});
|
||||
|
||||
let actual_json = serde_json::to_string(&text_content).unwrap();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::types::{
|
||||
KeyboardButtonPollType, KeyboardButtonRequestChat, KeyboardButtonRequestUser, True, WebAppInfo,
|
||||
KeyboardButtonPollType, KeyboardButtonRequestChat, KeyboardButtonRequestUsers, True, WebAppInfo,
|
||||
};
|
||||
|
||||
/// This object represents one button of the reply keyboard.
|
||||
|
@ -68,10 +68,10 @@ pub enum ButtonRequest {
|
|||
/// [`chat_shared`]: crate::types::MessageKind::ChatShared
|
||||
RequestChat(KeyboardButtonRequestChat),
|
||||
|
||||
/// If this variant is used, pressing the button will open a list of
|
||||
/// suitable users. Tapping on any user will send their identifier to the
|
||||
/// bot in a “user_shared” service message.
|
||||
RequestUser(KeyboardButtonRequestUser),
|
||||
/// If specified, pressing the button will open a list of suitable users.
|
||||
/// Identifiers of selected users will be sent to the bot in a
|
||||
/// “users_shared” service message. Available in private chats only.
|
||||
RequestUsers(KeyboardButtonRequestUsers),
|
||||
|
||||
/// If this variant is used, the user will be asked to create a poll and
|
||||
/// send it to the bot when the button is pressed.
|
||||
|
@ -110,10 +110,10 @@ struct RawRequest {
|
|||
chat: Option<KeyboardButtonRequestChat>,
|
||||
|
||||
/// If specified, pressing the button will open a list of suitable users.
|
||||
/// Tapping on any user will send their identifier to the bot in a
|
||||
/// “user_shared” service message. Available in private chats only.
|
||||
#[serde(rename = "request_user")]
|
||||
user: Option<KeyboardButtonRequestUser>,
|
||||
/// Identifiers of selected users will be sent to the bot in a
|
||||
/// “users_shared” service message. Available in private chats only.
|
||||
#[serde(rename = "request_users")]
|
||||
users: Option<KeyboardButtonRequestUsers>,
|
||||
|
||||
/// If specified, the user will be asked to create a poll and
|
||||
/// send it to the bot when the button is pressed. Available in private
|
||||
|
@ -134,11 +134,11 @@ impl<'de> Deserialize<'de> for ButtonRequest {
|
|||
{
|
||||
let raw = RawRequest::deserialize(deserializer)?;
|
||||
match raw {
|
||||
RawRequest { contact, location, chat, user, poll, web_app }
|
||||
RawRequest { contact, location, chat, users, poll, web_app }
|
||||
if 1 < (contact.is_some() as u8
|
||||
+ location.is_some() as u8
|
||||
+ chat.is_some() as u8
|
||||
+ user.is_some() as u8
|
||||
+ users.is_some() as u8
|
||||
+ poll.is_some() as u8
|
||||
+ web_app.is_some() as u8) =>
|
||||
{
|
||||
|
@ -150,7 +150,7 @@ impl<'de> Deserialize<'de> for ButtonRequest {
|
|||
RawRequest { contact: Some(True), .. } => Ok(Self::Contact),
|
||||
RawRequest { location: Some(True), .. } => Ok(Self::Location),
|
||||
RawRequest { chat: Some(request_chat), .. } => Ok(Self::RequestChat(request_chat)),
|
||||
RawRequest { user: Some(request_user), .. } => Ok(Self::RequestUser(request_user)),
|
||||
RawRequest { users: Some(request_users), .. } => Ok(Self::RequestUsers(request_users)),
|
||||
RawRequest { poll: Some(poll_type), .. } => Ok(Self::Poll(poll_type)),
|
||||
RawRequest { web_app: Some(web_app), .. } => Ok(Self::WebApp(web_app)),
|
||||
|
||||
|
@ -158,11 +158,11 @@ impl<'de> Deserialize<'de> for ButtonRequest {
|
|||
contact: None,
|
||||
location: None,
|
||||
chat: None,
|
||||
user: None,
|
||||
users: None,
|
||||
poll: None,
|
||||
web_app: None,
|
||||
} => Err(D::Error::custom(
|
||||
"Either one of `request_contact`, `request_chat`, `request_user`, \
|
||||
"Either one of `request_contact`, `request_chat`, `request_users`, \
|
||||
`request_location`, `request_poll` and `web_app` fields is required",
|
||||
)),
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ impl Serialize for ButtonRequest {
|
|||
contact: None,
|
||||
location: None,
|
||||
chat: None,
|
||||
user: None,
|
||||
users: None,
|
||||
poll: None,
|
||||
web_app: None,
|
||||
};
|
||||
|
@ -187,7 +187,7 @@ impl Serialize for ButtonRequest {
|
|||
Self::Contact => raw.contact = Some(True),
|
||||
Self::Location => raw.location = Some(True),
|
||||
Self::RequestChat(request_chat) => raw.chat = Some(request_chat.clone()),
|
||||
Self::RequestUser(request_user) => raw.user = Some(request_user.clone()),
|
||||
Self::RequestUsers(request_users) => raw.users = Some(request_users.clone()),
|
||||
Self::Poll(poll_type) => raw.poll = Some(poll_type.clone()),
|
||||
Self::WebApp(web_app) => raw.web_app = Some(web_app.clone()),
|
||||
};
|
||||
|
@ -198,6 +198,8 @@ impl Serialize for ButtonRequest {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::types::RequestId;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
@ -221,7 +223,10 @@ mod tests {
|
|||
fn serialize_chat_request() {
|
||||
let button = KeyboardButton {
|
||||
text: String::from(""),
|
||||
request: Some(ButtonRequest::RequestChat(KeyboardButtonRequestChat::new(0, false))),
|
||||
request: Some(ButtonRequest::RequestChat(KeyboardButtonRequestChat::new(
|
||||
RequestId(0),
|
||||
false,
|
||||
))),
|
||||
};
|
||||
let expected = r#"{"text":"","request_chat":{"request_id":0,"chat_is_channel":false}}"#;
|
||||
let actual = serde_json::to_string(&button).unwrap();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::ChatAdministratorRights;
|
||||
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
|
||||
|
@ -14,7 +14,7 @@ pub struct KeyboardButtonRequestChat {
|
|||
/// [`ChatShared`] object. Must be unique within the message.
|
||||
///
|
||||
/// [`ChatShared`]: crate::types::ChatShared
|
||||
pub request_id: i32,
|
||||
pub request_id: RequestId,
|
||||
|
||||
/// Pass `true` to request a channel chat, pass `false` to request a group
|
||||
/// or a supergroup chat.
|
||||
|
@ -57,7 +57,7 @@ pub struct KeyboardButtonRequestChat {
|
|||
|
||||
impl KeyboardButtonRequestChat {
|
||||
/// Creates a new [`KeyboardButtonRequestChat`].
|
||||
pub fn new(request_id: i32, chat_is_channel: bool) -> Self {
|
||||
pub fn new(request_id: RequestId, chat_is_channel: bool) -> Self {
|
||||
Self {
|
||||
request_id,
|
||||
chat_is_channel,
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// This object defines the criteria used to request a suitable user. The
|
||||
/// identifier of the selected user will be shared with the bot when the
|
||||
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
|
||||
/// corresponding button is pressed. More about requesting users »
|
||||
///
|
||||
/// [More about requesting users »]: https://core.telegram.org/bots/features#chat-and-user-selection
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct KeyboardButtonRequestUser {
|
||||
/// identifier of the request, which will be received back in the
|
||||
/// [`UserShared`] object. Must be unique within the message.
|
||||
pub struct KeyboardButtonRequestUsers {
|
||||
/// Identifier of the request, which will be received back in the
|
||||
/// [`UsersShared`] object. Must be unique within the message.
|
||||
///
|
||||
/// [`UserShared`]: crate::types::UserShared
|
||||
pub request_id: i32,
|
||||
/// [`UsersShared`]: crate::types::UsersShared
|
||||
pub request_id: RequestId,
|
||||
|
||||
/// Pass `true` to request a bot, pass `false` to request a regular user. If
|
||||
/// not specified, no additional restrictions are applied.
|
||||
|
@ -22,12 +26,16 @@ pub struct KeyboardButtonRequestUser {
|
|||
/// applied.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub user_is_premium: Option<bool>,
|
||||
|
||||
/// 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,
|
||||
}
|
||||
|
||||
impl KeyboardButtonRequestUser {
|
||||
/// Creates a new [`KeyboardButtonRequestUser`].
|
||||
pub fn new(request_id: i32) -> Self {
|
||||
Self { request_id, user_is_bot: None, user_is_premium: None }
|
||||
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 }
|
||||
}
|
||||
|
||||
/// Setter for `user_is_bot` field
|
||||
|
@ -41,4 +49,20 @@ impl KeyboardButtonRequestUser {
|
|||
self.user_is_premium = Some(value);
|
||||
self
|
||||
}
|
||||
|
||||
/// Setter for `max_quantity` field, the value must be in the range 1..=10
|
||||
pub fn max_quantity(mut self, value: u8) -> Self {
|
||||
assert!((1..=10).contains(&value));
|
||||
|
||||
self.max_quantity = value;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn one() -> u8 {
|
||||
1
|
||||
}
|
||||
|
||||
fn is_one(value: &u8) -> bool {
|
||||
*value == 1
|
||||
}
|
50
crates/teloxide-core/src/types/link_preview_options.rs
Normal file
50
crates/teloxide-core/src/types/link_preview_options.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Describes the options used for link preview generation.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct LinkPreviewOptions {
|
||||
/// `true`, if the link preview is disabled
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub is_disabled: bool,
|
||||
|
||||
/// URL to use for the link preview. If empty, then the first URL found in
|
||||
/// the message text will be used
|
||||
pub url: Option<String>,
|
||||
|
||||
/// `true`, if the media in the link preview is suppposed to be shrunk;
|
||||
/// ignored if the URL isn't explicitly specified or media size change isn't
|
||||
/// supported for the preview
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub prefer_small_media: bool,
|
||||
|
||||
/// `true`, if the media in the link preview is suppposed to be enlarged;
|
||||
/// ignored if the URL isn't explicitly specified or media size change isn't
|
||||
/// supported for the preview
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub prefer_large_media: bool,
|
||||
|
||||
/// `true`, if the link preview must be shown above the message text;
|
||||
/// otherwise, the link preview will be shown below the message text
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub show_above_text: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let data = r#"
|
||||
{
|
||||
"is_disabled": true,
|
||||
"url": "https://kernel.org/",
|
||||
"prefer_small_media": false,
|
||||
"prefer_large_media": true,
|
||||
"show_above_text": true
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<LinkPreviewOptions>(data).unwrap();
|
||||
}
|
||||
}
|
100
crates/teloxide-core/src/types/maybe_inaccessible_message.rs
Normal file
100
crates/teloxide-core/src/types/maybe_inaccessible_message.rs
Normal file
|
@ -0,0 +1,100 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Chat, InaccessibleMessage, Message, MessageId};
|
||||
|
||||
/// This object describes a message that can be inaccessible to the bot. It can
|
||||
/// be one of:
|
||||
/// - [Message]
|
||||
/// - [InaccessibleMessage]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum MaybeInaccessibleMessage {
|
||||
Inaccessible(InaccessibleMessage),
|
||||
Regular(Message),
|
||||
}
|
||||
|
||||
impl MaybeInaccessibleMessage {
|
||||
pub fn id(&self) -> MessageId {
|
||||
match self {
|
||||
Self::Inaccessible(i_message) => i_message.message_id,
|
||||
Self::Regular(message) => message.id,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn regular_message(&self) -> Option<&Message> {
|
||||
match self {
|
||||
Self::Regular(message) => Some(message),
|
||||
Self::Inaccessible(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn chat(&self) -> &Chat {
|
||||
match self {
|
||||
Self::Regular(message) => &message.chat,
|
||||
Self::Inaccessible(i_message) => &i_message.chat,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for MaybeInaccessibleMessage {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let message: Message = Message::deserialize(deserializer)?;
|
||||
|
||||
// Thank you, TBA 7.0 authors!
|
||||
if message.date.timestamp() == 0 {
|
||||
return Ok(MaybeInaccessibleMessage::Inaccessible(InaccessibleMessage {
|
||||
chat: message.chat,
|
||||
message_id: message.id,
|
||||
}));
|
||||
}
|
||||
Ok(MaybeInaccessibleMessage::Regular(message))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_inaccessible_message() {
|
||||
let json = r#"{
|
||||
"chat": {
|
||||
"id": 42,
|
||||
"first_name": "Вадим Игоревич",
|
||||
"last_name": "Сырцев",
|
||||
"username": "syrtcevvi",
|
||||
"type": "private"
|
||||
},
|
||||
"message_id": 4,
|
||||
"date": 0
|
||||
}"#;
|
||||
|
||||
let inaccessible_message = serde_json::from_str::<MaybeInaccessibleMessage>(json);
|
||||
assert!(inaccessible_message.is_ok());
|
||||
assert!(matches!(inaccessible_message.unwrap(), MaybeInaccessibleMessage::Inaccessible(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_regular_message() {
|
||||
let json = r#"{
|
||||
"chat": {
|
||||
"id": 42,
|
||||
"first_name": "Вадим Игоревич",
|
||||
"last_name": "Сырцев",
|
||||
"username": "syrtcevvi",
|
||||
"type": "private"
|
||||
},
|
||||
"message_id": 4,
|
||||
"date": 1
|
||||
}"#;
|
||||
|
||||
let regular_message = serde_json::from_str::<MaybeInaccessibleMessage>(json);
|
||||
assert!(regular_message.is_ok());
|
||||
assert!(matches!(regular_message.unwrap(), MaybeInaccessibleMessage::Regular(_)));
|
||||
}
|
||||
}
|
|
@ -6,12 +6,14 @@ use url::Url;
|
|||
|
||||
use crate::types::{
|
||||
Animation, Audio, BareChatId, Chat, ChatId, ChatShared, Contact, Dice, Document,
|
||||
ForumTopicClosed, ForumTopicCreated, ForumTopicEdited, ForumTopicReopened, Game,
|
||||
GeneralForumTopicHidden, GeneralForumTopicUnhidden, InlineKeyboardMarkup, Invoice, Location,
|
||||
MessageAutoDeleteTimerChanged, MessageEntity, MessageEntityRef, MessageId, PassportData,
|
||||
PhotoSize, Poll, ProximityAlertTriggered, Sticker, Story, SuccessfulPayment, ThreadId, True,
|
||||
User, UserShared, Venue, Video, VideoChatEnded, VideoChatParticipantsInvited,
|
||||
VideoChatScheduled, VideoChatStarted, VideoNote, Voice, WebAppData, WriteAccessAllowed,
|
||||
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, UsersShared, Venue, Video,
|
||||
VideoChatEnded, VideoChatParticipantsInvited, VideoChatScheduled, VideoChatStarted, VideoNote,
|
||||
Voice, WebAppData, WriteAccessAllowed,
|
||||
};
|
||||
|
||||
/// This object represents a message.
|
||||
|
@ -29,6 +31,15 @@ pub struct Message {
|
|||
#[serde(rename = "message_thread_id")]
|
||||
pub thread_id: Option<ThreadId>,
|
||||
|
||||
/// Sender, empty for messages sent to channels.
|
||||
pub from: Option<User>,
|
||||
|
||||
/// Sender of the message, sent on behalf of a chat. The channel itself for
|
||||
/// channel messages. The supergroup itself for messages from anonymous
|
||||
/// group administrators. The linked channel for messages automatically
|
||||
/// forwarded to the discussion group
|
||||
pub sender_chat: Option<Chat>,
|
||||
|
||||
/// Date the message was sent in Unix time.
|
||||
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
pub date: DateTime<Utc>,
|
||||
|
@ -36,6 +47,10 @@ pub struct Message {
|
|||
/// Conversation the message belongs to.
|
||||
pub chat: Chat,
|
||||
|
||||
/// `true`, if the message is sent to a forum topic.
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub is_topic_message: bool,
|
||||
|
||||
/// Bot through which the message was sent.
|
||||
pub via_bot: Option<User>,
|
||||
|
||||
|
@ -61,7 +76,7 @@ pub enum MessageKind {
|
|||
MessageAutoDeleteTimerChanged(MessageMessageAutoDeleteTimerChanged),
|
||||
Pinned(MessagePinned),
|
||||
ChatShared(MessageChatShared),
|
||||
UserShared(MessageUserShared),
|
||||
UsersShared(MessageUsersShared),
|
||||
Invoice(MessageInvoice),
|
||||
SuccessfulPayment(MessageSuccessfulPayment),
|
||||
ConnectedWebsite(MessageConnectedWebsite),
|
||||
|
@ -75,6 +90,10 @@ pub enum MessageKind {
|
|||
ForumTopicReopened(MessageForumTopicReopened),
|
||||
GeneralForumTopicHidden(MessageGeneralForumTopicHidden),
|
||||
GeneralForumTopicUnhidden(MessageGeneralForumTopicUnhidden),
|
||||
Giveaway(MessageGiveaway),
|
||||
GiveawayCompleted(MessageGiveawayCompleted),
|
||||
GiveawayCreated(MessageGiveawayCreated),
|
||||
GiveawayWinners(MessageGiveawayWinners),
|
||||
VideoChatScheduled(MessageVideoChatScheduled),
|
||||
VideoChatStarted(MessageVideoChatStarted),
|
||||
VideoChatEnded(MessageVideoChatEnded),
|
||||
|
@ -88,28 +107,26 @@ pub enum MessageKind {
|
|||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MessageCommon {
|
||||
/// Sender, empty for messages sent to channels.
|
||||
pub from: Option<User>,
|
||||
|
||||
/// Sender of the message, sent on behalf of a chat. The channel itself for
|
||||
/// channel messages. The supergroup itself for messages from anonymous
|
||||
/// group administrators. The linked channel for messages automatically
|
||||
/// forwarded to the discussion group
|
||||
pub sender_chat: Option<Chat>,
|
||||
|
||||
/// Signature of the post author for messages in channels, or the custom
|
||||
/// title of an anonymous group administrator.
|
||||
pub author_signature: Option<String>,
|
||||
|
||||
/// For forwarded messages, information about the forward
|
||||
#[serde(flatten)]
|
||||
pub forward: Option<Forward>,
|
||||
/// Information about the original message for forwarded messages
|
||||
pub forward_origin: Option<MessageOrigin>,
|
||||
|
||||
/// For replies, the original message. Note that the Message object in this
|
||||
/// field will not contain further `reply_to_message` fields even if it
|
||||
/// itself is a reply.
|
||||
pub reply_to_message: Option<Box<Message>>,
|
||||
|
||||
/// Information about the message that is being replied to, which may come
|
||||
/// from another chat or forum topic
|
||||
pub external_reply: Option<ExternalReplyInfo>,
|
||||
|
||||
/// For replies that quote part of the original message, the quoted part of
|
||||
/// the message
|
||||
pub quote: Option<TextQuote>,
|
||||
|
||||
/// Date the message was last edited in Unix time.
|
||||
#[serde(default, with = "crate::types::serde_opt_date_from_unix_timestamp")]
|
||||
pub edit_date: Option<DateTime<Utc>>,
|
||||
|
@ -121,12 +138,6 @@ pub struct MessageCommon {
|
|||
/// represented as ordinary `url` buttons.
|
||||
pub reply_markup: Option<InlineKeyboardMarkup>,
|
||||
|
||||
/// `true`, if the message is sent to a forum topic.
|
||||
// FIXME: `is_topic_message` is included even in service messages, like ForumTopicCreated.
|
||||
// more this to `Message`
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub is_topic_message: bool,
|
||||
|
||||
/// `true`, if the message is a channel post that was automatically
|
||||
/// forwarded to the connected discussion group.
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
|
@ -246,7 +257,7 @@ pub struct MessagePinned {
|
|||
/// field will not contain further `reply_to_message` fields even if it
|
||||
/// is itself a reply.
|
||||
#[serde(rename = "pinned_message")]
|
||||
pub pinned: Box<Message>,
|
||||
pub pinned: Box<MaybeInaccessibleMessage>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
|
@ -256,9 +267,9 @@ pub struct MessageChatShared {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MessageUserShared {
|
||||
/// A chat was shared with the bot.
|
||||
pub user_shared: UserShared,
|
||||
pub struct MessageUsersShared {
|
||||
/// Users were shared with the bot
|
||||
pub users_shared: UsersShared,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
|
@ -299,52 +310,6 @@ pub struct MessagePassportData {
|
|||
pub passport_data: PassportData,
|
||||
}
|
||||
|
||||
/// Information about forwarded message.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Forward {
|
||||
/// Date the original message was sent in Unix time.
|
||||
#[serde(rename = "forward_date")]
|
||||
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
pub date: DateTime<Utc>,
|
||||
|
||||
/// The entity that sent the original message.
|
||||
#[serde(flatten)]
|
||||
pub from: ForwardedFrom,
|
||||
|
||||
/// For messages forwarded from channels, signature of the post author if
|
||||
/// present. For messages forwarded from anonymous admins, authors title, if
|
||||
/// present.
|
||||
#[serde(rename = "forward_signature")]
|
||||
pub signature: Option<String>,
|
||||
|
||||
/// For messages forwarded from channels, identifier of the original message
|
||||
/// in the channel
|
||||
#[serde(
|
||||
rename = "forward_from_message_id",
|
||||
with = "crate::types::option_msg_id_as_int",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub message_id: Option<MessageId>,
|
||||
}
|
||||
|
||||
/// The entity that sent the original message that later was forwarded.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ForwardedFrom {
|
||||
/// The message was sent by a user.
|
||||
#[serde(rename = "forward_from")]
|
||||
User(User),
|
||||
/// The message was sent by an anonymous user on behalf of a group or
|
||||
/// channel.
|
||||
#[serde(rename = "forward_from_chat")]
|
||||
Chat(Chat),
|
||||
/// The message was sent by a user who disallow adding a link to their
|
||||
/// account in forwarded messages.
|
||||
#[serde(rename = "forward_sender_name")]
|
||||
SenderName(String),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum MediaKind {
|
||||
|
@ -513,6 +478,10 @@ pub struct MediaText {
|
|||
/// commands, etc. that appear in the text.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub entities: Vec<MessageEntity>,
|
||||
|
||||
/// Options used for link preview generation for the message, if it is a
|
||||
/// text message and link preview options were changed
|
||||
pub link_preview_options: Option<LinkPreviewOptions>,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
|
@ -634,6 +603,46 @@ pub struct MessageGeneralForumTopicUnhidden {
|
|||
pub general_forum_topic_unhidden: GeneralForumTopicUnhidden,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MessageGiveaway {
|
||||
/// Message is giveaway, information about a scheduled giveaway. [More about
|
||||
/// giveaways »]
|
||||
///
|
||||
/// [More about giveaways »]: https://core.telegram.org/api#giveaways-amp-gifts
|
||||
pub giveaway: Giveaway,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MessageGiveawayCompleted {
|
||||
/// Service message: a 'Giveaway' completed. [More about giveaways
|
||||
/// »]
|
||||
///
|
||||
/// [More about giveaways »]: https://core.telegram.org/api#giveaways-amp-gifts
|
||||
pub giveaway_completed: GiveawayCompleted,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MessageGiveawayCreated {
|
||||
/// Service message: a scheduled 'Giveaway' created. [More about giveaways
|
||||
/// »]
|
||||
///
|
||||
/// [More about giveaways »]: https://core.telegram.org/api#giveaways-amp-gifts
|
||||
pub giveaway_created: GiveawayCreated,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MessageGiveawayWinners {
|
||||
/// Message is giveaway winners, information about the completion of a
|
||||
/// giveaway with public winners. [More about giveaways »]
|
||||
///
|
||||
/// [More about giveaways »]: https://core.telegram.org/api#giveaways-amp-gifts
|
||||
pub giveaway_winners: GiveawayWinners,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MessageVideoChatScheduled {
|
||||
|
@ -674,22 +683,23 @@ mod getters {
|
|||
use std::ops::Deref;
|
||||
|
||||
use crate::types::{
|
||||
self, message::MessageKind::*, Chat, ChatId, ChatMigration, Forward, ForwardedFrom,
|
||||
MediaAnimation, MediaAudio, MediaContact, MediaDocument, MediaGame, MediaKind,
|
||||
MediaLocation, MediaPhoto, MediaPoll, MediaSticker, MediaStory, MediaText, MediaVenue,
|
||||
MediaVideo, MediaVideoNote, MediaVoice, Message, MessageChannelChatCreated,
|
||||
MessageChatShared, MessageCommon, MessageConnectedWebsite, MessageDeleteChatPhoto,
|
||||
MessageDice, MessageEntity, MessageGroupChatCreated, MessageId, MessageInvoice,
|
||||
MessageLeftChatMember, MessageNewChatMembers, MessageNewChatPhoto, MessageNewChatTitle,
|
||||
MessagePassportData, MessagePinned, MessageProximityAlertTriggered,
|
||||
MessageSuccessfulPayment, MessageSupergroupChatCreated, MessageUserShared,
|
||||
MessageVideoChatParticipantsInvited, PhotoSize, User,
|
||||
self, message::MessageKind::*, Chat, ChatId, ChatMigration, LinkPreviewOptions,
|
||||
MaybeInaccessibleMessage, MediaAnimation, MediaAudio, MediaContact, MediaDocument,
|
||||
MediaGame, MediaKind, MediaLocation, MediaPhoto, MediaPoll, MediaSticker, MediaStory,
|
||||
MediaText, MediaVenue, MediaVideo, MediaVideoNote, MediaVoice, Message,
|
||||
MessageChannelChatCreated, MessageChatShared, MessageCommon, MessageConnectedWebsite,
|
||||
MessageDeleteChatPhoto, MessageDice, MessageEntity, MessageGroupChatCreated, MessageId,
|
||||
MessageInvoice, MessageLeftChatMember, MessageNewChatMembers, MessageNewChatPhoto,
|
||||
MessageNewChatTitle, MessageOrigin, MessagePassportData, MessagePinned,
|
||||
MessageProximityAlertTriggered, MessageSuccessfulPayment, MessageSupergroupChatCreated,
|
||||
MessageUsersShared, MessageVideoChatParticipantsInvited, PhotoSize, TextQuote, User,
|
||||
};
|
||||
|
||||
use super::{
|
||||
MessageForumTopicClosed, MessageForumTopicCreated, MessageForumTopicEdited,
|
||||
MessageForumTopicReopened, MessageGeneralForumTopicHidden,
|
||||
MessageGeneralForumTopicUnhidden, MessageMessageAutoDeleteTimerChanged,
|
||||
MessageGeneralForumTopicUnhidden, MessageGiveaway, MessageGiveawayCompleted,
|
||||
MessageGiveawayCreated, MessageGiveawayWinners, MessageMessageAutoDeleteTimerChanged,
|
||||
MessageVideoChatEnded, MessageVideoChatScheduled, MessageVideoChatStarted,
|
||||
MessageWebAppData, MessageWriteAccessAllowed,
|
||||
};
|
||||
|
@ -700,12 +710,10 @@ mod getters {
|
|||
/// [telegram docs]: https://core.telegram.org/bots/api#message
|
||||
impl Message {
|
||||
/// Returns the user who sent the message.
|
||||
#[deprecated(since = "0.13.0", note = "use `.from` field instead")]
|
||||
#[must_use]
|
||||
pub fn from(&self) -> Option<&User> {
|
||||
match &self.kind {
|
||||
Common(MessageCommon { from, .. }) => from.as_ref(),
|
||||
_ => None,
|
||||
}
|
||||
self.from.as_ref()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
@ -716,61 +724,78 @@ mod getters {
|
|||
}
|
||||
}
|
||||
|
||||
#[deprecated(since = "0.13.0", note = "use `.sender_chat` field instead")]
|
||||
#[must_use]
|
||||
pub fn sender_chat(&self) -> Option<&Chat> {
|
||||
self.sender_chat.as_ref()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn forward_origin(&self) -> Option<&MessageOrigin> {
|
||||
match &self.kind {
|
||||
Common(MessageCommon { sender_chat, .. }) => sender_chat.as_ref(),
|
||||
Common(MessageCommon { forward_origin, .. }) => forward_origin.as_ref(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn forward(&self) -> Option<&Forward> {
|
||||
self.common().and_then(|m| m.forward.as_ref())
|
||||
pub fn quote(&self) -> Option<&TextQuote> {
|
||||
match &self.kind {
|
||||
Common(MessageCommon { quote, .. }) => quote.as_ref(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn forward_date(&self) -> Option<DateTime<Utc>> {
|
||||
self.forward().map(|f| f.date)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn forward_from(&self) -> Option<&ForwardedFrom> {
|
||||
self.forward().map(|f| &f.from)
|
||||
self.forward_origin().map(|f| f.date())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn forward_from_user(&self) -> Option<&User> {
|
||||
self.forward_from().and_then(|from| match from {
|
||||
ForwardedFrom::User(user) => Some(user),
|
||||
self.forward_origin().and_then(|origin| match origin {
|
||||
MessageOrigin::User { sender_user, .. } => Some(sender_user),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn forward_from_chat(&self) -> Option<&Chat> {
|
||||
self.forward_from().and_then(|from| match from {
|
||||
ForwardedFrom::Chat(chat) => Some(chat),
|
||||
self.forward_origin().and_then(|origin| match origin {
|
||||
MessageOrigin::Chat { sender_chat, .. } => Some(sender_chat),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn forward_from_sender_name(&self) -> Option<&str> {
|
||||
self.forward_from().and_then(|from| match from {
|
||||
ForwardedFrom::SenderName(sender_name) => Some(&**sender_name),
|
||||
self.forward_origin().and_then(|origin| match origin {
|
||||
MessageOrigin::HiddenUser { sender_user_name, .. } => {
|
||||
Some(sender_user_name.as_str())
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn forward_from_message_id(&self) -> Option<MessageId> {
|
||||
self.forward().and_then(|f| f.message_id)
|
||||
self.forward_origin().and_then(|origin| match origin {
|
||||
MessageOrigin::Channel { message_id, .. } => Some(*message_id),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn forward_signature(&self) -> Option<&str> {
|
||||
self.forward().and_then(|f| f.signature.as_deref())
|
||||
pub fn forward_author_signature(&self) -> Option<&str> {
|
||||
self.forward_origin().and_then(|origin| match origin {
|
||||
MessageOrigin::Chat { author_signature, .. } => {
|
||||
author_signature.as_ref().map(|a| a.as_str())
|
||||
}
|
||||
MessageOrigin::Channel { author_signature, .. } => {
|
||||
author_signature.as_ref().map(|a| a.as_str())
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
@ -843,6 +868,17 @@ mod getters {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn link_preview_options(&self) -> Option<&LinkPreviewOptions> {
|
||||
match &self.kind {
|
||||
Common(MessageCommon {
|
||||
media_kind: MediaKind::Text(MediaText { link_preview_options, .. }),
|
||||
..
|
||||
}) => link_preview_options.as_ref(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns message entities that represent text formatting.
|
||||
///
|
||||
/// **Note:** you probably want to use [`parse_caption_entities`]
|
||||
|
@ -1244,7 +1280,7 @@ mod getters {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn pinned_message(&self) -> Option<&Message> {
|
||||
pub fn pinned_message(&self) -> Option<&MaybeInaccessibleMessage> {
|
||||
match &self.kind {
|
||||
Pinned(MessagePinned { pinned }) => Some(pinned),
|
||||
_ => None,
|
||||
|
@ -1306,9 +1342,9 @@ mod getters {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn shared_user(&self) -> Option<&types::UserShared> {
|
||||
pub fn shared_users(&self) -> Option<&types::UsersShared> {
|
||||
match &self.kind {
|
||||
UserShared(MessageUserShared { user_shared }) => Some(user_shared),
|
||||
UsersShared(MessageUsersShared { users_shared }) => Some(users_shared),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -1391,6 +1427,44 @@ mod getters {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn giveaway(&self) -> Option<&types::Giveaway> {
|
||||
match &self.kind {
|
||||
Giveaway(MessageGiveaway { giveaway }) => Some(giveaway),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn giveaway_completed(&self) -> Option<&types::GiveawayCompleted> {
|
||||
match &self.kind {
|
||||
GiveawayCompleted(MessageGiveawayCompleted { giveaway_completed }) => {
|
||||
Some(giveaway_completed)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn giveaway_created(&self) -> Option<&types::GiveawayCreated> {
|
||||
match &self.kind {
|
||||
GiveawayCreated(MessageGiveawayCreated { giveaway_created }) => {
|
||||
Some(giveaway_created)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn giveaway_winners(&self) -> Option<&types::GiveawayWinners> {
|
||||
match &self.kind {
|
||||
GiveawayWinners(MessageGiveawayWinners { giveaway_winners }) => {
|
||||
Some(giveaway_winners)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn video_chat_scheduled(&self) -> Option<&types::VideoChatScheduled> {
|
||||
match &self.kind {
|
||||
|
@ -1670,8 +1744,8 @@ impl Message {
|
|||
|
||||
// Lets just hope we didn't forget something here...
|
||||
|
||||
self.from()
|
||||
.into_iter()
|
||||
self.from
|
||||
.iter()
|
||||
.chain(self.via_bot.as_ref())
|
||||
.chain(self.chat.mentioned_users_rec())
|
||||
.chain(flatten(self.reply_to_message().map(Self::mentioned_users_rec)))
|
||||
|
@ -1697,6 +1771,7 @@ impl Message {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::DateTime;
|
||||
use cool_asserts::assert_matches;
|
||||
use serde_json::from_str;
|
||||
|
||||
|
@ -1767,7 +1842,10 @@ mod tests {
|
|||
Message {
|
||||
id: MessageId(198283),
|
||||
thread_id: None,
|
||||
from: None,
|
||||
sender_chat: None,
|
||||
date: chrono::DateTime::from_timestamp(1567927221, 0).unwrap(),
|
||||
is_topic_message: false,
|
||||
chat: Chat {
|
||||
id: ChatId(250918540),
|
||||
kind: ChatKind::Private(ChatPrivate {
|
||||
|
@ -1775,19 +1853,22 @@ mod tests {
|
|||
last_name: Some("Власов".to_string()),
|
||||
username: Some("aka_dude".to_string()),
|
||||
bio: None,
|
||||
emoji_status_custom_emoji_id: None,
|
||||
has_private_forwards: None,
|
||||
has_restricted_voice_and_video_messages: None
|
||||
}),
|
||||
photo: None,
|
||||
available_reactions: None,
|
||||
has_aggressive_anti_spam_enabled: false,
|
||||
pinned_message: None,
|
||||
message_auto_delete_time: None,
|
||||
has_hidden_members: false,
|
||||
chat_full_info: ChatFullInfo { emoji_status_expiration_date: None }
|
||||
chat_full_info: ChatFullInfo::default()
|
||||
},
|
||||
kind: MessageKind::ChatShared(MessageChatShared {
|
||||
chat_shared: ChatShared { request_id: 348349, chat_id: ChatId(384939) }
|
||||
chat_shared: ChatShared {
|
||||
request_id: RequestId(348349),
|
||||
chat_id: ChatId(384939)
|
||||
}
|
||||
}),
|
||||
via_bot: None
|
||||
}
|
||||
|
@ -1975,14 +2056,17 @@ mod tests {
|
|||
"title": "a",
|
||||
"type": "supergroup"
|
||||
},
|
||||
"date": 1640359576,
|
||||
"forward_from_chat": {
|
||||
"id": -1001160242915,
|
||||
"title": "a",
|
||||
"type": "supergroup"
|
||||
"forward_origin": {
|
||||
"type": "chat",
|
||||
"date": 1640359544,
|
||||
"sender_chat": {
|
||||
"id": -1001160242915,
|
||||
"title": "a",
|
||||
"type": "supergroup"
|
||||
},
|
||||
"author_signature": "TITLE"
|
||||
},
|
||||
"forward_signature": "TITLE",
|
||||
"forward_date": 1640359544,
|
||||
"date": 1640359576,
|
||||
"text": "text"
|
||||
}"#;
|
||||
|
||||
|
@ -2014,18 +2098,19 @@ mod tests {
|
|||
}),
|
||||
message_auto_delete_time: None,
|
||||
photo: None,
|
||||
available_reactions: None,
|
||||
pinned_message: None,
|
||||
has_hidden_members: false,
|
||||
has_aggressive_anti_spam_enabled: false,
|
||||
chat_full_info: ChatFullInfo { emoji_status_expiration_date: None },
|
||||
chat_full_info: ChatFullInfo::default(),
|
||||
};
|
||||
|
||||
assert!(message.from().unwrap().is_anonymous());
|
||||
assert!(message.from.as_ref().unwrap().is_anonymous());
|
||||
assert_eq!(message.author_signature().unwrap(), "TITLE2");
|
||||
assert_eq!(message.sender_chat().unwrap(), &group);
|
||||
assert_eq!(message.sender_chat.as_ref().unwrap(), &group);
|
||||
assert_eq!(&message.chat, &group);
|
||||
assert_eq!(message.forward_from_chat().unwrap(), &group);
|
||||
assert_eq!(message.forward_signature().unwrap(), "TITLE");
|
||||
assert_eq!(message.forward_author_signature().unwrap(), "TITLE");
|
||||
assert!(message.forward_date().is_some());
|
||||
assert_eq!(message.text().unwrap(), "text");
|
||||
}
|
||||
|
@ -2045,7 +2130,7 @@ mod tests {
|
|||
assert_eq!(message.migrate_to_chat_id(), Some(&new));
|
||||
|
||||
// The user who initialized the migration
|
||||
assert!(message.from().is_some());
|
||||
assert!(message.from.is_some());
|
||||
|
||||
// Migration from a common group
|
||||
let json = r#"{"chat":{"id":-1001555296434,"title":"test","type":"supergroup"},"date":1629404938,"from":{"first_name":"Group","id":1087968824,"is_bot":true,"username":"GroupAnonymousBot"},"message_id":1,"migrate_from_chat_id":-599075523,"sender_chat":{"id":-1001555296434,"title":"test","type":"supergroup"}}"#;
|
||||
|
@ -2056,10 +2141,10 @@ mod tests {
|
|||
assert_eq!(message.migrate_from_chat_id(), Some(&old));
|
||||
|
||||
// Anonymous bot
|
||||
assert!(message.from().is_some());
|
||||
assert!(message.from.is_some());
|
||||
|
||||
// The chat to which the group migrated
|
||||
assert!(message.sender_chat().is_some());
|
||||
assert!(message.sender_chat.is_some());
|
||||
}
|
||||
|
||||
/// Regression test for <https://github.com/teloxide/teloxide/issues/481>
|
||||
|
@ -2215,7 +2300,9 @@ mod tests {
|
|||
"message_thread_id":4
|
||||
}"#;
|
||||
|
||||
let _: Message = serde_json::from_str(json).unwrap();
|
||||
let message: Message = serde_json::from_str(json).unwrap();
|
||||
// https://github.com/teloxide/teloxide/issues/945
|
||||
assert!(message.from.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2257,4 +2344,335 @@ mod tests {
|
|||
|
||||
let _: Message = serde_json::from_str(json).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn giveaway() {
|
||||
let json = r#"{
|
||||
"message_id": 27,
|
||||
"sender_chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"date": 1721162577,
|
||||
"giveaway": {
|
||||
"chats": [
|
||||
{
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
}
|
||||
],
|
||||
"winners_selection_date": 1721162701,
|
||||
"winner_count": 1,
|
||||
"has_public_winners": true,
|
||||
"premium_subscription_month_count": 6
|
||||
}
|
||||
}"#;
|
||||
let message: Message = from_str(json).unwrap();
|
||||
assert_eq!(
|
||||
message.giveaway().unwrap(),
|
||||
&Giveaway {
|
||||
chats: vec![Chat {
|
||||
id: ChatId(-1002236736395),
|
||||
kind: ChatKind::Public(ChatPublic {
|
||||
title: Some("Test".to_owned()),
|
||||
kind: PublicChatKind::Channel(PublicChatChannel {
|
||||
username: None,
|
||||
linked_chat_id: 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()
|
||||
}],
|
||||
winners_selection_date: DateTime::from_timestamp(1721162701, 0).unwrap(),
|
||||
winner_count: 1,
|
||||
only_new_members: false,
|
||||
has_public_winners: true,
|
||||
prize_description: None,
|
||||
country_codes: None,
|
||||
premium_subscription_month_count: Some(6)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn giveaway_created() {
|
||||
let json = r#"{
|
||||
"message_id": 27,
|
||||
"sender_chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"date": 1721162577,
|
||||
"giveaway_created": {}
|
||||
}"#;
|
||||
let message: Message = from_str(json).unwrap();
|
||||
assert_eq!(message.giveaway_created().unwrap(), &GiveawayCreated {})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn giveaway_completed() {
|
||||
let json = r#"{
|
||||
"message_id": 27,
|
||||
"sender_chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"date": 1721162577,
|
||||
"giveaway_completed": {
|
||||
"winner_count": 0,
|
||||
"unclaimed_prize_count": 1,
|
||||
"giveaway_message": {
|
||||
"message_id": 24,
|
||||
"sender_chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"date": 1721161230,
|
||||
"giveaway": {
|
||||
"chats": [
|
||||
{
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
}
|
||||
],
|
||||
"winners_selection_date": 1721162701,
|
||||
"winner_count": 1,
|
||||
"has_public_winners": true,
|
||||
"premium_subscription_month_count": 6
|
||||
}
|
||||
}
|
||||
}
|
||||
}"#;
|
||||
let message: Message = from_str(json).unwrap();
|
||||
assert_eq!(
|
||||
message.giveaway_completed().unwrap(),
|
||||
&GiveawayCompleted {
|
||||
winner_count: 0,
|
||||
unclaimed_prize_count: Some(1),
|
||||
giveaway_message: Some(Box::new(Message {
|
||||
id: MessageId(24),
|
||||
thread_id: None,
|
||||
from: None,
|
||||
sender_chat: Some(Chat {
|
||||
id: ChatId(-1002236736395),
|
||||
kind: ChatKind::Public(ChatPublic {
|
||||
title: Some("Test".to_owned()),
|
||||
kind: PublicChatKind::Channel(PublicChatChannel {
|
||||
linked_chat_id: None,
|
||||
username: None
|
||||
}),
|
||||
description: None,
|
||||
invite_link: None,
|
||||
has_protected_content: None
|
||||
}),
|
||||
chat_full_info: ChatFullInfo::default(),
|
||||
available_reactions: None,
|
||||
photo: None,
|
||||
has_aggressive_anti_spam_enabled: false,
|
||||
has_hidden_members: false,
|
||||
message_auto_delete_time: None,
|
||||
pinned_message: None
|
||||
}),
|
||||
is_topic_message: false,
|
||||
date: DateTime::from_timestamp(1721161230, 0).unwrap(),
|
||||
chat: Chat {
|
||||
id: ChatId(-1002236736395),
|
||||
kind: ChatKind::Public(ChatPublic {
|
||||
title: Some("Test".to_owned()),
|
||||
kind: PublicChatKind::Channel(PublicChatChannel {
|
||||
username: None,
|
||||
linked_chat_id: 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()
|
||||
},
|
||||
via_bot: None,
|
||||
kind: MessageKind::Giveaway(MessageGiveaway {
|
||||
giveaway: Giveaway {
|
||||
chats: vec![Chat {
|
||||
id: ChatId(-1002236736395),
|
||||
kind: ChatKind::Public(ChatPublic {
|
||||
title: Some("Test".to_owned()),
|
||||
kind: PublicChatKind::Channel(PublicChatChannel {
|
||||
username: None,
|
||||
linked_chat_id: 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()
|
||||
}],
|
||||
winners_selection_date: DateTime::from_timestamp(1721162701, 0)
|
||||
.unwrap(),
|
||||
winner_count: 1,
|
||||
only_new_members: false,
|
||||
has_public_winners: true,
|
||||
prize_description: None,
|
||||
country_codes: None,
|
||||
premium_subscription_month_count: Some(6)
|
||||
}
|
||||
})
|
||||
}))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn giveaway_winners() {
|
||||
let json = r#"{
|
||||
"message_id": 28,
|
||||
"sender_chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"date": 1721162702,
|
||||
"reply_to_message": {
|
||||
"message_id": 27,
|
||||
"sender_chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"date": 1721162577,
|
||||
"giveaway": {
|
||||
"chats": [
|
||||
{
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
}
|
||||
],
|
||||
"winners_selection_date": 1721162701,
|
||||
"winner_count": 1,
|
||||
"has_public_winners": true,
|
||||
"premium_subscription_month_count": 6
|
||||
}
|
||||
},
|
||||
"giveaway_winners": {
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"giveaway_message_id": 27,
|
||||
"winners_selection_date": 1721162701,
|
||||
"premium_subscription_month_count": 6,
|
||||
"winner_count": 1,
|
||||
"winners": [
|
||||
{
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}"#;
|
||||
let message: Message = from_str(json).unwrap();
|
||||
assert_eq!(
|
||||
message.giveaway_winners().expect("Failed to get GiveawayWinners from Message!"),
|
||||
&GiveawayWinners {
|
||||
chat: Chat {
|
||||
id: ChatId(-1002236736395),
|
||||
kind: ChatKind::Public(ChatPublic {
|
||||
title: Some("Test".to_owned()),
|
||||
kind: PublicChatKind::Channel(PublicChatChannel {
|
||||
username: None,
|
||||
linked_chat_id: 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()
|
||||
},
|
||||
giveaway_message_id: MessageId(27),
|
||||
winners_selection_date: DateTime::from_timestamp(1721162701, 0).unwrap(),
|
||||
winner_count: 1,
|
||||
winners: vec![User {
|
||||
id: UserId(1459074222),
|
||||
is_bot: false,
|
||||
first_name: "shadowchain".to_owned(),
|
||||
last_name: None,
|
||||
username: Some("shdwchn10".to_owned()),
|
||||
language_code: None,
|
||||
is_premium: false,
|
||||
added_to_attachment_menu: false
|
||||
}],
|
||||
additional_chat_count: None,
|
||||
premium_subscription_month_count: Some(6),
|
||||
unclaimed_prize_count: None,
|
||||
only_new_members: false,
|
||||
was_refunded: false,
|
||||
prize_description: None
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -249,6 +249,7 @@ pub enum MessageEntityKind {
|
|||
Email,
|
||||
PhoneNumber,
|
||||
Bold,
|
||||
Blockquote,
|
||||
Italic,
|
||||
Underline,
|
||||
Strikethrough,
|
||||
|
@ -285,6 +286,18 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
// https://github.com/teloxide/teloxide/issues/1062
|
||||
#[test]
|
||||
fn blockquote() {
|
||||
use serde_json::from_str;
|
||||
|
||||
assert_eq!(
|
||||
MessageEntity { kind: MessageEntityKind::Blockquote, offset: 32, length: 92 },
|
||||
from_str::<MessageEntity>(r#"{"type": "blockquote", "offset": 32, "length": 92}"#)
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre() {
|
||||
use serde_json::from_str;
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A unique message identifier.
|
||||
#[derive(Clone, Copy, Debug, derive_more::Display, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Default,
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
derive_more::Display,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize
|
||||
)]
|
||||
#[serde(from = "MessageIdRaw", into = "MessageIdRaw")]
|
||||
pub struct MessageId(pub i32);
|
||||
|
||||
|
|
58
crates/teloxide-core/src/types/message_origin.rs
Normal file
58
crates/teloxide-core/src/types/message_origin.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Chat, MessageId, User};
|
||||
|
||||
/// This object describes the origin of a message
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[serde(tag = "type")]
|
||||
pub enum MessageOrigin {
|
||||
User {
|
||||
/// Date the message was sent originally in Unix time
|
||||
#[serde(default, with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
date: DateTime<Utc>,
|
||||
/// User that sent the message originally
|
||||
sender_user: User,
|
||||
},
|
||||
HiddenUser {
|
||||
/// Date the message was sent originally in Unix time
|
||||
#[serde(default, with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
date: DateTime<Utc>,
|
||||
/// Name of the user that sent the message originally
|
||||
sender_user_name: String,
|
||||
},
|
||||
Chat {
|
||||
/// Date the message was sent originally in Unix time
|
||||
#[serde(default, with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
date: DateTime<Utc>,
|
||||
/// Chat that sent the message originally
|
||||
sender_chat: Chat,
|
||||
/// For messages originally sent by an anonymous chat administrator,
|
||||
/// original message author signature
|
||||
author_signature: Option<String>,
|
||||
},
|
||||
Channel {
|
||||
/// Date the message was sent originally in Unix time
|
||||
#[serde(default, with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
date: DateTime<Utc>,
|
||||
/// Channel chat to which the message was originally sent
|
||||
chat: Chat,
|
||||
/// Unique message identifier inside the chat
|
||||
#[serde(flatten)]
|
||||
message_id: MessageId,
|
||||
/// Signature of the original post author
|
||||
author_signature: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
impl MessageOrigin {
|
||||
pub fn date(&self) -> DateTime<Utc> {
|
||||
*match self {
|
||||
Self::User { date, .. } => date,
|
||||
Self::HiddenUser { date, .. } => date,
|
||||
Self::Chat { date, .. } => date,
|
||||
Self::Channel { date, .. } => date,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Chat, MessageId, ReactionType};
|
||||
|
||||
/// This object represents reaction changes on a message with anonymous
|
||||
/// reactions.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MessageReactionCountUpdated {
|
||||
/// The chat containing the message
|
||||
pub chat: Chat,
|
||||
|
||||
/// Unique message identifier inside the chat
|
||||
#[serde(flatten)]
|
||||
pub message_id: MessageId,
|
||||
|
||||
/// Date of the change in Unix time
|
||||
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
pub date: DateTime<Utc>,
|
||||
|
||||
/// List of reactions that are present on the message
|
||||
pub reactions: Vec<ReactionCount>,
|
||||
}
|
||||
|
||||
/// Represents a reaction added to a message along with the number of times it
|
||||
/// was added.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ReactionCount {
|
||||
/// Type of the reaction
|
||||
pub r#type: ReactionType,
|
||||
|
||||
/// Number of times the reaction was added
|
||||
pub total_count: u64,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let data = r#"
|
||||
{
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"message_id": 36,
|
||||
"date": 1721306391,
|
||||
"reactions": [
|
||||
{
|
||||
"type": {
|
||||
"type": "emoji",
|
||||
"emoji": "🗿"
|
||||
},
|
||||
"total_count": 2
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"type": "emoji",
|
||||
"emoji": "🌭"
|
||||
},
|
||||
"total_count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<MessageReactionCountUpdated>(data).unwrap();
|
||||
}
|
||||
}
|
82
crates/teloxide-core/src/types/message_reaction_updated.rs
Normal file
82
crates/teloxide-core/src/types/message_reaction_updated.rs
Normal file
|
@ -0,0 +1,82 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Chat, MessageId, ReactionType, User};
|
||||
|
||||
/// This object represents a change of a reaction on a message performed by a
|
||||
/// user.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MessageReactionUpdated {
|
||||
/// The chat containing the message the user reacted to
|
||||
pub chat: Chat,
|
||||
|
||||
/// Unique identifier of the message inside the chat
|
||||
#[serde(flatten)]
|
||||
pub message_id: MessageId,
|
||||
|
||||
/// The user that changed the reaction, if the user isn't anonymous
|
||||
pub user: Option<User>,
|
||||
|
||||
/// The chat on behalf of which the reaction was changed, if the user is
|
||||
/// anonymous
|
||||
pub actor_chat: Option<Chat>,
|
||||
|
||||
/// Date of the change in Unix time
|
||||
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||
pub date: DateTime<Utc>,
|
||||
|
||||
/// Previous list of reaction types that were set by the user
|
||||
pub old_reaction: Vec<ReactionType>,
|
||||
|
||||
/// New list of reaction types that have been set by the user
|
||||
pub new_reaction: Vec<ReactionType>,
|
||||
}
|
||||
|
||||
impl MessageReactionUpdated {
|
||||
#[must_use]
|
||||
pub fn actor_chat(&self) -> Option<&Chat> {
|
||||
self.actor_chat.as_ref()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn user(&self) -> Option<&User> {
|
||||
self.user.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let data = r#"
|
||||
{
|
||||
"chat": {
|
||||
"id": -1002184233434,
|
||||
"title": "Test",
|
||||
"type": "supergroup"
|
||||
},
|
||||
"message_id": 35,
|
||||
"user": {
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10",
|
||||
"language_code": "en",
|
||||
"is_premium": true
|
||||
},
|
||||
"date": 1721306082,
|
||||
"old_reaction": [],
|
||||
"new_reaction": [
|
||||
{
|
||||
"type": "emoji",
|
||||
"emoji": "🌭"
|
||||
}
|
||||
]
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<MessageReactionUpdated>(data).unwrap();
|
||||
}
|
||||
}
|
|
@ -55,6 +55,11 @@ use serde::{Deserialize, Serialize};
|
|||
/// ```rust
|
||||
#[doc = "pre-formatted fixed-width code block written in the Rust programming language"]
|
||||
/// ```
|
||||
/// >Block quotation started
|
||||
/// >Block quotation continued
|
||||
/// >Block quotation continued
|
||||
/// >Block quotation continued
|
||||
/// >The last line of the block quotation
|
||||
/// ````
|
||||
///
|
||||
/// Please note:
|
||||
|
@ -98,6 +103,8 @@ use serde::{Deserialize, Serialize};
|
|||
/// <pre>pre-formatted fixed-width code block</pre>
|
||||
#[doc = "<pre><code class=\"language-rust\">pre-formatted fixed-width code block written in the \
|
||||
Rust programming language</code></pre>"]
|
||||
/// <blockquote>Block quotation started\nBlock quotation continued\nThe last
|
||||
/// line of the block quotation</blockquote>
|
||||
/// ````
|
||||
///
|
||||
/// Please note:
|
||||
|
|
43
crates/teloxide-core/src/types/reaction_type.rs
Normal file
43
crates/teloxide-core/src/types/reaction_type.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The reaction type is based on an emoji or custom emoji.
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ReactionType {
|
||||
/// Emoji reaction.
|
||||
Emoji {
|
||||
/// Reaction emoji. Currently, it can be one of "👍", "👎", "❤", "🔥",
|
||||
/// "🥰", "👏", "😁", "🤔", "🤯", "😱", "🤬", "😢", "🎉", "🤩",
|
||||
/// "🤮", "💩", "🙏", "👌", "🕊", "🤡", "🥱", "🥴", "😍", "🐳",
|
||||
/// "❤🔥", "🌚", "🌭", "💯", "🤣", "⚡", "🍌", "🏆", "💔", "🤨",
|
||||
/// "😐", "🍓", "🍾", "💋", "🖕", "😈", "😴", "😭", "🤓", "👻",
|
||||
/// "👨💻", "👀", "🎃", "🙈", "😇", "😨", "🤝", "✍", "🤗", "🫡",
|
||||
/// "🎅", "🎄", "☃", "💅", "🤪", "🗿", "🆒", "💘", "🙉", "🦄", "😘",
|
||||
/// "💊", "🙊", "😎", "👾", "🤷♂", "🤷", "🤷♀", "😡"
|
||||
emoji: String,
|
||||
},
|
||||
/// Custom emoji reaction.
|
||||
CustomEmoji {
|
||||
/// Custom emoji identifier.
|
||||
custom_emoji_id: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl ReactionType {
|
||||
#[must_use]
|
||||
pub fn emoji(&self) -> Option<&String> {
|
||||
match &self {
|
||||
Self::Emoji { emoji } => Some(emoji),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn custom_emoji_id(&self) -> Option<&String> {
|
||||
match &self {
|
||||
Self::CustomEmoji { custom_emoji_id } => Some(custom_emoji_id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
61
crates/teloxide-core/src/types/reply_parameters.rs
Normal file
61
crates/teloxide-core/src/types/reply_parameters.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{MessageEntity, MessageId, Recipient};
|
||||
|
||||
/// Describes reply parameters for the message that is being sent.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Default, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ReplyParameters {
|
||||
/// Identifier of the message that will be replied to in the current chat,
|
||||
/// or in the chat _chat\_id_ if it is specified
|
||||
#[serde(flatten)]
|
||||
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`)
|
||||
pub chat_id: Option<Recipient>,
|
||||
/// 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.
|
||||
pub allow_sending_without_reply: Option<bool>,
|
||||
/// 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
|
||||
/// be replied to, including _bold_, _italic_, _underline_, _strikethrough_,
|
||||
/// _spoiler_, and _custom_emoji_ entities. The message will fail to send if
|
||||
/// the quote isn't found in the original message.
|
||||
pub quote: Option<String>,
|
||||
/// Mode for parsing entities in the quote. See [formatting options] for
|
||||
/// more details.
|
||||
///
|
||||
/// [formatting options]: https://core.telegram.org/bots/api#formatting-options
|
||||
pub quote_parse_mode: Option<String>,
|
||||
/// A JSON-serialized list of special entities that appear in the quote. It
|
||||
/// can be specified instead of quote_parse_mode.
|
||||
pub quote_entities: Option<Vec<MessageEntity>>,
|
||||
/// Position of the quote in the original message in UTF-16 code units
|
||||
pub quote_position: Option<u32>,
|
||||
}
|
||||
|
||||
impl ReplyParameters {
|
||||
pub fn new(message_id: MessageId) -> Self {
|
||||
Self { message_id, ..Self::default() }
|
||||
}
|
||||
|
||||
/// Setter for the `chat_id` field
|
||||
pub fn chat_id(mut self, chat_id: Recipient) -> Self {
|
||||
self.chat_id = Some(chat_id);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `allow_sending_without_reply_field` to _true_
|
||||
pub fn allow_sending_without_reply(mut self) -> Self {
|
||||
self.allow_sending_without_reply = Some(true);
|
||||
self
|
||||
}
|
||||
|
||||
/// Setter for the `quote` field
|
||||
pub fn quote(mut self, quote: String) -> Self {
|
||||
self.quote = Some(quote);
|
||||
self
|
||||
}
|
||||
}
|
24
crates/teloxide-core/src/types/request_id.rs
Normal file
24
crates/teloxide-core/src/types/request_id.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
use derive_more::Display;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Display, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct RequestId(pub i32);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_request_id_de() {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
|
||||
struct Dummy {
|
||||
request_id: RequestId,
|
||||
}
|
||||
let json = r#"{"request_id":42}"#;
|
||||
let dummy = Dummy { request_id: RequestId(42) };
|
||||
|
||||
assert_eq!(serde_json::to_string(&dummy).unwrap(), json);
|
||||
assert_eq!(dummy, serde_json::from_str(json).unwrap());
|
||||
}
|
||||
}
|
24
crates/teloxide-core/src/types/text_quote.rs
Normal file
24
crates/teloxide-core/src/types/text_quote.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::MessageEntity;
|
||||
|
||||
/// This object contains information about the quoted part of a message that is
|
||||
/// replied to by the given message.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct TextQuote {
|
||||
/// Text of the quoted part of a message that is replied to by the given
|
||||
/// message
|
||||
pub text: String,
|
||||
/// Special entities that appear in the quote. Currently, only _bold_,
|
||||
/// _italic_, _underline_, _strikethrough_, _spoiler_, and
|
||||
/// _custom_emoji_ entities are kept in quotes.
|
||||
#[serde(default)]
|
||||
pub entities: Vec<MessageEntity>,
|
||||
/// Approximate quote position in the original message in UTF-16 code units
|
||||
/// as specified by the sender
|
||||
pub position: u32,
|
||||
/// True, if the quote was chosen manually by the message sender. Otherwise,
|
||||
/// the quote was added automatically by the server.
|
||||
#[serde(default)]
|
||||
pub is_manual: bool,
|
||||
}
|
|
@ -3,8 +3,9 @@ use serde::{de::MapAccess, Deserialize, Serialize, Serializer};
|
|||
use serde_json::Value;
|
||||
|
||||
use crate::types::{
|
||||
CallbackQuery, Chat, ChatJoinRequest, ChatMemberUpdated, ChosenInlineResult, InlineQuery,
|
||||
Message, Poll, PollAnswer, PreCheckoutQuery, ShippingQuery, User,
|
||||
CallbackQuery, Chat, ChatBoostRemoved, ChatBoostUpdated, ChatJoinRequest, ChatMemberUpdated,
|
||||
ChosenInlineResult, InlineQuery, Message, MessageReactionCountUpdated, MessageReactionUpdated,
|
||||
Poll, PollAnswer, PreCheckoutQuery, ShippingQuery, User,
|
||||
};
|
||||
|
||||
/// This [object] represents an incoming update.
|
||||
|
@ -59,6 +60,24 @@ pub enum UpdateKind {
|
|||
/// New version of a channel post that is known to the bot and was edited.
|
||||
EditedChannelPost(Message),
|
||||
|
||||
/// 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`
|
||||
/// to receive these updates. The update isn't received for reactions
|
||||
/// set by bots.
|
||||
///
|
||||
/// [`AllowedUpdate::MessageReaction`]: crate::types::AllowedUpdate::MessageReaction
|
||||
MessageReaction(MessageReactionUpdated),
|
||||
|
||||
/// Reactions to a message with anonymous reactions were changed. The bot
|
||||
/// must be an administrator in the chat and must explicitly specify
|
||||
/// [`AllowedUpdate::MessageReactionCount`] in the list of `allowed_updates`
|
||||
/// to receive these updates. The updates are grouped and can be sent
|
||||
/// with delay up to a few minutes.
|
||||
///
|
||||
/// [`AllowedUpdate::MessageReactionCount`]: crate::types::AllowedUpdate::MessageReactionCount
|
||||
MessageReactionCount(MessageReactionCountUpdated),
|
||||
|
||||
/// New incoming [inline] query.
|
||||
///
|
||||
/// [inline]: https://core.telegram.org/bots/api#inline-mode
|
||||
|
@ -108,6 +127,14 @@ pub enum UpdateKind {
|
|||
/// updates.
|
||||
ChatJoinRequest(ChatJoinRequest),
|
||||
|
||||
/// A chat boost was added or changed. The bot must be an administrator in
|
||||
/// the chat to receive these updates.
|
||||
ChatBoost(ChatBoostUpdated),
|
||||
|
||||
/// A boost was removed from a chat. The bot must be an administrator in the
|
||||
/// chat to receive these updates.
|
||||
RemovedChatBoost(ChatBoostRemoved),
|
||||
|
||||
/// An error that happened during deserialization.
|
||||
///
|
||||
/// This allows `teloxide` to continue working even if telegram adds a new
|
||||
|
@ -129,10 +156,13 @@ impl Update {
|
|||
use UpdateKind::*;
|
||||
|
||||
let from = match &self.kind {
|
||||
Message(m) | EditedMessage(m) | ChannelPost(m) | EditedChannelPost(m) => m.from()?,
|
||||
Message(m) | EditedMessage(m) | ChannelPost(m) | EditedChannelPost(m) => {
|
||||
m.from.as_ref()?
|
||||
}
|
||||
|
||||
CallbackQuery(query) => &query.from,
|
||||
ChosenInlineResult(chosen) => &chosen.from,
|
||||
MessageReaction(reaction) => return reaction.user(),
|
||||
InlineQuery(query) => &query.from,
|
||||
ShippingQuery(query) => &query.from,
|
||||
PreCheckoutQuery(query) => &query.from,
|
||||
|
@ -140,8 +170,10 @@ impl Update {
|
|||
|
||||
MyChatMember(m) | ChatMember(m) => &m.from,
|
||||
ChatJoinRequest(r) => &r.from,
|
||||
ChatBoost(b) => return b.boost.source.user(),
|
||||
RemovedChatBoost(b) => return b.source.user(),
|
||||
|
||||
Poll(_) | Error(_) => return None,
|
||||
MessageReactionCount(_) | Poll(_) | Error(_) => return None,
|
||||
};
|
||||
|
||||
Some(from)
|
||||
|
@ -191,6 +223,13 @@ impl Update {
|
|||
| UpdateKind::ChannelPost(message)
|
||||
| UpdateKind::EditedChannelPost(message) => i0(message.mentioned_users()),
|
||||
|
||||
UpdateKind::MessageReaction(answer) => {
|
||||
if let Some(user) = answer.user() {
|
||||
return i1(once(user));
|
||||
}
|
||||
i6(empty())
|
||||
}
|
||||
|
||||
UpdateKind::InlineQuery(query) => i1(once(&query.from)),
|
||||
UpdateKind::ChosenInlineResult(query) => i1(once(&query.from)),
|
||||
UpdateKind::CallbackQuery(query) => i2(query.mentioned_users()),
|
||||
|
@ -209,7 +248,21 @@ impl Update {
|
|||
i4(member.mentioned_users())
|
||||
}
|
||||
UpdateKind::ChatJoinRequest(request) => i5(request.mentioned_users()),
|
||||
UpdateKind::Error(_) => i6(empty()),
|
||||
|
||||
UpdateKind::ChatBoost(b) => {
|
||||
if let Some(user) = b.boost.source.user() {
|
||||
return i1(once(user));
|
||||
}
|
||||
i6(empty())
|
||||
}
|
||||
UpdateKind::RemovedChatBoost(b) => {
|
||||
if let Some(user) = b.source.user() {
|
||||
return i1(once(user));
|
||||
}
|
||||
i6(empty())
|
||||
}
|
||||
|
||||
UpdateKind::MessageReactionCount(_) | UpdateKind::Error(_) => i6(empty()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,10 +273,14 @@ impl Update {
|
|||
|
||||
let chat = match &self.kind {
|
||||
Message(m) | EditedMessage(m) | ChannelPost(m) | EditedChannelPost(m) => &m.chat,
|
||||
CallbackQuery(q) => &q.message.as_ref()?.chat,
|
||||
CallbackQuery(q) => q.message.as_ref()?.chat(),
|
||||
ChatMember(m) => &m.chat,
|
||||
MyChatMember(m) => &m.chat,
|
||||
ChatJoinRequest(c) => &c.chat,
|
||||
MessageReaction(r) => &r.chat,
|
||||
MessageReactionCount(r) => &r.chat,
|
||||
ChatBoost(b) => &b.chat,
|
||||
RemovedChatBoost(b) => &b.chat,
|
||||
|
||||
InlineQuery(_)
|
||||
| ChosenInlineResult(_)
|
||||
|
@ -293,6 +350,14 @@ impl<'de> Deserialize<'de> for UpdateKind {
|
|||
"edited_channel_post" => {
|
||||
map.next_value::<Message>().ok().map(UpdateKind::EditedChannelPost)
|
||||
}
|
||||
"message_reaction" => map
|
||||
.next_value::<MessageReactionUpdated>()
|
||||
.ok()
|
||||
.map(UpdateKind::MessageReaction),
|
||||
"message_reaction_count" => map
|
||||
.next_value::<MessageReactionCountUpdated>()
|
||||
.ok()
|
||||
.map(UpdateKind::MessageReactionCount),
|
||||
"inline_query" => {
|
||||
map.next_value::<InlineQuery>().ok().map(UpdateKind::InlineQuery)
|
||||
}
|
||||
|
@ -324,6 +389,13 @@ impl<'de> Deserialize<'de> for UpdateKind {
|
|||
.next_value::<ChatJoinRequest>()
|
||||
.ok()
|
||||
.map(UpdateKind::ChatJoinRequest),
|
||||
"chat_boost" => {
|
||||
map.next_value::<ChatBoostUpdated>().ok().map(UpdateKind::ChatBoost)
|
||||
}
|
||||
"removed_chat_boost" => map
|
||||
.next_value::<ChatBoostRemoved>()
|
||||
.ok()
|
||||
.map(UpdateKind::RemovedChatBoost),
|
||||
_ => Some(empty_error()),
|
||||
})
|
||||
.unwrap_or_else(empty_error);
|
||||
|
@ -351,27 +423,37 @@ impl Serialize for UpdateKind {
|
|||
UpdateKind::EditedChannelPost(v) => {
|
||||
s.serialize_newtype_variant(name, 3, "edited_channel_post", v)
|
||||
}
|
||||
UpdateKind::InlineQuery(v) => s.serialize_newtype_variant(name, 4, "inline_query", v),
|
||||
UpdateKind::MessageReaction(v) => {
|
||||
s.serialize_newtype_variant(name, 4, "message_reaction", v)
|
||||
}
|
||||
UpdateKind::MessageReactionCount(v) => {
|
||||
s.serialize_newtype_variant(name, 5, "message_reaction_count", v)
|
||||
}
|
||||
UpdateKind::InlineQuery(v) => s.serialize_newtype_variant(name, 6, "inline_query", v),
|
||||
UpdateKind::ChosenInlineResult(v) => {
|
||||
s.serialize_newtype_variant(name, 5, "chosen_inline_result", v)
|
||||
s.serialize_newtype_variant(name, 7, "chosen_inline_result", v)
|
||||
}
|
||||
UpdateKind::CallbackQuery(v) => {
|
||||
s.serialize_newtype_variant(name, 6, "callback_query", v)
|
||||
s.serialize_newtype_variant(name, 8, "callback_query", v)
|
||||
}
|
||||
UpdateKind::ShippingQuery(v) => {
|
||||
s.serialize_newtype_variant(name, 7, "shipping_query", v)
|
||||
s.serialize_newtype_variant(name, 9, "shipping_query", v)
|
||||
}
|
||||
UpdateKind::PreCheckoutQuery(v) => {
|
||||
s.serialize_newtype_variant(name, 8, "pre_checkout_query", v)
|
||||
s.serialize_newtype_variant(name, 10, "pre_checkout_query", v)
|
||||
}
|
||||
UpdateKind::Poll(v) => s.serialize_newtype_variant(name, 9, "poll", v),
|
||||
UpdateKind::PollAnswer(v) => s.serialize_newtype_variant(name, 10, "poll_answer", 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::MyChatMember(v) => {
|
||||
s.serialize_newtype_variant(name, 11, "my_chat_member", v)
|
||||
s.serialize_newtype_variant(name, 13, "my_chat_member", v)
|
||||
}
|
||||
UpdateKind::ChatMember(v) => s.serialize_newtype_variant(name, 12, "chat_member", v),
|
||||
UpdateKind::ChatMember(v) => s.serialize_newtype_variant(name, 14, "chat_member", v),
|
||||
UpdateKind::ChatJoinRequest(v) => {
|
||||
s.serialize_newtype_variant(name, 13, "chat_join_request", v)
|
||||
s.serialize_newtype_variant(name, 15, "chat_join_request", v)
|
||||
}
|
||||
UpdateKind::ChatBoost(v) => s.serialize_newtype_variant(name, 16, "chat_boost", v),
|
||||
UpdateKind::RemovedChatBoost(v) => {
|
||||
s.serialize_newtype_variant(name, 17, "removed_chat_boost", v)
|
||||
}
|
||||
UpdateKind::Error(v) => v.serialize(s),
|
||||
}
|
||||
|
@ -385,8 +467,12 @@ fn empty_error() -> UpdateKind {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::types::{
|
||||
Chat, ChatFullInfo, ChatId, ChatKind, ChatPrivate, MediaKind, MediaText, Message,
|
||||
MessageCommon, MessageId, MessageKind, Update, UpdateId, UpdateKind, User, UserId,
|
||||
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,
|
||||
};
|
||||
|
||||
use chrono::DateTime;
|
||||
|
@ -415,7 +501,8 @@ mod test {
|
|||
"type":"private"
|
||||
},
|
||||
"date":1569518342,
|
||||
"text":"hello there"
|
||||
"text":"hello there",
|
||||
"link_preview_options":{"is_disabled":true}
|
||||
}
|
||||
}"#;
|
||||
|
||||
|
@ -425,6 +512,18 @@ mod test {
|
|||
via_bot: None,
|
||||
id: MessageId(6557),
|
||||
thread_id: None,
|
||||
from: Some(User {
|
||||
id: UserId(218_485_655),
|
||||
is_bot: false,
|
||||
first_name: String::from("Waffle"),
|
||||
last_name: None,
|
||||
username: Some(String::from("WaffleLapkin")),
|
||||
language_code: Some(String::from("en")),
|
||||
is_premium: false,
|
||||
added_to_attachment_menu: false,
|
||||
}),
|
||||
sender_chat: None,
|
||||
is_topic_message: false,
|
||||
date,
|
||||
chat: Chat {
|
||||
id: ChatId(218_485_655),
|
||||
|
@ -435,37 +534,34 @@ mod test {
|
|||
bio: None,
|
||||
has_private_forwards: None,
|
||||
has_restricted_voice_and_video_messages: None,
|
||||
emoji_status_custom_emoji_id: 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 { emoji_status_expiration_date: None },
|
||||
chat_full_info: ChatFullInfo::default(),
|
||||
},
|
||||
kind: MessageKind::Common(MessageCommon {
|
||||
from: Some(User {
|
||||
id: UserId(218_485_655),
|
||||
is_bot: false,
|
||||
first_name: String::from("Waffle"),
|
||||
last_name: None,
|
||||
username: Some(String::from("WaffleLapkin")),
|
||||
language_code: Some(String::from("en")),
|
||||
is_premium: false,
|
||||
added_to_attachment_menu: false,
|
||||
}),
|
||||
reply_to_message: None,
|
||||
forward: None,
|
||||
forward_origin: None,
|
||||
external_reply: None,
|
||||
quote: None,
|
||||
edit_date: None,
|
||||
media_kind: MediaKind::Text(MediaText {
|
||||
text: String::from("hello there"),
|
||||
entities: vec![],
|
||||
link_preview_options: Some(LinkPreviewOptions {
|
||||
is_disabled: true,
|
||||
url: None,
|
||||
prefer_small_media: false,
|
||||
prefer_large_media: false,
|
||||
show_above_text: false,
|
||||
}),
|
||||
}),
|
||||
reply_markup: None,
|
||||
sender_chat: None,
|
||||
author_signature: None,
|
||||
is_topic_message: false,
|
||||
is_automatic_forward: false,
|
||||
has_protected_content: false,
|
||||
}),
|
||||
|
@ -726,4 +822,315 @@ mod test {
|
|||
_ => panic!("Expected `MyChatMember`"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn message_reaction_updated() {
|
||||
let json = r#"
|
||||
{
|
||||
"update_id": 71651249,
|
||||
"message_reaction": {
|
||||
"chat": {
|
||||
"id": -1002184233434,
|
||||
"title": "Test",
|
||||
"type": "supergroup"
|
||||
},
|
||||
"message_id": 35,
|
||||
"user": {
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10",
|
||||
"language_code": "en",
|
||||
"is_premium": true
|
||||
},
|
||||
"date": 1721306082,
|
||||
"old_reaction": [],
|
||||
"new_reaction": [
|
||||
{
|
||||
"type": "emoji",
|
||||
"emoji": "🌭"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
let expected = Update {
|
||||
id: UpdateId(71651249),
|
||||
kind: UpdateKind::MessageReaction(MessageReactionUpdated {
|
||||
chat: Chat {
|
||||
id: ChatId(-1002184233434),
|
||||
kind: ChatKind::Public(ChatPublic {
|
||||
title: Some("Test".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,
|
||||
}),
|
||||
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(),
|
||||
},
|
||||
message_id: MessageId(35),
|
||||
user: Some(User {
|
||||
id: UserId(1459074222),
|
||||
is_bot: false,
|
||||
first_name: "shadowchain".to_owned(),
|
||||
last_name: None,
|
||||
username: Some("shdwchn10".to_owned()),
|
||||
language_code: Some("en".to_owned()),
|
||||
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() }],
|
||||
}),
|
||||
};
|
||||
|
||||
let actual = serde_json::from_str::<Update>(json).unwrap();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn message_reaction_count_updated() {
|
||||
let json = r#"
|
||||
{
|
||||
"update_id": 71651251,
|
||||
"message_reaction_count": {
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"message_id": 36,
|
||||
"date": 1721306391,
|
||||
"reactions": [
|
||||
{
|
||||
"type": {
|
||||
"type": "emoji",
|
||||
"emoji": "🗿"
|
||||
},
|
||||
"total_count": 2
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"type": "emoji",
|
||||
"emoji": "🌭"
|
||||
},
|
||||
"total_count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
let expected = Update {
|
||||
id: UpdateId(71651251),
|
||||
kind: UpdateKind::MessageReactionCount(MessageReactionCountUpdated {
|
||||
chat: Chat {
|
||||
id: ChatId(-1002236736395),
|
||||
kind: ChatKind::Public(ChatPublic {
|
||||
title: Some("Test".to_owned()),
|
||||
kind: PublicChatKind::Channel(PublicChatChannel {
|
||||
username: None,
|
||||
linked_chat_id: 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(),
|
||||
},
|
||||
message_id: MessageId(36),
|
||||
date: DateTime::from_timestamp(1721306391, 0).unwrap(),
|
||||
reactions: vec![
|
||||
ReactionCount {
|
||||
r#type: ReactionType::Emoji { emoji: "🗿".to_owned() },
|
||||
total_count: 2,
|
||||
},
|
||||
ReactionCount {
|
||||
r#type: ReactionType::Emoji { emoji: "🌭".to_owned() },
|
||||
total_count: 1,
|
||||
},
|
||||
],
|
||||
}),
|
||||
};
|
||||
|
||||
let actual = serde_json::from_str::<Update>(json).unwrap();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chat_boost_updated() {
|
||||
let json = r#"
|
||||
{
|
||||
"update_id": 71651297,
|
||||
"chat_boost": {
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"boost": {
|
||||
"boost_id": "4506e1b7e866e33fcbde78fe1746ec3a",
|
||||
"add_date": 1721399621,
|
||||
"expiration_date": 1745088963,
|
||||
"source": {
|
||||
"source": "premium",
|
||||
"user": {
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10",
|
||||
"language_code": "en",
|
||||
"is_premium": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
let expected = Update {
|
||||
id: UpdateId(71651297),
|
||||
kind: UpdateKind::ChatBoost(ChatBoostUpdated {
|
||||
chat: Chat {
|
||||
id: ChatId(-1002236736395),
|
||||
kind: ChatKind::Public(ChatPublic {
|
||||
title: Some("Test".to_owned()),
|
||||
kind: PublicChatKind::Channel(PublicChatChannel {
|
||||
username: None,
|
||||
linked_chat_id: 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(),
|
||||
},
|
||||
boost: ChatBoost {
|
||||
boost_id: "4506e1b7e866e33fcbde78fe1746ec3a".to_owned(),
|
||||
add_date: DateTime::from_timestamp(1721399621, 0).unwrap(),
|
||||
expiration_date: DateTime::from_timestamp(1745088963, 0).unwrap(),
|
||||
source: ChatBoostSource::Premium(ChatBoostSourcePremium {
|
||||
user: User {
|
||||
id: UserId(1459074222),
|
||||
is_bot: false,
|
||||
first_name: "shadowchain".to_owned(),
|
||||
last_name: None,
|
||||
username: Some("shdwchn10".to_owned()),
|
||||
language_code: Some("en".to_owned()),
|
||||
is_premium: true,
|
||||
added_to_attachment_menu: false,
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
let actual = serde_json::from_str::<Update>(json).unwrap();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chat_boost_removed() {
|
||||
let json = r#"
|
||||
{
|
||||
"update_id": 71651297,
|
||||
"removed_chat_boost": {
|
||||
"chat": {
|
||||
"id": -1002236736395,
|
||||
"title": "Test",
|
||||
"type": "channel"
|
||||
},
|
||||
"boost_id": "4506e1b7e866e33fcbde78fe1746ec3a",
|
||||
"remove_date": 1721999621,
|
||||
"source": {
|
||||
"source": "premium",
|
||||
"user": {
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10",
|
||||
"language_code": "en",
|
||||
"is_premium": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
let expected = Update {
|
||||
id: UpdateId(71651297),
|
||||
kind: UpdateKind::RemovedChatBoost(ChatBoostRemoved {
|
||||
chat: Chat {
|
||||
id: ChatId(-1002236736395),
|
||||
kind: ChatKind::Public(ChatPublic {
|
||||
title: Some("Test".to_owned()),
|
||||
kind: PublicChatKind::Channel(PublicChatChannel {
|
||||
username: None,
|
||||
linked_chat_id: 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(),
|
||||
},
|
||||
boost_id: "4506e1b7e866e33fcbde78fe1746ec3a".to_owned(),
|
||||
remove_date: DateTime::from_timestamp(1721999621, 0).unwrap(),
|
||||
source: ChatBoostSource::Premium(ChatBoostSourcePremium {
|
||||
user: User {
|
||||
id: UserId(1459074222),
|
||||
is_bot: false,
|
||||
first_name: "shadowchain".to_owned(),
|
||||
last_name: None,
|
||||
username: Some("shdwchn10".to_owned()),
|
||||
language_code: Some("en".to_owned()),
|
||||
is_premium: true,
|
||||
added_to_attachment_menu: false,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
};
|
||||
|
||||
let actual = serde_json::from_str::<Update>(json).unwrap();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
}
|
||||
|
|
43
crates/teloxide-core/src/types/user_chat_boosts.rs
Normal file
43
crates/teloxide-core/src/types/user_chat_boosts.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::ChatBoost;
|
||||
|
||||
/// This object represents a list of boosts added to a chat by a user.
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct UserChatBoosts {
|
||||
/// The list of boosts added to the chat by the user.
|
||||
pub boosts: Vec<ChatBoost>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let data = r#"
|
||||
{
|
||||
"boosts": [
|
||||
{
|
||||
"boost_id": "4506e1b7e866e33fcbde78fe1746ec3a",
|
||||
"add_date": 1721399621,
|
||||
"expiration_date": 1745088963,
|
||||
"source": {
|
||||
"source": "premium",
|
||||
"user": {
|
||||
"id": 1459074222,
|
||||
"is_bot": false,
|
||||
"first_name": "shadowchain",
|
||||
"username": "shdwchn10",
|
||||
"language_code": "en",
|
||||
"is_premium": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"#;
|
||||
serde_json::from_str::<UserChatBoosts>(data).unwrap();
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::UserId;
|
||||
|
||||
/// Information about the chat whose identifier was shared with the bot using a
|
||||
/// [`KeyboardButtonRequestUser`] button.
|
||||
///
|
||||
/// [`KeyboardButtonRequestUser`]: crate::types::KeyboardButtonRequestUser
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub struct UserShared {
|
||||
/// Identifier of the request.
|
||||
pub request_id: i32,
|
||||
/// Identifier of the shared user.
|
||||
pub user_id: UserId,
|
||||
}
|
15
crates/teloxide-core/src/types/users_shared.rs
Normal file
15
crates/teloxide-core/src/types/users_shared.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{RequestId, UserId};
|
||||
|
||||
/// This object contains information about the users whose identifiers were
|
||||
/// shared with the bot using a [KeyboardButtonRequestUsers] button.
|
||||
///
|
||||
/// [KeyboardButtonRequestUsers]: crate::types::KeyboardButtonRequestUsers
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub struct UsersShared {
|
||||
/// Identifier of the request
|
||||
pub request_id: RequestId,
|
||||
/// Identifiers of the shared users
|
||||
pub user_ids: Vec<UserId>,
|
||||
}
|
|
@ -44,6 +44,7 @@ pub(crate) fn mentioned_users_from_entities(
|
|||
| Email
|
||||
| PhoneNumber
|
||||
| Bold
|
||||
| Blockquote
|
||||
| Italic
|
||||
| Underline
|
||||
| Strikethrough
|
||||
|
|
|
@ -79,7 +79,7 @@ async fn kick_user(bot: Bot, msg: Message) -> ResponseResult<()> {
|
|||
match msg.reply_to_message() {
|
||||
Some(replied) => {
|
||||
// bot.unban_chat_member can also kicks a user from a group chat.
|
||||
bot.unban_chat_member(msg.chat.id, replied.from().unwrap().id).await?;
|
||||
bot.unban_chat_member(msg.chat.id, replied.from.as_ref().unwrap().id).await?;
|
||||
}
|
||||
None => {
|
||||
bot.send_message(msg.chat.id, "Use this command in reply to another message").await?;
|
||||
|
@ -94,7 +94,7 @@ async fn ban_user(bot: Bot, msg: Message, time: Duration) -> ResponseResult<()>
|
|||
Some(replied) => {
|
||||
bot.kick_chat_member(
|
||||
msg.chat.id,
|
||||
replied.from().expect("Must be MessageKind::Common").id,
|
||||
replied.from.as_ref().expect("Must be MessageKind::Common").id,
|
||||
)
|
||||
.until_date(msg.date + time)
|
||||
.await?;
|
||||
|
@ -113,7 +113,7 @@ async fn mute_user(bot: Bot, msg: Message, time: Duration) -> ResponseResult<()>
|
|||
Some(replied) => {
|
||||
bot.restrict_chat_member(
|
||||
msg.chat.id,
|
||||
replied.from().expect("Must be MessageKind::Common").id,
|
||||
replied.from.as_ref().expect("Must be MessageKind::Common").id,
|
||||
ChatPermissions::empty(),
|
||||
)
|
||||
.until_date(msg.date + time)
|
||||
|
|
|
@ -116,8 +116,8 @@ async fn callback_handler(bot: Bot, q: CallbackQuery) -> Result<(), Box<dyn Erro
|
|||
bot.answer_callback_query(q.id).await?;
|
||||
|
||||
// Edit text of the message to which the buttons were attached
|
||||
if let Some(Message { id, chat, .. }) = q.message {
|
||||
bot.edit_message_text(chat.id, id, text).await?;
|
||||
if let Some(message) = q.message {
|
||||
bot.edit_message_text(message.chat().id, message.id(), text).await?;
|
||||
} else if let Some(id) = q.inline_message_id {
|
||||
bot.edit_message_text_inline(id, text).await?;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
|
||||
use rand::Rng;
|
||||
|
||||
use teloxide::{prelude::*, types::Dice, utils::command::BotCommands};
|
||||
use teloxide::{
|
||||
prelude::*,
|
||||
types::{Dice, ReplyParameters},
|
||||
utils::command::BotCommands,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
@ -30,7 +34,7 @@ async fn main() {
|
|||
.branch(
|
||||
// Filter a maintainer by a user ID.
|
||||
dptree::filter(|cfg: ConfigParameters, msg: Message| {
|
||||
msg.from().map(|user| user.id == cfg.bot_maintainer).unwrap_or_default()
|
||||
msg.from.map(|user| user.id == cfg.bot_maintainer).unwrap_or_default()
|
||||
})
|
||||
.filter_command::<MaintainerCommands>()
|
||||
.endpoint(|msg: Message, bot: Bot, cmd: MaintainerCommands| async move {
|
||||
|
@ -60,7 +64,7 @@ async fn main() {
|
|||
// filter only messages with dices.
|
||||
Message::filter_dice().endpoint(|bot: Bot, msg: Message, dice: Dice| async move {
|
||||
bot.send_message(msg.chat.id, format!("Dice value: {}", dice.value))
|
||||
.reply_to_message_id(msg.id)
|
||||
.reply_parameters(ReplyParameters::new(msg.id))
|
||||
.await?;
|
||||
Ok(())
|
||||
}),
|
||||
|
@ -121,7 +125,7 @@ async fn simple_commands_handler(
|
|||
) -> Result<(), teloxide::RequestError> {
|
||||
let text = match cmd {
|
||||
SimpleCommand::Help => {
|
||||
if msg.from().unwrap().id == cfg.bot_maintainer {
|
||||
if msg.from.unwrap().id == cfg.bot_maintainer {
|
||||
format!(
|
||||
"{}\n\n{}",
|
||||
SimpleCommand::descriptions(),
|
||||
|
@ -134,7 +138,7 @@ async fn simple_commands_handler(
|
|||
}
|
||||
}
|
||||
SimpleCommand::Maintainer => {
|
||||
if msg.from().unwrap().id == cfg.bot_maintainer {
|
||||
if msg.from.as_ref().unwrap().id == cfg.bot_maintainer {
|
||||
"Maintainer is you!".into()
|
||||
} else if let Some(username) = cfg.maintainer_username {
|
||||
format!("Maintainer is @{username}")
|
||||
|
@ -143,7 +147,7 @@ async fn simple_commands_handler(
|
|||
}
|
||||
}
|
||||
SimpleCommand::MyId => {
|
||||
format!("{}", msg.from().unwrap().id)
|
||||
format!("{}", msg.from.unwrap().id)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ impl GetChatId for Message {
|
|||
|
||||
impl GetChatId for CallbackQuery {
|
||||
fn chat_id(&self) -> Option<ChatId> {
|
||||
self.message.as_ref().map(|mes| mes.chat.id)
|
||||
self.message.as_ref().map(|mes| mes.chat().id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#![allow(clippy::redundant_closure_call)]
|
||||
// Required for the `filter_from` currently
|
||||
#![allow(deprecated)]
|
||||
|
||||
use dptree::{di::DependencyMap, Handler};
|
||||
|
||||
|
@ -68,6 +70,7 @@ macro_rules! define_message_ext {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: change macro so that we can filter things without getters
|
||||
// May be expanded in the future.
|
||||
define_message_ext! {
|
||||
// MessageCommon
|
||||
|
@ -92,7 +95,7 @@ define_message_ext! {
|
|||
(filter_migration_from, Message::migrate_from_chat_id),
|
||||
(filter_migration_to, Message::migrate_to_chat_id),
|
||||
(filter_reply_to_message, Message::reply_to_message),
|
||||
(filter_forward_from, Message::forward_from),
|
||||
(filter_forward_origin, Message::forward_origin),
|
||||
// Rest variants of a MessageKind
|
||||
(filter_new_chat_members, Message::new_chat_members),
|
||||
(filter_left_chat_member, Message::left_chat_member),
|
||||
|
@ -117,6 +120,10 @@ define_message_ext! {
|
|||
(filter_forum_topic_reopened, Message::forum_topic_reopened),
|
||||
(filter_general_forum_topic_hidden, Message::general_forum_topic_hidden),
|
||||
(filter_general_forum_topic_unhidden, Message::general_forum_topic_unhidden),
|
||||
(filter_giveaway, Message::giveaway),
|
||||
(filter_giveaway_completed, Message::giveaway_completed),
|
||||
(filter_giveaway_created, Message::giveaway_created),
|
||||
(filter_giveaway_winners, Message::giveaway_winners),
|
||||
(filter_video_chat_scheduled, Message::video_chat_scheduled),
|
||||
(filter_video_chat_started, Message::video_chat_started),
|
||||
(filter_video_chat_ended, Message::video_chat_ended),
|
||||
|
@ -146,6 +153,8 @@ define_update_ext! {
|
|||
(filter_edited_message, UpdateKind::EditedMessage, EditedMessage),
|
||||
(filter_channel_post, UpdateKind::ChannelPost, ChannelPost),
|
||||
(filter_edited_channel_post, UpdateKind::EditedChannelPost, EditedChannelPost),
|
||||
(filter_message_reaction_updated, UpdateKind::MessageReaction, MessageReaction),
|
||||
(filter_message_reaction_count_updated, UpdateKind::MessageReactionCount, MessageReactionCount),
|
||||
(filter_inline_query, UpdateKind::InlineQuery, InlineQuery),
|
||||
(filter_chosen_inline_result, UpdateKind::ChosenInlineResult, ChosenInlineResult),
|
||||
(filter_callback_query, UpdateKind::CallbackQuery, CallbackQuery),
|
||||
|
@ -156,4 +165,6 @@ define_update_ext! {
|
|||
(filter_my_chat_member, UpdateKind::MyChatMember, MyChatMember),
|
||||
(filter_chat_member, UpdateKind::ChatMember, ChatMember),
|
||||
(filter_chat_join_request, UpdateKind::ChatJoinRequest, ChatJoinRequest),
|
||||
(filter_chat_boost, UpdateKind::ChatBoost, ChatBoost),
|
||||
(filter_removed_chat_boost, UpdateKind::RemovedChatBoost, RemovedChatBoost),
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ impl EventKind for Kind {
|
|||
EditedMessage,
|
||||
ChannelPost,
|
||||
EditedChannelPost,
|
||||
MessageReaction,
|
||||
MessageReactionCount,
|
||||
InlineQuery,
|
||||
ChosenInlineResult,
|
||||
CallbackQuery,
|
||||
|
@ -75,6 +77,8 @@ impl EventKind for Kind {
|
|||
MyChatMember,
|
||||
ChatMember,
|
||||
ChatJoinRequest,
|
||||
ChatBoost,
|
||||
RemovedChatBoost,
|
||||
]
|
||||
.into_iter()
|
||||
.map(Kind)
|
||||
|
@ -91,10 +95,12 @@ mod tests {
|
|||
#[cfg(feature = "macros")]
|
||||
use crate::{
|
||||
self as teloxide, // fixup for the `BotCommands` macro
|
||||
dispatching::{HandlerExt, UpdateFilterExt},
|
||||
dispatching::{handler_description::Kind, HandlerExt, UpdateFilterExt},
|
||||
types::{AllowedUpdate::*, Update},
|
||||
utils::command::BotCommands,
|
||||
};
|
||||
#[cfg(feature = "macros")]
|
||||
use dptree::description::EventKind;
|
||||
|
||||
#[cfg(feature = "macros")]
|
||||
#[derive(BotCommands, Clone)]
|
||||
|
@ -128,4 +134,43 @@ mod tests {
|
|||
fn discussion_648() {
|
||||
panic!("this test requires `macros` feature")
|
||||
}
|
||||
|
||||
// Test that all possible updates are specified in `Kind::full_set()`
|
||||
#[test]
|
||||
#[cfg(feature = "macros")]
|
||||
fn allowed_updates_full_set() {
|
||||
let full_set = Kind::full_set();
|
||||
let allowed_updates_reference = vec![
|
||||
Message,
|
||||
EditedMessage,
|
||||
ChannelPost,
|
||||
EditedChannelPost,
|
||||
MessageReaction,
|
||||
MessageReactionCount,
|
||||
InlineQuery,
|
||||
ChosenInlineResult,
|
||||
CallbackQuery,
|
||||
ShippingQuery,
|
||||
PreCheckoutQuery,
|
||||
Poll,
|
||||
PollAnswer,
|
||||
MyChatMember,
|
||||
ChatMember,
|
||||
ChatJoinRequest,
|
||||
ChatBoost,
|
||||
RemovedChatBoost,
|
||||
];
|
||||
|
||||
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 => {
|
||||
assert!(full_set.contains(&Kind(update)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 `6.9` of [Telegram Bot API] is
|
||||
//! your business logic. Currently, version `7.0` of [Telegram Bot API] is
|
||||
//! supported.
|
||||
//!
|
||||
//! For a high-level overview, see [our GitHub repository](https://github.com/teloxide/teloxide).
|
||||
|
|
|
@ -14,6 +14,16 @@ pub fn bold(s: &str) -> String {
|
|||
format!("<b>{s}</b>")
|
||||
}
|
||||
|
||||
/// Applies the block quotation style to the string.
|
||||
///
|
||||
/// Passed string will not be automatically escaped because it can contain
|
||||
/// nested markup.
|
||||
#[must_use = "This function returns a new string, rather than mutating the argument, so calling it \
|
||||
without using its output does nothing useful"]
|
||||
pub fn blockquote(s: &str) -> String {
|
||||
format!("<blockquote>{s}</blockquote>")
|
||||
}
|
||||
|
||||
/// Applies the italic font style to the string.
|
||||
///
|
||||
/// Passed string will not be automatically escaped because it can contain
|
||||
|
|
|
@ -14,6 +14,16 @@ pub fn bold(s: &str) -> String {
|
|||
format!("*{s}*")
|
||||
}
|
||||
|
||||
/// Applies the block quotation style to the string.
|
||||
///
|
||||
/// Passed string will not be automatically escaped because it can contain
|
||||
/// nested markup.
|
||||
#[must_use = "This function returns a new string, rather than mutating the argument, so calling it \
|
||||
without using its output does nothing useful"]
|
||||
pub fn blockquote(s: &str) -> String {
|
||||
format!(">{s}")
|
||||
}
|
||||
|
||||
/// Applies the italic font style to the string.
|
||||
///
|
||||
/// Can be safely used with `utils::markdown::underline()`.
|
||||
|
|
Loading…
Reference in a new issue