Add p.rh command

This commit is contained in:
2026-04-06 17:11:08 -03:00
parent 5fdea76f37
commit 78fcfe386d
5 changed files with 180 additions and 7 deletions
+115 -3
View File
@@ -1,7 +1,8 @@
use async_trait::async_trait;
use deadpool_redis::redis::AsyncTypedCommands;
use time::UtcDateTime;
use crate::database::models::{UserIncident, UserIncidentType};
use crate::database::models::{Call, UserIncident, UserIncidentType};
use crate::extras::Extras;
use crate::framework::commands::arguments::{
Arg, Argument, ArgumentParsingError, NeedyGreedyString, ParseArguments,
@@ -10,11 +11,11 @@ use crate::framework::commands::context::CommandContext;
use crate::framework::commands::permissions::Permission;
use crate::framework::commands::{Command, CommandError};
use crate::framework::runtime::Runtime;
use crate::groups::moderation::arguments::{DurationArgument, UserArgument};
use crate::groups::moderation::arguments::{ChannelArgument, DurationArgument, UserArgument};
use crate::groups::moderation::get_incident_page;
use crate::groups::moderation::permissions::{BotModeratorPermission, BotOwnerPermission};
use crate::state::State;
use crate::utils::get_random_u64;
use crate::utils::{Bye, get_random_u64};
#[derive(Debug)]
pub struct ModeratorCommand;
@@ -246,3 +247,114 @@ impl Command<State, Extras> for BanCommand {
Ok(())
}
}
#[derive(Debug)]
pub struct RemoteHangupCommand;
#[async_trait]
impl Command<State, Extras> for RemoteHangupCommand {
fn name(&self) -> &'static str {
"remotehangup"
}
fn aliases(&self) -> &'static [&'static str] {
&["rh"]
}
fn permissions(&self) -> Vec<Box<dyn Permission<State, Extras> + Send + Sync + 'static>> {
vec![Box::new(BotModeratorPermission)]
}
fn show_in_help(&self, _rt: &Runtime<State, Extras>, extras: &Extras) -> bool {
extras.user.is_moderator
}
fn arguments(&self) -> &'static [Argument] {
&[Argument {
name: "channel",
is_optional: false,
is_greedy: false,
}]
}
async fn execute(
&self,
ctx: CommandContext<'_, State, Extras>,
args: &str,
) -> Result<(), CommandError> {
let Arg(mut channel) = match Arg::<ChannelArgument>::parse(args, &ctx).await {
Ok(arg) => arg,
Err(e) => match e {
ArgumentParsingError::InvalidArgument => {
ctx.send().content("❌ Channel not found in DB.").await?;
return Ok(());
}
ArgumentParsingError::DatabaseFailed(e) => {
return Err(CommandError::DatabaseFailed(e));
}
e => {
unreachable!("Unexpected error: {e}");
}
},
};
if channel.is_searching {
channel
.cancel_search(&ctx.rt.state.db)
.await
.inspect_err(|e| {
log::error!("Failed to cancel search: {e:?}");
})?;
ctx.send()
.content("The channel was remotely made to stop searching for a call!")
.await?;
return Ok(());
}
if let Some(call_id) = channel.call_id {
let mut redis = ctx.rt.state.redis.get().await?;
let Some(call) = Call::get_by_id(call_id, &ctx.rt.state.db)
.await
.inspect_err(|e| log::error!("Failed to get call: {e:?}"))?
else {
ctx.send().content("❌ The call could not be found.\n-# This is not supposed to happen. The channel is pointing to an ID in the database that does not exist.").await?;
channel.call_id = None;
channel.upsert(&ctx.rt.state.db).await.bye();
redis
.zrem("active-calls", format!("{}:{}", call_id, channel.id))
.await
.bye();
return Err(CommandError::DatabaseInconsistentState);
};
let channel_keys = [
format!("{call_id}:{}", call.channel_ids[0]),
format!("{call_id}:{}", call.channel_ids[1]),
];
redis
.zrem("active-calls", &channel_keys)
.await
.inspect_err(|e| log::error!("Failed to remove inactive call from redis: {e}"))
.ok();
call.hangup(&ctx.rt.state.db)
.await
.inspect_err(|e| log::error!("Failed to hang up call: {e:?}"))?;
} else {
ctx.send()
.content("❌ This channel is not in a call.")
.await?;
return Ok(());
}
Ok(())
}
}