const { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits } = require('discord.js'); const db = require('../../functions/database/db.js'); const { getUserXP } = require('../../functions/xp/xp.js'); const { colors } = require('../../utils/constants'); // Mapping des emojis personnalisés pour les badges Discord // Format: <:nom_emoji:ID> const BADGE_EMOJIS = { // Badges généraux (utiliser des emojis Unicode par défaut si pas d'emoji personnalisé fourni) 'staff': '👨‍💼', // Discord Staff (pas d'emoji fourni dans la liste) 'partner': '<:discord_partener:1437046788916904097>', // Partner 'hypesquad': '<:hypesquad_balance:1437046792922464337>', // HypeSquad (générique - utiliser Balance) 'hypesquad_bravery': '<:hypesquad_bravery:1437046793899872467>', // HypeSquad Bravery 'hypesquad_brilliance': '<:hypesquad_brilliance:1437046794868756550>', // HypeSquad Brilliance 'hypesquad_balance': '<:hypesquad_balance:1437046792922464337>', // HypeSquad Balance 'hypesquad_events': '<:hypesquad_events:1437046795778920448>', // HypeSquad Events 'early_supporter': '<:early_supporter:1437046790087250071>', // Early Supporter 'bug_hunter_level_1': '🐛', // Bug Hunter (pas d'emoji fourni) 'bug_hunter_level_2': '🐛', // Bug Hunter Gold (pas d'emoji fourni) 'verified_developer': '✅', // Verified Bot Developer (pas d'emoji fourni) 'active_developer': '<:active_developer:1437049369936531587>', // Active Developer 'certified_moderator': '🛡️', // Certified Moderator (pas d'emoji fourni) 'bot_http_interactions': '🤖', // Bot HTTP Interactions (pas d'emoji fourni) // Badges Quests 'quests': '<:quests:1437046809464934492>', // Quests 'slash_commands': '<:slash_commands:1437046810458984553>', // Slash Commands // Badges Orbs 'orbs': '<:orbs:1437046808185540628>', // Orbs // Badges Nitro (par durée) 'nitro': '<:nitro:1437046796810715136>', // Nitro (base) 'nitro_1_month': '<:nitro_1_month:1437046798685442241>', // Nitro 1 mois 'nitro_3_months': '<:nitro_3_months:1437046801550278757>', // Nitro 3 mois 'nitro_6_months': '<:nitro_6_months:1437046805102723143>', // Nitro 6 mois 'nitro_1_year': '<:nitro_1_year:1437046799515783198>', // Nitro 1 an 'nitro_2_years': '<:nitro_2_years:1437046800522416138>', // Nitro 2 ans 'nitro_3_years': '<:nitro_3_years:1437046802519035924>', // Nitro 3 ans (Émeraude) 'nitro_5_years': '<:nitro_5_years:1437046803747967016>', // Nitro 5 ans 'nitro_6_years': '<:nitro_6_years:1437046806747021514>', // Nitro 6 ans // Badges Boost (par durée) 'boost': '<:boost:1437046778083016745>', // Boost (base) 'boost_2_months': '<:boost_2_months:1437046780322779266>', // Boost 2 mois 'boost_3_months': '<:boost_3_months:1437046781375414383>', // Boost 3 mois 'boost_6_months': '<:boost_6_months:1437046782247829616>', // Boost 6 mois 'boost_9_months': '<:boost_9_months:1437046783070044200>', // Boost 9 mois 'boost_12_months': '<:boost_12_months:1437046784445644930>', // Boost 12 mois 'boost_15_months': '<:boost_15_months:1437046785402081281>', // Boost 15 mois 'boost_18_months': '<:boost_18_months:1437046786643722342>', // Boost 18 mois 'boost_24_months': '<:boost_24_months:1437046787667136612>', // Boost 24 mois }; // Fonction pour obtenir les badges Discord d'un utilisateur (emojis personnalisés) function getDiscordBadges(user, member) { const badgeEmojis = []; // Badges de compte - utiliser toArray() qui retourne les noms des flags if (user.flags) { try { const flagsArray = user.flags.toArray(); // Mapping des flags Discord.js vers les noms de badges const flagToBadgeMap = { 'Staff': 'staff', 'Partner': 'partner', 'HypeSquad': 'hypesquad', 'HypeSquadOnlineHouse1': 'hypesquad_bravery', 'HypeSquadOnlineHouse2': 'hypesquad_brilliance', 'HypeSquadOnlineHouse3': 'hypesquad_balance', 'HypeSquadEvents': 'hypesquad_events', 'BugHunterLevel1': 'bug_hunter_level_1', 'BugHunterLevel2': 'bug_hunter_level_2', 'PremiumEarlySupporter': 'early_supporter', 'VerifiedDeveloper': 'verified_developer', 'ActiveDeveloper': 'active_developer', 'CertifiedModerator': 'certified_moderator', 'BotHTTPInteractions': 'bot_http_interactions', 'Quests': 'quests', 'QuestsEarly': 'quests', 'SlashCommands': 'slash_commands', }; // Note: Les logs de debug sont commentés pour réduire le bruit dans les logs // Décommenter si besoin de debugger les flags // Vérifier chaque flag présent et ajouter l'emoji for (const flag of flagsArray) { const flagLower = flag.toLowerCase(); const badgeKey = flagToBadgeMap[flag]; // Si le flag est dans le mapping direct, l'utiliser if (badgeKey && BADGE_EMOJIS[badgeKey]) { badgeEmojis.push(BADGE_EMOJIS[badgeKey]); continue; } // Recherche flexible pour les badges avec durées // Badges Nitro avec durées (les noms peuvent varier dans Discord.js) if (flagLower.includes('nitro')) { // Essayer de détecter la durée exacte if (flagLower.match(/6.*year|year.*6|emerald/)) { badgeEmojis.push(BADGE_EMOJIS.nitro_6_years); } else if (flagLower.match(/5.*year|year.*5/)) { badgeEmojis.push(BADGE_EMOJIS.nitro_5_years); } else if (flagLower.match(/3.*year|year.*3/)) { badgeEmojis.push(BADGE_EMOJIS.nitro_3_years); } else if (flagLower.match(/2.*year|year.*2/)) { badgeEmojis.push(BADGE_EMOJIS.nitro_2_years); } else if (flagLower.match(/1.*year|year.*1/) && !flagLower.includes('month')) { badgeEmojis.push(BADGE_EMOJIS.nitro_1_year); } else if (flagLower.match(/6.*month|month.*6/)) { badgeEmojis.push(BADGE_EMOJIS.nitro_6_months); } else if (flagLower.match(/3.*month|month.*3/)) { badgeEmojis.push(BADGE_EMOJIS.nitro_3_months); } else if (flagLower.match(/1.*month|month.*1/)) { badgeEmojis.push(BADGE_EMOJIS.nitro_1_month); } else { // Badge Nitro de base (sans durée spécifique) badgeEmojis.push(BADGE_EMOJIS.nitro); } } // Badges Boost avec durées (les badges Boost personnels, pas le boost serveur) // Les badges Boost sont basés sur la durée totale de boost sur TOUS les serveurs else if (flagLower.includes('boost') && !flagLower.includes('server')) { // Détecter la durée exacte en vérifiant les nombres dans le flag // Les flags peuvent être: PremiumGuildSubscription, PremiumGuildSubscriptionTier1, etc. // ou des flags spécifiques comme "PremiumGuildSubscription24Months" // Vérifier d'abord les durées les plus longues (pour éviter les fausses détections) if (flagLower.match(/24|two.*four|twenty.*four/i)) { badgeEmojis.push(BADGE_EMOJIS.boost_24_months); } else if (flagLower.match(/18|eighteen/i)) { badgeEmojis.push(BADGE_EMOJIS.boost_18_months); } else if (flagLower.match(/15|fifteen/i)) { badgeEmojis.push(BADGE_EMOJIS.boost_15_months); } else if (flagLower.match(/12|twelve|one.*year|1.*year/) && !flagLower.match(/18|15|24|128|112/i)) { badgeEmojis.push(BADGE_EMOJIS.boost_12_months); } else if (flagLower.match(/9|nine/) && !flagLower.match(/19|29|90|99/i)) { badgeEmojis.push(BADGE_EMOJIS.boost_9_months); } else if (flagLower.match(/6|six/) && !flagLower.match(/16|26|60|66|68|69/i)) { badgeEmojis.push(BADGE_EMOJIS.boost_6_months); } else if (flagLower.match(/3|three/) && !flagLower.match(/13|23|30|33|34|35|36|37|38|39/i)) { badgeEmojis.push(BADGE_EMOJIS.boost_3_months); } else if (flagLower.match(/2|two/) && !flagLower.match(/12|20|21|22|23|24|25|26|27|28|29/i)) { badgeEmojis.push(BADGE_EMOJIS.boost_2_months); } else { // Badge Boost de base (sans durée spécifique) badgeEmojis.push(BADGE_EMOJIS.boost); } } // Autres badges else if (flagLower.includes('orb')) { badgeEmojis.push(BADGE_EMOJIS.orbs); } else if (flagLower.includes('quest')) { badgeEmojis.push(BADGE_EMOJIS.quests); } else if (flagLower.includes('slash')) { badgeEmojis.push(BADGE_EMOJIS.slash_commands); } // Log pour debugger les flags non mappés (pour les ajouter plus tard) else if (!flagToBadgeMap[flag]) { console.log(`[PROFIL] Flag non mappé détecté: "${flag}" (pour l'utilisateur ${user.id})`); } } } catch (err) { // Si toArray() échoue, ignorer silencieusement console.warn('Erreur lors de la récupération des flags:', err.message); } } // Badge Nitro de base (si l'utilisateur a Nitro mais pas les badges spéciaux dans les flags) // Vérifier si un badge Nitro n'a pas déjà été ajouté via les flags const hasNitroBadge = badgeEmojis.some(e => typeof e === 'string' && ( e.includes('nitro') || e === BADGE_EMOJIS.nitro || e === BADGE_EMOJIS.nitro_1_month || e === BADGE_EMOJIS.nitro_3_months || e === BADGE_EMOJIS.nitro_6_months || e === BADGE_EMOJIS.nitro_1_year || e === BADGE_EMOJIS.nitro_2_years || e === BADGE_EMOJIS.nitro_3_years || e === BADGE_EMOJIS.nitro_5_years || e === BADGE_EMOJIS.nitro_6_years ) ); // IMPORTANT: Les badges Nitro avec durée (Émeraude 3 ans, Boost 18 mois, etc.) ne sont PAS // accessibles via l'API Discord.js dans les flags utilisateur standard. // Ces badges sont visibles côté client Discord mais ne sont pas exposés via l'API du bot. // // LIMITATION DE L'API DISCORD.JS : // - premiumType : Méthode la plus fiable, mais souvent undefined même pour les utilisateurs Nitro // - banner : Nécessite généralement Nitro, mais peut être présent sans Nitro dans certains cas // - accentColor : Nécessite généralement Nitro, mais peut être présent sans Nitro dans certains cas // - avatar animé : Nécessite généralement Nitro, mais peut être présent sans Nitro dans certains cas // // SOLUTION : Détection multi-niveaux pour équilibrer précision et détection // Niveau 1 (preuve définitive) : premiumType défini ET != 0 → Nitro confirmé // - premiumType 1 = NitroClassic // - premiumType 2 = Nitro // - premiumType 3 = NitroBasic // - premiumType 0 = None (pas de Nitro) // Niveau 2 (très probable) : banner présent → très probablement Nitro // Niveau 3 (probable) : avatar animé ET accentColor → probablement Nitro (mais moins fiable) // // NOTE IMPORTANTE : accentColor seul n'est PAS utilisé car il peut être présent sans Nitro // Mais accentColor + avatar animé ensemble = probablement Nitro (moins fiable que banner) // // Référence: https://discord-api-types.dev/api/discord-api-types-v10/enum/UserPremiumType // Vérifier les indicateurs // premiumType peut être 0 (None), 1 (NitroClassic), 2 (Nitro), ou 3 (NitroBasic) // On vérifie que premiumType est défini ET différent de 0 const hasPremiumType = user.premiumType !== null && user.premiumType !== undefined && user.premiumType !== 0; const hasBanner = user.banner !== null && user.banner !== undefined; const hasAccentColor = user.accentColor !== null && user.accentColor !== undefined; const hasAnimatedAvatar = user.avatar && user.avatar.startsWith('a_'); // Détecter Nitro avec priorité (du plus fiable au moins fiable) : // 1. premiumType défini ET != 0 (preuve définitive) - score 100% // 2. banner présent (très fiable ~99%) - score 99% // 3. avatar animé ET accentColor (probable ~80%) - score 80% (moins fiable mais acceptable) const hasNitro = hasPremiumType || hasBanner || (hasAnimatedAvatar && hasAccentColor); // Ajouter le badge Nitro de base si on détecte Nitro et qu'il n'y a pas déjà un badge Nitro spécifique if (!hasNitroBadge && hasNitro) { badgeEmojis.push(BADGE_EMOJIS.nitro); } // Badge Booster (si le membre boost le serveur) // Note: Les badges Boost avec durée sont basés sur la durée TOTALE de boost sur TOUS les serveurs // et sont détectés via les flags utilisateur. Si aucun badge Boost n'est détecté dans les flags // mais que l'utilisateur boost le serveur actuel, on peut calculer la durée depuis premiumSince // pour afficher le badge approprié (mais ce n'est que pour le serveur actuel, pas la durée totale) if (member && member.premiumSince) { const hasBoostBadge = badgeEmojis.some(e => typeof e === 'string' && ( e.includes('boost') || e === BADGE_EMOJIS.boost || e === BADGE_EMOJIS.boost_2_months || e === BADGE_EMOJIS.boost_3_months || e === BADGE_EMOJIS.boost_6_months || e === BADGE_EMOJIS.boost_9_months || e === BADGE_EMOJIS.boost_12_months || e === BADGE_EMOJIS.boost_15_months || e === BADGE_EMOJIS.boost_18_months || e === BADGE_EMOJIS.boost_24_months ) ); if (!hasBoostBadge) { // Si le membre boost le serveur mais n'a pas de badge Boost dans les flags, // on calcule la durée depuis premiumSince pour afficher le badge approprié // NOTE: Ce n'est que pour le serveur actuel, pas la durée totale sur tous les serveurs const boostDurationMs = Date.now() - member.premiumSince.getTime(); const boostDurationMonths = Math.floor(boostDurationMs / (1000 * 60 * 60 * 24 * 30)); // Déterminer le badge Boost en fonction de la durée (sur ce serveur) let boostBadge = BADGE_EMOJIS.boost; // Badge de base par défaut if (boostDurationMonths >= 24) { boostBadge = BADGE_EMOJIS.boost_24_months; } else if (boostDurationMonths >= 18) { boostBadge = BADGE_EMOJIS.boost_18_months; } else if (boostDurationMonths >= 15) { boostBadge = BADGE_EMOJIS.boost_15_months; } else if (boostDurationMonths >= 12) { boostBadge = BADGE_EMOJIS.boost_12_months; } else if (boostDurationMonths >= 9) { boostBadge = BADGE_EMOJIS.boost_9_months; } else if (boostDurationMonths >= 6) { boostBadge = BADGE_EMOJIS.boost_6_months; } else if (boostDurationMonths >= 3) { boostBadge = BADGE_EMOJIS.boost_3_months; } else if (boostDurationMonths >= 2) { boostBadge = BADGE_EMOJIS.boost_2_months; } badgeEmojis.push(boostBadge); } } // Dédupliquer les emojis avant de retourner return [...new Set(badgeEmojis)]; } // Fonction pour obtenir le statut Discord en français function getStatusFrench(presence) { if (!presence || !presence.status) return { text: 'Hors ligne', emoji: '⚫' }; switch (presence.status) { case 'online': return { text: 'En ligne', emoji: '🟢' }; case 'idle': return { text: 'Absent', emoji: '🟡' }; case 'dnd': return { text: 'Ne pas déranger', emoji: '🔴' }; case 'invisible': case 'offline': default: return { text: 'Hors ligne', emoji: '⚫' }; } } module.exports = { category: 'info', data: new SlashCommandBuilder() .setName('profil') .setDescription('Afficher le profil d\'un utilisateur') .addSubcommand(subcommand => subcommand .setName('view') .setDescription('Voir le profil d\'un utilisateur') .addUserOption(option => option.setName('user') .setDescription('L\'utilisateur dont tu veux voir le profil') .setRequired(false))) .addSubcommand(subcommand => subcommand .setName('set') .setDescription('Modifier ton profil') .addStringOption(option => option.setName('signature') .setDescription('Ta signature personnalisée (max 200 caractères)') .setRequired(false) .setMaxLength(200))) .addSubcommand(subcommand => subcommand .setName('reset') .setDescription('Réinitialiser ta signature')), async execute(interaction) { const subcommand = interaction.options.getSubcommand(); if (subcommand === 'view') { await interaction.deferReply(); const target = interaction.options.getUser('user') || interaction.user; // Fetch l'utilisateur avec toutes les données pour avoir accès à premiumType, banner, accentColor, etc. // Utiliser { force: true } pour forcer le fetch même si l'utilisateur est dans le cache const fetchedUser = await interaction.client.users.fetch(target.id, { force: true, cache: false // Ne pas mettre en cache pour avoir les données les plus récentes }).catch(() => { // Si le fetch échoue, utiliser l'utilisateur du cache console.warn(`[PROFIL] Impossible de fetcher l'utilisateur ${target.id}, utilisation du cache`); return target; }); const member = await interaction.guild.members.fetch(target.id).catch(() => null); if (!member) { return interaction.editReply({ content: '❌ Cet utilisateur n\'est pas sur ce serveur.' }); } try { // Récupérer les données XP const userXP = await getUserXP(target.id, interaction.guild.id); // Récupérer le profil utilisateur const [profiles] = await db.query( 'SELECT * FROM user_profiles WHERE userId = ? AND guildId = ?', [target.id, interaction.guild.id] ); const profile = profiles[0] || null; // Obtenir les badges (emojis seulement) // Utiliser fetchedUser pour avoir accès à premiumType const badgeEmojis = getDiscordBadges(fetchedUser, member); const badgesText = badgeEmojis.length > 0 ? badgeEmojis.join(' ') : 'Aucun badge'; // Obtenir le statut (préserver la présence) const presence = member.presence; const status = getStatusFrench(presence); // Calculer l'âge du compte avec date const accountAge = Math.floor((Date.now() - target.createdTimestamp) / (1000 * 60 * 60 * 24)); const accountAgeYears = Math.floor(accountAge / 365); const accountAgeMonths = Math.floor((accountAge % 365) / 30); const accountAgeDays = accountAge % 30; let accountAgeText = ''; if (accountAgeYears > 0) { accountAgeText = `${accountAgeYears} an${accountAgeYears > 1 ? 's' : ''}`; if (accountAgeMonths > 0) { accountAgeText += ` ${accountAgeMonths} mois`; } } else if (accountAgeMonths > 0) { accountAgeText = `${accountAgeMonths} mois`; if (accountAgeDays > 0) { accountAgeText += ` ${accountAgeDays} jour${accountAgeDays > 1 ? 's' : ''}`; } } else { accountAgeText = `${accountAgeDays} jour${accountAgeDays > 1 ? 's' : ''}`; } // Date de création formatée const creationDate = ``; const accountAgeWithDate = `${accountAgeText} (${creationDate})`; // Calculer le temps vocal (en minutes) const voiceTimeMinutes = userXP?.totalVoiceTime || 0; const voiceTimeHours = Math.floor(voiceTimeMinutes / 60); const voiceTimeMins = voiceTimeMinutes % 60; const voiceTimeText = voiceTimeHours > 0 ? `${voiceTimeHours}h ${voiceTimeMins}min` : `${voiceTimeMins}min`; // Calculer le rang (nécessite un await séparé) const { getUserRank } = require('../../functions/xp/xp.js'); const rank = userXP ? await getUserRank(target.id, interaction.guild.id) : 0; // Statistiques supplémentaires // Nombre de bumps const [bumps] = await db.query( 'SELECT COUNT(*) as count FROM bumps WHERE userId = ? AND guildId = ?', [target.id, interaction.guild.id] ); const bumpsCount = bumps[0]?.count || 0; // Nombre de bienvenues (depuis les logs XP) const [welcomeLogs] = await db.query( 'SELECT COUNT(*) as count FROM xp_logs WHERE userId = ? AND guildId = ? AND source = ?', [target.id, interaction.guild.id, 'welcome'] ); const welcomeCount = welcomeLogs[0]?.count || 0; // Messages totaux (tous les serveurs où le bot est présent) // On récupère la somme de tous les messages de l'utilisateur sur tous les serveurs const [totalMessages] = await db.query( 'SELECT SUM(totalMessages) as total FROM user_xp WHERE userId = ?', [target.id] ); const totalMessagesCount = totalMessages[0]?.total || userXP?.totalMessages || 0; // Créer l'embed const embed = new EmbedBuilder() .setTitle(`📋 Profil de ${target.username}`) .setColor(colors.primary) .setThumbnail(target.displayAvatarURL({ dynamic: true, size: 256 })) .setDescription(profile?.signature || '*Aucune signature*') .addFields( { name: '🆔 Identifiant', value: `${target.tag} (${target.id})`, inline: false }, { name: '🏆 Badges', value: badgesText, inline: false }, { name: `${status.emoji} Statut`, value: status.text, inline: true }, { name: '📅 Âge du compte', value: accountAgeWithDate, inline: true }, { name: '⭐ Niveau', value: `${userXP?.level || 0}`, inline: true }, { name: '📊 XP Total', value: `${userXP?.xp || 0} XP`, inline: true }, { name: '💬 Messages', value: `${totalMessagesCount}`, inline: true }, { name: '🎤 Temps Vocal', value: voiceTimeText, inline: true }, { name: '📈 Rang', value: `#${rank}`, inline: true }, { name: '🚀 Bumps', value: `${bumpsCount}`, inline: true }, { name: '👋 Bienvenues', value: `${welcomeCount}`, inline: true } ) .setFooter({ text: interaction.guild.name, iconURL: interaction.guild.iconURL({ dynamic: true }) }) .setTimestamp(); // Ajouter l'âge si disponible (système d'anniversaire) if (profile?.birthday) { const birthday = new Date(profile.birthday); const today = new Date(); let age = today.getFullYear() - birthday.getFullYear(); const monthDiff = today.getMonth() - birthday.getMonth(); if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthday.getDate())) { age--; } embed.addFields({ name: '🎂 Âge', value: `${age} ans`, inline: true }); } await interaction.editReply({ embeds: [embed] }); } catch (err) { console.error('Erreur lors de l\'affichage du profil:', err); await interaction.editReply({ content: '❌ Erreur lors de l\'affichage du profil.' }); } } else if (subcommand === 'set') { await interaction.deferReply({ ephemeral: true }); const signature = interaction.options.getString('signature'); if (!signature) { return interaction.editReply({ content: '❌ Tu dois fournir une signature.' }); } try { // Vérifier ou créer le profil const [profiles] = await db.query( 'SELECT * FROM user_profiles WHERE userId = ? AND guildId = ?', [interaction.user.id, interaction.guild.id] ); if (profiles.length > 0) { // Mettre à jour la signature await db.query( 'UPDATE user_profiles SET signature = ?, updatedAt = ? WHERE userId = ? AND guildId = ?', [signature, Date.now(), interaction.user.id, interaction.guild.id] ); } else { // Créer le profil await db.query( 'INSERT INTO user_profiles (userId, guildId, signature, updatedAt) VALUES (?, ?, ?, ?)', [interaction.user.id, interaction.guild.id, signature, Date.now()] ); } const embed = new EmbedBuilder() .setTitle('✅ Signature Modifiée') .setColor(colors.success) .setDescription(`Ta signature a été mise à jour :\n\n${signature}`) .setTimestamp(); await interaction.editReply({ embeds: [embed] }); } catch (err) { console.error('Erreur lors de la modification de la signature:', err); await interaction.editReply({ content: '❌ Erreur lors de la modification de la signature.' }); } } else if (subcommand === 'reset') { await interaction.deferReply({ ephemeral: true }); try { // Vérifier si le profil existe const [profiles] = await db.query( 'SELECT * FROM user_profiles WHERE userId = ? AND guildId = ?', [interaction.user.id, interaction.guild.id] ); if (profiles.length === 0) { return interaction.editReply({ content: '❌ Tu n\'as pas de signature à réinitialiser.' }); } // Réinitialiser la signature await db.query( 'UPDATE user_profiles SET signature = NULL, updatedAt = ? WHERE userId = ? AND guildId = ?', [Date.now(), interaction.user.id, interaction.guild.id] ); const embed = new EmbedBuilder() .setTitle('✅ Signature Réinitialisée') .setColor(colors.success) .setDescription('Ta signature a été réinitialisée.') .setTimestamp(); await interaction.editReply({ embeds: [embed] }); } catch (err) { console.error('Erreur lors de la réinitialisation de la signature:', err); await interaction.editReply({ content: '❌ Erreur lors de la réinitialisation de la signature.' }); } } }, };