Skip to content

Commit

Permalink
🔊 Get discord logging channels and use them
Browse files Browse the repository at this point in the history
  • Loading branch information
byte-sized-emi committed Dec 28, 2023
1 parent 16278aa commit 4dacbc7
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 36 deletions.
8 changes: 5 additions & 3 deletions src/bot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub type Framework = poise::Framework<Data, Error>;
pub async fn entrypoint(database_pool: Pool<MySql>, redis_client: Client) {
info!("Starting the bot");

let db_clone = database_pool.clone();

let bot_token = match env::var("BOT_TOKEN") {
Ok(val) => val,
Err(_) => {
Expand Down Expand Up @@ -71,16 +73,16 @@ pub async fn entrypoint(database_pool: Pool<MySql>, redis_client: Client) {
.intents(
serenity::GatewayIntents::non_privileged() | serenity::GatewayIntents::MESSAGE_CONTENT,
)
.setup(|_ctx, _ready, _framework| {
.setup(|_ctx, ready, _framework| {
Box::pin(async move {
info!("Logged in as {}", _ready.user.name);
info!("Logged in as {}", ready.user.name);
Ok(Data { database_pool, redis_client })
})
});

let built_framework = framework.build().await.expect("Err building poise client");

logging::install_framework(built_framework.clone());
logging::setup_discord_logging(built_framework.clone(), db_clone).await;

built_framework.start().await.expect("Err running poise client");
}
90 changes: 60 additions & 30 deletions src/logging.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::env;
use std::fs;
use std::num::NonZeroU64;
use std::sync::Arc;
Expand All @@ -7,6 +8,8 @@ use std::sync::OnceLock;
use poise::serenity_prelude::futures::executor::block_on;
use poise::serenity_prelude::ChannelId;
use rolling_file::RollingConditionBasic;
use sqlx::MySql;
use sqlx::Pool;
use tracing::error;
use tracing::info;
use tracing::Level;
Expand All @@ -20,6 +23,7 @@ use tracing_subscriber::reload::Handle;
use tracing_subscriber::Registry;

use crate::bot;
use crate::mysql_lib;

const LOG_FILE_MAX_SIZE_MB: u64 = 10;
const MAX_AMOUNT_LOG_FILES: usize = 10;
Expand All @@ -29,8 +33,6 @@ static DISCORD_LAYER_CHANGE_HANDLE: OnceLock<Handle<DiscordTracingLayer, Registr

/// Returns a WorkerGuard which needs to be dropped at the end of the main function,
/// to ensure the log files get closed.
/// Also returns a Handle to later change the DiscordTracingLayer,
/// for example when the configuration changes or when we create the poise framework.
pub async fn setup_logging() -> WorkerGuard {
// create log dir
fs::create_dir_all("./appdata/logs").expect("Could not create log directory");
Expand All @@ -46,8 +48,7 @@ pub async fn setup_logging() -> WorkerGuard {
.expect("Could not create rolling file appender"),
);

// TODO: Get the guild and channel id's from a proper source
let discord_layer = DiscordTracingLayer::new(0);
let discord_layer = DiscordTracingLayer::new();

let (discord_layer_reloadable, log_reload_handle) = reload::Layer::new(discord_layer);

Expand All @@ -67,33 +68,61 @@ pub async fn setup_logging() -> WorkerGuard {
worker_guard
}

pub fn install_framework(framework: Arc<bot::Framework>) {
let result = DISCORD_LAYER_CHANGE_HANDLE
.get()
.unwrap()
.modify(|discord_layer| {
discord_layer.poise_framework = Some(framework);
});
if let Err(err) = result {
error!(
error = err.to_string(),
"Failed to install poise framework into discord tracing layer"
);
}
/// Panics if called twice
pub async fn setup_discord_logging(framework: Arc<bot::Framework>, db: Pool<MySql>) {
modify_discord_layer(|discord_layer| {
discord_layer.poise_framework = Some(framework.clone());
});

let http = &framework.client().cache_and_http.http;

// Setup main logging guild/channel

let main_guild_id: u64 = env::var("MAIN_GUILD_ID")
.expect("No main logging guild id configured")
.parse()
.expect("Could not parse MAIN_GUILD_ID env variable");

let main_guild = http
.get_channels(main_guild_id)
.await
.expect("Could not get main guild");

let main_logging_channel = main_guild[0].id;

modify_discord_layer(|discord_layer| {
discord_layer.main_log_channel = NonZeroU64::new(main_logging_channel.0);
});

// Setup logging channels per server
let guild_to_log_channel = mysql_lib::get_all_guilds(&db).await.into_iter()
.filter_map(|guild| {
if let Some(logger_pipe_channel) = guild.logger_pipe_channel {
Some((guild.guild_id.0, logger_pipe_channel.0))
} else {
None
}
})
.collect();

modify_discord_layer(|discord_layer| {
discord_layer.guild_to_log_channel = guild_to_log_channel;
});
}

pub fn setup_per_server_logging(guild_to_log_channel: HashMap<u64, u64>) {
let layer_change_handle = DISCORD_LAYER_CHANGE_HANDLE.get().unwrap();
let result =
layer_change_handle.modify(|layer| layer.guild_to_log_channel = guild_to_log_channel);
fn modify_discord_layer(f: impl FnOnce(&mut DiscordTracingLayer)) {
let result = DISCORD_LAYER_CHANGE_HANDLE.get().unwrap().modify(f);

if let Err(err) = result {
error!(
error = err.to_string(),
"Failed to install poise framework into discord tracing layer"
"Something went wrong while trying to modify the discord tracing layer"
);
}
}

#[allow(dead_code)]
/// Panics if called before [`install_framework`]
pub fn add_per_server_logging(guild_id: u64, log_channel_id: u64) {
let layer_change_handle = DISCORD_LAYER_CHANGE_HANDLE.get().unwrap();
let result = layer_change_handle.modify(|layer| {
Expand All @@ -108,16 +137,16 @@ pub fn add_per_server_logging(guild_id: u64, log_channel_id: u64) {
}

struct DiscordTracingLayer {
main_log_channel: u64,
main_log_channel: Option<NonZeroU64>,
poise_framework: Option<Arc<bot::Framework>>,
/// HashMap of GuilId's -> ChannelId's
guild_to_log_channel: HashMap<u64, u64>,
}

impl DiscordTracingLayer {
pub fn new(main_log_channel: u64) -> DiscordTracingLayer {
pub fn new() -> DiscordTracingLayer {
DiscordTracingLayer {
main_log_channel,
main_log_channel: None,
poise_framework: None,
guild_to_log_channel: HashMap::new(),
}
Expand Down Expand Up @@ -151,11 +180,12 @@ where

let http = &poise_framework.client().cache_and_http.http;

let channel_id = ChannelId(self.main_log_channel);

let _ = block_on(
channel_id.send_message(http, |m| m.content(format!("{event_level} {message}"))),
);
if let Some(channel_id) = self.main_log_channel {
let _ = block_on(
ChannelId(channel_id.get())
.send_message(http, |m| m.content(format!("{event_level} {message}"))),
);
}

if let Some(guild_id) = guild_id {
if let Some(channel_id) = self.guild_to_log_channel.get(&guild_id.get()) {
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod logging;

#[tokio::main]
async fn main() {
let _worker_guard = logging::setup_logging().await;
let _log_file_guard = logging::setup_logging().await;

info!("Starting hm-discord-bot");

Expand Down
19 changes: 17 additions & 2 deletions src/mysql_lib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,15 @@ enum Column {

#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct DatabaseGuild {
guild_id: GuildId,
pub guild_id: GuildId,
ghost_warning_deadline: u32,
ghost_kick_deadline: u32,
ghost_time_to_check: Time,
ghost_enabled: bool,
debug_channel: ChannelId,
bot_channel: ChannelId,
help_channel: ChannelId,
logger_pipe_channel: Option<ChannelId>,
pub logger_pipe_channel: Option<ChannelId>,
study_group_category: ChannelId,
subject_group_category: ChannelId,
studenty_role: RoleId,
Expand Down Expand Up @@ -428,6 +428,21 @@ pub async fn get_guild(pool: &Pool<MySql>, guild_id: GuildId) -> Option<Database
}
}

/// Gets the guild information from the Database
#[allow(dead_code)]
pub async fn get_all_guilds(pool: &Pool<MySql>) -> Vec<DatabaseGuild> {
match sqlx::query_as::<_, DatabaseGuild>("SELECT * FROM Guild")
.fetch_all(pool)
.await
{
Ok(val) => val,
Err(err) => {
error!(error = err.to_string(), "Problem executing query");
vec![]
}
}
}

/// Update the Ghost warning deadline (in days), returns if the value was changed
#[allow(dead_code)]
pub async fn update_ghost_warning_deadline(
Expand Down

0 comments on commit 4dacbc7

Please sign in to comment.