twilight_model/application/interaction/
mod.rs

1//! Used when receiving interactions through gateway or webhooks.
2//!
3//! See [Discord Docs/Receiving and Responding].
4//!
5//! [Discord Docs/Receiving and Responding]: https://discord.com/developers/docs/interactions/receiving-and-responding
6
7pub mod application_command;
8pub mod message_component;
9pub mod modal;
10
11mod context_type;
12mod interaction_type;
13mod metadata;
14mod resolved;
15
16pub use self::{
17    context_type::InteractionContextType,
18    interaction_type::InteractionType,
19    metadata::InteractionMetadata,
20    resolved::{InteractionChannel, InteractionDataResolved, InteractionMember},
21};
22
23use self::{
24    application_command::CommandData, message_component::MessageComponentInteractionData,
25    modal::ModalInteractionData,
26};
27use crate::{
28    channel::{Channel, Message},
29    guild::{GuildFeature, PartialMember, Permissions},
30    id::{
31        AnonymizableId, Id,
32        marker::{ApplicationMarker, ChannelMarker, GuildMarker, InteractionMarker, UserMarker},
33    },
34    oauth::ApplicationIntegrationMap,
35    user::User,
36};
37use serde::{
38    Deserialize, Deserializer, Serialize,
39    de::{Error as DeError, IgnoredAny, MapAccess, Visitor},
40};
41use serde_value::{DeserializerError, Value};
42use std::fmt::{Formatter, Result as FmtResult};
43
44use super::monetization::Entitlement;
45
46/// Payload received when a user executes an interaction.
47///
48/// See [Discord Docs/Interaction Object].
49///
50/// [Discord Docs/Interaction Object]: https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-structure
51#[derive(Clone, Debug, PartialEq, Serialize)]
52pub struct Interaction {
53    /// App's permissions in the channel the interaction was sent from.
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub app_permissions: Option<Permissions>,
56    /// ID of the associated application.
57    pub application_id: Id<ApplicationMarker>,
58    /// Mapping of installation contexts that the interaction was
59    /// authorized for to related user or guild IDs.
60    pub authorizing_integration_owners:
61        ApplicationIntegrationMap<AnonymizableId<GuildMarker>, Id<UserMarker>>,
62    /// The channel the interaction was invoked in.
63    ///
64    /// Present on all interactions types, except [`Ping`].
65    ///
66    /// [`Ping`]: InteractionType::Ping
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub channel: Option<Channel>,
69    /// ID of the channel the interaction was invoked in.
70    ///
71    /// Present on all interactions types, except [`Ping`].
72    ///
73    /// [`Ping`]: InteractionType::Ping
74    #[serde(skip_serializing_if = "Option::is_none")]
75    #[deprecated(
76        note = "channel_id is deprecated in the discord API and will no be sent in the future, users should use the channel field instead."
77    )]
78    pub channel_id: Option<Id<ChannelMarker>>,
79    /// Context where the interaction was triggered from.
80    #[serde(skip_serializing_if = "Option::is_none")]
81    pub context: Option<InteractionContextType>,
82    /// Data from the interaction.
83    ///
84    /// This field present on [`ApplicationCommand`], [`MessageComponent`],
85    /// [`ApplicationCommandAutocomplete`] and [`ModalSubmit`] interactions.
86    /// The inner enum variant matches the interaction type.
87    ///
88    /// [`ApplicationCommand`]: InteractionType::ApplicationCommand
89    /// [`MessageComponent`]: InteractionType::MessageComponent
90    /// [`ApplicationCommandAutocomplete`]: InteractionType::ApplicationCommandAutocomplete
91    /// [`ModalSubmit`]: InteractionType::ModalSubmit
92    #[serde(skip_serializing_if = "Option::is_none")]
93    pub data: Option<InteractionData>,
94    /// For monetized apps, any entitlements for the invoking user, representing access to premium SKUs
95    pub entitlements: Vec<Entitlement>,
96    /// Guild that the interaction was sent from.
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub guild: Option<InteractionPartialGuild>,
99    /// ID of the guild the interaction was invoked in.
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub guild_id: Option<Id<GuildMarker>>,
102    /// Guild’s preferred locale.
103    ///
104    /// Present when the interaction is invoked in a guild.
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub guild_locale: Option<String>,
107    /// ID of the interaction.
108    pub id: Id<InteractionMarker>,
109    /// Type of interaction.
110    #[serde(rename = "type")]
111    pub kind: InteractionType,
112    /// Selected language of the user who invoked the interaction.
113    ///
114    /// Present on all interactions types, except [`Ping`].
115    ///
116    /// [`Ping`]: InteractionType::Ping
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub locale: Option<String>,
119    /// Member that invoked the interaction.
120    ///
121    /// Present when the interaction is invoked in a guild.
122    #[serde(skip_serializing_if = "Option::is_none")]
123    pub member: Option<PartialMember>,
124    /// Message attached to the interaction.
125    ///
126    /// Present on [`MessageComponent`] interactions.
127    ///
128    /// [`MessageComponent`]: InteractionType::MessageComponent
129    #[serde(skip_serializing_if = "Option::is_none")]
130    pub message: Option<Message>,
131    /// Token for responding to the interaction.
132    pub token: String,
133    /// User that invoked the interaction.
134    ///
135    /// Present when the interaction is invoked in a direct message.
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub user: Option<User>,
138}
139
140impl Interaction {
141    /// ID of the user that invoked the interaction.
142    ///
143    /// This will first check for the [`member`]'s
144    /// [`user`][`PartialMember::user`]'s ID and then, if not present, check the
145    /// [`user`]'s ID.
146    ///
147    /// [`member`]: Self::member
148    /// [`user`]: Self::user
149    pub const fn author_id(&self) -> Option<Id<UserMarker>> {
150        if let Some(user) = self.author() {
151            Some(user.id)
152        } else {
153            None
154        }
155    }
156
157    /// The user that invoked the interaction.
158    ///
159    /// This will first check for the [`member`]'s
160    /// [`user`][`PartialMember::user`] and then, if not present, check the
161    /// [`user`].
162    ///
163    /// [`member`]: Self::member
164    /// [`user`]: Self::user
165    pub const fn author(&self) -> Option<&User> {
166        match self.member.as_ref() {
167            Some(member) if member.user.is_some() => member.user.as_ref(),
168            _ => self.user.as_ref(),
169        }
170    }
171
172    /// Whether the interaction was invoked in a DM.
173    pub const fn is_dm(&self) -> bool {
174        self.user.is_some()
175    }
176
177    /// Whether the interaction was invoked in a guild.
178    pub const fn is_guild(&self) -> bool {
179        self.member.is_some()
180    }
181}
182
183impl<'de> Deserialize<'de> for Interaction {
184    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
185        deserializer.deserialize_map(InteractionVisitor)
186    }
187}
188
189#[derive(Debug, Deserialize)]
190#[serde(field_identifier, rename_all = "snake_case")]
191enum InteractionField {
192    AppPermissions,
193    ApplicationId,
194    Context,
195    Channel,
196    ChannelId,
197    Data,
198    Entitlements,
199    Guild,
200    GuildId,
201    GuildLocale,
202    Id,
203    Locale,
204    Member,
205    Message,
206    Token,
207    Type,
208    User,
209    Version,
210    AuthorizingIntegrationOwners,
211}
212
213struct InteractionVisitor;
214
215impl<'de> Visitor<'de> for InteractionVisitor {
216    type Value = Interaction;
217
218    fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
219        f.write_str("enum Interaction")
220    }
221
222    #[allow(clippy::too_many_lines, deprecated)]
223    fn visit_map<V: MapAccess<'de>>(self, mut map: V) -> Result<Self::Value, V::Error> {
224        let mut app_permissions: Option<Permissions> = None;
225        let mut application_id: Option<Id<ApplicationMarker>> = None;
226        let mut channel: Option<Channel> = None;
227        let mut channel_id: Option<Id<ChannelMarker>> = None;
228        let mut context: Option<InteractionContextType> = None;
229        let mut data: Option<Value> = None;
230        let mut entitlements: Option<Vec<Entitlement>> = None;
231        let mut guild: Option<InteractionPartialGuild> = None;
232        let mut guild_id: Option<Id<GuildMarker>> = None;
233        let mut guild_locale: Option<String> = None;
234        let mut id: Option<Id<InteractionMarker>> = None;
235        let mut kind: Option<InteractionType> = None;
236        let mut locale: Option<String> = None;
237        let mut member: Option<PartialMember> = None;
238        let mut message: Option<Message> = None;
239        let mut token: Option<String> = None;
240        let mut user: Option<User> = None;
241        let mut authorizing_integration_owners: Option<
242            ApplicationIntegrationMap<AnonymizableId<GuildMarker>, Id<UserMarker>>,
243        > = None;
244
245        loop {
246            let key = match map.next_key() {
247                Ok(Some(key)) => key,
248                Ok(None) => break,
249                Err(_) => {
250                    map.next_value::<IgnoredAny>()?;
251
252                    continue;
253                }
254            };
255
256            match key {
257                InteractionField::AppPermissions => {
258                    if app_permissions.is_some() {
259                        return Err(DeError::duplicate_field("app_permissions"));
260                    }
261
262                    app_permissions = map.next_value()?;
263                }
264                InteractionField::ApplicationId => {
265                    if application_id.is_some() {
266                        return Err(DeError::duplicate_field("application_id"));
267                    }
268
269                    application_id = Some(map.next_value()?);
270                }
271                InteractionField::Context => {
272                    if context.is_some() {
273                        return Err(DeError::duplicate_field("context"));
274                    }
275
276                    context = map.next_value()?;
277                }
278                InteractionField::Channel => {
279                    if channel.is_some() {
280                        return Err(DeError::duplicate_field("channel"));
281                    }
282
283                    channel = map.next_value()?;
284                }
285                InteractionField::ChannelId => {
286                    if channel_id.is_some() {
287                        return Err(DeError::duplicate_field("channel_id"));
288                    }
289
290                    channel_id = map.next_value()?;
291                }
292                InteractionField::Data => {
293                    if data.is_some() {
294                        return Err(DeError::duplicate_field("data"));
295                    }
296
297                    data = map.next_value()?;
298                }
299                InteractionField::Entitlements => {
300                    if entitlements.is_some() {
301                        return Err(DeError::duplicate_field("entitlements"));
302                    }
303
304                    entitlements = map.next_value()?;
305                }
306                InteractionField::Guild => {
307                    if guild.is_some() {
308                        return Err(DeError::duplicate_field("guild"));
309                    }
310
311                    guild = map.next_value()?;
312                }
313                InteractionField::GuildId => {
314                    if guild_id.is_some() {
315                        return Err(DeError::duplicate_field("guild_id"));
316                    }
317
318                    guild_id = map.next_value()?;
319                }
320                InteractionField::GuildLocale => {
321                    if guild_locale.is_some() {
322                        return Err(DeError::duplicate_field("guild_locale"));
323                    }
324
325                    guild_locale = map.next_value()?;
326                }
327                InteractionField::Id => {
328                    if id.is_some() {
329                        return Err(DeError::duplicate_field("id"));
330                    }
331
332                    id = Some(map.next_value()?);
333                }
334                InteractionField::Locale => {
335                    if locale.is_some() {
336                        return Err(DeError::duplicate_field("locale"));
337                    }
338
339                    locale = map.next_value()?;
340                }
341                InteractionField::Member => {
342                    if member.is_some() {
343                        return Err(DeError::duplicate_field("member"));
344                    }
345
346                    member = map.next_value()?;
347                }
348                InteractionField::Message => {
349                    if message.is_some() {
350                        return Err(DeError::duplicate_field("message"));
351                    }
352
353                    message = map.next_value()?;
354                }
355                InteractionField::Token => {
356                    if token.is_some() {
357                        return Err(DeError::duplicate_field("token"));
358                    }
359
360                    token = Some(map.next_value()?);
361                }
362                InteractionField::Type => {
363                    if kind.is_some() {
364                        return Err(DeError::duplicate_field("kind"));
365                    }
366
367                    kind = Some(map.next_value()?);
368                }
369                InteractionField::User => {
370                    if user.is_some() {
371                        return Err(DeError::duplicate_field("user"));
372                    }
373
374                    user = map.next_value()?;
375                }
376                InteractionField::Version => {
377                    // Ignoring the version field.
378                    map.next_value::<IgnoredAny>()?;
379                }
380                InteractionField::AuthorizingIntegrationOwners => {
381                    if authorizing_integration_owners.is_some() {
382                        return Err(DeError::duplicate_field("authorizing_integration_owners"));
383                    }
384
385                    authorizing_integration_owners = map.next_value()?;
386                }
387            }
388        }
389
390        let application_id =
391            application_id.ok_or_else(|| DeError::missing_field("application_id"))?;
392        let authorizing_integration_owners = authorizing_integration_owners
393            .ok_or_else(|| DeError::missing_field("authorizing_integration_owners"))?;
394        let id = id.ok_or_else(|| DeError::missing_field("id"))?;
395        let token = token.ok_or_else(|| DeError::missing_field("token"))?;
396        let kind = kind.ok_or_else(|| DeError::missing_field("kind"))?;
397
398        let data = match kind {
399            InteractionType::Ping => None,
400            InteractionType::ApplicationCommand => {
401                let data = data
402                    .ok_or_else(|| DeError::missing_field("data"))?
403                    .deserialize_into()
404                    .map_err(DeserializerError::into_error)?;
405
406                Some(InteractionData::ApplicationCommand(data))
407            }
408            InteractionType::MessageComponent => {
409                let data = data
410                    .ok_or_else(|| DeError::missing_field("data"))?
411                    .deserialize_into()
412                    .map_err(DeserializerError::into_error)?;
413
414                Some(InteractionData::MessageComponent(data))
415            }
416            InteractionType::ApplicationCommandAutocomplete => {
417                let data = data
418                    .ok_or_else(|| DeError::missing_field("data"))?
419                    .deserialize_into()
420                    .map_err(DeserializerError::into_error)?;
421
422                Some(InteractionData::ApplicationCommand(data))
423            }
424            InteractionType::ModalSubmit => {
425                let data = data
426                    .ok_or_else(|| DeError::missing_field("data"))?
427                    .deserialize_into()
428                    .map_err(DeserializerError::into_error)?;
429
430                Some(InteractionData::ModalSubmit(data))
431            }
432        };
433
434        let entitlements = entitlements.unwrap_or_default();
435
436        Ok(Self::Value {
437            app_permissions,
438            application_id,
439            authorizing_integration_owners,
440            channel,
441            channel_id,
442            context,
443            data,
444            entitlements,
445            guild,
446            guild_id,
447            guild_locale,
448            id,
449            kind,
450            locale,
451            member,
452            message,
453            token,
454            user,
455        })
456    }
457}
458
459/// Additional [`Interaction`] data, such as the invoking user.
460#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
461#[non_exhaustive]
462#[serde(untagged)]
463pub enum InteractionData {
464    /// Data received for the [`ApplicationCommand`] and [`ApplicationCommandAutocomplete`]
465    /// interaction types.
466    ///
467    /// [`ApplicationCommand`]: InteractionType::ApplicationCommand
468    /// [`ApplicationCommandAutocomplete`]: InteractionType::ApplicationCommandAutocomplete
469    ApplicationCommand(Box<CommandData>),
470    /// Data received for the [`MessageComponent`] interaction type.
471    ///
472    /// [`MessageComponent`]: InteractionType::MessageComponent
473    MessageComponent(Box<MessageComponentInteractionData>),
474    /// Data received for the [`ModalSubmit`] interaction type.
475    ///
476    /// [`ModalSubmit`]: InteractionType::ModalSubmit
477    ModalSubmit(Box<ModalInteractionData>),
478}
479
480/// Partial guild containing only the fields sent in the partial guild
481/// in interactions.
482///
483/// # Note that the field `locale` does not exists on the full guild
484/// object, and is only found here. See
485/// <https://github.com/discord/discord-api-docs/issues/6938> for more
486/// info.
487#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize, Hash)]
488pub struct InteractionPartialGuild {
489    /// Id of the guild.
490    pub id: Option<Id<GuildMarker>>,
491    /// Enabled guild features
492    pub features: Option<Vec<GuildFeature>>,
493    pub locale: Option<String>,
494}
495
496#[cfg(test)]
497mod tests {
498    use super::{
499        Interaction, InteractionData, InteractionDataResolved, InteractionMember, InteractionType,
500        application_command::{CommandData, CommandDataOption, CommandOptionValue},
501    };
502    use crate::{
503        application::{
504            command::{CommandOptionType, CommandType},
505            monetization::{EntitlementType, entitlement::Entitlement},
506        },
507        channel::Channel,
508        guild::{MemberFlags, PartialMember, Permissions},
509        id::Id,
510        oauth::ApplicationIntegrationMap,
511        test::image_hash,
512        user::User,
513        util::datetime::{Timestamp, TimestampParseError},
514    };
515    use serde_test::Token;
516    use std::{collections::HashMap, str::FromStr};
517
518    #[test]
519    #[allow(clippy::too_many_lines, deprecated)]
520    fn test_interaction_full() -> Result<(), TimestampParseError> {
521        let joined_at = Some(Timestamp::from_str("2020-01-01T00:00:00.000000+00:00")?);
522        let flags = MemberFlags::BYPASSES_VERIFICATION | MemberFlags::DID_REJOIN;
523
524        let value = Interaction {
525            app_permissions: Some(Permissions::SEND_MESSAGES),
526            application_id: Id::new(100),
527            authorizing_integration_owners: ApplicationIntegrationMap {
528                guild: None,
529                user: None,
530            },
531            channel: Some(Channel {
532                bitrate: None,
533                guild_id: None,
534                id: Id::new(400),
535                kind: crate::channel::ChannelType::GuildText,
536                last_message_id: None,
537                last_pin_timestamp: None,
538                name: None,
539                nsfw: None,
540                owner_id: None,
541                parent_id: None,
542                permission_overwrites: None,
543                position: None,
544                rate_limit_per_user: None,
545                recipients: None,
546                rtc_region: None,
547                topic: None,
548                user_limit: None,
549                application_id: None,
550                applied_tags: None,
551                available_tags: None,
552                default_auto_archive_duration: None,
553                default_forum_layout: None,
554                default_reaction_emoji: None,
555                default_sort_order: None,
556                default_thread_rate_limit_per_user: None,
557                flags: None,
558                icon: None,
559                invitable: None,
560                managed: None,
561                member: None,
562                member_count: None,
563                message_count: None,
564                newly_created: None,
565                thread_metadata: None,
566                video_quality_mode: None,
567            }),
568            channel_id: Some(Id::new(200)),
569            context: None,
570            data: Some(InteractionData::ApplicationCommand(Box::new(CommandData {
571                guild_id: None,
572                id: Id::new(300),
573                name: "command name".into(),
574                kind: CommandType::ChatInput,
575                options: Vec::from([CommandDataOption {
576                    name: "member".into(),
577                    value: CommandOptionValue::User(Id::new(600)),
578                }]),
579                resolved: Some(InteractionDataResolved {
580                    attachments: HashMap::new(),
581                    channels: HashMap::new(),
582                    members: IntoIterator::into_iter([(
583                        Id::new(600),
584                        InteractionMember {
585                            avatar: None,
586                            avatar_decoration_data: None,
587                            banner: None,
588                            communication_disabled_until: None,
589                            flags,
590                            joined_at,
591                            nick: Some("nickname".into()),
592                            pending: false,
593                            permissions: Permissions::empty(),
594                            premium_since: None,
595                            roles: Vec::new(),
596                        },
597                    )])
598                    .collect(),
599                    messages: HashMap::new(),
600                    roles: HashMap::new(),
601                    users: IntoIterator::into_iter([(
602                        Id::new(600),
603                        User {
604                            accent_color: None,
605                            avatar: Some(image_hash::AVATAR),
606                            avatar_decoration: None,
607                            avatar_decoration_data: None,
608                            banner: None,
609                            bot: false,
610                            discriminator: 1111,
611                            email: None,
612                            flags: None,
613                            global_name: Some("test".into()),
614                            id: Id::new(600),
615                            locale: None,
616                            mfa_enabled: None,
617                            name: "username".into(),
618                            premium_type: None,
619                            primary_guild: None,
620                            public_flags: None,
621                            system: None,
622                            verified: None,
623                        },
624                    )])
625                    .collect(),
626                }),
627                target_id: None,
628            }))),
629            entitlements: vec![Entitlement {
630                application_id: Id::new(100),
631                consumed: Some(false),
632                deleted: false,
633                ends_at: None,
634                guild_id: None,
635                id: Id::new(200),
636                kind: EntitlementType::ApplicationSubscription,
637                sku_id: Id::new(300),
638                starts_at: None,
639                user_id: None,
640            }],
641            guild: None,
642            guild_id: Some(Id::new(400)),
643            guild_locale: Some("de".to_owned()),
644            id: Id::new(500),
645            kind: InteractionType::ApplicationCommand,
646            locale: Some("en-GB".to_owned()),
647            member: Some(PartialMember {
648                avatar: None,
649                avatar_decoration_data: None,
650                banner: None,
651                communication_disabled_until: None,
652                deaf: false,
653                flags,
654                joined_at,
655                mute: false,
656                nick: Some("nickname".into()),
657                permissions: Some(Permissions::empty()),
658                premium_since: None,
659                roles: Vec::new(),
660                user: Some(User {
661                    accent_color: None,
662                    avatar: Some(image_hash::AVATAR),
663                    avatar_decoration: None,
664                    avatar_decoration_data: None,
665                    banner: None,
666                    bot: false,
667                    discriminator: 1111,
668                    email: None,
669                    flags: None,
670                    global_name: Some("test".into()),
671                    id: Id::new(600),
672                    locale: None,
673                    mfa_enabled: None,
674                    name: "username".into(),
675                    premium_type: None,
676                    primary_guild: None,
677                    public_flags: None,
678                    system: None,
679                    verified: None,
680                }),
681            }),
682            message: None,
683            token: "interaction token".into(),
684            user: None,
685        };
686
687        // TODO: switch the `assert_tokens` see #2190
688        serde_test::assert_ser_tokens(
689            &value,
690            &[
691                Token::Struct {
692                    name: "Interaction",
693                    len: 14,
694                },
695                Token::Str("app_permissions"),
696                Token::Some,
697                Token::Str("2048"),
698                Token::Str("application_id"),
699                Token::NewtypeStruct { name: "Id" },
700                Token::Str("100"),
701                Token::Str("authorizing_integration_owners"),
702                Token::Struct {
703                    name: "ApplicationIntegrationMap",
704                    len: 0,
705                },
706                Token::StructEnd,
707                Token::Str("channel"),
708                Token::Some,
709                Token::Struct {
710                    name: "Channel",
711                    len: 2,
712                },
713                Token::Str("id"),
714                Token::NewtypeStruct { name: "Id" },
715                Token::Str("400"),
716                Token::Str("type"),
717                Token::U8(0),
718                Token::StructEnd,
719                Token::Str("channel_id"),
720                Token::Some,
721                Token::NewtypeStruct { name: "Id" },
722                Token::Str("200"),
723                Token::Str("data"),
724                Token::Some,
725                Token::Struct {
726                    name: "CommandData",
727                    len: 5,
728                },
729                Token::Str("id"),
730                Token::NewtypeStruct { name: "Id" },
731                Token::Str("300"),
732                Token::Str("name"),
733                Token::Str("command name"),
734                Token::Str("type"),
735                Token::U8(1),
736                Token::Str("options"),
737                Token::Seq { len: Some(1) },
738                Token::Struct {
739                    name: "CommandDataOption",
740                    len: 3,
741                },
742                Token::Str("name"),
743                Token::Str("member"),
744                Token::Str("type"),
745                Token::U8(CommandOptionType::User as u8),
746                Token::Str("value"),
747                Token::NewtypeStruct { name: "Id" },
748                Token::Str("600"),
749                Token::StructEnd,
750                Token::SeqEnd,
751                Token::Str("resolved"),
752                Token::Some,
753                Token::Struct {
754                    name: "InteractionDataResolved",
755                    len: 2,
756                },
757                Token::Str("members"),
758                Token::Map { len: Some(1) },
759                Token::NewtypeStruct { name: "Id" },
760                Token::Str("600"),
761                Token::Struct {
762                    name: "InteractionMember",
763                    len: 7,
764                },
765                Token::Str("communication_disabled_until"),
766                Token::None,
767                Token::Str("flags"),
768                Token::U64(flags.bits()),
769                Token::Str("joined_at"),
770                Token::Some,
771                Token::Str("2020-01-01T00:00:00.000000+00:00"),
772                Token::Str("nick"),
773                Token::Some,
774                Token::Str("nickname"),
775                Token::Str("pending"),
776                Token::Bool(false),
777                Token::Str("permissions"),
778                Token::Str("0"),
779                Token::Str("roles"),
780                Token::Seq { len: Some(0) },
781                Token::SeqEnd,
782                Token::StructEnd,
783                Token::MapEnd,
784                Token::Str("users"),
785                Token::Map { len: Some(1) },
786                Token::NewtypeStruct { name: "Id" },
787                Token::Str("600"),
788                Token::Struct {
789                    name: "User",
790                    len: 10,
791                },
792                Token::Str("accent_color"),
793                Token::None,
794                Token::Str("avatar"),
795                Token::Some,
796                Token::Str(image_hash::AVATAR_INPUT),
797                Token::Str("avatar_decoration"),
798                Token::None,
799                Token::Str("avatar_decoration_data"),
800                Token::None,
801                Token::Str("banner"),
802                Token::None,
803                Token::Str("bot"),
804                Token::Bool(false),
805                Token::Str("discriminator"),
806                Token::Str("1111"),
807                Token::Str("global_name"),
808                Token::Some,
809                Token::Str("test"),
810                Token::Str("id"),
811                Token::NewtypeStruct { name: "Id" },
812                Token::Str("600"),
813                Token::Str("username"),
814                Token::Str("username"),
815                Token::StructEnd,
816                Token::MapEnd,
817                Token::StructEnd,
818                Token::StructEnd,
819                Token::Str("entitlements"),
820                Token::Seq { len: Some(1) },
821                Token::Struct {
822                    name: "Entitlement",
823                    len: 6,
824                },
825                Token::Str("application_id"),
826                Token::NewtypeStruct { name: "Id" },
827                Token::Str("100"),
828                Token::Str("consumed"),
829                Token::Some,
830                Token::Bool(false),
831                Token::Str("deleted"),
832                Token::Bool(false),
833                Token::Str("id"),
834                Token::NewtypeStruct { name: "Id" },
835                Token::Str("200"),
836                Token::Str("type"),
837                Token::U8(8),
838                Token::Str("sku_id"),
839                Token::NewtypeStruct { name: "Id" },
840                Token::Str("300"),
841                Token::StructEnd,
842                Token::SeqEnd,
843                Token::Str("guild_id"),
844                Token::Some,
845                Token::NewtypeStruct { name: "Id" },
846                Token::Str("400"),
847                Token::Str("guild_locale"),
848                Token::Some,
849                Token::String("de"),
850                Token::Str("id"),
851                Token::NewtypeStruct { name: "Id" },
852                Token::Str("500"),
853                Token::Str("type"),
854                Token::U8(InteractionType::ApplicationCommand as u8),
855                Token::Str("locale"),
856                Token::Some,
857                Token::Str("en-GB"),
858                Token::Str("member"),
859                Token::Some,
860                Token::Struct {
861                    name: "PartialMember",
862                    len: 9,
863                },
864                Token::Str("communication_disabled_until"),
865                Token::None,
866                Token::Str("deaf"),
867                Token::Bool(false),
868                Token::Str("flags"),
869                Token::U64(flags.bits()),
870                Token::Str("joined_at"),
871                Token::Some,
872                Token::Str("2020-01-01T00:00:00.000000+00:00"),
873                Token::Str("mute"),
874                Token::Bool(false),
875                Token::Str("nick"),
876                Token::Some,
877                Token::Str("nickname"),
878                Token::Str("permissions"),
879                Token::Some,
880                Token::Str("0"),
881                Token::Str("roles"),
882                Token::Seq { len: Some(0) },
883                Token::SeqEnd,
884                Token::Str("user"),
885                Token::Some,
886                Token::Struct {
887                    name: "User",
888                    len: 10,
889                },
890                Token::Str("accent_color"),
891                Token::None,
892                Token::Str("avatar"),
893                Token::Some,
894                Token::Str(image_hash::AVATAR_INPUT),
895                Token::Str("avatar_decoration"),
896                Token::None,
897                Token::Str("avatar_decoration_data"),
898                Token::None,
899                Token::Str("banner"),
900                Token::None,
901                Token::Str("bot"),
902                Token::Bool(false),
903                Token::Str("discriminator"),
904                Token::Str("1111"),
905                Token::Str("global_name"),
906                Token::Some,
907                Token::Str("test"),
908                Token::Str("id"),
909                Token::NewtypeStruct { name: "Id" },
910                Token::Str("600"),
911                Token::Str("username"),
912                Token::Str("username"),
913                Token::StructEnd,
914                Token::StructEnd,
915                Token::Str("token"),
916                Token::Str("interaction token"),
917                Token::StructEnd,
918            ],
919        );
920
921        Ok(())
922    }
923}