feat: ajouter la gestion des boutons pour la commande viewlogs et améliorer le traitement des logs d'audit

This commit is contained in:
Puechberty Arthur
2026-04-10 09:26:28 +02:00
parent e28f9a364f
commit 421c87a441
4 changed files with 83 additions and 34 deletions
+3
View File
@@ -36,6 +36,9 @@ fn parse_owner_component_id(custom_id: &str) -> Option<(&str, u64)> {
let mut parts = custom_id.rsplitn(2, ':'); let mut parts = custom_id.rsplitn(2, ':');
let owner = parts.next()?.parse::<u64>().ok()?; let owner = parts.next()?.parse::<u64>().ok()?;
let action = parts.next()?; let action = parts.next()?;
if !action.starts_with("adv:") {
return None;
}
Some((action, owner)) Some((action, owner))
} }
+18 -11
View File
@@ -8,6 +8,10 @@ use crate::db::DbPoolKey;
const LOGS_PER_PAGE: i64 = 10; const LOGS_PER_PAGE: i64 = 10;
fn total_pages(total: i64) -> i64 {
((total + LOGS_PER_PAGE - 1) / LOGS_PER_PAGE).max(1)
}
pub async fn pool(ctx: &Context) -> Option<sqlx::PgPool> { pub async fn pool(ctx: &Context) -> Option<sqlx::PgPool> {
let data = ctx.data.read().await; let data = ctx.data.read().await;
data.get::<DbPoolKey>().cloned() data.get::<DbPoolKey>().cloned()
@@ -51,7 +55,9 @@ pub async fn handle_viewlogs(ctx: &Context, msg: &Message, args: &[&str]) {
.await .await
.unwrap_or(0); .unwrap_or(0);
if page > (total / LOGS_PER_PAGE) + 1 && total > 0 { let total_pages = total_pages(total);
if page > total_pages {
send_embed( send_embed(
ctx, ctx,
msg, msg,
@@ -73,9 +79,7 @@ pub async fn handle_viewlogs(ctx: &Context, msg: &Message, args: &[&str]) {
.title("Logs d'audit") .title("Logs d'audit")
.description(format!( .description(format!(
"Page {}/{} ({} logs total)", "Page {}/{} ({} logs total)",
page, page, total_pages, total
(total / LOGS_PER_PAGE) + if total % LOGS_PER_PAGE > 0 { 1 } else { 0 },
total
)) ))
.color(theme_color(ctx).await); .color(theme_color(ctx).await);
@@ -98,7 +102,6 @@ pub async fn handle_viewlogs(ctx: &Context, msg: &Message, args: &[&str]) {
); );
} }
let total_pages = (total / LOGS_PER_PAGE) + if total % LOGS_PER_PAGE > 0 { 1 } else { 0 };
let mut components = Vec::new(); let mut components = Vec::new();
if total_pages > 1 { if total_pages > 1 {
@@ -139,10 +142,12 @@ pub async fn handle_viewlogs_button(ctx: &Context, component: &ComponentInteract
} }
let direction = parts[1]; let direction = parts[1];
let user_id_str = parts[2]; let Ok(expected_user_id) = parts[2].parse::<u64>() else {
let current_page = parts[3].parse::<i64>().unwrap_or(1); return false;
};
let current_page = parts[3].parse::<i64>().unwrap_or(1).max(1);
if component.user.id.get().to_string() != user_id_str { if component.user.id.get() != expected_user_id {
let _ = component let _ = component
.create_response( .create_response(
&ctx.http, &ctx.http,
@@ -162,7 +167,9 @@ pub async fn handle_viewlogs_button(ctx: &Context, component: &ComponentInteract
_ => current_page, _ => current_page,
}; };
let guild_id = component.guild_id.unwrap_or_else(|| GuildId::new(0)); let Some(guild_id) = component.guild_id else {
return true;
};
let Some(pool) = pool(ctx).await else { let Some(pool) = pool(ctx).await else {
return true; return true;
}; };
@@ -172,8 +179,8 @@ pub async fn handle_viewlogs_button(ctx: &Context, component: &ComponentInteract
.await .await
.unwrap_or(0); .unwrap_or(0);
let total_pages = (total / LOGS_PER_PAGE) + if total % LOGS_PER_PAGE > 0 { 1 } else { 0 }; let total_pages = total_pages(total);
let new_page = new_page.min(total_pages); let new_page = new_page.clamp(1, total_pages);
let offset = (new_page - 1) * LOGS_PER_PAGE; let offset = (new_page - 1) * LOGS_PER_PAGE;
let logs = crate::db::get_audit_logs(&pool, bot_id, guild_id, LOGS_PER_PAGE, offset) let logs = crate::db::get_audit_logs(&pool, bot_id, guild_id, LOGS_PER_PAGE, offset)
+57 -22
View File
@@ -78,7 +78,29 @@ async fn is_nolog_channel(
} }
} }
async fn record_audit_log(
ctx: &Context,
guild_id: GuildId,
log_type: &str,
user_id: Option<UserId>,
channel_id: Option<ChannelId>,
role_id: Option<RoleId>,
action: &str,
) {
let Some(pool) = pool(ctx).await else {
return;
};
let bot_id = ctx.cache.current_user().id;
let _ = crate::db::insert_audit_log(
&pool, bot_id, guild_id, log_type, user_id, channel_id, role_id, None, action, None,
)
.await;
}
pub async fn send_log_embed(ctx: &Context, guild_id: GuildId, log_type: &str, embed: CreateEmbed) { pub async fn send_log_embed(ctx: &Context, guild_id: GuildId, log_type: &str, embed: CreateEmbed) {
record_audit_log(ctx, guild_id, log_type, None, None, None, log_type).await;
if let Some(channel_id) = get_log_channel(ctx, guild_id, log_type).await { if let Some(channel_id) = get_log_channel(ctx, guild_id, log_type).await {
let _ = channel_id let _ = channel_id
.send_message( .send_message(
@@ -99,36 +121,38 @@ pub async fn emit_log(
action: &str, action: &str,
mut embed: CreateEmbed, mut embed: CreateEmbed,
) { ) {
let bot_id = ctx.cache.current_user().id;
let timestamp = Utc::now(); let timestamp = Utc::now();
embed = embed.timestamp(timestamp); embed = embed.timestamp(timestamp);
if let Some(pool) = pool(ctx).await { record_audit_log(ctx, guild_id, log_type, user_id, channel_id, role_id, action).await;
let _ = crate::db::insert_audit_log(
&pool, bot_id, guild_id, log_type, user_id, channel_id, role_id, None, action, None,
)
.await;
}
send_log_embed(ctx, guild_id, log_type, embed).await; if let Some(log_channel_id) = get_log_channel(ctx, guild_id, log_type).await {
} let _ = log_channel_id
pub async fn on_member_join(ctx: &Context, guild_id: GuildId, user: &User) {
if let Some(channel_id) = get_log_channel(ctx, guild_id, "raid").await {
let _ = channel_id
.send_message( .send_message(
&ctx.http, &ctx.http,
serenity::builder::CreateMessage::new().embed( serenity::builder::CreateMessage::new().embed(embed),
CreateEmbed::new().title("RaidLog").description(format!(
"Nouveau membre: <@{}> (`{}`)",
user.id.get(),
user.tag()
)),
),
) )
.await; .await;
} }
}
pub async fn on_member_join(ctx: &Context, guild_id: GuildId, user: &User) {
emit_log(
ctx,
guild_id,
"raid",
Some(user.id),
None,
None,
"join",
CreateEmbed::new().title("RaidLog").description(format!(
"Nouveau membre: <@{}> (`{}`)",
user.id.get(),
user.tag()
)),
)
.await;
run_join_leave_action(ctx, guild_id, "join", user).await; run_join_leave_action(ctx, guild_id, "join", user).await;
} }
@@ -226,7 +250,14 @@ pub async fn send_boost_embed(ctx: &Context, guild_id: GuildId, user: &User) {
.description(description) .description(description)
.color(color); .color(color);
send_log_embed(ctx, guild_id, "boost", embed).await; if let Some(channel_id) = get_log_channel(ctx, guild_id, "boost").await {
let _ = channel_id
.send_message(
&ctx.http,
serenity::builder::CreateMessage::new().embed(embed),
)
.await;
}
} }
pub async fn on_message_deleted( pub async fn on_message_deleted(
@@ -481,10 +512,14 @@ pub async fn log_moderation_command(ctx: &Context, msg: &Message, command: &str,
format!("{} {}", command, args.join(" ")) format!("{} {}", command, args.join(" "))
}; };
send_log_embed( emit_log(
ctx, ctx,
guild_id, guild_id,
"moderation", "moderation",
Some(msg.author.id),
Some(msg.channel_id),
None,
command,
CreateEmbed::new().title("ModLog").description(format!( CreateEmbed::new().title("ModLog").description(format!(
"Modérateur: <@{}>\nCommande: `+{}`", "Modérateur: <@{}>\nCommande: `+{}`",
msg.author.id.get(), msg.author.id.get(),
+5 -1
View File
@@ -3,7 +3,7 @@ use serenity::prelude::*;
use crate::commands::{ use crate::commands::{
advanced_tools, boostembed, help, helpsetting, mp, perms_service, rolemenu, suggestion, advanced_tools, boostembed, help, helpsetting, mp, perms_service, rolemenu, suggestion,
tempvoc, ticket, tempvoc, ticket, viewlogs,
}; };
pub async fn handle_interaction_create(ctx: &Context, interaction: &Interaction) { pub async fn handle_interaction_create(ctx: &Context, interaction: &Interaction) {
@@ -50,6 +50,10 @@ pub async fn handle_interaction_create(ctx: &Context, interaction: &Interaction)
return; return;
} }
if viewlogs::handle_viewlogs_button(ctx, component).await {
return;
}
let _ = advanced_tools::handle_component_interaction(ctx, component).await; let _ = advanced_tools::handle_component_interaction(ctx, component).await;
return; return;
} }