const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js'); const db = require('../../functions/database/db.js'); const { parseDuration, formatDuration } = require('../../utils/helpers'); 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), 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 }); 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.' }); } 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] ); if (!muteRows.length && !member.communicationDisabledUntil) { 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; 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).' }); } 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); // Mettre à jour le timeout const durationSeconds = Math.floor(newDurationMs / 1000); await member.timeout(durationSeconds * 1000, `Mute modifié par ${interaction.user.tag}: ${newReason || oldReason}`); } // Mettre à jour la DB const finalReason = newReason || oldReason; const type = newUnmuteDate && newUnmuteDate > Date.now() ? 'Temporary' : 'Permanent'; 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(', '); 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(); if (newUnmuteDate) { embed.addFields({ name: '📅 Démute le', value: ``, inline: true }); } await interaction.editReply({ embeds: [embed] }); // 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: ``, 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}` }); } }, };