diff options
| author | Illia K <[email protected]> | 2016-11-28 12:28:23 +0000 |
|---|---|---|
| committer | Austin Hellyer <[email protected]> | 2016-11-28 10:16:22 -0800 |
| commit | 6c2c7b73d9fb5ed46b642e323065c560ffef9ef2 (patch) | |
| tree | 8cb587fd6fcd8e3e06f8960475ea2a54432e3d18 /src/utils | |
| parent | Add an initial tiny test suite to get Travis going (diff) | |
| download | serenity-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.rs | 10 | ||||
| -rw-r--r-- | src/utils/builder/edit_profile.rs | 10 | ||||
| -rw-r--r-- | src/utils/message_builder.rs | 171 | ||||
| -rw-r--r-- | src/utils/mod.rs | 10 |
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 |