diff options
| author | Zeyla Hellyer <[email protected]> | 2017-04-26 21:27:16 -0700 |
|---|---|---|
| committer | Zeyla Hellyer <[email protected]> | 2017-04-26 21:27:16 -0700 |
| commit | 9268f9c10ef47ffeaeb3d5040e65b1093e04b866 (patch) | |
| tree | 94f8b0a8d38b2f91206ee2010ee110c3b1ce76dd | |
| parent | Make `User.discriminator` a u16 (diff) | |
| download | serenity-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.rs | 13 | ||||
| -rw-r--r-- | src/model/channel/guild_channel.rs | 16 | ||||
| -rw-r--r-- | src/model/channel/mod.rs | 14 | ||||
| -rw-r--r-- | src/model/channel/private_channel.rs | 13 | ||||
| -rw-r--r-- | src/utils/mod.rs | 53 | ||||
| -rw-r--r-- | tests/test_channels.rs | 79 |
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()); +} |