serenity/builder/edit_channel.rs
1#[cfg(feature = "http")]
2use super::Builder;
3use super::CreateForumTag;
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 edit a [`GuildChannel`] for use via [`GuildChannel::edit`].
11///
12/// [Discord docs](https://discord.com/developers/docs/resources/channel#modify-channel-json-params-guild-channel).
13///
14/// # Examples
15///
16/// Edit a channel, providing a new name and topic:
17///
18/// ```rust,no_run
19/// # use serenity::builder::EditChannel;
20/// # use serenity::http::Http;
21/// # use serenity::model::channel::GuildChannel;
22/// #
23/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
24/// # let http: Http = unimplemented!();
25/// # let mut channel: GuildChannel = unimplemented!();
26/// let builder = EditChannel::new().name("new name").topic("a test topic");
27/// if let Err(why) = channel.edit(&http, builder).await {
28/// // properly handle the error
29/// }
30/// # Ok(())
31/// # }
32/// ```
33#[derive(Clone, Debug, Default, Serialize)]
34#[must_use]
35pub struct EditChannel<'a> {
36 #[serde(skip_serializing_if = "Option::is_none")]
37 name: Option<String>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 #[serde(rename = "type")]
40 kind: Option<ChannelType>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 position: Option<u16>,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 topic: Option<String>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 nsfw: Option<bool>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 rate_limit_per_user: Option<u16>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 bitrate: Option<u32>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 user_limit: Option<u32>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 permission_overwrites: Option<Vec<PermissionOverwriteData>>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 parent_id: Option<Option<ChannelId>>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 rtc_region: Option<Option<String>>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 video_quality_mode: Option<VideoQualityMode>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 default_auto_archive_duration: Option<AutoArchiveDuration>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 flags: Option<ChannelFlags>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 available_tags: Option<Vec<CreateForumTag>>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 default_reaction_emoji: Option<Option<ForumEmoji>>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 default_thread_rate_limit_per_user: Option<u16>,
71 #[serde(skip_serializing_if = "Option::is_none")]
72 default_sort_order: Option<SortOrder>,
73 #[serde(skip_serializing_if = "Option::is_none")]
74 default_forum_layout: Option<ForumLayoutType>,
75 #[serde(skip_serializing_if = "Option::is_none")]
76 status: Option<String>,
77
78 #[serde(skip)]
79 audit_log_reason: Option<&'a str>,
80}
81
82impl<'a> EditChannel<'a> {
83 /// Equivalent to [`Self::default`].
84 pub fn new() -> Self {
85 Self::default()
86 }
87
88 /// The bitrate of the channel in bits.
89 ///
90 /// This is for [voice] channels only.
91 ///
92 /// [voice]: ChannelType::Voice
93 pub fn bitrate(mut self, bitrate: u32) -> Self {
94 self.bitrate = Some(bitrate);
95 self
96 }
97
98 /// The camera video quality mode of the channel.
99 ///
100 /// This is for [voice] channels only.
101 ///
102 /// [voice]: ChannelType::Voice
103 pub fn video_quality_mode(mut self, quality: VideoQualityMode) -> Self {
104 self.video_quality_mode = Some(quality);
105 self
106 }
107
108 /// The voice region of the channel. It is automatic when `None`.
109 ///
110 /// This is for [voice] channels only.
111 ///
112 /// [voice]: ChannelType::Voice
113 pub fn voice_region(mut self, id: Option<String>) -> Self {
114 self.rtc_region = Some(id);
115 self
116 }
117
118 /// The name of the channel.
119 ///
120 /// Must be between 2 and 100 characters long.
121 pub fn name(mut self, name: impl Into<String>) -> Self {
122 self.name = Some(name.into());
123 self
124 }
125
126 /// The position of the channel in the channel list.
127 pub fn position(mut self, position: u16) -> Self {
128 self.position = Some(position);
129 self
130 }
131
132 /// The topic of the channel. Can be empty.
133 ///
134 /// Must be between 0 and 1024 characters long.
135 ///
136 /// This is for [text] channels only.
137 ///
138 /// [text]: ChannelType::Text
139 pub fn topic(mut self, topic: impl Into<String>) -> Self {
140 self.topic = Some(topic.into());
141 self
142 }
143
144 /// The status of the voice channel. Can be empty.
145 ///
146 /// Must be between 0 and 1024 characters long.
147 ///
148 /// This is for [voice] channels only.
149 ///
150 /// [voice]: ChannelType::Voice
151 pub fn status(mut self, status: impl Into<String>) -> Self {
152 self.status = Some(status.into());
153 self
154 }
155
156 /// Is the channel inappropriate for work?
157 ///
158 /// This is for [text] channels only.
159 ///
160 /// [text]: ChannelType::Text
161 pub fn nsfw(mut self, nsfw: bool) -> Self {
162 self.nsfw = Some(nsfw);
163 self
164 }
165
166 /// The number of users that may be in the channel simultaneously.
167 ///
168 /// This is for [voice] channels only.
169 ///
170 /// [voice]: ChannelType::Voice
171 pub fn user_limit(mut self, user_limit: u32) -> Self {
172 self.user_limit = Some(user_limit);
173 self
174 }
175
176 /// The parent category of the channel.
177 ///
178 /// This is for [text] and [voice] channels only.
179 ///
180 /// [text]: ChannelType::Text
181 /// [voice]: ChannelType::Voice
182 #[inline]
183 pub fn category<C: Into<Option<ChannelId>>>(mut self, category: C) -> Self {
184 self.parent_id = Some(category.into());
185 self
186 }
187
188 /// How many seconds must a user wait before sending another message.
189 ///
190 /// Bots, or users with the [`MANAGE_MESSAGES`] and/or [`MANAGE_CHANNELS`] permissions are
191 /// exempt from this restriction.
192 ///
193 /// **Note**: Must be between 0 and 21600 seconds (360 minutes or 6 hours).
194 ///
195 /// [`MANAGE_MESSAGES`]: Permissions::MANAGE_MESSAGES
196 /// [`MANAGE_CHANNELS`]: Permissions::MANAGE_CHANNELS
197 #[doc(alias = "slowmode")]
198 pub fn rate_limit_per_user(mut self, seconds: u16) -> Self {
199 self.rate_limit_per_user = Some(seconds);
200 self
201 }
202
203 /// A set of overwrites defining what a user or a user carrying a certain role can or can't do.
204 ///
205 /// # Example
206 ///
207 /// Inheriting permissions from an existing channel:
208 ///
209 /// ```rust,no_run
210 /// # use serenity::builder::EditChannel;
211 /// # use serenity::http::Http;
212 /// # use serenity::model::channel::GuildChannel;
213 /// # use std::sync::Arc;
214 /// #
215 /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
216 /// # let http: Arc<Http> = unimplemented!();
217 /// # let mut channel: GuildChannel = unimplemented!();
218 /// use serenity::model::channel::{PermissionOverwrite, PermissionOverwriteType};
219 /// use serenity::model::id::UserId;
220 /// use serenity::model::permissions::Permissions;
221 ///
222 /// // Assuming a channel has already been bound.
223 /// let permissions = vec![PermissionOverwrite {
224 /// allow: Permissions::VIEW_CHANNEL,
225 /// deny: Permissions::SEND_TTS_MESSAGES,
226 /// kind: PermissionOverwriteType::Member(UserId::new(1234)),
227 /// }];
228 ///
229 /// let builder = EditChannel::new().name("my_edited_cool_channel").permissions(permissions);
230 /// channel.edit(http, builder).await?;
231 /// # Ok(())
232 /// # }
233 /// ```
234 pub fn permissions(mut self, perms: impl IntoIterator<Item = PermissionOverwrite>) -> Self {
235 let overwrites = perms.into_iter().map(Into::into).collect::<Vec<_>>();
236
237 self.permission_overwrites = Some(overwrites);
238 self
239 }
240
241 /// If this is a forum channel, sets the tags that can be assigned to forum posts.
242 pub fn available_tags(mut self, tags: impl IntoIterator<Item = CreateForumTag>) -> Self {
243 self.available_tags = Some(tags.into_iter().collect());
244 self
245 }
246
247 /// Sets the request's audit log reason.
248 pub fn audit_log_reason(mut self, reason: &'a str) -> Self {
249 self.audit_log_reason = Some(reason);
250 self
251 }
252
253 /// The type of channel; only conversion between text and announcement is supported and only in
254 /// guilds with the "NEWS" feature
255 pub fn kind(mut self, kind: ChannelType) -> Self {
256 self.kind = Some(kind);
257 self
258 }
259
260 /// The default duration that the clients use (not the API) for newly created threads in the
261 /// channel, in minutes, to automatically archive the thread after recent activity
262 pub fn default_auto_archive_duration(
263 mut self,
264 default_auto_archive_duration: AutoArchiveDuration,
265 ) -> Self {
266 self.default_auto_archive_duration = Some(default_auto_archive_duration);
267 self
268 }
269
270 /// Channel flags combined as a bitfield. Currently only [`ChannelFlags::REQUIRE_TAG`] is
271 /// supported.
272 pub fn flags(mut self, flags: ChannelFlags) -> Self {
273 self.flags = Some(flags);
274 self
275 }
276
277 /// The emoji to show in the add reaction button on a thread in a forum channel
278 pub fn default_reaction_emoji(mut self, default_reaction_emoji: Option<ForumEmoji>) -> Self {
279 self.default_reaction_emoji = Some(default_reaction_emoji);
280 self
281 }
282
283 /// The initial rate_limit_per_user to set on newly created threads in a channel. This field is
284 /// copied to the thread at creation time and does not live update.
285 pub fn default_thread_rate_limit_per_user(
286 mut self,
287 default_thread_rate_limit_per_user: u16,
288 ) -> Self {
289 self.default_thread_rate_limit_per_user = Some(default_thread_rate_limit_per_user);
290 self
291 }
292
293 /// The default sort order type used to order posts in forum channels
294 pub fn default_sort_order(mut self, default_sort_order: SortOrder) -> Self {
295 self.default_sort_order = Some(default_sort_order);
296 self
297 }
298
299 /// The default forum layout type used to display posts in forum channels
300 pub fn default_forum_layout(mut self, default_forum_layout: ForumLayoutType) -> Self {
301 self.default_forum_layout = Some(default_forum_layout);
302 self
303 }
304}
305
306#[cfg(feature = "http")]
307#[async_trait::async_trait]
308impl Builder for EditChannel<'_> {
309 type Context<'ctx> = ChannelId;
310 type Built = GuildChannel;
311
312 /// Edits the channel's settings.
313 ///
314 /// **Note**: Requires the [Manage Channels] permission. Modifying permissions via
315 /// [`Self::permissions`] also requires the [Manage Roles] permission.
316 ///
317 /// # Errors
318 ///
319 /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
320 /// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
321 ///
322 /// [Manage Channels]: Permissions::MANAGE_CHANNELS
323 /// [Manage Roles]: Permissions::MANAGE_ROLES
324 async fn execute(
325 self,
326 cache_http: impl CacheHttp,
327 ctx: Self::Context<'_>,
328 ) -> Result<Self::Built> {
329 #[cfg(feature = "cache")]
330 {
331 if let Some(cache) = cache_http.cache() {
332 crate::utils::user_has_perms_cache(cache, ctx, Permissions::MANAGE_CHANNELS)?;
333 if self.permission_overwrites.is_some() {
334 crate::utils::user_has_perms_cache(cache, ctx, Permissions::MANAGE_ROLES)?;
335 }
336 }
337 }
338
339 if let Some(status) = &self.status {
340 #[derive(Serialize)]
341 struct EditVoiceStatusBody<'a> {
342 status: &'a str,
343 }
344
345 cache_http
346 .http()
347 .edit_voice_status(
348 ctx,
349 &EditVoiceStatusBody {
350 status: status.as_str(),
351 },
352 self.audit_log_reason,
353 )
354 .await?;
355 }
356
357 cache_http.http().edit_channel(ctx, &self, self.audit_log_reason).await
358 }
359}