Skip to content
Snippets Groups Projects
Select Git revision
  • b0f2a07eb8384b1ce2169287eb0465fc455de949
  • main default protected
  • dev
3 results

index.js

Blame
  • SofianeLasri's avatar
    Sofiane Lasri authored
    b0f2a07e
    History
    index.js 27.78 KiB
    // Configuration
    const config = require('./config');
    // Driver SQL
    const Sequelize = require('sequelize');
    const { Op } = require("sequelize");
    // API externe
    const express = require('express')
    const app = express()
    var XMLHttpRequest = require('xhr2');
    // Couleurs de la console
    var colors = require('colors');
    
    // API discord
    const { REST } = require('@discordjs/rest');
    const { Routes } = require('discord-api-types/v9');
    
    // Moment JS
    var moment = require('moment');
    
    // Schedule
    const schedule = require('node-schedule');
    
    ////////////////////////////////////////////////////////////////
    // MODELES DES TABLES
    ////////////////////////////////////////////////////////////////
    
    // Connexion à la base de données
    const sequelize = new Sequelize(config.get("BDD_NAME"), config.get("BDD_USER"), config.get("BDD_PASSWORD"), {
        host: config.get("BDD_HOST"),
        dialect: 'mariadb',
        logging: false,
    });
    
    // Paramètres du bot
    const botSettings = sequelize.define('discord_settings', {
        name: { type: Sequelize.STRING(128), primaryKey: true },
        value: Sequelize.STRING(512),
    }, {
        timestamps: false
    });
    
    // Entrées et sorties des membres
    const entries = sequelize.define('discord_entries', {
        id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true },
        memberId: Sequelize.BIGINT(255),
        isJoin: Sequelize.BOOLEAN,
        date: Sequelize.DATE,
    }, {
        timestamps: false
    });
    
    // Paramètres des membres
    const memberSettings = sequelize.define('discord_memberSettings', {
        memberId: { type: Sequelize.BIGINT(255), primaryKey: true },
        name: { type: Sequelize.STRING(128), primaryKey: true },
        value: Sequelize.STRING(512),
    }, {
        timestamps: false
    });
    
    // Paramètres des joueurs MC
    const minecraftPlayerSetting = sequelize.define('site_userSetting', {
        uuid: { type: Sequelize.STRING(36), primaryKey: true },
        name: { type: Sequelize.STRING(128), primaryKey: true },
        value: Sequelize.TEXT,
    }, {
        timestamps: false,
        freezeTableName: true
    });
    
    // Codes de liaison du serveur MC
    const mcLinkCode = sequelize.define('site_linkCode', {
        uuid: { type: Sequelize.STRING(36), primaryKey: true },
        code: { type: Sequelize.STRING(8), unique: true },
        time: { type: 'TIMESTAMP', defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), allowNull: false },
        used: { type: Sequelize.BOOLEAN, defaultValue: false },
    }, {
        timestamps: false,
        freezeTableName: true
    });
    
    ////////////////////////////////////////////////////////////////
    
    const commands = [{
        name: 'ping',
        description: 'Répond avec pong!'
    },
    {
        name: 'setanniv',
        description: 'Permet de définir ta date d\'anniversaire (usage unique).',
        options: [{
            name: "date", // no uppercase as well
            description: "Date au format DD/MM/YYYY - 31/12/2001",
            type: 3,
            required: true
        }]
    },
    {
        name: 'delanniv',
        description: '[Admin] Supprime la date d\'anniversaire d\'un membre.',
        options: [{
            name: "membre", // no uppercase as well
            description: "Membre à supprimer la date d'anniversaire.",
            type: 6,
            required: true
        }]
    },
    {
        name: 'linkmc',
        description: 'Te permet de lier ton compte Minecraft au serveur Discord.',
        options: [{
            name: "code", // no uppercase as well
            description: "Code généré par la commande /getlinkcode.",
            type: 3,
            required: true
        }]
    }];
    
    ////////////////////////////////////////////////////////////////
    // INITIALISATION DES COMMANDES ET CONNEXION À LA BASE DE DONNÉES
    ////////////////////////////////////////////////////////////////
    const rest = new REST({ version: '9' }).setToken(config.get("DISCORD_BOT_TOKEN"));
    
    (async () => {
        console.log('[' + 'INFO'.yellow + '] Connexion à la base de donnée...'.brightWhite);
        try {
            await sequelize.authenticate();
            console.log('[' + 'SUCCES'.brightGreen + '] Connexion à la base de donnée réussie.'.brightWhite);
            await initialiseDatabaseTables(); // On va initialiser les tables de la base de donnée
    
            try {
                console.log('[' + 'INFO'.yellow + '] Actualisation des commandes...'.brightWhite);
                //console.log(JSON.stringify(commands));
                await rest.put(
                    Routes.applicationGuildCommands(config.get("CLIENT_ID"), config.get("GUILD_ID")),
                    { body: commands },
                );
    
                console.log('[' + 'SUCCES'.brightGreen + '] Toutes les commandes ont été actualisées.');
            } catch (error) {
                console.error('[' + 'ERREUR'.brightRed + '] Erreur lors de l\'actualisation des commandes:'.brightWhite + error);
            }
        } catch (error) {
            console.log('[' + 'ERREUR'.brightRed + '] Erreur lors de la connexion à la base de donnée:'.brightWhite);
            console.log('[' + 'DEBUG'.yellow + '] '.brightWhite + config.get("BDD_USER") + ":" + config.get("BDD_PASSWORD") + "@" + config.get("BDD_HOST") + " db:" + config.get("BDD_NAME") + '\n');
            console.error(error);
        }
    
    })();
    
    async function initialiseDatabaseTables() {
        console.log('[' + 'INFO'.yellow + '] Initialisation des tables...'.brightWhite);
        try {
            // On synchronise les modèles de sequlize
            await botSettings.sync();
            await entries.sync();
            await memberSettings.sync();
            await minecraftPlayerSetting.sync();
            await mcLinkCode.sync();
    
            // Basiquement on regarde si l'entrée existe, puis on agit en conséquence
            let token = await botSettings.findOne({ where: { name: "token" } });
            if (token == null) {
                // INSERT si elle n'existe pas
                console.log('[' + 'INSERT'.brightMagenta + '] Insertion de token'.brightWhite);
                let token = botSettings.create({
                    name: "token",
                    value: config.get("DISCORD_BOT_TOKEN")
                });
            } else {
                // UPDATE si différente
                if (token.value != config.get("DISCORD_BOT_TOKEN")) {
                    token.update({ value: config.get("DISCORD_BOT_TOKEN") })
                        .then(updatedRecord => {
                            console.log('[' + 'UPDATE'.brightMagenta + '] Mise à jour du token dans la base de donnée'.brightWhite);
                        }).catch(err => {
                            console.log('[' + 'ERREUR'.brightRed + '] Erreur lors de la màj de token dans la base de donnée: '.brightWhite + '\n');
                            throw new Error(err);
                        });
                }
            }
    
            // Et c'est pareil à chaque fois
            let clientId = await botSettings.findOne({ where: { name: "clientId" } });
            if (clientId == null) {
                console.log('[' + 'INSERT'.brightMagenta + '] Insertion de clientId'.brightWhite);
                let clientId = botSettings.create({
                    name: "clientId",
                    value: config.get("CLIENT_ID")
                });
            } else {
                if (clientId.value != config.get("CLIENT_ID")) {
                    clientId.update({ value: config.get("CLIENT_ID") })
                        .then(updatedRecord => {
                            console.log('[' + 'UPDATE'.brightMagenta + '] Mise à jour du clientId dans la base de donnée'.brightWhite);
                        }).catch(err => {
                            console.log('[' + 'ERREUR'.brightRed + '] Erreur lors de la màj de clientId dans la base de donnée: '.brightWhite + '\n');
                            throw new Error(err);
                        });
                }
            }
    
            let guildId = await botSettings.findOne({ where: { name: "guildId" } });
            if (guildId == null) {
                console.log('[' + 'INSERT'.brightMagenta + '] Insertion de guildId'.brightWhite);
                let guildId = botSettings.create({
                    name: "guildId",
                    value: config.get("GUILD_ID")
                });
            } else {
                if (guildId.value != config.get("GUILD_ID")) {
                    guildId.update({ value: config.get("GUILD_ID") })
                        .then(updatedRecord => {
                            console.log('[' + 'UPDATE'.brightMagenta + '] Mise à jour du guildId dans la base de donnée'.brightWhite);
                        }).catch(err => {
                            console.log('[' + 'ERREUR'.brightRed + '] Erreur lors de la màj de guildId dans la base de donnée: '.brightWhite + '\n');
                            throw new Error(err);
                        });
                }
            }
    
            console.log('[' + 'SUCCES'.brightGreen + '] Tables initialisées avec succès.'.brightWhite);
        } catch (error) {
            console.error('[' + 'ERREUR'.brightRed + '] Erreur lors de l\'initialisation des tables:'.brightWhite + '\n', error);
        }
    
    }
    
    ////////////////////////////////////////////////////////////////
    
    ////////////////////////////////////////////////////////////////
    // CONSOLE
    ////////////////////////////////////////////////////////////////
    
    // Console Input/Output
    var readline = require('readline');
    
    var rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });
    
    // Ce code est a améliorer, je l'ai vulgairement recopié d'un ancien bot (lui même pas très bien conçu)
    var recursiveAsyncReadLine = function () {
        rl.question('Commande: ', function (answer) {
            //if (answer == 'exit')
            //  return rl.close();
            const args = answer.match(/(".*?"|[^"\s]+)+(?=\s*|\s*$)/g);
            const command = args.shift().toLowerCase();
    
            switch (command) {
                case "say":
                    if (!args[0] || !args[1])
                        console.log('\n' + '[' + 'ERREUR'.brightRed + "] Tu n'as pas mis d'arguments :p" + '\n' + '[' + 'INFO'.yellow + "] Usage: say <Numéro du canal> <\"Texte\">");
                    else {
                        var message = args[1].substring(1, args[1].length - 1);
                        client.channels.cache.get(args[0]).send(message);
                        console.log('\n' + '[' + 'SUCCES'.brightGreen + '] Le message a été envoyé dans le canal n°' + args[0]);
                    }
                    break;
    
                default:
                    console.log('\n' + "Commande inconnue. :p");
                    break;
            }
    
            recursiveAsyncReadLine(); //Calling this function again to ask new question
        });
    };
    
    recursiveAsyncReadLine(); //we have to actually start our recursion somehow
    
    ////////////////////////////////////////////////////////////////
    
    ////////////////////////////////////////////////////////////////
    // BOT DISCORD
    ////////////////////////////////////////////////////////////////
    // require the needed discord.js classes
    const { Client, Intents, MessageActionRow, MessageButton, WebhookClient } = require('discord.js');
    const { verify } = require('crypto');
    
    // create a new Discord client
    const client = new Client({ intents: ["GUILDS", "GUILD_MESSAGES", "DIRECT_MESSAGES", "GUILD_MEMBERS"] });
    var mcChatWebhook;
    
    client.on("ready", async function () {
        console.log('\n' + "SL-Projects Bot".brightCyan);
        console.log("");
        console.log("Bot démarré".brightGreen);
    
        var guild = client.guilds.cache.get(config.get("GUILD_ID"));
        var memberCount = guild.memberCount.toLocaleString();
        console.log('\n' + "Nous sommes " + memberCount + " membres.");
        client.user.setActivity("Regarde " + memberCount + " membres");
    
        checkAnniv();
    
        verifyMcChatWebhook();
    });
    
    // Actions lorsqu'un membre rejoins ou part
    client.on('guildMemberAdd', async (member) => {
        let guild = client.guilds.cache.get(config.get("GUILD_ID"));
        var memberCount = guild.memberCount.toLocaleString();
    
        console.log('\n' + "Nouveau membre - " + member.user.username + " - " + memberCount + " membres");
        member.guild.channels.cache.get(config.get("CANAL_LOG")).send("Nouveau membre - " + member.user.username + " - " + memberCount + " membres");
        client.user.setActivity("Regarde " + memberCount + " membres");
    
        var currentdate = new Date();
        var datetime = currentdate.getFullYear() + "-"
            + (currentdate.getMonth() + 1) + "-"
            + currentdate.getDate() + " "
            + (currentdate.getHours() + 1) + ":"
            + currentdate.getMinutes() + ":"
            + currentdate.getSeconds();
    
        await entries.create({
            id: null,
            memberId: member.user.id,
            isJoin: 1,
            date: datetime,
        });
    });
    client.on('guildMemberRemove', async (member) => {
        let guild = client.guilds.cache.get(config.get("GUILD_ID"));
        var memberCount = guild.memberCount.toLocaleString();
    
        console.log('\n' + "Un membre a quitté le serveur - " + member.user.username + " - " + memberCount + " membres");
        member.guild.channels.cache.get(config.get("CANAL_LOG")).send("Un membre a quitté le serveur - " + member.user.username + " - " + memberCount + " membres");
        client.user.setActivity("Regarde " + memberCount + " membres");
    
        var currentdate = new Date();
        var datetime = currentdate.getFullYear() + "-"
            + (currentdate.getMonth() + 1) + "-"
            + currentdate.getDate() + " "
            + (currentdate.getHours() + 1) + ":"
            + currentdate.getMinutes() + ":"
            + currentdate.getSeconds();
    
        await entries.create({
            id: null,
            memberId: member.user.id,
            isJoin: 0,
            date: datetime,
        });
    });
    
    // Lorsqu'un message est envoyé
    client.on('messageCreate', async message => {
        // On va regarder si le message vient du canal de tchat du serveur MC
        if (message.channel.id == config.get("CANAL_CHAT_MC") && !message.author.bot) {
            var playerName = message.author.username;
            var messageContent = message.content;
    
            // On va vérifier si l'utilisateur a associé son compte discord avec le serveur MC
            var memberAccountAssoc = await minecraftPlayerSetting.findOne({
                where: {
                    name: 'discordAccountId',
                    value: message.author.id
                }
            });
    
            if (memberAccountAssoc != null) {
                // L'utilisateur a bien associé son compte discord avec le serveur MC
                let userMcUsername = await minecraftPlayerSetting.findOne({
                    where: {
                        uuid: memberAccountAssoc.uuid,
                        name: 'playerName'
                    }
                });
                if(userMcUsername != null) {
                    playerName = userMcUsername.value;
                }
            }
    
            // On encode ça en JSON
            var jsonEncodedMessage = JSON.stringify({
                "message": messageContent,
                "playerName": playerName
            });
    
            // Maintenant on va appeler le serveur pour envoyer le message
            var xmlHttp = new XMLHttpRequest();
            xmlHttp.open("GET", "http://node.sl-projects.com:" + config.get("PORT_MSG_SRVMC") + "/discordMsg/" + encodeURIComponent(jsonEncodedMessage), true);
            xmlHttp.send();
        }
    });
    
    
    
    // Commandes
    client.on('interactionCreate', async interaction => {
        if (interaction.isCommand()) {
            console.log('[' + 'COMMANDE'.brightMagenta + '] '.brightWhite + interaction.user.username.brightBlue + ' a lancé la commande '.brightWhite + interaction.commandName.yellow);
            if (interaction.commandName === 'ping') {
                await interaction.reply('Pong!');
            } else if (interaction.commandName === 'setanniv') {
                // Je check si le membre a déjà enregistré sa date d'anniversaire
                let userAnniv = await memberSettings.findOne({
                    where: {
                        memberId: interaction.user.id,
                        name: 'birthday'
                    }
                });
                // S'il ne l'a pas déjà fait
                if (userAnniv == null) {
                    // On va checker que ce qu'il a envoyé est bien une date valide
                    let memberBirthday = moment(interaction.options.getString('date'), "DD/MM/YYYY");
                    if (isNaN(memberBirthday)) {
                        console.log('\n' + '[' + 'ERREUR'.brightRed + "] Date illisible: " + interaction.options.getString('date'));
                        await interaction.reply('J\'ai du mal à lire la date que tu m\'as donné. Est-elle bien dans ce format **DD/MM/YYYY**? :thinking:');
                    } else {
                        try {
                            memberBirthday = memberBirthday.toDate();
                            console.log('[' + 'INSERT'.brightMagenta + '] '.brightWhite + interaction.user.username.brightBlue + " a renseigné sa date d'anniversaire. ".brightWhite + interaction.options.getString('date').yellow);
                            var dd = memberBirthday.getDate();
                            var mm = memberBirthday.getMonth() + 1;
    
                            var yyyy = memberBirthday.getFullYear();
                            if (dd < 10) {
                                dd = '0' + dd;
                            }
                            if (mm < 10) {
                                mm = '0' + mm;
                            }
                            let birthday = mm + '/' + dd + '/' + yyyy;
                            let insetMemberBirthday = memberSettings.create({
                                memberId: interaction.user.id,
                                name: "birthday",
                                value: birthday
                            });
                            await interaction.reply({ content: 'Je m\'en souviendrai. :thumbup:', ephemeral: true });
                            checkAnniv();
                        } catch (error) {
                            console.error('[' + 'ERREUR'.brightRed + '] Erreur lors de l\'insertion de la date d\'anniversaire: '.brightWhite + '\n', error);
                            await interaction.reply("J'ai eu un petit problème pour enregistrer ta date d'anniversaire, re-essaie plus-tard. :p");
                        }
                    }
                } else {
                    await interaction.reply('Tu ne peux pas redéfinir ta date d\'anniversaire. Demande au staff si besoin. :p');
                }
            } else if (interaction.commandName === 'delanniv') {
                // On check les perms
                if (interaction.member.roles.cache.has(config.get("ROLE_ANNIV"))) {
                    try {
                        console.log('\n' + '[' + 'DELETE'.brightMagenta + "] Suppression de la date d'anniversaire de " + interaction.options.getMember('membre'));
                        await memberSettings.destroy({
                            where: {
                                name: "birthday",
                                memberId: interaction.options.getMember('membre').id
                            }
                        });
                    } catch (error) {
                        console.error('[' + 'ERREUR'.brightRed + '] Erreur lors de la supression de la date d\'anniversaire: '.brightWhite + '\n', error);
                        await interaction.reply("J'ai eu un petit problème pour supprimer la date d'anniversaire, re-essaie plus-tard. :p");
                    }
    
                    await interaction.reply({ content: 'La date d\'anniversaire de <@' + interaction.options.getMember('membre') + '> a été supprimée.', ephemeral: true });
                    checkAnniv();
                } else {
                    await interaction.reply({ content: "Tu n'as pas le droit d'exécuter cette commande. :p", ephemeral: true });
                }
    
            } else if (interaction.commandName === 'linkmc') {
                console.log('[' + 'INFO'.yellow + '] L\'utilisateur '.brightWhite + interaction.user.username.brightBlue + " a demandé une association de son compte Minecraft avec le code ".brightWhite + interaction.options.getString('code').yellow);
                // On va vérifier si le membre a déjà associé son compte minecraft
                let memberAccountAssoc = await minecraftPlayerSetting.findOne({
                    where: {
                        name: 'discordAccountId',
                        value: interaction.user.id
                    }
                });
    
                if (memberAccountAssoc == null) {
                    // Il ne l'a pas déjà associé 
                    // On va donc checker la validité du code
                    let code = interaction.options.getString('code');
    
                    // On va le chercher dans la bdd
                    let isCodeValid = await mcLinkCode.findOne({
                        where: {
                            code: code,
                            used: false
                        }
                    });
    
                    if (isCodeValid != null) {
                        // Le code est valide
                        // On va le mettre dans la bdd
                        await minecraftPlayerSetting.create({
                            name: 'discordAccountId',
                            value: interaction.user.id,
                            uuid: isCodeValid.uuid
                        });
    
                        // On va mettre à jour le code
                        await mcLinkCode.update({
                            used: true
                        }, {
                            where: {
                                code: code
                            }
                        });
    
                        // On va récupérer le pseudo du joueur pour la réponse
                        let playerName = await minecraftPlayerSetting.findOne({
                            where: {
                                uuid: isCodeValid.uuid,
                                name: 'playerName'
                            }
                        });
    
                        // On va envoyer le message
                        await interaction.reply({ content: 'Ton compte a été associé avec le compte Minecraft de **' + playerName.value + '** !', ephemeral: true });
                    } else {
                        // Le code n'est pas valide
                        await interaction.reply({ content: 'Le code que tu as entré est invalide. :p', ephemeral: true });
                    }
                } else {
                    // Il l'a déjà associé
                    await interaction.reply({ content: 'Tu as déjà associé ton compte minecraft avec le serveur Discord. :thinking:', ephemeral: true });
                }
            }
        }
    });
    
    
    async function checkAnniv() {
        console.log('[' + 'INFO'.yellow + '] Vérification des anniversaires.'.brightWhite);
    
        let today = new Date();
        var dd = today.getDate();
        var mm = today.getMonth() + 1;
    
        var yyyy = today.getFullYear();
        if (dd < 10) {
            dd = '0' + dd;
        }
        if (mm < 10) {
            mm = '0' + mm;
        }
        today = mm + '/' + dd;
    
        let { count, rows } = await memberSettings.findAndCountAll({
            where: {
                name: "birthday",
                value: {
                    [Op.like]: today + '%'
                }
            }
        });
    
        const guild = client.guilds.cache.get(config.get("GUILD_ID"));
        //console.log(guild);
    
        var membersWithAnnivRole = await guild.roles.cache.get(config.get("ROLE_ANNIV")).members;
        //console.log(membersWithAnnivRole);
    
        // On va vérifier que c'est bien l'anniv des membres ayant le rôle. :p
        for await (var memberWithAnnivRole of membersWithAnnivRole) {
    
            var isMemberBirthday = false;
            for await (const member of rows) {
                if (memberWithAnnivRole[0] === member.memberId.toString()) {
                    isMemberBirthday = true;
                }
            }
            if (!isMemberBirthday) {
                console.log('[' + 'INFO'.yellow + '] Suppression du rôle anniversaire pour '.brightWhite + memberWithAnnivRole[1].user.username);
                memberWithAnnivRole[1].roles.remove(config.get("ROLE_ANNIV")).catch(console.error);
            }
        }
        console.log('[' + 'SUCCES'.brightGreen + '] C\'est l\'anniversaire de ' + count + ' personne(s).');
    
        for await (var member of rows) {
            let memberFetch = await guild.members.fetch(member.memberId.toString());
            //console.log(memberFetch);
            if (memberFetch) {
                console.log(" 🎂 " + memberFetch.user.username);
                if (!memberFetch.roles.cache.has(config.get("ROLE_ANNIV"))) {
                    let annivRole = await memberFetch.guild.roles.cache.find(role => role.id === config.get("ROLE_ANNIV"));
                    if (annivRole) {
                        memberFetch.roles.add(annivRole);
                        console.log('[' + 'INFO'.yellow + '] Le rôle '.brightWhite + annivRole.name.yellow + "a été donné à " + memberFetch.user.username.brightBlue);
                        client.channels.cache.get(config.get("CANAL_GENERAL")).send("Fêtons l'anniversaire de <@" + memberFetch.id + "> ! :partying_face:").catch(console.error);
                    }
    
                }
            }
        }
    }
    
    async function verifyMcChatWebhook() {
        let mcChatWebhookId = await botSettings.findOne({ where: { name: "mcChatWebhookId" } });
        if (mcChatWebhookId != null) {
            console.log("[" + 'INFO'.yellow + "] Le Webhook du serveur MC est déjà configuré.");
            let mcChatWebhookToken = await botSettings.findOne({ where: { name: "mcChatWebhookToken" } });
            if (mcChatWebhookToken) {
                mcChatWebhook = new WebhookClient({ id: mcChatWebhookId.value, token: mcChatWebhookToken.value });
            } else {
                console.log("[" + 'ERREUR'.brightRed + "] Impossible de trouver le token du webhook dans la base de donnée.");
                createMcChatWebhook();
            }
        } else {
            createMcChatWebhook();
        }
    }
    
    async function createMcChatWebhook() {
        console.log("[" + 'INFO'.yellow + "] Création du Webhook du serveur MC.");
        client.channels.cache.get(config.get("CANAL_CHAT_MC")).createWebhook('Chat Serveur Minecraft', {
            avatar: 'https://sl-craft.fr/data/images/logo/short-color.png',
        })
            .then(webhook => {
                botSettings.create({
                    name: "mcChatWebhookId",
                    value: webhook.id
                });
                botSettings.create({
                    name: "mcChatWebhookToken",
                    value: webhook.token
                });
                mcChatWebhook = new WebhookClient({ id: mcChatWebhookId.value, token: mcChatWebhookToken.value });
                console.log("[" + 'INFO'.yellow + "] Le Webhook du serveur MC a été configuré avec succès.");
            })
            .catch(console.error);
    }
    
    function sendMessageFromMcChat(username, message) {
        if(username == "SL-Craft"){
            mcChatWebhook.send({
                content: message,
                username: username,
                avatarURL: 'https://sl-craft.fr/data/images/logo/favicon-color.png',
            });
        }else{
            // On va vérifier que le joueur ne fait pas de @everyone ou de @here
            message = message.replace("<@everyone>", "**everyone**");
            message = message.replace("<@here>", "**here**");
            message = message.replace("@everyone", "**everyone**");
            message = message.replace("@here", "**here**");
    
            // On va regarder si le joueur souhaite tagger quelqu'un avec un @
            var regex = /@(.*?\s)/g;
            var match = regex.exec(message);
            if (match){
                var member = match[1].trim();
                var memberFetch = client.users.cache.find(user => user.username == member);
                if (memberFetch){
                    message = message.replace("@"+member, "<@" + memberFetch.id + ">");
                }
            }
            
            mcChatWebhook.send({
                content: message,
                username: username,
                avatarURL: 'https://live.mc.sl-projects.com/tiles/faces/32x32/' + username + '.png',
            });
        }
    }
    
    
    const job = schedule.scheduleJob('0 0 * * *', function () {
        console.log('[' + 'INFO'.yellow + '] Éxecution des tâches de fonds quotidiennes...'.brightWhite);
        checkAnniv();
    });
    
    
    // login to Discord with your app's token
    client.login(config.get("DISCORD_BOT_TOKEN"));
    
    ////////////////////////////////////////////////////////////////
    
    ////////////////////////////////////////////////////////////////
    // API
    ////////////////////////////////////////////////////////////////
    
    app.get('/ping', (req, res) => {
        res.send("Pong!")
    })
    app.get('/channels/:id', (req, res) => {
        var id = req.params.id;
        res.send(client.channels.cache.get(id));
    })
    app.get('/mc/chat/:detail', (req, res) => {
        var detail = JSON.parse(decodeURI(req.params.detail));
        sendMessageFromMcChat(detail.username, detail.message);
        res.send("Envoyé!")
    })
    
    app.listen(27001, () => {
        console.log('[' + 'INFO'.yellow + '] Écoute sur '.brightWhite + 'node.sl-projects.com:27001'.yellow);
    });
    
    ////////////////////////////////////////////////////////////////