1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use nanoserde::{DeJson, SerJson};
use crate::consts::{ButtonStyle, ChannelType, SelectMenuType};
use super::emoji::Emoji;
/// Represents a component in a Discord message.
#[derive(DeJson, SerJson, Debug, Default, Clone)]
pub struct Component {
/// Type of component.
#[nserde(default = 1, rename = "type")]
pub type_: u32,
/// Nested components.
pub components: Option<Vec<Component>>,
/// Button style.
pub style: Option<u32>,
/// Button label.
pub label: Option<String>,
/// Button emoji.
pub emoji: Option<Emoji>,
/// Custom ID for the component.
pub custom_id: Option<String>,
/// URL for the button.
pub url: Option<String>,
/// Whether the component is disabled.
#[nserde(default)]
pub disabled: bool,
/// Options for select menus.
pub options: Option<Vec<SelectOption>>,
/// Channel types for select menus.
pub channel_types: Option<Vec<u32>>,
/// Placeholder text for select menus.
pub placeholder: Option<String>,
/// Default values for select menus.
pub default_values: Option<Vec<SelectDefaultValue>>,
/// Minimum values for select menus.
///
/// # TODO
/// Add checks for the range: 0-25.
pub min_values: Option<u32>,
/// Maximum values for select menus.
///
/// Defaults to 1.
///
/// # TODO
/// Add checks for the range: 0-25.
pub max_values: Option<u32>,
}
/// Represents an option in a select menu.
#[derive(DeJson, SerJson, Debug, Default, Clone)]
pub struct SelectOption {
/// Label for the option.
pub label: String,
/// Value for the option.
pub value: String,
/// Description for the option.
pub description: Option<String>,
/// Emoji for the option.
pub emoji: Option<Emoji>,
/// Whether the option is the default.
pub default: Option<bool>,
}
/// Represents a default value in a select menu.
#[derive(DeJson, SerJson, Debug, Default, Clone)]
pub struct SelectDefaultValue {
/// ID of a user, role, or channel.
pub id: String,
/// Either "user", "roles", or "channel".
#[nserde(rename = "type")]
pub type_: String,
}
/// Represents a select menu object.
#[derive(Debug, Clone, Default)]
pub struct SelectObject {
/// Type of the select menu.
pub select_type: SelectMenuType,
/// Custom ID for the select menu.
pub custom_id: String,
/// Options for the select menu.
pub options: Option<Vec<SelectOption>>,
/// Channel types for the select menu.
pub channel_types: Option<Vec<ChannelType>>,
/// Placeholder text for the select menu.
pub placeholder: Option<String>,
/// Default values for the select menu.
pub default_values: Option<Vec<SelectDefaultValue>>,
/// Minimum values for the select menu.
pub min_values: Option<u32>,
/// Maximum values for the select menu.
pub max_values: Option<u32>,
/// Whether the select menu is disabled.
pub disabled: bool,
}
impl SelectObject {
/// Verifies the select menu object.
///
/// # Errors
///
/// Returns an error if the min or max values are out of range.
pub(crate) fn verify(&self) -> Result<(), &'static str> {
if self.min_values.map(|i| i <= 25) == Some(false)
|| self.max_values.map(|i| i <= 25) == Some(false)
{
return Err("Min and max values should be in the range 0 to 25");
}
Ok(())
}
}
/// Represents a button object.
#[derive(Default)]
pub struct ButtonObject {
/// Style of the button.
pub style: u32,
/// Label for the button.
pub label: Option<String>,
/// Emoji for the button.
pub emoji: Option<Emoji>,
/// Custom ID for the button.
pub custom_id: Option<String>,
/// URL for the button.
pub url: Option<String>,
/// Whether the button is disabled.
pub disabled: bool,
}
impl ButtonObject {
/// Verifies the button object.
///
/// # Errors
///
/// Returns an error if the button configuration is invalid.
pub(crate) fn verify(&self) -> Result<(), &'static str> {
if self.style == ButtonStyle::Link as u32 {
if self.custom_id.is_some() {
return Err("Link buttons cannot have a custom id");
}
if self.url.is_none() {
return Err("Link buttons must have a url");
}
}
Ok(())
}
}