aboutsummaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/client/context.rs41
-rw-r--r--src/client/error.rs5
-rw-r--r--src/client/gateway/prep.rs4
-rw-r--r--src/client/gateway/shard.rs4
-rw-r--r--src/client/rest/mod.rs26
-rw-r--r--src/ext/cache/mod.rs12
-rw-r--r--src/ext/voice/threading.rs6
-rw-r--r--src/model/channel.rs26
-rw-r--r--src/model/gateway.rs2
-rw-r--r--src/model/id.rs14
-rw-r--r--src/model/webhook.rs10
-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
15 files changed, 262 insertions, 89 deletions
diff --git a/src/client/context.rs b/src/client/context.rs
index 26ed22c..5558658 100644
--- a/src/client/context.rs
+++ b/src/client/context.rs
@@ -403,6 +403,7 @@ impl Context {
/// [`Role`]: ../model/struct.Role.html
/// [Attach Files]: ../model/permissions/constant.ATTACH_FILES.html
/// [Manage Channels]: ../model/permissions/constant.MANAGE_CHANNELS.html
+ /// [Manage Webhooks]: ../model/permissions/constant.MANAGE_WEBHOOKS.html
/// [Send TTS Messages]: ../model/permissions/constant.SEND_TTS_MESSAGES.html
pub fn create_permission<C>(&self,
channel_id: C,
@@ -495,7 +496,7 @@ impl Context {
/// [`Channel`]: ../model/enum.Channel.html
/// [`Guild`]: ../model/struct.Guild.html
/// [`GuildChannel`]: ../model/struct.GuildChannel.html
- /// [Manage Messages]: ../model/permissions/constant.MANAGE_CHANNELS.html
+ /// [Manage Channels]: ../model/permissions/constant.MANAGE_CHANNELS.html
pub fn delete_channel<C>(&self, channel_id: C) -> Result<Channel>
where C: Into<ChannelId> {
rest::delete_channel(channel_id.into().0)
@@ -522,7 +523,7 @@ impl Context {
rest::delete_guild(guild_id.into().0)
}
- /// Deletes an integration by Id from a server which Id was given.
+ /// Deletes an integration by Id from a guild which Id was given.
pub fn delete_integration<G, I>(&self, guild_id: G, integration_id: I)
-> Result<()> where G: Into<GuildId>, I: Into<IntegrationId> {
rest::delete_guild_integration(guild_id.into().0,
@@ -622,7 +623,7 @@ impl Context {
/// Deletes the given [`Reaction`], but only if the current user is the user
/// who made the reaction or has permission to.
///
- /// **Note**: Requires the [`Manage Messages`] permission, _if_ the current
+ /// **Note**: Requires the [Manage Messages] permission, _if_ the current
/// user did not perform the reaction.
///
/// [`Reaction`]: ../model/struct.Reaction.html
@@ -698,7 +699,8 @@ impl Context {
}
/// Allows to configure channel options like position, name, etc.
- /// You can see available methods in `EditChannel` docs.
+ ///
+ /// You can see available methods in `EditChannel`s docs.
///
/// # Examples
///
@@ -758,19 +760,14 @@ impl Context {
///
/// # Examples
///
- /// Change a server's icon using a file name "icon.png":
+ /// Change a guild's icon using a file name "icon.png":
///
/// ```rust,ignore
/// use serenity::utils;
///
/// // We are using read_image helper function from utils.
- /// let base64_icon = match utils::read_image("./icon.png") {
- /// Ok(base64_icon) => base64_icon,
- /// Err(why) => {
- /// println!("Error reading image: {:?}", why);
- /// return;
- /// },
- /// };
+ /// let base64_icon = utils::read_image("./icon.png")
+ /// .expect("Failed to read image");
///
/// context.edit_guild(guild_id, |g|
/// g.icon(base64_icon));
@@ -782,14 +779,14 @@ impl Context {
rest::edit_guild(guild_id.into().0, map)
}
- /// Allows to do specific things with members of a server
- /// like mute, change nickname, etc.
- /// Full list of methods is available at `EditMember` docs.
+ /// Modify the properties of member of a guild, such as muting or nicknaming
+ /// them.
+ ///
+ /// Refer to `EditMember`s documentation for a full list of methods.
///
/// # Examples
///
- /// Mute a member and set their roles to just one role with
- /// the predefined Id.
+ /// Mute a member and set their roles to just one role with a predefined Id:
///
/// ```rust,ignore
/// context.edit_member(guild_id, user_id, |m| m
@@ -913,7 +910,7 @@ impl Context {
rest::edit_note(user_id.into().0, map)
}
- /// Gets a vector of bans server has.
+ /// Gets a vector of bans guild has.
pub fn get_bans<G: Into<GuildId>>(&self, guild_id: G) -> Result<Vec<Ban>> {
rest::get_bans(guild_id.into().0)
}
@@ -960,13 +957,13 @@ impl Context {
Ok(channels)
}
- /// Gets [`Emoji`] by the given Id from a server.
+ /// Gets an `Emoji` by the given Id from a guild.
pub fn get_emoji<E, G>(&self, guild_id: G, emoji_id: E) -> Result<Emoji>
where E: Into<EmojiId>, G: Into<GuildId> {
rest::get_emoji(guild_id.into().0, emoji_id.into().0)
}
- /// Gets a vector of all [`Emojis`] a server has.
+ /// Gets a vector of all `Emoji` a guild has.
pub fn get_emojis<G: Into<GuildId>>(&self, guild_id: G)
-> Result<Vec<Emoji>> {
rest::get_emojis(guild_id.into().0)
@@ -1013,7 +1010,7 @@ impl Context {
rest::get_invite(code)
}
- /// Gets `Member` of a specific server by Id, checking cache first.
+ /// Gets `Member` of a specific guild by Id, checking cache first.
pub fn get_member<G, U>(&self, guild_id: G, user_id: U) -> Result<Member>
where G: Into<GuildId>, U: Into<UserId> {
let guild_id = guild_id.into();
@@ -1490,7 +1487,7 @@ impl Context {
.set_presence(game, status, afk)
}
- /// Deletes an undefined amount of members from the given server
+ /// Deletes an undefined amount of members from the given guild
/// based on the amount of days they've been offline for.
///
/// **Note**: This will trigger [`GuildMemberRemove`] events
diff --git a/src/client/error.rs b/src/client/error.rs
index 76e0d2c..0ed3bd8 100644
--- a/src/client/error.rs
+++ b/src/client/error.rs
@@ -21,10 +21,7 @@ use ::model::{ChannelType, Permissions};
/// let mut client = Client::login_bot(&token);
///
/// client.on_member_unban(|context, guild_id, user| {
-/// let discriminator = match user.discriminator.parse::<u16>() {
-/// Ok(discriminator) => discriminator,
-/// Err(_why) => return,
-/// };
+/// let discriminator = user.discriminator.parse::<u16>().unwrap();
///
/// // If the user has an even discriminator, don't re-ban them.
/// if discriminator % 2 == 0 {
diff --git a/src/client/gateway/prep.rs b/src/client/gateway/prep.rs
index e3b8656..2ca435b 100644
--- a/src/client/gateway/prep.rs
+++ b/src/client/gateway/prep.rs
@@ -117,7 +117,7 @@ pub fn keepalive(interval: u64,
},
Ok(GatewayStatus::SendMessage(val)) => {
if let Err(why) = sender.send_json(&val) {
- warn!("Err sending message: {:?}", why);
+ warn!("Error sending message: {:?}", why);
}
},
Ok(GatewayStatus::Sequence(seq)) => {
@@ -137,7 +137,7 @@ pub fn keepalive(interval: u64,
.build();
if let Err(why) = sender.send_json(&map) {
- warn!("Err sending keepalive: {:?}", why);
+ warn!("Error sending keepalive: {:?}", why);
}
}
}
diff --git a/src/client/gateway/shard.rs b/src/client/gateway/shard.rs
index ab2e561..e64d6fe 100644
--- a/src/client/gateway/shard.rs
+++ b/src/client/gateway/shard.rs
@@ -315,7 +315,7 @@ impl Shard {
if let Some(session_id) = self.session_id.clone() {
match self.resume(session_id, receiver) {
Ok((ev, rec)) => return Ok(Some((ev, Some(rec)))),
- Err(why) => debug!("Err resuming: {:?}", why),
+ Err(why) => debug!("Error resuming: {:?}", why),
}
}
}
@@ -335,7 +335,7 @@ impl Shard {
if let Some(session_id) = self.session_id.clone() {
match self.resume(session_id, &mut receiver) {
Ok((ev, rec)) => return Ok(Some((ev, Some(rec)))),
- Err(why) => debug!("Err resuming: {:?}", why),
+ Err(why) => debug!("Error resuming: {:?}", why),
}
}
diff --git a/src/client/rest/mod.rs b/src/client/rest/mod.rs
index b6218cd..4c2199a 100644
--- a/src/client/rest/mod.rs
+++ b/src/client/rest/mod.rs
@@ -392,7 +392,7 @@ pub fn create_role(guild_id: u64) -> Result<Role> {
/// let channel_id = 81384788765712384;
/// let map = ObjectBuilder::new().insert("name", "test").build();
///
-/// let webhook = rest::create_webhook(channel_id, map).expect("err creating");
+/// let webhook = rest::create_webhook(channel_id, map).expect("Error creating");
/// ```
///
/// [`GuildChannel`]: ../../model/struct.GuildChannel.html
@@ -484,10 +484,8 @@ pub fn delete_messages(channel_id: u64, map: Value) -> Result<()> {
/// let channel_id = ChannelId(7);
/// let message_id = MessageId(8);
///
-/// match rest::delete_message_reactions(channel_id.0, message_id.0) {
-/// Ok(()) => println!("Reactions deleted"),
-/// Err(why) => println!("Error deleting reactions: {:?}", why),
-/// }
+/// let _ = rest::delete_message_reactions(channel_id.0, message_id.0)
+/// .expect("Error deleting reactions");
/// ```
///
/// [`Message`]: ../../model/struct.Message.html
@@ -555,7 +553,7 @@ pub fn delete_role(guild_id: u64, role_id: u64) -> Result<()> {
/// // must have initialized a client first.
/// let client = Client::login_user(&env::var("DISCORD_TOKEN").unwrap());
///
-/// rest::delete_webhook(245037420704169985).expect("err deleting webhook");
+/// rest::delete_webhook(245037420704169985).expect("Error deleting webhook");
/// ```
///
/// [`Webhook`]: ../../model/struct.Webhook.html
@@ -578,7 +576,7 @@ pub fn delete_webhook(webhook_id: u64) -> Result<()> {
/// let id = 245037420704169985;
/// let token = "ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV";
///
-/// rest::delete_webhook_with_token(id, token).expect("err deleting webhook");
+/// rest::delete_webhook_with_token(id, token).expect("Error deleting webhook");
///
/// [`Webhook`]: ../../model/struct.Webhook.html
pub fn delete_webhook_with_token(webhook_id: u64, token: &str) -> Result<()> {
@@ -727,11 +725,11 @@ pub fn edit_role(guild_id: u64, role_id: u64, map: Value)
/// let id = 245037420704169985;
/// let token = "ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV";
/// let image = serenity::utils::read_image("./webhook_img.png")
-/// .expect("err reading image");
+/// .expect("Error reading image");
/// let map = ObjectBuilder::new().insert("avatar", image).build();
///
/// let edited = rest::edit_webhook_with_token(id, token, map)
-/// .expect("err editing webhook");
+/// .expect("Error editing webhook");
/// ```
///
/// [`create_webhook`]: fn.create_webhook.html
@@ -770,7 +768,7 @@ pub fn edit_webhook(webhook_id: u64, map: Value) -> Result<Webhook> {
/// let map = ObjectBuilder::new().insert("name", "new name").build();
///
/// let edited = rest::edit_webhook_with_token(id, token, map)
-/// .expect("err editing webhook");
+/// .expect("Error editing webhook");
/// ```
///
/// [`edit_webhook`]: fn.edit_webhook.html
@@ -910,7 +908,7 @@ pub fn get_channel_invites(channel_id: u64)
/// let channel_id = 81384788765712384;
///
/// let webhooks = rest::get_channel_webhooks(channel_id)
-/// .expect("err getting channel webhooks");
+/// .expect("Error getting channel webhooks");
/// ```
///
/// [`GuildChannel`]: ../../model/struct.GuildChannel.html
@@ -1056,7 +1054,7 @@ pub fn get_guild_regions(guild_id: u64) -> Result<Vec<VoiceRegion>> {
/// let guild_id = 81384788765712384;
///
/// let webhooks = rest::get_guild_webhooks(guild_id)
-/// .expect("err getting guild webhooks");
+/// .expect("Error getting guild webhooks");
/// ```
///
/// [`Guild`]: ../../model/struct.Guild.html
@@ -1203,7 +1201,7 @@ pub fn get_voice_regions() -> Result<Vec<VoiceRegion>> {
/// use serenity::client::rest;
///
/// let id = 245037420704169985;
-/// let webhook = rest::get_webhook(id).expect("err getting webhook");
+/// let webhook = rest::get_webhook(id).expect("Error getting webhook");
/// ```
///
/// [`get_webhook_with_token`]: fn.get_webhook_with_token.html
@@ -1228,7 +1226,7 @@ pub fn get_webhook(webhook_id: u64) -> Result<Webhook> {
/// let token = "ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV";
///
/// let webhook = rest::get_webhook_with_token(id, token)
-/// .expect("err getting webhook");
+/// .expect("Error getting webhook");
/// ```
pub fn get_webhook_with_token(webhook_id: u64, token: &str) -> Result<Webhook> {
let client = HyperClient::new();
diff --git a/src/ext/cache/mod.rs b/src/ext/cache/mod.rs
index d07f7a6..0981cf3 100644
--- a/src/ext/cache/mod.rs
+++ b/src/ext/cache/mod.rs
@@ -325,7 +325,7 @@ impl Cache {
/// Some(channel) => channel,
/// None => {
/// context.say("Could not find guild's channel data")
- /// .map_err(|why| println!("Err sending message: {:?}", why));
+ /// .map_err(|why| println!("Error sending message: {:?}", why));
///
/// return;
/// },
@@ -373,8 +373,8 @@ impl Cache {
/// let channel = match cache.get_guild_channel(message.channel_id) {
/// Some(channel) => channel,
/// None => {
- /// if let Err(why) = context.say("Err finding channel data") {
- /// println!("Err sending message: {:?}", why);
+ /// if let Err(why) = context.say("Error finding channel data") {
+ /// println!("Error sending message: {:?}", why);
/// }
/// },
/// };
@@ -382,8 +382,8 @@ impl Cache {
/// match cache.get_member(channel.guild_id, message.author.id) {
/// Some(member) => member,
/// None => {
- /// if let Err(why) = context.say("Err finding member data") {
- /// println!("Err sending message: {:?}", why);
+ /// if let Err(why) = context.say("Error finding member data") {
+ /// println!("Error sending message: {:?}", why);
/// }
/// },
/// }
@@ -392,7 +392,7 @@ impl Cache {
/// let msg = format!("You have {} roles", member.roles.len());
///
/// if let Err(why) = context.say(&msg) {
- /// println!("Err sending message: {:?}", why);
+ /// println!("Error sending message: {:?}", why);
/// }
/// ```
///
diff --git a/src/ext/voice/threading.rs b/src/ext/voice/threading.rs
index 4110c5f..113c23d 100644
--- a/src/ext/voice/threading.rs
+++ b/src/ext/voice/threading.rs
@@ -13,7 +13,7 @@ pub fn start(target_id: Target, rx: MpscReceiver<Status>) {
ThreadBuilder::new()
.name(name)
.spawn(move || runner(rx))
- .expect("Err starting voice");
+ .expect("Error starting voice");
}
fn runner(rx: MpscReceiver<Status>) {
@@ -29,7 +29,7 @@ fn runner(rx: MpscReceiver<Status>) {
connection = match Connection::new(info) {
Ok(connection) => Some(connection),
Err(why) => {
- error!("Err connecting via voice: {:?}", why);
+ error!("Error connecting via voice: {:?}", why);
None
},
@@ -71,7 +71,7 @@ fn runner(rx: MpscReceiver<Status>) {
match update {
Ok(()) => false,
Err(why) => {
- error!("Err updating voice connection: {:?}", why);
+ error!("Error updating voice connection: {:?}", why);
true
},
diff --git a/src/model/channel.rs b/src/model/channel.rs
index 9a3f9ea..a95b1f3 100644
--- a/src/model/channel.rs
+++ b/src/model/channel.rs
@@ -139,7 +139,7 @@ impl Attachment {
///
/// // Make sure that the directory to store images in exists.
/// fs::create_dir_all("./attachment_downloads")
- /// .expect("err making directory");
+ /// .expect("Error making directory");
///
/// let token = env::var("DISCORD_TOKEN").expect("token in environment");
/// let mut client = Client::login_bot(&token);
@@ -820,6 +820,16 @@ impl GuildChannel {
rest::broadcast_typing(self.id.0)
}
+ /// Creates an invite leading to the given channel.
+ ///
+ /// # Examples
+ ///
+ /// Create an invite that can only be used 5 times:
+ ///
+ /// ```rust,ignore
+ /// let invite = channel.create_invite(|i| i
+ /// .max_uses(5));
+ /// ```
#[cfg(feature = "methods")]
pub fn create_invite<F>(&self, f: F) -> Result<RichInvite>
where F: FnOnce(CreateInvite) -> CreateInvite {
@@ -875,6 +885,19 @@ impl GuildChannel {
rest::delete_channel(self.id.0)
}
+ /// Modifies a channel's settings, such as its position or name.
+ ///
+ /// Refer to `EditChannel`s documentation for a full list of methods.
+ ///
+ /// # Examples
+ ///
+ /// Change a voice channels name and bitrate:
+ ///
+ /// ```rust,ignore
+ /// channel.edit(|c| c
+ /// .name("test")
+ /// .bitrate(71));
+ /// ```
#[cfg(feature = "methods")]
pub fn edit<F>(&mut self, f: F) -> Result<()>
where F: FnOnce(EditChannel) -> EditChannel {
@@ -919,6 +942,7 @@ impl GuildChannel {
self.id.mention()
}
+ /// Gets all channel's pins.
#[cfg(feature = "methods")]
pub fn pins(&self) -> Result<Vec<Message>> {
rest::get_pins(self.id.0)
diff --git a/src/model/gateway.rs b/src/model/gateway.rs
index 101f050..30ed695 100644
--- a/src/model/gateway.rs
+++ b/src/model/gateway.rs
@@ -3,6 +3,7 @@ use super::*;
use ::internal::prelude::*;
impl Game {
+ /// Creates a `Game` struct that appears as a `**Playing** <name>` status.
#[cfg(feature="methods")]
pub fn playing(name: &str) -> Game {
Game {
@@ -12,6 +13,7 @@ impl Game {
}
}
+ /// Creates a `Game` struct that appears as a `**Streaming** <name>` status.
#[cfg(feature="methods")]
pub fn streaming(name: &str, url: &str) -> Game {
Game {
diff --git a/src/model/id.rs b/src/model/id.rs
index cba72ae..5f534ec 100644
--- a/src/model/id.rs
+++ b/src/model/id.rs
@@ -50,6 +50,7 @@ impl ChannelId {
}
impl From<Channel> for ChannelId {
+ /// Gets the Id of a `Channel`.
fn from(channel: Channel) -> ChannelId {
match channel {
Channel::Group(group) => group.channel_id,
@@ -60,18 +61,21 @@ impl From<Channel> for ChannelId {
}
impl From<PrivateChannel> for ChannelId {
+ /// Gets the Id of a private channel.
fn from(private_channel: PrivateChannel) -> ChannelId {
private_channel.id
}
}
impl From<GuildChannel> for ChannelId {
+ /// Gets the Id of a guild channel.
fn from(public_channel: GuildChannel) -> ChannelId {
public_channel.id
}
}
impl From<Emoji> for EmojiId {
+ /// Gets the Id of an `Emoji`.
fn from(emoji: Emoji) -> EmojiId {
emoji.id
}
@@ -122,42 +126,49 @@ impl GuildId {
}
impl From<PartialGuild> for GuildId {
+ /// Gets the Id of a partial guild.
fn from(guild: PartialGuild) -> GuildId {
guild.id
}
}
impl From<GuildInfo> for GuildId {
+ /// Gets the Id of Guild information struct.
fn from(guild_info: GuildInfo) -> GuildId {
guild_info.id
}
}
impl From<InviteGuild> for GuildId {
+ /// Gets the Id of Invite Guild struct.
fn from(invite_guild: InviteGuild) -> GuildId {
invite_guild.id
}
}
impl From<Guild> for GuildId {
+ /// Gets the Id of Guild.
fn from(live_guild: Guild) -> GuildId {
live_guild.id
}
}
impl From<Integration> for IntegrationId {
+ /// Gets the Id of integration.
fn from(integration: Integration) -> IntegrationId {
integration.id
}
}
impl From<Message> for MessageId {
+ /// Gets the Id of a `Message`.
fn from(message: Message) -> MessageId {
message.id
}
}
impl From<Role> for RoleId {
+ /// Gets the Id of a `Role`.
fn from(role: Role) -> RoleId {
role.id
}
@@ -192,18 +203,21 @@ impl RoleId {
}
impl From<CurrentUser> for UserId {
+ /// Gets the Id of a `CurrentUser` struct.
fn from(current_user: CurrentUser) -> UserId {
current_user.id
}
}
impl From<Member> for UserId {
+ /// Gets the Id of a `Member`.
fn from(member: Member) -> UserId {
member.user.id
}
}
impl From<User> for UserId {
+ /// Gets the Id of a `User`.
fn from(user: User) -> UserId {
user.id
}
diff --git a/src/model/webhook.rs b/src/model/webhook.rs
index 4553f30..9d3a393 100644
--- a/src/model/webhook.rs
+++ b/src/model/webhook.rs
@@ -41,7 +41,7 @@ impl Webhook {
/// let mut webhook = rest::get_webhook_with_token(id, token)
/// .expect("valid webhook");
///
- /// let _ = webhook.edit(Some("new name"), None).expect("err editing");
+ /// let _ = webhook.edit(Some("new name"), None).expect("Error editing");
/// ```
///
/// Setting a webhook's avatar:
@@ -56,9 +56,9 @@ impl Webhook {
/// .expect("valid webhook");
///
/// let image = serenity::utils::read_image("./webhook_img.png")
- /// .expect("err reading image");
+ /// .expect("Error reading image");
///
- /// let _ = webhook.edit(None, Some(&image)).expect("err editing");
+ /// let _ = webhook.edit(None, Some(&image)).expect("Error editing");
/// ```
///
/// [`rest::edit_webhook`]: ../client/rest/fn.edit_webhook.html
@@ -114,7 +114,7 @@ impl Webhook {
/// let mut webhook = rest::get_webhook_with_token(id, token)
/// .expect("valid webhook");
///
- /// let _ = webhook.execute(|w| w.content("test")).expect("err executing");
+ /// let _ = webhook.execute(|w| w.content("test")).expect("Error executing");
/// ```
///
/// Execute a webhook with message content of `test`, overriding the
@@ -141,7 +141,7 @@ impl Webhook {
/// .content("test")
/// .username("serenity")
/// .embeds(vec![embed]))
- /// .expect("err executing");
+ /// .expect("Error executing");
/// ```
#[cfg(feature="methods")]
pub fn execute<F>(&self, f: F) -> Result<Message>
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