1mod guild;
2mod role;
3
4pub use guild::TemplateGuild;
5pub use role::TemplateRole;
6
7use crate::{
8 id::{
9 marker::{GuildMarker, UserMarker},
10 Id,
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 permission_overwrite::{PermissionOverwrite, PermissionOverwriteType},
41 Channel, ChannelType,
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 public_flags: Some(UserFlags::empty()),
199 system: None,
200 verified: None,
201 },
202 creator_id: Id::new(100),
203 description: Some("description".into()),
204 is_dirty: None,
205 name: "name".into(),
206 serialized_source_guild: TemplateGuild {
207 afk_channel_id: None,
208 afk_timeout: AfkTimeout::FIVE_MINUTES,
209 channels: Vec::from([
210 Channel {
211 application_id: None,
212 applied_tags: None,
213 available_tags: None,
214 bitrate: None,
215 default_auto_archive_duration: None,
216 default_forum_layout: None,
217 default_reaction_emoji: None,
218 default_sort_order: None,
219 default_thread_rate_limit_per_user: None,
220 flags: None,
221 guild_id: None,
222 icon: None,
223 id: Id::new(1),
224 invitable: None,
225 kind: ChannelType::GuildCategory,
226 last_message_id: None,
227 last_pin_timestamp: None,
228 managed: None,
229 member: None,
230 member_count: None,
231 message_count: None,
232 name: Some("Text Channels".into()),
233 newly_created: None,
234 nsfw: Some(false),
235 owner_id: None,
236 parent_id: None,
237 permission_overwrites: Some(vec![]),
238 position: Some(0),
239 rate_limit_per_user: None,
240 recipients: None,
241 rtc_region: None,
242 thread_metadata: None,
243 topic: None,
244 user_limit: None,
245 video_quality_mode: None,
246 },
247 Channel {
248 application_id: None,
249 applied_tags: None,
250 available_tags: None,
251 bitrate: None,
252 default_auto_archive_duration: None,
253 default_forum_layout: None,
254 default_reaction_emoji: None,
255 default_sort_order: None,
256 default_thread_rate_limit_per_user: None,
257 flags: None,
258 guild_id: None,
259 icon: None,
260 id: Id::new(2),
261 invitable: None,
262 kind: ChannelType::GuildText,
263 last_message_id: None,
264 last_pin_timestamp: None,
265 managed: None,
266 member: None,
267 member_count: None,
268 message_count: None,
269 name: Some("general".into()),
270 newly_created: None,
271 nsfw: Some(false),
272 owner_id: None,
273 parent_id: Some(Id::new(1)),
274 permission_overwrites: Some(vec![
275 PermissionOverwrite {
276 allow: Permissions::from_bits(0).unwrap(),
277 deny: Permissions::from_bits(2048).unwrap(),
278 id: Id::new(1),
279 kind: PermissionOverwriteType::Role,
280 },
281 PermissionOverwrite {
282 allow: Permissions::from_bits(2048).unwrap(),
283 deny: Permissions::from_bits(0).unwrap(),
284 id: Id::new(2),
285 kind: PermissionOverwriteType::Role,
286 },
287 ]),
288 position: Some(0),
289 rate_limit_per_user: Some(0),
290 recipients: None,
291 rtc_region: None,
292 thread_metadata: None,
293 topic: None,
294 user_limit: None,
295 video_quality_mode: None,
296 },
297 Channel {
298 application_id: None,
299 applied_tags: None,
300 available_tags: None,
301 bitrate: None,
302 default_auto_archive_duration: None,
303 default_forum_layout: None,
304 default_reaction_emoji: None,
305 default_sort_order: None,
306 default_thread_rate_limit_per_user: None,
307 flags: None,
308 guild_id: None,
309 icon: None,
310 id: Id::new(3),
311 invitable: None,
312 kind: ChannelType::GuildCategory,
313 last_message_id: None,
314 last_pin_timestamp: None,
315 managed: None,
316 member: None,
317 member_count: None,
318 message_count: None,
319 name: Some("Voice Channels".into()),
320 newly_created: None,
321 nsfw: Some(false),
322 owner_id: None,
323 parent_id: None,
324 permission_overwrites: Some(vec![]),
325 position: Some(0),
326 rate_limit_per_user: None,
327 recipients: None,
328 rtc_region: None,
329 thread_metadata: None,
330 topic: None,
331 user_limit: None,
332 video_quality_mode: None,
333 },
334 Channel {
335 application_id: None,
336 applied_tags: None,
337 available_tags: None,
338 bitrate: Some(64000),
339 default_auto_archive_duration: None,
340 default_forum_layout: None,
341 default_reaction_emoji: None,
342 default_sort_order: None,
343 default_thread_rate_limit_per_user: None,
344 flags: None,
345 guild_id: None,
346 icon: None,
347 id: Id::new(4),
348 invitable: None,
349 kind: ChannelType::GuildVoice,
350 last_message_id: None,
351 last_pin_timestamp: None,
352 managed: None,
353 member: None,
354 member_count: None,
355 message_count: None,
356 name: Some("General".into()),
357 newly_created: None,
358 nsfw: Some(false),
359 owner_id: None,
360 parent_id: Some(Id::new(3)),
361 permission_overwrites: Some(vec![]),
362 position: Some(0),
363 rate_limit_per_user: None,
364 recipients: None,
365 rtc_region: None,
366 thread_metadata: None,
367 topic: None,
368 user_limit: Some(0),
369 video_quality_mode: None,
370 },
371 ]),
372 default_message_notifications: DefaultMessageNotificationLevel::All,
373 description: None,
374 explicit_content_filter: ExplicitContentFilter::None,
375 icon_hash: None,
376 name: "server name".into(),
377 preferred_locale: "en-US".into(),
378 roles: vec![
379 TemplateRole {
380 color: 0,
381 hoist: false,
382 id: Id::new(200),
383 mentionable: false,
384 name: "@everyone".into(),
385 permissions: Permissions::CREATE_INVITE
386 | Permissions::ADD_REACTIONS
387 | Permissions::STREAM
388 | Permissions::VIEW_CHANNEL
389 | Permissions::SEND_MESSAGES
390 | Permissions::EMBED_LINKS
391 | Permissions::ATTACH_FILES
392 | Permissions::READ_MESSAGE_HISTORY
393 | Permissions::MENTION_EVERYONE
394 | Permissions::USE_EXTERNAL_EMOJIS
395 | Permissions::CONNECT
396 | Permissions::SPEAK
397 | Permissions::USE_VAD
398 | Permissions::CHANGE_NICKNAME,
399 tags: None,
400 },
401 TemplateRole {
402 color: 0,
403 hoist: false,
404 id: Id::new(1),
405 mentionable: false,
406 name: "new role".into(),
407 permissions: Permissions::CREATE_INVITE
408 | Permissions::ADD_REACTIONS
409 | Permissions::STREAM
410 | Permissions::VIEW_CHANNEL
411 | Permissions::SEND_MESSAGES
412 | Permissions::EMBED_LINKS
413 | Permissions::ATTACH_FILES
414 | Permissions::READ_MESSAGE_HISTORY
415 | Permissions::MENTION_EVERYONE
416 | Permissions::USE_EXTERNAL_EMOJIS
417 | Permissions::CONNECT
418 | Permissions::SPEAK
419 | Permissions::USE_VAD
420 | Permissions::CHANGE_NICKNAME,
421 tags: None,
422 },
423 ],
424 system_channel_flags: SystemChannelFlags::empty(),
425 system_channel_id: Some(Id::new(2)),
426 verification_level: VerificationLevel::None,
427 },
428 source_guild_id: Id::new(200),
429 updated_at,
430 usage_count: 0,
431 };
432
433 let deserialized = serde_json::from_str::<Template>(&raw).unwrap();
434
435 assert_eq!(deserialized, value);
436
437 serde_test::assert_tokens(
438 &value,
439 &[
440 Token::Struct {
441 name: "Template",
442 len: 11,
443 },
444 Token::Str("code"),
445 Token::Str("code"),
446 Token::Str("created_at"),
447 Token::Str("2021-04-07T14:55:37.000000+00:00"),
448 Token::Str("creator"),
449 Token::Struct {
450 name: "User",
451 len: 11,
452 },
453 Token::Str("accent_color"),
454 Token::None,
455 Token::Str("avatar"),
456 Token::Some,
457 Token::Str(image_hash::AVATAR_INPUT),
458 Token::Str("avatar_decoration"),
459 Token::None,
460 Token::Str("avatar_decoration_data"),
461 Token::None,
462 Token::Str("banner"),
463 Token::Some,
464 Token::Str(image_hash::BANNER_INPUT),
465 Token::Str("bot"),
466 Token::Bool(false),
467 Token::Str("discriminator"),
468 Token::Str("1111"),
469 Token::Str("global_name"),
470 Token::Some,
471 Token::Str("test"),
472 Token::Str("id"),
473 Token::NewtypeStruct { name: "Id" },
474 Token::Str("100"),
475 Token::Str("username"),
476 Token::Str("username"),
477 Token::Str("public_flags"),
478 Token::Some,
479 Token::U64(0),
480 Token::StructEnd,
481 Token::Str("creator_id"),
482 Token::NewtypeStruct { name: "Id" },
483 Token::Str("100"),
484 Token::Str("description"),
485 Token::Some,
486 Token::Str("description"),
487 Token::Str("is_dirty"),
488 Token::None,
489 Token::Str("name"),
490 Token::Str("name"),
491 Token::Str("serialized_source_guild"),
492 Token::Struct {
493 name: "TemplateGuild",
494 len: 13,
495 },
496 Token::Str("afk_channel_id"),
497 Token::None,
498 Token::Str("afk_timeout"),
499 Token::NewtypeStruct { name: "AfkTimeout" },
500 Token::U16(300),
501 Token::Str("channels"),
502 Token::Seq { len: Some(4) },
503 Token::Struct {
504 name: "Channel",
505 len: 6,
506 },
507 Token::Str("id"),
508 Token::NewtypeStruct { name: "Id" },
509 Token::Str("1"),
510 Token::Str("type"),
511 Token::U8(4),
512 Token::Str("name"),
513 Token::Some,
514 Token::Str("Text Channels"),
515 Token::Str("nsfw"),
516 Token::Some,
517 Token::Bool(false),
518 Token::Str("permission_overwrites"),
519 Token::Some,
520 Token::Seq { len: Some(0) },
521 Token::SeqEnd,
522 Token::Str("position"),
523 Token::Some,
524 Token::I32(0),
525 Token::StructEnd,
526 Token::Struct {
527 name: "Channel",
528 len: 8,
529 },
530 Token::Str("id"),
531 Token::NewtypeStruct { name: "Id" },
532 Token::Str("2"),
533 Token::Str("type"),
534 Token::U8(0),
535 Token::Str("name"),
536 Token::Some,
537 Token::Str("general"),
538 Token::Str("nsfw"),
539 Token::Some,
540 Token::Bool(false),
541 Token::Str("parent_id"),
542 Token::Some,
543 Token::NewtypeStruct { name: "Id" },
544 Token::Str("1"),
545 Token::Str("permission_overwrites"),
546 Token::Some,
547 Token::Seq { len: Some(2) },
548 Token::Struct {
549 name: "PermissionOverwrite",
550 len: 4,
551 },
552 Token::Str("allow"),
553 Token::Str("0"),
554 Token::Str("deny"),
555 Token::Str("2048"),
556 Token::Str("id"),
557 Token::NewtypeStruct { name: "Id" },
558 Token::Str("1"),
559 Token::Str("type"),
560 Token::U8(0),
561 Token::StructEnd,
562 Token::Struct {
563 name: "PermissionOverwrite",
564 len: 4,
565 },
566 Token::Str("allow"),
567 Token::Str("2048"),
568 Token::Str("deny"),
569 Token::Str("0"),
570 Token::Str("id"),
571 Token::NewtypeStruct { name: "Id" },
572 Token::Str("2"),
573 Token::Str("type"),
574 Token::U8(0),
575 Token::StructEnd,
576 Token::SeqEnd,
577 Token::Str("position"),
578 Token::Some,
579 Token::I32(0),
580 Token::Str("rate_limit_per_user"),
581 Token::Some,
582 Token::U16(0),
583 Token::StructEnd,
584 Token::Struct {
585 name: "Channel",
586 len: 6,
587 },
588 Token::Str("id"),
589 Token::NewtypeStruct { name: "Id" },
590 Token::Str("3"),
591 Token::Str("type"),
592 Token::U8(4),
593 Token::Str("name"),
594 Token::Some,
595 Token::Str("Voice Channels"),
596 Token::Str("nsfw"),
597 Token::Some,
598 Token::Bool(false),
599 Token::Str("permission_overwrites"),
600 Token::Some,
601 Token::Seq { len: Some(0) },
602 Token::SeqEnd,
603 Token::Str("position"),
604 Token::Some,
605 Token::I32(0),
606 Token::StructEnd,
607 Token::Struct {
608 name: "Channel",
609 len: 9,
610 },
611 Token::Str("bitrate"),
612 Token::Some,
613 Token::U32(64000),
614 Token::Str("id"),
615 Token::NewtypeStruct { name: "Id" },
616 Token::Str("4"),
617 Token::Str("type"),
618 Token::U8(2),
619 Token::Str("name"),
620 Token::Some,
621 Token::Str("General"),
622 Token::Str("nsfw"),
623 Token::Some,
624 Token::Bool(false),
625 Token::Str("parent_id"),
626 Token::Some,
627 Token::NewtypeStruct { name: "Id" },
628 Token::Str("3"),
629 Token::Str("permission_overwrites"),
630 Token::Some,
631 Token::Seq { len: Some(0) },
632 Token::SeqEnd,
633 Token::Str("position"),
634 Token::Some,
635 Token::I32(0),
636 Token::Str("user_limit"),
637 Token::Some,
638 Token::U32(0),
639 Token::StructEnd,
640 Token::SeqEnd,
641 Token::Str("default_message_notifications"),
642 Token::U8(0),
643 Token::Str("description"),
644 Token::None,
645 Token::Str("explicit_content_filter"),
646 Token::U8(0),
647 Token::Str("icon_hash"),
648 Token::None,
649 Token::Str("name"),
650 Token::Str("server name"),
651 Token::Str("preferred_locale"),
652 Token::Str("en-US"),
653 Token::Str("roles"),
654 Token::Seq { len: Some(2) },
655 Token::Struct {
656 name: "TemplateRole",
657 len: 6,
658 },
659 Token::Str("color"),
660 Token::U32(0),
661 Token::Str("hoist"),
662 Token::Bool(false),
663 Token::Str("id"),
664 Token::NewtypeStruct { name: "Id" },
665 Token::Str("200"),
666 Token::Str("mentionable"),
667 Token::Bool(false),
668 Token::Str("name"),
669 Token::Str("@everyone"),
670 Token::Str("permissions"),
671 Token::Str("104320577"),
672 Token::StructEnd,
673 Token::Struct {
674 name: "TemplateRole",
675 len: 6,
676 },
677 Token::Str("color"),
678 Token::U32(0),
679 Token::Str("hoist"),
680 Token::Bool(false),
681 Token::Str("id"),
682 Token::NewtypeStruct { name: "Id" },
683 Token::Str("1"),
684 Token::Str("mentionable"),
685 Token::Bool(false),
686 Token::Str("name"),
687 Token::Str("new role"),
688 Token::Str("permissions"),
689 Token::Str("104320577"),
690 Token::StructEnd,
691 Token::SeqEnd,
692 Token::Str("system_channel_flags"),
693 Token::U64(0),
694 Token::Str("system_channel_id"),
695 Token::Some,
696 Token::NewtypeStruct { name: "Id" },
697 Token::Str("2"),
698 Token::Str("verification_level"),
699 Token::U8(0),
700 Token::StructEnd,
701 Token::Str("source_guild_id"),
702 Token::NewtypeStruct { name: "Id" },
703 Token::Str("200"),
704 Token::Str("updated_at"),
705 Token::Str("2021-04-07T14:55:37.000000+00:00"),
706 Token::Str("usage_count"),
707 Token::U64(0),
708 Token::StructEnd,
709 ],
710 );
711
712 Ok(())
713 }
714}