serenity/model/guild/
mod.rs

1//! Models relating to guilds and types that it owns.
2
3pub mod audit_log;
4pub mod automod;
5mod emoji;
6mod guild_id;
7mod guild_preview;
8mod integration;
9mod member;
10mod partial_guild;
11mod premium_tier;
12mod role;
13mod scheduled_event;
14mod system_channel;
15mod welcome_screen;
16
17#[cfg(feature = "model")]
18use std::borrow::Cow;
19
20#[cfg(feature = "model")]
21use tracing::{error, warn};
22
23pub use self::emoji::*;
24pub use self::guild_id::*;
25pub use self::guild_preview::*;
26pub use self::integration::*;
27pub use self::member::*;
28pub use self::partial_guild::*;
29pub use self::premium_tier::*;
30pub use self::role::*;
31pub use self::scheduled_event::*;
32pub use self::system_channel::*;
33pub use self::welcome_screen::*;
34#[cfg(feature = "model")]
35use crate::builder::{
36    AddMember,
37    CreateChannel,
38    CreateCommand,
39    CreateScheduledEvent,
40    CreateSticker,
41    EditAutoModRule,
42    EditCommandPermissions,
43    EditGuild,
44    EditGuildWelcomeScreen,
45    EditGuildWidget,
46    EditMember,
47    EditRole,
48    EditScheduledEvent,
49    EditSticker,
50};
51#[cfg(all(feature = "cache", feature = "model"))]
52use crate::cache::Cache;
53#[cfg(feature = "collector")]
54use crate::collector::{MessageCollector, ReactionCollector};
55#[cfg(feature = "model")]
56use crate::constants::LARGE_THRESHOLD;
57#[cfg(feature = "collector")]
58use crate::gateway::ShardMessenger;
59#[cfg(feature = "model")]
60use crate::http::{CacheHttp, Http, UserPagination};
61#[cfg(feature = "model")]
62use crate::json::json;
63use crate::model::prelude::*;
64use crate::model::utils::*;
65
66/// A representation of a banning of a user.
67///
68/// [Discord docs](https://discord.com/developers/docs/resources/guild#ban-object).
69#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
70#[non_exhaustive]
71pub struct Ban {
72    /// The reason given for this ban.
73    pub reason: Option<String>,
74    /// The user that was banned.
75    pub user: User,
76}
77
78/// The response from [`GuildId::bulk_ban`].
79///
80/// [Discord docs](https://discord.com/developers/docs/resources/guild#bulk-guild-ban).
81#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
82#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
83#[non_exhaustive]
84pub struct BulkBanResponse {
85    /// The users that were successfully banned.
86    pub banned_users: Vec<UserId>,
87    /// The users that were not successfully banned.
88    pub failed_users: Vec<UserId>,
89}
90
91#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
92#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
93pub struct AfkMetadata {
94    /// Id of a voice channel that's considered the AFK channel.
95    pub afk_channel_id: ChannelId,
96    /// The amount of seconds a user can not show any activity in a voice channel before being
97    /// moved to an AFK channel -- if one exists.
98    pub afk_timeout: AfkTimeout,
99}
100
101/// Information about a Discord guild, such as channels, emojis, etc.
102///
103/// [Discord docs](https://discord.com/developers/docs/resources/guild#guild-object) plus
104/// [extension](https://discord.com/developers/docs/topics/gateway-events#guild-create).
105#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
106#[derive(Clone, Debug, Default, Deserialize, Serialize)]
107#[non_exhaustive]
108pub struct Guild {
109    /// The unique Id identifying the guild.
110    ///
111    /// This is equivalent to the Id of the default role (`@everyone`).
112    pub id: GuildId,
113    /// The name of the guild.
114    pub name: String,
115    /// The hash of the icon used by the guild.
116    ///
117    /// In the client, this appears on the guild list on the left-hand side.
118    pub icon: Option<ImageHash>,
119    /// Icon hash, returned when in the template object
120    pub icon_hash: Option<ImageHash>,
121    /// An identifying hash of the guild's splash icon.
122    ///
123    /// If the `InviteSplash` feature is enabled, this can be used to generate a URL to a splash
124    /// image.
125    pub splash: Option<ImageHash>,
126    /// An identifying hash of the guild discovery's splash icon.
127    ///
128    /// **Note**: Only present for guilds with the `DISCOVERABLE` feature.
129    pub discovery_splash: Option<ImageHash>,
130    // Omitted `owner` field because only Http::get_guilds uses it, which returns GuildInfo
131    /// The Id of the [`User`] who owns the guild.
132    pub owner_id: UserId,
133    // Omitted `permissions` field because only Http::get_guilds uses it, which returns GuildInfo
134    // Omitted `region` field because it is deprecated (see Discord docs)
135    /// Information about the voice afk channel.
136    #[serde(flatten)]
137    pub afk_metadata: Option<AfkMetadata>,
138    /// Whether or not the guild widget is enabled.
139    pub widget_enabled: Option<bool>,
140    /// The channel id that the widget will generate an invite to, or null if set to no invite
141    pub widget_channel_id: Option<ChannelId>,
142    /// Indicator of the current verification level of the guild.
143    pub verification_level: VerificationLevel,
144    /// Indicator of whether notifications for all messages are enabled by
145    /// default in the guild.
146    pub default_message_notifications: DefaultMessageNotificationLevel,
147    /// Default explicit content filter level.
148    pub explicit_content_filter: ExplicitContentFilter,
149    /// A mapping of the guild's roles.
150    #[serde(with = "roles")]
151    pub roles: HashMap<RoleId, Role>,
152    /// All of the guild's custom emojis.
153    #[serde(with = "emojis")]
154    pub emojis: HashMap<EmojiId, Emoji>,
155    /// The guild features. More information available at [`discord documentation`].
156    ///
157    /// The following is a list of known features:
158    /// - `ANIMATED_ICON`
159    /// - `BANNER`
160    /// - `COMMERCE`
161    /// - `COMMUNITY`
162    /// - `DISCOVERABLE`
163    /// - `FEATURABLE`
164    /// - `INVITE_SPLASH`
165    /// - `MEMBER_VERIFICATION_GATE_ENABLED`
166    /// - `MONETIZATION_ENABLED`
167    /// - `MORE_STICKERS`
168    /// - `NEWS`
169    /// - `PARTNERED`
170    /// - `PREVIEW_ENABLED`
171    /// - `PRIVATE_THREADS`
172    /// - `ROLE_ICONS`
173    /// - `SEVEN_DAY_THREAD_ARCHIVE`
174    /// - `THREE_DAY_THREAD_ARCHIVE`
175    /// - `TICKETED_EVENTS_ENABLED`
176    /// - `VANITY_URL`
177    /// - `VERIFIED`
178    /// - `VIP_REGIONS`
179    /// - `WELCOME_SCREEN_ENABLED`
180    /// - `THREE_DAY_THREAD_ARCHIVE`
181    /// - `SEVEN_DAY_THREAD_ARCHIVE`
182    /// - `PRIVATE_THREADS`
183    ///
184    ///
185    /// [`discord documentation`]: https://discord.com/developers/docs/resources/guild#guild-object-guild-features
186    pub features: Vec<String>,
187    /// Indicator of whether the guild requires multi-factor authentication for [`Role`]s or
188    /// [`User`]s with moderation permissions.
189    pub mfa_level: MfaLevel,
190    /// Application ID of the guild creator if it is bot-created.
191    pub application_id: Option<ApplicationId>,
192    /// The ID of the channel to which system messages are sent.
193    pub system_channel_id: Option<ChannelId>,
194    /// System channel flags.
195    pub system_channel_flags: SystemChannelFlags,
196    /// The id of the channel where rules and/or guidelines are displayed.
197    ///
198    /// **Note**: Only available on `COMMUNITY` guild, see [`Self::features`].
199    pub rules_channel_id: Option<ChannelId>,
200    /// The maximum number of presences for the guild. The default value is currently 25000.
201    ///
202    /// **Note**: It is in effect when it is `None`.
203    pub max_presences: Option<u64>,
204    /// The maximum number of members for the guild.
205    pub max_members: Option<u64>,
206    /// The vanity url code for the guild, if it has one.
207    pub vanity_url_code: Option<String>,
208    /// The server's description, if it has one.
209    pub description: Option<String>,
210    /// The guild's banner, if it has one.
211    pub banner: Option<String>,
212    /// The server's premium boosting level.
213    pub premium_tier: PremiumTier,
214    /// The total number of users currently boosting this server.
215    pub premium_subscription_count: Option<u64>,
216    /// The preferred locale of this guild only set if guild has the "DISCOVERABLE" feature,
217    /// defaults to en-US.
218    pub preferred_locale: String,
219    /// The id of the channel where admins and moderators of Community guilds receive notices from
220    /// Discord.
221    ///
222    /// **Note**: Only available on `COMMUNITY` guild, see [`Self::features`].
223    pub public_updates_channel_id: Option<ChannelId>,
224    /// The maximum amount of users in a video channel.
225    pub max_video_channel_users: Option<u64>,
226    /// The maximum amount of users in a stage video channel
227    pub max_stage_video_channel_users: Option<u64>,
228    /// Approximate number of members in this guild.
229    pub approximate_member_count: Option<u64>,
230    /// Approximate number of non-offline members in this guild.
231    pub approximate_presence_count: Option<u64>,
232    /// The welcome screen of the guild.
233    ///
234    /// **Note**: Only available on `COMMUNITY` guild, see [`Self::features`].
235    pub welcome_screen: Option<GuildWelcomeScreen>,
236    /// The guild NSFW state. See [`discord support article`].
237    ///
238    /// [`discord support article`]: https://support.discord.com/hc/en-us/articles/1500005389362-NSFW-Server-Designation
239    pub nsfw_level: NsfwLevel,
240    /// All of the guild's custom stickers.
241    #[serde(with = "stickers")]
242    pub stickers: HashMap<StickerId, Sticker>,
243    /// Whether the guild has the boost progress bar enabled
244    pub premium_progress_bar_enabled: bool,
245
246    // =======
247    // From here on, all fields are from Guild Create Event's extra fields (see Discord docs)
248    // =======
249    /// The date that the current user joined the guild.
250    pub joined_at: Timestamp,
251    /// Indicator of whether the guild is considered "large" by Discord.
252    pub large: bool,
253    /// Whether this guild is unavailable due to an outage.
254    #[serde(default)]
255    pub unavailable: bool,
256    /// The number of members in the guild.
257    pub member_count: u64,
258    /// A mapping of [`User`]s to their current voice state.
259    #[serde(serialize_with = "serialize_map_values")]
260    #[serde(deserialize_with = "deserialize_voice_states")]
261    pub voice_states: HashMap<UserId, VoiceState>,
262    /// Users who are members of the guild.
263    ///
264    /// Members might not all be available when the [`ReadyEvent`] is received if the
265    /// [`Self::member_count`] is greater than the [`LARGE_THRESHOLD`] set by the library.
266    #[serde(with = "members")]
267    pub members: HashMap<UserId, Member>,
268    /// All voice and text channels contained within a guild.
269    ///
270    /// This contains all channels regardless of permissions (i.e. the ability of the bot to read
271    /// from or connect to them).
272    #[serde(serialize_with = "serialize_map_values")]
273    #[serde(deserialize_with = "deserialize_guild_channels")]
274    pub channels: HashMap<ChannelId, GuildChannel>,
275    /// All active threads in this guild that current user has permission to view.
276    ///
277    /// A thread is guaranteed (for errors, not for panics) to be cached if a `MESSAGE_CREATE`
278    /// event is fired in said thread, however an `INTERACTION_CREATE` may not have a private
279    /// thread in cache.
280    pub threads: Vec<GuildChannel>,
281    /// A mapping of [`User`]s' Ids to their current presences.
282    ///
283    /// **Note**: This will be empty unless the "guild presences" privileged intent is enabled.
284    #[serde(with = "presences")]
285    pub presences: HashMap<UserId, Presence>,
286    /// The stage instances in this guild.
287    pub stage_instances: Vec<StageInstance>,
288    /// The stage instances in this guild.
289    #[serde(rename = "guild_scheduled_events")]
290    pub scheduled_events: Vec<ScheduledEvent>,
291}
292
293#[cfg(feature = "model")]
294impl Guild {
295    /// Gets all auto moderation [`Rule`]s of this guild via HTTP.
296    ///
297    /// **Note**: Requires the [Manage Guild] permission.
298    ///
299    /// # Errors
300    ///
301    /// Returns an [`Error::Http`] if the guild is unavailable.
302    ///
303    /// [Manage Guild]: Permissions::MANAGE_GUILD
304    #[inline]
305    pub async fn automod_rules(&self, http: impl AsRef<Http>) -> Result<Vec<Rule>> {
306        self.id.automod_rules(http).await
307    }
308
309    /// Gets an auto moderation [`Rule`] of this guild by its ID via HTTP.
310    ///
311    /// **Note**: Requires the [Manage Guild] permission.
312    ///
313    /// # Errors
314    ///
315    /// Returns an [`Error::Http`] if a rule with the given ID does not exist.
316    ///
317    /// [Manage Guild]: Permissions::MANAGE_GUILD
318    #[inline]
319    pub async fn automod_rule(
320        &self,
321        http: impl AsRef<Http>,
322        rule_id: impl Into<RuleId>,
323    ) -> Result<Rule> {
324        self.id.automod_rule(http, rule_id).await
325    }
326
327    /// Creates an auto moderation [`Rule`] in the guild.
328    ///
329    /// **Note**: Requires the [Manage Guild] permission.
330    ///
331    /// # Examples
332    ///
333    /// See [`GuildId::create_automod_rule`] for details.
334    ///
335    /// # Errors
336    ///
337    /// Returns [`Error::Http`] if the current user lacks permission, or if invalid data is given.
338    ///
339    /// [Manage Guild]: Permissions::MANAGE_GUILD
340    #[inline]
341    pub async fn create_automod_rule(
342        &self,
343        cache_http: impl CacheHttp,
344        builder: EditAutoModRule<'_>,
345    ) -> Result<Rule> {
346        self.id.create_automod_rule(cache_http, builder).await
347    }
348
349    /// Edit an auto moderation [`Rule`], given its Id.
350    ///
351    /// **Note**: Requires the [Manage Guild] permission.
352    ///
353    /// # Errors
354    ///
355    /// Returns [`Error::Http`] if the current user lacks permission, or if invalid data is given.
356    ///
357    /// [Manage Guild]: Permissions::MANAGE_GUILD
358    #[inline]
359    pub async fn edit_automod_rule(
360        &self,
361        cache_http: impl CacheHttp,
362        rule_id: impl Into<RuleId>,
363        builder: EditAutoModRule<'_>,
364    ) -> Result<Rule> {
365        self.id.edit_automod_rule(cache_http, rule_id, builder).await
366    }
367
368    /// Deletes an auto moderation [`Rule`] from the guild.
369    ///
370    /// **Note**: Requires the [Manage Guild] permission.
371    ///
372    /// # Errors
373    ///
374    /// Returns [`Error::Http`] if the current user lacks permission, or if a rule with that Id
375    /// does not exist.
376    ///
377    /// [Manage Guild]: Permissions::MANAGE_GUILD
378    #[inline]
379    pub async fn delete_automod_rule(
380        &self,
381        http: impl AsRef<Http>,
382        rule_id: impl Into<RuleId>,
383    ) -> Result<()> {
384        self.id.delete_automod_rule(http, rule_id).await
385    }
386
387    #[cfg(feature = "cache")]
388    fn check_hierarchy(&self, cache: &Cache, other_user: UserId) -> Result<()> {
389        let current_id = cache.as_ref().current_user().id;
390
391        if let Some(higher) = self.greater_member_hierarchy(cache, other_user, current_id) {
392            if higher != current_id {
393                return Err(Error::Model(ModelError::Hierarchy));
394            }
395        }
396
397        Ok(())
398    }
399
400    /// Returns the "default" channel of the guild for the passed user id. (This returns the first
401    /// channel that can be read by the user, if there isn't one, returns [`None`])
402    #[must_use]
403    pub fn default_channel(&self, uid: UserId) -> Option<&GuildChannel> {
404        let member = self.members.get(&uid)?;
405        self.channels.values().find(|&channel| {
406            channel.kind != ChannelType::Category
407                && self.user_permissions_in(channel, member).view_channel()
408        })
409    }
410
411    /// Returns the guaranteed "default" channel of the guild. (This returns the first channel that
412    /// can be read by everyone, if there isn't one, returns [`None`])
413    ///
414    /// **Note**: This is very costly if used in a server with lots of channels, members, or both.
415    #[must_use]
416    pub fn default_channel_guaranteed(&self) -> Option<&GuildChannel> {
417        self.channels.values().find(|&channel| {
418            channel.kind != ChannelType::Category
419                && self
420                    .members
421                    .values()
422                    .map(|member| self.user_permissions_in(channel, member))
423                    .all(Permissions::view_channel)
424        })
425    }
426
427    /// Intentionally not async. Retrieving anything from HTTP here is overkill/undesired
428    #[cfg(feature = "cache")]
429    pub(crate) fn require_perms(
430        &self,
431        cache: &Cache,
432        required_permissions: Permissions,
433    ) -> Result<(), Error> {
434        if let Some(member) = self.members.get(&cache.current_user().id) {
435            // This isn't used for any channel-specific permissions, but sucks still.
436            #[allow(deprecated)]
437            let bot_permissions = self.member_permissions(member);
438            if !bot_permissions.contains(required_permissions) {
439                return Err(Error::Model(ModelError::InvalidPermissions {
440                    required: required_permissions,
441                    present: bot_permissions,
442                }));
443            }
444        }
445        Ok(())
446    }
447
448    #[cfg(feature = "cache")]
449    #[deprecated = "Iterate through Guild::channels and use Iterator::find"]
450    pub fn channel_id_from_name(
451        &self,
452        #[allow(unused_variables)] cache: impl AsRef<Cache>,
453        name: impl AsRef<str>,
454    ) -> Option<ChannelId> {
455        let name = name.as_ref();
456
457        self.channels.values().find(|c| c.name == name).map(|c| c.id)
458    }
459
460    /// Ban a [`User`] from the guild, deleting a number of days' worth of messages (`dmd`) between
461    /// the range 0 and 7.
462    ///
463    /// Refer to the documentation for [`Guild::ban`] for more information.
464    ///
465    /// **Note**: Requires the [Ban Members] permission.
466    ///
467    /// # Examples
468    ///
469    /// Ban a member and remove all messages they've sent in the last 4 days:
470    ///
471    /// ```rust,ignore
472    /// // assumes a `user` and `guild` have already been bound
473    /// let _ = guild.ban(user, 4);
474    /// ```
475    ///
476    /// # Errors
477    ///
478    /// Returns a [`ModelError::DeleteMessageDaysAmount`] if the number of days' worth of messages
479    /// to delete is over the maximum.
480    ///
481    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
482    /// does not have permission to perform bans, or may return a [`ModelError::Hierarchy`] if the
483    /// member to be banned has a higher role than the current user.
484    ///
485    /// Otherwise returns [`Error::Http`] if the member cannot be banned.
486    ///
487    /// [Ban Members]: Permissions::BAN_MEMBERS
488    #[inline]
489    pub async fn ban(
490        &self,
491        cache_http: impl CacheHttp,
492        user: impl Into<UserId>,
493        dmd: u8,
494    ) -> Result<()> {
495        self.ban_with_reason_(cache_http, user.into(), dmd, "").await
496    }
497
498    /// Ban a [`User`] from the guild with a reason. Refer to [`Self::ban`] to further
499    /// documentation.
500    ///
501    /// # Errors
502    ///
503    /// In addition to the possible reasons [`Self::ban`] may return an error, an
504    /// [`Error::ExceededLimit`] may also be returned if the reason is too long.
505    #[inline]
506    pub async fn ban_with_reason(
507        &self,
508        cache_http: impl CacheHttp,
509        user: impl Into<UserId>,
510        dmd: u8,
511        reason: impl AsRef<str>,
512    ) -> Result<()> {
513        self.ban_with_reason_(cache_http, user.into(), dmd, reason.as_ref()).await
514    }
515
516    async fn ban_with_reason_(
517        &self,
518        cache_http: impl CacheHttp,
519        user: UserId,
520        dmd: u8,
521        reason: &str,
522    ) -> Result<()> {
523        #[cfg(feature = "cache")]
524        {
525            if let Some(cache) = cache_http.cache() {
526                self.require_perms(cache, Permissions::BAN_MEMBERS)?;
527
528                self.check_hierarchy(cache, user)?;
529            }
530        }
531
532        self.id.ban_with_reason(cache_http.http(), user, dmd, reason).await
533    }
534
535    /// Bans multiple users from the guild, returning the users that were and weren't banned.
536    ///
537    /// # Errors
538    ///
539    /// See [`GuildId::bulk_ban`] for more information.
540    pub async fn bulk_ban(
541        &self,
542        cache_http: impl CacheHttp,
543        user_ids: &[UserId],
544        delete_message_seconds: u32,
545        reason: Option<&str>,
546    ) -> Result<BulkBanResponse> {
547        #[cfg(feature = "cache")]
548        {
549            if let Some(cache) = cache_http.cache() {
550                self.require_perms(cache, Permissions::BAN_MEMBERS & Permissions::MANAGE_GUILD)?;
551            }
552        }
553
554        self.id.bulk_ban(cache_http.http(), user_ids, delete_message_seconds, reason).await
555    }
556
557    /// Returns the formatted URL of the guild's banner image, if one exists.
558    #[must_use]
559    pub fn banner_url(&self) -> Option<String> {
560        self.banner.as_ref().map(|banner| cdn!("/banners/{}/{}.webp?size=1024", self.id, banner))
561    }
562
563    /// Gets a list of the guild's bans, with additional options and filtering. See
564    /// [`Http::get_bans`] for details.
565    ///
566    /// **Note**: Requires the [Ban Members] permission.
567    ///
568    /// # Errors
569    ///
570    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
571    /// does not have permission to perform bans.
572    ///
573    /// [Ban Members]: Permissions::BAN_MEMBERS
574    pub async fn bans(
575        &self,
576        cache_http: impl CacheHttp,
577        target: Option<UserPagination>,
578        limit: Option<u8>,
579    ) -> Result<Vec<Ban>> {
580        #[cfg(feature = "cache")]
581        {
582            if let Some(cache) = cache_http.cache() {
583                self.require_perms(cache, Permissions::BAN_MEMBERS)?;
584            }
585        }
586
587        self.id.bans(cache_http.http(), target, limit).await
588    }
589
590    /// Adds a [`User`] to this guild with a valid OAuth2 access token.
591    ///
592    /// Returns the created [`Member`] object, or nothing if the user is already a member of the
593    /// guild.
594    ///
595    /// # Errors
596    ///
597    /// Returns [`Error::Http`] if the current user lacks permission, or if invalid data is given.
598    #[inline]
599    pub async fn add_member(
600        &self,
601        cache_http: impl CacheHttp,
602        user_id: impl Into<UserId>,
603        builder: AddMember,
604    ) -> Result<Option<Member>> {
605        self.id.add_member(cache_http, user_id, builder).await
606    }
607
608    /// Retrieves a list of [`AuditLogs`] for the guild.
609    ///
610    /// **Note**: Requires the [View Audit Log] permission.
611    ///
612    /// # Errors
613    ///
614    /// Returns [`Error::Http`] if the current user does not have permission to view the audit log,
615    /// or if an invalid value is given.
616    ///
617    /// [View Audit Log]: Permissions::VIEW_AUDIT_LOG
618    #[inline]
619    pub async fn audit_logs(
620        &self,
621        http: impl AsRef<Http>,
622        action_type: Option<audit_log::Action>,
623        user_id: Option<UserId>,
624        before: Option<AuditLogEntryId>,
625        limit: Option<u8>,
626    ) -> Result<AuditLogs> {
627        self.id.audit_logs(http, action_type, user_id, before, limit).await
628    }
629
630    /// Gets all of the guild's channels over the REST API.
631    ///
632    /// # Errors
633    ///
634    /// Returns [`Error::Http`] if the guild is currently unavailable.
635    #[inline]
636    pub async fn channels(
637        &self,
638        http: impl AsRef<Http>,
639    ) -> Result<HashMap<ChannelId, GuildChannel>> {
640        self.id.channels(http).await
641    }
642
643    /// Creates a guild with the data provided.
644    ///
645    /// Only a [`PartialGuild`] will be immediately returned, and a full [`Guild`] will be received
646    /// over a [`Shard`].
647    ///
648    /// **Note**: This endpoint is usually only available for user accounts. Refer to Discord's
649    /// information for the endpoint [here][whitelist] for more information. If you require this as
650    /// a bot, re-think what you are doing and if it _really_ needs to be doing this.
651    ///
652    /// # Examples
653    ///
654    /// Create a guild called `"test"` in the [US West region] with no icon:
655    ///
656    /// ```rust,ignore
657    /// use serenity::model::Guild;
658    ///
659    /// let _guild = Guild::create_guild(&http, "test", None).await;
660    /// ```
661    ///
662    /// # Errors
663    ///
664    /// Returns [`Error::Http`] if the current user cannot create a Guild.
665    ///
666    /// [`Shard`]: crate::gateway::Shard
667    /// [whitelist]: https://discord.com/developers/docs/resources/guild#create-guild
668    pub async fn create(
669        http: impl AsRef<Http>,
670        name: &str,
671        icon: Option<ImageHash>,
672    ) -> Result<PartialGuild> {
673        let map = json!({
674            "icon": icon,
675            "name": name,
676        });
677
678        http.as_ref().create_guild(&map).await
679    }
680
681    /// Creates a new [`Channel`] in the guild.
682    ///
683    /// **Note**: Requires the [Manage Channels] permission.
684    ///
685    /// # Examples
686    ///
687    /// ```rust,no_run
688    /// # use serenity::http::Http;
689    /// # use serenity::model::guild::Guild;
690    /// # use serenity::model::id::GuildId;
691    /// use serenity::builder::CreateChannel;
692    /// use serenity::model::channel::ChannelType;
693    ///
694    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
695    /// # let http: Http = unimplemented!();
696    /// # let guild = Guild::get(&http, GuildId::new(7)).await?;
697    /// let builder = CreateChannel::new("my-test-channel").kind(ChannelType::Text);
698    ///
699    /// // assuming a `guild` has already been bound
700    /// let _channel = guild.create_channel(&http, builder).await?;
701    /// # Ok(())
702    /// # }
703    /// ```
704    ///
705    /// # Errors
706    ///
707    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
708    /// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
709    ///
710    /// [Manage Channels]: Permissions::MANAGE_CHANNELS
711    pub async fn create_channel(
712        &self,
713        cache_http: impl CacheHttp,
714        builder: CreateChannel<'_>,
715    ) -> Result<GuildChannel> {
716        self.id.create_channel(cache_http, builder).await
717    }
718
719    /// Creates an emoji in the guild with a name and base64-encoded image. The
720    /// [`CreateAttachment`] builder is provided for you as a simple method to read an image and
721    /// encode it into base64, if you are reading from the filesystem.
722    ///
723    /// The name of the emoji must be at least 2 characters long and can only contain alphanumeric
724    /// characters and underscores.
725    ///
726    /// Requires the [Create Guild Expressions] permission.
727    ///
728    /// # Examples
729    ///
730    /// See the [`EditProfile::avatar`] example for an in-depth example as to how to read an image
731    /// from the filesystem and encode it as base64. Most of the example can be applied similarly
732    /// for this method.
733    ///
734    /// # Errors
735    ///
736    /// Returns [`Error::Http`] if the current user lacks permission.
737    ///
738    /// [`EditProfile::avatar`]: crate::builder::EditProfile::avatar
739    /// [`CreateAttachment`]: crate::builder::CreateAttachment
740    /// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS
741    #[inline]
742    pub async fn create_emoji(
743        &self,
744        http: impl AsRef<Http>,
745        name: &str,
746        image: &str,
747    ) -> Result<Emoji> {
748        self.id.create_emoji(http, name, image).await
749    }
750
751    /// Creates an integration for the guild.
752    ///
753    /// Requires the [Manage Guild] permission.
754    ///
755    /// # Errors
756    ///
757    /// Returns [`Error::Http`] if the current user lacks permission.
758    ///
759    /// [Manage Guild]: Permissions::MANAGE_GUILD
760    #[inline]
761    pub async fn create_integration(
762        &self,
763        http: impl AsRef<Http>,
764        integration_id: impl Into<IntegrationId>,
765        kind: &str,
766    ) -> Result<()> {
767        self.id.create_integration(http, integration_id, kind).await
768    }
769
770    /// Create a guild specific application [`Command`].
771    ///
772    /// **Note**: Unlike global commands, guild commands will update instantly.
773    ///
774    /// # Errors
775    ///
776    /// See [`CreateCommand::execute`] for a list of possible errors.
777    ///
778    /// [`CreateCommand::execute`]: ../../builder/struct.CreateCommand.html#method.execute
779    #[inline]
780    pub async fn create_command(
781        &self,
782        cache_http: impl CacheHttp,
783        builder: CreateCommand,
784    ) -> Result<Command> {
785        self.id.create_command(cache_http, builder).await
786    }
787
788    /// Override all guild application commands.
789    ///
790    /// # Errors
791    ///
792    /// Returns the same errors as [`Self::create_command`].
793    pub async fn set_commands(
794        &self,
795        http: impl AsRef<Http>,
796        commands: Vec<CreateCommand>,
797    ) -> Result<Vec<Command>> {
798        self.id.set_commands(http, commands).await
799    }
800
801    /// Overwrites permissions for a specific command.
802    ///
803    /// **Note**: It will update instantly.
804    ///
805    /// # Errors
806    ///
807    /// See [`CreateCommandPermissionsData::execute`] for a list of possible errors.
808    ///
809    /// [`CreateCommandPermissionsData::execute`]: ../../builder/struct.CreateCommandPermissionsData.html#method.execute
810    pub async fn edit_command_permissions(
811        &self,
812        cache_http: impl CacheHttp,
813        command_id: CommandId,
814        builder: EditCommandPermissions,
815    ) -> Result<CommandPermissions> {
816        self.id.edit_command_permissions(cache_http, command_id, builder).await
817    }
818
819    /// Get all guild application commands.
820    ///
821    /// # Errors
822    ///
823    /// If there is an error, it will be either [`Error::Http`] or [`Error::Json`].
824    pub async fn get_commands(&self, http: impl AsRef<Http>) -> Result<Vec<Command>> {
825        self.id.get_commands(http).await
826    }
827
828    /// Get all guild application commands with localizations.
829    ///
830    /// # Errors
831    ///
832    /// If there is an error, it will be either [`Error::Http`] or [`Error::Json`].
833    pub async fn get_commands_with_localizations(
834        &self,
835        http: impl AsRef<Http>,
836    ) -> Result<Vec<Command>> {
837        self.id.get_commands_with_localizations(http).await
838    }
839
840    /// Get a specific guild application command by its Id.
841    ///
842    /// # Errors
843    ///
844    /// If there is an error, it will be either [`Error::Http`] or [`Error::Json`].
845    pub async fn get_command(
846        &self,
847        http: impl AsRef<Http>,
848        command_id: CommandId,
849    ) -> Result<Command> {
850        self.id.get_command(http, command_id).await
851    }
852
853    /// Edit a guild application command, given its Id.
854    ///
855    /// # Errors
856    ///
857    /// See [`CreateCommand::execute`] for a list of possible errors.
858    ///
859    /// [`CreateCommand::execute`]: ../../builder/struct.CreateCommand.html#method.execute
860    pub async fn edit_command(
861        &self,
862        cache_http: impl CacheHttp,
863        command_id: CommandId,
864        builder: CreateCommand,
865    ) -> Result<Command> {
866        self.id.edit_command(cache_http, command_id, builder).await
867    }
868
869    /// Delete guild application command by its Id.
870    ///
871    /// # Errors
872    ///
873    /// If there is an error, it will be either [`Error::Http`] or [`Error::Json`].
874    pub async fn delete_command(
875        &self,
876        http: impl AsRef<Http>,
877        command_id: CommandId,
878    ) -> Result<()> {
879        self.id.delete_command(http, command_id).await
880    }
881
882    /// Get all guild application commands permissions only.
883    ///
884    /// # Errors
885    ///
886    /// If there is an error, it will be either [`Error::Http`] or [`Error::Json`].
887    pub async fn get_commands_permissions(
888        &self,
889        http: impl AsRef<Http>,
890    ) -> Result<Vec<CommandPermissions>> {
891        self.id.get_commands_permissions(http).await
892    }
893
894    /// Get permissions for specific guild application command by its Id.
895    ///
896    /// # Errors
897    ///
898    /// If there is an error, it will be either [`Error::Http`] or [`Error::Json`].
899    pub async fn get_command_permissions(
900        &self,
901        http: impl AsRef<Http>,
902        command_id: CommandId,
903    ) -> Result<CommandPermissions> {
904        self.id.get_command_permissions(http, command_id).await
905    }
906
907    /// Creates a new role in the guild with the data set, if any.
908    ///
909    /// **Note**: Requires the [Manage Roles] permission.
910    ///
911    /// # Examples
912    ///
913    /// See the documentation for [`EditRole`] for details.
914    ///
915    /// # Errors
916    ///
917    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
918    /// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
919    ///
920    /// [Manage Roles]: Permissions::MANAGE_ROLES
921    pub async fn create_role(
922        &self,
923        cache_http: impl CacheHttp,
924        builder: EditRole<'_>,
925    ) -> Result<Role> {
926        self.id.create_role(cache_http, builder).await
927    }
928
929    /// Creates a new scheduled event in the guild with the data set, if any.
930    ///
931    /// **Note**: Requires the [Create Events] permission.
932    ///
933    /// # Errors
934    ///
935    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
936    /// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
937    ///
938    /// [Create Events]: Permissions::CREATE_EVENTS
939    pub async fn create_scheduled_event(
940        &self,
941        cache_http: impl CacheHttp,
942        builder: CreateScheduledEvent<'_>,
943    ) -> Result<ScheduledEvent> {
944        self.id.create_scheduled_event(cache_http, builder).await
945    }
946
947    /// Creates a new sticker in the guild with the data set, if any.
948    ///
949    /// **Note**: Requires the [Create Guild Expressions] permission.
950    ///
951    /// # Errors
952    ///
953    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
954    /// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
955    ///
956    /// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS
957    pub async fn create_sticker(
958        &self,
959        cache_http: impl CacheHttp,
960        builder: CreateSticker<'_>,
961    ) -> Result<Sticker> {
962        self.id.create_sticker(cache_http.http(), builder).await
963    }
964
965    /// Deletes the current guild if the current user is the owner of the
966    /// guild.
967    ///
968    /// **Note**: Requires the current user to be the owner of the guild.
969    ///
970    /// # Errors
971    ///
972    /// If the `cache` is enabled, then returns a [`ModelError::InvalidUser`] if the current user
973    /// is not the guild owner.
974    ///
975    /// Otherwise returns [`Error::Http`] if the current user is not the owner of the guild.
976    pub async fn delete(&self, cache_http: impl CacheHttp) -> Result<()> {
977        #[cfg(feature = "cache")]
978        {
979            if let Some(cache) = cache_http.cache() {
980                if self.owner_id != cache.current_user().id {
981                    return Err(Error::Model(ModelError::InvalidUser));
982                }
983            }
984        }
985
986        self.id.delete(cache_http.http()).await
987    }
988
989    /// Deletes an [`Emoji`] from the guild.
990    ///
991    /// **Note**: If the emoji was created by the current user, requires either the [Create Guild
992    /// Expressions] or the [Manage Guild Expressions] permission. Otherwise, the [Manage Guild
993    /// Expressions] permission is required.
994    ///
995    /// # Errors
996    ///
997    /// Returns [`Error::Http`] if the current user lacks permission, or if an emoji with the given
998    /// id does not exist in the guild.
999    ///
1000    /// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS
1001    /// [Manage Guild Expressions]: Permissions::MANAGE_GUILD_EXPRESSIONS
1002    #[inline]
1003    pub async fn delete_emoji(
1004        &self,
1005        http: impl AsRef<Http>,
1006        emoji_id: impl Into<EmojiId>,
1007    ) -> Result<()> {
1008        self.id.delete_emoji(http, emoji_id).await
1009    }
1010
1011    /// Deletes an integration by Id from the guild.
1012    ///
1013    /// Requires the [Manage Guild] permission.
1014    ///
1015    /// # Errors
1016    ///
1017    /// Returns an [`Error::Http`] if the current user lacks permission, or if an Integration with
1018    /// that Id does not exist.
1019    ///
1020    /// [Manage Guild]: Permissions::MANAGE_GUILD
1021    #[inline]
1022    pub async fn delete_integration(
1023        &self,
1024        http: impl AsRef<Http>,
1025        integration_id: impl Into<IntegrationId>,
1026    ) -> Result<()> {
1027        self.id.delete_integration(http, integration_id).await
1028    }
1029
1030    /// Deletes a [`Role`] by Id from the guild.
1031    ///
1032    /// Also see [`Role::delete`] if you have the `cache` and `model` features enabled.
1033    ///
1034    /// Requires the [Manage Roles] permission.
1035    ///
1036    /// # Errors
1037    ///
1038    /// Returns [`Error::Http`] if the current user lacks permission to delete the role.
1039    ///
1040    /// [Manage Roles]: Permissions::MANAGE_ROLES
1041    #[inline]
1042    pub async fn delete_role(
1043        &self,
1044        http: impl AsRef<Http>,
1045        role_id: impl Into<RoleId>,
1046    ) -> Result<()> {
1047        self.id.delete_role(http, role_id).await
1048    }
1049
1050    /// Deletes a [`ScheduledEvent`] by id from the guild.
1051    ///
1052    /// **Note**: If the event was created by the current user, requires either [Create Events] or
1053    /// the [Manage Events] permission. Otherwise, the [Manage Events] permission is required.
1054    ///
1055    /// # Errors
1056    ///
1057    /// Returns [`Error::Http`] if the current user lacks permission to delete the scheduled event.
1058    ///
1059    /// [Create Events]: Permissions::CREATE_EVENTS
1060    /// [Manage Events]: Permissions::MANAGE_EVENTS
1061    #[inline]
1062    pub async fn delete_scheduled_event(
1063        &self,
1064        http: impl AsRef<Http>,
1065        event_id: impl Into<ScheduledEventId>,
1066    ) -> Result<()> {
1067        self.id.delete_scheduled_event(http, event_id).await
1068    }
1069
1070    /// Deletes a [`Sticker`] by Id from the guild.
1071    ///
1072    /// **Note**: If the sticker was created by the current user, requires either the [Create Guild
1073    /// Expressions] or the [Manage Guild Expressions] permission. Otherwise, the [Manage Guild
1074    /// Expressions] permission is required.
1075    ///
1076    /// # Errors
1077    ///
1078    /// Returns [`Error::Http`] if the current user lacks permission, or if a sticker with that id
1079    /// does not exist.
1080    ///
1081    /// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS
1082    /// [Manage Guild Expressions]: Permissions::MANAGE_GUILD_EXPRESSIONS
1083    #[inline]
1084    pub async fn delete_sticker(
1085        &self,
1086        http: impl AsRef<Http>,
1087        sticker_id: impl Into<StickerId>,
1088    ) -> Result<()> {
1089        self.id.delete_sticker(http, sticker_id).await
1090    }
1091
1092    /// Edits the current guild with new data where specified.
1093    ///
1094    /// **Note**: Requires the [Manage Guild] permission.
1095    ///
1096    /// # Examples
1097    ///
1098    /// Change a guild's icon using a file named "icon.png":
1099    ///
1100    /// ```rust,no_run
1101    /// # use serenity::builder::{EditGuild, CreateAttachment};
1102    /// # use serenity::{http::Http, model::guild::Guild};
1103    /// #
1104    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
1105    /// # let http: Http = unimplemented!();
1106    /// # let mut guild: Guild = unimplemented!();
1107    /// let icon = CreateAttachment::path("./icon.png").await?;
1108    ///
1109    /// // assuming a `guild` has already been bound
1110    /// let builder = EditGuild::new().icon(Some(&icon));
1111    /// guild.edit(&http, builder).await?;
1112    /// # Ok(())
1113    /// # }
1114    /// ```
1115    ///
1116    /// # Errors
1117    ///
1118    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
1119    /// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
1120    ///
1121    /// [Manage Guild]: Permissions::MANAGE_GUILD
1122    pub async fn edit(&mut self, cache_http: impl CacheHttp, builder: EditGuild<'_>) -> Result<()> {
1123        let guild = self.id.edit(cache_http, builder).await?;
1124
1125        self.afk_metadata = guild.afk_metadata;
1126        self.default_message_notifications = guild.default_message_notifications;
1127        self.emojis = guild.emojis;
1128        self.features = guild.features;
1129        self.icon = guild.icon;
1130        self.mfa_level = guild.mfa_level;
1131        self.name = guild.name;
1132        self.owner_id = guild.owner_id;
1133        self.roles = guild.roles;
1134        self.splash = guild.splash;
1135        self.verification_level = guild.verification_level;
1136
1137        Ok(())
1138    }
1139
1140    /// Edits an [`Emoji`]'s name in the guild.
1141    ///
1142    /// Also see [`Emoji::edit`] if you have the `cache` and `model` features enabled.
1143    ///
1144    /// **Note**: If the emoji was created by the current user, requires either the [Create Guild
1145    /// Expressions] or the [Manage Guild Expressions] permission. Otherwise, the [Manage Guild
1146    /// Expressions] permission is required.
1147    ///
1148    /// # Errors
1149    ///
1150    /// Returns [`Error::Http`] if the current user lacks permission, or if an emoji with the given
1151    /// id does not exist.
1152    ///
1153    /// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS
1154    /// [Manage Guild Expressions]: Permissions::MANAGE_GUILD_EXPRESSIONS
1155    #[inline]
1156    pub async fn edit_emoji(
1157        &self,
1158        http: impl AsRef<Http>,
1159        emoji_id: impl Into<EmojiId>,
1160        name: &str,
1161    ) -> Result<Emoji> {
1162        self.id.edit_emoji(http, emoji_id, name).await
1163    }
1164
1165    /// Edits the properties a guild member, such as muting or nicknaming them. Returns the new
1166    /// member.
1167    ///
1168    /// Refer to the documentation of [`EditMember`] for a full list of methods and permission
1169    /// restrictions.
1170    ///
1171    /// # Examples
1172    ///
1173    /// See [`GuildId::edit_member`] for details.
1174    ///
1175    /// # Errors
1176    ///
1177    /// Returns [`Error::Http`] if the current user lacks permission, or if invalid data is given.
1178    #[inline]
1179    pub async fn edit_member(
1180        &self,
1181        cache_http: impl CacheHttp,
1182        user_id: impl Into<UserId>,
1183        builder: EditMember<'_>,
1184    ) -> Result<Member> {
1185        self.id.edit_member(cache_http, user_id, builder).await
1186    }
1187
1188    /// Edits the guild's MFA level. Returns the new level on success.
1189    ///
1190    /// Requires guild ownership.
1191    ///
1192    /// # Errors
1193    ///
1194    /// Returns [`Error::Http`] if the current user lacks permission.
1195    pub async fn edit_mfa_level(
1196        &self,
1197        http: impl AsRef<Http>,
1198        mfa_level: MfaLevel,
1199        audit_log_reason: Option<&str>,
1200    ) -> Result<MfaLevel> {
1201        self.id.edit_mfa_level(http, mfa_level, audit_log_reason).await
1202    }
1203
1204    /// Edits the current user's nickname for the guild.
1205    ///
1206    /// Pass [`None`] to reset the nickname.
1207    ///
1208    /// **Note**: Requires the [Change Nickname] permission.
1209    ///
1210    /// # Errors
1211    ///
1212    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
1213    /// does not have permission to change their own nickname.
1214    ///
1215    /// Otherwise will return [`Error::Http`] if the current user lacks permission.
1216    ///
1217    /// [Change Nickname]: Permissions::CHANGE_NICKNAME
1218    pub async fn edit_nickname(
1219        &self,
1220        cache_http: impl CacheHttp,
1221        new_nickname: Option<&str>,
1222    ) -> Result<()> {
1223        #[cfg(feature = "cache")]
1224        {
1225            if let Some(cache) = cache_http.cache() {
1226                self.require_perms(cache, Permissions::CHANGE_NICKNAME)?;
1227            }
1228        }
1229
1230        self.id.edit_nickname(cache_http.http(), new_nickname).await
1231    }
1232
1233    /// Edits a role, optionally setting its fields.
1234    ///
1235    /// **Note**: Requires the [Manage Roles] permission.
1236    ///
1237    /// # Examples
1238    ///
1239    /// See the documentation of [`GuildId::edit_role`] for details.
1240    ///
1241    /// # Errors
1242    ///
1243    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
1244    /// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
1245    ///
1246    /// [Manage Roles]: Permissions::MANAGE_ROLES
1247    #[inline]
1248    pub async fn edit_role(
1249        &self,
1250        cache_http: impl CacheHttp,
1251        role_id: impl Into<RoleId>,
1252        builder: EditRole<'_>,
1253    ) -> Result<Role> {
1254        self.id.edit_role(cache_http, role_id, builder).await
1255    }
1256
1257    /// Edits the order of [`Role`]s. Requires the [Manage Roles] permission.
1258    ///
1259    /// # Examples
1260    ///
1261    /// Change the order of a role:
1262    ///
1263    /// ```rust,ignore
1264    /// use serenity::model::id::RoleId;
1265    /// guild.edit_role_position(&context, RoleId::new(8), 2);
1266    /// ```
1267    ///
1268    /// # Errors
1269    ///
1270    /// Returns [`Error::Http`] if the current user lacks permission.
1271    ///
1272    /// [Manage Roles]: Permissions::MANAGE_ROLES
1273    #[inline]
1274    pub async fn edit_role_position(
1275        &self,
1276        http: impl AsRef<Http>,
1277        role_id: impl Into<RoleId>,
1278        position: u16,
1279    ) -> Result<Vec<Role>> {
1280        self.id.edit_role_position(http, role_id, position).await
1281    }
1282
1283    /// Modifies a scheduled event in the guild with the data set, if any.
1284    ///
1285    /// **Note**: If the event was created by the current user, requires either [Create Events] or
1286    /// the [Manage Events] permission. Otherwise, the [Manage Events] permission is required.
1287    ///
1288    /// # Errors
1289    ///
1290    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
1291    /// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
1292    ///
1293    /// [Create Events]: Permissions::CREATE_EVENTS
1294    /// [Manage Events]: Permissions::MANAGE_EVENTS
1295    pub async fn edit_scheduled_event(
1296        &self,
1297        cache_http: impl CacheHttp,
1298        event_id: impl Into<ScheduledEventId>,
1299        builder: EditScheduledEvent<'_>,
1300    ) -> Result<ScheduledEvent> {
1301        self.id.edit_scheduled_event(cache_http, event_id, builder).await
1302    }
1303
1304    /// Edits a sticker.
1305    ///
1306    /// **Note**: If the sticker was created by the current user, requires either the [Create Guild
1307    /// Expressions] or the [Manage Guild Expressions] permission. Otherwise, the [Manage Guild
1308    /// Expressions] permission is required.
1309    ///
1310    /// # Examples
1311    ///
1312    /// Rename a sticker:
1313    ///
1314    /// ```rust,no_run
1315    /// # use serenity::http::Http;
1316    /// # use serenity::model::guild::Guild;
1317    /// # use serenity::model::id::GuildId;
1318    /// use serenity::builder::EditSticker;
1319    /// use serenity::model::id::StickerId;
1320    ///
1321    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
1322    /// # let http: Http = unimplemented!();
1323    /// # let guild: Guild = unimplemented!();
1324    /// let builder = EditSticker::new().name("Bun bun meow");
1325    /// guild.edit_sticker(&http, StickerId::new(7), builder).await?;
1326    /// # Ok(())
1327    /// # }
1328    /// ```
1329    ///
1330    /// # Errors
1331    ///
1332    /// Returns [`Error::Http`] if the current user lacks permission, or if invalid data is given.
1333    ///
1334    /// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS
1335    /// [Manage Guild Expressions]: Permissions::MANAGE_GUILD_EXPRESSIONS
1336    #[inline]
1337    pub async fn edit_sticker(
1338        &self,
1339        cache_http: impl CacheHttp,
1340        sticker_id: impl Into<StickerId>,
1341        builder: EditSticker<'_>,
1342    ) -> Result<Sticker> {
1343        self.id.edit_sticker(cache_http, sticker_id, builder).await
1344    }
1345
1346    /// Edits the guild's welcome screen.
1347    ///
1348    /// **Note**: Requires the [Manage Guild] permission.
1349    ///
1350    /// # Errors
1351    ///
1352    /// Returns [`Error::Http`] if the current user lacks permission.
1353    ///
1354    /// [Manage Guild]: Permissions::MANAGE_GUILD
1355    pub async fn edit_welcome_screen(
1356        &self,
1357        cache_http: impl CacheHttp,
1358        builder: EditGuildWelcomeScreen<'_>,
1359    ) -> Result<GuildWelcomeScreen> {
1360        self.id.edit_welcome_screen(cache_http, builder).await
1361    }
1362
1363    /// Edits the guild's widget.
1364    ///
1365    /// **Note**: Requires the [Manage Guild] permission.
1366    ///
1367    /// # Errors
1368    ///
1369    /// Returns [`Error::Http`] if the current user lacks permission.
1370    ///
1371    /// [Manage Guild]: Permissions::MANAGE_GUILD
1372    pub async fn edit_widget(
1373        &self,
1374        cache_http: impl CacheHttp,
1375        builder: EditGuildWidget<'_>,
1376    ) -> Result<GuildWidget> {
1377        self.id.edit_widget(cache_http, builder).await
1378    }
1379
1380    /// Gets a partial amount of guild data by its Id.
1381    ///
1382    /// **Note**: This will not be a [`Guild`], as the REST API does not send all data with a guild
1383    /// retrieval.
1384    ///
1385    /// # Errors
1386    ///
1387    /// Returns an [`Error::Http`] if the current user is not in the guild.
1388    #[inline]
1389    pub async fn get(
1390        cache_http: impl CacheHttp,
1391        guild_id: impl Into<GuildId>,
1392    ) -> Result<PartialGuild> {
1393        guild_id.into().to_partial_guild(cache_http).await
1394    }
1395
1396    /// Gets the highest role a [`Member`] of this Guild has.
1397    ///
1398    /// Returns None if the member has no roles or the member from this guild.
1399    #[must_use]
1400    pub fn member_highest_role(&self, member: &Member) -> Option<&Role> {
1401        let mut highest: Option<&Role> = None;
1402
1403        for role_id in &member.roles {
1404            if let Some(role) = self.roles.get(role_id) {
1405                // Skip this role if this role in iteration has:
1406                // - a position less than the recorded highest
1407                // - a position equal to the recorded, but a higher ID
1408                if let Some(highest) = highest {
1409                    if role.position < highest.position
1410                        || (role.position == highest.position && role.id > highest.id)
1411                    {
1412                        continue;
1413                    }
1414                }
1415
1416                highest = Some(role);
1417            }
1418        }
1419
1420        highest
1421    }
1422
1423    /// Returns which of two [`User`]s has a higher [`Member`] hierarchy.
1424    ///
1425    /// Hierarchy is essentially who has the [`Role`] with the highest [`position`].
1426    ///
1427    /// Returns [`None`] if at least one of the given users' member instances is not present.
1428    /// Returns [`None`] if the users have the same hierarchy, as neither are greater than the
1429    /// other.
1430    ///
1431    /// If both user IDs are the same, [`None`] is returned. If one of the users is the guild
1432    /// owner, their ID is returned.
1433    ///
1434    /// [`position`]: Role::position
1435    #[cfg(feature = "cache")]
1436    #[inline]
1437    pub fn greater_member_hierarchy(
1438        &self,
1439        #[allow(unused_variables)] _cache: impl AsRef<Cache>,
1440        lhs_id: impl Into<UserId>,
1441        rhs_id: impl Into<UserId>,
1442    ) -> Option<UserId> {
1443        self.greater_member_hierarchy_(lhs_id.into(), rhs_id.into())
1444    }
1445
1446    #[cfg(feature = "cache")]
1447    fn greater_member_hierarchy_(&self, lhs_id: UserId, rhs_id: UserId) -> Option<UserId> {
1448        // Check that the IDs are the same. If they are, neither is greater.
1449        if lhs_id == rhs_id {
1450            return None;
1451        }
1452
1453        // Check if either user is the guild owner.
1454        if lhs_id == self.owner_id {
1455            return Some(lhs_id);
1456        } else if rhs_id == self.owner_id {
1457            return Some(rhs_id);
1458        }
1459
1460        let lhs = self
1461            .member_highest_role(self.members.get(&lhs_id)?)
1462            .map_or((RoleId::new(1), 0), |r| (r.id, r.position));
1463
1464        let rhs = self
1465            .member_highest_role(self.members.get(&rhs_id)?)
1466            .map_or((RoleId::new(1), 0), |r| (r.id, r.position));
1467
1468        // If LHS and RHS both have no top position or have the same role ID, then no one wins.
1469        if (lhs.1 == 0 && rhs.1 == 0) || (lhs.0 == rhs.0) {
1470            return None;
1471        }
1472
1473        // If LHS's top position is higher than RHS, then LHS wins.
1474        if lhs.1 > rhs.1 {
1475            return Some(lhs_id);
1476        }
1477
1478        // If RHS's top position is higher than LHS, then RHS wins.
1479        if rhs.1 > lhs.1 {
1480            return Some(rhs_id);
1481        }
1482
1483        // If LHS and RHS both have the same position, but LHS has the lower role ID, then LHS
1484        // wins.
1485        //
1486        // If RHS has the higher role ID, then RHS wins.
1487        if lhs.1 == rhs.1 && lhs.0 < rhs.0 {
1488            Some(lhs_id)
1489        } else {
1490            Some(rhs_id)
1491        }
1492    }
1493
1494    /// Returns the formatted URL of the guild's icon, if one exists.
1495    ///
1496    /// This will produce a WEBP image URL, or GIF if the guild has a GIF icon.
1497    #[must_use]
1498    pub fn icon_url(&self) -> Option<String> {
1499        icon_url(self.id, self.icon.as_ref())
1500    }
1501
1502    /// Gets all [`Emoji`]s of this guild via HTTP.
1503    ///
1504    /// # Errors
1505    ///
1506    /// Returns [`Error::Http`] if the guild is unavailable
1507    #[inline]
1508    pub async fn emojis(&self, http: impl AsRef<Http>) -> Result<Vec<Emoji>> {
1509        self.id.emojis(http).await
1510    }
1511
1512    /// Gets an [`Emoji`] of this guild by its ID via HTTP.
1513    ///
1514    /// # Errors
1515    ///
1516    /// Returns an [`Error::Http`] if an emoji with that id does not exist in the guild, or if the
1517    /// guild is unavailable.
1518    ///
1519    /// May also return [`Error::Json`] if there is an error in deserializing the API response.
1520    #[inline]
1521    pub async fn emoji(&self, http: impl AsRef<Http>, emoji_id: EmojiId) -> Result<Emoji> {
1522        self.id.emoji(http, emoji_id).await
1523    }
1524
1525    /// Gets all integration of the guild.
1526    ///
1527    /// **Note**: Requires the [Manage Guild] permission.
1528    ///
1529    /// # Errors
1530    ///
1531    /// Returns [`Error::Http`] if the current user does not have permission to see integrations.
1532    ///
1533    /// May also return [`Error::Json`] if there is an error in deserializing the API response.
1534    ///
1535    /// [Manage Guild]: Permissions::MANAGE_GUILD
1536    #[inline]
1537    pub async fn integrations(&self, http: impl AsRef<Http>) -> Result<Vec<Integration>> {
1538        self.id.integrations(http).await
1539    }
1540
1541    /// Retrieves the active invites for the guild.
1542    ///
1543    /// **Note**: Requires the [Manage Guild] permission.
1544    ///
1545    /// # Errors
1546    ///
1547    /// If the `cache` is enabled, returns [`ModelError::InvalidPermissions`] if the current user
1548    /// does not have permission to see invites.
1549    ///
1550    /// Otherwise will return [`Error::Http`] if the current user does not have permission.
1551    ///
1552    /// [Manage Guild]: Permissions::MANAGE_GUILD
1553    pub async fn invites(&self, cache_http: impl CacheHttp) -> Result<Vec<RichInvite>> {
1554        #[cfg(feature = "cache")]
1555        {
1556            if let Some(cache) = cache_http.cache() {
1557                self.require_perms(cache, Permissions::MANAGE_GUILD)?;
1558            }
1559        }
1560
1561        self.id.invites(cache_http.http()).await
1562    }
1563
1564    /// Checks if the guild is 'large'.
1565    ///
1566    /// A guild is considered large if it has more than 250 members.
1567    #[inline]
1568    #[must_use]
1569    #[deprecated = "Use Guild::large"]
1570    pub fn is_large(&self) -> bool {
1571        self.member_count > u64::from(LARGE_THRESHOLD)
1572    }
1573
1574    /// Kicks a [`Member`] from the guild.
1575    ///
1576    /// Requires the [Kick Members] permission.
1577    ///
1578    /// # Errors
1579    ///
1580    /// Returns [`Error::Http`] if the member cannot be kicked by the current user.
1581    ///
1582    /// [Kick Members]: Permissions::KICK_MEMBERS
1583    #[inline]
1584    pub async fn kick(&self, http: impl AsRef<Http>, user_id: impl Into<UserId>) -> Result<()> {
1585        self.id.kick(http, user_id).await
1586    }
1587
1588    /// # Errors
1589    ///
1590    /// In addition to the reasons [`Self::kick`] may return an error, may also return an error if
1591    /// the reason is too long.
1592    #[inline]
1593    pub async fn kick_with_reason(
1594        &self,
1595        http: impl AsRef<Http>,
1596        user_id: impl Into<UserId>,
1597        reason: &str,
1598    ) -> Result<()> {
1599        self.id.kick_with_reason(http, user_id, reason).await
1600    }
1601
1602    /// Returns a guild [`Member`] object for the current user.
1603    ///
1604    /// See [`Http::get_current_user_guild_member`] for more.
1605    ///
1606    /// # Errors
1607    ///
1608    /// Returns an [`Error::Http`] if the current user is not in the guild or the access token
1609    /// lacks the necessary scope.
1610    #[inline]
1611    pub async fn current_user_member(&self, http: impl AsRef<Http>) -> Result<Member> {
1612        self.id.current_user_member(http).await
1613    }
1614
1615    /// Leaves the guild.
1616    ///
1617    /// # Errors
1618    ///
1619    /// May return an [`Error::Http`] if the current user cannot leave the guild, or currently is
1620    /// not in the guild.
1621    #[inline]
1622    pub async fn leave(&self, http: impl AsRef<Http>) -> Result<()> {
1623        self.id.leave(http).await
1624    }
1625
1626    /// Gets a user's [`Member`] for the guild by Id.
1627    ///
1628    /// If the cache feature is enabled [`Self::members`] will be checked first, if so, a reference
1629    /// to the member will be returned.
1630    ///
1631    /// # Errors
1632    ///
1633    /// Returns an [`Error::Http`] if the user is not in the guild or if the guild is otherwise
1634    /// unavailable.
1635    #[inline]
1636    pub async fn member(
1637        &self,
1638        cache_http: impl CacheHttp,
1639        user_id: impl Into<UserId>,
1640    ) -> Result<Cow<'_, Member>> {
1641        let user_id = user_id.into();
1642
1643        if let Some(member) = self.members.get(&user_id) {
1644            Ok(Cow::Borrowed(member))
1645        } else {
1646            cache_http.http().get_member(self.id, user_id).await.map(Cow::Owned)
1647        }
1648    }
1649
1650    /// Gets a list of the guild's members.
1651    ///
1652    /// Optionally pass in the `limit` to limit the number of results. Minimum value is 1, maximum
1653    /// and default value is 1000.
1654    ///
1655    /// Optionally pass in `after` to offset the results by a [`User`]'s Id.
1656    ///
1657    /// # Errors
1658    ///
1659    /// Returns an [`Error::Http`] if the API returns an error, may also return
1660    /// [`Error::NotInRange`] if the input is not within range.
1661    ///
1662    /// [`User`]: crate::model::user::User
1663    #[inline]
1664    pub async fn members(
1665        &self,
1666        http: impl AsRef<Http>,
1667        limit: Option<u64>,
1668        after: impl Into<Option<UserId>>,
1669    ) -> Result<Vec<Member>> {
1670        self.id.members(http, limit, after).await
1671    }
1672
1673    /// Gets a list of all the members (satisfying the status provided to the function) in this
1674    /// guild.
1675    pub fn members_with_status(&self, status: OnlineStatus) -> impl Iterator<Item = &Member> {
1676        self.members.iter().filter_map(move |(id, member)| match self.presences.get(id) {
1677            Some(presence) if presence.status == status => Some(member),
1678            _ => None,
1679        })
1680    }
1681
1682    /// Retrieves the first [`Member`] found that matches the name - with an optional discriminator
1683    /// - provided.
1684    ///
1685    /// Searching with a discriminator given is the most precise form of lookup, as no two people
1686    /// can share the same username *and* discriminator.
1687    ///
1688    /// If a member can not be found by username or username#discriminator, then a search will be
1689    /// done for the nickname. When searching by nickname, the hash (`#`) and everything after it
1690    /// is included in the search.
1691    ///
1692    /// The following are valid types of searches:
1693    /// - **username**: "zey"
1694    /// - **username and discriminator**: "zey#5479"
1695    ///
1696    /// **Note**: This will only search members that are cached. If you want to search all members
1697    /// in the guild via the Http API, use [`Self::search_members`].
1698    #[must_use]
1699    pub fn member_named(&self, name: &str) -> Option<&Member> {
1700        let (username, discrim) = match crate::utils::parse_user_tag(name) {
1701            Some((username, discrim)) => (username, Some(discrim)),
1702            None => (name, None),
1703        };
1704
1705        for member in self.members.values() {
1706            if member.user.name == username
1707                && discrim.map_or(true, |d| member.user.discriminator == d)
1708            {
1709                return Some(member);
1710            }
1711        }
1712
1713        self.members.values().find(|member| member.nick.as_ref().is_some_and(|nick| nick == name))
1714    }
1715
1716    /// Retrieves all [`Member`] that start with a given [`String`].
1717    ///
1718    /// `sorted` decides whether the best early match of the `prefix` should be the criteria to
1719    /// sort the result.
1720    ///
1721    /// For the `prefix` "zey" and the unsorted result:
1722    /// - "zeya", "zeyaa", "zeyla", "zeyzey", "zeyzeyzey"
1723    ///
1724    /// It would be sorted:
1725    /// - "zeya", "zeyaa", "zeyla", "zeyzey", "zeyzeyzey"
1726    ///
1727    /// **Note**: This will only search members that are cached. If you want to search all members
1728    /// in the guild via the Http API, use [`Self::search_members`].
1729    #[must_use]
1730    pub fn members_starting_with(
1731        &self,
1732        prefix: &str,
1733        case_sensitive: bool,
1734        sorted: bool,
1735    ) -> Vec<(&Member, String)> {
1736        fn starts_with(name: &str, prefix: &str, case_sensitive: bool) -> bool {
1737            if case_sensitive {
1738                name.starts_with(prefix)
1739            } else {
1740                name.to_lowercase().starts_with(&prefix.to_lowercase())
1741            }
1742        }
1743
1744        let mut members = self
1745            .members
1746            .values()
1747            .filter_map(|member| {
1748                let username = &member.user.name;
1749
1750                if starts_with(username, prefix, case_sensitive) {
1751                    Some((member, username.clone()))
1752                } else {
1753                    match &member.nick {
1754                        Some(nick) => starts_with(nick, prefix, case_sensitive)
1755                            .then(|| (member, nick.clone())),
1756                        None => None,
1757                    }
1758                }
1759            })
1760            .collect::<Vec<(&Member, String)>>();
1761
1762        if sorted {
1763            members.sort_by(|a, b| closest_to_origin(prefix, &a.1[..], &b.1[..]));
1764        }
1765
1766        members
1767    }
1768
1769    /// Retrieves all [`Member`] containing a given [`String`] as either username or nick, with a
1770    /// priority on username.
1771    ///
1772    /// If the substring is "yla", following results are possible:
1773    /// - "zeyla", "meiyla", "yladenisyla"
1774    ///
1775    /// If 'case_sensitive' is false, the following are not found:
1776    /// - "zeYLa", "meiyLa", "LYAdenislyA"
1777    ///
1778    /// `sorted` decides whether the best early match of the search-term should be the criteria to
1779    /// sort the result. It will look at the account name first, if that does not fit the
1780    /// search-criteria `substring`, the display-name will be considered.
1781    ///
1782    /// For the `substring` "zey" and the unsorted result:
1783    /// - "azey", "zey", "zeyla", "zeylaa", "zeyzeyzey"
1784    ///
1785    /// It would be sorted:
1786    /// - "zey", "azey", "zeyla", "zeylaa", "zeyzeyzey"
1787    ///
1788    /// **Note**: Due to two fields of a [`Member`] being candidates for the searched field,
1789    /// setting `sorted` to `true` will result in an overhead, as both fields have to be considered
1790    /// again for sorting.
1791    ///
1792    /// **Note**: This will only search members that are cached. If you want to search all members
1793    /// in the guild via the Http API, use [`Self::search_members`].
1794    #[must_use]
1795    pub fn members_containing(
1796        &self,
1797        substring: &str,
1798        case_sensitive: bool,
1799        sorted: bool,
1800    ) -> Vec<(&Member, String)> {
1801        let mut members = self
1802            .members
1803            .values()
1804            .filter_map(|member| {
1805                let username = &member.user.name;
1806
1807                if contains(username, substring, case_sensitive) {
1808                    Some((member, username.clone()))
1809                } else {
1810                    match &member.nick {
1811                        Some(nick) => contains(nick, substring, case_sensitive)
1812                            .then(|| (member, nick.clone())),
1813                        None => None,
1814                    }
1815                }
1816            })
1817            .collect::<Vec<(&Member, String)>>();
1818
1819        if sorted {
1820            members.sort_by(|a, b| closest_to_origin(substring, &a.1[..], &b.1[..]));
1821        }
1822
1823        members
1824    }
1825
1826    /// Retrieves a tuple of [`Member`]s containing a given [`String`] in their username as the
1827    /// first field and the name used for sorting as the second field.
1828    ///
1829    /// If the substring is "yla", following results are possible:
1830    /// - "zeyla", "meiyla", "yladenisyla"
1831    ///
1832    /// If 'case_sensitive' is false, the following are not found:
1833    /// - "zeYLa", "meiyLa", "LYAdenislyA"
1834    ///
1835    /// `sort` decides whether the best early match of the search-term should be the criteria to
1836    /// sort the result.
1837    ///
1838    /// For the `substring` "zey" and the unsorted result:
1839    /// - "azey", "zey", "zeyla", "zeylaa", "zeyzeyzey"
1840    ///
1841    /// It would be sorted:
1842    /// - "zey", "azey", "zeyla", "zeylaa", "zeyzeyzey"
1843    ///
1844    /// **Note**: This will only search members that are cached. If you want to search all members
1845    /// in the guild via the Http API, use [`Self::search_members`].
1846    #[must_use]
1847    pub fn members_username_containing(
1848        &self,
1849        substring: &str,
1850        case_sensitive: bool,
1851        sorted: bool,
1852    ) -> Vec<(&Member, String)> {
1853        let mut members = self
1854            .members
1855            .values()
1856            .filter_map(|member| {
1857                let name = &member.user.name;
1858                contains(name, substring, case_sensitive).then(|| (member, name.clone()))
1859            })
1860            .collect::<Vec<(&Member, String)>>();
1861
1862        if sorted {
1863            members.sort_by(|a, b| closest_to_origin(substring, &a.1[..], &b.1[..]));
1864        }
1865
1866        members
1867    }
1868
1869    /// Retrieves all [`Member`] containing a given [`String`] in their nick.
1870    ///
1871    /// If the substring is "yla", following results are possible:
1872    /// - "zeyla", "meiyla", "yladenisyla"
1873    ///
1874    /// If 'case_sensitive' is false, the following are not found:
1875    /// - "zeYLa", "meiyLa", "LYAdenislyA"
1876    ///
1877    /// `sort` decides whether the best early match of the search-term should be the criteria to
1878    /// sort the result.
1879    ///
1880    /// For the `substring` "zey" and the unsorted result:
1881    /// - "azey", "zey", "zeyla", "zeylaa", "zeyzeyzey"
1882    ///
1883    /// It would be sorted:
1884    /// - "zey", "azey", "zeyla", "zeylaa", "zeyzeyzey"
1885    ///
1886    /// **Note**: Instead of panicking, when sorting does not find a nick, the username will be
1887    /// used (this should never happen).
1888    ///
1889    /// **Note**: This will only search members that are cached. If you want to search all members
1890    /// in the guild via the Http API, use [`Self::search_members`].
1891    #[must_use]
1892    pub fn members_nick_containing(
1893        &self,
1894        substring: &str,
1895        case_sensitive: bool,
1896        sorted: bool,
1897    ) -> Vec<(&Member, String)> {
1898        let mut members = self
1899            .members
1900            .values()
1901            .filter_map(|member| {
1902                let nick = member.nick.as_ref().unwrap_or(&member.user.name);
1903                contains(nick, substring, case_sensitive).then(|| (member, nick.clone()))
1904            })
1905            .collect::<Vec<(&Member, String)>>();
1906
1907        if sorted {
1908            members.sort_by(|a, b| closest_to_origin(substring, &a.1[..], &b.1[..]));
1909        }
1910
1911        members
1912    }
1913
1914    /// Calculate a [`Member`]'s permissions in the guild.
1915    #[inline]
1916    #[must_use]
1917    #[deprecated = "Use Guild::member_permissions_in, as this doesn't consider permission overwrites"]
1918    pub fn member_permissions(&self, member: &Member) -> Permissions {
1919        Self::user_permissions_in_(
1920            None,
1921            member.user.id,
1922            &member.roles,
1923            self.id,
1924            &self.roles,
1925            self.owner_id,
1926        )
1927    }
1928
1929    /// Calculate a [`PartialMember`]'s permissions in the guild.
1930    ///
1931    /// # Panics
1932    ///
1933    /// Panics if the passed [`UserId`] does not match the [`PartialMember`] id, if user is Some.
1934    #[inline]
1935    #[must_use]
1936    #[deprecated = "Use Guild::partial_member_permissions_in, as this doesn't consider permission overwrites"]
1937    pub fn partial_member_permissions(
1938        &self,
1939        member_id: UserId,
1940        member: &PartialMember,
1941    ) -> Permissions {
1942        if let Some(user) = &member.user {
1943            assert_eq!(user.id, member_id, "User::id does not match provided PartialMember");
1944        }
1945
1946        Self::user_permissions_in_(
1947            None,
1948            member_id,
1949            &member.roles,
1950            self.id,
1951            &self.roles,
1952            self.owner_id,
1953        )
1954    }
1955
1956    /// Moves a member to a specific voice channel.
1957    ///
1958    /// Requires the [Move Members] permission.
1959    ///
1960    /// # Errors
1961    ///
1962    /// Returns an [`Error::Http`] if the current user lacks permission, or if the member is not
1963    /// currently in a voice channel for this [`Guild`].
1964    ///
1965    /// [Move Members]: Permissions::MOVE_MEMBERS
1966    #[inline]
1967    pub async fn move_member(
1968        &self,
1969        cache_http: impl CacheHttp,
1970        user_id: impl Into<UserId>,
1971        channel_id: impl Into<ChannelId>,
1972    ) -> Result<Member> {
1973        self.id.move_member(cache_http, user_id, channel_id).await
1974    }
1975
1976    /// Calculate a [`Member`]'s permissions in a given channel in the guild.
1977    #[inline]
1978    #[must_use]
1979    pub fn user_permissions_in(&self, channel: &GuildChannel, member: &Member) -> Permissions {
1980        Self::user_permissions_in_(
1981            Some(channel),
1982            member.user.id,
1983            &member.roles,
1984            self.id,
1985            &self.roles,
1986            self.owner_id,
1987        )
1988    }
1989
1990    /// Calculate a [`PartialMember`]'s permissions in a given channel in a guild.
1991    ///
1992    /// # Panics
1993    ///
1994    /// Panics if the passed [`UserId`] does not match the [`PartialMember`] id, if user is Some.
1995    #[must_use]
1996    pub fn partial_member_permissions_in(
1997        &self,
1998        channel: &GuildChannel,
1999        member_id: UserId,
2000        member: &PartialMember,
2001    ) -> Permissions {
2002        if let Some(user) = &member.user {
2003            assert_eq!(user.id, member_id, "User::id does not match provided PartialMember");
2004        }
2005
2006        Self::user_permissions_in_(
2007            Some(channel),
2008            member_id,
2009            &member.roles,
2010            self.id,
2011            &self.roles,
2012            self.owner_id,
2013        )
2014    }
2015
2016    /// Helper function that can also be used from [`PartialGuild`].
2017    pub(crate) fn user_permissions_in_(
2018        channel: Option<&GuildChannel>,
2019        member_user_id: UserId,
2020        member_roles: &[RoleId],
2021        guild_id: GuildId,
2022        guild_roles: &HashMap<RoleId, Role>,
2023        guild_owner_id: UserId,
2024    ) -> Permissions {
2025        let mut everyone_allow_overwrites = Permissions::empty();
2026        let mut everyone_deny_overwrites = Permissions::empty();
2027        let mut roles_allow_overwrites = Vec::new();
2028        let mut roles_deny_overwrites = Vec::new();
2029        let mut member_allow_overwrites = Permissions::empty();
2030        let mut member_deny_overwrites = Permissions::empty();
2031
2032        if let Some(channel) = channel {
2033            for overwrite in &channel.permission_overwrites {
2034                match overwrite.kind {
2035                    PermissionOverwriteType::Member(user_id) => {
2036                        if member_user_id == user_id {
2037                            member_allow_overwrites = overwrite.allow;
2038                            member_deny_overwrites = overwrite.deny;
2039                        }
2040                    },
2041                    PermissionOverwriteType::Role(role_id) => {
2042                        if role_id.get() == guild_id.get() {
2043                            everyone_allow_overwrites = overwrite.allow;
2044                            everyone_deny_overwrites = overwrite.deny;
2045                        } else if member_roles.contains(&role_id) {
2046                            roles_allow_overwrites.push(overwrite.allow);
2047                            roles_deny_overwrites.push(overwrite.deny);
2048                        }
2049                    },
2050                }
2051            }
2052        }
2053
2054        calculate_permissions(CalculatePermissions {
2055            is_guild_owner: member_user_id == guild_owner_id,
2056            everyone_permissions: if let Some(role) = guild_roles.get(&RoleId::new(guild_id.get()))
2057            {
2058                role.permissions
2059            } else {
2060                error!("@everyone role missing in {}", guild_id);
2061                Permissions::empty()
2062            },
2063            user_roles_permissions: member_roles
2064                .iter()
2065                .map(|role_id| {
2066                    if let Some(role) = guild_roles.get(role_id) {
2067                        role.permissions
2068                    } else {
2069                        warn!(
2070                            "{} on {} has non-existent role {:?}",
2071                            member_user_id, guild_id, role_id
2072                        );
2073                        Permissions::empty()
2074                    }
2075                })
2076                .collect(),
2077            everyone_allow_overwrites,
2078            everyone_deny_overwrites,
2079            roles_allow_overwrites,
2080            roles_deny_overwrites,
2081            member_allow_overwrites,
2082            member_deny_overwrites,
2083        })
2084    }
2085
2086    /// Calculate a [`Role`]'s permissions in a given channel in the guild.
2087    ///
2088    /// # Errors
2089    ///
2090    /// Will return an [`Error::Model`] if the [`Role`] or [`Channel`] is not from this [`Guild`].
2091    #[inline]
2092    #[deprecated = "this function ignores other roles the user may have as well as user-specific permissions; use user_permissions_in instead"]
2093    pub fn role_permissions_in(&self, channel: &GuildChannel, role: &Role) -> Result<Permissions> {
2094        Self::role_permissions_in_(channel, role, self.id)
2095    }
2096
2097    /// Helper function that can also be used from [`PartialGuild`].
2098    pub(crate) fn role_permissions_in_(
2099        channel: &GuildChannel,
2100        role: &Role,
2101        guild_id: GuildId,
2102    ) -> Result<Permissions> {
2103        // Fail if the role or channel is not from this guild.
2104        if role.guild_id != guild_id || channel.guild_id != guild_id {
2105            return Err(Error::Model(ModelError::WrongGuild));
2106        }
2107
2108        let mut permissions = role.permissions;
2109
2110        if permissions.contains(Permissions::ADMINISTRATOR) {
2111            return Ok(Self::remove_unnecessary_voice_permissions(channel, Permissions::all()));
2112        }
2113
2114        for overwrite in &channel.permission_overwrites {
2115            if let PermissionOverwriteType::Role(permissions_role_id) = overwrite.kind {
2116                if permissions_role_id == role.id {
2117                    permissions = (permissions & !overwrite.deny) | overwrite.allow;
2118
2119                    break;
2120                }
2121            }
2122        }
2123
2124        Self::remove_unusable_permissions(&mut permissions);
2125
2126        Ok(permissions)
2127    }
2128
2129    /// Retrieves the count of the number of [`Member`]s that would be pruned with the number of
2130    /// given days.
2131    ///
2132    /// See the documentation on [`GuildPrune`] for more information.
2133    ///
2134    /// **Note**: Requires the [Kick Members] permission.
2135    ///
2136    /// # Errors
2137    ///
2138    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
2139    /// does not have permission to kick members.
2140    ///
2141    /// Otherwise may return [`Error::Http`] if the current user does not have permission. Can also
2142    /// return [`Error::Json`] if there is an error in deserializing the API response.
2143    ///
2144    /// [Kick Members]: Permissions::KICK_MEMBERS
2145    /// [`Error::Http`]: crate::error::Error::Http
2146    /// [`Error::Json`]: crate::error::Error::Json
2147    pub async fn prune_count(&self, cache_http: impl CacheHttp, days: u8) -> Result<GuildPrune> {
2148        #[cfg(feature = "cache")]
2149        {
2150            if let Some(cache) = cache_http.cache() {
2151                self.require_perms(cache, Permissions::KICK_MEMBERS)?;
2152            }
2153        }
2154
2155        self.id.prune_count(cache_http.http(), days).await
2156    }
2157
2158    pub(crate) fn remove_unusable_permissions(permissions: &mut Permissions) {
2159        // No SEND_MESSAGES => no message-sending-related actions
2160        // If the member does not have the `SEND_MESSAGES` permission, then throw out message-able
2161        // permissions.
2162        if !permissions.contains(Permissions::SEND_MESSAGES) {
2163            *permissions &= !(Permissions::SEND_TTS_MESSAGES
2164                | Permissions::MENTION_EVERYONE
2165                | Permissions::EMBED_LINKS
2166                | Permissions::ATTACH_FILES);
2167        }
2168
2169        // If the permission does not have the `VIEW_CHANNEL` permission, then throw out actionable
2170        // permissions.
2171        if !permissions.contains(Permissions::VIEW_CHANNEL) {
2172            *permissions &= !(Permissions::KICK_MEMBERS
2173                | Permissions::BAN_MEMBERS
2174                | Permissions::ADMINISTRATOR
2175                | Permissions::MANAGE_GUILD
2176                | Permissions::CHANGE_NICKNAME
2177                | Permissions::MANAGE_NICKNAMES);
2178        }
2179    }
2180
2181    pub(crate) fn remove_unnecessary_voice_permissions(
2182        channel: &GuildChannel,
2183        mut permissions: Permissions,
2184    ) -> Permissions {
2185        // If this is a text channel, then throw out voice permissions.
2186        if channel.kind == ChannelType::Text {
2187            permissions &= !(Permissions::CONNECT
2188                | Permissions::SPEAK
2189                | Permissions::MUTE_MEMBERS
2190                | Permissions::DEAFEN_MEMBERS
2191                | Permissions::MOVE_MEMBERS
2192                | Permissions::USE_VAD
2193                | Permissions::STREAM);
2194        }
2195
2196        permissions
2197    }
2198
2199    /// Re-orders the channels of the guild.
2200    ///
2201    /// Although not required, you should specify all channels' positions, regardless of whether
2202    /// they were updated. Otherwise, positioning can sometimes get weird.
2203    ///
2204    /// **Note**: Requires the [Manage Channels] permission.
2205    ///
2206    /// # Errors
2207    ///
2208    /// Returns an [`Error::Http`] if the current user is lacking permission.
2209    ///
2210    /// [Manage Channels]: Permissions::MANAGE_CHANNELS
2211    #[inline]
2212    pub async fn reorder_channels(
2213        &self,
2214        http: impl AsRef<Http>,
2215        channels: impl IntoIterator<Item = (ChannelId, u64)>,
2216    ) -> Result<()> {
2217        self.id.reorder_channels(http, channels).await
2218    }
2219
2220    /// Returns a list of [`Member`]s in a [`Guild`] whose username or nickname starts with a
2221    /// provided string.
2222    ///
2223    /// Optionally pass in the `limit` to limit the number of results. Minimum value is 1, maximum
2224    /// and default value is 1000.
2225    ///
2226    /// **Note**: Queries are case insensitive.
2227    ///
2228    /// # Errors
2229    ///
2230    /// Returns an [`Error::Http`] if the API returns an error.
2231    #[inline]
2232    pub async fn search_members(
2233        &self,
2234        http: impl AsRef<Http>,
2235        query: &str,
2236        limit: Option<u64>,
2237    ) -> Result<Vec<Member>> {
2238        self.id.search_members(http, query, limit).await
2239    }
2240
2241    /// Fetches a specified scheduled event in the guild, by Id. If `with_user_count` is set to
2242    /// `true`, then the `user_count` field will be populated, indicating the number of users
2243    /// interested in the event.
2244    ///
2245    /// **Note**: Requires the [View Channel] permission for the channel associated with the event.
2246    ///
2247    /// # Errors
2248    ///
2249    /// Returns [`Error::Http`] if the current user lacks permission, or if the provided id is
2250    /// invalid.
2251    ///
2252    /// [View Channel]: Permissions::VIEW_CHANNEL
2253    pub async fn scheduled_event(
2254        &self,
2255        http: impl AsRef<Http>,
2256        event_id: impl Into<ScheduledEventId>,
2257        with_user_count: bool,
2258    ) -> Result<ScheduledEvent> {
2259        self.id.scheduled_event(http, event_id, with_user_count).await
2260    }
2261
2262    /// Fetches a list of all scheduled events in the guild. If `with_user_count` is set to `true`,
2263    /// then each event returned will have its `user_count` field populated.
2264    ///
2265    /// **Note**: Requires the [View Channel] permission at the guild level.
2266    ///
2267    /// # Errors
2268    ///
2269    /// Returns [`Error::Http`] if the current user lacks permission.
2270    ///
2271    /// [View Channel]: Permissions::VIEW_CHANNEL
2272    pub async fn scheduled_events(
2273        &self,
2274        http: impl AsRef<Http>,
2275        with_user_count: bool,
2276    ) -> Result<Vec<ScheduledEvent>> {
2277        self.id.scheduled_events(http, with_user_count).await
2278    }
2279
2280    /// Fetches a list of interested users for the specified event.
2281    ///
2282    /// If `limit` is left unset, by default at most 100 users are returned.
2283    ///
2284    /// **Note**: Requires the [View Channel] permission for the channel associated with the event.
2285    ///
2286    /// # Errors
2287    ///
2288    /// Returns [`Error::Http`] if the current user lacks permission, or if the provided Id is
2289    /// invalid.
2290    ///
2291    /// [View Channel]: Permissions::VIEW_CHANNEL
2292    pub async fn scheduled_event_users(
2293        &self,
2294        http: impl AsRef<Http>,
2295        event_id: impl Into<ScheduledEventId>,
2296        limit: Option<u64>,
2297    ) -> Result<Vec<ScheduledEventUser>> {
2298        self.id.scheduled_event_users(http, event_id, limit).await
2299    }
2300
2301    /// Fetches a list of interested users for the specified event, with additional options and
2302    /// filtering. See [`Http::get_scheduled_event_users`] for details.
2303    ///
2304    /// **Note**: Requires the [View Channel] permission for the channel associated with the event.
2305    ///
2306    /// # Errors
2307    ///
2308    /// Returns [`Error::Http`] if the current user lacks permission, or if the provided Id is
2309    /// invalid.
2310    ///
2311    /// [View Channel]: Permissions::VIEW_CHANNEL
2312    pub async fn scheduled_event_users_optioned(
2313        &self,
2314        http: impl AsRef<Http>,
2315        event_id: impl Into<ScheduledEventId>,
2316        limit: Option<u64>,
2317        target: Option<UserPagination>,
2318        with_member: Option<bool>,
2319    ) -> Result<Vec<ScheduledEventUser>> {
2320        self.id.scheduled_event_users_optioned(http, event_id, limit, target, with_member).await
2321    }
2322
2323    /// Returns the Id of the shard associated with the guild.
2324    ///
2325    /// When the cache is enabled this will automatically retrieve the total number of shards.
2326    ///
2327    /// **Note**: When the cache is enabled, this function unlocks the cache to retrieve the total
2328    /// number of shards in use. If you already have the total, consider using [`utils::shard_id`].
2329    ///
2330    /// [`utils::shard_id`]: crate::utils::shard_id
2331    #[cfg(all(feature = "cache", feature = "utils"))]
2332    #[inline]
2333    pub fn shard_id(&self, cache: impl AsRef<Cache>) -> u32 {
2334        self.id.shard_id(&cache)
2335    }
2336
2337    /// Returns the Id of the shard associated with the guild.
2338    ///
2339    /// When the cache is enabled this will automatically retrieve the total number of shards.
2340    ///
2341    /// When the cache is not enabled, the total number of shards being used will need to be
2342    /// passed.
2343    ///
2344    /// # Examples
2345    ///
2346    /// Retrieve the Id of the shard for a guild with Id `81384788765712384`, using 17 shards:
2347    ///
2348    /// ```rust,ignore
2349    /// use serenity::utils;
2350    ///
2351    /// // assumes a `guild` has already been bound
2352    ///
2353    /// assert_eq!(guild.shard_id(17), 7);
2354    /// ```
2355    #[cfg(all(feature = "utils", not(feature = "cache")))]
2356    #[inline]
2357    #[must_use]
2358    pub fn shard_id(&self, shard_count: u32) -> u32 {
2359        self.id.shard_id(shard_count)
2360    }
2361
2362    /// Returns the formatted URL of the guild's splash image, if one exists.
2363    #[must_use]
2364    pub fn splash_url(&self) -> Option<String> {
2365        self.splash.as_ref().map(|splash| cdn!("/splashes/{}/{}.webp?size=4096", self.id, splash))
2366    }
2367
2368    /// Starts an integration sync for the given integration Id.
2369    ///
2370    /// Requires the [Manage Guild] permission.
2371    ///
2372    /// # Errors
2373    ///
2374    /// Returns an [`Error::Http`] if the current user does not have permission, or if an
2375    /// [`Integration`] with that Id does not exist.
2376    ///
2377    /// [Manage Guild]: Permissions::MANAGE_GUILD
2378    #[inline]
2379    pub async fn start_integration_sync(
2380        &self,
2381        http: impl AsRef<Http>,
2382        integration_id: impl Into<IntegrationId>,
2383    ) -> Result<()> {
2384        self.id.start_integration_sync(http, integration_id).await
2385    }
2386
2387    /// Starts a prune of [`Member`]s.
2388    ///
2389    /// See the documentation on [`GuildPrune`] for more information.
2390    ///
2391    /// **Note**: Requires [Kick Members] and [Manage Guild] permissions.
2392    ///
2393    /// # Errors
2394    ///
2395    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
2396    /// does not have permission to kick members.
2397    ///
2398    /// Otherwise will return [`Error::Http`] if the current user does not have permission.
2399    ///
2400    /// Can also return an [`Error::Json`] if there is an error deserializing the API response.
2401    ///
2402    /// [Kick Members]: Permissions::KICK_MEMBERS
2403    /// [Manage Guild]: Permissions::MANAGE_GUILD
2404    /// [`Error::Http`]: crate::error::Error::Http
2405    /// [`Error::Json`]: crate::error::Error::Json
2406    pub async fn start_prune(&self, cache_http: impl CacheHttp, days: u8) -> Result<GuildPrune> {
2407        #[cfg(feature = "cache")]
2408        {
2409            if let Some(cache) = cache_http.cache() {
2410                self.require_perms(cache, Permissions::KICK_MEMBERS | Permissions::MANAGE_GUILD)?;
2411            }
2412        }
2413
2414        self.id.start_prune(cache_http.http(), days).await
2415    }
2416
2417    /// Unbans the given [`User`] from the guild.
2418    ///
2419    /// **Note**: Requires the [Ban Members] permission.
2420    ///
2421    /// # Errors
2422    ///
2423    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
2424    /// does not have permission to perform bans.
2425    ///
2426    /// Otherwise will return an [`Error::Http`] if the current user does not have permission.
2427    ///
2428    /// [Ban Members]: Permissions::BAN_MEMBERS
2429    pub async fn unban(
2430        &self,
2431        cache_http: impl CacheHttp,
2432        user_id: impl Into<UserId>,
2433    ) -> Result<()> {
2434        #[cfg(feature = "cache")]
2435        {
2436            if let Some(cache) = cache_http.cache() {
2437                self.require_perms(cache, Permissions::BAN_MEMBERS)?;
2438            }
2439        }
2440
2441        self.id.unban(cache_http.http(), user_id).await
2442    }
2443
2444    /// Retrieve's the guild's vanity URL.
2445    ///
2446    /// **Note**: Requires the [Manage Guild] permission.
2447    ///
2448    /// [Manage Guild]: Permissions::MANAGE_GUILD
2449    ///
2450    /// # Errors
2451    ///
2452    /// Will return [`Error::Http`] if the current user is lacking permissions. Can also return an
2453    /// [`Error::Json`] if there is an error deserializing the API response.
2454    #[inline]
2455    pub async fn vanity_url(&self, http: impl AsRef<Http>) -> Result<String> {
2456        self.id.vanity_url(http).await
2457    }
2458
2459    /// Retrieves the guild's webhooks.
2460    ///
2461    /// **Note**: Requires the [Manage Webhooks] permission.
2462    ///
2463    /// [Manage Webhooks]: Permissions::MANAGE_WEBHOOKS
2464    ///
2465    /// # Errors
2466    ///
2467    /// Will return an [`Error::Http`] if the current user is lacking permissions. Can also return
2468    /// an [`Error::Json`] if there is an error deserializing the API response.
2469    #[inline]
2470    pub async fn webhooks(&self, http: impl AsRef<Http>) -> Result<Vec<Webhook>> {
2471        self.id.webhooks(http).await
2472    }
2473
2474    /// Obtain a reference to a role by its name.
2475    ///
2476    /// **Note**: If two or more roles have the same name, obtained reference will be one of them.
2477    ///
2478    /// # Examples
2479    ///
2480    /// Obtain a reference to a [`Role`] by its name.
2481    ///
2482    /// ```rust,no_run
2483    /// # use serenity::model::prelude::*;
2484    /// # use serenity::prelude::*;
2485    /// # struct Handler;
2486    ///
2487    /// #[serenity::async_trait]
2488    /// #[cfg(all(feature = "cache", feature = "client"))]
2489    /// impl EventHandler for Handler {
2490    ///     async fn message(&self, ctx: Context, msg: Message) {
2491    ///         if let Some(guild_id) = msg.guild_id {
2492    ///             if let Some(guild) = guild_id.to_guild_cached(&ctx) {
2493    ///                 if let Some(role) = guild.role_by_name("role_name") {
2494    ///                     println!("{:?}", role);
2495    ///                 }
2496    ///             }
2497    ///         }
2498    ///     }
2499    /// }
2500    /// ```
2501    #[must_use]
2502    pub fn role_by_name(&self, role_name: &str) -> Option<&Role> {
2503        self.roles.values().find(|role| role_name == role.name)
2504    }
2505
2506    /// Returns a builder which can be awaited to obtain a message or stream of messages in this
2507    /// guild.
2508    #[cfg(feature = "collector")]
2509    pub fn await_reply(&self, shard_messenger: impl AsRef<ShardMessenger>) -> MessageCollector {
2510        MessageCollector::new(shard_messenger).guild_id(self.id)
2511    }
2512
2513    /// Same as [`Self::await_reply`].
2514    #[cfg(feature = "collector")]
2515    pub fn await_replies(&self, shard_messenger: impl AsRef<ShardMessenger>) -> MessageCollector {
2516        self.await_reply(shard_messenger)
2517    }
2518
2519    /// Returns a builder which can be awaited to obtain a message or stream of reactions sent in
2520    /// this guild.
2521    #[cfg(feature = "collector")]
2522    pub fn await_reaction(&self, shard_messenger: impl AsRef<ShardMessenger>) -> ReactionCollector {
2523        ReactionCollector::new(shard_messenger).guild_id(self.id)
2524    }
2525
2526    /// Same as [`Self::await_reaction`].
2527    #[cfg(feature = "collector")]
2528    pub fn await_reactions(
2529        &self,
2530        shard_messenger: impl AsRef<ShardMessenger>,
2531    ) -> ReactionCollector {
2532        self.await_reaction(shard_messenger)
2533    }
2534
2535    /// Gets the guild active threads.
2536    ///
2537    /// # Errors
2538    ///
2539    /// Returns [`Error::Http`] if there is an error in the deserialization, or if the bot issuing
2540    /// the request is not in the guild.
2541    pub async fn get_active_threads(&self, http: impl AsRef<Http>) -> Result<ThreadsData> {
2542        self.id.get_active_threads(http).await
2543    }
2544}
2545
2546#[cfg(feature = "model")]
2547struct CalculatePermissions {
2548    /// Whether the guild member is the guild owner
2549    pub is_guild_owner: bool,
2550    /// Base permissions given to @everyone (guild level)
2551    pub everyone_permissions: Permissions,
2552    /// Permissions allowed to a user by their roles (guild level)
2553    pub user_roles_permissions: Vec<Permissions>,
2554    /// Overwrites that deny permissions for @everyone (channel level)
2555    pub everyone_allow_overwrites: Permissions,
2556    /// Overwrites that allow permissions for @everyone (channel level)
2557    pub everyone_deny_overwrites: Permissions,
2558    /// Overwrites that deny permissions for specific roles (channel level)
2559    pub roles_allow_overwrites: Vec<Permissions>,
2560    /// Overwrites that allow permissions for specific roles (channel level)
2561    pub roles_deny_overwrites: Vec<Permissions>,
2562    /// Member-specific overwrites that deny permissions (channel level)
2563    pub member_allow_overwrites: Permissions,
2564    /// Member-specific overwrites that allow permissions (channel level)
2565    pub member_deny_overwrites: Permissions,
2566}
2567
2568#[cfg(feature = "model")]
2569impl Default for CalculatePermissions {
2570    fn default() -> Self {
2571        Self {
2572            is_guild_owner: false,
2573            everyone_permissions: Permissions::empty(),
2574            user_roles_permissions: Vec::new(),
2575            everyone_allow_overwrites: Permissions::empty(),
2576            everyone_deny_overwrites: Permissions::empty(),
2577            roles_allow_overwrites: Vec::new(),
2578            roles_deny_overwrites: Vec::new(),
2579            member_allow_overwrites: Permissions::empty(),
2580            member_deny_overwrites: Permissions::empty(),
2581        }
2582    }
2583}
2584
2585/// Translated from the pseudo code at https://discord.com/developers/docs/topics/permissions#permission-overwrites
2586///
2587/// The comments within this file refer to the above link
2588#[cfg(feature = "model")]
2589fn calculate_permissions(data: CalculatePermissions) -> Permissions {
2590    if data.is_guild_owner {
2591        return Permissions::all();
2592    }
2593
2594    // 1. Base permissions given to @everyone are applied at a guild level
2595    let mut permissions = data.everyone_permissions;
2596    // 2. Permissions allowed to a user by their roles are applied at a guild level
2597    for role_permission in data.user_roles_permissions {
2598        permissions |= role_permission;
2599    }
2600
2601    if permissions.contains(Permissions::ADMINISTRATOR) {
2602        return Permissions::all();
2603    }
2604
2605    // 3. Overwrites that deny permissions for @everyone are applied at a channel level
2606    permissions &= !data.everyone_deny_overwrites;
2607    // 4. Overwrites that allow permissions for @everyone are applied at a channel level
2608    permissions |= data.everyone_allow_overwrites;
2609
2610    // 5. Overwrites that deny permissions for specific roles are applied at a channel level
2611    let mut role_deny_permissions = Permissions::empty();
2612    for p in data.roles_deny_overwrites {
2613        role_deny_permissions |= p;
2614    }
2615    permissions &= !role_deny_permissions;
2616
2617    // 6. Overwrites that allow permissions for specific roles are applied at a channel level
2618    let mut role_allow_permissions = Permissions::empty();
2619    for p in data.roles_allow_overwrites {
2620        role_allow_permissions |= p;
2621    }
2622    permissions |= role_allow_permissions;
2623
2624    // 7. Member-specific overwrites that deny permissions are applied at a channel level
2625    permissions &= !data.member_deny_overwrites;
2626    // 8. Member-specific overwrites that allow permissions are applied at a channel level
2627    permissions |= data.member_allow_overwrites;
2628
2629    permissions
2630}
2631
2632/// Checks if a `&str` contains another `&str`.
2633#[cfg(feature = "model")]
2634fn contains(haystack: &str, needle: &str, case_sensitive: bool) -> bool {
2635    if case_sensitive {
2636        haystack.contains(needle)
2637    } else {
2638        haystack.to_lowercase().contains(&needle.to_lowercase())
2639    }
2640}
2641
2642/// Takes a `&str` as `origin` and tests if either `word_a` or `word_b` is closer.
2643///
2644/// **Note**: Normally `word_a` and `word_b` are expected to contain `origin` as substring. If not,
2645/// using `closest_to_origin` would sort these the end.
2646#[cfg(feature = "model")]
2647fn closest_to_origin(origin: &str, word_a: &str, word_b: &str) -> std::cmp::Ordering {
2648    let value_a = match word_a.find(origin) {
2649        Some(value) => value + word_a.len(),
2650        None => return std::cmp::Ordering::Greater,
2651    };
2652
2653    let value_b = match word_b.find(origin) {
2654        Some(value) => value + word_b.len(),
2655        None => return std::cmp::Ordering::Less,
2656    };
2657
2658    value_a.cmp(&value_b)
2659}
2660
2661/// A [`Guild`] widget.
2662///
2663/// [Discord docs](https://discord.com/developers/docs/resources/guild#guild-widget-settings-object).
2664#[derive(Clone, Debug, Deserialize, Serialize)]
2665#[non_exhaustive]
2666pub struct GuildWidget {
2667    /// Whether the widget is enabled.
2668    pub enabled: bool,
2669    /// The widget channel id.
2670    pub channel_id: Option<ChannelId>,
2671}
2672
2673/// Representation of the number of members that would be pruned by a guild prune operation.
2674///
2675/// [Discord docs](https://discord.com/developers/docs/resources/guild#get-guild-prune-count).
2676#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
2677#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
2678#[non_exhaustive]
2679pub struct GuildPrune {
2680    /// The number of members that would be pruned by the operation.
2681    pub pruned: u64,
2682}
2683
2684/// Variant of [`Guild`] returned from [`Http::get_guilds`].
2685///
2686/// [Discord docs](https://discord.com/developers/docs/resources/guild#guild-object),
2687/// [subset example](https://discord.com/developers/docs/resources/user#get-current-user-guilds-example-partial-guild).
2688#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
2689#[derive(Clone, Debug, Deserialize, Serialize)]
2690#[non_exhaustive]
2691pub struct GuildInfo {
2692    /// The unique Id of the guild.
2693    ///
2694    /// Can be used to calculate creation date.
2695    pub id: GuildId,
2696    /// The name of the guild.
2697    pub name: String,
2698    /// The hash of the icon of the guild.
2699    ///
2700    /// This can be used to generate a URL to the guild's icon image.
2701    pub icon: Option<ImageHash>,
2702    /// Indicator of whether the current user is the owner.
2703    pub owner: bool,
2704    /// The permissions that the current user has.
2705    pub permissions: Permissions,
2706    /// See [`Guild::features`].
2707    pub features: Vec<String>,
2708}
2709
2710#[cfg(feature = "model")]
2711impl GuildInfo {
2712    /// Returns the formatted URL of the guild's icon, if the guild has an icon.
2713    ///
2714    /// This will produce a WEBP image URL, or GIF if the guild has a GIF icon.
2715    #[must_use]
2716    pub fn icon_url(&self) -> Option<String> {
2717        icon_url(self.id, self.icon.as_ref())
2718    }
2719}
2720
2721#[cfg(feature = "model")]
2722impl InviteGuild {
2723    /// Returns the formatted URL of the guild's splash image, if one exists.
2724    #[must_use]
2725    pub fn splash_url(&self) -> Option<String> {
2726        self.splash.as_ref().map(|splash| cdn!("/splashes/{}/{}.webp?size=4096", self.id, splash))
2727    }
2728}
2729
2730/// Data for an unavailable guild.
2731///
2732/// [Discord docs](https://discord.com/developers/docs/resources/guild#unavailable-guild-object).
2733#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
2734#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
2735#[non_exhaustive]
2736pub struct UnavailableGuild {
2737    /// The Id of the [`Guild`] that may be unavailable.
2738    pub id: GuildId,
2739    /// Indicator of whether the guild is unavailable.
2740    #[serde(default)]
2741    pub unavailable: bool,
2742}
2743
2744enum_number! {
2745    /// Default message notification level for a guild.
2746    ///
2747    /// [Discord docs](https://discord.com/developers/docs/resources/guild#guild-object-default-message-notification-level).
2748    #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
2749    #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
2750    #[serde(from = "u8", into = "u8")]
2751    #[non_exhaustive]
2752    pub enum DefaultMessageNotificationLevel {
2753        /// Receive notifications for everything.
2754        #[default]
2755        All = 0,
2756        /// Receive only mentions.
2757        Mentions = 1,
2758        _ => Unknown(u8),
2759    }
2760}
2761
2762enum_number! {
2763    /// Setting used to filter explicit messages from members.
2764    ///
2765    /// [Discord docs](https://discord.com/developers/docs/resources/guild#guild-object-explicit-content-filter-level).
2766    #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
2767    #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
2768    #[serde(from = "u8", into = "u8")]
2769    #[non_exhaustive]
2770    pub enum ExplicitContentFilter {
2771        /// Don't scan any messages.
2772        #[default]
2773        None = 0,
2774        /// Scan messages from members without a role.
2775        WithoutRole = 1,
2776        /// Scan messages sent by all members.
2777        All = 2,
2778        _ => Unknown(u8),
2779    }
2780}
2781
2782enum_number! {
2783    /// Multi-Factor Authentication level for guild moderators.
2784    ///
2785    /// [Discord docs](https://discord.com/developers/docs/resources/guild#guild-object-mfa-level).
2786    #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
2787    #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
2788    #[serde(from = "u8", into = "u8")]
2789    #[non_exhaustive]
2790    pub enum MfaLevel {
2791        /// MFA is disabled.
2792        #[default]
2793        None = 0,
2794        /// MFA is enabled.
2795        Elevated = 1,
2796        _ => Unknown(u8),
2797    }
2798}
2799
2800enum_number! {
2801    /// The level to set as criteria prior to a user being able to send
2802    /// messages in a [`Guild`].
2803    ///
2804    /// [Discord docs](https://discord.com/developers/docs/resources/guild#guild-object-verification-level).
2805    #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
2806    #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
2807    #[serde(from = "u8", into = "u8")]
2808    #[non_exhaustive]
2809    pub enum VerificationLevel {
2810        /// Does not require any verification.
2811        #[default]
2812        None = 0,
2813        /// Must have a verified email on the user's Discord account.
2814        Low = 1,
2815        /// Must also be a registered user on Discord for longer than 5 minutes.
2816        Medium = 2,
2817        /// Must also be a member of the guild for longer than 10 minutes.
2818        High = 3,
2819        /// Must have a verified phone on the user's Discord account.
2820        Higher = 4,
2821        _ => Unknown(u8),
2822    }
2823}
2824
2825enum_number! {
2826    /// The [`Guild`] nsfw level.
2827    ///
2828    /// [Discord docs](https://discord.com/developers/docs/resources/guild#guild-object-guild-nsfw-level).
2829    #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
2830    #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
2831    #[serde(from = "u8", into = "u8")]
2832    #[non_exhaustive]
2833    pub enum NsfwLevel {
2834        /// The nsfw level is not specified.
2835        #[default]
2836        Default = 0,
2837        /// The guild is considered as explicit.
2838        Explicit = 1,
2839        /// The guild is considered as safe.
2840        Safe = 2,
2841        /// The guild is age restricted.
2842        AgeRestricted = 3,
2843        _ => Unknown(u8),
2844    }
2845}
2846
2847enum_number! {
2848    /// The [`Guild`] AFK timeout length.
2849    ///
2850    /// See [AfkMetadata::afk_timeout].
2851    #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
2852    #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
2853    #[serde(from = "u16", into = "u16")]
2854    #[non_exhaustive]
2855    pub enum AfkTimeout {
2856        OneMinute = 60,
2857        FiveMinutes = 300,
2858        FifteenMinutes = 900,
2859        ThirtyMinutes = 1800,
2860        OneHour = 3600,
2861        _ => Unknown(u16),
2862    }
2863}
2864
2865#[cfg(test)]
2866mod test {
2867    #[cfg(feature = "model")]
2868    mod model {
2869        use std::collections::*;
2870        use std::num::NonZeroU16;
2871
2872        use crate::model::prelude::*;
2873
2874        fn gen_member() -> Member {
2875            Member {
2876                nick: Some("aaaa".to_string()),
2877                user: User {
2878                    name: "test".into(),
2879                    discriminator: NonZeroU16::new(1432),
2880                    ..User::default()
2881                },
2882                ..Default::default()
2883            }
2884        }
2885
2886        fn gen() -> Guild {
2887            let m = gen_member();
2888
2889            Guild {
2890                members: HashMap::from([(m.user.id, m)]),
2891                ..Default::default()
2892            }
2893        }
2894
2895        #[test]
2896        fn member_named_username() {
2897            let guild = gen();
2898            let lhs = guild.member_named("test#1432").unwrap().display_name();
2899
2900            assert_eq!(lhs, gen_member().display_name());
2901        }
2902
2903        #[test]
2904        fn member_named_nickname() {
2905            let guild = gen();
2906            let lhs = guild.member_named("aaaa").unwrap().display_name();
2907
2908            assert_eq!(lhs, gen_member().display_name());
2909        }
2910    }
2911}