serenity/model/application/
component_interaction.rs1use serde::de::Error as DeError;
2use serde::ser::{Serialize, SerializeMap as _};
3
4#[cfg(feature = "model")]
5use crate::builder::{
6    Builder,
7    CreateInteractionResponse,
8    CreateInteractionResponseFollowup,
9    CreateInteractionResponseMessage,
10    EditInteractionResponse,
11};
12#[cfg(feature = "collector")]
13use crate::client::Context;
14#[cfg(feature = "model")]
15use crate::http::{CacheHttp, Http};
16use crate::internal::prelude::*;
17use crate::json;
18use crate::model::prelude::*;
19#[cfg(all(feature = "collector", feature = "utils"))]
20use crate::utils::{CreateQuickModal, QuickModalResponse};
21
22#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
26#[derive(Clone, Debug, Deserialize, Serialize)]
27#[serde(remote = "Self")]
28#[non_exhaustive]
29pub struct ComponentInteraction {
30    pub id: InteractionId,
32    pub application_id: ApplicationId,
34    pub data: ComponentInteractionData,
36    #[serde(skip_serializing_if = "Option::is_none")]
38    pub guild_id: Option<GuildId>,
39    pub channel: Option<PartialChannel>,
41    pub channel_id: ChannelId,
43    #[serde(skip_serializing_if = "Option::is_none")]
47    pub member: Option<Member>,
48    #[serde(default)]
50    pub user: User,
51    pub token: String,
53    pub version: u8,
55    pub message: Box<Message>,
57    pub app_permissions: Option<Permissions>,
59    pub locale: String,
61    pub guild_locale: Option<String>,
63    pub entitlements: Vec<Entitlement>,
65    #[serde(default)]
67    pub authorizing_integration_owners: AuthorizingIntegrationOwners,
68    pub context: Option<InteractionContext>,
70}
71
72#[cfg(feature = "model")]
73impl ComponentInteraction {
74    pub async fn get_response(&self, http: impl AsRef<Http>) -> Result<Message> {
80        http.as_ref().get_original_interaction_response(&self.token).await
81    }
82
83    pub async fn create_response(
93        &self,
94        cache_http: impl CacheHttp,
95        builder: CreateInteractionResponse,
96    ) -> Result<()> {
97        builder.execute(cache_http, (self.id, &self.token)).await
98    }
99
100    pub async fn edit_response(
110        &self,
111        cache_http: impl CacheHttp,
112        builder: EditInteractionResponse,
113    ) -> Result<Message> {
114        builder.execute(cache_http, &self.token).await
115    }
116
117    pub async fn delete_response(&self, http: impl AsRef<Http>) -> Result<()> {
126        http.as_ref().delete_original_interaction_response(&self.token).await
127    }
128
129    pub async fn create_followup(
139        &self,
140        cache_http: impl CacheHttp,
141        builder: CreateInteractionResponseFollowup,
142    ) -> Result<Message> {
143        builder.execute(cache_http, (None, &self.token)).await
144    }
145
146    pub async fn edit_followup(
156        &self,
157        cache_http: impl CacheHttp,
158        message_id: impl Into<MessageId>,
159        builder: CreateInteractionResponseFollowup,
160    ) -> Result<Message> {
161        builder.execute(cache_http, (Some(message_id.into()), &self.token)).await
162    }
163
164    pub async fn delete_followup<M: Into<MessageId>>(
171        &self,
172        http: impl AsRef<Http>,
173        message_id: M,
174    ) -> Result<()> {
175        http.as_ref().delete_followup_message(&self.token, message_id.into()).await
176    }
177
178    pub async fn get_followup<M: Into<MessageId>>(
185        &self,
186        http: impl AsRef<Http>,
187        message_id: M,
188    ) -> Result<Message> {
189        http.as_ref().get_followup_message(&self.token, message_id.into()).await
190    }
191
192    pub async fn defer(&self, cache_http: impl CacheHttp) -> Result<()> {
199        self.create_response(cache_http, CreateInteractionResponse::Acknowledge).await
200    }
201
202    pub async fn defer_ephemeral(&self, cache_http: impl CacheHttp) -> Result<()> {
209        let builder = CreateInteractionResponse::Defer(
210            CreateInteractionResponseMessage::new().ephemeral(true),
211        );
212        self.create_response(cache_http, builder).await
213    }
214
215    #[cfg(all(feature = "collector", feature = "utils"))]
221    pub async fn quick_modal(
222        &self,
223        ctx: &Context,
224        builder: CreateQuickModal,
225    ) -> Result<Option<QuickModalResponse>> {
226        builder.execute(ctx, self.id, &self.token).await
227    }
228}
229
230impl<'de> Deserialize<'de> for ComponentInteraction {
232    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
233        let mut interaction = Self::deserialize(deserializer)?;
235        if let (Some(guild_id), Some(member)) = (interaction.guild_id, &mut interaction.member) {
236            member.guild_id = guild_id;
237            interaction.user = member.user.clone();
239        }
240        Ok(interaction)
241    }
242}
243
244impl Serialize for ComponentInteraction {
245    fn serialize<S: serde::Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
246        Self::serialize(self, serializer)
248    }
249}
250
251#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
252#[derive(Clone, Debug)]
253pub enum ComponentInteractionDataKind {
254    Button,
255    StringSelect { values: Vec<String> },
256    UserSelect { values: Vec<UserId> },
257    RoleSelect { values: Vec<RoleId> },
258    MentionableSelect { values: Vec<GenericId> },
259    ChannelSelect { values: Vec<ChannelId> },
260    Unknown(u8),
261}
262
263impl<'de> Deserialize<'de> for ComponentInteractionDataKind {
265    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
266        #[derive(Deserialize)]
267        struct Json {
268            component_type: ComponentType,
269            values: Option<json::Value>,
270        }
271        let json = Json::deserialize(deserializer)?;
272
273        macro_rules! parse_values {
274            () => {
275                json::from_value(json.values.ok_or_else(|| D::Error::missing_field("values"))?)
276                    .map_err(D::Error::custom)?
277            };
278        }
279
280        Ok(match json.component_type {
281            ComponentType::Button => Self::Button,
282            ComponentType::StringSelect => Self::StringSelect {
283                values: parse_values!(),
284            },
285            ComponentType::UserSelect => Self::UserSelect {
286                values: parse_values!(),
287            },
288            ComponentType::RoleSelect => Self::RoleSelect {
289                values: parse_values!(),
290            },
291            ComponentType::MentionableSelect => Self::MentionableSelect {
292                values: parse_values!(),
293            },
294            ComponentType::ChannelSelect => Self::ChannelSelect {
295                values: parse_values!(),
296            },
297            ComponentType::Unknown(x) => Self::Unknown(x),
298            x @ (ComponentType::ActionRow | ComponentType::InputText) => {
299                return Err(D::Error::custom(format_args!(
300                    "invalid message component type in this context: {x:?}",
301                )));
302            },
303        })
304    }
305}
306
307impl Serialize for ComponentInteractionDataKind {
308    #[rustfmt::skip] fn serialize<S: serde::Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
310        let mut map = serializer.serialize_map(Some(2))?;
311        map.serialize_entry("component_type", &match self {
312            Self::Button { .. } => 2,
313            Self::StringSelect { .. } => 3,
314            Self::UserSelect { .. } => 5,
315            Self::RoleSelect { .. } => 6,
316            Self::MentionableSelect { .. } => 7,
317            Self::ChannelSelect { .. } => 8,
318            Self::Unknown(x) => *x,
319        })?;
320
321        match self {
322            Self::StringSelect { values } => map.serialize_entry("values", values)?,
323            Self::UserSelect { values } => map.serialize_entry("values", values)?,
324            Self::RoleSelect { values } => map.serialize_entry("values", values)?,
325            Self::MentionableSelect { values } => map.serialize_entry("values", values)?,
326            Self::ChannelSelect { values } => map.serialize_entry("values", values)?,
327            Self::Button | Self::Unknown(_) => map.serialize_entry("values", &None::<()>)?,
328        };
329
330        map.end()
331    }
332}
333
334#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
338#[derive(Clone, Debug, Deserialize, Serialize)]
339#[non_exhaustive]
340pub struct ComponentInteractionData {
341    pub custom_id: String,
343    #[serde(flatten)]
345    pub kind: ComponentInteractionDataKind,
346}