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(model, validate, cache)!: Add new select components #2051

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 37 additions & 5 deletions twilight-cache-inmemory/src/event/interaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl UpdateCache for InteractionCreate {
}
}

// Cache resolved interaction data
// Cache resolved interaction data from a command
if let Some(InteractionData::ApplicationCommand(data)) = &self.data {
if let Some(resolved) = &data.resolved {
// Cache resolved users and members
Expand Down Expand Up @@ -56,6 +56,39 @@ impl UpdateCache for InteractionCreate {
}
}
}

// Cache resolved interaction data from a message component
if let Some(InteractionData::MessageComponent(data)) = &self.data {
if let Some(resolved) = &data.resolved {
// Cache resolved users and members
for u in resolved.users.values() {
if cache.wants(ResourceType::USER) {
cache.cache_user(Cow::Borrowed(u), self.guild_id);
}

if !cache.wants(ResourceType::MEMBER) || self.guild_id.is_none() {
continue;
}

// This should always match, because resolved members
// are guaranteed to have a matching resolved user
if let Some((&id, member)) =
&resolved.members.iter().find(|(&id, _)| id == u.id)
{
if let Some(guild_id) = self.guild_id {
cache.cache_borrowed_interaction_member(guild_id, member, id);
}
}
}

// Cache resolved roles
if cache.wants(ResourceType::ROLE) {
if let Some(guild_id) = self.guild_id {
cache.cache_roles(guild_id, resolved.roles.values().cloned());
}
}
}
}
}
}

Expand All @@ -67,9 +100,8 @@ mod tests {
application::{
command::CommandType,
interaction::{
application_command::{
CommandData, CommandInteractionDataResolved, InteractionMember,
},
application_command::CommandData,
resolved::{InteractionDataResolved, InteractionMember},
Interaction, InteractionData, InteractionType,
},
},
Expand Down Expand Up @@ -107,7 +139,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::resolved::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::resolved::InteractionMember,
guild::{Member, PartialMember},
id::{
marker::{GuildMarker, 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::resolved::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
97 changes: 87 additions & 10 deletions twilight-model/src/application/interaction/message_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
//!
//! [`MessageComponent`]: crate::application::interaction::InteractionType::MessageComponent

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

/// Data received when an [`MessageComponent`] interaction is executed.
Expand All @@ -11,7 +14,15 @@ use serde::{Deserialize, Serialize};
///
/// [`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,
Eq,
// Hash,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just leaving a pr comment on this (todo?) for visibility

PartialEq,
Serialize,
)]
pub struct MessageComponentInteractionData {
/// User defined identifier for the component.
///
Expand All @@ -23,33 +34,41 @@ pub struct MessageComponentInteractionData {
pub component_type: ComponentType,
/// Values selected by the user.
///
/// Only used for [`SelectMenu`] components.
///
/// [`SelectMenu`]: ComponentType::SelectMenu
/// Only used for Select Menu components.
#[serde(default)]
pub values: Vec<String>,
/// Resolved data from the interaction's select menu.
///
/// Only used for Select Menu components.
pub resolved: Option<InteractionDataResolved>,
}

#[cfg(test)]
mod tests {
use super::MessageComponentInteractionData;
use crate::channel::message::component::ComponentType;
use crate::{
application::interaction::resolved::InteractionDataResolved,
channel::message::component::ComponentType,
guild::{Permissions, Role},
id::Id,
};
use serde::{Deserialize, Serialize};
use serde_test::Token;
use static_assertions::{assert_fields, assert_impl_all};
use std::{fmt::Debug, hash::Hash};
use std::{collections::HashMap, fmt::Debug};

assert_fields!(
MessageComponentInteractionData: custom_id,
component_type,
values
values,
resolved
);
assert_impl_all!(
MessageComponentInteractionData: Clone,
Debug,
Deserialize<'static>,
Eq,
Hash,
// Hash,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just leaving a pr comment on this (todo?) for visibility

PartialEq,
Send,
Serialize,
Expand All @@ -62,14 +81,38 @@ mod tests {
custom_id: "test".to_owned(),
component_type: ComponentType::Button,
values: Vec::from(["1".to_owned(), "2".to_owned()]),
resolved: Some(InteractionDataResolved {
attachments: HashMap::new(),
channels: HashMap::new(),
members: HashMap::new(),
messages: HashMap::new(),
roles: IntoIterator::into_iter([(
Id::new(400),
Role {
color: 0,
hoist: true,
icon: None,
id: Id::new(400),
managed: false,
mentionable: true,
name: "test".to_owned(),
permissions: Permissions::ADMINISTRATOR,
position: 12,
tags: None,
unicode_emoji: None,
},
)])
.collect(),
users: HashMap::new(),
}),
};

serde_test::assert_tokens(
&value,
&[
Token::Struct {
name: "MessageComponentInteractionData",
len: 3,
len: 4,
},
Token::String("custom_id"),
Token::String("test"),
Expand All @@ -80,6 +123,40 @@ mod tests {
Token::String("1"),
Token::String("2"),
Token::SeqEnd,
Token::String("resolved"),
Token::Some,
Token::Struct {
name: "InteractionDataResolved",
len: 1,
},
Token::Str("roles"),
Token::Map { len: Some(1) },
Token::NewtypeStruct { name: "Id" },
Token::Str("400"),
Token::Struct {
name: "Role",
len: 8,
},
Token::Str("color"),
Token::U32(0),
Token::Str("hoist"),
Token::Bool(true),
Token::Str("id"),
Token::NewtypeStruct { name: "Id" },
Token::Str("400"),
Token::Str("managed"),
Token::Bool(false),
Token::Str("mentionable"),
Token::Bool(true),
Token::Str("name"),
Token::Str("test"),
Token::Str("permissions"),
Token::Str("8"),
Token::Str("position"),
Token::I64(12),
Token::StructEnd,
Token::MapEnd,
Token::StructEnd,
Token::StructEnd,
],
)
Expand Down
13 changes: 6 additions & 7 deletions twilight-model/src/application/interaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
pub mod application_command;
pub mod message_component;
pub mod modal;
pub mod resolved;

mod interaction_type;

Expand Down Expand Up @@ -404,7 +405,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 @@ -414,10 +415,8 @@ pub enum InteractionData {
#[cfg(test)]
mod tests {
use super::{
application_command::{
CommandData, CommandDataOption, CommandInteractionDataResolved, CommandOptionValue,
InteractionMember,
},
application_command::{CommandData, CommandDataOption, CommandOptionValue},
resolved::{InteractionDataResolved, InteractionMember},
Interaction, InteractionData, InteractionType,
};
use crate::{
Expand Down Expand Up @@ -449,7 +448,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 @@ -578,7 +577,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 @@ -11,14 +11,13 @@ use crate::{
use serde::{Deserialize, Serialize};
use std::collections::hash_map::HashMap;

/// Resolved mentioned resources.
/// Resolved resources.
///
/// See [Discord Docs/Resolved Data Structure].
///
/// [`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, Eq, 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 @@ -93,7 +92,7 @@ pub struct InteractionMember {

#[cfg(test)]
mod tests {
use super::{CommandInteractionDataResolved, InteractionChannel, InteractionMember};
use super::{InteractionChannel, InteractionDataResolved, InteractionMember};
use crate::{
channel::{
message::{
Expand All @@ -117,7 +116,7 @@ mod tests {
let joined_at = Timestamp::from_str("2021-08-10T12:18:37.000000+00:00")?;
let timestamp = Timestamp::from_str("2020-02-02T02:02:02.020000+00:00")?;

let value = CommandInteractionDataResolved {
let value = InteractionDataResolved {
attachments: IntoIterator::into_iter([(
Id::new(400),
Attachment {
Expand Down Expand Up @@ -272,7 +271,7 @@ mod tests {
&value,
&[
Token::Struct {
name: "CommandInteractionDataResolved",
name: "InteractionDataResolved",
len: 6,
},
Token::Str("attachments"),
Expand Down
Loading