1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
use json::JsonValue;
use std::collections::HashMap;
use crate::consts::*;
use crate::models::allowed_mentions::AllowedMentions;
use crate::models::guild::Member;
use crate::prelude::{Component, Embed};
use crate::utils::request;
use nanoserde::{DeJson, SerJson};
use reqwest::Method;
use super::guild::{Guild, PartialGuild};
use super::message_response::CreateMessageData;
use super::{channel::Channel, message_response::Message, user::User};
/// Payload for an interaction response.
#[derive(DeJson, SerJson, Clone, Debug)]
pub struct InteractionResponsePayload {
/// The interaction data.
#[nserde(rename = "d")]
pub data: Interaction,
}
/// Represents an interaction with the Discord API.
#[derive(DeJson, SerJson, Clone, Debug)]
pub struct Interaction {
/// The interaction ID.
pub id: String,
/// The application ID.
pub application_id: String,
/// The interaction type.
#[nserde(rename = "type")]
pub type_: u32,
/// The interaction data.
pub data: Option<InteractionData>,
/// The channel where the interaction was sent.
pub channel: Option<Channel>,
/// The channel ID.
pub channel_id: Option<String>,
/// The member who invoked the interaction.
pub member: Option<Member>,
/// The interaction token.
pub token: String,
/// The message associated with the interaction.
pub message: Option<Message>,
/// The application permissions.
pub app_permissions: String,
/// The locale of the interaction.
pub locale: Option<String>,
/// The guild locale of the interaction.
pub guild_locale: Option<String>,
/// The context of the interaction.
pub context: Option<u32>,
/// The guild ID where the interaction was sent.
pub guild_id: String,
/// The user who invoked the interaction, if in a DM.
pub user: Option<User>,
}
impl Interaction {
/// Sends a reply to the interaction.
///
/// # Arguments
///
/// * `response` - The response data.
/// * `ephemeral` - Whether the response should be ephemeral.
///
/// # Examples
///
/// ```
/// interaction.reply("Hello, world!", true).await;
/// ```
pub async fn reply(&self, response: impl Into<CreateMessageData>, ephemeral: bool) {
let mut message_data: CreateMessageData = response.into();
ephemeral.then(|| message_data.flags = Some(64));
let response = InteractionResponse {
type_: 4,
data: Some(message_data),
};
let json_response = SerJson::serialize_json(&response);
request(
Method::POST,
format!("interactions/{}/{}/callback", self.id, self.token).as_str(),
Some(JsonValue::from(json_response)),
)
.await;
}
/// Defers the interaction response.
///
/// # Examples
///
/// ```
/// interaction.defer().await;
/// ```
pub async fn defer(&self) {
let response = InteractionResponse {
type_: 5,
data: None,
};
let json_response = SerJson::serialize_json(&response);
request(
Method::POST,
format!("interactions/{}/{}/callback", self.id, self.token).as_str(),
Some(JsonValue::from(json_response)),
)
.await;
}
/// Sends a follow-up message to the interaction.
///
/// # Arguments
///
/// * `response` - The follow-up message content.
///
/// # Examples
///
/// ```
/// interaction.followup("Follow-up message").await;
/// ```
pub async fn followup<S: AsRef<str>>(&self, response: S) {
request(
Method::POST,
format!("webhooks/{}/{}", self.application_id, self.token).as_str(),
Some(json::object! {
content: response.as_ref(),
}),
)
.await;
}
/// Edits the original interaction response.
///
/// # Arguments
///
/// * `response` - The new response data.
///
/// # Examples
///
/// ```
/// interaction.edit_original("Edited message").await;
/// ```
pub async fn edit_original(&self, response: impl Into<CreateMessageData>) {
let response: CreateMessageData = response.into();
let resp = request(
Method::PATCH,
format!(
"webhooks/{}/{}/messages/@original",
self.application_id, self.token
)
.as_str(),
Some(json::parse(&response.serialize_json()).unwrap()),
)
.await;
println!("{}", resp.text().await.unwrap());
}
/// Deletes the original interaction response.
///
/// # Examples
///
/// ```
/// interaction.delete_original().await;
/// ```
pub async fn delete_original(&self) {
request(
Method::DELETE,
format!(
"webhooks/{}/{}/messages/@original",
self.application_id, self.token
)
.as_str(),
None,
)
.await;
}
}
/// Data associated with an interaction.
#[derive(DeJson, SerJson, Clone, Debug, Default)]
pub struct InteractionData {
/// The custom ID of the interaction.
pub custom_id: Option<String>,
/// The component type of the interaction.
pub component_type: Option<u32>,
/// The ID of the interaction.
pub id: Option<String>,
/// The command name of the interaction.
#[nserde(rename = "name")]
pub command_name: Option<String>,
/// The type of the interaction.
#[nserde(rename = "type")]
pub type_: Option<u32>,
/// The resolved data of the interaction.
pub resolved: Option<ResolvedData>,
/// The options of the interaction.
pub options: Option<Vec<AppCommandInteractionData>>,
/// The guild ID where the interaction was sent.
pub guild_id: Option<String>,
/// The target ID of the interaction.
pub target_id: Option<String>,
}
/// Resolved data associated with an interaction.
#[derive(DeJson, SerJson, Clone, Debug)]
pub struct ResolvedData {
/// The users involved in the interaction.
pub users: Option<HashMap<String, User>>,
/// The members involved in the interaction.
pub members: Option<HashMap<String, Member>>,
/// The channels involved in the interaction.
pub channels: Option<HashMap<String, Channel>>,
/// The messages involved in the interaction.
pub messages: Option<HashMap<String, Message>>,
// TODO: roles, attachments
}
/// Data for an application command interaction.
#[derive(DeJson, SerJson, Clone, Debug)]
pub struct AppCommandInteractionData {
/// The name of the command.
pub name: String,
/// The type of the command.
#[nserde(rename = "type")]
pub type_: u32,
/// The value of the command.
/// Can be a string, int, float, or bool.
pub value: String,
/// The options for the command.
pub options: Option<Vec<AppCommandInteractionData>>,
/// Whether the command is focused.
pub focused: Option<bool>,
}
/// Choices for an autocomplete interaction.
#[derive(DeJson, SerJson, Clone, Debug, Default)]
pub struct InteractionAutoCompleteChoices {
/// The type of the interaction.
#[nserde(rename = "type")]
pub type_: u32,
/// The data for the interaction.
pub data: Option<InteractionAutoCompleteChoicePlaceholder>,
}
impl InteractionAutoCompleteChoices {
/// Creates a new instance of `InteractionAutoCompleteChoices`.
///
/// # Arguments
///
/// * `choices` - The autocomplete choices.
///
/// # Examples
///
/// ```
/// let choices = InteractionAutoCompleteChoices::new(vec![choice1, choice2]);
/// ```
pub fn new(choices: Vec<InteractionAutoCompleteChoice>) -> Self {
Self {
type_: InteractionCallbackType::ApplicationCommandAutocompleteResult as _,
data: Some(InteractionAutoCompleteChoicePlaceholder { choices }),
}
}
}
/// Placeholder for autocomplete choices.
#[derive(DeJson, SerJson, Clone, Debug, Default)]
pub struct InteractionAutoCompleteChoicePlaceholder {
/// The autocomplete choices.
pub choices: Vec<InteractionAutoCompleteChoice>,
}
/// Represents an autocomplete choice.
#[derive(DeJson, SerJson, Clone, Debug, Default)]
pub struct InteractionAutoCompleteChoice {
/// The name of the choice.
pub name: String,
/// The value of the choice.
pub value: String,
}
/// Represents an interaction response.
#[derive(DeJson, SerJson, Clone, Debug)]
pub struct InteractionResponse {
/// The type of the interaction response.
#[nserde(rename = "type")]
pub type_: u32,
/// The data for the interaction response.
pub data: Option<CreateMessageData>,
}