const { SlashCommandBuilder, MessageFlags } = require('discord.js'); const fs = require('node:fs/promises'); const path = require('node:path'); const ROLE_RYGAINLAND = '1444684935632912394'; const KEEP_LIST_FILE_PATH = path.resolve(__dirname, 'server-clean-keep.json'); const normUid32 = (val) => { if (!val) return ''; const s = String(val).replace(/-/g, '').trim().toLowerCase(); if (s.length !== 32) return ''; if (!/^[0-9a-f]{32}$/.test(s)) return ''; return s; }; async function readKeepList() { try { const raw = await fs.readFile(KEEP_LIST_FILE_PATH, 'utf8'); const parsed = JSON.parse(raw); const discordIds = Array.isArray(parsed.discordIds) ? parsed.discordIds.map((x) => String(x || '').trim()).filter(Boolean) : []; const playerIds = Array.isArray(parsed.playerIds) ? parsed.playerIds.map(normUid32).filter(Boolean) : []; return { discordIds: [...new Set(discordIds)], playerIds: [...new Set(playerIds)], }; } catch (error) { if (error && error.code === 'ENOENT') { return { discordIds: [], playerIds: [] }; } throw error; } } async function writeKeepList(keepList) { const payload = { discordIds: [...new Set((keepList.discordIds || []).map((x) => String(x || '').trim()).filter(Boolean))], playerIds: [...new Set((keepList.playerIds || []).map(normUid32).filter(Boolean))], }; await fs.writeFile(KEEP_LIST_FILE_PATH, JSON.stringify(payload, null, 2), 'utf8'); } module.exports = { data: new SlashCommandBuilder() .setName('server-clean-keep') .setDescription('Gérer la liste blanche des joueurs protégés du /server-clean') .addSubcommand((sub) => sub .setName('list') .setDescription('Afficher la liste blanche actuelle') ) .addSubcommand((sub) => sub .setName('add-discord') .setDescription('Ajouter un compte Discord à la liste blanche') .addUserOption((opt) => opt .setName('membre') .setDescription('Compte Discord à protéger') .setRequired(true) ) ) .addSubcommand((sub) => sub .setName('remove-discord') .setDescription('Retirer un compte Discord de la liste blanche') .addUserOption((opt) => opt .setName('membre') .setDescription('Compte Discord à retirer') .setRequired(true) ) ) .addSubcommand((sub) => sub .setName('add-player') .setDescription('Ajouter un Player ID Palworld à la liste blanche') .addStringOption((opt) => opt .setName('player-id') .setDescription('UID hexadécimal (32 caractères)') .setRequired(true) ) ) .addSubcommand((sub) => sub .setName('remove-player') .setDescription('Retirer un Player ID Palworld de la liste blanche') .addStringOption((opt) => opt .setName('player-id') .setDescription('UID hexadécimal (32 caractères)') .setRequired(true) ) ), async execute(interaction) { if (!interaction.member.roles.cache.has(ROLE_RYGAINLAND)) { await interaction.reply({ content: '❌ Il faut avoir le rôle Rygainland pour utiliser cette commande.', flags: MessageFlags.Ephemeral, }); return; } const sub = interaction.options.getSubcommand(); try { const keepList = await readKeepList(); if (sub === 'list') { const discordText = keepList.discordIds.length ? keepList.discordIds.map((id) => `- <@${id}> (${id})`).join('\n') : '- (vide)'; const playerText = keepList.playerIds.length ? keepList.playerIds.map((id) => `- ${id}`).join('\n') : '- (vide)'; await interaction.reply({ content: '🛡️ Liste blanche /server-clean\n\n' + `Discord IDs (${keepList.discordIds.length})\n${discordText}\n\n` + `Player IDs (${keepList.playerIds.length})\n${playerText}`, flags: MessageFlags.Ephemeral, }); return; } if (sub === 'add-discord') { const user = interaction.options.getUser('membre', true); if (!keepList.discordIds.includes(user.id)) { keepList.discordIds.push(user.id); await writeKeepList(keepList); await interaction.reply({ content: `✅ Ajouté à la liste blanche Discord: <@${user.id}> (${user.id})`, flags: MessageFlags.Ephemeral, }); return; } await interaction.reply({ content: `ℹ️ Déjà présent dans la liste blanche Discord: <@${user.id}>`, flags: MessageFlags.Ephemeral, }); return; } if (sub === 'remove-discord') { const user = interaction.options.getUser('membre', true); const before = keepList.discordIds.length; keepList.discordIds = keepList.discordIds.filter((id) => id !== user.id); if (keepList.discordIds.length !== before) { await writeKeepList(keepList); await interaction.reply({ content: `✅ Retiré de la liste blanche Discord: <@${user.id}> (${user.id})`, flags: MessageFlags.Ephemeral, }); return; } await interaction.reply({ content: `ℹ️ Ce compte n'était pas dans la liste blanche Discord: <@${user.id}>`, flags: MessageFlags.Ephemeral, }); return; } if (sub === 'add-player') { const raw = interaction.options.getString('player-id', true); const uid = normUid32(raw); if (!uid) { await interaction.reply({ content: '❌ Player ID invalide. Format attendu: 32 caractères hexadécimaux.', flags: MessageFlags.Ephemeral, }); return; } if (!keepList.playerIds.includes(uid)) { keepList.playerIds.push(uid); await writeKeepList(keepList); await interaction.reply({ content: `✅ Player ID ajouté à la liste blanche: ${uid}`, flags: MessageFlags.Ephemeral, }); return; } await interaction.reply({ content: `ℹ️ Player ID déjà présent dans la liste blanche: ${uid}`, flags: MessageFlags.Ephemeral, }); return; } if (sub === 'remove-player') { const raw = interaction.options.getString('player-id', true); const uid = normUid32(raw); if (!uid) { await interaction.reply({ content: '❌ Player ID invalide. Format attendu: 32 caractères hexadécimaux.', flags: MessageFlags.Ephemeral, }); return; } const before = keepList.playerIds.length; keepList.playerIds = keepList.playerIds.filter((id) => id !== uid); if (keepList.playerIds.length !== before) { await writeKeepList(keepList); await interaction.reply({ content: `✅ Player ID retiré de la liste blanche: ${uid}`, flags: MessageFlags.Ephemeral, }); return; } await interaction.reply({ content: `ℹ️ Player ID non trouvé dans la liste blanche: ${uid}`, flags: MessageFlags.Ephemeral, }); return; } await interaction.reply({ content: '❌ Sous-commande inconnue.', flags: MessageFlags.Ephemeral, }); } catch (error) { console.error('Erreur server-clean-keep:', error); await interaction.reply({ content: `❌ Erreur: ${error.message || String(error)}`, flags: MessageFlags.Ephemeral, }).catch(() => {}); } }, };