twilight_model/gateway/payload/incoming/
typing_start.rs1use crate::{
2 guild::Member,
3 id::{
4 Id,
5 marker::{ChannelMarker, GuildMarker, UserMarker},
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 avatar_decoration_data: None,
46 banner: None,
47 communication_disabled_until: None,
48 deaf: false,
49 flags,
50 joined_at,
51 mute: false,
52 nick: Some("typing".to_owned()),
53 pending: false,
54 premium_since: None,
55 roles: vec![Id::new(4)],
56 user: User {
57 id: Id::new(3),
58 accent_color: None,
59 avatar: Some(image_hash::AVATAR),
60 avatar_decoration: None,
61 avatar_decoration_data: None,
62 banner: None,
63 bot: false,
64 discriminator: 1,
65 global_name: Some("test".to_owned()),
66 name: "test".to_owned(),
67 mfa_enabled: None,
68 locale: None,
69 verified: None,
70 email: None,
71 flags: None,
72 premium_type: None,
73 primary_guild: None,
74 public_flags: None,
75 system: None,
76 },
77 }),
78 timestamp: 1_500_000_000,
79 user_id: Id::new(3),
80 };
81
82 serde_test::assert_tokens(
83 &value,
84 &[
85 Token::Struct {
86 name: "TypingStart",
87 len: 5,
88 },
89 Token::Str("channel_id"),
90 Token::NewtypeStruct { name: "Id" },
91 Token::Str("2"),
92 Token::Str("guild_id"),
93 Token::Some,
94 Token::NewtypeStruct { name: "Id" },
95 Token::Str("1"),
96 Token::Str("member"),
97 Token::Some,
98 Token::Struct {
99 name: "Member",
100 len: 9,
101 },
102 Token::Str("communication_disabled_until"),
103 Token::None,
104 Token::Str("deaf"),
105 Token::Bool(false),
106 Token::Str("flags"),
107 Token::U64(flags.bits()),
108 Token::Str("joined_at"),
109 Token::Some,
110 Token::Str("2020-01-01T00:00:00.000000+00:00"),
111 Token::Str("mute"),
112 Token::Bool(false),
113 Token::Str("nick"),
114 Token::Some,
115 Token::Str("typing"),
116 Token::Str("pending"),
117 Token::Bool(false),
118 Token::Str("roles"),
119 Token::Seq { len: Some(1) },
120 Token::NewtypeStruct { name: "Id" },
121 Token::Str("4"),
122 Token::SeqEnd,
123 Token::Str("user"),
124 Token::Struct {
125 name: "User",
126 len: 10,
127 },
128 Token::Str("accent_color"),
129 Token::None,
130 Token::Str("avatar"),
131 Token::Some,
132 Token::Str(image_hash::AVATAR_INPUT),
133 Token::Str("avatar_decoration"),
134 Token::None,
135 Token::Str("avatar_decoration_data"),
136 Token::None,
137 Token::Str("banner"),
138 Token::None,
139 Token::Str("bot"),
140 Token::Bool(false),
141 Token::Str("discriminator"),
142 Token::Str("0001"),
143 Token::Str("global_name"),
144 Token::Some,
145 Token::Str("test"),
146 Token::Str("id"),
147 Token::NewtypeStruct { name: "Id" },
148 Token::Str("3"),
149 Token::Str("username"),
150 Token::Str("test"),
151 Token::StructEnd,
152 Token::StructEnd,
153 Token::Str("timestamp"),
154 Token::U64(1_500_000_000),
155 Token::Str("user_id"),
156 Token::NewtypeStruct { name: "Id" },
157 Token::Str("3"),
158 Token::StructEnd,
159 ],
160 );
161
162 Ok(())
163 }
164
165 #[test]
166 fn typing_start_without_member() {
167 let value = TypingStart {
168 channel_id: Id::new(2),
169 guild_id: None,
170 member: None,
171 timestamp: 1_500_000_000,
172 user_id: Id::new(3),
173 };
174
175 serde_test::assert_tokens(
176 &value,
177 &[
178 Token::Struct {
179 name: "TypingStart",
180 len: 3,
181 },
182 Token::Str("channel_id"),
183 Token::NewtypeStruct { name: "Id" },
184 Token::Str("2"),
185 Token::Str("timestamp"),
186 Token::U64(1_500_000_000),
187 Token::Str("user_id"),
188 Token::NewtypeStruct { name: "Id" },
189 Token::Str("3"),
190 Token::StructEnd,
191 ],
192 );
193 }
194}