1use crate::{
2 channel::Attachment,
3 id::{Id, marker::GuildMarker},
4 util::Timestamp,
5};
6
7use super::{Component, Embed, Mention, MessageFlags, MessageSticker, MessageType};
8
9use crate::id::marker::RoleMarker;
10use serde::{Deserialize, Serialize};
11
12#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
14pub struct MessageSnapshot {
15 pub message: MessageSnapshotFields,
17 #[serde(skip_serializing_if = "Option::is_none")]
19 pub guild_id: Option<Id<GuildMarker>>,
20}
21
22#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
24pub struct MessageSnapshotFields {
25 pub attachments: Vec<Attachment>,
27 #[serde(default, skip_serializing_if = "Vec::is_empty")]
29 pub components: Vec<Component>,
30 pub content: String,
32 pub edited_timestamp: Option<Timestamp>,
34 pub embeds: Vec<Embed>,
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub flags: Option<MessageFlags>,
39 #[serde(rename = "type")]
41 pub kind: MessageType,
42 #[serde(default, skip_serializing_if = "Vec::is_empty")]
44 pub mentions: Vec<Mention>,
45 #[serde(default, skip_serializing_if = "Vec::is_empty")]
47 pub mention_roles: Vec<Id<RoleMarker>>,
48 #[serde(default, skip_serializing_if = "Vec::is_empty")]
50 pub sticker_items: Vec<MessageSticker>,
51 pub timestamp: Timestamp,
53}
54
55#[cfg(test)]
56mod tests {
57 use super::{MessageSnapshot, MessageSnapshotFields};
58 use crate::channel::message::component::{ActionRow, Button, ButtonStyle, ComponentType};
59 use crate::channel::message::sticker::StickerFormatType;
60 use crate::channel::message::{Component, MessageSticker, MessageType};
61 use crate::{channel::Attachment, id::Id, util::Timestamp};
62 use serde_test::Token;
63
64 #[test]
65 fn test_message_snapshot() {
66 let value = MessageSnapshot {
67 message: MessageSnapshotFields {
68 attachments: vec![Attachment {
69 content_type: None,
70 description: None,
71 duration_secs: None,
72 ephemeral: false,
73 filename: "file.jpg".to_owned(),
74 flags: None,
75 height: Some(100),
76 id: Id::new(1),
77 placeholder: Some("zSeKDQIoCLiHeIKeiLyfrsBqCIaYaHJ2Vg".to_owned()),
79 placeholder_version: Some(1),
80 proxy_url: "https://example.com".to_owned(),
81 size: 1000,
82 title: None,
83 url: "https://example.com".to_owned(),
84 waveform: None,
85 width: Some(100),
86 }],
87 components: vec![],
88 content: "test".to_owned(),
89 edited_timestamp: Some(Timestamp::from_secs(1_571_573_184).unwrap()),
90 embeds: Vec::new(),
91 kind: MessageType::Regular,
92 flags: None,
93 mentions: Vec::new(),
94 mention_roles: Vec::new(),
95 sticker_items: Vec::new(),
96 timestamp: Timestamp::from_secs(1_571_573_184).unwrap(),
97 },
98 guild_id: Some(Id::new(1)),
99 };
100
101 serde_test::assert_tokens(
102 &value,
103 &[
104 Token::Struct {
105 name: "MessageSnapshot",
106 len: 2,
107 },
108 Token::Str("message"),
109 Token::Struct {
110 name: "MessageSnapshotFields",
111 len: 6,
112 },
113 Token::Str("attachments"),
114 Token::Seq { len: Some(1) },
115 Token::Struct {
116 name: "Attachment",
117 len: 10,
118 },
119 Token::Str("content_type"),
120 Token::None,
121 Token::Str("filename"),
122 Token::Str("file.jpg"),
123 Token::Str("height"),
124 Token::Some,
125 Token::U64(100),
126 Token::Str("id"),
127 Token::NewtypeStruct { name: "Id" },
128 Token::Str("1"),
129 Token::Str("placeholder"),
130 Token::Some,
131 Token::Str("zSeKDQIoCLiHeIKeiLyfrsBqCIaYaHJ2Vg"),
132 Token::Str("placeholder_version"),
133 Token::Some,
134 Token::U64(1),
135 Token::Str("proxy_url"),
136 Token::Str("https://example.com"),
137 Token::Str("size"),
138 Token::U64(1000),
139 Token::Str("url"),
140 Token::Str("https://example.com"),
141 Token::Str("width"),
142 Token::Some,
143 Token::U64(100),
144 Token::StructEnd,
145 Token::SeqEnd,
146 Token::Str("content"),
147 Token::Str("test"),
148 Token::Str("edited_timestamp"),
149 Token::Some,
150 Token::Str("2019-10-20T12:06:24.000000+00:00"),
151 Token::Str("embeds"),
152 Token::Seq { len: Some(0) },
153 Token::SeqEnd,
154 Token::Str("type"),
155 Token::U8(0),
156 Token::Str("timestamp"),
157 Token::Str("2019-10-20T12:06:24.000000+00:00"),
158 Token::StructEnd,
159 Token::Str("guild_id"),
160 Token::Some,
161 Token::NewtypeStruct { name: "Id" },
162 Token::Str("1"),
163 Token::StructEnd,
164 ],
165 );
166 }
167
168 #[allow(clippy::too_many_lines)]
169 #[test]
170 fn test_message_snapshot_with_sticker_and_components() {
171 let value = MessageSnapshot {
172 message: MessageSnapshotFields {
173 attachments: vec![Attachment {
174 content_type: None,
175 description: None,
176 duration_secs: None,
177 ephemeral: false,
178 filename: "file.jpg".to_owned(),
179 flags: None,
180 height: Some(100),
181 id: Id::new(1),
182 placeholder: Some("zSeKDQIoCLiHeIKeiLyfrsBqCIaYaHJ2Vg".to_owned()),
184 placeholder_version: Some(1),
185 proxy_url: "https://example.com".to_owned(),
186 size: 1000,
187 title: None,
188 url: "https://example.com".to_owned(),
189 waveform: None,
190 width: Some(100),
191 }],
192 components: vec![Component::ActionRow(ActionRow {
193 id: None,
194 components: Vec::from([Component::Button(Button {
195 id: None,
196 custom_id: Some("button-1".to_owned()),
197 disabled: false,
198 emoji: None,
199 style: ButtonStyle::Primary,
200 label: Some("Button".to_owned()),
201 url: None,
202 sku_id: None,
203 })]),
204 })],
205 content: "test".to_owned(),
206 edited_timestamp: Some(Timestamp::from_secs(1_571_573_184).unwrap()),
207 embeds: Vec::new(),
208 kind: MessageType::Regular,
209 flags: None,
210 mentions: Vec::new(),
211 mention_roles: Vec::new(),
212 sticker_items: vec![MessageSticker {
213 format_type: StickerFormatType::Png,
214 id: Id::new(1),
215 name: "sticker name".to_owned(),
216 }],
217 timestamp: Timestamp::from_secs(1_571_573_184).unwrap(),
218 },
219 guild_id: Some(Id::new(1)),
220 };
221
222 serde_test::assert_tokens(
223 &value,
224 &[
225 Token::Struct {
226 name: "MessageSnapshot",
227 len: 2,
228 },
229 Token::Str("message"),
230 Token::Struct {
231 name: "MessageSnapshotFields",
232 len: 8,
233 },
234 Token::Str("attachments"),
235 Token::Seq { len: Some(1) },
236 Token::Struct {
237 name: "Attachment",
238 len: 10,
239 },
240 Token::Str("content_type"),
241 Token::None,
242 Token::Str("filename"),
243 Token::Str("file.jpg"),
244 Token::Str("height"),
245 Token::Some,
246 Token::U64(100),
247 Token::Str("id"),
248 Token::NewtypeStruct { name: "Id" },
249 Token::Str("1"),
250 Token::Str("placeholder"),
251 Token::Some,
252 Token::Str("zSeKDQIoCLiHeIKeiLyfrsBqCIaYaHJ2Vg"),
253 Token::Str("placeholder_version"),
254 Token::Some,
255 Token::U64(1),
256 Token::Str("proxy_url"),
257 Token::Str("https://example.com"),
258 Token::Str("size"),
259 Token::U64(1000),
260 Token::Str("url"),
261 Token::Str("https://example.com"),
262 Token::Str("width"),
263 Token::Some,
264 Token::U64(100),
265 Token::StructEnd,
266 Token::SeqEnd,
267 Token::String("components"),
268 Token::Seq { len: Some(1) },
269 Token::Struct {
270 name: "Component",
271 len: 2,
272 },
273 Token::String("type"),
274 Token::U8(ComponentType::ActionRow.into()),
275 Token::String("components"),
276 Token::Seq { len: Some(1) },
277 Token::Struct {
278 name: "Component",
279 len: 4,
280 },
281 Token::String("type"),
282 Token::U8(2),
283 Token::String("custom_id"),
284 Token::Some,
285 Token::String("button-1"),
286 Token::String("label"),
287 Token::Some,
288 Token::String("Button"),
289 Token::String("style"),
290 Token::U8(1),
291 Token::StructEnd,
292 Token::SeqEnd,
293 Token::StructEnd,
294 Token::SeqEnd,
295 Token::Str("content"),
296 Token::Str("test"),
297 Token::Str("edited_timestamp"),
298 Token::Some,
299 Token::Str("2019-10-20T12:06:24.000000+00:00"),
300 Token::Str("embeds"),
301 Token::Seq { len: Some(0) },
302 Token::SeqEnd,
303 Token::Str("type"),
304 Token::U8(0),
305 Token::Str("sticker_items"),
306 Token::Seq { len: Some(1) },
307 Token::Struct {
308 name: "MessageSticker",
309 len: 3,
310 },
311 Token::Str("format_type"),
312 Token::U8(1),
313 Token::Str("id"),
314 Token::NewtypeStruct { name: "Id" },
315 Token::Str("1"),
316 Token::Str("name"),
317 Token::Str("sticker name"),
318 Token::StructEnd,
319 Token::SeqEnd,
320 Token::Str("timestamp"),
321 Token::Str("2019-10-20T12:06:24.000000+00:00"),
322 Token::StructEnd,
323 Token::Str("guild_id"),
324 Token::Some,
325 Token::NewtypeStruct { name: "Id" },
326 Token::Str("1"),
327 Token::StructEnd,
328 ],
329 );
330 }
331}