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