mirror of
https://github.com/revanced/revanced-discord-bot.git
synced 2025-04-30 06:24:27 +02:00
feat: unban
command
This commit is contained in:
parent
042fc8c466
commit
b7d333c86c
@ -1,13 +1,17 @@
|
|||||||
use std::cmp;
|
|
||||||
|
|
||||||
use bson::{doc, Document};
|
use bson::{doc, Document};
|
||||||
use chrono::{Duration, Utc};
|
use chrono::{Duration, Utc};
|
||||||
use mongodb::options::{UpdateModifications, UpdateOptions};
|
use mongodb::options::{UpdateModifications, UpdateOptions};
|
||||||
use poise::serenity_prelude::{self as serenity, Member, RoleId};
|
use poise::serenity_prelude::{self as serenity, Member, RoleId, User};
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
use crate::db::model::Muted;
|
use crate::db::model::Muted;
|
||||||
use crate::utils::moderation::{queue_unmute_member, respond_mute_command, ModerationKind};
|
use crate::utils::moderation::{
|
||||||
|
ban_moderation,
|
||||||
|
queue_unmute_member,
|
||||||
|
respond_moderation,
|
||||||
|
BanKind,
|
||||||
|
ModerationKind,
|
||||||
|
};
|
||||||
use crate::{Context, Error};
|
use crate::{Context, Error};
|
||||||
|
|
||||||
/// Unmute a member.
|
/// Unmute a member.
|
||||||
@ -26,7 +30,7 @@ pub async fn unmute(
|
|||||||
pending_unmute.abort();
|
pending_unmute.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
respond_mute_command(
|
respond_moderation(
|
||||||
&ctx,
|
&ctx,
|
||||||
ModerationKind::Unmute(
|
ModerationKind::Unmute(
|
||||||
queue_unmute_member(
|
queue_unmute_member(
|
||||||
@ -40,7 +44,6 @@ pub async fn unmute(
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
&member.user,
|
&member.user,
|
||||||
configuration.general.embed_color,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -88,7 +91,6 @@ pub async fn mute(
|
|||||||
|
|
||||||
let data = &mut *ctx.data().write().await;
|
let data = &mut *ctx.data().write().await;
|
||||||
let configuration = &data.configuration;
|
let configuration = &data.configuration;
|
||||||
let embed_color = configuration.general.embed_color;
|
|
||||||
let mute = &configuration.general.mute;
|
let mute = &configuration.general.mute;
|
||||||
let mute_role_id = mute.role;
|
let mute_role_id = mute.role;
|
||||||
let take = &mute.take;
|
let take = &mute.take;
|
||||||
@ -170,11 +172,10 @@ pub async fn mute(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
respond_mute_command(
|
respond_moderation(
|
||||||
&ctx,
|
&ctx,
|
||||||
ModerationKind::Mute(reason, format!("<t:{}:F>", unmute_time.timestamp()), result),
|
ModerationKind::Mute(reason, format!("<t:{}:F>", unmute_time.timestamp()), result),
|
||||||
&member.user,
|
&member.user,
|
||||||
embed_color,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -183,7 +184,7 @@ pub async fn mute(
|
|||||||
#[poise::command(slash_command)]
|
#[poise::command(slash_command)]
|
||||||
pub async fn purge(
|
pub async fn purge(
|
||||||
ctx: Context<'_>,
|
ctx: Context<'_>,
|
||||||
#[description = "User"] member: Option<Member>,
|
#[description = "User"] user: Option<User>,
|
||||||
#[description = "Until message"] until: Option<String>,
|
#[description = "Until message"] until: Option<String>,
|
||||||
#[min = 1]
|
#[min = 1]
|
||||||
#[max = 1000]
|
#[max = 1000]
|
||||||
@ -203,10 +204,10 @@ pub async fn purge(
|
|||||||
let channel = ctx.channel_id();
|
let channel = ctx.channel_id();
|
||||||
let too_old_timestamp = Utc::now().timestamp() - MAX_BULK_DELETE_AGO_SECS;
|
let too_old_timestamp = Utc::now().timestamp() - MAX_BULK_DELETE_AGO_SECS;
|
||||||
|
|
||||||
let user = ctx.discord().http.get_current_user().await?;
|
let current_user = ctx.discord().http.get_current_user().await?;
|
||||||
let image = user
|
let image = current_user
|
||||||
.avatar_url()
|
.avatar_url()
|
||||||
.unwrap_or_else(|| user.default_avatar_url());
|
.unwrap_or_else(|| current_user.default_avatar_url());
|
||||||
|
|
||||||
let handle = ctx
|
let handle = ctx
|
||||||
.send(|f| {
|
.send(|f| {
|
||||||
@ -238,13 +239,13 @@ pub async fn purge(
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// Filter for messages from the user
|
// Filter for messages from the user
|
||||||
if let Some(ref member) = member {
|
if let Some(ref user) = user {
|
||||||
messages = messages
|
messages = messages
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|msg| msg.author.id == member.user.id)
|
.filter(|msg| msg.author.id == user.id)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
debug!("Filtered messages by {}. Left: {}", member, messages.len());
|
debug!("Filtered messages by {}. Left: {}", user, messages.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter for messages until the g/mutiven id
|
// Filter for messages until the g/mutiven id
|
||||||
@ -291,41 +292,32 @@ pub async fn purge(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ban a member.
|
/// Ban a user.
|
||||||
#[poise::command(slash_command)]
|
#[poise::command(slash_command)]
|
||||||
pub async fn ban(
|
pub async fn ban(
|
||||||
ctx: Context<'_>,
|
ctx: Context<'_>,
|
||||||
#[description = "User"] member: Member,
|
#[description = "User"] user: User,
|
||||||
#[description = "Amount of days to delete messages"] dmd: Option<u8>,
|
#[description = "Amount of days to delete messages"] dmd: Option<u8>,
|
||||||
#[description = "Reason for the ban"] reason: Option<String>,
|
#[description = "Reason for the ban"] reason: Option<String>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let reason = &reason
|
respond_moderation(
|
||||||
.or_else(|| Some("None specified".to_string()))
|
&ctx,
|
||||||
.unwrap();
|
ModerationKind::Ban(
|
||||||
|
reason.clone(),
|
||||||
let ban_result = member
|
ban_moderation(&ctx, BanKind::Ban(user.clone(), dmd, reason)).await,
|
||||||
.ban_with_reason(&ctx.discord().http, cmp::min(dmd.unwrap_or(0), 7), reason)
|
),
|
||||||
.await;
|
&user,
|
||||||
|
)
|
||||||
let embed_color = ctx.data().read().await.configuration.general.embed_color;
|
.await
|
||||||
|
}
|
||||||
ctx.send(|f| {
|
|
||||||
f.embed(|e| {
|
/// Unban a user.
|
||||||
if let Err(error) = ban_result {
|
#[poise::command(slash_command)]
|
||||||
e.title(format!("Failed to ban {}", member.user.tag()))
|
pub async fn unban(ctx: Context<'_>, #[description = "User"] user: User) -> Result<(), Error> {
|
||||||
.field("Error", error, false)
|
respond_moderation(
|
||||||
} else {
|
&ctx,
|
||||||
e.title(format!("Banned {}", member.user.tag()))
|
ModerationKind::Unban(ban_moderation(&ctx, BanKind::Unban(user.clone())).await),
|
||||||
.thumbnail(
|
&user,
|
||||||
member
|
)
|
||||||
.avatar_url()
|
.await
|
||||||
.unwrap_or_else(|| member.user.default_avatar_url()),
|
|
||||||
)
|
|
||||||
.field("Reason", reason, false)
|
|
||||||
}
|
|
||||||
.color(embed_color)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
use std::cmp;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use mongodb::options::FindOptions;
|
use mongodb::options::FindOptions;
|
||||||
use poise::serenity_prelude::Http;
|
use poise::serenity_prelude::{Http, User};
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use tracing::{debug, error, trace};
|
use tracing::{debug, error, trace};
|
||||||
|
|
||||||
@ -9,13 +10,18 @@ use super::bot::get_data_lock;
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::db::database::Database;
|
use crate::db::database::Database;
|
||||||
use crate::db::model::Muted;
|
use crate::db::model::Muted;
|
||||||
|
use crate::serenity::SerenityError;
|
||||||
use crate::{Context, Error};
|
use crate::{Context, Error};
|
||||||
|
|
||||||
pub enum ModerationKind {
|
pub enum ModerationKind {
|
||||||
Mute(String, String, Option<Error>), // Reason, Expires, Error
|
Mute(String, String, Option<Error>), // Reason, Expires, Error
|
||||||
Unmute(Option<Error>), // Error
|
Unmute(Option<Error>), // Error
|
||||||
|
Ban(Option<String>, Option<SerenityError>), // Reason, Error
|
||||||
|
Unban(Option<SerenityError>), // Error
|
||||||
|
}
|
||||||
|
pub enum BanKind {
|
||||||
|
Ban(User, Option<u8>, Option<String>), // User, Amount of days to delete messages, Reason
|
||||||
|
Unban(User), // User
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn mute_on_join(ctx: &serenity::Context, new_member: &mut serenity::Member) {
|
pub async fn mute_on_join(ctx: &serenity::Context, new_member: &mut serenity::Member) {
|
||||||
let data = get_data_lock(ctx).await;
|
let data = get_data_lock(ctx).await;
|
||||||
let data = data.read().await;
|
let data = data.read().await;
|
||||||
@ -105,17 +111,19 @@ pub fn queue_unmute_member(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn respond_mute_command(
|
// TODO: refactor
|
||||||
|
pub async fn respond_moderation(
|
||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
moderation: ModerationKind,
|
moderation: ModerationKind,
|
||||||
user: &serenity::User,
|
user: &serenity::User,
|
||||||
embed_color: i32,
|
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let tag = user.tag();
|
let tag = user.tag();
|
||||||
let image = user
|
let image = user
|
||||||
.avatar_url()
|
.avatar_url()
|
||||||
.unwrap_or_else(|| user.default_avatar_url());
|
.unwrap_or_else(|| user.default_avatar_url());
|
||||||
|
|
||||||
|
let embed_color = ctx.data().read().await.configuration.general.embed_color;
|
||||||
|
|
||||||
ctx.send(|f| {
|
ctx.send(|f| {
|
||||||
f.embed(|f| {
|
f.embed(|f| {
|
||||||
match moderation {
|
match moderation {
|
||||||
@ -137,6 +145,29 @@ pub async fn respond_mute_command(
|
|||||||
),
|
),
|
||||||
None => f.title(format!("Unmuted {}", tag)),
|
None => f.title(format!("Unmuted {}", tag)),
|
||||||
},
|
},
|
||||||
|
ModerationKind::Ban(reason, error) => {
|
||||||
|
let f = match error {
|
||||||
|
Some(err) => f.title(format!("Failed to ban {}", tag)).field(
|
||||||
|
"Exception",
|
||||||
|
err.to_string(),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
None => f.title(format!("Banned {}", tag)),
|
||||||
|
};
|
||||||
|
if let Some(reason) = reason {
|
||||||
|
f.field("Reason", reason, false)
|
||||||
|
} else {
|
||||||
|
f
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ModerationKind::Unban(error) => match error {
|
||||||
|
Some(err) => f.title(format!("Failed to unban {}", tag)).field(
|
||||||
|
"Exception",
|
||||||
|
err.to_string(),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
None => f.title(format!("Unbanned {}", tag)),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
.color(embed_color)
|
.color(embed_color)
|
||||||
.thumbnail(image)
|
.thumbnail(image)
|
||||||
@ -146,3 +177,37 @@ pub async fn respond_mute_command(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn ban_moderation(ctx: &Context<'_>, kind: BanKind) -> Option<SerenityError> {
|
||||||
|
let guild_id = ctx.guild_id().unwrap().0;
|
||||||
|
let http = &ctx.discord().http;
|
||||||
|
|
||||||
|
match kind {
|
||||||
|
BanKind::Ban(user, dmd, reason) => {
|
||||||
|
let reason = &reason
|
||||||
|
.or_else(|| Some("None specified".to_string()))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let ban_result = http
|
||||||
|
.ban_user(guild_id, user.id.0, cmp::min(dmd.unwrap_or(0), 7), reason)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if let Err(err) = ban_result {
|
||||||
|
error!("Failed to ban user {}: {}", user.id.0, err);
|
||||||
|
Some(err)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
BanKind::Unban(user) => {
|
||||||
|
let unban_result = http.remove_ban(guild_id, user.id.0, None).await;
|
||||||
|
|
||||||
|
if let Err(err) = unban_result {
|
||||||
|
error!("Failed to unban user {}: {}", user.id.0, err);
|
||||||
|
Some(err)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user