aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2017-04-26 21:27:16 -0700
committerZeyla Hellyer <[email protected]>2017-04-26 21:27:16 -0700
commit9268f9c10ef47ffeaeb3d5040e65b1093e04b866 (patch)
tree94f8b0a8d38b2f91206ee2010ee110c3b1ce76dd
parentMake `User.discriminator` a u16 (diff)
downloadserenity-9268f9c10ef47ffeaeb3d5040e65b1093e04b866.tar.xz
serenity-9268f9c10ef47ffeaeb3d5040e65b1093e04b866.zip
Add `is_nsfw` check to channels
A new feature in Discord is warning users about NSFW channels. This can be useful when wanting to determine if a command can be used in a channel or not, depending on the command content. To help with this, provide a utility function named `utils::is_nsfw`. This function accepts a channel name, which determines if the channel is NSFW. This information is not provided with data from the server. It is determined client-side based on a few rules. The rules for a channel being NSFW are: - must be a guild channel - must be a text channel - must be named `nsfw` or be prefixed with `nsfw-` If any of these conditions are false, then the channel is not NSFW. Additionally, provide four helper methods: - `GuildChannel::is_nsfw`: follows rules - `Group::is_nsfw`: always false - `PrivateChannel::is_nsfw`: always false - `Channel::is_nsfw`: depends on inner channel (one of 3 above) This check is volatile, as Discord may change requirements at any time. The check provided by the library should not be taken as being accurate all the time.
-rw-r--r--src/model/channel/group.rs13
-rw-r--r--src/model/channel/guild_channel.rs16
-rw-r--r--src/model/channel/mod.rs14
-rw-r--r--src/model/channel/private_channel.rs13
-rw-r--r--src/utils/mod.rs53
-rw-r--r--tests/test_channels.rs79
6 files changed, 188 insertions, 0 deletions
diff --git a/src/model/channel/group.rs b/src/model/channel/group.rs
index b85bc7d..bf87590 100644
--- a/src/model/channel/group.rs
+++ b/src/model/channel/group.rs
@@ -149,6 +149,19 @@ impl Group {
format!(cdn!("/channel-icons/{}/{}.webp"), self.channel_id, icon))
}
+ /// Determines if the channel is NSFW.
+ ///
+ /// Refer to [`utils::is_nsfw`] for more details.
+ ///
+ /// **Note**: This method is for consistency. This will always return
+ /// `false`, due to groups not being considered NSFW.
+ ///
+ /// [`utils::is_nsfw`]: ../utils/fn.is_nsfw.html
+ #[inline]
+ pub fn is_nsfw(&self) -> bool {
+ false
+ }
+
/// Leaves the group.
#[inline]
pub fn leave(&self) -> Result<Group> {
diff --git a/src/model/channel/guild_channel.rs b/src/model/channel/guild_channel.rs
index 6cbdda0..d8fa5c2 100644
--- a/src/model/channel/guild_channel.rs
+++ b/src/model/channel/guild_channel.rs
@@ -5,6 +5,7 @@ use ::client::rest;
use ::internal::prelude::*;
use ::model::*;
use ::utils::builder::{CreateInvite, CreateMessage, EditChannel, GetMessages};
+use ::utils as serenity_utils;
#[cfg(feature="cache")]
use ::client::CACHE;
@@ -319,6 +320,21 @@ impl GuildChannel {
self.id.invites()
}
+ /// Determines if the channel is NSFW.
+ ///
+ /// Refer to [`utils::is_nsfw`] for more details.
+ ///
+ /// Only [text channels][`ChannelType::Text`] are taken into consideration
+ /// as being NSFW. [voice channels][`ChannelType::Voice`] are never NSFW.
+ ///
+ /// [`ChannelType::Text`]: enum.ChannelType.html#variant.Text
+ /// [`ChannelType::Voice`]: enum.ChannelType.html#variant.Voice
+ /// [`utils::is_nsfw`]: ../utils/fn.is_nsfw.html
+ #[inline]
+ pub fn is_nsfw(&self) -> bool {
+ self.kind == ChannelType::Text && serenity_utils::is_nsfw(&self.name)
+ }
+
/// Gets a message from the channel.
///
/// Requires the [Read Message History] permission.
diff --git a/src/model/channel/mod.rs b/src/model/channel/mod.rs
index 09cf70a..a54acdf 100644
--- a/src/model/channel/mod.rs
+++ b/src/model/channel/mod.rs
@@ -165,6 +165,20 @@ impl Channel {
self.id().edit_message(message_id, f)
}
+ /// Determines if the channel is NSFW.
+ ///
+ /// Refer to [`utils::is_nsfw`] for more details.
+ ///
+ /// [`utils::is_nsfw`]: ../utils/fn.is_nsfw.html
+ #[inline]
+ pub fn is_nsfw(&self) -> bool {
+ match *self {
+ Channel::Group(_) => false,
+ Channel::Guild(ref channel) => channel.read().unwrap().is_nsfw(),
+ Channel::Private(_) => false,
+ }
+ }
+
/// Gets a message from the channel.
///
/// Requires the [Read Message History] permission.
diff --git a/src/model/channel/private_channel.rs b/src/model/channel/private_channel.rs
index 2ede408..910daa2 100644
--- a/src/model/channel/private_channel.rs
+++ b/src/model/channel/private_channel.rs
@@ -128,6 +128,19 @@ impl PrivateChannel {
self.id.edit_message(message_id, f)
}
+ /// Determines if the channel is NSFW.
+ ///
+ /// Refer to [`utils::is_nsfw`] for more details.
+ ///
+ /// **Note**: This method is for consistency. This will always return
+ /// `false`, due to DMs not being considered NSFW.
+ ///
+ /// [`utils::is_nsfw`]: ../utils/fn.is_nsfw.html
+ #[inline]
+ pub fn is_nsfw(&self) -> bool {
+ false
+ }
+
/// Gets a message from the channel.
///
/// Requires the [Read Message History] permission.
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index adb2d45..ec19ff7 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -22,6 +22,59 @@ use ::model::{EmojiIdentifier, EmojiId};
pub use self::message_builder::MessageBuilder;
+/// Determines if a name is NSFW.
+///
+/// This checks that the name is either `"nsfw"` or, for names longer than that,
+/// is prefixed with `"nsfw"`.
+///
+/// **Note**: Whether a channel is NSFW is done client-side, as a field for the
+/// NSFW-ness of a channel is not sent to clients. Discord's requirements for
+/// defining a channel as NSFW can change at any time.
+///
+/// # Examples
+///
+/// Check that a channel named `"nsfw"` is in fact NSFW:
+///
+/// ```rust
+/// use serenity::utils;
+///
+/// assert!(utils::is_nsfw("nsfw"));
+/// ```
+///
+/// Check that a channel named `"cats"` is _not_ NSFW:
+///
+/// ```rust
+/// use serenity::utils;
+///
+/// assert!(!utils::is_nsfw("cats"));
+/// ```
+///
+/// Check that a channel named `"nsfw-stuff"` _is_ NSFW:
+///
+/// ```rust
+/// use serenity::utils;
+///
+/// assert!(utils::is_nsfw("nsfw-stuff"));
+/// ```
+///
+/// Channels prefixed with `"nsfw"` but not the hyphen (`'-'`) are _not_
+/// considered NSFW:
+///
+/// ```rust
+/// use serenity::utils;
+///
+/// assert!(!utils::is_nsfw("nsfwstuff"));
+/// ```
+pub fn is_nsfw(name: &str) -> bool {
+ if name.len() == 4 {
+ &name[..4] == "nsfw"
+ } else if name.len() > 4 {
+ &name[..5] == "nsfw-"
+ } else {
+ false
+ }
+}
+
/// Retrieves the "code" part of an [invite][`RichInvite`] out of a URL.
///
/// # Examples
diff --git a/tests/test_channels.rs b/tests/test_channels.rs
new file mode 100644
index 0000000..5ceb333
--- /dev/null
+++ b/tests/test_channels.rs
@@ -0,0 +1,79 @@
+extern crate serenity;
+
+use serenity::model::*;
+use std::collections::HashMap;
+use std::sync::{Arc, RwLock};
+
+fn group() -> Group {
+ Group {
+ channel_id: ChannelId(1),
+ icon: None,
+ last_message_id: None,
+ last_pin_timestamp: None,
+ name: None,
+ owner_id: UserId(2),
+ recipients: HashMap::new(),
+ }
+}
+
+fn guild_channel() -> GuildChannel {
+ GuildChannel {
+ id: ChannelId(1),
+ bitrate: None,
+ guild_id: GuildId(2),
+ kind: ChannelType::Text,
+ last_message_id: None,
+ last_pin_timestamp: None,
+ name: "nsfw-stuff".to_owned(),
+ permission_overwrites: vec![],
+ position: 0,
+ topic: None,
+ user_limit: None,
+ }
+}
+
+fn private_channel() -> PrivateChannel {
+ PrivateChannel {
+ id: ChannelId(1),
+ last_message_id: None,
+ last_pin_timestamp: None,
+ kind: ChannelType::Private,
+ recipient: Arc::new(RwLock::new(User {
+ id: UserId(2),
+ avatar: None,
+ bot: false,
+ discriminator: 1,
+ name: "ab".to_owned(),
+ })),
+ }
+}
+
+#[test]
+fn nsfw_checks() {
+ let mut channel = guild_channel();
+ assert!(channel.is_nsfw());
+ channel.kind = ChannelType::Voice;
+ assert!(!channel.is_nsfw());
+
+ channel.kind = ChannelType::Text;
+ channel.name = "nsfw-".to_owned();
+ assert!(channel.is_nsfw());
+
+ channel.name = "nsfw".to_owned();
+ assert!(channel.is_nsfw());
+ channel.kind = ChannelType::Voice;
+ assert!(!channel.is_nsfw());
+ channel.kind = ChannelType::Text;
+
+ channel.name = "nsf".to_owned();
+ assert!(!channel.is_nsfw());
+
+ let channel = Channel::Guild(Arc::new(RwLock::new(channel)));
+ assert!(!channel.is_nsfw());
+
+ let group = group();
+ assert!(!group.is_nsfw());
+
+ let private_channel = private_channel();
+ assert!(!private_channel.is_nsfw());
+}