refactor(moderation): improve unmute scheduling

This commit is contained in:
Ax333l 2022-12-20 13:01:01 +01:00
parent 5fcad81483
commit 4c35fe5327
4 changed files with 33 additions and 45 deletions

View File

@ -176,16 +176,16 @@ pub async fn unmute(
let author = ctx.author(); let author = ctx.author();
let queue = queue_unmute_member( let queue = queue_unmute_member(
&ctx.discord().http, ctx.discord().clone(),
&ctx.discord().cache, data.database.clone(),
&data.database,
ctx.guild_id().unwrap(), ctx.guild_id().unwrap(),
id, id,
configuration.general.mute.role, configuration.general.mute.role,
0, 0,
) )
.await .await
.unwrap(); .unwrap()
.err();
respond_moderation( respond_moderation(
&ctx, &ctx,
@ -243,6 +243,9 @@ pub async fn mute(
let mute = &configuration.general.mute; let mute = &configuration.general.mute;
let guild_id = ctx.guild_id().unwrap(); let guild_id = ctx.guild_id().unwrap();
let discord = ctx.discord();
let cache = &discord.cache;
if let Some(pending_unmute) = data.pending_unmutes.get(&id.0) { if let Some(pending_unmute) = data.pending_unmutes.get(&id.0) {
trace!("Cancelling pending unmute for {}", id.0); trace!("Cancelling pending unmute for {}", id.0);
pending_unmute.abort(); pending_unmute.abort();
@ -252,9 +255,8 @@ pub async fn mute(
data.pending_unmutes.insert( data.pending_unmutes.insert(
id.0, id.0,
queue_unmute_member( queue_unmute_member(
&ctx.discord().http, discord.clone(),
&ctx.discord().cache, data.database.clone(),
&data.database,
guild_id, guild_id,
id, id,
mute.role, mute.role,
@ -274,7 +276,7 @@ pub async fn mute(
}; };
let result = async { let result = async {
if let Some(mut member) = ctx.discord().cache.member(guild_id, id) { if let Some(mut member) = cache.member(guild_id, id) {
let (is_currently_muted, removed_roles) = let (is_currently_muted, removed_roles) =
crate::utils::moderation::mute_moderation(&ctx, &mut member, mute).await?; crate::utils::moderation::mute_moderation(&ctx, &mut member, mute).await?;
// Prevent the bot from overriding the "take" field. // Prevent the bot from overriding the "take" field.

View File

@ -39,9 +39,8 @@ pub async fn load_muted_members(ctx: &serenity::Context, _: &serenity::Ready) {
data.pending_unmutes.insert( data.pending_unmutes.insert(
member.user.id.0, member.user.id.0,
queue_unmute_member( queue_unmute_member(
&ctx.http, ctx.clone(),
&ctx.cache, data.database.clone(),
&data.database,
member.guild_id, member.guild_id,
member.user.id, member.user.id,
mute_role_id, mute_role_id,

View File

@ -31,7 +31,7 @@ impl serenity::TypeMapKey for Data {
pub struct Data { pub struct Data {
configuration: Configuration, configuration: Configuration,
database: Arc<Database>, database: Arc<Database>,
pending_unmutes: HashMap<u64, JoinHandle<Option<Error>>>, pending_unmutes: HashMap<u64, JoinHandle<Result<(), Error>>>,
api: Api, api: Api,
} }

View File

@ -2,9 +2,7 @@ use std::cmp;
use std::sync::Arc; use std::sync::Arc;
use mongodb::options::FindOptions; use mongodb::options::FindOptions;
use poise::serenity_prelude::{ use poise::serenity_prelude::{ChannelId, GuildChannel, GuildId, Mentionable, User, UserId};
Cache, ChannelId, GuildChannel, GuildId, Http, Mentionable, User, UserId,
};
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use tracing::{debug, error, warn}; use tracing::{debug, error, warn};
@ -73,21 +71,16 @@ pub async fn mute_on_join(ctx: &serenity::Context, new_member: &mut serenity::Me
} }
pub fn queue_unmute_member( pub fn queue_unmute_member(
http: &Arc<Http>, ctx: serenity::Context,
cache: &Arc<Cache>, database: Arc<Database>,
database: &Arc<Database>,
guild_id: GuildId, guild_id: GuildId,
user_id: UserId, user_id: UserId,
mute_role_id: u64, mute_role_id: u64,
mute_duration: u64, mute_duration: u64,
) -> JoinHandle<Option<Error>> { ) -> JoinHandle<Result<(), Error>> {
let cache = cache.clone();
let http = http.clone();
let database = database.clone();
tokio::spawn(async move { tokio::spawn(async move {
tokio::time::sleep(std::time::Duration::from_secs(mute_duration)).await; tokio::time::sleep(std::time::Duration::from_secs(mute_duration)).await;
let delete_result = database let db_result = database
.find_and_delete::<Muted>( .find_and_delete::<Muted>(
"muted", "muted",
Muted { Muted {
@ -97,30 +90,24 @@ pub fn queue_unmute_member(
.into(), .into(),
None, None,
) )
.await; .await?
.ok_or("User was not muted.")?;
if let Err(database_remove_result) = delete_result { let taken_roles = db_result
Some(database_remove_result)
} else if let Some(find_result) = delete_result.unwrap() {
let taken_roles = find_result
.taken_roles .taken_roles
.unwrap() .unwrap()
.into_iter() .into_iter()
.map(|r| RoleId::from(r.parse::<u64>().unwrap())) .map(|r| RoleId::from(r.parse::<u64>().unwrap()))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let http = &ctx.http;
// Update roles if they didn't leave the guild. // Update roles if they didn't leave the guild.
let mut member = cache.member(guild_id, user_id)?; if let Some(mut member) = ctx.cache.member(guild_id, user_id) {
if let Err(add_role_result) = member.add_roles(&http, &taken_roles).await { member.add_roles(http, &taken_roles).await?;
Some(Error::from(add_role_result)) member.remove_role(http, mute_role_id).await?;
} else if let Err(remove_result) = member.remove_role(http, mute_role_id).await {
Some(Error::from(remove_result))
} else {
None
}
} else {
None
} }
Ok(())
}) })
} }