diff options
Diffstat (limited to 'src/commands/math.rs')
| -rw-r--r-- | src/commands/math.rs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/commands/math.rs b/src/commands/math.rs new file mode 100644 index 0000000..43a7de8 --- /dev/null +++ b/src/commands/math.rs | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | use crate::lang; | ||
| 2 | use crate::Data; | ||
| 3 | use crate::error::{Error, Result}; | ||
| 4 | |||
| 5 | type Context<'a> = poise::Context<'a, Data, Error>; | ||
| 6 | |||
| 7 | /// Evaluate a math expression via qalc | ||
| 8 | #[poise::command(slash_command)] | ||
| 9 | pub async fn math( | ||
| 10 | ctx: Context<'_>, | ||
| 11 | #[description = "Ekspresja matematyczn"] equation: String, | ||
| 12 | ) -> Result<()> { | ||
| 13 | if equation.len() > 1000 { | ||
| 14 | ctx.say(lang::L_MATH_TOO_LONG).await?; | ||
| 15 | return Ok(()); | ||
| 16 | } | ||
| 17 | |||
| 18 | if !equation.is_ascii() { | ||
| 19 | ctx.say(lang::L_MATH_NOT_ASCII).await?; | ||
| 20 | return Ok(()); | ||
| 21 | } | ||
| 22 | |||
| 23 | let mut depth = 0i32; | ||
| 24 | for c in equation.chars() { | ||
| 25 | match c { | ||
| 26 | '(' | '[' | '{' => depth += 1, | ||
| 27 | ')' | ']' | '}' => depth -= 1, | ||
| 28 | _ => {} | ||
| 29 | } | ||
| 30 | if depth < 0 { | ||
| 31 | ctx.say(lang::L_MATH_UNBALANCED).await?; | ||
| 32 | return Ok(()); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | if depth != 0 { | ||
| 36 | ctx.say(lang::L_MATH_UNBALANCED).await?; | ||
| 37 | return Ok(()); | ||
| 38 | } | ||
| 39 | |||
| 40 | let dangerous = [ | ||
| 41 | "eval", | ||
| 42 | "exec", | ||
| 43 | "os.", | ||
| 44 | "subprocess", | ||
| 45 | "import", | ||
| 46 | "__", | ||
| 47 | "system", | ||
| 48 | "shutil", | ||
| 49 | "typecast", | ||
| 50 | "shell", | ||
| 51 | "fork", | ||
| 52 | "execve", | ||
| 53 | ]; | ||
| 54 | let lower = equation.to_lowercase(); | ||
| 55 | if dangerous.iter().any(|d| lower.contains(d)) { | ||
| 56 | ctx.say(lang::L_MATH_DANGEROUS).await?; | ||
| 57 | return Ok(()); | ||
| 58 | } | ||
| 59 | |||
| 60 | let output = tokio::process::Command::new("qalc") | ||
| 61 | .arg(&equation) | ||
| 62 | .output() | ||
| 63 | .await | ||
| 64 | .map_err(|e| Error::Custom(lang::fmt_math_qalc_err(&e)))?; | ||
| 65 | |||
| 66 | let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); | ||
| 67 | if result.is_empty() { | ||
| 68 | ctx.say(lang::L_MATH_NO_RESULT).await?; | ||
| 69 | } else { | ||
| 70 | ctx.say(lang::fmt_math_result(&result)).await?; | ||
| 71 | } | ||
| 72 | Ok(()) | ||
| 73 | } | ||
| 74 | |||
| 75 | pub fn commands() -> Vec<poise::Command<Data, Error>> { | ||
| 76 | vec![math()] | ||
| 77 | } | ||
