twilight_util/builder/message/
button.rs1use twilight_model::channel::message::{
2 component::{Button, ButtonStyle},
3 EmojiReactionType,
4};
5use twilight_validate::component::{button, ComponentValidationError};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
9#[must_use = "must be built into a button"]
10pub struct ButtonBuilder(Button);
11
12impl ButtonBuilder {
13 pub const fn new(style: ButtonStyle) -> Self {
15 Self(Button {
16 custom_id: None,
17 disabled: false,
18 emoji: None,
19 label: None,
20 style,
21 url: None,
22 id: None,
23 sku_id: None,
24 })
25 }
26
27 pub fn custom_id(mut self, custom_id: impl Into<String>) -> Self {
29 self.0.custom_id.replace(custom_id.into());
30
31 self
32 }
33
34 pub const fn disabled(mut self, disabled: bool) -> Self {
36 self.0.disabled = disabled;
37
38 self
39 }
40
41 pub fn emoji(mut self, emoji: EmojiReactionType) -> Self {
43 self.0.emoji.replace(emoji);
44
45 self
46 }
47
48 pub fn url(mut self, url: impl Into<String>) -> Self {
50 self.0.url.replace(url.into());
51
52 self
53 }
54
55 pub fn label(mut self, label: impl Into<String>) -> Self {
57 self.0.label.replace(label.into());
58
59 self
60 }
61
62 pub fn validate(self) -> Result<Self, ComponentValidationError> {
66 button(&self.0)?;
67
68 Ok(self)
69 }
70
71 pub fn build(self) -> Button {
73 self.0
74 }
75}
76
77impl From<ButtonBuilder> for Button {
78 fn from(builder: ButtonBuilder) -> Self {
79 builder.build()
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use static_assertions::assert_impl_all;
87 use std::fmt::Debug;
88
89 assert_impl_all!(ButtonBuilder: Clone, Debug, Eq, PartialEq, Send, Sync);
90 assert_impl_all!(Button: From<ButtonBuilder>);
91
92 #[test]
93 fn builder() {
94 let expected = Button {
95 custom_id: None,
96 disabled: false,
97 emoji: None,
98 label: None,
99 style: ButtonStyle::Primary,
100 url: None,
101 id: None,
102 sku_id: None,
103 };
104
105 let actual = ButtonBuilder::new(ButtonStyle::Primary).build();
106
107 assert_eq!(actual, expected);
108 }
109}