Skip to content

Commit

Permalink
Mutes: Overhaul unmute logic
Browse files Browse the repository at this point in the history
Unmutes were not being properly handled due to how I wrote the code
previously.

When a user is forcibly unmuted using the command, the future
within the in-memory dashmap is aborted AND the database entry
is now deleted after future abortion.

However, aborting a future doesn't mean that the dashmap's entry
containing the abort handler is deleted. There are two ways this could
have been approached:
1. Forcibly drop the element guard's reference and delete the dashmap
entry after aborting the future.
2. Abort the future and when the future is eventually awaited, delete
the dashmap entry.

I opted for number 2 because it allows for less redundant code and makes
more sense idiomatically.

If circumstances force me to adopt to number 1, I will do so, but forcibly
dropping a reference from memory and deleting something seems like a bad
idea in general instead of passively deleting entries from the dashmap.

The mutes command has also been simplified and everything should hopefully
be fine with this change.

Signed-off-by: kingbri <[email protected]>
  • Loading branch information
bdashore3 committed May 29, 2021
1 parent 9086192 commit befe3a1
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 45 deletions.
16 changes: 16 additions & 0 deletions src/commands/mutes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,22 @@ async fn unmute(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {

if let Some(mute_guard) = wrapped_mute {
mute_guard.value().abort();

let pool = ctx
.data
.read()
.await
.get::<ConnectionPool>()
.cloned()
.unwrap();

sqlx::query!(
"DELETE FROM mutes WHERE guild_id = $1 AND user_id = $2",
guild.id.0 as i64,
mute_user_id.0 as i64
)
.execute(&pool)
.await?;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/helpers/embed_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ pub fn get_guild_mutes_embed(
eb.title(format!("Mutes for guild {}", guild_name));

eb.color(0x6ac7e6);
eb.description("All times are when the user will be unmuted in UTC");
eb.description("All times are in UTC");
eb.field("Permanent mutes", permanent_mute_string, false);
eb.field("Timed mutes", timed_mute_string, false);
eb.footer(|f| {
Expand Down
61 changes: 17 additions & 44 deletions src/helpers/mute_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,32 +81,9 @@ pub async fn create_mute_timer(ctx: Context, time: u64, user_id: UserId, guild_i
mute_map.insert((guild_id, user_id), abort_handle);

sleep(Duration::from_secs(time)).await;
match future.await {
Ok(_) => {}
Err(_e) => {
let pool = ctx
.data
.read()
.await
.get::<ConnectionPool>()
.cloned()
.unwrap();

if let Err(e) = sqlx::query!(
"DELETE FROM mutes WHERE guild_id = $1 AND user_id = $2",
guild_id.0 as i64,
user_id.0 as i64
)
.execute(&pool)
.await
{
eprintln!(
"Error when deleting mute entry from user {} in guild {}: {}",
user_id.0, guild_id.0, e
);
}
}
}
let _ = future.await;

mute_map.remove(&(guild_id, user_id));
}

pub async fn unmute_by_time(ctx: &Context, user_id: &UserId, guild_id: &GuildId) -> CommandResult {
Expand Down Expand Up @@ -313,32 +290,28 @@ pub async fn fetch_guild_mutes(
) -> CommandResult<(String, String)> {
let timed_mutes = fetch_timed_mutes(pool, &guild.id).await?;

let permanent_mutes = guild
let permanent_mute_test = guild
.members
.iter()
.filter(|(_, m)| m.roles.contains(&mute_role_id))
.collect::<HashMap<&UserId, &Member>>();

let (permanent_mute_string, timed_mute_string) = if permanent_mutes.is_empty() {
(
"No permanent mutes!".to_string(),
"No temporary mutes!".to_string(),
)
.filter(|(u, m)| m.roles.contains(&mute_role_id) && !timed_mutes.contains_key(&u))
.format_with(" \n", |(u, _), f| f(&u.mention()))
.to_string();

let permanent_mute_string = if permanent_mute_test.is_empty() {
"No permanent mutes!".to_string()
} else {
let permanent_mute_string = permanent_mutes
.iter()
.format_with(" \n", |(u, _), f| f(&u.mention()))
.to_string();
permanent_mute_test
};

let timed_mute_string = timed_mutes
let timed_mute_string = if timed_mutes.is_empty() {
"No temporary mutes!".to_string()
} else {
timed_mutes
.iter()
.filter(|(user_id, _)| permanent_mutes.contains_key(user_id))
.format_with(" \n", |(user_id, timestamp), f| {
f(&format_args!("{}: {}", user_id.mention(), timestamp))
})
.to_string();

(permanent_mute_string, timed_mute_string)
.to_string()
};

Ok((permanent_mute_string, timed_mute_string))
Expand Down

0 comments on commit befe3a1

Please sign in to comment.