diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 2292afd..9ef591b 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -43,5 +43,7 @@ pub fn all() -> Vec { general!(stars), general!(tag), moderation!(set_welcome), + moderation!(support_ban, support_ban), + moderation!(support_ban, support_unban), ] } diff --git a/src/commands/moderation/mod.rs b/src/commands/moderation/mod.rs index d5578a0..cb77981 100644 --- a/src/commands/moderation/mod.rs +++ b/src/commands/moderation/mod.rs @@ -1 +1,2 @@ pub mod set_welcome; +pub mod support_ban; diff --git a/src/commands/moderation/support_ban.rs b/src/commands/moderation/support_ban.rs new file mode 100644 index 0000000..276eb00 --- /dev/null +++ b/src/commands/moderation/support_ban.rs @@ -0,0 +1,72 @@ +#![allow(clippy::unreadable_literal)] + +use poise::serenity_prelude::{Member, RoleId}; + +use crate::{Context, Error}; + +const ROLE_ID: RoleId = RoleId::new(1149435921301786634); +const HELPER_ID: RoleId = RoleId::new(1391519658917761106); + +#[poise::command( + slash_command, + prefix_command, + check = "require_helper", + ephemeral, + guild_only +)] +pub async fn support_ban(ctx: Context<'_>, member: Member) -> Result<(), Error> { + if member.roles.contains(&ROLE_ID) { + ctx.say(format!( + "❌ `{}` is already banned from support.", + member.user.tag() + )) + .await?; + + return Ok(()); + } + + member.add_role(ctx.http(), ROLE_ID).await?; + ctx.say(format!("✅ Banned `{}` from support!", &member.user.tag())) + .await?; + + Ok(()) +} + +#[poise::command( + slash_command, + prefix_command, + check = "require_helper", + ephemeral, + guild_only +)] +pub async fn support_unban(ctx: Context<'_>, member: Member) -> Result<(), Error> { + if !member.roles.contains(&ROLE_ID) { + ctx.say(format!( + "❌ `{}` is not banned from support.", + member.user.tag() + )) + .await?; + + return Ok(()); + } + + member.remove_role(ctx.http(), ROLE_ID).await?; + ctx.say(format!( + "✅ Unbanned `{}` from support!", + &member.user.tag() + )) + .await?; + + Ok(()) +} + +async fn require_helper(ctx: Context<'_>) -> Result { + let Some(member) = ctx.author_member().await else { + return Ok(false); + }; + + let is_helper = member.roles.contains(&HELPER_ID); + let is_moderator = member.permissions.unwrap_or_default().manage_roles(); + + Ok(is_helper || is_moderator) +} diff --git a/src/handlers/error.rs b/src/handlers/error.rs index 58d7a86..5306b0b 100644 --- a/src/handlers/error.rs +++ b/src/handlers/error.rs @@ -89,6 +89,25 @@ pub async fn handle(error: FrameworkError<'_, Data, Error>) { } } + FrameworkError::CommandCheckFailed { error, ctx, .. } => { + if let Some(error) = error { + // just log - it's probably best if people don't find out when they're breaking the perm checking + log::error!( + "Error checking permissions for {}:\n{error:?}", + ctx.command().name + ); + } else if let poise::Context::Application(ctx) = ctx { + // only show for application commands - for prefix commands there is no way to hide the response and avoid spam + ctx.send( + poise::CreateReply::default() + .content("❌ You're not allowed to use this command.") + .ephemeral(true), + ) + .await + .ok(); + } + } + error => { if let Err(e) = poise::builtins::on_error(error).await { error!("Unhandled error occurred:\n{e:#?}");