Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a builder for CallbackData #1146

Merged
merged 13 commits into from
Oct 2, 2021
202 changes: 202 additions & 0 deletions util/src/builder/callback_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
use twilight_model::{
application::{callback::CallbackData, component::Component},
channel::{
embed::Embed,
message::{AllowedMentions, MessageFlags},
},
};

/// Create a [`CallbackData`] with a builder.
///
/// # Example
/// ```
/// use twilight_util::builder::CallbackDataBuilder;
/// use twilight_model::{
/// channel::message::MessageFlags,
/// application::component::{button::ButtonStyle, Component, Button}
/// };
///
/// let component = Component::Button(Button {
/// style: ButtonStyle::Primary,
/// emoji: None,
/// label: Some("Button label".to_string()),
/// custom_id: Some("button_id".to_string()),
/// url: None,
/// disabled: false,
/// });
///
/// let callback_data = CallbackDataBuilder::new()
/// .content("Callback message".to_string())
/// .flags(MessageFlags::EPHEMERAL)
/// .components([component.clone()])
/// .build();
///
/// assert_eq!(callback_data.components, Some(vec![component]));
/// ```
#[derive(Clone, Debug)]
#[must_use = "builders have no effect if unused"]
pub struct CallbackDataBuilder(CallbackData);

impl CallbackDataBuilder {
/// Set the [`AllowedMentions`] of the callback.
baptiste0928 marked this conversation as resolved.
Show resolved Hide resolved
///
/// Defaults to [`None`].
#[allow(clippy::missing_const_for_fn)]
7596ff marked this conversation as resolved.
Show resolved Hide resolved
pub fn allowed_mentions(mut self, allowed_mentions: AllowedMentions) -> Self {
self.0.allowed_mentions = Some(allowed_mentions);

self
}

/// Consume the builder, returning a [`CallbackData`].
#[allow(clippy::missing_const_for_fn)]
#[must_use = "builders have no effect if unused"]
pub fn build(self) -> CallbackData {
self.0
}

/// Set the message [`Component`]s of the callback.
baptiste0928 marked this conversation as resolved.
Show resolved Hide resolved
///
/// Defaults to [`None`].
pub fn components(mut self, components: impl IntoIterator<Item = Component>) -> Self {
self.0.components = Some(components.into_iter().collect());

self
}

/// Set the message content of the callback.
baptiste0928 marked this conversation as resolved.
Show resolved Hide resolved
///
/// Defaults to [`None`].
#[allow(clippy::missing_const_for_fn)]
pub fn content(mut self, content: String) -> Self {
self.0.content = Some(content);

self
}

/// Set the [`Embed`]s of the callback.
baptiste0928 marked this conversation as resolved.
Show resolved Hide resolved
///
/// Defaults to an empty list.
pub fn embeds(mut self, embeds: impl IntoIterator<Item = Embed>) -> Self {
self.0.embeds = embeds.into_iter().collect();

self
}

/// Set the [`MessageFlags`].
///
/// The only supported flag is [`EPHEMERAL`].
///
/// Defaults to [`None`].
///
/// [`EPHEMERAL`]: twilight_model::channel::message::MessageFlags::EPHEMERAL
pub const fn flags(mut self, flags: MessageFlags) -> Self {
self.0.flags = Some(flags);

self
}

/// Create a new builder to construct a [`CallbackData`].
pub const fn new() -> Self {
Self(CallbackData {
allowed_mentions: None,
components: None,
content: None,
embeds: Vec::new(),
flags: None,
tts: None,
})
}

/// Set whether the response has text-to-speech enabled.
baptiste0928 marked this conversation as resolved.
Show resolved Hide resolved
///
/// Defaults to [`None`].
pub const fn tts(mut self, value: bool) -> Self {
self.0.tts = Some(value);

self
}
}

impl Default for CallbackDataBuilder {
fn default() -> Self {
Self(CallbackData {
allowed_mentions: None,
components: None,
content: None,
embeds: Vec::new(),
flags: None,
tts: None,
})
}
}

#[cfg(test)]
mod tests {
use super::CallbackDataBuilder;

use static_assertions::assert_impl_all;
use std::fmt::Debug;
use twilight_model::{
application::{
callback::CallbackData,
component::{button::ButtonStyle, Button, Component},
},
channel::{
embed::Embed,
message::{AllowedMentions, MessageFlags},
},
};

assert_impl_all!(CallbackDataBuilder: Debug, Default, Send, Sync);
baptiste0928 marked this conversation as resolved.
Show resolved Hide resolved

#[test]
fn callback_data_builder() {
let allowed_mentions = AllowedMentions::builder().everyone().build();

let component = Component::Button(Button {
style: ButtonStyle::Primary,
emoji: None,
label: Some("test label".into()),
custom_id: Some("test custom id".into()),
url: None,
disabled: false,
});

let embed = Embed {
author: None,
color: Some(123),
description: Some("a description".to_owned()),
fields: Vec::new(),
footer: None,
image: None,
kind: "rich".to_owned(),
provider: None,
thumbnail: None,
timestamp: Some("a timestamp".to_owned()),
title: Some("a title".to_owned()),
url: Some("https://example.com".to_owned()),
video: None,
};

let value = CallbackDataBuilder::new()
.allowed_mentions(allowed_mentions.clone())
.components([component.clone()])
.content("a content".into())
.embeds([embed.clone()])
.flags(MessageFlags::empty())
.tts(false)
.build();

let expected = CallbackData {
allowed_mentions: Some(allowed_mentions),
components: Some(vec![component]),
content: Some("a content".to_owned()),
embeds: vec![embed],
flags: Some(MessageFlags::empty()),
tts: Some(false),
};

assert_eq!(value, expected);
}
}
4 changes: 4 additions & 0 deletions util/src/builder/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! Builders for large structs.
#![allow(clippy::module_name_repetitions)]

mod callback_data;
pub mod command;

pub use self::callback_data::CallbackDataBuilder;
2 changes: 1 addition & 1 deletion util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]

#[cfg(feature = "builder")]
#[cfg_attr(docrs, doc(cfg(feature = "builder")))]
#[cfg_attr(docsrs, doc(cfg(feature = "builder")))]
7596ff marked this conversation as resolved.
Show resolved Hide resolved
pub mod builder;

#[cfg(feature = "link")]
Expand Down