1use super::MemberFlags;
4use crate::{
5 id::{Id, marker::RoleMarker},
6 user::User,
7 util::{ImageHash, Timestamp},
8};
9
10use crate::user::AvatarDecorationData;
11use serde::{Deserialize, Serialize};
12
13#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
17pub struct Member {
18 #[serde(skip_serializing_if = "Option::is_none")]
20 pub avatar: Option<ImageHash>,
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub avatar_decoration_data: Option<AvatarDecorationData>,
24 #[serde(skip_serializing_if = "Option::is_none")]
26 pub banner: Option<ImageHash>,
27 pub communication_disabled_until: Option<Timestamp>,
28 pub deaf: bool,
29 pub flags: MemberFlags,
33 pub joined_at: Option<Timestamp>,
34 pub mute: bool,
35 pub nick: Option<String>,
36 #[serde(default)]
39 pub pending: bool,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub premium_since: Option<Timestamp>,
42 pub roles: Vec<Id<RoleMarker>>,
43 pub user: User,
44}
45
46#[cfg(test)]
47mod tests {
48 use super::Member;
49 use crate::{
50 guild::MemberFlags,
51 id::Id,
52 test::image_hash,
53 user::User,
54 util::datetime::{Timestamp, TimestampParseError},
55 };
56 use serde_test::Token;
57 use std::str::FromStr;
58
59 #[test]
60 #[allow(clippy::too_many_lines)]
61 fn member_deserializer() -> Result<(), TimestampParseError> {
62 let joined_at = Some(Timestamp::from_str("2015-04-26T06:26:56.936000+00:00")?);
63 let premium_since = Timestamp::from_str("2021-03-16T14:29:19.046000+00:00")?;
64 let flags = MemberFlags::BYPASSES_VERIFICATION | MemberFlags::DID_REJOIN;
65
66 let value = Member {
67 avatar: Some(image_hash::AVATAR),
68 avatar_decoration_data: None,
69 banner: None,
70 communication_disabled_until: None,
71 deaf: false,
72 flags,
73 joined_at,
74 mute: true,
75 nick: Some("twilight".to_owned()),
76 pending: false,
77 premium_since: Some(premium_since),
78 roles: Vec::new(),
79 user: User {
80 accent_color: None,
81 avatar: None,
82 avatar_decoration: None,
83 avatar_decoration_data: None,
84 banner: None,
85 bot: false,
86 discriminator: 1,
87 email: None,
88 flags: None,
89 global_name: Some("test".to_owned()),
90 id: Id::new(3),
91 locale: None,
92 mfa_enabled: None,
93 name: "twilight".to_owned(),
94 premium_type: None,
95 primary_guild: None,
96 public_flags: None,
97 system: None,
98 verified: None,
99 },
100 };
101
102 serde_test::assert_tokens(
103 &value,
104 &[
105 Token::Struct {
106 name: "Member",
107 len: 11,
108 },
109 Token::Str("avatar"),
110 Token::Some,
111 Token::Str(image_hash::AVATAR_INPUT),
112 Token::Str("communication_disabled_until"),
113 Token::None,
114 Token::Str("deaf"),
115 Token::Bool(false),
116 Token::Str("flags"),
117 Token::U64(flags.bits()),
118 Token::Str("joined_at"),
119 Token::Some,
120 Token::Str("2015-04-26T06:26:56.936000+00:00"),
121 Token::Str("mute"),
122 Token::Bool(true),
123 Token::Str("nick"),
124 Token::Some,
125 Token::Str("twilight"),
126 Token::Str("pending"),
127 Token::Bool(false),
128 Token::Str("premium_since"),
129 Token::Some,
130 Token::Str("2021-03-16T14:29:19.046000+00:00"),
131 Token::Str("roles"),
132 Token::Seq { len: Some(0) },
133 Token::SeqEnd,
134 Token::Str("user"),
135 Token::Struct {
136 name: "User",
137 len: 10,
138 },
139 Token::Str("accent_color"),
140 Token::None,
141 Token::Str("avatar"),
142 Token::None,
143 Token::Str("avatar_decoration"),
144 Token::None,
145 Token::Str("avatar_decoration_data"),
146 Token::None,
147 Token::Str("banner"),
148 Token::None,
149 Token::Str("bot"),
150 Token::Bool(false),
151 Token::Str("discriminator"),
152 Token::Str("0001"),
153 Token::Str("global_name"),
154 Token::Some,
155 Token::Str("test"),
156 Token::Str("id"),
157 Token::NewtypeStruct { name: "Id" },
158 Token::Str("3"),
159 Token::Str("username"),
160 Token::Str("twilight"),
161 Token::StructEnd,
162 Token::StructEnd,
163 ],
164 );
165
166 Ok(())
167 }
168
169 #[test]
170 #[allow(clippy::too_many_lines)]
171 fn guild_member_communication_disabled_until() -> Result<(), TimestampParseError> {
172 let communication_disabled_until = Timestamp::from_str("2021-12-23T14:29:19.046000+00:00")?;
173 let joined_at = Some(Timestamp::from_str("2015-04-26T06:26:56.936000+00:00")?);
174 let premium_since = Timestamp::from_str("2021-03-16T14:29:19.046000+00:00")?;
175 let flags = MemberFlags::BYPASSES_VERIFICATION | MemberFlags::DID_REJOIN;
176
177 let value = Member {
178 avatar: Some(image_hash::AVATAR),
179 avatar_decoration_data: None,
180 banner: None,
181 communication_disabled_until: Some(communication_disabled_until),
182 deaf: false,
183 flags,
184 joined_at,
185 mute: true,
186 nick: Some("twilight".to_owned()),
187 pending: false,
188 premium_since: Some(premium_since),
189 roles: Vec::new(),
190 user: User {
191 accent_color: None,
192 avatar: None,
193 avatar_decoration: None,
194 avatar_decoration_data: None,
195 banner: None,
196 bot: false,
197 discriminator: 1,
198 email: None,
199 flags: None,
200 global_name: Some("test".to_owned()),
201 id: Id::new(3),
202 locale: None,
203 mfa_enabled: None,
204 name: "twilight".to_owned(),
205 premium_type: None,
206 primary_guild: None,
207 public_flags: None,
208 system: None,
209 verified: None,
210 },
211 };
212
213 serde_test::assert_tokens(
214 &value,
215 &[
216 Token::Struct {
217 name: "Member",
218 len: 11,
219 },
220 Token::Str("avatar"),
221 Token::Some,
222 Token::Str(image_hash::AVATAR_INPUT),
223 Token::Str("communication_disabled_until"),
224 Token::Some,
225 Token::Str("2021-12-23T14:29:19.046000+00:00"),
226 Token::Str("deaf"),
227 Token::Bool(false),
228 Token::Str("flags"),
229 Token::U64(flags.bits()),
230 Token::Str("joined_at"),
231 Token::Some,
232 Token::Str("2015-04-26T06:26:56.936000+00:00"),
233 Token::Str("mute"),
234 Token::Bool(true),
235 Token::Str("nick"),
236 Token::Some,
237 Token::Str("twilight"),
238 Token::Str("pending"),
239 Token::Bool(false),
240 Token::Str("premium_since"),
241 Token::Some,
242 Token::Str("2021-03-16T14:29:19.046000+00:00"),
243 Token::Str("roles"),
244 Token::Seq { len: Some(0) },
245 Token::SeqEnd,
246 Token::Str("user"),
247 Token::Struct {
248 name: "User",
249 len: 10,
250 },
251 Token::Str("accent_color"),
252 Token::None,
253 Token::Str("avatar"),
254 Token::None,
255 Token::Str("avatar_decoration"),
256 Token::None,
257 Token::Str("avatar_decoration_data"),
258 Token::None,
259 Token::Str("banner"),
260 Token::None,
261 Token::Str("bot"),
262 Token::Bool(false),
263 Token::Str("discriminator"),
264 Token::Str("0001"),
265 Token::Str("global_name"),
266 Token::Some,
267 Token::Str("test"),
268 Token::Str("id"),
269 Token::NewtypeStruct { name: "Id" },
270 Token::Str("3"),
271 Token::Str("username"),
272 Token::Str("twilight"),
273 Token::StructEnd,
274 Token::StructEnd,
275 ],
276 );
277
278 Ok(())
279 }
280}