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