From 7f8aebb1e51651b31a2e3d7922eecdc5a2d268bb Mon Sep 17 00:00:00 2001 From: Max batleforc Date: Mon, 26 May 2025 00:42:51 +0200 Subject: [PATCH] feat: Setup preflight check to be sure that user is admin ++ add event to set activity and get basic data like nbr of guild ++ add ascii art because why the hell not ? --- apps/bot/src/banner.art | 10 +++++ apps/bot/src/bot/event/mod.rs | 29 +++++++++++++ apps/bot/src/bot/helper/mod.rs | 72 +++++++++++++++++++++++++++++++ apps/bot/src/bot/mod.rs | 6 +++ apps/bot/src/bot/trivia/create.rs | 9 +++- apps/bot/src/bot/trivia/list.rs | 9 +++- apps/bot/src/config.rs | 1 + apps/bot/src/main.rs | 1 + resources/config.toml | 1 + 9 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 apps/bot/src/banner.art create mode 100644 apps/bot/src/bot/event/mod.rs create mode 100644 apps/bot/src/bot/helper/mod.rs diff --git a/apps/bot/src/banner.art b/apps/bot/src/banner.art new file mode 100644 index 0000000..bc41500 --- /dev/null +++ b/apps/bot/src/banner.art @@ -0,0 +1,10 @@ + ███▄ ▄███▓ ██▓ ▒█████ ███▄ █ ▓█████ ▒█████ ██▓ ▄▄▄ ██████ +▓██▒▀█▀ ██▒▓██▒▒██▒ ██▒ ██ ▀█ █ ▓█ ▀ ▒██▒ ██▒▓██▒ ▒████▄ ▒██ ▒ +▓██ ▓██░▒██▒▒██░ ██▒▓██ ▀█ ██▒▒███ ▒██░ ██▒▒██░ ▒██ ▀█▄ ░ ▓██▄ +▒██ ▒██ ░██░▒██ ██░▓██▒ ▐▌██▒▒▓█ ▄ ▒██ ██░▒██░ ░██▄▄▄▄██ ▒ ██▒ +▒██▒ ░██▒░██░░ ████▓▒░▒██░ ▓██░░▒████▒░ ████▓▒░░██████▒▓█ ▓██▒▒██████▒▒ +░ ▒░ ░ ░░▓ ░ ▒░▒░▒░ ░ ▒░ ▒ ▒ ░░ ▒░ ░░ ▒░▒░▒░ ░ ▒░▓ ░▒▒ ▓▒█░▒ ▒▓▒ ▒ ░ +░ ░ ░ ▒ ░ ░ ▒ ▒░ ░ ░░ ░ ▒░ ░ ░ ░ ░ ▒ ▒░ ░ ░ ▒ ░ ▒ ▒▒ ░░ ░▒ ░ ░ +░ ░ ▒ ░░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░ ░ ░ + ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ + \ No newline at end of file diff --git a/apps/bot/src/bot/event/mod.rs b/apps/bot/src/bot/event/mod.rs new file mode 100644 index 0000000..74cf5f5 --- /dev/null +++ b/apps/bot/src/bot/event/mod.rs @@ -0,0 +1,29 @@ +use crate::bot::{Data, Error}; +use poise::serenity_prelude::{self as serenity, ActivityData}; +use tracing::info; + +pub async fn event_handler( + ctx: &serenity::Context, + event: &serenity::FullEvent, + _framework: poise::FrameworkContext<'_, Data, Error>, + data: &Data, +) -> Result<(), Error> { + match event { + serenity::FullEvent::Ready { data_about_bot, .. } => { + info!("Logged in as {}", data_about_bot.user.name); + info!("Guilds: {}", data_about_bot.guilds.len()); + ctx.set_activity(Some(ActivityData { + name: data.config.default_status.clone(), + kind: serenity::ActivityType::Playing, + url: None, + state: None, + })); + info!( + "Bot is ready and set to default status: {}", + data.config.default_status + ); + } + _ => {} + } + Ok(()) +} diff --git a/apps/bot/src/bot/helper/mod.rs b/apps/bot/src/bot/helper/mod.rs new file mode 100644 index 0000000..9fec1b4 --- /dev/null +++ b/apps/bot/src/bot/helper/mod.rs @@ -0,0 +1,72 @@ +use clickhouse_pool::traits::Model; +use database::guild::Guild; +use tracing::{info, warn}; + +use crate::bot::{Context, Error}; + +/// Check if the guild has been initialized, if it is check if user is in list of admins +/// If not, check the user's permissions +/// If the user is not allowed dont allow the action +pub async fn is_user_admin_right(ctx: Context<'_>) -> Result { + let guild_id = match ctx.guild_id() { + Some(id) => id.get(), + None => { + ctx.say("This command can only be used in a server.") + .await?; + info!( + "User {} tried to use a guild command outside of a guild.", + ctx.author().id + ); + return Ok(false); + } + }; + + // Check if the user has the required permissions + let users_permissions = match ctx.author_member().await.unwrap().permissions { + Some(permissions) => permissions, + None => { + warn!("User permissions not found for user: {}", ctx.author().id); + return Ok(false); + } + }; + if users_permissions.administrator() + || users_permissions.manage_guild() + || users_permissions.manage_roles() + || users_permissions.manage_channels() + { + info!( + "User {} has admin rights in guild {}.", + ctx.author().id, + guild_id + ); + return Ok(true); + } + + let manager_pool = ctx.data().datalake_config.clone(); + + let fetch_query = Guild::build_select_query(Some(&format!("id = {}", guild_id)), None, None); + let guilds = manager_pool + .execute_select_with_retry::(&fetch_query) + .await?; + if guilds.is_empty() { + warn!("Guild with ID {} not found in database.", guild_id); + return Ok(false); + } + let guild = &guilds[0]; + if guild.enrolled { + if guild.moderator.contains(&ctx.author().id.get()) { + info!( + "User {} is a moderator in guild {}.", + ctx.author().id, + guild_id + ); + return Ok(true); + } + } + info!( + "User {} does not have admin rights in guild {}.", + ctx.author().id, + guild_id + ); + Ok(false) +} diff --git a/apps/bot/src/bot/mod.rs b/apps/bot/src/bot/mod.rs index 95ea02e..0a5e5f7 100644 --- a/apps/bot/src/bot/mod.rs +++ b/apps/bot/src/bot/mod.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use clickhouse_pool::pool_manager::PoolManager; +use event::event_handler; use poise::serenity_prelude::GatewayIntents; use tracing::info; use trivia::trivia; @@ -8,6 +9,8 @@ use utility::{age::age, help::help, server::servers}; use crate::config::Config; +pub mod event; +pub mod helper; pub mod trivia; pub mod utility; @@ -40,6 +43,9 @@ pub async fn start_bot(config: Config, datalake_config: Arc) { prefix: Some(prefix), ..Default::default() }, + event_handler: |ctx, event, framework, data| { + Box::pin(event_handler(ctx, event, framework, data)) + }, ..Default::default() }) .setup(|ctx, _ready, framework| { diff --git a/apps/bot/src/bot/trivia/create.rs b/apps/bot/src/bot/trivia/create.rs index ca543f7..a98d983 100644 --- a/apps/bot/src/bot/trivia/create.rs +++ b/apps/bot/src/bot/trivia/create.rs @@ -1,3 +1,4 @@ +use crate::bot::helper::is_user_admin_right; use crate::bot::{Context, Error}; use clickhouse_pool::traits::Model; use database::trivial::Trivial; @@ -7,7 +8,13 @@ use tracing::{debug, info, instrument}; /// Create a trivia game /// Use the current channel by default, or specify a different channel. #[instrument(name="trivia_create",skip(ctx), level = "info", fields(channel = ctx.channel_id().get(), guild = ?ctx.guild_id().unwrap().get()))] -#[poise::command(prefix_command, slash_command, guild_only, category = "Trivia")] +#[poise::command( + prefix_command, + slash_command, + guild_only, + category = "Trivia", + check = "is_user_admin_right" +)] pub async fn create( ctx: Context<'_>, #[description = "Name of the trivia game"] name: String, diff --git a/apps/bot/src/bot/trivia/list.rs b/apps/bot/src/bot/trivia/list.rs index 9c207d8..c6d730f 100644 --- a/apps/bot/src/bot/trivia/list.rs +++ b/apps/bot/src/bot/trivia/list.rs @@ -1,3 +1,4 @@ +use crate::bot::helper::is_user_admin_right; use crate::bot::{Context, Error}; use clickhouse_pool::traits::Model; use database::trivial::Trivial; @@ -29,7 +30,13 @@ pub fn trivia_list_embed(trivia: &Trivial, current_channel: bool) -> serenity_pr /// List trivia games in the current server and show if there are any in the current channel. #[instrument(name="trivia_list",skip(ctx), level = "info", fields(channel = ctx.channel_id().get(), guild = ?ctx.guild_id().unwrap().get()))] -#[poise::command(prefix_command, slash_command, guild_only, category = "Trivia")] +#[poise::command( + prefix_command, + slash_command, + guild_only, + category = "Trivia", + check = "is_user_admin_right" +)] pub async fn list(ctx: Context<'_>) -> Result<(), Error> { let guild_id = match ctx.guild_id() { Some(id) => id.get(), diff --git a/apps/bot/src/config.rs b/apps/bot/src/config.rs index 5e37d2c..2dcb19e 100644 --- a/apps/bot/src/config.rs +++ b/apps/bot/src/config.rs @@ -33,6 +33,7 @@ pub struct Config { pub prefix: String, pub tracing: Vec, pub persistence: PersistenceConfig, + pub default_status: String, } pub fn parse_local_config() -> Config { diff --git a/apps/bot/src/main.rs b/apps/bot/src/main.rs index f9004e8..5119a4d 100644 --- a/apps/bot/src/main.rs +++ b/apps/bot/src/main.rs @@ -8,6 +8,7 @@ pub mod dotenv; #[tokio::main] async fn main() { + println!(include_str!("banner.art")); let config = parse_local_config(); tool_tracing::init::init_tracing(config.tracing.clone(), config.bot_name.clone()); diff --git a/resources/config.toml b/resources/config.toml index eaa35ce..3c2e9dd 100644 --- a/resources/config.toml +++ b/resources/config.toml @@ -3,6 +3,7 @@ env = "dev-che" port = 5437 token = "" prefix = "!" +default_status = "Cooking some nasty shit !" [persistence] host = "127.0.0.1"