From fd2354e2789c8868a6574cb5af475d7976241e25 Mon Sep 17 00:00:00 2001 From: paninizer <101371138+paninizer@users.noreply.github.com> Date: Thu, 15 Feb 2024 19:46:09 -0500 Subject: [PATCH 1/4] Error handling --- src/main.rs | 3 ++ src/utilities/embeds.rs | 2 +- src/utilities/mod.rs | 1 + src/utilities/on_error.rs | 63 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/utilities/on_error.rs diff --git a/src/main.rs b/src/main.rs index a721f6b..d9def2e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use std::{sync::Arc, time::Duration}; use tokio::time::sleep; use tracing::{error, info}; use utilities::event_handler::event_handler; +use utilities::on_error::on_error; use utilities::types::GuildSettings; mod commands; @@ -26,6 +27,7 @@ pub struct Data { pub is_loop_running: AtomicBool, } // User data, which is stored and accessible in all command invocations pub type Error = Box; +pub type FrameworkError<'a> = poise::FrameworkError<'a, Data, Error>; pub type Context<'a> = poise::Context<'a, Data, Error>; pub type PartialContext<'a> = poise::PartialContext<'a, Data, Error>; @@ -216,6 +218,7 @@ async fn main() { commands_ran_global.fetch_add(1, Ordering::Relaxed); }) }, + on_error: |error| Box::pin(on_error(error)), ..Default::default() }) .setup(|context, _ready, framework| { diff --git a/src/utilities/embeds.rs b/src/utilities/embeds.rs index 9a3cee1..7516b70 100644 --- a/src/utilities/embeds.rs +++ b/src/utilities/embeds.rs @@ -56,7 +56,7 @@ pub fn warnings_command_embed( ("Reason", reason_field, true), ("\u{200B}", "\u{200B}".to_owned(), false), ("ID", id_field, true), - ("Date", date_field, true) + ("Date", date_field, true), ]; CreateEmbed::default() diff --git a/src/utilities/mod.rs b/src/utilities/mod.rs index 34dfd72..1ba7e5d 100644 --- a/src/utilities/mod.rs +++ b/src/utilities/mod.rs @@ -4,5 +4,6 @@ pub mod git; pub mod messages; pub mod models; pub mod modlog; +pub mod on_error; pub mod paginate; pub mod types; diff --git a/src/utilities/on_error.rs b/src/utilities/on_error.rs new file mode 100644 index 0000000..b24d564 --- /dev/null +++ b/src/utilities/on_error.rs @@ -0,0 +1,63 @@ +use tracing::error; + +use crate::FrameworkError; + +use super::messages; + +pub async fn on_error(error: FrameworkError<'_>) { + match error { + FrameworkError::Setup { .. } | FrameworkError::EventHandler { .. } => {} + FrameworkError::Command { ctx, .. } => { + let reply = + messages::error_reply("Oh no! There's a problem in executing this command.", true); + if let Err(why) = ctx.send(reply).await { + if why.to_string().contains("40060") { + // Interaction has already been acknowledged. + return; + } + + error!("Couldn't send reply: {why:?}"); + } + } + FrameworkError::CommandPanic { ctx, .. } => { + let reply = messages::error_reply( + "Oh no! A panic occurred whilst executing this command.", + true, + ); + if let Err(why) = ctx.send(reply).await { + error!("Couldn't send reply: {:?}", why); + } + } + FrameworkError::ArgumentParse { .. } + | poise::FrameworkError::CommandStructureMismatch { .. } => {} + FrameworkError::MissingBotPermissions { + missing_permissions, + ctx, + .. + } => { + let permissions = missing_permissions + .iter() + .map(|permission| permission.to_string()) + .collect::>() + .join(", "); + + let reply = messages::error_reply( + format!("Oh no! I'm missing the following permission(s): `{permissions}`"), + true, + ); + if let Err(why) = ctx.send(reply).await { + error!("Couldn't send reply: {:?}", why); + } + } + FrameworkError::NsfwOnly { ctx, .. } => { + let reply = messages::error_reply( + "Sorry, but I can only execute this command in a NSFW channel.", + true, + ); + if let Err(why) = ctx.send(reply).await { + error!("Couldn't send reply: {:?}", why); + } + } + _ => {} + } +} From d454f8228572a39c966b86e2cc738f367ea2ce9b Mon Sep 17 00:00:00 2001 From: paninizer <101371138+paninizer@users.noreply.github.com> Date: Thu, 15 Feb 2024 20:17:19 -0500 Subject: [PATCH 2/4] stuck chunks implementation chunks implement for warnings command currently warnings command does not work, but will fix when I know how --- database.sqlite | Bin 98304 -> 98304 bytes src/commands/moderation.rs | 89 ++++++++++++++++++++++++++++++++++++- src/utilities/modlog.rs | 6 +-- 3 files changed, 91 insertions(+), 4 deletions(-) diff --git a/database.sqlite b/database.sqlite index 1813986e2dedbfcb3fac592e64c378fedfda380d..769d5e3a31e6b1a9a638d2c1a37172cfe0ffd380 100644 GIT binary patch delta 193 zcmZo@U~6b#+u$Z=Yo=geU}a)%Wo)$kd%&d6AM$SNv|JC*wmtSn!md>7{QiE~DH^_; zZA!I7pWL3b??v^mV>@p|Je6Pd73!GSM|K(ltafB}?9bnJw$b|@h_nQBg?h0=#TXxT#Ij5j{-SWNGJJcE0 zv~QZx_Ih*HYXgNZ6Zwzdes8u~T8QUT&g5n}MJ|L1lh?@^Ftc6Znfy>r1zDJ1-cYOR zMkEtEtE4e!4l{$kf>f(WZhlHme!7u?k%_K>k**<, + #[description = "The user to get warnings for."] + #[rename = "user"] + user_id: UserId, +) -> Result<(), Error> { + let database = &context.data().sqlite; + + let user = models::user(context, user_id).await?; + + if user.system { + let reply = messages::error_reply("Cannot get warnings for a system user.", false); + context.send(reply).await?; + return Ok(()); + } + + let result = { + let (user_name, user_mention) = (&user.name, models::user_mention(context, user_id).await?); + + let (guild_id, guild_name) = { + let guild_id = context.guild_id().unwrap(); + let guild = context.guild().unwrap(); + (guild_id, guild.name.clone()) + }; + + let user_mod_history = + match modlog::select_modlog(ModType::Warn, &user_id, &guild_id, database).await { + Ok(user_mod_history) => user_mod_history, + Err(why) => { + error!("Couldn't select warnings from infractions: {why:?}"); + return Err(why.into()); + } + }; + + let warning_count = user_mod_history.len(); + if warning_count < 1 { + let reply = + messages::info_reply(format!("{user_mention} doesn't have any warnings."), true); + context.send(reply).await?; + + return Ok(()); + } + + let (uuids, moderator_ids, reasons, created_ats) = ( + user_mod_history + .iter() + .map(|(uuid, _, _, _, _, _, _)| uuid) + .collect::>(), + user_mod_history + .iter() + .map(|(_, _, _, moderator_id, _, _, _)| moderator_id) + .collect::>(), + user_mod_history + .iter() + .map(|(_, _, _, _, reason, _, _)| reason) + .collect::>(), + user_mod_history + .iter() + .map(|(_, _, _, _, _, created_at, _)| created_at) + .collect::>(), + ); + + // TODO: Add pagination + let uuids_iter = uuids.chunks(25); + let mod_ids_iter = moderator_ids.chunks(25); + let reasons_iter = reasons.chunks(25); + let created_ats_iter = created_ats.chunks(25); + + // Cycle through the chunks of 25, creating pagination embeds + }; + + if let Err(why) = result { + let reply = messages::error_reply(&why, true); + context.send(reply).await?; + } + + Ok(()) +} diff --git a/src/utilities/modlog.rs b/src/utilities/modlog.rs index 3be3452..9b9d1bc 100644 --- a/src/utilities/modlog.rs +++ b/src/utilities/modlog.rs @@ -28,12 +28,12 @@ impl ModType { } } -pub async fn select_mod_log( +pub async fn select_modlog( modtype: ModType, user_id: &UserId, guild_id: &GuildId, pool: &SqlitePool, -) -> Result, sqlx::Error> { +) -> Result, sqlx::Error> { let start_time = Instant::now(); let rows = sqlx::query( @@ -67,7 +67,7 @@ pub async fn select_mod_log( user_id, moderator_id, action_type, - created_at.to_string(), + created_at, reason, )); } From 646cef31a8736e3381bd566e70c64bb1fb5f276d Mon Sep 17 00:00:00 2001 From: paninizer <101371138+paninizer@users.noreply.github.com> Date: Fri, 16 Feb 2024 17:04:11 -0500 Subject: [PATCH 3/4] implementation of paginated warning commands --- src/commands/moderation.rs | 27 ++++++++++++++++++++------- src/main.rs | 1 + src/utilities/embeds.rs | 8 ++++---- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/commands/moderation.rs b/src/commands/moderation.rs index 38609cd..2cc9af4 100644 --- a/src/commands/moderation.rs +++ b/src/commands/moderation.rs @@ -2,8 +2,7 @@ use std::time::Duration; use crate::{ utilities::{ - messages, models, - modlog::{self, ModType}, + self, embeds::warnings_command_embed, messages, models, modlog::{self, ModType} }, Context, Error, }; @@ -635,11 +634,7 @@ pub async fn warnings( let result = { let (user_name, user_mention) = (&user.name, models::user_mention(context, user_id).await?); - let (guild_id, guild_name) = { - let guild_id = context.guild_id().unwrap(); - let guild = context.guild().unwrap(); - (guild_id, guild.name.clone()) - }; + let guild_id = context.guild_id().unwrap(); let user_mod_history = match modlog::select_modlog(ModType::Warn, &user_id, &guild_id, database).await { @@ -685,6 +680,24 @@ pub async fn warnings( let created_ats_iter = created_ats.chunks(25); // Cycle through the chunks of 25, creating pagination embeds + let mut embeds = Vec::new(); + uuids_iter.zip(mod_ids_iter.zip(reasons_iter.zip(created_ats_iter))).for_each( + |(uuids, (moderator_ids, (reasons, created_ats)))| { + embeds.push(warnings_command_embed(&user, uuids, moderator_ids, reasons, created_ats)); + } + ); + + match utilities::paginate::paginate(context, embeds).await { + Ok(_) => { + let author = context.author().id; + info!("@{author} requested @{user_name}'s warnings"); + Ok(format!("{user_mention} has {warning_count} warning(s).")) + } + Err(why) => { + error!("Failed to paginate: {why:?}"); + Err(why.to_string()) + }, + } }; if let Err(why) = result { diff --git a/src/main.rs b/src/main.rs index d9def2e..264e30a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -194,6 +194,7 @@ async fn main() { timeout(), untimeout(), warn(), + warnings(), // Utility commands help(), ping(), diff --git a/src/utilities/embeds.rs b/src/utilities/embeds.rs index 7516b70..0bd96e4 100644 --- a/src/utilities/embeds.rs +++ b/src/utilities/embeds.rs @@ -9,10 +9,10 @@ use std::fmt::Write; // Modified from wakalaka-rs pub fn warnings_command_embed( user: &User, - uuids: Vec<&String>, - moderator_ids: Vec<&i64>, - reasons: Vec<&String>, - dates: Vec, + uuids: &[&String], + moderator_ids: &[&i64], + reasons: &[&String], + dates: &[&NaiveDateTime], ) -> CreateEmbed { // |(PFP) {user_name} | // | ID | Moderator | Reason | From c989d16e0da2fdce5ee4bd6866a494f3d8907e50 Mon Sep 17 00:00:00 2001 From: paninizer <101371138+paninizer@users.noreply.github.com> Date: Sat, 17 Feb 2024 15:35:10 -0500 Subject: [PATCH 4/4] Update rust.yml --- .github/workflows/rust.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 5d61780..ea2170a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -26,6 +26,9 @@ jobs: - uses: hecrj/setup-rust-action@v2 with: rust-version: ${{ matrix.rust }} + - name: Update APT Cache + if: matrix.os == 'ubuntu-latest' + run: sudo apt-get update - name: Install 'libatk1.0-dev' on Ubuntu if: matrix.os == 'ubuntu-latest' run: sudo apt-get install -y libatk1.0-dev