serenity/builder/
edit_guild.rs

1#[cfg(feature = "http")]
2use super::Builder;
3use super::CreateAttachment;
4#[cfg(feature = "http")]
5use crate::http::CacheHttp;
6#[cfg(feature = "http")]
7use crate::internal::prelude::*;
8use crate::model::prelude::*;
9
10/// A builder to optionally edit certain fields of a guild
11///
12/// [Discord docs](https://discord.com/developers/docs/resources/guild#modify-guild).
13#[derive(Clone, Debug, Default, Serialize)]
14#[must_use]
15pub struct EditGuild<'a> {
16    #[serde(skip_serializing_if = "Option::is_none")]
17    name: Option<String>,
18    // [Omitting region because Discord deprecated it]
19    #[serde(skip_serializing_if = "Option::is_none")]
20    verification_level: Option<VerificationLevel>,
21    #[serde(skip_serializing_if = "Option::is_none")]
22    default_message_notifications: Option<Option<DefaultMessageNotificationLevel>>,
23    #[serde(skip_serializing_if = "Option::is_none")]
24    explicit_content_filter: Option<Option<ExplicitContentFilter>>,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    afk_channel_id: Option<Option<ChannelId>>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    afk_timeout: Option<AfkTimeout>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    icon: Option<Option<String>>,
31    #[serde(skip_serializing_if = "Option::is_none")]
32    owner_id: Option<UserId>,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    splash: Option<Option<String>>,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    discovery_splash: Option<Option<String>>,
37    #[serde(skip_serializing_if = "Option::is_none")]
38    banner: Option<Option<String>>,
39    #[serde(skip_serializing_if = "Option::is_none")]
40    system_channel_id: Option<Option<ChannelId>>,
41    #[serde(skip_serializing_if = "Option::is_none")]
42    system_channel_flags: Option<SystemChannelFlags>,
43    #[serde(skip_serializing_if = "Option::is_none")]
44    rules_channel_id: Option<Option<ChannelId>>,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    public_updates_channel_id: Option<Option<ChannelId>>,
47    #[serde(skip_serializing_if = "Option::is_none")]
48    preferred_locale: Option<Option<String>>,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    features: Option<Vec<String>>,
51    #[serde(skip_serializing_if = "Option::is_none")]
52    description: Option<String>,
53    #[serde(skip_serializing_if = "Option::is_none")]
54    premium_progress_bar_enabled: Option<bool>,
55
56    #[serde(skip)]
57    audit_log_reason: Option<&'a str>,
58}
59
60impl<'a> EditGuild<'a> {
61    /// Equivalent to [`Self::default`].
62    pub fn new() -> Self {
63        Self::default()
64    }
65
66    /// Set the "AFK voice channel" that users are to move to if they have been AFK for an amount
67    /// of time, configurable by [`Self::afk_timeout`]. Pass [`None`] to unset the current value.
68    #[inline]
69    pub fn afk_channel(mut self, channel: Option<ChannelId>) -> Self {
70        self.afk_channel_id = Some(channel);
71        self
72    }
73
74    /// Set the amount of time a user is to be moved to the AFK channel - configured via
75    /// [`Self::afk_channel`] - after being AFK.
76    pub fn afk_timeout(mut self, timeout: AfkTimeout) -> Self {
77        self.afk_timeout = Some(timeout);
78        self
79    }
80
81    /// Set the icon of the guild. Pass [`None`] to remove the icon.
82    ///
83    /// # Examples
84    ///
85    /// Using the utility builder - [`CreateAttachment`] - to read an image and encode it in
86    /// base64, to then set as the guild icon.
87    ///
88    /// ```rust,no_run
89    /// # use serenity::builder::{EditGuild, CreateAttachment};
90    /// # use serenity::{http::Http, model::id::GuildId};
91    /// #
92    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
93    /// # let http: Http = unimplemented!();
94    /// # let mut guild = GuildId::new(1).to_partial_guild(&http).await?;
95    /// let icon = CreateAttachment::path("./guild_icon.png").await?;
96    ///
97    /// // assuming a `guild` has already been bound
98    /// let builder = EditGuild::new().icon(Some(&icon));
99    /// guild.edit(&http, builder).await?;
100    /// # Ok(())
101    /// # }
102    /// ```
103    pub fn icon(mut self, icon: Option<&CreateAttachment>) -> Self {
104        self.icon = Some(icon.map(CreateAttachment::to_base64));
105        self
106    }
107
108    /// Clear the current guild icon, resetting it to the default logo.
109    pub fn delete_icon(mut self) -> Self {
110        self.icon = Some(None);
111        self
112    }
113
114    /// Set the name of the guild.
115    ///
116    /// **Note**: Must be between (and including) 2-100 characters.
117    pub fn name(mut self, name: impl Into<String>) -> Self {
118        self.name = Some(name.into());
119        self
120    }
121
122    /// Set the description of the guild.
123    ///
124    /// **Note**: Requires that the guild have the `DISCOVERABLE` feature enabled. You can check
125    /// this through a guild's [`features`] list.
126    ///
127    /// [`features`]: Guild::features
128    pub fn description(mut self, name: impl Into<String>) -> Self {
129        self.description = Some(name.into());
130        self
131    }
132
133    /// Set the features of the guild.
134    ///
135    /// **Note**: Requires that the guild have the `DISCOVERABLE` feature enabled. You can check
136    /// this through a guild's [`features`] list.
137    ///
138    /// [`features`]: Guild::features
139    pub fn features(mut self, features: Vec<String>) -> Self {
140        self.features = Some(features);
141        self
142    }
143
144    /// Transfers the ownership of the guild to another user by Id.
145    ///
146    /// **Note**: The current user must be the owner of the guild.
147    #[inline]
148    pub fn owner(mut self, user_id: impl Into<UserId>) -> Self {
149        self.owner_id = Some(user_id.into());
150        self
151    }
152
153    /// Set the splash image of the guild on the invitation page.
154    ///
155    /// The `splash` must be base64-encoded 1024x1024 png/jpeg/gif image-data.
156    ///
157    /// Requires that the guild have the `INVITE_SPLASH` feature enabled. You can check this
158    /// through a guild's [`features`] list.
159    ///
160    /// [`features`]: Guild::features
161    pub fn splash(mut self, splash: Option<String>) -> Self {
162        self.splash = Some(splash);
163        self
164    }
165
166    /// Set the splash image of the guild on the discovery page.
167    ///
168    /// The `splash` must be base64-encoded 1024x1024 png/jpeg/gif image-data.
169    ///
170    /// Requires that the guild have the `DISCOVERABLE` feature enabled. You can check this through
171    /// a guild's [`features`] list.
172    ///
173    /// [`features`]: Guild::features
174    pub fn discovery_splash(mut self, splash: Option<String>) -> Self {
175        self.discovery_splash = Some(splash);
176        self
177    }
178
179    /// Set the banner image of the guild, it appears on the left side-bar.
180    ///
181    /// The `banner` must be base64-encoded 16:9 png/jpeg image data.
182    ///
183    /// Requires that the guild have the `BANNER` feature enabled. You can check this through a
184    /// guild's [`features`] list.
185    ///
186    /// [`features`]: Guild::features
187    pub fn banner(mut self, banner: Option<String>) -> Self {
188        self.banner = Some(banner);
189        self
190    }
191
192    /// Set the channel ID where welcome messages and boost events will be posted.
193    pub fn system_channel_id(mut self, channel_id: Option<ChannelId>) -> Self {
194        self.system_channel_id = Some(channel_id);
195        self
196    }
197
198    /// Set the channel ID of the rules and guidelines channel.
199    ///
200    /// **Note**: This feature is for Community guilds only.
201    pub fn rules_channel_id(mut self, channel_id: Option<ChannelId>) -> Self {
202        self.rules_channel_id = Some(channel_id);
203        self
204    }
205
206    /// Set the channel ID where admins and moderators receive update messages from Discord.
207    ///
208    /// **Note**: This feature is for Community guilds only.
209    pub fn public_updates_channel_id(mut self, channel_id: Option<ChannelId>) -> Self {
210        self.public_updates_channel_id = Some(channel_id);
211        self
212    }
213
214    /// Set the preferred locale used in Server Discovery and update messages from Discord.
215    ///
216    /// If this is not set, the locale will default to "en-US";
217    ///
218    /// **Note**: This feature is for Community guilds only.
219    pub fn preferred_locale(mut self, locale: Option<String>) -> Self {
220        self.preferred_locale = Some(locale);
221        self
222    }
223
224    /// Set the content filter level.
225    pub fn explicit_content_filter(mut self, level: Option<ExplicitContentFilter>) -> Self {
226        self.explicit_content_filter = Some(level);
227        self
228    }
229
230    /// Set the default message notification level.
231    pub fn default_message_notifications(
232        mut self,
233        level: Option<DefaultMessageNotificationLevel>,
234    ) -> Self {
235        self.default_message_notifications = Some(level);
236        self
237    }
238
239    /// Set the verification level of the guild. This can restrict what a user must have prior to
240    /// being able to send messages in a guild.
241    ///
242    /// Refer to the documentation for [`VerificationLevel`] for more information on each variant.
243    ///
244    /// # Examples
245    ///
246    /// Setting the verification level to [`High`][`VerificationLevel::High`]:
247    ///
248    /// ```rust,no_run
249    /// # use serenity::builder::EditGuild;
250    /// # use serenity::{http::Http, model::guild::Guild};
251    /// #
252    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
253    /// # let http: Http = unimplemented!();
254    /// # let mut guild: Guild = unimplemented!();
255    /// use serenity::model::guild::VerificationLevel;
256    ///
257    /// let builder = EditGuild::new().verification_level(VerificationLevel::High);
258    ///
259    /// // assuming a `guild` has already been bound
260    /// let edit = guild.edit(&http, builder).await;
261    /// if let Err(why) = edit {
262    ///     println!("Error setting verification level: {:?}", why);
263    /// }
264    /// # Ok(())
265    /// # }
266    /// ```
267    #[inline]
268    pub fn verification_level(mut self, verification_level: impl Into<VerificationLevel>) -> Self {
269        self.verification_level = Some(verification_level.into());
270        self
271    }
272
273    /// Modifies the notifications that are sent by discord to the configured system channel.
274    ///
275    /// ```rust,no_run
276    /// # use serenity::builder::EditGuild;
277    /// # use serenity::{http::Http, model::guild::Guild};
278    /// #
279    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
280    /// # let http: Http = unimplemented!();
281    /// # let mut guild: Guild = unimplemented!();
282    /// use serenity::model::guild::SystemChannelFlags;
283    ///
284    /// let builder = EditGuild::new().system_channel_flags(
285    ///     SystemChannelFlags::SUPPRESS_JOIN_NOTIFICATIONS
286    ///         | SystemChannelFlags::SUPPRESS_GUILD_REMINDER_NOTIFICATIONS,
287    /// );
288    ///
289    /// // assuming a `guild` has already been bound
290    /// let edit = guild.edit(&http, builder).await;
291    /// if let Err(why) = edit {
292    ///     println!("Error setting system channel flags: {:?}", why);
293    /// }
294    /// # Ok(())
295    /// # }
296    /// ```
297    pub fn system_channel_flags(mut self, system_channel_flags: SystemChannelFlags) -> Self {
298        self.system_channel_flags = Some(system_channel_flags);
299        self
300    }
301
302    /// Sets the request's audit log reason.
303    pub fn audit_log_reason(mut self, reason: &'a str) -> Self {
304        self.audit_log_reason = Some(reason);
305        self
306    }
307
308    /// Whether the guild's boost progress bar should be enabled
309    pub fn premium_progress_bar_enabled(mut self, premium_progress_bar_enabled: bool) -> Self {
310        self.premium_progress_bar_enabled = Some(premium_progress_bar_enabled);
311        self
312    }
313}
314
315#[cfg(feature = "http")]
316#[async_trait::async_trait]
317impl Builder for EditGuild<'_> {
318    type Context<'ctx> = GuildId;
319    type Built = PartialGuild;
320
321    /// Edits the given guild.
322    ///
323    /// **Note**: Requires the [Manage Guild] permission.
324    ///
325    /// # Errors
326    ///
327    /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
328    /// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
329    ///
330    /// [Manage Guild]: Permissions::MANAGE_GUILD
331    async fn execute(
332        self,
333        cache_http: impl CacheHttp,
334        ctx: Self::Context<'_>,
335    ) -> Result<Self::Built> {
336        #[cfg(feature = "cache")]
337        crate::utils::user_has_guild_perms(&cache_http, ctx, Permissions::MANAGE_GUILD)?;
338
339        cache_http.http().edit_guild(ctx, &self, self.audit_log_reason).await
340    }
341}