use crate::cofd::dice::DicePool; use crate::context::Context; use crate::db::DataError; use crate::dice::ElementExpression; use crate::error::BotError; use crate::help::HelpTopic; use crate::roll::Roll; use thiserror::Error; pub mod parser; #[derive(Error, Debug)] pub enum CommandError { #[error("invalid command: {0}")] InvalidCommand(String), #[error("ignored command")] IgnoredCommand, } pub struct Execution { plain: String, html: String, } impl Execution { pub fn plain(&self) -> &str { &self.plain } pub fn html(&self) -> &str { &self.html } } pub trait Command { fn execute(&self, ctx: &Context) -> Execution; fn name(&self) -> &'static str; } pub struct RollCommand(ElementExpression); impl Command for RollCommand { fn name(&self) -> &'static str { "roll regular dice" } fn execute(&self, _ctx: &Context) -> Execution { let roll = self.0.roll(); let plain = format!("Dice: {}\nResult: {}", self.0, roll); let html = format!( "
Dice: {}
Result: {}
", self.0, roll ); Execution { plain, html } } } pub struct PoolRollCommand(DicePool); impl Command for PoolRollCommand { fn name(&self) -> &'static str { "roll dice pool" } fn execute(&self, _ctx: &Context) -> Execution { let roll_result = self.0.roll(); let (plain, html) = match roll_result { Ok(rolled_pool) => { let plain = format!("Pool: {}\nResult: {}", rolled_pool, rolled_pool.roll); let html = format!( "Pool: {}
Result: {}
", rolled_pool, rolled_pool.roll ); (plain, html) } Err(e) => { let plain = format!("Error: {}", e); let html = format!("Error: {}
", e); (plain, html) } }; Execution { plain, html } } } pub struct HelpCommand(OptionHelp: {}", help.replace("\n", "
"));
Execution { plain, html }
}
}
pub struct GetVariableCommand(String);
impl Command for GetVariableCommand {
fn name(&self) -> &'static str {
"retrieve variable value"
}
fn execute(&self, ctx: &Context) -> Execution {
let name = &self.0;
let value = match ctx.db.get_user_variable(ctx.room_id, ctx.username, name) {
Ok(num) => format!("{} = {}", name, num),
Err(DataError::KeyDoesNotExist(_)) => format!("{} is not set", name),
Err(e) => format!("error getting {}: {}", name, e),
};
let plain = format!("Variable: {}", value);
let html = format!("
Variable: {}", value); Execution { plain, html } } } pub struct SetVariableCommand(String, i32); impl Command for SetVariableCommand { fn name(&self) -> &'static str { "set variable value" } fn execute(&self, ctx: &Context) -> Execution { let name = &self.0; let value = self.1; let result = ctx .db .set_user_variable(ctx.room_id, ctx.username, name, value); let content = match result { Ok(_) => format!("{} = {}", name, value), Err(e) => format!("error setting {}: {}", name, e), }; let plain = format!("Set Variable: {}", content); let html = format!("
Set Variable: {}", content); Execution { plain, html } } } pub struct DeleteVariableCommand(String); impl Command for DeleteVariableCommand { fn name(&self) -> &'static str { "delete variable" } fn execute(&self, ctx: &Context) -> Execution { let name = &self.0; let value = match ctx.db.delete_user_variable(ctx.room_id, ctx.username, name) { Ok(()) => format!("{} now unset", name), Err(DataError::KeyDoesNotExist(_)) => format!("{} is not currently set", name), Err(e) => format!("error deleting {}: {}", name, e), }; let plain = format!("Remove Variable: {}", value); let html = format!("
Remove Variable: {}", value);
Execution { plain, html }
}
}
impl dyn Command {
/// Parse a command string into a dynamic command execution trait
/// object. Returns an error if a command was recognized but not
/// parsed correctly. Returns Ok(None) if no command was recognized.
pub fn parse(s: &str) -> Result {} {}