twilight_util/builder/message/
button.rs

1use twilight_model::channel::message::{
2    component::{Button, ButtonStyle},
3    EmojiReactionType,
4};
5use twilight_validate::component::{button, ComponentValidationError};
6
7/// Create a button from a builder.
8#[derive(Clone, Debug, Eq, PartialEq)]
9#[must_use = "must be built into a button"]
10pub struct ButtonBuilder(Button);
11
12impl ButtonBuilder {
13    /// Create a new button builder.
14    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    /// Sets the custom identifier of the button.
28    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    /// Specify whether this button is disabled.
35    pub const fn disabled(mut self, disabled: bool) -> Self {
36        self.0.disabled = disabled;
37
38        self
39    }
40
41    /// Add an emoji to this button.
42    pub fn emoji(mut self, emoji: EmojiReactionType) -> Self {
43        self.0.emoji.replace(emoji);
44
45        self
46    }
47
48    /// Sets the URL for this button.
49    pub fn url(mut self, url: impl Into<String>) -> Self {
50        self.0.url.replace(url.into());
51
52        self
53    }
54
55    /// Sets the label for this button.
56    pub fn label(mut self, label: impl Into<String>) -> Self {
57        self.0.label.replace(label.into());
58
59        self
60    }
61
62    /// Validate the fields in this builder.
63    ///
64    /// # Errors
65    pub fn validate(self) -> Result<Self, ComponentValidationError> {
66        button(&self.0)?;
67
68        Ok(self)
69    }
70
71    /// Build into a button.
72    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}