1pub mod permissions;
11
12mod command_type;
13mod option;
14
15pub use self::{
16 command_type::CommandType,
17 option::{
18 CommandOption, CommandOptionChoice, CommandOptionChoiceValue, CommandOptionType,
19 CommandOptionValue,
20 },
21};
22
23use crate::{
24 guild::Permissions,
25 id::{
26 marker::{ApplicationMarker, CommandMarker, CommandVersionMarker, GuildMarker},
27 Id,
28 },
29 oauth::ApplicationIntegrationType,
30};
31use serde::{Deserialize, Serialize};
32use std::collections::HashMap;
33
34use super::interaction::InteractionContextType;
35
36#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
44pub struct Command {
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub application_id: Option<Id<ApplicationMarker>>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub contexts: Option<Vec<InteractionContextType>>,
49 pub default_member_permissions: Option<Permissions>,
54 #[deprecated(note = "use contexts instead")]
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub dm_permission: Option<bool>,
61 pub description: String,
68 #[serde(skip_serializing_if = "Option::is_none")]
74 pub description_localizations: Option<HashMap<String, String>>,
75 #[serde(skip_serializing_if = "Option::is_none")]
77 pub guild_id: Option<Id<GuildMarker>>,
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub id: Option<Id<CommandMarker>>,
80 #[serde(skip_serializing_if = "Option::is_none")]
81 pub integration_types: Option<Vec<ApplicationIntegrationType>>,
82 #[serde(rename = "type")]
83 pub kind: CommandType,
84 pub name: String,
85 #[serde(skip_serializing_if = "Option::is_none")]
93 pub name_localizations: Option<HashMap<String, String>>,
94 #[serde(skip_serializing_if = "Option::is_none")]
98 pub nsfw: Option<bool>,
99 #[serde(default)]
100 pub options: Vec<CommandOption>,
101 pub version: Id<CommandVersionMarker>,
103}
104
105#[cfg(test)]
106mod tests {
107 use super::{
108 Command, CommandOption, CommandOptionChoice, CommandOptionChoiceValue, CommandOptionType,
109 CommandOptionValue, CommandType,
110 };
111 use crate::{channel::ChannelType, guild::Permissions, id::Id};
112 use serde_test::Token;
113 use std::collections::HashMap;
114
115 #[test]
116 #[allow(clippy::too_many_lines, deprecated)]
117 fn command_option_full() {
118 let value = Command {
119 application_id: Some(Id::new(100)),
120 contexts: None,
121 default_member_permissions: Some(Permissions::ADMINISTRATOR),
122 dm_permission: Some(false),
123 description: "this command is a test".into(),
124 description_localizations: Some(HashMap::from([(
125 "en-US".into(),
126 "this command is a test".into(),
127 )])),
128 guild_id: Some(Id::new(300)),
129 id: Some(Id::new(200)),
130 integration_types: None,
131 kind: CommandType::ChatInput,
132 name: "test command".into(),
133 name_localizations: Some(HashMap::from([("en-US".into(), "test command".into())])),
134 nsfw: None,
135 options: Vec::from([CommandOption {
136 autocomplete: None,
137 channel_types: None,
138 choices: None,
139 description: "sub command group desc".to_owned(),
140 description_localizations: None,
141 kind: CommandOptionType::SubCommandGroup,
142 max_length: None,
143 max_value: None,
144 min_length: None,
145 min_value: None,
146 name: "sub command group name".to_owned(),
147 name_localizations: None,
148 options: Some(Vec::from([CommandOption {
149 autocomplete: None,
150 channel_types: None,
151 choices: None,
152 description: "sub command desc".to_owned(),
153 description_localizations: None,
154 kind: CommandOptionType::SubCommand,
155 max_length: None,
156 max_value: None,
157 min_length: None,
158 min_value: None,
159 name: "sub command name".to_owned(),
160 name_localizations: None,
161 options: Some(Vec::from([
162 CommandOption {
163 autocomplete: None,
164 channel_types: None,
165 choices: None,
166 description: "attachment desc".to_owned(),
167 description_localizations: None,
168 kind: CommandOptionType::Attachment,
169 max_length: None,
170 max_value: None,
171 min_length: None,
172 min_value: None,
173 name: "attachment name".to_owned(),
174 name_localizations: None,
175 options: None,
176 required: None,
177 },
178 CommandOption {
179 autocomplete: None,
180 channel_types: None,
181 choices: None,
182 description: "boolean desc".to_owned(),
183 description_localizations: None,
184 kind: CommandOptionType::Boolean,
185 max_length: None,
186 max_value: None,
187 min_length: None,
188 min_value: None,
189 name: "boolean name".to_owned(),
190 name_localizations: None,
191 options: None,
192 required: Some(true),
193 },
194 CommandOption {
195 autocomplete: None,
196 channel_types: Some(Vec::new()),
197 choices: None,
198 description: "channel desc".to_owned(),
199 description_localizations: None,
200 kind: CommandOptionType::Channel,
201 max_length: None,
202 max_value: None,
203 min_length: None,
204 min_value: None,
205 name: "channel name".to_owned(),
206 name_localizations: None,
207 options: None,
208 required: None,
209 },
210 CommandOption {
211 autocomplete: None,
212 channel_types: Some(Vec::from([ChannelType::GuildText])),
213 choices: None,
214 description: "channel desc".to_owned(),
215 description_localizations: None,
216 kind: CommandOptionType::Channel,
217 max_length: None,
218 max_value: None,
219 min_length: None,
220 min_value: None,
221 name: "channel name".to_owned(),
222 name_localizations: None,
223 options: None,
224 required: None,
225 },
226 CommandOption {
227 autocomplete: Some(true),
228 channel_types: None,
229 choices: Some(Vec::new()),
230 description: "integer desc".to_owned(),
231 description_localizations: None,
232 kind: CommandOptionType::Integer,
233 max_length: None,
234 max_value: Some(CommandOptionValue::Integer(100)),
235 min_length: None,
236 min_value: Some(CommandOptionValue::Integer(0)),
237 name: "integer name".to_owned(),
238 name_localizations: None,
239 options: None,
240 required: None,
241 },
242 CommandOption {
243 autocomplete: None,
244 channel_types: None,
245 choices: None,
246 description: "mentionable desc".to_owned(),
247 description_localizations: Some(HashMap::from([(
248 "en-GB".to_owned(),
249 "mentionable desc (but british)".to_owned(),
250 )])),
251 kind: CommandOptionType::Mentionable,
252 max_length: None,
253 max_value: None,
254 min_length: None,
255 min_value: None,
256 name: "mentionable name".to_owned(),
257 name_localizations: None,
258 options: None,
259 required: None,
260 },
261 CommandOption {
262 autocomplete: Some(false),
263 channel_types: None,
264 choices: Some(Vec::from([CommandOptionChoice {
265 name: "number choice".to_owned(),
266 name_localizations: Some(HashMap::from([(
267 "en-US".to_owned(),
268 "number choice (but american)".to_owned(),
269 )])),
270 value: CommandOptionChoiceValue::Number(10.0),
271 }])),
272 description: "number desc".to_owned(),
273 description_localizations: None,
274 kind: CommandOptionType::Number,
275 max_length: None,
276 max_value: None,
277 min_length: None,
278 min_value: None,
279 name: "number name".to_owned(),
280 name_localizations: None,
281 options: None,
282 required: None,
283 },
284 CommandOption {
285 autocomplete: None,
286 channel_types: None,
287 choices: None,
288 description: "role desc".to_owned(),
289 description_localizations: None,
290 kind: CommandOptionType::Role,
291 max_length: None,
292 max_value: None,
293 min_length: None,
294 min_value: None,
295 name: "role name".to_owned(),
296 name_localizations: Some(HashMap::from([(
297 "de-DE".to_owned(),
298 "role name (but german)".to_owned(),
299 )])),
300 options: None,
301 required: None,
302 },
303 CommandOption {
304 autocomplete: None,
305 channel_types: None,
306 choices: None,
307 description: "string desc".to_owned(),
308 description_localizations: None,
309 kind: CommandOptionType::String,
310 max_length: Some(6000),
311 max_value: None,
312 min_length: Some(0),
313 min_value: None,
314 name: "string name".to_owned(),
315 name_localizations: None,
316 options: None,
317 required: None,
318 },
319 ])),
320 required: None,
321 }])),
322 required: None,
323 }]),
324 version: Id::new(1),
325 };
326
327 serde_test::assert_tokens(
328 &value,
329 &[
330 Token::Struct {
331 name: "Command",
332 len: 12,
333 },
334 Token::Str("application_id"),
335 Token::Some,
336 Token::NewtypeStruct { name: "Id" },
337 Token::Str("100"),
338 Token::Str("default_member_permissions"),
339 Token::Some,
340 Token::Str("8"),
341 Token::Str("dm_permission"),
342 Token::Some,
343 Token::Bool(false),
344 Token::Str("description"),
345 Token::Str("this command is a test"),
346 Token::Str("description_localizations"),
347 Token::Some,
348 Token::Map { len: Some(1) },
349 Token::Str("en-US"),
350 Token::Str("this command is a test"),
351 Token::MapEnd,
352 Token::Str("guild_id"),
353 Token::Some,
354 Token::NewtypeStruct { name: "Id" },
355 Token::Str("300"),
356 Token::Str("id"),
357 Token::Some,
358 Token::NewtypeStruct { name: "Id" },
359 Token::Str("200"),
360 Token::Str("type"),
361 Token::U8(CommandType::ChatInput.into()),
362 Token::Str("name"),
363 Token::Str("test command"),
364 Token::Str("name_localizations"),
365 Token::Some,
366 Token::Map { len: Some(1) },
367 Token::Str("en-US"),
368 Token::Str("test command"),
369 Token::MapEnd,
370 Token::Str("options"),
371 Token::Seq { len: Some(1) },
372 Token::Struct {
373 name: "CommandOption",
374 len: 4,
375 },
376 Token::Str("description"),
377 Token::Str("sub command group desc"),
378 Token::Str("type"),
379 Token::U8(CommandOptionType::SubCommandGroup as u8),
380 Token::Str("name"),
381 Token::Str("sub command group name"),
382 Token::Str("options"),
383 Token::Some,
384 Token::Seq { len: Some(1) },
385 Token::Struct {
386 name: "CommandOption",
387 len: 4,
388 },
389 Token::Str("description"),
390 Token::Str("sub command desc"),
391 Token::Str("type"),
392 Token::U8(CommandOptionType::SubCommand as u8),
393 Token::Str("name"),
394 Token::Str("sub command name"),
395 Token::Str("options"),
396 Token::Some,
397 Token::Seq { len: Some(9) },
398 Token::Struct {
399 name: "CommandOption",
400 len: 3,
401 },
402 Token::Str("description"),
403 Token::Str("attachment desc"),
404 Token::Str("type"),
405 Token::U8(CommandOptionType::Attachment as u8),
406 Token::Str("name"),
407 Token::Str("attachment name"),
408 Token::StructEnd,
409 Token::Struct {
410 name: "CommandOption",
411 len: 4,
412 },
413 Token::Str("description"),
414 Token::Str("boolean desc"),
415 Token::Str("type"),
416 Token::U8(CommandOptionType::Boolean as u8),
417 Token::Str("name"),
418 Token::Str("boolean name"),
419 Token::Str("required"),
420 Token::Some,
421 Token::Bool(true),
422 Token::StructEnd,
423 Token::Struct {
424 name: "CommandOption",
425 len: 4,
426 },
427 Token::Str("channel_types"),
428 Token::Some,
429 Token::Seq { len: Some(0) },
430 Token::SeqEnd,
431 Token::Str("description"),
432 Token::Str("channel desc"),
433 Token::Str("type"),
434 Token::U8(CommandOptionType::Channel as u8),
435 Token::Str("name"),
436 Token::Str("channel name"),
437 Token::StructEnd,
438 Token::Struct {
439 name: "CommandOption",
440 len: 4,
441 },
442 Token::Str("channel_types"),
443 Token::Some,
444 Token::Seq { len: Some(1) },
445 Token::U8(ChannelType::GuildText.into()),
446 Token::SeqEnd,
447 Token::Str("description"),
448 Token::Str("channel desc"),
449 Token::Str("type"),
450 Token::U8(CommandOptionType::Channel as u8),
451 Token::Str("name"),
452 Token::Str("channel name"),
453 Token::StructEnd,
454 Token::Struct {
455 name: "CommandOption",
456 len: 7,
457 },
458 Token::Str("autocomplete"),
459 Token::Some,
460 Token::Bool(true),
461 Token::Str("choices"),
462 Token::Some,
463 Token::Seq { len: Some(0) },
464 Token::SeqEnd,
465 Token::Str("description"),
466 Token::Str("integer desc"),
467 Token::Str("type"),
468 Token::U8(CommandOptionType::Integer as u8),
469 Token::Str("max_value"),
470 Token::Some,
471 Token::I64(100),
472 Token::Str("min_value"),
473 Token::Some,
474 Token::I64(0),
475 Token::Str("name"),
476 Token::Str("integer name"),
477 Token::StructEnd,
478 Token::Struct {
479 name: "CommandOption",
480 len: 4,
481 },
482 Token::Str("description"),
483 Token::Str("mentionable desc"),
484 Token::Str("description_localizations"),
485 Token::Some,
486 Token::Map { len: Some(1) },
487 Token::Str("en-GB"),
488 Token::Str("mentionable desc (but british)"),
489 Token::MapEnd,
490 Token::Str("type"),
491 Token::U8(CommandOptionType::Mentionable as u8),
492 Token::Str("name"),
493 Token::Str("mentionable name"),
494 Token::StructEnd,
495 Token::Struct {
496 name: "CommandOption",
497 len: 5,
498 },
499 Token::Str("autocomplete"),
500 Token::Some,
501 Token::Bool(false),
502 Token::Str("choices"),
503 Token::Some,
504 Token::Seq { len: Some(1) },
505 Token::Struct {
506 name: "CommandOptionChoice",
507 len: 3,
508 },
509 Token::Str("name"),
510 Token::Str("number choice"),
511 Token::Str("name_localizations"),
512 Token::Some,
513 Token::Map { len: Some(1) },
514 Token::Str("en-US"),
515 Token::Str("number choice (but american)"),
516 Token::MapEnd,
517 Token::Str("value"),
518 Token::F64(10.0),
519 Token::StructEnd,
520 Token::SeqEnd,
521 Token::Str("description"),
522 Token::Str("number desc"),
523 Token::Str("type"),
524 Token::U8(CommandOptionType::Number as u8),
525 Token::Str("name"),
526 Token::Str("number name"),
527 Token::StructEnd,
528 Token::Struct {
529 name: "CommandOption",
530 len: 4,
531 },
532 Token::Str("description"),
533 Token::Str("role desc"),
534 Token::Str("type"),
535 Token::U8(CommandOptionType::Role as u8),
536 Token::Str("name"),
537 Token::Str("role name"),
538 Token::Str("name_localizations"),
539 Token::Some,
540 Token::Map { len: Some(1) },
541 Token::Str("de-DE"),
542 Token::Str("role name (but german)"),
543 Token::MapEnd,
544 Token::StructEnd,
545 Token::Struct {
546 name: "CommandOption",
547 len: 5,
548 },
549 Token::Str("description"),
550 Token::Str("string desc"),
551 Token::Str("type"),
552 Token::U8(CommandOptionType::String as u8),
553 Token::Str("max_length"),
554 Token::Some,
555 Token::U16(6000),
556 Token::Str("min_length"),
557 Token::Some,
558 Token::U16(0),
559 Token::Str("name"),
560 Token::Str("string name"),
561 Token::StructEnd,
562 Token::SeqEnd,
563 Token::StructEnd,
564 Token::SeqEnd,
565 Token::StructEnd,
566 Token::SeqEnd,
567 Token::Str("version"),
568 Token::NewtypeStruct { name: "Id" },
569 Token::Str("1"),
570 Token::StructEnd,
571 ],
572 );
573 }
574}