1use super::create_poll::Ready;
2#[cfg(feature = "http")]
3use super::{check_overflow, Builder};
4use super::{
5 CreateActionRow,
6 CreateAllowedMentions,
7 CreateAttachment,
8 CreateEmbed,
9 CreatePoll,
10 EditAttachments,
11};
12#[cfg(feature = "http")]
13use crate::constants;
14#[cfg(feature = "http")]
15use crate::http::CacheHttp;
16use crate::internal::prelude::*;
17use crate::model::prelude::*;
18
19#[derive(Clone, Debug)]
21pub enum CreateInteractionResponse {
22 Pong,
26 Message(CreateInteractionResponseMessage),
30 Defer(CreateInteractionResponseMessage),
35 Acknowledge,
43 UpdateMessage(CreateInteractionResponseMessage),
49 Autocomplete(CreateAutocompleteResponse),
55 Modal(CreateModal),
61 #[deprecated = "use premium button components via `CreateButton::new_premium` instead"]
68 PremiumRequired,
69 LaunchActivity,
76}
77
78impl serde::Serialize for CreateInteractionResponse {
79 #[allow(deprecated)] fn serialize<S: serde::Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
81 use serde::ser::SerializeMap as _;
82
83 let mut map = serializer.serialize_map(Some(2))?;
84 map.serialize_entry("type", &match self {
85 Self::Pong => 1,
86 Self::Message(_) => 4,
87 Self::Defer(_) => 5,
88 Self::Acknowledge => 6,
89 Self::UpdateMessage(_) => 7,
90 Self::Autocomplete(_) => 8,
91 Self::Modal(_) => 9,
92 Self::PremiumRequired => 10,
93 Self::LaunchActivity => 12,
94 })?;
95
96 match self {
97 Self::Pong => map.serialize_entry("data", &None::<()>)?,
98 Self::Message(x) => map.serialize_entry("data", &x)?,
99 Self::Defer(x) => map.serialize_entry("data", &x)?,
100 Self::Acknowledge => map.serialize_entry("data", &None::<()>)?,
101 Self::UpdateMessage(x) => map.serialize_entry("data", &x)?,
102 Self::Autocomplete(x) => map.serialize_entry("data", &x)?,
103 Self::Modal(x) => map.serialize_entry("data", &x)?,
104 Self::PremiumRequired => map.serialize_entry("data", &None::<()>)?,
105 Self::LaunchActivity => map.serialize_entry("data", &None::<()>)?,
106 }
107
108 map.end()
109 }
110}
111
112impl CreateInteractionResponse {
113 #[cfg(feature = "http")]
114 fn check_length(&self) -> Result<()> {
115 if let CreateInteractionResponse::Message(data)
116 | CreateInteractionResponse::Defer(data)
117 | CreateInteractionResponse::UpdateMessage(data) = self
118 {
119 if let Some(content) = &data.content {
120 check_overflow(content.chars().count(), constants::MESSAGE_CODE_LIMIT)
121 .map_err(|overflow| Error::Model(ModelError::MessageTooLong(overflow)))?;
122 }
123
124 if let Some(embeds) = &data.embeds {
125 check_overflow(embeds.len(), constants::EMBED_MAX_COUNT)
126 .map_err(|_| Error::Model(ModelError::EmbedAmount))?;
127
128 for embed in embeds {
129 embed.check_length()?;
130 }
131 }
132 }
133 Ok(())
134 }
135}
136
137#[cfg(feature = "http")]
138#[async_trait::async_trait]
139impl Builder for CreateInteractionResponse {
140 type Context<'ctx> = (InteractionId, &'ctx str);
141 type Built = ();
142
143 async fn execute(
154 mut self,
155 cache_http: impl CacheHttp,
156 ctx: Self::Context<'_>,
157 ) -> Result<Self::Built> {
158 self.check_length()?;
159 let files = match &mut self {
160 CreateInteractionResponse::Message(msg)
161 | CreateInteractionResponse::Defer(msg)
162 | CreateInteractionResponse::UpdateMessage(msg) => msg.attachments.take_files(),
163 _ => Vec::new(),
164 };
165
166 let http = cache_http.http();
167 if let Self::Message(msg) | Self::Defer(msg) | Self::UpdateMessage(msg) = &mut self {
168 if msg.allowed_mentions.is_none() {
169 msg.allowed_mentions.clone_from(&http.default_allowed_mentions);
170 }
171 };
172
173 http.create_interaction_response(ctx.0, ctx.1, &self, files).await
174 }
175}
176
177#[derive(Clone, Debug, Default, Serialize)]
179#[must_use]
180pub struct CreateInteractionResponseMessage {
181 #[serde(skip_serializing_if = "Option::is_none")]
182 tts: Option<bool>,
183 #[serde(skip_serializing_if = "Option::is_none")]
184 content: Option<String>,
185 #[serde(skip_serializing_if = "Option::is_none")]
186 embeds: Option<Vec<CreateEmbed>>,
187 #[serde(skip_serializing_if = "Option::is_none")]
188 allowed_mentions: Option<CreateAllowedMentions>,
189 #[serde(skip_serializing_if = "Option::is_none")]
190 flags: Option<InteractionResponseFlags>,
191 #[serde(skip_serializing_if = "Option::is_none")]
192 components: Option<Vec<CreateActionRow>>,
193 #[serde(skip_serializing_if = "Option::is_none")]
194 poll: Option<CreatePoll<Ready>>,
195 attachments: EditAttachments,
196}
197
198impl CreateInteractionResponseMessage {
199 pub fn new() -> Self {
201 Self::default()
202 }
203
204 pub fn tts(mut self, tts: bool) -> Self {
210 self.tts = Some(tts);
211 self
212 }
213
214 pub fn add_file(mut self, file: CreateAttachment) -> Self {
216 self.attachments = self.attachments.add(file);
217 self
218 }
219
220 pub fn add_files(mut self, files: impl IntoIterator<Item = CreateAttachment>) -> Self {
222 for file in files {
223 self.attachments = self.attachments.add(file);
224 }
225 self
226 }
227
228 pub fn files(mut self, files: impl IntoIterator<Item = CreateAttachment>) -> Self {
233 self.attachments = EditAttachments::new();
234 self.add_files(files)
235 }
236
237 #[inline]
241 pub fn content(mut self, content: impl Into<String>) -> Self {
242 self.content = Some(content.into());
243 self
244 }
245
246 pub fn add_embed(mut self, embed: CreateEmbed) -> Self {
250 self.embeds.get_or_insert_with(Vec::new).push(embed);
251 self
252 }
253
254 pub fn add_embeds(mut self, embeds: Vec<CreateEmbed>) -> Self {
258 self.embeds.get_or_insert_with(Vec::new).extend(embeds);
259 self
260 }
261
262 pub fn embed(self, embed: CreateEmbed) -> Self {
267 self.embeds(vec![embed])
268 }
269
270 pub fn embeds(mut self, embeds: Vec<CreateEmbed>) -> Self {
275 self.embeds = Some(embeds);
276 self
277 }
278
279 pub fn allowed_mentions(mut self, allowed_mentions: CreateAllowedMentions) -> Self {
281 self.allowed_mentions = Some(allowed_mentions);
282 self
283 }
284
285 pub fn flags(mut self, flags: InteractionResponseFlags) -> Self {
287 self.flags = Some(flags);
288 self
289 }
290
291 pub fn ephemeral(mut self, ephemeral: bool) -> Self {
293 let mut flags = self.flags.unwrap_or_else(InteractionResponseFlags::empty);
294
295 if ephemeral {
296 flags |= InteractionResponseFlags::EPHEMERAL;
297 } else {
298 flags &= !InteractionResponseFlags::EPHEMERAL;
299 };
300
301 self.flags = Some(flags);
302 self
303 }
304
305 pub fn components(mut self, components: Vec<CreateActionRow>) -> Self {
307 self.components = Some(components);
308 self
309 }
310
311 pub fn poll(mut self, poll: CreatePoll<Ready>) -> Self {
315 self.poll = Some(poll);
316 self
317 }
318
319 super::button_and_select_menu_convenience_methods!(self.components);
320}
321
322#[must_use]
325#[derive(Clone, Debug, Deserialize, Serialize)]
326#[serde(transparent)]
327pub struct AutocompleteChoice(CommandOptionChoice);
328impl AutocompleteChoice {
329 pub fn new(name: impl Into<String>, value: impl Into<Value>) -> Self {
330 Self(CommandOptionChoice {
331 name: name.into(),
332 name_localizations: None,
333 value: value.into(),
334 })
335 }
336
337 pub fn add_localized_name(
338 mut self,
339 locale: impl Into<String>,
340 localized_name: impl Into<String>,
341 ) -> Self {
342 self.0
343 .name_localizations
344 .get_or_insert_with(Default::default)
345 .insert(locale.into(), localized_name.into());
346 self
347 }
348}
349
350impl<S: Into<String>> From<S> for AutocompleteChoice {
351 fn from(value: S) -> Self {
352 let value = value.into();
353 let name = value.clone();
354 Self::new(name, value)
355 }
356}
357
358#[derive(Clone, Debug, Default, Serialize)]
360#[must_use]
361pub struct CreateAutocompleteResponse {
362 choices: Vec<AutocompleteChoice>,
363}
364
365impl CreateAutocompleteResponse {
366 pub fn new() -> Self {
368 Self::default()
369 }
370
371 pub fn set_choices(mut self, choices: Vec<AutocompleteChoice>) -> Self {
377 self.choices = choices;
378 self
379 }
380
381 pub fn add_int_choice(self, name: impl Into<String>, value: i64) -> Self {
386 self.add_choice(AutocompleteChoice::new(name, value))
387 }
388
389 pub fn add_string_choice(self, name: impl Into<String>, value: impl Into<String>) -> Self {
394 self.add_choice(AutocompleteChoice::new(name, value.into()))
395 }
396
397 pub fn add_number_choice(self, name: impl Into<String>, value: f64) -> Self {
402 self.add_choice(AutocompleteChoice::new(name, value))
403 }
404
405 fn add_choice(mut self, value: AutocompleteChoice) -> Self {
406 self.choices.push(value);
407 self
408 }
409}
410
411#[cfg(feature = "http")]
412#[async_trait::async_trait]
413impl Builder for CreateAutocompleteResponse {
414 type Context<'ctx> = (InteractionId, &'ctx str);
415 type Built = ();
416
417 async fn execute(
423 self,
424 cache_http: impl CacheHttp,
425 ctx: Self::Context<'_>,
426 ) -> Result<Self::Built> {
427 cache_http.http().create_interaction_response(ctx.0, ctx.1, &self, Vec::new()).await
428 }
429}
430
431#[derive(Clone, Debug, Default, Serialize)]
433#[must_use]
434pub struct CreateModal {
435 components: Vec<CreateActionRow>,
436 custom_id: String,
437 title: String,
438}
439
440impl CreateModal {
441 pub fn new(custom_id: impl Into<String>, title: impl Into<String>) -> Self {
443 Self {
444 components: Vec::new(),
445 custom_id: custom_id.into(),
446 title: title.into(),
447 }
448 }
449
450 pub fn components(mut self, components: Vec<CreateActionRow>) -> Self {
454 self.components = components;
455 self
456 }
457}