twilight_model/http/attachment.rs
1//! Models used when sending attachments to Discord.
2
3use serde::{Deserialize, Serialize};
4
5/// Attachments used in messages.
6///
7/// # Examples
8///
9/// Create an attachment of a short JSON blob describing a cat with a
10/// description for screen readers:
11///
12/// ```
13/// use twilight_model::http::attachment::Attachment;
14///
15/// let filename = "twilight_sparkle.json".to_owned();
16/// let file_content = br#"{
17/// "best_friend": "Spike",
18/// "cutie_mark": "sparkles",
19/// "name": "Twilight Sparkle"
20/// }"#
21/// .to_vec();
22/// let id = 1;
23///
24/// let mut attachment = Attachment::from_bytes(filename, file_content, id);
25/// attachment.description("Raw data about Twilight Sparkle".to_owned());
26/// ```
27#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
28pub struct Attachment {
29 /// Title of the file.
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub title: Option<String>,
32 /// Description of the attachment, useful for screen readers and users
33 /// requiring alt text.
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub description: Option<String>,
36 /// Content of the file.
37 #[serde(skip)]
38 pub file: Vec<u8>,
39 /// Name of the file.
40 ///
41 /// Examples may be `twilight_sparkle.png`, `cat.jpg`, or `logs.txt`.
42 pub filename: String,
43 /// Unique ID of the attachment in the message.
44 ///
45 /// While attachment IDs can be the same as attachments in other messages,
46 /// they must be unique within the same message. Attachment IDs don't need
47 /// to be in any particular format; for example, IDs of 0, 100, the current
48 /// timestamp, and so on are all valid.
49 pub id: u64,
50 /// Duration of the audio or video file.
51 ///
52 /// Required for voice messages.
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub duration_secs: Option<f64>,
55 /// Base64 encoded bytearray representing a sampled waveform.
56 ///
57 /// Required for voice messages.
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub waveform: Option<String>,
60 /// Whether the attachment should be marked as a spoiler and blurred until clicked.
61 ///
62 /// This sets the [`IS_SPOILER`] attachment flag.
63 ///
64 /// [`IS_SPOILER`]: twilight_model::channel::attachment_flags::AttachmentFlags::IS_SPOILER
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub is_spoiler: Option<bool>,
67}
68
69impl Attachment {
70 /// Create an attachment from a filename and bytes.
71 ///
72 /// # Examples
73 ///
74 /// Create an attachment with a grocery list named "grocerylist.txt":
75 ///
76 /// ```
77 /// use twilight_model::http::attachment::Attachment;
78 ///
79 /// let filename = "grocerylist.txt".to_owned();
80 /// let file_content = b"Apples\nGrapes\nLemonade".to_vec();
81 /// let id = 1;
82 ///
83 /// let attachment = Attachment::from_bytes(filename, file_content, id);
84 /// ```
85 pub const fn from_bytes(filename: String, file: Vec<u8>, id: u64) -> Self {
86 Self {
87 title: None,
88 description: None,
89 file,
90 filename,
91 id,
92 duration_secs: None,
93 waveform: None,
94 is_spoiler: None,
95 }
96 }
97
98 /// Set the description of the attachment.
99 ///
100 /// Attachment descriptions are useful for those requiring screen readers
101 /// and are displayed as alt text.
102 pub fn description(&mut self, description: String) {
103 self.description = Some(description);
104 }
105}