Add request chat and user

This commit is contained in:
Awiteb 2024-02-06 06:41:43 +03:00
parent f52665dbd0
commit dbf3e66a99
No known key found for this signature in database
GPG key ID: 16C8AD0B49C39C88
9 changed files with 441 additions and 58 deletions

View file

@ -17,6 +17,7 @@ pub use chat_member::*;
pub use chat_member_updated::*;
pub use chat_permissions::*;
pub use chat_photo::*;
pub use chat_shared::*;
pub use chat_type::*;
pub use chosen_inline_result::*;
pub use contact::*;
@ -67,6 +68,8 @@ pub use input_sticker::*;
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 label_price::*;
pub use location::*;
pub use login_url::*;
@ -106,6 +109,7 @@ pub use unit_true::*;
pub use update::*;
pub use user::*;
pub use user_profile_photos::*;
pub use user_shared::*;
pub use venue::*;
pub use video::*;
pub use video_chat_ended::*;
@ -136,6 +140,7 @@ mod chat_member;
mod chat_member_updated;
mod chat_permissions;
mod chat_photo;
mod chat_shared;
mod chat_type;
mod chosen_inline_result;
mod contact;
@ -162,6 +167,8 @@ mod input_sticker;
mod invoice;
mod keyboard_button;
mod keyboard_button_poll_type;
mod keyboard_button_request_chat;
mod keyboard_button_request_user;
mod label_price;
mod location;
mod login_url;
@ -198,6 +205,7 @@ mod unit_true;
mod update;
mod user;
mod user_profile_photos;
mod user_shared;
mod venue;
mod video;
mod video_chat_ended;

View file

@ -632,15 +632,46 @@ impl ChatMemberKind {
}
}
/// Returns `true` if the user is allowed to send audios, documents, photos,
/// videos, video notes and voice notes.
///
/// I.e. returns **`false`** if the user
/// - has left or has been banned in the chat
/// - is restricted and doesn't have all send media right
/// Returns `true` otherwise.
#[must_use]
pub fn can_send_media_messages(&self) -> bool {
match &self {
Self::Restricted(Restricted {
can_send_audios,
can_send_documents,
can_send_photos,
can_send_videos,
can_send_video_notes,
can_send_voice_notes,
..
}) => {
*can_send_audios
&& *can_send_documents
&& *can_send_photos
&& *can_send_videos
&& *can_send_video_notes
&& *can_send_voice_notes
}
Self::Owner(_) | Self::Administrator(_) | Self::Member => true,
Self::Left | Self::Banned(_) => false,
}
}
/// Returns `true` if the user is allowed to send animations, games,
/// stickers and use inline bots.
///
/// I.e. returns **`false`** if the user
/// - has left or has been banned from the chat
/// - is restricted and doesn't have the [`can_send_media_messages`] right
/// - is restricted and has no [`can_send_other_messages`] right
/// Returns `true` otherwise.
///
/// [`can_send_media_messages`]: Restricted::can_send_media_messages
/// [`can_send_other_messages`]: Restricted::can_send_other_messages
#[deprecated(
since = "0.9.0",
note = "Match manually and use `can_send_other_messages` field directly. Details: https://github.com/teloxide/teloxide/issues/781"
@ -661,10 +692,10 @@ impl ChatMemberKind {
///
/// I.e. returns **`false`** if the user
/// - has left or has been banned from the chat
/// - is restricted and doesn't have the [`can_send_media_messages`] right
/// - is restricted and has no [`can_add_web_page_previews`] right
/// Returns `true` otherwise.
///
/// [`can_send_media_messages`]: Restricted::can_send_media_messages
/// [`can_add_web_page_previews`]: Restricted::can_add_web_page_previews
#[deprecated(
since = "0.9.0",
note = "Match manually and use `can_add_web_page_previews` field directly. Details: https://github.com/teloxide/teloxide/issues/781"
@ -884,6 +915,7 @@ mod tests {
"status":"restricted",
"is_member": true,
"can_send_messages": true,
"can_send_media_messages": true,
"can_send_audios": false,
"can_send_documents": false,
"can_send_photos": true,

View file

@ -51,59 +51,69 @@ bitflags::bitflags! {
/// locations and venues.
const SEND_MESSAGES = 1;
/// Set if the user is allowed to send audios.
const SEND_AUDIOS = (1 << 1) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send documents.
const SEND_DOCUMENTS = (1 << 2) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send photos.
const SEND_PHOTOS = (1 << 3) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send videos.
const SEND_VIDEOS = (1 << 4) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send video notes.
const SEND_VIDEO_NOTES = (1 << 5) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send voice notes.
const SEND_VOICE_NOTES = (1 << 6) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send polls, implies
/// `SEND_MESSAGES`.
const SEND_POLLS = (1 << 7) | Self::SEND_MESSAGES.bits;
const SEND_POLLS = (1 << 2) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send animations, games, stickers and
/// use inline bots, implies midia messages permissions.
const SEND_OTHER_MESSAGES = (1 << 8) | Self::SEND_AUDIOS.bits
| Self::SEND_DOCUMENTS.bits
| Self::SEND_PHOTOS.bits
| Self::SEND_VIDEOS.bits
| Self::SEND_VIDEO_NOTES.bits
| Self::SEND_VOICE_NOTES.bits;
/// use inline bots, implies `SEND_MEDIA_MESSAGES`.
const SEND_OTHER_MESSAGES = (1 << 3);
/// Set if the user is allowed to add web page previews to
/// their messages, implies midia messages permissions.
const ADD_WEB_PAGE_PREVIEWS = (1 << 9) | Self::SEND_AUDIOS.bits
| Self::SEND_DOCUMENTS.bits
| Self::SEND_PHOTOS.bits
| Self::SEND_VIDEOS.bits
| Self::SEND_VIDEO_NOTES.bits
| Self::SEND_VOICE_NOTES.bits;
/// their messages, implies `SEND_MEDIA_MESSAGES`.
const ADD_WEB_PAGE_PREVIEWS = (1 << 4);
/// Set if the user is allowed to change the chat title, photo and
/// other settings. Ignored in public supergroups.
const CHANGE_INFO = (1 << 10);
const CHANGE_INFO = (1 << 5);
/// Set if the user is allowed to invite new users to the chat.
const INVITE_USERS = (1 << 11);
const INVITE_USERS = (1 << 6);
/// Set if the user is allowed to pin messages. Ignored in public
/// supergroups.
const PIN_MESSAGES = (1 << 12);
const PIN_MESSAGES = (1 << 7);
/// Set if the user is allowed to create, rename, close, and reopen forum topics.
const MANAGE_TOPICS = (1 << 13);
const MANAGE_TOPICS = (1 << 8);
/// Set if the user is allowed to send audios. implies
/// `SEND_MESSAGES`.
const SEND_AUDIOS = (1 << 9) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send documents. implies
/// `SEND_MESSAGES`.
const SEND_DOCUMENTS = (1 << 10) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send photos. implies
/// `SEND_MESSAGES`.
const SEND_PHOTOS = (1 << 11) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send videos. implies
/// `SEND_MESSAGES`.
const SEND_VIDEOS = (1 << 12) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send video notes. implies
/// `SEND_MESSAGES`.
const SEND_VIDEO_NOTES = (1 << 13) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send voice notes. implies
/// `SEND_MESSAGES`.
const SEND_VOICE_NOTES = (1 << 14) | Self::SEND_MESSAGES.bits;
/// Set if the user is allowed to send audios, documents,
/// photos, videos, video notes and voice notes, implies
/// `SEND_MESSAGES`, `SEND_AUDIOS`, `SEND_DOCUMENTS`,
/// `SEND_PHOTOS`, `SEND_VIDEOS`, `SEND_VIDEO_NOTES` and `SEND_VOICE_NOTES`.
/// Note: this is not a separate permission on it's own, this is just a alias for all the permissions mentioned.
const SEND_MEDIA_MESSAGES = Self::SEND_MESSAGES.bits
| Self::SEND_AUDIOS.bits
| Self::SEND_DOCUMENTS.bits
| Self::SEND_PHOTOS.bits
| Self::SEND_VIDEOS.bits
| Self::SEND_VIDEO_NOTES.bits
| Self::SEND_VOICE_NOTES.bits;
}
}
@ -157,6 +167,13 @@ impl ChatPermissions {
self.contains(ChatPermissions::SEND_VOICE_NOTES)
}
/// Checks for [`SEND_MEDIA_MESSAGES`] permission.
///
/// [`SEND_MEDIA_MESSAGES`]: ChatPermissions::SEND_MEDIA_MESSAGES
pub fn can_send_media_messages(&self) -> bool {
self.contains(ChatPermissions::SEND_MEDIA_MESSAGES)
}
/// Checks for [`SEND_POLLS`] permission.
///
/// [`SEND_POLLS`]: ChatPermissions::SEND_POLLS

View file

@ -0,0 +1,15 @@
use serde::{Deserialize, Serialize};
use crate::types::ChatId;
/// Information about the chat whose identifier was shared with the bot using a
/// [`KeyboardButtonRequestChat`] button.
///
/// [`KeyboardButtonRequestChat`]: crate::types::KeyboardButtonRequestChat
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct ChatShared {
/// Identifier of the request.
pub request_id: i32,
/// Identifier of the shared chat.
pub chat_id: ChatId,
}

View file

@ -1,6 +1,8 @@
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
use crate::types::{KeyboardButtonPollType, True, WebAppInfo};
use crate::types::{
KeyboardButtonPollType, KeyboardButtonRequestChat, KeyboardButtonRequestUser, True, WebAppInfo,
};
/// This object represents one button of the reply keyboard.
///
@ -59,6 +61,18 @@ pub enum ButtonRequest {
/// 9 April, 2016. Older clients will display unsupported message.
Contact,
/// If this variant is used, pressing the button will open a list of
/// suitable chats. Tapping on a chat will send its identifier to the bot in
/// a [`chat_shared`] service message.
///
/// [`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 this variant is used, the user will be asked to create a poll and
/// send it to the bot when the button is pressed.
///
@ -89,6 +103,18 @@ struct RawRequest {
#[serde(rename = "request_location")]
location: Option<True>,
/// If specified, pressing the button will open a list of suitable chats.
/// Tapping on a chat will send its identifier to the bot in a “chat_shared”
/// service message. Available in private chats only.
#[serde(rename = "request_chat")]
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>,
/// 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
/// chats only.
@ -108,25 +134,36 @@ impl<'de> Deserialize<'de> for ButtonRequest {
{
let raw = RawRequest::deserialize(deserializer)?;
match raw {
RawRequest { contact, location, poll, web_app }
RawRequest { contact, location, chat, user, 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
+ poll.is_some() as u8
+ web_app.is_some() as u8) =>
{
Err(D::Error::custom(
"`request_contact`, `request_location`, `request_poll` and `web_app` fields \
are mutually exclusive",
"`request_contact`, `request_location`, `request_chat`, `request_user`, \
`request_poll` and `web_app` fields are mutually exclusive",
))
}
RawRequest { contact: Some(_), .. } => Ok(Self::Contact),
RawRequest { location: Some(_), .. } => Ok(Self::Location),
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 { poll: Some(poll_type), .. } => Ok(Self::Poll(poll_type)),
RawRequest { web_app: Some(web_app), .. } => Ok(Self::WebApp(web_app)),
_ => Err(D::Error::custom(
"Either one of `request_contact`, `request_location`, `request_poll` and \
`web_app` fields is required",
RawRequest {
contact: None,
location: None,
chat: None,
user: None,
poll: None,
web_app: None,
} => Err(D::Error::custom(
"Either one of `request_contact`, `request_chat`, `request_user`, \
`request_location`, `request_poll` and `web_app` fields is required",
)),
}
}
@ -137,11 +174,20 @@ impl Serialize for ButtonRequest {
where
S: Serializer,
{
let mut raw = RawRequest { contact: None, location: None, poll: None, web_app: None };
let mut raw = RawRequest {
contact: None,
location: None,
chat: None,
user: None,
poll: None,
web_app: None,
};
match self {
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::Poll(poll_type) => raw.poll = Some(poll_type.clone()),
Self::WebApp(web_app) => raw.web_app = Some(web_app.clone()),
};
@ -171,6 +217,17 @@ mod tests {
assert_eq!(expected, actual);
}
#[test]
fn serialize_chat_request() {
let button = KeyboardButton {
text: String::from(""),
request: Some(ButtonRequest::RequestChat(KeyboardButtonRequestChat::new(0, false))),
};
let expected = r#"{"text":"","request_chat":{"request_id":0,"chat_is_channel":false}}"#;
let actual = serde_json::to_string(&button).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn deserialize_no_request() {
let json = r#"{"text":""}"#;

View file

@ -0,0 +1,114 @@
use serde::{Deserialize, Serialize};
use crate::types::ChatAdministratorRights;
/// This object defines the criteria used to request a suitable chat. The
/// identifier of the selected chat will be shared with the bot when the
/// corresponding button is pressed. [More about requesting chats »]
///
/// [More about requesting chats »]: 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 KeyboardButtonRequestChat {
/// identifier of the request, which will be received back in the
/// [`ChatShared`] object. Must be unique within the message.
///
/// [`ChatShared`]: crate::types::ChatShared
pub request_id: i32,
/// Pass `true` to request a channel chat, pass `false` to request a group
/// or a supergroup chat.
pub chat_is_channel: bool,
/// Pass `true` to request a forum supergroup, pass `false` to request a
/// non-forum chat. If not specified, no additional restrictions are
/// applied.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub chat_is_forum: Option<bool>,
/// Pass `true` to request a supergroup or a channel with a username, pass
/// `false` to request a chat without a username. If not specified, no
/// additional restrictions are applied.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub chat_has_username: Option<bool>,
/// Pass `true` to request a chat owned by the user. Otherwise, no
/// additional restrictions are applied.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub chat_is_created: Option<bool>,
/// Listing the required administrator rights of the user in the chat. The
/// rights must be a superset of bot_administrator_rights. If not specified,
/// no additional restrictions are applied.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_administrator_rights: Option<ChatAdministratorRights>,
/// Listing the required administrator rights of the bot in the chat. The
/// rights must be a subset of user_administrator_rights. If not specified,
/// no additional restrictions are applied.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bot_administrator_rights: Option<ChatAdministratorRights>,
/// Pass `true` to request a chat with the bot as a member. Otherwise, no
/// additional restrictions are applied.
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub bot_is_member: bool,
}
impl KeyboardButtonRequestChat {
/// Creates a new [`KeyboardButtonRequestChat`].
pub fn new(request_id: i32, chat_is_channel: bool) -> Self {
Self {
request_id,
chat_is_channel,
chat_is_forum: None,
chat_has_username: None,
chat_is_created: None,
user_administrator_rights: None,
bot_administrator_rights: None,
bot_is_member: false,
}
}
/// Setter for `chat_is_forum` field.
#[must_use]
pub fn chat_is_forum(mut self, value: bool) -> Self {
self.chat_is_forum = Some(value);
self
}
/// Setter for `chat_has_username` field.
#[must_use]
pub fn chat_has_username(mut self, value: bool) -> Self {
self.chat_has_username = Some(value);
self
}
/// Setter for `chat_is_created` field.
#[must_use]
pub fn chat_is_created(mut self, value: bool) -> Self {
self.chat_is_created = Some(value);
self
}
/// Request a chat where the user has the specified administrator rights.
#[must_use]
pub fn user_administrator_rights(mut self, rights: ChatAdministratorRights) -> Self {
self.user_administrator_rights = Some(rights);
self
}
/// Request a chat where the bot has the specified administrator rights.
#[must_use]
pub fn bot_administrator_rights(mut self, rights: ChatAdministratorRights) -> Self {
self.bot_administrator_rights = Some(rights);
self
}
/// Setter for `bot_is_member` field.
#[must_use]
pub fn bot_is_member(mut self, value: bool) -> Self {
self.bot_is_member = value;
self
}
}

View file

@ -0,0 +1,44 @@
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
/// corresponding button is pressed. More about requesting users »
#[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.
///
/// [`UserShared`]: crate::types::UserShared
pub request_id: i32,
/// Pass `true` to request a bot, pass `false` to request a regular user. If
/// not specified, no additional restrictions are applied.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_is_bot: Option<bool>,
/// Pass `true` to request a premium user, pass `false` to request a
/// non-premium user. If not specified, no additional restrictions are
/// applied.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_is_premium: Option<bool>,
}
impl KeyboardButtonRequestUser {
/// Creates a new [`KeyboardButtonRequestUser`].
pub fn new(request_id: i32) -> Self {
Self { request_id, user_is_bot: None, user_is_premium: None }
}
/// Setter for `user_is_bot` field
pub fn user_is_bot(mut self, value: bool) -> Self {
self.user_is_bot = Some(value);
self
}
/// Setter for `user_is_premium` field
pub fn user_is_premium(mut self, value: bool) -> Self {
self.user_is_premium = Some(value);
self
}
}

View file

@ -5,12 +5,12 @@ use serde::{Deserialize, Serialize};
use url::Url;
use crate::types::{
Animation, Audio, BareChatId, Chat, ChatId, Contact, Dice, Document, ForumTopicClosed,
ForumTopicCreated, ForumTopicEdited, ForumTopicReopened, Game, GeneralForumTopicHidden,
GeneralForumTopicUnhidden, InlineKeyboardMarkup, Invoice, Location,
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, SuccessfulPayment, ThreadId, True, User,
Venue, Video, VideoChatEnded, VideoChatParticipantsInvited, VideoChatScheduled,
UserShared, Venue, Video, VideoChatEnded, VideoChatParticipantsInvited, VideoChatScheduled,
VideoChatStarted, VideoNote, Voice, WebAppData, WriteAccessAllowed,
};
@ -60,6 +60,8 @@ pub enum MessageKind {
ChannelChatCreated(MessageChannelChatCreated),
MessageAutoDeleteTimerChanged(MessageMessageAutoDeleteTimerChanged),
Pinned(MessagePinned),
ChatShared(MessageChatShared),
UserShared(MessageUserShared),
Invoice(MessageInvoice),
SuccessfulPayment(MessageSuccessfulPayment),
ConnectedWebsite(MessageConnectedWebsite),
@ -247,6 +249,18 @@ pub struct MessagePinned {
pub pinned: Box<Message>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MessageChatShared {
/// A chat was shared with the bot.
pub chat_shared: ChatShared,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MessageUserShared {
/// A chat was shared with the bot.
pub user_shared: UserShared,
}
#[serde_with_macros::skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MessageInvoice {
@ -655,12 +669,13 @@ mod getters {
self, message::MessageKind::*, Chat, ChatId, ChatMigration, Forward, ForwardedFrom,
MediaAnimation, MediaAudio, MediaContact, MediaDocument, MediaGame, MediaKind,
MediaLocation, MediaPhoto, MediaPoll, MediaSticker, MediaText, MediaVenue, MediaVideo,
MediaVideoNote, MediaVoice, Message, MessageChannelChatCreated, MessageCommon,
MessageConnectedWebsite, MessageDeleteChatPhoto, MessageDice, MessageEntity,
MediaVideoNote, MediaVoice, Message, MessageChannelChatCreated, MessageChatShared,
MessageCommon, MessageConnectedWebsite, MessageDeleteChatPhoto, MessageDice, MessageEntity,
MessageGroupChatCreated, MessageId, MessageInvoice, MessageLeftChatMember,
MessageNewChatMembers, MessageNewChatPhoto, MessageNewChatTitle, MessagePassportData,
MessagePinned, MessageProximityAlertTriggered, MessageSuccessfulPayment,
MessageSupergroupChatCreated, MessageVideoChatParticipantsInvited, PhotoSize, User,
MessageSupergroupChatCreated, MessageUserShared, MessageVideoChatParticipantsInvited,
PhotoSize, User,
};
use super::{
@ -1269,6 +1284,22 @@ mod getters {
}
}
#[must_use]
pub fn shared_chat(&self) -> Option<&types::ChatShared> {
match &self.kind {
ChatShared(MessageChatShared { chat_shared }) => Some(chat_shared),
_ => None,
}
}
#[must_use]
pub fn shared_user(&self) -> Option<&types::UserShared> {
match &self.kind {
UserShared(MessageUserShared { user_shared }) => Some(user_shared),
_ => None,
}
}
#[must_use]
pub fn dice(&self) -> Option<&types::Dice> {
match &self.kind {
@ -1699,6 +1730,56 @@ mod tests {
assert!(message.is_ok());
}
#[test]
fn de_shared_chat() {
let json = r#"{
"message_id": 198283,
"chat": {
"id": 250918540,
"first_name": "Андрей",
"last_name": "Власов",
"username": "aka_dude",
"type": "private"
},
"date": 1567927221,
"chat_shared": {
"request_id": 348349,
"chat_id": 384939
}
}"#;
let message = from_str::<Message>(json);
assert!(message.is_ok());
assert_eq!(
message.unwrap(),
Message {
id: MessageId(198283),
thread_id: None,
date: chrono::NaiveDateTime::from_timestamp_opt(1567927221, 0).unwrap().and_utc(),
chat: Chat {
id: ChatId(250918540),
kind: ChatKind::Private(ChatPrivate {
first_name: Some("Андрей".to_string()),
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,
has_aggressive_anti_spam_enabled: false,
pinned_message: None,
message_auto_delete_time: None,
has_hidden_members: false
},
kind: MessageKind::ChatShared(MessageChatShared {
chat_shared: ChatShared { request_id: 348349, chat_id: ChatId(384939) }
}),
via_bot: None
}
);
}
#[test]
fn de_media_group_forwarded() {
let json = r#"{

View file

@ -0,0 +1,15 @@
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,
}