Slight chat/play refactor, add roll command

This commit is contained in:
Benjamin Sherriff
2024-01-29 13:50:57 -05:00
parent 096a47b96e
commit 51e63d8dbe
13 changed files with 290 additions and 35 deletions

View File

@@ -0,0 +1,134 @@
use log::{error, warn};
use rand::Rng;
use serenity::{builder::CreateApplicationCommand, client::Context, model::application::{command::CommandOptionType, interaction::application_command::ApplicationCommandInteraction}};
use crate::bot::commands::audio::edit_response;
use super::audio::create_response;
pub async fn run(ctx: &Context, command: &ApplicationCommandInteraction) {
if let Err(why) = create_response(&ctx, &command, format!("Processing command...")).await {
error!("Failed to create response message: {}", why);
return;
}
let dice_string: String = match command.data.options.get(0) {
Some(o) => match &o.value {
Some(v) => match v.as_str() {
Some(s) => s.split_whitespace().collect::<String>(),
None => {
warn!("Missing dice option");
if let Err(why) = edit_response(&ctx, &command, format!("Dice option is missing")).await {
error!("Failed to create response message: {}", why);
}
return;
}
},
None => {
warn!("Missing dice option");
if let Err(why) = edit_response(&ctx, &command, format!("Dice option is missing")).await {
error!("Failed to create response message: {}", why);
}
return;
}
},
None => {
warn!("Missing dice option");
if let Err(why) = edit_response(&ctx, &command, format!("Dice option is missing")).await {
error!("Failed to create response message: {}", why);
}
return;
}
};
let dice = parse_dice(dice_string.as_str());
match dice {
Ok((count, sides, modifier)) => {
let mut rolls = Vec::new();
let mut total = 0;
for _ in 0..count {
let roll = rand::thread_rng().gen_range(1..=sides);
total += roll;
rolls.push(roll);
}
let response = format!("{}d{}{} = {}",
count,
sides,
if modifier > 0 { format!("+{}", modifier) } else if modifier < 0 { format!("-{}", modifier) } else { "".to_string() },
total + (modifier as u32)
);
if let Err(why) = edit_response(&ctx, &command, response).await {
error!("Failed to create response message: {}", why);
}
}
Err(why) => {
if let Err(why) = edit_response(&ctx, &command, format!("Invalid dice string: {}", why)).await {
error!("Failed to create response message: {}", why);
}
}
}
}
fn parse_dice(dice: &str) -> Result<(u32, u32, i32), String> {
let mut parts = dice.split("d");
let count = match parts.next() {
Some(c) => match c.parse::<u32>() {
Ok(n) => n,
Err(_) => return Err(format!("Invalid dice count: {}", c))
},
None => return Err(format!("Invalid dice string: {}", dice))
};
let mut positive_modifier = true;
let mut parts = match parts.next() {
Some(p) => {
// Check if contains a +/- modifier
if p.contains("+") {
positive_modifier = true;
p.split("+")
} else if p.contains("-") {
positive_modifier = false;
p.split("-")
} else {
p.split("+")
}
},
None => return Err(format!("Invalid dice string: {}", dice))
};
let sides = match parts.next() {
Some(s) => match s.parse::<u32>() {
Ok(n) => {
if n == 4 || n == 6 || n == 8 || n == 10 || n == 12 || n == 20 || n == 100 {
n
} else {
return Err(format!("Invalid dice sides: {}", s));
}
}
Err(_) => return Err(format!("Invalid dice sides: {}", s))
},
None => return Err(format!("Invalid dice string: {}", dice))
};
let modifier = match parts.next() {
Some(m) => match m.parse::<i32>() {
Ok(n) => {
if positive_modifier {
n
} else {
n * -1
}
},
Err(_) => return Err(format!("Invalid dice modifier: {}", m))
},
None => 0
};
Ok((count, sides, modifier))
}
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
command.name("roll").description("Rolls D&D dice").create_option(|option| {
option
.name("dice")
.description("Dice to roll")
.kind(CommandOptionType::String)
.required(true)
})
}