aboutsummaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
authorIllia K <[email protected]>2016-11-28 12:28:23 +0000
committerAustin Hellyer <[email protected]>2016-11-28 10:16:22 -0800
commit6c2c7b73d9fb5ed46b642e323065c560ffef9ef2 (patch)
tree8cb587fd6fcd8e3e06f8960475ea2a54432e3d18 /src/utils
parentAdd an initial tiny test suite to get Travis going (diff)
downloadserenity-6c2c7b73d9fb5ed46b642e323065c560ffef9ef2.tar.xz
serenity-6c2c7b73d9fb5ed46b642e323065c560ffef9ef2.zip
Improve docs and add new message builder methods
Add documentation for some missing methods - such as Game methods - and add more methods to the Message Builder.
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/builder/edit_guild.rs10
-rw-r--r--src/utils/builder/edit_profile.rs10
-rw-r--r--src/utils/message_builder.rs171
-rw-r--r--src/utils/mod.rs10
4 files changed, 171 insertions, 30 deletions
diff --git a/src/utils/builder/edit_guild.rs b/src/utils/builder/edit_guild.rs
index dd4ce84..43e93da 100644
--- a/src/utils/builder/edit_guild.rs
+++ b/src/utils/builder/edit_guild.rs
@@ -51,14 +51,8 @@ impl EditGuild {
///
/// // assuming a `guild` has already been bound
///
- /// let base64_icon = match utils::read_image("./guild_icon.png") {
- /// Ok(base64_icon) => base64_icon,
- /// Err(why) => {
- /// println!("Error reading image: {:?}", why);
- ///
- /// return;
- /// },
- /// };
+ /// let base64_icon = utils::read_image("./guild_icon.png")
+ /// .expect("Failed to read image");
///
/// let _ = guild.edit(|g| g.icon(base64_icon));
/// ```
diff --git a/src/utils/builder/edit_profile.rs b/src/utils/builder/edit_profile.rs
index 257a8e5..4517ae2 100644
--- a/src/utils/builder/edit_profile.rs
+++ b/src/utils/builder/edit_profile.rs
@@ -20,14 +20,8 @@ impl EditProfile {
///
/// // assuming you are in a context
///
- /// let base64 = match utils::read_image("./my_image.jpg") {
- /// Ok(base64) => base64,
- /// Err(why) => {
- /// println!("Error reading image: {:?}", why);
- ///
- /// return;
- /// },
- /// };
+ /// let base64 = utils::read_image("./my_image.jpg")
+ /// .expect("Failed to read image");
///
/// let _ = context.edit_profile(|profile| {
/// profile.avatar(Some(base64))
diff --git a/src/utils/message_builder.rs b/src/utils/message_builder.rs
index ca1ac8d..0a78815 100644
--- a/src/utils/message_builder.rs
+++ b/src/utils/message_builder.rs
@@ -1,5 +1,5 @@
use std::default::Default;
-use std::fmt;
+use std::fmt::{self, Write};
use ::model::{ChannelId, Emoji, Mentionable, RoleId, UserId};
/// The Message Builder is an ergonomic utility to easily build a message,
@@ -28,6 +28,28 @@ use ::model::{ChannelId, Emoji, Mentionable, RoleId, UserId};
/// [`build`]: #method.build
/// [`emoji`]: #method.emoji
/// [`user`]: #method.user
+
+fn normalize(text: &str) -> String {
+ // Remove everyone and here mentions
+ // This changes 'at' symbol to a full-width variation
+ text.replace("@everyone", "@everyone")
+ .replace("@here", "@here")
+ // Remove invite links and popular scam websites, mostly to prevent the
+ // current user from triggering various ad detectors
+ .replace("discord.gg", "discord․gg")
+ .replace("discord.me", "discord․me")
+ .replace("discordlist.net", "discordlist․net")
+ .replace("discordservers.com", "discordservers․com")
+ .replace("discordapp.com/invite", "discordapp․com/invite")
+ // Remove right-to-left and other similar overrides
+ .replace('\u{202E}', " ") // RTL
+ .replace('\u{200F}', " ") // RTL Mark
+ .replace('\u{202B}', " ") // RTL Embedding
+ .replace('\u{200B}', " ") // Zero-width space
+ .replace('\u{200D}', " ") // Zero-width joiner
+ .replace('\u{200C}', " ") // Zero-width non-joiner
+}
+
pub struct MessageBuilder(pub String);
impl MessageBuilder {
@@ -65,7 +87,7 @@ impl MessageBuilder {
/// [`GuildChannel`]: ../model/struct.GuildChannel.html
/// [Display implementation]: ../model/struct.ChannelId.html#method.fmt-1
pub fn channel<C: Into<ChannelId>>(mut self, channel: C) -> Self {
- self.0.push_str(&format!("{}", channel.into()));
+ write!(self.0, "{}", channel.into());
self
}
@@ -77,7 +99,7 @@ impl MessageBuilder {
///
/// [Display implementation]: ../model/struct.Emoji.html#method.fmt
pub fn emoji(mut self, emoji: Emoji) -> Self {
- self.0.push_str(&format!("{}", emoji));
+ write!(self.0, "{}", emoji);
self
}
@@ -86,7 +108,7 @@ impl MessageBuilder {
///
/// [`Mentionable`]: ../model/trait.Mentionable.html
pub fn mention<M: Mentionable>(mut self, item: M) -> Self {
- self.0.push_str(&item.mention());
+ write!(self.0, "{}", item.mention());
self
}
@@ -112,6 +134,143 @@ impl MessageBuilder {
self
}
+ /// Pushes a code-block to your message, with optional syntax highlighting.
+ pub fn push_codeblock(mut self, content: &str, language: Option<&str>) -> Self {
+ self.0.push_str("```");
+
+ if let Some(language) = language {
+ self.0.push_str(language);
+ }
+
+ self.0.push('\n');
+ self.0.push_str(content);
+ self.0.push_str("\n```");
+
+ self
+ }
+
+ /// Pushes an inline monospaced text to your message.
+ pub fn push_mono(mut self, content: &str) -> Self {
+ self.0.push('`');
+ self.0.push_str(content);
+ self.0.push('`');
+
+ self
+ }
+
+ /// Pushes an inline italicized text to your message.
+ pub fn push_italic(mut self, content: &str) -> Self {
+ self.0.push('_');
+ self.0.push_str(content);
+ self.0.push('_');
+
+ self
+ }
+
+ /// Pushes an inline bold text to your message.
+ pub fn push_bold(mut self, content: &str) -> Self {
+ self.0.push_str("**");
+ self.0.push_str(content);
+ self.0.push_str("**");
+
+ self
+ }
+
+ /// Pushes an underlined inline text to your message.
+ pub fn push_underline(mut self, content: &str) -> Self {
+ self.0.push_str("__");
+ self.0.push_str(content);
+ self.0.push_str("__");
+
+ self
+ }
+
+ /// Pushes a strikethrough inline text to your message.
+ pub fn push_strike(mut self, content: &str) -> Self {
+ self.0.push_str("~~");
+ self.0.push_str(content);
+ self.0.push_str("~~");
+
+ self
+ }
+
+ /// Pushes text to your message, but normalizing content - that means
+ /// ensuring that there's no unwanted formatting, mention spam etc.
+ pub fn push_safe(mut self, content: &str) -> Self {
+ let normalized = normalize(&content)
+ .replace('*', "\\*")
+ .replace('`', "\\`")
+ .replace('_', "\\_");
+
+ self.0.push_str(&normalized);
+
+ self
+ }
+
+ /// Pushes a code-block to your message normalizing content.
+ pub fn push_codeblock_safe(mut self, content: &str, language: Option<&str>)
+ -> Self {
+ let mut content = &normalize(&content)
+ .replace("```", "\u{201B}\u{201B}\u{201B}");
+
+ self.0.push_str("```");
+
+ if let Some(language) = language {
+ self.0.push_str(language);
+ }
+
+ self.0.push('\n');
+ self.0.push_str(content);
+ self.0.push_str("```");
+
+ self
+ }
+
+ /// Pushes an inline monospaced text to your message normalizing content.
+ pub fn push_mono_safe(mut self, content: &str) -> Self {
+ self.0.push('`');
+ self.0.push_str(&normalize(content).replace("`", "\u{201B}"));
+ self.0.push('`');
+
+ self
+ }
+
+ /// Pushes an inline italicized text to your message normalizing content.
+ pub fn push_italic_safe(mut self, content: &str) -> Self {
+ self.0.push('_');
+ self.0.push_str(&normalize(content).replace('_', "_"));
+ self.0.push('_');
+
+ self
+ }
+
+ /// Pushes an inline bold text to your message normalizing content.
+ pub fn push_bold_safe(mut self, content: &str) -> Self {
+ self.0.push_str("**");
+ self.0.push_str(&normalize(content).replace("**", "∗∗"));
+ self.0.push_str("**");
+
+ self
+ }
+
+ /// Pushes an underlined inline text to your message normalizing content.
+ pub fn push_underline_safe(mut self, content: &str) -> Self {
+ self.0.push_str("__");
+ self.0.push_str(&normalize(content).replace("__", "__"));
+ self.0.push_str("__");
+
+ self
+ }
+
+ /// Pushes a strikethrough inline text to your message normalizing content.
+ pub fn push_strike_safe(mut self, content: &str) -> Self {
+ self.0.push_str("~~");
+ self.0.push_str(&normalize(content).replace("~~", "∼∼"));
+ self.0.push_str("~~");
+
+ self
+ }
+
/// Mentions the [`Role`] in the built message.
///
/// This accepts anything that converts _into_ a [`RoleId`]. Refer to
@@ -124,7 +283,7 @@ impl MessageBuilder {
/// [`RoleId`]: ../model/struct.RoleId.html
/// [Display implementation]: ../model/struct.RoleId.html#method.fmt-1
pub fn role<R: Into<RoleId>>(mut self, role: R) -> Self {
- self.0.push_str(&format!("{}", role.into()));
+ write!(self.0, "{}", role.into());
self
}
@@ -141,7 +300,7 @@ impl MessageBuilder {
/// [`UserId`]: ../model/struct.UserId.html
/// [Display implementation]: ../model/struct.UserId.html#method.fmt-1
pub fn user<U: Into<UserId>>(mut self, user: U) -> Self {
- self.0.push_str(&format!("{}", user.into()));
+ write!(self.0, "{}", user.into());
self
}
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index 2356ece..0c154dd 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -148,14 +148,8 @@ pub fn parse_invite(code: &str) -> &str {
/// ```rust,no_run
/// use serenity::utils;
///
-/// let image = match utils::read_image("./cat.png") {
-/// Ok(image) => image,
-/// Err(why) => {
-/// // properly handle the error
-///
-/// return;
-/// },
-/// };
+/// let image = utils::read_image("./cat.png")
+/// .expect("Failed to read image");
/// ```
///
/// [`EditProfile::avatar`]: ../builder/struct.EditProfile.html#method.avatar