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