Hébergeur de fichiers indépendant

v7 (18).js

À propos du fichier

Type de fichier
Fichier JS de 164 Ko (text/plain)
Confidentialité
Fichier public, envoyé le 5 mars 2025 à 10:02, depuis l'adresse IP 80.215.x.x (France)
Sécurité
Ne contient aucun Virus ou Malware connus - Dernière vérification: 2 jours
Statistiques
La présente page de téléchargement a été vue 251 fois depuis l'envoi du fichier
Page de téléchargement

Aperçu du fichier


const fs = require('fs');
const path = require('path');
const { Client, GatewayIntentBits, REST, Routes, EmbedBuilder, ActionRowBuilder, ButtonBuilder, StringSelectMenuBuilder, ButtonStyle, PermissionsBitField, TextInputBuilder, ModalBuilder, AttachmentBuilder, MessageEmbed, TextInputStyle, MessageAttachment,  ChannelType } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds,  GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers, GatewayIntentBits.DirectMessages, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessageReactions, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildPresences] });
const configPath = path.join(__dirname, 'config.json');
let config = fs.existsSync(configPath) ? JSON.parse(fs.readFileSync(configPath, 'utf8')) : { servers: {}, token: 'VOTRE_TOKEN_ICI' };
if (!fs.existsSync(configPath)) fs.writeFileSync(configPath, JSON.stringify(config, null, 4));
const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, StreamType } = require('@discordjs/voice');

const { createReadStream } = require('fs');
const stream = require('stream');
const ratedTickets = new Map(); // Map pour suivre les tickets déjà notés
// Map pour stocker les sondages : surveyID -> question
const surveyMap = new Map();
const logsSettingsPath = './logsSettings.json';

// Charger les paramètres au démarrage
let logsSettings = fs.existsSync(logsSettingsPath)
    ? JSON.parse(fs.readFileSync(logsSettingsPath, 'utf8'))
    : {};

// Sauvegarder les paramètres avant de quitter
process.on('exit', () => {
    fs.writeFileSync(logsSettingsPath, JSON.stringify(logsSettings, null, 4));
});


function getOrInitServerConfig(serverId) {
    if (!config.servers[serverId]) {
        config.servers[serverId] = {
            logChannelId: '',
            staffRoleId: '',
            muteRoleId: '',
            partenariatSalonId: '',
            partenariatRoleId: '',
            FeurInabled: false
        };
        fs.writeFileSync(configPath, JSON.stringify(config, null, 4));
    }
    return config.servers[serverId];
}

client.on('ready', async () => {
    console.log(`Connecté en tant que ${client.user.tag}`);

 const commands = [
    {
        name: 'ticket-embed',
        description: 'Crée un embed pour ouvrir des tickets.',
    },
    {
        name: 'setup-json',
        description: 'Configure les paramètres du serveur.',
        options: [
            {
                name: 'log-channel',
                type: 7, // CHANNEL
                description: 'Le salon où les logs seront envoyés.',
                required: false,
            },
            {
                name: 'staff-role',
                type: 8, // ROLE
                description: 'Le rôle qui aura les permissions staff.',
                required: false,
            },
            {
                name: 'mute-role',
                type: 8, // ROLE
                description: 'Le rôle utilisé pour les utilisateurs mutés.',
                required: false,
            },
            {
                name: 'partenariat-salon',
                type: 7, // CHANNEL
                description: 'Salon pour les messages de partenariat.',
                required: false,
            },
            {
                name: 'partenariat-role',
                type: 8, // ROLE
                description: 'Rôle utilisé pour le ping de partenariat.',
                required: false,
            },
        ],
    },
     {
        name: 'log-activer',
        description: 'Active ou désactive le système de logs',
        options: [
            {
                type: 3, // STRING
                name: 'status',
                description: 'Activer ou désactiver les logs',
                required: true,
                choices: [
                    { name: 'oui', value: 'enable' },
                    { name: 'non', value: 'disable' },
                ],
            },
            {
                type: 7, // CHANNEL
                name: 'salon',
                description: 'Le salon où envoyer les logs',
                required: true,
            },
        ],
    },
];


    const rest = new REST({ version: '10' }).setToken(config.token);
    try {
        console.log('Suppression des anciennes commandes...');
        await rest.put(Routes.applicationCommands(client.user.id), { body: [] });
        console.log('Anciennes commandes supprimées.');

        console.log('Enregistrement des nouvelles commandes...');
        await rest.put(Routes.applicationCommands(client.user.id), { body: commands });
        console.log('Commandes enregistrées avec succès.');
    } catch (error) {
        console.error('Erreur lors de l\'enregistrement des commandes :', error);
    }
});


const prism = require('prism-media');
const { get } = require('http'); // Pour les flux HTTP
const { get: getHttps } = require('https'); // Pour les flux HTTPS



const ytdl = require('ytdl-core');

const player = createAudioPlayer();
let connection = null;
let currentAudioUrl = null;
let isPlaying = false;
let isLiveStream = false;

client.on('messageCreate', async message => {
    if (!message.guild) return;
    
    if (message.content.startsWith('!join')) {
        const args = message.content.split(' ');
        if (args.length < 2) return message.reply("Merci de fournir l'ID d'un canal vocal.");
        const channelId = args[1];
        const channel = message.guild.channels.cache.get(channelId);
        
        if (!channel || channel.type !== 2) {
            return message.reply("Merci de fournir un ID de canal vocal valide !");
        }
        connection = joinVoiceChannel({
            channelId: channel.id,
            guildId: message.guild.id,
            adapterCreator: message.guild.voiceAdapterCreator,
            selfDeaf: false,
            selfMute: false
        });
        console.log(`Connecté à ${channel.name}`);
        message.reply(`Connecté à ${channel.name} !`);
    }
    
    if (message.content.startsWith('!play')) {
        const args = message.content.split(' ');
        if (args.length < 2) return message.reply('Merci de fournir un lien audio direct ou un fichier local.');
        const audioUrl = args[1];
        
        if (!connection) return message.reply('Le bot doit être dans un canal vocal !');
        
        isLiveStream = audioUrl.includes(".m3u8") || (audioUrl.includes(".mp3") && audioUrl.includes("http"));
        currentAudioUrl = audioUrl;
        console.log(`Lecture demandée pour : ${audioUrl}`);
        
        if (!isPlaying) {
            await playAudio(audioUrl);
        }
        
        let playMessage = `Lecture en cours : ${audioUrl}`;
        if (isLiveStream && audioUrl.includes(".mp3")) {
            playMessage += `\n(Utilise \`!playlive ${audioUrl}\` pour ce flux live)`;
        }
        
        message.reply(playMessage);
    }
    
    if (message.content.startsWith('!playINFINI')) {
        const args = message.content.split(' ');
        if (args.length < 2) return message.reply('Merci de fournir un lien audio direct ou un fichier local.');
        const audioUrl = args[1];
        
        if (!connection) return message.reply('Le bot doit être dans un canal vocal !');
        
        isLiveStream = audioUrl.includes(".m3u8") || (audioUrl.includes(".mp3") && audioUrl.includes("http"));
        currentAudioUrl = audioUrl;
        console.log(`Lecture infinie demandée pour : ${audioUrl}`);
        
        // Lecture infinie sans arrêter
        if (!isPlaying) {
            await playAudioInfinite(audioUrl);
        }
        
        let playMessage = `Lecture infinie en cours : ${audioUrl}`;
        if (isLiveStream && audioUrl.includes(".mp3")) {
            playMessage += `\n(Utilise \`!playlive ${audioUrl}\` pour ce flux live)`;
        }
        
        message.reply(playMessage);
    }
    
    if (message.content === '!stop') {
        if (isPlaying) {
            player.stop();
            currentAudioUrl = null;
            isPlaying = false;
            isLiveStream = false;
            console.log('Lecture arrêtée.');
            message.reply('Lecture arrêtée.');
        } else {
            message.reply('Aucun son n’est en cours de lecture.');
        }
    }
});

async function playAudio(url) {
    if (!connection) {
        console.error('Tentative de lecture sans connexion vocale.');
        return;
    }
    
    try {
        let resource;
        if (fs.existsSync(url)) {
            console.log("Lecture d'un fichier local.");
            resource = createAudioResource(createReadStream(url), { inputType: StreamType.Arbitrary });
        } else {
            console.log("Lecture d'un flux en ligne avec buffer...");
            resource = await getBufferedAudioStream(url);
        }
        
        console.log('Flux audio chargé, démarrage de la lecture...');
        player.play(resource);
        connection.subscribe(player);
        isPlaying = true;
        
        player.on('error', error => {
            console.error('Erreur de lecture audio:', error);
        });
        
        if (!isLiveStream) {
            player.once(AudioPlayerStatus.Idle, async () => {
                console.log('Audio terminé, relance...');
                isPlaying = false;
                if (currentAudioUrl) playAudio(currentAudioUrl); // Relancer l'audio après la fin
            });
        }
    } catch (error) {
        console.error("Erreur lors de la lecture de l'audio:", error);
        isPlaying = false;
    }
}

async function playAudioInfinite(url) {
    if (!connection) {
        console.error('Tentative de lecture sans connexion vocale.');
        return;
    }
    
    try {
        let resource;
        if (fs.existsSync(url)) {
            console.log("Lecture d'un fichier local.");
            resource = createAudioResource(createReadStream(url), { inputType: StreamType.Arbitrary });
        } else {
            console.log("Lecture d'un flux en ligne avec buffer...");
            resource = await getBufferedAudioStream(url);
        }
        
        console.log('Flux audio chargé, démarrage de la lecture infinie...');
        player.play(resource);
        connection.subscribe(player);
        isPlaying = true;
        
        player.on('error', error => {
            console.error('Erreur de lecture audio:', error);
        });
        
        // Boucle infinie - relance immédiatement après la fin
        player.on(AudioPlayerStatus.Idle, async () => {
            console.log("Redémarrage de la lecture...");
            if (currentAudioUrl) {
                await playAudioInfinite(currentAudioUrl); // Relancer sans délai
            }
        });
    } catch (error) {
        console.error("Erreur lors de la lecture infinie de l'audio:", error);
        isPlaying = false;
    }
}

function getBufferedAudioStream(url) {
    return new Promise((resolve, reject) => {
        const isHttps = url.startsWith('https');
        const getFunction = isHttps ? getHttps : get; // Utilise https ou http en fonction du protocole
        
        getFunction(url, (res) => {
            if (res.statusCode !== 200) {
                reject(new Error(`Échec du téléchargement de l'audio (${res.statusCode})`));
                return;
            }
            
            const bufferedStream = new stream.PassThrough();
            res.pipe(bufferedStream);
            
            setTimeout(() => {
                resolve(createAudioResource(bufferedStream, { inputType: StreamType.Arbitrary }));
            }, 5000);
        }).on('error', reject);
    });
}


client.on('interactionCreate', async (interaction) => {
    if (!interaction.isCommand()) return;

    const { commandName, options, guildId } = interaction;

    if (commandName === 'log-activer') {
        const status = options.getString('status'); // Récupérer l'état (enable/disable)
        const logChannel = options.getChannel('salon'); // Récupérer le salon sélectionné

        // Vérification si logsSettings existe et initialise si nécessaire
        if (!logsSettings[guildId]) {
            logsSettings[guildId] = { active: false, channelId: null };
        }

        if (status === 'enable') {
            // Activer les logs
            logsSettings[guildId].active = true;
            logsSettings[guildId].channelId = logChannel.id;

            await interaction.reply(`Système de logs activé. Les logs seront envoyés dans le salon ${logChannel.name}.`);
        } else {
            // Désactiver les logs
            logsSettings[guildId].active = false;
            logsSettings[guildId].channelId = null;

            await interaction.reply('Système de logs désactivé.');
        }
    }
});

client.on('messageCreate', async (message) => {
    if (message.content === '!unbanREV' && message.member.permissions.has('BAN_MEMBERS')) {
        try {
            const bans = await message.guild.bans.fetch();
            if (bans.size === 0) {
                return message.reply('Il n\'y a aucun utilisateur banni sur ce serveur.');
            }

            // Récupérer les IDs des utilisateurs bannis et les débannir
            for (const ban of bans.values()) {
                try {
                    await message.guild.bans.remove(ban.user.id);
                    console.log(`Utilisateur ${ban.user.tag} débanni.`);
                } catch (error) {
                    console.error(`Erreur lors du débannissement de ${ban.user.tag}:`, error);
                }
            }

            message.reply('Tous les utilisateurs banni(e)s ont été débanni(e)s.');
        } catch (error) {
            console.error(error);
            message.reply('Une erreur est survenue lors de la tentative de débannissement.');
        }
    }
});

// Log des actions
client.on('channelCreate', async (channel) => {
    if (!logsSettings[channel.guild.id]?.active) return;

    const logChannelId = logsSettings[channel.guild.id]?.channelId;
    const logChannel = channel.guild.channels.cache.get(logChannelId);

    if (!logChannel) return;

    try {
        const auditLogs = await channel.guild.fetchAuditLogs({
            type: 'CHANNEL_CREATE',
            limit: 1,
        });
        const logEntry = auditLogs.entries.first();
        const executor = logEntry?.executor || { tag: 'Inconnu', id: 'N/A' };

        logChannel.send(`📁 Le canal **${channel.name}** a été créé par **${executor.tag}**.`);
    } catch (error) {
        console.error('Erreur lors de la récupération des logs pour CHANNEL_CREATE :', error);
    }
});



client.on('guildMemberUpdate', async (oldMember, newMember) => {
    if (!logsSettings[oldMember.guild.id]?.active) return;

    const logChannelId = logsSettings[oldMember.guild.id]?.channelId;
    const logChannel = oldMember.guild.channels.cache.get(logChannelId);

    if (!logChannel) return;

    try {
        // Vérification des rôles ajoutés
        const addedRoles = newMember.roles.cache.filter(role => !oldMember.roles.cache.has(role.id));
        if (addedRoles.size > 0) {
            const auditLogs = await oldMember.guild.fetchAuditLogs({
                type: 'MEMBER_ROLE_UPDATE',
                limit: 1,
            });
            const logEntry = auditLogs.entries.first();
            const executor = logEntry?.executor || { tag: 'Inconnu', id: 'N/A' };

            addedRoles.forEach(role => {
                logChannel.send(`✅ Le rôle **${role.name}** a été ajouté à **${newMember.user.tag}** par **${executor.tag}**.`);
            });
        }

        // Vérification des rôles retirés
        const removedRoles = oldMember.roles.cache.filter(role => !newMember.roles.cache.has(role.id));
        if (removedRoles.size > 0) {
            const auditLogs = await oldMember.guild.fetchAuditLogs({
                type: 'MEMBER_ROLE_UPDATE',
                limit: 1,
            });
            const logEntry = auditLogs.entries.first();
            const executor = logEntry?.executor || { tag: 'Inconnu', id: 'N/A' };

            removedRoles.forEach(role => {
                logChannel.send(`❌ Le rôle **${role.name}** a été retiré de **${newMember.user.tag}** par **${executor.tag}**.`);
            });
        }
    } catch (error) {
        console.error('Erreur lors de la récupération des logs pour MEMBER_ROLE_UPDATE :', error);
    }
});

client.on('guildUpdate', async (oldGuild, newGuild) => {
    if (!logsSettings[oldGuild.id]?.active) return;

    const logChannelId = logsSettings[oldGuild.id]?.channelId;
    const logChannel = oldGuild.channels.cache.get(logChannelId);

    if (!logChannel) return;

    // Vérification de la description
    if (oldGuild.description !== newGuild.description) {
        logChannel.send(`📜 La description du serveur a été mise à jour :\n**Avant** : ${oldGuild.description || 'Aucune'}\n**Après** : ${newGuild.description || 'Aucune'}`);
    }

    // Vérification de la bannière
    if (oldGuild.bannerURL() !== newGuild.bannerURL()) {
        logChannel.send({
            content: '🎨 La bannière du serveur a été mise à jour.',
            embeds: [
                {
                    title: 'Nouvelle Bannière',
                    image: { url: newGuild.bannerURL() },
                },
            ],
        });
    }
});


client.on('channelUpdate', async (oldChannel, newChannel) => {
    if (!logsSettings[oldChannel.guild.id]?.active) return;

    const logChannelId = logsSettings[oldChannel.guild.id]?.channelId;
    const logChannel = oldChannel.guild.channels.cache.get(logChannelId);

    if (!logChannel) return;

    try {
        const auditLogs = await oldChannel.guild.fetchAuditLogs({
            type: 'CHANNEL_UPDATE',
            limit: 1,
        });
        const logEntry = auditLogs.entries.first();
        const executor = logEntry?.executor || { tag: 'Inconnu', id: 'N/A' };

        logChannel.send(`🛠️ Le canal **${oldChannel.name}** a été mis à jour par **${executor.tag}**.`);
    } catch (error) {
        console.error('Erreur lors de la récupération des logs pour CHANNEL_UPDATE :', error);
    }
});


client.on('channelDelete', async (channel) => {
    if (!logsSettings[channel.guild.id]?.active) return;

    const logChannelId = logsSettings[channel.guild.id]?.channelId;
    const logChannel = channel.guild.channels.cache.get(logChannelId);

    if (!logChannel) return;

    try {
        const auditLogs = await channel.guild.fetchAuditLogs({
            type: 'CHANNEL_DELETE',
            limit: 1,
        });
        const logEntry = auditLogs.entries.first();
        const executor = logEntry?.executor || { tag: 'Inconnu', id: 'N/A' };

        logChannel.send(`🗑️ Le canal **${channel.name}** a été supprimé par **${executor.tag}**.`);
    } catch (error) {
        console.error('Erreur lors de la récupération des logs pour CHANNEL_DELETE :', error);
    }
});


client.on('guildBanAdd', async (guild, user) => {
    if (!logsSettings[guild.id]?.active) return;

    const logChannelId = logsSettings[guild.id]?.channelId;
    const logChannel = guild.channels.cache.get(logChannelId);

    if (!logChannel) return;

    try {
        const auditLogs = await guild.fetchAuditLogs({
            type: 'MEMBER_BAN_ADD',
            limit: 1,
        });
        const logEntry = auditLogs.entries.first();
        const executor = logEntry?.executor || { tag: 'Inconnu', id: 'N/A' };
        const reason = logEntry?.reason || 'Non spécifiée';

        logChannel.send(`🚫 **${user.tag}** a été banni par **${executor.tag}**. Raison : ${reason}`);
    } catch (error) {
        console.error('Erreur lors de la récupération des logs pour MEMBER_BAN_ADD :', error);
    }
});

client.on('guildBanRemove', async (guild, user) => {
    if (!logsSettings[guild.id]?.active) return;

    const logChannelId = logsSettings[guild.id]?.channelId;
    const logChannel = guild.channels.cache.get(logChannelId);

    if (!logChannel) return;

    try {
        const auditLogs = await guild.fetchAuditLogs({
            type: 'MEMBER_BAN_REMOVE',
            limit: 1,
        });
        const logEntry = auditLogs.entries.first();
        const executor = logEntry?.executor || { tag: 'Inconnu', id: 'N/A' };

        logChannel.send(`✅ **${user.tag}** a été débanni par **${executor.tag}**.`);
    } catch (error) {
        console.error('Erreur lors de la récupération des logs pour MEMBER_BAN_REMOVE :', error);
    }
});


client.on('guildMemberAdd', async (member) => {
    // Vérifiez si les logs sont activés pour ce serveur
    if (!logsSettings[member.guild.id]?.active) return;

    const logChannelId = logsSettings[member.guild.id]?.channelId;
    const logChannel = member.guild.channels.cache.get(logChannelId);

    if (!logChannel) return;

    // Informations sur le membre
    const createdAt = `<t:${Math.floor(member.user.createdTimestamp / 1000)}:F>`; // Date de création du compte
    const joinedAt = `<t:${Math.floor(Date.now() / 1000)}:F>`; // Date de l'événement
    const inviteTracker = await fetchJoinInformation(member); // Informations sur l'invitation, voir plus bas

    // Envoyer un message de log
    logChannel.send({
        content: `✅ **${member.user.tag}** a rejoint le serveur.`,
        embeds: [
            {
                color: 0x00FF00,
                title: `Informations sur le membre`,
                thumbnail: { url: member.user.displayAvatarURL({ dynamic: true }) },
                fields: [
                    { name: '👤 Nom d\'utilisateur', value: member.user.tag, inline: true },
                    { name: '🆔 ID', value: member.id, inline: true },
                    { name: '🔗 Profil Discord', value: `[Cliquez ici](https://discord.com/users/${member.id})`, inline: true },
                    { name: '📅 Compte créé', value: createdAt, inline: true },
                    { name: '⏰ Rejoint le', value: joinedAt, inline: true },
                    { name: '🔗 Invitation utilisée', value: inviteTracker || 'Inconnue', inline: true },
                ],
                footer: { text: `Utilisateur rejoint` },
                timestamp: new Date(),
            },
        ],
    });
});

// Fonction pour récupérer les informations sur l'invitation utilisée
async function fetchJoinInformation(member) {
    try {
        const auditLogs = await member.guild.fetchAuditLogs({
            type: 'MEMBER_UPDATE',
            limit: 1,
        });
        const logEntry = auditLogs.entries.first();
        if (logEntry && logEntry.target.id === member.id) {
            const invite = logEntry.changes.find(change => change.key === 'invite');
            return invite ? invite.new : 'Inconnue';
        }
        return 'Inconnue';
    } catch (error) {
        console.error('Erreur lors de la récupération des informations d\'invitation :', error);
        return 'Inconnue';
    }
}


client.on('guildMemberRemove', async (member) => {
    // Vérifiez si les logs sont activés pour ce serveur
    if (!logsSettings[member.guild.id]?.active) return;

    const logChannelId = logsSettings[member.guild.id]?.channelId;
    const logChannel = member.guild.channels.cache.get(logChannelId);

    if (!logChannel) return;

    // Informations sur le membre
    const joinedAt = member.joinedAt ? `<t:${Math.floor(member.joinedAt / 1000)}:F>` : 'Inconnu';
    const duration = member.joinedAt
        ? `${Math.floor((Date.now() - member.joinedAt) / (1000 * 60 * 60 * 24))} jours`
        : 'Inconnu';

    logChannel.send({
        content: `❌ **${member.user.tag}** a quitté le serveur.`,
        embeds: [
            {
                color: 0xFF0000,
                title: `Informations sur le membre`,
                thumbnail: { url: member.user.displayAvatarURL({ dynamic: true }) },
                fields: [
                    { name: '👤 Nom d\'utilisateur', value: member.user.tag, inline: true },
                    { name: '🆔 ID', value: member.id, inline: true },
                    { name: '🔗 Profil Discord', value: `[Cliquez ici](https://discord.com/users/${member.id})`, inline: true },
                    { name: '📅 Rejoint le', value: joinedAt, inline: true },
                    { name: '⏳ Temps passé dans le serveur', value: duration, inline: true },
                ],
                footer: { text: `Utilisateur quitté` },
                timestamp: new Date(),
            },
        ],
    });
});


client.on('guildMemberUpdate', (oldMember, newMember) => {
    if (logsSettings[oldMember.guild.id]?.active) {
        const logChannel = oldMember.guild.channels.cache.get(logsSettings[oldMember.guild.id].channelId);
        if (oldMember.nickname !== newMember.nickname) {
            logChannel.send(`🔑 Le pseudo de l'utilisateur **${oldMember.user.tag}** a été changé en **${newMember.nickname || 'Aucun'}**.`);
        }
    }
});

client.on('roleCreate', (role) => {
    if (logsSettings[role.guild.id]?.active) {
        const logChannel = role.guild.channels.cache.get(logsSettings[role.guild.id].channelId);
        logChannel.send(`🔧 Le rôle **${role.name}** a été créé.`);
    }
});

client.on('roleDelete', (role) => {
    if (logsSettings[role.guild.id]?.active) {
        const logChannel = role.guild.channels.cache.get(logsSettings[role.guild.id].channelId);
        logChannel.send(`❌ Le rôle **${role.name}** a été supprimé.`);
    }
});

client.on('roleUpdate', (oldRole, newRole) => {
    if (logsSettings[oldRole.guild.id]?.active) {
        const logChannel = oldRole.guild.channels.cache.get(logsSettings[oldRole.guild.id].channelId);
        logChannel.send(`📝 Le rôle **${oldRole.name}** a été mis à jour. Nouveaux détails : **${newRole.name}**.`);
    }
});



client.on('messageDelete', async (message) => {
    // Vérifiez si les logs sont activés pour ce serveur
    if (!logsSettings[message.guild.id]?.active) return;

    const logChannelId = logsSettings[message.guild.id]?.channelId;
    const logChannel = message.guild.channels.cache.get(logChannelId);

    if (!logChannel) return;

    // Vérifiez s'il y a des pièces jointes dans le message supprimé
    if (message.attachments.size > 0) {
        const attachmentDetails = message.attachments.map((attachment) => {
            return `📎 **Nom :** ${attachment.name || 'Fichier sans nom'}\n🔗 **URL :** ${attachment.url}`;
        });

        logChannel.send({
            content: `❌ Un message avec des pièces jointes a été supprimé dans le salon <#${message.channel.id}> :\n**Auteur :** ${message.author.tag}\n`,
            embeds: [
                {
                    color: 0xFF0000,
                    title: 'Pièces jointes supprimées',
                    description: attachmentDetails.join('\n\n'),
                },
            ],
        });
    } else {
        // Message supprimé sans pièce jointe (uniquement pour information)
        logChannel.send(`❌ Un message a été supprimé dans <#${message.channel.id}> par **${message.author?.tag || 'Utilisateur inconnu'}**.`);
    }
});


client.on('messageDeleteBulk', (messages) => {
    if (messages.first()?.guild && logsSettings[messages.first().guild.id]?.active) {
        const logChannel = messages.first().guild.channels.cache.get(logsSettings[messages.first().guild.id].channelId);
        logChannel.send(`❌ Plusieurs messages ont été supprimés.`);
    }
});

client.on('emojiCreate', (emoji) => {
    if (logsSettings[emoji.guild.id]?.active) {
        const logChannel = emoji.guild.channels.cache.get(logsSettings[emoji.guild.id].channelId);
        logChannel.send(`🌟 Un emoji a été créé : **${emoji.name}**.`);
    }
});

client.on('emojiDelete', (emoji) => {
    if (logsSettings[emoji.guild.id]?.active) {
        const logChannel = emoji.guild.channels.cache.get(logsSettings[emoji.guild.id].channelId);
        logChannel.send(`❌ Un emoji a été supprimé : **${emoji.name}**.`);
    }
});

client.on('interactionCreate', async (interaction) => {
    if (!interaction.isButton() || interaction.customId !== 'delete_staff_thread') return;

    try {
        const channel = interaction.channel;

        // Vérification que le canal existe avant de continuer
        if (!channel) {
            console.error("Le canal est introuvable ou a déjà été supprimé.");
            return;
        }

        // Récupération du salon de logs depuis la configuration
        const serverConfig = getOrInitServerConfig(interaction.guild.id);
        const logChannelId = serverConfig.logChannelId;
        const logChannel = await interaction.guild.channels.fetch(logChannelId);

        if (!logChannel) {
            console.error("Le salon de logs est introuvable.");
            return;
        }

        // Création du dossier 'transcripts' s'il n'existe pas
        const transcriptsDir = path.join(__dirname, 'transcripts');
        if (!fs.existsSync(transcriptsDir)) {
            fs.mkdirSync(transcriptsDir);
        }

        // Génération de la transcription
        const transcript = await generateTranscript(channel);

        // Enregistrement de la transcription dans un fichier temporaire
        const filePath = path.join(transcriptsDir, `channel_${channel.id}.html`);
        fs.writeFileSync(filePath, transcript);

        // Création d'un fichier attachement
        const attachment = new AttachmentBuilder(filePath, { name: `channel_${channel.id}.html` });

        // Envoi de la transcription dans le salon de logs
        await logChannel.send({
            content: `📋 Voici la transcription du salon thread staff  **${channel.name}** avant sa suppression :`,
            files: [attachment],
        });

        // Suppression du fichier temporaire
        fs.unlinkSync(filePath);

        // Suppression du canal
        await channel.delete();
    } catch (error) {
        console.error("Erreur lors de la gestion de la transcription ou de la suppression du canal :", error);
    }
});


client.on('interactionCreate', async (interaction) => {
    if (interaction.isCommand() && interaction.commandName === 'ticket-embed') {
        const embed = new EmbedBuilder()
            .setTitle('Créer un ticket')
            .setDescription('Cliquez sur le bouton ci-dessous pour ouvrir un ticket. Tout abus est interdit ')
            .setColor('#00ff00');

        const button = new ActionRowBuilder().addComponents(
            new ButtonBuilder()
                .setCustomId('create_ticket')
                .setLabel('Ouvrir un ticket')
                .setStyle(ButtonStyle.Primary)
        );

        await interaction.reply({ embeds: [embed], components: [button] });
    }

    if (interaction.isButton() && interaction.customId === 'create_ticket') {
        const serverConfig = getOrInitServerConfig(interaction.guildId);

        const existingChannel = interaction.guild.channels.cache.find(
            (channel) => channel.name === `ticket-${interaction.user.username}`
        );

        if (existingChannel) {
            return interaction.reply({ content: `Vous avez déjà un ticket ouvert : ${existingChannel}`, ephemeral: true });
        }

       const ticketChannel = await interaction.guild.channels.create({
    name: `ticket-${interaction.user.username}`,
    type: 0,
    topic: `Ticket créé par ${interaction.user.id}`,
    permissionOverwrites: [
        {
            id: interaction.guild.id,
            deny: [PermissionsBitField.Flags.ViewChannel],
        },
        {
            id: interaction.user.id,
            allow: [
                PermissionsBitField.Flags.ViewChannel,
                PermissionsBitField.Flags.SendMessages,
                PermissionsBitField.Flags.ReadMessageHistory,
                PermissionsBitField.Flags.AttachFiles,
                PermissionsBitField.Flags.EmbedLinks,
            ],
        },
        {
            id: serverConfig.staffRoleId || interaction.guild.roles.everyone.id,
            allow: [
                PermissionsBitField.Flags.ViewChannel,
                PermissionsBitField.Flags.SendMessages,
                PermissionsBitField.Flags.ReadMessageHistory,
                PermissionsBitField.Flags.AttachFiles,
                PermissionsBitField.Flags.EmbedLinks,
            ],
        },
    ],
});

        const ticketEmbed = new EmbedBuilder()
            .setTitle('Gestion du ticket')
            .setDescription('Utilisez le sélecteur ci-dessous pour gérer ce ticket.')
            .setColor('#00ff00');

        const selectMenu = new ActionRowBuilder().addComponents(
            new StringSelectMenuBuilder()
                .setCustomId('ticket_menu')
                .setPlaceholder('Actions disponibles')
                .addOptions([
                     { label: 'TICKET URGENT', value: 'revive_staff' },
                    { label: 'Ping la Personne', value: 'revive_client' },
                    { label: 'Claim', value: 'claim_ticket' },
                    { label: 'Discussion Staff', value: 'staff-thread' },
                    { label: 'Fermer le ticket', value: 'close_ticket' },
                    { label: 'Supprimer le ticket', value: 'delete_ticket' },
                    { label: 'Ajouter un membre au ticket', value: 'add_member' },
                    { label: 'Retirer un membre du ticket ', value: 'remove_member' },
                    { label: 'Réouvrir le ticket fermé ', value: 'reopen_ticket' }, 
                    { label: 'Transcription du Ticket ', value: 'transcript-receive' },
                ])
        );

        await ticketChannel.send({
            content: `Ticket ouvert par <@${interaction.user.id}>. Merci de patienter , un  staff (<@&${serverConfig.staffRoleId}>) prendra en charge votre ticket .En attendant vous pouvez déjà expliquer la raison du ticket etc... 
(Si besoin jettez un oeil aux options si dessous)`,
            embeds: [ticketEmbed],
            components: [selectMenu],
        });

        await interaction.reply({ content: `Votre ticket a été créé, Rendez vous ici :  ${ticketChannel}`, ephemeral: true });
    }

    if (interaction.isSelectMenu() && interaction.customId === 'ticket_menu') {
        const action = interaction.values[0];
        const ticketChannel = interaction.channel;
        const ticketOwner = ticketChannel.topic?.match(/Ticket créé par (.+)/)?.[1];

        switch (action) {
            case 'claim_ticket':
                if (!interaction.member.roles.cache.has(getOrInitServerConfig(interaction.guildId).staffRoleId)) {
                    return interaction.reply({ content: 'Seul un membre du staff peut utiliser cette option.', ephemeral: true });
                }
                await ticketChannel.send(`Ticket pris en charge par <@${interaction.user.id}>.`);
                break;

            case 'close_ticket':
                await interaction.reply({ content: 'Veuillez fournir une raison pour fermer ce ticket. (Votre message prochain serala raison de la fermeture du ticker )', ephemeral: true });

                const filter = (msg) => msg.author.id === interaction.user.id;
                const collected = await ticketChannel.awaitMessages({ filter, max: 1, time: 60000 }).catch(() => null);

                if (!collected?.size) {
                    return interaction.followUp({ content: 'Aucune raison fournie. Fermeture annulée.', ephemeral: true });
                }

                const reason = collected.first().content;
                collected.first().delete();

                await ticketChannel.permissionOverwrites.edit(ticketOwner, { ViewChannel: false });

                try {
                    const user = await client.users.fetch(ticketOwner);
                    await user.send(`Votre ticket a été fermé pour la raison suivante : ${reason}`);
                } catch (error) {
                    console.error("Impossible d'envoyer un MP à l'utilisateur.", error);
                }

                await ticketChannel.send(`Le ticket a été fermé avec la raison : ${reason}`);
                break;

            case 'reopen_ticket':
                if (!interaction.member.roles.cache.has(getOrInitServerConfig(interaction.guildId).staffRoleId)) {
                    return interaction.reply({ content: 'Seul un membre du staff peut réouvrir ce ticket.', ephemeral: true });
                }
                await ticketChannel.permissionOverwrites.edit(ticketOwner, { ViewChannel: true });
                await ticketChannel.send(`Le ticket a été réouvert pour <@${ticketOwner}>.`);
                if (log1) {
            await log1.send({
                content: `Dans le ticket  **${interaction.channel.name}** ,  <@${interaction.user.id}> a appuyé sur le bouton Réouvrir le ticket  , ce qui a redonné l'accès à  <@${ticketOwner}> dans son ticket :`
            });
        } else {
            console.error('Le salon de log est introuvable.');
        }
                break;

            case 'add_member':
                if (!interaction.member.roles.cache.has(getOrInitServerConfig(interaction.guildId).staffRoleId)) {
                    return interaction.reply({ content: 'Seul un membre du staff peut utiliser cette option.', ephemeral: true });
                }
                await interaction.reply({ content: 'Mentionnez l\'utilisateur à ajouter.', ephemeral: true });

                const addFilter = (msg) => msg.mentions.users.size > 0 && msg.author.id === interaction.user.id;
                const addCollected = await ticketChannel.awaitMessages({ filter: addFilter, max: 1, time: 60000 }).catch(() => null);

                if (!addCollected?.size) {
                    return interaction.followUp({ content: 'Aucun utilisateur mentionné. Action annulée.', ephemeral: true });
                }

                const userToAdd = addCollected.first().mentions.users.first();
                await ticketChannel.permissionOverwrites.edit(userToAdd.id, {
                    ViewChannel: true,
                    SendMessages: true,
                });

                addCollected.first().delete();
                await ticketChannel.send(`<@${userToAdd.id}> a été ajouté au ticket.`);
                if (log1) {
            await log1.send({
                content: `Dans le ticket  **${interaction.channel.name}** ,  <@${interaction.user.id}> a appuyé sur le bouton ajouté une  personne , ce qui a ajouté <@${userToAdd.id}> au ticket de  <@${ticketOwner}> :`
            });
        } else {
            console.error('Le salon de log est introuvable.');
        }
                break;
         
case 'staff-thread':
    // Récupération des informations depuis la configuration
    const serverConfig = getOrInitServerConfig(interaction.guild.id);
    const staffRoleId = serverConfig.staffRoleId;
    const guild = interaction.guild;
    const user = interaction.user;

    // Vérifier si l'utilisateur est staff
    if (!interaction.member.roles.cache.has(staffRoleId)) {
        await interaction.reply({
            content: "❌ Vous n'avez pas la permission d'accéder à ce bouton réservé au staff.",
            flags: 64, // Réponse éphémère
        });
        break;
    }

    // Vérification si un salon staff-thread existe déjà
    const ticketName = interaction.channel.name;
    let existingChannel = guild.channels.cache.find(
        (channel) => channel.name === `staff-thread-${ticketName}` && channel.type === ChannelType.GuildText
    );

    if (existingChannel) {
        await existingChannel.send(


Partager le fichier v7 (18).js sur le Web et les réseaux sociaux:


Télécharger le fichier v7 (18).js


Télécharger v7 (18).js