Skip to content

Commit

Permalink
Add builders for creating interactions (#1186)
Browse files Browse the repository at this point in the history
  • Loading branch information
Th3-M4jor authored and arqunis committed Jan 17, 2021
1 parent 0e2b648 commit 0d743fd
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 1 deletion.
176 changes: 176 additions & 0 deletions src/builder/create_interaction.rs
@@ -0,0 +1,176 @@
use std::collections::HashMap;
use serde_json::{Value, json};

use crate::{
model::interactions::ApplicationCommandOptionType,
utils,
};

/// A builder for creating a new [`ApplicationCommandInteractionDataOption`].
///
/// [`kind`], [`name`], and [`description`] are required fields.
///
/// [`ApplicationCommandInteractionDataOption`]: crate::model::interactions::ApplicationCommandInteractionDataOption
/// [`kind`]: Self::kind
/// [`name`]: Self::name
/// [`description`]: Self::description
#[derive(Clone, Debug, Default)]
pub struct CreateInteractionOption(pub HashMap<&'static str, Value>);

impl CreateInteractionOption {

/// Set the ApplicationCommandOptionType for the InteractionOption.
pub fn kind(&mut self, kind: ApplicationCommandOptionType) -> &mut Self {
self.0.insert("type", Value::Number(serde_json::Number::from(kind as u8)));
self
}

/// Sets the name of the option.
///
/// **Note**: The option name must be between 1 and 32 characters.
pub fn name<D: ToString>(&mut self, name: D) -> &mut Self {
self.0.insert("name", Value::String(name.to_string()));
self
}

/// Sets the description for the option.
///
/// **Note**: The description must be between 1 and 100 characters.
pub fn description<D: ToString>(&mut self, description: D) -> &mut Self {
self.0.insert("description", Value::String(description.to_string()));
self
}

/// The first required option for the user to complete
///
/// **Note**: Only one option can be `default`.
pub fn default_option(&mut self, default: bool) -> &mut Self {
self.0.insert("default", Value::Bool(default));
self
}

/// Sets if this option is required or optional.
///
/// **Note**: This defaults to `false`.
pub fn required(&mut self, required: bool) -> &mut Self {
self.0.insert("required", Value::Bool(required));
self
}

/// Interaction commands can optionally have a limited
/// number of integer or string choices.
///
/// **Note**: There can be no more than 10 choices set.
pub fn add_int_choice<D: ToString>(&mut self, name: D, value: i32) -> &mut Self {
let choice = json!({
"name": name.to_string(),
"value" : value
});
self.add_choice(choice)
}

pub fn add_string_choice<D: ToString, E: ToString>(&mut self, name: D, value: E) -> &mut Self {
let choice = json!({
"name": name.to_string(),
"value": value.to_string()
});
self.add_choice(choice)
}

fn add_choice(&mut self, value: Value) -> &mut Self {
let choices = self.0.entry("options").or_insert_with(|| Value::Array(Vec::new()));
if let Some(choices_arr) = choices.as_array_mut() {
choices_arr.push(value);
};
self
}

/// If the option is a [`SubCommand`] or [`SubCommandGroup`] nested options are its parameters.
///
/// [`SubCommand`]: crate::model::interactions::ApplicationCommandOptionType::SubCommand
/// [`SubCommandGroup`]: crate::model::interactions::ApplicationCommandOptionType::SubCommandGroup
pub fn create_sub_option<F>(&mut self, f: F) -> &mut Self
where F: FnOnce(&mut CreateInteractionOption) -> &mut CreateInteractionOption {
let mut data = CreateInteractionOption::default();
f(&mut data);
self.add_sub_option(data)
}

pub fn add_sub_option(&mut self, sub_option: CreateInteractionOption) -> &mut Self {
let new_option = utils::hashmap_to_json_map(sub_option.0);
let options = self.0.entry("options").or_insert_with(|| Value::Array(Vec::new()));
if let Some(opt_arr) = options.as_array_mut() {
opt_arr.push(Value::Object(new_option));
};
self
}

}


/// A builder for creating a new [`ApplicationCommand`].
///
/// [`name`] and [`description`] are required fields.
///
/// [`ApplicationCommand`]: crate::model::interactions::ApplicationCommand
/// [`name`]: Self::name
/// [`description`]: Self::description
#[derive(Clone, Debug, Default)]
pub struct CreateInteraction(pub HashMap<&'static str, Value>);

impl CreateInteraction {

/// Specify the name of the Interaction.
///
/// **Note**: Must be between 1 and 32 characters long,
/// and cannot start with a space.
pub fn name<D: ToString>(&mut self, name: D) -> &mut Self {
self.0.insert("name", Value::String(name.to_string()));
self
}

/// Specify the description of the Interaction.
///
/// **Note**: Must be between 1 and 100 characters long.
pub fn description<D: ToString>(&mut self, description: D) -> &mut Self {
self.0.insert("description", Value::String(description.to_string()));
self
}

/// Create an interaction option for the interaction.
///
/// **Note**: Interactions can only have up to 10 options.
pub fn create_interaction_option<F>(&mut self, f: F) -> &mut Self
where F: FnOnce(&mut CreateInteractionOption) -> &mut CreateInteractionOption {
let mut data = CreateInteractionOption::default();
f(&mut data);
self.add_interaction_option(data)

}

/// Add an interaction option for the interaction.
///
/// **Note**: Interactions can only have up to 10 options.
pub fn add_interaction_option(&mut self, option: CreateInteractionOption) -> &mut Self {
let new_option = utils::hashmap_to_json_map(option.0);
let options = self.0.entry("options").or_insert_with(|| Value::Array(Vec::new()));
if let Some(opt_arr) = options.as_array_mut() {
opt_arr.push(Value::Object(new_option));
};
// should this be changed to have None be a panic?
self

}

/// Sets all the interaction options for the interaction.
///
/// **Note**: Interactions can only have up to 10 options.
pub fn set_interaction_options(&mut self, options: Vec<CreateInteractionOption>) -> &mut Self {
let new_options = options.into_iter().map(
|f| Value::Object(utils::hashmap_to_json_map(f.0))
).collect::<Vec<Value>>();
self.0.insert("options", Value::Array(new_options));
self
}

}
13 changes: 12 additions & 1 deletion src/builder/mod.rs
Expand Up @@ -7,6 +7,11 @@

mod create_embed;
mod create_channel;

#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable_discord_api")))]
mod create_interaction;

mod create_invite;
#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(feature = "unstable_discord_api"))]
Expand All @@ -28,6 +33,7 @@ mod edit_role;
mod execute_webhook;
mod get_messages;


pub use self::{
create_embed::{CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter, Timestamp},
create_channel::CreateChannel,
Expand All @@ -46,8 +52,13 @@ pub use self::{
};

#[cfg(feature = "unstable_discord_api")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable_discord_api")))]
pub use self::{
create_interaction::{
CreateInteraction,
CreateInteractionOption,
},
create_interaction_response_followup::CreateInteractionResponseFollowup,
create_interaction_response::{CreateInteractionResponse, CreateInteractionResponseData},
edit_interaction_response::EditInteractionResponse,
};
};

0 comments on commit 0d743fd

Please sign in to comment.