1use crate::command::CommandType;
4use crate::component::ComponentType;
5use crate::member::GuildMember;
6use crate::snowflake::Snowflake;
7use crate::Message;
8use crate::TitanString;
9use crate::User;
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct Interaction<'a> {
15 pub id: Snowflake,
17 pub application_id: Snowflake,
19 #[serde(rename = "type")]
21 pub interaction_type: InteractionType,
22 #[serde(default)]
24 pub data: Option<InteractionData<'a>>,
25 #[serde(default)]
27 pub guild_id: Option<Snowflake>,
28 #[serde(default)]
30 pub channel_id: Option<Snowflake>,
31 #[serde(default)]
33 pub member: Option<GuildMember<'a>>,
34 #[serde(default)]
36 pub user: Option<User<'a>>,
37 pub token: String,
39 pub version: u8,
41 #[serde(default)]
43 pub message: Option<Box<Message<'a>>>,
44 #[serde(default)]
46 pub locale: Option<TitanString<'a>>,
47 #[serde(default)]
49 pub guild_locale: Option<TitanString<'a>>,
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
54#[serde(from = "u8", into = "u8")]
55pub enum InteractionType {
56 Ping = 1,
58 ApplicationCommand = 2,
60 MessageComponent = 3,
62 ApplicationCommandAutocomplete = 4,
64 ModalSubmit = 5,
66}
67
68impl From<u8> for InteractionType {
69 fn from(value: u8) -> Self {
70 match value {
71 1 => InteractionType::Ping,
72
73 3 => InteractionType::MessageComponent,
74 4 => InteractionType::ApplicationCommandAutocomplete,
75 5 => InteractionType::ModalSubmit,
76 _ => InteractionType::ApplicationCommand,
77 }
78 }
79}
80
81impl From<InteractionType> for u8 {
82 fn from(value: InteractionType) -> Self {
83 value as u8
84 }
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct InteractionData<'a> {
90 #[serde(default)]
92 pub id: Option<Snowflake>,
93 #[serde(default)]
95 pub name: Option<TitanString<'a>>,
96 #[serde(default, rename = "type")]
98 pub command_type: Option<CommandType>,
99 #[serde(default)]
101 pub resolved: Option<ResolvedData<'a>>,
102 #[serde(default)]
104 pub options: Vec<InteractionDataOption<'a>>,
105 #[serde(default)]
107 pub custom_id: Option<TitanString<'a>>,
108 #[serde(default)]
110 pub component_type: Option<ComponentType>,
111 #[serde(default)]
113 pub values: Vec<String>,
114 #[serde(default)]
116 pub target_id: Option<Snowflake>,
117 #[serde(default)]
119 pub components: Vec<crate::json::Value>,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct ResolvedData<'a> {
125 #[serde(default)]
127 pub users: ahash::AHashMap<Snowflake, User<'a>>,
128 #[serde(default)]
130 pub members: ahash::AHashMap<Snowflake, GuildMember<'a>>,
131 #[serde(default)]
133 pub roles: ahash::AHashMap<Snowflake, crate::member::Role<'a>>,
134 #[serde(default)]
136 pub channels: ahash::AHashMap<Snowflake, crate::Channel<'a>>,
137 #[serde(default)]
139 pub messages: ahash::AHashMap<Snowflake, Message<'a>>,
140 #[serde(default)]
142 pub attachments: ahash::AHashMap<Snowflake, crate::Attachment<'a>>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct InteractionDataOption<'a> {
148 pub name: TitanString<'a>,
150 #[serde(rename = "type")]
152 pub option_type: crate::command::OptionType,
153 #[serde(default)]
155 pub value: Option<crate::json::Value>,
156 #[serde(default)]
158 pub options: Vec<InteractionDataOption<'a>>,
159 #[serde(default)]
161 pub focused: bool,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct InteractionResponse<'a> {
167 #[serde(rename = "type")]
169 pub response_type: InteractionCallbackType,
170 #[serde(skip_serializing_if = "Option::is_none")]
172 pub data: Option<InteractionCallbackData<'a>>,
173}
174
175impl<'a> InteractionResponse<'a> {
176 pub fn builder() -> crate::builder::InteractionResponseBuilder<'a> {
178 crate::builder::InteractionResponseBuilder::new()
179 }
180
181 pub fn reply(
183 content: impl Into<TitanString<'a>>,
184 ) -> crate::builder::InteractionResponseBuilder<'a> {
185 Self::builder().content(content)
186 }
187
188 pub fn deferred() -> crate::builder::InteractionResponseBuilder<'a> {
190 Self::builder().kind(InteractionCallbackType::DeferredChannelMessageWithSource)
191 }
192}
193
194#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
196#[serde(from = "u8", into = "u8")]
197pub enum InteractionCallbackType {
198 Pong = 1,
200 ChannelMessageWithSource = 4,
202 DeferredChannelMessageWithSource = 5,
204 DeferredUpdateMessage = 6,
206 UpdateMessage = 7,
208 ApplicationCommandAutocompleteResult = 8,
210 Modal = 9,
212}
213
214impl From<u8> for InteractionCallbackType {
215 fn from(value: u8) -> Self {
216 match value {
217 1 => InteractionCallbackType::Pong,
218
219 5 => InteractionCallbackType::DeferredChannelMessageWithSource,
220 6 => InteractionCallbackType::DeferredUpdateMessage,
221 7 => InteractionCallbackType::UpdateMessage,
222 8 => InteractionCallbackType::ApplicationCommandAutocompleteResult,
223 9 => InteractionCallbackType::Modal,
224 _ => InteractionCallbackType::ChannelMessageWithSource,
225 }
226 }
227}
228
229impl From<InteractionCallbackType> for u8 {
230 fn from(value: InteractionCallbackType) -> Self {
231 value as u8
232 }
233}
234
235#[derive(Debug, Clone, Default, Serialize, Deserialize)]
237pub struct InteractionCallbackData<'a> {
238 #[serde(default)]
240 pub tts: bool,
241 #[serde(skip_serializing_if = "Option::is_none")]
243 pub content: Option<TitanString<'a>>,
244 #[serde(skip_serializing_if = "Vec::is_empty")]
246 pub embeds: Vec<crate::Embed<'a>>,
247 #[serde(skip_serializing_if = "Option::is_none")]
249 pub allowed_mentions: Option<crate::json::Value>,
250 #[serde(skip_serializing_if = "Option::is_none")]
252 pub flags: Option<u64>,
253 #[serde(skip_serializing_if = "Vec::is_empty")]
255 pub components: Vec<crate::Component<'a>>,
256 #[serde(skip_serializing_if = "Option::is_none")]
258 pub choices: Option<Vec<InteractionDataOption<'a>>>,
259 #[serde(default)]
261 pub attachments: Vec<crate::Attachment<'a>>,
262 #[serde(skip_serializing_if = "Option::is_none")]
264 pub custom_id: Option<TitanString<'a>>,
265 #[serde(skip_serializing_if = "Option::is_none")]
267 pub title: Option<TitanString<'a>>,
268}
269
270#[derive(Debug, Clone, Serialize, Deserialize)]
272pub struct Modal<'a> {
273 pub custom_id: TitanString<'a>,
274 pub title: TitanString<'a>,
275 pub components: Vec<crate::Component<'a>>,
276}