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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user