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            1 => CommandType::ChatInput,
69            2 => CommandType::User,
70            3 => CommandType::Message,
71            _ => CommandType::ChatInput,
72        }
73    }
74}
75
76impl From<CommandType> for u8 {
77    fn from(value: CommandType) -> Self {
78        value as u8
79    }
80}
81
82/// Option for a command.
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct CommandOption {
85    /// Type of option.
86    #[serde(rename = "type")]
87    pub option_type: OptionType,
88    /// Name (1-32 chars).
89    pub name: String,
90    /// Description (1-100 chars).
91    pub description: String,
92    /// Whether required.
93    #[serde(default)]
94    pub required: bool,
95    /// Choices (for string/int/number).
96    #[serde(default)]
97    pub choices: Vec<CommandChoice>,
98    /// Sub-options (for SubCommand/SubCommandGroup).
99    #[serde(default)]
100    pub options: Vec<CommandOption>,
101    /// Channel types specific.
102    #[serde(default)]
103    pub channel_types: Vec<u8>,
104    /// Min value (int/number).
105    #[serde(default)]
106    pub min_value: Option<crate::json::Value>,
107    /// Max value (int/number).
108    #[serde(default)]
109    pub max_value: Option<crate::json::Value>,
110    /// Min length (string).
111    #[serde(default)]
112    pub min_length: Option<u16>,
113    /// Max length (string).
114    #[serde(default)]
115    pub max_length: Option<u16>,
116    /// Whether to autocomplete.
117    #[serde(default)]
118    pub autocomplete: bool,
119}
120
121/// Type of command option.
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
123#[serde(from = "u8", into = "u8")]
124pub enum OptionType {
125    SubCommand = 1,
126    SubCommandGroup = 2,
127    String = 3,
128    Integer = 4,
129    Boolean = 5,
130    User = 6,
131    Channel = 7,
132    Role = 8,
133    Mentionable = 9,
134    Number = 10,
135    Attachment = 11,
136}
137
138impl From<u8> for OptionType {
139    fn from(value: u8) -> Self {
140        match value {
141            1 => OptionType::SubCommand,
142            2 => OptionType::SubCommandGroup,
143            3 => OptionType::String,
144            4 => OptionType::Integer,
145            5 => OptionType::Boolean,
146            6 => OptionType::User,
147            7 => OptionType::Channel,
148            8 => OptionType::Role,
149            9 => OptionType::Mentionable,
150            10 => OptionType::Number,
151            11 => OptionType::Attachment,
152            _ => OptionType::String,
153        }
154    }
155}
156
157impl From<OptionType> for u8 {
158    fn from(value: OptionType) -> Self {
159        value as u8
160    }
161}
162
163/// Command Choice.
164#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct CommandChoice {
166    /// Choice name.
167    pub name: String,
168    /// Choice value (string/int/double).
169    pub value: crate::json::Value,
170}