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 pub attachment_size_limit: u32,
72}
73
74#[cfg(feature = "model")]
75impl ComponentInteraction {
76 pub async fn get_response(&self, http: impl AsRef<Http>) -> Result<Message> {
82 http.as_ref().get_original_interaction_response(&self.token).await
83 }
84
85 pub async fn create_response(
95 &self,
96 cache_http: impl CacheHttp,
97 builder: CreateInteractionResponse,
98 ) -> Result<()> {
99 builder.execute(cache_http, (self.id, &self.token)).await
100 }
101
102 pub async fn edit_response(
112 &self,
113 cache_http: impl CacheHttp,
114 builder: EditInteractionResponse,
115 ) -> Result<Message> {
116 builder.execute(cache_http, &self.token).await
117 }
118
119 pub async fn delete_response(&self, http: impl AsRef<Http>) -> Result<()> {
128 http.as_ref().delete_original_interaction_response(&self.token).await
129 }
130
131 pub async fn create_followup(
141 &self,
142 cache_http: impl CacheHttp,
143 builder: CreateInteractionResponseFollowup,
144 ) -> Result<Message> {
145 builder.execute(cache_http, (None, &self.token)).await
146 }
147
148 pub async fn edit_followup(
158 &self,
159 cache_http: impl CacheHttp,
160 message_id: impl Into<MessageId>,
161 builder: CreateInteractionResponseFollowup,
162 ) -> Result<Message> {
163 builder.execute(cache_http, (Some(message_id.into()), &self.token)).await
164 }
165
166 pub async fn delete_followup<M: Into<MessageId>>(
173 &self,
174 http: impl AsRef<Http>,
175 message_id: M,
176 ) -> Result<()> {
177 http.as_ref().delete_followup_message(&self.token, message_id.into()).await
178 }
179
180 pub async fn get_followup<M: Into<MessageId>>(
187 &self,
188 http: impl AsRef<Http>,
189 message_id: M,
190 ) -> Result<Message> {
191 http.as_ref().get_followup_message(&self.token, message_id.into()).await
192 }
193
194 pub async fn defer(&self, cache_http: impl CacheHttp) -> Result<()> {
201 self.create_response(cache_http, CreateInteractionResponse::Acknowledge).await
202 }
203
204 pub async fn defer_ephemeral(&self, cache_http: impl CacheHttp) -> Result<()> {
211 let builder = CreateInteractionResponse::Defer(
212 CreateInteractionResponseMessage::new().ephemeral(true),
213 );
214 self.create_response(cache_http, builder).await
215 }
216
217 #[cfg(all(feature = "collector", feature = "utils"))]
223 pub async fn quick_modal(
224 &self,
225 ctx: &Context,
226 builder: CreateQuickModal,
227 ) -> Result<Option<QuickModalResponse>> {
228 builder.execute(ctx, self.id, &self.token).await
229 }
230}
231
232impl<'de> Deserialize<'de> for ComponentInteraction {
234 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
235 let mut interaction = Self::deserialize(deserializer)?;
237 if let (Some(guild_id), Some(member)) = (interaction.guild_id, &mut interaction.member) {
238 member.guild_id = guild_id;
239 interaction.user = member.user.clone();
241 }
242 Ok(interaction)
243 }
244}
245
246impl Serialize for ComponentInteraction {
247 fn serialize<S: serde::Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
248 Self::serialize(self, serializer)
250 }
251}
252
253#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
254#[derive(Clone, Debug)]
255pub enum ComponentInteractionDataKind {
256 Button,
257 StringSelect { values: Vec<String> },
258 UserSelect { values: Vec<UserId> },
259 RoleSelect { values: Vec<RoleId> },
260 MentionableSelect { values: Vec<GenericId> },
261 ChannelSelect { values: Vec<ChannelId> },
262 Unknown(u8),
263}
264
265impl<'de> Deserialize<'de> for ComponentInteractionDataKind {
267 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
268 #[derive(Deserialize)]
269 struct Json {
270 component_type: ComponentType,
271 values: Option<json::Value>,
272 }
273 let json = Json::deserialize(deserializer)?;
274
275 macro_rules! parse_values {
276 () => {
277 json::from_value(json.values.ok_or_else(|| D::Error::missing_field("values"))?)
278 .map_err(D::Error::custom)?
279 };
280 }
281
282 Ok(match json.component_type {
283 ComponentType::Button => Self::Button,
284 ComponentType::StringSelect => Self::StringSelect {
285 values: parse_values!(),
286 },
287 ComponentType::UserSelect => Self::UserSelect {
288 values: parse_values!(),
289 },
290 ComponentType::RoleSelect => Self::RoleSelect {
291 values: parse_values!(),
292 },
293 ComponentType::MentionableSelect => Self::MentionableSelect {
294 values: parse_values!(),
295 },
296 ComponentType::ChannelSelect => Self::ChannelSelect {
297 values: parse_values!(),
298 },
299 ComponentType::Unknown(x) => Self::Unknown(x),
300 x @ (ComponentType::ActionRow | ComponentType::InputText) => {
301 return Err(D::Error::custom(format_args!(
302 "invalid message component type in this context: {x:?}",
303 )));
304 },
305 })
306 }
307}
308
309impl Serialize for ComponentInteractionDataKind {
310 #[rustfmt::skip] fn serialize<S: serde::Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
312 let mut map = serializer.serialize_map(Some(2))?;
313 map.serialize_entry("component_type", &match self {
314 Self::Button { .. } => 2,
315 Self::StringSelect { .. } => 3,
316 Self::UserSelect { .. } => 5,
317 Self::RoleSelect { .. } => 6,
318 Self::MentionableSelect { .. } => 7,
319 Self::ChannelSelect { .. } => 8,
320 Self::Unknown(x) => *x,
321 })?;
322
323 match self {
324 Self::StringSelect { values } => map.serialize_entry("values", values)?,
325 Self::UserSelect { values } => map.serialize_entry("values", values)?,
326 Self::RoleSelect { values } => map.serialize_entry("values", values)?,
327 Self::MentionableSelect { values } => map.serialize_entry("values", values)?,
328 Self::ChannelSelect { values } => map.serialize_entry("values", values)?,
329 Self::Button | Self::Unknown(_) => map.serialize_entry("values", &None::<()>)?,
330 }
331
332 map.end()
333 }
334}
335
336#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
340#[derive(Clone, Debug, Deserialize, Serialize)]
341#[non_exhaustive]
342pub struct ComponentInteractionData {
343 pub custom_id: String,
345 #[serde(flatten)]
347 pub kind: ComponentInteractionDataKind,
348 #[serde(default)]
350 pub resolved: CommandDataResolved,
351}