twilight_model/guild/
mod.rs

1//! Group of [`Channel`]s and [`User`]s with additional moderation options.
2//!
3//! [`Guild`]s allow, for example, assigning [`Role`]s to [`Member`]s to limit
4//! their [`Permissions`] globally, or per [`Channel`].
5//!
6//! [`User`]: super::user::User
7
8pub mod audit_log;
9pub mod auto_moderation;
10pub mod invite;
11pub mod onboarding;
12pub mod scheduled_event;
13pub mod template;
14pub mod widget;
15
16mod afk_timeout;
17mod ban;
18mod default_message_notification_level;
19mod emoji;
20mod explicit_content_filter;
21mod feature;
22mod info;
23mod integration;
24mod integration_account;
25mod integration_application;
26mod integration_expire_behavior;
27mod integration_type;
28mod member;
29mod member_flags;
30mod mfa_level;
31mod nsfw_level;
32mod partial_guild;
33mod partial_member;
34mod permissions;
35mod premium_tier;
36mod preview;
37mod prune;
38mod role;
39mod role_colors;
40mod role_flags;
41mod role_position;
42mod role_tags;
43mod system_channel_flags;
44mod unavailable_guild;
45mod vanity_url;
46mod verification_level;
47
48pub use self::nsfw_level::NSFWLevel;
49pub use self::permissions::Permissions;
50pub use self::{
51    afk_timeout::AfkTimeout, ban::Ban,
52    default_message_notification_level::DefaultMessageNotificationLevel, emoji::Emoji,
53    explicit_content_filter::ExplicitContentFilter, feature::GuildFeature, info::GuildInfo,
54    integration::GuildIntegration, integration_account::IntegrationAccount,
55    integration_application::IntegrationApplication,
56    integration_expire_behavior::IntegrationExpireBehavior, integration_type::GuildIntegrationType,
57    member::Member, member_flags::MemberFlags, mfa_level::MfaLevel, partial_guild::PartialGuild,
58    partial_member::PartialMember, premium_tier::PremiumTier, preview::GuildPreview,
59    prune::GuildPrune, role::Role, role_colors::RoleColors, role_flags::RoleFlags,
60    role_position::RolePosition, role_tags::RoleTags, system_channel_flags::SystemChannelFlags,
61    unavailable_guild::UnavailableGuild, vanity_url::VanityUrl,
62    verification_level::VerificationLevel, widget::GuildWidget,
63};
64
65use super::gateway::presence::PresenceListDeserializer;
66use crate::{
67    channel::{Channel, StageInstance, message::sticker::Sticker},
68    gateway::presence::Presence,
69    id::{
70        Id,
71        marker::{ApplicationMarker, ChannelMarker, GuildMarker, UserMarker},
72    },
73    util::{ImageHash, Timestamp},
74    voice::VoiceState,
75};
76use serde::{
77    Deserialize, Serialize,
78    de::{Deserializer, Error as DeError, IgnoredAny, MapAccess, Visitor},
79};
80use std::fmt::{Formatter, Result as FmtResult};
81
82#[derive(Clone, Debug, Eq, PartialEq, Serialize, Hash)]
83pub struct Guild {
84    pub afk_channel_id: Option<Id<ChannelMarker>>,
85    pub afk_timeout: AfkTimeout,
86    pub application_id: Option<Id<ApplicationMarker>>,
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub approximate_member_count: Option<u64>,
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub approximate_presence_count: Option<u64>,
91    pub banner: Option<ImageHash>,
92    #[serde(default)]
93    pub channels: Vec<Channel>,
94    pub default_message_notifications: DefaultMessageNotificationLevel,
95    pub description: Option<String>,
96    pub discovery_splash: Option<ImageHash>,
97    pub emojis: Vec<Emoji>,
98    pub explicit_content_filter: ExplicitContentFilter,
99    /// Enabled guild features
100    pub features: Vec<GuildFeature>,
101    /// Scheduled guild events.
102    #[serde(default, skip_serializing_if = "Vec::is_empty")]
103    pub guild_scheduled_events: Vec<scheduled_event::GuildScheduledEvent>,
104    pub icon: Option<ImageHash>,
105    pub id: Id<GuildMarker>,
106    #[serde(skip_serializing_if = "Option::is_none")]
107    pub joined_at: Option<Timestamp>,
108    pub large: bool,
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub max_members: Option<u64>,
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub max_presences: Option<u64>,
113    /// Maximum number of users in a stage video channel.
114    #[serde(skip_serializing_if = "Option::is_none")]
115    pub max_stage_video_channel_users: Option<u64>,
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub max_video_channel_users: Option<u64>,
118    #[serde(skip_serializing_if = "Option::is_none")]
119    pub member_count: Option<u64>,
120    #[serde(default)]
121    pub members: Vec<Member>,
122    pub mfa_level: MfaLevel,
123    pub name: String,
124    pub nsfw_level: NSFWLevel,
125    pub owner_id: Id<UserMarker>,
126    #[serde(skip_serializing_if = "Option::is_none")]
127    pub owner: Option<bool>,
128    #[serde(skip_serializing_if = "Option::is_none")]
129    pub permissions: Option<Permissions>,
130    pub preferred_locale: String,
131    /// Whether the premium progress bar is enabled in the guild.
132    pub premium_progress_bar_enabled: bool,
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub premium_subscription_count: Option<u64>,
135    #[serde(default)]
136    pub premium_tier: PremiumTier,
137    #[serde(default)]
138    pub presences: Vec<Presence>,
139    /// ID of the where moderators of Community guilds receive notices from
140    /// Discord.
141    pub public_updates_channel_id: Option<Id<ChannelMarker>>,
142    pub roles: Vec<Role>,
143    pub rules_channel_id: Option<Id<ChannelMarker>>,
144    /// The ID of the channel where admins and moderators of Community guilds receive safety alerts from Discord.
145    #[serde(skip_serializing_if = "Option::is_none")]
146    pub safety_alerts_channel_id: Option<Id<ChannelMarker>>,
147    pub splash: Option<ImageHash>,
148    #[serde(skip_serializing_if = "Vec::is_empty")]
149    pub stage_instances: Vec<StageInstance>,
150    #[serde(skip_serializing_if = "Vec::is_empty")]
151    pub stickers: Vec<Sticker>,
152    pub system_channel_flags: SystemChannelFlags,
153    pub system_channel_id: Option<Id<ChannelMarker>>,
154    #[serde(default)]
155    pub threads: Vec<Channel>,
156    /// If the guild is unavailable.
157    ///
158    /// # Note:
159    ///
160    /// While it is not documented and may change in the future if
161    /// this field is not sent it is because the user joined a new
162    /// guild.
163    #[serde(skip_serializing_if = "Option::is_none")]
164    pub unavailable: Option<bool>,
165    pub vanity_url_code: Option<String>,
166    pub verification_level: VerificationLevel,
167    #[serde(default)]
168    pub voice_states: Vec<VoiceState>,
169    #[serde(skip_serializing_if = "Option::is_none")]
170    pub widget_channel_id: Option<Id<ChannelMarker>>,
171    #[serde(skip_serializing_if = "Option::is_none")]
172    pub widget_enabled: Option<bool>,
173}
174
175impl<'de> Deserialize<'de> for Guild {
176    #[allow(clippy::too_many_lines)]
177    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
178        #[derive(Debug, Deserialize)]
179        #[serde(field_identifier, rename_all = "snake_case")]
180        enum Field {
181            AfkChannelId,
182            AfkTimeout,
183            ApplicationId,
184            ApproximateMemberCount,
185            ApproximatePresenceCount,
186            Banner,
187            Channels,
188            DefaultMessageNotifications,
189            Description,
190            DiscoverySplash,
191            Emojis,
192            ExplicitContentFilter,
193            Features,
194            GuildScheduledEvents,
195            Icon,
196            Id,
197            JoinedAt,
198            Large,
199            MaxMembers,
200            MaxPresences,
201            MaxStageVideoChannelUsers,
202            MaxVideoChannelUsers,
203            MemberCount,
204            Members,
205            MfaLevel,
206            Name,
207            NsfwLevel,
208            OwnerId,
209            Owner,
210            Permissions,
211            PreferredLocale,
212            PremiumProgressBarEnabled,
213            PremiumSubscriptionCount,
214            PremiumTier,
215            Presences,
216            PublicUpdatesChannelId,
217            Roles,
218            SafetyAlertsChannelId,
219            Splash,
220            StageInstances,
221            Stickers,
222            SystemChannelFlags,
223            SystemChannelId,
224            RulesChannelId,
225            Threads,
226            Unavailable,
227            VerificationLevel,
228            VoiceStates,
229            VanityUrlCode,
230            WidgetChannelId,
231            WidgetEnabled,
232        }
233
234        struct GuildVisitor;
235
236        impl<'de> Visitor<'de> for GuildVisitor {
237            type Value = Guild;
238
239            fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
240                f.write_str("struct Guild")
241            }
242
243            #[allow(clippy::too_many_lines)]
244            fn visit_map<V: MapAccess<'de>>(self, mut map: V) -> Result<Self::Value, V::Error> {
245                let mut afk_channel_id = None::<Option<_>>;
246                let mut afk_timeout = None;
247                let mut application_id = None::<Option<_>>;
248                let mut approximate_member_count = None::<Option<_>>;
249                let mut approximate_presence_count = None::<Option<_>>;
250                let mut banner = None::<Option<_>>;
251                let mut channels = None::<Vec<Channel>>;
252                let mut default_message_notifications = None;
253                let mut description = None::<Option<_>>;
254                let mut discovery_splash = None::<Option<_>>;
255                let mut emojis = None;
256                let mut explicit_content_filter = None;
257                let mut features = None;
258                let mut guild_scheduled_events = None;
259                let mut icon = None::<Option<_>>;
260                let mut id = None;
261                let mut joined_at = None::<Option<_>>;
262                let mut large = None;
263                let mut max_members = None::<Option<_>>;
264                let mut max_presences = None::<Option<_>>;
265                let mut max_stage_video_channel_users = None::<Option<_>>;
266                let mut max_video_channel_users = None::<Option<_>>;
267                let mut member_count = None::<Option<_>>;
268                let mut members = None;
269                let mut mfa_level = None;
270                let mut name = None;
271                let mut nsfw_level = None;
272                let mut owner = None::<Option<_>>;
273                let mut owner_id = None;
274                let mut permissions = None::<Option<_>>;
275                let mut preferred_locale = None;
276                let mut premium_progress_bar_enabled = None;
277                let mut premium_subscription_count = None::<Option<_>>;
278                let mut premium_tier = None;
279                let mut presences = None;
280                let mut public_updates_channel_id = None::<Option<_>>;
281                let mut roles = None;
282                let mut rules_channel_id = None::<Option<_>>;
283                let mut safety_alerts_channel_id = None::<Option<_>>;
284                let mut splash = None::<Option<_>>;
285                let mut stage_instances = None::<Vec<StageInstance>>;
286                let mut stickers = None::<Vec<Sticker>>;
287                let mut system_channel_flags = None;
288                let mut system_channel_id = None::<Option<_>>;
289                let mut threads = None::<Vec<Channel>>;
290                let mut unavailable = None;
291                let mut vanity_url_code = None::<Option<_>>;
292                let mut verification_level = None;
293                let mut voice_states = None::<Vec<VoiceState>>;
294                let mut widget_channel_id = None::<Option<_>>;
295                let mut widget_enabled = None::<Option<_>>;
296
297                loop {
298                    let key = match map.next_key() {
299                        Ok(Some(key)) => key,
300                        Ok(None) => break,
301                        Err(_) => {
302                            map.next_value::<IgnoredAny>()?;
303
304                            continue;
305                        }
306                    };
307
308                    match key {
309                        Field::AfkChannelId => {
310                            if afk_channel_id.is_some() {
311                                return Err(DeError::duplicate_field("afk_channel_id"));
312                            }
313
314                            afk_channel_id = Some(map.next_value()?);
315                        }
316                        Field::AfkTimeout => {
317                            if afk_timeout.is_some() {
318                                return Err(DeError::duplicate_field("afk_timeout"));
319                            }
320
321                            afk_timeout = Some(map.next_value()?);
322                        }
323                        Field::ApplicationId => {
324                            if application_id.is_some() {
325                                return Err(DeError::duplicate_field("application_id"));
326                            }
327
328                            application_id = Some(map.next_value()?);
329                        }
330                        Field::ApproximateMemberCount => {
331                            if approximate_member_count.is_some() {
332                                return Err(DeError::duplicate_field("approximate_member_count"));
333                            }
334
335                            approximate_member_count = Some(map.next_value()?);
336                        }
337                        Field::ApproximatePresenceCount => {
338                            if approximate_presence_count.is_some() {
339                                return Err(DeError::duplicate_field("approximate_presence_count"));
340                            }
341
342                            approximate_presence_count = Some(map.next_value()?);
343                        }
344                        Field::Banner => {
345                            if banner.is_some() {
346                                return Err(DeError::duplicate_field("banner"));
347                            }
348
349                            banner = Some(map.next_value()?);
350                        }
351                        Field::Channels => {
352                            if channels.is_some() {
353                                return Err(DeError::duplicate_field("channels"));
354                            }
355
356                            channels = Some(map.next_value()?);
357                        }
358                        Field::DefaultMessageNotifications => {
359                            if default_message_notifications.is_some() {
360                                return Err(DeError::duplicate_field(
361                                    "default_message_notifications",
362                                ));
363                            }
364
365                            default_message_notifications = Some(map.next_value()?);
366                        }
367                        Field::Description => {
368                            if description.is_some() {
369                                return Err(DeError::duplicate_field("description"));
370                            }
371
372                            description = Some(map.next_value()?);
373                        }
374                        Field::DiscoverySplash => {
375                            if discovery_splash.is_some() {
376                                return Err(DeError::duplicate_field("discovery_splash"));
377                            }
378
379                            discovery_splash = Some(map.next_value()?);
380                        }
381                        Field::Emojis => {
382                            if emojis.is_some() {
383                                return Err(DeError::duplicate_field("emojis"));
384                            }
385
386                            emojis = Some(map.next_value()?);
387                        }
388                        Field::ExplicitContentFilter => {
389                            if explicit_content_filter.is_some() {
390                                return Err(DeError::duplicate_field("explicit_content_filter"));
391                            }
392
393                            explicit_content_filter = Some(map.next_value()?);
394                        }
395                        Field::Features => {
396                            if features.is_some() {
397                                return Err(DeError::duplicate_field("features"));
398                            }
399
400                            features = Some(map.next_value()?);
401                        }
402                        Field::GuildScheduledEvents => {
403                            if guild_scheduled_events.is_some() {
404                                return Err(DeError::duplicate_field("guild_scheduled_events"));
405                            }
406
407                            guild_scheduled_events = Some(map.next_value()?);
408                        }
409                        Field::Icon => {
410                            if icon.is_some() {
411                                return Err(DeError::duplicate_field("icon"));
412                            }
413
414                            icon = Some(map.next_value()?);
415                        }
416                        Field::Id => {
417                            if id.is_some() {
418                                return Err(DeError::duplicate_field("id"));
419                            }
420
421                            id = Some(map.next_value()?);
422                        }
423                        Field::JoinedAt => {
424                            if joined_at.is_some() {
425                                return Err(DeError::duplicate_field("joined_at"));
426                            }
427
428                            joined_at = Some(map.next_value()?);
429                        }
430                        Field::Large => {
431                            if large.is_some() {
432                                return Err(DeError::duplicate_field("large"));
433                            }
434
435                            large = Some(map.next_value()?);
436                        }
437                        Field::MaxMembers => {
438                            if max_members.is_some() {
439                                return Err(DeError::duplicate_field("max_members"));
440                            }
441
442                            max_members = Some(map.next_value()?);
443                        }
444                        Field::MaxPresences => {
445                            if max_presences.is_some() {
446                                return Err(DeError::duplicate_field("max_presences"));
447                            }
448
449                            max_presences = Some(map.next_value()?);
450                        }
451                        Field::MaxStageVideoChannelUsers => {
452                            if max_stage_video_channel_users.is_some() {
453                                return Err(DeError::duplicate_field(
454                                    "max_stage_video_channel_users",
455                                ));
456                            }
457
458                            max_stage_video_channel_users = Some(map.next_value()?);
459                        }
460                        Field::MaxVideoChannelUsers => {
461                            if max_video_channel_users.is_some() {
462                                return Err(DeError::duplicate_field("max_video_channel_users"));
463                            }
464
465                            max_video_channel_users = Some(map.next_value()?);
466                        }
467                        Field::MemberCount => {
468                            if member_count.is_some() {
469                                return Err(DeError::duplicate_field("member_count"));
470                            }
471
472                            member_count = Some(map.next_value()?);
473                        }
474                        Field::Members => {
475                            if members.is_some() {
476                                return Err(DeError::duplicate_field("members"));
477                            }
478
479                            members = Some(map.next_value()?);
480                        }
481                        Field::MfaLevel => {
482                            if mfa_level.is_some() {
483                                return Err(DeError::duplicate_field("mfa_level"));
484                            }
485
486                            mfa_level = Some(map.next_value()?);
487                        }
488                        Field::Name => {
489                            if name.is_some() {
490                                return Err(DeError::duplicate_field("name"));
491                            }
492
493                            name = Some(map.next_value()?);
494                        }
495                        Field::NsfwLevel => {
496                            if nsfw_level.is_some() {
497                                return Err(DeError::duplicate_field("nsfw_level"));
498                            }
499
500                            nsfw_level = Some(map.next_value()?);
501                        }
502                        Field::Owner => {
503                            if owner.is_some() {
504                                return Err(DeError::duplicate_field("owner"));
505                            }
506
507                            owner = Some(map.next_value()?);
508                        }
509                        Field::OwnerId => {
510                            if owner_id.is_some() {
511                                return Err(DeError::duplicate_field("owner_id"));
512                            }
513
514                            owner_id = Some(map.next_value()?);
515                        }
516                        Field::Permissions => {
517                            if permissions.is_some() {
518                                return Err(DeError::duplicate_field("permissions"));
519                            }
520
521                            permissions = Some(map.next_value()?);
522                        }
523                        Field::PreferredLocale => {
524                            if preferred_locale.is_some() {
525                                return Err(DeError::duplicate_field("preferred_locale"));
526                            }
527
528                            preferred_locale = Some(map.next_value()?);
529                        }
530                        Field::PremiumProgressBarEnabled => {
531                            if premium_progress_bar_enabled.is_some() {
532                                return Err(DeError::duplicate_field(
533                                    "premium_progress_bar_enabled",
534                                ));
535                            }
536
537                            premium_progress_bar_enabled = Some(map.next_value()?);
538                        }
539                        Field::PremiumSubscriptionCount => {
540                            if premium_subscription_count.is_some() {
541                                return Err(DeError::duplicate_field("premium_subscription_count"));
542                            }
543
544                            premium_subscription_count = Some(map.next_value()?);
545                        }
546                        Field::PremiumTier => {
547                            if premium_tier.is_some() {
548                                return Err(DeError::duplicate_field("premium_tier"));
549                            }
550
551                            premium_tier = Some(map.next_value()?);
552                        }
553                        Field::Presences => {
554                            if presences.is_some() {
555                                return Err(DeError::duplicate_field("presences"));
556                            }
557
558                            let deserializer = PresenceListDeserializer::new(Id::new(1));
559
560                            presences = Some(map.next_value_seed(deserializer)?);
561                        }
562                        Field::PublicUpdatesChannelId => {
563                            if public_updates_channel_id.is_some() {
564                                return Err(DeError::duplicate_field("public_updates_channel_id"));
565                            }
566
567                            public_updates_channel_id = Some(map.next_value()?);
568                        }
569                        Field::Roles => {
570                            if roles.is_some() {
571                                return Err(DeError::duplicate_field("roles"));
572                            }
573
574                            roles = Some(map.next_value()?);
575                        }
576                        Field::SafetyAlertsChannelId => {
577                            if safety_alerts_channel_id.is_some() {
578                                return Err(DeError::duplicate_field("safety_alerts_channel_id"));
579                            }
580
581                            safety_alerts_channel_id = Some(map.next_value()?);
582                        }
583                        Field::Splash => {
584                            if splash.is_some() {
585                                return Err(DeError::duplicate_field("splash"));
586                            }
587
588                            splash = Some(map.next_value()?);
589                        }
590                        Field::StageInstances => {
591                            if stage_instances.is_some() {
592                                return Err(DeError::duplicate_field("stage_instances"));
593                            }
594
595                            stage_instances = Some(map.next_value()?);
596                        }
597                        Field::Stickers => {
598                            if stickers.is_some() {
599                                return Err(DeError::duplicate_field("stickers"));
600                            }
601
602                            stickers = Some(map.next_value()?);
603                        }
604                        Field::SystemChannelId => {
605                            if system_channel_id.is_some() {
606                                return Err(DeError::duplicate_field("system_channel_id"));
607                            }
608
609                            system_channel_id = Some(map.next_value()?);
610                        }
611                        Field::SystemChannelFlags => {
612                            if system_channel_flags.is_some() {
613                                return Err(DeError::duplicate_field("system_channel_flags"));
614                            }
615
616                            system_channel_flags = Some(map.next_value()?);
617                        }
618                        Field::RulesChannelId => {
619                            if rules_channel_id.is_some() {
620                                return Err(DeError::duplicate_field("rules_channel_id"));
621                            }
622
623                            rules_channel_id = Some(map.next_value()?);
624                        }
625                        Field::Threads => {
626                            if threads.is_some() {
627                                return Err(DeError::duplicate_field("threads"));
628                            }
629
630                            threads = Some(map.next_value()?);
631                        }
632                        Field::Unavailable => {
633                            if unavailable.is_some() {
634                                return Err(DeError::duplicate_field("unavailable"));
635                            }
636
637                            unavailable = Some(map.next_value()?);
638                        }
639                        Field::VerificationLevel => {
640                            if verification_level.is_some() {
641                                return Err(DeError::duplicate_field("verification_level"));
642                            }
643
644                            verification_level = Some(map.next_value()?);
645                        }
646                        Field::VoiceStates => {
647                            if voice_states.is_some() {
648                                return Err(DeError::duplicate_field("voice_states"));
649                            }
650
651                            voice_states = Some(map.next_value()?);
652                        }
653                        Field::VanityUrlCode => {
654                            if vanity_url_code.is_some() {
655                                return Err(DeError::duplicate_field("vanity_url_code"));
656                            }
657
658                            vanity_url_code = Some(map.next_value()?);
659                        }
660                        Field::WidgetChannelId => {
661                            if widget_channel_id.is_some() {
662                                return Err(DeError::duplicate_field("widget_channel_id"));
663                            }
664
665                            widget_channel_id = Some(map.next_value()?);
666                        }
667                        Field::WidgetEnabled => {
668                            if widget_enabled.is_some() {
669                                return Err(DeError::duplicate_field("widget_enabled"));
670                            }
671
672                            widget_enabled = Some(map.next_value()?);
673                        }
674                    }
675                }
676
677                let afk_timeout =
678                    afk_timeout.ok_or_else(|| DeError::missing_field("afk_timeout"))?;
679                let default_message_notifications = default_message_notifications
680                    .ok_or_else(|| DeError::missing_field("default_message_notifications"))?;
681                let explicit_content_filter = explicit_content_filter
682                    .ok_or_else(|| DeError::missing_field("explicit_content_filter"))?;
683                let features = features.ok_or_else(|| DeError::missing_field("features"))?;
684                let id = id.ok_or_else(|| DeError::missing_field("id"))?;
685                let mfa_level = mfa_level.ok_or_else(|| DeError::missing_field("mfa_level"))?;
686                let name = name.ok_or_else(|| DeError::missing_field("name"))?;
687                let owner_id = owner_id.ok_or_else(|| DeError::missing_field("owner_id"))?;
688                let preferred_locale =
689                    preferred_locale.ok_or_else(|| DeError::missing_field("preferred_locale"))?;
690                let roles = roles.ok_or_else(|| DeError::missing_field("roles"))?;
691                let system_channel_flags = system_channel_flags
692                    .ok_or_else(|| DeError::missing_field("system_channel_flags"))?;
693                let premium_progress_bar_enabled = premium_progress_bar_enabled
694                    .ok_or_else(|| DeError::missing_field("premium_progress_bar_enabled"))?;
695                let verification_level = verification_level
696                    .ok_or_else(|| DeError::missing_field("verification_level"))?;
697
698                let afk_channel_id = afk_channel_id.unwrap_or_default();
699                let application_id = application_id.unwrap_or_default();
700                let approximate_member_count = approximate_member_count.unwrap_or_default();
701                let approximate_presence_count = approximate_presence_count.unwrap_or_default();
702                let banner = banner.unwrap_or_default();
703                let mut channels = channels.unwrap_or_default();
704                let description = description.unwrap_or_default();
705                let discovery_splash = discovery_splash.unwrap_or_default();
706                let emojis = emojis.unwrap_or_default();
707                let guild_scheduled_events = guild_scheduled_events.unwrap_or_default();
708                let icon = icon.unwrap_or_default();
709                let large = large.unwrap_or_default();
710                let joined_at = joined_at.unwrap_or_default();
711                let max_members = max_members.unwrap_or_default();
712                let max_presences = max_presences.unwrap_or_default();
713                let max_stage_video_channel_users =
714                    max_stage_video_channel_users.unwrap_or_default();
715                let max_video_channel_users = max_video_channel_users.unwrap_or_default();
716                let member_count = member_count.unwrap_or_default();
717                let members = members.unwrap_or_default();
718                let nsfw_level = nsfw_level.ok_or_else(|| DeError::missing_field("nsfw_level"))?;
719                let owner = owner.unwrap_or_default();
720                let permissions = permissions.unwrap_or_default();
721                let premium_subscription_count = premium_subscription_count.unwrap_or_default();
722                let premium_tier = premium_tier.unwrap_or_default();
723                let mut presences = presences.unwrap_or_default();
724                let public_updates_channel_id = public_updates_channel_id.unwrap_or_default();
725                let rules_channel_id = rules_channel_id.unwrap_or_default();
726                let safety_alerts_channel_id = safety_alerts_channel_id.unwrap_or_default();
727                let splash = splash.unwrap_or_default();
728                let stage_instances = stage_instances.unwrap_or_default();
729                let stickers = stickers.unwrap_or_default();
730                let system_channel_id = system_channel_id.unwrap_or_default();
731                let mut threads = threads.unwrap_or_default();
732                let vanity_url_code = vanity_url_code.unwrap_or_default();
733                let mut voice_states = voice_states.unwrap_or_default();
734                let widget_channel_id = widget_channel_id.unwrap_or_default();
735                let widget_enabled = widget_enabled.unwrap_or_default();
736
737                for channel in &mut channels {
738                    channel.guild_id = Some(id);
739                }
740
741                for presence in &mut presences {
742                    presence.guild_id = id;
743                }
744
745                for thread in &mut threads {
746                    thread.guild_id = Some(id);
747                }
748
749                for voice_state in &mut voice_states {
750                    voice_state.guild_id.replace(id);
751                }
752
753                Ok(Guild {
754                    afk_channel_id,
755                    afk_timeout,
756                    application_id,
757                    approximate_member_count,
758                    approximate_presence_count,
759                    banner,
760                    channels,
761                    default_message_notifications,
762                    description,
763                    discovery_splash,
764                    emojis,
765                    explicit_content_filter,
766                    features,
767                    guild_scheduled_events,
768                    icon,
769                    id,
770                    joined_at,
771                    large,
772                    max_members,
773                    max_presences,
774                    max_stage_video_channel_users,
775                    max_video_channel_users,
776                    member_count,
777                    members,
778                    mfa_level,
779                    name,
780                    nsfw_level,
781                    owner_id,
782                    owner,
783                    permissions,
784                    preferred_locale,
785                    premium_progress_bar_enabled,
786                    premium_subscription_count,
787                    premium_tier,
788                    presences,
789                    public_updates_channel_id,
790                    roles,
791                    rules_channel_id,
792                    safety_alerts_channel_id,
793                    splash,
794                    stage_instances,
795                    stickers,
796                    system_channel_flags,
797                    system_channel_id,
798                    threads,
799                    unavailable,
800                    vanity_url_code,
801                    verification_level,
802                    voice_states,
803                    widget_channel_id,
804                    widget_enabled,
805                })
806            }
807        }
808
809        const FIELDS: &[&str] = &[
810            "afk_channel_id",
811            "afk_timeout",
812            "application_id",
813            "approximate_member_count",
814            "approximate_presence_count",
815            "banner",
816            "channels",
817            "default_message_notifications",
818            "description",
819            "discovery_splash",
820            "emojis",
821            "explicit_content_filter",
822            "features",
823            "icon",
824            "id",
825            "joined_at",
826            "large",
827            "max_members",
828            "max_presences",
829            "max_video_channel_users",
830            "member_count",
831            "members",
832            "mfa_level",
833            "name",
834            "nsfw_level",
835            "owner",
836            "owner_id",
837            "permissions",
838            "preferred_locale",
839            "premium_progress_bar_enabled",
840            "premium_subscription_count",
841            "premium_tier",
842            "presences",
843            "public_updates_channel_id",
844            "roles",
845            "splash",
846            "system_channel_id",
847            "system_channel_flags",
848            "rules_channel_id",
849            "threads",
850            "unavailable",
851            "verification_level",
852            "voice_states",
853            "vanity_url_code",
854            "widget_channel_id",
855            "widget_enabled",
856        ];
857
858        deserializer.deserialize_struct("Guild", FIELDS, GuildVisitor)
859    }
860}
861
862#[cfg(test)]
863mod tests {
864    use super::{
865        AfkTimeout, DefaultMessageNotificationLevel, ExplicitContentFilter, Guild, GuildFeature,
866        MfaLevel, NSFWLevel, Permissions, PremiumTier, SystemChannelFlags, VerificationLevel,
867    };
868    use crate::{
869        id::Id,
870        test::image_hash,
871        util::datetime::{Timestamp, TimestampParseError},
872    };
873    use serde_test::Token;
874    use std::str::FromStr;
875
876    #[allow(clippy::too_many_lines)]
877    #[test]
878    fn guild() -> Result<(), TimestampParseError> {
879        let joined_at = Some(Timestamp::from_str("2015-04-26T06:26:56.936000+00:00")?);
880
881        let value = Guild {
882            afk_channel_id: Some(Id::new(2)),
883            afk_timeout: AfkTimeout::FIFTEEN_MINUTES,
884            application_id: Some(Id::new(3)),
885            approximate_member_count: Some(1_200),
886            approximate_presence_count: Some(900),
887            banner: Some(image_hash::BANNER),
888            channels: Vec::new(),
889            default_message_notifications: DefaultMessageNotificationLevel::Mentions,
890            description: Some("a description".to_owned()),
891            discovery_splash: Some(image_hash::SPLASH),
892            emojis: Vec::new(),
893            explicit_content_filter: ExplicitContentFilter::MembersWithoutRole,
894            features: Vec::from([GuildFeature::Banner]),
895            guild_scheduled_events: Vec::new(),
896            icon: Some(image_hash::ICON),
897            id: Id::new(1),
898            joined_at,
899            large: true,
900            max_members: Some(25_000),
901            max_presences: Some(10_000),
902            max_stage_video_channel_users: Some(10),
903            max_video_channel_users: Some(10),
904            member_count: Some(12_000),
905            members: Vec::new(),
906            mfa_level: MfaLevel::Elevated,
907            name: "the name".to_owned(),
908            nsfw_level: NSFWLevel::Default,
909            owner_id: Id::new(5),
910            owner: Some(false),
911            permissions: Some(Permissions::SEND_MESSAGES),
912            preferred_locale: "en-us".to_owned(),
913            premium_progress_bar_enabled: false,
914            premium_subscription_count: Some(3),
915            premium_tier: PremiumTier::Tier1,
916            presences: Vec::new(),
917            public_updates_channel_id: None,
918            roles: Vec::new(),
919            rules_channel_id: Some(Id::new(6)),
920            safety_alerts_channel_id: Some(Id::new(9)),
921            splash: Some(image_hash::SPLASH),
922            stage_instances: Vec::new(),
923            stickers: Vec::new(),
924            system_channel_flags: SystemChannelFlags::SUPPRESS_PREMIUM_SUBSCRIPTIONS,
925            system_channel_id: Some(Id::new(7)),
926            threads: Vec::new(),
927            unavailable: None,
928            vanity_url_code: Some("twilight".to_owned()),
929            verification_level: VerificationLevel::Medium,
930            voice_states: Vec::new(),
931            widget_channel_id: Some(Id::new(8)),
932            widget_enabled: Some(true),
933        };
934
935        serde_test::assert_tokens(
936            &value,
937            &[
938                Token::Struct {
939                    name: "Guild",
940                    len: 47,
941                },
942                Token::Str("afk_channel_id"),
943                Token::Some,
944                Token::NewtypeStruct { name: "Id" },
945                Token::Str("2"),
946                Token::Str("afk_timeout"),
947                Token::NewtypeStruct { name: "AfkTimeout" },
948                Token::U16(900),
949                Token::Str("application_id"),
950                Token::Some,
951                Token::NewtypeStruct { name: "Id" },
952                Token::Str("3"),
953                Token::Str("approximate_member_count"),
954                Token::Some,
955                Token::U64(1_200),
956                Token::Str("approximate_presence_count"),
957                Token::Some,
958                Token::U64(900),
959                Token::Str("banner"),
960                Token::Some,
961                Token::Str(image_hash::BANNER_INPUT),
962                Token::Str("channels"),
963                Token::Seq { len: Some(0) },
964                Token::SeqEnd,
965                Token::Str("default_message_notifications"),
966                Token::U8(1),
967                Token::Str("description"),
968                Token::Some,
969                Token::Str("a description"),
970                Token::Str("discovery_splash"),
971                Token::Some,
972                Token::Str(image_hash::SPLASH_INPUT),
973                Token::Str("emojis"),
974                Token::Seq { len: Some(0) },
975                Token::SeqEnd,
976                Token::Str("explicit_content_filter"),
977                Token::U8(1),
978                Token::Str("features"),
979                Token::Seq { len: Some(1) },
980                Token::Str("BANNER"),
981                Token::SeqEnd,
982                Token::Str("icon"),
983                Token::Some,
984                Token::Str(image_hash::ICON_INPUT),
985                Token::Str("id"),
986                Token::NewtypeStruct { name: "Id" },
987                Token::Str("1"),
988                Token::Str("joined_at"),
989                Token::Some,
990                Token::Str("2015-04-26T06:26:56.936000+00:00"),
991                Token::Str("large"),
992                Token::Bool(true),
993                Token::Str("max_members"),
994                Token::Some,
995                Token::U64(25_000),
996                Token::Str("max_presences"),
997                Token::Some,
998                Token::U64(10_000),
999                Token::Str("max_stage_video_channel_users"),
1000                Token::Some,
1001                Token::U64(10),
1002                Token::Str("max_video_channel_users"),
1003                Token::Some,
1004                Token::U64(10),
1005                Token::Str("member_count"),
1006                Token::Some,
1007                Token::U64(12_000),
1008                Token::Str("members"),
1009                Token::Seq { len: Some(0) },
1010                Token::SeqEnd,
1011                Token::Str("mfa_level"),
1012                Token::U8(1),
1013                Token::Str("name"),
1014                Token::Str("the name"),
1015                Token::Str("nsfw_level"),
1016                Token::U8(0),
1017                Token::Str("owner_id"),
1018                Token::NewtypeStruct { name: "Id" },
1019                Token::Str("5"),
1020                Token::Str("owner"),
1021                Token::Some,
1022                Token::Bool(false),
1023                Token::Str("permissions"),
1024                Token::Some,
1025                Token::Str("2048"),
1026                Token::Str("preferred_locale"),
1027                Token::Str("en-us"),
1028                Token::Str("premium_progress_bar_enabled"),
1029                Token::Bool(false),
1030                Token::Str("premium_subscription_count"),
1031                Token::Some,
1032                Token::U64(3),
1033                Token::Str("premium_tier"),
1034                Token::U8(1),
1035                Token::Str("presences"),
1036                Token::Seq { len: Some(0) },
1037                Token::SeqEnd,
1038                Token::Str("public_updates_channel_id"),
1039                Token::None,
1040                Token::Str("roles"),
1041                Token::Seq { len: Some(0) },
1042                Token::SeqEnd,
1043                Token::Str("rules_channel_id"),
1044                Token::Some,
1045                Token::NewtypeStruct { name: "Id" },
1046                Token::Str("6"),
1047                Token::Str("safety_alerts_channel_id"),
1048                Token::Some,
1049                Token::NewtypeStruct { name: "Id" },
1050                Token::Str("9"),
1051                Token::Str("splash"),
1052                Token::Some,
1053                Token::Str(image_hash::SPLASH_INPUT),
1054                Token::Str("system_channel_flags"),
1055                Token::U64(2),
1056                Token::Str("system_channel_id"),
1057                Token::Some,
1058                Token::NewtypeStruct { name: "Id" },
1059                Token::Str("7"),
1060                Token::Str("threads"),
1061                Token::Seq { len: Some(0) },
1062                Token::SeqEnd,
1063                Token::Str("vanity_url_code"),
1064                Token::Some,
1065                Token::Str("twilight"),
1066                Token::Str("verification_level"),
1067                Token::U8(2),
1068                Token::Str("voice_states"),
1069                Token::Seq { len: Some(0) },
1070                Token::SeqEnd,
1071                Token::Str("widget_channel_id"),
1072                Token::Some,
1073                Token::NewtypeStruct { name: "Id" },
1074                Token::Str("8"),
1075                Token::Str("widget_enabled"),
1076                Token::Some,
1077                Token::Bool(true),
1078                Token::StructEnd,
1079            ],
1080        );
1081
1082        Ok(())
1083    }
1084}