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