p4bl0t/src/discord/commands/logging.rs

140 lines
4.3 KiB
Rust

use super::super::{Context, Result};
use poise::serenity_prelude as serenity;
/// Main command for logging subcommands.
///
/// This command cannot be called on its own and will do nothing by
/// itself.
///
/// # Errors
///
/// This command will never error out, even if its signature says it
/// can.
#[allow(clippy::unused_async)]
#[poise::command(
slash_command,
subcommands("add_channel", "list_channels", "remove_channel"),
required_permissions = "ADMINISTRATOR"
)]
pub async fn logging(_ctx: Context<'_>) -> Result {
Ok(())
}
/// Add a channel as a logger.
///
/// # Errors
///
/// This function will return an error if .
#[poise::command(slash_command)]
async fn add_channel(
ctx: Context<'_>,
#[description = "New logging channel"] channel: serenity::Channel,
) -> Result {
let channel_id = channel.id();
let response = match ctx.guild_id() {
None => "Error: Could not determine the guild's ID".to_owned(),
Some(guild_id) => {
match ctx
.data()
.database
.set_logging_channel(guild_id, channel_id)
.await
{
Ok(()) => format!(
"Added channel <#{channel_id}> as a logging channel"
),
Err(e) => {
if let Some(db_error) = e.as_database_error() {
if db_error.is_unique_violation() {
format!("Channel <#{channel_id}> is already a logging channel")
} else {
format!("Error: {e:?}")
}
} else {
format!(
"Something bad happened with the database: {e:?}"
)
}
}
}
}
};
ctx.say(response).await?;
Ok(())
}
/// List all channels registered as loggers for a guild.
///
/// This will list all channels that are logger channels in the server
/// from which the command was executed.
///
/// # Errors
///
/// This function will return an error if the database returns one.
#[poise::command(slash_command)]
async fn list_channels(ctx: Context<'_>) -> Result {
let response = match ctx.guild_id() {
None => "Error: Could not determine the guild's ID".to_owned(),
Some(guild_id) => {
match ctx.data().database.get_logging_channels(guild_id).await {
Err(e) => format!("Could not retrieve loggers: {e:?}"),
Ok(channels) => {
if channels.is_empty() {
"No channels registered as loggers".to_owned()
} else {
format!(
"Here are the channels currently set as loggers:\n{}",
channels
.iter()
.map(|channel| format!("- <#{channel}>"))
.collect::<Vec<String>>()
.join("\n")
)
}
}
}
}
};
ctx.say(response).await?;
Ok(())
}
/// Remove a channel as a logger in a guild.
///
/// This will remove a channel from the list of logger channels in the
/// guild from which the command was executed. If the channel is not a
/// logger, the bot will still consider unsetting the channel as a
/// logger a success.
///
/// # Errors
///
/// This function will return an error if the database errors.
#[poise::command(slash_command)]
async fn remove_channel(
ctx: Context<'_>,
#[description = "Logger channel to remove"] channel: serenity::Channel,
) -> Result {
let channel_id = channel.id();
let response = match ctx.guild_id() {
None => "Error: Could not determine the guild's ID".to_owned(),
Some(guild_id) => {
match ctx
.data()
.database
.remove_logging_channel(guild_id, channel_id)
.await
{
Ok(()) => {
format!("Removed channel <#{channel_id}> as a logger")
}
Err(e) => {
format!("Could not remove channel as a logger: {e:?}")
}
}
}
};
ctx.say(response).await?;
Ok(())
}