Skip to content
This repository has been archived by the owner on Aug 7, 2024. It is now read-only.

feat(Moderation): Add command to kick members #78

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions src/commands/moderation.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,17 @@



use bson::{doc, Document};
use chrono::Utc;
use mongodb::options::{UpdateModifications, UpdateOptions};
use poise::serenity_prelude::{
self as serenity,
CreateEmbed,
CreateEmbedFooter,
EditMessage,
GetMessages,
Mentionable,
UserId,
self as serenity, CreateEmbed, CreateEmbedFooter, EditMessage, GetMessages, Mentionable, UserId,
};
use poise::CreateReply;
use tracing::{debug, trace};

use crate::db::model::{Muted};
use crate::db::model::Muted;
use crate::utils::bot::get_member;
use crate::utils::macros::to_user;
use crate::utils::moderation::{
ban_moderation,
queue_unmute_member,
respond_moderation,
BanKind,
ModerationKind,
ban_moderation, queue_unmute_member, respond_moderation, BanKind, ModerationKind,
};
use crate::utils::parse_duration;
use crate::{Context, Error};
Expand Down Expand Up @@ -299,6 +286,23 @@ pub async fn purge(
Ok(())
}

/// Kick a member.
#[poise::command(slash_command)]
pub async fn kick(
ctx: Context<'_>,
#[description = "Member"] user: UserId,
#[description = "Reason for the ban"] reason: Option<String>,
) -> Result<(), Error> {
// We cannot use `User` as a parameter for the moderation commands because of a bug in serenity. See: https://github.com/revanced/revanced-discord-bot/issues/38
let user = to_user!(user, ctx);

let kick_result = kick_moderation(ctx).await;

let author = ctx.author();

ModerationKind::Kick(user.clone(), author.clone(), reason.clone(), kick_result)
}

/// Ban a member.
#[poise::command(slash_command)]
pub async fn ban(
Expand Down
60 changes: 50 additions & 10 deletions src/utils/moderation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,7 @@ use std::sync::{Arc, Mutex};

use mongodb::options::FindOptions;
use poise::serenity_prelude::{
ChannelId,
CreateEmbed,
CreateEmbedFooter,
CreateMessage,
GuildId,
Mentionable,
User,
UserId,
ChannelId, CreateEmbed, CreateEmbedFooter, CreateMessage, GuildId, Mentionable, User, UserId,
};
use poise::CreateReply;
use serenity::prelude::SerenityError;
Expand All @@ -28,8 +21,9 @@ use crate::{Context, Error};
pub enum ModerationKind {
Mute(User, User, String, Option<String>, Option<Error>), /* User, Command author, Reason, Expires, Error */
Unmute(User, User, Option<Error>), // User, Command author, Error
Ban(User, User, Option<String>, Option<SerenityError>), // User, Command author, Reason, Error
Unban(User, User, Option<SerenityError>), // User, Command author, Error
Kick(User, User, Option<String>, Option<SerenityError>), // User, Command author, Reason, Error
Ban(User, User, Option<String>, Option<SerenityError>), // User, Command author, Reason, Error
Unban(User, User, Option<SerenityError>), // User, Command author, Error
}
pub enum BanKind {
Ban(User, Option<u8>, Option<String>), // User, Amount of days to delete messages, Reason
Expand Down Expand Up @@ -191,6 +185,35 @@ pub async fn respond_moderation<'a>(
false,
),
},
ModerationKind::Kick(user, author, reason, error) => {
let f = match error {
Some(err) => {
*send_ephemeral.lock().unwrap() = true;

f.title(format!("Failed to kick {}", user.tag()))
.field("Exception", err.to_string(), false)
.field(
"Action",
format!(
"{} was kicked by {} but failed",
user.mention(),
author.mention()
),
false,
)
},
None => f.title(format!("Kicked {}", user.tag())).field(
"Action",
format!("{} was kicked by {}", user.mention(), author.mention()),
false,
),
};
if let Some(reason) = reason {
f.field("Reason", reason, true)
} else {
f
}
},
ModerationKind::Ban(user, author, reason, error) => {
let f = match error {
Some(err) => {
Expand Down Expand Up @@ -283,6 +306,23 @@ pub async fn respond_moderation<'a>(
Ok(())
}

pub async fn kick_moderation(ctx: &Context<'_>) -> Option<SerenityError> {
let guild_id = ctx.guild_id().unwrap();

let http = &ctx.serenity_context().http;

let reason = reason.as_deref().or(Some("None specified"));

let kick_result = http.kick_member(guild_id, user.id, reason).await;

if let Err(err) = kick_result {
error!("Failed to kick user {}: {}", user.id, err);
Some(err)
} else {
None
}
}

pub async fn ban_moderation(ctx: &Context<'_>, kind: &BanKind) -> Option<SerenityError> {
let guild_id = ctx.guild_id().unwrap();

Expand Down
Loading