1use std::slice::Iter;
2
3use serde::Serialize;
4use twilight_model::{
5 gateway::payload::incoming::GuildUpdate,
6 guild::{
7 scheduled_event::GuildScheduledEvent, AfkTimeout, DefaultMessageNotificationLevel,
8 ExplicitContentFilter, Guild, GuildFeature, MfaLevel, NSFWLevel, Permissions, PremiumTier,
9 SystemChannelFlags, VerificationLevel,
10 },
11 id::{
12 marker::{ApplicationMarker, ChannelMarker, GuildMarker, UserMarker},
13 Id,
14 },
15 util::{ImageHash, Timestamp},
16};
17
18use crate::CacheableGuild;
19
20#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
24pub struct CachedGuild {
25 pub(crate) afk_channel_id: Option<Id<ChannelMarker>>,
26 pub(crate) afk_timeout: AfkTimeout,
27 pub(crate) application_id: Option<Id<ApplicationMarker>>,
28 pub(crate) banner: Option<ImageHash>,
29 pub(crate) default_message_notifications: DefaultMessageNotificationLevel,
30 pub(crate) description: Option<String>,
31 pub(crate) discovery_splash: Option<ImageHash>,
32 pub(crate) explicit_content_filter: ExplicitContentFilter,
33 pub(crate) features: Vec<GuildFeature>,
34 pub(crate) guild_scheduled_events: Vec<GuildScheduledEvent>,
35 pub(crate) icon: Option<ImageHash>,
36 pub(crate) id: Id<GuildMarker>,
37 pub(crate) joined_at: Option<Timestamp>,
38 pub(crate) large: bool,
39 pub(crate) max_members: Option<u64>,
40 pub(crate) max_presences: Option<u64>,
41 pub(crate) max_stage_video_channel_users: Option<u64>,
42 pub(crate) max_video_channel_users: Option<u64>,
43 pub(crate) member_count: Option<u64>,
44 pub(crate) mfa_level: MfaLevel,
45 pub(crate) name: String,
46 pub(crate) nsfw_level: NSFWLevel,
47 pub(crate) owner: Option<bool>,
48 pub(crate) owner_id: Id<UserMarker>,
49 pub(crate) permissions: Option<Permissions>,
50 pub(crate) preferred_locale: String,
51 pub(crate) premium_progress_bar_enabled: bool,
52 pub(crate) premium_subscription_count: Option<u64>,
53 pub(crate) premium_tier: PremiumTier,
54 pub(crate) public_updates_channel_id: Option<Id<ChannelMarker>>,
55 pub(crate) rules_channel_id: Option<Id<ChannelMarker>>,
56 pub(crate) safety_alerts_channel_id: Option<Id<ChannelMarker>>,
57 pub(crate) splash: Option<ImageHash>,
58 pub(crate) system_channel_flags: SystemChannelFlags,
59 pub(crate) system_channel_id: Option<Id<ChannelMarker>>,
60 pub(crate) unavailable: Option<bool>,
61 pub(crate) vanity_url_code: Option<String>,
62 pub(crate) verification_level: VerificationLevel,
63 pub(crate) widget_channel_id: Option<Id<ChannelMarker>>,
64 pub(crate) widget_enabled: Option<bool>,
65}
66
67impl CachedGuild {
68 pub const fn afk_channel_id(&self) -> Option<Id<ChannelMarker>> {
70 self.afk_channel_id
71 }
72
73 pub const fn afk_timeout(&self) -> AfkTimeout {
75 self.afk_timeout
76 }
77
78 pub const fn application_id(&self) -> Option<Id<ApplicationMarker>> {
80 self.application_id
81 }
82
83 pub const fn banner(&self) -> Option<&ImageHash> {
89 self.banner.as_ref()
90 }
91
92 pub const fn default_message_notifications(&self) -> DefaultMessageNotificationLevel {
94 self.default_message_notifications
95 }
96
97 pub fn description(&self) -> Option<&str> {
99 self.description.as_deref()
100 }
101
102 pub const fn discovery_splash(&self) -> Option<&ImageHash> {
108 self.discovery_splash.as_ref()
109 }
110
111 pub const fn explicit_content_filter(&self) -> ExplicitContentFilter {
113 self.explicit_content_filter
114 }
115
116 pub fn features(&self) -> Features<'_> {
120 Features {
121 inner: self.features.iter(),
122 }
123 }
124
125 pub fn guild_scheduled_events(&self) -> &[GuildScheduledEvent] {
127 &self.guild_scheduled_events
128 }
129
130 pub const fn icon(&self) -> Option<&ImageHash> {
136 self.icon.as_ref()
137 }
138
139 pub const fn id(&self) -> Id<GuildMarker> {
141 self.id
142 }
143
144 pub const fn joined_at(&self) -> Option<Timestamp> {
146 self.joined_at
147 }
148
149 pub const fn large(&self) -> bool {
151 self.large
152 }
153
154 pub const fn max_members(&self) -> Option<u64> {
156 self.max_members
157 }
158
159 pub const fn max_presences(&self) -> Option<u64> {
161 self.max_presences
162 }
163
164 pub const fn max_stage_video_channel_users(&self) -> Option<u64> {
166 self.max_stage_video_channel_users
167 }
168
169 pub const fn max_video_channel_users(&self) -> Option<u64> {
171 self.max_video_channel_users
172 }
173
174 pub const fn member_count(&self) -> Option<u64> {
176 self.member_count
177 }
178
179 pub const fn mfa_level(&self) -> MfaLevel {
181 self.mfa_level
182 }
183
184 pub fn name(&self) -> &str {
186 &self.name
187 }
188
189 pub const fn nsfw_level(&self) -> NSFWLevel {
191 self.nsfw_level
192 }
193
194 pub const fn owner(&self) -> Option<bool> {
196 self.owner
197 }
198
199 pub const fn owner_id(&self) -> Id<UserMarker> {
201 self.owner_id
202 }
203
204 pub const fn permissions(&self) -> Option<Permissions> {
206 self.permissions
207 }
208
209 pub fn preferred_locale(&self) -> &str {
213 &self.preferred_locale
214 }
215
216 pub const fn premium_progress_bar_enabled(&self) -> bool {
218 self.premium_progress_bar_enabled
219 }
220
221 pub const fn premium_subscription_count(&self) -> Option<u64> {
223 self.premium_subscription_count
224 }
225
226 pub const fn premium_tier(&self) -> PremiumTier {
228 self.premium_tier
229 }
230
231 pub const fn public_updates_channel_id(&self) -> Option<Id<ChannelMarker>> {
234 self.public_updates_channel_id
235 }
236
237 pub const fn rules_channel_id(&self) -> Option<Id<ChannelMarker>> {
239 self.rules_channel_id
240 }
241
242 pub const fn safety_alerts_channel_id(&self) -> Option<Id<ChannelMarker>> {
244 self.safety_alerts_channel_id
245 }
246
247 pub const fn splash(&self) -> Option<&ImageHash> {
253 self.splash.as_ref()
254 }
255
256 pub const fn system_channel_id(&self) -> Option<Id<ChannelMarker>> {
260 self.system_channel_id
261 }
262
263 pub const fn system_channel_flags(&self) -> SystemChannelFlags {
265 self.system_channel_flags
266 }
267
268 pub const fn unavailable(&self) -> Option<bool> {
270 self.unavailable
271 }
272
273 pub fn vanity_url_code(&self) -> Option<&str> {
275 self.vanity_url_code.as_deref()
276 }
277
278 pub const fn verification_level(&self) -> VerificationLevel {
280 self.verification_level
281 }
282
283 pub const fn widget_channel_id(&self) -> Option<Id<ChannelMarker>> {
285 self.widget_channel_id
286 }
287
288 pub const fn widget_enabled(&self) -> Option<bool> {
290 self.widget_enabled
291 }
292}
293
294impl From<Guild> for CachedGuild {
295 fn from(guild: Guild) -> Self {
296 let Guild {
297 afk_channel_id,
298 afk_timeout,
299 application_id,
300 approximate_member_count: _,
301 approximate_presence_count: _,
302 banner,
303 default_message_notifications,
304 description,
305 discovery_splash,
306 explicit_content_filter,
307 features,
308 guild_scheduled_events,
309 icon,
310 id,
311 joined_at,
312 large,
313 max_members,
314 max_presences,
315 max_stage_video_channel_users,
316 max_video_channel_users,
317 member_count,
318 mfa_level,
319 name,
320 nsfw_level,
321 owner,
322 owner_id,
323 permissions,
324 preferred_locale,
325 premium_progress_bar_enabled,
326 premium_subscription_count,
327 premium_tier,
328 public_updates_channel_id,
329 rules_channel_id,
330 safety_alerts_channel_id,
331 splash,
332 system_channel_flags,
333 system_channel_id,
334 unavailable,
335 vanity_url_code,
336 verification_level,
337 widget_channel_id,
338 widget_enabled,
339 ..
340 } = guild;
341
342 Self {
343 afk_channel_id,
344 afk_timeout,
345 application_id,
346 banner,
347 default_message_notifications,
348 description,
349 discovery_splash,
350 explicit_content_filter,
351 features,
352 guild_scheduled_events,
353 icon,
354 id,
355 joined_at,
356 large,
357 max_members,
358 max_presences,
359 max_stage_video_channel_users,
360 max_video_channel_users,
361 member_count,
362 mfa_level,
363 name,
364 nsfw_level,
365 owner,
366 owner_id,
367 permissions,
368 preferred_locale,
369 premium_progress_bar_enabled,
370 premium_subscription_count,
371 premium_tier,
372 public_updates_channel_id,
373 rules_channel_id,
374 safety_alerts_channel_id,
375 splash,
376 system_channel_flags,
377 system_channel_id,
378 unavailable,
379 vanity_url_code,
380 verification_level,
381 widget_channel_id,
382 widget_enabled,
383 }
384 }
385}
386
387impl PartialEq<Guild> for CachedGuild {
388 fn eq(&self, other: &Guild) -> bool {
389 self.afk_channel_id == other.afk_channel_id
390 && self.afk_timeout == other.afk_timeout
391 && self.application_id == other.application_id
392 && self.banner == other.banner
393 && self.default_message_notifications == other.default_message_notifications
394 && self.description == other.description
395 && self.discovery_splash == other.discovery_splash
396 && self.explicit_content_filter == other.explicit_content_filter
397 && self.features == other.features
398 && self.icon == other.icon
399 && self.joined_at == other.joined_at
400 && self.large == other.large
401 && self.max_members == other.max_members
402 && self.max_presences == other.max_presences
403 && self.max_video_channel_users == other.max_video_channel_users
404 && self.member_count == other.member_count
405 && self.mfa_level == other.mfa_level
406 && self.name == other.name
407 && self.nsfw_level == other.nsfw_level
408 && self.owner_id == other.owner_id
409 && self.owner == other.owner
410 && self.permissions == other.permissions
411 && self.preferred_locale == other.preferred_locale
412 && self.premium_progress_bar_enabled == other.premium_progress_bar_enabled
413 && self.premium_subscription_count == other.premium_subscription_count
414 && self.premium_tier == other.premium_tier
415 && self.public_updates_channel_id == other.public_updates_channel_id
416 && self.rules_channel_id == other.rules_channel_id
417 && self.safety_alerts_channel_id == other.safety_alerts_channel_id
418 && self.splash == other.splash
419 && self.system_channel_id == other.system_channel_id
420 && self.system_channel_flags == other.system_channel_flags
421 && self.unavailable == other.unavailable
422 && self.vanity_url_code == other.vanity_url_code
423 && self.verification_level == other.verification_level
424 && self.widget_channel_id == other.widget_channel_id
425 && self.widget_enabled == other.widget_enabled
426 }
427}
428
429impl CacheableGuild for CachedGuild {
430 fn id(&self) -> Id<GuildMarker> {
431 self.id
432 }
433
434 #[cfg(feature = "permission-calculator")]
435 fn owner_id(&self) -> Id<UserMarker> {
436 self.owner_id
437 }
438
439 fn set_unavailable(&mut self, unavailable: Option<bool>) {
440 self.unavailable = unavailable;
441 }
442
443 fn update_with_guild_update(&mut self, guild_update: &GuildUpdate) {
444 self.afk_channel_id = guild_update.afk_channel_id;
445 self.afk_timeout = guild_update.afk_timeout;
446 self.banner = guild_update.banner;
447 self.default_message_notifications = guild_update.default_message_notifications;
448 self.description.clone_from(&guild_update.description);
449 self.features.clone_from(&guild_update.features);
450 self.icon = guild_update.icon;
451 self.max_members = guild_update.max_members;
452 self.max_presences = Some(guild_update.max_presences.unwrap_or(25000));
453 self.mfa_level = guild_update.mfa_level;
454 self.name.clone_from(&guild_update.name);
455 self.nsfw_level = guild_update.nsfw_level;
456 self.owner = guild_update.owner;
457 self.owner_id = guild_update.owner_id;
458 self.permissions = guild_update.permissions;
459 self.preferred_locale
460 .clone_from(&guild_update.preferred_locale);
461 self.premium_tier = guild_update.premium_tier;
462 self.premium_subscription_count
463 .replace(guild_update.premium_subscription_count.unwrap_or_default());
464 self.splash = guild_update.splash;
465 self.system_channel_id = guild_update.system_channel_id;
466 self.verification_level = guild_update.verification_level;
467 self.vanity_url_code
468 .clone_from(&guild_update.vanity_url_code);
469 self.widget_channel_id = guild_update.widget_channel_id;
470 self.widget_enabled = guild_update.widget_enabled;
471 }
472
473 fn increase_member_count(&mut self, amount: u64) {
474 self.member_count = self.member_count.map(|count| count + amount);
475 }
476
477 fn decrease_member_count(&mut self, amount: u64) {
478 self.member_count = self.member_count.map(|count| count - amount);
479 }
480}
481
482pub struct Features<'a> {
483 inner: Iter<'a, GuildFeature>,
484}
485
486impl<'a> Iterator for Features<'a> {
487 type Item = &'a GuildFeature;
488
489 fn next(&mut self) -> Option<Self::Item> {
490 self.inner.next()
491 }
492}
493
494#[cfg(test)]
495mod tests {
496 use super::{CachedGuild, Features};
497 use serde::Serialize;
498 use static_assertions::{assert_fields, assert_impl_all};
499 use std::fmt::Debug;
500
501 assert_fields!(
502 CachedGuild: afk_channel_id,
503 afk_timeout,
504 application_id,
505 banner,
506 default_message_notifications,
507 description,
508 discovery_splash,
509 explicit_content_filter,
510 features,
511 icon,
512 id,
513 joined_at,
514 large,
515 max_members,
516 max_presences,
517 max_video_channel_users,
518 member_count,
519 mfa_level,
520 name,
521 nsfw_level,
522 owner_id,
523 owner,
524 permissions,
525 preferred_locale,
526 premium_progress_bar_enabled,
527 premium_subscription_count,
528 premium_tier,
529 rules_channel_id,
530 splash,
531 system_channel_id,
532 system_channel_flags,
533 unavailable,
534 vanity_url_code,
535 verification_level,
536 widget_channel_id,
537 widget_enabled
538 );
539 assert_impl_all!(
540 CachedGuild: Clone,
541 Debug,
542 Eq,
543 PartialEq,
544 Send,
545 Serialize,
546 Sync,
547 );
548 assert_impl_all!(Features<'_>: Iterator, Send, Sync);
549}