Public Access
improve calculator, improve logging, fix auto role
This commit is contained in:
@@ -14,6 +14,7 @@ dotenv = "0.15.0"
|
||||
exmex = "0.21.0"
|
||||
f128 = "0.2.9"
|
||||
f256 = "0.11.2"
|
||||
num-bigint = "0.5.1"
|
||||
num-traits = "0.2.19"
|
||||
poise = "0.6.2"
|
||||
regex = "1.12.4"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE auto_roles ADD CONSTRAINT auto_roles_guild_id_key UNIQUE (guild_id);
|
||||
+85
-17
@@ -1,12 +1,12 @@
|
||||
use crate::{Context, Error};
|
||||
use tracing::{debug, trace, info};
|
||||
use tracing::{debug, trace, warn};
|
||||
use crate::shared_functions::trace_message;
|
||||
use regex::Regex;
|
||||
use std::sync::LazyLock;
|
||||
use std::str::FromStr;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use f128::f128;
|
||||
use exmex::{Express, FlatEx, MakeOperators, Operator, BinOp};
|
||||
use exmex::{Express, MakeOperators, Operator, BinOp};
|
||||
use num_traits::float::Float;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
@@ -142,22 +142,27 @@ pub async fn calc(ctx: Context<'_>,
|
||||
let response_message = ctx.say(msg).await?;
|
||||
let start_time = std::time::Instant::now();
|
||||
trace!("Saving start time: {:?}", start_time);
|
||||
let processed_expr = FIND_SCI_NOTATION_RE.replace_all(&expression, "($1 * 10^($2))");
|
||||
if expression.contains('=') {
|
||||
let error_msg = format!("Invalid expression: {}\nYou are not allowed to have an equal sign in the expression.", expression);
|
||||
debug!("Invalid expression detected: {}", expression);
|
||||
trace_message(error_msg.clone(), ctx.channel_id().to_string(), ctx.guild_id().unwrap().to_string()).await;
|
||||
edit_response_message(&response_message, ctx, error_msg, false).await?;
|
||||
return Ok(());
|
||||
}
|
||||
let processed_expr : String = FIND_SCI_NOTATION_RE.replace_all(&expression, "$1 * 10^($2)").to_string();
|
||||
trace!("Processed expression: {}", processed_expr);
|
||||
|
||||
let value = match precision {
|
||||
Some(Precision::Bits32) => exmex::eval_str::<f32>(&processed_expr).map_err(|err| err.to_string())?.to_string(),
|
||||
Some(Precision::Bits64) => exmex::eval_str::<f64>(&processed_expr).map_err(|err| err.to_string())?.to_string(),
|
||||
Some(Precision::Bits128) => {
|
||||
let expr = exmex::FlatEx::<F128, F128OpsFactory>::parse(&processed_expr).map_err(|err| err.to_string())?;
|
||||
expr.eval(&[]).map_err(|err| err.to_string())?.to_string()
|
||||
},
|
||||
Some(Precision::Bits256) => {
|
||||
let expr = exmex::FlatEx::<f256::f256, F256OpsFactory>::parse(&processed_expr).map_err(|err| err.to_string())?;
|
||||
expr.eval(&[]).map_err(|err| err.to_string())?.to_string()
|
||||
},
|
||||
None => exmex::eval_str::<f64>(&processed_expr).map_err(|err| err.to_string())?.to_string(),
|
||||
let value = match evaluate_expression(processed_expr, &precision) {
|
||||
Ok(v) => v,
|
||||
Err(err_msg) => {
|
||||
let error_msg = format!("Failed to parse or evaluate expression: `{}`", err_msg);
|
||||
warn!("Failed to parse or evaluate expression: `{}` in guild {} channel {} by {}", err_msg, ctx.guild_id().unwrap().get(), ctx.channel_id().get(), ctx.author().name);
|
||||
trace_message(error_msg.clone(), ctx.channel_id().to_string(), ctx.guild_id().unwrap().to_string()).await;
|
||||
edit_response_message(&response_message, ctx, error_msg, false).await?;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
trace!("Result: {}", value);
|
||||
let end_time = std::time::Instant::now();
|
||||
trace!("Saving end time: {:?}", end_time);
|
||||
let duration = end_time - start_time;
|
||||
@@ -169,10 +174,17 @@ pub async fn calc(ctx: Context<'_>,
|
||||
Some(Precision::Bits256) => "256-bit".to_string(),
|
||||
None => "64-bit".to_string(),
|
||||
};
|
||||
let msg = format!("{} = {} \n-# Precision: {} Compute time : {:?}", expression, value, precision_str, duration);
|
||||
// Turn to scientifc notation if number has more than 30 digits
|
||||
let value_string = if value.len() > 30 {
|
||||
to_scientific_notation(value)
|
||||
} else {
|
||||
value
|
||||
};
|
||||
|
||||
let msg = format!("{} = {} \n-# Precision: {} Compute time : {:?}", expression, value_string, precision_str, duration);
|
||||
trace_message(msg.clone(), ctx.channel_id().to_string(), ctx.guild_id().unwrap().to_string()).await;
|
||||
edit_response_message(&response_message, ctx, msg, false).await?;
|
||||
debug!("Calculation perfomed for {} with result {} in {:?} by {}", expression, value, duration, ctx.author().name);
|
||||
debug!("Calculation perfomed for {} with result {} in {:?} by {}", expression, value_string, duration, ctx.author().name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -183,4 +195,60 @@ async fn edit_response_message<'a>(response_message: &poise::ReplyHandle<'a>, ct
|
||||
response_message.edit(ctx, poise::CreateReply::default().content(content)).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_scientific_notation(value: String) -> String {
|
||||
trace!("Converting {} to scientific notation", value);
|
||||
if value.contains('e') || value.contains('E') {
|
||||
trace!("Already in scientific notation");
|
||||
return value;
|
||||
}
|
||||
|
||||
let mut is_negative = false;
|
||||
let mut val_str = value.as_str();
|
||||
if val_str.starts_with('-') {
|
||||
is_negative = true;
|
||||
val_str = &val_str[1..];
|
||||
}
|
||||
|
||||
let parts: Vec<&str> = val_str.split('.').collect();
|
||||
let integer_part = parts[0];
|
||||
let fractional_part = if parts.len() > 1 { parts[1] } else { "" };
|
||||
|
||||
if integer_part.len() <= 1 {
|
||||
return value;
|
||||
}
|
||||
|
||||
let first_digit = &integer_part[0..1];
|
||||
let rest_integer = &integer_part[1..];
|
||||
let exponent = integer_part.len() - 1;
|
||||
|
||||
let mut fractional_combined = format!("{}{}", rest_integer, fractional_part);
|
||||
fractional_combined = fractional_combined.trim_end_matches('0').to_string();
|
||||
|
||||
let sign = if is_negative { "-" } else { "" };
|
||||
|
||||
if fractional_combined.is_empty() {
|
||||
format!("{}{}e{}", sign, first_digit, exponent)
|
||||
} else {
|
||||
format!("{}{}.{}e{}", sign, first_digit, fractional_combined, exponent)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn evaluate_expression(expr: String, precision: &Option<Precision>) -> Result<String, String> {
|
||||
let value = match precision {
|
||||
Some(Precision::Bits32) => exmex::eval_str::<f32>(&expr).map_err(|err| err.to_string())?.to_string(),
|
||||
Some(Precision::Bits64) => exmex::eval_str::<f64>(&expr).map_err(|err| err.to_string())?.to_string(),
|
||||
Some(Precision::Bits128) => {
|
||||
let parsed_expr = exmex::FlatEx::<F128, F128OpsFactory>::parse(&expr).map_err(|err| err.to_string())?;
|
||||
parsed_expr.eval(&[]).map_err(|err| err.to_string())?.to_string()
|
||||
},
|
||||
Some(Precision::Bits256) => {
|
||||
let parsed_expr = exmex::FlatEx::<f256::f256, F256OpsFactory>::parse(&expr).map_err(|err| err.to_string())?;
|
||||
parsed_expr.eval(&[]).map_err(|err| err.to_string())?.to_string()
|
||||
},
|
||||
None => exmex::eval_str::<f64>(&expr).map_err(|err| err.to_string())?.to_string(),
|
||||
};
|
||||
Ok(value)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{Context, Error};
|
||||
use crate::shared_functions::get_all_admin_users;
|
||||
use poise::serenity_prelude as sere;
|
||||
use tracing::{error, warn, info, debug, trace};
|
||||
use tracing::{error, info, debug, trace};
|
||||
|
||||
#[derive(Debug, poise::ChoiceParameter)]
|
||||
pub enum AdminOperationType {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{Context, Error};
|
||||
use crate::shared_functions::get_all_admin_users;
|
||||
use poise::serenity_prelude as sere;
|
||||
use tracing::{error, warn, info, debug, trace};
|
||||
use tracing::{error, info, debug, trace};
|
||||
|
||||
#[derive(Debug, poise::ChoiceParameter)]
|
||||
pub enum AutoRoleOperationType {
|
||||
@@ -97,7 +97,7 @@ async fn enable_auto_role(ctx: Context<'_>, response_message: &poise::ReplyHandl
|
||||
let query = sqlx::query!("UPDATE auto_roles SET enabled = true WHERE guild_id = $1 AND role_id = $2;", ctx.guild_id().unwrap().get() as i64, role.id.get() as i64).execute(&ctx.data().pool).await;
|
||||
match query {
|
||||
Ok(_) => {
|
||||
info!("Enabled auto role {} in guild {}", role.name, ctx.guild_id().unwrap().get());
|
||||
debug!("Enabled auto role {} in guild {}", role.name, ctx.guild_id().unwrap().get());
|
||||
edit_response_message(response_message, ctx, format!("Enabled auto role: <@&{}>", role.id.get()), false).await?;
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -137,7 +137,7 @@ async fn set_auto_role(ctx: Context<'_>, response_message: &poise::ReplyHandle<'
|
||||
let query = sqlx::query!("INSERT INTO auto_roles (guild_id, role_id, enabled) VALUES ($1, $2, false) ON CONFLICT (guild_id) DO UPDATE SET role_id = $2;", ctx.guild_id().unwrap().get() as i64, role.id.get() as i64).execute(&ctx.data().pool).await;
|
||||
match query {
|
||||
Ok(_) => {
|
||||
info!("Set {} as auto role in guild {}", role.name, ctx.guild_id().unwrap().get());
|
||||
debug!("Set {} as auto role in guild {}", role.name, ctx.guild_id().unwrap().get());
|
||||
edit_response_message(response_message, ctx, format!("Set {} as auto role", role.name), false).await?;
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -165,7 +165,7 @@ async fn disable_auto_role(ctx: Context<'_>, response_message: &poise::ReplyHand
|
||||
let query = sqlx::query!("UPDATE auto_roles SET enabled = false WHERE guild_id = $1 AND role_id = $2;", ctx.guild_id().unwrap().get() as i64, role.id.get() as i64).execute(&ctx.data().pool).await;
|
||||
match query {
|
||||
Ok(_) => {
|
||||
info!("Disabled auto role {} in guild {}", role.name, ctx.guild_id().unwrap().get());
|
||||
debug!("Disabled auto role {} in guild {}", role.name, ctx.guild_id().unwrap().get());
|
||||
edit_response_message(response_message, ctx, format!("Disabled auto role: {}", role.name), false).await?;
|
||||
}
|
||||
Err(e) => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use poise::serenity_prelude as sere;
|
||||
use tracing::{error, warn, info, debug, trace};
|
||||
use tracing::{error, debug, trace};
|
||||
|
||||
pub async fn user_join(ctx: &sere::Context, new_member: &sere::Member, pool: &sqlx::PgPool) {
|
||||
trace!("User joined event handler called for guild {}", new_member.guild_id);
|
||||
@@ -35,6 +35,7 @@ pub async fn user_join(ctx: &sere::Context, new_member: &sere::Member, pool: &sq
|
||||
async fn give_role_to_user(ctx: &sere::Context, member: &sere::Member, role_id: u64) {
|
||||
if let Err(e) = member.add_role(&ctx.http, sere::RoleId::new(role_id)).await {
|
||||
error!("Error adding role to member: {:?}", e);
|
||||
return;
|
||||
}
|
||||
debug!("Role {} added to user {} in guild {}", role_id, member.user.name, member.guild_id);
|
||||
}
|
||||
Reference in New Issue
Block a user