Ajout de l'identifiant du message dans la fonction de gestion de mise à jour des messages et amélioration de l'enrichissement des logs pour les messages modifiés et supprimés.

This commit is contained in:
Puechberty Arthur
2026-04-10 19:18:15 +02:00
parent 6110da331d
commit 6a22ea0631
2 changed files with 238 additions and 35 deletions
+1
View File
@@ -62,6 +62,7 @@ pub async fn handle_message_update(
ctx, ctx,
event.guild_id, event.guild_id,
event.channel_id, event.channel_id,
event.id,
author_id, author_id,
before, before,
after, after,
+237 -35
View File
@@ -1,7 +1,7 @@
use std::collections::BTreeSet; use std::collections::BTreeSet;
use chrono::Utc; use chrono::Utc;
use serenity::builder::CreateEmbed; use serenity::builder::{CreateEmbed, CreateEmbedFooter};
use serenity::model::prelude::*; use serenity::model::prelude::*;
use serenity::prelude::*; use serenity::prelude::*;
@@ -98,10 +98,124 @@ async fn record_audit_log(
.await; .await;
} }
fn color_for_log_type(log_type: &str) -> u32 {
match log_type {
"message" => 0xF4C430,
"voice" => 0x3BA55D,
"role" => 0x5865F2,
"channel" => 0x2D7D9A,
"moderation" => 0xED4245,
"raid" => 0xF04747,
"boost" => 0xFF73FA,
_ => 0x99AAB5,
}
}
fn truncate_for_embed(value: &str, max_chars: usize) -> String {
let mut out = String::new();
let mut count = 0usize;
for ch in value.chars() {
if count >= max_chars {
out.push_str("...");
break;
}
out.push(ch);
count += 1;
}
if out.trim().is_empty() {
"(vide)".to_string()
} else {
out
}
}
fn enrich_log_embed(
ctx: &Context,
guild_id: GuildId,
log_type: &str,
action: Option<&str>,
user_id: Option<UserId>,
channel_id: Option<ChannelId>,
role_id: Option<RoleId>,
log_channel_id: Option<ChannelId>,
embed: CreateEmbed,
) -> CreateEmbed {
let now = Utc::now();
let guild_name = ctx
.cache
.guild(guild_id)
.map(|guild| guild.name.clone())
.unwrap_or_else(|| "Serveur inconnu".to_string());
let mut context_lines = Vec::new();
context_lines.push(format!("Type: `{}`", log_type));
if let Some(action) = action {
context_lines.push(format!("Action: `{}`", action));
}
context_lines.push(format!("Serveur: `{}` (`{}`)", guild_name, guild_id.get()));
context_lines.push(format!(
"Canal de log: {}",
log_channel_id
.map(|id| format!("<#{}> (`{}`)", id.get(), id.get()))
.unwrap_or_else(|| "non configure".to_string())
));
if let Some(channel_id) = channel_id {
context_lines.push(format!(
"Canal cible: <#{}> (`{}`)",
channel_id.get(),
channel_id.get()
));
}
if let Some(user_id) = user_id {
context_lines.push(format!(
"Utilisateur cible: <@{}> (`{}`)",
user_id.get(),
user_id.get()
));
}
if let Some(role_id) = role_id {
context_lines.push(format!(
"Role cible: <@&{}> (`{}`)",
role_id.get(),
role_id.get()
));
}
context_lines.push(format!(
"Horodatage: <t:{}:F> (<t:{}:R>)",
now.timestamp(),
now.timestamp()
));
embed
.color(color_for_log_type(log_type))
.timestamp(now)
.field("Contexte", context_lines.join("\n"), false)
.footer(CreateEmbedFooter::new(format!(
"{} • logs {}",
guild_name, log_type
)))
}
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; 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 { let log_channel_id = get_log_channel(ctx, guild_id, log_type).await;
if let Some(channel_id) = log_channel_id {
let embed = enrich_log_embed(
ctx,
guild_id,
log_type,
None,
None,
None,
None,
Some(channel_id),
embed,
);
let _ = channel_id let _ = channel_id
.send_message( .send_message(
&ctx.http, &ctx.http,
@@ -119,18 +233,26 @@ pub async fn emit_log(
channel_id: Option<ChannelId>, channel_id: Option<ChannelId>,
role_id: Option<RoleId>, role_id: Option<RoleId>,
action: &str, action: &str,
mut embed: CreateEmbed, embed: CreateEmbed,
) { ) {
let timestamp = Utc::now();
embed = embed.timestamp(timestamp);
record_audit_log( record_audit_log(
ctx, guild_id, log_type, user_id, channel_id, role_id, action, ctx, guild_id, log_type, user_id, channel_id, role_id, action,
) )
.await; .await;
if let Some(log_channel_id) = get_log_channel(ctx, guild_id, log_type).await { if let Some(log_channel_id) = get_log_channel(ctx, guild_id, log_type).await {
let embed = enrich_log_embed(
ctx,
guild_id,
log_type,
Some(action),
user_id,
channel_id,
role_id,
Some(log_channel_id),
embed,
);
let _ = log_channel_id let _ = log_channel_id
.send_message( .send_message(
&ctx.http, &ctx.http,
@@ -254,6 +376,18 @@ pub async fn send_boost_embed(ctx: &Context, guild_id: GuildId, user: &User) {
.color(color); .color(color);
if let Some(channel_id) = get_log_channel(ctx, guild_id, "boost").await { if let Some(channel_id) = get_log_channel(ctx, guild_id, "boost").await {
let embed = enrich_log_embed(
ctx,
guild_id,
"boost",
Some("boost_custom_embed"),
Some(user.id),
None,
None,
Some(channel_id),
embed,
);
let _ = channel_id let _ = channel_id
.send_message( .send_message(
&ctx.http, &ctx.http,
@@ -278,24 +412,48 @@ pub async fn on_message_deleted(
return; return;
} }
let author = author_id
.map(|id| format!("<@{}> (`{}`)", id.get(), id.get()))
.unwrap_or_else(|| "inconnu".to_string());
let content_value = content.unwrap_or_else(|| "(indisponible)".to_string());
let message_url = format!(
"https://discord.com/channels/{}/{}/{}",
guild_id.get(),
channel_id.get(),
message_id.get()
);
let embed = CreateEmbed::new() let embed = CreateEmbed::new()
.title("Message supprimé") .title("Message supprime")
.description(format!( .description("Un message a ete supprime.")
"Salon: <#{}>\nAuteur: {}\nMessage: `{}`\nContenu: {}", .field("Auteur", author, true)
channel_id.get(), .field(
author_id "Salon",
.map(|id| format!("<@{}>", id.get())) format!("<#{}>\n`{}`", channel_id.get(), channel_id.get()),
.unwrap_or_else(|| "inconnu".to_string()), true,
message_id.get(), )
content.unwrap_or_else(|| "(indisponible)".to_string()) .field("Message ID", format!("`{}`", message_id.get()), true)
)); .field("Lien", format!("[Acces rapide]({})", message_url), false)
send_log_embed(ctx, guild_id, "message", embed).await; .field("Contenu", truncate_for_embed(&content_value, 900), false);
emit_log(
ctx,
guild_id,
"message",
author_id,
Some(channel_id),
None,
"message_delete",
embed,
)
.await;
} }
pub async fn on_message_edited( pub async fn on_message_edited(
ctx: &Context, ctx: &Context,
guild_id: Option<GuildId>, guild_id: Option<GuildId>,
channel_id: ChannelId, channel_id: ChannelId,
message_id: MessageId,
author_id: Option<UserId>, author_id: Option<UserId>,
before: Option<String>, before: Option<String>,
after: Option<String>, after: Option<String>,
@@ -307,19 +465,43 @@ pub async fn on_message_edited(
return; return;
} }
let embed = CreateEmbed::new() let author = author_id
.title("Message édité") .map(|id| format!("<@{}> (`{}`)", id.get(), id.get()))
.description(format!( .unwrap_or_else(|| "inconnu".to_string());
"Salon: <#{}>\nAuteur: {}\nAvant: {}\nAprès: {}", let before_value = before.unwrap_or_else(|| "(indisponible)".to_string());
channel_id.get(), let after_value = after.unwrap_or_else(|| "(indisponible)".to_string());
author_id let message_url = format!(
.map(|id| format!("<@{}>", id.get())) "https://discord.com/channels/{}/{}/{}",
.unwrap_or_else(|| "inconnu".to_string()), guild_id.get(),
before.unwrap_or_else(|| "(indisponible)".to_string()), channel_id.get(),
after.unwrap_or_else(|| "(indisponible)".to_string()) message_id.get()
)); );
send_log_embed(ctx, guild_id, "message", embed).await; let embed = CreateEmbed::new()
.title("Message edite")
.description("Un message a ete modifie.")
.field("Auteur", author, true)
.field(
"Salon",
format!("<#{}>\n`{}`", channel_id.get(), channel_id.get()),
true,
)
.field("Message ID", format!("`{}`", message_id.get()), true)
.field("Lien", format!("[Acces rapide]({})", message_url), false)
.field("Avant", truncate_for_embed(&before_value, 900), false)
.field("Apres", truncate_for_embed(&after_value, 900), false);
emit_log(
ctx,
guild_id,
"message",
author_id,
Some(channel_id),
None,
"message_update",
embed,
)
.await;
} }
pub async fn on_voice_update( pub async fn on_voice_update(
@@ -833,10 +1015,14 @@ pub async fn on_message_delete_bulk(
description.push_str(&format!("\n... et {} autres", hidden)); description.push_str(&format!("\n... et {} autres", hidden));
} }
send_log_embed( emit_log(
ctx, ctx,
guild_id, guild_id,
"message", "message",
None,
Some(channel_id),
None,
"message_delete_bulk",
CreateEmbed::new() CreateEmbed::new()
.title("Suppression en masse") .title("Suppression en masse")
.description(description), .description(description),
@@ -857,10 +1043,14 @@ pub async fn on_reaction_add(ctx: &Context, reaction: &Reaction) {
.map(|id| format!("<@{}>", id.get())) .map(|id| format!("<@{}>", id.get()))
.unwrap_or_else(|| "Inconnu".to_string()); .unwrap_or_else(|| "Inconnu".to_string());
send_log_embed( emit_log(
ctx, ctx,
guild_id, guild_id,
"message", "message",
reaction.user_id,
Some(reaction.channel_id),
None,
"reaction_add",
CreateEmbed::new() CreateEmbed::new()
.title("Reaction ajoutee") .title("Reaction ajoutee")
.description(format!( .description(format!(
@@ -887,10 +1077,14 @@ pub async fn on_reaction_remove(ctx: &Context, reaction: &Reaction) {
.map(|id| format!("<@{}>", id.get())) .map(|id| format!("<@{}>", id.get()))
.unwrap_or_else(|| "Inconnu".to_string()); .unwrap_or_else(|| "Inconnu".to_string());
send_log_embed( emit_log(
ctx, ctx,
guild_id, guild_id,
"message", "message",
reaction.user_id,
Some(reaction.channel_id),
None,
"reaction_remove",
CreateEmbed::new() CreateEmbed::new()
.title("Reaction retiree") .title("Reaction retiree")
.description(format!( .description(format!(
@@ -916,10 +1110,14 @@ pub async fn on_reaction_remove_all(
return; return;
} }
send_log_embed( emit_log(
ctx, ctx,
guild_id, guild_id,
"message", "message",
None,
Some(channel_id),
None,
"reaction_remove_all",
CreateEmbed::new() CreateEmbed::new()
.title("Toutes les reactions retirees") .title("Toutes les reactions retirees")
.description(format!( .description(format!(
@@ -939,10 +1137,14 @@ pub async fn on_reaction_remove_emoji(ctx: &Context, removed_reactions: &Reactio
return; return;
} }
send_log_embed( emit_log(
ctx, ctx,
guild_id, guild_id,
"message", "message",
removed_reactions.user_id,
Some(removed_reactions.channel_id),
None,
"reaction_remove_emoji",
CreateEmbed::new() CreateEmbed::new()
.title("Emoji de reaction retire") .title("Emoji de reaction retire")
.description(format!( .description(format!(