Add request for multiple users

This commit is contained in:
Сырцев Вадим Игоревич 2024-07-16 14:14:05 +03:00 committed by Andrey Brusnik
parent fcf3a14510
commit 7dc7047ea1
No known key found for this signature in database
GPG key ID: D33232F28CFF442C
6 changed files with 67 additions and 49 deletions

View file

@ -116,7 +116,7 @@ pub use unit_true::*;
pub use update::*; pub use update::*;
pub use user::*; pub use user::*;
pub use user_profile_photos::*; pub use user_profile_photos::*;
pub use user_shared::*; pub use users_shared::*;
pub use venue::*; pub use venue::*;
pub use video::*; pub use video::*;
pub use video_chat_ended::*; pub use video_chat_ended::*;
@ -219,7 +219,7 @@ mod unit_true;
mod update; mod update;
mod user; mod user;
mod user_profile_photos; mod user_profile_photos;
mod user_shared; mod users_shared;
mod venue; mod venue;
mod video; mod video;
mod video_chat_ended; mod video_chat_ended;

View file

@ -1,7 +1,7 @@
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
use crate::types::{ use crate::types::{
KeyboardButtonPollType, KeyboardButtonRequestChat, KeyboardButtonRequestUser, True, WebAppInfo, KeyboardButtonPollType, KeyboardButtonRequestChat, KeyboardButtonRequestUsers, True, WebAppInfo,
}; };
/// This object represents one button of the reply keyboard. /// This object represents one button of the reply keyboard.
@ -68,10 +68,10 @@ pub enum ButtonRequest {
/// [`chat_shared`]: crate::types::MessageKind::ChatShared /// [`chat_shared`]: crate::types::MessageKind::ChatShared
RequestChat(KeyboardButtonRequestChat), RequestChat(KeyboardButtonRequestChat),
/// If this variant is used, pressing the button will open a list of /// If specified, pressing the button will open a list of suitable users.
/// suitable users. Tapping on any user will send their identifier to the /// Identifiers of selected users will be sent to the bot in a
/// bot in a “user_shared” service message. /// “users_shared” service message. Available in private chats only.
RequestUser(KeyboardButtonRequestUser), RequestUsers(KeyboardButtonRequestUsers),
/// If this variant is used, the user will be asked to create a poll and /// 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. /// send it to the bot when the button is pressed.
@ -110,10 +110,10 @@ struct RawRequest {
chat: Option<KeyboardButtonRequestChat>, chat: Option<KeyboardButtonRequestChat>,
/// If specified, pressing the button will open a list of suitable users. /// 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 /// Identifiers of selected users will be sent to the bot in a
/// “user_shared” service message. Available in private chats only. /// “users_shared” service message. Available in private chats only.
#[serde(rename = "request_user")] #[serde(rename = "request_users")]
user: Option<KeyboardButtonRequestUser>, users: Option<KeyboardButtonRequestUsers>,
/// If specified, the user will be asked to create a poll and /// 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 /// 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)?; let raw = RawRequest::deserialize(deserializer)?;
match raw { 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 if 1 < (contact.is_some() as u8
+ location.is_some() as u8 + location.is_some() as u8
+ chat.is_some() as u8 + chat.is_some() as u8
+ user.is_some() as u8 + users.is_some() as u8
+ poll.is_some() as u8 + poll.is_some() as u8
+ web_app.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 { contact: Some(True), .. } => Ok(Self::Contact),
RawRequest { location: Some(True), .. } => Ok(Self::Location), RawRequest { location: Some(True), .. } => Ok(Self::Location),
RawRequest { chat: Some(request_chat), .. } => Ok(Self::RequestChat(request_chat)), 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 { poll: Some(poll_type), .. } => Ok(Self::Poll(poll_type)),
RawRequest { web_app: Some(web_app), .. } => Ok(Self::WebApp(web_app)), RawRequest { web_app: Some(web_app), .. } => Ok(Self::WebApp(web_app)),
@ -158,11 +158,11 @@ impl<'de> Deserialize<'de> for ButtonRequest {
contact: None, contact: None,
location: None, location: None,
chat: None, chat: None,
user: None, users: None,
poll: None, poll: None,
web_app: None, web_app: None,
} => Err(D::Error::custom( } => 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", `request_location`, `request_poll` and `web_app` fields is required",
)), )),
} }
@ -178,7 +178,7 @@ impl Serialize for ButtonRequest {
contact: None, contact: None,
location: None, location: None,
chat: None, chat: None,
user: None, users: None,
poll: None, poll: None,
web_app: None, web_app: None,
}; };
@ -187,7 +187,7 @@ impl Serialize for ButtonRequest {
Self::Contact => raw.contact = Some(True), Self::Contact => raw.contact = Some(True),
Self::Location => raw.location = Some(True), Self::Location => raw.location = Some(True),
Self::RequestChat(request_chat) => raw.chat = Some(request_chat.clone()), 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::Poll(poll_type) => raw.poll = Some(poll_type.clone()),
Self::WebApp(web_app) => raw.web_app = Some(web_app.clone()), Self::WebApp(web_app) => raw.web_app = Some(web_app.clone()),
}; };

View file

@ -1,15 +1,17 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// This object defines the criteria used to request a suitable user. The /// This object defines the criteria used to request a suitable users. The
/// identifier of the selected user will be shared with the bot when the /// identifiers of the selected users will be shared with the bot when the
/// corresponding button is pressed. More about requesting users » /// 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)] #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub struct KeyboardButtonRequestUser { pub struct KeyboardButtonRequestUsers {
/// identifier of the request, which will be received back in the /// Identifier of the request, which will be received back in the
/// [`UserShared`] object. Must be unique within the message. /// [`UsersShared`] object. Must be unique within the message.
/// ///
/// [`UserShared`]: crate::types::UserShared /// [`UsersShared`]: crate::types::UsersShared
pub request_id: i32, pub request_id: i32,
/// Pass `true` to request a bot, pass `false` to request a regular user. If /// Pass `true` to request a bot, pass `false` to request a regular user. If
@ -22,12 +24,16 @@ pub struct KeyboardButtonRequestUser {
/// applied. /// applied.
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
pub user_is_premium: Option<bool>, pub user_is_premium: Option<bool>,
/// The maximum number of users to be selected; 1-10. Defaults to 1.
#[serde(default = "de_max_quantity_default")]
pub max_quantity: u8,
} }
impl KeyboardButtonRequestUser { impl KeyboardButtonRequestUsers {
/// Creates a new [`KeyboardButtonRequestUser`]. /// Creates a new [`KeyboardButtonRequestUser`].
pub fn new(request_id: i32) -> Self { pub fn new(request_id: i32) -> Self {
Self { request_id, user_is_bot: None, user_is_premium: None } Self { request_id, user_is_bot: None, user_is_premium: None, max_quantity: 1 }
} }
/// Setter for `user_is_bot` field /// Setter for `user_is_bot` field
@ -41,4 +47,16 @@ impl KeyboardButtonRequestUser {
self.user_is_premium = Some(value); self.user_is_premium = Some(value);
self 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 de_max_quantity_default() -> u8 {
1
} }

View file

@ -10,7 +10,7 @@ use crate::types::{
GeneralForumTopicHidden, GeneralForumTopicUnhidden, InlineKeyboardMarkup, Invoice, Location, GeneralForumTopicHidden, GeneralForumTopicUnhidden, InlineKeyboardMarkup, Invoice, Location,
MessageAutoDeleteTimerChanged, MessageEntity, MessageEntityRef, MessageId, PassportData, MessageAutoDeleteTimerChanged, MessageEntity, MessageEntityRef, MessageId, PassportData,
PhotoSize, Poll, ProximityAlertTriggered, Sticker, Story, SuccessfulPayment, ThreadId, True, PhotoSize, Poll, ProximityAlertTriggered, Sticker, Story, SuccessfulPayment, ThreadId, True,
User, UserShared, Venue, Video, VideoChatEnded, VideoChatParticipantsInvited, User, UsersShared, Venue, Video, VideoChatEnded, VideoChatParticipantsInvited,
VideoChatScheduled, VideoChatStarted, VideoNote, Voice, WebAppData, WriteAccessAllowed, VideoChatScheduled, VideoChatStarted, VideoNote, Voice, WebAppData, WriteAccessAllowed,
}; };
@ -61,7 +61,7 @@ pub enum MessageKind {
MessageAutoDeleteTimerChanged(MessageMessageAutoDeleteTimerChanged), MessageAutoDeleteTimerChanged(MessageMessageAutoDeleteTimerChanged),
Pinned(MessagePinned), Pinned(MessagePinned),
ChatShared(MessageChatShared), ChatShared(MessageChatShared),
UserShared(MessageUserShared), UsersShared(MessageUsersShared),
Invoice(MessageInvoice), Invoice(MessageInvoice),
SuccessfulPayment(MessageSuccessfulPayment), SuccessfulPayment(MessageSuccessfulPayment),
ConnectedWebsite(MessageConnectedWebsite), ConnectedWebsite(MessageConnectedWebsite),
@ -256,9 +256,9 @@ pub struct MessageChatShared {
} }
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MessageUserShared { pub struct MessageUsersShared {
/// A chat was shared with the bot. /// Users were shared with the bot
pub user_shared: UserShared, pub users_shared: UsersShared,
} }
#[serde_with::skip_serializing_none] #[serde_with::skip_serializing_none]
@ -682,7 +682,7 @@ mod getters {
MessageDice, MessageEntity, MessageGroupChatCreated, MessageId, MessageInvoice, MessageDice, MessageEntity, MessageGroupChatCreated, MessageId, MessageInvoice,
MessageLeftChatMember, MessageNewChatMembers, MessageNewChatPhoto, MessageNewChatTitle, MessageLeftChatMember, MessageNewChatMembers, MessageNewChatPhoto, MessageNewChatTitle,
MessagePassportData, MessagePinned, MessageProximityAlertTriggered, MessagePassportData, MessagePinned, MessageProximityAlertTriggered,
MessageSuccessfulPayment, MessageSupergroupChatCreated, MessageUserShared, MessageSuccessfulPayment, MessageSupergroupChatCreated, MessageUsersShared,
MessageVideoChatParticipantsInvited, PhotoSize, User, MessageVideoChatParticipantsInvited, PhotoSize, User,
}; };
@ -1306,9 +1306,9 @@ mod getters {
} }
#[must_use] #[must_use]
pub fn shared_user(&self) -> Option<&types::UserShared> { pub fn shared_users(&self) -> Option<&types::UsersShared> {
match &self.kind { match &self.kind {
UserShared(MessageUserShared { user_shared }) => Some(user_shared), UsersShared(MessageUsersShared { users_shared }) => Some(users_shared),
_ => None, _ => None,
} }
} }

View file

@ -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,
}

View file

@ -0,0 +1,15 @@
use serde::{Deserialize, Serialize};
use crate::types::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: i32,
/// Identifiers of the shared users
pub user_ids: Vec<UserId>,
}