Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(twilight-model)!: Implement additional select menu types #2219

Merged
merged 7 commits into from
Jul 1, 2023
8 changes: 3 additions & 5 deletions twilight-cache-inmemory/src/event/interaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,8 @@ mod tests {
application::{
command::CommandType,
interaction::{
application_command::{
CommandData, CommandInteractionDataResolved, InteractionMember,
},
Interaction, InteractionData, InteractionType,
application_command::CommandData, Interaction, InteractionData,
InteractionDataResolved, InteractionMember, InteractionType,
},
},
channel::{
Expand Down Expand Up @@ -143,7 +141,7 @@ mod tests {
name: "command name".into(),
kind: CommandType::ChatInput, // This isn't actually a valid command, so just mark it as a slash command.
options: Vec::new(),
resolved: Some(CommandInteractionDataResolved {
resolved: Some(InteractionDataResolved {
attachments: HashMap::new(),
channels: HashMap::new(),
members: HashMap::from([(
Expand Down
2 changes: 1 addition & 1 deletion twilight-cache-inmemory/src/event/member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
};
use std::borrow::Cow;
use twilight_model::{
application::interaction::application_command::InteractionMember,
application::interaction::InteractionMember,
gateway::payload::incoming::{MemberAdd, MemberChunk, MemberRemove, MemberUpdate},
guild::{Member, PartialMember},
id::{
Expand Down
2 changes: 1 addition & 1 deletion twilight-cache-inmemory/src/model/member.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use serde::Serialize;
use twilight_model::{
application::interaction::application_command::InteractionMember,
application::interaction::InteractionMember,
guild::{Member, MemberFlags, PartialMember},
id::{
marker::{RoleMarker, UserMarker},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,11 @@
//! [`ApplicationCommand`]: crate::application::interaction::InteractionType::ApplicationCommand

mod option;
mod resolved;

pub use self::{
option::{CommandDataOption, CommandOptionValue},
resolved::{CommandInteractionDataResolved, InteractionChannel, InteractionMember},
};
pub use self::option::{CommandDataOption, CommandOptionValue};

use crate::{
application::command::CommandType,
application::{command::CommandType, interaction::InteractionDataResolved},
id::{
marker::{CommandMarker, GenericMarker, GuildMarker},
Id,
Expand Down Expand Up @@ -44,7 +40,7 @@ pub struct CommandData {
pub options: Vec<CommandDataOption>,
/// Resolved data from the interaction's options.
#[serde(skip_serializing_if = "Option::is_none")]
pub resolved: Option<CommandInteractionDataResolved>,
pub resolved: Option<InteractionDataResolved>,
/// If this is a user or message command, the ID of the targeted user/message.
#[serde(skip_serializing_if = "Option::is_none")]
pub target_id: Option<Id<GenericMarker>>,
Expand Down
22 changes: 15 additions & 7 deletions twilight-model/src/application/interaction/message_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
//!
//! [`MessageComponent`]: crate::application::interaction::InteractionType::MessageComponent

use crate::application::interaction::InteractionDataResolved;
use crate::channel::message::component::ComponentType;
use serde::{Deserialize, Serialize};

/// Data received when an [`MessageComponent`] interaction is executed.
/// Data received when a [`MessageComponent`] interaction is executed.
///
/// See [Discord Docs/Message Component Data Structure].
///
/// [`MessageComponent`]: crate::application::interaction::InteractionType::MessageComponent
/// [Discord Docs/Message Component Data Structure]: https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-message-component-data-structure
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct MessageComponentInteractionData {
/// User defined identifier for the component.
///
Expand All @@ -21,11 +22,17 @@ pub struct MessageComponentInteractionData {
pub custom_id: String,
/// Type of the component.
pub component_type: ComponentType,
/// Converted users, roles, channels, or attachments.
///
/// Only used for [`SelectMenu`] components.
///
/// [`SelectMenu`]: crate::channel::message::component::SelectMenu
pub resolved: Option<InteractionDataResolved>,
/// Values selected by the user.
///
/// Only used for [`SelectMenu`] components.
///
/// [`SelectMenu`]: ComponentType::SelectMenu
/// [`SelectMenu`]: crate::channel::message::component::SelectMenu
#[serde(default)]
pub values: Vec<String>,
}
Expand All @@ -37,7 +44,7 @@ mod tests {
use serde::{Deserialize, Serialize};
use serde_test::Token;
use static_assertions::{assert_fields, assert_impl_all};
use std::{fmt::Debug, hash::Hash};
use std::fmt::Debug;

assert_fields!(
MessageComponentInteractionData: custom_id,
Expand All @@ -48,8 +55,6 @@ mod tests {
MessageComponentInteractionData: Clone,
Debug,
Deserialize<'static>,
Eq,
Hash,
PartialEq,
Send,
Serialize,
Expand All @@ -61,6 +66,7 @@ mod tests {
let value = MessageComponentInteractionData {
custom_id: "test".to_owned(),
component_type: ComponentType::Button,
resolved: None,
values: Vec::from(["1".to_owned(), "2".to_owned()]),
};

Expand All @@ -69,12 +75,14 @@ mod tests {
&[
Token::Struct {
name: "MessageComponentInteractionData",
len: 3,
len: 4,
},
Token::String("custom_id"),
Token::String("test"),
Token::String("component_type"),
Token::U8(ComponentType::Button.into()),
Token::String("resolved"),
Token::None,
Token::String("values"),
Token::Seq { len: Some(2) },
Token::String("1"),
Expand Down
19 changes: 10 additions & 9 deletions twilight-model/src/application/interaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ pub mod message_component;
pub mod modal;

mod interaction_type;
mod resolved;

pub use self::interaction_type::InteractionType;
pub use self::{
interaction_type::InteractionType,
resolved::{InteractionChannel, InteractionDataResolved, InteractionMember},
};

use self::{
application_command::CommandData, message_component::MessageComponentInteractionData,
Expand Down Expand Up @@ -424,7 +428,7 @@ pub enum InteractionData {
/// Data received for the [`MessageComponent`] interaction type.
///
/// [`MessageComponent`]: InteractionType::MessageComponent
MessageComponent(MessageComponentInteractionData),
MessageComponent(Box<MessageComponentInteractionData>),
/// Data received for the [`ModalSubmit`] interaction type.
///
/// [`ModalSubmit`]: InteractionType::ModalSubmit
Expand All @@ -434,11 +438,8 @@ pub enum InteractionData {
#[cfg(test)]
mod tests {
use super::{
application_command::{
CommandData, CommandDataOption, CommandInteractionDataResolved, CommandOptionValue,
InteractionMember,
},
Interaction, InteractionData, InteractionType,
application_command::{CommandData, CommandDataOption, CommandOptionValue},
Interaction, InteractionData, InteractionDataResolved, InteractionMember, InteractionType,
};
use crate::{
application::command::{CommandOptionType, CommandType},
Expand Down Expand Up @@ -508,7 +509,7 @@ mod tests {
name: "member".into(),
value: CommandOptionValue::User(Id::new(600)),
}]),
resolved: Some(CommandInteractionDataResolved {
resolved: Some(InteractionDataResolved {
attachments: HashMap::new(),
channels: HashMap::new(),
members: IntoIterator::into_iter([(
Expand Down Expand Up @@ -652,7 +653,7 @@ mod tests {
Token::Str("resolved"),
Token::Some,
Token::Struct {
name: "CommandInteractionDataResolved",
name: "InteractionDataResolved",
len: 2,
},
Token::Str("members"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::collections::hash_map::HashMap;
/// [`ApplicationCommand`]: crate::application::interaction::InteractionType::ApplicationCommand
/// [Discord Docs/Resolved Data Structure]: https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-resolved-data-structure
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct CommandInteractionDataResolved {
pub struct InteractionDataResolved {
/// Map of resolved attachments.
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub attachments: HashMap<Id<AttachmentMarker>, Attachment>,
Expand Down Expand Up @@ -97,7 +97,7 @@ pub struct InteractionMember {

#[cfg(test)]
mod tests {
use super::{CommandInteractionDataResolved, InteractionChannel, InteractionMember};
use super::{InteractionChannel, InteractionDataResolved, InteractionMember};
use crate::{
channel::{
message::{
Expand All @@ -122,7 +122,7 @@ mod tests {
let timestamp = Timestamp::from_str("2020-02-02T02:02:02.020000+00:00")?;
let flags = MemberFlags::BYPASSES_VERIFICATION | MemberFlags::DID_REJOIN;

let value = CommandInteractionDataResolved {
let value = InteractionDataResolved {
attachments: IntoIterator::into_iter([(
Id::new(400),
Attachment {
Expand Down Expand Up @@ -282,7 +282,7 @@ mod tests {
&value,
&[
Token::Struct {
name: "CommandInteractionDataResolved",
name: "InteractionDataResolved",
len: 6,
},
Token::Str("attachments"),
Expand Down
50 changes: 43 additions & 7 deletions twilight-model/src/channel/message/component/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,30 @@ pub enum ComponentType {
///
/// [`Button`]: super::Button
Button,
/// Component is an [`SelectMenu`].
/// Component is a [`SelectMenu`] with custom string options.
///
/// [`SelectMenu`]: super::SelectMenu
SelectMenu,
TextSelectMenu,
/// Component is an [`TextInput`].
///
/// [`TextInput`]: super::TextInput
TextInput,
/// Component is a [`SelectMenu`] for users.
///
/// [`SelectMenu`]: super::SelectMenu
UserSelectMenu,
/// Component is a [`SelectMenu`] for roles.
///
/// [`SelectMenu`]: super::SelectMenu
RoleSelectMenu,
/// Component is a [`SelectMenu`] for mentionables.
///
/// [`SelectMenu`]: super::SelectMenu
MentionableSelectMenu,
/// Component is a [`SelectMenu`] for channels.
///
/// [`SelectMenu`]: super::SelectMenu
ChannelSelectMenu,
/// Variant value is unknown to the library.
Unknown(u8),
}
Expand All @@ -33,8 +49,12 @@ impl From<u8> for ComponentType {
match value {
1 => ComponentType::ActionRow,
2 => ComponentType::Button,
3 => ComponentType::SelectMenu,
3 => ComponentType::TextSelectMenu,
4 => ComponentType::TextInput,
5 => ComponentType::UserSelectMenu,
6 => ComponentType::RoleSelectMenu,
7 => ComponentType::MentionableSelectMenu,
8 => ComponentType::ChannelSelectMenu,
unknown => ComponentType::Unknown(unknown),
}
}
Expand All @@ -45,8 +65,12 @@ impl From<ComponentType> for u8 {
match value {
ComponentType::ActionRow => 1,
ComponentType::Button => 2,
ComponentType::SelectMenu => 3,
ComponentType::TextSelectMenu => 3,
ComponentType::TextInput => 4,
ComponentType::UserSelectMenu => 5,
ComponentType::RoleSelectMenu => 6,
ComponentType::MentionableSelectMenu => 7,
ComponentType::ChannelSelectMenu => 8,
ComponentType::Unknown(unknown) => unknown,
}
}
Expand All @@ -72,7 +96,11 @@ impl ComponentType {
match self {
Self::ActionRow => "ActionRow",
Self::Button => "Button",
Self::SelectMenu => "SelectMenu",
Self::TextSelectMenu
| Self::UserSelectMenu
| Self::RoleSelectMenu
| Self::MentionableSelectMenu
| Self::ChannelSelectMenu => "SelectMenu",
Self::TextInput => "TextInput",
Self::Unknown(_) => "Unknown",
}
Expand Down Expand Up @@ -110,16 +138,24 @@ mod tests {
fn variants() {
serde_test::assert_tokens(&ComponentType::ActionRow, &[Token::U8(1)]);
serde_test::assert_tokens(&ComponentType::Button, &[Token::U8(2)]);
serde_test::assert_tokens(&ComponentType::SelectMenu, &[Token::U8(3)]);
serde_test::assert_tokens(&ComponentType::TextSelectMenu, &[Token::U8(3)]);
serde_test::assert_tokens(&ComponentType::TextInput, &[Token::U8(4)]);
serde_test::assert_tokens(&ComponentType::UserSelectMenu, &[Token::U8(5)]);
serde_test::assert_tokens(&ComponentType::RoleSelectMenu, &[Token::U8(6)]);
serde_test::assert_tokens(&ComponentType::MentionableSelectMenu, &[Token::U8(7)]);
serde_test::assert_tokens(&ComponentType::ChannelSelectMenu, &[Token::U8(8)]);
serde_test::assert_tokens(&ComponentType::Unknown(99), &[Token::U8(99)]);
}

#[test]
fn names() {
assert_eq!("ActionRow", ComponentType::ActionRow.name());
assert_eq!("Button", ComponentType::Button.name());
assert_eq!("SelectMenu", ComponentType::SelectMenu.name());
assert_eq!("SelectMenu", ComponentType::TextSelectMenu.name());
assert_eq!("SelectMenu", ComponentType::UserSelectMenu.name());
assert_eq!("SelectMenu", ComponentType::RoleSelectMenu.name());
assert_eq!("SelectMenu", ComponentType::MentionableSelectMenu.name());
assert_eq!("SelectMenu", ComponentType::ChannelSelectMenu.name());
assert_eq!("TextInput", ComponentType::TextInput.name());
assert_eq!("Unknown", ComponentType::Unknown(99).name());
}
Expand Down
Loading