#[derive(Debug, Clone)]
pub struct Button {
pub(crate) label: String,
pub(crate) kind: ButtonKind,
}
#[derive(Debug, Clone)]
pub(crate) enum ButtonKind {
Callback(String),
Url(String),
}
impl Button {
pub fn callback(label: impl Into<String>, id: impl Into<String>) -> Self {
Self {
label: label.into(),
kind: ButtonKind::Callback(id.into()),
}
}
pub fn url(label: impl Into<String>, url: impl Into<String>) -> Self {
Self {
label: label.into(),
kind: ButtonKind::Url(url.into()),
}
}
pub fn label(&self) -> &str {
&self.label
}
pub fn callback_id(&self) -> Option<&str> {
match &self.kind {
ButtonKind::Callback(id) => Some(id.as_str()),
_ => None,
}
}
pub fn url_target(&self) -> Option<&str> {
match &self.kind {
ButtonKind::Url(u) => Some(u.as_str()),
_ => None,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct Keyboard {
pub(crate) rows: Vec<Vec<Button>>,
}
impl Keyboard {
pub fn new() -> Self {
Self { rows: Vec::new() }
}
pub fn row(mut self, buttons: impl IntoIterator<Item = Button>) -> Self {
self.rows.push(buttons.into_iter().collect());
self
}
pub fn rows(&self) -> &[Vec<Button>] {
&self.rows
}
pub fn len(&self) -> usize {
self.rows.iter().map(|r| r.len()).sum()
}
pub fn is_empty(&self) -> bool {
self.rows.iter().all(|r| r.is_empty())
}
}
#[derive(Debug, Clone)]
pub struct EmbedField {
pub(crate) name: String,
pub(crate) value: String,
pub(crate) inline: bool,
}
impl EmbedField {
pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
Self {
name: name.into(),
value: value.into(),
inline: false,
}
}
pub fn inline(mut self, yes: bool) -> Self {
self.inline = yes;
self
}
pub fn name(&self) -> &str {
&self.name
}
pub fn value(&self) -> &str {
&self.value
}
pub fn is_inline(&self) -> bool {
self.inline
}
}
#[derive(Debug, Clone, Default)]
pub struct Embed {
pub(crate) title: Option<String>,
pub(crate) description: Option<String>,
pub(crate) fields: Vec<EmbedField>,
pub(crate) footer: Option<String>,
pub(crate) color: Option<u32>,
pub(crate) url: Option<String>,
pub(crate) image_url: Option<String>,
pub(crate) thumbnail_url: Option<String>,
}
impl Embed {
pub fn new() -> Self {
Self::default()
}
pub fn title(mut self, t: impl Into<String>) -> Self {
self.title = Some(t.into());
self
}
pub fn description(mut self, d: impl Into<String>) -> Self {
self.description = Some(d.into());
self
}
pub fn field(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
self.fields.push(EmbedField::new(name, value));
self
}
pub fn field_inline(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
self.fields.push(EmbedField::new(name, value).inline(true));
self
}
pub fn push_field(mut self, field: EmbedField) -> Self {
self.fields.push(field);
self
}
pub fn footer(mut self, f: impl Into<String>) -> Self {
self.footer = Some(f.into());
self
}
pub fn color(mut self, rgb: u32) -> Self {
self.color = Some(rgb & 0x00FF_FFFF);
self
}
pub fn url(mut self, u: impl Into<String>) -> Self {
self.url = Some(u.into());
self
}
pub fn image(mut self, url: impl Into<String>) -> Self {
self.image_url = Some(url.into());
self
}
pub fn thumbnail(mut self, url: impl Into<String>) -> Self {
self.thumbnail_url = Some(url.into());
self
}
pub fn get_title(&self) -> Option<&str> {
self.title.as_deref()
}
pub fn get_description(&self) -> Option<&str> {
self.description.as_deref()
}
pub fn get_fields(&self) -> &[EmbedField] {
&self.fields
}
pub fn get_footer(&self) -> Option<&str> {
self.footer.as_deref()
}
pub fn get_color(&self) -> Option<u32> {
self.color
}
pub fn get_url(&self) -> Option<&str> {
self.url.as_deref()
}
pub fn get_image(&self) -> Option<&str> {
self.image_url.as_deref()
}
pub fn get_thumbnail(&self) -> Option<&str> {
self.thumbnail_url.as_deref()
}
pub fn is_empty(&self) -> bool {
self.title.is_none()
&& self.description.is_none()
&& self.fields.is_empty()
&& self.footer.is_none()
}
}
#[derive(Debug, Clone, Default)]
pub struct Reply {
pub(crate) text: String,
pub(crate) embed: Option<Embed>,
pub(crate) keyboard: Option<Keyboard>,
}
impl Reply {
pub fn text(text: impl Into<String>) -> Self {
Self {
text: text.into(),
embed: None,
keyboard: None,
}
}
pub fn embed(embed: Embed) -> Self {
Self {
text: String::new(),
embed: Some(embed),
keyboard: None,
}
}
pub fn with_embed(mut self, embed: Embed) -> Self {
self.embed = Some(embed);
self
}
pub fn keyboard(mut self, kb: Keyboard) -> Self {
self.keyboard = Some(kb);
self
}
pub fn with_text(mut self, text: impl Into<String>) -> Self {
self.text = text.into();
self
}
pub fn get_text(&self) -> &str {
&self.text
}
pub fn get_embed(&self) -> Option<&Embed> {
self.embed.as_ref()
}
pub fn get_keyboard(&self) -> Option<&Keyboard> {
self.keyboard.as_ref()
}
}
impl From<&str> for Reply {
fn from(s: &str) -> Self {
Self::text(s)
}
}
impl From<String> for Reply {
fn from(s: String) -> Self {
Self::text(s)
}
}
impl From<Embed> for Reply {
fn from(e: Embed) -> Self {
Self::embed(e)
}
}