twilight_util/builder/
interaction_response_data.rs1use twilight_model::{
2 application::command::CommandOptionChoice,
3 channel::message::{AllowedMentions, Component, Embed, MessageFlags},
4 http::{attachment::Attachment, interaction::InteractionResponseData},
5 poll::Poll,
6};
7
8#[derive(Clone, Debug)]
39#[must_use = "builders have no effect if unused"]
40pub struct InteractionResponseDataBuilder(InteractionResponseData);
41
42impl InteractionResponseDataBuilder {
43 pub const fn new() -> Self {
45 Self(InteractionResponseData {
46 allowed_mentions: None,
47 attachments: None,
48 choices: None,
49 components: None,
50 content: None,
51 custom_id: None,
52 embeds: None,
53 flags: None,
54 title: None,
55 tts: None,
56 poll: None,
57 })
58 }
59
60 #[allow(clippy::missing_const_for_fn)]
62 #[must_use = "builders have no effect if unused"]
63 pub fn build(self) -> InteractionResponseData {
64 self.0
65 }
66
67 #[allow(clippy::missing_const_for_fn)]
71 pub fn allowed_mentions(mut self, allowed_mentions: AllowedMentions) -> Self {
72 self.0.allowed_mentions = Some(allowed_mentions);
73
74 self
75 }
76
77 pub fn attachments(mut self, attachments: impl IntoIterator<Item = Attachment>) -> Self {
81 self.0.attachments = Some(attachments.into_iter().collect());
82
83 self
84 }
85
86 pub fn choices(mut self, choices: impl IntoIterator<Item = CommandOptionChoice>) -> Self {
93 self.0.choices = Some(choices.into_iter().collect());
94
95 self
96 }
97
98 pub fn components(mut self, components: impl IntoIterator<Item = Component>) -> Self {
102 self.0.components = Some(components.into_iter().collect());
103
104 self
105 }
106
107 pub fn content(mut self, content: impl Into<String>) -> Self {
111 self.0.content = Some(content.into());
112
113 self
114 }
115
116 pub fn custom_id(mut self, custom_id: impl Into<String>) -> Self {
120 self.0.custom_id = Some(custom_id.into());
121
122 self
123 }
124
125 pub fn embeds(mut self, embeds: impl IntoIterator<Item = Embed>) -> Self {
129 self.0.embeds = Some(embeds.into_iter().collect());
130
131 self
132 }
133
134 pub const fn flags(mut self, flags: MessageFlags) -> Self {
143 self.0.flags = Some(flags);
144
145 self
146 }
147
148 pub fn title(mut self, title: impl Into<String>) -> Self {
152 self.0.title = Some(title.into());
153
154 self
155 }
156
157 pub const fn tts(mut self, value: bool) -> Self {
161 self.0.tts = Some(value);
162
163 self
164 }
165
166 pub fn poll(mut self, poll: Poll) -> Self {
168 self.0.poll = Some(poll);
169
170 self
171 }
172}
173
174impl Default for InteractionResponseDataBuilder {
175 fn default() -> Self {
176 Self::new()
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183 use static_assertions::assert_impl_all;
184 use std::fmt::Debug;
185 use twilight_model::{
186 channel::message::{
187 component::{Button, ButtonStyle},
188 MentionType,
189 },
190 poll::{PollLayoutType, PollMedia},
191 util::Timestamp,
192 };
193
194 assert_impl_all!(
195 InteractionResponseDataBuilder: Clone,
196 Debug,
197 Default,
198 Send,
199 Sync
200 );
201
202 #[test]
203 fn callback_data_builder() {
204 let allowed_mentions = AllowedMentions {
205 parse: Vec::from([MentionType::Everyone]),
206 ..Default::default()
207 };
208
209 let component = Component::Button(Button {
210 style: ButtonStyle::Primary,
211 emoji: None,
212 label: Some("test label".into()),
213 custom_id: Some("test custom id".into()),
214 url: None,
215 disabled: false,
216 sku_id: None,
217 });
218
219 let embed = Embed {
220 author: None,
221 color: Some(123),
222 description: Some("a description".to_owned()),
223 fields: Vec::new(),
224 footer: None,
225 image: None,
226 kind: "rich".to_owned(),
227 provider: None,
228 thumbnail: None,
229 timestamp: Some(Timestamp::from_secs(1_580_608_922).unwrap()),
230 title: Some("a title".to_owned()),
231 url: Some("https://example.com".to_owned()),
232 video: None,
233 };
234
235 let poll = Poll {
236 answers: vec![],
237 allow_multiselect: false,
238 expiry: None,
239 layout_type: PollLayoutType::Default,
240 question: PollMedia {
241 emoji: None,
242 text: Some("lorem ipsum".to_owned()),
243 },
244 results: None,
245 };
246
247 let value = InteractionResponseDataBuilder::new()
248 .allowed_mentions(allowed_mentions.clone())
249 .components([component.clone()])
250 .content("a content")
251 .embeds([embed.clone()])
252 .flags(MessageFlags::empty())
253 .tts(false)
254 .poll(poll.clone())
255 .build();
256
257 let expected = InteractionResponseData {
258 allowed_mentions: Some(allowed_mentions),
259 attachments: None,
260 choices: None,
261 components: Some(vec![component]),
262 content: Some("a content".to_owned()),
263 custom_id: None,
264 embeds: Some(vec![embed]),
265 flags: Some(MessageFlags::empty()),
266 title: None,
267 tts: Some(false),
268 poll: Some(poll),
269 };
270
271 assert_eq!(value, expected);
272 }
273}