Skip to content

Commit

Permalink
Rework CreateChannel
Browse files Browse the repository at this point in the history
  • Loading branch information
mkrasnitski committed Jun 29, 2022
1 parent 28d6f3a commit 7ff0b7e
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 85 deletions.
99 changes: 61 additions & 38 deletions src/builder/create_channel.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#[cfg(feature = "http")]
use crate::http::{CacheHttp, Http};
#[cfg(feature = "http")]
use crate::internal::prelude::*;
use crate::model::prelude::*;

/// A builder for creating a new [`GuildChannel`] in a [`Guild`].
///
/// Except [`Self::name`], all fields are optional.
///
/// [`GuildChannel`]: crate::model::channel::GuildChannel
/// [`Guild`]: crate::model::guild::Guild
#[derive(Debug, Clone, Serialize)]
#[derive(Clone, Debug, Serialize)]
#[must_use]
pub struct CreateChannel {
kind: ChannelType,
#[serde(skip_serializing_if = "Option::is_none")]
Expand All @@ -29,55 +31,87 @@ pub struct CreateChannel {
}

impl CreateChannel {
/// Creates a new [`Channel`] in the guild.
///
/// **Note**: Requires the [Manage Channels] permission.
///
/// # Errors
///
/// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
/// lacks permission. Otherwise, returns [`Error::Http`], as well as if invalid data is given.
///
/// [Manage Channels]: Permissions::MANAGE_CHANNELS
#[cfg(feature = "http")]
#[inline]
pub async fn execute(
self,
cache_http: impl CacheHttp,
guild_id: GuildId,
) -> Result<GuildChannel> {
#[cfg(feature = "cache")]
{
if let Some(cache) = cache_http.cache() {
if let Some(guild) = cache.guild(guild_id) {
let req = Permissions::MANAGE_CHANNELS;

if !guild.has_perms(&cache_http, req).await {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
}
}

self._execute(cache_http.http(), guild_id).await
}

#[cfg(feature = "http")]
async fn _execute(self, http: &Http, guild_id: GuildId) -> Result<GuildChannel> {
http.create_channel(guild_id.into(), &self, None).await
}

/// Specify how to call this new channel.
///
/// **Note**: Must be between 2 and 100 characters long.
pub fn name(&mut self, name: impl Into<String>) -> &mut Self {
pub fn name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());

self
}

/// Specify what type the channel is, whether it's a text, voice, category or news channel.
pub fn kind(&mut self, kind: ChannelType) -> &mut Self {
pub fn kind(mut self, kind: ChannelType) -> Self {
self.kind = kind;

self
}

/// Specify the category, the "parent" of this channel.
pub fn category<I: Into<ChannelId>>(&mut self, id: I) -> &mut Self {
pub fn category<I: Into<ChannelId>>(mut self, id: I) -> Self {
self.parent_id = Some(id.into());

self
}

/// Set an interesting topic.
///
/// **Note**: Must be between 0 and 1000 characters long.
pub fn topic(&mut self, topic: impl Into<String>) -> &mut Self {
pub fn topic(mut self, topic: impl Into<String>) -> Self {
self.topic = Some(topic.into());

self
}

/// Specify if this channel will be inappropriate to browse while at work.
pub fn nsfw(&mut self, b: bool) -> &mut Self {
pub fn nsfw(mut self, b: bool) -> Self {
self.nsfw = Some(b);

self
}

/// [Voice-only] Specify the bitrate at which sound plays in the voice channel.
pub fn bitrate(&mut self, rate: u32) -> &mut Self {
pub fn bitrate(mut self, rate: u32) -> Self {
self.bitrate = Some(rate);

self
}

/// [Voice-only] Set how many users may occupy this voice channel.
pub fn user_limit(&mut self, limit: u32) -> &mut Self {
pub fn user_limit(mut self, limit: u32) -> Self {
self.user_limit = Some(limit);

self
}

Expand All @@ -91,21 +125,19 @@ impl CreateChannel {
/// [`MANAGE_MESSAGES`]: crate::model::permissions::Permissions::MANAGE_MESSAGES
/// [`MANAGE_CHANNELS`]: crate::model::permissions::Permissions::MANAGE_CHANNELS
#[doc(alias = "slowmode")]
pub fn rate_limit_per_user(&mut self, seconds: u64) -> &mut Self {
pub fn rate_limit_per_user(mut self, seconds: u64) -> Self {
self.rate_limit_per_user = Some(seconds);

self
}

/// Specify where the channel should be located.
pub fn position(&mut self, pos: u32) -> &mut Self {
pub fn position(mut self, pos: u32) -> Self {
self.position = Some(pos);

self
}

/// A set of overwrites defining what a user or a user carrying a certain role can
/// and cannot do.
/// A set of overwrites defining what a user or a user carrying a certain role can and cannot
/// do.
///
/// # Example
///
Expand All @@ -118,6 +150,7 @@ impl CreateChannel {
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
/// # let http = Arc::new(Http::new("token"));
/// # let mut guild = GuildId::new(1).to_partial_guild(&http).await?;
/// use serenity::builder::CreateChannel;
/// use serenity::model::channel::{PermissionOverwrite, PermissionOverwriteType};
/// use serenity::model::id::UserId;
/// use serenity::model::permissions::Permissions;
Expand All @@ -129,34 +162,24 @@ impl CreateChannel {
/// kind: PermissionOverwriteType::Member(UserId::new(1234)),
/// }];
///
/// guild.create_channel(http, |c| c.name("my_new_cool_channel").permissions(permissions)).await?;
/// let builder = CreateChannel::default().name("my_new_cool_channel").permissions(permissions);
/// guild.create_channel(&http, builder).await?;
/// # Ok(())
/// # }
/// ```
pub fn permissions<I>(&mut self, perms: I) -> &mut Self
pub fn permissions<I>(mut self, perms: I) -> Self
where
I: IntoIterator<Item = PermissionOverwrite>,
{
self.permission_overwrites = perms.into_iter().map(Into::into).collect();

self
}
}

impl Default for CreateChannel {
/// Creates a builder with default values, setting [`Self::kind`] to [`ChannelType::Text`].
///
/// # Examples
///
/// Create a default [`CreateChannel`] builder:
///
/// ```rust
/// use serenity::builder::CreateChannel;
///
/// let channel_builder = CreateChannel::default();
/// ```
fn default() -> Self {
CreateChannel {
Self {
name: None,
nsfw: None,
topic: None,
Expand Down
25 changes: 12 additions & 13 deletions src/model/guild/guild_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,40 +199,39 @@ impl GuildId {
///
/// Refer to [`Http::create_channel`] for more information.
///
/// Requires the [Manage Channels] permission.
/// **Note**: Requires the [Manage Channels] permission.
///
/// # Examples
///
/// Create a voice channel in a guild with the name `test`:
///
/// ```rust,no_run
/// # use serenity::http::Http;
/// use serenity::builder::CreateChannel;
/// use serenity::model::channel::ChannelType;
/// use serenity::model::id::GuildId;
///
/// # async fn run() {
/// # use serenity::http::Http;
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
/// # let http = Http::new("token");
/// let _channel =
/// GuildId::new(7).create_channel(&http, |c| c.name("test").kind(ChannelType::Voice)).await;
/// let builder = CreateChannel::default().name("test").kind(ChannelType::Voice);
/// let _channel = GuildId::new(7).create_channel(&http, builder).await?;
/// # Ok(())
/// # }
/// ```
///
/// # Errors
///
/// Returns [`Error::Http`] if the current user lacks permission,
/// or if invalid values are set.
/// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
/// lacks permission. Otherwise, returns [`Error::Http`], as well as if invalid data is given.
///
/// [Manage Channels]: Permissions::MANAGE_CHANNELS
#[inline]
pub async fn create_channel(
self,
http: impl AsRef<Http>,
f: impl FnOnce(&mut CreateChannel) -> &mut CreateChannel,
cache_http: impl CacheHttp,
builder: CreateChannel,
) -> Result<GuildChannel> {
let mut builder = CreateChannel::default();
f(&mut builder);

http.as_ref().create_channel(self.get(), &builder, None).await
builder.execute(cache_http, self).await
}

/// Creates an emoji in the guild with a name and base64-encoded image.
Expand Down
41 changes: 18 additions & 23 deletions src/model/guild/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,41 +559,36 @@ impl Guild {
///
/// # Examples
///
/// ```rust,ignore
/// use serenity::model::ChannelType;
/// ```rust,no_run
/// # use serenity::http::Http;
/// # use serenity::model::guild::Guild;
/// # use serenity::model::id::GuildId;
/// use serenity::builder::CreateChannel;
/// use serenity::model::channel::ChannelType;
///
/// // assuming a `guild` has already been bound
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
/// # let http = Http::new("token");
/// # let guild = Guild::get(&http, GuildId::new(7)).await?;
/// let builder = CreateChannel::default().name("my-test-channel").kind(ChannelType::Text);
///
/// let _ = guild
/// .create_channel(&http, |c| c.name("my-test-channel").kind(ChannelType::Text))
/// .await;
/// // assuming a `guild` has already been bound
/// let _channel = guild.create_channel(&http, builder).await?;
/// # Ok(())
/// # }
/// ```
///
/// # Errors
///
/// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`]
/// if the current user does not have permission to manage channels.
///
/// Otherwise will return [`Error::Http`] if the current user lacks permission.
/// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
/// lacks permission. Otherwise, returns [`Error::Http`], as well as if invalid data is given.
///
/// [Manage Channels]: Permissions::MANAGE_CHANNELS
pub async fn create_channel(
&self,
cache_http: impl CacheHttp,
f: impl FnOnce(&mut CreateChannel) -> &mut CreateChannel,
builder: CreateChannel,
) -> Result<GuildChannel> {
#[cfg(feature = "cache")]
{
if cache_http.cache().is_some() {
let req = Permissions::MANAGE_CHANNELS;

if !self.has_perms(&cache_http, req).await {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
}

self.id.create_channel(cache_http.http(), f).await
self.id.create_channel(cache_http, builder).await
}

/// Creates an emoji in the guild with a name and base64-encoded image. The
Expand Down
32 changes: 21 additions & 11 deletions src/model/guild/partial_guild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,32 +273,42 @@ impl PartialGuild {
///
/// Refer to [`Http::create_channel`] for more information.
///
/// Requires the [Manage Channels] permission.
/// **Note**: Requires the [Manage Channels] permission.
///
/// # Examples
///
/// Create a voice channel in a guild with the name `test`:
///
/// ```rust,ignore
/// use serenity::model::ChannelType;
/// ```rust,no_run
/// # use serenity::http::Http;
/// # use serenity::model::guild::PartialGuild;
/// # use serenity::model::id::GuildId;
/// use serenity::builder::CreateChannel;
/// use serenity::model::channel::ChannelType;
///
/// guild.create_channel(|c| c.name("test").kind(ChannelType::Voice));
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
/// # let http = Http::new("token");
/// # let guild = PartialGuild::get(&http, GuildId::new(7)).await?;
/// let builder = CreateChannel::default().name("my-test-channel").kind(ChannelType::Text);
///
/// // assuming a `guild` has already been bound
/// let _channel = guild.create_channel(&http, builder).await?;
/// # Ok(())
/// # }
/// ```
///
/// # Errors
///
/// Returns [`Error::Http`] if the current user lacks permission,
/// or if invalid data was given, such as the channel name being
/// too long.
/// If the `cache` is enabled, returns a [`ModelError::InvalidPermissions`] if the current user
/// lacks permission. Otherwise, returns [`Error::Http`], as well as if invalid data is given.
///
/// [Manage Channels]: Permissions::MANAGE_CHANNELS
#[inline]
pub async fn create_channel(
&self,
http: impl AsRef<Http>,
f: impl FnOnce(&mut CreateChannel) -> &mut CreateChannel,
cache_http: impl CacheHttp,
builder: CreateChannel,
) -> Result<GuildChannel> {
self.id.create_channel(&http, f).await
self.id.create_channel(cache_http, builder).await
}

/// Creates an emoji in the guild with a name and base64-encoded image.
Expand Down

0 comments on commit 7ff0b7e

Please sign in to comment.