diff --git a/src/commands.rs b/src/commands.rs index fec7ca6..9468ff0 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,14 +1,13 @@ -use crate::cofd::dice::{roll_pool, DicePool, DicePoolWithContext}; use crate::context::Context; -use crate::db::errors::DataError; -use crate::dice::ElementExpression; use crate::error::BotError; -use crate::help::HelpTopic; -use crate::roll::Roll; use async_trait::async_trait; use thiserror::Error; +pub mod basic_rolling; +pub mod cofd; +pub mod misc; pub mod parser; +pub mod variables; #[derive(Error, Debug)] pub enum CommandError { @@ -40,194 +39,6 @@ pub trait Command: Send + Sync { fn name(&self) -> &'static str; } -pub struct RollCommand(ElementExpression); - -#[async_trait] -impl Command for RollCommand { - fn name(&self) -> &'static str { - "roll regular dice" - } - - async 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); - -#[async_trait] -impl Command for PoolRollCommand { - fn name(&self) -> &'static str { - "roll dice pool" - } - - async fn execute(&self, ctx: &Context) -> Execution { - let pool_with_ctx = DicePoolWithContext(&self.0, ctx); - let roll_result = roll_pool(&pool_with_ctx).await; - - 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(Option); - -#[async_trait] -impl Command for HelpCommand { - fn name(&self) -> &'static str { - "help information" - } - - async fn execute(&self, _ctx: &Context) -> Execution { - let help = match &self.0 { - Some(topic) => topic.message(), - _ => "There is no help for this topic", - }; - - let plain = format!("Help: {}", help); - let html = format!("

Help: {}", help.replace("\n", "
")); - Execution { plain, html } - } -} - -pub struct GetAllVariablesCommand; - -#[async_trait] -impl Command for GetAllVariablesCommand { - fn name(&self) -> &'static str { - "get all variables" - } - - async fn execute(&self, ctx: &Context) -> Execution { - let result = ctx - .db - .variables - .get_user_variables(&ctx.room_id, &ctx.username); - - let value = match result { - Ok(variables) => { - let mut variable_list = variables - .into_iter() - .map(|(name, value)| format!(" - {} = {}", name, value)) - .collect::>(); - - variable_list.sort(); - variable_list.join("\n") - } - Err(e) => format!("error getting variables: {}", e), - }; - - let plain = format!("Variables:\n{}", value); - let html = format!( - "

Variables:
{}", - value.replace("\n", "
") - ); - Execution { plain, html } - } -} - -pub struct GetVariableCommand(String); - -#[async_trait] -impl Command for GetVariableCommand { - fn name(&self) -> &'static str { - "retrieve variable value" - } - - async fn execute(&self, ctx: &Context) -> Execution { - let name = &self.0; - let result = ctx - .db - .variables - .get_user_variable(&ctx.room_id, &ctx.username, name); - - let value = match result { - 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); - -#[async_trait] -impl Command for SetVariableCommand { - fn name(&self) -> &'static str { - "set variable value" - } - - async fn execute(&self, ctx: &Context) -> Execution { - let name = &self.0; - let value = self.1; - let result = ctx - .db - .variables - .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); - -#[async_trait] -impl Command for DeleteVariableCommand { - fn name(&self) -> &'static str { - "delete variable" - } - - async fn execute(&self, ctx: &Context) -> Execution { - let name = &self.0; - let result = ctx - .db - .variables - .delete_user_variable(&ctx.room_id, &ctx.username, name); - - let value = match result { - 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 } - } -} - /// 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. diff --git a/src/commands/basic_rolling.rs b/src/commands/basic_rolling.rs new file mode 100644 index 0000000..47d5454 --- /dev/null +++ b/src/commands/basic_rolling.rs @@ -0,0 +1,24 @@ +use super::{Command, Execution}; +use crate::context::Context; +use crate::dice::ElementExpression; +use crate::roll::Roll; +use async_trait::async_trait; + +pub struct RollCommand(pub ElementExpression); + +#[async_trait] +impl Command for RollCommand { + fn name(&self) -> &'static str { + "roll regular dice" + } + + async 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 } + } +} diff --git a/src/commands/cofd.rs b/src/commands/cofd.rs new file mode 100644 index 0000000..abed8be --- /dev/null +++ b/src/commands/cofd.rs @@ -0,0 +1,36 @@ +use super::{Command, Execution}; +use crate::cofd::dice::{roll_pool, DicePool, DicePoolWithContext}; +use crate::context::Context; +use async_trait::async_trait; + +pub struct PoolRollCommand(pub DicePool); + +#[async_trait] +impl Command for PoolRollCommand { + fn name(&self) -> &'static str { + "roll dice pool" + } + + async fn execute(&self, ctx: &Context) -> Execution { + let pool_with_ctx = DicePoolWithContext(&self.0, ctx); + let roll_result = roll_pool(&pool_with_ctx).await; + + 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 } + } +} diff --git a/src/commands/misc.rs b/src/commands/misc.rs new file mode 100644 index 0000000..e78492f --- /dev/null +++ b/src/commands/misc.rs @@ -0,0 +1,24 @@ +use super::{Command, Execution}; +use crate::context::Context; +use crate::help::HelpTopic; +use async_trait::async_trait; + +pub struct HelpCommand(pub Option); + +#[async_trait] +impl Command for HelpCommand { + fn name(&self) -> &'static str { + "help information" + } + + async fn execute(&self, _ctx: &Context) -> Execution { + let help = match &self.0 { + Some(topic) => topic.message(), + _ => "There is no help for this topic", + }; + + let plain = format!("Help: {}", help); + let html = format!("

Help: {}", help.replace("\n", "
")); + Execution { plain, html } + } +} diff --git a/src/commands/parser.rs b/src/commands/parser.rs index 04e623e..6194320 100644 --- a/src/commands/parser.rs +++ b/src/commands/parser.rs @@ -1,7 +1,12 @@ use crate::cofd::parser::{create_chance_die, parse_dice_pool}; use crate::commands::{ - Command, DeleteVariableCommand, GetAllVariablesCommand, GetVariableCommand, HelpCommand, - PoolRollCommand, RollCommand, SetVariableCommand, + basic_rolling::RollCommand, + cofd::PoolRollCommand, + misc::HelpCommand, + variables::{ + DeleteVariableCommand, GetAllVariablesCommand, GetVariableCommand, SetVariableCommand, + }, + Command, }; use crate::dice::parser::parse_element_expression; use crate::error::BotError; diff --git a/src/commands/variables.rs b/src/commands/variables.rs new file mode 100644 index 0000000..01a7d10 --- /dev/null +++ b/src/commands/variables.rs @@ -0,0 +1,121 @@ +use super::{Command, Execution}; +use crate::context::Context; +use crate::db::errors::DataError; +use async_trait::async_trait; + +pub struct GetAllVariablesCommand; + +#[async_trait] +impl Command for GetAllVariablesCommand { + fn name(&self) -> &'static str { + "get all variables" + } + + async fn execute(&self, ctx: &Context) -> Execution { + let result = ctx + .db + .variables + .get_user_variables(&ctx.room_id, &ctx.username); + + let value = match result { + Ok(variables) => { + let mut variable_list = variables + .into_iter() + .map(|(name, value)| format!(" - {} = {}", name, value)) + .collect::>(); + + variable_list.sort(); + variable_list.join("\n") + } + Err(e) => format!("error getting variables: {}", e), + }; + + let plain = format!("Variables:\n{}", value); + let html = format!( + "

Variables:
{}", + value.replace("\n", "
") + ); + Execution { plain, html } + } +} + +pub struct GetVariableCommand(pub String); + +#[async_trait] +impl Command for GetVariableCommand { + fn name(&self) -> &'static str { + "retrieve variable value" + } + + async fn execute(&self, ctx: &Context) -> Execution { + let name = &self.0; + let result = ctx + .db + .variables + .get_user_variable(&ctx.room_id, &ctx.username, name); + + let value = match result { + 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(pub String, pub i32); + +#[async_trait] +impl Command for SetVariableCommand { + fn name(&self) -> &'static str { + "set variable value" + } + + async fn execute(&self, ctx: &Context) -> Execution { + let name = &self.0; + let value = self.1; + let result = ctx + .db + .variables + .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(pub String); + +#[async_trait] +impl Command for DeleteVariableCommand { + fn name(&self) -> &'static str { + "delete variable" + } + + async fn execute(&self, ctx: &Context) -> Execution { + let name = &self.0; + let result = ctx + .db + .variables + .delete_user_variable(&ctx.room_id, &ctx.username, name); + + let value = match result { + 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 } + } +}