const { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits } = require('discord.js'); const { clashRoyaleAPI } = require('../services/clashRoyaleService'); const { UserProfileService } = require('../utils/database'); module.exports = { data: new SlashCommandBuilder() .setName('sync') .setDescription('Associer votre profil Clash Royale à votre compte Discord') .addStringOption(option => option .setName('id') .setDescription('Votre tag Clash Royale (ex: #ABC123DEF)') .setRequired(true) ), async execute(interaction, client) { await interaction.deferReply({ ephemeral: true }); try { // Vérification du rôle requis const requiredRoleId = process.env.CLASH_ROYALE_ROLE_ID; if (!interaction.member.roles.cache.has(requiredRoleId)) { const errorEmbed = new EmbedBuilder() .setColor('#FF0000') .setTitle('❌ Accès refusé') .setDescription('Vous devez avoir le rôle requis pour utiliser cette commande.') .addFields([ { name: 'Rôle requis', value: `<@&${requiredRoleId}>`, inline: true } ]) .setTimestamp(); await interaction.editReply({ embeds: [errorEmbed] }); return; } const clashTag = interaction.options.getString('id'); const discordId = interaction.user.id; client.logger.clash(`Tentative de synchronisation: ${interaction.user.tag} -> ${clashTag}`); // Vérifier si l'utilisateur a déjà un profil synchronisé const existingProfile = await UserProfileService.getByDiscordId(discordId); // Vérifier si le tag Clash Royale est déjà utilisé par quelqu'un d'autre const existingClashProfile = await UserProfileService.getByClashTag(clashTag); if (existingClashProfile && existingClashProfile.discord_id !== discordId) { const conflictEmbed = new EmbedBuilder() .setColor('#FF6B00') .setTitle('⚠️ Tag déjà utilisé') .setDescription('Ce tag Clash Royale est déjà associé à un autre utilisateur Discord.') .addFields([ { name: 'Tag Clash Royale', value: `\`${clashTag}\``, inline: true }, { name: 'Solution', value: 'Vérifiez que vous avez entré le bon tag ou contactez un administrateur.', inline: false } ]) .setTimestamp(); await interaction.editReply({ embeds: [conflictEmbed] }); return; } // Valider le profil Clash Royale via l'API const validationResult = await clashRoyaleAPI.validatePlayer(clashTag); if (!validationResult.valid) { let errorMessage = 'Tag Clash Royale invalide ou joueur non trouvé.'; let errorTitle = '❌ Profil non trouvé'; switch (validationResult.error.type) { case 'NOT_FOUND': errorMessage = 'Aucun joueur trouvé avec ce tag. Vérifiez que vous avez entré le bon tag.'; break; case 'BAD_REQUEST': errorMessage = 'Format de tag invalide. Utilisez le format #ABC123DEF.'; break; case 'RATE_LIMITED': errorMessage = 'Trop de requêtes à l\'API. Réessayez dans quelques minutes.'; errorTitle = '⏳ Limite atteinte'; break; case 'SERVICE_UNAVAILABLE': errorMessage = 'API Clash Royale temporairement indisponible. Réessayez plus tard.'; errorTitle = '🛠️ Maintenance'; break; } const errorEmbed = new EmbedBuilder() .setColor('#FF0000') .setTitle(errorTitle) .setDescription(errorMessage) .addFields([ { name: 'Tag fourni', value: `\`${clashTag}\``, inline: true }, { name: 'Aide', value: 'Le tag se trouve dans votre profil Clash Royale, sous votre nom.', inline: false } ]) .setTimestamp(); await interaction.editReply({ embeds: [errorEmbed] }); return; } const playerData = validationResult.data; // Créer ou mettre à jour le profil dans la base de données const profile = await UserProfileService.createOrUpdate(discordId, playerData); client.logger.success(`Profil synchronisé: ${playerData.name} (${playerData.tag})`); // Déterminer si c'est une nouvelle synchronisation ou une mise à jour const isNewSync = !existingProfile; const actionText = isNewSync ? 'synchronisé' : 'mis à jour'; const actionEmoji = isNewSync ? '🎉' : '🔄'; // Créer l'embed de confirmation const successEmbed = new EmbedBuilder() .setColor('#00FF00') .setTitle(`${actionEmoji} Profil ${actionText} avec succès !`) .setDescription(`Votre compte Discord est maintenant associé à votre profil Clash Royale.`) .setThumbnail(interaction.user.displayAvatarURL({ dynamic: true })) .addFields([ { name: '👤 Nom du joueur', value: playerData.name, inline: true }, { name: '🏷️ Tag Clash Royale', value: `\`${playerData.tag}\``, inline: true }, { name: '🏆 Trophées actuels', value: `${playerData.trophies.toLocaleString()}`, inline: true }, { name: '🥇 Meilleur score', value: `${playerData.bestTrophies.toLocaleString()}`, inline: true }, { name: '⭐ Niveau', value: `${playerData.expLevel}`, inline: true }, { name: '🏰 Clan', value: playerData.clan ? `${playerData.clan.name}\n\`${playerData.clan.tag}\`\n*${playerData.clan.role}*` : 'Aucun clan', inline: true } ]) .addFields([ { name: '✨ Fonctionnalités disponibles', value: '• Classement automatique du serveur\n• Félicitations pour les gains de trophées\n• Statistiques personnalisées\n• Comparaisons avec les autres membres', inline: false } ]) .setFooter({ text: `${isNewSync ? 'Première synchronisation' : 'Profile mis à jour'} • Clash Royale Bot`, iconURL: client.user.displayAvatarURL() }) .setTimestamp(); await interaction.editReply({ embeds: [successEmbed] }); // Log dans le canal de logs si configuré try { const logChannel = client.channels.cache.get(process.env.LOGS_CHANNEL_ID); if (logChannel) { const logEmbed = new EmbedBuilder() .setColor('#00BFFF') .setTitle('📊 Nouvelle synchronisation') .setDescription(`Un utilisateur a ${actionText} son profil Clash Royale`) .addFields([ { name: 'Utilisateur Discord', value: `${interaction.user.tag} (<@${interaction.user.id}>)`, inline: true }, { name: 'Joueur Clash Royale', value: `${playerData.name} (\`${playerData.tag}\`)`, inline: true }, { name: 'Trophées', value: `${playerData.trophies.toLocaleString()}`, inline: true } ]) .setTimestamp(); await logChannel.send({ embeds: [logEmbed] }); } } catch (error) { client.logger.warning('Impossible d\'envoyer le log de synchronisation'); } } catch (error) { client.logger.error(`Erreur lors de la synchronisation: ${error.message}`); const errorEmbed = new EmbedBuilder() .setColor('#FF0000') .setTitle('❌ Erreur interne') .setDescription('Une erreur s\'est produite lors de la synchronisation. Veuillez réessayer.') .addFields([ { name: 'Code d\'erreur', value: `\`${error.message}\``, inline: false } ]) .setTimestamp(); await interaction.editReply({ embeds: [errorEmbed] }); } } };