twilight_util/builder/message/
select_menu.rs1use twilight_model::channel::{
2 ChannelType,
3 message::{
4 EmojiReactionType,
5 component::{SelectDefaultValue, SelectMenu, SelectMenuOption, SelectMenuType},
6 },
7};
8
9#[derive(Clone, Debug, Eq, PartialEq)]
11#[must_use = "must be built into a select menu option"]
12pub struct SelectMenuOptionBuilder(SelectMenuOption);
13
14impl SelectMenuOptionBuilder {
15 pub fn new(label: impl Into<String>, value: impl Into<String>) -> Self {
17 Self(SelectMenuOption {
18 default: false,
19 description: None,
20 emoji: None,
21 label: label.into(),
22 value: value.into(),
23 })
24 }
25
26 pub const fn default(mut self, default: bool) -> Self {
28 self.0.default = default;
29
30 self
31 }
32
33 pub fn emoji(mut self, emoji: EmojiReactionType) -> Self {
35 self.0.emoji.replace(emoji);
36
37 self
38 }
39
40 pub fn description(mut self, description: impl Into<String>) -> Self {
42 self.0.description.replace(description.into());
43
44 self
45 }
46
47 pub fn build(self) -> SelectMenuOption {
49 self.0
50 }
51}
52
53impl From<SelectMenuOptionBuilder> for SelectMenuOption {
54 fn from(builder: SelectMenuOptionBuilder) -> Self {
55 builder.build()
56 }
57}
58
59#[derive(Clone, Debug, Eq, PartialEq)]
61#[must_use = "must be built into a select menu"]
62pub struct SelectMenuBuilder(SelectMenu);
63
64impl SelectMenuBuilder {
65 pub fn new(custom_id: impl Into<String>, kind: SelectMenuType) -> Self {
67 Self(SelectMenu {
68 custom_id: custom_id.into(),
69 disabled: false,
70 max_values: None,
71 min_values: None,
72 options: None,
73 placeholder: None,
74 id: None,
75 channel_types: None,
76 default_values: None,
77 kind,
78 required: None,
79 })
80 }
81
82 pub const fn disabled(mut self, disabled: bool) -> Self {
84 self.0.disabled = disabled;
85
86 self
87 }
88
89 pub const fn max_values(mut self, max_values: u8) -> Self {
91 self.0.max_values.replace(max_values);
92
93 self
94 }
95
96 pub const fn min_values(mut self, min_values: u8) -> Self {
98 self.0.min_values.replace(min_values);
99
100 self
101 }
102
103 #[allow(clippy::missing_panics_doc)] pub fn option(mut self, option: impl Into<SelectMenuOption>) -> Self {
106 if self.0.options.is_none() {
107 self.0.options.replace(Vec::new());
108 }
109
110 self.0.options.as_mut().unwrap().push(option.into());
111
112 self
113 }
114
115 pub fn placeholder(mut self, placeholder: impl Into<String>) -> Self {
117 self.0.placeholder.replace(placeholder.into());
118
119 self
120 }
121
122 pub fn id(mut self, id: impl Into<i32>) -> Self {
124 self.0.id.replace(id.into());
125
126 self
127 }
128
129 pub fn channel_types(mut self, channel_types: Vec<ChannelType>) -> Self {
131 self.0.channel_types.replace(channel_types);
132
133 self
134 }
135
136 pub fn default_values(mut self, default_values: Vec<SelectDefaultValue>) -> Self {
138 self.0.default_values.replace(default_values);
139
140 self
141 }
142
143 pub const fn required(mut self, required: bool) -> Self {
147 self.0.required.replace(required);
148
149 self
150 }
151
152 pub fn build(self) -> SelectMenu {
154 self.0
155 }
156}
157
158impl From<SelectMenuBuilder> for SelectMenu {
159 fn from(builder: SelectMenuBuilder) -> Self {
160 builder.build()
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167 use static_assertions::assert_impl_all;
168 use std::fmt::Debug;
169
170 assert_impl_all!(SelectMenuBuilder: Clone, Debug, Eq, PartialEq, Send, Sync);
171 assert_impl_all!(SelectMenu: From<SelectMenuBuilder>);
172
173 #[test]
174 fn builder() {
175 let expected_option = SelectMenuOption {
176 default: false,
177 description: Some("test".to_string()),
178 emoji: None,
179 label: "bar".to_string(),
180 value: "foo".to_string(),
181 };
182
183 let expected = SelectMenu {
184 custom_id: "foo".to_string(),
185 disabled: false,
186 max_values: None,
187 min_values: None,
188 options: Some(vec![expected_option]),
189 placeholder: None,
190 id: None,
191 channel_types: None,
192 default_values: None,
193 kind: SelectMenuType::Text,
194 required: None,
195 };
196
197 let actual = SelectMenuBuilder::new("foo", SelectMenuType::Text)
198 .option(SelectMenuOptionBuilder::new("bar", "foo").description("test"))
199 .build();
200
201 assert_eq!(actual, expected);
202 }
203}