serenity/builder/create_channel.rs
1#[cfg(feature = "http")]
2use super::Builder;
3#[cfg(feature = "http")]
4use crate::http::CacheHttp;
5#[cfg(feature = "http")]
6use crate::internal::prelude::*;
7use crate::model::prelude::*;
8
9/// A builder for creating a new [`GuildChannel`] in a [`Guild`].
10///
11/// Except [`Self::name`], all fields are optional.
12///
13/// [Discord docs](https://discord.com/developers/docs/resources/guild#create-guild-channel).
14#[derive(Clone, Debug, Serialize)]
15#[must_use]
16pub struct CreateChannel<'a> {
17 name: String,
18 #[serde(rename = "type")]
19 kind: ChannelType,
20
21 #[serde(skip_serializing_if = "Option::is_none")]
22 topic: Option<String>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 bitrate: Option<u32>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 user_limit: Option<u32>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 rate_limit_per_user: Option<u16>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 position: Option<u16>,
31 #[serde(skip_serializing_if = "Vec::is_empty")]
32 permission_overwrites: Vec<PermissionOverwriteData>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 parent_id: Option<ChannelId>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 nsfw: Option<bool>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 rtc_region: Option<String>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 video_quality_mode: Option<VideoQualityMode>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 default_auto_archive_duration: Option<AutoArchiveDuration>,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 default_reaction_emoji: Option<ForumEmoji>,
45 #[serde(skip_serializing_if = "Vec::is_empty")]
46 available_tags: Vec<ForumTag>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 default_sort_order: Option<SortOrder>,
49
50 #[serde(skip)]
51 audit_log_reason: Option<&'a str>,
52}
53
54impl<'a> CreateChannel<'a> {
55 /// Creates a builder with the given name, setting [`Self::kind`] to [`ChannelType::Text`] and
56 /// leaving all other fields empty.
57 pub fn new(name: impl Into<String>) -> Self {
58 Self {
59 name: name.into(),
60 nsfw: None,
61 topic: None,
62 bitrate: None,
63 position: None,
64 parent_id: None,
65 user_limit: None,
66 rate_limit_per_user: None,
67 kind: ChannelType::Text,
68 permission_overwrites: Vec::new(),
69 audit_log_reason: None,
70 rtc_region: None,
71 video_quality_mode: None,
72 default_auto_archive_duration: None,
73 default_reaction_emoji: None,
74 available_tags: Vec::new(),
75 default_sort_order: None,
76 }
77 }
78
79 /// Specify how to call this new channel, replacing the current value as set in [`Self::new`].
80 ///
81 /// **Note**: Must be between 2 and 100 characters long.
82 pub fn name(mut self, name: impl Into<String>) -> Self {
83 self.name = name.into();
84 self
85 }
86
87 /// Specify what type the channel is, whether it's a text, voice, category or news channel.
88 pub fn kind(mut self, kind: ChannelType) -> Self {
89 self.kind = kind;
90 self
91 }
92
93 /// Specify the category, the "parent" of this channel.
94 ///
95 /// Only for [`ChannelType::Text`], [`ChannelType::Voice`], [`ChannelType::News`],
96 /// [`ChannelType::Stage`], [`ChannelType::Forum`]
97 #[doc(alias = "parent_id")]
98 pub fn category(mut self, id: impl Into<ChannelId>) -> Self {
99 self.parent_id = Some(id.into());
100 self
101 }
102
103 /// Channel topic (0-1024 characters)
104 ///
105 /// Only for [`ChannelType::Text`], [`ChannelType::News`], [`ChannelType::Forum`]
106 pub fn topic(mut self, topic: impl Into<String>) -> Self {
107 self.topic = Some(topic.into());
108 self
109 }
110
111 /// Specify if this channel is NSFW (18+)
112 ///
113 /// Only for [`ChannelType::Text`], [`ChannelType::Voice`], [`ChannelType::News`],
114 /// [`ChannelType::Stage`], [`ChannelType::Forum`]
115 pub fn nsfw(mut self, b: bool) -> Self {
116 self.nsfw = Some(b);
117 self
118 }
119
120 /// The bitrate (in bits) of the voice or stage channel; min 8000
121 ///
122 /// For voice channels, normal servers can set bitrate up to 96000, servers with Boost level 1
123 /// can set up to 128000, servers with Boost level 2 can set up to 256000, and servers with
124 /// Boost level 3 or the VIP_REGIONS guild feature can set up to 384000. For stage channels,
125 /// bitrate can be set up to 64000.
126 ///
127 /// Only for [`ChannelType::Voice`] and [`ChannelType::Stage`]
128 pub fn bitrate(mut self, rate: u32) -> Self {
129 self.bitrate = Some(rate);
130 self
131 }
132
133 /// Set how many users may occupy this voice channel
134 ///
135 /// Only for [`ChannelType::Voice`] and [`ChannelType::Stage`]
136 pub fn user_limit(mut self, limit: u32) -> Self {
137 self.user_limit = Some(limit);
138 self
139 }
140
141 /// How many seconds must a user wait before sending another message.
142 ///
143 /// Bots, or users with the [`MANAGE_MESSAGES`] and/or [`MANAGE_CHANNELS`] permissions are
144 /// exempt from this restriction.
145 ///
146 /// **Note**: Must be between 0 and 21600 seconds (360 minutes or 6 hours).
147 ///
148 /// [`MANAGE_MESSAGES`]: crate::model::permissions::Permissions::MANAGE_MESSAGES
149 /// [`MANAGE_CHANNELS`]: crate::model::permissions::Permissions::MANAGE_CHANNELS
150 #[doc(alias = "slowmode")]
151 pub fn rate_limit_per_user(mut self, seconds: u16) -> Self {
152 self.rate_limit_per_user = Some(seconds);
153 self
154 }
155
156 /// Specify where the channel should be located.
157 pub fn position(mut self, pos: u16) -> Self {
158 self.position = Some(pos);
159 self
160 }
161
162 /// A set of overwrites defining what a user or a user carrying a certain role can and cannot
163 /// do.
164 ///
165 /// # Example
166 ///
167 /// Inheriting permissions from an existing channel:
168 ///
169 /// ```rust,no_run
170 /// # use serenity::{http::Http, model::guild::Guild};
171 /// # use std::sync::Arc;
172 /// #
173 /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
174 /// # let http: Http = unimplemented!();
175 /// # let mut guild: Guild = unimplemented!();
176 /// use serenity::builder::CreateChannel;
177 /// use serenity::model::channel::{PermissionOverwrite, PermissionOverwriteType};
178 /// use serenity::model::id::UserId;
179 /// use serenity::model::permissions::Permissions;
180 ///
181 /// // Assuming a guild has already been bound.
182 /// let permissions = vec![PermissionOverwrite {
183 /// allow: Permissions::VIEW_CHANNEL,
184 /// deny: Permissions::SEND_TTS_MESSAGES,
185 /// kind: PermissionOverwriteType::Member(UserId::new(1234)),
186 /// }];
187 ///
188 /// let builder = CreateChannel::new("my_new_cool_channel").permissions(permissions);
189 /// guild.create_channel(&http, builder).await?;
190 /// # Ok(())
191 /// # }
192 /// ```
193 pub fn permissions(mut self, perms: impl IntoIterator<Item = PermissionOverwrite>) -> Self {
194 self.permission_overwrites = perms.into_iter().map(Into::into).collect();
195 self
196 }
197
198 /// Sets the request's audit log reason.
199 pub fn audit_log_reason(mut self, reason: &'a str) -> Self {
200 self.audit_log_reason = Some(reason);
201 self
202 }
203
204 /// Channel voice region id of the voice or stage channel, automatic when not set
205 ///
206 /// Only for [`ChannelType::Voice`] and [`ChannelType::Stage`]
207 pub fn rtc_region(mut self, rtc_region: String) -> Self {
208 self.rtc_region = Some(rtc_region);
209 self
210 }
211
212 /// The camera video quality mode of the voice channel
213 ///
214 /// Only for [`ChannelType::Voice`] and [`ChannelType::Stage`]
215 pub fn video_quality_mode(mut self, video_quality_mode: VideoQualityMode) -> Self {
216 self.video_quality_mode = Some(video_quality_mode);
217 self
218 }
219
220 /// The default duration that the clients use (not the API) for newly created threads in the
221 /// channel, in minutes, to automatically archive the thread after recent activity
222 ///
223 /// Only for [`ChannelType::Text`], [`ChannelType::News`], [`ChannelType::Forum`]
224 pub fn default_auto_archive_duration(
225 mut self,
226 default_auto_archive_duration: AutoArchiveDuration,
227 ) -> Self {
228 self.default_auto_archive_duration = Some(default_auto_archive_duration);
229 self
230 }
231
232 /// Emoji to show in the add reaction button on a thread in a forum
233 ///
234 /// Only for [`ChannelType::Forum`]
235 pub fn default_reaction_emoji(mut self, default_reaction_emoji: ForumEmoji) -> Self {
236 self.default_reaction_emoji = Some(default_reaction_emoji);
237 self
238 }
239
240 /// Set of tags that can be used in a forum channel
241 ///
242 /// Only for [`ChannelType::Forum`]
243 pub fn available_tags(mut self, available_tags: impl IntoIterator<Item = ForumTag>) -> Self {
244 self.available_tags = available_tags.into_iter().collect();
245 self
246 }
247
248 /// The default sort order type used to order posts in forum channels
249 ///
250 /// Only for [`ChannelType::Forum`]
251 pub fn default_sort_order(mut self, default_sort_order: SortOrder) -> Self {
252 self.default_sort_order = Some(default_sort_order);
253 self
254 }
255}
256
257#[cfg(feature = "http")]
258#[async_trait::async_trait]
259impl Builder for CreateChannel<'_> {
260 type Context<'ctx> = GuildId;
261 type Built = GuildChannel;
262
263 /// Creates a new [`Channel`] in the guild.
264 ///
265 /// **Note**: Requires the [Manage Channels] permission.
266 ///
267 /// # Errors
268 ///
269 /// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
270 /// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
271 ///
272 /// [Manage Channels]: Permissions::MANAGE_CHANNELS
273 async fn execute(
274 self,
275 cache_http: impl CacheHttp,
276 ctx: Self::Context<'_>,
277 ) -> Result<Self::Built> {
278 #[cfg(feature = "cache")]
279 crate::utils::user_has_guild_perms(&cache_http, ctx, Permissions::MANAGE_CHANNELS)?;
280
281 cache_http.http().create_channel(ctx, &self, self.audit_log_reason).await
282 }
283}