slack_messaging/blocks/elements/types.rs
1use crate::composition_objects::{Plain, Text};
2use crate::validators::*;
3
4use serde::Serialize;
5use slack_messaging_derive::Builder;
6
7/// Icons for [`IconButton`](crate::blocks::elements::IconButton).
8#[derive(Debug, Copy, Clone, Serialize, PartialEq)]
9#[serde(rename_all = "snake_case")]
10pub enum Icon {
11 Trash,
12}
13
14/// Possible filetype values for filetypes field of
15/// [`FileInput`](crate::blocks::elements::FileInput).
16/// See [this](https://docs.slack.dev/reference/objects/file-object#types).
17#[derive(Debug, Copy, Clone, Serialize, PartialEq)]
18#[serde(rename_all = "snake_case")]
19pub enum FileType {
20 /// Auto Detect Type
21 Auto,
22 /// Plain Text
23 Text,
24 /// Illustrator File
25 Ai,
26 /// APK
27 Apk,
28 /// AppleScript
29 Applescript,
30 /// Binary
31 Binary,
32 /// Bitmap
33 Bmp,
34 /// BoxNote
35 Boxnote,
36 /// C
37 C,
38 /// C#
39 Csharp,
40 /// C++
41 Cpp,
42 /// Css
43 Css,
44 /// CSV
45 Csv,
46 /// Clojure
47 Clojure,
48 /// CoffeeScript
49 Coffeescript,
50 /// ColdFusion
51 Cfm,
52 /// D
53 D,
54 /// Dart
55 Dart,
56 /// Diff
57 Diff,
58 /// Word Document
59 Doc,
60 /// Word document
61 Docx,
62 /// Docker
63 Dockerfile,
64 /// Word template
65 Dotx,
66 /// Email
67 Email,
68 /// EPS
69 Eps,
70 /// EPUB
71 Epub,
72 /// Erlang
73 Erlang,
74 /// Flash FLA
75 Fla,
76 /// Flash video
77 Flv,
78 /// F#
79 Fsharp,
80 /// Fortran
81 Fortran,
82 /// GDocs Document
83 Gdoc,
84 /// GDocs Drawing
85 Gdraw,
86 /// GIF
87 Gif,
88 /// Go
89 Go,
90 /// GDocs Presentation
91 Gpres,
92 /// Groovy
93 Groovy,
94 /// GDocs Spreadsheet
95 Gsheet,
96 /// Gzip
97 Gzip,
98 /// HTML
99 Html,
100 /// Handlebars
101 Handlebars,
102 /// Haskell
103 Haskell,
104 /// Haxe
105 Haxe,
106 /// InDesign Document
107 Indd,
108 /// Java
109 Java,
110 /// JavaScript
111 Javascript,
112 /// JPEG
113 Jpg,
114 /// JSON
115 Json,
116 /// Keynote Document
117 Keynote,
118 /// Kotlin
119 Kotlin,
120 /// LaTeX/sTeX
121 Latex,
122 /// Lisp
123 Lisp,
124 /// Lua
125 Lua,
126 /// MPEG 4 audio
127 M4a,
128 /// Markdown (raw)
129 Markdown,
130 /// MATLAB
131 Matlab,
132 /// MHTML
133 Mhtml,
134 /// Matroska video
135 Mkv,
136 /// QuickTime video
137 Mov,
138 /// MP3
139 Mp3,
140 /// MPEG 4 video
141 Mp4,
142 /// MPEG video
143 Mpg,
144 /// MUMPS
145 Mumps,
146 /// Numbers Document
147 Numbers,
148 /// NZB
149 Nzb,
150 /// Objective-C
151 Objc,
152 /// OCaml
153 Ocaml,
154 /// OpenDocument Drawing
155 Odg,
156 /// OpenDocument Image
157 Odi,
158 /// OpenDocument Presentation
159 Odp,
160 /// OpenDocument Spreadsheet
161 Ods,
162 /// OpenDocument Text
163 Odt,
164 /// Ogg Vorbis
165 Ogg,
166 /// Ogg video
167 Ogv,
168 /// Pages Document
169 Pages,
170 /// Pascal
171 Pascal,
172 /// PDF
173 Pdf,
174 /// Perl
175 Perl,
176 /// PHP
177 Php,
178 /// Pig
179 Pig,
180 /// PNG
181 Png,
182 /// Slack Post
183 Post,
184 /// PowerShell
185 Powershell,
186 /// PowerPoint presentation
187 Ppt,
188 /// PowerPoint presentation
189 Pptx,
190 /// Photoshop Document
191 Psd,
192 /// Puppet
193 Puppet,
194 /// Python
195 Python,
196 /// Quartz Composer Composition
197 Qtz,
198 /// R
199 R,
200 /// Rich Text File
201 Rtf,
202 /// Ruby
203 Ruby,
204 /// Rust
205 Rust,
206 /// SQL
207 Sql,
208 /// Sass
209 Sass,
210 /// Scala
211 Scala,
212 /// Scheme
213 Scheme,
214 /// Sketch File
215 Sketch,
216 /// Shell
217 Shell,
218 /// Smalltalk
219 Smalltalk,
220 /// SVG
221 Svg,
222 /// Flash SWF
223 Swf,
224 /// Swift
225 Swift,
226 /// Tarball
227 Tar,
228 /// TIFF
229 Tiff,
230 /// TSV
231 Tsv,
232 /// VB.NET
233 Vb,
234 /// VBScript
235 Vbscript,
236 /// vCard
237 Vcard,
238 /// Velocity
239 Velocity,
240 /// Verilog
241 Verilog,
242 /// Waveform audio
243 Wav,
244 /// WebM
245 Webm,
246 /// Windows Media Video
247 Wmv,
248 /// Excel spreadsheet
249 Xls,
250 /// Excel spreadsheet
251 Xlsx,
252 /// Excel Spreadsheet (Binary, Macro Enabled)
253 Xlsb,
254 /// Excel Spreadsheet (Macro Enabled)
255 Xlsm,
256 /// Excel template
257 Xltx,
258 /// XML
259 Xml,
260 /// YAML
261 Yaml,
262 /// Zip
263 Zip,
264}
265
266/// Button object to be set to the `positive_buttons` and `negative_buttons`
267/// fields of [`FeedbackButtons`](crate::blocks::elements::FeedbackButtons) object.
268///
269/// # Fields and Validations
270///
271/// For more details, see the [official
272/// documentation](https://docs.slack.dev/reference/block-kit/block-elements/feedback-buttons-element).
273///
274/// | Field | Type | Required | Validation |
275/// |-------|------|----------|------------|
276/// | text | [Text]<[Plain]> | Yes | Max length 75 characters |
277/// | value | String | Yes | Max length 2000 characters |
278/// | accessibility_label | String | No | Max length 75 characters |
279///
280/// # Example
281///
282/// ```
283/// use slack_messaging::plain_text;
284/// use slack_messaging::blocks::elements::types::FeedbackButton;
285/// # use std::error::Error;
286///
287/// # fn try_main() -> Result<(), Box<dyn Error>> {
288/// let button = FeedbackButton::builder()
289/// .text(plain_text!("Good")?)
290/// .value("positive_feedback")
291/// .accessibility_label("Mark this response as good")
292/// .build()?;
293///
294/// let expected = serde_json::json!({
295/// "text": {
296/// "type": "plain_text",
297/// "text": "Good"
298/// },
299/// "value": "positive_feedback",
300/// "accessibility_label": "Mark this response as good"
301/// });
302///
303/// let json = serde_json::to_value(button).unwrap();
304///
305/// assert_eq!(json, expected);
306///
307/// // If your object has any validation errors, the build method returns Result::Err
308/// let button = FeedbackButton::builder()
309/// .text(plain_text!("Good")?)
310/// .build();
311/// assert!(button.is_err());
312/// # Ok(())
313/// # }
314/// # fn main() {
315/// # try_main().unwrap()
316/// # }
317/// ```
318#[derive(Debug, Clone, Serialize, PartialEq, Builder)]
319pub struct FeedbackButton {
320 #[builder(validate("required", "text_object::max_75"))]
321 pub(crate) text: Option<Text<Plain>>,
322
323 #[builder(validate("required", "text::max_2000"))]
324 pub(crate) value: Option<String>,
325
326 #[serde(skip_serializing_if = "Option::is_none")]
327 #[builder(validate("text::max_75"))]
328 pub(crate) accessibility_label: Option<String>,
329}
330
331#[cfg(test)]
332mod tests {
333 use super::*;
334 use crate::composition_objects::test_helpers::*;
335 use crate::errors::*;
336
337 mod feedback_button {
338 use super::*;
339
340 #[test]
341 fn it_implements_builder() {
342 let expected = FeedbackButton {
343 text: Some(plain_text("Good")),
344 value: Some("positive_feedback".into()),
345 accessibility_label: Some("Mark this response as good".into()),
346 };
347
348 let val = FeedbackButton::builder()
349 .set_text(Some(plain_text("Good")))
350 .set_value(Some("positive_feedback"))
351 .set_accessibility_label(Some("Mark this response as good"))
352 .build()
353 .unwrap();
354
355 assert_eq!(val, expected);
356
357 let val = FeedbackButton::builder()
358 .text(plain_text("Good"))
359 .value("positive_feedback")
360 .accessibility_label("Mark this response as good")
361 .build()
362 .unwrap();
363
364 assert_eq!(val, expected);
365 }
366
367 #[test]
368 fn it_requires_text_field() {
369 let err = FeedbackButton::builder()
370 .value("positive_feedback")
371 .build()
372 .unwrap_err();
373 assert_eq!(err.object(), "FeedbackButton");
374
375 let errors = err.field("text");
376 assert!(errors.includes(ValidationErrorKind::Required));
377 }
378
379 #[test]
380 fn it_requires_text_less_than_75_characters_long() {
381 let err = FeedbackButton::builder()
382 .text(plain_text("a".repeat(76)))
383 .value("positive_feedback")
384 .build()
385 .unwrap_err();
386 assert_eq!(err.object(), "FeedbackButton");
387
388 let errors = err.field("text");
389 assert!(errors.includes(ValidationErrorKind::MaxTextLength(75)));
390 }
391
392 #[test]
393 fn it_requires_value_field() {
394 let err = FeedbackButton::builder()
395 .text(plain_text("Good"))
396 .build()
397 .unwrap_err();
398 assert_eq!(err.object(), "FeedbackButton");
399
400 let errors = err.field("value");
401 assert!(errors.includes(ValidationErrorKind::Required));
402 }
403
404 #[test]
405 fn it_requires_value_less_than_2000_characters_long() {
406 let err = FeedbackButton::builder()
407 .text(plain_text("Good"))
408 .value("a".repeat(2001))
409 .build()
410 .unwrap_err();
411 assert_eq!(err.object(), "FeedbackButton");
412
413 let errors = err.field("value");
414 assert!(errors.includes(ValidationErrorKind::MaxTextLength(2000)));
415 }
416
417 #[test]
418 fn it_requires_accessibility_label_less_than_75_characters_long() {
419 let err = FeedbackButton::builder()
420 .text(plain_text("Good"))
421 .value("positive_feedback")
422 .accessibility_label("a".repeat(76))
423 .build()
424 .unwrap_err();
425 assert_eq!(err.object(), "FeedbackButton");
426
427 let errors = err.field("accessibility_label");
428 assert!(errors.includes(ValidationErrorKind::MaxTextLength(75)));
429 }
430 }
431}