twilight_model/gateway/payload/incoming/
typing_start.rs

1use crate::{
2    guild::Member,
3    id::{
4        marker::{ChannelMarker, GuildMarker, UserMarker},
5        Id,
6    },
7};
8use serde::{Deserialize, Serialize};
9
10#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
11pub struct TypingStart {
12    pub channel_id: Id<ChannelMarker>,
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub guild_id: Option<Id<GuildMarker>>,
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub member: Option<Member>,
17    pub timestamp: u64,
18    pub user_id: Id<UserMarker>,
19}
20
21#[cfg(test)]
22mod tests {
23    use super::TypingStart;
24    use crate::{
25        guild::{Member, MemberFlags},
26        id::Id,
27        test::image_hash,
28        user::User,
29        util::datetime::{Timestamp, TimestampParseError},
30    };
31    use serde_test::Token;
32    use std::str::FromStr;
33
34    #[allow(clippy::too_many_lines)]
35    #[test]
36    fn typing_start_with_member() -> Result<(), TimestampParseError> {
37        let joined_at = Some(Timestamp::from_str("2020-01-01T00:00:00.000000+00:00")?);
38        let flags = MemberFlags::BYPASSES_VERIFICATION | MemberFlags::DID_REJOIN;
39
40        let value = TypingStart {
41            channel_id: Id::new(2),
42            guild_id: Some(Id::new(1)),
43            member: Some(Member {
44                avatar: None,
45                communication_disabled_until: None,
46                deaf: false,
47                flags,
48                joined_at,
49                mute: false,
50                nick: Some("typing".to_owned()),
51                pending: false,
52                premium_since: None,
53                roles: vec![Id::new(4)],
54                user: User {
55                    id: Id::new(3),
56                    accent_color: None,
57                    avatar: Some(image_hash::AVATAR),
58                    avatar_decoration: None,
59                    avatar_decoration_data: None,
60                    banner: None,
61                    bot: false,
62                    discriminator: 1,
63                    global_name: Some("test".to_owned()),
64                    name: "test".to_owned(),
65                    mfa_enabled: None,
66                    locale: None,
67                    verified: None,
68                    email: None,
69                    flags: None,
70                    premium_type: None,
71                    system: None,
72                    public_flags: None,
73                },
74            }),
75            timestamp: 1_500_000_000,
76            user_id: Id::new(3),
77        };
78
79        serde_test::assert_tokens(
80            &value,
81            &[
82                Token::Struct {
83                    name: "TypingStart",
84                    len: 5,
85                },
86                Token::Str("channel_id"),
87                Token::NewtypeStruct { name: "Id" },
88                Token::Str("2"),
89                Token::Str("guild_id"),
90                Token::Some,
91                Token::NewtypeStruct { name: "Id" },
92                Token::Str("1"),
93                Token::Str("member"),
94                Token::Some,
95                Token::Struct {
96                    name: "Member",
97                    len: 9,
98                },
99                Token::Str("communication_disabled_until"),
100                Token::None,
101                Token::Str("deaf"),
102                Token::Bool(false),
103                Token::Str("flags"),
104                Token::U64(flags.bits()),
105                Token::Str("joined_at"),
106                Token::Some,
107                Token::Str("2020-01-01T00:00:00.000000+00:00"),
108                Token::Str("mute"),
109                Token::Bool(false),
110                Token::Str("nick"),
111                Token::Some,
112                Token::Str("typing"),
113                Token::Str("pending"),
114                Token::Bool(false),
115                Token::Str("roles"),
116                Token::Seq { len: Some(1) },
117                Token::NewtypeStruct { name: "Id" },
118                Token::Str("4"),
119                Token::SeqEnd,
120                Token::Str("user"),
121                Token::Struct {
122                    name: "User",
123                    len: 10,
124                },
125                Token::Str("accent_color"),
126                Token::None,
127                Token::Str("avatar"),
128                Token::Some,
129                Token::Str(image_hash::AVATAR_INPUT),
130                Token::Str("avatar_decoration"),
131                Token::None,
132                Token::Str("avatar_decoration_data"),
133                Token::None,
134                Token::Str("banner"),
135                Token::None,
136                Token::Str("bot"),
137                Token::Bool(false),
138                Token::Str("discriminator"),
139                Token::Str("0001"),
140                Token::Str("global_name"),
141                Token::Some,
142                Token::Str("test"),
143                Token::Str("id"),
144                Token::NewtypeStruct { name: "Id" },
145                Token::Str("3"),
146                Token::Str("username"),
147                Token::Str("test"),
148                Token::StructEnd,
149                Token::StructEnd,
150                Token::Str("timestamp"),
151                Token::U64(1_500_000_000),
152                Token::Str("user_id"),
153                Token::NewtypeStruct { name: "Id" },
154                Token::Str("3"),
155                Token::StructEnd,
156            ],
157        );
158
159        Ok(())
160    }
161
162    #[test]
163    fn typing_start_without_member() {
164        let value = TypingStart {
165            channel_id: Id::new(2),
166            guild_id: None,
167            member: None,
168            timestamp: 1_500_000_000,
169            user_id: Id::new(3),
170        };
171
172        serde_test::assert_tokens(
173            &value,
174            &[
175                Token::Struct {
176                    name: "TypingStart",
177                    len: 3,
178                },
179                Token::Str("channel_id"),
180                Token::NewtypeStruct { name: "Id" },
181                Token::Str("2"),
182                Token::Str("timestamp"),
183                Token::U64(1_500_000_000),
184                Token::Str("user_id"),
185                Token::NewtypeStruct { name: "Id" },
186                Token::Str("3"),
187                Token::StructEnd,
188            ],
189        );
190    }
191}