Skip to content

Commit

Permalink
Add Function to neutralise Mentions (serenity-rs#414)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lakelezz committed Oct 30, 2018
1 parent 41ff44b commit 867a744
Show file tree
Hide file tree
Showing 4 changed files with 579 additions and 7 deletions.
31 changes: 31 additions & 0 deletions examples/05_command_framework/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use serenity::model::gateway::Ready;
use serenity::model::Permissions;
use serenity::prelude::Mutex;
use serenity::prelude::*;
use serenity::utils::{content_safe, ContentSafeOptions};
use std::collections::HashMap;
use std::env;
use std::fmt::Write;
Expand Down Expand Up @@ -175,6 +176,10 @@ fn main() {
// Make this command use the "complicated" bucket.
.bucket("complicated")
.cmd(commands))
// Command that will repeat passed arguments and remove user and
// role mentions with safe alternative.
.command("say", |c| c
.cmd(say))
.group("Emoji", |g| g
// Sets multiple prefixes for a group.
// This requires us to call commands in this group
Expand Down Expand Up @@ -250,6 +255,32 @@ command!(commands(ctx, msg, _args) {
}
});

// Repeats what the user passed as argument but ensures that user and role
// mentions are replaced with a safe textual alternative.
// In this example channel mentions are excluded via the `ContentSafeOptions`.
command!(say(_ctx, msg, args) {
let mut settings = if let Some(guild_id) = msg.guild_id {
// By default roles, users, and channel mentions are cleaned.
ContentSafeOptions::default()
// We do not want to clean channal mentions as they
// do not ping users.
.clean_channel(false)
// If it's a guild channel, we want mentioned users to be displayed
// as their display name.
.display_as_member_from(guild_id)
} else {
ContentSafeOptions::default()
.clean_channel(false)
.clean_role(false)
};

let mut content = content_safe(&args.full(), &settings);

if let Err(why) = msg.channel_id.say(&content) {
println!("Error sending message: {:?}", why);
}
});

// A function which acts as a "check", to determine whether to call a command.
//
// In this case, this command checks to ensure you are the owner of the message
Expand Down
14 changes: 13 additions & 1 deletion src/model/channel/channel_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use builder::{
};
#[cfg(all(feature = "cache", feature = "model"))]
use CACHE;
#[cfg(all(feature = "cache", feature = "model"))]
use Cache;
#[cfg(feature = "model")]
use http::{self, AttachmentType};
#[cfg(feature = "model")]
Expand Down Expand Up @@ -293,7 +295,17 @@ impl ChannelId {
/// [`Channel`]: ../channel/enum.Channel.html
#[cfg(feature = "cache")]
#[inline]
pub fn to_channel_cached(self) -> Option<Channel> { CACHE.read().channel(self) }
pub fn to_channel_cached(self) -> Option<Channel> {
self._to_channel_cached(&CACHE)
}

/// To allow testing pass their own cache instead of using the globale one.
#[cfg(feature = "cache")]
#[inline]
pub(crate) fn _to_channel_cached(self, cache: &RwLock<Cache>) -> Option<Channel> {
cache.read().channel(self)
}


/// Search the cache for the channel. If it can't be found, the channel is
/// requested over REST.
Expand Down
9 changes: 6 additions & 3 deletions src/model/guild/role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use builder::EditRole;
#[cfg(all(feature = "cache", feature = "model"))]
use internal::prelude::*;
#[cfg(all(feature = "cache", feature = "model"))]
use {CACHE, http};
use {CACHE, Cache, http};

#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use std::str::FromStr;
Expand Down Expand Up @@ -182,9 +182,12 @@ impl RoleId {
/// [`Role`]: ../guild/struct.Role.html
#[cfg(feature = "cache")]
pub fn to_role_cached(self) -> Option<Role> {
let cache = CACHE.read();
self._to_role_cached(&CACHE)
}

for guild in cache.guilds.values() {
#[cfg(feature = "cache")]
pub(crate) fn _to_role_cached(self, cache: &RwLock<Cache>) -> Option<Role> {
for guild in cache.read().guilds.values() {
let guild = guild.read();

if !guild.roles.contains_key(&self) {
Expand Down
Loading

0 comments on commit 867a744

Please sign in to comment.