Update
This commit is contained in:
@@ -1,134 +1,119 @@
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { parseDuration, formatDuration, sendLog } = require('../../utils/helpers');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('ban')
|
||||
.setDescription('Bannir un membre du serveur.')
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('Le membre à bannir')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison du bannissement')
|
||||
.setRequired(false))
|
||||
.addStringOption(option =>
|
||||
option.setName('duration')
|
||||
.setDescription('Durée du ban (ex: 1h, 2d, laisser vide pour permanent)')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.BanMembers),
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('ban')
|
||||
.setDescription('Bannir un membre du serveur.')
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('Le membre à bannir')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison du bannissement')
|
||||
.setRequired(false))
|
||||
.addStringOption(option =>
|
||||
option.setName('duration')
|
||||
.setDescription('Durée du ban (ex: 1h, 2d, laisser vide pour permanent)')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.BanMembers),
|
||||
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('target');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
const durationInput = interaction.options.getString('duration');
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('target');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
const durationInput = interaction.options.getString('duration');
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
if (!target) {
|
||||
return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
}
|
||||
if (!target) return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
|
||||
// Vérifier que l'utilisateur peut être banni
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (member) {
|
||||
if (member.roles.highest.position >= interaction.member.roles.highest.position && interaction.guild.ownerId !== interaction.user.id) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas bannir cet utilisateur car il a un rôle supérieur ou égal au tien.' });
|
||||
}
|
||||
if (member.id === interaction.guild.ownerId) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas bannir le propriétaire du serveur.' });
|
||||
}
|
||||
}
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (member) {
|
||||
if (member.roles.highest.position >= interaction.member.roles.highest.position && interaction.guild.ownerId !== interaction.user.id) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas bannir cet utilisateur car il a un rôle supérieur ou égal au tien.' });
|
||||
}
|
||||
if (member.id === interaction.guild.ownerId) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas bannir le propriétaire du serveur.' });
|
||||
}
|
||||
if (!member.bannable) {
|
||||
return interaction.editReply({ content: '❌ Je ne peux pas bannir cet utilisateur (rôle supérieur au mien ?).' });
|
||||
}
|
||||
}
|
||||
|
||||
let type = 'Permanent';
|
||||
let unbanDate = null;
|
||||
let durationText = 'Permanent';
|
||||
let type = 'Permanent';
|
||||
let unbanDate = null;
|
||||
let durationText = 'Permanent';
|
||||
|
||||
if (durationInput) {
|
||||
const { parseDuration, formatDuration } = require('../../utils/helpers');
|
||||
const durationMs = parseDuration(durationInput);
|
||||
if (durationMs) {
|
||||
unbanDate = Date.now() + durationMs;
|
||||
type = 'Temporary';
|
||||
durationText = formatDuration(durationMs);
|
||||
}
|
||||
}
|
||||
if (durationInput) {
|
||||
const durationMs = parseDuration(durationInput);
|
||||
if (durationMs) {
|
||||
unbanDate = Date.now() + durationMs;
|
||||
type = 'Temporary';
|
||||
durationText = formatDuration(durationMs);
|
||||
} else {
|
||||
return interaction.editReply({ content: '❌ Format de durée invalide (ex: 1h, 2d).' });
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Bannissement
|
||||
await interaction.guild.bans.create(target.id, { reason: `Banni par ${interaction.user.tag}: ${reason}` });
|
||||
try {
|
||||
await interaction.guild.bans.create(target.id, { reason: `Banni par ${interaction.user.tag}: ${reason}` });
|
||||
|
||||
// Stockage dans MySQL (bans)
|
||||
await db.query(
|
||||
`INSERT INTO bans (userId, reason, modId, timestamp, type, unbanDate, guildId)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE reason=VALUES(reason), modId=VALUES(modId), timestamp=VALUES(timestamp), type=VALUES(type), unbanDate=VALUES(unbanDate)`,
|
||||
[target.id, reason, interaction.user.id, Date.now(), type, unbanDate, interaction.guild.id]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO bans (userId, reason, modId, timestamp, type, unbanDate, guildId)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE reason=VALUES(reason), modId=VALUES(modId), timestamp=VALUES(timestamp), type=VALUES(type), unbanDate=VALUES(unbanDate)`,
|
||||
[target.id, reason, interaction.user.id, Date.now(), type, unbanDate, interaction.guild.id]
|
||||
);
|
||||
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Bannissement', reason, type, interaction.guild.id, Date.now()]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Bannissement', reason, type, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({ name: target.displayName, iconURL: target.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.ban} Utilisateur Banni`)
|
||||
.setColor(colors.ban)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été banni du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '⏱️ Durée', value: `\`${durationText}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true },
|
||||
{ name: '🏷️ Type', value: `\`${type}\``, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${target.displayName}`,
|
||||
iconURL: target.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.ban} Utilisateur Banni`)
|
||||
.setColor(colors.ban)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été banni du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '⏱️ Durée', value: `\`${durationText}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true },
|
||||
{ name: '🏷️ Type', value: `\`${type}\``, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({ name: interaction.user.displayName, iconURL: interaction.user.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.ban} Bannissement`)
|
||||
.setColor(colors.ban)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été banni du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '⏱️ Durée', value: `\`${durationText}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
// Log dans le canal de logs
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${interaction.user.displayName}`,
|
||||
iconURL: interaction.user.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.ban} Bannissement`)
|
||||
.setColor(colors.ban)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été banni du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '⏱️ Durée', value: `\`${durationText}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors du bannissement:', err);
|
||||
if (err.code === 50013) {
|
||||
await interaction.editReply({ content: '❌ Je n\'ai pas les permissions nécessaires pour bannir cet utilisateur.', ephemeral: true });
|
||||
} else if (err.code === 50035) {
|
||||
await interaction.editReply({ content: '❌ Cet utilisateur est déjà banni.', ephemeral: true });
|
||||
} else {
|
||||
await interaction.editReply({ content: `❌ Échec du bannissement de ${target.tag}: ${err.message}`, ephemeral: true });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
} catch (err) {
|
||||
console.error('Erreur ban:', err);
|
||||
await interaction.editReply({ content: `❌ Erreur: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,115 +1,106 @@
|
||||
const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
|
||||
const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { colors } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('casier')
|
||||
.setDescription('Voir toutes les sanctions d\'un membre.')
|
||||
.addUserOption(option =>
|
||||
option.setName('membre')
|
||||
.setDescription('Le membre dont tu veux voir le casier')
|
||||
.setRequired(true)),
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('casier')
|
||||
.setDescription('Voir toutes les sanctions d\'un membre.')
|
||||
.addUserOption(option =>
|
||||
option.setName('membre')
|
||||
.setDescription('Le membre dont tu veux voir le casier')
|
||||
.setRequired(true)),
|
||||
|
||||
async execute(interaction) {
|
||||
await interaction.deferReply();
|
||||
async execute(interaction) {
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
const member = interaction.options.getUser('membre');
|
||||
const member = interaction.options.getUser('membre');
|
||||
|
||||
try {
|
||||
const [rows] = await db.query(
|
||||
'SELECT * FROM logs WHERE userId = ? AND guildId = ? ORDER BY timestamp DESC',
|
||||
[member.id, interaction.guild.id]
|
||||
);
|
||||
try {
|
||||
const [rows] = await db.query(
|
||||
'SELECT * FROM logs WHERE userId = ? AND guildId = ? ORDER BY timestamp DESC',
|
||||
[member.id, interaction.guild.id]
|
||||
);
|
||||
|
||||
// Filtrer les modifications et révocations (ce ne sont pas des sanctions à afficher)
|
||||
const sanctions = rows.filter(row =>
|
||||
row.action !== 'Modification de sanction' &&
|
||||
row.action !== 'Révocation de sanction' &&
|
||||
row.action !== 'Modification de mute'
|
||||
);
|
||||
const sanctions = rows.filter(row =>
|
||||
row.action !== 'Modification de sanction' &&
|
||||
row.action !== 'Révocation de sanction' &&
|
||||
row.action !== 'Modification de mute'
|
||||
);
|
||||
|
||||
if (!sanctions.length) {
|
||||
return interaction.editReply({ content: `✅ ${member.tag} n'a aucune sanction sur ce serveur.` });
|
||||
}
|
||||
if (!sanctions.length) {
|
||||
return interaction.editReply({ content: `✅ ${member.tag} n'a aucune sanction sur ce serveur.` });
|
||||
}
|
||||
|
||||
// Découpe les sanctions en pages de 10
|
||||
const pages = [];
|
||||
for (let i = 0; i < sanctions.length; i += 10) {
|
||||
pages.push(sanctions.slice(i, i + 10));
|
||||
}
|
||||
const pages = [];
|
||||
for (let i = 0; i < sanctions.length; i += 10) {
|
||||
pages.push(sanctions.slice(i, i + 10));
|
||||
}
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
const embeds = pages.map((page, pageIndex) => {
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${member.displayName}`,
|
||||
iconURL: member.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`📋 Casier Judiciaire - Page ${pageIndex + 1}/${pages.length}`)
|
||||
.setColor(colors.warning)
|
||||
.setThumbnail(member.displayAvatarURL({ dynamic: true, size: 256 }))
|
||||
.setDescription(`**${member.toString()}** • \`${member.tag}\``)
|
||||
.setFooter({ text: `Total: ${sanctions.length} sanction(s) • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
const embeds = pages.map((page, pageIndex) => {
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({ name: member.displayName, iconURL: member.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`📋 Casier Judiciaire - Page ${pageIndex + 1}/${pages.length}`)
|
||||
.setColor(colors.warning)
|
||||
.setThumbnail(member.displayAvatarURL({ dynamic: true, size: 256 }))
|
||||
.setDescription(`**${member.toString()}** • \`${member.tag}\``)
|
||||
.setFooter({ text: `Total: ${sanctions.length} sanction(s) • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
page.forEach((row, index) => {
|
||||
const date = `<t:${Math.floor(row.timestamp / 1000)}:F>`;
|
||||
const actionCapitalized = row.action.charAt(0).toUpperCase() + row.action.slice(1);
|
||||
const guildName = row.guildId
|
||||
? interaction.client.guilds.cache.get(row.guildId)?.name || 'Serveur inconnu'
|
||||
: 'Serveur inconnu';
|
||||
|
||||
// Numéro d'affichage (position dans la liste filtrée, à partir de 1)
|
||||
const displayNumber = index + 1 + pageIndex * 10;
|
||||
page.forEach((row, index) => {
|
||||
const date = `<t:${Math.floor(row.timestamp / 1000)}:F>`;
|
||||
const actionCapitalized = row.action.charAt(0).toUpperCase() + row.action.slice(1);
|
||||
const guildName = row.guildId
|
||||
? interaction.client.guilds.cache.get(row.guildId)?.name || 'Serveur inconnu'
|
||||
: 'Serveur inconnu';
|
||||
|
||||
const displayNumber = index + 1 + pageIndex * 10;
|
||||
|
||||
embed.addFields({
|
||||
name: `#${displayNumber} (ID: \`${row.id}\`) - ${actionCapitalized}`,
|
||||
value: `**Modérateur:** <@${row.modId}> (\`${row.modTag || 'N/A'}\`)\n` +
|
||||
`**Raison:** ${row.reason || '`N/A`'}\n` +
|
||||
`**Serveur:** \`${guildName}\`\n` +
|
||||
`**Date:** ${date}\n` +
|
||||
`**Type:** \`${row.type || 'N/A'}\``,
|
||||
inline: false
|
||||
});
|
||||
});
|
||||
embed.addFields({
|
||||
name: `#${displayNumber} (ID: \`${row.id}\`) - ${actionCapitalized}`,
|
||||
value: `**Modérateur:** <@${row.modId}> (\`${row.modTag || 'N/A'}\`)\n` +
|
||||
`**Raison:** ${row.reason || '`N/A`'}\n` +
|
||||
`**Serveur:** \`${guildName}\`\n` +
|
||||
`**Date:** ${date}\n` +
|
||||
`**Type:** \`${row.type || 'N/A'}\``,
|
||||
inline: false
|
||||
});
|
||||
});
|
||||
|
||||
return embed;
|
||||
});
|
||||
return embed;
|
||||
});
|
||||
|
||||
// Composants pour naviguer
|
||||
const row = new ActionRowBuilder().addComponents(
|
||||
new ButtonBuilder().setCustomId('prev').setLabel('⬅️ Précédent').setStyle(ButtonStyle.Primary).setDisabled(pages.length === 1),
|
||||
new ButtonBuilder().setCustomId('next').setLabel('Suivant ➡️').setStyle(ButtonStyle.Primary).setDisabled(pages.length === 1)
|
||||
);
|
||||
const row = new ActionRowBuilder().addComponents(
|
||||
new ButtonBuilder().setCustomId('prev').setLabel('⬅️ Précédent').setStyle(ButtonStyle.Primary).setDisabled(pages.length === 1),
|
||||
new ButtonBuilder().setCustomId('next').setLabel('Suivant ➡️').setStyle(ButtonStyle.Primary).setDisabled(pages.length === 1)
|
||||
);
|
||||
|
||||
let currentPage = 0;
|
||||
const message = await interaction.editReply({ embeds: [embeds[currentPage]], components: pages.length > 1 ? [row] : [] });
|
||||
let currentPage = 0;
|
||||
const message = await interaction.editReply({ embeds: [embeds[currentPage]], components: pages.length > 1 ? [row] : [] });
|
||||
|
||||
// Collecteur de boutons
|
||||
const collector = message.createMessageComponentCollector({ time: 60_000 });
|
||||
collector.on('collect', async i => {
|
||||
if (i.user.id !== interaction.user.id) {
|
||||
return i.reply({ content: '❌ Ce n\'est pas ton menu !', ephemeral: true });
|
||||
}
|
||||
if (i.customId === 'next') {
|
||||
currentPage = (currentPage + 1) % embeds.length;
|
||||
}
|
||||
if (i.customId === 'prev') {
|
||||
currentPage = (currentPage - 1 + embeds.length) % embeds.length;
|
||||
}
|
||||
const collector = message.createMessageComponentCollector({ time: 60_000 });
|
||||
collector.on('collect', async i => {
|
||||
if (i.user.id !== interaction.user.id) {
|
||||
return i.reply({ content: '❌ Ce n\'est pas ton menu !', flags: MessageFlags.Ephemeral });
|
||||
}
|
||||
if (i.customId === 'next') {
|
||||
currentPage = (currentPage + 1) % embeds.length;
|
||||
}
|
||||
if (i.customId === 'prev') {
|
||||
currentPage = (currentPage - 1 + embeds.length) % embeds.length;
|
||||
}
|
||||
|
||||
await i.update({ embeds: [embeds[currentPage]] });
|
||||
});
|
||||
await i.update({ embeds: [embeds[currentPage]] });
|
||||
});
|
||||
|
||||
collector.on('end', () => {
|
||||
message.edit({ components: [] }).catch(() => null);
|
||||
});
|
||||
collector.on('end', () => {
|
||||
message.edit({ components: [] }).catch(() => null);
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de la récupération du casier:', err);
|
||||
await interaction.editReply({ content: '❌ Une erreur est survenue lors de la récupération du casier.' });
|
||||
}
|
||||
},
|
||||
};
|
||||
} catch (err) {
|
||||
console.error('Erreur casier:', err);
|
||||
await interaction.editReply({ content: '❌ Une erreur est survenue lors de la récupération du casier.' });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,172 +1,149 @@
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { parseDuration, formatDuration } = require('../../utils/helpers');
|
||||
const { parseDuration, formatDuration, sendLog } = require('../../utils/helpers');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('changemute')
|
||||
.setDescription('Changer le temps ou la raison d\'un mute.')
|
||||
.addUserOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('Le membre concerné')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('time')
|
||||
.setDescription('Nouvelle durée du mute (ex: 5m, 1h, 1d)')
|
||||
.setRequired(false))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Nouvelle raison du mute')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('changemute')
|
||||
.setDescription('Changer le temps ou la raison d\'un mute.')
|
||||
.addUserOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('Le membre concerné')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('time')
|
||||
.setDescription('Nouvelle durée du mute (ex: 5m, 1h, 1d)')
|
||||
.setRequired(false))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Nouvelle raison du mute')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('user');
|
||||
const newTime = interaction.options.getString('time');
|
||||
const newReason = interaction.options.getString('reason');
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('user');
|
||||
const newTime = interaction.options.getString('time');
|
||||
const newReason = interaction.options.getString('reason');
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
if (!target) {
|
||||
return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
}
|
||||
if (!target) return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
}
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
|
||||
if (!newTime && !newReason) {
|
||||
return interaction.editReply({ content: '❌ Tu dois spécifier au moins une nouvelle durée ou une nouvelle raison.' });
|
||||
}
|
||||
if (!newTime && !newReason) return interaction.editReply({ content: '❌ Tu dois spécifier au moins une nouvelle durée ou une nouvelle raison.' });
|
||||
|
||||
// Récupérer le mute actuel depuis la DB
|
||||
const [muteRows] = await db.query(
|
||||
'SELECT * FROM mutes WHERE userId = ? AND guildId = ?',
|
||||
[target.id, interaction.guild.id]
|
||||
);
|
||||
const [muteRows] = await db.query(
|
||||
'SELECT * FROM mutes WHERE userId = ? AND guildId = ?',
|
||||
[target.id, interaction.guild.id]
|
||||
);
|
||||
|
||||
if (!muteRows.length && !member.communicationDisabledUntil) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas muté.' });
|
||||
}
|
||||
if (!muteRows.length && (!member.communicationDisabledUntilTimestamp || member.communicationDisabledUntilTimestamp < Date.now())) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas muté.' });
|
||||
}
|
||||
|
||||
const currentMute = muteRows[0];
|
||||
const oldReason = currentMute?.reason || 'N/A';
|
||||
const oldUnmuteDate = currentMute?.unmuteDate || null;
|
||||
const currentMute = muteRows[0];
|
||||
const oldReason = currentMute?.reason || 'N/A';
|
||||
const oldUnmuteDate = currentMute?.unmuteDate || null;
|
||||
|
||||
try {
|
||||
let newUnmuteDate = oldUnmuteDate;
|
||||
let newDurationMs = null;
|
||||
let durationText = 'Non modifié';
|
||||
try {
|
||||
let newUnmuteDate = oldUnmuteDate;
|
||||
let newDurationMs = null;
|
||||
let durationText = 'Non modifié';
|
||||
|
||||
// Si nouvelle durée spécifiée
|
||||
if (newTime) {
|
||||
newDurationMs = parseDuration(newTime);
|
||||
if (!newDurationMs) {
|
||||
return interaction.editReply({ content: '❌ Durée invalide. Utilise un format comme: 5m, 1h, 2d (max 28 jours).' });
|
||||
}
|
||||
if (newTime) {
|
||||
newDurationMs = parseDuration(newTime);
|
||||
if (!newDurationMs) return interaction.editReply({ content: '❌ Durée invalide. Utilise un format comme: 5m, 1h, 2d (max 28 jours).' });
|
||||
|
||||
const maxDuration = 28 * 24 * 60 * 60 * 1000;
|
||||
if (newDurationMs > maxDuration) {
|
||||
return interaction.editReply({ content: '❌ La durée maximum est de 28 jours.' });
|
||||
}
|
||||
const maxDuration = 28 * 24 * 60 * 60 * 1000;
|
||||
if (newDurationMs > maxDuration) return interaction.editReply({ content: '❌ La durée maximum est de 28 jours.' });
|
||||
|
||||
newUnmuteDate = Date.now() + newDurationMs;
|
||||
durationText = formatDuration(newDurationMs);
|
||||
newUnmuteDate = Date.now() + newDurationMs;
|
||||
durationText = formatDuration(newDurationMs);
|
||||
|
||||
// Mettre à jour le timeout
|
||||
const durationSeconds = Math.floor(newDurationMs / 1000);
|
||||
await member.timeout(durationSeconds * 1000, `Mute modifié par ${interaction.user.tag}: ${newReason || oldReason}`);
|
||||
}
|
||||
await member.timeout(newDurationMs, `Mute modifié par ${interaction.user.tag}: ${newReason || oldReason}`);
|
||||
}
|
||||
|
||||
// Mettre à jour la DB
|
||||
const finalReason = newReason || oldReason;
|
||||
const type = newUnmuteDate && newUnmuteDate > Date.now() ? 'Temporary' : 'Permanent';
|
||||
const finalReason = newReason || oldReason;
|
||||
const type = 'Temporary';
|
||||
|
||||
if (currentMute) {
|
||||
await db.query(
|
||||
'UPDATE mutes SET reason = ?, modId = ?, modTag = ?, timestamp = ?, unmuteDate = ?, type = ? WHERE userId = ? AND guildId = ?',
|
||||
[finalReason, interaction.user.id, interaction.user.tag, Date.now(), newUnmuteDate, type, target.id, interaction.guild.id]
|
||||
);
|
||||
} else {
|
||||
await db.query(
|
||||
`INSERT INTO mutes (userId, guildId, reason, modId, modTag, timestamp, unmuteDate, type)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, interaction.guild.id, finalReason, interaction.user.id, interaction.user.tag, Date.now(), newUnmuteDate, type]
|
||||
);
|
||||
}
|
||||
if (currentMute) {
|
||||
await db.query(
|
||||
'UPDATE mutes SET reason = ?, modId = ?, modTag = ?, timestamp = ?, unmuteDate = ?, type = ? WHERE userId = ? AND guildId = ?',
|
||||
[finalReason, interaction.user.id, interaction.user.tag, Date.now(), newUnmuteDate, type, target.id, interaction.guild.id]
|
||||
);
|
||||
} else {
|
||||
await db.query(
|
||||
`INSERT INTO mutes (userId, guildId, reason, modId, modTag, timestamp, unmuteDate, type)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, interaction.guild.id, finalReason, interaction.user.id, interaction.user.tag, Date.now(), newUnmuteDate, type]
|
||||
);
|
||||
}
|
||||
|
||||
// Log dans la DB
|
||||
const changeLog = [];
|
||||
if (newTime) changeLog.push(`Durée: ${formatDuration(newDurationMs)}`);
|
||||
if (newReason) changeLog.push(`Raison: ${oldReason} → ${newReason}`);
|
||||
const changeReason = changeLog.join(', ');
|
||||
const changeLog = [];
|
||||
if (newTime) changeLog.push(`Durée: ${formatDuration(newDurationMs)}`);
|
||||
if (newReason) changeLog.push(`Raison: ${oldReason} → ${newReason}`);
|
||||
const changeReason = changeLog.join(', ');
|
||||
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Modification de mute', changeReason, type, interaction.guild.id, Date.now()]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Modification de mute', changeReason, type, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Mute Modifié`)
|
||||
.setColor(colors.success)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '🔧 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '⏰ Nouvelle durée', value: durationText, inline: true },
|
||||
{ name: '📝 Ancienne raison', value: oldReason, inline: false },
|
||||
{ name: '📝 Nouvelle raison', value: finalReason, inline: false }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id}` })
|
||||
.setTimestamp();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Mute Modifié`)
|
||||
.setColor(colors.success)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '🔧 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '⏰ Nouvelle durée', value: durationText, inline: true },
|
||||
{ name: '📝 Ancienne raison', value: oldReason, inline: false },
|
||||
{ name: '📝 Nouvelle raison', value: finalReason, inline: false }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id}` })
|
||||
.setTimestamp();
|
||||
if (newUnmuteDate) {
|
||||
embed.addFields({ name: '📅 Démute le', value: `<t:${Math.floor(newUnmuteDate / 1000)}:F>`, inline: true });
|
||||
}
|
||||
|
||||
if (newUnmuteDate) {
|
||||
embed.addFields({ name: '📅 Démute le', value: `<t:${Math.floor(newUnmuteDate / 1000)}:F>`, inline: true });
|
||||
}
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
try {
|
||||
const dmEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.info} Ton mute a été modifié`)
|
||||
.setColor(colors.info)
|
||||
.setDescription(`Ton mute sur **${interaction.guild.name}** a été modifié`)
|
||||
.addFields(
|
||||
{ name: '⏰ Durée', value: durationText, inline: true },
|
||||
{ name: '📝 Raison', value: finalReason, inline: false }
|
||||
)
|
||||
.setFooter({ text: interaction.guild.name, iconURL: interaction.guild.iconURL({ dynamic: true }) })
|
||||
.setTimestamp();
|
||||
await target.send({ embeds: [dmEmbed] });
|
||||
} catch { /* DMs fermés */ }
|
||||
|
||||
// Envoyer un message privé à l'utilisateur
|
||||
try {
|
||||
const dmEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.info} Ton mute a été modifié`)
|
||||
.setColor(colors.info)
|
||||
.setDescription(`Ton mute sur **${interaction.guild.name}** a été modifié`)
|
||||
.addFields(
|
||||
{ name: '⏰ Durée', value: durationText, inline: true },
|
||||
{ name: '📝 Raison', value: finalReason, inline: false }
|
||||
)
|
||||
.setFooter({ text: interaction.guild.name, iconURL: interaction.guild.iconURL({ dynamic: true }) })
|
||||
.setTimestamp();
|
||||
await target.send({ embeds: [dmEmbed] });
|
||||
} catch {
|
||||
// L'utilisateur a les DMs fermés, on continue
|
||||
}
|
||||
|
||||
// Log dans le canal de logs
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Modification de Mute`)
|
||||
.setColor(colors.success)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '🔧 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Modifications', value: changeReason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} | Serveur: ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de la modification du mute:', err);
|
||||
await interaction.editReply({ content: `❌ Échec de la modification du mute: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Modification de Mute`)
|
||||
.setColor(colors.success)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '🔧 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Modifications', value: changeReason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} | Serveur: ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur changemute:', err);
|
||||
await interaction.editReply({ content: `❌ Échec de la modification du mute: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,125 +1,114 @@
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('changesanction')
|
||||
.setDescription('Changer la raison d\'une sanction.')
|
||||
.addUserOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('L\'utilisateur concerné')
|
||||
.setRequired(true))
|
||||
.addIntegerOption(option =>
|
||||
option.setName('sanction_id')
|
||||
.setDescription('L\'ID DB de la sanction (visible dans /casier, ex: ID: 123)')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('new_reason')
|
||||
.setDescription('La nouvelle raison')
|
||||
.setRequired(true))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('user');
|
||||
const sanctionId = interaction.options.getInteger('sanction_id');
|
||||
const newReason = interaction.options.getString('new_reason');
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('changesanction')
|
||||
.setDescription('Changer la raison d\'une sanction.')
|
||||
.addUserOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('L\'utilisateur concerné')
|
||||
.setRequired(true))
|
||||
.addIntegerOption(option =>
|
||||
option.setName('sanction_id')
|
||||
.setDescription('L\'ID DB de la sanction (visible dans /casier, ex: ID: 123)')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('new_reason')
|
||||
.setDescription('La nouvelle raison')
|
||||
.setRequired(true))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('user');
|
||||
const sanctionId = interaction.options.getInteger('sanction_id');
|
||||
const newReason = interaction.options.getString('new_reason');
|
||||
|
||||
try {
|
||||
console.log(`[changesanction] Recherche sanction ID: ${sanctionId}, userId: ${target.id}, guildId: ${interaction.guild.id}`);
|
||||
|
||||
// Récupérer directement la sanction par son ID DB (plus stable)
|
||||
const [sanctionRows] = await db.query(
|
||||
'SELECT * FROM logs WHERE id = ? AND userId = ? AND guildId = ?',
|
||||
[sanctionId, target.id, interaction.guild.id]
|
||||
);
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
console.log(`[changesanction] Résultats trouvés: ${sanctionRows.length}`);
|
||||
try {
|
||||
const [sanctionRows] = await db.query(
|
||||
'SELECT * FROM logs WHERE id = ? AND userId = ? AND guildId = ?',
|
||||
[sanctionId, target.id, interaction.guild.id]
|
||||
);
|
||||
|
||||
if (!sanctionRows.length) {
|
||||
// Vérifier si l'ID existe pour cet utilisateur (peut-être mauvais serveur?)
|
||||
const [allUserLogs] = await db.query(
|
||||
'SELECT id, action, guildId FROM logs WHERE id = ? AND userId = ?',
|
||||
[sanctionId, target.id]
|
||||
);
|
||||
|
||||
if (allUserLogs.length > 0) {
|
||||
const log = allUserLogs[0];
|
||||
const guildName = interaction.client.guilds.cache.get(log.guildId)?.name || 'Serveur inconnu';
|
||||
return interaction.editReply({
|
||||
content: `❌ La sanction avec l'ID ${sanctionId} existe, mais elle appartient au serveur "${guildName}" (guildId: ${log.guildId}), pas à "${interaction.guild.name}" (guildId: ${interaction.guild.id}).`
|
||||
});
|
||||
}
|
||||
|
||||
return interaction.editReply({
|
||||
content: `❌ Aucune sanction trouvée avec l'ID ${sanctionId} pour ${target.tag}.\n\n💡 **Astuce:** Utilise l'ID DB visible dans \`/casier\` (ex: \`#1 (ID: 123)\` → utilise \`123\`).`
|
||||
});
|
||||
}
|
||||
if (!sanctionRows.length) {
|
||||
const [allUserLogs] = await db.query(
|
||||
'SELECT id, action, guildId FROM logs WHERE id = ? AND userId = ?',
|
||||
[sanctionId, target.id]
|
||||
);
|
||||
|
||||
if (allUserLogs.length > 0) {
|
||||
const log = allUserLogs[0];
|
||||
const guildName = interaction.client.guilds.cache.get(log.guildId)?.name || 'Serveur inconnu';
|
||||
return interaction.editReply({
|
||||
content: `❌ La sanction avec l'ID ${sanctionId} existe, mais elle appartient au serveur "${guildName}" (guildId: ${log.guildId}), pas à "${interaction.guild.name}" (guildId: ${interaction.guild.id}).`
|
||||
});
|
||||
}
|
||||
|
||||
return interaction.editReply({
|
||||
content: `❌ Aucune sanction trouvée avec l'ID ${sanctionId} pour ${target.tag}.\n\n💡 **Astuce:** Utilise l'ID DB visible dans \`/casier\` (ex: \`#1 (ID: 123)\` → utilise \`123\`).`
|
||||
});
|
||||
}
|
||||
|
||||
const sanction = sanctionRows[0];
|
||||
const sanction = sanctionRows[0];
|
||||
|
||||
// Vérifier que ce n'est pas une modification/révocation
|
||||
if (sanction.action === 'Modification de sanction' ||
|
||||
sanction.action === 'Révocation de sanction' ||
|
||||
sanction.action === 'Modification de mute') {
|
||||
return interaction.editReply({ content: `❌ Cette entrée est une modification, pas une sanction. Utilise l'ID d'une vraie sanction.` });
|
||||
}
|
||||
const oldReason = sanction.reason;
|
||||
if (sanction.action === 'Modification de sanction' ||
|
||||
sanction.action === 'Révocation de sanction' ||
|
||||
sanction.action === 'Modification de mute') {
|
||||
return interaction.editReply({ content: `❌ Cette entrée est une modification, pas une sanction. Utilise l'ID d'une vraie sanction.` });
|
||||
}
|
||||
const oldReason = sanction.reason;
|
||||
|
||||
// Mettre à jour la raison
|
||||
await db.query(
|
||||
'UPDATE logs SET reason = ?, modId = ?, modTag = ? WHERE id = ?',
|
||||
[newReason, interaction.user.id, interaction.user.tag, sanction.id]
|
||||
);
|
||||
await db.query(
|
||||
'UPDATE logs SET reason = ?, modId = ?, modTag = ? WHERE id = ?',
|
||||
[newReason, interaction.user.id, interaction.user.tag, sanction.id]
|
||||
);
|
||||
|
||||
// Log de la modification
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Modification de sanction', `Ancienne raison: ${oldReason} → Nouvelle raison: ${newReason}`, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Modification de sanction', `Ancienne raison: ${oldReason} → Nouvelle raison: ${newReason}`, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Sanction Modifiée`)
|
||||
.setColor(colors.success)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '🔧 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Ancienne raison', value: oldReason || 'N/A', inline: false },
|
||||
{ name: '📝 Nouvelle raison', value: newReason, inline: false },
|
||||
{ name: '🆔 ID Sanction', value: `${sanction.id}`, inline: true },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id}` })
|
||||
.setTimestamp();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Sanction Modifiée`)
|
||||
.setColor(colors.success)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '🔧 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Ancienne raison', value: oldReason || 'N/A', inline: false },
|
||||
{ name: '📝 Nouvelle raison', value: newReason, inline: false },
|
||||
{ name: '🆔 ID Sanction', value: `${sanction.id}`, inline: true },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id}` })
|
||||
.setTimestamp();
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
// Log dans le canal de logs
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Modification de Sanction`)
|
||||
.setColor(colors.success)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '🔧 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Ancienne raison', value: oldReason || 'N/A', inline: false },
|
||||
{ name: '📝 Nouvelle raison', value: newReason, inline: false },
|
||||
{ name: '🆔 ID Sanction', value: `${sanction.id}`, inline: true },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} | Serveur: ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de la modification de la sanction:', err);
|
||||
await interaction.editReply({ content: `❌ Échec de la modification de la sanction: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Modification de Sanction`)
|
||||
.setColor(colors.success)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '🔧 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Ancienne raison', value: oldReason || 'N/A', inline: false },
|
||||
{ name: '📝 Nouvelle raison', value: newReason, inline: false },
|
||||
{ name: '🆔 ID Sanction', value: `${sanction.id}`, inline: true },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} | Serveur: ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur changesanction:', err);
|
||||
await interaction.editReply({ content: `❌ Échec de la modification de la sanction: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,85 +1,74 @@
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('clear')
|
||||
.setDescription('Supprimer plusieurs messages d\'un coup.')
|
||||
.addIntegerOption(option =>
|
||||
option.setName('amount')
|
||||
.setDescription('Nombre de messages à supprimer (1-100)')
|
||||
.setRequired(true)
|
||||
.setMinValue(1)
|
||||
.setMaxValue(100))
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('Supprimer uniquement les messages de cet utilisateur')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('clear')
|
||||
.setDescription('Supprimer plusieurs messages d\'un coup.')
|
||||
.addIntegerOption(option =>
|
||||
option.setName('amount')
|
||||
.setDescription('Nombre de messages à supprimer (1-100)')
|
||||
.setRequired(true)
|
||||
.setMinValue(1)
|
||||
.setMaxValue(100))
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('Supprimer uniquement les messages de cet utilisateur')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
|
||||
|
||||
async execute(interaction) {
|
||||
const amount = interaction.options.getInteger('amount');
|
||||
const target = interaction.options.getUser('target');
|
||||
async execute(interaction) {
|
||||
const amount = interaction.options.getInteger('amount');
|
||||
const target = interaction.options.getUser('target');
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
if (!interaction.channel.isTextBased()) {
|
||||
return interaction.editReply({ content: '❌ Cette commande ne peut être utilisée que dans un canal texte.' });
|
||||
}
|
||||
if (!interaction.channel.isTextBased()) {
|
||||
return interaction.editReply({ content: '❌ Cette commande ne peut être utilisée que dans un canal texte.' });
|
||||
}
|
||||
|
||||
try {
|
||||
const messages = await interaction.channel.messages.fetch({ limit: amount });
|
||||
let messagesToDelete = messages;
|
||||
try {
|
||||
const messages = await interaction.channel.messages.fetch({ limit: amount });
|
||||
let messagesToDelete = messages;
|
||||
|
||||
if (target) {
|
||||
messagesToDelete = messages.filter(msg => msg.author.id === target.id);
|
||||
}
|
||||
if (target) {
|
||||
messagesToDelete = messages.filter(msg => msg.author.id === target.id);
|
||||
}
|
||||
|
||||
// Ne pas supprimer les messages de plus de 14 jours
|
||||
const filteredMessages = messagesToDelete.filter(msg => {
|
||||
const msgAge = Date.now() - msg.createdTimestamp;
|
||||
return msgAge < 14 * 24 * 60 * 60 * 1000;
|
||||
});
|
||||
const filteredMessages = messagesToDelete.filter(msg => {
|
||||
const msgAge = Date.now() - msg.createdTimestamp;
|
||||
return msgAge < 14 * 24 * 60 * 60 * 1000;
|
||||
});
|
||||
|
||||
if (filteredMessages.size === 0) {
|
||||
return interaction.editReply({ content: '❌ Aucun message à supprimer (les messages de plus de 14 jours ne peuvent pas être supprimés).' });
|
||||
}
|
||||
if (filteredMessages.size === 0) {
|
||||
return interaction.editReply({ content: '❌ Aucun message à supprimer (les messages de plus de 14 jours ne peuvent pas être supprimés).' });
|
||||
}
|
||||
|
||||
await interaction.channel.bulkDelete(filteredMessages, true);
|
||||
await interaction.channel.bulkDelete(filteredMessages, true);
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({ name: interaction.user.displayName, iconURL: interaction.user.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.success} Messages Supprimés`)
|
||||
.setColor(colors.success)
|
||||
.setDescription(`**${filteredMessages.size}** message(s) supprimé(s)${target ? ` de ${target.toString()}` : ''}.`)
|
||||
.addFields(
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📊 Messages supprimés', value: `\`${filteredMessages.size}\``, inline: true },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `${interaction.guild.name} • ${interaction.channel.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${interaction.user.displayName}`,
|
||||
iconURL: interaction.user.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.success} Messages Supprimés`)
|
||||
.setColor(colors.success)
|
||||
.setDescription(`**${filteredMessages.size}** message(s) supprimé(s)${target ? ` de ${target.toString()}` : ''}.`)
|
||||
.addFields(
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📊 Messages supprimés', value: `\`${filteredMessages.size}\``, inline: true },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `${interaction.guild.name} • ${interaction.channel.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
// Supprimer le message de confirmation après 5 secondes
|
||||
setTimeout(() => {
|
||||
interaction.deleteReply().catch(() => null);
|
||||
}, 5000);
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de la suppression des messages:', err);
|
||||
if (err.code === 50034) {
|
||||
await interaction.editReply({ content: '❌ Les messages de plus de 14 jours ne peuvent pas être supprimés.' });
|
||||
} else {
|
||||
await interaction.editReply({ content: `❌ Échec de la suppression des messages: ${err.message}` });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur clear:', err);
|
||||
if (err.code === 50034) {
|
||||
await interaction.editReply({ content: '❌ Les messages de plus de 14 jours ne peuvent pas être supprimés.' });
|
||||
} else {
|
||||
await interaction.editReply({ content: `❌ Échec de la suppression: ${err.message}` });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,111 +1,89 @@
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('kick')
|
||||
.setDescription('Expulser un membre du serveur.')
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('Le membre à expulser')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison de l\'expulsion')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.KickMembers),
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('kick')
|
||||
.setDescription('Expulser un membre du serveur.')
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('Le membre à expulser')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison de l\'expulsion')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.KickMembers),
|
||||
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('target');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('target');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
|
||||
await interaction.deferReply();
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
if (!target) {
|
||||
return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
}
|
||||
if (!target) return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
}
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
|
||||
// Vérifications de permissions
|
||||
if (member.id === interaction.guild.ownerId) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas expulser le propriétaire du serveur.' });
|
||||
}
|
||||
if (member.id === interaction.user.id) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas t\'expulser toi-même.' });
|
||||
}
|
||||
if (member.roles.highest.position >= interaction.member.roles.highest.position && interaction.guild.ownerId !== interaction.user.id) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas expulser cet utilisateur car il a un rôle supérieur ou égal au tien.' });
|
||||
}
|
||||
if (!member.kickable) {
|
||||
return interaction.editReply({ content: '❌ Je n\'ai pas les permissions nécessaires pour expulser cet utilisateur.' });
|
||||
}
|
||||
if (member.id === interaction.guild.ownerId) return interaction.editReply({ content: '❌ Tu ne peux pas expulser le propriétaire du serveur.' });
|
||||
if (member.id === interaction.user.id) return interaction.editReply({ content: '❌ Tu ne peux pas t\'expulser toi-même.' });
|
||||
|
||||
if (member.roles.highest.position >= interaction.member.roles.highest.position && interaction.guild.ownerId !== interaction.user.id) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas expulser cet utilisateur car il a un rôle supérieur ou égal au tien.' });
|
||||
}
|
||||
if (!member.kickable) {
|
||||
return interaction.editReply({ content: '❌ Je n\'ai pas les permissions nécessaires pour expulser cet utilisateur.' });
|
||||
}
|
||||
|
||||
try {
|
||||
await member.kick(`Expulsé par ${interaction.user.tag}: ${reason}`);
|
||||
try {
|
||||
await member.kick(`Expulsé par ${interaction.user.tag}: ${reason}`);
|
||||
|
||||
// Log dans la DB
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Expulsion', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Expulsion', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({ name: target.displayName, iconURL: target.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.kick} Utilisateur Expulsé`)
|
||||
.setColor(colors.kick)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été expulsé du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${target.displayName}`,
|
||||
iconURL: target.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.kick} Utilisateur Expulsé`)
|
||||
.setColor(colors.kick)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été expulsé du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
// Log dans le canal de logs
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${interaction.user.displayName}`,
|
||||
iconURL: interaction.user.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.kick} Expulsion`)
|
||||
.setColor(colors.kick)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été expulsé du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de l\'expulsion:', err);
|
||||
if (err.code === 50013) {
|
||||
await interaction.editReply({ content: '❌ Je n\'ai pas les permissions nécessaires pour expulser cet utilisateur.' });
|
||||
} else {
|
||||
await interaction.editReply({ content: `❌ Échec de l'expulsion de ${target.tag}: ${err.message}` });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({ name: interaction.user.displayName, iconURL: interaction.user.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.kick} Expulsion`)
|
||||
.setColor(colors.kick)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été expulsé du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur kick:', err);
|
||||
await interaction.editReply({ content: `❌ Erreur: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,144 +1,113 @@
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { parseDuration, formatDuration } = require('../../utils/helpers');
|
||||
const { parseDuration, formatDuration, sendLog } = require('../../utils/helpers');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('mute')
|
||||
.setDescription('Muter un membre du serveur.')
|
||||
.addUserOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('Le membre à muter')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('duration')
|
||||
.setDescription('Durée du mute (ex: 5m, 1h, 1d, max 28j)')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison du mute')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('mute')
|
||||
.setDescription('Muter un membre du serveur.')
|
||||
.addUserOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('Le membre à muter')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('duration')
|
||||
.setDescription('Durée du mute (ex: 5m, 1h, 1d, max 28j)')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison du mute')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('user');
|
||||
const durationInput = interaction.options.getString('duration');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('user');
|
||||
const durationInput = interaction.options.getString('duration');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
if (!target) {
|
||||
return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
}
|
||||
if (!target) return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
}
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
|
||||
// Vérifications
|
||||
if (member.id === interaction.guild.ownerId) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas muter le propriétaire du serveur.' });
|
||||
}
|
||||
if (member.id === interaction.user.id) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas te muter toi-même.' });
|
||||
}
|
||||
if (member.roles.highest.position >= interaction.member.roles.highest.position && interaction.guild.ownerId !== interaction.user.id) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas muter cet utilisateur car il a un rôle supérieur ou égal au tien.' });
|
||||
}
|
||||
if (!member.moderatable) {
|
||||
return interaction.editReply({ content: '❌ Je n\'ai pas les permissions nécessaires pour muter cet utilisateur.' });
|
||||
}
|
||||
if (member.id === interaction.guild.ownerId) return interaction.editReply({ content: '❌ Tu ne peux pas muter le propriétaire du serveur.' });
|
||||
if (member.id === interaction.user.id) return interaction.editReply({ content: '❌ Tu ne peux pas te muter toi-même.' });
|
||||
|
||||
if (member.roles.highest.position >= interaction.member.roles.highest.position && interaction.guild.ownerId !== interaction.user.id) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas muter cet utilisateur car il a un rôle supérieur ou égal au tien.' });
|
||||
}
|
||||
if (!member.moderatable) {
|
||||
return interaction.editReply({ content: '❌ Je n\'ai pas les permissions nécessaires pour muter cet utilisateur.' });
|
||||
}
|
||||
|
||||
// Parser la durée
|
||||
const durationMs = parseDuration(durationInput);
|
||||
if (!durationMs) {
|
||||
return interaction.editReply({ content: '❌ Durée invalide. Utilise un format comme: 5m, 1h, 2d (max 28 jours).' });
|
||||
}
|
||||
const durationMs = parseDuration(durationInput);
|
||||
if (!durationMs) return interaction.editReply({ content: '❌ Durée invalide. Utilise un format comme: 5m, 1h, 2d (max 28 jours).' });
|
||||
|
||||
// Maximum 28 jours (Discord limit)
|
||||
const maxDuration = 28 * 24 * 60 * 60 * 1000;
|
||||
if (durationMs > maxDuration) {
|
||||
return interaction.editReply({ content: '❌ La durée maximum est de 28 jours.' });
|
||||
}
|
||||
const maxDuration = 28 * 24 * 60 * 60 * 1000;
|
||||
if (durationMs > maxDuration) return interaction.editReply({ content: '❌ La durée maximum est de 28 jours.' });
|
||||
|
||||
const durationSeconds = Math.floor(durationMs / 1000);
|
||||
const unmuteDate = Date.now() + durationMs;
|
||||
const type = durationMs > 0 ? 'Temporary' : 'Permanent';
|
||||
const unmuteDate = Date.now() + durationMs;
|
||||
const type = 'Temporary'; // Timeout est toujours temporaire
|
||||
|
||||
try {
|
||||
// Muter avec timeout (Discord)
|
||||
await member.timeout(durationSeconds * 1000, `Muté par ${interaction.user.tag}: ${reason}`);
|
||||
try {
|
||||
await member.timeout(durationMs, `Muté par ${interaction.user.tag}: ${reason}`);
|
||||
|
||||
// Stocker dans la DB
|
||||
await db.query(
|
||||
`INSERT INTO mutes (userId, guildId, reason, modId, modTag, timestamp, unmuteDate, type)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE reason=VALUES(reason), modId=VALUES(modId), modTag=VALUES(modTag), timestamp=VALUES(timestamp), unmuteDate=VALUES(unmuteDate), type=VALUES(type)`,
|
||||
[target.id, interaction.guild.id, reason, interaction.user.id, interaction.user.tag, Date.now(), unmuteDate, type]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO mutes (userId, guildId, reason, modId, modTag, timestamp, unmuteDate, type)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE reason=VALUES(reason), modId=VALUES(modId), modTag=VALUES(modTag), timestamp=VALUES(timestamp), unmuteDate=VALUES(unmuteDate), type=VALUES(type)`,
|
||||
[target.id, interaction.guild.id, reason, interaction.user.id, interaction.user.tag, Date.now(), unmuteDate, type]
|
||||
);
|
||||
|
||||
// Log dans la DB
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Mute', reason, type, interaction.guild.id, Date.now()]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Mute', reason, type, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({ name: target.displayName, iconURL: target.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.mute} Utilisateur Muté`)
|
||||
.setColor(colors.mute)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été muté.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '⏰ Durée', value: `\`${formatDuration(durationMs)}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Jusqu\'à', value: `<t:${Math.floor(unmuteDate / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${target.displayName}`,
|
||||
iconURL: target.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.mute} Utilisateur Muté`)
|
||||
.setColor(colors.mute)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été muté.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '⏰ Durée', value: `\`${formatDuration(durationMs)}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Jusqu\'à', value: `<t:${Math.floor(unmuteDate / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
// Log dans le canal de logs
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${interaction.user.displayName}`,
|
||||
iconURL: interaction.user.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.mute} Mute`)
|
||||
.setColor(colors.mute)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été muté.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '⏰ Durée', value: `\`${formatDuration(durationMs)}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Jusqu\'à', value: `<t:${Math.floor(unmuteDate / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors du mute:', err);
|
||||
if (err.code === 50013) {
|
||||
await interaction.editReply({ content: '❌ Je n\'ai pas les permissions nécessaires pour muter cet utilisateur.' });
|
||||
} else {
|
||||
await interaction.editReply({ content: `❌ Échec du mute de ${target.tag}: ${err.message}` });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({ name: interaction.user.displayName, iconURL: interaction.user.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.mute} Mute`)
|
||||
.setColor(colors.mute)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été muté.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '⏰ Durée', value: `\`${formatDuration(durationMs)}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Jusqu\'à', value: `<t:${Math.floor(unmuteDate / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur mute:', err);
|
||||
await interaction.editReply({ content: `❌ Erreur: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,98 +1,97 @@
|
||||
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { colors } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('mysanctions')
|
||||
.setDescription('Voir tes propres sanctions sur ce serveur.'),
|
||||
async execute(interaction) {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('mysanctions')
|
||||
.setDescription('Voir tes propres sanctions sur ce serveur.'),
|
||||
async execute(interaction) {
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
const userId = interaction.user.id;
|
||||
const userId = interaction.user.id;
|
||||
|
||||
try {
|
||||
const [rows] = await db.query(
|
||||
'SELECT * FROM logs WHERE userId = ? AND guildId = ? ORDER BY timestamp DESC',
|
||||
[userId, interaction.guild.id]
|
||||
);
|
||||
try {
|
||||
const [rows] = await db.query(
|
||||
'SELECT * FROM logs WHERE userId = ? AND guildId = ? ORDER BY timestamp DESC',
|
||||
[userId, interaction.guild.id]
|
||||
);
|
||||
|
||||
if (!rows.length) {
|
||||
return interaction.editReply({ content: '✅ Tu n\'as aucune sanction sur ce serveur.' });
|
||||
}
|
||||
const sanctions = rows.filter(row =>
|
||||
row.action !== 'Modification de sanction' &&
|
||||
row.action !== 'Révocation de sanction' &&
|
||||
row.action !== 'Modification de mute'
|
||||
);
|
||||
|
||||
const { colors } = require('../../utils/constants');
|
||||
if (!sanctions.length) {
|
||||
return interaction.editReply({ content: '✅ Tu n\'as aucune sanction sur ce serveur.' });
|
||||
}
|
||||
|
||||
// Découpe les sanctions en pages de 10
|
||||
const pages = [];
|
||||
for (let i = 0; i < rows.length; i += 10) {
|
||||
pages.push(rows.slice(i, i + 10));
|
||||
}
|
||||
const pages = [];
|
||||
for (let i = 0; i < sanctions.length; i += 10) {
|
||||
pages.push(sanctions.slice(i, i + 10));
|
||||
}
|
||||
|
||||
const embeds = pages.map((page, pageIndex) => {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`📋 Mes Sanctions - Page ${pageIndex + 1}/${pages.length}`)
|
||||
.setColor(colors.warning)
|
||||
.setThumbnail(interaction.user.displayAvatarURL({ dynamic: true }))
|
||||
.setFooter({ text: `Total: ${rows.length} sanction(s)` })
|
||||
.setTimestamp();
|
||||
const embeds = pages.map((page, pageIndex) => {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`📋 Mes Sanctions - Page ${pageIndex + 1}/${pages.length}`)
|
||||
.setColor(colors.warning)
|
||||
.setThumbnail(interaction.user.displayAvatarURL({ dynamic: true }))
|
||||
.setFooter({ text: `Total: ${sanctions.length} sanction(s)` })
|
||||
.setTimestamp();
|
||||
|
||||
page.forEach((row, index) => {
|
||||
const date = `<t:${Math.floor(row.timestamp / 1000)}:F>`;
|
||||
const actionCapitalized = row.action.charAt(0).toUpperCase() + row.action.slice(1);
|
||||
page.forEach((row, index) => {
|
||||
const date = `<t:${Math.floor(row.timestamp / 1000)}:F>`;
|
||||
const actionCapitalized = row.action.charAt(0).toUpperCase() + row.action.slice(1);
|
||||
|
||||
embed.addFields({
|
||||
name: `#${index + 1 + pageIndex * 10} - ${actionCapitalized}`,
|
||||
value: `**Modérateur:** <@${row.modId}> (${row.modTag || 'N/A'})\n` +
|
||||
`**Raison:** ${row.reason || 'N/A'}\n` +
|
||||
`**Date:** ${date}\n` +
|
||||
`**Type:** ${row.type || 'N/A'}`,
|
||||
inline: false
|
||||
});
|
||||
});
|
||||
embed.addFields({
|
||||
name: `#${index + 1 + pageIndex * 10} - ${actionCapitalized}`,
|
||||
value: `**Modérateur:** <@${row.modId}> (${row.modTag || 'N/A'})\n` +
|
||||
`**Raison:** ${row.reason || 'N/A'}\n` +
|
||||
`**Date:** ${date}\n` +
|
||||
`**Type:** ${row.type || 'N/A'}`,
|
||||
inline: false
|
||||
});
|
||||
});
|
||||
|
||||
return embed;
|
||||
});
|
||||
return embed;
|
||||
});
|
||||
|
||||
// Si une seule page, pas besoin de boutons
|
||||
if (pages.length === 1) {
|
||||
return interaction.editReply({ embeds: [embeds[0]] });
|
||||
}
|
||||
if (pages.length === 1) {
|
||||
return interaction.editReply({ embeds: [embeds[0]] });
|
||||
}
|
||||
|
||||
// Sinon, ajouter les boutons de navigation
|
||||
const { ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
|
||||
const row = new ActionRowBuilder().addComponents(
|
||||
new ButtonBuilder().setCustomId('prev').setLabel('⬅️ Précédent').setStyle(ButtonStyle.Primary),
|
||||
new ButtonBuilder().setCustomId('next').setLabel('Suivant ➡️').setStyle(ButtonStyle.Primary)
|
||||
);
|
||||
const row = new ActionRowBuilder().addComponents(
|
||||
new ButtonBuilder().setCustomId('prev').setLabel('⬅️ Précédent').setStyle(ButtonStyle.Primary),
|
||||
new ButtonBuilder().setCustomId('next').setLabel('Suivant ➡️').setStyle(ButtonStyle.Primary)
|
||||
);
|
||||
|
||||
let currentPage = 0;
|
||||
const message = await interaction.editReply({ embeds: [embeds[currentPage]], components: [row] });
|
||||
let currentPage = 0;
|
||||
const message = await interaction.editReply({ embeds: [embeds[currentPage]], components: [row] });
|
||||
|
||||
// Collecteur de boutons
|
||||
const collector = message.createMessageComponentCollector({ time: 60_000 });
|
||||
collector.on('collect', async i => {
|
||||
if (i.user.id !== interaction.user.id) {
|
||||
return i.reply({ content: '❌ Ce n\'est pas ton menu !', ephemeral: true });
|
||||
}
|
||||
if (i.customId === 'next') {
|
||||
currentPage = (currentPage + 1) % embeds.length;
|
||||
}
|
||||
if (i.customId === 'prev') {
|
||||
currentPage = (currentPage - 1 + embeds.length) % embeds.length;
|
||||
}
|
||||
const collector = message.createMessageComponentCollector({ time: 60_000 });
|
||||
collector.on('collect', async i => {
|
||||
if (i.user.id !== interaction.user.id) {
|
||||
return i.reply({ content: '❌ Ce n\'est pas ton menu !', flags: MessageFlags.Ephemeral });
|
||||
}
|
||||
if (i.customId === 'next') {
|
||||
currentPage = (currentPage + 1) % embeds.length;
|
||||
}
|
||||
if (i.customId === 'prev') {
|
||||
currentPage = (currentPage - 1 + embeds.length) % embeds.length;
|
||||
}
|
||||
|
||||
await i.update({ embeds: [embeds[currentPage]] });
|
||||
});
|
||||
await i.update({ embeds: [embeds[currentPage]] });
|
||||
});
|
||||
|
||||
collector.on('end', () => {
|
||||
message.edit({ components: [] }).catch(() => null);
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de la récupération des sanctions:', err);
|
||||
await interaction.editReply({ content: '❌ Une erreur est survenue lors de la récupération de tes sanctions.' });
|
||||
}
|
||||
},
|
||||
};
|
||||
collector.on('end', () => {
|
||||
message.edit({ components: [] }).catch(() => null);
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur mysanctions:', err);
|
||||
await interaction.editReply({ content: '❌ Une erreur est survenue lors de la récupération de tes sanctions.' });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,114 +1,103 @@
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('purge')
|
||||
.setDescription('Supprimer les messages d\'un utilisateur dans un canal.')
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('L\'utilisateur dont supprimer les messages')
|
||||
.setRequired(true))
|
||||
.addIntegerOption(option =>
|
||||
option.setName('amount')
|
||||
.setDescription('Nombre de messages à vérifier (1-100)')
|
||||
.setRequired(true)
|
||||
.setMinValue(1)
|
||||
.setMaxValue(100))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison de la purge')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('purge')
|
||||
.setDescription('Supprimer les messages d\'un utilisateur dans un canal.')
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('L\'utilisateur dont supprimer les messages')
|
||||
.setRequired(true))
|
||||
.addIntegerOption(option =>
|
||||
option.setName('amount')
|
||||
.setDescription('Nombre de messages à vérifier (1-100)')
|
||||
.setRequired(true)
|
||||
.setMinValue(1)
|
||||
.setMaxValue(100))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison de la purge')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
|
||||
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('target');
|
||||
const amount = interaction.options.getInteger('amount');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('target');
|
||||
const amount = interaction.options.getInteger('amount');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
if (!interaction.channel.isTextBased()) {
|
||||
return interaction.editReply({ content: '❌ Cette commande ne peut être utilisée que dans un canal texte.' });
|
||||
}
|
||||
if (!interaction.channel.isTextBased()) {
|
||||
return interaction.editReply({ content: '❌ Cette commande ne peut être utilisée que dans un canal texte.' });
|
||||
}
|
||||
|
||||
try {
|
||||
const messages = await interaction.channel.messages.fetch({ limit: amount });
|
||||
const messagesToDelete = messages.filter(msg => msg.author.id === target.id);
|
||||
try {
|
||||
const messages = await interaction.channel.messages.fetch({ limit: amount });
|
||||
const messagesToDelete = messages.filter(msg => msg.author.id === target.id);
|
||||
|
||||
// Ne pas supprimer les messages de plus de 14 jours
|
||||
const filteredMessages = messagesToDelete.filter(msg => {
|
||||
const msgAge = Date.now() - msg.createdTimestamp;
|
||||
return msgAge < 14 * 24 * 60 * 60 * 1000;
|
||||
});
|
||||
const filteredMessages = messagesToDelete.filter(msg => {
|
||||
const msgAge = Date.now() - msg.createdTimestamp;
|
||||
return msgAge < 14 * 24 * 60 * 60 * 1000;
|
||||
});
|
||||
|
||||
if (filteredMessages.size === 0) {
|
||||
return interaction.editReply({ content: `❌ Aucun message à supprimer de ${target.tag} (les messages de plus de 14 jours ne peuvent pas être supprimés).` });
|
||||
}
|
||||
if (filteredMessages.size === 0) {
|
||||
return interaction.editReply({ content: `❌ Aucun message à supprimer de ${target.tag} (les messages de plus de 14 jours ne peuvent pas être supprimés).` });
|
||||
}
|
||||
|
||||
await interaction.channel.bulkDelete(filteredMessages, true);
|
||||
await interaction.channel.bulkDelete(filteredMessages, true);
|
||||
|
||||
// Log dans la DB
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Purge', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Purge', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({ name: target.displayName, iconURL: target.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.success} Messages Supprimés`)
|
||||
.setColor(colors.success)
|
||||
.setDescription(`**${filteredMessages.size}** message(s) de ${target.toString()} supprimé(s).`)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📊 Messages supprimés', value: `\`${filteredMessages.size}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${target.displayName}`,
|
||||
iconURL: target.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.success} Messages Supprimés`)
|
||||
.setColor(colors.success)
|
||||
.setDescription(`**${filteredMessages.size}** message(s) de ${target.toString()} supprimé(s).`)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📊 Messages supprimés', value: `\`${filteredMessages.size}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
// Log dans le canal de logs
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${interaction.user.displayName}`,
|
||||
iconURL: interaction.user.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.success} Purge`)
|
||||
.setColor(colors.success)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`**${filteredMessages.size}** message(s) de ${target.toString()} supprimé(s).`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📊 Messages supprimés', value: `\`${filteredMessages.size}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de la purge:', err);
|
||||
if (err.code === 50034) {
|
||||
await interaction.editReply({ content: '❌ Les messages de plus de 14 jours ne peuvent pas être supprimés.' });
|
||||
} else {
|
||||
await interaction.editReply({ content: `❌ Échec de la purge: ${err.message}` });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({ name: interaction.user.displayName, iconURL: interaction.user.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.success} Purge`)
|
||||
.setColor(colors.success)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`**${filteredMessages.size}** message(s) de ${target.toString()} supprimé(s).`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📊 Messages supprimés', value: `\`${filteredMessages.size}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur purge:', err);
|
||||
if (err.code === 50034) {
|
||||
await interaction.editReply({ content: '❌ Les messages de plus de 14 jours ne peuvent pas être supprimés.' });
|
||||
} else {
|
||||
await interaction.editReply({ content: `❌ Échec de la purge: ${err.message}` });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,109 +1,101 @@
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('revokesanction')
|
||||
.setDescription('Révoquer une sanction (Haut gradés, Co-Fonda/Fonda uniquement).')
|
||||
.addUserOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('L\'utilisateur concerné')
|
||||
.setRequired(true))
|
||||
.addIntegerOption(option =>
|
||||
option.setName('sanction_id')
|
||||
.setDescription('L\'ID DB de la sanction à révoquer (visible dans /casier, ex: ID: 123)')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison de la révocation')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('user');
|
||||
const sanctionId = interaction.options.getInteger('sanction_id');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('revokesanction')
|
||||
.setDescription('Révoquer une sanction (Haut gradés, Co-Fonda/Fonda uniquement).')
|
||||
.addUserOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('L\'utilisateur concerné')
|
||||
.setRequired(true))
|
||||
.addIntegerOption(option =>
|
||||
option.setName('sanction_id')
|
||||
.setDescription('L\'ID DB de la sanction à révoquer (visible dans /casier, ex: ID: 123)')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison de la révocation')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('user');
|
||||
const sanctionId = interaction.options.getInteger('sanction_id');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
// Vérifier les permissions (Administrateur ou propriétaire)
|
||||
if (!interaction.member.permissions.has(PermissionFlagsBits.Administrator) && interaction.user.id !== interaction.guild.ownerId) {
|
||||
return interaction.editReply({ content: '❌ Seuls les administrateurs et le propriétaire du serveur peuvent révoquer une sanction.' });
|
||||
}
|
||||
if (!interaction.member.permissions.has(PermissionFlagsBits.Administrator) && interaction.user.id !== interaction.guild.ownerId) {
|
||||
return interaction.editReply({ content: '❌ Seuls les administrateurs et le propriétaire du serveur peuvent révoquer une sanction.' });
|
||||
}
|
||||
|
||||
try {
|
||||
// Récupérer directement la sanction par son ID DB (plus stable)
|
||||
const [sanctionRows] = await db.query(
|
||||
'SELECT * FROM logs WHERE id = ? AND userId = ? AND guildId = ?',
|
||||
[sanctionId, target.id, interaction.guild.id]
|
||||
);
|
||||
try {
|
||||
const [sanctionRows] = await db.query(
|
||||
'SELECT * FROM logs WHERE id = ? AND userId = ? AND guildId = ?',
|
||||
[sanctionId, target.id, interaction.guild.id]
|
||||
);
|
||||
|
||||
if (!sanctionRows.length) {
|
||||
return interaction.editReply({
|
||||
content: `❌ Aucune sanction trouvée avec l'ID ${sanctionId} pour ${target.tag}.\n\n💡 **Astuce:** Utilise l'ID DB visible dans \`/casier\` (ex: \`#1 (ID: 123)\` → utilise \`123\`).`
|
||||
});
|
||||
}
|
||||
if (!sanctionRows.length) {
|
||||
return interaction.editReply({
|
||||
content: `❌ Aucune sanction trouvée avec l'ID ${sanctionId} pour ${target.tag}.\n\n💡 **Astuce:** Utilise l'ID DB visible dans \`/casier\` (ex: \`#1 (ID: 123)\` → utilise \`123\`).`
|
||||
});
|
||||
}
|
||||
|
||||
const sanction = sanctionRows[0];
|
||||
const sanction = sanctionRows[0];
|
||||
|
||||
// Vérifier que ce n'est pas une modification/révocation
|
||||
if (sanction.action === 'Modification de sanction' ||
|
||||
sanction.action === 'Révocation de sanction' ||
|
||||
sanction.action === 'Modification de mute') {
|
||||
return interaction.editReply({ content: `❌ Cette entrée est une modification, pas une sanction. Utilise l'ID d'une vraie sanction.` });
|
||||
}
|
||||
if (sanction.action === 'Modification de sanction' ||
|
||||
sanction.action === 'Révocation de sanction' ||
|
||||
sanction.action === 'Modification de mute') {
|
||||
return interaction.editReply({ content: `❌ Cette entrée est une modification, pas une sanction. Utilise l'ID d'une vraie sanction.` });
|
||||
}
|
||||
|
||||
// Marquer la sanction comme révoquée (on ne la supprime pas, on la marque)
|
||||
await db.query(
|
||||
'UPDATE logs SET reason = CONCAT(reason, " [RÉVOQUÉE]") WHERE id = ?',
|
||||
[sanction.id]
|
||||
);
|
||||
await db.query(
|
||||
'UPDATE logs SET reason = CONCAT(reason, " [RÉVOQUÉE]") WHERE id = ?',
|
||||
[sanction.id]
|
||||
);
|
||||
|
||||
// Log de la révocation
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Révocation de sanction', `Sanction #${sanction.id} révoquée. Raison: ${reason}`, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Révocation de sanction', `Sanction #${sanction.id} révoquée. Raison: ${reason}`, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Sanction Révoquée`)
|
||||
.setColor(colors.success)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '👑 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Raison de révocation', value: reason, inline: false },
|
||||
{ name: '🆔 ID Sanction révoquée', value: `${sanction.id}`, inline: true },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id}` })
|
||||
.setTimestamp();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Sanction Révoquée`)
|
||||
.setColor(colors.success)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '👑 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Raison de révocation', value: reason, inline: false },
|
||||
{ name: '🆔 ID Sanction révoquée', value: `${sanction.id}`, inline: true },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id}` })
|
||||
.setTimestamp();
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
// Log dans le canal de logs
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Révocation de Sanction`)
|
||||
.setColor(colors.success)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '👑 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Raison de révocation', value: reason, inline: false },
|
||||
{ name: '🆔 ID Sanction révoquée', value: `${sanction.id}`, inline: true },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} | Serveur: ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de la révocation de la sanction:', err);
|
||||
await interaction.editReply({ content: `❌ Échec de la révocation de la sanction: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Révocation de Sanction`)
|
||||
.setColor(colors.success)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '👑 Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Raison de révocation', value: reason, inline: false },
|
||||
{ name: '🆔 ID Sanction révoquée', value: `${sanction.id}`, inline: true },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} | Serveur: ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur revokesanction:', err);
|
||||
await interaction.editReply({ content: `❌ Échec de la révocation de la sanction: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,100 +1,80 @@
|
||||
const { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits } = require('discord.js');
|
||||
const { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('unban')
|
||||
.setDescription('Débannir un utilisateur par son ID ou son tag.')
|
||||
.addStringOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('L\'ID ou le tag (Username#1234) de l\'utilisateur à débannir')
|
||||
.setRequired(true))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.BanMembers),
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('unban')
|
||||
.setDescription('Débannir un utilisateur par son ID ou son tag.')
|
||||
.addStringOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('L\'ID ou le tag (Username#1234) de l\'utilisateur à débannir')
|
||||
.setRequired(true))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.BanMembers),
|
||||
|
||||
async execute(interaction) {
|
||||
await interaction.deferReply();
|
||||
async execute(interaction) {
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
const input = interaction.options.getString('user').trim();
|
||||
const input = interaction.options.getString('user').trim();
|
||||
|
||||
try {
|
||||
const bannedUsers = await interaction.guild.bans.fetch();
|
||||
const bannedUser = bannedUsers.find(b =>
|
||||
b.user.id === input || b.user.tag.toLowerCase() === input.toLowerCase()
|
||||
);
|
||||
try {
|
||||
const bannedUsers = await interaction.guild.bans.fetch();
|
||||
const bannedUser = bannedUsers.find(b =>
|
||||
b.user.id === input || b.user.tag.toLowerCase() === input.toLowerCase()
|
||||
);
|
||||
|
||||
if (!bannedUser) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas banni.' });
|
||||
}
|
||||
if (!bannedUser) return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas banni.' });
|
||||
|
||||
// Récupération depuis MySQL
|
||||
const [rows] = await db.query('SELECT * FROM bans WHERE userId = ? AND guildId = ?', [bannedUser.user.id, interaction.guild.id]);
|
||||
const banRecord = rows[0];
|
||||
const reason = `Débanni par ${interaction.user.tag}`;
|
||||
await interaction.guild.members.unban(bannedUser.user.id, reason);
|
||||
|
||||
const reason = `Débanni par ${interaction.user.tag}`;
|
||||
await interaction.guild.members.unban(bannedUser.user.id, reason);
|
||||
await db.query('DELETE FROM bans WHERE userId = ? AND guildId = ?', [bannedUser.user.id, interaction.guild.id]);
|
||||
|
||||
if (banRecord) {
|
||||
await db.query('DELETE FROM bans WHERE userId = ? AND guildId = ?', [bannedUser.user.id, interaction.guild.id]);
|
||||
}
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({ name: bannedUser.user.displayName, iconURL: bannedUser.user.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.unban} Utilisateur Débanni`)
|
||||
.setColor(colors.unban)
|
||||
.setThumbnail(bannedUser.user.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${bannedUser.user.toString()} a été débanni du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${bannedUser.user.toString()}\n\`${bannedUser.user.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${bannedUser.user.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${bannedUser.user.displayName}`,
|
||||
iconURL: bannedUser.user.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.unban} Utilisateur Débanni`)
|
||||
.setColor(colors.unban)
|
||||
.setThumbnail(bannedUser.user.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${bannedUser.user.toString()} a été débanni du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${bannedUser.user.toString()}\n\`${bannedUser.user.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${bannedUser.user.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({ name: interaction.user.displayName, iconURL: interaction.user.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.unban} Débannissement`)
|
||||
.setColor(colors.unban)
|
||||
.setThumbnail(bannedUser.user.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${bannedUser.user.toString()} a été débanni du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${bannedUser.user.toString()}\n\`${bannedUser.user.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${bannedUser.user.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[bannedUser.user.id, bannedUser.user.tag, interaction.user.id, interaction.user.tag, 'Débannissement', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
// Log dans le canal de logs
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${interaction.user.displayName}`,
|
||||
iconURL: interaction.user.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.unban} Débannissement`)
|
||||
.setColor(colors.unban)
|
||||
.setThumbnail(bannedUser.user.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${bannedUser.user.toString()} a été débanni du serveur.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${bannedUser.user.toString()}\n\`${bannedUser.user.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${bannedUser.user.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
// Log dans la DB avec guildId
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[bannedUser.user.id, bannedUser.user.tag, interaction.user.id, interaction.user.tag, 'Débannissement', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors du débannissement:', err);
|
||||
if (err.code === 50013) {
|
||||
await interaction.editReply({ content: '❌ Je n\'ai pas les permissions nécessaires pour débannir cet utilisateur.' });
|
||||
} else {
|
||||
await interaction.editReply({ content: '❌ Échec du débannissement de l\'utilisateur.' });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
} catch (err) {
|
||||
console.error('Erreur unban:', err);
|
||||
await interaction.editReply({ content: `❌ Erreur: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,105 +1,86 @@
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('unmute')
|
||||
.setDescription('Démuter un membre du serveur.')
|
||||
.addUserOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('Le membre à démuter')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison du démute')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('unmute')
|
||||
.setDescription('Démuter un membre du serveur.')
|
||||
.addUserOption(option =>
|
||||
option.setName('user')
|
||||
.setDescription('Le membre à démuter')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison du démute')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('user');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('user');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
if (!target) {
|
||||
return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
}
|
||||
if (!target) return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
}
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
|
||||
if (!member.communicationDisabledUntil) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas muté.' });
|
||||
}
|
||||
if (!member.communicationDisabledUntilTimestamp || member.communicationDisabledUntilTimestamp < Date.now()) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas muté.' });
|
||||
}
|
||||
|
||||
try {
|
||||
// Démuter
|
||||
await member.timeout(null, `Démuté par ${interaction.user.tag}: ${reason}`);
|
||||
try {
|
||||
await member.timeout(null, `Démuté par ${interaction.user.tag}: ${reason}`);
|
||||
|
||||
// Supprimer de la DB
|
||||
await db.query('DELETE FROM mutes WHERE userId = ? AND guildId = ?', [target.id, interaction.guild.id]);
|
||||
await db.query('DELETE FROM mutes WHERE userId = ? AND guildId = ?', [target.id, interaction.guild.id]);
|
||||
|
||||
// Log dans la DB
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Unmute', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Unmute', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({ name: target.displayName, iconURL: target.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.unmute} Utilisateur Démuté`)
|
||||
.setColor(colors.unmute)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été démuté.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${target.displayName}`,
|
||||
iconURL: target.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.unmute} Utilisateur Démuté`)
|
||||
.setColor(colors.unmute)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été démuté.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
// Log dans le canal de logs
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${interaction.user.displayName}`,
|
||||
iconURL: interaction.user.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.unmute} Unmute`)
|
||||
.setColor(colors.unmute)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été démuté.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de l\'unmute:', err);
|
||||
if (err.code === 50013) {
|
||||
await interaction.editReply({ content: '❌ Je n\'ai pas les permissions nécessaires pour démuter cet utilisateur.' });
|
||||
} else {
|
||||
await interaction.editReply({ content: `❌ Échec de l'unmute de ${target.tag}: ${err.message}` });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({ name: interaction.user.displayName, iconURL: interaction.user.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.unmute} Unmute`)
|
||||
.setColor(colors.unmute)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a été démuté.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur unmute:', err);
|
||||
await interaction.editReply({ content: `❌ Erreur: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,90 +1,78 @@
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('untimeout')
|
||||
.setDescription('Retirer le timeout d\'un membre.')
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('Le membre à dé-timeout')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison de la levée du timeout')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('untimeout')
|
||||
.setDescription('Retirer le timeout d\'un membre.')
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('Le membre à dé-timeout')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison de la levée du timeout')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('target');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('target');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
if (!target) {
|
||||
return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
}
|
||||
if (!target) return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
}
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
|
||||
if (!member.communicationDisabledUntil) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas en timeout.' });
|
||||
}
|
||||
if (!member.communicationDisabledUntilTimestamp || member.communicationDisabledUntilTimestamp < Date.now()) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas en timeout.' });
|
||||
}
|
||||
|
||||
try {
|
||||
await member.timeout(null, `Timeout retiré par ${interaction.user.tag}: ${reason}`);
|
||||
try {
|
||||
await member.timeout(null, `Timeout retiré par ${interaction.user.tag}: ${reason}`);
|
||||
|
||||
// Log dans la DB
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Timeout retiré', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Timeout retiré', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Timeout Retiré`)
|
||||
.setColor(colors.success)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '✅ Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id}` })
|
||||
.setTimestamp();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Timeout Retiré`)
|
||||
.setColor(colors.success)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '✅ Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id}` })
|
||||
.setTimestamp();
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
// Log dans le canal de logs
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Timeout Retiré`)
|
||||
.setColor(colors.success)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '✅ Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} | Serveur: ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de la levée du timeout:', err);
|
||||
if (err.code === 50013) {
|
||||
await interaction.editReply({ content: '❌ Je n\'ai pas les permissions nécessaires pour retirer le timeout de cet utilisateur.' });
|
||||
} else {
|
||||
await interaction.editReply({ content: `❌ Échec de la levée du timeout de ${target.tag}: ${err.message}` });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.success} Timeout Retiré`)
|
||||
.setColor(colors.success)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `<@${target.id}> (${target.tag})`, inline: true },
|
||||
{ name: '✅ Modérateur', value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} | Serveur: ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur untimeout:', err);
|
||||
await interaction.editReply({ content: `❌ Erreur: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,121 +1,101 @@
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js');
|
||||
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } = require('discord.js');
|
||||
const db = require('../../functions/database/db.js');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
|
||||
module.exports = {
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('warn')
|
||||
.setDescription('Avertir un membre.')
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('Le membre à avertir')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison de l\'avertissement')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
category: 'moderation',
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('warn')
|
||||
.setDescription('Avertir un membre.')
|
||||
.addUserOption(option =>
|
||||
option.setName('target')
|
||||
.setDescription('Le membre à avertir')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('reason')
|
||||
.setDescription('Raison de l\'avertissement')
|
||||
.setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
||||
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('target');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
async execute(interaction) {
|
||||
const target = interaction.options.getUser('target');
|
||||
const reason = interaction.options.getString('reason') || 'Aucune raison fournie';
|
||||
|
||||
await interaction.deferReply();
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||
|
||||
if (!target) {
|
||||
return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
}
|
||||
if (!target) return interaction.editReply({ content: '❌ Aucun utilisateur spécifié !' });
|
||||
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) {
|
||||
return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
}
|
||||
const member = await interaction.guild.members.fetch(target.id).catch(() => null);
|
||||
if (!member) return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur le serveur.' });
|
||||
|
||||
if (member.id === interaction.user.id) {
|
||||
return interaction.editReply({ content: '❌ Tu ne peux pas t\'avertir toi-même.' });
|
||||
}
|
||||
if (member.id === interaction.user.id) return interaction.editReply({ content: '❌ Tu ne peux pas t\'avertir toi-même.' });
|
||||
|
||||
try {
|
||||
// Compter les avertissements existants
|
||||
const [warnRows] = await db.query(
|
||||
'SELECT COUNT(*) as count FROM logs WHERE userId = ? AND guildId = ? AND action = ?',
|
||||
[target.id, interaction.guild.id, 'Avertissement']
|
||||
);
|
||||
const warnCount = warnRows[0].count + 1;
|
||||
try {
|
||||
const [warnRows] = await db.query(
|
||||
'SELECT COUNT(*) as count FROM logs WHERE userId = ? AND guildId = ? AND action = ?',
|
||||
[target.id, interaction.guild.id, 'Avertissement']
|
||||
);
|
||||
const warnCount = warnRows[0].count + 1;
|
||||
|
||||
// Log dans la DB
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Avertissement', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
await db.query(
|
||||
`INSERT INTO logs (userId, userTag, modId, modTag, action, reason, type, guildId, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[target.id, target.tag, interaction.user.id, interaction.user.tag, 'Avertissement', reason, null, interaction.guild.id, Date.now()]
|
||||
);
|
||||
|
||||
const { colors, emojis } = require('../../utils/constants');
|
||||
const { sendLog } = require('../../utils/helpers');
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({ name: target.displayName, iconURL: target.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.warn} Utilisateur Averti`)
|
||||
.setColor(colors.warn)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a reçu un avertissement.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '🔢 Nombre d\'avertissements', value: `\`${warnCount}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${target.displayName}`,
|
||||
iconURL: target.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.warn} Utilisateur Averti`)
|
||||
.setColor(colors.warn)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a reçu un avertissement.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '🔢 Nombre d\'avertissements', value: `\`${warnCount}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
try {
|
||||
const dmEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.warn} Tu as reçu un avertissement`)
|
||||
.setColor(colors.warn)
|
||||
.setDescription(`Tu as été averti sur **${interaction.guild.name}**`)
|
||||
.addFields(
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '🔢 Nombre d\'avertissements', value: `${warnCount}`, inline: true }
|
||||
)
|
||||
.setFooter({ text: interaction.guild.name, iconURL: interaction.guild.iconURL({ dynamic: true }) })
|
||||
.setTimestamp();
|
||||
await target.send({ embeds: [dmEmbed] });
|
||||
} catch { /* DMs fermés */ }
|
||||
|
||||
// Envoyer un message privé à l'utilisateur
|
||||
try {
|
||||
const dmEmbed = new EmbedBuilder()
|
||||
.setTitle(`${emojis.warn} Tu as reçu un avertissement`)
|
||||
.setColor(colors.warn)
|
||||
.setDescription(`Tu as été averti sur **${interaction.guild.name}**`)
|
||||
.addFields(
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '🔢 Nombre d\'avertissements', value: `${warnCount}`, inline: true }
|
||||
)
|
||||
.setFooter({ text: interaction.guild.name, iconURL: interaction.guild.iconURL({ dynamic: true }) })
|
||||
.setTimestamp();
|
||||
await target.send({ embeds: [dmEmbed] });
|
||||
} catch {
|
||||
// L'utilisateur a les DMs fermés, on continue
|
||||
}
|
||||
|
||||
// Log dans le canal de logs
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({
|
||||
name: `${interaction.user.displayName}`,
|
||||
iconURL: interaction.user.displayAvatarURL({ dynamic: true })
|
||||
})
|
||||
.setTitle(`${emojis.warn} Avertissement`)
|
||||
.setColor(colors.warn)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a reçu un avertissement.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '🔢 Nombre d\'avertissements', value: `\`${warnCount}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de l\'avertissement:', err);
|
||||
await interaction.editReply({ content: `❌ Échec de l'avertissement de ${target.tag}: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setAuthor({ name: interaction.user.displayName, iconURL: interaction.user.displayAvatarURL({ dynamic: true }) })
|
||||
.setTitle(`${emojis.warn} Avertissement`)
|
||||
.setColor(colors.warn)
|
||||
.setThumbnail(target.displayAvatarURL({ dynamic: true }))
|
||||
.setDescription(`${target.toString()} a reçu un avertissement.`)
|
||||
.addFields(
|
||||
{ name: '👤 Utilisateur', value: `${target.toString()}\n\`${target.tag}\``, inline: true },
|
||||
{ name: '👮 Modérateur', value: `${interaction.user.toString()}\n\`${interaction.user.tag}\``, inline: true },
|
||||
{ name: '🔢 Nombre d\'avertissements', value: `\`${warnCount}\``, inline: true },
|
||||
{ name: '📝 Raison', value: reason, inline: false },
|
||||
{ name: '📅 Date', value: `<t:${Math.floor(Date.now() / 1000)}:F>`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `ID: ${target.id} • ${interaction.guild.name}` })
|
||||
.setTimestamp();
|
||||
await sendLog(interaction.guild, { embeds: [logEmbed] });
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur warn:', err);
|
||||
await interaction.editReply({ content: `❌ Erreur: ${err.message}` });
|
||||
}
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user