twilight_interactions/command/
internal.rs

1//! Internal types used by command traits.
2//!
3//! This module contains types used by trait definitions in the [`command`]
4//! module and implementations generated by the derive macros.
5//!
6//! [`command`]: crate::command
7
8use std::collections::HashMap;
9
10use twilight_model::{
11    application::command::{
12        CommandOption, CommandOptionChoice, CommandOptionType, CommandOptionValue,
13    },
14    channel::ChannelType,
15};
16
17use super::{DescLocalizations, NameLocalizations};
18
19/// Internal representation of localization types ([`NameLocalizations`] and
20/// [`DescLocalizations`]).
21#[derive(Debug, Clone, PartialEq)]
22pub struct LocalizationsInternal {
23    pub fallback: String,
24    pub localizations: Option<HashMap<String, String>>,
25}
26
27/// Convert a type into a [`LocalizationsInternal`].
28pub trait IntoLocalizationsInternal {
29    fn into_localizations(self) -> LocalizationsInternal;
30}
31
32impl IntoLocalizationsInternal for DescLocalizations {
33    fn into_localizations(self) -> LocalizationsInternal {
34        LocalizationsInternal {
35            fallback: self.fallback,
36            localizations: Some(self.localizations),
37        }
38    }
39}
40
41impl IntoLocalizationsInternal for (&str, Option<NameLocalizations>) {
42    fn into_localizations(self) -> LocalizationsInternal {
43        LocalizationsInternal {
44            fallback: self.0.to_owned(),
45            localizations: self.1.map(|v| v.localizations),
46        }
47    }
48}
49
50impl IntoLocalizationsInternal for &str {
51    fn into_localizations(self) -> LocalizationsInternal {
52        LocalizationsInternal {
53            fallback: self.to_owned(),
54            localizations: None,
55        }
56    }
57}
58
59/// Data to create a command option from.
60///
61/// This type is used in the [`CreateOption`] trait and contains a subset of
62/// twilight's [`CommandOption`] fields.
63///
64/// [`CreateOption`]: super::CreateOption
65#[derive(Debug, Clone, PartialEq)]
66pub struct CreateOptionData {
67    /// Name of the option. It must be 32 characters or less.
68    pub name: String,
69    /// Localization dictionary for the option name. Keys must be valid locales.
70    pub name_localizations: Option<HashMap<String, String>>,
71    /// Description of the option. It must be 100 characters or less.
72    pub description: String,
73    /// Localization dictionary for the option description. Keys must be valid
74    /// locales.
75    pub description_localizations: Option<HashMap<String, String>>,
76    /// Whether the option is required to be completed by a user.
77    pub required: Option<bool>,
78    /// Whether the command supports autocomplete. Only for `STRING`, `INTEGER`
79    /// and `NUMBER` option types.
80    pub autocomplete: bool,
81    /// Data of the command option.
82    pub data: CommandOptionData,
83}
84
85/// Data of a command option.
86///
87/// This type holds settings of a command option used when
88/// parsing the option. It is used in the [`CommandOption`]
89/// trait.
90///
91/// [`CommandOption`]: super::CommandOption
92#[derive(Debug, Clone, Default, PartialEq)]
93pub struct CommandOptionData {
94    /// Restricts the channel choice to specific types. Only for `CHANNEL`
95    /// option type.
96    pub channel_types: Option<Vec<ChannelType>>,
97    /// Maximum value permitted. Only for `INTEGER` and `NUMBER` option types.
98    pub max_value: Option<CommandOptionValue>,
99    /// Minimum value permitted. Only for `INTEGER` and `NUMBER` option types.
100    pub min_value: Option<CommandOptionValue>,
101    /// Minimum value length. Only for `STRING` option type.
102    pub max_length: Option<u16>,
103    /// Maximum value length. Only for `STRING` option type.
104    pub min_length: Option<u16>,
105}
106
107/// Builder to convert a [`CreateOptionData`] into a [`CommandOption`].
108pub struct CreateOptionBuilder {
109    kind: CommandOptionType,
110    option: CreateOptionData,
111    choices: Option<Vec<CommandOptionChoice>>,
112    options: Option<Vec<CommandOption>>,
113}
114
115impl CreateOptionBuilder {
116    /// Create a new [`CreateOptionBuilder`].
117    pub fn new(option: CreateOptionData, kind: CommandOptionType) -> Self {
118        Self {
119            kind,
120            option,
121            choices: None,
122            options: None,
123        }
124    }
125
126    /// Set the option choices.
127    pub fn choices(mut self, choices: Vec<CommandOptionChoice>) -> Self {
128        self.choices = Some(choices);
129
130        self
131    }
132
133    /// Set the subcommand options.
134    pub fn options(mut self, options: Vec<CommandOption>) -> Self {
135        self.options = Some(options);
136
137        self
138    }
139
140    /// Build the [`CommandOption`].
141    pub fn build(self) -> CommandOption {
142        CommandOption {
143            autocomplete: Some(self.option.autocomplete),
144            channel_types: self.option.data.channel_types,
145            choices: self.choices,
146            description: self.option.description,
147            description_localizations: self.option.description_localizations,
148            kind: self.kind,
149            max_length: self.option.data.max_length,
150            max_value: self.option.data.max_value,
151            min_length: self.option.data.min_length,
152            min_value: self.option.data.min_value,
153            name: self.option.name,
154            name_localizations: self.option.name_localizations,
155            options: self.options,
156            required: self.option.required,
157        }
158    }
159}
160
161impl CreateOptionData {
162    /// Create a new [`CreateOptionBuilder`].
163    pub fn builder(self, kind: CommandOptionType) -> CreateOptionBuilder {
164        CreateOptionBuilder::new(self, kind)
165    }
166
167    /// Convert the data into a [`CommandOption`].
168    pub fn into_option(self, kind: CommandOptionType) -> CommandOption {
169        self.builder(kind).build()
170    }
171}