titanium_model/
command.rs

1//! Application Commands (Slash Commands).
2
3use crate::snowflake::Snowflake;
4use crate::TitanString;
5use serde::{Deserialize, Serialize};
6
7/// Application command structure.
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct ApplicationCommand {
10    /// Unique ID of the command.
11    #[serde(default)]
12    pub id: Option<Snowflake>,
13    /// Type of command.
14    #[serde(default, rename = "type")]
15    pub command_type: Option<CommandType>,
16    /// Application ID.
17    #[serde(default)]
18    pub application_id: Option<Snowflake>,
19    /// Guild ID (if guild-specific).
20    #[serde(default)]
21    pub guild_id: Option<Snowflake>,
22    /// Name of the command (1-32 chars).
23    pub name: String,
24    /// Description (1-100 characters).
25    pub description: String,
26    /// Parameters for the command.
27    #[serde(default)]
28    pub options: Vec<CommandOption>,
29    /// Default Permissions.
30    #[serde(default)]
31    pub default_member_permissions: Option<String>,
32    /// Whether usable in DMs.
33    #[serde(default)]
34    pub dm_permission: Option<bool>,
35    /// Whether unsafe for age-gated users.
36    #[serde(default)]
37    pub nsfw: bool,
38    /// Version ID.
39    #[serde(default)]
40    pub version: Option<Snowflake>,
41}
42
43impl ApplicationCommand {
44    /// Create a builder for an `ApplicationCommand`.
45    pub fn builder<'a>(
46        name: impl Into<TitanString<'a>>,
47        description: impl Into<TitanString<'a>>,
48    ) -> crate::builder::CommandBuilder<'a> {
49        crate::builder::CommandBuilder::new(name, description)
50    }
51}
52
53/// Type of Application Command.
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
55#[serde(from = "u8", into = "u8")]
56pub enum CommandType {
57    /// Slash Command (Chat Input).
58    ChatInput = 1,
59    /// User Context Menu.
60    User = 2,
61    /// Message Context Menu.
62    Message = 3,
63}
64
65impl From<u8> for CommandType {
66    fn from(value: u8) -> Self {
67        match value {
68            2 => CommandType::User,
69            3 => CommandType::Message,
70            _ => CommandType::ChatInput,
71        }
72    }
73}
74
75impl From<CommandType> for u8 {
76    fn from(value: CommandType) -> Self {
77        value as u8
78    }
79}
80
81/// Option for a command.
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct CommandOption {
84    /// Type of option.
85    #[serde(rename = "type")]
86    pub option_type: OptionType,
87    /// Name (1-32 chars).
88    pub name: String,
89    /// Description (1-100 chars).
90    pub description: String,
91    /// Whether required.
92    #[serde(default)]
93    pub required: bool,
94    /// Choices (for string/int/number).
95    #[serde(default)]
96    pub choices: Vec<CommandChoice>,
97    /// Sub-options (for SubCommand/SubCommandGroup).
98    #[serde(default)]
99    pub options: Vec<CommandOption>,
100    /// Channel types specific.
101    #[serde(default)]
102    pub channel_types: Vec<u8>,
103    /// Min value (int/number).
104    #[serde(default)]
105    pub min_value: Option<crate::json::Value>,
106    /// Max value (int/number).
107    #[serde(default)]
108    pub max_value: Option<crate::json::Value>,
109    /// Min length (string).
110    #[serde(default)]
111    pub min_length: Option<u16>,
112    /// Max length (string).
113    #[serde(default)]
114    pub max_length: Option<u16>,
115    /// Whether to autocomplete.
116    #[serde(default)]
117    pub autocomplete: bool,
118}
119
120/// Type of command option.
121#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
122#[serde(from = "u8", into = "u8")]
123pub enum OptionType {
124    SubCommand = 1,
125    SubCommandGroup = 2,
126    String = 3,
127    Integer = 4,
128    Boolean = 5,
129    User = 6,
130    Channel = 7,
131    Role = 8,
132    Mentionable = 9,
133    Number = 10,
134    Attachment = 11,
135}
136
137impl From<u8> for OptionType {
138    fn from(value: u8) -> Self {
139        match value {
140            1 => OptionType::SubCommand,
141            2 => OptionType::SubCommandGroup,
142
143            4 => OptionType::Integer,
144            5 => OptionType::Boolean,
145            6 => OptionType::User,
146            7 => OptionType::Channel,
147            8 => OptionType::Role,
148            9 => OptionType::Mentionable,
149            10 => OptionType::Number,
150            11 => OptionType::Attachment,
151            _ => OptionType::String,
152        }
153    }
154}
155
156impl From<OptionType> for u8 {
157    fn from(value: OptionType) -> Self {
158        value as u8
159    }
160}
161
162/// Command Choice.
163#[derive(Debug, Clone, Serialize, Deserialize)]
164pub struct CommandChoice {
165    /// Choice name.
166    pub name: String,
167    /// Choice value (string/int/double).
168    pub value: crate::json::Value,
169}