twilight_model/channel/message/
mod.rs

1//! Textual user communication method.
2#![warn(missing_docs)]
3
4pub mod component;
5pub mod embed;
6pub mod sticker;
7
8mod activity;
9mod allowed_mentions;
10mod application;
11mod call;
12mod flags;
13mod interaction;
14mod kind;
15mod mention;
16mod reaction;
17mod reaction_type;
18mod reference;
19mod reference_type;
20mod role_subscription_data;
21mod snapshot;
22
23pub use self::{
24    activity::{MessageActivity, MessageActivityType},
25    allowed_mentions::{AllowedMentions, MentionType},
26    application::MessageApplication,
27    call::MessageCall,
28    component::Component,
29    embed::Embed,
30    flags::MessageFlags,
31    interaction::MessageInteraction,
32    kind::MessageType,
33    mention::Mention,
34    reaction::{EmojiReactionType, Reaction, ReactionCountDetails},
35    reaction_type::ReactionType,
36    reference::MessageReference,
37    reference_type::MessageReferenceType,
38    role_subscription_data::RoleSubscriptionData,
39    snapshot::MessageSnapshot,
40    sticker::{MessageSticker, Sticker},
41};
42
43use crate::{
44    application::interaction::InteractionMetadata,
45    channel::{Attachment, Channel, ChannelMention},
46    guild::PartialMember,
47    id::{
48        marker::{
49            ApplicationMarker, ChannelMarker, GuildMarker, MessageMarker, RoleMarker, WebhookMarker,
50        },
51        Id,
52    },
53    poll::Poll,
54    user::User,
55    util::Timestamp,
56};
57use serde::{Deserialize, Serialize};
58
59/// Text message sent in a [`Channel`].
60#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
61pub struct Message {
62    /// Present with Rich Presence-related chat embeds.
63    #[serde(skip_serializing_if = "Option::is_none")]
64    pub activity: Option<MessageActivity>,
65    /// Present with Rich Presence-related chat embeds.
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub application: Option<MessageApplication>,
68    /// Associated application's ID.
69    ///
70    /// Present if the message is a response to an [`Interaction`].
71    ///
72    /// [`Interaction`]: crate::application::interaction::Interaction
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub application_id: Option<Id<ApplicationMarker>>,
75    /// List of attachments.
76    ///
77    /// Receiving the attachments of messages requires that the
78    /// [Message Content Intent] be enabled for the application. In the case of
79    /// receiving messages over the Gateway, the intent must also be enabled for
80    /// the session.
81    ///
82    /// Message attachments will be empty unless the [Message Content Intent] is
83    /// enabled, the message was sent by the current user, or the message is in
84    /// a direct message channel.
85    ///
86    /// [Message Content Intent]: crate::gateway::Intents::MESSAGE_CONTENT
87    pub attachments: Vec<Attachment>,
88    /// Author of the message.
89    pub author: User,
90    /// The call associated with the message.
91    pub call: Option<MessageCall>,
92    /// ID of the [`Channel`] the message was sent in.
93    pub channel_id: Id<ChannelMarker>,
94    /// List of provided components, such as buttons.
95    ///
96    /// Receiving the components of messages requires that the
97    /// [Message Content Intent] be enabled for the application. In the case of
98    /// receiving messages over the Gateway, the intent must also be enabled for
99    /// the session.
100    ///
101    /// Message components will be empty unless the [Message Content Intent] is
102    /// enabled, the message was sent by the current user, or the message is in
103    /// a direct message channel.
104    ///
105    /// [Message Content Intent]: crate::gateway::Intents::MESSAGE_CONTENT
106    #[serde(default, skip_serializing_if = "Vec::is_empty")]
107    pub components: Vec<Component>,
108    /// Content of the message.
109    ///
110    /// Receiving the content of messages requires that the
111    /// [Message Content Intent] be enabled for the application. In the case of
112    /// receiving messages over the Gateway, the intent must also be enabled for
113    /// the session.
114    ///
115    /// Message content will be empty unless the [Message Content Intent] is
116    /// enabled, the message was sent by the current user, or the message is in
117    /// a direct message channel.
118    ///
119    /// [Message Content Intent]: crate::gateway::Intents::MESSAGE_CONTENT
120    pub content: String,
121    /// When the message was last edited.
122    pub edited_timestamp: Option<Timestamp>,
123    /// List of embeds.
124    ///
125    /// Receiving the embeds of messages requires that the
126    /// [Message Content Intent] be enabled for the application. In the case of
127    /// receiving messages over the Gateway, the intent must also be enabled for
128    /// the session.
129    ///
130    /// Message embeds will be empty unless the [Message Content Intent] is
131    /// enabled, the message was sent by the current user, or the message is in
132    /// a direct message channel.
133    ///
134    /// [Message Content Intent]: crate::gateway::Intents::MESSAGE_CONTENT
135    pub embeds: Vec<Embed>,
136    /// Flags of the message.
137    #[serde(skip_serializing_if = "Option::is_none")]
138    pub flags: Option<MessageFlags>,
139    /// ID of the [`Guild`] the message was sent in.
140    ///
141    /// [`Guild`]: crate::guild::Guild
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub guild_id: Option<Id<GuildMarker>>,
144    /// Id of the message.
145    pub id: Id<MessageMarker>,
146    /// Interaction the message was sent as a response to.
147    #[deprecated(note = "use interaction_metadata instead")]
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub interaction: Option<MessageInteraction>,
150    /// Contains metadata related to the interacting if the message is
151    /// sent as a result of an interaction.
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub interaction_metadata: Option<Box<InteractionMetadata>>,
154    /// Type of message.
155    #[serde(rename = "type")]
156    pub kind: MessageType,
157    /// Member properties of the [`author`].
158    ///
159    /// [`author`]: Message::author
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub member: Option<PartialMember>,
162    /// [`Channel`]s mentioned in the message.
163    ///
164    /// Note: only textual channels visible to everyone mentioned in crossposted
165    /// messages (via channel following) will be included.
166    #[serde(default, skip_serializing_if = "Vec::is_empty")]
167    pub mention_channels: Vec<ChannelMention>,
168    /// Whether the message mentions `@everyone`.
169    pub mention_everyone: bool,
170    /// [`Role`]s mentioned in the message.
171    ///
172    /// [`Role`]: crate::guild::Role
173    pub mention_roles: Vec<Id<RoleMarker>>,
174    /// Users mentioned in the message.
175    pub mentions: Vec<Mention>,
176    /// The message associated with the [`MessageReference`]. This is a minimal subset
177    /// of fields in a message (e.g. author is excluded.).
178    #[serde(default, skip_serializing_if = "Vec::is_empty")]
179    pub message_snapshots: Vec<MessageSnapshot>,
180    /// Whether the message is pinned.
181    pub pinned: bool,
182    /// The poll associated with the message.
183    #[serde(skip_serializing_if = "Option::is_none")]
184    pub poll: Option<Poll>,
185    /// List of reactions to the message.
186    #[serde(default, skip_serializing_if = "Vec::is_empty")]
187    pub reactions: Vec<Reaction>,
188    /// Crosspost, channel follow add, pin and reply source message data.
189    #[serde(rename = "message_reference", skip_serializing_if = "Option::is_none")]
190    pub reference: Option<MessageReference>,
191    /// The message associated with the [`reference`].
192    ///
193    /// [`reference`]: Self::reference
194    #[serde(skip_serializing_if = "Option::is_none")]
195    pub referenced_message: Option<Box<Message>>,
196    /// Information about the role subscription purchase or renewal that
197    /// prompted this message.
198    ///
199    /// Applies to [`RoleSubscriptionPurchase`] messages.
200    ///
201    /// [`RoleSubscriptionPurchase`]: MessageType::RoleSubscriptionPurchase
202    #[serde(skip_serializing_if = "Option::is_none")]
203    pub role_subscription_data: Option<RoleSubscriptionData>,
204    /// Stickers within the message.
205    #[serde(default)]
206    pub sticker_items: Vec<MessageSticker>,
207    /// Timestamp of when the message was created.
208    pub timestamp: Timestamp,
209    /// Thread started from this message, includes [`Channel::member`].
210    #[serde(skip_serializing_if = "Option::is_none")]
211    pub thread: Option<Channel>,
212    /// Whether the message was a TTS message.
213    pub tts: bool,
214    /// ID of the webhook that generated the message.
215    #[serde(skip_serializing_if = "Option::is_none")]
216    pub webhook_id: Option<Id<WebhookMarker>>,
217}
218
219#[cfg(test)]
220mod tests {
221    use super::{
222        reaction::ReactionCountDetails,
223        reference_type::MessageReferenceType,
224        sticker::{MessageSticker, StickerFormatType},
225        EmojiReactionType, Message, MessageActivity, MessageActivityType, MessageApplication,
226        MessageCall, MessageFlags, MessageReference, MessageType, Reaction,
227    };
228    use crate::{
229        channel::{ChannelMention, ChannelType},
230        guild::{MemberFlags, PartialMember},
231        id::Id,
232        test::image_hash,
233        user::User,
234        util::{datetime::TimestampParseError, Timestamp},
235    };
236    use serde_test::Token;
237    use std::str::FromStr;
238
239    #[allow(clippy::too_many_lines, deprecated)]
240    #[test]
241    fn message_deserialization() {
242        let joined_at = Some(Timestamp::from_str("2020-01-01T00:00:00.000000+00:00").unwrap());
243        let timestamp = Timestamp::from_micros(1_580_608_922_020_000).expect("non zero");
244        let flags = MemberFlags::BYPASSES_VERIFICATION | MemberFlags::DID_REJOIN;
245
246        let value = Message {
247            activity: None,
248            application: None,
249            application_id: None,
250            attachments: Vec::new(),
251            author: User {
252                accent_color: None,
253                avatar: Some(image_hash::AVATAR),
254                avatar_decoration: None,
255                avatar_decoration_data: None,
256                banner: None,
257                bot: false,
258                discriminator: 1,
259                email: None,
260                flags: None,
261                global_name: Some("test".to_owned()),
262                id: Id::new(3),
263                locale: None,
264                mfa_enabled: None,
265                name: "test".to_owned(),
266                premium_type: None,
267                public_flags: None,
268                system: None,
269                verified: None,
270            },
271            call: Some(MessageCall {
272                ended_timestamp: None,
273                participants: Vec::new(),
274            }),
275            channel_id: Id::new(2),
276            components: Vec::new(),
277            content: "ping".to_owned(),
278            edited_timestamp: None,
279            embeds: Vec::new(),
280            flags: Some(MessageFlags::empty()),
281            guild_id: Some(Id::new(1)),
282            id: Id::new(4),
283            interaction: None,
284            kind: MessageType::Regular,
285            member: Some(PartialMember {
286                avatar: None,
287                communication_disabled_until: None,
288                deaf: false,
289                flags,
290                joined_at,
291                mute: false,
292                nick: Some("member nick".to_owned()),
293                permissions: None,
294                premium_since: None,
295                roles: Vec::new(),
296                user: None,
297            }),
298            mention_channels: Vec::new(),
299            mention_everyone: false,
300            mention_roles: Vec::new(),
301            mentions: Vec::new(),
302            message_snapshots: Vec::new(),
303            pinned: false,
304            poll: None,
305            reactions: Vec::new(),
306            reference: None,
307            role_subscription_data: None,
308            sticker_items: vec![MessageSticker {
309                format_type: StickerFormatType::Png,
310                id: Id::new(1),
311                name: "sticker name".to_owned(),
312            }],
313            referenced_message: None,
314            timestamp,
315            thread: None,
316            tts: false,
317            webhook_id: None,
318            interaction_metadata: None,
319        };
320
321        serde_test::assert_tokens(
322            &value,
323            &[
324                Token::Struct {
325                    name: "Message",
326                    len: 19,
327                },
328                Token::Str("attachments"),
329                Token::Seq { len: Some(0) },
330                Token::SeqEnd,
331                Token::Str("author"),
332                Token::Struct {
333                    name: "User",
334                    len: 10,
335                },
336                Token::Str("accent_color"),
337                Token::None,
338                Token::Str("avatar"),
339                Token::Some,
340                Token::Str(image_hash::AVATAR_INPUT),
341                Token::Str("avatar_decoration"),
342                Token::None,
343                Token::Str("avatar_decoration_data"),
344                Token::None,
345                Token::Str("banner"),
346                Token::None,
347                Token::Str("bot"),
348                Token::Bool(false),
349                Token::Str("discriminator"),
350                Token::Str("0001"),
351                Token::Str("global_name"),
352                Token::Some,
353                Token::Str("test"),
354                Token::Str("id"),
355                Token::NewtypeStruct { name: "Id" },
356                Token::Str("3"),
357                Token::Str("username"),
358                Token::Str("test"),
359                Token::StructEnd,
360                Token::Str("call"),
361                Token::Some,
362                Token::Struct {
363                    name: "MessageCall",
364                    len: 2,
365                },
366                Token::Str("ended_timestamp"),
367                Token::None,
368                Token::Str("participants"),
369                Token::Seq { len: Some(0) },
370                Token::SeqEnd,
371                Token::StructEnd,
372                Token::Str("channel_id"),
373                Token::NewtypeStruct { name: "Id" },
374                Token::Str("2"),
375                Token::Str("content"),
376                Token::Str("ping"),
377                Token::Str("edited_timestamp"),
378                Token::None,
379                Token::Str("embeds"),
380                Token::Seq { len: Some(0) },
381                Token::SeqEnd,
382                Token::Str("flags"),
383                Token::Some,
384                Token::U64(0),
385                Token::Str("guild_id"),
386                Token::Some,
387                Token::NewtypeStruct { name: "Id" },
388                Token::Str("1"),
389                Token::Str("id"),
390                Token::NewtypeStruct { name: "Id" },
391                Token::Str("4"),
392                Token::Str("type"),
393                Token::U8(0),
394                Token::Str("member"),
395                Token::Some,
396                Token::Struct {
397                    name: "PartialMember",
398                    len: 8,
399                },
400                Token::Str("communication_disabled_until"),
401                Token::None,
402                Token::Str("deaf"),
403                Token::Bool(false),
404                Token::Str("flags"),
405                Token::U64(flags.bits()),
406                Token::Str("joined_at"),
407                Token::Some,
408                Token::Str("2020-01-01T00:00:00.000000+00:00"),
409                Token::Str("mute"),
410                Token::Bool(false),
411                Token::Str("nick"),
412                Token::Some,
413                Token::Str("member nick"),
414                Token::Str("roles"),
415                Token::Seq { len: Some(0) },
416                Token::SeqEnd,
417                Token::Str("user"),
418                Token::None,
419                Token::StructEnd,
420                Token::Str("mention_everyone"),
421                Token::Bool(false),
422                Token::Str("mention_roles"),
423                Token::Seq { len: Some(0) },
424                Token::SeqEnd,
425                Token::Str("mentions"),
426                Token::Seq { len: Some(0) },
427                Token::SeqEnd,
428                Token::Str("pinned"),
429                Token::Bool(false),
430                Token::Str("sticker_items"),
431                Token::Seq { len: Some(1) },
432                Token::Struct {
433                    name: "MessageSticker",
434                    len: 3,
435                },
436                Token::Str("format_type"),
437                Token::U8(1),
438                Token::Str("id"),
439                Token::NewtypeStruct { name: "Id" },
440                Token::Str("1"),
441                Token::Str("name"),
442                Token::Str("sticker name"),
443                Token::StructEnd,
444                Token::SeqEnd,
445                Token::Str("timestamp"),
446                Token::Str("2020-02-02T02:02:02.020000+00:00"),
447                Token::Str("tts"),
448                Token::Bool(false),
449                Token::StructEnd,
450            ],
451        );
452    }
453
454    #[allow(clippy::too_many_lines, deprecated)]
455    #[test]
456    fn message_deserialization_complete() -> Result<(), TimestampParseError> {
457        let edited_timestamp = Timestamp::from_str("2021-08-10T12:41:51.602000+00:00")?;
458        let joined_at = Some(Timestamp::from_str("2020-01-01T00:00:00.000000+00:00")?);
459        let timestamp = Timestamp::from_micros(1_580_608_922_020_000).expect("non zero");
460        let flags = MemberFlags::BYPASSES_VERIFICATION | MemberFlags::DID_REJOIN;
461
462        let value = Message {
463            activity: Some(MessageActivity {
464                kind: MessageActivityType::Join,
465                party_id: None,
466            }),
467            application: Some(MessageApplication {
468                cover_image: Some(image_hash::COVER),
469                description: "a description".to_owned(),
470                icon: Some(image_hash::ICON),
471                id: Id::new(1),
472                name: "application".to_owned(),
473            }),
474            application_id: Some(Id::new(1)),
475            attachments: Vec::new(),
476            author: User {
477                accent_color: None,
478                avatar: Some(image_hash::AVATAR),
479                avatar_decoration: None,
480                avatar_decoration_data: None,
481                banner: None,
482                bot: false,
483                discriminator: 1,
484                email: None,
485                flags: None,
486                global_name: Some("test".to_owned()),
487                id: Id::new(3),
488                locale: None,
489                mfa_enabled: None,
490                name: "test".to_owned(),
491                premium_type: None,
492                public_flags: None,
493                system: None,
494                verified: None,
495            },
496            call: None,
497            channel_id: Id::new(2),
498            components: Vec::new(),
499            content: "ping".to_owned(),
500            edited_timestamp: Some(edited_timestamp),
501            embeds: Vec::new(),
502            flags: Some(MessageFlags::empty()),
503            guild_id: Some(Id::new(1)),
504            id: Id::new(4),
505            interaction: None,
506            kind: MessageType::Regular,
507            member: Some(PartialMember {
508                avatar: None,
509                communication_disabled_until: None,
510                deaf: false,
511                flags,
512                joined_at,
513                mute: false,
514                nick: Some("member nick".to_owned()),
515                permissions: None,
516                premium_since: None,
517                roles: Vec::new(),
518                user: None,
519            }),
520            mention_channels: vec![ChannelMention {
521                guild_id: Id::new(1),
522                id: Id::new(2),
523                kind: ChannelType::GuildText,
524                name: "channel".to_owned(),
525            }],
526            mention_everyone: false,
527            mention_roles: Vec::new(),
528            mentions: Vec::new(),
529            message_snapshots: Vec::new(),
530            pinned: false,
531            poll: None,
532            reactions: vec![Reaction {
533                burst_colors: Vec::new(),
534                count: 7,
535                count_details: ReactionCountDetails {
536                    burst: 0,
537                    normal: 7,
538                },
539                emoji: EmojiReactionType::Unicode {
540                    name: "a".to_owned(),
541                },
542                me: true,
543                me_burst: false,
544            }],
545            reference: Some(MessageReference {
546                channel_id: Some(Id::new(1)),
547                guild_id: None,
548                kind: MessageReferenceType::Default,
549                message_id: None,
550                fail_if_not_exists: None,
551            }),
552            role_subscription_data: None,
553            sticker_items: vec![MessageSticker {
554                format_type: StickerFormatType::Png,
555                id: Id::new(1),
556                name: "sticker name".to_owned(),
557            }],
558            referenced_message: None,
559            timestamp,
560            thread: None,
561            tts: false,
562            webhook_id: Some(Id::new(1)),
563            interaction_metadata: None,
564        };
565
566        serde_test::assert_tokens(
567            &value,
568            &[
569                Token::Struct {
570                    name: "Message",
571                    len: 26,
572                },
573                Token::Str("activity"),
574                Token::Some,
575                Token::Struct {
576                    name: "MessageActivity",
577                    len: 1,
578                },
579                Token::Str("type"),
580                Token::U8(1),
581                Token::StructEnd,
582                Token::Str("application"),
583                Token::Some,
584                Token::Struct {
585                    name: "MessageApplication",
586                    len: 5,
587                },
588                Token::Str("cover_image"),
589                Token::Some,
590                Token::Str(image_hash::COVER_INPUT),
591                Token::Str("description"),
592                Token::Str("a description"),
593                Token::Str("icon"),
594                Token::Some,
595                Token::Str(image_hash::ICON_INPUT),
596                Token::Str("id"),
597                Token::NewtypeStruct { name: "Id" },
598                Token::Str("1"),
599                Token::Str("name"),
600                Token::Str("application"),
601                Token::StructEnd,
602                Token::Str("application_id"),
603                Token::Some,
604                Token::NewtypeStruct { name: "Id" },
605                Token::Str("1"),
606                Token::Str("attachments"),
607                Token::Seq { len: Some(0) },
608                Token::SeqEnd,
609                Token::Str("author"),
610                Token::Struct {
611                    name: "User",
612                    len: 10,
613                },
614                Token::Str("accent_color"),
615                Token::None,
616                Token::Str("avatar"),
617                Token::Some,
618                Token::Str(image_hash::AVATAR_INPUT),
619                Token::Str("avatar_decoration"),
620                Token::None,
621                Token::Str("avatar_decoration_data"),
622                Token::None,
623                Token::Str("banner"),
624                Token::None,
625                Token::Str("bot"),
626                Token::Bool(false),
627                Token::Str("discriminator"),
628                Token::Str("0001"),
629                Token::Str("global_name"),
630                Token::Some,
631                Token::Str("test"),
632                Token::Str("id"),
633                Token::NewtypeStruct { name: "Id" },
634                Token::Str("3"),
635                Token::Str("username"),
636                Token::Str("test"),
637                Token::StructEnd,
638                Token::Str("call"),
639                Token::None,
640                Token::Str("channel_id"),
641                Token::NewtypeStruct { name: "Id" },
642                Token::Str("2"),
643                Token::Str("content"),
644                Token::Str("ping"),
645                Token::Str("edited_timestamp"),
646                Token::Some,
647                Token::Str("2021-08-10T12:41:51.602000+00:00"),
648                Token::Str("embeds"),
649                Token::Seq { len: Some(0) },
650                Token::SeqEnd,
651                Token::Str("flags"),
652                Token::Some,
653                Token::U64(0),
654                Token::Str("guild_id"),
655                Token::Some,
656                Token::NewtypeStruct { name: "Id" },
657                Token::Str("1"),
658                Token::Str("id"),
659                Token::NewtypeStruct { name: "Id" },
660                Token::Str("4"),
661                Token::Str("type"),
662                Token::U8(0),
663                Token::Str("member"),
664                Token::Some,
665                Token::Struct {
666                    name: "PartialMember",
667                    len: 8,
668                },
669                Token::Str("communication_disabled_until"),
670                Token::None,
671                Token::Str("deaf"),
672                Token::Bool(false),
673                Token::Str("flags"),
674                Token::U64(flags.bits()),
675                Token::Str("joined_at"),
676                Token::Some,
677                Token::Str("2020-01-01T00:00:00.000000+00:00"),
678                Token::Str("mute"),
679                Token::Bool(false),
680                Token::Str("nick"),
681                Token::Some,
682                Token::Str("member nick"),
683                Token::Str("roles"),
684                Token::Seq { len: Some(0) },
685                Token::SeqEnd,
686                Token::Str("user"),
687                Token::None,
688                Token::StructEnd,
689                Token::Str("mention_channels"),
690                Token::Seq { len: Some(1) },
691                Token::Struct {
692                    name: "ChannelMention",
693                    len: 4,
694                },
695                Token::Str("guild_id"),
696                Token::NewtypeStruct { name: "Id" },
697                Token::Str("1"),
698                Token::Str("id"),
699                Token::NewtypeStruct { name: "Id" },
700                Token::Str("2"),
701                Token::Str("type"),
702                Token::U8(0),
703                Token::Str("name"),
704                Token::Str("channel"),
705                Token::StructEnd,
706                Token::SeqEnd,
707                Token::Str("mention_everyone"),
708                Token::Bool(false),
709                Token::Str("mention_roles"),
710                Token::Seq { len: Some(0) },
711                Token::SeqEnd,
712                Token::Str("mentions"),
713                Token::Seq { len: Some(0) },
714                Token::SeqEnd,
715                Token::Str("pinned"),
716                Token::Bool(false),
717                Token::Str("reactions"),
718                Token::Seq { len: Some(1) },
719                Token::Struct {
720                    name: "Reaction",
721                    len: 6,
722                },
723                Token::Str("burst_colors"),
724                Token::Seq { len: Some(0) },
725                Token::SeqEnd,
726                Token::Str("count"),
727                Token::U64(7),
728                Token::Str("count_details"),
729                Token::Struct {
730                    name: "ReactionCountDetails",
731                    len: 2,
732                },
733                Token::Str("burst"),
734                Token::U64(0),
735                Token::Str("normal"),
736                Token::U64(7),
737                Token::StructEnd,
738                Token::Str("emoji"),
739                Token::Struct {
740                    name: "EmojiReactionType",
741                    len: 1,
742                },
743                Token::Str("name"),
744                Token::Str("a"),
745                Token::StructEnd,
746                Token::Str("me"),
747                Token::Bool(true),
748                Token::Str("me_burst"),
749                Token::Bool(false),
750                Token::StructEnd,
751                Token::SeqEnd,
752                Token::Str("message_reference"),
753                Token::Some,
754                Token::Struct {
755                    name: "MessageReference",
756                    len: 2,
757                },
758                Token::Str("channel_id"),
759                Token::Some,
760                Token::NewtypeStruct { name: "Id" },
761                Token::Str("1"),
762                Token::Str("type"),
763                Token::U8(0),
764                Token::StructEnd,
765                Token::Str("sticker_items"),
766                Token::Seq { len: Some(1) },
767                Token::Struct {
768                    name: "MessageSticker",
769                    len: 3,
770                },
771                Token::Str("format_type"),
772                Token::U8(1),
773                Token::Str("id"),
774                Token::NewtypeStruct { name: "Id" },
775                Token::Str("1"),
776                Token::Str("name"),
777                Token::Str("sticker name"),
778                Token::StructEnd,
779                Token::SeqEnd,
780                Token::Str("timestamp"),
781                Token::Str("2020-02-02T02:02:02.020000+00:00"),
782                Token::Str("tts"),
783                Token::Bool(false),
784                Token::Str("webhook_id"),
785                Token::Some,
786                Token::NewtypeStruct { name: "Id" },
787                Token::Str("1"),
788                Token::StructEnd,
789            ],
790        );
791
792        Ok(())
793    }
794}