Skip to main content

twilight_model/guild/template/
mod.rs

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