feat: add listing logger channels in a guild #11
@ -7,7 +7,8 @@
|
||||
-- them from the database. This operation is noop in Rust and should
|
||||
-- therefore not cost a single CPU cycle.
|
||||
CREATE TABLE IF NOT EXISTS guild_log_channels (
|
||||
guild_id INTEGER PRIMARY KEY,
|
||||
guild_id INTEGER NOT NULL,
|
||||
channel_id INTEGER NOT NULL,
|
||||
UNIQUE(guild_id, channel_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS guild_log_channels_guild_id ON guild_log_channels(guild_id);
|
||||
|
@ -1,7 +1,10 @@
|
||||
#![allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
|
||||
|
||||
use std::env;
|
||||
|
||||
use poise::serenity_prelude::{ChannelId, GuildId};
|
||||
use sqlx::SqlitePool;
|
||||
use tracing::error;
|
||||
|
||||
pub type Result<T> = ::std::result::Result<T, sqlx::Error>;
|
||||
|
||||
@ -22,9 +25,9 @@ impl Database {
|
||||
|
||||
pub async fn get_logging_channel(
|
||||
&self,
|
||||
guild_id: u64,
|
||||
guild_id: GuildId,
|
||||
) -> Result<Vec<u64>> {
|
||||
let guild_id = guild_id as i64;
|
||||
let guild_id = guild_id.0 as i64;
|
||||
let channels = sqlx::query!(
|
||||
r#"
|
||||
SELECT channel_id
|
||||
@ -34,7 +37,11 @@ WHERE guild_id = ?1
|
||||
guild_id
|
||||
)
|
||||
.fetch_all(&self.pool)
|
||||
.await?;
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Error getting logging channels for guild {guild_id}: {e:?}");
|
||||
e
|
||||
})?;
|
||||
Ok(channels.iter().map(|id| id.channel_id as u64).collect())
|
||||
}
|
||||
|
||||
@ -57,6 +64,10 @@ VALUES ( ?1, ?2 )
|
||||
)
|
||||
.execute(&mut *conn)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Error setting channel {channel_id} as logger for guild {guild_id}: {e:?}");
|
||||
e
|
||||
})
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,13 @@ use super::{Context, Error};
|
||||
|
||||
use super::utils::serenity;
|
||||
|
||||
#[allow(clippy::unused_async)]
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
subcommands("add_channel"),
|
||||
subcommands("add_channel", "list_channels"),
|
||||
required_permissions = "ADMINISTRATOR"
|
||||
)]
|
||||
pub async fn logging(_ctx: Context<'_>, _arg: String) -> Result<(), Error> {
|
||||
pub async fn logging(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -18,7 +19,7 @@ pub async fn add_channel(
|
||||
) -> Result<(), Error> {
|
||||
let channel_id = channel.id();
|
||||
let response = match ctx.guild_id() {
|
||||
None => "Error: Could not determine the guild's ID.".to_owned(),
|
||||
None => "Error: Could not determine the guild's ID".to_owned(),
|
||||
Some(guild_id) => {
|
||||
match ctx
|
||||
.data()
|
||||
@ -26,7 +27,7 @@ pub async fn add_channel(
|
||||
.set_logging_channel(guild_id, channel_id)
|
||||
.await
|
||||
{
|
||||
Ok(_) => format!(
|
||||
Ok(()) => format!(
|
||||
"Added channel <#{channel_id}> as a logging channel"
|
||||
),
|
||||
Err(e) => {
|
||||
@ -34,7 +35,7 @@ pub async fn add_channel(
|
||||
if db_error.is_unique_violation() {
|
||||
format!("Channel <#{channel_id}> is already a logging channel")
|
||||
} else {
|
||||
format!("Error: {:?}", e)
|
||||
format!("Error: {e:?}")
|
||||
}
|
||||
} else {
|
||||
format!(
|
||||
@ -48,3 +49,31 @@ pub async fn add_channel(
|
||||
ctx.say(response).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[poise::command(slash_command, aliases("list-channels"))]
|
||||
pub async fn list_channels(ctx: Context<'_>) -> Result<(), Error> {
|
||||
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_channel(guild_id).await {
|
||||
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")
|
||||
)
|
||||
}
|
||||
}
|
||||
Err(e) => format!("Could not retrieve loggers: {e:?}"),
|
||||
}
|
||||
}
|
||||
};
|
||||
ctx.say(response).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -8,9 +8,8 @@ use utils::serenity;
|
||||
use commands::logging;
|
||||
use utils::{BotData, Context, Error};
|
||||
|
||||
pub async fn make_bot() -> color_eyre::Result<FrameworkBuilder<BotData, Error>>
|
||||
{
|
||||
let framework = poise::Framework::builder()
|
||||
pub fn make_bot() -> FrameworkBuilder<BotData, Error> {
|
||||
poise::Framework::builder()
|
||||
.options(poise::FrameworkOptions {
|
||||
commands: vec![logging()],
|
||||
..Default::default()
|
||||
@ -26,6 +25,5 @@ pub async fn make_bot() -> color_eyre::Result<FrameworkBuilder<BotData, Error>>
|
||||
.await?;
|
||||
Ok(BotData::new().await?)
|
||||
})
|
||||
});
|
||||
Ok(framework)
|
||||
})
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![warn(clippy::style, clippy::pedantic)]
|
||||
|
||||
mod utils;
|
||||
mod db;
|
||||
mod discord;
|
||||
@ -10,7 +12,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
color_eyre::install()?;
|
||||
utils::setup_logging();
|
||||
|
||||
let bot = discord::make_bot().await?;
|
||||
let bot = discord::make_bot();
|
||||
bot.run().await?;
|
||||
|
||||
Ok(())
|
||||
|
Loading…
Reference in New Issue
Block a user