refactor moderation; change prefix to r

This commit is contained in:
TheKodeToad 2023-12-06 17:00:26 +00:00
parent 174d93544c
commit 20e2dbbe46
No known key found for this signature in database
GPG key ID: 5E39D70B4C93C38E
3 changed files with 123 additions and 52 deletions

View file

@ -15,7 +15,7 @@ pub fn to_global_commands() -> Vec<Command<Data, Report>> {
general::say(), general::say(),
general::stars(), general::stars(),
general::tag(), general::tag(),
moderation::ban_user(), moderation::ban(),
moderation::kick_user(), moderation::kick(),
] ]
} }

View file

@ -1,25 +1,94 @@
use crate::{consts::COLORS, Context}; use crate::{consts::COLORS, Context};
use color_eyre::eyre::{eyre, Result}; use color_eyre::eyre::{eyre, Result};
use poise::serenity_prelude::{CreateEmbed, User}; use poise::serenity_prelude::{
futures::TryFutureExt, CreateEmbed, CreateMessage, FutureExt, Guild, Timestamp, User, UserId,
};
fn create_moderation_embed( struct Action {
title: String, reason: String,
user: &User, data: ActionData,
delete_messages_days: Option<u8>, }
reason: Option<String>,
) -> impl FnOnce(&mut CreateEmbed) -> &mut CreateEmbed {
let fields = [
("User", format!("{} ({})", user.name, user.id), false),
("Reason", reason.unwrap_or("None".to_string()), false),
(
"Deleted messages",
format!("Last {} days", delete_messages_days.unwrap_or(0)),
false,
),
];
|e: &mut CreateEmbed| e.title(title).fields(fields).color(COLORS["red"]) enum ActionData {
Kick,
Ban { purge: u8 },
Timeout { until: Timestamp },
}
fn build_dm<'a, 'b>(
message: &'b mut CreateMessage<'a>,
guild: &Guild,
action: &Action,
) -> &'b mut CreateMessage<'a> {
let description = match &action.data {
ActionData::Kick => "kicked from".to_string(),
ActionData::Ban { purge: _ } => "banned from".to_string(),
ActionData::Timeout { until } => {
format!("timed out until <t:{}> in", until.unix_timestamp())
}
};
let guild_name = &guild.name;
let reason = &action.reason;
message.content(format!(
"You have been {description} {guild_name}.\nReason: {reason}"
))
}
async fn moderate(
ctx: &Context<'_>,
users: &Vec<UserId>,
action: &Action,
quiet: bool,
) -> Result<()> {
let guild = ctx
.guild()
.ok_or_else(|| eyre!("Couldn't get guild from message!"))?;
let reason = &action.reason;
let mut count = 0;
for user in users {
if quiet {
if let Ok(channel) = user.create_dm_channel(ctx.http()).await {
let _ = channel
.send_message(ctx.http(), |message| build_dm(message, &guild, action))
.await;
}
}
let success = match action.data {
ActionData::Kick => guild
.kick_with_reason(ctx.http(), user, reason)
.await
.is_ok(),
ActionData::Ban { purge } => guild
.ban_with_reason(ctx.http(), user, purge, reason)
.await
.is_ok(),
ActionData::Timeout { until } => guild
.edit_member(ctx.http(), user, |member| {
member.disable_communication_until_datetime(until)
})
.await
.is_ok(),
};
if success {
count += 1;
}
}
let total = users.len();
if count == total {
ctx.reply("✅ Done!").await?;
} else {
ctx.reply(format!("⚠️ {count}/{total} succeeded!"))
.await?;
}
Ok(())
} }
/// Ban a user /// Ban a user
@ -27,28 +96,28 @@ fn create_moderation_embed(
slash_command, slash_command,
prefix_command, prefix_command,
default_member_permissions = "BAN_MEMBERS", default_member_permissions = "BAN_MEMBERS",
required_permissions = "BAN_MEMBERS" required_permissions = "BAN_MEMBERS",
aliases("ban")
)] )]
pub async fn ban_user( pub async fn ban(
ctx: Context<'_>, ctx: Context<'_>,
user: User, users: Vec<UserId>,
delete_messages_days: Option<u8>, purge: Option<u8>,
reason: Option<String>, reason: Option<String>,
quiet: Option<bool>,
) -> Result<()> { ) -> Result<()> {
let days = delete_messages_days.unwrap_or(1); moderate(
let guild = ctx &ctx,
.guild() &users,
.ok_or_else(|| eyre!("Couldn't get guild from message; Unable to ban!"))?; &Action {
reason: reason.unwrap_or_default(),
guild data: ActionData::Ban {
.ban_with_reason(ctx, &user, days, reason.clone().unwrap_or_default()) purge: purge.unwrap_or(0),
.await?; },
},
let embed = create_moderation_embed("User banned!".to_string(), &user, Some(days), reason); quiet.unwrap_or(false),
)
ctx.send(|m| m.embed(embed)).await?; .await
Ok(())
} }
/// Kick a user /// Kick a user
@ -58,18 +127,20 @@ pub async fn ban_user(
default_member_permissions = "KICK_MEMBERS", default_member_permissions = "KICK_MEMBERS",
required_permissions = "KICK_MEMBERS" required_permissions = "KICK_MEMBERS"
)] )]
pub async fn kick_user(ctx: Context<'_>, user: User, reason: Option<String>) -> Result<()> { pub async fn kick(
let guild = ctx ctx: Context<'_>,
.guild() users: Vec<UserId>,
.ok_or_else(|| eyre!("Couldn't get guild from message; Unable to ban!"))?; reason: Option<String>,
quiet: Option<bool>,
guild ) -> Result<()> {
.kick_with_reason(ctx, &user, &reason.clone().unwrap_or_default()) moderate(
.await?; &ctx,
&users,
let embed = create_moderation_embed("User kicked!".to_string(), &user, None, reason); &Action {
reason: reason.unwrap_or_default(),
ctx.send(|m| m.embed(embed)).await?; data: ActionData::Kick {},
},
Ok(()) quiet.unwrap_or(false),
)
.await
} }

View file

@ -62,7 +62,7 @@ async fn main() -> Result<()> {
Box::pin(handlers::handle_event(ctx, event, framework, data)) Box::pin(handlers::handle_event(ctx, event, framework, data))
}, },
prefix_options: PrefixFrameworkOptions { prefix_options: PrefixFrameworkOptions {
prefix: Some("!".into()), prefix: Some("r".into()),
edit_tracker: Some(EditTracker::for_timespan(Duration::from_secs(3600))), edit_tracker: Some(EditTracker::for_timespan(Duration::from_secs(3600))),
..Default::default() ..Default::default()
}, },