Add ban command

This commit is contained in:
2025-08-25 19:36:18 -03:00
parent 6d8217ed81
commit e44ab51adf
7 changed files with 189 additions and 27 deletions
+62 -7
View File
@@ -1,4 +1,7 @@
use std::ops::{Deref, DerefMut};
use std::{
ops::{Deref, DerefMut},
time::Duration,
};
use scylla::client::session::Session;
@@ -10,6 +13,7 @@ use crate::{
context::CommandContext,
},
state::State,
utils::split_at_nth_from_end,
};
/// Fetch a user by their ID from the database.
@@ -81,12 +85,13 @@ impl FromArguments<State, Extras> for UserArgument {
args: &'a str,
ctx: &'a CommandContext<'_, State, Extras>,
) -> Result<(Self, &'a str), ArgumentParsingError> {
let user: User;
if !args.is_empty() {
// There's an argument, so that argument is used to find the user.
let user: User;
let (identifier, args) = NeedyString::from_args(args, ctx).await?;
let identifier = identifier.0.trim();
if identifier.starts_with("<@") && identifier.ends_with(">") {
// The argument is a Discord mention.
@@ -108,7 +113,9 @@ impl FromArguments<State, Extras> for UserArgument {
} else {
// The argument is (probably) a username.
let Some(db_user) = User::get_by_name(identifier.0, &ctx.rt.state.db).await? else {
let Some(db_user) =
User::get_by_name(identifier.to_string(), &ctx.rt.state.db).await?
else {
// Check in the message's reply, and if not use the command executor.
user = user_from_reply_or_command_executor(ctx).await?;
@@ -117,12 +124,16 @@ impl FromArguments<State, Extras> for UserArgument {
user = db_user;
}
// Notice that `args` is shadowed above, so this line can't be removed (or else the
// full args will be passed and not just the remaining ones as it should be).
Ok((UserArgument(user), args))
} else {
// Check in the message's reply, and if not use the command executor.
user = user_from_reply_or_command_executor(ctx).await?;
}
let user = user_from_reply_or_command_executor(ctx).await?;
Ok((UserArgument(user), args))
Ok((UserArgument(user), args))
}
}
}
@@ -139,3 +150,47 @@ impl DerefMut for UserArgument {
&mut self.0
}
}
#[derive(Debug, Clone, Copy)]
pub struct DurationArgument(pub Duration);
impl FromArguments<State, Extras> for DurationArgument {
async fn from_args<'a>(
mut args: &'a str,
_ctx: &'a CommandContext<'_, State, Extras>,
) -> Result<(Self, &'a str), ArgumentParsingError> {
let mut i = 1;
let mut finding = None;
while let Some((substring, remaining_args)) = split_at_nth_from_end(args, " ", i) {
if let Ok(duration) = humantime::parse_duration(substring) {
finding = Some(DurationArgument(duration));
args = remaining_args;
break;
}
i += 1;
}
if let Some(duration) = finding {
Ok((duration, args))
} else {
Err(ArgumentParsingError::InvalidArgument)
}
}
}
impl Deref for DurationArgument {
type Target = Duration;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for DurationArgument {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}