This commit is contained in:
Arthur Puechberty
2026-01-18 15:08:55 +01:00
parent 6de9768e3f
commit 3f1f3ba40d
25 changed files with 1994 additions and 3 deletions
+53
View File
@@ -0,0 +1,53 @@
const { AuditLogEvent, ChannelType } = require('discord.js');
const { sendLog } = require('../fonctions/sendLog');
const CHANNEL_TYPE_NAMES = {
[ChannelType.GuildText]: 'Salon textuel',
[ChannelType.GuildVoice]: 'Salon vocal',
[ChannelType.GuildCategory]: 'Catégorie',
[ChannelType.GuildAnnouncement]: 'Salon d\'annonces',
[ChannelType.GuildStageVoice]: 'Salon de conférence',
[ChannelType.GuildForum]: 'Forum',
[ChannelType.GuildMedia]: 'Salon média'
};
module.exports = {
name: 'channelCreate',
async execute(client, channel) {
if (!channel.guild) return;
let executor = null;
try {
const auditLogs = await channel.guild.fetchAuditLogs({
type: AuditLogEvent.ChannelCreate,
limit: 1
});
const createLog = auditLogs.entries.first();
if (createLog && createLog.target.id === channel.id && (Date.now() - createLog.createdTimestamp) < 5000) {
executor = createLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs channel create:', err);
}
const typeName = CHANNEL_TYPE_NAMES[channel.type] || 'Salon';
const fields = [
{ name: '📁 Nom', value: channel.name, inline: true },
{ name: '🏷️ Type', value: typeName, inline: true }
];
if (channel.parent) {
fields.push({ name: '📂 Catégorie', value: channel.parent.name, inline: true });
}
await sendLog(client, channel.guild.id, 'channels', {
action: 'create',
title: '✅ Salon créé',
description: `Le salon ${channel} a été créé.`,
fields: fields,
executor: executor
});
}
};
+54
View File
@@ -0,0 +1,54 @@
const { AuditLogEvent, ChannelType } = require('discord.js');
const { sendLog } = require('../fonctions/sendLog');
const CHANNEL_TYPE_NAMES = {
[ChannelType.GuildText]: 'Salon textuel',
[ChannelType.GuildVoice]: 'Salon vocal',
[ChannelType.GuildCategory]: 'Catégorie',
[ChannelType.GuildAnnouncement]: 'Salon d\'annonces',
[ChannelType.GuildStageVoice]: 'Salon de conférence',
[ChannelType.GuildForum]: 'Forum',
[ChannelType.GuildMedia]: 'Salon média'
};
module.exports = {
name: 'channelDelete',
async execute(client, channel) {
if (!channel.guild) return;
let executor = null;
try {
const auditLogs = await channel.guild.fetchAuditLogs({
type: AuditLogEvent.ChannelDelete,
limit: 1
});
const deleteLog = auditLogs.entries.first();
if (deleteLog && deleteLog.target.id === channel.id && (Date.now() - deleteLog.createdTimestamp) < 5000) {
executor = deleteLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs channel delete:', err);
}
const typeName = CHANNEL_TYPE_NAMES[channel.type] || 'Salon';
const fields = [
{ name: '📁 Nom', value: channel.name, inline: true },
{ name: '🏷️ Type', value: typeName, inline: true },
{ name: '🆔 ID', value: channel.id, inline: true }
];
if (channel.parent) {
fields.push({ name: '📂 Catégorie', value: channel.parent.name, inline: true });
}
await sendLog(client, channel.guild.id, 'channels', {
action: 'delete',
title: '🗑️ Salon supprimé',
description: `Le salon **#${channel.name}** a été supprimé.`,
fields: fields,
executor: executor
});
}
};
+77
View File
@@ -0,0 +1,77 @@
const { AuditLogEvent } = require('discord.js');
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'channelUpdate',
async execute(client, oldChannel, newChannel) {
if (!newChannel.guild) return;
const changes = [];
// Changement de nom
if (oldChannel.name !== newChannel.name) {
changes.push({ name: '📝 Nom', value: `\`${oldChannel.name}\`\`${newChannel.name}\``, inline: false });
}
// Changement de topic (description)
if (oldChannel.topic !== newChannel.topic) {
const oldTopic = oldChannel.topic || '*Aucun*';
const newTopic = newChannel.topic || '*Aucun*';
changes.push({ name: '📄 Description', value: `${oldTopic.substring(0, 100)}${newTopic.substring(0, 100)}`, inline: false });
}
// Changement de catégorie
if (oldChannel.parentId !== newChannel.parentId) {
const oldParent = oldChannel.parent?.name || '*Aucune*';
const newParent = newChannel.parent?.name || '*Aucune*';
changes.push({ name: '📂 Catégorie', value: `${oldParent}${newParent}`, inline: false });
}
// Changement de slowmode
if (oldChannel.rateLimitPerUser !== newChannel.rateLimitPerUser) {
const formatSlowmode = (seconds) => {
if (seconds === 0) return 'Désactivé';
if (seconds < 60) return `${seconds}s`;
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
return `${Math.floor(seconds / 3600)}h`;
};
changes.push({
name: '🐌 Slowmode',
value: `${formatSlowmode(oldChannel.rateLimitPerUser)}${formatSlowmode(newChannel.rateLimitPerUser)}`,
inline: true
});
}
// Changement NSFW
if (oldChannel.nsfw !== newChannel.nsfw) {
changes.push({ name: '🔞 NSFW', value: `${oldChannel.nsfw ? 'Oui' : 'Non'}${newChannel.nsfw ? 'Oui' : 'Non'}`, inline: true });
}
// Si aucun changement détecté, ignorer
if (changes.length === 0) return;
let executor = null;
try {
const auditLogs = await newChannel.guild.fetchAuditLogs({
type: AuditLogEvent.ChannelUpdate,
limit: 1
});
const updateLog = auditLogs.entries.first();
if (updateLog && updateLog.target.id === newChannel.id && (Date.now() - updateLog.createdTimestamp) < 5000) {
executor = updateLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs channel update:', err);
}
await sendLog(client, newChannel.guild.id, 'channels', {
action: 'update',
title: '✏️ Salon modifié',
description: `Le salon ${newChannel} a été modifié.`,
fields: changes,
executor: executor
});
}
};
+41
View File
@@ -0,0 +1,41 @@
const { AuditLogEvent } = require('discord.js');
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'guildBanAdd',
async execute(client, ban) {
const { guild, user } = ban;
// Essayer de récupérer l'exécuteur depuis les audit logs
let executor = null;
let reason = 'Aucune raison spécifiée';
try {
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.MemberBan,
limit: 1
});
const banLog = auditLogs.entries.first();
if (banLog && banLog.target.id === user.id && (Date.now() - banLog.createdTimestamp) < 5000) {
executor = banLog.executor;
reason = banLog.reason || reason;
}
} catch (err) {
console.error('Erreur récupération audit logs ban:', err);
}
await sendLog(client, guild.id, 'moderation', {
action: 'ban',
title: '🔨 Membre banni',
description: `**${user.tag}** a été banni du serveur.`,
fields: [
{ name: '👤 Utilisateur', value: `${user} (${user.id})`, inline: true },
{ name: '📝 Raison', value: reason, inline: false }
],
thumbnail: user.displayAvatarURL({ size: 128 }),
user: user,
executor: executor
});
}
};
+38
View File
@@ -0,0 +1,38 @@
const { AuditLogEvent } = require('discord.js');
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'guildBanRemove',
async execute(client, ban) {
const { guild, user } = ban;
// Essayer de récupérer l'exécuteur depuis les audit logs
let executor = null;
try {
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.MemberBanRemove,
limit: 1
});
const unbanLog = auditLogs.entries.first();
if (unbanLog && unbanLog.target.id === user.id && (Date.now() - unbanLog.createdTimestamp) < 5000) {
executor = unbanLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs unban:', err);
}
await sendLog(client, guild.id, 'moderation', {
action: 'unban',
title: '🔓 Membre débanni',
description: `**${user.tag}** a été débanni du serveur.`,
fields: [
{ name: '👤 Utilisateur', value: `${user} (${user.id})`, inline: true }
],
thumbnail: user.displayAvatarURL({ size: 128 }),
user: user,
executor: executor
});
}
};
+26
View File
@@ -1,9 +1,33 @@
const { Events, EmbedBuilder } = require("discord.js");
const db = require("../db");
const { sendLog } = require("../fonctions/sendLog");
module.exports = {
name: Events.GuildMemberAdd,
async execute(client, member) {
// ===== LOG MEMBRE REJOINT =====
const accountAge = Math.floor((Date.now() - member.user.createdTimestamp) / (1000 * 60 * 60 * 24));
const accountAgeStr = accountAge < 1 ? 'Moins d\'un jour' :
accountAge < 7 ? `${accountAge} jours ⚠️` :
accountAge < 30 ? `${accountAge} jours` :
accountAge < 365 ? `${Math.floor(accountAge / 30)} mois` :
`${Math.floor(accountAge / 365)} ans`;
await sendLog(client, member.guild.id, 'members', {
action: 'join',
title: '📥 Membre rejoint',
description: `**${member.user.tag}** a rejoint le serveur.`,
fields: [
{ name: '👤 Membre', value: `${member} (${member.user.tag})`, inline: true },
{ name: '📊 Membres', value: `${member.guild.memberCount}`, inline: true },
{ name: '📅 Compte créé', value: `<t:${Math.floor(member.user.createdTimestamp / 1000)}:R>`, inline: true },
{ name: '⏳ Âge du compte', value: accountAgeStr, inline: true }
],
thumbnail: member.user.displayAvatarURL({ size: 128 }),
user: member.user
});
// ===== MESSAGE DE BIENVENUE =====
db.get(
"SELECT enabled, channel_id, message FROM welcome_config WHERE guild_id = ?",
[member.guild.id],
@@ -31,6 +55,8 @@ module.exports = {
}
}
);
// ===== AUTOROLE =====
db.get(
"SELECT enabled, role_id FROM autorole_newuser_config WHERE guild_id = ?",
[member.guild.id],
+57 -1
View File
@@ -1,9 +1,65 @@
const { Events, EmbedBuilder } = require("discord.js");
const { Events, EmbedBuilder, AuditLogEvent } = require("discord.js");
const db = require("../db");
const { sendLog } = require("../fonctions/sendLog");
module.exports = {
name: Events.GuildMemberRemove,
async execute(client, member) {
// ===== VÉRIFIER SI C'EST UN KICK =====
let wasKicked = false;
let kickExecutor = null;
let kickReason = null;
try {
const auditLogs = await member.guild.fetchAuditLogs({
type: AuditLogEvent.MemberKick,
limit: 1
});
const kickLog = auditLogs.entries.first();
if (kickLog && kickLog.target.id === member.id && (Date.now() - kickLog.createdTimestamp) < 5000) {
wasKicked = true;
kickExecutor = kickLog.executor;
kickReason = kickLog.reason || 'Aucune raison spécifiée';
}
} catch (err) {
// Pas de permission audit logs
}
if (wasKicked) {
// ===== LOG KICK =====
await sendLog(client, member.guild.id, 'moderation', {
action: 'kick',
title: '👢 Membre expulsé',
description: `**${member.user.tag}** a été expulsé du serveur.`,
fields: [
{ name: '👤 Membre', value: `${member.user} (${member.user.tag})`, inline: true },
{ name: '📝 Raison', value: kickReason, inline: false }
],
thumbnail: member.user.displayAvatarURL({ size: 128 }),
user: member.user,
executor: kickExecutor
});
} else {
// ===== LOG MEMBRE PARTI =====
const joinedAt = member.joinedTimestamp ?
`<t:${Math.floor(member.joinedTimestamp / 1000)}:R>` : 'Inconnu';
await sendLog(client, member.guild.id, 'members', {
action: 'leave',
title: '📤 Membre parti',
description: `**${member.user.tag}** a quitté le serveur.`,
fields: [
{ name: '👤 Membre', value: `${member.user} (${member.user.tag})`, inline: true },
{ name: '📊 Membres', value: `${member.guild.memberCount}`, inline: true },
{ name: '📅 Avait rejoint', value: joinedAt, inline: true }
],
thumbnail: member.user.displayAvatarURL({ size: 128 }),
user: member.user
});
}
// ===== MESSAGE D'AU REVOIR =====
db.get(
"SELECT enabled, channel_id, message FROM goodbye_config WHERE guild_id = ?",
[member.guild.id],
+180
View File
@@ -0,0 +1,180 @@
const { AuditLogEvent } = require('discord.js');
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'guildMemberUpdate',
async execute(client, oldMember, newMember) {
const guild = newMember.guild;
// Vérifier les changements de rôles
const oldRoles = oldMember.roles.cache;
const newRoles = newMember.roles.cache;
const addedRoles = newRoles.filter(role => !oldRoles.has(role.id));
const removedRoles = oldRoles.filter(role => !newRoles.has(role.id));
// Log des rôles ajoutés
if (addedRoles.size > 0) {
let executor = null;
try {
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.MemberRoleUpdate,
limit: 1
});
const roleLog = auditLogs.entries.first();
if (roleLog && roleLog.target.id === newMember.id && (Date.now() - roleLog.createdTimestamp) < 5000) {
executor = roleLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs role:', err);
}
await sendLog(client, guild.id, 'members', {
action: 'add',
title: '✅ Rôle(s) ajouté(s)',
description: `**${newMember.user.tag}** a reçu de nouveaux rôles.`,
fields: [
{ name: '👤 Membre', value: `${newMember} (${newMember.user.tag})`, inline: true },
{ name: '🎭 Rôle(s)', value: addedRoles.map(r => r.toString()).join(', '), inline: false }
],
thumbnail: newMember.user.displayAvatarURL({ size: 128 }),
user: newMember.user,
executor: executor
});
}
// Log des rôles retirés
if (removedRoles.size > 0) {
let executor = null;
try {
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.MemberRoleUpdate,
limit: 1
});
const roleLog = auditLogs.entries.first();
if (roleLog && roleLog.target.id === newMember.id && (Date.now() - roleLog.createdTimestamp) < 5000) {
executor = roleLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs role:', err);
}
await sendLog(client, guild.id, 'members', {
action: 'remove',
title: '❌ Rôle(s) retiré(s)',
description: `**${newMember.user.tag}** a perdu des rôles.`,
fields: [
{ name: '👤 Membre', value: `${newMember} (${newMember.user.tag})`, inline: true },
{ name: '🎭 Rôle(s)', value: removedRoles.map(r => r.toString()).join(', '), inline: false }
],
thumbnail: newMember.user.displayAvatarURL({ size: 128 }),
user: newMember.user,
executor: executor
});
}
// Vérifier les changements de pseudo
if (oldMember.nickname !== newMember.nickname) {
let executor = null;
try {
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.MemberUpdate,
limit: 1
});
const nicknameLog = auditLogs.entries.first();
if (nicknameLog && nicknameLog.target.id === newMember.id && (Date.now() - nicknameLog.createdTimestamp) < 5000) {
executor = nicknameLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs nickname:', err);
}
await sendLog(client, guild.id, 'members', {
action: 'change',
title: '📝 Pseudo modifié',
fields: [
{ name: '👤 Membre', value: `${newMember} (${newMember.user.tag})`, inline: true },
{ name: '📝 Ancien pseudo', value: oldMember.nickname || '*Aucun*', inline: true },
{ name: '📝 Nouveau pseudo', value: newMember.nickname || '*Aucun*', inline: true }
],
thumbnail: newMember.user.displayAvatarURL({ size: 128 }),
user: newMember.user,
executor: executor
});
}
// Vérifier les timeouts
const oldTimeout = oldMember.communicationDisabledUntil;
const newTimeout = newMember.communicationDisabledUntil;
if (!oldTimeout && newTimeout) {
// Membre mis en timeout
let executor = null;
let reason = 'Aucune raison spécifiée';
try {
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.MemberUpdate,
limit: 1
});
const timeoutLog = auditLogs.entries.first();
if (timeoutLog && timeoutLog.target.id === newMember.id && (Date.now() - timeoutLog.createdTimestamp) < 5000) {
executor = timeoutLog.executor;
reason = timeoutLog.reason || reason;
}
} catch (err) {
console.error('Erreur récupération audit logs timeout:', err);
}
await sendLog(client, guild.id, 'moderation', {
action: 'timeout',
title: '⏰ Membre mis en timeout',
description: `**${newMember.user.tag}** a été mis en timeout.`,
fields: [
{ name: '👤 Membre', value: `${newMember} (${newMember.user.tag})`, inline: true },
{ name: '⏱️ Expire', value: `<t:${Math.floor(newTimeout.getTime() / 1000)}:R>`, inline: true },
{ name: '📝 Raison', value: reason, inline: false }
],
thumbnail: newMember.user.displayAvatarURL({ size: 128 }),
user: newMember.user,
executor: executor
});
} else if (oldTimeout && !newTimeout) {
// Timeout retiré
let executor = null;
try {
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.MemberUpdate,
limit: 1
});
const timeoutLog = auditLogs.entries.first();
if (timeoutLog && timeoutLog.target.id === newMember.id && (Date.now() - timeoutLog.createdTimestamp) < 5000) {
executor = timeoutLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs untimeout:', err);
}
await sendLog(client, guild.id, 'moderation', {
action: 'untimeout',
title: '✅ Timeout retiré',
description: `Le timeout de **${newMember.user.tag}** a été retiré.`,
fields: [
{ name: '👤 Membre', value: `${newMember} (${newMember.user.tag})`, inline: true }
],
thumbnail: newMember.user.displayAvatarURL({ size: 128 }),
user: newMember.user,
executor: executor
});
}
}
};
+101
View File
@@ -0,0 +1,101 @@
const { AuditLogEvent } = require('discord.js');
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'guildUpdate',
async execute(client, oldGuild, newGuild) {
const changes = [];
// Changement de nom
if (oldGuild.name !== newGuild.name) {
changes.push({ name: '📝 Nom', value: `\`${oldGuild.name}\`\`${newGuild.name}\``, inline: false });
}
// Changement d'icône
if (oldGuild.icon !== newGuild.icon) {
changes.push({ name: '🖼️ Icône', value: 'L\'icône du serveur a été modifiée', inline: false });
}
// Changement de bannière
if (oldGuild.banner !== newGuild.banner) {
changes.push({ name: '🎨 Bannière', value: 'La bannière du serveur a été modifiée', inline: false });
}
// Changement de description
if (oldGuild.description !== newGuild.description) {
const oldDesc = oldGuild.description || '*Aucune*';
const newDesc = newGuild.description || '*Aucune*';
changes.push({ name: '📄 Description', value: `${oldDesc.substring(0, 100)}${newDesc.substring(0, 100)}`, inline: false });
}
// Changement de région/locale
if (oldGuild.preferredLocale !== newGuild.preferredLocale) {
changes.push({ name: '🌍 Langue', value: `${oldGuild.preferredLocale}${newGuild.preferredLocale}`, inline: true });
}
// Changement du salon AFK
if (oldGuild.afkChannelId !== newGuild.afkChannelId) {
const oldChannel = oldGuild.afkChannel?.name || '*Aucun*';
const newChannel = newGuild.afkChannel?.name || '*Aucun*';
changes.push({ name: '💤 Salon AFK', value: `${oldChannel}${newChannel}`, inline: true });
}
// Changement du timeout AFK
if (oldGuild.afkTimeout !== newGuild.afkTimeout) {
const formatTimeout = (seconds) => `${Math.floor(seconds / 60)} minutes`;
changes.push({ name: '⏰ Timeout AFK', value: `${formatTimeout(oldGuild.afkTimeout)}${formatTimeout(newGuild.afkTimeout)}`, inline: true });
}
// Changement du niveau de vérification
if (oldGuild.verificationLevel !== newGuild.verificationLevel) {
const levels = ['Aucun', 'Faible', 'Moyen', 'Élevé', 'Très élevé'];
changes.push({ name: '🛡️ Niveau de vérification', value: `${levels[oldGuild.verificationLevel]}${levels[newGuild.verificationLevel]}`, inline: true });
}
// Changement du filtre de contenu explicite
if (oldGuild.explicitContentFilter !== newGuild.explicitContentFilter) {
const filters = ['Désactivé', 'Membres sans rôle', 'Tous les membres'];
changes.push({ name: '🔞 Filtre de contenu', value: `${filters[oldGuild.explicitContentFilter]}${filters[newGuild.explicitContentFilter]}`, inline: true });
}
// Changement du salon système
if (oldGuild.systemChannelId !== newGuild.systemChannelId) {
const oldChannel = oldGuild.systemChannel?.name || '*Aucun*';
const newChannel = newGuild.systemChannel?.name || '*Aucun*';
changes.push({ name: '📢 Salon système', value: `#${oldChannel} → #${newChannel}`, inline: true });
}
// Changement du propriétaire
if (oldGuild.ownerId !== newGuild.ownerId) {
changes.push({ name: '👑 Propriétaire', value: `<@${oldGuild.ownerId}> → <@${newGuild.ownerId}>`, inline: false });
}
// Si aucun changement détecté, ignorer
if (changes.length === 0) return;
let executor = null;
try {
const auditLogs = await newGuild.fetchAuditLogs({
type: AuditLogEvent.GuildUpdate,
limit: 1
});
const updateLog = auditLogs.entries.first();
if (updateLog && (Date.now() - updateLog.createdTimestamp) < 5000) {
executor = updateLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs guild update:', err);
}
await sendLog(client, newGuild.id, 'server', {
action: 'update',
title: '⚙️ Serveur modifié',
description: `Les paramètres du serveur ont été modifiés.`,
fields: changes,
thumbnail: newGuild.iconURL({ size: 128 }),
executor: executor
});
}
};
+41
View File
@@ -0,0 +1,41 @@
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'inviteCreate',
async execute(client, invite) {
if (!invite.guild) return;
const fields = [
{ name: '🔗 Code', value: invite.code, inline: true },
{ name: '📁 Salon', value: invite.channel ? `${invite.channel} (#${invite.channel.name})` : 'Inconnu', inline: true }
];
if (invite.maxUses) {
fields.push({ name: '🔢 Utilisations max', value: invite.maxUses.toString(), inline: true });
}
if (invite.maxAge) {
const hours = Math.floor(invite.maxAge / 3600);
const minutes = Math.floor((invite.maxAge % 3600) / 60);
let expiration = '';
if (hours > 0) expiration += `${hours}h `;
if (minutes > 0) expiration += `${minutes}m`;
if (!expiration) expiration = 'Jamais';
fields.push({ name: '⏰ Expire dans', value: expiration, inline: true });
} else {
fields.push({ name: '⏰ Expiration', value: 'Jamais', inline: true });
}
if (invite.temporary) {
fields.push({ name: '⏳ Temporaire', value: 'Oui (membres expulsés s\'ils quittent)', inline: true });
}
await sendLog(client, invite.guild.id, 'invites', {
action: 'create',
title: '🔗 Invitation créée',
description: `Une nouvelle invitation a été créée: **discord.gg/${invite.code}**`,
fields: fields,
executor: invite.inviter
});
}
};
+42
View File
@@ -0,0 +1,42 @@
const { AuditLogEvent } = require('discord.js');
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'inviteDelete',
async execute(client, invite) {
if (!invite.guild) return;
let executor = null;
try {
const auditLogs = await invite.guild.fetchAuditLogs({
type: AuditLogEvent.InviteDelete,
limit: 1
});
const deleteLog = auditLogs.entries.first();
if (deleteLog && deleteLog.target.code === invite.code && (Date.now() - deleteLog.createdTimestamp) < 5000) {
executor = deleteLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs invite delete:', err);
}
const fields = [
{ name: '🔗 Code', value: invite.code, inline: true },
{ name: '📁 Salon', value: invite.channel ? `#${invite.channel.name}` : 'Inconnu', inline: true }
];
if (invite.uses !== null && invite.uses !== undefined) {
fields.push({ name: '📊 Utilisations', value: invite.uses.toString(), inline: true });
}
await sendLog(client, invite.guild.id, 'invites', {
action: 'delete',
title: '🗑️ Invitation supprimée',
description: `L'invitation **discord.gg/${invite.code}** a été supprimée.`,
fields: fields,
executor: executor
});
}
};
+38
View File
@@ -0,0 +1,38 @@
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'messageDelete',
async execute(client, message) {
// Ignorer les messages du bot et les messages système
if (!message.guild) return;
if (message.author?.bot) return;
if (!message.content && message.attachments.size === 0 && message.embeds.length === 0) return;
const fields = [
{ name: '👤 Auteur', value: message.author ? `${message.author} (${message.author.tag})` : 'Inconnu', inline: true },
{ name: '📁 Salon', value: `${message.channel} (#${message.channel.name})`, inline: true }
];
// Ajouter le contenu du message s'il existe
if (message.content) {
const content = message.content.length > 1024
? message.content.substring(0, 1021) + '...'
: message.content;
fields.push({ name: '💬 Contenu', value: content, inline: false });
}
// Ajouter les pièces jointes
if (message.attachments.size > 0) {
const attachments = message.attachments.map(a => `[${a.name}](${a.url})`).join('\n');
fields.push({ name: '📎 Pièces jointes', value: attachments.substring(0, 1024), inline: false });
}
await sendLog(client, message.guild.id, 'messages', {
action: 'delete',
title: '🗑️ Message supprimé',
fields: fields,
thumbnail: message.author?.displayAvatarURL({ size: 128 }),
user: message.author
});
}
};
+29
View File
@@ -0,0 +1,29 @@
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'messageDeleteBulk',
async execute(client, messages, channel) {
if (!channel.guild) return;
const messageList = messages.map(m => {
const author = m.author ? m.author.tag : 'Inconnu';
const content = m.content
? (m.content.length > 50 ? m.content.substring(0, 47) + '...' : m.content)
: '*Pas de contenu*';
return `**${author}**: ${content}`;
}).slice(0, 10).join('\n');
const additionalCount = messages.size > 10 ? `\n... et ${messages.size - 10} autres messages` : '';
await sendLog(client, channel.guild.id, 'messages', {
action: 'delete',
title: '🗑️ Suppression en masse',
description: `**${messages.size}** messages ont été supprimés dans ${channel}.`,
fields: [
{ name: '📁 Salon', value: `${channel} (#${channel.name})`, inline: true },
{ name: '📊 Nombre', value: `${messages.size} messages`, inline: true },
{ name: '📝 Aperçu', value: (messageList + additionalCount).substring(0, 1024) || '*Aucun aperçu*', inline: false }
]
});
}
};
+38
View File
@@ -0,0 +1,38 @@
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'messageUpdate',
async execute(client, oldMessage, newMessage) {
// Ignorer si pas de guild ou si c'est un bot
if (!newMessage.guild) return;
if (newMessage.author?.bot) return;
// Ignorer si le contenu n'a pas changé (peut être un embed qui se charge)
if (oldMessage.content === newMessage.content) return;
// Ignorer les messages vides
if (!oldMessage.content && !newMessage.content) return;
const oldContent = oldMessage.content
? (oldMessage.content.length > 1024 ? oldMessage.content.substring(0, 1021) + '...' : oldMessage.content)
: '*Message vide ou non caché*';
const newContent = newMessage.content
? (newMessage.content.length > 1024 ? newMessage.content.substring(0, 1021) + '...' : newMessage.content)
: '*Message vide*';
await sendLog(client, newMessage.guild.id, 'messages', {
action: 'edit',
title: '✏️ Message modifié',
description: `[Aller au message](${newMessage.url})`,
fields: [
{ name: '👤 Auteur', value: `${newMessage.author} (${newMessage.author.tag})`, inline: true },
{ name: '📁 Salon', value: `${newMessage.channel} (#${newMessage.channel.name})`, inline: true },
{ name: '📝 Avant', value: oldContent, inline: false },
{ name: '📝 Après', value: newContent, inline: false }
],
thumbnail: newMessage.author?.displayAvatarURL({ size: 128 }),
user: newMessage.author
});
}
};
+35
View File
@@ -0,0 +1,35 @@
const { AuditLogEvent } = require('discord.js');
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'roleCreate',
async execute(client, role) {
let executor = null;
try {
const auditLogs = await role.guild.fetchAuditLogs({
type: AuditLogEvent.RoleCreate,
limit: 1
});
const createLog = auditLogs.entries.first();
if (createLog && createLog.target.id === role.id && (Date.now() - createLog.createdTimestamp) < 5000) {
executor = createLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs role create:', err);
}
await sendLog(client, role.guild.id, 'roles', {
action: 'create',
title: '✅ Rôle créé',
description: `Le rôle ${role} a été créé.`,
fields: [
{ name: '🎭 Nom', value: role.name, inline: true },
{ name: '🎨 Couleur', value: role.hexColor || '#000000', inline: true },
{ name: '🆔 ID', value: role.id, inline: true }
],
executor: executor
});
}
};
+35
View File
@@ -0,0 +1,35 @@
const { AuditLogEvent } = require('discord.js');
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'roleDelete',
async execute(client, role) {
let executor = null;
try {
const auditLogs = await role.guild.fetchAuditLogs({
type: AuditLogEvent.RoleDelete,
limit: 1
});
const deleteLog = auditLogs.entries.first();
if (deleteLog && deleteLog.target.id === role.id && (Date.now() - deleteLog.createdTimestamp) < 5000) {
executor = deleteLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs role delete:', err);
}
await sendLog(client, role.guild.id, 'roles', {
action: 'delete',
title: '🗑️ Rôle supprimé',
description: `Le rôle **@${role.name}** a été supprimé.`,
fields: [
{ name: '🎭 Nom', value: role.name, inline: true },
{ name: '🎨 Couleur', value: role.hexColor || '#000000', inline: true },
{ name: '🆔 ID', value: role.id, inline: true }
],
executor: executor
});
}
};
+72
View File
@@ -0,0 +1,72 @@
const { AuditLogEvent } = require('discord.js');
const { sendLog } = require('../fonctions/sendLog');
module.exports = {
name: 'roleUpdate',
async execute(client, oldRole, newRole) {
const changes = [];
// Changement de nom
if (oldRole.name !== newRole.name) {
changes.push({ name: '📝 Nom', value: `\`${oldRole.name}\`\`${newRole.name}\``, inline: false });
}
// Changement de couleur
if (oldRole.hexColor !== newRole.hexColor) {
changes.push({ name: '🎨 Couleur', value: `${oldRole.hexColor}${newRole.hexColor}`, inline: true });
}
// Changement hoisted (affiché séparément)
if (oldRole.hoist !== newRole.hoist) {
changes.push({ name: '📊 Affiché séparément', value: `${oldRole.hoist ? 'Oui' : 'Non'}${newRole.hoist ? 'Oui' : 'Non'}`, inline: true });
}
// Changement mentionnable
if (oldRole.mentionable !== newRole.mentionable) {
changes.push({ name: '🔔 Mentionnable', value: `${oldRole.mentionable ? 'Oui' : 'Non'}${newRole.mentionable ? 'Oui' : 'Non'}`, inline: true });
}
// Changement de permissions
if (oldRole.permissions.bitfield !== newRole.permissions.bitfield) {
const oldPerms = oldRole.permissions.toArray();
const newPerms = newRole.permissions.toArray();
const addedPerms = newPerms.filter(p => !oldPerms.includes(p));
const removedPerms = oldPerms.filter(p => !newPerms.includes(p));
if (addedPerms.length > 0) {
changes.push({ name: '✅ Permissions ajoutées', value: addedPerms.slice(0, 10).join(', ') + (addedPerms.length > 10 ? '...' : ''), inline: false });
}
if (removedPerms.length > 0) {
changes.push({ name: '❌ Permissions retirées', value: removedPerms.slice(0, 10).join(', ') + (removedPerms.length > 10 ? '...' : ''), inline: false });
}
}
// Si aucun changement détecté, ignorer
if (changes.length === 0) return;
let executor = null;
try {
const auditLogs = await newRole.guild.fetchAuditLogs({
type: AuditLogEvent.RoleUpdate,
limit: 1
});
const updateLog = auditLogs.entries.first();
if (updateLog && updateLog.target.id === newRole.id && (Date.now() - updateLog.createdTimestamp) < 5000) {
executor = updateLog.executor;
}
} catch (err) {
console.error('Erreur récupération audit logs role update:', err);
}
await sendLog(client, newRole.guild.id, 'roles', {
action: 'update',
title: '✏️ Rôle modifié',
description: `Le rôle ${newRole} a été modifié.`,
fields: changes,
executor: executor
});
}
};
+87
View File
@@ -1,5 +1,6 @@
const { Events, ChannelType, PermissionFlagsBits } = require("discord.js");
const db = require("../db");
const { sendLog } = require("../fonctions/sendLog");
// Store voice join times and intervals for economy
const voiceJoinTimes = new Map(); // guildId_oderId -> timestamp
@@ -11,6 +12,9 @@ module.exports = {
// ===== PRIVATE ROOM (TEMP VOICE CHANNELS) =====
await handlePrivateRoom(client, oldState, newState);
// ===== VOICE LOGS =====
await handleVoiceLogs(client, oldState, newState);
if (newState.member.user.bot) return;
const guildId = newState.guild.id;
@@ -272,3 +276,86 @@ async function trackVoiceTime(guildId, userId, oldState, newState) {
// No action needed, session continues
}
}
// ===== VOICE LOGS =====
async function handleVoiceLogs(client, oldState, newState) {
// Ignorer les bots
if (newState.member?.user?.bot) return;
const guild = newState.guild;
const member = newState.member;
if (!member) return;
// Utilisateur rejoint un salon vocal
if (newState.channelId && !oldState.channelId) {
await sendLog(client, guild.id, 'voice', {
action: 'join',
title: '🔊 Connexion vocale',
description: `**${member.user.tag}** a rejoint un salon vocal.`,
fields: [
{ name: '👤 Membre', value: `${member} (${member.user.tag})`, inline: true },
{ name: '🔊 Salon', value: `${newState.channel}`, inline: true }
],
thumbnail: member.user.displayAvatarURL({ size: 128 }),
user: member.user
});
}
// Utilisateur quitte un salon vocal
else if (!newState.channelId && oldState.channelId) {
await sendLog(client, guild.id, 'voice', {
action: 'leave',
title: '🔇 Déconnexion vocale',
description: `**${member.user.tag}** a quitté un salon vocal.`,
fields: [
{ name: '👤 Membre', value: `${member} (${member.user.tag})`, inline: true },
{ name: '🔊 Salon', value: `${oldState.channel?.name || 'Inconnu'}`, inline: true }
],
thumbnail: member.user.displayAvatarURL({ size: 128 }),
user: member.user
});
}
// Utilisateur change de salon
else if (newState.channelId && oldState.channelId && newState.channelId !== oldState.channelId) {
await sendLog(client, guild.id, 'voice', {
action: 'move',
title: '🔀 Changement de salon',
description: `**${member.user.tag}** a changé de salon vocal.`,
fields: [
{ name: '👤 Membre', value: `${member} (${member.user.tag})`, inline: true },
{ name: '📤 Ancien salon', value: `${oldState.channel?.name || 'Inconnu'}`, inline: true },
{ name: '📥 Nouveau salon', value: `${newState.channel}`, inline: true }
],
thumbnail: member.user.displayAvatarURL({ size: 128 }),
user: member.user
});
}
// Vérifier les changements de mute/deafen serveur
if (oldState.serverMute !== newState.serverMute) {
await sendLog(client, guild.id, 'voice', {
action: newState.serverMute ? 'timeout' : 'untimeout',
title: newState.serverMute ? '🔇 Mute serveur activé' : '🔊 Mute serveur désactivé',
description: `**${member.user.tag}** a été ${newState.serverMute ? 'muté' : 'démuté'} par le serveur.`,
fields: [
{ name: '👤 Membre', value: `${member} (${member.user.tag})`, inline: true },
{ name: '🔊 Salon', value: newState.channel ? `${newState.channel}` : 'N/A', inline: true }
],
thumbnail: member.user.displayAvatarURL({ size: 128 }),
user: member.user
});
}
if (oldState.serverDeaf !== newState.serverDeaf) {
await sendLog(client, guild.id, 'voice', {
action: newState.serverDeaf ? 'timeout' : 'untimeout',
title: newState.serverDeaf ? '🔇 Sourd serveur activé' : '🔊 Sourd serveur désactivé',
description: `**${member.user.tag}** a été rendu ${newState.serverDeaf ? 'sourd' : 'non-sourd'} par le serveur.`,
fields: [
{ name: '👤 Membre', value: `${member} (${member.user.tag})`, inline: true },
{ name: '🔊 Salon', value: newState.channel ? `${newState.channel}` : 'N/A', inline: true }
],
thumbnail: member.user.displayAvatarURL({ size: 128 }),
user: member.user
});
}
}