Skip to content

Commit

Permalink
port 3db66ab: embed message building trait (#601)
Browse files Browse the repository at this point in the history
Add `EmbedMessageBuilding` trait as extension to `MessageBuilder` (#599)

Add a trait to the `utils` module, `EmbedMessageBuilding`, which adds
additional functionality for embed-only content. The trait is
implemented on the `MessageBuilder`. This is a separate trait so that
users knowingly opt-in to embed-only functionality when they import it
to avoid confusion when calls to embed-only methods don't work outside
of embeds.

This currently contains two methods, the non-escaping `push_named_link`
and its escaping version `push_named_link_safe`. These are both for
making a named link with standard Markdown, like
`[Rust](https://rust-lang.org)`.

An example of using this is:

```rust
use serenity::utils::{EmbedMessageBuilding, MessageBuilder};

let msg = MessageBuilder::new()
    .push_named_link("Rust's GitHub", "https://github.com/rust-lang")
    .build();

assert_eq!(msg, "[Rust's GitHub](https://github.com/rust-lang)");
```

(cherry picked from commit 3db66ab)
  • Loading branch information
zeylahellyer authored and arqunis committed Jun 8, 2019
1 parent 4541935 commit 7c61f95
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 1 deletion.
113 changes: 113 additions & 0 deletions src/utils/message_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,119 @@ impl Display for MessageBuilder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
}

/// A trait with additional functionality over the [`MessageBuilder`] for
/// creating content with additional functionality available only in embeds.
///
/// Namely, this allows you to create named links via the non-escaping
/// [`push_named_link`] method and the escaping [`push_named_link_safe`] method.
///
/// # Examples
///
/// Make a named link to Rust's GitHub organization:
///
/// ```rust
/// # #[cfg(feature = "utils")]
/// # fn main() {
/// #
/// use serenity::utils::{EmbedMessageBuilding, MessageBuilder};
///
/// let msg = MessageBuilder::new()
/// .push_named_link("Rust's GitHub", "https://github.com/rust-lang")
/// .build();
///
/// assert_eq!(msg, "[Rust's GitHub](https://github.com/rust-lang)");
/// # }
/// #
/// # #[cfg(not(feature = "utils"))]
/// # fn main() { }
/// ```
///
/// [`MessageBuilder`]: struct.MessageBuilder.html
/// [`push_named_link`]: #tymethod.push_named_link
/// [`push_named_link_safe`]: #tymethod.push_named_link_safe
pub trait EmbedMessageBuilding {
/// Pushes a named link to a message, intended for use in embeds.
///
/// # Examples
///
/// Make a simple link to Rust's homepage for use in an embed:
///
/// ```rust
/// # #[cfg(feature = "utils")]
/// # fn main() {
/// #
/// use serenity::utils::{EmbedMessageBuilding, MessageBuilder};
///
/// let mut msg = MessageBuilder::new();
/// msg.push("Rust's website: ");
/// msg.push_named_link("Homepage", "https://rust-lang.org");
/// let content = msg.build();
///
/// assert_eq!(content, "Rust's website: [Homepage](https://rust-lang.org)");
/// # }
/// #
/// # #[cfg(not(feature = "utils"))]
/// # fn main() { }
/// ```
fn push_named_link<T: I, U: I>(&mut self, name: T, url: U) -> &mut Self;

/// Pushes a named link intended for use in an embed, but with a normalized
/// name to avoid escaping issues.
///
/// Refer to [`push_named_link`] for more information.
///
/// # Examples
///
/// ```rust
/// # #[cfg(feature = "utils")]
/// # fn main() {
/// #
/// use serenity::utils::{EmbedMessageBuilding, MessageBuilder};
///
/// let mut msg = MessageBuilder::new();
/// msg.push("A weird website name: ");
/// msg.push_named_link_safe("Try to ] break links (](", "https://rust-lang.org");
/// let content = msg.build();
///
/// assert_eq!(content, "A weird website name: [Try to break links ( (](https://rust-lang.org)");
/// # }
/// #
/// # #[cfg(not(feature = "utils"))]
/// # fn main() { }
/// ```
///
/// [`push_named_link`]: #tymethod.push_named_link
fn push_named_link_safe<T: I, U: I>(&mut self, name: T, url: U) -> &mut Self;
}

impl EmbedMessageBuilding for MessageBuilder {
fn push_named_link<T: I, U: I>(&mut self, name: T, url: U) -> &mut Self {
let name = name.into().to_string();
let url = url.into().to_string();

let _ = write!(self.0, "[{}]({})", name, url);

self
}

fn push_named_link_safe<T: I, U: I>(&mut self, name: T, url: U) -> &mut Self {
self.0.push_str("[");
{
let mut c = name.into();
c.inner = normalize(&c.inner).replace("]", " ");
self.0.push_str(&c.to_string());
}
self.0.push_str("](");
{
let mut c = url.into();
c.inner = normalize(&c.inner).replace(")", " ");
self.0.push_str(&c.to_string());
}
self.0.push_str(")");

self
}
}

/// Formatting modifiers for MessageBuilder content pushes
///
Expand Down
7 changes: 6 additions & 1 deletion src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ mod message_builder;

pub use self::{
colour::Colour,
message_builder::{Content, ContentModifier, MessageBuilder},
message_builder::{
Content,
ContentModifier,
EmbedMessageBuilding,
MessageBuilder,
},
};

use base64;
Expand Down

0 comments on commit 7c61f95

Please sign in to comment.