twilight_util/builder/
interaction_response_data.rs
1use twilight_model::{
2 application::command::CommandOptionChoice,
3 channel::message::{AllowedMentions, Component, Embed, MessageFlags},
4 http::{attachment::Attachment, interaction::InteractionResponseData},
5};
6
7#[derive(Clone, Debug)]
38#[must_use = "builders have no effect if unused"]
39pub struct InteractionResponseDataBuilder(InteractionResponseData);
40
41impl InteractionResponseDataBuilder {
42 pub const fn new() -> Self {
44 Self(InteractionResponseData {
45 allowed_mentions: None,
46 attachments: None,
47 choices: None,
48 components: None,
49 content: None,
50 custom_id: None,
51 embeds: None,
52 flags: None,
53 title: None,
54 tts: None,
55 })
56 }
57
58 #[allow(clippy::missing_const_for_fn)]
60 #[must_use = "builders have no effect if unused"]
61 pub fn build(self) -> InteractionResponseData {
62 self.0
63 }
64
65 #[allow(clippy::missing_const_for_fn)]
69 pub fn allowed_mentions(mut self, allowed_mentions: AllowedMentions) -> Self {
70 self.0.allowed_mentions = Some(allowed_mentions);
71
72 self
73 }
74
75 pub fn attachments(mut self, attachments: impl IntoIterator<Item = Attachment>) -> Self {
79 self.0.attachments = Some(attachments.into_iter().collect());
80
81 self
82 }
83
84 pub fn choices(mut self, choices: impl IntoIterator<Item = CommandOptionChoice>) -> Self {
91 self.0.choices = Some(choices.into_iter().collect());
92
93 self
94 }
95
96 pub fn components(mut self, components: impl IntoIterator<Item = Component>) -> Self {
100 self.0.components = Some(components.into_iter().collect());
101
102 self
103 }
104
105 pub fn content(mut self, content: impl Into<String>) -> Self {
109 self.0.content = Some(content.into());
110
111 self
112 }
113
114 pub fn custom_id(mut self, custom_id: impl Into<String>) -> Self {
118 self.0.custom_id = Some(custom_id.into());
119
120 self
121 }
122
123 pub fn embeds(mut self, embeds: impl IntoIterator<Item = Embed>) -> Self {
127 self.0.embeds = Some(embeds.into_iter().collect());
128
129 self
130 }
131
132 pub const fn flags(mut self, flags: MessageFlags) -> Self {
141 self.0.flags = Some(flags);
142
143 self
144 }
145
146 pub fn title(mut self, title: impl Into<String>) -> Self {
150 self.0.title = Some(title.into());
151
152 self
153 }
154
155 pub const fn tts(mut self, value: bool) -> Self {
159 self.0.tts = Some(value);
160
161 self
162 }
163}
164
165impl Default for InteractionResponseDataBuilder {
166 fn default() -> Self {
167 Self::new()
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174 use static_assertions::assert_impl_all;
175 use std::fmt::Debug;
176 use twilight_model::{
177 channel::message::{
178 component::{Button, ButtonStyle},
179 MentionType,
180 },
181 util::Timestamp,
182 };
183
184 assert_impl_all!(
185 InteractionResponseDataBuilder: Clone,
186 Debug,
187 Default,
188 Send,
189 Sync
190 );
191
192 #[test]
193 fn callback_data_builder() {
194 let allowed_mentions = AllowedMentions {
195 parse: Vec::from([MentionType::Everyone]),
196 ..Default::default()
197 };
198
199 let component = Component::Button(Button {
200 style: ButtonStyle::Primary,
201 emoji: None,
202 label: Some("test label".into()),
203 custom_id: Some("test custom id".into()),
204 url: None,
205 disabled: false,
206 sku_id: None,
207 });
208
209 let embed = Embed {
210 author: None,
211 color: Some(123),
212 description: Some("a description".to_owned()),
213 fields: Vec::new(),
214 footer: None,
215 image: None,
216 kind: "rich".to_owned(),
217 provider: None,
218 thumbnail: None,
219 timestamp: Some(Timestamp::from_secs(1_580_608_922).unwrap()),
220 title: Some("a title".to_owned()),
221 url: Some("https://example.com".to_owned()),
222 video: None,
223 };
224
225 let value = InteractionResponseDataBuilder::new()
226 .allowed_mentions(allowed_mentions.clone())
227 .components([component.clone()])
228 .content("a content")
229 .embeds([embed.clone()])
230 .flags(MessageFlags::empty())
231 .tts(false)
232 .build();
233
234 let expected = InteractionResponseData {
235 allowed_mentions: Some(allowed_mentions),
236 attachments: None,
237 choices: None,
238 components: Some(vec![component]),
239 content: Some("a content".to_owned()),
240 custom_id: None,
241 embeds: Some(vec![embed]),
242 flags: Some(MessageFlags::empty()),
243 title: None,
244 tts: Some(false),
245 };
246
247 assert_eq!(value, expected);
248 }
249}