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}