From 0bb587c4b80fc5ae8a23ec61f60f2847cce4fbe0 Mon Sep 17 00:00:00 2001 From: paninizer <101371138+paninizer@users.noreply.github.com> Date: Tue, 19 Mar 2024 10:40:14 -0400 Subject: [PATCH] moderation rework removed some relations so that a user's logs will not be deleted after they leave (which would be idiotic) and fixed all moderation commands that use logging next step is to implement guild logging channel setup --- migrations/0_initial.sql | 7 +-- src/commands/moderation.rs | 92 +++++++++++++++++++++++++++++++++++++- src/main.rs | 2 +- src/utilities/modlog.rs | 36 +++++++++++++-- 4 files changed, 127 insertions(+), 10 deletions(-) diff --git a/migrations/0_initial.sql b/migrations/0_initial.sql index 1b67589..d112596 100644 --- a/migrations/0_initial.sql +++ b/migrations/0_initial.sql @@ -31,13 +31,11 @@ CREATE TABLE guild_logged_channel ( ); CREATE TABLE user_guild ( - user_id BIGINT, - guild_id BIGINT, + user_id BIGINT NOT NULL, + guild_id BIGINT NOT NULL, join_date TEXT NOT NULL, - first_join_date TEXT NOT NULL, infractions INT NOT NULL DEFAULT 0, PRIMARY KEY (user_id, guild_id), - FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE, FOREIGN KEY (guild_id) REFERENCES guild(id) ON DELETE CASCADE ); @@ -51,7 +49,6 @@ CREATE TABLE guild_log ( time_created TIMESTAMP NOT NULL, PRIMARY KEY (uuid), FOREIGN KEY (guild_id) REFERENCES guild(id) ON DELETE CASCADE, - FOREIGN KEY (user_id) REFERENCES user(id) FOREIGN KEY (moderator_id) REFERENCES user(id) ); diff --git a/src/commands/moderation.rs b/src/commands/moderation.rs index 0879ab4..ef79ce8 100644 --- a/src/commands/moderation.rs +++ b/src/commands/moderation.rs @@ -5,7 +5,7 @@ use crate::{ self, embeds::warnings_command_embed, messages, models, - modlog::{self, ModType}, + modlog::{self, ensure_user, ModType}, }, Context, Error, }; @@ -39,6 +39,15 @@ pub async fn ban( let user = models::user(context, user_id).await?; + let member = models::member(context, context.guild_id().unwrap(), user_id).await?; + + let ensure = ensure_user(&member, &user_id, &context.guild_id().unwrap(), database).await; + + if let Err(why) = ensure { + let _ = messages::error_response(why.to_string(), true).await; + return Ok(()); + } + let moderator = context.author(); let moderator_id = moderator.id; @@ -120,6 +129,9 @@ pub async fn ban( if let Err(why) = result { let reply = messages::error_reply(&why, true); context.send(reply).await?; + } else { + let reply = messages::info_reply(result.unwrap(), true); + context.send(reply).await?; } Ok(()) @@ -148,6 +160,15 @@ pub async fn kick( let user = models::user(context, user_id).await?; + let member = models::member(context, context.guild_id().unwrap(), user_id).await?; + + let ensure = ensure_user(&member, &user_id, &context.guild_id().unwrap(), database).await; + + if let Err(why) = ensure { + let _ = messages::error_response(why.to_string(), true).await; + return Ok(()); + } + let moderator = context.author(); let moderator_id = moderator.id; @@ -228,6 +249,10 @@ pub async fn kick( if let Err(why) = result { let reply = messages::error_reply(&why, true); + context.send(reply).await?; + } else { + let reply = messages::info_reply(result.unwrap(), true); + context.send(reply).await?; } @@ -257,6 +282,15 @@ pub async fn unban( let user = models::user(context, user_id).await?; + let member = models::member(context, context.guild_id().unwrap(), user_id).await?; + + let ensure = ensure_user(&member, &user_id, &context.guild_id().unwrap(), database).await; + + if let Err(why) = ensure { + let _ = messages::error_response(why.to_string(), true).await; + return Ok(()); + } + let moderator = context.author(); let moderator_id = moderator.id; @@ -327,6 +361,10 @@ pub async fn unban( if let Err(why) = result { let reply = messages::error_reply(&why, true); + context.send(reply).await?; + } else { + let reply = messages::info_reply(result.unwrap(), true); + context.send(reply).await?; } @@ -373,6 +411,15 @@ pub async fn timeout( return Ok(()); } + let member = models::member(context, context.guild_id().unwrap(), user_id).await?; + + let ensure = ensure_user(&member, &user_id, &context.guild_id().unwrap(), database).await; + + if let Err(why) = ensure { + let _ = messages::error_response(why.to_string(), true).await; + return Ok(()); + } + let reason = reason.unwrap_or_else(|| "No reason provided.".to_string()); let reason_char_count = reason.chars().count(); @@ -455,6 +502,10 @@ pub async fn timeout( if let Err(why) = result { let reply = messages::error_reply(&why, true); + context.send(reply).await?; + } else { + let reply = messages::info_reply(result.unwrap(), true); + context.send(reply).await?; } @@ -487,6 +538,15 @@ pub async fn untimeout( return Ok(()); } + let member = models::member(context, context.guild_id().unwrap(), user_id).await?; + + let ensure = ensure_user(&member, &user_id, &context.guild_id().unwrap(), database).await; + + if let Err(why) = ensure { + let _ = messages::error_response(why.to_string(), true).await; + return Ok(()); + } + let result = { let (user_name, user_mention) = (&user.name, models::user_mention(context, user_id).await?); @@ -533,6 +593,10 @@ pub async fn untimeout( if let Err(why) = result { let reply = messages::error_reply(&why, true); + context.send(reply).await?; + } else { + let reply = messages::info_reply(result.unwrap(), true); + context.send(reply).await?; } @@ -560,6 +624,15 @@ pub async fn warn( let user = models::user(context, user_id).await?; + let member = models::member(context, context.guild_id().unwrap(), user_id).await?; + + let ensure = ensure_user(&member, &user_id, &context.guild_id().unwrap(), database).await; + + if let Err(why) = ensure { + let _ = messages::error_response(why.to_string(), true).await; + return Ok(()); + } + if user.system { let reply = messages::error_reply("Cannot warn a system user.", false); context.send(reply).await?; @@ -610,6 +683,10 @@ pub async fn warn( if let Err(why) = result { let reply = messages::error_reply(&why, true); + context.send(reply).await?; + } else { + let reply = messages::info_reply(result.unwrap(), true); + context.send(reply).await?; } @@ -635,6 +712,15 @@ pub async fn warnings( let user = models::user(context, user_id).await?; + let member = models::member(context, context.guild_id().unwrap(), user_id).await?; + + let ensure = ensure_user(&member, &user_id, &context.guild_id().unwrap(), database).await; + + if let Err(why) = ensure { + let _ = messages::error_response(why.to_string(), true).await; + return Ok(()); + } + if user.system { let reply = messages::error_reply("Cannot get warnings for a system user.", false); context.send(reply).await?; @@ -718,6 +804,10 @@ pub async fn warnings( if let Err(why) = result { let reply = messages::error_reply(&why, true); + context.send(reply).await?; + } else { + let reply = messages::info_reply(result.unwrap(), true); + context.send(reply).await?; } diff --git a/src/main.rs b/src/main.rs index 763fe29..2548a55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -298,7 +298,7 @@ async fn main() { let author_id = i64::from(context.author().id); if let Err(query) = sqlx::query!( - "INSERT INTO user ( + "INSERT OR IGNORE INTO user ( id ) VALUES (?)", author_id diff --git a/src/utilities/modlog.rs b/src/utilities/modlog.rs index fe14713..dfc6175 100644 --- a/src/utilities/modlog.rs +++ b/src/utilities/modlog.rs @@ -1,3 +1,4 @@ +use ::serenity::all::Member; use chrono::NaiveDateTime; use poise::serenity_prelude as serenity; use serenity::all::{GuildId, UserId}; @@ -136,14 +137,43 @@ pub async fn insert_modlog( Ok(()) } +pub async fn ensure_user( + member: &Member, + user_id: &UserId, + guild_id: &GuildId, + pool: &SqlitePool, +) -> Result<(), sqlx::Error> { + let start_time = Instant::now(); + + let join = member.joined_at.unwrap().to_rfc2822(); + + let query = sqlx::query( + "INSERT OR IGNORE INTO user_guild (user_id, guild_id, infractions, join_date) VALUES (?, ?, ?, ?)") + .bind(i64::from(*user_id)) + .bind(i64::from(*guild_id)) + .bind(0) + .bind(join); + + if let Err(why) = query.execute(pool).await { + error!("Failed to execute query: {:?}", why); + return Err(why); + } + + let elapsed_time = start_time.elapsed(); + + info!("Ensured user in Users in {elapsed_time:.2?}"); + + Ok(()) +} + pub async fn select_modlog_from_users( user_id: &UserId, pool: &SqlitePool, ) -> Result { let start_time = Instant::now(); - let query = - sqlx::query("SELECT infractions FROM users WHERE user_id = ?").bind(i64::from(*user_id)); + let query = sqlx::query("SELECT infractions FROM user_guild WHERE user_id = ?") + .bind(i64::from(*user_id)); let row = match query.fetch_one(pool).await { Ok(infractions) => infractions, Err(why) => { @@ -173,7 +203,7 @@ pub async fn update_users_set_modlog( ) -> Result<(), sqlx::Error> { let start_time = Instant::now(); - let query = sqlx::query("UPDATE users SET infractions = ? WHERE user_id = ?") + let query = sqlx::query("UPDATE user_guild SET infractions = ? WHERE user_id = ?") .bind(infractions) .bind(i64::from(*user_id)); if let Err(why) = query.execute(pool).await {