1mod channel;
2mod guild;
3mod invite_type;
4mod target_type;
5mod welcome_screen;
6
7pub use self::{
8 channel::InviteChannel,
9 guild::InviteGuild,
10 invite_type::InviteType,
11 target_type::TargetType,
12 welcome_screen::{WelcomeScreen, WelcomeScreenChannel},
13};
14
15use crate::{user::User, util::Timestamp};
16use serde::{Deserialize, Serialize};
17
18#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
19pub struct Invite {
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub approximate_member_count: Option<u64>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub approximate_presence_count: Option<u64>,
24 pub channel: Option<InviteChannel>,
25 pub code: String,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub created_at: Option<Timestamp>,
28 #[serde(skip_serializing_if = "Option::is_none")]
29 pub expires_at: Option<Timestamp>,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub guild: Option<InviteGuild>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 pub inviter: Option<User>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub max_age: Option<u64>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub max_uses: Option<u64>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub target_type: Option<TargetType>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub target_user: Option<User>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub temporary: Option<bool>,
44 #[serde(rename = "type")]
45 pub kind: InviteType,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub uses: Option<u64>,
48}
49
50#[cfg(test)]
51mod tests {
52 use super::{
53 welcome_screen::WelcomeScreenChannel, Invite, InviteChannel, InviteGuild, InviteType,
54 TargetType, User, WelcomeScreen,
55 };
56 use crate::{
57 channel::ChannelType,
58 guild::{GuildFeature, VerificationLevel},
59 id::Id,
60 test::image_hash,
61 util::datetime::{Timestamp, TimestampParseError},
62 };
63 use serde::{Deserialize, Serialize};
64 use serde_test::Token;
65 use static_assertions::{assert_fields, assert_impl_all};
66 use std::{fmt::Debug, str::FromStr};
67
68 assert_fields!(
69 Invite: approximate_member_count,
70 approximate_presence_count,
71 channel,
72 code,
73 created_at,
74 expires_at,
75 guild,
76 inviter,
77 max_age,
78 max_uses,
79 target_type,
80 target_user,
81 temporary,
82 uses
83 );
84
85 assert_impl_all!(
86 Invite: Clone,
87 Debug,
88 Deserialize<'static>,
89 Eq,
90 PartialEq,
91 Serialize,
92 Send,
93 Sync,
94 );
95
96 #[test]
97 fn invite() {
98 let value = Invite {
99 approximate_member_count: Some(31),
100 approximate_presence_count: Some(7),
101 channel: Some(InviteChannel {
102 id: Id::new(2),
103 kind: ChannelType::Group,
104 name: None,
105 }),
106 code: "uniquecode".to_owned(),
107 created_at: None,
108 expires_at: None,
109 guild: None,
110 inviter: None,
111 max_age: None,
112 max_uses: None,
113 target_type: Some(TargetType::Stream),
114 target_user: None,
115 temporary: None,
116 kind: InviteType::Guild,
117 uses: None,
118 };
119
120 serde_test::assert_tokens(
121 &value,
122 &[
123 Token::Struct {
124 name: "Invite",
125 len: 6,
126 },
127 Token::Str("approximate_member_count"),
128 Token::Some,
129 Token::U64(31),
130 Token::Str("approximate_presence_count"),
131 Token::Some,
132 Token::U64(7),
133 Token::Str("channel"),
134 Token::Some,
135 Token::Struct {
136 name: "InviteChannel",
137 len: 2,
138 },
139 Token::Str("id"),
140 Token::NewtypeStruct { name: "Id" },
141 Token::Str("2"),
142 Token::Str("type"),
143 Token::U8(3),
144 Token::StructEnd,
145 Token::Str("code"),
146 Token::Str("uniquecode"),
147 Token::Str("target_type"),
148 Token::Some,
149 Token::U8(1),
150 Token::Str("type"),
151 Token::U8(0),
152 Token::StructEnd,
153 ],
154 );
155 }
156
157 #[allow(clippy::too_many_lines)]
158 #[test]
159 fn invite_complete() -> Result<(), TimestampParseError> {
160 let created_at = Timestamp::from_str("2021-08-03T16:08:36.325000+00:00")?;
161 let expires_at = Timestamp::from_str("2021-08-10T16:08:36.325000+00:00")?;
162
163 let value = Invite {
164 approximate_member_count: Some(31),
165 approximate_presence_count: Some(7),
166 channel: Some(InviteChannel {
167 id: Id::new(2),
168 kind: ChannelType::Group,
169 name: None,
170 }),
171 code: "uniquecode".to_owned(),
172 created_at: Some(created_at),
173 expires_at: Some(expires_at),
174 guild: Some(InviteGuild {
175 banner: Some(image_hash::BANNER),
176 description: Some("a description".to_owned()),
177 features: Vec::from([GuildFeature::Discoverable]),
178 icon: Some(image_hash::ICON),
179 id: Id::new(1),
180 name: "guild name".to_owned(),
181 premium_subscription_count: None,
182 splash: Some(image_hash::SPLASH),
183 vanity_url_code: Some("twilight".to_owned()),
184 verification_level: VerificationLevel::Medium,
185 welcome_screen: Some(WelcomeScreen {
186 description: Some("welcome description".to_owned()),
187 welcome_channels: vec![
188 WelcomeScreenChannel {
189 channel_id: Id::new(123),
190 description: "channel description".to_owned(),
191 emoji_id: None,
192 emoji_name: Some("\u{1f352}".to_owned()),
193 },
194 WelcomeScreenChannel {
195 channel_id: Id::new(456),
196 description: "custom description".to_owned(),
197 emoji_id: Some(Id::new(789)),
198 emoji_name: Some("custom_name".to_owned()),
199 },
200 ],
201 }),
202 }),
203 inviter: Some(User {
204 accent_color: None,
205 avatar: None,
206 avatar_decoration: None,
207 avatar_decoration_data: None,
208 banner: None,
209 bot: false,
210 discriminator: 1,
211 email: None,
212 flags: None,
213 global_name: Some("test".to_owned()),
214 id: Id::new(2),
215 locale: None,
216 mfa_enabled: None,
217 name: "test".to_owned(),
218 premium_type: None,
219 public_flags: None,
220 system: None,
221 verified: None,
222 }),
223 max_age: Some(86_400),
224 max_uses: Some(10),
225 target_type: Some(TargetType::Stream),
226 target_user: Some(User {
227 accent_color: None,
228 avatar: None,
229 avatar_decoration: None,
230 avatar_decoration_data: None,
231 banner: None,
232 bot: false,
233 discriminator: 1,
234 email: None,
235 flags: None,
236 global_name: Some("test".to_owned()),
237 id: Id::new(2),
238 locale: None,
239 mfa_enabled: None,
240 name: "test".to_owned(),
241 premium_type: None,
242 public_flags: None,
243 system: None,
244 verified: None,
245 }),
246 temporary: Some(false),
247 kind: InviteType::Guild,
248 uses: Some(3),
249 };
250
251 serde_test::assert_tokens(
252 &value,
253 &[
254 Token::Struct {
255 name: "Invite",
256 len: 15,
257 },
258 Token::Str("approximate_member_count"),
259 Token::Some,
260 Token::U64(31),
261 Token::Str("approximate_presence_count"),
262 Token::Some,
263 Token::U64(7),
264 Token::Str("channel"),
265 Token::Some,
266 Token::Struct {
267 name: "InviteChannel",
268 len: 2,
269 },
270 Token::Str("id"),
271 Token::NewtypeStruct { name: "Id" },
272 Token::Str("2"),
273 Token::Str("type"),
274 Token::U8(3),
275 Token::StructEnd,
276 Token::Str("code"),
277 Token::Str("uniquecode"),
278 Token::Str("created_at"),
279 Token::Some,
280 Token::Str("2021-08-03T16:08:36.325000+00:00"),
281 Token::Str("expires_at"),
282 Token::Some,
283 Token::Str("2021-08-10T16:08:36.325000+00:00"),
284 Token::Str("guild"),
285 Token::Some,
286 Token::Struct {
287 name: "InviteGuild",
288 len: 11,
289 },
290 Token::Str("banner"),
291 Token::Some,
292 Token::Str(image_hash::BANNER_INPUT),
293 Token::Str("description"),
294 Token::Some,
295 Token::Str("a description"),
296 Token::Str("features"),
297 Token::Seq { len: Some(1) },
298 Token::Str("DISCOVERABLE"),
299 Token::SeqEnd,
300 Token::Str("icon"),
301 Token::Some,
302 Token::Str(image_hash::ICON_INPUT),
303 Token::Str("id"),
304 Token::NewtypeStruct { name: "Id" },
305 Token::Str("1"),
306 Token::Str("name"),
307 Token::Str("guild name"),
308 Token::Str("premium_subscription_count"),
309 Token::None,
310 Token::Str("splash"),
311 Token::Some,
312 Token::Str(image_hash::SPLASH_INPUT),
313 Token::Str("vanity_url_code"),
314 Token::Some,
315 Token::Str("twilight"),
316 Token::Str("verification_level"),
317 Token::U8(2),
318 Token::Str("welcome_screen"),
319 Token::Some,
320 Token::Struct {
321 name: "WelcomeScreen",
322 len: 2,
323 },
324 Token::Str("description"),
325 Token::Some,
326 Token::Str("welcome description"),
327 Token::Str("welcome_channels"),
328 Token::Seq { len: Some(2) },
329 Token::Struct {
330 name: "WelcomeScreenChannel",
331 len: 4,
332 },
333 Token::Str("channel_id"),
334 Token::NewtypeStruct { name: "Id" },
335 Token::Str("123"),
336 Token::Str("description"),
337 Token::Str("channel description"),
338 Token::Str("emoji_id"),
339 Token::None,
340 Token::Str("emoji_name"),
341 Token::Some,
342 Token::Str("\u{1f352}"),
343 Token::StructEnd,
344 Token::Struct {
345 name: "WelcomeScreenChannel",
346 len: 4,
347 },
348 Token::Str("channel_id"),
349 Token::NewtypeStruct { name: "Id" },
350 Token::Str("456"),
351 Token::Str("description"),
352 Token::Str("custom description"),
353 Token::Str("emoji_id"),
354 Token::Some,
355 Token::NewtypeStruct { name: "Id" },
356 Token::Str("789"),
357 Token::Str("emoji_name"),
358 Token::Some,
359 Token::Str("custom_name"),
360 Token::StructEnd,
361 Token::SeqEnd,
362 Token::StructEnd,
363 Token::StructEnd,
364 Token::Str("inviter"),
365 Token::Some,
366 Token::Struct {
367 name: "User",
368 len: 10,
369 },
370 Token::Str("accent_color"),
371 Token::None,
372 Token::Str("avatar"),
373 Token::None,
374 Token::Str("avatar_decoration"),
375 Token::None,
376 Token::Str("avatar_decoration_data"),
377 Token::None,
378 Token::Str("banner"),
379 Token::None,
380 Token::Str("bot"),
381 Token::Bool(false),
382 Token::Str("discriminator"),
383 Token::Str("0001"),
384 Token::Str("global_name"),
385 Token::Some,
386 Token::Str("test"),
387 Token::Str("id"),
388 Token::NewtypeStruct { name: "Id" },
389 Token::Str("2"),
390 Token::Str("username"),
391 Token::Str("test"),
392 Token::StructEnd,
393 Token::Str("max_age"),
394 Token::Some,
395 Token::U64(86_400),
396 Token::Str("max_uses"),
397 Token::Some,
398 Token::U64(10),
399 Token::Str("target_type"),
400 Token::Some,
401 Token::U8(1),
402 Token::Str("target_user"),
403 Token::Some,
404 Token::Struct {
405 name: "User",
406 len: 10,
407 },
408 Token::Str("accent_color"),
409 Token::None,
410 Token::Str("avatar"),
411 Token::None,
412 Token::Str("avatar_decoration"),
413 Token::None,
414 Token::Str("avatar_decoration_data"),
415 Token::None,
416 Token::Str("banner"),
417 Token::None,
418 Token::Str("bot"),
419 Token::Bool(false),
420 Token::Str("discriminator"),
421 Token::Str("0001"),
422 Token::Str("global_name"),
423 Token::Some,
424 Token::Str("test"),
425 Token::Str("id"),
426 Token::NewtypeStruct { name: "Id" },
427 Token::Str("2"),
428 Token::Str("username"),
429 Token::Str("test"),
430 Token::StructEnd,
431 Token::Str("temporary"),
432 Token::Some,
433 Token::Bool(false),
434 Token::Str("type"),
435 Token::U8(0),
436 Token::Str("uses"),
437 Token::Some,
438 Token::U64(3),
439 Token::StructEnd,
440 ],
441 );
442
443 Ok(())
444 }
445}