1mod guild;
2mod role;
3
4pub use guild::TemplateGuild;
5pub use role::TemplateRole;
6
7use crate::{
8 id::{
9 Id,
10 marker::{GuildMarker, UserMarker},
11 },
12 user::User,
13 util::Timestamp,
14};
15use serde::{Deserialize, Serialize};
16
17#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
18pub struct Template {
19 pub code: String,
20 pub created_at: Timestamp,
21 pub creator: User,
23 pub creator_id: Id<UserMarker>,
25 pub description: Option<String>,
26 pub is_dirty: Option<bool>,
28 pub name: String,
29 pub serialized_source_guild: TemplateGuild,
30 pub source_guild_id: Id<GuildMarker>,
31 pub updated_at: Timestamp,
32 pub usage_count: u64,
33}
34
35#[cfg(test)]
36mod tests {
37 use super::{Template, TemplateGuild, TemplateRole};
38 use crate::{
39 channel::{
40 Channel, ChannelType,
41 permission_overwrite::{PermissionOverwrite, PermissionOverwriteType},
42 },
43 guild::{
44 AfkTimeout, DefaultMessageNotificationLevel, ExplicitContentFilter, Permissions,
45 SystemChannelFlags, VerificationLevel,
46 },
47 id::Id,
48 test::image_hash,
49 user::{User, UserFlags},
50 util::datetime::{Timestamp, TimestampParseError},
51 };
52 use serde_test::Token;
53 use std::str::FromStr;
54
55 #[test]
56 #[allow(clippy::too_many_lines)]
57 fn test_template() -> Result<(), TimestampParseError> {
58 let created_at = Timestamp::from_str("2021-04-07T14:55:37+00:00")?;
59 let updated_at = Timestamp::from_str("2021-04-07T14:55:37+00:00")?;
60
61 let raw = format!(
62 r#"{{
63 "code": "code",
64 "created_at": "2021-04-07T14:55:37+00:00",
65 "creator": {{
66 "accent_color": null,
67 "avatar": "{avatar}",
68 "banner": "{banner}",
69 "discriminator": "1111",
70 "global_name": "test",
71 "id": "100",
72 "public_flags": 0,
73 "username": "username"
74 }},
75 "creator_id": "100",
76 "description": "description",
77 "is_dirty": null,
78 "name": "name",
79 "serialized_source_guild": {{
80 "afk_channel_id": null,
81 "afk_timeout": 300,
82 "channels": [
83 {{
84 "bitrate": null,
85 "id": 1,
86 "name": "Text Channels",
87 "nsfw": false,
88 "parent_id": null,
89 "permission_overwrites": [],
90 "position": 0,
91 "topic": null,
92 "type": 4
93 }},
94 {{
95 "bitrate": null,
96 "id": 2,
97 "name": "general",
98 "nsfw": false,
99 "parent_id": 1,
100 "permission_overwrites": [
101 {{
102 "allow": "0",
103 "deny": "2048",
104 "id": 1,
105 "type": 0
106 }},
107 {{
108 "allow": "2048",
109 "deny": "0",
110 "id": 2,
111 "type": 0
112 }}
113 ],
114 "position": 0,
115 "rate_limit_per_user": 0,
116 "topic": null,
117 "type": 0
118 }},
119 {{
120 "bitrate": null,
121 "id": 3,
122 "name": "Voice Channels",
123 "nsfw": false,
124 "parent_id": null,
125 "permission_overwrites": [],
126 "position": 0,
127 "topic": null,
128 "type": 4
129 }},
130 {{
131 "bitrate": 64000,
132 "id": 4,
133 "name": "General",
134 "nsfw": false,
135 "parent_id": 3,
136 "permission_overwrites": [],
137 "position": 0,
138 "topic": null,
139 "type": 2,
140 "user_limit": 0
141 }}
142 ],
143 "default_message_notifications": 0,
144 "description": null,
145 "explicit_content_filter": 0,
146 "icon_hash": null,
147 "name": "server name",
148 "preferred_locale": "en-US",
149 "roles": [
150 {{
151 "color": 0,
152 "hoist": false,
153 "id": 200,
154 "mentionable": false,
155 "name": "@everyone",
156 "permissions": "104320577"
157 }},
158 {{
159 "color": 0,
160 "hoist": false,
161 "id": 1,
162 "mentionable": false,
163 "name": "new role",
164 "permissions": "104320577"
165 }}
166 ],
167 "system_channel_flags": 0,
168 "system_channel_id": 2,
169 "verification_level": 0
170 }},
171 "source_guild_id": "200",
172 "updated_at": "2021-04-07T14:55:37+00:00",
173 "usage_count": 0
174}}"#,
175 avatar = image_hash::AVATAR_INPUT,
176 banner = image_hash::BANNER_INPUT
177 );
178
179 let value = Template {
180 code: "code".into(),
181 created_at,
182 creator: User {
183 accent_color: None,
184 avatar: Some(image_hash::AVATAR),
185 avatar_decoration: None,
186 avatar_decoration_data: None,
187 banner: Some(image_hash::BANNER),
188 bot: false,
189 email: None,
190 discriminator: 1111,
191 flags: None,
192 global_name: Some("test".into()),
193 id: Id::new(100),
194 locale: None,
195 mfa_enabled: None,
196 name: "username".into(),
197 premium_type: None,
198 primary_guild: None,
199 public_flags: Some(UserFlags::empty()),
200 system: None,
201 verified: None,
202 },
203 creator_id: Id::new(100),
204 description: Some("description".into()),
205 is_dirty: None,
206 name: "name".into(),
207 serialized_source_guild: TemplateGuild {
208 afk_channel_id: None,
209 afk_timeout: AfkTimeout::FIVE_MINUTES,
210 channels: Vec::from([
211 Channel {
212 application_id: None,
213 applied_tags: None,
214 available_tags: None,
215 bitrate: None,
216 default_auto_archive_duration: None,
217 default_forum_layout: None,
218 default_reaction_emoji: None,
219 default_sort_order: None,
220 default_thread_rate_limit_per_user: None,
221 flags: None,
222 guild_id: None,
223 icon: None,
224 id: Id::new(1),
225 invitable: None,
226 kind: ChannelType::GuildCategory,
227 last_message_id: None,
228 last_pin_timestamp: None,
229 managed: None,
230 member: None,
231 member_count: None,
232 message_count: None,
233 name: Some("Text Channels".into()),
234 newly_created: None,
235 nsfw: Some(false),
236 owner_id: None,
237 parent_id: None,
238 permission_overwrites: Some(vec![]),
239 position: Some(0),
240 rate_limit_per_user: None,
241 recipients: None,
242 rtc_region: None,
243 thread_metadata: None,
244 topic: None,
245 user_limit: None,
246 video_quality_mode: None,
247 },
248 Channel {
249 application_id: None,
250 applied_tags: None,
251 available_tags: None,
252 bitrate: None,
253 default_auto_archive_duration: None,
254 default_forum_layout: None,
255 default_reaction_emoji: None,
256 default_sort_order: None,
257 default_thread_rate_limit_per_user: None,
258 flags: None,
259 guild_id: None,
260 icon: None,
261 id: Id::new(2),
262 invitable: None,
263 kind: ChannelType::GuildText,
264 last_message_id: None,
265 last_pin_timestamp: None,
266 managed: None,
267 member: None,
268 member_count: None,
269 message_count: None,
270 name: Some("general".into()),
271 newly_created: None,
272 nsfw: Some(false),
273 owner_id: None,
274 parent_id: Some(Id::new(1)),
275 permission_overwrites: Some(vec![
276 PermissionOverwrite {
277 allow: Permissions::from_bits(0).unwrap(),
278 deny: Permissions::from_bits(2048).unwrap(),
279 id: Id::new(1),
280 kind: PermissionOverwriteType::Role,
281 },
282 PermissionOverwrite {
283 allow: Permissions::from_bits(2048).unwrap(),
284 deny: Permissions::from_bits(0).unwrap(),
285 id: Id::new(2),
286 kind: PermissionOverwriteType::Role,
287 },
288 ]),
289 position: Some(0),
290 rate_limit_per_user: Some(0),
291 recipients: None,
292 rtc_region: None,
293 thread_metadata: None,
294 topic: None,
295 user_limit: None,
296 video_quality_mode: None,
297 },
298 Channel {
299 application_id: None,
300 applied_tags: None,
301 available_tags: None,
302 bitrate: None,
303 default_auto_archive_duration: None,
304 default_forum_layout: None,
305 default_reaction_emoji: None,
306 default_sort_order: None,
307 default_thread_rate_limit_per_user: None,
308 flags: None,
309 guild_id: None,
310 icon: None,
311 id: Id::new(3),
312 invitable: None,
313 kind: ChannelType::GuildCategory,
314 last_message_id: None,
315 last_pin_timestamp: None,
316 managed: None,
317 member: None,
318 member_count: None,
319 message_count: None,
320 name: Some("Voice Channels".into()),
321 newly_created: None,
322 nsfw: Some(false),
323 owner_id: None,
324 parent_id: None,
325 permission_overwrites: Some(vec![]),
326 position: Some(0),
327 rate_limit_per_user: None,
328 recipients: None,
329 rtc_region: None,
330 thread_metadata: None,
331 topic: None,
332 user_limit: None,
333 video_quality_mode: None,
334 },
335 Channel {
336 application_id: None,
337 applied_tags: None,
338 available_tags: None,
339 bitrate: Some(64000),
340 default_auto_archive_duration: None,
341 default_forum_layout: None,
342 default_reaction_emoji: None,
343 default_sort_order: None,
344 default_thread_rate_limit_per_user: None,
345 flags: None,
346 guild_id: None,
347 icon: None,
348 id: Id::new(4),
349 invitable: None,
350 kind: ChannelType::GuildVoice,
351 last_message_id: None,
352 last_pin_timestamp: None,
353 managed: None,
354 member: None,
355 member_count: None,
356 message_count: None,
357 name: Some("General".into()),
358 newly_created: None,
359 nsfw: Some(false),
360 owner_id: None,
361 parent_id: Some(Id::new(3)),
362 permission_overwrites: Some(vec![]),
363 position: Some(0),
364 rate_limit_per_user: None,
365 recipients: None,
366 rtc_region: None,
367 thread_metadata: None,
368 topic: None,
369 user_limit: Some(0),
370 video_quality_mode: None,
371 },
372 ]),
373 default_message_notifications: DefaultMessageNotificationLevel::All,
374 description: None,
375 explicit_content_filter: ExplicitContentFilter::None,
376 icon_hash: None,
377 name: "server name".into(),
378 preferred_locale: "en-US".into(),
379 roles: vec![
380 TemplateRole {
381 color: 0,
382 hoist: false,
383 id: Id::new(200),
384 mentionable: false,
385 name: "@everyone".into(),
386 permissions: Permissions::CREATE_INVITE
387 | Permissions::ADD_REACTIONS
388 | Permissions::STREAM
389 | Permissions::VIEW_CHANNEL
390 | Permissions::SEND_MESSAGES
391 | Permissions::EMBED_LINKS
392 | Permissions::ATTACH_FILES
393 | Permissions::READ_MESSAGE_HISTORY
394 | Permissions::MENTION_EVERYONE
395 | Permissions::USE_EXTERNAL_EMOJIS
396 | Permissions::CONNECT
397 | Permissions::SPEAK
398 | Permissions::USE_VAD
399 | Permissions::CHANGE_NICKNAME,
400 tags: None,
401 },
402 TemplateRole {
403 color: 0,
404 hoist: false,
405 id: Id::new(1),
406 mentionable: false,
407 name: "new role".into(),
408 permissions: Permissions::CREATE_INVITE
409 | Permissions::ADD_REACTIONS
410 | Permissions::STREAM
411 | Permissions::VIEW_CHANNEL
412 | Permissions::SEND_MESSAGES
413 | Permissions::EMBED_LINKS
414 | Permissions::ATTACH_FILES
415 | Permissions::READ_MESSAGE_HISTORY
416 | Permissions::MENTION_EVERYONE
417 | Permissions::USE_EXTERNAL_EMOJIS
418 | Permissions::CONNECT
419 | Permissions::SPEAK
420 | Permissions::USE_VAD
421 | Permissions::CHANGE_NICKNAME,
422 tags: None,
423 },
424 ],
425 system_channel_flags: SystemChannelFlags::empty(),
426 system_channel_id: Some(Id::new(2)),
427 verification_level: VerificationLevel::None,
428 },
429 source_guild_id: Id::new(200),
430 updated_at,
431 usage_count: 0,
432 };
433
434 let deserialized = serde_json::from_str::<Template>(&raw).unwrap();
435
436 assert_eq!(deserialized, value);
437
438 serde_test::assert_tokens(
439 &value,
440 &[
441 Token::Struct {
442 name: "Template",
443 len: 11,
444 },
445 Token::Str("code"),
446 Token::Str("code"),
447 Token::Str("created_at"),
448 Token::Str("2021-04-07T14:55:37.000000+00:00"),
449 Token::Str("creator"),
450 Token::Struct {
451 name: "User",
452 len: 11,
453 },
454 Token::Str("accent_color"),
455 Token::None,
456 Token::Str("avatar"),
457 Token::Some,
458 Token::Str(image_hash::AVATAR_INPUT),
459 Token::Str("avatar_decoration"),
460 Token::None,
461 Token::Str("avatar_decoration_data"),
462 Token::None,
463 Token::Str("banner"),
464 Token::Some,
465 Token::Str(image_hash::BANNER_INPUT),
466 Token::Str("bot"),
467 Token::Bool(false),
468 Token::Str("discriminator"),
469 Token::Str("1111"),
470 Token::Str("global_name"),
471 Token::Some,
472 Token::Str("test"),
473 Token::Str("id"),
474 Token::NewtypeStruct { name: "Id" },
475 Token::Str("100"),
476 Token::Str("username"),
477 Token::Str("username"),
478 Token::Str("public_flags"),
479 Token::Some,
480 Token::U64(0),
481 Token::StructEnd,
482 Token::Str("creator_id"),
483 Token::NewtypeStruct { name: "Id" },
484 Token::Str("100"),
485 Token::Str("description"),
486 Token::Some,
487 Token::Str("description"),
488 Token::Str("is_dirty"),
489 Token::None,
490 Token::Str("name"),
491 Token::Str("name"),
492 Token::Str("serialized_source_guild"),
493 Token::Struct {
494 name: "TemplateGuild",
495 len: 13,
496 },
497 Token::Str("afk_channel_id"),
498 Token::None,
499 Token::Str("afk_timeout"),
500 Token::NewtypeStruct { name: "AfkTimeout" },
501 Token::U16(300),
502 Token::Str("channels"),
503 Token::Seq { len: Some(4) },
504 Token::Struct {
505 name: "Channel",
506 len: 6,
507 },
508 Token::Str("id"),
509 Token::NewtypeStruct { name: "Id" },
510 Token::Str("1"),
511 Token::Str("type"),
512 Token::U8(4),
513 Token::Str("name"),
514 Token::Some,
515 Token::Str("Text Channels"),
516 Token::Str("nsfw"),
517 Token::Some,
518 Token::Bool(false),
519 Token::Str("permission_overwrites"),
520 Token::Some,
521 Token::Seq { len: Some(0) },
522 Token::SeqEnd,
523 Token::Str("position"),
524 Token::Some,
525 Token::I32(0),
526 Token::StructEnd,
527 Token::Struct {
528 name: "Channel",
529 len: 8,
530 },
531 Token::Str("id"),
532 Token::NewtypeStruct { name: "Id" },
533 Token::Str("2"),
534 Token::Str("type"),
535 Token::U8(0),
536 Token::Str("name"),
537 Token::Some,
538 Token::Str("general"),
539 Token::Str("nsfw"),
540 Token::Some,
541 Token::Bool(false),
542 Token::Str("parent_id"),
543 Token::Some,
544 Token::NewtypeStruct { name: "Id" },
545 Token::Str("1"),
546 Token::Str("permission_overwrites"),
547 Token::Some,
548 Token::Seq { len: Some(2) },
549 Token::Struct {
550 name: "PermissionOverwrite",
551 len: 4,
552 },
553 Token::Str("allow"),
554 Token::Str("0"),
555 Token::Str("deny"),
556 Token::Str("2048"),
557 Token::Str("id"),
558 Token::NewtypeStruct { name: "Id" },
559 Token::Str("1"),
560 Token::Str("type"),
561 Token::U8(0),
562 Token::StructEnd,
563 Token::Struct {
564 name: "PermissionOverwrite",
565 len: 4,
566 },
567 Token::Str("allow"),
568 Token::Str("2048"),
569 Token::Str("deny"),
570 Token::Str("0"),
571 Token::Str("id"),
572 Token::NewtypeStruct { name: "Id" },
573 Token::Str("2"),
574 Token::Str("type"),
575 Token::U8(0),
576 Token::StructEnd,
577 Token::SeqEnd,
578 Token::Str("position"),
579 Token::Some,
580 Token::I32(0),
581 Token::Str("rate_limit_per_user"),
582 Token::Some,
583 Token::U16(0),
584 Token::StructEnd,
585 Token::Struct {
586 name: "Channel",
587 len: 6,
588 },
589 Token::Str("id"),
590 Token::NewtypeStruct { name: "Id" },
591 Token::Str("3"),
592 Token::Str("type"),
593 Token::U8(4),
594 Token::Str("name"),
595 Token::Some,
596 Token::Str("Voice Channels"),
597 Token::Str("nsfw"),
598 Token::Some,
599 Token::Bool(false),
600 Token::Str("permission_overwrites"),
601 Token::Some,
602 Token::Seq { len: Some(0) },
603 Token::SeqEnd,
604 Token::Str("position"),
605 Token::Some,
606 Token::I32(0),
607 Token::StructEnd,
608 Token::Struct {
609 name: "Channel",
610 len: 9,
611 },
612 Token::Str("bitrate"),
613 Token::Some,
614 Token::U32(64000),
615 Token::Str("id"),
616 Token::NewtypeStruct { name: "Id" },
617 Token::Str("4"),
618 Token::Str("type"),
619 Token::U8(2),
620 Token::Str("name"),
621 Token::Some,
622 Token::Str("General"),
623 Token::Str("nsfw"),
624 Token::Some,
625 Token::Bool(false),
626 Token::Str("parent_id"),
627 Token::Some,
628 Token::NewtypeStruct { name: "Id" },
629 Token::Str("3"),
630 Token::Str("permission_overwrites"),
631 Token::Some,
632 Token::Seq { len: Some(0) },
633 Token::SeqEnd,
634 Token::Str("position"),
635 Token::Some,
636 Token::I32(0),
637 Token::Str("user_limit"),
638 Token::Some,
639 Token::U32(0),
640 Token::StructEnd,
641 Token::SeqEnd,
642 Token::Str("default_message_notifications"),
643 Token::U8(0),
644 Token::Str("description"),
645 Token::None,
646 Token::Str("explicit_content_filter"),
647 Token::U8(0),
648 Token::Str("icon_hash"),
649 Token::None,
650 Token::Str("name"),
651 Token::Str("server name"),
652 Token::Str("preferred_locale"),
653 Token::Str("en-US"),
654 Token::Str("roles"),
655 Token::Seq { len: Some(2) },
656 Token::Struct {
657 name: "TemplateRole",
658 len: 6,
659 },
660 Token::Str("color"),
661 Token::U32(0),
662 Token::Str("hoist"),
663 Token::Bool(false),
664 Token::Str("id"),
665 Token::NewtypeStruct { name: "Id" },
666 Token::Str("200"),
667 Token::Str("mentionable"),
668 Token::Bool(false),
669 Token::Str("name"),
670 Token::Str("@everyone"),
671 Token::Str("permissions"),
672 Token::Str("104320577"),
673 Token::StructEnd,
674 Token::Struct {
675 name: "TemplateRole",
676 len: 6,
677 },
678 Token::Str("color"),
679 Token::U32(0),
680 Token::Str("hoist"),
681 Token::Bool(false),
682 Token::Str("id"),
683 Token::NewtypeStruct { name: "Id" },
684 Token::Str("1"),
685 Token::Str("mentionable"),
686 Token::Bool(false),
687 Token::Str("name"),
688 Token::Str("new role"),
689 Token::Str("permissions"),
690 Token::Str("104320577"),
691 Token::StructEnd,
692 Token::SeqEnd,
693 Token::Str("system_channel_flags"),
694 Token::U64(0),
695 Token::Str("system_channel_id"),
696 Token::Some,
697 Token::NewtypeStruct { name: "Id" },
698 Token::Str("2"),
699 Token::Str("verification_level"),
700 Token::U8(0),
701 Token::StructEnd,
702 Token::Str("source_guild_id"),
703 Token::NewtypeStruct { name: "Id" },
704 Token::Str("200"),
705 Token::Str("updated_at"),
706 Token::Str("2021-04-07T14:55:37.000000+00:00"),
707 Token::Str("usage_count"),
708 Token::U64(0),
709 Token::StructEnd,
710 ],
711 );
712
713 Ok(())
714 }
715}