1use crate::{
2 channel::{thread::ThreadMetadata, Attachment, ChannelType, Message},
3 guild::{MemberFlags, Permissions, Role},
4 id::{
5 marker::{AttachmentMarker, ChannelMarker, MessageMarker, RoleMarker, UserMarker},
6 Id,
7 },
8 user::User,
9 util::{ImageHash, Timestamp},
10};
11use serde::{Deserialize, Serialize};
12use std::collections::hash_map::HashMap;
13
14#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
21pub struct InteractionDataResolved {
22 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
24 pub attachments: HashMap<Id<AttachmentMarker>, Attachment>,
25 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
27 pub channels: HashMap<Id<ChannelMarker>, InteractionChannel>,
28 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
32 pub members: HashMap<Id<UserMarker>, InteractionMember>,
33 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
35 pub messages: HashMap<Id<MessageMarker>, Message>,
36 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
38 pub roles: HashMap<Id<RoleMarker>, Role>,
39 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
41 pub users: HashMap<Id<UserMarker>, User>,
42}
43
44#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
48pub struct InteractionChannel {
49 pub id: Id<ChannelMarker>,
51 #[serde(rename = "type")]
55 pub kind: ChannelType,
56 pub name: String,
58 #[serde(skip_serializing_if = "Option::is_none")]
60 pub parent_id: Option<Id<ChannelMarker>>,
61 pub permissions: Permissions,
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub thread_metadata: Option<ThreadMetadata>,
66}
67
68#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
72pub struct InteractionMember {
73 #[serde(skip_serializing_if = "Option::is_none")]
75 pub avatar: Option<ImageHash>,
76 pub communication_disabled_until: Option<Timestamp>,
78 pub flags: MemberFlags,
82 pub joined_at: Option<Timestamp>,
84 pub nick: Option<String>,
86 pub pending: bool,
89 pub permissions: Permissions,
91 #[serde(skip_serializing_if = "Option::is_none")]
92 pub premium_since: Option<Timestamp>,
93 #[serde(default)]
95 pub roles: Vec<Id<RoleMarker>>,
96}
97
98#[cfg(test)]
99mod tests {
100 use super::{InteractionChannel, InteractionDataResolved, InteractionMember};
101 use crate::{
102 channel::{
103 message::{
104 sticker::{MessageSticker, StickerFormatType},
105 MessageFlags, MessageType,
106 },
107 Attachment, ChannelType, Message,
108 },
109 guild::{MemberFlags, PartialMember, Permissions, Role, RoleFlags},
110 id::Id,
111 test::image_hash,
112 user::{PremiumType, User, UserFlags},
113 util::datetime::{Timestamp, TimestampParseError},
114 };
115 use serde_test::Token;
116 use std::str::FromStr;
117
118 #[test]
119 #[allow(clippy::too_many_lines, deprecated)]
120 fn test_data_resolved() -> Result<(), TimestampParseError> {
121 let joined_at = Some(Timestamp::from_str("2021-08-10T12:18:37.000000+00:00")?);
122 let timestamp = Timestamp::from_str("2020-02-02T02:02:02.020000+00:00")?;
123 let flags = MemberFlags::BYPASSES_VERIFICATION | MemberFlags::DID_REJOIN;
124
125 let value = InteractionDataResolved {
126 attachments: IntoIterator::into_iter([(
127 Id::new(400),
128 Attachment {
129 content_type: Some("image/png".to_owned()),
130 ephemeral: true,
131 filename: "rainbow_dash.png".to_owned(),
132 flags: None,
133 description: None,
134 duration_secs: None,
135 height: Some(2674),
136 id: Id::new(400),
137 proxy_url: "https://proxy.example.com/rainbow_dash.png".to_owned(),
138 size: 13370,
139 title: None,
140 url: "https://example.com/rainbow_dash.png".to_owned(),
141 waveform: None,
142 width: Some(1337),
143 },
144 )])
145 .collect(),
146 channels: IntoIterator::into_iter([(
147 Id::new(100),
148 InteractionChannel {
149 id: Id::new(100),
150 kind: ChannelType::GuildText,
151 name: "channel name".into(),
152 parent_id: None,
153 permissions: Permissions::empty(),
154 thread_metadata: None,
155 },
156 )])
157 .collect(),
158 members: IntoIterator::into_iter([(
159 Id::new(300),
160 InteractionMember {
161 avatar: None,
162 communication_disabled_until: None,
163 flags,
164 joined_at,
165 nick: None,
166 pending: false,
167 permissions: Permissions::empty(),
168 premium_since: None,
169 roles: Vec::new(),
170 },
171 )])
172 .collect(),
173 messages: IntoIterator::into_iter([(
174 Id::new(4),
175 Message {
176 activity: None,
177 application: None,
178 application_id: None,
179 attachments: Vec::new(),
180 author: User {
181 accent_color: None,
182 avatar: Some(image_hash::AVATAR),
183 avatar_decoration: None,
184 avatar_decoration_data: None,
185 banner: None,
186 bot: false,
187 discriminator: 1,
188 email: None,
189 flags: None,
190 global_name: Some("test".to_owned()),
191 id: Id::new(3),
192 locale: None,
193 mfa_enabled: None,
194 name: "test".to_owned(),
195 premium_type: None,
196 public_flags: None,
197 system: None,
198 verified: None,
199 },
200 call: None,
201 channel_id: Id::new(2),
202 components: Vec::new(),
203 content: "ping".to_owned(),
204 edited_timestamp: None,
205 embeds: Vec::new(),
206 flags: Some(MessageFlags::empty()),
207 guild_id: Some(Id::new(1)),
208 id: Id::new(4),
209 interaction: None,
210 interaction_metadata: None,
211 kind: MessageType::Regular,
212 member: Some(PartialMember {
213 avatar: None,
214 communication_disabled_until: None,
215 flags,
216 deaf: false,
217 joined_at,
218 mute: false,
219 nick: Some("member nick".to_owned()),
220 permissions: None,
221 premium_since: None,
222 roles: Vec::new(),
223 user: None,
224 }),
225 mention_channels: Vec::new(),
226 mention_everyone: false,
227 mention_roles: Vec::new(),
228 mentions: Vec::new(),
229 message_snapshots: Vec::new(),
230 pinned: false,
231 poll: None,
232 reactions: Vec::new(),
233 reference: None,
234 referenced_message: None,
235 role_subscription_data: None,
236 sticker_items: vec![MessageSticker {
237 format_type: StickerFormatType::Png,
238 id: Id::new(1),
239 name: "sticker name".to_owned(),
240 }],
241 timestamp,
242 thread: None,
243 tts: false,
244 webhook_id: None,
245 },
246 )])
247 .collect(),
248 roles: IntoIterator::into_iter([(
249 Id::new(400),
250 Role {
251 color: 0,
252 hoist: true,
253 icon: None,
254 id: Id::new(400),
255 managed: false,
256 mentionable: true,
257 name: "test".to_owned(),
258 permissions: Permissions::ADMINISTRATOR,
259 position: 12,
260 flags: RoleFlags::empty(),
261 tags: None,
262 unicode_emoji: None,
263 },
264 )])
265 .collect(),
266 users: IntoIterator::into_iter([(
267 Id::new(300),
268 User {
269 accent_color: None,
270 avatar: Some(image_hash::AVATAR),
271 avatar_decoration: None,
272 avatar_decoration_data: None,
273 banner: None,
274 bot: false,
275 discriminator: 1,
276 email: Some("address@example.com".to_owned()),
277 flags: Some(UserFlags::PREMIUM_EARLY_SUPPORTER | UserFlags::VERIFIED_DEVELOPER),
278 global_name: Some("test".to_owned()),
279 id: Id::new(300),
280 locale: Some("en-us".to_owned()),
281 mfa_enabled: Some(true),
282 name: "test".to_owned(),
283 premium_type: Some(PremiumType::Nitro),
284 public_flags: Some(
285 UserFlags::PREMIUM_EARLY_SUPPORTER | UserFlags::VERIFIED_DEVELOPER,
286 ),
287 system: None,
288 verified: Some(true),
289 },
290 )])
291 .collect(),
292 };
293
294 serde_test::assert_tokens(
295 &value,
296 &[
297 Token::Struct {
298 name: "InteractionDataResolved",
299 len: 6,
300 },
301 Token::Str("attachments"),
302 Token::Map { len: Some(1) },
303 Token::NewtypeStruct { name: "Id" },
304 Token::Str("400"),
305 Token::Struct {
306 name: "Attachment",
307 len: 9,
308 },
309 Token::Str("content_type"),
310 Token::Some,
311 Token::Str("image/png"),
312 Token::Str("ephemeral"),
313 Token::Bool(true),
314 Token::Str("filename"),
315 Token::Str("rainbow_dash.png"),
316 Token::Str("height"),
317 Token::Some,
318 Token::U64(2674),
319 Token::Str("id"),
320 Token::NewtypeStruct { name: "Id" },
321 Token::Str("400"),
322 Token::Str("proxy_url"),
323 Token::Str("https://proxy.example.com/rainbow_dash.png"),
324 Token::Str("size"),
325 Token::U64(13370),
326 Token::Str("url"),
327 Token::Str("https://example.com/rainbow_dash.png"),
328 Token::Str("width"),
329 Token::Some,
330 Token::U64(1337),
331 Token::StructEnd,
332 Token::MapEnd,
333 Token::Str("channels"),
334 Token::Map { len: Some(1) },
335 Token::NewtypeStruct { name: "Id" },
336 Token::Str("100"),
337 Token::Struct {
338 name: "InteractionChannel",
339 len: 4,
340 },
341 Token::Str("id"),
342 Token::NewtypeStruct { name: "Id" },
343 Token::Str("100"),
344 Token::Str("type"),
345 Token::U8(0),
346 Token::Str("name"),
347 Token::Str("channel name"),
348 Token::Str("permissions"),
349 Token::Str("0"),
350 Token::StructEnd,
351 Token::MapEnd,
352 Token::Str("members"),
353 Token::Map { len: Some(1) },
354 Token::NewtypeStruct { name: "Id" },
355 Token::Str("300"),
356 Token::Struct {
357 name: "InteractionMember",
358 len: 7,
359 },
360 Token::Str("communication_disabled_until"),
361 Token::None,
362 Token::Str("flags"),
363 Token::U64(flags.bits()),
364 Token::Str("joined_at"),
365 Token::Some,
366 Token::Str("2021-08-10T12:18:37.000000+00:00"),
367 Token::Str("nick"),
368 Token::None,
369 Token::Str("pending"),
370 Token::Bool(false),
371 Token::Str("permissions"),
372 Token::Str("0"),
373 Token::Str("roles"),
374 Token::Seq { len: Some(0) },
375 Token::SeqEnd,
376 Token::StructEnd,
377 Token::MapEnd,
378 Token::Str("messages"),
379 Token::Map { len: Some(1) },
380 Token::NewtypeStruct { name: "Id" },
381 Token::Str("4"),
382 Token::Struct {
383 name: "Message",
384 len: 19,
385 },
386 Token::Str("attachments"),
387 Token::Seq { len: Some(0) },
388 Token::SeqEnd,
389 Token::Str("author"),
390 Token::Struct {
391 name: "User",
392 len: 10,
393 },
394 Token::Str("accent_color"),
395 Token::None,
396 Token::Str("avatar"),
397 Token::Some,
398 Token::Str(image_hash::AVATAR_INPUT),
399 Token::Str("avatar_decoration"),
400 Token::None,
401 Token::Str("avatar_decoration_data"),
402 Token::None,
403 Token::Str("banner"),
404 Token::None,
405 Token::Str("bot"),
406 Token::Bool(false),
407 Token::Str("discriminator"),
408 Token::Str("0001"),
409 Token::Str("global_name"),
410 Token::Some,
411 Token::Str("test"),
412 Token::Str("id"),
413 Token::NewtypeStruct { name: "Id" },
414 Token::Str("3"),
415 Token::Str("username"),
416 Token::Str("test"),
417 Token::StructEnd,
418 Token::Str("call"),
419 Token::None,
420 Token::Str("channel_id"),
421 Token::NewtypeStruct { name: "Id" },
422 Token::Str("2"),
423 Token::Str("content"),
424 Token::Str("ping"),
425 Token::Str("edited_timestamp"),
426 Token::None,
427 Token::Str("embeds"),
428 Token::Seq { len: Some(0) },
429 Token::SeqEnd,
430 Token::Str("flags"),
431 Token::Some,
432 Token::U64(0),
433 Token::Str("guild_id"),
434 Token::Some,
435 Token::NewtypeStruct { name: "Id" },
436 Token::Str("1"),
437 Token::Str("id"),
438 Token::NewtypeStruct { name: "Id" },
439 Token::Str("4"),
440 Token::Str("type"),
441 Token::U8(0),
442 Token::Str("member"),
443 Token::Some,
444 Token::Struct {
445 name: "PartialMember",
446 len: 8,
447 },
448 Token::Str("communication_disabled_until"),
449 Token::None,
450 Token::Str("deaf"),
451 Token::Bool(false),
452 Token::Str("flags"),
453 Token::U64(flags.bits()),
454 Token::Str("joined_at"),
455 Token::Some,
456 Token::Str("2021-08-10T12:18:37.000000+00:00"),
457 Token::Str("mute"),
458 Token::Bool(false),
459 Token::Str("nick"),
460 Token::Some,
461 Token::Str("member nick"),
462 Token::Str("roles"),
463 Token::Seq { len: Some(0) },
464 Token::SeqEnd,
465 Token::Str("user"),
466 Token::None,
467 Token::StructEnd,
468 Token::Str("mention_everyone"),
469 Token::Bool(false),
470 Token::Str("mention_roles"),
471 Token::Seq { len: Some(0) },
472 Token::SeqEnd,
473 Token::Str("mentions"),
474 Token::Seq { len: Some(0) },
475 Token::SeqEnd,
476 Token::Str("pinned"),
477 Token::Bool(false),
478 Token::Str("sticker_items"),
479 Token::Seq { len: Some(1) },
480 Token::Struct {
481 name: "MessageSticker",
482 len: 3,
483 },
484 Token::Str("format_type"),
485 Token::U8(1),
486 Token::Str("id"),
487 Token::NewtypeStruct { name: "Id" },
488 Token::Str("1"),
489 Token::Str("name"),
490 Token::Str("sticker name"),
491 Token::StructEnd,
492 Token::SeqEnd,
493 Token::Str("timestamp"),
494 Token::Str("2020-02-02T02:02:02.020000+00:00"),
495 Token::Str("tts"),
496 Token::Bool(false),
497 Token::StructEnd,
498 Token::MapEnd,
499 Token::Str("roles"),
500 Token::Map { len: Some(1) },
501 Token::NewtypeStruct { name: "Id" },
502 Token::Str("400"),
503 Token::Struct {
504 name: "Role",
505 len: 9,
506 },
507 Token::Str("color"),
508 Token::U32(0),
509 Token::Str("hoist"),
510 Token::Bool(true),
511 Token::Str("id"),
512 Token::NewtypeStruct { name: "Id" },
513 Token::Str("400"),
514 Token::Str("managed"),
515 Token::Bool(false),
516 Token::Str("mentionable"),
517 Token::Bool(true),
518 Token::Str("name"),
519 Token::Str("test"),
520 Token::Str("permissions"),
521 Token::Str("8"),
522 Token::Str("position"),
523 Token::I64(12),
524 Token::Str("flags"),
525 Token::U64(0),
526 Token::StructEnd,
527 Token::MapEnd,
528 Token::Str("users"),
529 Token::Map { len: Some(1) },
530 Token::NewtypeStruct { name: "Id" },
531 Token::Str("300"),
532 Token::Struct {
533 name: "User",
534 len: 17,
535 },
536 Token::Str("accent_color"),
537 Token::None,
538 Token::Str("avatar"),
539 Token::Some,
540 Token::Str(image_hash::AVATAR_INPUT),
541 Token::Str("avatar_decoration"),
542 Token::None,
543 Token::Str("avatar_decoration_data"),
544 Token::None,
545 Token::Str("banner"),
546 Token::None,
547 Token::Str("bot"),
548 Token::Bool(false),
549 Token::Str("discriminator"),
550 Token::Str("0001"),
551 Token::Str("email"),
552 Token::Some,
553 Token::Str("address@example.com"),
554 Token::Str("flags"),
555 Token::Some,
556 Token::U64(131_584),
557 Token::Str("global_name"),
558 Token::Some,
559 Token::Str("test"),
560 Token::Str("id"),
561 Token::NewtypeStruct { name: "Id" },
562 Token::Str("300"),
563 Token::Str("locale"),
564 Token::Some,
565 Token::Str("en-us"),
566 Token::Str("mfa_enabled"),
567 Token::Some,
568 Token::Bool(true),
569 Token::Str("username"),
570 Token::Str("test"),
571 Token::Str("premium_type"),
572 Token::Some,
573 Token::U8(2),
574 Token::Str("public_flags"),
575 Token::Some,
576 Token::U64(131_584),
577 Token::Str("verified"),
578 Token::Some,
579 Token::Bool(true),
580 Token::StructEnd,
581 Token::MapEnd,
582 Token::StructEnd,
583 ],
584 );
585
586 Ok(())
587 }
588}