From c026b012615c80d548c87abed95ac075bb7885f5 Mon Sep 17 00:00:00 2001 From: Greensky-gs <72513011+Greensky-gs@users.noreply.github.com> Date: Fri, 12 Aug 2022 15:42:57 +0200 Subject: [PATCH 01/14] Update --- assets/embeds.js | 95 ++++++-- assets/managers/LotoManager.js | 230 ++++++++++++++++++ commands/misc/levels.js | 2 +- events/{message.js => message.js.txt} | 0 events/messageCreate.js | 1 + events/messageUpdate.js | 2 +- slash-commands/economy/loto.js | 87 +++++++ slash-commands/fun/vigenere.js | 62 +++++ slash-commands/moderation/censure.js | 77 ++++++ slash-commands/moderation/clear.js | 43 ++++ slash-commands/moderation/edit-case.js | 2 +- .../moderation/filtre-case-action.js | 2 +- slash-commands/moderation/kick.js | 2 +- slash-commands/moderation/logs.js | 151 ++++++++++++ slash-commands/usefull/commande.js | 15 +- slash-commands/usefull/levels.js | 92 +++++++ 16 files changed, 830 insertions(+), 33 deletions(-) create mode 100644 assets/managers/LotoManager.js rename events/{message.js => message.js.txt} (100%) create mode 100644 slash-commands/economy/loto.js create mode 100644 slash-commands/fun/vigenere.js create mode 100644 slash-commands/moderation/censure.js create mode 100644 slash-commands/moderation/clear.js create mode 100644 slash-commands/moderation/logs.js create mode 100644 slash-commands/usefull/levels.js diff --git a/assets/embeds.js b/assets/embeds.js index 81a82bb..3dd74be 100644 --- a/assets/embeds.js +++ b/assets/embeds.js @@ -20,25 +20,25 @@ module.exports = { */ noUser: (user) => { return new MessageEmbed() - .setTitle("Utilisateur introuvable") + .setTitle("🚫 Utilisateur introuvable") .setColor('DARK_RED') .setDescription(`Oops, cet utilisateur est introuvable, réessayez avec l'identifiant ou la mention.\n> Un [utilisateur](https://github.com/BotOracle/Documentation/blob/main/others/user.md) est attendu.`) }, invalidNumber: (user) => { return generateBasic(user) - .setTitle("Nombre invalide") + .setTitle("🚫 Nombre invalide") .setColor('RED') .setDescription(`Oops, on dirait que ce n'est pas un nombre correct.\n> Un [nombre](https://github.com/BotOracle/Documentation/blob/main/others/nombre.md) est attendu`) }, noReason: (user) => { return generateBasic(user) - .setTitle("Raison invalide") + .setTitle("🚫 Raison invalide") .setColor('RED') .setDescription(`Oops, vous avez oublié de saisir la raison.\n> Un [texte](https://github.com/BotOracle/Documentation/blob/main/others/texte.md) est attendu`) }, notEnoughHiger: (user, member) => { return generateBasic(user) - .setTitle("Vous n'êtes pas assez élevé") + .setTitle("🚫 Vous n'êtes pas assez élevé") .setDescription(`Oops, <@${member.id}> est supérieur ou égal à vous dans la hiérarchie des rôles.`) .setColor('DARK_RED') }, @@ -61,7 +61,7 @@ module.exports = { */ noChannel: (user) => { return generateBasic(user) - .setTitle("Salon inexistant") + .setTitle("🚫 Salon inexistant") .setDescription(`Oops, ce salon n'existe pas, réessayez avec identifiant ou la mention.\n> Un [salon](https://github.com/BotOracle/Documentation/blob/main/others/salon.md) est attendu`) .setColor('RED') }, @@ -72,19 +72,19 @@ module.exports = { }, noText: (user) => { return generateBasic(user) - .setTitle("Pas de texte") + .setTitle("🚫 Pas de texte") .setColor('RED') .setDescription(`Oops, vous avez oublié le texte, réessayez la commande en saisissant un texte.\n> Un [texte](https://github.com/BotOracle/Documentation/blob/main/others/texte.md) est attendu`) }, collectorNoMessage: (user) => { return generateBasic(user) - .setTitle("Aucune réponse") + .setTitle("🚫 Aucune réponse") .setColor('RED') .setDescription(`<@${user.id}>, je vous ai proposé un collecteur de messages mais il se trouve que vous n'y avez pas répondu.\nVeuillez réessayer.\n> Vous utilisez un [collecteur de messages](https://github.com/BotOracle/Documentation/blob/main/others/msg-collector.md)`) }, invalidTime: (user) => { return generateBasic(user) - .setTitle("Durée invalide :x:") + .setTitle("🚫 Durée invalide :x:") .setColor('RED') .setDescription(`Oops, ce n'est pas une durée valide, utilisez :\n\`s\` pour secondes\n\`m\` pour minutes\n\`h\` pour heures\n\`d\` pour jours\n\`y\` pour années.\n> [Documentation](https://github.com/BotOracle/Documentation/blob/main/others/temps.md)`) }, @@ -95,7 +95,7 @@ module.exports = { collections.errorsOnInvalidArg.set(user.id, collections.errorsOnInvalidArg.get(user.id) + 1); return generateBasic(user) - .setTitle("Arguments invalides :x:") + .setTitle("🚫 Arguments invalides :x:") .setDescription(text) .setColor('RED') }, @@ -111,37 +111,37 @@ module.exports = { collections.errors.set(user.id, collections.errors.get(user.id) + 1); return generateBasic(user) - .setTitle("Oops") + .setTitle("🚫 Oops") .setDescription(text) .setColor('#ff0000') }, guillement: (user) => { return generateBasic(user) - .setTitle("Oula !") + .setTitle("🚫 Erreur de guillemets") .setDescription(`Oops, vous ne pouvez pas saisir de \`"\` pour des raisons de sécurité.`) .setColor('#ff0000') }, noRole: (user) => { return generateBasic(user) - .setTitle("Pas de rôle") + .setTitle("🚫 Pas de rôle") .setDescription(`Vous n'avez pas précisé de [**rôle**](https://github.com/BotOracle/Documentation/blob/main/others/role.md)`) .setColor('#ff0000') }, noRoles: (user) => { return generateBasic(user) - .setTitle("Pas de rôles") + .setTitle("🚫 Pas de rôles") .setDescription(`Je n'ai pas trouvé suffisament de [**rôles**](https://github.com/BotOracle/Documentation/blob/main/others/role.md).`) .setColor('#ff0000') }, noMember: (user) => { return generateBasic(user) - .setTitle("Pas de membres") + .setTitle("🚫 Pas de membres") .setDescription(`Je n'ai pas trouvé suffisament de [**membres**](https://github.com/BotOracle/Documentation/blob/main/others/user.md).`) .setColor('#ff0000') }, noText: (user) => { return generateBasic(user) - .setTitle("Texte manquant") + .setTitle("🚫 Texte manquant") .setDescription(`Vous avez oublié de saisir un **texte**.\n> Un [texte](https://github.com/BotOracle/Documentation/blob/main/others/texte.md) est attendu`) .setColor('#ff0000') }, @@ -153,7 +153,7 @@ module.exports = { }, missingPermission: (user, perm) => { return generateBasic(user) - .setTitle("Permission manquante") + .setTitle("🚫 Permission manquante") .setDescription(`La permission \`${perm}\` est requise pour exécuter cette commande.`) .setColor('#ff0000') }, @@ -167,14 +167,73 @@ module.exports = { }, notTextChannel: (user) => { return generateBasic(user) - .setTitle("Salon invalide") + .setTitle("🚫 Salon invalide") .setDescription(`Le salon que vous avez spécifié n'est pas un salon textuel.`) .setColor('#ff0000') }, notEnoughCoins: (user) => { return generateBasic(user) - .setTitle(`Pas assez ${data.coinsSuffix}`) + .setTitle(`🚫 Pas assez ${data.coinsSuffix}`) .setDescription(`Vous n'avez pas assez ${data.coinsSuffix} pour faire ça.\n> :bulb:\n> Les ${data.coins} sont ceux comptés **qui ne sont pas dans votre banque**`) .setColor('#ff0000') + }, + loto: { + /** + * + * @param {User} user + * @param {'participate' | 'end'} type + * @returns + */ + invalidLoto: (user, type) => { + return generateBasic(user) + .setTitle("❌ Loto invalide") + .setDescription(`Il n'y a pas de loto sur le serveur.\n${type == 'participate' ? `Il n'y a pas de loto en cours.` : `Le loto en cours n'est pas terminé`}`) + .setColor('#ff0000') + }, + invalidNumbers: (user) => { + return generateBasic(user) + .setTitle("🚫 Nombres invalides") + .setDescription(`Les nombres que vous avez spécifié sont invalides.\n**Vérifiez que vous avez le même nombre de numéro que celui requis**.`) + .setColor('#ff0000') + }, + alreadyParticipate: (user) => { + return generateBasic(user) + .setTitle("❌ Participation déjà enregistrée") + .setColor('#ff0000') + .setDescription(`Vous participez déjà à ce loto`) + }, + /** + * @param {User} user + * @param {Number[]} numbers + * @param {Number[]} complementaries + */ + added: (user, numbers, complementaries) => { + return generateBasic(user) + .setTitle("✅ Participation enregistrée") + .setDescription(`J'ai enregistré votre participation`) + .addFields( + { + name: "Numéro gagnants", + value: numbers.join(', '), + inline: true + }, + { + name: "Numéro complémentaires", + value: complementaries.join(', '), + inline: true + } + ) + .setColor('#00ff00') + }, + /** + * @param {{ numbers: Number[], complementaries: Number[], winners: [], user: User }} data + */ + end: (data) => { + return generateBasic(data.user) + .setTitle('🎉 Tirage') + .setDescription(`**Numéro gagnants :** ${data.numbers.join(' ')}\n**Numéro complémentaires :** ${data.complementaries.join(' ')} + +${data.winners.length == 0 ? 'Pas de gagnants' : data.winners.map(w => `<@${w.user_id}> : ${x}`)}`) + } } } \ No newline at end of file diff --git a/assets/managers/LotoManager.js b/assets/managers/LotoManager.js new file mode 100644 index 0000000..3d99e31 --- /dev/null +++ b/assets/managers/LotoManager.js @@ -0,0 +1,230 @@ +class LotoManager { + constructor(client, db) { + this.client = client; + this.db = db; + this.cache = new Map(); + } + convertToObject(data) { + let x = data; + x.ended = data.ended == "1"; + ['reward', 'numbers', 'complementaries', 'endsAt'].forEach((y) => x[y] = parseInt(x[y])); + + if (typeof x.json == 'string') x.json = JSON.parse(x.json); + // x.json.forEach((userData, index) => { + // let y = userData; + // Object.keys(y).filter(x => typeof x !== "string").forEach((k) => { + // y[k] = y[k].map(yy => parseInt(yy)); + // }); + + // x.json[index] = y; + // }); + + return x; + } + convertToSql(data) { + let x = data; + x.ended = x.ended == true ? '1':'0'; + + if (typeof x.json == 'object') x.json = JSON.stringify(x.json); + + return x + } + createQuery(data, exists) { + let sql = `INSERT INTO loto (${Object.keys(data).join(', ')}) VALUES (${Object.values(data).map(x => `'${x}'`).join(', ')})`; + + if (exists == true) sql = `UPDATE loto SET ${Object.keys(data).map(x => `${x}='${data[x]}'`).join(', ')}`; + + return sql; + } + validLoto(guildId) { + let x = this.cache.get(guildId); + if (!x) { + return false; + }; + if (x.ended == true) { + return false; + }; + if (x.endsAt <= Date.now()) { + return false; + }; + + return true; + } + validArray(array) { + if (array.filter(x => x <= 100 && x > 0).length !== array.length) return false; + array = array.sort(); + + let valid = true; + array.forEach((x, i) => { + if (array[i + 1] == x) valid = false; + }); + if (!valid) return false; + return true; + } + /** + * @param {Number[]} array the array to tets + * @param {Number[]} compared the array that is used for compare + */ + validArrayCompare(array, compared) { + let valid = true; + array.forEach(x => { + if (compared.includes(x)) valid = false; + }); + return valid; + } + resetCache() { + this.cache = new Map(); + } + fillCache() { + this.db.query(`SELECT * FROM loto`, (err, req) => { + if (err) throw err; + + for (const data of req) { + let x = this.convertToObject(data); + + this.cache.set(x.guild_id, x); + }; + }); + } + init() { + this.fillCache(); + } + /** + * @param {{ guildId: String, userId: String, numbers: Number[], complementaries: Number[] }} data + */ + addParticipation(data) { + if (!this.validLoto(data.guildId)) return 'invalid loto'; + const loto = this.cache.get(data.guildId); + + if (loto.numbers !== data.numbers?.length) return 'invalid numbers'; + if (loto.complementaries !== data.complementaries?.length) return 'invalid numbers'; + + if (!this.validArray(data.numbers) || !this.validArray(data.complementaries)) return 'invalid arrays'; + if (!this.validArrayCompare(data.complementaries, data.numbers)) return 'invalid compared'; + + if (loto.json.find(x => x.user_id == data.userId)) return 'user already exists'; + + loto.json.push({ + user_id: data.userId, + numbers: data.numbers, + complementaries: data.complementaries + }); + this.cache.set(loto.guild_id, loto); + const sql = this.createQuery(this.convertToSql(loto), true); + this.db.query(sql, (err) => {if (err) throw err}); + + return 'added'; + } + compareArrays(first, second) { + let same = false; + + if (second.filter(x => first.includes(x)).length == second.length) same = true; + + return same; + } + /** + * @param {Number[]} first Array generated + * @param {Number[]} second Array of the user + * @returns {{matches: Number, total: Number}} total is the length of the first array + */ + compareComplementariesArrays(first, second) { + let same = second.filter(x => first.includes(x)).length; + + return { + matches: same, + total: first.length + }; + } + /** + * @param {Number[]} map + */ + random(map) { + let numbers = []; + for (let i = 1; i < 100; i++) { + numbers.push(i); + }; + + numbers = numbers.filter(x => !map.includes(x)); + let random = numbers[Math.floor(Math.random() * numbers.length)]; + + map.push(random); + return random; + } + roll(guildId) { + let loto = this.cache.get(guildId); + if (typeof loto.ended == 'string') loto = this.convertToObject(loto); + + let numbers = []; + let complementaries = []; + let all = []; + + for (let i = 0; i < loto.numbers; i++) { + numbers.push(this.random(all)); + }; + for (let i = 0; i < loto.complementaries; i++) { + complementaries.push(this.random(all)); + }; + + numbers.sort(); + complementaries.sort(); + + let winners = loto.json.filter(x => this.compareArrays(x.numbers, numbers) == true); + if (winners.length == 0) return { numbers, complementaries, winners: [] }; + + let reward = loto.reward; + if (winners.length == 1) { + let percent = this.compareComplementariesArrays(complementaries, winners[0].complementaries); + let total = numbers.length + complementaries.length; + + let winned = (reward * (percent.matches + numbers.length)) / total; + winners[0].reward = winned; + } else { + let splited = reward / winners.length; + winners.forEach((winner, index) => { + let percent = this.compareComplementariesArrays(complementaries, winner.complementaries); + let total = numbers.length + complementaries.length; + + let winned = (splited * (percent.matches + numbers.length)) / total; + winners[index].reward = winned; + }); + }; + + return { numbers, complementaries, winners }; + } + end(guildId) { + if (!this.validLoto(guildId)) return 'invalid loto'; + let loto = this.cache.get(guildId); + loto.ended = true; + + let sql = this.createQuery(this.convertToSql(loto), true); + this.db.query(sql, (err) => { + if (err) throw err; + + this.fillCache(); + }) + + return this.roll(guildId); + } + /** + * @param {{ numbers: Number, complementaries: Number, guildId: String, time: Number, reward: Number }} data + */ + start(data) { + let x = { + guild_id: data.guildId, + numbers: data?.numbers ?? 5, + complementaries: data?.complementaries ?? 2, + reward: data.reward, + endsAt: Date.now() + data.time, + json: [], + ended: false + }; + + this.db.query(this.createQuery(this.convertToSql(x), this.cache.has(data.guildId)), (err) => { + if (err) throw err; + + this.fillCache(); + }); + } +}; + +module.exports = LotoManager; \ No newline at end of file diff --git a/commands/misc/levels.js b/commands/misc/levels.js index 1be524d..8a9cd20 100644 --- a/commands/misc/levels.js +++ b/commands/misc/levels.js @@ -19,7 +19,7 @@ module.exports.help = { * @param {String} prefix */ module.exports.run = (message, args, client, prefix) => { - client.db.query(`SELECT * FROM configs WHERE guild_id="${message.guild.id}"`, (err, req) => { + client.db.query(`SELECT level_enable FROM configs WHERE guild_id="${message.guild.id}"`, (err, req) => { if (err) { console.log(err); message.channel.send({ embeds: [ package.embeds.errorSQL(message.author) ] }); diff --git a/events/message.js b/events/message.js.txt similarity index 100% rename from events/message.js rename to events/message.js.txt diff --git a/events/messageCreate.js b/events/messageCreate.js index b0e3178..b52fc97 100644 --- a/events/messageCreate.js +++ b/events/messageCreate.js @@ -14,6 +14,7 @@ module.exports = { if (message.webhookId) return; client.db.query(`SELECT * FROM configs WHERE interchat_enable="1"`, (err, req) => { + return; if (err) return console.log(err); if (req.find((x) => x.guild_id === message.guild.id)) { diff --git a/events/messageUpdate.js b/events/messageUpdate.js index eb43bf4..b46cdd7 100644 --- a/events/messageUpdate.js +++ b/events/messageUpdate.js @@ -32,6 +32,6 @@ module.exports = { functions.log(a.guild, embed); }; - run(a); + // run(a); } }; \ No newline at end of file diff --git a/slash-commands/economy/loto.js b/slash-commands/economy/loto.js new file mode 100644 index 0000000..b06742a --- /dev/null +++ b/slash-commands/economy/loto.js @@ -0,0 +1,87 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + dm: false, + dev: false, + systems: [{name: "d'économie", value: "economy_enable", state: true}], + permissions: [] + }, + configs: { + name: "loto", + description: "Gère un loto sur le serveur", + options: [ + { + name: 'gérer', + description: "Gère le loto", + type: "SUB_COMMAND_GROUP", + options: [ + { + name: "démarrer", + description: "Lance le loto sur le serveur", + type: 'SUB_COMMAND', + options: [ + { + name: "récompense", + description: `Récompense en ${package.configs.coins} du loto`, + type: 'INTEGER', + required: true + }, + { + name: 'gagnants', + description: "Nombre de numéro gagnants à tirer (minimum 5)", + type: 'INTEGER', + required: true + }, + { + name: "complémentaires", + description: "Nombre de numéro complémentaires à tirer (minimum 2)", + type: 'INTEGER', + required: true + }, + { + name: "temps", + description: "Temps avant la fin du loto (ex: 1d)", + type: 'STRING', + required: true + } + ] + }, + { + name: "tirage", + description: "Fait le tirage du loto", + type: 'SUB_COMMAND' + } + ] + }, + { + name: 'participer', + description: "Participez au loto en cours", + type: 'SUB_COMMAND', + options: [ + { + name: "gagnants", + description: "Les numéro gagnants que vous jouez (ex: 15 68 46 75 12)", + type: 'STRING', + required: true + }, + { + name: "complémentaires", + description: "Les numéro complémentaires que vous jouez (ex: 94 60)", + required: true, + type: 'STRING' + } + ] + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: (interaction) => { + + } +}; \ No newline at end of file diff --git a/slash-commands/fun/vigenere.js b/slash-commands/fun/vigenere.js new file mode 100644 index 0000000..ecff4ed --- /dev/null +++ b/slash-commands/fun/vigenere.js @@ -0,0 +1,62 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); +const vigenere = require('../../assets/scripts/vigenereCode'); + +new vigenere('', 't', '') + +module.exports = { + help: { + cd: 5, + dm: true, + permissions: [], + systems: [], + dev: false + }, + configs: { + name: 'cryptage', + description: "Crypte ou décrypte un texte selon votre clé", + options: [ + { + name: "action", + description: "Action à effectuer sur votre texte", + required: true, + type: 'STRING', + choices: [ + { + name: 'Chiffrer', + value: 'code' + }, + { + name: "Déchiffrer", + value: 'decode' + } + ] + }, + { + name: 'texte', + type: 'STRING', + required: true, + description: "Texte à examiner" + }, + { + name: "clé", + required: true, + description: "Clé de chiffrage/déchiffrage", + type: 'STRING' + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: (interaction) => { + let action = interaction.options.getString('action'); + let text = interaction.options.getString('texte'); + let key = interaction.options.getString('clé'); + + const result = new vigenere(text, key, action).run(); + + interaction.reply({ content: `\`\`\`${result}\`\`\``, ephemeral: true }).catch(() => {}); + } +} \ No newline at end of file diff --git a/slash-commands/moderation/censure.js b/slash-commands/moderation/censure.js new file mode 100644 index 0000000..9ca44c7 --- /dev/null +++ b/slash-commands/moderation/censure.js @@ -0,0 +1,77 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + permissions: ['manage_nicknames'], + systems: [], + dm: false, + dev: false + }, + configs: { + name: 'censure', + description: "Censure le pseudo d'un membre", + options: [ + { + name: 'membre', + description: "Membre à censurer", + type: 'USER', + required: true + }, + { + name: 'raison', + description: "Raison de la censure", + type: 'STRING', + required: true + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: (interaction) => { + let member = interaction.options.getMember('membre'); + let reason = interaction.options.getString('raison'); + if (!functions.checkAllConditions(interaction.guild, null, interaction.member, member, interaction)) return; + + const caracts = "0132456798#&@%*:/;,?!§^$*"; + let nickname = ""; + + const max = member?.nick?.length ?? functions.random(16, 8); + for (let i = 0; i (${message.author.tag})`, + inline: true + }, + { + name: "Membre", + value: `<@${member.id}> (${member.user.tag})`, + inline: true + }, + { + name: 'Raison', + value: reason, + inline: true + } + ) + + member.setNickname(nickname, reason).catch(() => {}); + + interaction.reply({ embeds: [ embed ] }).catch(() => {}); + member.send({ embeds: [embed] }).catch(() => {}); + + functions.log(interaction.guild, embed); + functions.addCase(interaction.guild.id, member.id, interaction.user.id, reason, 'censure'); + } +} \ No newline at end of file diff --git a/slash-commands/moderation/clear.js b/slash-commands/moderation/clear.js new file mode 100644 index 0000000..ed4931b --- /dev/null +++ b/slash-commands/moderation/clear.js @@ -0,0 +1,43 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + permissions: ['manage_messages'], + cd: 5, + dm: false, + dev: false, + systems: [] + }, + configs: { + name: 'clear', + description: "Supprime un nombre de messages dans le salon", + options: [ + { + name: 'messages', + description: "Nombre de messages à supprimer", + required: true, + type: 'INTEGER' + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + let number = parseInt(interaction.options.get('messages').value); + if (number < 1 || number > 100) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("🚫 Nombre invalide") + .setDescription(`Merci de saisir un nombre entre **1** et **100**`) + .setColor('#ff0000') + ] }).catch(() => {}); + + await interaction.channel.bulkDelete(number).catch(() => {}); + interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("✅ Messages supprimés") + .setDescription(`**${number}** message${number > 1 ? 's a été supprimé':' ont été supprimés'}.`) + .setColor('#00ff00') + ] }).catch(() => {}); + } +} \ No newline at end of file diff --git a/slash-commands/moderation/edit-case.js b/slash-commands/moderation/edit-case.js index e810246..80e33d3 100644 --- a/slash-commands/moderation/edit-case.js +++ b/slash-commands/moderation/edit-case.js @@ -27,7 +27,7 @@ module.exports = { dm: false, dev: false, permissions: ['manage_guild'], - systems: [], + systems: [{name: 'de logs', value: 'logs_enable', state: true}], cd: 5 }, /** diff --git a/slash-commands/moderation/filtre-case-action.js b/slash-commands/moderation/filtre-case-action.js index 21371ca..b20bf63 100644 --- a/slash-commands/moderation/filtre-case-action.js +++ b/slash-commands/moderation/filtre-case-action.js @@ -50,7 +50,7 @@ module.exports = { dm: false, dev: false, permissions: ['manage_guild'], - systems: [], + systems: [{name: 'de logs', value: 'logs_enable', state: true}], cd: 5 }, /** diff --git a/slash-commands/moderation/kick.js b/slash-commands/moderation/kick.js index 783ab41..bba3718 100644 --- a/slash-commands/moderation/kick.js +++ b/slash-commands/moderation/kick.js @@ -48,7 +48,7 @@ module.exports = { .addFields( { name: 'Modérateur', - value: `<@${interaction.user}> ( ${interaction.user.tag} ${interaction.user.id} )`, + value: `<@${interaction.user.id}> ( ${interaction.user.tag} ${interaction.user.id} )`, inline: true }, { diff --git a/slash-commands/moderation/logs.js b/slash-commands/moderation/logs.js new file mode 100644 index 0000000..82479bc --- /dev/null +++ b/slash-commands/moderation/logs.js @@ -0,0 +1,151 @@ +const Discord = require('discord.js'); +const moment = require('moment'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + dev: false, + dm: false, + systems: [{name: 'de logs', value: 'logs_enable', state: true}], + permissions: ['manage_guild'] + }, + configs: { + name: 'logs', + description: "Gère les logs du serveur", + options: [ + { + name: "afficher", + description: "Affiche les logs du serveur", + type: 'SUB_COMMAND' + }, + { + name: 'identifier', + description: "Affiche un log spécifique", + type: 'SUB_COMMAND', + options: [ + { + name: 'identifiant', + description: "Identifiant du log que vous voulez voir", + type: 'STRING', + required: true + } + ] + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + await interaction.reply({ embeds: [ package.embeds.waitForDb(interaction.user) ] }).catch(() => {}); + const subcommand = interaction.options.getSubcommand(); + + if (subcommand == 'afficher') { + interaction.client.db.query(`SELECT * FROM mod_cases WHERE guild_id="${interaction.guild.id}"`, (err, req) => { + if (err) { + functions.sendError(err, 'query fetch at /logs afficher', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + return; + }; + + if (req.length === 0) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("🚫 Logs de modération") + .setDescription(`Il n'y a aucun log de modération.`) + .setColor('ORANGE') + ] }); + + if (req.length > 5) { + let now = package.embeds.classic(interaction.user) + .setTitle("Logs de modération") + .setDescription(`Voici les logs de modération (**${req.length.toLocaleString('fr-DE')}** logs).`) + .setColor('ORANGE') + + var embeds = []; + let pile = false; + let count = 0; + + for (let i = 0; i < req.length; i++) { + const warn = req[i]; + + now.addField(`${warn.action}`, `<@${warn.user_id}>\n> Donné par <@${warn.mod_id}>\n> Raison: \`${warn.reason}\`\n> Date: \n*Log id: ${warn.case_id}*`, false); + + pile = false; + + count++; + if (count === 5) { + count=0; + pile = true; + embeds.push(now); + + now = null; + now = package.embeds.classic(interaction.user) + .setTitle("Logs de modération") + .setDescription(`Voici les logs de modération (**${req.length.toLocaleString('fr-DE')}** logs).`) + .setColor('ORANGE') + } + }; + + if (!pile) embeds.push(now); + + functions.pagination(interaction.user, 'none', embeds, 'modlogs', interaction); + } else { + const embed = package.embeds.classic(interaction.user) + .setTitle("Logs de modération") + .setColor('ORANGE') + .setDescription(`voici les logs de modération.`) + + req.forEach((warn) => { + embed.addField(`${warn.action}`, `<@${warn.user_id}>\n> Donné par <@${warn.mod_id}> \n> Raison: \`${warn.reason}\`\n> Date: \n*Log id: ${warn.case_id}*`, false); + }); + + interaction.editReply({ embeds: [ embed ] }).catch(() => {}); + } + }) + }; + if (subcommand == 'identifier') { + let id = interaction.options.getString('identifiant'); + interaction.client.db.query(`SELECT * FROM mod_cases WHERE guild_id="${interaction.guild.id}" AND case_id="${id}"`, (err, req) => { + if (err) { + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + functions.sendError(err, 'query at /logs identifier', interaction.user); + return; + }; + if (req.length == 0) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("🚫 Pas de log") + .setDescription(`Le log avec \`${id}\` pour identifiant n'existe pas`) + .setColor('#ff0000') + ] }).catch(() => {}); + + const log = req[0]; + const modlog = package.embeds.classic(interaction.user) + .setTitle(modlog.action) + .addFields( + { + name: "Membre", + value: `<@${log.user_id}> (\`${log.user_id}\`)`, + inline: true + }, + { + name: "Modérateur", + value: `<@${log.mod_id}> (\`${log.mod_id}\`)`, + inline: true + }, + { + name: "Raison", + value: log.reason ?? "Pas de raison", + inline: true + }, + { + name: "Date", + value: ``, + inline: false + } + ) + + interaction.editReply({ embeds: [ modlog ] }).catch(() => {}); + }); + } + } +} \ No newline at end of file diff --git a/slash-commands/usefull/commande.js b/slash-commands/usefull/commande.js index ceec9b9..1a6ce1b 100644 --- a/slash-commands/usefull/commande.js +++ b/slash-commands/usefull/commande.js @@ -37,7 +37,7 @@ module.exports = { const ephemeral = interaction.options.get('discret') ? interaction.options.get('discret').value : true; const commandName = interaction.options.get('commande').value; - const commandList = require('../../assets/data/commands.json'); + const commandList = require('../../assets/data/slashCommands'); let command; Object.keys(commandList).forEach((key) => { @@ -56,17 +56,17 @@ module.exports = { .addFields( { name: "Cooldown", - value: `${command.help.cooldown} seconde(s)`, + value: `${command.help.cd} seconde(s)`, inline: true }, { - name: "Alias", - value: command.help.aliases.length === 0 ? "Aucun alias" : command.help.aliases.map((alias) => `\`${alias}\``).join(', '), + name: "Systèmes", + value: command.help.systems?.length === 0 ? "Aucun système requis" : command.help.systems.map((system) => `Système ${system.name} : doit être **${system.state == true ? 'activé':'désactivé'}**`).join(', '), inline: true }, { name: "Permissions", - value: command.help.permissions.length === 0 ? 'Aucune permission nécéssaires' : command.help.permissions.map((perm) => '`' + perms[perm.toUpperCase()] + '`').join(', '), + value: command.help.permissions?.length === 0 ? 'Aucune permission nécéssaires' : command.help.permissions.map((perm) => '`' + perms[perm.toUpperCase()] + '`').join(', '), inline: true }, { @@ -78,11 +78,6 @@ module.exports = { name: "Exécutable en privé ?", value: command.help.dm ? "Oui" : "Non", inline: true - }, - { - name: "Documentation", - value: `[${command.name}](https://github.com/BotOracle/Documentation/blob/main/commands/${command.name})`, - inline: true } ) .setColor('ORANGE') diff --git a/slash-commands/usefull/levels.js b/slash-commands/usefull/levels.js new file mode 100644 index 0000000..77ccf41 --- /dev/null +++ b/slash-commands/usefull/levels.js @@ -0,0 +1,92 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + dev: false, + dm: false, + systems: [{name: "de niveau", value: "level_enable", state: true}], + permissions: [] + }, + configs: { + name: 'classement', + description: "Affiche le classement des niveaux du serveur" + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: (interaction) => { + interaction.client.db.query(`SELECT * FROM levels WHERE guild_id="${interaction.guild.id}"`, (error, request) => { + if (error) { + functions.sendError(error, 'query at /classement', interaction.user) + interaction.reply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + + return; + }; + + const levels = request.sort((a, b) => b.total - a.total); + + if (request.length < 5) { + const embed = package.embeds.classic(interaction.user) + .setTitle("Niveaux") + .setDescription(`Voici le top **${levels.length.toLocaleString('fr-DE')}** des niveaux du serveur.`) + .setColor('ORANGE') + + levels.forEach((lvl) => { + embed.addField( + (levels.indexOf(lvl) + 1).toString(), + `<@${lvl.user_id}> +> Niveau **${parseInt(lvl.level).toLocaleString('fr-DE')}** +> Avec un total de **${parseInt(lvl.total).toLocaleString('fr-DE')} messages**`, + false + ); + }); + + interaction.reply({ embeds: [ embed ] }).catch(() => {}); + } else { + let now = package.embeds.classic(interaction.user) + .setTitle("Niveaux") + .setDescription(`Voici le top **${levels.length.toLocaleString('fr-DE')}** des niveaux du serveur.`) + .setColor('ORANGE') + + var embeds = []; + let pile = false; + let count = 0; + + for (let i = 0; i < levels.length; i++) { + const lvl = levels[i]; + + now.addField( + (levels.indexOf(lvl) + 1).toString(), + `<@${lvl.user_id}> +> Niveau **${parseInt(lvl.level).toLocaleString('fr-DE')}** +> Avec un total de **${parseInt(lvl.total).toLocaleString('fr-DE')} messages**`, + false + ); + + pile = false; + + count++; + if (count === 5) { + count=0; + pile = true; + embeds.push(now); + + now = null; + now = package.embeds.classic(interaction.user) + .setTitle("Niveaux") + .setDescription(`Voici le top **${levels.length.toLocaleString('fr-DE')}** des niveaux du serveur.`) + .setColor('ORANGE') + + } + }; + + if (!pile) embeds.push(now); + + functions.pagination(interaction.user, 'none', embeds, 'classement', interaction); + } + }) + } +} \ No newline at end of file From 7e62352bab5ce394e1bdce3ffb1b13458a3c9215 Mon Sep 17 00:00:00 2001 From: Greensky-gs <72513011+Greensky-gs@users.noreply.github.com> Date: Sat, 13 Aug 2022 14:04:50 +0200 Subject: [PATCH 02/14] Rename mailManager.js to mailsManager.js --- assets/managers/{mailManager.js => mailsManager.js} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename assets/managers/{mailManager.js => mailsManager.js} (99%) diff --git a/assets/managers/mailManager.js b/assets/managers/mailsManager.js similarity index 99% rename from assets/managers/mailManager.js rename to assets/managers/mailsManager.js index 85739c4..952c0c3 100644 --- a/assets/managers/mailManager.js +++ b/assets/managers/mailsManager.js @@ -389,4 +389,4 @@ class MailManager { } }; -module.exports = MailManager \ No newline at end of file +module.exports = MailManager From d7098b16cef352ef16df78e6dc43a4c4381cc8a0 Mon Sep 17 00:00:00 2001 From: Greensky-gs <72513011+Greensky-gs@users.noreply.github.com> Date: Sat, 13 Aug 2022 14:06:50 +0200 Subject: [PATCH 03/14] Update csc.js --- slash-commands/usefull/csc.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slash-commands/usefull/csc.js b/slash-commands/usefull/csc.js index 706ca5b..f78c5be 100644 --- a/slash-commands/usefull/csc.js +++ b/slash-commands/usefull/csc.js @@ -128,7 +128,7 @@ module.exports = { const fileContent = `const Discord = require('discord.js'); -const functions = require('../../assets/functions'); +const functions = require('../assets/functions'); const package = functions.package(); module.exports = { @@ -278,4 +278,4 @@ module.exports = { } } } -} \ No newline at end of file +} From 68cea3a6ffc93a8a33b5e1ed41eaa7b3464915e2 Mon Sep 17 00:00:00 2001 From: Greensky Date: Tue, 16 Aug 2022 18:04:25 +0200 Subject: [PATCH 04/14] 1.5 --- assets/data/configs.json | 18 +- assets/data/data.json | 2 +- assets/embeds.js | 46 +- assets/functions.js | 1 - assets/managers/assets/buttons.js | 30 ++ assets/managers/assets/embeds.js | 102 +++++ assets/managers/giveawayManager.js | 579 ++++++++++++++++---------- assets/managers/ticketsManager.js | 54 ++- commands/.devs/exportdb.js | 5 +- events/guildCreate.js | 12 +- events/guildMemberAdd.js | 17 +- events/messageCreateMention.js | 50 +++ events/messageReactionAdd.js | 32 -- events/messageReactionRemove.js | 32 -- events/messageUpdate.js | 2 +- events/ready.js | 10 +- slash-commands/economy/daily.js | 4 +- slash-commands/economy/loto.js | 78 +++- slash-commands/economy/weekly.js | 2 +- slash-commands/fun/game.js | 2 +- slash-commands/moderation/autorole.js | 136 ++++++ slash-commands/moderation/ticket.js | 130 +++++- slash-commands/usefull/channel.js | 37 ++ slash-commands/usefull/contact.js | 4 +- slash-commands/usefull/feedback.js | 39 ++ slash-commands/usefull/giveaway.js | 88 ++-- 26 files changed, 1148 insertions(+), 364 deletions(-) create mode 100644 assets/managers/assets/buttons.js create mode 100644 assets/managers/assets/embeds.js create mode 100644 events/messageCreateMention.js delete mode 100644 events/messageReactionAdd.js delete mode 100644 events/messageReactionRemove.js create mode 100644 slash-commands/moderation/autorole.js create mode 100644 slash-commands/usefull/feedback.js diff --git a/assets/data/configs.json b/assets/data/configs.json index e06b133..b15add6 100644 --- a/assets/data/configs.json +++ b/assets/data/configs.json @@ -126,18 +126,6 @@ "description": "Active ou désactive le système de niveaux", "param": "level_enable" }, - { - "name": "Système d'interchat", - "type": "boolean", - "description": "Active ou désactive le système d'interchat", - "param": "interchat_enable" - }, - { - "name": "Salon d'interchat", - "type": "channel", - "description": "Configure le salon d'interchat", - "param": "interchat_channel" - }, { "name": "Roles d'arrivée", "type": "boolean", @@ -167,6 +155,12 @@ "type": "boolean", "description": "Active ou désactive le système d'économie", "param": "economy_enable" + }, + { + "name": "Système de tickets", + "type": "boolean", + "description": "Active oudésactive le système de tickets", + "param": "ticket_enable" } ] } \ No newline at end of file diff --git a/assets/data/data.json b/assets/data/data.json index 33ada91..837dee0 100644 --- a/assets/data/data.json +++ b/assets/data/data.json @@ -7,7 +7,7 @@ "errorChannel": "839497213113270322", "botID": "918137973202112592", "contactChannel": "827790768272834580", - "version": "1.4.2", + "version": "1.5", "beta_token": "OTE4MTM3OTczMjAyMTEyNTky.G5q2vD.tYpVroN28ovgVIPXUKR9GDVqmZexUEwneXTTLk", "beta": false, "doc": "https://bit.ly/3c37f8V", diff --git a/assets/embeds.js b/assets/embeds.js index 3dd74be..ec22eb4 100644 --- a/assets/embeds.js +++ b/assets/embeds.js @@ -1,5 +1,5 @@ const emojis = require('./data/emojis.json'); -const { MessageEmbed, User, Message } = require('discord.js'); +const { MessageEmbed, User, Message, Interaction } = require('discord.js'); const collections = require('./data/collects'); const data = require('./data/data.json'); @@ -187,13 +187,13 @@ module.exports = { invalidLoto: (user, type) => { return generateBasic(user) .setTitle("❌ Loto invalide") - .setDescription(`Il n'y a pas de loto sur le serveur.\n${type == 'participate' ? `Il n'y a pas de loto en cours.` : `Le loto en cours n'est pas terminé`}`) + .setDescription(`Il n'y a pas de loto sur le serveur.\n\n:warning:\n> Vous ne pouvez participer qu'a un loto en cours\n> Vous ne pouvez faire le tirage sur un loto terminé`) .setColor('#ff0000') }, invalidNumbers: (user) => { return generateBasic(user) .setTitle("🚫 Nombres invalides") - .setDescription(`Les nombres que vous avez spécifié sont invalides.\n**Vérifiez que vous avez le même nombre de numéro que celui requis**.`) + .setDescription(`Les nombres que vous avez spécifié sont invalides.\n**Vérifiez que vous avez le même nombre de numéro que celui requis**.\n:warning: Vous ne pouvez pas jouer deux fois le même numéro`) .setColor('#ff0000') }, alreadyParticipate: (user) => { @@ -226,14 +226,44 @@ module.exports = { .setColor('#00ff00') }, /** - * @param {{ numbers: Number[], complementaries: Number[], winners: [], user: User }} data + * @param {{ numbers: Number[], complementaries: Number[], winners: [], user: User }} Edata */ - end: (data) => { - return generateBasic(data.user) + end: (Edata) => { + return generateBasic(Edata.user) .setTitle('🎉 Tirage') - .setDescription(`**Numéro gagnants :** ${data.numbers.join(' ')}\n**Numéro complémentaires :** ${data.complementaries.join(' ')} + .setDescription(`**Numéro gagnants :** ${Edata.numbers.join(' ')}\n**Numéro complémentaires :** ${Edata.complementaries.join(' ')} -${data.winners.length == 0 ? 'Pas de gagnants' : data.winners.map(w => `<@${w.user_id}> : ${x}`)}`) +${Edata.winners.length == 0 ? 'Pas de gagnants' : Edata.winners.map(w => `<@${w.user_id}> : ${w.reward} ${data.coins}`).join('\n')}`) + .setColor('#00ee00') + .setFooter({ iconURL: undefined, text: `Les ${data.coins} ont été ajoutés au(x) gagnant(s)` }) + }, + started: (user, numbers, complementaries, reward, Rtime) => { + let time = ((parseInt(Rtime) + Date.now()) / 1000).toFixed(0); + + return generateBasic(user) + .setTitle("🎉 Loto lancé") + .setDescription(`Le loto a été lancé !\nIl prendra fin le ( )\n\nPour participer il faut **${numbers}** numéro et **${complementaries}** numéro complémentaires.\n\nRécompense :\n${reward} ${data.coins}`) + .setColor('#ff0000') + } + }, + giveaway: { + noGw: (user, id) => { + return generateBasic(user) + .setTitle("❌ Giveaway introuvable") + .setDescription(`Le giveaway avec l'identifiant \`${id}\` est introuvable.`) + .setColor('#ff0000') + }, + alreadyEnded: (user) => { + return generateBasic(user) + .setTitle("❌ Giveaway terminé") + .setDescription(`Ce giveaway est déjà terminé`) + .setColor('#ff0000') + }, + notEnded: (user) => { + return generateBasic(user) + .setTitle("❌ Giveaway en cours") + .setDescription(`Ce giveaway n'est pas terminé`) + .setColor('#ff0000') } } } \ No newline at end of file diff --git a/assets/functions.js b/assets/functions.js index 28998a9..ca3ffde 100644 --- a/assets/functions.js +++ b/assets/functions.js @@ -464,7 +464,6 @@ module.exports = { command: data.commandName, date: data.time }; - if (data.isSlash == true) dataset.command = `/${data.commandName}`; data.client.db.query(`INSERT INTO cooldowns (${Object.keys(dataset).join(', ')}) VALUES (${Object.values(dataset).map(x => `"${x}"`).join(', ')})`, (err) => { if (err) console.log(err); diff --git a/assets/managers/assets/buttons.js b/assets/managers/assets/buttons.js new file mode 100644 index 0000000..570f957 --- /dev/null +++ b/assets/managers/assets/buttons.js @@ -0,0 +1,30 @@ +const { MessageButton, MessageActionRow } = require('discord.js'); + +module.exports = { + participate: () => { + const button = new MessageButton() + .setCustomId('gw-participate') + .setStyle('SUCCESS') + .setLabel("Participer") + .setEmoji('🎉') + + return button; + }, + cancelParticipation: () => { + const button = new MessageButton() + .setCustomId('gw-unparticipate') + .setLabel("Annuler la participation") + .setStyle('DANGER') + + return button + }, + /** + * @param {MessageActionRow[]} components + */ + getAsRow: (components) => { + const row = new MessageActionRow() + .addComponents(components) + + return row; + } +} \ No newline at end of file diff --git a/assets/managers/assets/embeds.js b/assets/managers/assets/embeds.js new file mode 100644 index 0000000..44cbf3d --- /dev/null +++ b/assets/managers/assets/embeds.js @@ -0,0 +1,102 @@ +const { MessageEmbed } = require('discord.js'); + +module.exports = { + /** + * @param {{ reward: String, winnerCount: Number, hosterId: String, channel: TextChannel, time: Number, ?bonusRoles: String[], ?deniedRoles: String[], ?requiredRoles: String[] }} data + */ + giveaway: (data) => { + const embed = new MessageEmbed() + .setTitle("🎉 Giveaway 🎉") + .setColor('#00ff00') + .setDescription(`**${data.reward}** +Offert par <@${data.hosterId}> +**${data.winnerCount}** gagnant${data.winnerCount > 1 ? 's':''} +Participants : ${data.participants ? data.participants.length : "0"} + +Finit `) + + if (data.bonusRoles && data.bonusRoles.length > 0) { + embed.addFields({ + name: "Rôles bonus", + value: data.bonusRoles.map((rId) => `<@&${rId}>`).join(' '), + inline: false + }); + }; + if (data.requiredRoles && data.requiredRoles.length > 0) { + embed.addFields({ + name: "Rôles requis", + value: data.requiredRoles.map((rId) => `<@&${rId}>`).join(' '), + inline: false + }); + }; + if (data.deniedRoles && data.deniedRoles.length > 0) { + embed.addFields({ + name: "Rôles interdits", + value: data.deniedRoles.map((rId) => `<@&${rId}>`).join(' '), + inline: false + }); + }; + + return embed; + }, + ended: (data, winners) => { + const embed = new MessageEmbed() + .setTitle("🎉 Giveaway terminé 🎉") + .setColor('#ff0000') + .setDescription(`**${data.reward}** +Offert par <@${data.hoster_id}> +${winners.length > 0 ? `Gagnant${data.winnerCount > 1 ? 's': ''} : ${winners.map(x => `<@${x}>`).join(' ')}`: "Pas de gagnants"} +Participants : ${data.participants.length} + +Finit `) + + return embed; + }, + hasDeniedRoles: (deniedRoles, url) => { + return new MessageEmbed() + .setTitle("🚫 Accès refusé") + .setDescription(`L'accès à [**ce giveaway**](${url}) vous est refusé car vous avez un ou plusieurs de ces rôles :\n${deniedRoles.map(x => `<@&${x}>`).join(' ')}`) + .setColor('#ff0000') + }, + missingRequiredRoles: (requiredRoles, url) => { + return new MessageEmbed() + .setTitle("🚫 Accès refusé") + .setDescription(`L'accès à [**ce giveaway**](${url}) vous est réfusé car vous n'avez pas un ou plusieurs de ces rôles :\n${requiredRoles.map(x => `<@&${x}>`).join(' ')}`) + .setColor('#ff0000') + }, + entryAllowed: (url) => { + return new MessageEmbed() + .setTitle("🎉 Accès autorisé") + .setColor('#00ff00') + .setDescription(`Votre participation à [**ce giveaway**](${url}) a été confirmée.\nBonne chance !`) + }, + alreadyParticipate: (url) => { + return new MessageEmbed() + .setTitle("🚫 Déjà participé") + .setDescription(`Vous participez déjà à [**ce giveaway**](${url}).`) + .setColor('#ff0000') + }, + notParticipated: (url) => { + return new MessageEmbed() + .setTitle("🚫 Pas de participation") + .setDescription(`Vous n'avez pas participé à [**ce giveaway**](${url})`) + .setColor('#ff0000') + }, + removeParticipation: (url) => { + return new MessageEmbed() + .setTitle("❌ Participation annulée") + .setDescription(`Votre participation à [**ce giveaway**](${url}) a été annulée.`) + .setColor('#00ff00') + }, + winners: (winners, url) => { + if (winners.length == 0) return new MessageEmbed() + .setTitle("Pas de gagnants") + .setDescription(`Il n'y a aucun gagnants pour [**ce giveaway**](${url}).`) + .setColor('#ff0000'); + + return new MessageEmbed() + .setTitle("🎉 Gagnants") + .setDescription(`Le${winners.length > 1 ? 's':''} gagnant${winners.length > 1 ? 's':''} de [**ce giveaway**](${url}) ${winners.length > 1 ? 'sont':'est'} ${winners.map(x => `<@${x}>`).join(' ')}`) + .setColor('#00ff00') + } +}; \ No newline at end of file diff --git a/assets/managers/giveawayManager.js b/assets/managers/giveawayManager.js index f07ff95..6b5e44c 100644 --- a/assets/managers/giveawayManager.js +++ b/assets/managers/giveawayManager.js @@ -1,276 +1,425 @@ -const Discord = require('discord.js'); -const functions = require('../functions.js'); -const embeds = functions.package().embeds; +const { Client, Collection, TextChannel, GuildMember, ButtonInteraction, Guild, Message } = require('discord.js'); const mysql = require('mysql'); -const moment = require('moment'); -moment.locale('fr'); +const embeds = require('./assets/embeds'); +const buttons = require('./assets/buttons'); -class GiveawayManager { +class GiveawaysManager { /** - * @param {Discord.Client} client + * @param {Client} client * @param {mysql.Connection} db */ constructor(client, db) { this.client = client; this.db = db; + this.giveaways = new Collection(); + this.ended = new Collection(); + this.timeout = new Collection(); } - generateEmbed(data, guild) { - const hoster = (guild.members.cache.get(data.hoster_id) || guild.me).user; - - const embed = embeds.classic(hoster) - .setTitle(":tada: GIVEAWAY :tada:") - .setTimestamp(new Date(parseInt(data.endsAt)).toISOString()) - .setDescription(`Appuyez sur le boutton pour participer !\n\nRécompense: \`${data.reward}\`\nOffert par: <@${data.hoster_id}>\n${data.winnerCount} gagnan${data.winnerCount > 1 ? "ts" : "t"}\nFinit le `) - .setColor(guild.me.displayHexColor) - - if (data.endsAt - Date.now() < 10000) embed.setColor('#ff0000').setTitle(":tada: **G I V E A W A Y** :tada:"); - - return embed + getUrl(data) { + return `https://discord.com/channels/${data.guild_id}/${data.channel_id}/${data.message_id}`; } /** - * @param {objectGW} data - * @param {Discord.Guild} guild + * @param {{ reward: String, winnerCount: Number, hosterId: String, channel: TextChannel, time: Number, ?bonusRoles: String[], ?deniedRoles: String[], ?requiredRoles: String[] }} data */ - generateEndedEmbed(data, guild) { - const hoster = (guild.members.cache.get(data.hoster_id) || guild.me).user; + start(data) { + if (!data.channel?.guild) return 'no guild'; + + const embed = embeds.giveaway(data); + const row = buttons.getAsRow([ buttons.participate(), buttons.cancelParticipation() ]); + + data.channel.send({ embeds: [ embed ], components: [ row ] }).then((sent) => { + let dataset = { + reward: data.reward, + hoster_id: data.hosterId, + guild_id: data.channel.guild.id, + channel_id: data.channel.id, + message_id: sent.id, + winnerCount: data.winnerCount, + winners: [], + ended: false, + participants: [], + required_roles: data.requiredRoles ?? [], + bonus_roles: data.bonusRoles ?? [], + denied_roles: data.deniedRoles ?? [], + endsAt: Date.now() + data.time + }; - const embed = embeds.classic(hoster) - .setTitle(":tada: **GIVEAWAY TERMINÉ** :tada:") - .setTimestamp(new Date(parseInt(data.endsAt)).toISOString()) - .setColor(guild.me.displayHexColor) - .setDescription(`Giveaway terminé !\n\nRécompense: \`${data.reward}\`\nOffert par <@${hoster.id}>\n${data.winnerCount} gagnan${data.winnerCount > 1 ? 'ts' : "t"}`) + let sql = this.createQuery(this.formatToSql(dataset), false); + this.giveaways.set(sent.id, this.formatToObject(dataset)); - return embed; + this.db.query(sql, (err) => { + if (err) throw err; + }); + }).catch((e) => {console.log(e)}); } - edit(data, guild) { - const channel = guild.channels.cache.get(data.channel_id); - if (!channel) return; + /** + * @param {GuildMember} member + */ + checkIfValidEntry(member, data) { + if (data.denied_roles && data.denied_roles?.length > 0) { + let has = false; + for (const role of data.denied_roles) { + if (member.roles.cache.has(role)) has = true; + }; - const msg = channel.messages.cache.get(data.message_id); - if (!msg) return; + if (has) { + return { + embed: embeds.hasDeniedRoles(data.denied_roles, this.getUrl(data)), + state: false + } + } + }; + if (data.required_roles && data.required_roles.length > 0) { + let has = true; + for (const role of data.required_roles) { + if (!member.roles.cache.has(role)) has = false; + }; - const embed = this.generateEmbed(data, guild); - msg.edit({ embeds: [ embed ] }).catch((e) => console.log(e)); + if (!has) { + return { + embed: embeds.missingRequiredRoles(data.required_roles, this.getUrl(data)), + state: false + }; + }; + }; + return { + embed: embeds.entryAllowed(this.getUrl(data)), + state: true + }; } /** - * @param {Discord.Guild} guild - * @param {Discord.TextChannel} - * @param {Discord.User} user - * @param {String} reward - * @param {Number} winnerCount - * @param {Number} time + * @param {{}} data + * @param {Boolean} exists */ - start(guild, channel, user, reward, winnerCount, time) { - const data = { - endsAt: time + Date.now(), - hoster_id: user.id, - reward: reward, - winnerCount: winnerCount + createQuery(data, exists) { + const arrays = ['participants', 'bonus_roles', 'denied_roles', 'required_roles', 'winners']; + + let sql = `INSERT INTO giveaways (${Object.keys(data).join(', ')}) VALUES ( ${Object.values(data).map(x => x.toString().includes('[') ? `'${x}'` : (typeof x =="string") ? `"${x.replace(/"/g, '\\"')}"`: `"${x}"`).join(', ')} )`; + + if (exists == true) { + sql = `UPDATE giveaways SET ${Object.keys(data).map((x => `${x}=${(typeof data[x] == "string" && arrays.includes(x)) ? `'${data[x].replace(/"/g, '\\"')}'` : `"${data[x]}"`}`)).join(', ')}`; }; - const row = new Discord.MessageActionRow() - .addComponents( - new Discord.MessageButton() - .setCustomId('giveaway-participate') - .setLabel('Participer') - .setEmoji('🎉') - .setStyle('SUCCESS') - ) - - const embed = this.generateEmbed(data, guild); - channel.send({ embeds: [ embed ], components: [ row ] }).then((msg) => { - this.db.query(`INSERT INTO giveaways (guild_id, channel_id, message_id, hoster_id, reward, endsAt, winnerCount, path) VALUES ("${guild.id}", "${channel.id}", "${msg.id}", "${user.id}", "${reward}", "${data.endsAt}", "${winnerCount}", "https://discord.com/channels/${guild.id}/${channel.id}/${msg.id}")`, (err, req) => { - if (err) return console.log(err) & channel.send({ embeds: [ embeds.errorSQL(user) ] }); - }); - }) + return sql; + } + formatToSql(data) { + let gw = data; + const arrays = ['participants', 'bonus_roles', 'denied_roles', 'required_roles', 'winners']; + + for (const prop of arrays) { + gw[prop] = JSON.stringify(gw[prop]); + }; + gw.ended = gw.ended == true ? '1' : "0"; + for (const string of Object.keys(gw).filter(x => typeof gw[x] == "string" && !arrays.includes(x))) { + gw[string] = gw[string].replace(/"/g, '\\"'); + }; + + return gw; + } + formatToObject(data) { + let gw = data; + + for (const prop of ['participants', 'bonus_roles', 'denied_roles', 'required_roles', 'winners']) { + gw[prop] = JSON.parse(gw[prop]); + }; + + gw.winnerCount = parseInt(gw.winnerCount); + gw.endsAt = parseInt(gw.endsAt); + gw.ended = gw.ended == "1"; + + for (const string of Object.keys(data).filter(x => typeof gw[x] == "string")) { + gw[string] = gw[string].replace(/\\"/g, '"'); + }; + + return gw; } /** - * @param {Discord.Guild} guild - * @param {objectGW} data + * @param {{ guild: Guild, channel: TextChannel, message: Message }} data */ - end(guild, data) { - const channel = guild.channels.cache.get(data.channel_id); - if (!channel) return; + async roll(gw, data) { + if (gw.participants.length == 0) return []; + let participants = []; + + for (const id of gw.participants) { + const member = await data.guild.members.fetch(id); + if (!member) return console.log('hey'); + + participants.push(id); + if (gw.bonus_roles?.length > 0) { + for (const rId of gw.bonus_roles) { + if (member.roles.cache.has(rId)) participants.push(id); + }; + }; + }; - this.db.query(`SELECT user_id FROM gw_participants WHERE message_id="${data.message_id}" AND guild_id="${guild.id}"`, (err, req) => { - if (err) return channel.send({ content: "Une erreur s'est produite lors de la récupération des participants." }) & console.log(err); + if (participants.length == 0) return []; - const users = req - this.db.query(`UPDATE giveaways SET ended="1" WHERE message_id="${data.message_id}" AND guild_id="${guild.id}"`, (e) => { - if (e) console.log(e); - }); - - if (users.length === 0) return functions.lineReply(data.message_id, channel, `Je n'ai pu trouver aucun gagnant pour ce giveaway.`); - - let winners = []; - for (let i = 0; i < data.winnerCount; i++) { - const possible = users.filter(x => !winners.includes(x)); - if (!possible.length === 0) return; - - const index = Math.floor(Math.random() * users.length); - const id = users[index].user_id; - - winners.push(id); + let winners = []; + const roll = () => { + let winner = participants[Math.floor(Math.random() * participants.length)]; + if (winner) { + participants = participants.filter(x => x !== winner); }; + return winner; + }; - let pluriel = data.winnerCount > 1; + let i = 0; + let end = false; + while (end == false) { + i++; + let winner = roll(); - this.edit(data, guild); - functions.lineReply(data.message_id, channel, `Giveaway terminé ! L${pluriel ? 'es' : 'e'} gagnan${pluriel ? 'ts sont' : "t est"} ${winners.map(u => `<@${u}>`).join(', ')} !\n${pluriel ? 'vous avez' : 'tu as'} gagné **${data.reward}**`); + if (winner) winners.push(winner); + if (participants.length == 0 || i == gw.winnerCount) end = true; + }; - }); + return winners; } /** - * @param {Discord.Guild} guild - * @param {objectGW} data + * @param {String} messageId + * @returns { "no giveaway" | "no guild" | "no channel" | "no message" | "no winner" | "not ended" | String[] } */ - reroll (guild, data) { - const channel = guild.channels.cache.get(data.channel_id); - if (!channel) return; - - this.db.query(`SELECT user_id FROM gw_participants WHERE message_id="${data.message_id}" AND guild_id="${guild.id}"`, (err, req) => { - if (err) return channel.send({ content: "Une erreur s'est produite lors de la récupération des participants." }) & console.log(err); - - const users = req - - if (users.length === 0) return functions.lineReply(data.message_id, channel, `Je n'ai pu trouver aucun gagnant pour ce giveaway.`); - - let winners = []; - for (let i = 0; i < data.winnerCount; i++) { - const possible = users.filter(x => !winners.includes(x)); - if (!possible.length === 0) return; - - const index = Math.floor(Math.random() * users.length); - const id = users[index].user_id; - - winners.push(id); - }; + async reroll(messageId) { + let gw = this.ended.get(messageId); + if (!gw && this.giveaways.has(messageId)) return 'not ended'; + if (!gw) return 'no giveaway'; + - let pluriel = data.winnerCount > 1; + const guild = this.client.guilds.cache.get(gw.guild_id); + if (!guild) return 'no guild'; - this.edit(data, guild); - functions.lineReply(data.message_id, channel, `L${pluriel ? 'es' : 'e'} nouvea${pluriel ? 'ux' : 'u'} gagnan${pluriel ? 'ts sont' : "t est"} ${winners.map(u => `<@${u}>`).join(', ')} !\n${pluriel ? 'vous avez' : 'tu as'} gagné **${data.reward}**`); + const channel = guild.channels.cache.get(gw.channel_id); + if (!channel) return 'no channel'; + + const message = await channel.messages.fetch(messageId); + if (!message) return 'no message'; + + let winners = await this.roll(gw, { guild, channel, message }); + gw.winners = winners; + const embed = embeds.ended(gw, winners); + + message.edit({ embeds: [ embed ] }).catch(() => {}); + channel.send({ reply: { messageReference: message }, embeds: [ embeds.winners(winners, this.getUrl(gw)) ] }).catch(() => {}); + + let sql = this.createQuery(this.formatToSql(gw), true); + this.db.query(sql, (err) => { + if (err) throw err; }); + + this.ended.set(messageId, gw); + + return winners; } /** - * @param {Discord.TextChannel} channel - * @param {Discord.User} user + * @param {String} messageId + * @returns { "no giveaway" | "no guild" | "no channel" | "no message" | "no winner" | "already ended" | String[] } */ - list(channel, user) { - const guild = channel.guild; - - this.db.query(`SELECT * FROM giveaways WHERE guild_id="${guild.id}" AND endsAt>"${Date.now()}"`, (err, req) => { - if (err) return channel.send({ embeds: [ embeds.errorSQL(user) ] }); - - if (req.length === 0) return channel.send({ embeds: [ embeds.classic(user) - .setTitle("Pas de giveaways") - .setDescription(`Il n'y a aucun giveaway en cours sur ce serveur.`) - .setColor('#ff0000') - ] }); - - const original = require('./functions').package().embeds.classic(user) - .setTitle("Giveaways") - .setDescription(`Voici la liste des giveaways sur \`${guild.name}\`.\nIl y a actuellement **${req.length}** giveawa${req.length > 1 ? "ys" : "y"} en cours sur le serveur.`) - .setColor('ORANGE') - - if (req.length > 5) { - let now = original; - - let embeds = []; - let pile = false; - let count = 0; - - for (let i = 0; i < req.length; i++) { - const warn = req[i]; - - now.addField(`Giveaway`, `Offert par <@${warn.hoster_id}>\n> Récompense: \`${warn.reward}\`\n> Finit: ${moment(parseInt(warn.endsAt)).format('DD/MM/YYYY - hh:mm:ss')}\nDans <#${warn.channel_id}> avec ${warn.winnerCount} gagnan${warn.winnerCount > 1 ? "ts" : "t"}`, false); - - pile = false; - - count++; - if (count === 5) { - count=0; - pile = true; - embeds.push(now); - - now = null; - now = embeds.classic(user) - .setTitle("Giveaways") - .setDescription(`Voici la liste des giveaways sur \`${guild.name}\`.`) - .setColor('ORANGE') - - } - }; - - if (!pile) embeds.push(now); - - functions.pagination(user, channel, embeds, `giveaways`); - } else { - const embed = original; - - req.forEach((warn) => { - embed.addField(`Giveaway`, `Offert par <@${warn.hoster_id}>\n> Récompense: \`${warn.reward}\`\n> Finit: ${moment(parseInt(warn.endsAt)).format('DD/MM/YYYY - hh:mm:ss')}\nDans <#${warn.channel_id}> avec ${warn.winnerCount} gagnan${warn.winnerCount > 1 ? "ts" : "t"}`, false); - }); - - channel.send({ embeds: [ embed ] }); + async end(messageId) { + let gw = this.giveaways.get(messageId); + if (!gw && this.ended.has(messageId)) return 'already ended'; + if (!gw) return 'no giveaway' + + const guild = this.client.guilds.cache.get(gw.guild_id); + if (!guild) return 'no guild'; + + const channel = guild.channels.cache.get(gw.channel_id); + if (!channel) return 'no channel'; + + const message = await channel.messages.fetch(messageId); + if (!message) return 'no message'; + + if (!gw.ended == false) { + gw = this.formatToObject(gw); + }; + + let winners = await this.roll(gw, { guild, channel, message }); + const embed = embeds.ended(gw, winners); + + gw.winners = winners; + message.edit({ embeds: [ embed ], components: [] }).catch((e) => {console.log(e)}); + channel.send({ reply: { messageReference: message }, embeds: [ embeds.winners(winners, this.getUrl(gw)) ] }).catch((e) => {console.log(e)}); + gw.ended = true; + + let sql = this.createQuery(this.formatToSql(gw), true); + this.db.query(sql, (err) => { + if (err) throw err; + }); + + this.giveaways.delete(messageId); + this.ended.set(messageId, gw); + + return winners; + } + checkGw() { + this.giveaways.forEach((gw) => { + if (!this.timeout.has(gw.message_id)) { + setTimeout(() => { + this.end(gw.message_id); + this.timeout.delete(gw.message_id); + }, gw.endsAt - Date.now()); + this.timeout.set(gw.message_id, gw); } }) } - updateAll(guild) { - this.db.query(`SELECT * FROM giveaways WHERE guild_id="${guild.id}" AND ended="0"`, (err, req) => { - if(err) return console.log(err); + addParticipation(userId, data) { + let gw = data; + gw.participants.push(userId); - req.forEach((x) => { - if (parseInt(x.endsAt) <= Date.now()) { - this.end(guild, x); - } else { - this.edit(x, guild); - } - }); + let sql = this.createQuery(this.formatToSql(gw), true); + + this.db.query(sql, (err) => { + if (err) throw err; }); + + this.giveaways.set(gw.message_id, gw); + return gw; } - init() { - this.client.on('interactionCreate', (interaction) => { - if (!interaction.isButton()) return; - - if (!interaction.customId === 'giveaway-participate') return; + removeParticipation(userId, data) { + let gw = data; + let index = gw.participants.indexOf(userId); + gw.participants.splice(index, 1); + + let sql = this.createQuery(this.formatToSql(gw), true); + this.db.query(sql, (err) => { + if (err) throw err; + }); - this.db.query(`SELECT guild_id FROM giveaways WHERE guild_id="${interaction.guild.id}" AND channel_id="${interaction.channel.id}" AND message_id="${interaction.message.id}" AND ended="0"`, (err, req) => { - if (err) return interaction.reply({ embeds: [ embeds.errorSQL(interaction.user) ], ephemeral: true }) & console.log(err); - const data = req[0]; + this.giveaways.set(gw.message_id, gw); + return gw; + } + setOnInteraction() { + this.client.on('interactionCreate', /** @param {ButtonInteraction} interaction */ (interaction) => { + if (interaction.isButton()) { + if (interaction.customId == 'gw-participate') { + let gw = this.giveaways.get(interaction.message.id); + if (!gw) return; - if (!data) return; + if (gw.participants.includes(interaction.user.id)) return interaction.reply({ embeds: [ embeds.alreadyParticipate(this.getUrl(gw)) ], ephemeral: true }).catch(() => {}); - this.db.query(`SELECT user_id FROM gw_participants WHERE message_id="${interaction.message.id}" AND guild_id="${interaction.guild.id}" AND user_id="${interaction.user.id}"`, (error, request) => { - if (error) return interaction.reply({ embeds: [ embeds.errorSQL(interaction.user) ], ephemeral: true }) & console.log(error); + const check = this.checkIfValidEntry(interaction.member, gw); + interaction.reply({ embeds: [ check.embed ], ephemeral: true }).catch(() => {}); - if (request.length === 0) { - this.db.query(`INSERT INTO gw_participants (guild_id, channel_id, message_id, user_id) VALUES ("${interaction.guild.id}", "${interaction.channel.id}", "${interaction.message.id}", "${interaction.user.id}")`); - interaction.reply({ content: `J'ai enregistré votre participation`, ephemeral: true }); - return; - } else { - this.db.query(`DELETE FROM gw_participants WHERE guild_id="${interaction.guild.id}" AND message_id="${interaction.message.id}" AND user_id="${interaction.user.id}"`); + if (check.state == true) { + gw = this.addParticipation(interaction.user.id, gw); - interaction.reply({ content: `J'annule votre participation à ce giveaway`, ephemeral: true }); + let dataset = { + reward: gw.reward, + winnerCount: gw.winnerCount, + participants: JSON.parse(gw.participants), + winners: JSON.parse(gw.winners), + requiredRoles: JSON.parse(gw.required_roles), + deniedRoles: JSON.parse(gw.denied_roles), + bonusRoles: JSON.parse(gw.bonus_roles), + time: parseInt(gw.endsAt) - Date.now(), + hosterId: gw.hoster_id + }; + + interaction.message.edit({ embeds: [ embeds.giveaway(dataset) ] }).catch(() => {}); }; - }); - }); + }; + if (interaction.customId == 'gw-unparticipate') { + let gw = this.giveaways.get(interaction.message.id); + if (!gw) return; + + if (!gw.participants.includes(interaction.user.id)) return interaction.reply({ embeds: [ embeds.notParticipated(this.getUrl(gw)) ], ephemeral: true }).catch(() => {}); + gw = this.removeParticipation(interaction.user.id, gw); + + let dataset = { + reward: gw.reward, + winnerCount: gw.winnerCount, + participants: gw.participants, + winners: gw.winners, + requiredRoles: gw.required_roles, + bonusRoles: gw.bonus_roles, + deniedRoles: gw.denied_roles, + time: Date.now() - parseInt(gw.date), + channel: interaction.channel, + hosterId: gw.hoster_id + }; + + interaction.message.edit({ embeds: [ embeds.giveaway(this.formatToObject(dataset)) ] }).catch(() => {}); + interaction.reply({ embeds: [ embeds.removeParticipation(this.getUrl(gw)) ] }).catch(() => {}); + } + }; + }); + } + /** + * @param {{ guildId: String, messageId: String }} data + * @description Search a specific giveaway in the server + * @returns {{reward: String, hoster_id: String, guild_id: String, channel_id: String, message_id: String, winnerCount: Number, winners: String[], ended: Boolean, participants: String[], required_roles: String[], bonus_roles: String[], denied_roles: String[], endsAt: Number}} + */ + fetch(data) { + let id = data.messageId; + let gId = data.guildId; + if (!id || !gId) return 'invalid data'; + + let gw = this.giveaways.find(x => x.guild_id == gId && x.message_id == id); + if (!gw) gw = this.ended.find(x => x.guild_id == gId && x.message_id == id); + + if (!gw) return 'giveaway not found'; + return gw; + } + /** + * @description Returns the list of all giveaways in the server + * @param {String} guildId + * @returns {{reward: String, hoster_id: String, guild_id: String, channel_id: String, message_id: String, winnerCount: Number, winners: String[], ended: Boolean, participants: String[], required_roles: String[], bonus_roles: String[], denied_roles: String[], endsAt: Number}[]} + */ + list(guildId) { + if (!guildId) return 'invalid data'; + + let giveaways = []; + const notEnded = this.giveaways.filter(x => x.guild_id === guildId).toJSON(); + const ended = this.ended.filter(x => x.guild_id === guildId).toJSON(); + + giveaways = giveaways.concat(notEnded); + giveaways = giveaways.concat(ended); + + return giveaways; + } + delete(guildId, messageId) { + if (!guildId || !messageId) return 'invalid data'; + const giveaway = this.fetch({ guildId, messageId }); + + if (!giveaway) return 'giveaway not found'; + + this.db.query(`DELETE FROM giveaways WHERE message_id="${messageId}"`, (err, req) => { + if (err) throw err; + + this.fillCache(); }); - setInterval(() => { - this.db.query(`SELECT * FROM giveaways WHERE ended="0"`, (err, req) => { - if (err) return console.log(err); + return 'deleted'; + } + resetCache() { + this.giveaways = new Collection(); + this.ended = new Collection(); + } + fillCache() { + this.db.query(`SELECT * FROM giveaways`, (err, req) => { + if (err) throw err; + this.resetCache(); - req.forEach(/**@param {objectGW} gw */(gw) => { - const guild = this.client.guilds.cache.get(gw.guild_id); - if (!guild) return; + for (const RawGw of req) { + let gw = this.formatToObject(RawGw); - this.updateAll(guild); - }); - }); + if (gw.ended == true || gw.date <= Date.now()) { + this.ended.set(gw.message_id, gw); + } else { + this.giveaways.set(gw.message_id, gw); + }; + }; + }) + } + init() { + this.fillCache(); + setInterval(() => { + this.checkGw(); }, 10000); + this.setOnInteraction(); + + console.log(`Giveaways Manager is ready !`); } }; -module.exports = GiveawayManager; \ No newline at end of file +module.exports = GiveawaysManager; \ No newline at end of file diff --git a/assets/managers/ticketsManager.js b/assets/managers/ticketsManager.js index 5445df1..e198b46 100644 --- a/assets/managers/ticketsManager.js +++ b/assets/managers/ticketsManager.js @@ -25,6 +25,7 @@ class TicketsManager { this.client = client; this.db = db; this.tickets = new Discord.Collection(); + this.configs = new Discord.Collection(); this.meanGuillement = "alt3"; } isTicket(id) { @@ -77,6 +78,9 @@ class TicketsManager { */ createTicket(data) { if (!this.validString(data.sujet)) return 'not a valid text'; + let { roles } = this.configs.get(data.guild.id); + if (!roles) roles = []; + const embed = new Discord.MessageEmbed() .setTitle("Ticket") .setDescription(`Ticket ouvert par <@${data.user.id}>.\n__Sujet :__ ${data.sujet}`) @@ -96,7 +100,14 @@ class TicketsManager { .setLabel('mentionner everyone') ) - data.guild.channels.create(`Ticket-${functions.random(9, 0)}${functions.random(9, 0)}${functions.random(9, 0)}${functions.random(9, 0)}`, {permissionOverwrites: [{id: data.user.id, allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'ADD_REACTIONS', 'ATTACH_FILES'], deny: ['MENTION_EVERYONE', 'MUTE_MEMBERS']}, { id: data.guild.id, deny: ['VIEW_CHANNEL'] }]}).then((channel) => { + const permissions = [{id: data.user.id, allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'ADD_REACTIONS', 'ATTACH_FILES'], deny: ['MENTION_EVERYONE', 'MUTE_MEMBERS']}, { id: data.guild.id, deny: ['VIEW_CHANNEL'] }]; + if (roles.length > 0) { + for (const rId of roles) { + permissions.push({ id: rId, allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'ADD_REACTIONS', 'ATTACH_FILES'] }); + }; + }; + + data.guild.channels.create(`Ticket-${functions.random(9, 0)}${functions.random(9, 0)}${functions.random(9, 0)}${functions.random(9, 0)}`, {permissionOverwrites: permissions}).then((channel) => { channel.send({ embeds: [ embed ], components: [ row ], content: `<@${data.user.id}>, votre ticket a été crée.` }).then((sent) => { const dataset = { guild_id: data.guild.id, @@ -116,7 +127,7 @@ class TicketsManager { if (err) throw err; }); }); - }); + }).catch(() => {}); } /** * @returns {String} @@ -241,22 +252,48 @@ class TicketsManager { } resetCache() { this.tickets = new Discord.Collection(); + this.configs = new Discord.Collection(); } loadCache() { this.db.query(`SELECT * FROM tickets`, (err, req) => { if (err) throw err; - this.resetCache(); + + this.db.query(`SELECT ticket_enable, ticket_roles, guild_id FROM configs`, (er, re) => { + if (er) throw er; + + this.resetCache(); + re.forEach((conf) => { + this.configs.set(conf.guild_id, { + enable: conf.ticket_enable == "1", + roles: JSON.parse(conf.ticket_roles).map(x => x.toString()) + }); + }); + req.forEach((ticket) => { + this.tickets.set(ticket.message_id, ticket); + }); - req.forEach((ticket) => { - this.tickets.set(ticket.message_id, ticket); - }); + }) }) } + checkForActivation(interaction) { + const activated = this.configs.get(interaction.guild.id).enable; + if (activated == false) { + interaction.reply({ embeds: [ pack.embeds.classic(interaction.user) + .setTitle("Système désactivé") + .setDescription(`Le système de tickets est **désactivé**.\n\nVeuillez l'activer pour utiliser les commandes de ticket.\n:bulb:\n> Utilisez la commande \`/config configurer\``) + .setColor('#ff0000') + ], ephemeral: true }).catch(() => {}); + return false; + }; + return true; + } loadInteraction() { this.client.on('interactionCreate', /** @param {Discord.ButtonInteraction} interaction */ async(interaction) => { if (interaction.isButton()) { const id = interaction.customId; if (id == 'ticket_panel') { + if (!this.checkForActivation(interaction)) return; + let { subject } = this.tickets.get(interaction.message.id); await interaction.deferUpdate(); @@ -265,6 +302,7 @@ class TicketsManager { this.createTicket(dataset); }; if (id == 'mention-everyone') { + if (!this.checkForActivation(interaction)) return; await interaction.reply({ embeds: [ pack.embeds.classic(interaction.user) .setTitle("Mention everyone") .setDescription(`Êtes-vous sûr de vouloir mentionner everyone ?`) @@ -296,11 +334,13 @@ class TicketsManager { }); }; if (id == 'ticket-close') { + if (!this.checkForActivation(interaction)) return; await interaction.deferUpdate(); this.closeTicket({ channel: interaction.channel }); }; if (id == 'ticket-save') { + if (!this.checkForActivation(interaction)) return; const customId = await this.saveTicket({ channel: interaction.channel }); interaction.deferReply(); @@ -319,11 +359,13 @@ class TicketsManager { }, 3000) }; if (id == 'ticket-reopen') { + if (!this.checkForActivation(interaction)) return; await interaction.deferUpdate(); this.reopenTicket({ channel: interaction.channel }); }; if (id == 'ticket-delete') { + if (!this.checkForActivation(interaction)) return; await interaction.deferUpdate(); this.delete({ channel: interaction.channel }); diff --git a/commands/.devs/exportdb.js b/commands/.devs/exportdb.js index e90ba3a..7c4ed79 100644 --- a/commands/.devs/exportdb.js +++ b/commands/.devs/exportdb.js @@ -42,12 +42,9 @@ module.exports = { return; }; let structure = `CREATE TABLE ${table} ( -${tableData.map((x) => ` ${x.Field} ${x.Type.toUpperCase()} ${x.Null == 'NO' ? 'NOT NULL':''} ${x.Default == null ? '': `DEFAULT ${x.Default == "current_timestamp()" ? "CURRENT_TIMESTAMP" : `"${x.Default.startsWith("'") ? x.Default.substring(1, x.Default.length - 1) : x.Default}"`}`}${x.Extra.includes('auto_increment') ? " AUTO_INCREMENT":''}`).join(',\n')} +${tableData.map((x) => ` ${x.Field} ${x.Type.toUpperCase()} ${x.Null == 'NO' ? 'NOT NULL':''} ${x.Default == null ? '': `DEFAULT ${x.Default == "current_timestamp()" ? "CURRENT_TIMESTAMP" : `"${x.Default.startsWith("'") ? x.Default.substring(1, x.Default.length - 1) : x.Default}"`}`}${x.Extra.includes('auto_increment') ? " AUTO_INCREMENT":''} ${x.Key == 'PRI' ? 'PRIMARY KEY' :''}`).join(',\n')} );`; - let primaryKey = tableData.find(x => x.Key && x.Key == 'PRI'); - if (primaryKey) structure+=`\n\nALTER TABLE ${table} ADD PRIMARY KEY ( ${primaryKey.Field} );`; - sql+=structure; sql+="\n\n"; diff --git a/events/guildCreate.js b/events/guildCreate.js index 2783191..c82dcbb 100644 --- a/events/guildCreate.js +++ b/events/guildCreate.js @@ -17,6 +17,16 @@ module.exports = { if (!web) return; web.send({ content: `J'ai été ajouté sur ${guild.name} ( ${guild.memberCount.toLocaleString('fr')} membres ) ! Je suis maintenant sur \`${guild.client.guilds.cache.size}\` serveurs` }).catch(() => {}); - }) + }); + + guild.client.db.query(`SELECT guild_id FROM configs WHERE guild_id="${guild.id}"`, (e, r) => { + if (e) functions.sendError(e, 'guild create event query fetch', guild.client.user); + + if (r.length == 0) { + guild.client.db.query(`INSERT INTO configs (guild_id) VALUES ("${guild.id}")`, (er) => { + if (er) functions.sendError(err, 'query insert at guildCreate', guild.client.user); + }); + }; + }); } } \ No newline at end of file diff --git a/events/guildMemberAdd.js b/events/guildMemberAdd.js index 86b2fb6..04bb3c5 100644 --- a/events/guildMemberAdd.js +++ b/events/guildMemberAdd.js @@ -27,12 +27,27 @@ module.exports = { }; } - client.db.query(`SELECT join_enable, join_channel, join_message, gban_enable FROM configs WHERE guild_id="${guild.id}"`, (err, req) => { + const addRoles = () => { + client.db.query(`SELECT role_id FROM roles_start WHERE guild_id="${guild.id}"`, (err, req) => { + if (err) { + functions.sendError(err, 'query fetch at roles start', member.user); + return; + }; + (async() => {await guild.roles.fetch();})(); + const roles = guild.roles.cache.filter(x => x.id !== guild.id && req.some(x => x.role_id==x.id)); + if (roles.size == 0) return; + + member.roles.add(roles).catch(() => {}); + }); + }; + client.db.query(`SELECT join_enable, join_channel, join_message, gban_enable, roles_enable FROM configs WHERE guild_id="${guild.id}"`, (err, req) => { if (err) return console.log(err); const data = req[0]; if (!data) return check(true); + if (data.roles_enable == "1") addRoles(); + if (data.join_enable == "0") return; check(data.gban_enable == '1'); diff --git a/events/messageCreateMention.js b/events/messageCreateMention.js new file mode 100644 index 0000000..356050d --- /dev/null +++ b/events/messageCreateMention.js @@ -0,0 +1,50 @@ +const functions = require('../assets/functions'); +const package = functions.package(); + +module.exports = { + event: 'messageCreate', + execute: (message) => { + if (message.mentions.users.has(message.client.user.id) && !message.mentions.everyone) { + let splashes = require('../assets/data/splash.json').filter(x => !x.includes('weird')); + + if (!functions.random(200, 0) === 132) { + const index = splashes.indexOf(x => x === 'This is an easter egg !'); + splashes.splice(index, 1); + }; + let size = require('../assets/data/splash.json').length; + + let splash = splashes[functions.random(splashes.length, 0)].replace('{username}', message.author.username); + splash.replace('{size}', size); + + const reponse = package.embeds.classic(message.author) + .setTitle(splash) + .setDescription(`Bonjour ! Je suis fait en slash commandes, alors mon préfixe est (\`/\`) comme beaucoup d'autres bots !\n\nFaites \`/help\` pour obtenir de l'aide.\n\n:bulb: <@${message.client.user.id}> est désormais disponible en slash commands !\n> Si vous ne voyez pas mes slash commands, réinvitez moi par le lien de la commande \`/invite\`.`) + .setColor(message.guild.me.displayHexColor) + .setAuthor({ name: message.guild ? message.guild.me.nickname ? message.guild.me.nickname :'Oracle' : "Oracle", iconURL: message.author.displayAvatarURL({ dynamic: true }) }) + + if (splash === "Click on the link") { + reponse.setURL('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + }; + + functions.reply(message, reponse); + + if (message.guild) { + if (functions.random(10000, 0) === 794) { + message.guild.me.setNickname(`Oralce`); + }; + if ((message.guild.me.nickname === 'Dinnerbone' || message.guild.me.nickname === 'Grumm') && functions.random(10, 0) === 5) { + const reverse = (text) => { + let t =""; + for (let i =0;i { - if (!reaction.message || !reaction.message.guild || user.bot) return; - - const client = reaction.client; - - const message = reaction.message; - const channel = message.channel; - const guild = message.guild; - - client.db.query(`SELECT * FROM rolesreact WHERE guild_id="${guild.id}" AND channel_id="${channel.id}" AND message_id="${message.id}" AND emoji="${reaction.emoji.identifier}"`, (err, req) => { - if (err) return console.log(err); - if (req.length === 0) return; - - const data = req[0]; - const role = guild.roles.cache.get(data.role_id); - if (!role) return; - - const member = guild.members.cache.get(user.id); - member.roles.add([ role ]).catch(() => console.log); - }); - } -}; \ No newline at end of file diff --git a/events/messageReactionRemove.js b/events/messageReactionRemove.js deleted file mode 100644 index efa2c9f..0000000 --- a/events/messageReactionRemove.js +++ /dev/null @@ -1,32 +0,0 @@ -const Discord = require('discord.js'); -const functions = require('../assets/functions.js'); -const package = functions.package(); - -module.exports = { - event: 'messageReactionRemove', - /** - * @param {Discord.MessageReaction} reaction - * @param {Discord.User} user - */ - execute: (reaction, user) => { - if (!reaction.message || !reaction.message.guild || user.bot) return; - - const client = reaction.client; - - const message = reaction.message; - const channel = message.channel; - const guild = message.guild; - - client.db.query(`SELECT * FROM rolesreact WHERE guild_id="${guild.id}" AND channel_id="${channel.id}" AND message_id="${message.id}" AND emoji="${reaction.emoji.identifier}"`, (err, req) => { - if (err) return console.log(err); - if (req.length === 0) return; - - const data = req[0]; - const role = guild.roles.cache.get(data.role_id); - if (!role) return; - - const member = guild.members.cache.get(user.id); - member.roles.remove([ role ]).catch(() => console.log); - }); - } -}; \ No newline at end of file diff --git a/events/messageUpdate.js b/events/messageUpdate.js index b46cdd7..c679702 100644 --- a/events/messageUpdate.js +++ b/events/messageUpdate.js @@ -24,7 +24,7 @@ module.exports = { }, { name: "Après", - value: b.content || '\u200b', + value: a.content || '\u200b', inline: false } ) diff --git a/events/ready.js b/events/ready.js index e1fa522..e036679 100644 --- a/events/ready.js +++ b/events/ready.js @@ -35,19 +35,19 @@ module.exports = { }) }; const loadSpecificsCooldowns = () => { - client.db.query(`SELECT * FROM cooldowns WHERE date >= "${Date.now()}"`, (err, req) => { + client.db.query(`SELECT * FROM cooldowns WHERE date > "${Date.now()}"`, (err, req) => { if (err) throw err; for (const cd of req) { const dataset = cd; - dataset.command = `/${dataset.command}`; + dataset.command = `${dataset.command}`; cooldowns.set(`${dataset.user_id}.${dataset.command}`, dataset); } }) }; const managerBuilder = () => { - fs.readdirSync('./assets/managers').forEach((managerFileName) => { + fs.readdirSync('./assets/managers').filter(x => x.endsWith('.js')).forEach((managerFileName) => { const file = require(`../assets/managers/${managerFileName}`); const managerName = capitalize(managerFileName.split('.')[0]); @@ -106,9 +106,9 @@ module.exports = { let statusIndex = 0; let status = [ {name: 'la version ' + require('../assets/data/data.json').version, type: 'WATCHING'}, - {name: `%users% utilisateurs`, type: 'WATCHING'}, + {name: `%users% utilisateurs`, type: 'LISTENING'}, {name: `%servers% serveurs`, type: 'WATCHING'}, - {name: `Le préfixe ${default_prefix}`, type: 'WATCHING'} + {name: "Passage en slash commandes !", type: 'WATCHING'} ]; setInterval(() => { diff --git a/slash-commands/economy/daily.js b/slash-commands/economy/daily.js index 9944d0b..49bbed7 100644 --- a/slash-commands/economy/daily.js +++ b/slash-commands/economy/daily.js @@ -23,9 +23,9 @@ module.exports = { interaction.reply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Récompense quotidienne") - .setDescription(`Vous récupérez **${reward}** ${package.configs.coins} grâce à votre récompense quotidienne`) + .setDescription(`Vous récupérez **${reward.toLocaleString('fr-DE')}** ${package.configs.coins} grâce à votre récompense quotidienne`) .setColor(interaction.guild.me.displayHexColor) - ] }).catch(() => {}); + ] }).catch((e) => console.log(e)); interaction.client.CoinsManager.addCoins({ user_id: interaction.user.id, guild_id: interaction.guild.id }, reward); } diff --git a/slash-commands/economy/loto.js b/slash-commands/economy/loto.js index b06742a..98e31bf 100644 --- a/slash-commands/economy/loto.js +++ b/slash-commands/economy/loto.js @@ -1,6 +1,7 @@ const Discord = require('discord.js'); const functions = require('../../assets/functions'); const package = functions.package(); +const ms = require('ms'); module.exports = { help: { @@ -82,6 +83,81 @@ module.exports = { * @param {Discord.CommandInteraction} interaction */ run: (interaction) => { - + const subcommand = interaction.options.getSubcommand(); + + if (subcommand == 'démarrer') { + if (!interaction.member.permissions.has('MANAGE_GUILD')) return interaction.reply({ embeds: [ package.embeds.missingPermission(interaction.user, "gérer le serveur") ] }).catch(() => {}); + const reward = parseInt(interaction.options.get('récompense').value); + const numbers = parseInt(interaction.options.get('gagnants').value); + const complementaries = parseInt(interaction.options.get('complémentaires').value); + const time = ms(interaction.options.get('temps').value); + + if (!time) return interaction.reply({ embeds: [ package.embeds.invalidTime(interaction.user) ] }).catch(() => {}); + if (isNaN(reward) || isNaN(numbers) || isNaN(complementaries)) return interaction.reply({ embeds: [ package.embeds.invalidNumber(interaction.user) ] }).catch(() => {}); + + if (reward < 1 || numbers < 5 || complementaries < 2) return interaction.reply({ embeds: [ package.embeds.invalidNumber(interaction.user) ] }).catch(() => {}); + const result = interaction.client.LotoManager.start({ + numbers, + complementaries, + reward, + time, + guildId: interaction.guild.id + }); + + interaction.reply({ embeds: [ package.embeds.loto.started(interaction.user, numbers, complementaries, reward, time) ] }).catch(() => {}); + }; + if (subcommand == 'tirage') { + if (!interaction.member.permissions.has('MANAGE_GUILD')) return interaction.reply({ embeds: [ package.embeds.missingPermission(interaction.user, "gérer le serveur") ] }).catch(() => {}); + + const result = interaction.client.LotoManager.end(interaction.guild.id); + let embed; + switch(result) { + case 'invalid loto': + embed = package.embeds.loto.invalidLoto(interaction.user, 'end'); + break; + default: + let x = result; + x.user = interaction.user; + embed = package.embeds.loto.end(x); + break; + }; + + if (typeof result == 'object' && result.length > 0) { + result.forEach((winner) => { + interaction.client.CoinsManager.addCoins({ user_id: winner.user_id, guild_id: interaction.guild.id }, winner.reward.toFixed(0)); + }); + }; + interaction.reply({ embeds: [ embed ] }).catch(() => {}); + }; + if (subcommand == 'participer') { + const numbers = interaction.options.getString('gagnants').split(' ').map(x => parseInt(x)); + const complementaries = interaction.options.getString('complémentaires').split(' ').map(x => parseInt(x)); + + const result = interaction.client.LotoManager.addParticipation({ + guildId: interaction.guild.id, + userId: interaction.user.id, + numbers, complementaries + }); + + let embed = package.embeds.loto; + switch(result) { + case 'invalid loto': + embed = embed.invalidLoto(interaction.user, 'participate'); + break; + case 'invalid numbers': + case 'invalid arrays': + case 'invalid compared': + embed = embed.invalidNumbers(interaction.user); + break; + case 'user already exists': + embed = embed.alreadyParticipate(interaction.user); + break; + case 'added': + embed = embed.added(interaction.user, numbers, complementaries); + break; + }; + + interaction.reply({ embeds: [ embed ] }).catch(() => {}); + } } }; \ No newline at end of file diff --git a/slash-commands/economy/weekly.js b/slash-commands/economy/weekly.js index 409223d..a8e1b89 100644 --- a/slash-commands/economy/weekly.js +++ b/slash-commands/economy/weekly.js @@ -23,7 +23,7 @@ module.exports = { interaction.reply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Récompense quotidienne") - .setDescription(`Vous récupérez **${reward}** ${package.configs.coins} grâce à votre récompense quotidienne`) + .setDescription(`Vous récupérez **${reward.toLocaleString('fr-DE')}** ${package.configs.coins} grâce à votre récompense hebdomadaire.`) .setColor(interaction.guild.me.displayHexColor) ] }).catch(() => {}); diff --git a/slash-commands/fun/game.js b/slash-commands/fun/game.js index 94b8ee8..8bc59cd 100644 --- a/slash-commands/fun/game.js +++ b/slash-commands/fun/game.js @@ -385,7 +385,7 @@ module.exports = { const embed = package.embeds.classic(interaction.user) .setTitle("Dés") - .setDescription(`Les dés on été lancés :\n\n\`${results.map(x => `${x}`).join(' + ')}\`\n> = ${results.reduce((a, b) => a + b)}`) + .setDescription(`Les dés ont été lancés :\n\n\`${results.map(x => `${x}`).join(' + ')}\`\n> = ${results.reduce((a, b) => a + b)}`) .setColor('ORANGE') interaction.reply({ embeds: [ embed ] }).catch(() => {}); diff --git a/slash-commands/moderation/autorole.js b/slash-commands/moderation/autorole.js new file mode 100644 index 0000000..1519834 --- /dev/null +++ b/slash-commands/moderation/autorole.js @@ -0,0 +1,136 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + systems: [{name: "de rôles d'arrivée", value: "roles_enable", state: true}], + permissions: ['manage_guild', 'manage_roles'], + dev: false, + dm: false + }, + configs: { + name: "autorole", + description: "Gère les rôles donnés automatiquement à l'arrivée sur le serveur", + options: [ + { + name: "ajouter", + description: "Ajoute un rôle automatiquement donné", + type: 'SUB_COMMAND', + options: [ + { + name: "rôle", + description: "Rôle à ajouter", + type: 'ROLE', + required: true + } + ] + }, + { + name: "retirer", + description: "Retirer un rôle automatiquement donné", + type: 'SUB_COMMAND', + options: [ + { + name: "rôle", + description: "Rôle à retirer", + type: 'ROLE', + required: true + } + ] + }, + { + name: "liste", + description: "Affiche la liste des rôles automatiques", + type: "SUB_COMMAND" + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + const subcommand = interaction.options.getSubcommand(); + + await interaction.reply({ embeds: [ package.embeds.waitForDb(interaction.user) ] }).catch(() => {}); + interaction.client.db.query(`SELECT role_id FROM roles_start WHERE guild_id="${interaction.guild.id}"`, (err, req) => { + if (err) { + functions.sendError(err, 'query fetch at /autorole', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + return; + }; + + if (subcommand == 'liste') { + if (req.length == 0) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Aucun rôle automatique") + .setDescription(`Aucun rôle automatique n'a été configuré`) + .setColor('#ff0000') + ] }).catch(() => {}); + + const embed = package.embeds.classic(interaction.user) + .setTitle("Rôles automatiques") + .setDescription(`Le${req.length > 1 ? 's rôles configurés' : ' rôle configuré'} sur ${interaction.guild.name} ${req.length > 1 ? 'sont':'est'} :\n${req.map(r => `<@&${r.role_id}>`).join(' ')}`) + .setColor(interaction.member.displayHexColor) + + interaction.editReply({ embeds: [ embed ] }).catch(() => {}); + }; + if (subcommand == 'ajouter') { + let role = interaction.options.getRole('rôle'); + if (role.position >= interaction.member.roles.highest.position) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("🚫 Rôle trop haut") + .setDescription(`Ce rôle est **supérieur** ou **égal** à vous dans la hiérarchie des rôles`) + .setColor(role.hexColor) + ] }).catch(() => {}); + + if (req.find(x => x.role_id == role.id)) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle déjà configuré") + .setDescription(`Le rôle <@&${role.id}> est déjà configuré sur ${interaction.guild.name}`) + .setColor(role.hexColor) + ] }).catch(() => {}); + + interaction.client.db.query(`INSERT INTO roles_start (guild_id, role_id) VALUES ("${interaction.guild.id}", '${role.id}')`, (er) => { + if (er) { + functions.sendError(er, 'query add at /autorole ajouter', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + return; + }; + + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle configuré") + .setDescription(`Le rôle <@&${role.id}> est maintenant un rôle donné automatiquement aux nouveaux membres`) + .setColor(role.hexColor) + ] }).catch(() => {}); + }); + }; + if (subcommand == 'retirer') { + let role = interaction.options.getRole('rôle'); + if (role.position >= interaction.member.roles.highest.position) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("🚫 Rôle trop haut") + .setDescription(`Ce rôle est **supérieur** ou **égal** à vous dans la hiérarchie des rôles`) + .setColor(role.hexColor) + ] }).catch(() => {}); + + if (!req.find(x => x.role_id == role.id)) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle non configuré") + .setDescription(`Le rôle <@&${role.id}> n'est pas configuré sur ${interaction.guild.name}`) + .setColor(role.hexColor) + ] }).catch(() => {}); + + interaction.client.db.query(`DELETE FROM roles_start WHERE guild_id="${interaction.guild.id}" AND role_id="${role.id}"`, (er) => { + if (er) { + functions.sendError(er, 'query remove at /autorole retirer', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + return; + }; + + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle configuré") + .setDescription(`Le rôle <@&${role.id}> n'est maintenant plus un rôle donné automatiquement aux nouveaux membres`) + .setColor(role.hexColor) + ] }).catch(() => {}); + }); + }; + }); + } +}; \ No newline at end of file diff --git a/slash-commands/moderation/ticket.js b/slash-commands/moderation/ticket.js index 644ffe9..b1034ed 100644 --- a/slash-commands/moderation/ticket.js +++ b/slash-commands/moderation/ticket.js @@ -116,6 +116,44 @@ module.exports = { name: 'reopen', description: "Réouvre le ticket", type: 'SUB_COMMAND' + }, + { + name: 'modrole', + description: "Gère les rôles de modérateurs de tickets", + type: 'SUB_COMMAND_GROUP', + options: [ + { + name: 'ajouter', + type: 'SUB_COMMAND', + description: "Ajoute un rôle de modérateur de tickets", + options: [ + { + name: "rôle", + type: 'ROLE', + description: "Rôle à ajouter", + required: true + } + ] + }, + { + name: 'retirer', + type: 'SUB_COMMAND', + description: "Retirer un rôle de modérateur de tickets", + options: [ + { + name: "rôle", + type: 'ROLE', + description: "Rôle à retirer", + required: true + } + ] + }, + { + name: "liste", + description: "Affiche la liste des rôles de modérateurs de tickets", + type: 'SUB_COMMAND' + } + ] } ] }, @@ -123,7 +161,7 @@ module.exports = { dm: false, dev: false, permissions: [], - systems: [], + systems: [{name: "de tickets", value: "ticket_enable", state: true}], cd: 5 }, /** @@ -148,6 +186,96 @@ module.exports = { return true; }; + if (['ajouter', 'liste', 'retirer'].includes(subcommand)) { + await interaction.reply({ embeds: [ package.embeds.waitForDb(interaction.user) ] }).catch(() => {}); + interaction.client.db.query(`SELECT ticket_roles FROM configs WHERE guild_id="${interaction.guild.id}"`, (err, req) => { + if (err) { + functions.sendError(err, 'query fetch at /ticket modrole', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + return; + }; + if (req.length > 0) req[0].ticket_roles = JSON.parse(req[0].ticket_roles); + // console.log(req[0]); + + if (subcommand == 'liste') { + if (req[0].ticket_roles.length == 0) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Aucun rôle automatique") + .setDescription(`Aucun rôle de modérateur de tickets n'a été configuré`) + .setColor('#ff0000') + ] }).catch(() => {}); + + const embed = package.embeds.classic(interaction.user) + .setTitle("Rôles de modérateurs de tickets") + .setDescription(`Les rôles configurés sur ${interaction.guild.name} en tant que modérateurs de tickets ${req[0].ticket_roles.length > 1 ? 'sont':'est'} :\n${req[0].ticket_roles.map(r => `<@&${r}>`).join(' ')}`) + .setColor(interaction.member.displayHexColor) + + interaction.editReply({ embeds: [ embed ] }).catch(() => {}); + }; + if (subcommand == 'ajouter') { + let role = interaction.options.getRole('rôle'); + if (role.position >= interaction.member.roles.highest.position) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("🚫 Rôle trop haut") + .setDescription(`Ce rôle est **supérieur** ou **égal** à vous dans la hiérarchie des rôles`) + .setColor(role.hexColor) + ] }).catch(() => {}); + + if (req[0].ticket_roles.includes(role.id)) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle déjà configuré") + .setDescription(`Le rôle <@&${role.id}> est déjà configuré sur ${interaction.guild.name}`) + .setColor(role.hexColor) + ] }).catch(() => {}); + + req[0].ticket_roles.push(role.id) + + interaction.client.db.query(`UPDATE configs SET ticket_roles='${JSON.stringify(req[0].ticket_roles)}' WHERE guild_id="${interaction.guild.id}"`, (er) => { + if (er) { + functions.sendError(er, 'query add at /autorole ajouter', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + return; + }; + + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle configuré") + .setDescription(`Le rôle <@&${role.id}> est maintenant un rôle de modérateurs de tickets`) + .setColor(role.hexColor) + ] }).catch(() => {}); + interaction.client.TicketsManager.loadCache(); + }); + }; + if (subcommand == 'retirer') { + let role = interaction.options.getRole('rôle'); + if (role.position >= interaction.member.roles.highest.position) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("🚫 Rôle trop haut") + .setDescription(`Ce rôle est **supérieur** ou **égal** à vous dans la hiérarchie des rôles`) + .setColor(role.hexColor) + ] }).catch(() => {}); + + if (!req[0].ticket_roles.includes(role.id)) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle non configuré") + .setDescription(`Le rôle <@&${role.id}> n'est pas configuré sur ${interaction.guild.name}`) + .setColor(role.hexColor) + ] }).catch(() => {}); + + let index = req[0].ticket_roles.indexOf(role.id); + req[0].ticket_roles.splice(index, 1); + + interaction.client.db.query(`UPDATE configs SET ticket_roles='${JSON.stringify(req[0].ticket_roles)}' WHERE guild_id="${interaction.guild.id}"`, (er) => { + if (er) { + functions.sendError(er, 'query remove at /ticket modrole retirer', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + return; + }; + + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle configuré") + .setDescription(`Le rôle <@&${role.id}> n'est maintenant plus un rôle de modérateur de tickets`) + .setColor(role.hexColor) + ] }).catch(() => {}); + interaction.client.TicketsManager.loadCache(); + }); + }; + }); + } if (subcommand == 'ticket') { let sujet = interaction.options.getString('sujet'); tickets.createTicket({ guild: interaction.guild, user: interaction.user, sujet }); diff --git a/slash-commands/usefull/channel.js b/slash-commands/usefull/channel.js index 4a94a43..01f241b 100644 --- a/slash-commands/usefull/channel.js +++ b/slash-commands/usefull/channel.js @@ -118,6 +118,25 @@ module.exports = { type: 'CHANNEL' } ] + }, + { + name: "décrire", + type: 'SUB_COMMAND', + description: "Configure la description d'un salon", + options: [ + { + name: "salon", + description: "Salon à décrire", + type: 'CHANNEL', + required: false + }, + { + name: "description", + type: 'STRING', + required: false, + description: "Description à donner au salon (laisser vide pour réinitialiser)" + } + ] } ] }, @@ -133,6 +152,24 @@ module.exports = { */ run: (interaction) => { const subcommand = interaction.options.getSubcommand(); + + if (subcommand == "décrirer") { + let channel = interaction.options.getChannel('salon') ?? interaction.channel; + let description = interaction.options.getString('description'); + + if (channel.type !== 'GUILD_TEXT') return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Salon invalide") + .setDescription(`Je ne peux modifier la description que d'un **salon textuel**${functions.random(10 == 2) ? ` (et aux dernières nouvelles, ${channel.name} n'en est pas un)`:''}`) + .setColor('#ff0000') + ] }).catch(() => {}); + + channel.setTopic(description ?? null).catch(() => {}); + interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Description mise à jour") + .setDescription(`La description de <#${channel.id}> a été ${description ? `mise sur \`\`\`${description}\`\`\``:'réinitialisée'}`) + .setColor(interaction.guild.me.displayHexColor) + ] }).catch(() => {}); + } if (subcommand == 'créer') { let name = interaction.options.getString('nom'); let type = interaction.options.getString('type'); diff --git a/slash-commands/usefull/contact.js b/slash-commands/usefull/contact.js index 4f62a9a..cc836b5 100644 --- a/slash-commands/usefull/contact.js +++ b/slash-commands/usefull/contact.js @@ -33,7 +33,7 @@ module.exports = { .setDescription(`${interaction.user.username} ( ${interaction.user.id} ) a trouvé un bug sur Oracle :\n\`\`\`${bug}\`\`\``) .setColor('ORANGE') - interaction.client.channels.cache.get('954998495977291807').send({ embeds: [ embed ] }); - interaction.reply({ content: `J'ai signalé ce bug à mes développeurs.` }); + interaction.client.channels.cache.get('954998495977291807').send({ embeds: [ embed ] }).catch(() => {}); + interaction.reply({ content: `J'ai signalé ce bug à mes développeurs.` }).catch(() => {}); } } \ No newline at end of file diff --git a/slash-commands/usefull/feedback.js b/slash-commands/usefull/feedback.js new file mode 100644 index 0000000..12f9c2c --- /dev/null +++ b/slash-commands/usefull/feedback.js @@ -0,0 +1,39 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + configs: { + name: 'avis', + description: "Envoie votre avis sur le bot", + options: [ + { + name: 'avis', + description: "Votre avis", + type: 'STRING', + required: true, + autocomplete: false + } + ] + }, + help: { + dm: true, + dev: false, + permissions: [], + systems: [], + cd: 5 + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: (interaction) => { + const avis = interaction.options.get('avis').value; + const embed = package.embeds.classic(interaction.user) + .setTitle("Avis") + .setDescription(`${interaction.user.username} ( ${interaction.user.id} ) vient de donner son avis sur Oracle :\n\`\`\`${avis}\`\`\``) + .setColor('ORANGE') + + interaction.client.channels.cache.get('946079273335279676').send({ embeds: [ embed ] }).catch(() => {}); + interaction.reply({ content: `Vous avez donné votre avis sur Oracle`, ephemeral: true }).catch(() => {}); + } +} \ No newline at end of file diff --git a/slash-commands/usefull/giveaway.js b/slash-commands/usefull/giveaway.js index b71ba79..2bdbbcd 100644 --- a/slash-commands/usefull/giveaway.js +++ b/slash-commands/usefull/giveaway.js @@ -9,11 +9,6 @@ module.exports = { name: 'giveaway', description: "Giveaways", options: [ - { - name: 'liste', - description: "Affiche la liste des giveaways", - type: 'SUB_COMMAND' - }, { name: 'create', description: "Crée un giveaway", @@ -46,7 +41,25 @@ module.exports = { required: false, autocomplete: false, description: "Le salon dans lequel aura lieu le giveaway" - } + }, + { + name: "bonus", + type: 'STRING', + required: false, + description: "Identifiants des rôles bonus (séparés par un espace)" + }, + { + name: "requis", + type: 'STRING', + required: false, + description: "Identifiants des rôles requis (séparés par un espace)" + }, + { + name: "interdits", + type: 'STRING', + required: false, + description: "Identifiants des rôles interdits (séparés par un espace)" + }, ] }, { @@ -93,50 +106,51 @@ module.exports = { const client = interaction.client; const subCommand = interaction.options.getSubcommand(); - if (subCommand === 'liste') { - client.GiveawayManager.list(interaction.channel, interaction.user); - interaction.reply({ content: "Voici la liste", ephemeral: true }); - } else if (subCommand === 'create') { + if (subCommand === 'create') { const channel = interaction.options.get('salon') ? interaction.options.get('salon').channel : interaction.channel; const ms = require('ms'); if (!ms(interaction.options.get('temps').value)) return interaction.reply({ embeds: [ package.embeds.invalidTime(interaction.user) ], ephemeral: true }); - client.GiveawayManager.start(interaction.guild, channel, interaction.user, interaction.options.get('récompense').value, interaction.options.get('gagnants').value, ms(interaction.options.get('temps').value)); + let bonus = interaction.options.getString('bonus'); + let required = interaction.options.getString('requis'); + let denied = interaction.options.getString('interdits'); + + if (bonus) bonus = bonus.split(' '); + if (required) required = required.split(' '); + if (denied) denied = denied.split(' '); + if (!bonus) bonus = []; + if (!required) required = []; + if (!denied) denied = []; + + client.GiveawayManager.start({ + reward: interaction.options.getString('récompense'), + winnerCount: interaction.options.get('gagnants').value, + hosterId: interaction.user.id, + channel: interaction.channel, + time: ms(interaction.options.get('temps').value), + bonusRoles: bonus, + requiredRoles: required, + deniedRoles: denied + }); interaction.reply({ content: `Je lance un giveaway sur <#${channel.id}>`, ephemeral: true }); } else if (subCommand === 'end') { let id = interaction.options.get('id').value; - client.db.query(`SELECT * FROM giveaways WHERE channel_id="${interaction.channel.id}" AND guild_id="${interaction.guild.id}" AND ended="0"`, (err, req) => { - if (err) return interaction.reply({ embeds: [ package.embeds.errorSQL(interaction.user) ], ephemeral: true }); - - let gw = req.find(x => x.message_id === id); - if (!gw) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) - .setTitle("Pas de giveaway") - .setColor('#ff0000') - .setDescription(`Je ne trouve pas de giveway avec l'id \`${id}\` qui n'est pas terminé dans <#${interaction.channel.id}>`) - ], ephemeral: true }); - - client.GiveawayManager.end(interaction.guild, gw); - interaction.reply({ content: "Je met fin à ce giveaway", ephemeral: true }); - }); + const result = interaction.client.GiveawayManager.end(id); + if (result == 'already ended') return interaction.reply({ embeds: [ package.embeds.giveaway.alreadyEnded(interaction.user) ] }).catch(() => {}); + if (['no giveaway', 'no guild', 'no channel', 'no message'].includes(result)) return interaction.reply({ embeds: [ package.embeds.giveaway.noGw(interaction.user, id) ] }).catch(() => {}); + + interaction.reply({ content: "Giveaway terminé", ephemeral: true }).catch(() => {}); } else if (subCommand === 'reroll') { let id = interaction.options.get('id').value; - client.db.query(`SELECT * FROM giveaways WHERE channel_id="${interaction.channel.id}" AND guild_id="${interaction.guild.id}" AND ended="1"`, (err, req) => { - if (err) return interaction.reply({ embeds: [ package.embeds.errorSQL(interaction.user) ], ephemeral: true }); - - let gw = req.find(x => x.message_id === id); - if (!gw) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) - .setTitle("Pas de giveaway") - .setColor('#ff0000') - .setDescription(`Je ne trouve pas de giveway avec l'id \`${id}\` qui est terminé dans <#${interaction.channel.id}>`) - ], ephemeral: true }); - - client.GiveawayManager.reroll(interaction.guild, gw); - interaction.reply({ content: "Je reroll ce giveaway", ephemeral: true }); - }); + const result = interaction.client.GiveawayManager.reroll(id); + if (result == 'not ended') return interaction.reply({ embeds: [ package.embeds.giveaway.notEnded(interaction.user) ] }).catch(() => {}); + if (['no giveaway', 'no guild', 'no channel', 'no message'].includes(result)) return interaction.reply({ embeds: [ package.embeds.giveaway.noGw(interaction.user, id) ] }).catch(() => {}); + + interaction.reply({ content: "Je reroll ce giveaway", ephemeral: true }); } } } \ No newline at end of file From 92fc55b4aad2e4698fbfe485d0ffd7b06d6466fd Mon Sep 17 00:00:00 2001 From: Greensky Date: Wed, 17 Aug 2022 17:52:20 +0200 Subject: [PATCH 05/14] 1.5.1 --- assets/data/commands.json | 1227 +---------------- assets/data/data.json | 2 +- assets/data/perms.json | 5 +- assets/embeds.js | 10 +- assets/functions.js | 64 + assets/managers/LotoManager.js | 3 +- assets/managers/assets/embeds.js | 10 +- assets/managers/remindsManager.js | 46 +- assets/message.js | 112 +- events/{message.js.txt => message.js} | 0 events/messageCreateMention.js | 1 + events/ready.js | 12 +- index.js | 23 +- package-lock.json | 162 +-- package.json | 4 +- slash-commands/economy/adminCoins.js | 6 +- slash-commands/fun/meme.js | 39 + slash-commands/moderation/ban.js | 2 +- slash-commands/moderation/censure.js | 2 +- slash-commands/moderation/configs.js | 23 + slash-commands/moderation/demote.js | 2 +- slash-commands/moderation/kick.js | 2 +- slash-commands/moderation/mute.js | 120 ++ slash-commands/moderation/prefix.js | 6 + slash-commands/moderation/warn.js | 2 +- slash-commands/usefull/channel.js | 39 +- slash-commands/usefull/commande.js | 13 +- slash-commands/usefull/contact.js | 7 +- slash-commands/usefull/giveaway.js | 2 +- slash-commands/usefull/remind.js | 10 +- .../{moderation => usefull}/role.js | 139 ++ 31 files changed, 587 insertions(+), 1508 deletions(-) rename events/{message.js.txt => message.js} (100%) create mode 100644 slash-commands/fun/meme.js create mode 100644 slash-commands/moderation/mute.js rename slash-commands/{moderation => usefull}/role.js (62%) diff --git a/assets/data/commands.json b/assets/data/commands.json index c47619e..9e26dfe 100644 --- a/assets/data/commands.json +++ b/assets/data/commands.json @@ -1,1226 +1 @@ -{ - ".devs": [ - { - "name": "dev", - "help": { - "name": "dev", - "description": "dev", - "aliases": [], - "permissions": [], - "private": true, - "dm": true, - "cooldown": 0 - }, - "path": "./commands/.devs/dev.js" - }, - { - "name": "eval", - "help": { - "name": "eval", - "private": true, - "exemples": [ - "isNaN('-31');", - "message.channel.send('Hello');" - ], - "description": "Éxecute le code passé en arguments. Renvoie `undefined` si il n'y a pas de sortie", - "cooldown": 5, - "aliases": [], - "dm": true, - "permissions": [] - }, - "path": "./commands/.devs/eval.js" - }, - { - "name": "exportdb", - "help": { - "name": "exportdb", - "description": "Exporte la base de données", - "aliases": [], - "permissions": [], - "private": true, - "dm": false, - "cooldown": 0 - }, - "path": "./commands/.devs/exportdb.js" - }, - { - "name": "gban", - "help": { - "name": "gban", - "description": "Gère les gbans", - "aliases": [ - "dev-ban" - ], - "permissions": [], - "private": true, - "dm": false, - "cooldown": 0 - }, - "path": "./commands/.devs/gban.js" - }, - { - "name": "sendglobalmail", - "help": { - "name": "sendglobalmail", - "description": "Envoie un mail à tous les utilisateurs", - "aliases": [], - "permissions": [], - "private": true, - "dm": false, - "cooldown": 10 - }, - "path": "./commands/.devs/sendglobalmail.js" - }, - { - "name": "sql", - "help": { - "name": "sql", - "description": "Fait une requete sql", - "aliases": [ - "mysql" - ], - "permissions": [], - "private": true, - "dm": true, - "cooldown": 0 - }, - "path": "./commands/.devs/sql.js" - }, - { - "name": "switch", - "help": { - "name": "switch", - "description": "Alterne beta/finale", - "aliases": [], - "permissions": [], - "private": true, - "dm": false, - "cooldown": 0 - }, - "path": "./commands/.devs/switch.js" - }, - { - "name": "test", - "help": { - "name": "test", - "description": "Test", - "private": true, - "aliases": [ - "tset" - ], - "permissions": [], - "dm": false - }, - "path": "./commands/.devs/test.js" - } - ], - "aide": [ - { - "name": "commande", - "help": { - "name": "commande", - "aliases": [ - "cmd", - "commande-help" - ], - "description": "Affiche l'aide concernant une commande", - "permissions": [], - "private": false, - "dm": true, - "cooldown": 5 - }, - "path": "./commands/aide/cmd.js" - }, - { - "name": "help", - "help": { - "name": "help", - "description": "Commande affichant toutes les autres commandes", - "aliases": [ - "aide" - ], - "permissions": [], - "cooldown": 5, - "private": false, - "dm": true - }, - "path": "./commands/aide/help.js" - } - ], - "giveaways": [ - { - "name": "gcreate", - "help": { - "name": "gcreate", - "description": "Crée un giveaway avec un système de messages", - "aliases": [ - "giveaway-create" - ], - "permissions": [ - "manage_guild" - ], - "dm": false, - "private": false, - "cooldown": 5 - }, - "path": "./commands/giveaways/create.js" - }, - { - "name": "gend", - "help": { - "name": "gend", - "description": "Termine un giveaway", - "permissions": [ - "manage_guild" - ], - "aliases": [ - "giveaway-end" - ], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/giveaways/end.js" - }, - { - "name": "glist", - "help": { - "name": "glist", - "description": "Affiche la liste des giveaways en cours sur le serveur", - "aliases": [ - "giveaway-list" - ], - "permissions": [ - "manage_guild" - ], - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/giveaways/list.js" - }, - { - "name": "greroll", - "help": { - "name": "greroll", - "description": "Reroll un giveaway", - "aliases": [ - "giveaway-reroll" - ], - "permissions": [ - "manage_guild" - ], - "dm": false, - "private": false, - "cooldown": 5 - }, - "path": "./commands/giveaways/reroll.js" - }, - { - "name": "gstart", - "help": { - "name": "gstart", - "description": "Démarre un giveaway", - "aliases": [ - "giveaway-start" - ], - "permissions": [ - "manage_guild" - ], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/giveaways/start.js" - } - ], - "mails": [ - { - "name": "mail", - "help": { - "name": "mail", - "description": "Mail", - "private": false, - "dm": true, - "permissions": [], - "aliases": [], - "cooldown": 5 - }, - "path": "./commands/mails/mail.js" - }, - { - "name": "mail-envoi", - "help": { - "name": "mail-envoi", - "description": "Envoie un mail à un utilisateur", - "aliases": [ - "msend", - "menvoi", - "e-mail" - ], - "permissions": [], - "dm": false, - "private": false, - "cooldown": 10 - }, - "path": "./commands/mails/send.js" - } - ], - "misc": [ - { - "name": "8ball", - "help": { - "name": "8ball", - "description": "Répond à votre question (aléatoirement)", - "aliases": [], - "permissions": [], - "cooldown": 5, - "private": false, - "dm": true - }, - "path": "./commands/misc/8ball.js" - }, - { - "name": "avatar", - "help": { - "name": "avatar", - "aliases": [ - "pp", - "pdp" - ], - "permissions": [], - "description": "Affiche la photo de profil d'un utilisateur", - "cooldown": 5, - "private": false, - "dm": true - }, - "path": "./commands/misc/avatar.js" - }, - { - "name": "blague", - "help": { - "name": "blague", - "description": "Affiche une blague aléatoire", - "permissions": [], - "aliases": [ - "joke" - ], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/misc/blague.js" - }, - { - "name": "crypt", - "help": { - "name": "crypt", - "description": "Crypte un texte selon le code de vigenere", - "aliases": [ - "encrypt" - ], - "permissions": [], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/misc/crypt.js" - }, - { - "name": "customcommand", - "help": { - "name": "customcommand", - "description": "Gère les commandes personnalisées", - "private": false, - "dm": false, - "aliases": [ - "cc" - ], - "permissions": [ - "manage_guild" - ], - "cooldown": 5 - }, - "path": "./commands/misc/customcommands.js" - }, - { - "name": "decrypt", - "help": { - "name": "decrypt", - "description": "Décrypte un texte selon le code de vigenere", - "aliases": [], - "permissions": [], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/misc/decrypt.js" - }, - { - "name": "documentation", - "help": { - "name": "documentation", - "aliases": [ - "doc" - ], - "description": "Affiche la documentation du bot", - "permissions": [], - "dm": true, - "private": false, - "cooldown": 5 - }, - "path": "./commands/misc/doc.js" - }, - { - "name": "drop", - "help": { - "name": "drop", - "description": "Fait un drop dans le salon actuel", - "permissions": [ - "manage_guild" - ], - "dm": false, - "private": false, - "aliases": [] - }, - "path": "./commands/misc/drop.js" - }, - { - "name": "embed", - "help": { - "name": "embed", - "description": "Construisez un embed avec des bouttons", - "aliases": [ - "embedbuilder" - ], - "permissions": [ - "manage_channels" - ], - "private": false, - "dm": false, - "cooldown": 15 - }, - "path": "./commands/misc/embed.js" - }, - { - "name": "farsight", - "help": { - "name": "farsight", - "appear": false, - "dm": true, - "private": false, - "cooldown": 5 - }, - "path": "./commands/misc/farsight.js" - }, - { - "name": "game-number", - "help": { - "name": "game-number", - "description": "Jouez à guess the number directement sur Discord. Peut se jouer à plusieurs en ajoutant multijoueur", - "aliases": [ - "guess-the-number" - ], - "permissions": [], - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/misc/gameNumber.js" - }, - { - "name": "generatepassword", - "help": { - "name": "generatepassword", - "aliases": [ - "getpassword" - ], - "permissions": [], - "description": "Vous génère un mot de passe aléatoire plus ou moins sécurisé en fonction de vos choix", - "cooldown": 5, - "private": false, - "dm": true - }, - "path": "./commands/misc/generatePassword.js" - }, - { - "name": "google", - "help": { - "name": "google", - "description": "Effectue une recherche google", - "permissions": [], - "aliases": [ - "googlesearch" - ], - "cooldown": 5, - "private": false, - "dm": true - }, - "path": "./commands/misc/google.js" - }, - { - "name": "herobrine", - "help": { - "name": "herobrine", - "appear": false, - "dm": false, - "private": false, - "permissions": [ - "administrator" - ], - "aliases": [], - "description": ".", - "cooldown": 5 - }, - "path": "./commands/misc/herobrine.js" - }, - { - "name": "invite", - "help": { - "name": "invite", - "aliases": [ - "link" - ], - "description": "Envoie le lien d'invitation du bot", - "permissions": [], - "cooldown": 1, - "private": false, - "dm": true - }, - "path": "./commands/misc/invite.js" - }, - { - "name": "top", - "help": { - "name": "top", - "aliases": [ - "levels" - ], - "description": "Affiche le classement des niveaux sur le serveur", - "permissions": [], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/misc/levels.js" - }, - { - "name": "demineur", - "help": { - "name": "demineur", - "description": "Lance une partie de démineur sur Discord", - "aliases": [ - "minesweeper" - ], - "permissions": [], - "cooldown": 5, - "private": false, - "dm": true - }, - "path": "./commands/misc/minesweeper.js" - }, - { - "name": "morpion", - "help": { - "name": "morpion", - "description": "Joue au morpion", - "aliases": [ - "tictactoe", - "tic-tac-toe" - ], - "permissions": [], - "private": false, - "dm": false, - "cooldown": 10 - }, - "path": "./commands/misc/morpion.js" - }, - { - "name": "pile-ou-face", - "help": { - "name": "pile-ou-face", - "description": "Lance une pièce pour le pile ou face", - "aliases": [ - "pof", - "pileouface" - ], - "permissions": [], - "cooldown": 5, - "private": false, - "dm": true - }, - "path": "./commands/misc/pileOuFace.js" - }, - { - "name": "rank", - "help": { - "name": "rank", - "description": "Affiche les informations de niveaux d'un utilisateur mentionné.", - "aliases": [ - "lvl" - ], - "permissions": [], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/misc/rank.js" - }, - { - "name": "rappel", - "help": { - "name": "rappel", - "description": "Gère vos rappels", - "aliases": [ - "rmd", - "remind", - "reminders", - "rap" - ], - "permissions": [], - "dm": true, - "private": false, - "cooldown": 5 - }, - "path": "./commands/misc/remind.js" - }, - { - "name": "contact", - "help": { - "name": "contact", - "aliases": [ - "bug", - "erreur", - "report" - ], - "description": "Signale un bug à Greensky", - "permissions": [], - "dm": true, - "private": false, - "cooldown": 5 - }, - "path": "./commands/misc/report.js" - }, - { - "name": "roulette-russe", - "help": { - "name": "roulette-russe", - "description": "Joue à la roulette russe", - "aliases": [ - "russian-roulette", - "rr" - ], - "permissions": [], - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/misc/russian-roulette.js" - }, - { - "name": "suggestion", - "help": { - "name": "suggestion", - "description": "Envoie une suggestion **dans le salon actuel**", - "aliases": [ - "suggest" - ], - "permissions": [], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/misc/suggestion.js" - }, - { - "name": "super-secret-settings", - "help": { - "name": "super-secret-settings", - "appear": false, - "permissions": [], - "aliases": [ - "supersecretsettings", - "sss" - ], - "cooldown": 5, - "private": false, - "dm": true - }, - "path": "./commands/misc/supersecretsettings.js" - }, - { - "name": "support", - "help": { - "name": "support", - "description": "Affiche le lien du serveur de support.", - "aliases": [ - "support-server", - "support-server" - ], - "permissions": [], - "private": false, - "dm": true, - "cooldown": 1 - }, - "path": "./commands/misc/support.js" - }, - { - "name": "ticket", - "help": { - "name": "ticket", - "description": "Interagir avec le système de ticket. Utilisez `help` en argument pour avoir l'aide.", - "private": false, - "dm": false, - "aliases": [], - "permissions": [], - "cooldown": 5 - }, - "path": "./commands/misc/ticket.js" - } - ], - "moderation": [ - { - "name": "ban", - "help": { - "name": "ban", - "permissions": [ - "ban_members" - ], - "description": "Permet de bannir un membre", - "aliases": [], - "private": false, - "dm": false, - "cooldown": 15 - }, - "path": "./commands/moderation/ban.js" - }, - { - "name": "censure", - "help": { - "name": "censure", - "description": "Censure le pseudo d'un membre", - "aliases": [], - "permissions": [ - "manage_guild" - ], - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/moderation/censor.js" - }, - { - "name": "create-channel", - "help": { - "name": "create-channel", - "aliases": [ - "channel-create" - ], - "permissions": [ - "manage_channels" - ], - "description": "Permet de créer un salon", - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/moderation/channel-create.js" - }, - { - "name": "clear", - "help": { - "name": "clear", - "aliases": [], - "description": "Nettoie un certain nombre de messages dans un salon", - "permissions": [ - "manage_messages" - ], - "private": false, - "dm": false, - "cooldown": 10 - }, - "path": "./commands/moderation/clear.js" - }, - { - "name": "set", - "help": { - "name": "set", - "aliases": [ - "config", - "configs", - "settings", - "configssettings" - ], - "description": "Configure les différents paramètres modifiables", - "permissions": [ - "manage_guild" - ], - "private": false, - "dm": false, - "cooldown": 10 - }, - "path": "./commands/moderation/config.js" - }, - { - "name": "demote", - "help": { - "name": "demote", - "description": "Retire un ou plusieurs roles à un utilisateur. Utilisez `help` pour avoir toutes les informations.", - "aliases": [ - "downgrade", - "role-remove" - ], - "permissions": [ - "MANAGE_ROLES" - ], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/moderation/demote.js" - }, - { - "name": "edit-case", - "help": { - "name": "edit-case", - "description": "Modifie une case de modération", - "aliases": [], - "permissions": [ - "manage_guild" - ], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/moderation/edit-case.js" - }, - { - "name": "filtre-case-action", - "help": { - "name": "filtre-case-action", - "description": "Filtre les cases de modération selon votre choix.", - "private": false, - "aliases": [ - "filtre-modlogs" - ], - "permissions": [ - "manage_guild" - ], - "dm": false, - "cooldown": 5 - }, - "path": "./commands/moderation/filtre-case-action.js" - }, - { - "name": "kick", - "help": { - "name": "kick", - "description": "Expulse un membre du serveur pour une raison donnée", - "permissions": [ - "kick_members" - ], - "aliases": [ - "expulse" - ], - "private": false, - "dm": false, - "cooldown": 10 - }, - "path": "./commands/moderation/kick.js" - }, - { - "name": "lock", - "help": { - "name": "lock", - "aliases": [ - "channellock", - "lockchannel", - "lock-channel", - "channel-lock" - ], - "permissions": [ - "manage_channels" - ], - "cooldown": 5, - "private": false, - "dm": false, - "description": "Vérouille un salon pour le role everyone" - }, - "path": "./commands/moderation/lock.js" - }, - { - "name": "log", - "help": { - "name": "log", - "description": "Affiche un log de modération donné", - "aliases": [ - "log-info" - ], - "permissions": [ - "MANAGE_GUILD" - ], - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/moderation/log.js" - }, - { - "name": "massban", - "help": { - "name": "massban", - "description": "Permet de bannir plusieurs membres à la fois", - "aliases": [ - "multipleban" - ], - "permissions": [ - "ban_members" - ], - "private": false, - "dm": false, - "cooldown": 10 - }, - "path": "./commands/moderation/massBan.js" - }, - { - "name": "modlogs", - "help": { - "name": "modlogs", - "description": "Affiche les logs de modération", - "aliases": [], - "permissions": [ - "manage_guild" - ], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/moderation/modlogs.js" - }, - { - "name": "mute", - "help": { - "name": "mute", - "description": "Rend un membre du serveur muet", - "permissions": [ - "kick_members" - ], - "aliases": [], - "private": false, - "dm": false, - "cooldown": 10 - }, - "path": "./commands/moderation/mute.js" - }, - { - "name": "nuke", - "help": { - "name": "nuke", - "description": "Nettoie un salon entier", - "cooldown": 10, - "permissions": [ - "manage_channels" - ], - "private": false, - "dm": false, - "aliases": [] - }, - "path": "./commands/moderation/nuke.js" - }, - { - "name": "pin", - "help": { - "name": "pin", - "aliases": [ - "epingle", - "épingle" - ], - "permissions": [ - "manage_messages" - ], - "description": "Épingle un message. Utilisez un identifiant.", - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/moderation/pin.js" - }, - { - "name": "prefix", - "help": { - "name": "prefix", - "description": "Configure le préfixe.", - "aliases": [ - "prefixe" - ], - "permissions": [ - "manage_guild" - ], - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/moderation/prefix.js" - }, - { - "name": "purge", - "help": { - "name": "purge", - "description": "Ban tous les membres GBannis du serveur.", - "permissions": [ - "ADMINISTRATOR" - ], - "aliases": [ - "gban-purge" - ], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/moderation/purge.js" - }, - { - "name": "role", - "help": { - "name": "role", - "description": "Ajoute un rôle choisi à un utilisateur choisi", - "permissions": [ - "manage_roles" - ], - "aliases": [ - "addrole" - ], - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/moderation/role.js" - }, - { - "name": "see-warns", - "help": { - "name": "see-warns", - "aliases": [ - "infractions", - "seewarns" - ], - "description": "Montre les avertissements d'un utilisateur.", - "permissions": [ - "manage_guild" - ], - "dm": false, - "private": false, - "cooldown": 5 - }, - "path": "./commands/moderation/see-warns.js" - }, - { - "name": "slowmode", - "help": { - "name": "slowmode", - "description": "Configure le slowmode du salon", - "permissions": [ - "manage_channels" - ], - "aliases": [], - "private": false, - "dm": false, - "cooldown": 5 - }, - "path": "./commands/moderation/slowmode.js" - }, - { - "name": "snipe", - "help": { - "name": "snipe", - "description": "Affiche le dernier message supprimé dans le salon, et plus si un nombre est spécifié.", - "aliases": [], - "permissions": [ - "manage_messages" - ], - "dm": false, - "private": false, - "cooldown": 5 - }, - "path": "./commands/moderation/snipe.js" - }, - { - "name": "sondage", - "help": { - "name": "sondage", - "description": "Faites un sondage, utilisez-là de cette manière\n\n`gs sondage --choix 1 --choix 2... --choix 7` ou simplement aucun choix", - "aliases": [ - "poll" - ], - "permissions": [ - "manage_guild" - ], - "cooldown": 10, - "private": false, - "dm": false - }, - "path": "./commands/moderation/sondage.js" - }, - { - "name": "ticket-config", - "help": { - "name": "ticket-config", - "description": "Configurez un panel de ticket. Utilisez `create` pour le créer et `delete` pour le supprimer.", - "aliases": [ - "configtickets", - "config-tickets", - "tickets-config", - "ticket-panel", - "ticket-configs" - ], - "permissions": [ - "manage_guild" - ], - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/moderation/ticket-manage.js" - }, - { - "name": "unban", - "help": { - "name": "unban", - "description": "Débanni un utilisateur du serveur. Utilisez l'identifiant du membre.", - "aliases": [ - "deban" - ], - "permissions": [ - "ban_members" - ], - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/moderation/unban.js" - }, - { - "name": "unlock", - "help": { - "name": "unlock", - "description": "Dévérouille le salon pour le rôle everyone", - "permissions": [ - "manage_channels" - ], - "aliases": [], - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/moderation/unlock.js" - }, - { - "name": "unmute", - "help": { - "name": "unmute", - "description": "Démute un membre mentionné", - "aliases": [ - "demute" - ], - "permissions": [ - "manage_roles" - ], - "dm": false, - "private": false, - "cooldown": 10 - }, - "path": "./commands/moderation/unmute.js" - }, - { - "name": "unpin", - "help": { - "name": "unpin", - "aliases": [ - "desepingle", - "désepingle" - ], - "permissions": [ - "manage_messages" - ], - "description": "Désepingle un message. Utilisez un identifiant.", - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/moderation/unpin.js" - }, - { - "name": "unwarn", - "help": { - "name": "unwarn", - "aliases": [ - "dewarn" - ], - "permissions": [ - "manage_guild" - ], - "description": "Enlève un avertissement à un utilsateur", - "cooldown": 5, - "private": false, - "dm": false - }, - "path": "./commands/moderation/unwarn.js" - }, - { - "name": "warn", - "help": { - "name": "warn", - "description": "Avertit un membre", - "aliases": [ - "avertit" - ], - "permissions": [ - "manage_guild" - ], - "dm": false, - "private": false, - "cooldown": 5 - }, - "path": "./commands/moderation/warn.js" - } - ], - "rolereacts": [ - { - "name": "role-react-manage", - "help": { - "name": "role-react-manage", - "aliases": [ - "rrm", - "manage-rolesreact", - "manage-rolereact", - "rm" - ], - "description": "Configure les rôles à réactions", - "permissions": [ - "manage_guild" - ], - "dm": false, - "private": false, - "cooldown": 5 - }, - "path": "./commands/rolereacts/manage.js" - } - ], - "rpg": [ - { - "name": "adventure", - "help": { - "name": "adventure", - "aliases": [ - "aventure" - ], - "description": "Obtenez les infos sur le RPG", - "permissions": [], - "cooldown": 5, - "private": false, - "dm": true - }, - "path": "./commands/rpg/adventure.js" - } - ] -} \ No newline at end of file +{} \ No newline at end of file diff --git a/assets/data/data.json b/assets/data/data.json index 837dee0..b849702 100644 --- a/assets/data/data.json +++ b/assets/data/data.json @@ -7,7 +7,7 @@ "errorChannel": "839497213113270322", "botID": "918137973202112592", "contactChannel": "827790768272834580", - "version": "1.5", + "version": "1.5.1", "beta_token": "OTE4MTM3OTczMjAyMTEyNTky.G5q2vD.tYpVroN28ovgVIPXUKR9GDVqmZexUEwneXTTLk", "beta": false, "doc": "https://bit.ly/3c37f8V", diff --git a/assets/data/perms.json b/assets/data/perms.json index f550ee2..70ba089 100644 --- a/assets/data/perms.json +++ b/assets/data/perms.json @@ -1,2 +1,3 @@ -{"CREATE_INSTANT_INVITE":"Créer des invitations","KICK_MEMBERS": "Expulser des membres","BAN_MEMBERS": "Bannir des membres","ADMINISTRATOR": "Administrateur","MANAGE_CHANNELS": "Gérer les salons","MANAGE_GUILD": "Gérer le serveur","ADD_REACTIONS": "Ajouter des réactions","VIEW_AUDIT_LOG": "Voir les logs du serveur","PRIORITY_SPEAKER": "Voix prioritaire","STREAM": "Faire des streams","VIEW_CHANNEL": "Voir les salons","SEND_MESSAGES": "Envoyer des messages","SEND_TTS_MESSAGES": "Envoyer des TTS","MANAGE_MESSAGES": "Gérer les messages","EMBED_LINKS": "envoyer des liens","ATTACH_FILES": "Envoyer des fichiers","READ_MESSAGE_HISTORY": "Voir l'historique des messages","MENTION_EVERYONE": "Mentionner les rôles","USE_EXTERNAL_EMOJIS": "Utiliser des émojis externes","VIEW_GUILD_INSIGHTS": "Voir les paramètres du serveur","CONNECT": "Se connecter à des salons vocaux","SPEAK": "Parler en vocal","MUTE_MEMBERS": "Rendre des membres muets","DEAFEN_MEMBERS": "Déconnecter des membres","MOVE_MEMBERS": "Changer les membres de salons","USE_VAD": "je ne connais pas cette permission", - "CHANGE_NICKNAME": "Changer le pseudo","MANAGE_NICKNAMES": "Gérer les pseudos","MANAGE_ROLES": "Gérer les rôles","MANAGE_WEBHOOKS": "Gérer les webhooks","MANAGE_EMOJIS": "Gérer les émojis"} \ No newline at end of file +{"CREATE_INSTANT_INVITE":"Créer des invitations","KICK_MEMBERS": "Expulser des membres","BAN_MEMBERS": "Bannir des membres","ADMINISTRATOR": "Administrateur","MANAGE_CHANNELS": "Gérer les salons","MANAGE_GUILD": "Gérer le serveur","ADD_REACTIONS": "Ajouter des réactions","VIEW_AUDIT_LOG": "Voir les logs du serveur","PRIORITY_SPEAKER": "Voix prioritaire","STREAM": "Faire des streams","VIEW_CHANNEL": "Voir les salons","SEND_MESSAGES": "Envoyer des messages","SEND_TTS_MESSAGES": "Envoyer des TTS","MANAGE_MESSAGES": "Gérer les messages","EMBED_LINKS": "envoyer des liens","ATTACH_FILES": "Envoyer des fichiers","READ_MESSAGE_HISTORY": "Voir l'historique des messages","MENTION_EVERYONE": "Mentionner les rôles","USE_EXTERNAL_EMOJIS": "Utiliser des émojis externes","VIEW_GUILD_INSIGHTS": "Voir les paramètres du serveur","CONNECT": "Se connecter à des salons vocaux","SPEAK": "Parler en vocal","MUTE_MEMBERS": "Rendre des membres muets","DEAFEN_MEMBERS": "Déconnecter des membres","MOVE_MEMBERS": "Changer les membres de salons","USE_VAD": "Utiliser la détection de la voix", + "CHANGE_NICKNAME": "Changer le pseudo","MANAGE_NICKNAMES": "Gérer les pseudos","MANAGE_ROLES": "Gérer les rôles","MANAGE_WEBHOOKS": "Gérer les webhooks","MANAGE_EMOJIS_AND_STICKERS": "Gérer les émojis et les stickers", +"MANAGE_EVENTS": "Gérer les évènements", "MANAGE_THREADS": "Gérer les fils", "USE_APPLICATION_COMMANDS": "Utiliser les slash commandes", "SEND_MESSAGES_IN_THREADS": "Envoyer des messages dans un fil", "CREATE_PUBLIC_THREADS": "Créer des fils publiques", "CREATE_PRIVATE_THREADS": "Créer des fils privés"} \ No newline at end of file diff --git a/assets/embeds.js b/assets/embeds.js index ec22eb4..33650e0 100644 --- a/assets/embeds.js +++ b/assets/embeds.js @@ -1,16 +1,18 @@ const emojis = require('./data/emojis.json'); -const { MessageEmbed, User, Message, Interaction } = require('discord.js'); +const { MessageEmbed, User, Message, Interaction, GuildMember } = require('discord.js'); const collections = require('./data/collects'); const data = require('./data/data.json'); /** - * @param {User} user + * @param {User | GuildMember} user * @returns {MessageEmbed} */ const generateBasic = (user) => { + let u = user; + if (u.guild) u = u.user; return new MessageEmbed() .setTimestamp() - .setFooter({ text: user.username.toString(), iconURL: user.avatarURL({dynamic: true})}) + .setFooter({ text: u.username.toString(), iconURL: u.avatarURL({dynamic: true})}) } module.exports = { @@ -242,7 +244,7 @@ ${Edata.winners.length == 0 ? 'Pas de gagnants' : Edata.winners.map(w => `<@${w. return generateBasic(user) .setTitle("🎉 Loto lancé") - .setDescription(`Le loto a été lancé !\nIl prendra fin le ( )\n\nPour participer il faut **${numbers}** numéro et **${complementaries}** numéro complémentaires.\n\nRécompense :\n${reward} ${data.coins}`) + .setDescription(`Le loto a été lancé !\nIl prendra fin le ( )\n\nPour participer il faut **${numbers}** numéro et **${complementaries}** numéro complémentaires.\n\nRécompense :\n${reward} ${parseInt(data.coins).toLocaleString('fr-DE')}`) .setColor('#ff0000') } }, diff --git a/assets/functions.js b/assets/functions.js index ca3ffde..518bcf5 100644 --- a/assets/functions.js +++ b/assets/functions.js @@ -238,6 +238,7 @@ module.exports = { * @param {Discord.GuildMember} modo * @param {Discord.GuildMember} member * @param {?Discord.CommandInteraction} interaction + * @deprecated Use `checkPerms` instead */ checkAllConditions: (guild, channel, modo, member, interaction) => { const { compareRoles } = require('./functions.js') @@ -291,6 +292,69 @@ module.exports = { }; return true; }, + /** + * @param {{ mod: Discord.GuildMember, member: Discord.GuildMember, interaction: Discord.CommandInteraction, ?checkBotCompare: Boolean ?checkSelfUser: Boolean, ?checkOwner: Boolean, ?checkBot: Boolean, ?all: Boolean }} data + */ + checkPerms(data) { + const send = (embed) => { + if (data.interaction.replied) { + data.interaction.editReply({ embeds: [ embed ], components: [] }).catch(() => {}); + } else { + data.interaction.reply({ embeds: [ embed ] }).catch(() => {}); + }; + }; + if (data.all == true) { + for (const x of ['checkBot', 'checkOwner', 'checkBotCompare', 'checkSelfUser']) { + data[x] = true; + }; + }; + + if (data.mod.roles.highest.position <= data.member.roles.highest.position) { + send(embeds.notEnoughHiger(data.mod.user, data.member)); + return false; + }; + if (data.checkBotCompare == true && data.member.roles.position >= data.member.guild.me.roles.highest.position) { + send(embeds.classic(data.mod.user) + .setTitle("Pas assez élevé") + .setDescription(`Oops, il semblerait que <@${data.member.id}> soit supérieur ou égal à moi dans la hiérarchie des rôles.`) + .setColor('#ff0000') + ) + return false; + }; + if (data.checkBot == true && data.member.user.bot == true) { + send(embeds.classic(data.mod) + .setTitle("Bot") + .setDescription(`<@${data.member.id}> est un bot (je ne peux tout de même pas blâmer un coupain)`) + .setColor('#ff0000') + ); + return false; + }; + if (data.checkOwner == true && data.member.id == data.member.guild.ownerId) { + send(embeds.classic(data.mod) + .setTitle("Propriétaire") + .setDescription(`<@${data.member.id}> est le propriétaire du serveur, vous n'allez quand même pas tenter un coup d'état ?`) + .setColor('#ff0000') + ); + return false; + }; + if (data.checkSelfUser == true && data.member.id == data.mod.id) { + send(embeds.classic(data.mod) + .setTitle("Narcissisme") + .setDescription(`La personne que vous ciblez ( <@${data.member.id}> ) est **vous**. Je suis sûr que vous n'êtes pas narcissique à ce point !`) + .setColor('#ff0000') + ); + return false; + }; + if (!data.member.moderatable) { + send(embeds.classic(data.mod) + .setTitle("Membre non-modérable") + .setDescription(`Je ne peux pas effectuer d'actions de modération sur <@${data.member.id}>`) + .setColor('#ff0000') + ); + return false; + } + return true; + }, /** * @param {Number} number * @deprecated Use `numberToHuman` instead diff --git a/assets/managers/LotoManager.js b/assets/managers/LotoManager.js index 3d99e31..274c83b 100644 --- a/assets/managers/LotoManager.js +++ b/assets/managers/LotoManager.js @@ -32,7 +32,7 @@ class LotoManager { createQuery(data, exists) { let sql = `INSERT INTO loto (${Object.keys(data).join(', ')}) VALUES (${Object.values(data).map(x => `'${x}'`).join(', ')})`; - if (exists == true) sql = `UPDATE loto SET ${Object.keys(data).map(x => `${x}='${data[x]}'`).join(', ')}`; + if (exists == true) sql = `UPDATE loto SET ${Object.keys(data).map(x => `${x}='${data[x]}'`).join(', ')} WHERE guild_id="${data.guild_id}"`; return sql; } @@ -102,6 +102,7 @@ class LotoManager { if (!this.validArray(data.numbers) || !this.validArray(data.complementaries)) return 'invalid arrays'; if (!this.validArrayCompare(data.complementaries, data.numbers)) return 'invalid compared'; + if (typeof data.json == 'string') loto.json = JSON.parse(loto.json); if (loto.json.find(x => x.user_id == data.userId)) return 'user already exists'; loto.json.push({ diff --git a/assets/managers/assets/embeds.js b/assets/managers/assets/embeds.js index 44cbf3d..26587fa 100644 --- a/assets/managers/assets/embeds.js +++ b/assets/managers/assets/embeds.js @@ -53,15 +53,21 @@ Finit `) return embed; }, hasDeniedRoles: (deniedRoles, url) => { + let roles = deniedRoles; + if (typeof roles == 'string') roles = JSON.parse(roles); + return new MessageEmbed() .setTitle("🚫 Accès refusé") - .setDescription(`L'accès à [**ce giveaway**](${url}) vous est refusé car vous avez un ou plusieurs de ces rôles :\n${deniedRoles.map(x => `<@&${x}>`).join(' ')}`) + .setDescription(`L'accès à [**ce giveaway**](${url}) vous est refusé car vous avez un ou plusieurs de ces rôles :\n${roles.map(x => `<@&${x}>`).join(' ')}`) .setColor('#ff0000') }, missingRequiredRoles: (requiredRoles, url) => { + let roles = requiredRoles; + if (typeof roles == 'string') roles = JSON.parse(roles); + return new MessageEmbed() .setTitle("🚫 Accès refusé") - .setDescription(`L'accès à [**ce giveaway**](${url}) vous est réfusé car vous n'avez pas un ou plusieurs de ces rôles :\n${requiredRoles.map(x => `<@&${x}>`).join(' ')}`) + .setDescription(`L'accès à [**ce giveaway**](${url}) vous est réfusé car vous n'avez pas un ou plusieurs de ces rôles :\n${roles.map(x => `<@&${x}>`).join(' ')}`) .setColor('#ff0000') }, entryAllowed: (url) => { diff --git a/assets/managers/remindsManager.js b/assets/managers/remindsManager.js index 5a4f0ad..ffc41f7 100644 --- a/assets/managers/remindsManager.js +++ b/assets/managers/remindsManager.js @@ -54,11 +54,39 @@ class RemindsManger { }) }) } + removeInteraction(user, interaction, number) { + if (isNaN(number)) return interaction.reply({ content: pack.embeds.invalidNumber(user) }).catch(() => {}); + + this.db.query(`SELECT * FROM reminds WHERE user_id="${user.id}" AND ended="0" ORDER BY createdAt DESC`, (err, req) => { + if (err) return interaction.reply({ embeds: [ pack.embeds.errorSQL(user) ] }).catch(() => {}); + + const index = number - 1; + if (!req[index]) return interaction.reply({ content: `Vous n'avez aucun rappel de numéro \`${number}\`` }).catch(() => {}); + + const date = req[index].createdAt; + this.db.query(`DELETE FROM reminds WHERE user_id="${user.id}" AND createdAt="${date}" AND ended="0"`, (e) => { + if (e) return interaction.reply({ embeds: [ pack.embeds.errorSQL(user) ] }).catch(() => {}); + + interaction.reply({ content: `Je supprime le rappel numéro \`${number}\`` }).catch(() => {}); + }); + }); + } + /** + * @param {Discord.User} user + * @param {Discord.TextChannel | Discord.CommandInteraction} channel + */ list(user, channel) { + const fnt = (params) => { + if (channel.commandName) { + channel.reply(params).catch(() => {}); + } else { + channel.send(params).catch(() => {}); + }; + }; this.db.query(`SELECT * FROM reminds WHERE user_id="${user.id}" AND ended="0"`, (err, req) => { - if (err) return channel.send({ embeds: [ pack.embeds.errorSQL(user) ] }); + if (err) return fnt({ embeds: [ pack.embeds.errorSQL(user) ] }); - if (req.length === 0) return channel.send({ content: `Vous n'avez aucun rappel.` }); + if (req.length === 0) return fnt({ content: `Vous n'avez aucun rappel.` }); if (req.length > 5) { let now = pack.embeds.classic(user) .setTitle("Rappels") @@ -72,7 +100,7 @@ class RemindsManger { for (let i = 0; i < req.length; i++) { const warn = req[i]; - now.addField(`${i + 1})Rappel`, `\`\`\`${warn.content}\`\`\`\n> ${moment(parseInt(warn.date)).fromNow()}`, false); + now.addField(`${i + 1})Rappel`, `\`\`\`${warn.content}\`\`\`\n> `, false); pile = false; @@ -92,8 +120,12 @@ class RemindsManger { }; if (!pile) embeds.push(now); - - functions.pagination(user, channel, embeds, `rappels`); + + if (channel.commandName) { + functions.pagination(user, 'none', embeds, 'rappels', channel); + } else { + functions.pagination(user, channel, embeds, `rappels`); + }; } else { const embed = pack.embeds.classic(user) .setTitle("Rappels") @@ -102,10 +134,10 @@ class RemindsManger { req.forEach((warn) => { const id = req.indexOf(warn) + 1; - embed.addField(`${id}) Rappel`, `\`\`\`${warn.content}\`\`\`\n> ${moment(parseInt(warn.date)).fromNow()}`, false); + embed.addField(`${id}) Rappel`, `\`\`\`${warn.content}\`\`\`\n> `, false); }); - channel.send({ embeds: [ embed ] }); + fnt({ embeds: [ embed ] }); } }) } diff --git a/assets/message.js b/assets/message.js index 316862e..38a1135 100644 --- a/assets/message.js +++ b/assets/message.js @@ -25,48 +25,6 @@ module.exports = { const run = (prefix) => { - if (message.mentions.users.has(client.user.id) && !message.mentions.everyone) { - let splashes = require('./data/splash.json').filter(x => !x.includes('weird')); - - if (!functions.random(200, 0) === 132) { - const index = splashes.indexOf(x => x === 'This is an easter egg !'); - splashes.splice(index, 1); - }; - let size = require('./data/splash.json').length; - - let splash = splashes[functions.random(splashes.length, 0)].replace('{username}', message.author.username); - splash.replace('{size}', size); - - const reponse = package.embeds.classic(message.author) - .setTitle(splash) - .setDescription(`Bonjour ! Mon préfixe sur ce serveur est \`${prefix}\` !\n\nFaites \`${prefix}help\` pour obtenir de l'aide.\n\n:bulb: <@${client.user.id}> est désormais disponible en slash commands !\n> Si vous ne voyez pas mes slash commands, réinvitez moi par le lien de la commande \`${prefix}invite\`.`) - .setColor(message.guild.me.displayHexColor) - .setAuthor({ name: message.guild ? message.guild.me.nickname ? message.guild.me.nickname :'Oracle' : "Oracle", iconURL: message.author.displayAvatarURL({ dynamic: true }) }) - - if (splash === "Click on the link") { - reponse.setURL('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); - }; - - functions.reply(message, reponse); - - if (message.guild) { - if (functions.random(10000, 0) === 794) { - message.guild.me.setNickname(`Oralce`); - }; - if ((message.guild.me.nickname === 'Dinnerbone' || message.guild.me.nickname === 'Grumm') && functions.random(10, 0) === 5) { - const reverse = (text) => { - let t =""; - for (let i =0;i { - if (error) go = false; - if (error) return message.channel.send({ embeds: [ package.embeds.errorSQL(message.author) ] }) & console.log(error); - }); - } else { - if (parseInt(req[0].date) > Date.now()) { - const moment = require('moment'); - moment.locale('fr'); - - return message.channel.send({ embeds: [ package.embeds.classic(message.author) - .setTitle('Cooldown') - .setDescription(`Oops, vous avez un cooldown sur cette commande, réessayez ${moment(req[0].date)}`) - .setColor('#ff0000') - ] }); - } else { - client.db.query(`INSERT INTO cooldowns (guild_id, user_id, command, date) VALUES ("${message.guild.id}", "${message.author.id}", "${file.name}", "${Date.now() + file.help.cooldown * 1000}")`, (error) => { - if (error) go =false & console.log(error); - if (error) return message.channel.send({ embeds: [ package.embeds.errorSQL(message.author) ] }); - }); - } - }; - if (!go) return; - suite(); }) }; - if (message.guild) { - client.db.query(`SELECT * FROM customs WHERE guild_id="${message.guild.id}" AND name="${commandName}"`, (error, request) => { - if (error) { - console.log(error); - message.channel.send({ embeds: [ package.embeds.errorSQL(message.author) ] }); - return; - } - - if (request.length === 0) return next(); - - let original = request[0].text; - - let response = original; - function replace(x, y) { - const regex = new RegExp(`{${x}}`, 'g'); - - response = response.replace(regex, y); - }; - - const corres = [ - {x: 'user.name', y: message.author.username}, - {x: 'user.tag', y: message.author.discriminator}, - {x: 'user.mention', y: `<@${message.author.id}>`}, - {x: 'user.id', y: message.author.id}, - {x: "del", y: ' '}, - {x: "args", y: args.join(' ') ? args.join(' ') : 'missingno'}, - {x: 'guild.name', y: message.guild.name}, - {x: 'guild.count', y: message.guild.members.cache.size}, - {x: 'reply', y: ' '}, - {x: 'mp', y: ' '} - ]; - corres.forEach((x) => {replace(x.x, x.y)}); - - let line = false; - - if (original.includes('{del}')) message.delete().catch(() => {}); - if (original.includes('{reply}')) line = true; - - if (original.includes('{mp}')) { - message.author.send({ content: response }).catch(() => {}); - } else { - if (line) return functions.lineReply(message.id, message.channel, response, false); - return message.channel.send({ content: response }); - } - }); + if (message.guild) { } else { next(); } diff --git a/events/message.js.txt b/events/message.js similarity index 100% rename from events/message.js.txt rename to events/message.js diff --git a/events/messageCreateMention.js b/events/messageCreateMention.js index 356050d..8a00669 100644 --- a/events/messageCreateMention.js +++ b/events/messageCreateMention.js @@ -4,6 +4,7 @@ const package = functions.package(); module.exports = { event: 'messageCreate', execute: (message) => { + if (message.author.bot) return; if (message.mentions.users.has(message.client.user.id) && !message.mentions.everyone) { let splashes = require('../assets/data/splash.json').filter(x => !x.includes('weird')); diff --git a/events/ready.js b/events/ready.js index e036679..6f4588a 100644 --- a/events/ready.js +++ b/events/ready.js @@ -108,7 +108,10 @@ module.exports = { {name: 'la version ' + require('../assets/data/data.json').version, type: 'WATCHING'}, {name: `%users% utilisateurs`, type: 'LISTENING'}, {name: `%servers% serveurs`, type: 'WATCHING'}, - {name: "Passage en slash commandes !", type: 'WATCHING'} + {name: "Passage en slash commandes !", type: 'WATCHING'}, + {name: "Mentionnez moi pour des informations", type: 'WATCHING'}, + {name: "%members% membres", type: 'WATCHING'}, + {name: 'une vidéo', type: 'STREAMING', url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'} ]; setInterval(() => { @@ -124,6 +127,13 @@ module.exports = { statut.name = statut.name .replace('%users%', client.users.cache.size) .replace('%servers%', client.guilds.cache.size); + + if (statut.name.includes('%members%')) { + (async() => {await client.guilds.fetch()}); + let members = client.guilds.cache.map(x => x.memberCount).reduce((a, b) => a + b); + + statut.name = statut.name.replace('%members%', members); + }; client.user.setActivity(statut); }, 20000); diff --git a/index.js b/index.js index 37dd48d..e195d83 100644 --- a/index.js +++ b/index.js @@ -22,17 +22,18 @@ fs.readdirSync('./events').filter(x => x.endsWith('.js')).forEach((fileName) => module.exports.client = client; var obj = {}; -fs.readdirSync('./commands').forEach((dirName) => { - obj[dirName] = []; - fs.readdirSync(`./commands/${dirName}`).filter((x) => x.endsWith('.js')).forEach((fileName) => { - let commandFile = require(`./commands/${dirName}/${fileName}`); - obj[dirName].push({ - name: commandFile.help.name, - help: commandFile.help, - path: `./commands/${dirName}/${fileName}` - }); - }); -}); + +// fs.readdirSync('./commands').forEach((dirName) => { +// obj[dirName] = []; +// fs.readdirSync(`./commands/${dirName}`).filter((x) => x.endsWith('.js')).forEach((fileName) => { +// let commandFile = require(`./commands/${dirName}/${fileName}`); +// obj[dirName].push({ +// name: commandFile.help.name, +// help: commandFile.help, +// path: `./commands/${dirName}/${fileName}` +// }); +// }); +// }); fs.writeFileSync(`./assets/data/commands.json`, JSON.stringify(obj, '', 1)); diff --git a/package-lock.json b/package-lock.json index 7c60cd5..666eba1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "@discordjs/rest": "^0.3.0", + "axios": "^0.27.2", "blagues-api": "^2.1.0", "dblapi.js": "^2.4.1", "discord-api-types": "^0.26.1", @@ -17,8 +18,7 @@ "fs": "^0.0.1-security", "moment": "^2.29.1", "ms": "^2.1.3", - "mysql": "^2.18.1", - "twemoji": "^14.0.2" + "mysql": "^2.18.1" } }, "node_modules/@discordjs/builders": { @@ -132,6 +132,15 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "node_modules/bignumber.js": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", @@ -215,6 +224,25 @@ "npm": ">=7.0.0" } }, + "node_modules/follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -233,32 +261,6 @@ "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-extra/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -269,17 +271,6 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, - "node_modules/jsonfile": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz", - "integrity": "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==", - "dependencies": { - "universalify": "^0.1.2" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", @@ -400,30 +391,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, - "node_modules/twemoji": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/twemoji/-/twemoji-14.0.2.tgz", - "integrity": "sha512-BzOoXIe1QVdmsUmZ54xbEH+8AgtOKUiG53zO5vVP2iUu6h5u9lN15NcuS6te4OY96qx0H7JK9vjjl9WQbkTRuA==", - "dependencies": { - "fs-extra": "^8.0.1", - "jsonfile": "^5.0.0", - "twemoji-parser": "14.0.0", - "universalify": "^0.1.2" - } - }, - "node_modules/twemoji-parser": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/twemoji-parser/-/twemoji-parser-14.0.0.tgz", - "integrity": "sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA==" - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -558,6 +525,15 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "bignumber.js": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", @@ -623,6 +599,11 @@ "ws": "^8.4.0" } }, + "follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" + }, "form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -638,31 +619,6 @@ "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "dependencies": { - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "requires": { - "graceful-fs": "^4.1.6" - } - } - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -673,15 +629,6 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, - "jsonfile": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz", - "integrity": "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^0.1.2" - } - }, "mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", @@ -776,27 +723,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, - "twemoji": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/twemoji/-/twemoji-14.0.2.tgz", - "integrity": "sha512-BzOoXIe1QVdmsUmZ54xbEH+8AgtOKUiG53zO5vVP2iUu6h5u9lN15NcuS6te4OY96qx0H7JK9vjjl9WQbkTRuA==", - "requires": { - "fs-extra": "^8.0.1", - "jsonfile": "^5.0.0", - "twemoji-parser": "14.0.0", - "universalify": "^0.1.2" - } - }, - "twemoji-parser": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/twemoji-parser/-/twemoji-parser-14.0.0.tgz", - "integrity": "sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA==" - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index ca4ddb7..708c51c 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "@discordjs/rest": "^0.3.0", + "axios": "^0.27.2", "blagues-api": "^2.1.0", "dblapi.js": "^2.4.1", "discord-api-types": "^0.26.1", @@ -17,7 +18,6 @@ "fs": "^0.0.1-security", "moment": "^2.29.1", "ms": "^2.1.3", - "mysql": "^2.18.1", - "twemoji": "^14.0.2" + "mysql": "^2.18.1" } } diff --git a/slash-commands/economy/adminCoins.js b/slash-commands/economy/adminCoins.js index fc2f760..273583f 100644 --- a/slash-commands/economy/adminCoins.js +++ b/slash-commands/economy/adminCoins.js @@ -92,7 +92,7 @@ module.exports = { if (amount < 0) amount = parseInt(amount.toString().slice(1)); amount = amount.toFixed(0); if (isNaN(amount)) return interaction.reply({ embeds: [ package.embeds.invalidNumber(interaction.user) ] }).catch(() => {}); - if (!functions.checkAllConditions(interaction.guild, interaction.channel, interaction.member, member, interaction)) return; + if (!functions.checkPerms({ interaction, member, mod: interaction.member, checkBot: true, checkBotCompare: true })) return; interaction.client.CoinsManager.addCoins({ user_id: member.id, guild_id: interaction.guild.id }, amount); @@ -109,7 +109,7 @@ module.exports = { if (amount < 0) amount = parseInt(amount.toString().slice(1)); amount = amount.toFixed(0); if (isNaN(amount)) return interaction.reply({ embeds: [ package.embeds.invalidNumber(interaction.user) ] }).catch(() => {}); - if (!functions.checkAllConditions(interaction.guild, interaction.channel, interaction.member, member, interaction)) return; + if (!functions.checkPerms({ mod: interaction.member, member: member, checkBot: true, checkBotCompare: true, interaction: interaction })) return; const result = interaction.client.CoinsManager.removeCoins({ user_id: member.id, guild_id: interaction.guild.id }, amount); if (result == 'not enough coins' || result == false) return interaction.reply({ embeds: [ package.embeds.notEnoughCoins(member.user) ] }).catch(() => {}); @@ -123,7 +123,7 @@ module.exports = { if (subcommand == 'utilisateur') { let member = interaction.options.getMember('utilisateur'); - if (!functions.checkAllConditions(interaction.guild, interaction.channel, interaction.member, member, interaction)) return; + if (!functions.checkPerms({ mod: interaction.member, member: member, checkBot: true, checkBotCompare: true, interaction: interaction })) return; await interaction.reply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Confirmation") diff --git a/slash-commands/fun/meme.js b/slash-commands/fun/meme.js new file mode 100644 index 0000000..4ee44a4 --- /dev/null +++ b/slash-commands/fun/meme.js @@ -0,0 +1,39 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); +const axios = require('axios'); + +module.exports = { + help: { + cd: 5, + dev: false, + dm: true, + systems: [], + permissions: [] + }, + configs: { + name: 'meme', + description: "Envoie un meme" + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + await interaction.deferReply(); + + axios('https://some-random-api.ml/meme').then((res) => { + if (res.statusText !== 'OK') return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Erreur") + .setDescription(`Je n'ai pas pu récupérer de meme.\nSi ce message se réaffiche, contactez mes développeurs (\`/contact\`)`) + .setColor('#ff0000') + ] }).catch(() => {}); + + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Meme") + .setColor(interaction?.guild?.me?.displayHexColor ?? 'ORANGE') + .setDescription(res.data.caption) + .setImage(res.data.image) + ] }).catch(() => {}); + }); + } +} \ No newline at end of file diff --git a/slash-commands/moderation/ban.js b/slash-commands/moderation/ban.js index cf9dbe4..1f22e37 100644 --- a/slash-commands/moderation/ban.js +++ b/slash-commands/moderation/ban.js @@ -38,7 +38,7 @@ module.exports = { const reason = interaction.options.get('raison').value; if (reason.includes('"')) return interaction.reply({ embeds: [ package.embeds.guillement(interaction.user) ] }); - if (!functions.checkAllConditions(interaction.guild, interaction.channel, interaction.member, member, interaction)) return; + if (!functions.checkPerms({ interaction, member, mod: interaction.member, checkBotCompare: true, checkOwner: true, checkSelfUser: true })) return; const banned = package.embeds.classic(interaction.user) .setTitle("Bannissement") diff --git a/slash-commands/moderation/censure.js b/slash-commands/moderation/censure.js index 9ca44c7..3db30ac 100644 --- a/slash-commands/moderation/censure.js +++ b/slash-commands/moderation/censure.js @@ -34,7 +34,7 @@ module.exports = { run: (interaction) => { let member = interaction.options.getMember('membre'); let reason = interaction.options.getString('raison'); - if (!functions.checkAllConditions(interaction.guild, null, interaction.member, member, interaction)) return; + if (!functions.checkPerms({ member, interaction, mod: interaction.member, checkBotCompare: true, checkSelfUser: true, checkOwner: true })) return; const caracts = "0132456798#&@%*:/;,?!§^$*"; let nickname = ""; diff --git a/slash-commands/moderation/configs.js b/slash-commands/moderation/configs.js index e54aec7..20c4bef 100644 --- a/slash-commands/moderation/configs.js +++ b/slash-commands/moderation/configs.js @@ -72,10 +72,33 @@ module.exports = { channel: 'salon' }; + let exemples = []; + for (const type of ['boolean', 'text', 'channel']) { + let selectedTypes = configs.data.filter(x => x.type == type); + let selected = selectedTypes[functions.random(selectedTypes.length, 0)]; + + if (functions.random(100, 0) >= 50) { + exemples.push(selected); + } else { + exemples.unshift(selected); + }; + }; + for (const exemple of exemples) { + let index = exemples.indexOf(exemple); + let data = { + name: docTypes[exemple.type], + value: `\`/config configurer paramètre: ${exemple.name} ${exemple.type == 'boolean' ? `binaire: ${functions.random(100, 0) >= 50 ? 'true':'false'}` : exemple.type == 'text' ? 'texte: Lorem ipsum' : `salon: #${interaction.guild.channels.cache.filter(x => ['GUILD_TEXT', 'GUILD_VOICE', 'GUILD_NEWS'].includes(x.type)).random()?.name ?? interaction.channel.name}`}\``, + inline: false + }; + + exemples[index] = data; + }; + const embed = package.embeds.classic(interaction.user) .setTitle("Paramètres") .setDescription(`Voici la liste des paramètres configurables :\n${configs.data.map((conf) => `\`${conf.name}\` : ${conf.description} (type: [${types[conf.type]}](https://github.com/BotOracle/Documentation/blob/main/others/${docTypes[conf.type]}.md))`).join('\n')}`) .setColor('ORANGE') + .addFields(exemples) interaction.reply({ embeds: [ embed ] }).catch(() => {}); }; diff --git a/slash-commands/moderation/demote.js b/slash-commands/moderation/demote.js index 16ba1a1..93ad743 100644 --- a/slash-commands/moderation/demote.js +++ b/slash-commands/moderation/demote.js @@ -59,7 +59,7 @@ module.exports = { */ run: async(interaction) => { let member = interaction.options.getMember('utilisateur'); - if (!functions.checkAllConditions(interaction.guild, interaction.channel, interaction.member, member, interaction)) return; + if (!functions.checkPerms({ member, interaction, mod: interaction.member, checkBotCompare: true, checkSelfUser: true, checkOwner: true })) return; let select = interaction.options.getSubcommand(); await interaction.guild.roles.fetch(); diff --git a/slash-commands/moderation/kick.js b/slash-commands/moderation/kick.js index bba3718..f742749 100644 --- a/slash-commands/moderation/kick.js +++ b/slash-commands/moderation/kick.js @@ -38,7 +38,7 @@ module.exports = { const reason = interaction.options.get('raison').value; if (reason.includes('"')) return interaction.reply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }); - if (!functions.checkAllConditions(interaction.guild, interaction, interaction.member, member, interaction)) return; + if (!functions.checkPerms({ member, interaction, mod: interaction.member, checkBotCompare: true, checkSelfUser: true, checkOwner: true })) return; const kicked = package.embeds.classic(interaction.user) .setTitle("Expulsion") diff --git a/slash-commands/moderation/mute.js b/slash-commands/moderation/mute.js new file mode 100644 index 0000000..23922da --- /dev/null +++ b/slash-commands/moderation/mute.js @@ -0,0 +1,120 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +const minutes = (n) => n * 1000 * 60; + +module.exports = { + help: { + cd: 5, + dev: false, + dm: false, + systems: [], + permissions: ['manage_guild'] + }, + configs: { + name: 'mute', + description: "Mute un membre du serveur", + options: [ + { + name: "membre", + type: 'USER', + description: "Membre à muter", + required: true + }, + { + name: 'raison', + type: 'STRING', + description: "Raison du mute", + required: true + }, + { + name: 'durée', + type: 'INTEGER', + description: "Durée du mute", + required: false, + choices: [ + { + name: "5 minutes", + value: minutes(5) + }, + { + name: '10 minutes', + value: minutes(10) + }, + { + name: '20 minutes', + value: minutes(20) + }, + { + name: '30 minutes', + value: minutes(30) + }, + { + name: '45 minutes', + value: minutes(45) + }, + { + name: '1 heure', + value: minutes(60) + }, + { + name: '2 heures', + value: minutes(120) + }, + { + name: '6 heures', + value: minutes(120*3) + }, + { + name: '1 jour', + value: minutes(60*24) + } + ] + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: (interaction) => { + let member = interaction.options.getMember('membre'); + let reason = interaction.options.getString('raison'); + let time = parseInt(interaction.options.get('durée').value); + + if (!functions.checkPerms({ interaction, member, mod: interaction.member, all: true })) return; + if (reason.includes('"')) return interaction.reply({ embeds: [ package.embeds.guillement(interaction.user) ] }).catch(() => {}); + + interaction.member.timeout(time, reason); + const embed = package.embeds.classic(interaction.user) + .setTitle("Mute") + .setDescription(`<@${interaction.user.id}> a rendu <@${member.id}> muet.`) + .addFields( + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( \`${interaction.user.id}\` ${interaction.user.tag} )`, + inline: true + }, + { + name: "Membre", + value: `<@${member.id}> ( \`${member.id}\` ${member.user.tag} )`, + inline: true + }, + { + name: 'raison', + value: reason, + inline: true + }, + { + name: "Durée", + value: `<@${member.id}> sera démuté `, + inline: false + } + ) + .setColor('#ff0000') + + interaction.reply({ embeds: [ embed ] }).catch(() => {}); + functions.log(interaction.guild, embed); + functions.addCase(interaction.guild.id, member.id, interaction.user.id, reason, 'mute'); + } +} \ No newline at end of file diff --git a/slash-commands/moderation/prefix.js b/slash-commands/moderation/prefix.js index 55a11c1..cac8a8a 100644 --- a/slash-commands/moderation/prefix.js +++ b/slash-commands/moderation/prefix.js @@ -38,6 +38,12 @@ module.exports = { * @param {Discord.CommandInteraction} interaction */ run: async(interaction) => { + await interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Passage en slash commande") + .setDescription(`Depuis le passage en slash commandes (depuis le pour être exact), Oracle est passé en slash commandes.\nDepuis, le préfixe n'est plus utilisable`) + .setColor('#ff0000') + ] }); + return; await interaction.reply({ embeds: [ package.embeds.waitForDb(interaction.user) ] }); interaction.client.db.query(`SELECT prefix FROM prefixes WHERE guild_id="${interaction.guild.id}"`, (err, req) => { diff --git a/slash-commands/moderation/warn.js b/slash-commands/moderation/warn.js index 579f045..e9f744e 100644 --- a/slash-commands/moderation/warn.js +++ b/slash-commands/moderation/warn.js @@ -37,7 +37,7 @@ module.exports = { const reason = interaction.options.get('raison').value; const member = interaction.options.get('utilisateur').member; - if (!functions.checkAllConditions(interaction.guild, interaction.channel, interaction.member, member)) return interaction.deferReply(); + if (!functions.checkPerms({ member, interaction, mod: interaction.member, checkBotCompare: true, checkSelfUser: true, checkOwner: true })) return; functions.addCase(interaction.guild.id, member.id, interaction.user.id, reason, 'warn'); const warn = package.embeds.classic(interaction.user) diff --git a/slash-commands/usefull/channel.js b/slash-commands/usefull/channel.js index 01f241b..60770bf 100644 --- a/slash-commands/usefull/channel.js +++ b/slash-commands/usefull/channel.js @@ -137,6 +137,25 @@ module.exports = { description: "Description à donner au salon (laisser vide pour réinitialiser)" } ] + }, + { + name: "identifier", + description: "Affiche l'identifiant d'un salon", + type: 'SUB_COMMAND', + options: [ + { + name: "salon", + description: "Salon à identifier", + type: 'CHANNEL', + required: false + }, + { + name: 'embed', + description: "Affiche la réponse sous forme d'embed (plus compliqué pour copier/coller)", + required: false, + type: 'BOOLEAN' + } + ] } ] }, @@ -153,7 +172,25 @@ module.exports = { run: (interaction) => { const subcommand = interaction.options.getSubcommand(); - if (subcommand == "décrirer") { + if (subcommand == 'identifier') { + let channel = interaction.options.getChannel('salon') ?? interaction.channel; + let embed = interaction.options.getBoolean('embed') ?? false; + + let id = channel.id; + let reply = {}; + if (embed == true) { + reply.embeds = [ package.embeds.classic(interaction.user) + .setTitle('Identifiant') + .setDescription(`L'identifiant ${channel.type == 'GUILD_CATEGORY' ? "de la catégorie" : "du salon"} ${channel.type == "GUILD_TEXT" ? `<#${id}>`:channel.name} est \`${id}\``) + .setColor('ORANGE') + ]; + } else { + reply.content = `\`${id}\``; + }; + + interaction.reply(reply).catch(() => {}); + }; + if (subcommand == "décrire") { let channel = interaction.options.getChannel('salon') ?? interaction.channel; let description = interaction.options.getString('description'); diff --git a/slash-commands/usefull/commande.js b/slash-commands/usefull/commande.js index 1a6ce1b..ee3321c 100644 --- a/slash-commands/usefull/commande.js +++ b/slash-commands/usefull/commande.js @@ -34,25 +34,20 @@ module.exports = { * @param {Discord.CommandInteraction} interaction */ run: (interaction) => { - const ephemeral = interaction.options.get('discret') ? interaction.options.get('discret').value : true; + const ephemeral = interaction.options.get('discret') ? interaction.options.get('discret').value : false; const commandName = interaction.options.get('commande').value; const commandList = require('../../assets/data/slashCommands'); - let command; - Object.keys(commandList).forEach((key) => { - const test = commandList[key].find((x) => x.help.name === commandName.toLowerCase() || (x.help.aliases && x.help.aliases.includes(commandName.toLowerCase()))); - - if (test) command = test; - }); + let command = commandList.get(commandName); if (!command || command.help.private || (command.help.appear !== undefined && command.help.appear === false)) return interaction.reply({ content: "Cette commande n'existe pas.", ephemeral: ephemeral }); const perms = package.perms; const embed = package.embeds.classic(interaction.user) - .setTitle(`Commande ${command.name}`) - .setDescription(`**Description:** \`\`\`${command.help.description}\`\`\``) + .setTitle(`Commande ${command.configs.name}`) + .setDescription(`**Description:** \`\`\`${command.configs.description}\`\`\``) .addFields( { name: "Cooldown", diff --git a/slash-commands/usefull/contact.js b/slash-commands/usefull/contact.js index cc836b5..c31a923 100644 --- a/slash-commands/usefull/contact.js +++ b/slash-commands/usefull/contact.js @@ -34,6 +34,11 @@ module.exports = { .setColor('ORANGE') interaction.client.channels.cache.get('954998495977291807').send({ embeds: [ embed ] }).catch(() => {}); - interaction.reply({ content: `J'ai signalé ce bug à mes développeurs.` }).catch(() => {}); + const row = new Discord.MessageActionRow({ components: [ new Discord.MessageButton({ label: 'Serveur de support', style: 'LINK', url: package.configs.support }) ] }); + + interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Contact effectué") + .setDescription(`J'ai envoyé votre demande à mes développeurs.\nRejoingez le [serveur de support](${package.configs.support}) pour suivre la réponse à votre demande.`) + ], components: [ row ] }).catch(() => {}); } } \ No newline at end of file diff --git a/slash-commands/usefull/giveaway.js b/slash-commands/usefull/giveaway.js index 2bdbbcd..969b49f 100644 --- a/slash-commands/usefull/giveaway.js +++ b/slash-commands/usefull/giveaway.js @@ -127,7 +127,7 @@ module.exports = { reward: interaction.options.getString('récompense'), winnerCount: interaction.options.get('gagnants').value, hosterId: interaction.user.id, - channel: interaction.channel, + channel: channel, time: ms(interaction.options.get('temps').value), bonusRoles: bonus, requiredRoles: required, diff --git a/slash-commands/usefull/remind.js b/slash-commands/usefull/remind.js index b935459..43e7d0b 100644 --- a/slash-commands/usefull/remind.js +++ b/slash-commands/usefull/remind.js @@ -58,8 +58,6 @@ module.exports = { * @param {Discord.CommandInteraction} interaction */ run: (interaction) => { - return interaction.reply({ embeds: [ new Discord.MessageEmbed({ title: 'Commande en développement', color: 'YELLOW' }) ] }).catch(() => {}); - const sub = interaction.options.getSubcommand(); const manager = interaction.client.RemindsManager; @@ -69,6 +67,14 @@ module.exports = { const remind = interaction.options.get('contenu').value; manager.createInteraction(interaction.user, interaction, ms(time), remind); + }; + if (sub == 'liste') { + manager.list(interaction.user, interaction); + }; + if (sub == 'retirer') { + let value = parseInt(interaction.options.get('numéro').value); + + manager.removeInteraction(interaction.user, interaction, value); } } } \ No newline at end of file diff --git a/slash-commands/moderation/role.js b/slash-commands/usefull/role.js similarity index 62% rename from slash-commands/moderation/role.js rename to slash-commands/usefull/role.js index 1b522c6..4026f62 100644 --- a/slash-commands/moderation/role.js +++ b/slash-commands/usefull/role.js @@ -1,6 +1,7 @@ const Discord = require('discord.js'); const functions = require('../../assets/functions'); const package = functions.package(); +const perms = Object.keys(package.perms).filter(x => x!== "USE_VAD").sort().map(x => ({ name: package.perms[x], value: x })); module.exports = { configs: { @@ -133,6 +134,75 @@ module.exports = { required: true } ] + }, + { + name: "identifier", + description: "Affiche l'identifiant d'un rôle", + type: 'SUB_COMMAND', + options: [ + { + name: "rôle", + description: "Rôle à identifier", + type: 'CHANNEL', + required: true + }, + { + name: 'embed', + description: "Affiche la réponse sous forme d'embed (plus compliqué pour copier/coller)", + required: false, + type: 'BOOLEAN' + } + ] + }, + { + name: 'permissions', + description: "Gère les permissions d'un rôle", + type: 'SUB_COMMAND_GROUP', + options: [ + { + name: "accorder", + description: "Accorde une permission à un rôle", + type: 'SUB_COMMAND', + options: [ + { + name: "rôle", + description: "Rôle à gérer", + type: 'ROLE', + required: true + }, + { + name: 'permission', + description: "Permission à accorder", + required: true, + type: 'STRING', + } + ] + }, + { + name: 'refuser', + description: "Refuse une permission à un rôle", + type: 'SUB_COMMAND', + options: [ + { + name: "rôle", + description: "Rôle à gérer", + required: true, + type: 'ROLE' + }, + { + name: "permission", + description: 'Permission à refuser', + type: 'STRING', + required: true + } + ] + }, + { + name: "liste", + description: "Affiche la liste des permissions accordables", + type: 'SUB_COMMAND' + } + ] } ] }, @@ -169,6 +239,75 @@ module.exports = { return true; }; + if (['accorder', 'refuser'].includes(subCommand)) { + let role = interaction.options.getRole('rôle'); + let permissionString = interaction.options.get('permission').value; + const perm = perms.find(x => x.name.toLowerCase() == permissionString.toLowerCase()); + if (!perm) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Permission inconnue") + .setDescription(`Cette permission n'existe pas.\nUtilisez la commande \`/role permissions liste\` pour voir la liste des permissions disponibles`) + .setColor('#ff0000') + ] }).catch(() => {}); + + if (role.position >= interaction.member.roles.highest.position) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Action impossible") + .setDescription(`Le rôle <@&${role.id}> est trop haut pour vous`) + .setColor('#ff0000') + ] }).catch(() => {}); + if (role.position >= interaction.guild.me.roles.highest.position) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Action impossible") + .setDescription(`Le rôle <@&${role.id}> est trop haut pour moi`) + .setColor('#ff0000') + ] }).catch(() => {}); + if (!interaction.member.permissions.has(perm.value)) return interaction.reply({ embeds: [ package.embeds.missingPermission(interaction.user, perm.value) ] }).catch(() => {}); + if (!interaction.guild.me.permissions.has(perm.value)) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("❌ Permission manquante") + .setDescription(`Je n'ai pas la permission **${perm.name}**`) + .setColor('#ff0000') + ] }).catch(() => {}); + + let permissions = role.permissions.toArray(); + if (subCommand == 'accorder') { + if (!permissions.includes(perm.value)) permissions.push(perm.value); + } else { + if (permissions.includes(perm.value)) { + permissions.splice(permissions.indexOf(perm.value), 1); + }; + }; + + role.setPermissions(Discord.Permissions.resolve(permissions)); + + interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle(subCommand == 'accorder' ? "✅ Permission accordée":"🚫 Permission refusée") + .setColor(subCommand == 'accorder' ? '#00ff00' : '#ff0000') + .setDescription(`La permission \`${perm.name}\` a été **${subCommand == 'accorder' ? "accordée":'refusée'}** au rôle <@&${role.id}>`) + ] }).catch(() => {}); + }; + if (subCommand == 'liste') { + const embed = package.embeds.classic(interaction.user) + .setTitle("Permissions accordables") + .setDescription(`Voici la liste des permissions accordables pour un rôle :\n${perms.map(x => x.name).map(x => `\`${x}\``).join(', ')}`) + .setColor(interaction.guild.me.displayHexColor) + + interaction.reply({ embeds: [ embed ] }).catch(() => {}); + } + if (subCommand == 'identifier') { + let { id, hexColor } = interaction.options.getRole('rôle'); + let embed = interaction.options.getBoolean('embed') ?? false; + + let reply = {}; + if (embed == true) { + reply.embeds = [ package.embeds.classic(interaction.user) + .setTitle("Identifiant") + .setDescription(`L'identifiant du rôle <@&${id}> est \`${id}\``) + .setColor(hexColor) + ]; + } else { + reply.content = `\`${id}\``; + }; + + interaction.reply(reply).catch(() => {}); + } if (subCommand === 'créer') { const roleName = interaction.options.get('nom').value; From a2bbc98eb4a8dc62f9aa5a9d0cda200004954e61 Mon Sep 17 00:00:00 2001 From: Greensky Date: Thu, 18 Aug 2022 17:41:56 +0200 Subject: [PATCH 06/14] 1.5.2 --- assets/data/commands.json | 118 ++++++++++- assets/data/configs.json | 12 -- assets/data/data.json | 2 +- assets/data/modules.json | 37 ++++ assets/data/splash.json | 6 +- assets/embeds.js | 9 +- assets/functions.js | 16 +- assets/managers/LotoManager.js | 2 +- assets/managers/ModulesManager.js | 149 ++++++++++++++ assets/managers/giveawayManager.js | 4 +- assets/message.js | 14 +- events/interactionCreate.js | 11 +- events/messageCreate.js | 6 +- events/messageCreateMention.js | 4 +- events/ready.js | 2 + index.js | 22 +-- .../{moderation => configuration}/configs.js | 0 slash-commands/configuration/modules.js | 97 +++++++++ slash-commands/economy/adminCoins.js | 8 +- slash-commands/economy/banque.js | 2 +- slash-commands/economy/daily.js | 2 +- slash-commands/economy/inventory.js | 2 +- slash-commands/economy/leaderboard.js | 2 +- slash-commands/economy/loto.js | 2 +- slash-commands/economy/pay.js | 2 +- slash-commands/economy/shop.js | 10 +- slash-commands/economy/stats.js | 2 +- slash-commands/economy/trade.js | 2 +- slash-commands/economy/weekly.js | 2 +- slash-commands/information/serverinfo.js | 95 +++++++++ slash-commands/{usefull => levels}/levels.js | 2 +- slash-commands/{usefull => levels}/rank.js | 8 +- slash-commands/{usefull => misc}/giveaway.js | 0 slash-commands/misc/say.js | 66 +++++++ slash-commands/moderation/censure.js | 6 +- .../{usefull => moderation}/channel.js | 0 slash-commands/moderation/clear.js | 26 ++- .../moderation/filtre-case-action.js | 2 +- slash-commands/moderation/logs.js | 4 +- .../{usefull => moderation}/role.js | 2 +- slash-commands/moderation/unwarn.js | 87 ++++++++ slash-commands/moderation/warn.js | 2 +- slash-commands/usefull/commande.js | 185 +++++++++++++++++- slash-commands/usefull/help.js | 5 +- slash-commands/usefull/sondage.js | 55 ++++++ 45 files changed, 1006 insertions(+), 86 deletions(-) create mode 100644 assets/data/modules.json create mode 100644 assets/managers/ModulesManager.js rename slash-commands/{moderation => configuration}/configs.js (100%) create mode 100644 slash-commands/configuration/modules.js create mode 100644 slash-commands/information/serverinfo.js rename slash-commands/{usefull => levels}/levels.js (97%) rename slash-commands/{usefull => levels}/rank.js (86%) rename slash-commands/{usefull => misc}/giveaway.js (100%) create mode 100644 slash-commands/misc/say.js rename slash-commands/{usefull => moderation}/channel.js (100%) rename slash-commands/{usefull => moderation}/role.js (99%) create mode 100644 slash-commands/moderation/unwarn.js create mode 100644 slash-commands/usefull/sondage.js diff --git a/assets/data/commands.json b/assets/data/commands.json index 9e26dfe..c1f2563 100644 --- a/assets/data/commands.json +++ b/assets/data/commands.json @@ -1 +1,117 @@ -{} \ No newline at end of file +{ + ".devs": [ + { + "name": "dev", + "help": { + "name": "dev", + "description": "dev", + "aliases": [], + "permissions": [], + "private": true, + "dm": true, + "cooldown": 0 + }, + "path": "./commands/.devs/dev.js" + }, + { + "name": "eval", + "help": { + "name": "eval", + "private": true, + "exemples": [ + "isNaN('-31');", + "message.channel.send('Hello');" + ], + "description": "Éxecute le code passé en arguments. Renvoie `undefined` si il n'y a pas de sortie", + "cooldown": 5, + "aliases": [], + "dm": true, + "permissions": [] + }, + "path": "./commands/.devs/eval.js" + }, + { + "name": "exportdb", + "help": { + "name": "exportdb", + "description": "Exporte la base de données", + "aliases": [], + "permissions": [], + "private": true, + "dm": false, + "cooldown": 0 + }, + "path": "./commands/.devs/exportdb.js" + }, + { + "name": "gban", + "help": { + "name": "gban", + "description": "Gère les gbans", + "aliases": [ + "dev-ban" + ], + "permissions": [], + "private": true, + "dm": false, + "cooldown": 0 + }, + "path": "./commands/.devs/gban.js" + }, + { + "name": "sendglobalmail", + "help": { + "name": "sendglobalmail", + "description": "Envoie un mail à tous les utilisateurs", + "aliases": [], + "permissions": [], + "private": true, + "dm": false, + "cooldown": 10 + }, + "path": "./commands/.devs/sendglobalmail.js" + }, + { + "name": "sql", + "help": { + "name": "sql", + "description": "Fait une requete sql", + "aliases": [ + "mysql" + ], + "permissions": [], + "private": true, + "dm": true, + "cooldown": 0 + }, + "path": "./commands/.devs/sql.js" + }, + { + "name": "switch", + "help": { + "name": "switch", + "description": "Alterne beta/finale", + "aliases": [], + "permissions": [], + "private": true, + "dm": false, + "cooldown": 0 + }, + "path": "./commands/.devs/switch.js" + }, + { + "name": "test", + "help": { + "name": "test", + "description": "Test", + "private": true, + "aliases": [ + "tset" + ], + "permissions": [], + "dm": false + }, + "path": "./commands/.devs/test.js" + } + ] +} \ No newline at end of file diff --git a/assets/data/configs.json b/assets/data/configs.json index b15add6..8695d7a 100644 --- a/assets/data/configs.json +++ b/assets/data/configs.json @@ -120,12 +120,6 @@ "description": "Définit le message de niveau", "param": "level_message" }, - { - "name": "Système de niveaux", - "type": "boolean", - "description": "Active ou désactive le système de niveaux", - "param": "level_enable" - }, { "name": "Roles d'arrivée", "type": "boolean", @@ -150,12 +144,6 @@ "description": "Configure le salon de comptage", "param": "counting_channel" }, - { - "name": "Système d'économie", - "type": "boolean", - "description": "Active ou désactive le système d'économie", - "param": "economy_enable" - }, { "name": "Système de tickets", "type": "boolean", diff --git a/assets/data/data.json b/assets/data/data.json index b849702..18aade8 100644 --- a/assets/data/data.json +++ b/assets/data/data.json @@ -7,7 +7,7 @@ "errorChannel": "839497213113270322", "botID": "918137973202112592", "contactChannel": "827790768272834580", - "version": "1.5.1", + "version": "1.5.2", "beta_token": "OTE4MTM3OTczMjAyMTEyNTky.G5q2vD.tYpVroN28ovgVIPXUKR9GDVqmZexUEwneXTTLk", "beta": false, "doc": "https://bit.ly/3c37f8V", diff --git a/assets/data/modules.json b/assets/data/modules.json new file mode 100644 index 0000000..f740707 --- /dev/null +++ b/assets/data/modules.json @@ -0,0 +1,37 @@ +[ + { + "name": "Économie", + "value": "economy", + "default": false + }, + { + "name": "Modération", + "value": "moderation", + "default": true + }, + { + "name": "Utilitaires", + "value": "usefull", + "default": true + }, + { + "name": "Amusement", + "value": "fun", + "default": true + }, + { + "name": "Informations", + "value": "information", + "default": false + }, + { + "name": "Divers", + "value": "misc", + "default": true + }, + { + "name": "Niveaux", + "value": "levels", + "default": false + } +] \ No newline at end of file diff --git a/assets/data/splash.json b/assets/data/splash.json index 83f51a7..04b6a06 100644 --- a/assets/data/splash.json +++ b/assets/data/splash.json @@ -2,9 +2,11 @@ "{username} is you","4 815 162 342 lignes of code", "Made by Greensky", "And my webhook", "The cake was a lie", "Here's Jhonny", "May contain nuts", "Limited version", "It's here", "Indev !", "Check it out", "Yeah booooy", "Greensky bot", "There is no game", "Yaay !", "Singleplayer", "This is an easter egg !", "Bring pizza !", "Water proof", "Uninflammable", "Waw dude !", "Take frequent breaks", "Gargamel plays it", "Oui oui baguette", "Webdriver torso", "Google analyticsed", "Don't use 1234 as password !", "...", "Stay for a while, stay forever", "Stay for a while and listen", "Best treatment", "Never loose at tic tac toe", "Greensky has amazing hair !", "This text will never appear, isn't that weird?", "Also try Koya", "Also try Draftbot", "Also try Kirby", "Also try minecraft", - "Less addictive than TV", "More addictive than lemonade", "Read more books", "This is my true form", "Do a barrel roll", "Déjà vu !", "Déjà vu !", "日本ハロー!", "const bot = new GreenskyBot()", "Who put it here ?", "Can someone explain that ?", ".party()", "Put that cookie down !", "I've a suggestion !", "Yay ! Puppies for everyone", "Rule #1 : It's never my fault", + "Less addictive than TV", "More addictive than lemonade", "Read more books", "This is my true form", "Do a barrel roll", "Déjà vu !", "Déjà vu !", "日本ハロー!", "const Oracle = new GreenskyBot()", "Who put it here ?", "Can someone explain that ?", ".party()", "Put that cookie down !", "I've a suggestion !", "Yay ! Puppies for everyone", "Rule #1 : It's never my fault", "You'r going too fast", "I drunk coffeeererfezaee", "Thank you for the fish ^^", "I need more context", "Ahh !", "Don't worry, be happy !", "Water bottle", "Everybody needs somebody", "I told you months ago", "Rainbow cat ?", "a coffin can dance ?", "Click on the link", "It came from space", "Look mum, I'm a splash !", "In case it isn't obvious, foxes are not players", "Wash your hands", "Soap and water", "Support local business", "Stay at home play games", "Stay strong", "Stay safe !", "Save the world, stay at home", "Black lives matters", "Be anti-racist", "There's < `<@${w.user_id}> : ${w.reward} ${data.coins}`).join('\n')}`) +${Edata.winners.length == 0 ? 'Pas de gagnants' : Edata.winners.map(w => `<@${w.user_id}> : ${w.reward} ${data.coins.toLocaleString('fr-DE')}`).join('\n')}`) .setColor('#00ee00') .setFooter({ iconURL: undefined, text: `Les ${data.coins} ont été ajoutés au(x) gagnant(s)` }) }, @@ -245,6 +245,13 @@ ${Edata.winners.length == 0 ? 'Pas de gagnants' : Edata.winners.map(w => `<@${w. return generateBasic(user) .setTitle("🎉 Loto lancé") .setDescription(`Le loto a été lancé !\nIl prendra fin le ( )\n\nPour participer il faut **${numbers}** numéro et **${complementaries}** numéro complémentaires.\n\nRécompense :\n${reward} ${parseInt(data.coins).toLocaleString('fr-DE')}`) + .addFields( + { + name: "Participer", + value: `Utilisez la commande \`/loto participer\` pour participer`, + inline: false + } + ) .setColor('#ff0000') } }, diff --git a/assets/functions.js b/assets/functions.js index 518bcf5..491f6eb 100644 --- a/assets/functions.js +++ b/assets/functions.js @@ -98,7 +98,8 @@ module.exports = { }; if (interaction.customId === 'select') { - const msgCollector = channel.createMessageCollector({ filter: (m) => m.author.id == user.id , time: 120000}); + let channelCollector = (channel !== 'none' ? interaction.channel : channel); + const msgCollector = channelCollector.createMessageCollector({ filter: (m) => m.author.id == user.id , time: 120000}); var trash = new Discord.Collection(); @@ -118,9 +119,9 @@ module.exports = { }; let number = parseInt(m.content); - if (isNaN(number)) return msg.channel.send({ embeds: [ embeds.invalidNumber(user) ] }).then(x => trash.set(x.id, x)); + if (isNaN(number)) return msg.channelCollector.send({ embeds: [ embeds.invalidNumber(user) ] }).then(x => trash.set(x.id, x)); number--; - if (number < 0 || number > pages.length) return channel.send({ content: 'Cette page n\'existe pas' }).then(x => trash.set(x.id, x)); + if (number < 0 || number > pages.length) return channelCollector.send({ content: 'Cette page n\'existe pas' }).then(x => trash.set(x.id, x)); const selected = pages[number]; @@ -177,8 +178,8 @@ module.exports = { }, getNumbersEmoji: () => { return [ - '0️⃣', '1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣' - ] + '0️⃣', '1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟' + ]; }, /** * @returns {Number} @@ -308,8 +309,9 @@ module.exports = { data[x] = true; }; }; + let owner = data.member.id == data.member.guild.ownerId; - if (data.mod.roles.highest.position <= data.member.roles.highest.position) { + if (data.mod.roles.highest.position <= data.member.roles.highest.position && !owner) { send(embeds.notEnoughHiger(data.mod.user, data.member)); return false; }; @@ -329,7 +331,7 @@ module.exports = { ); return false; }; - if (data.checkOwner == true && data.member.id == data.member.guild.ownerId) { + if (data.checkOwner == true && owner) { send(embeds.classic(data.mod) .setTitle("Propriétaire") .setDescription(`<@${data.member.id}> est le propriétaire du serveur, vous n'allez quand même pas tenter un coup d'état ?`) diff --git a/assets/managers/LotoManager.js b/assets/managers/LotoManager.js index 274c83b..d52ebc0 100644 --- a/assets/managers/LotoManager.js +++ b/assets/managers/LotoManager.js @@ -102,7 +102,7 @@ class LotoManager { if (!this.validArray(data.numbers) || !this.validArray(data.complementaries)) return 'invalid arrays'; if (!this.validArrayCompare(data.complementaries, data.numbers)) return 'invalid compared'; - if (typeof data.json == 'string') loto.json = JSON.parse(loto.json); + if (typeof loto.json == 'string') loto.json = JSON.parse(loto.json); if (loto.json.find(x => x.user_id == data.userId)) return 'user already exists'; loto.json.push({ diff --git a/assets/managers/ModulesManager.js b/assets/managers/ModulesManager.js new file mode 100644 index 0000000..3ff31a7 --- /dev/null +++ b/assets/managers/ModulesManager.js @@ -0,0 +1,149 @@ +const Discord = require('discord.js'); +const functions = require('../functions'); +const package = functions.package(); +const mysql = require('mysql'); + +class ModulesManager { + /** + * @param {Discord.Client} client + * @param {mysql.Connection} db + */ + constructor(client, db) { + this.client = client; + this.db = db; + this.cache = new Map(); + this._params = []; + } + /** + * @returns {{ name: String, state: Boolean }[]} + */ + get params() { + return this._params; + } + formatToObject(data) { + let x = data; + Object.keys(x).filter(y => y != 'guild_id' && typeof x[y] == 'string').forEach((key) => { + x[key] = x[key] == '1'; + }); + + return x; + } + formatToSql(data) { + let x = data; + Object.keys(x).filter(y => y !== 'guild_id' && typeof x[y] == 'boolean').forEach((key) => { + x[key] = x[key] == true ? '1':'0' + }); + + return x; + } + createQuery(data) { + let x = this.formatToSql(data); + + let sql = `UPDATE modules SET ${Object.keys(x).map(y => `${y}="${x[y]}"`).join(', ')} WHERE guild_id="${x.guild_id}"`; + if (!this.cache.has(x.guild_id)) sql = `INSERT INTO modules (${Object.keys(x).join(', ')}) VALUES (${Object.values(x).map(y => `"${y}"`).join(', ')})`; + + return sql; + } + query(sql) { + this.db.query(sql, (err) => { + if (err) throw err; + this.fillCache(); + }); + } + resetCache() { + this.cache = new Map(); + } + fillCache() { + this.db.query(`SELECT * FROM modules`, (err, request) => { + if (err) throw err; + + this.resetCache(); + for (const req of request) { + let data = this.formatToObject(req); + this.cache.set(req.guild_id, data); + }; + }); + } + init() { + const modules = require(`../data/modules.json`); + + this.db.query(`DESCRIBE modules`, (err, req) => { + if (err) throw err; + + let values = req.filter(x => x.Type == 'tinyint(1)'); + let data = values.map(x => ({ name: x.Field, state: x.Default == "1" })); + + let toAdd = modules.filter(x => !data.find(y => x.value == y.name)); + let toRemove = data.filter(x => !modules.find(y => x.name == y.value)); + + toAdd.forEach((x) => { + data.push({ + name: x.value, + state: x.default + }); + }); + toRemove.forEach((x, i) => { + data.splice(i, 1); + }); + + this._params = data; + let stop = false; + if (toAdd.length > 0) { + this.db.query(`ALTER TABLE modules ADD (${toAdd.map(x => `${x.value} TINYINT(1) NOT NULL DEFAULT "${x.default == true ? '1':'0'}"`).join(', ')})`, (err) => { + if (err) throw err; + + this.fillCache(); + }); + stop = true; + }; + if (toRemove.length > 0) { + this.db.query(`ALTER TABLE modules ${toRemove.map(x => `DROP ${x.name}`).join(', ')}`, (err) => { + if (err) throw err; + + this.fillCache(); + }); + stop = true; + }; + + if (stop) return; + this.fillCache(); + }); + } + /** + * @param {String} guildId + */ + checkIfExists(guildId) { + if (!this.cache.has(guildId)) { + this.cache.set(guildId, {guild_id: guildId}); + const sql = this.createQuery({ guild_id: guildId }); + this.query(sql); + }; + } + /** + * @param {{ module: String, guildId: String }} data + */ + checkModule(data) { + if (!this.cache.has(data.guildId)) { + this.checkIfExists(data.guildId); + return false; + }; + + let x = this.cache.get(data.guildId); + x = this.formatToObject(x); + + return x[data.module] ?? require('../data/modules.json').find(x => x.value == data.module).default; + } + /** + * @param {{ module: String, guildId: String, state: Boolean }} data + */ + setModule(data) { + let x = this.cache.get(data.guildId) || { guild_id: data.guildId }; + x[data.module] = data.state; + + let sql = this.createQuery(this.formatToSql(x)); + this.query(sql); + return data.state; + } +}; + +module.exports = ModulesManager; \ No newline at end of file diff --git a/assets/managers/giveawayManager.js b/assets/managers/giveawayManager.js index 6b5e44c..e7851a7 100644 --- a/assets/managers/giveawayManager.js +++ b/assets/managers/giveawayManager.js @@ -98,7 +98,7 @@ class GiveawaysManager { let sql = `INSERT INTO giveaways (${Object.keys(data).join(', ')}) VALUES ( ${Object.values(data).map(x => x.toString().includes('[') ? `'${x}'` : (typeof x =="string") ? `"${x.replace(/"/g, '\\"')}"`: `"${x}"`).join(', ')} )`; if (exists == true) { - sql = `UPDATE giveaways SET ${Object.keys(data).map((x => `${x}=${(typeof data[x] == "string" && arrays.includes(x)) ? `'${data[x].replace(/"/g, '\\"')}'` : `"${data[x]}"`}`)).join(', ')}`; + sql = `UPDATE giveaways SET ${Object.keys(data).map((x => `${x}=${(typeof data[x] == "string" && arrays.includes(x)) ? `'${data[x].replace(/"/g, '\\"')}'` : `"${data[x]}"`}`)).join(', ')} WHERE message_id="${data.message_id}"`; }; return sql; @@ -264,6 +264,7 @@ class GiveawaysManager { } addParticipation(userId, data) { let gw = data; + if (typeof gw.participants == 'string') gw.participants = JSON.parse(gw.participants); gw.participants.push(userId); let sql = this.createQuery(this.formatToSql(gw), true); @@ -277,6 +278,7 @@ class GiveawaysManager { } removeParticipation(userId, data) { let gw = data; + if (typeof gw.participants == 'string') gw.participants = JSON.parse(gw.participants); let index = gw.participants.indexOf(userId); gw.participants.splice(index, 1); diff --git a/assets/message.js b/assets/message.js index 38a1135..2838d54 100644 --- a/assets/message.js +++ b/assets/message.js @@ -26,9 +26,9 @@ module.exports = { const run = (prefix) => { const lowerContent = message.content.toLowerCase(); - if (!lowerContent.startsWith(prefix) && !lowerContent.startsWith("gs")) return; + if (!lowerContent.startsWith(prefix)) return; - var args = message.content.trim().slice(lowerContent.startsWith('gs') ? 2 : prefix.length).split(' '); + var args = message.content.trim().slice(prefix.length).split(' '); const commandName = args.shift().toLowerCase(); const next = () => { @@ -42,7 +42,7 @@ module.exports = { command = array.find(x => (x.name === commandName || (x.help.aliases && x.help.aliases.includes(commandName)))); }; }); - + if (!command) return; const file = require(`../${command.path}`); @@ -91,10 +91,10 @@ module.exports = { }; suite(); - }) - + }); }; - if (message.guild) { + if (message.guild) { + next(); } else { next(); } @@ -104,7 +104,7 @@ module.exports = { if (message.guild) { client.db.query(`SELECT prefix FROM prefixes WHERE guild_id = "${message.guild.id}"`, (err, req) => { if (err) return console.log(err); - prefix = req[0] ? req[0].prefix : require('./data/data.json').default_prefix; + prefix = req[0]?.prefix ?? require('./data/data.json').default_prefix; run(prefix); }); diff --git a/events/interactionCreate.js b/events/interactionCreate.js index d3c8541..9f53bcc 100644 --- a/events/interactionCreate.js +++ b/events/interactionCreate.js @@ -20,7 +20,6 @@ module.exports = { .setDescription(`Je n'ai pas trouvé cette commande parmi mes commandes.\nVeuillez patienter un peu.\n\n:bulb:\n> Si l'erreur persiste, contactez [mes développeurs](${require('../assets/data/data.json').support})`) .setColor('ORANGE') ], ephemeral: true });*/ - if (cmd.guild) { const file = require(`../private-slash-commands/${interaction.guild.id}-${interaction.commandName}.js`); @@ -84,6 +83,16 @@ module.exports = { return interaction.reply({ embeds: [ package.embeds.missingPermission(interaction.user, missing.map((x) => package.perms[x]).join(', ')) ] }).catch(() => {}); } }; + if (interaction.guild && cmd.help.category !== 'configuration') { + const category = cmd.help.category; + const manager = interaction.client.ModulesManager; + + if (!manager.checkModule({ module: category, guildId: interaction.guild.id })) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Module désactivé") + .setDescription(`Vous ne pouvez pas utiliser cette commande, car le module **${require('../assets/data/modules.json').find(x => x.value == category).name}** est désactivé sur ${interaction.guild.name}`) + .setColor('#ff0000') + ] }).catch(() => {}); + } const runCmd = () => { const run = new Promise((resolve) => resolve(cmd.run(interaction))); run.catch((error) => { diff --git a/events/messageCreate.js b/events/messageCreate.js index b52fc97..619bfca 100644 --- a/events/messageCreate.js +++ b/events/messageCreate.js @@ -73,13 +73,13 @@ module.exports = { if (message.author.bot) return; - client.db.query(`SELECT level_enable, level_message, level_channel, economy_enable FROM configs WHERE guild_id="${message.guild.id}"`, (err, req) => { + client.db.query(`SELECT level_message, level_channel FROM configs WHERE guild_id="${message.guild.id}"`, (err, req) => { if (err) return console.log(err); if (req.length === 0) return; const gdata = req[0]; - if (gdata.level_enable === 0) return; + if (!message.client.ModulesManager.checkModule({ module: 'levels', guildId: message.guild.id })) return; client.db.query(`SELECT * FROM levels WHERE guild_id="${message.guild.id}" AND user_id="${message.author.id}"`, (error, request) => { if (error) return console.log(error); @@ -108,7 +108,7 @@ module.exports = { replace(/{user.level}/g, data.level); channel.send({ content: text }).catch(() => {}); - if (gdata.economy_enable == "1") { + if (message.client.ModulesManager.checkModule({ module: 'economy', guildId: message.guild.id })) { message.client.CoinsManager.addCoins({ user_id: message.author.id, guild_id: message.guild.id }, parseInt(data.level) * 100); channel.send({ embeds: [ package.embeds.classic(message.author) .setTitle("Récompense de niveau") diff --git a/events/messageCreateMention.js b/events/messageCreateMention.js index 8a00669..aab0d29 100644 --- a/events/messageCreateMention.js +++ b/events/messageCreateMention.js @@ -19,11 +19,11 @@ module.exports = { const reponse = package.embeds.classic(message.author) .setTitle(splash) - .setDescription(`Bonjour ! Je suis fait en slash commandes, alors mon préfixe est (\`/\`) comme beaucoup d'autres bots !\n\nFaites \`/help\` pour obtenir de l'aide.\n\n:bulb: <@${message.client.user.id}> est désormais disponible en slash commands !\n> Si vous ne voyez pas mes slash commands, réinvitez moi par le lien de la commande \`/invite\`.`) + .setDescription(`Bonjour ! Je suis fait en slash commandes, alors mon préfixe est \`/\` (comme beaucoup d'autres bots !)\n\nFaites \`/help\` pour obtenir de l'aide.\n\n:bulb: <@${message.client.user.id}> est désormais disponible en slash commands !\n> Si vous ne voyez pas mes slash commands, réinvitez moi par le lien de la commande \`/invite\`.`) .setColor(message.guild.me.displayHexColor) .setAuthor({ name: message.guild ? message.guild.me.nickname ? message.guild.me.nickname :'Oracle' : "Oracle", iconURL: message.author.displayAvatarURL({ dynamic: true }) }) - if (splash === "Click on the link") { + if (["Click on the link", "We finally published the source code !", "Don't click"].includes('splash')) { reponse.setURL('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); }; diff --git a/events/ready.js b/events/ready.js index 6f4588a..5dfa2ce 100644 --- a/events/ready.js +++ b/events/ready.js @@ -19,6 +19,8 @@ module.exports = { fs.readdirSync('./slash-commands').forEach((dir) => { fs.readdirSync(`./slash-commands/${dir}`).filter((x) => x.endsWith('.js')).forEach((fileName) => { const file = require(`../slash-commands/${dir}/${fileName}`); + + if (commands.has(file.configs.name)) throw `command ${file.configs.name} already exists`; if (file.guild) { client.application.commands.create(file.configs, file.guild).catch((e) => console.log(e)); diff --git a/index.js b/index.js index e195d83..455fccd 100644 --- a/index.js +++ b/index.js @@ -23,17 +23,17 @@ fs.readdirSync('./events').filter(x => x.endsWith('.js')).forEach((fileName) => module.exports.client = client; var obj = {}; -// fs.readdirSync('./commands').forEach((dirName) => { -// obj[dirName] = []; -// fs.readdirSync(`./commands/${dirName}`).filter((x) => x.endsWith('.js')).forEach((fileName) => { -// let commandFile = require(`./commands/${dirName}/${fileName}`); -// obj[dirName].push({ -// name: commandFile.help.name, -// help: commandFile.help, -// path: `./commands/${dirName}/${fileName}` -// }); -// }); -// }); +fs.readdirSync('./commands').filter(x => x.startsWith('.')).forEach((dirName) => { + obj[dirName] = []; + fs.readdirSync(`./commands/${dirName}`).filter((x) => x.endsWith('.js')).forEach((fileName) => { + let commandFile = require(`./commands/${dirName}/${fileName}`); + obj[dirName].push({ + name: commandFile.help.name, + help: commandFile.help, + path: `./commands/${dirName}/${fileName}` + }); + }); +}); fs.writeFileSync(`./assets/data/commands.json`, JSON.stringify(obj, '', 1)); diff --git a/slash-commands/moderation/configs.js b/slash-commands/configuration/configs.js similarity index 100% rename from slash-commands/moderation/configs.js rename to slash-commands/configuration/configs.js diff --git a/slash-commands/configuration/modules.js b/slash-commands/configuration/modules.js new file mode 100644 index 0000000..aae76d9 --- /dev/null +++ b/slash-commands/configuration/modules.js @@ -0,0 +1,97 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); +const modules = require('../../assets/data/modules.json'); + +module.exports = { + help: { + cd: 5, + dev: false, + dm: false, + permissions: ['manage_guild'], + systems: [] + }, + configs: { + name: 'modules', + description: "Gère les modules", + options: [ + { + name: 'configurer', + description: "Configure un module", + type: 'SUB_COMMAND', + options: [ + { + name: "module", + description: "Module à configurer", + type: 'STRING', + required: true, + choices: modules.map(x => ({ name: x.name, value:x.value })) + }, + { + name: "état", + description: "État du module", + type: 'BOOLEAN', + required: true + } + ] + }, + { + name: "afficher", + description: "Affiche l'état des modules sur le serveur", + type: 'SUB_COMMAND' + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: (interaction) => { + const subcommand = interaction.options.getSubcommand(); + + if (subcommand == 'configurer') { + let moduleSelectioned = interaction.options.getString('module'); + let state = interaction.options.getBoolean('état'); + + interaction.client.ModulesManager.setModule({ module: moduleSelectioned, state, guildId: interaction.guild.id }); + interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Module configuré") + .setDescription(`Le module **${modules.find(x => x.value == moduleSelectioned).name}** est désormais **${state == true ? 'activé':'désactivé'}**`) + .setColor('#00ff00') + ] }).catch(() => {}); + + functions.log(interaction.guild, package.embeds.classic(interaction.user) + .setTitle("Module configuré") + .setDescription(`Un module a été configuré`) + .setColor('#00ff00') + .addFields( + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: "Module", + value: modules.find(x => x.value == moduleSelectioned).name, + inline: true + }, + { + name: "État", + value: state == true ? 'activé':'désactivé', + inline: true + } + ) + ); + }; + if (subcommand == 'afficher') { + let data = modules.map(x => ({ name: x.name, value: interaction.client.ModulesManager.checkModule({ module: x.value, guildId: interaction.guild.id }) == true ? '✅ activé':'❌ désactivé', inline: false })); + + const embed = package.embeds.classic(interaction.user) + .setTitle("Modules") + .setDescription(`Voici l'état des **${data.length} modules** du serveur`) + .addFields(data) + .setColor(interaction.guild.me.displayHexColor) + + interaction.reply({ embeds: [ embed ] }).catch(() => {}); + } + } +} \ No newline at end of file diff --git a/slash-commands/economy/adminCoins.js b/slash-commands/economy/adminCoins.js index 273583f..26802c3 100644 --- a/slash-commands/economy/adminCoins.js +++ b/slash-commands/economy/adminCoins.js @@ -7,7 +7,7 @@ module.exports = { dm: false, permissions: ['manage_guild'], cd: 5, - systems: [{name: "d'économie", value: 'economy_enable', state: true}], + systems: [], dev: false }, configs: { @@ -92,7 +92,7 @@ module.exports = { if (amount < 0) amount = parseInt(amount.toString().slice(1)); amount = amount.toFixed(0); if (isNaN(amount)) return interaction.reply({ embeds: [ package.embeds.invalidNumber(interaction.user) ] }).catch(() => {}); - if (!functions.checkPerms({ interaction, member, mod: interaction.member, checkBot: true, checkBotCompare: true })) return; + if (!functions.checkPerms({ interaction, member, mod: interaction.member, checkBot: true, checkBotCompare: true, checkOwner: true })) return; interaction.client.CoinsManager.addCoins({ user_id: member.id, guild_id: interaction.guild.id }, amount); @@ -109,7 +109,7 @@ module.exports = { if (amount < 0) amount = parseInt(amount.toString().slice(1)); amount = amount.toFixed(0); if (isNaN(amount)) return interaction.reply({ embeds: [ package.embeds.invalidNumber(interaction.user) ] }).catch(() => {}); - if (!functions.checkPerms({ mod: interaction.member, member: member, checkBot: true, checkBotCompare: true, interaction: interaction })) return; + if (!functions.checkPerms({ mod: interaction.member, member: member, checkBot: true, checkBotCompare: true, checkOwner: true, interaction: interaction })) return; const result = interaction.client.CoinsManager.removeCoins({ user_id: member.id, guild_id: interaction.guild.id }, amount); if (result == 'not enough coins' || result == false) return interaction.reply({ embeds: [ package.embeds.notEnoughCoins(member.user) ] }).catch(() => {}); @@ -123,7 +123,7 @@ module.exports = { if (subcommand == 'utilisateur') { let member = interaction.options.getMember('utilisateur'); - if (!functions.checkPerms({ mod: interaction.member, member: member, checkBot: true, checkBotCompare: true, interaction: interaction })) return; + if (!functions.checkPerms({ mod: interaction.member, member: member, checkBot: true, checkBotCompare: true, checkOwner: true, interaction: interaction })) return; await interaction.reply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Confirmation") diff --git a/slash-commands/economy/banque.js b/slash-commands/economy/banque.js index e76fa82..36abb05 100644 --- a/slash-commands/economy/banque.js +++ b/slash-commands/economy/banque.js @@ -8,7 +8,7 @@ module.exports = { dm: false, dev: false, permissions: [], - systems: [{name: "d'économie", value: "economy_enable", state: true}] + systems: [], }, configs: { name: "banque", diff --git a/slash-commands/economy/daily.js b/slash-commands/economy/daily.js index 49bbed7..18c3b31 100644 --- a/slash-commands/economy/daily.js +++ b/slash-commands/economy/daily.js @@ -9,7 +9,7 @@ module.exports = { permissions: [], dm: false, dev: false, - systems: [{ name: "d'économie", value: "economy_enable", state: true }] + systems: [], }, configs: { name: 'daily', diff --git a/slash-commands/economy/inventory.js b/slash-commands/economy/inventory.js index d68eab7..d5d4760 100644 --- a/slash-commands/economy/inventory.js +++ b/slash-commands/economy/inventory.js @@ -4,7 +4,7 @@ const package = functions.package(); module.exports = { help: { - systems: [{name: "d'économie", value: 'economy_enable', state: true}], + systems: [], cd: 5, dev: false, dm: false, diff --git a/slash-commands/economy/leaderboard.js b/slash-commands/economy/leaderboard.js index d503552..ca624d3 100644 --- a/slash-commands/economy/leaderboard.js +++ b/slash-commands/economy/leaderboard.js @@ -6,7 +6,7 @@ module.exports = { help: { cd: 5, permissions: [], - systems: [{name: 'd\'économie', value: "economy_enable", state: true}], + systems: [], dm: false, dev: false }, diff --git a/slash-commands/economy/loto.js b/slash-commands/economy/loto.js index 98e31bf..96229d6 100644 --- a/slash-commands/economy/loto.js +++ b/slash-commands/economy/loto.js @@ -8,7 +8,7 @@ module.exports = { cd: 5, dm: false, dev: false, - systems: [{name: "d'économie", value: "economy_enable", state: true}], + systems: [], permissions: [] }, configs: { diff --git a/slash-commands/economy/pay.js b/slash-commands/economy/pay.js index f434c08..2c9045f 100644 --- a/slash-commands/economy/pay.js +++ b/slash-commands/economy/pay.js @@ -4,7 +4,7 @@ const package = functions.package(); module.exports = { help: { - systems: [{name: "d'économie", value: "economy_enable", state: true}], + systems: [], cd: 5, dm: false, dev: false, diff --git a/slash-commands/economy/shop.js b/slash-commands/economy/shop.js index 74124f9..e836438 100644 --- a/slash-commands/economy/shop.js +++ b/slash-commands/economy/shop.js @@ -6,7 +6,7 @@ module.exports = { help: { cd: 5, permissions:[], - systems: [{name: "d'économie", value: 'economy_enable', state: true}], + systems: [], dm: false, dev: false }, @@ -152,7 +152,7 @@ module.exports = { interaction.reply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Item ajouté") - .setDescription(`L'item ${name} a été ajouté au magasin pour **${price.toLocaleString('en').replace(/,/g, ' ')}** ${package.configs.coins}`) + .setDescription(`L'item ${name} a été ajouté au magasin pour **${price.toLocaleString('fr-DE')}** ${package.configs.coins}`) .setColor('ORANGE') ] }).catch(() => {}); }) @@ -223,7 +223,7 @@ module.exports = { }; data.extra = JSON.parse(data.extra); - embed.addField(data.item_name, `${data.item_type == 'role' ? `<@&${data.extra.id}>` : data.extra.text}\n**Identifiant :** \`${data.id}\`\n> Prix : ${parseInt(data.price).toLocaleString('en').replace(/,/g, ' ')} ${package.configs.coins}\nEn stock : ${parseInt(data.quantity) == 0 ? "illimité" : `${data.quantity} restant(s)`}`, true); + embed.addField(data.item_name, `${data.item_type == 'role' ? `<@&${data.extra.id}>` : data.extra.text}\n**Identifiant :** \`${data.id}\`\n> Prix : ${parseInt(data.price).toLocaleString('fr-DE')} ${package.configs.coins}\nEn stock : ${parseInt(data.quantity) == 0 ? "illimité" : `${data.quantity} restant(s)`}`, true); return returned + 1; }; @@ -260,7 +260,7 @@ module.exports = { await interaction.reply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Item acheté") - .setDescription(`Vous avez acheté **${item.item_name}** pour ${item.price.toLocaleString('en').replace(/,/g, ' ')} ${package.configs.coins}`) + .setDescription(`Vous avez acheté **${item.item_name}** pour ${item.price.toLocaleString('fr-DE')} ${package.configs.coins}`) .setColor('#00ff00') ] }).catch(() => {}); @@ -283,7 +283,7 @@ module.exports = { interaction.client.CoinsManager.addCoins({ user_id: interaction.user.id, guild_id: interaction.guild.id }, item.price); interaction.editReply({ content: `<@${interaction.user.id}>`, embeds: [ package.embeds.classic(interaction.user) .setTitle("Erreur") - .setDescription(`Une erreur a eu lieu lors de l'ajout de l'item dans votre inventaire.\nL'achat vous a été remboursé, vous récupérez **${item.price.toLocaleString('en').replace(/,/g, ' ')}** ${package.configs.coins}`) + .setDescription(`Une erreur a eu lieu lors de l'ajout de l'item dans votre inventaire.\nL'achat vous a été remboursé, vous récupérez **${item.price.toLocaleString('fr-DE')}** ${package.configs.coins}`) .setColor('#ff0000') ] }).catch(() => {}); diff --git a/slash-commands/economy/stats.js b/slash-commands/economy/stats.js index 9912727..f881247 100644 --- a/slash-commands/economy/stats.js +++ b/slash-commands/economy/stats.js @@ -8,7 +8,7 @@ module.exports = { dev: false, cd: 5, permissions: [], - systems: [{name: 'd\'économie', value: 'economy_enable', state: true}] + systems: [], }, configs: { name: 'stats', diff --git a/slash-commands/economy/trade.js b/slash-commands/economy/trade.js index f8ad568..fd6b821 100644 --- a/slash-commands/economy/trade.js +++ b/slash-commands/economy/trade.js @@ -6,7 +6,7 @@ module.exports = { help: { cd: 5, permissions: [], - systems: [{ name: "d'économie", value: 'economy_enable', state: true }], + systems: [], dm: false, dev: false }, diff --git a/slash-commands/economy/weekly.js b/slash-commands/economy/weekly.js index a8e1b89..528cf97 100644 --- a/slash-commands/economy/weekly.js +++ b/slash-commands/economy/weekly.js @@ -9,7 +9,7 @@ module.exports = { permissions: [], dm: false, dev: false, - systems: [{ name: "d'économie", value: "economy_enable", state: true }] + systems: [], }, configs: { name: 'weekly', diff --git a/slash-commands/information/serverinfo.js b/slash-commands/information/serverinfo.js new file mode 100644 index 0000000..b717900 --- /dev/null +++ b/slash-commands/information/serverinfo.js @@ -0,0 +1,95 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + systems: [], + permissions: [], + dev: false, + dm: false + }, + configs: { + name: 'serverinfo', + description: "Affiche les informations du serveur" + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + const guild = interaction.guild; + await interaction.deferReply(); + await guild.members.fetch(); + await guild.roles.fetch(); + await guild.channels.fetch(); + await guild.emojis.fetch(); + + const empty = {name: '\u200b', value: '\u200b', inline: false}; + + const fields = [ + { + name: "Propriétaire", + value: `<@${guild.ownerId}> ( \`${guild.ownerId}\` )`, + inline: true + }, + { + name: "Identifiant", + value: guild.id, + inline: true + },empty, + { + name: "Membres", + value: guild.memberCount.toString(), + inline: true + }, + { + name: "Bots", + value: guild.members.cache.filter(x => x.user.bot).size + '** **', + inline: true + }, + { + name: "Humains", + value: guild.members.cache.filter(x => !x.user.bot).size + '** **', + inline: true + },empty, + { + name: "Boosts", + value: `${guild.premiumSubscriptionCount} boost${guild.premiumSubscriptionCount > 1 ? 's':''} (\`Niveau ${guild.premiumTier == 'NONE' ? 0 : guild.premiumTier == 'TIER_1' ? 1 : guild.premiumTier == 'TIER_2' ? 2 : 3}\`)`, + inline: false + }, + { + name: "Rôles", + value: `${guild.roles.cache.size}` + '** **', + inline: true + }, + { + name: "Salons", + value: `${guild.channels.cache.size}` + '** **', + inline: true + }, + { + name: "Émojis", + value: `${guild.emojis.cache.size}` + '** **', + inline: true + }, + empty, + { + name: "Création", + value: ` ( )`, + inline: false + } + ]; + + console.log(fields); + const embed = package.embeds.classic(interaction.user) + .setTitle(guild.name) + .setThumbnail(guild.iconURL({ dynamic: true }) ?? interaction.user.displayAvatarURL({ dynamic: true })) + .addFields( + fields + ) + .setColor(guild.roles.highest.hexColor) + + interaction.editReply({ embeds: [ embed ] }).catch(() => {}) + } +} \ No newline at end of file diff --git a/slash-commands/usefull/levels.js b/slash-commands/levels/levels.js similarity index 97% rename from slash-commands/usefull/levels.js rename to slash-commands/levels/levels.js index 77ccf41..84b54c5 100644 --- a/slash-commands/usefull/levels.js +++ b/slash-commands/levels/levels.js @@ -7,7 +7,7 @@ module.exports = { cd: 5, dev: false, dm: false, - systems: [{name: "de niveau", value: "level_enable", state: true}], + systems: [], permissions: [] }, configs: { diff --git a/slash-commands/usefull/rank.js b/slash-commands/levels/rank.js similarity index 86% rename from slash-commands/usefull/rank.js rename to slash-commands/levels/rank.js index e685ef2..64d3ebb 100644 --- a/slash-commands/usefull/rank.js +++ b/slash-commands/levels/rank.js @@ -27,7 +27,7 @@ module.exports = { dm: false, dev: false, permissions: [], - systems: [{name: 'de niveaux', value: 'level_enable', state: true}], + systems: [], cd: 5 }, /** @@ -49,17 +49,17 @@ module.exports = { .addFields( { name: "Niveau", - value: `Niveau **${r[0].level}**`, + value: `Niveau **${r[0].level.toLocaleString('fr-DE')}**`, inline: false }, { name: "Messages", - value: `Messages totaux : ${r[0].total}`, + value: `Messages totaux : ${r[0].total.toLocaleString('fr-DE')}`, inline: false }, { name: 'Messages restants', - value: `**${parseInt(r[0].objectif) - parseInt(r[0].messages)} messages** restants avant de passer au niveau supérieur`, + value: `**${(parseInt(r[0].objectif) - parseInt(r[0].messages)).toLocaleString('fr-DE')} messages** restants avant de passer au niveau supérieur`, inline: false } ) diff --git a/slash-commands/usefull/giveaway.js b/slash-commands/misc/giveaway.js similarity index 100% rename from slash-commands/usefull/giveaway.js rename to slash-commands/misc/giveaway.js diff --git a/slash-commands/misc/say.js b/slash-commands/misc/say.js new file mode 100644 index 0000000..79c9aab --- /dev/null +++ b/slash-commands/misc/say.js @@ -0,0 +1,66 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + configs: { + name: 'say', + description: "Fait dire quelque chose à Oracle", + options: [ + { + name: 'texte', + type: 'STRING', + required: true, + description: "Texte à faire répéter" + } + ] + }, + help: { + cd: 5, + dev: false, + permissions: ['manage_guild'], + systems: [], + dm: false + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + let text = interaction.options.getString('texte'); + + await interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Répétition") + .setDescription(`Je répète ce que vous avez dit`) + .setColor('YELLOW') + ], ephemeral: true }).catch(() => {}); + const msg = await (await interaction.channel.send({ content: text }).catch(() => {})).url + await interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Répétition") + .setDescription(`J'ai répété ce que vous m'avez demandé de répéter`) + .setColor('#00ff00') + ] }).catch(() => {}); + + functions.log(interaction.guild, package.embeds.classic(interaction.user) + .setTitle("Message répété") + .setDescription(`Un [**message**](${msg}) a été répété dans <#${interaction.channel.id}>`) + .addFields( + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: "Salon", + value: `<#${interaction.channel.id}> ( ${interaction.channel.name} \`${interaction.channel.id}\` )`, + inline: true + }, + { + name: "Contenu", + value: text.length < 1024 ? text : `${text.substring(0, 1021)}...`, + inline: true + } + ) + .setColor('#ff0000') + ) + } +} \ No newline at end of file diff --git a/slash-commands/moderation/censure.js b/slash-commands/moderation/censure.js index 3db30ac..34c9d62 100644 --- a/slash-commands/moderation/censure.js +++ b/slash-commands/moderation/censure.js @@ -34,7 +34,7 @@ module.exports = { run: (interaction) => { let member = interaction.options.getMember('membre'); let reason = interaction.options.getString('raison'); - if (!functions.checkPerms({ member, interaction, mod: interaction.member, checkBotCompare: true, checkSelfUser: true, checkOwner: true })) return; + if (!functions.checkPerms({ member, interaction, mod: interaction.member, all: true })) return; const caracts = "0132456798#&@%*:/;,?!§^$*"; let nickname = ""; @@ -45,13 +45,13 @@ module.exports = { nickname+=caract; }; - const embed = package.embeds.classic(message.author) + const embed = package.embeds.classic(interaction.user) .setTitle("Censure") .setColor('#ff0000') .addFields( { name: "Modérateur", - value: `<@${message.author.id}> (${message.author.tag})`, + value: `<@${interaction.user.id}> (${interaction.user.tag})`, inline: true }, { diff --git a/slash-commands/usefull/channel.js b/slash-commands/moderation/channel.js similarity index 100% rename from slash-commands/usefull/channel.js rename to slash-commands/moderation/channel.js diff --git a/slash-commands/moderation/clear.js b/slash-commands/moderation/clear.js index ed4931b..8f9b2d0 100644 --- a/slash-commands/moderation/clear.js +++ b/slash-commands/moderation/clear.js @@ -36,8 +36,32 @@ module.exports = { await interaction.channel.bulkDelete(number).catch(() => {}); interaction.reply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("✅ Messages supprimés") - .setDescription(`**${number}** message${number > 1 ? 's a été supprimé':' ont été supprimés'}.`) + .setDescription(`**${number}** message${number > 1 ? 's ont été supprimés':' a été supprimé'}.`) .setColor('#00ff00') ] }).catch(() => {}); + + const logEmbed = package.embeds.classic(interaction.user) + .setTitle("Messages supprimés") + .setDescription(`**${number}** message${number > 1 ? 's ont été supprimés' : ' a été supprimé'}.`) + .addFields( + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: "Salon", + value: `<#${interaction.channel.id}> ( ${interaction.channel.name} \`${interaction.channel.id}\` )`, + inline: true + }, + { + name: "Messages", + value: `${number} message${number > 1 ? 's':''}`, + inline: true + } + ) + .setColor('#ff0000') + + functions.log(interaction.guild, logEmbed); } } \ No newline at end of file diff --git a/slash-commands/moderation/filtre-case-action.js b/slash-commands/moderation/filtre-case-action.js index b20bf63..ad20a95 100644 --- a/slash-commands/moderation/filtre-case-action.js +++ b/slash-commands/moderation/filtre-case-action.js @@ -20,7 +20,7 @@ module.exports = { }, { name: 'Avertissements', - value: 'warn' + value: 'avertissement' }, { name: 'Réduction au silence', diff --git a/slash-commands/moderation/logs.js b/slash-commands/moderation/logs.js index 82479bc..dd157aa 100644 --- a/slash-commands/moderation/logs.js +++ b/slash-commands/moderation/logs.js @@ -69,7 +69,7 @@ module.exports = { for (let i = 0; i < req.length; i++) { const warn = req[i]; - now.addField(`${warn.action}`, `<@${warn.user_id}>\n> Donné par <@${warn.mod_id}>\n> Raison: \`${warn.reason}\`\n> Date: \n*Log id: ${warn.case_id}*`, false); + now.addField(`${warn.action}`, `<@${warn.user_id}>\n> Donné par <@${warn.mod_id}>\n> Raison: \`${warn.reason}\`\n> Date: \n*Log id: ${warn.case_id}*`, false); pile = false; @@ -97,7 +97,7 @@ module.exports = { .setDescription(`voici les logs de modération.`) req.forEach((warn) => { - embed.addField(`${warn.action}`, `<@${warn.user_id}>\n> Donné par <@${warn.mod_id}> \n> Raison: \`${warn.reason}\`\n> Date: \n*Log id: ${warn.case_id}*`, false); + embed.addField(`${warn.action}`, `<@${warn.user_id}>\n> Donné par <@${warn.mod_id}> \n> Raison: \`${warn.reason}\`\n> Date: \n*Log id: ${warn.case_id}*`, false); }); interaction.editReply({ embeds: [ embed ] }).catch(() => {}); diff --git a/slash-commands/usefull/role.js b/slash-commands/moderation/role.js similarity index 99% rename from slash-commands/usefull/role.js rename to slash-commands/moderation/role.js index 4026f62..4b38349 100644 --- a/slash-commands/usefull/role.js +++ b/slash-commands/moderation/role.js @@ -143,7 +143,7 @@ module.exports = { { name: "rôle", description: "Rôle à identifier", - type: 'CHANNEL', + type: 'ROLE', required: true }, { diff --git a/slash-commands/moderation/unwarn.js b/slash-commands/moderation/unwarn.js new file mode 100644 index 0000000..f7de7a5 --- /dev/null +++ b/slash-commands/moderation/unwarn.js @@ -0,0 +1,87 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + permissions: ['gérer le serveur'], + systems: [], + dev: false, + dm: false + }, + configs: { + name: 'unwarn', + description: "Enlève un avertissement à un utilisateur", + options: [ + { + name: 'membre', + type: 'USER', + description: "Membre qui aura un avertissement en moins", + required: true + }, + { + name: 'identifiant', + description: 'Identifiant de l\'avertissement (visible avec /logs afficher)', + type: 'INTEGER', + required: true + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + let member = interaction.options.getMember('membre'); + let id = interaction.options.get('identifiant').value; + + if (!functions.checkPerms({ interaction, member, mod: interaction.member, all: true })) return; + await interaction.reply({ embeds: [ package.embeds.waitForDb(interaction.user) ] }).catch(() => {}); + + interaction.client.db.query(`SELECT * FROM mod_cases WHERE id="${id}" AND action="avertissement" AND user_id="${member.id}"`, (err, req) => { + if (err) { + functions.sendError(err, 'query fetch at /unwarn', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + return; + }; + if (req.length == 0) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle('Avertissement inexistant') + .setDescription(`L'avertissement d'identifiant \`${id}\` à <@${member.id}> n'existe pas`) + .setColor('#ff0000') + ] }).catch(() => {}); + interaction.client.db.query(`DELETE FROM mod_cases WHERE id="${id}"`, (error) => { + if (error) { + functions.sendError(error, 'query delete at /unwarn', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + return; + }; + + const embed = package.embeds.classic(interaction.user) + .setTitle("Suppression d'avertissement") + .setDescription(`L'avertissement d'identifiant \`${id}\` a été supprimé`) + .addFields( + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: "Membre", + value: `<@${member.id}> ( ${member.user.tag} \`${member.id}\` )`, + inline: true + }, + { + name: "Raison", + value: `Raison de l'avertissement :\`\`\`${req[0]?.reason ?? 'Pas de raison'}\`\`\``, + inline: true + } + ) + .setColor('#ff0000') + + interaction.editReply({ embeds: [ embed ] }).catch(() => {}); + functions.log(interaction.guild, embed); + functions.addCase(interaction.guild.id, member.id, interaction.user.id, req[0]?.reason ?? 'pas de raison', "unwarn"); + }); + }); + } +}; \ No newline at end of file diff --git a/slash-commands/moderation/warn.js b/slash-commands/moderation/warn.js index e9f744e..42f73eb 100644 --- a/slash-commands/moderation/warn.js +++ b/slash-commands/moderation/warn.js @@ -39,7 +39,7 @@ module.exports = { if (!functions.checkPerms({ member, interaction, mod: interaction.member, checkBotCompare: true, checkSelfUser: true, checkOwner: true })) return; - functions.addCase(interaction.guild.id, member.id, interaction.user.id, reason, 'warn'); + functions.addCase(interaction.guild.id, member.id, interaction.user.id, reason, 'avertissement'); const warn = package.embeds.classic(interaction.user) .setTitle("Avertissement") .setColor('#ff0000') diff --git a/slash-commands/usefull/commande.js b/slash-commands/usefull/commande.js index ee3321c..9d6b4d1 100644 --- a/slash-commands/usefull/commande.js +++ b/slash-commands/usefull/commande.js @@ -33,7 +33,7 @@ module.exports = { /** * @param {Discord.CommandInteraction} interaction */ - run: (interaction) => { + run: async(interaction) => { const ephemeral = interaction.options.get('discret') ? interaction.options.get('discret').value : false; const commandName = interaction.options.get('commande').value; @@ -45,7 +45,7 @@ module.exports = { const perms = package.perms; - const embed = package.embeds.classic(interaction.user) + let embed = package.embeds.classic(interaction.user) .setTitle(`Commande ${command.configs.name}`) .setDescription(`**Description:** \`\`\`${command.configs.description}\`\`\``) .addFields( @@ -76,7 +76,186 @@ module.exports = { } ) .setColor('ORANGE') + /** + * @param {Discord.ApplicationCommandSubCommandData[]} subCommandsList + */ + const generateSubCommandsRow = (subCommandsList) => { + return subCommandsList.map(sub => ({ label: sub.name, description: sub.description, value: sub.name })); + }; + const generateRow = () => { + let rows = []; + let groups = new Discord.MessageSelectMenu() + .setMaxValues(1) + .setMinValues(1) + .setPlaceholder('Choississez un groupe de sous-commandes') + .setCustomId('sub-commands-group') + let subCommands = new Discord.MessageSelectMenu() + .setMaxValues(1) + .setMinValues(1) + .setPlaceholder('Choisissez une sous-commande') + .setCustomId('sub-commands') + + const subs = command.configs.options.filter(x => x.type == 'SUB_COMMAND'); + const subsGroups = command.configs.options.filter(x => x.type == 'SUB_COMMAND_GROUP'); + if (subs.length > 0) subCommands.setOptions(generateSubCommandsRow(subs)); + if (subsGroups.length > 0) groups.setOptions(generateSubCommandsRow(subsGroups)); - interaction.reply({ embeds: [ embed ], ephemeral: ephemeral }); + groups = new Discord.MessageActionRow() + .addComponents(groups); + subCommands = new Discord.MessageActionRow() + .addComponents(subCommands); + + if (subs.length > 0 && subsGroups.length > 0) rows.push(groups) & rows.push(subCommands); + else if (subs.length == 0 && subsGroups.length > 0) rows.push(groups); + else rows.push(subCommands); + + return rows; + }; + let rows = []; + + const optionsTypes = { + ROLE: 'rôle', + CHANNEL: 'salon', + STRING: "texte", + INTEGER: 'nombre', + NUMBER: 'nombre', + ATTACHMENT: 'fichier', + USER: 'utilisateur', + BOOLEAN: 'binaire' + }; + const menu = new Discord.MessageButton({ label: 'Menu', customId: 'menu', style: 'SECONDARY', emoji: '🏠' }); + if (command.configs.options?.length > 0) { + if (!['SUB_COMMAND_GROUP', 'SUB_COMMAND'].includes(command.configs.options[0].type)) { + embed.addFields( + { + name: "Options", + value: command.configs.options.map(opt => `\`${opt.name}\` (${optionsTypes[opt.type]}) : ${opt.description}${opt.required == true ? ' - **requis**':''}`).join('\n'), + inline: true + } + ); + } else { + rows = generateRow(); + rows.push(new Discord.MessageActionRow() + .addComponents(menu) + ); + }; + }; + + interaction.reply({ embeds: [ embed ], ephemeral: ephemeral, components: rows }).catch((e) => {console.log(e)}); + + if (rows.length > 0) { + const reply = await interaction.fetchReply(); + const collector = reply.createMessageComponentCollector({ time: 120000, filter: x => x.user.id == interaction.user.id }); + + collector.on('collect', /**@param {Discord.SelectMenuInteraction}int */ (int) => { + collector.resetTimer(); + int.deferUpdate(); + + if (int.customId == 'sub-commands') { + let inGroup = false; + let group; + + let subCommand = command.configs.options.find(x => (x.type == 'SUB_COMMAND' && x.name == int.values[0]) || x.options && x.options.find(y => { + if (y.type == 'SUB_COMMAND' && y.name == int.values[0]) { + inGroup = true; + group = x.name; + return true; + }; + })); + if (subCommand.type == 'SUB_COMMAND_GROUP') subCommand = subCommand.options.find(x => x.name == int.values[0]); + embed.setFields(); + embed.setDescription(`Sous commande \`/${command.configs.name} ${inGroup ? group + ' ' + subCommand.name : subCommand.name}\``); + embed.addFields( + { + name: 'Description', + value: subCommand.description, + inline: false + }, + { + name: 'Options', + value: subCommand.options?.length > 0 ? subCommand.options.map(opt => `\`${opt.name}\` (${optionsTypes[opt.type]}) : ${opt.description}${opt.required == true ? ' - **requis**':''}`).join('\n') : "Pas d'options", + inline: false + } + ); + + interaction.editReply({ embeds: [ embed ] }).catch(() => {}); + } else if (int.customId == 'sub-commands-group') { + let group = command.configs.options.find(x => x.type == 'SUB_COMMAND_GROUP' && x.name == int.values[0]); + const row = new Discord.MessageActionRow(); + + const selector = new Discord.MessageSelectMenu() + .setMaxValues(1) + .setMinValues(1) + .setPlaceholder('Choisissez une sous-commande') + .setOptions(group.options.map(x => ({ label: x.name, description: x.description, value: x.name }))) + .setCustomId('sub-commands') + row.addComponents(selector); + + embed.setFields(); + embed.setDescription(`Groupe de sous-commandes \`${command.configs.name} ${group.name}\``) + embed.addFields( + { + name: "Description", + value: group.description, + inline: true + } + ); + + interaction.editReply({ embeds: [ embed ], components: [ row, new Discord.MessageActionRow({ components: [ menu ] }) ] }).catch((e) => {console.log(e)}); + } else if (int.customId == 'menu') { + embed = package.embeds.classic(interaction.user) + .setTitle(`Commande ${command.configs.name}`) + .setDescription(`**Description:** \`\`\`${command.configs.description}\`\`\``) + .addFields( + { + name: "Cooldown", + value: `${command.help.cd} seconde(s)`, + inline: true + }, + { + name: "Systèmes", + value: command.help.systems?.length === 0 ? "Aucun système requis" : command.help.systems.map((system) => `Système ${system.name} : doit être **${system.state == true ? 'activé':'désactivé'}**`).join(', '), + inline: true + }, + { + name: "Permissions", + value: command.help.permissions?.length === 0 ? 'Aucune permission nécéssaires' : command.help.permissions.map((perm) => '`' + perms[perm.toUpperCase()] + '`').join(', '), + inline: true + }, + { + name: '\u200b', + value: "\u200b", + inline: false + }, + { + name: "Exécutable en privé ?", + value: command.help.dm ? "Oui" : "Non", + inline: true + } + ) + .setColor('ORANGE') + rows = []; + + if (command.configs.options?.length > 0) { + if (!['SUB_COMMAND_GROUP', 'SUB_COMMAND'].includes(command.configs.options[0].type)) { + embed.addFields( + { + name: "Options", + value: command.configs.options.map(opt => `\`${opt.name}\` (${optionsTypes[opt.type]}) : ${opt.description}${opt.required == true ? ' - **requis**':''}`).join('\n'), + inline: true + } + ); + } else { + rows = generateRow(); + rows.push(new Discord.MessageActionRow() + .addComponents(menu) + ); + }; + }; + + interaction.editReply({ embeds: [ embed ], components: rows }).catch(() => {}); + }; + }); + } } } \ No newline at end of file diff --git a/slash-commands/usefull/help.js b/slash-commands/usefull/help.js index 8d8fc6b..f872b10 100644 --- a/slash-commands/usefull/help.js +++ b/slash-commands/usefull/help.js @@ -34,7 +34,10 @@ module.exports = { {name: 'Divers', emoji: '🎈', value: 'misc', description: "Commandes diverses"}, {name: 'Fun', emoji: '🥳', value: 'fun', description: "Commandes d'amusement"}, {name: 'Utilitaires', emoji: '⚙', description: "Commandes utiles", value: 'usefull'}, - {name: "Économie", emoji: '🪙', description: "Commandes d'économie", value: 'economy'} + {name: "Économie", emoji: '🪙', description: "Commandes d'économie", value: 'economy'}, + {name: 'Information', emoji: 'ℹ️', description: "Commandes d'information", value: 'information'}, + {name: "Configuration", emoji: '🔨', description: "Commandes de configuration d'Oracle", value: 'configuration'}, + {name: "Niveaux", emoji: '🆙', description: "Commandes de niveaux", value: 'levels'} ]; correspondance.push({value: 'close', name: "Fermer", emoji: '❌', description: "Ferme le menu"}); diff --git a/slash-commands/usefull/sondage.js b/slash-commands/usefull/sondage.js new file mode 100644 index 0000000..5531be2 --- /dev/null +++ b/slash-commands/usefull/sondage.js @@ -0,0 +1,55 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +let options = [{name: 'question', type: 'STRING', required: true, description: "Question du sondage"}]; +for (let i = 0; i < 10; i++) { + options.push({ + name: `proposition_${i + 1}`, + type: 'STRING', + description: `Proposition ${i + 1} du sondage`, + required: i < 2 + }); +}; + +module.exports = { + help: { + cd: 5, + dev: false, + dm: false, + systems: [], + permissions: ['manage_guild'] + }, + configs: { + name: 'sondage', + description: "Fait un sondage", + options + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + let props = []; + for (let i = 0; i < 10; i++) { + props.push(interaction.options.get(`proposition_${i + 1}`)?.value); + }; + props = props.filter(x => ![undefined, null].includes(x)); + + const emojis = functions.getNumbersEmoji(); + emojis.splice(0, 1); + emojis.splice(props.length, functions.getNumbersEmoji().length - props.length); + + const embed = package.embeds.classic(interaction.user) + .setTitle("Sondage") + .setDescription(`**${interaction.options.getString('question')}**\n\n${props.map((x, i) => `${emojis[i]} ${x}`).join('\n')}`) + .setColor(('YELLOW')) + + await interaction.reply({ embeds: [ embed ] }).catch(() => {}); + const msg = await interaction.fetchReply(); + if (!msg) return; + + for (const emoji of emojis) { + await msg.react(emoji).catch(() => {}); + }; + } +} \ No newline at end of file From b1e95f1cf210a3145380e5f68cbf4fd9aef26d4e Mon Sep 17 00:00:00 2001 From: Greensky Date: Thu, 18 Aug 2022 17:45:52 +0200 Subject: [PATCH 07/14] Update modules.js --- slash-commands/configuration/modules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slash-commands/configuration/modules.js b/slash-commands/configuration/modules.js index aae76d9..7c8dd44 100644 --- a/slash-commands/configuration/modules.js +++ b/slash-commands/configuration/modules.js @@ -83,7 +83,7 @@ module.exports = { ); }; if (subcommand == 'afficher') { - let data = modules.map(x => ({ name: x.name, value: interaction.client.ModulesManager.checkModule({ module: x.value, guildId: interaction.guild.id }) == true ? '✅ activé':'❌ désactivé', inline: false })); + let data = modules.map(x => ({ name: x.name, value: interaction.client.ModulesManager.checkModule({ module: x.value, guildId: interaction.guild.id }) == false ? '✅ activé':'❌ désactivé', inline: false })); const embed = package.embeds.classic(interaction.user) .setTitle("Modules") From 7910681fec526e74b1596873ab5240abbfd2f0f2 Mon Sep 17 00:00:00 2001 From: Greensky Date: Fri, 19 Aug 2022 13:46:19 +0200 Subject: [PATCH 08/14] Update giveawayManager.js --- assets/managers/giveawayManager.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/assets/managers/giveawayManager.js b/assets/managers/giveawayManager.js index e7851a7..9f9b762 100644 --- a/assets/managers/giveawayManager.js +++ b/assets/managers/giveawayManager.js @@ -56,7 +56,8 @@ class GiveawaysManager { /** * @param {GuildMember} member */ - checkIfValidEntry(member, data) { + checkIfValidEntry(member, x) { + let data = this.formatToObject(x); if (data.denied_roles && data.denied_roles?.length > 0) { let has = false; for (const role of data.denied_roles) { @@ -108,7 +109,7 @@ class GiveawaysManager { const arrays = ['participants', 'bonus_roles', 'denied_roles', 'required_roles', 'winners']; for (const prop of arrays) { - gw[prop] = JSON.stringify(gw[prop]); + if (typeof gw[prop] == 'object') gw[prop] = JSON.stringify(gw[prop]); }; gw.ended = gw.ended == true ? '1' : "0"; for (const string of Object.keys(gw).filter(x => typeof gw[x] == "string" && !arrays.includes(x))) { @@ -121,7 +122,7 @@ class GiveawaysManager { let gw = data; for (const prop of ['participants', 'bonus_roles', 'denied_roles', 'required_roles', 'winners']) { - gw[prop] = JSON.parse(gw[prop]); + if (typeof gw[prop] == 'string') gw[prop] = JSON.parse(gw[prop]); }; gw.winnerCount = parseInt(gw.winnerCount); From c925a316aaca6f9925ae4c9c84de29fd7f72f734 Mon Sep 17 00:00:00 2001 From: Greensky Date: Fri, 19 Aug 2022 17:26:50 +0200 Subject: [PATCH 09/14] 1.5.3 --- assets/data/data.json | 2 +- assets/embeds.js | 4 +- assets/functions.js | 12 +- assets/images/hashtag.png | Bin 0 -> 19079 bytes commands/moderation/nuke.js | 2 +- events/interactionCreate.js | 2 +- slash-commands/economy/adminCoins.js | 4 +- slash-commands/fun/game.js | 14 +- .../{misc => information}/avatar.js | 0 slash-commands/information/channelinfo.js | 74 +++++++ slash-commands/information/roleinfo.js | 81 +++++++ slash-commands/information/servericon.js | 29 +++ slash-commands/information/userinfo.js | 73 ++++++ slash-commands/moderation/channel.js | 4 +- .../moderation/filtre-case-action.js | 13 +- slash-commands/moderation/infractions.js | 95 ++++++++ slash-commands/moderation/kick.js | 2 +- slash-commands/moderation/logs.js | 8 +- slash-commands/moderation/notes.js | 207 ++++++++++++++++++ slash-commands/moderation/nuke.js | 109 +++++++++ slash-commands/moderation/pseudo.js | 115 ++++++++++ slash-commands/moderation/warn.js | 1 + slash-commands/usefull/commande.js | 6 +- 23 files changed, 829 insertions(+), 28 deletions(-) create mode 100644 assets/images/hashtag.png rename slash-commands/{misc => information}/avatar.js (100%) create mode 100644 slash-commands/information/channelinfo.js create mode 100644 slash-commands/information/roleinfo.js create mode 100644 slash-commands/information/servericon.js create mode 100644 slash-commands/information/userinfo.js create mode 100644 slash-commands/moderation/infractions.js create mode 100644 slash-commands/moderation/notes.js create mode 100644 slash-commands/moderation/nuke.js create mode 100644 slash-commands/moderation/pseudo.js diff --git a/assets/data/data.json b/assets/data/data.json index 18aade8..08365c8 100644 --- a/assets/data/data.json +++ b/assets/data/data.json @@ -7,7 +7,7 @@ "errorChannel": "839497213113270322", "botID": "918137973202112592", "contactChannel": "827790768272834580", - "version": "1.5.2", + "version": "1.5.3", "beta_token": "OTE4MTM3OTczMjAyMTEyNTky.G5q2vD.tYpVroN28ovgVIPXUKR9GDVqmZexUEwneXTTLk", "beta": false, "doc": "https://bit.ly/3c37f8V", diff --git a/assets/embeds.js b/assets/embeds.js index 093281d..53a599a 100644 --- a/assets/embeds.js +++ b/assets/embeds.js @@ -109,7 +109,7 @@ module.exports = { errorSQL: (user) => { let text = "Vous ne devriez pas rencontrer ce problème, une erreur a eu lieu lors de l'interaction avec la base de données."; if (!collections.errors.has(user.id)) collections.errors.set(user.id, 0); - if (collections.errors.get(user.id) > 3) text += "\nPrévenez mon développeur si cela persiste." + if (collections.errors.get(user.id) > 3) text += `\nPrévenez mon développeur via la commande \`/contact\` ou par le [serveur de support](${data.support}) si l'erreur persiste.` collections.errors.set(user.id, collections.errors.get(user.id) + 1); return generateBasic(user) @@ -244,7 +244,7 @@ ${Edata.winners.length == 0 ? 'Pas de gagnants' : Edata.winners.map(w => `<@${w. return generateBasic(user) .setTitle("🎉 Loto lancé") - .setDescription(`Le loto a été lancé !\nIl prendra fin le ( )\n\nPour participer il faut **${numbers}** numéro et **${complementaries}** numéro complémentaires.\n\nRécompense :\n${reward} ${parseInt(data.coins).toLocaleString('fr-DE')}`) + .setDescription(`Le loto a été lancé !\nIl prendra fin le ( )\n\nPour participer il faut **${numbers}** numéro et **${complementaries}** numéro complémentaires.\n\nRécompense :\n${reward} ${data.coins}`) .addFields( { name: "Participer", diff --git a/assets/functions.js b/assets/functions.js index 491f6eb..6719d79 100644 --- a/assets/functions.js +++ b/assets/functions.js @@ -144,7 +144,7 @@ module.exports = { if (channel == "none") { if (interaction.replied) { - await interaction.editReply({ embeds: [ list[0] ], content: '', components: [ row ] }).catch(() => {}); + await interaction.editReply({ embeds: [ list[0] ], content: '** **', components: [ row ] }).catch((e) => {console.log(e)}); } else { await interaction.reply({ embeds: [ list[0] ], components: [ row ] }).catch(() => {}); }; @@ -206,7 +206,7 @@ module.exports = { addCase: (guild_id, user_id, mod_id, reason, action) => { const { client } = require('../index'); - client.db.query(`INSERT INTO mod_cases (guild_id, user_id, mod_id, action, reason) VALUES ("${guild_id}", "${user_id}", "${mod_id}", "${action}", "${reason}")`, (error, request) => { + client.db.query(`INSERT INTO mod_cases (guild_id, user_id, mod_id, action, reason) VALUES ("${guild_id?.id ?? guild_id}", "${user_id}", "${mod_id}", "${action}", "${reason}")`, (error, request) => { if (error) console.error(error); }); }, @@ -218,7 +218,6 @@ module.exports = { */ log: (guild, embed) => { const client = guild.client; - let action = capitalize(embed.title); client.db.query(`SELECT logs_enable, logs_channel FROM configs WHERE guild_id="${guild.id}"`, (err, req) => { if (err) return console.log(err); @@ -294,7 +293,7 @@ module.exports = { return true; }, /** - * @param {{ mod: Discord.GuildMember, member: Discord.GuildMember, interaction: Discord.CommandInteraction, ?checkBotCompare: Boolean ?checkSelfUser: Boolean, ?checkOwner: Boolean, ?checkBot: Boolean, ?all: Boolean }} data + * @param {{ mod: Discord.GuildMember, member: Discord.GuildMember, interaction: Discord.CommandInteraction, ?checkBotCompare: Boolean ?checkSelfUser: Boolean, ?checkOwner: Boolean, ?checkBot: Boolean, ?ownerValid: Boolean, ?all: Boolean }} data */ checkPerms(data) { const send = (embed) => { @@ -308,10 +307,11 @@ module.exports = { for (const x of ['checkBot', 'checkOwner', 'checkBotCompare', 'checkSelfUser']) { data[x] = true; }; + data.ownerValid = false; }; let owner = data.member.id == data.member.guild.ownerId; - if (data.mod.roles.highest.position <= data.member.roles.highest.position && !owner) { + if (data.mod.id !== data.member.guild.ownerId && data.mod.roles.highest.position <= data.member.roles.highest.position) { send(embeds.notEnoughHiger(data.mod.user, data.member)); return false; }; @@ -331,7 +331,7 @@ module.exports = { ); return false; }; - if (data.checkOwner == true && owner) { + if (data.checkOwner == true && owner && (data.mod.id !== data.mod.guild.ownerId && data.ownerValid == true)) { send(embeds.classic(data.mod) .setTitle("Propriétaire") .setDescription(`<@${data.member.id}> est le propriétaire du serveur, vous n'allez quand même pas tenter un coup d'état ?`) diff --git a/assets/images/hashtag.png b/assets/images/hashtag.png new file mode 100644 index 0000000000000000000000000000000000000000..9b3d0ed71698d37041487c705bb5eaee2b272e72 GIT binary patch literal 19079 zcmdqIWmHt(_XiA!ASf6}gD5Q^Al-bGQc}80x+RAiLPSAIxeRh2IXYU*NLS2cBl#Ub+50C8mGkGmMJc1BB zJp9OO1mKtCXOs`{@RZe`%RkZao!y!z_N8|STJwAM$s=}v5MPH9@4&ZbA+wfAV?8Hl zCR-Xd6(CsOyxd&P@oQ$7FhGk~;k`HoAq!0xr|oM(&mmR<&m{Tx327f0nhN!}Ygv_B zioZM~Wo8r6Wc}~;>F;Byz;U{1jYjEt^H#Sr1lPUvVq&lc!R6m>_~3tn8+dpjcvt@K zclX=D*vlvW4|mu2!Qjhr|A#x=Qt&Rv{eR#6|9{Cx&Hpbsx5t;hXNe?DCByBTgSQcz z?NE@Zttd*{D`DfMG28H8qd@B5aQ3uc&$^Q>Ux5B>g9`7t`Asmoj6pMJ;h|I6?r3YB z)6LBNn?_WhY%AOBX@h?T>}me~EB$Vhh5X$?#V{^8swsN}MCG5zJ=$+U0;I-P=P2^N# zd&B-~17B15*vT$9E06kvj*gD+)e{tl2&9I11pU`o4GHB}mJ_8p48y-=f#=B+yoX3@ z7jWc0>}EZ~R4uqKv~@`|+RSDBs1lEN36SbvO}uMoD6Q+&=_P1*C;9xobZFrke?YgH z&-ZD@h1+bmb$aaxc&?S*I=Y+R0qid1*cA`0%5-6KCTx}3rmd|#oSu-)xxRQNvCu2M z_BYabj>6D~qiRcimEl~d+fYx^Q`Yy}-PG2zfpw*fIR;m}>eTWV=6|4HSi`upuk>AY z4!Od8EEE3i2UXP~9o-F}i)m8rnOcfgCk?6=U+LQ}9+r76GbJ$2dlaJrnCA{y&&F00 zb?gkwr-cL!E54LY_7==^9*W;DC1?d*7T;tkbU{rStoCGOMC3=!X-4L=R>7|FsCedRhj zXJh`i%z4g4wYqbdE=3kc<@%(H)$9bjGz?i1L_M0()TKv@ zk__Ez6mcu(L+Mlu#tXq)GzTiek||W$HeKu#;~X1-+*27Bgj#;v!&yJQzc|2-5!h%a5Rc z)qXXnV1wLMygE$Za}r)xoCL0eZRLPCsmub}p*+lZf?d_;z_Zx#`2Jka+;*(uGt2|@ z9nHV5F=Q1!Bqi=7CEnyb)bdUncm*9Hc*}11?H+0tGd9sO0SB+=ILErOiCcnIY9Ik? zvxnZ$`DCAMzk_?nKHmk>z4;HTpD#(ZdRCaFN%z#HcG@6<_nlLX^E?+{B8@v!C;r;h z?x#}P^W)r}7qQCNTk!M?wZ6GTJ8zZI6N~U$D2x9>cIxpg8rds@rhLQpILE&GxwIhI zBm%e){)nmVN0`C-y&sUjIx|fDf8GhZOJ@H0GU}$rC_U2$B~Z}|wp`Xsme+HUhdOxg zTS?q4_qDqMVrk_#o^f$>QO>eVC9Pd}1ss?zV3DGSj6Z({I`Q17DrJ5Wt> zromqjp8gT2D|9B?PO=E@vxh>(yP-=w_Bmg@>h~dW`?QuHGc#Vei;>h;>On)h{RmX( zw4l@VI(JQabBz%h;VAA86QnEN-#+%G69JO~(=Q5z+T=dQE{T69DeD(S@0~xI+0n`Q zJy1Q5I)PuGoYG$Tqr13nYOf*M5SiZF)byj@XJ{g->U*&n{EyE}u5@5se{00WcJ|s# zM```IXpJ6?5yy@4Wnz6&s}Ue%{E#_9y~(3PQk;gnQS@!l{61sXT#P^T*4B3`g%$UW zl!mO9c!+gWgi#AqKhoVew2Qug9t#gq7{qke`zq}{Hym8rJ{c;9h5TlQQ4{J%zVzD9 zrLUwW18{`K`-*SC>=8N>xRnEp5Lkx+j#k2ZuzxhfA->pq; zW%C|yJtJT1C;v?U>s9`L3`W&SSke^?vtQW#2BT+a1uI^hJor5bxVKKF$=R%A5sAsJ z=VF5+(!&k4XjOkZr1AQ?>G~hjKVDq#%!q^MO@yE`y#;J6zt}6+b7h}TZ0&OvSqt}! z*SnfQQCD|~jGoo<7f}X`0RI~Dn8M&8OISSwq!(DBN6UV-6BoQ)(;;F3Mi-lMxS z&D^HU6Z?Dl)X_5))6&n*HhGKTFkE~(e0g})Xl}6Cb$n;!d(akSKmXT*0tBywg0ReuP^4H?#w); zG_`XrQy*w^{%#_jEI72fpS(l-VLR~Ht2iJ&r17NrbNX63wyC86&TLe`|4H%g+!Msj z9!YxOeM7=i+ul|61iu(?Ac!*bwXHK-Jrn7j5k%NN=7@zC!4+VB)T5}y2&ylOkJiEp zxz6CxJHem-$b{;8{w6~E;!_&69@WA=JV!sp*o2QqEJ>`}nOHI200+q<7Akz8dHs;2 zEVzGiHz*gmneO&$p!x}P22T=BYeDSKXtKmVzu3r!Z_QEJA_0#3c#_;GoAcvSC+Z4V z|6Fm!>Qwy`G5W>7?3VVA<}J#?@WFB+#A!ikItSq=s=W=-7H4YDW>Pc+rt#>-_e_o| zR$y1kr+bUjTr0mjhrwuwe6@G&SJtoa#%;fZUmy}|C8bm%e@ZOdPEz z*@1(Ue;_P^ulqFJ0ZG5W8f{R;r+;H%F`JY5k9SeIn|w8Al>#e_W2reUo#)aer8OotZ4Im! zXBcNGr3YmfuAJ@MK&aG?r>}*hQ2NL}=EzO+rOm=S@(u`Y_*XWUZx9j+gL@NU^uOLm zR5r0?i)G|49AgSg!gm#K&sz*w;{$CLq%g=#P}+Of2u%6=hpO^iTZsV5v>JG<7gQzt ztUv2YUv`U5($i{jHFL?Gh`oM_3tol#&SF(gST67lbCCs*aR_^>kmV;Mni8sBdb`OE zdw$@O8;HwB-85)vkFz=nsm``i`OLPZGrZT6MyDy1%smlPkn>pxd;7V~X^0ja(lPY0 z$T-g2gMlG4!-J$moWbBxl4oX$Dv`OiD|stGKLzDf-3`}-2;2CF_el9@|twa zEsHkzb8}!Z<2lJ2_t|4QJ2xGi!j~@YlPJ3*h*ZYlJDU zfNDuoK-MArz9m$jVavPY^;zY7vL8+E8n{mv>)bH`LD1=RyR&?oZGTpDe6a;~j8Yl9 zecN%@OZ4mmj}*sskTziiLu+LLW=Jtz`70soL%>~eOduV)qTSF%p`;$wfbO5vzx6`> zs{WRk?vbo^EwE_PVY9Vt&irpkwSXo2I(R%1GAU}Lq=@fSAUJ$|N`FMT zt0qCyQQ#}}@a0ZpG%UndktLgt4{V;oq7gr~Xj%tPcI&GCv~Mbu zr6vQ&VmiS^cBKIJ<|NB9-+sRJBIeM@Djhe ze0r)3;Itvlp-C9rZiCz0-M7#AequB`8A z)-vH_ss2HSFnN`c$5jo6!8Wv0!$FJ#OFACK*R3~CRV>(XDqSlY%GOJp>)-88paR(t zLB}}+B3`<>8NMq8AkjF?Mq z3L4@LBb%hGm3CRSyrl<(kt)j%hs9o@<~ySr3_Ac&KY79Suykfy^HhU&3kbI=pu$;7 z_o;%Ap(3=HzKn%phUhZDw`Zia@1mCgEFN~qh{?4jNyp1v?*eJqZdhqoo-lnZwS1k) z5)ixQ#*A7Hjl>};7a=<+Xa{_RcQ=(Z}4)2_4j`C(0mcj`T6y= zl3T?3S{=#quh?i!9+FqweW#=OKzHc_m%u0GJ6ez8b+vD3nX!yk9hmezj@vTVLi=_J&fY1dtl{qA}s z7InCG<4SsqtlgNbY~LSfQum42yF+&o^fJ$?9WR?S$sU+vP7Y-*sD-xfZ?>lv32Faa{Lf;?6$h76Vv+Znb>*&^LIX`k<`x zfOBqL({)ADQsIK9ez$CT-LQ6~I$>2;da$`~w)w4Q>qxUt0i?VZvSpiVbn=tkLjg%Y z_251FZg<@XSrK(d0}}v=?RO$}_lLwOez)d!A0lElTj}QmMEiW-*Qf90!gtQ#%@0f= zRqwVv)7oF=63mPH9O}4hSTBEQIhW!t3wmKDOCuv^Cd=wZL+VCzqd2&#?H*}?=|^F+ z2>X^>GAva)PkqN;`7YP|==uGl==WdRcr|L44Boe*=FvLl`>^H@bLDG+GjgJBUNHE_ zpRo!hO3dR0)%ilzJv0M+H8sz$Yhv6_C39xIF#(Y-K6z@NXhF^b;|q&$VM{!5=O+P) z#Wttyu~V+_elbli z*3HnM0^0+LREI<@r4g;=;au_kcGQFRCu+_iYLa_W6pN7YRC0dzrpyQ@ju~(MgM5Gs z{tKD%3ORwi6HRbt=A6CpH|K+`K70FW4h|9UG< zxh5^aVK*XQGbn|>d}QnX;Rexit^kn4twmwVMRo`0llQ8okG|lhTT5%TKdmMLxd}lF zQS5^i^39am0V3aS+Z^f&zA&kIg`%AAXE<+hYq6GUQP&jFWyV|*_iX)v_ORvu-dIj3 zRsp3{Gi@yeh=ozAl{#h%cgPDj{(7>vC&Jbb2Qp{1WMFzjjt!gCg7^z8PVRulz{l8} zCrHi9eOd~_iSI4`P~jD+v-iejA&*{OEn}Fbm|dcq5~+uOEvWj2f$AS^45QeePcU-d@At^0XDJl1d`Kr>u0du)273L@+nc<3LN?zl5Ph=ag1` z;p))BRo;d0A(?RIwxum4&+}Xz;pzlI*YdO1hIzyj*$5xzT+)(PB%Bn4I@iMbm*h=zI^*kkA<|HGJKM>cp~yC>e}0gv)Y!} zPZJco{?Fx?$q{{sRPvvx9UE1N68p^rj;2<%)-`Y6Pezcv(4^DKE4+*Igs~%$R$k*Z zdhV*FZ;l_vx=?9mw`E)``DVn3I(%psnK`b+hSA(toxF9azaMY+k-(8} zp-(S{WQ#YkoHpp#aN+w7BA2fRqz@r%d|0=fS<< z1qd?)9r3x;V+lWA5-UL)0fMp9zUA@R6-)lH6HfAwM1##qExDP9#!vf*F(z(dSIhHxjtea zcVGNBkr%?18Ny}!R_(uu-{7{LtGV3~TyyP?nIGwt3?HElET7Jaz3aCPJL8_f8?Nqo zsOrKryZP5Bv9)DJZ{a1MoBM})u{X71Z%VdkeJmZ{@yD=qJ}_CnRpEVYYWAHIBXdpc zZKL9A<@`q592b3O} zT^*897?Qafh$hGjevBTb&FHVUOMM%aZIN-zd;3Muk7juqod?%ADXu18597M}WaV4C zho(h1XBxZpEdX6^DZT>K@cR!V@>N{7Tklrfek))tOyF1kpBcBn{iLz}m&|3c>@bR6 z)YadZr3h?!&Ptdl6HPNg&Ka_Pd5*l7o{dzPval$h7Jyh~7ACl-?0VaH}A;``drUA+ub78 zsAn98?D8!WCpG@;JHGM6qVay^(_03=zuh9zBYj=eNT^RjOYm0Z8Cevc)kM<|$E!C| z)6K8Tq2A*30Jyj&g)P5)oStaV7%@dAb4f(-&n?c$BR|gXsAevw9~7@nPNh6HHg8VH&eD!g zox5OGPN>l0>1%W^By3J=gquw&=vq1eQUFyI5>8P$sOcZfQ@>WR7E4$#=A_u0L9uXp z#iRKgo(zc*GZHL@cg-PH;I;6_PG8~A&*XRU;-{59k>%rD)__pMI#qm7$F_Cd*4G;W zqARD^S^6^Q)`F3_MsmTE5XRQ)SA)9sa&6DX(y0J|yO(U|r2HlI1__t({P^M(EE>2H=_nl5Qc5~LH{{|J;%7D3e5#f@FHtx*zc^F09iOPn_Pl^ zKMc$X@duyFFC@d2pPU#3xb}*$4I=YO$#@%2=DA5}w;(9>f}cnkED@3y<@Ok@u~BXX z5!0}UBJU3cN!%^1^$;UJ7LX}PI=fmlWWR3GD+ zlWJy8bat{KcgcMak;w?!2PC-u)k5|k^41)3{c@K&+!><=d}Rgn+#dCqGPm)>X#k2~ zo6x^IX~9>z+>e~jq7x5Q2tHXTSUVv=g~vO-oKQ0@FTxgO73SW}77D@fR(}=4!tLH} zYS_-?4AkxYs5jpqpKyk5;GNvv^5{R&dnUd{Qnu?k<(vEGPDgT4MpK5qd1y;$g#GNA zIc7OYgnW42ny=Yr)6)s&82OZ?ePB=3A7N%rMF&7$NGOT>j?2=(E$KvWf$s})HqKB+ z=zD;=>Eo;~q~!Yjk~XZ5+us)W-DR|(7?Pr&oMJ0`Lib$5qH)4x@zs^Iv!GXd5w#lS zVv0&UaQI_XExejcT@IH)^Jn!c(^ttRJE2mX)=C7vz++_;m@n=u%$AbluOUdrvb}m;05cQm5Ms94@gzx`(%;uBVcb1*P_kNa7>`dY2OyKU%rDq z%P&XUT+^U{zs$WEGBGjCf|IEc_BGc_sC(&G zPcrb4B6!W7&aNTX76DG|?Y~;>zianF27yFVP0zQz`cJqG z*}yS=J1=cv@w0wLiAdszwMB7TPr{cXR!xH@E~HyKr?K!Luc>ay$%Wd{G`-6tq*okc zQ<%ka$^4rQTT=q~ju>2wUt8C0c!fJjlT#Jn+|^SjJ&?JVv9Lku<5sjE=>8)zyh2zq z%cZ%Ybi6JPG?$Uc-f=DF064vB{K6i%0)p?;4m$L8v??PkVU zeipXK+OXA{;WGDvqaxFL3OcW9H`EyhOZX@ji^%R#dQ+o4{Jg05_S$R?w#gh4x@wlX zM!o^RUdG40!jmo%jXOX70FjLp&NG76YX?6d`w#t{pp5Ie-MsL^7L6+6iiI_)(3N## zEnq=md=t=hu>=7{uY_SC+hD7+Uyff4nTUZ#mF^ebVU{vjvrzqXf8u1&46`0 zEj4guMN=JarF@9`qe{r{Akm3Gd#S$^(|PBy9{rD#`9Jl2;)q=xPmOS{A}L8#tb5hq zHfUCNzL3a>Pxj^;pxC~CM$di9Dirv~7NT0$GxN)$01AsWJC22Sdm>SPv?N(Y={YP+`ue(6hfFsx!!)b}mg+izvM7V*x!z1Kpk|KGmAavm z96Cv58EzTrYsVPMx1!Grj6{5O-#RFY|Ejm;J2AlgwY?yknik0t6L3W$O)=7f&s4;f zY)s^FHt8#!s8DoM+?Ptszr=P5zW;i<-r$zO&%s~+MTMhO*>2@dz`nd>3NxhTkRWQr}L>ZqWh9C^<1LC#fm zI2%~}nX)NZc~AoMcMmm#Qo0$uYVTp~&CmB${g&+2p$fMLd2bH}Tya9n`VaXLL@`zT zR&wl0^D|q(4hf~HD&f|e_N1+u9~vP;yJ@<(Zv1p=s%^Zdc)il@!HKmsIfVhWE7Sp+ zAM#;>=VV~dcuXbAp1mOBX88DpP4rv9cy-U+tUnfwp!|%!Q&h2_ix3Rkm-j;Y2{76v z0!ArqK8hF4*4OYKg6M$D|^^?o0N^ zQ}DN1!xS5x*7qhmuJNDq;tgb}y`(eY+2{KWO(@t*2esJ!v$P`ULgAaTSudOx>)#zw zRd6b6Ep4v&wZ`8l4V@`5C0=oKca~IVaF=r5ufq=A>1!(>+_W9opfW{R)#>v`iAzAm0+fPi6P7a7LClhl5(nG_YADp{ zuw3JA#M422b4}~(l=B|^pMJxZ=Nej?BO5n8McaNYA@0Yz$Uz6S5Z7x2!*qz~qCtC) zTn0?`gD2*DcmeR_33ENZ9Pgj`&F{i(EJLyHnT=UV2dUbc5Xo6`+;lAYVKv2?GKWjSqjBEoBsVe4QNMRyLSozGk@oDW~Wb zj@S#2-|vqSIT_Dt-f0JQnLJwRR&k{;(8y7n{W0-+U2l|!BQ^!Hnr^TN zhs~f=+)MakRGC;uEP&C?-&xzp_Qc2!9gUZ!D#i&srf-|q-*yo*jej zOUg2#Q*&VPY?=5uqsg|h;MMIGY&X?~;&XN|o{%rYN@o zULM^Kqcuj%;C-)+{i{xO#}WhT001m;YCY1muRod$(s>Lhbnc?F_ul^{3c;-yholl8 zayRTbzd-C?m&fwQ2Zav&7k1ks#9KVH7F2-?vQG#nVM+6o_X@2IT4#_d{P+v&x{0E% z!a5V>ro)D0`DlJojxxuf+9L}nOZXDa=+b3)iq`T0YXUZUre@)ye6O4#z`{AiuI+>= zKjYw7H(?i7*7Bc&A|Ml~AL~C(%mq5~&HGvJC(79d?W7hLICN!XrkEjj08$(gt?3%2BDM zc%^CE0}ycNmUDr6rzj=bhcNR$;}fGO?)N%TR$lZ_M-?JB&y4o`;B!?!pSZGaVL0?` z0@7`VV^we_R+fop%n>)KD)k3M^74qDE9c3~jShA>=2N1|EYYL4G&8dCG5Xumzrml) zoHLI`w|Yr0i?QixlTL@e!iPIC)_1@-Vh{Gpilv^M^AbEU8OO4$Z<&7UN_eLo8F z-&>k=I2>2+CL36%Uqto$(e=`Lc&AQ}g1|C!y724EIXnsaWt1++RtQt4j)5K{RBJS9fMGw(j7!G>-JNziI-c9MJS5JQSjo#!b3N-DUtAhNAY|M81gml5wydx7s zDgWgv+Ti4lCY|OdML=2gwk^~f^tFI^tdOXwYX_lKU^P@O`D1d1ThXpEpB>p z%5~0M6;JBM%0gFoJEr1xOhQDFL%do=yxQoGRl}tpR1V|O_Lv(nr7tsd@{+k~DoD2i zh)gIY+@ptt6%Wm#w_B$t+oa~}CfeW!qo%+YwVefX4bRHkx1~>G7Bu}-5)E^mACvz+0iK0KP&Z>g@Dt~ee zE-qLUk|h7@s7!Ix?pu!)ENEGe5?(e3{a3Tgx*d{w_FI}go_w_)e6>D&^NVI8g9QV# z1+Z z8riiP^X$1zYH&;@6jdIG@^jUlYV&p6C!`9P1U(y*?Y22?%c~z()$oN%KT?(6ul0V> zUt>}0T{+8T(CU!U^FcRaQn_gUuE3yjQ7!3&(U?)WoVQ+HlNymozwy>mllxM{@~r4G zbF#Z;R&UdPHs(FJpkVMgA9Ozry)j3$eh3W+Iy*c~-L#&XC)O~dIg^lGT^n0VU40? zL#)9OCmem`$Z_h$b4Fj|-!{p8y$M;IIZ}5EQCF%tFM2MroMmbv8cCs~@&z63JfHwf zh&%LUO51@Uh4zub(ApYXs*jTQvxJjZOZFw0Y*1X_qXSFM!($p^2o`uArz)Kph&i1Q z@U4B*B$W$pSCrHK1WmvOyk|7hUCu6aeJvq6#X^lYLEtbkr%U#Wbl_jj2YxI08h=2W z&-0b8@B6tMO0JY<(-adA)jGx}1SV3$y>Sjj06!=a&sa6&;_KqKoON}FK0J`Oe1WG& zeMa9X1MVF3u;oHvAyK^BvD*nnH!QZA8!iJ#?`5b3{at>Lkart+9ETuN6WEj*CgI0< znEUNVJe33s6cZcD#57=0&2XIe0v&66Ljmmrw^E#T!E4e#fxK}@?td>4B?xra&`A|4 zWIBYZ=^_SH_M@&>D?LsOznqOm{fXdVh&EQ?GprY>Vq;2W2d=memy!CvklPlW56Y5) z2Bi4Baa61Tr$1vfPOM-oTxkRL0%feDdu)t zr&A8Cz}?s`(>MAy-_wC<;eFPcs9dLs@3ex(1GeJV;nd8O%#y#TRY_tXnd%qDS*F*f!lSNBz24Jp@e?KC+x#4Av!oo`^NQgY5!f zZ8dxCpVVCCa~AacFpC@20UDIsdprwkrcJ}m)-cFM5Ywzok6G?+E4)TJXeHp3>)=Rt z6H_|9rtkiU;mw z&d1OzRXt}_MOUhd!oZa`Sau~kEbq}f8se2l#4AV#OQc+Mm}Q2c&uxhu^JR_XD+BNf zcS-c7ja^Rb;GRR3w%2ByqvWj#_Yadn{9n%gtH~R>GLlVPAbErFg%_>Fr*$csu|bKu zV}8#@z~%B+a{irz>ARQy2Jfu=k4VmRv}8jml(>z}FO`HUA+WXPD1{ZpeEWqWp?-w5 z@ZGQvx`5u-w2$GeiM>`%(T94oYn0bw2D*t>FmGDa?<`bymY!bpqgG7>a^FT72Yx|B zjeLk7wAP6dGh&H#y{%N*YyXJ0JTG53VQM_-sT`MA(o+^qd$z|$&s9rV6_vW}OK7si ziqw?HBCWiarhODk#fo(4lqkN}MlMUF<+?0Q*SWEKIbU~u@7g91K&xmXvKPF{QClD> z=Z$7N)QXf&=yIh>{;9_H)!*RGTi;b`9S_(82M?H7VH{iGMU_UzFVPdpgd`b#qqaY4 zFPq?E?lq*y6Kv2wA6EE6{X@8DWX*%1|I+y@O=wKmEE?X7R~`xIl}DB7wJ-KN_E!2Y z^a4=-My_|-?Enn{Yc3LhAZ7^OrMvE+NRhP_z7 zrhuwR(@S{LRYS{cHOsoQHHkksyK_?gMEGE@bD;X9V74o=wQIvQg|p)Yt~BPG$oX~Z zR{Hb_7W#U?oOkyOx6t>lp5hote{nVC0~MZo$i}#7X5PXjP154Uo?gRPOIqr2=v025OOB9$TsM zf=%|*ZaE+^CL=rP>ikpAO25Q)X6w{hb2z;fJ)W$@7xCHZF9%KL8W1C55$;)B6F63G zaK&X;&*3Euv}u9al_5D~sQ!;XaT$@}HgS}|JJZ*t;98qXC4c36Ww=}@4~px{MihE) zlYOC9Dh0_FbDb#z!jkdlub>rtknf`lbERn})brpdA0(0y(|rjMdWgnQ7EfN(-fx&y z(6cize`24_*%DL`V2G~ei+(h-3At*i7Q4&-EgHjSH5dMMi+E*LNkd%SLOS?-l=n** z6GCkX&WDt2`xgTG#S@cdc&=4=kyPA%1FwMnXXeINT8n`Nb+q(`b`nlb+r`x%k4NN3 zXZnd8fV>o%zT(!b_QvNSg~1ikd#))PpIOHtXOsFZ7SONcAW=&RVB{&i{dT+(;~hU0 z^^N`}p$=43ebDlH>O72BD%dFu5@V1jJP}zi-H3rohw6HT?h)!~A!1?#%2^w!IbtXG z2KJ`LL3ss8P28?Z;B9z^Fo9uAR7(yYj9N*^6~lGmGJ=;%!n1mkt4HRxTkfrEuLi*} zH|Zp0xRrYzR(u)Obep$KoTzn95@=ag`9r-oh6-F{YITy1 zk=*aMKB`0RMUS6(d)x#XQQ>qG;7A=UL?2qJ08XW4K4AR-tfrAX#oF{2O8+=W3N+4c zo}=hn9X}0_Srpjihyy}@>Y@02t+dV_UtuSZjr!rQ%7l$iy-=qkIE)5kdVp1jg?-=Q zy9GpEVxr>e8pU|@d7lToO*ZwW>t1QHqEqV5qwAp8>+aNp=j&CZj^gu!xOS`qSRdck zHMc~%vXIAnEp>>h`(_o`)##B+l`p~9Go4S8$dMd4^A2KS^=7!?@aZl(uye6$05Hp7 zswdsRc1i;(WQDMB4EQ`Jd)AI(?4kNo=;J--KcZHN+qvS zERLXxr$wpsc>lGMbk3j6X;WCih6#IspVWy^^&xgL~LKJ>E1_4EOz`(Cu;+1$7p?_qg*zw1Qs*M~YB z>d5X$mS2Y}W|u*2QT59x(+`FV_ZeL);z&DmOU?$ouA^Cxu0YTjs<4xt@Me3f5copr!i!xW6h&vU85L_e{+F4VJg|5}LL@Y6pFn-7Gi72-D62MZYe8D0|LO zodvoz8sPay>h4dcRxJkG$+kgzlj?SL%ocm1`_eUxX)HD$kac+PNXoKH3MdYNFKG4M z8C9SBbEl-}AM06iq@FshKKHo}mgAn)jy)ZTYSmx+D3tmQ|6zht z!pZaKoeMp`7+~^G*L0l_5)RI℞zHx!F{UXB16!;mGq=q+XE-O!?bpm&Xx>1e zt-mHV1qs4w*esHJh&J(0bRuwlcU?rcrQgg-J_V&9+$8yJib=MkvHLvrmK7!uB2$>52(vqE?{b!>Y4 zZMOai-I(oYx?Lx>svjX2?}AW6gZhH5s1HJ-MmIws1iJ)>JxBEu`l^=6^JiSSMZ-hCf+N;-rlb@YgF06H9b#QXf^Vb3j75Gip!)aaGFhF7YP4Ic2J zQ#_c$-_CbH#c!2RZ`3|J2k>U~8uc@M#$8|8+t89KUQJQTn+sfHWD7w;Cu?|Ce8ySh zYqtfZ*c(|vM!y?qdnAZT~v^3pGNW%1D9Ezr?2c92Eeiuo&EPg2I0DWU3Xt(pJW6!qR zuG6jWb(y8``TVi@gs$x{%`GPDEYQxV>wUbZmgiEjPqHX{o^q8GW9t1ckXjt%9$H6V zl&wm%3jGlZrOX?1+jUFosReWyfKv`H(IS4RTt{&=i^qt=Ns}37H$a$#f?Vf?x#uK= z>YVZoUS|{e-_@j%#hhU=HH#71i|5|1`md^m>gECQ4VpIwKCok4lNKP zmOIIBX05jSFu61!7+%j)wtZ=rWruif%Cws1P+aeC=2sV=-$q{}?ErRA$=WVTXsUmM z972G0NrmifPqBHq-(9zDbM$NALYp8ARmw!}?w^b)qNRg6TnJE6-}w&0g|4fan|IcWB~EXd#%iVbEJYa2UnqJ=4K8eMpE$O~6$K~G!aVNvg zW8W`I&fk9RN6aK#E%`1&EE2>5HwAR{`#Vi+&s#G)jbtn6mqFodvJAnn@Ea&Lh0<_?BK$V_&8)vNFPpbp02S>%mE;X9`mB%oVq0`XuWy5Y6gT$?|l?=cRe?}uq z_&h~OaLi>H#hv6J&)sLJ+V4PZ;kV~(nMw+m1^}P`R5X3MTDZphXvhjstF~}%sri15 z_4viE+sNh&WE3v@p1l4(y~eNrG9lm^WK&ctzD(8;ga326v~7g;cI=@{SE24C^jpPlBT!}+RRH`+OdY1SAt z|NLbwhHd{@BDU^rEu-N#!pV`hkuJBhD<0Ybx6To(=W-d_CQn(!6qko^HAzh3uTbec zM+cL4&o32-AHOc4cJ=1M3V&#KP*9Sf7k`m)0uWvUy7>#LdB_e>2?oo?KaCTVn%q2c z+d(N*Tpro=b+wc){-+%KfpcoT+4&|3uulC%*pYkd=^L}h>I`}C(q=g7G#hjlmaQng zy0*J7LTeS5qmJ`;*zPgYjz_k0en9=fXHLBC^PWW+)WI{bzXduOQn06`(eJssV9+lN_@dhddf?4C^u5+q7BBYIAyo zw&19|^kr0<2+Rx!0+YLBi{K;cHixF}-$eY9eSapzn%F)+_iq}zY&I`+1C);|xtr{) z7>?(RtF@ZjASuHikg{5xd5u&lZ@W~0S0ON0Wm+|fVH*M`tap(3m4Fqx=Yhqb7ytuY zj_BLEm9G>AeBh%s=m%k6&LZO$a-SScgs?6GQx6cYrJ9CCVf6k&K1XGa+UQ{jwL{$` zvqGko4!2E8wp|M6*VJdod8$d7-Q%&6l9IJVSaieYbKBdeOUc?MFwd8=;S@@MCkVxu z>f?jS7dYGGid%1G(EW0jS*jT} zHR-5&o{#VpWAODP$^xL*&J4D`vFl0tS=w)%3Fuv3)8FjRxY<8mCMQs<#<}&%zW?`& zL7vPPF)=2d&njxk#w6s|P42p^mhq{4_}L$ac7MMm{%KvJY`rcLY3;>SbWw%+kl(L3 zV$)x#xlbd(Fz>=N=fs5guCe)jKoIFPf-&W|wD%pN>(?tt1o=qv$6s@n|2M+*qK1^R z{9BsC>$Ez<{4^0u=S==O)Am~#PRPDW_&%=?l)gcu{TBOyK+#3QdG;rn+j42+vbh!` zhtOW(>Vs}$s!2!a)DxUSE`OG4ZTKsZ?j0FDd3(f2ph$P%{>&lWAP6px2Q17skN!7d3ZC8Ie)I{lTtIK-7kCG2omoYfwncsNU8m=MwGhVQeCkmqGtb zI9kEZ^rb5iYEl7u`4?_XGUxYhKiuEgtXA`j-L7Qrh!1mXnFDV$u$NK7r_!Q#00>!w zVbo&3R|sYKXFi;{r)VM4iQ+)glOmg_01Gp|bUrW4RZ7qqhJZz^T$t*RKe*N*MRXm9 z7T=uU9-yTFFDcBuc`q-u?W@cG=Fv8fGRM)5{#xG24zDsf>liN|z#1t-AGHF_ZQnn$ zU_KFGw6MJz4Y-Bd+b2fy&`16_mf06%NfGG#OS3qs*^N)VM)rf+B~K9e744t$D} zIM^Krk1K9;+C^F4ZU3tbbAXY;!DrkHzT#eBJk?PkZ^ChVs!ER zuYHt0OORP&{^5I6moXLpUi9Tds308s+-|mSv*ZPy3QxBygKC;z|H9Xb%XKHeoh>%- zY6ea6d3+eAq(Cwt$Egn# zIx^jE03>lK2=ICfO)~a%BFGqVBJgh*1?Zzs@X|mKU5NN!GODuf-ytyt``}Q^hg0bw zbOS^{HHW{dV`m_q6?b&NG#+3~YjLI#5>GZnm#6ggPQd@>DTJ4L;?m4l8NJGzmIBfL z6NoC*5T^zGb_e+s0YBc{!^I;OoLHN`;Amu?-$DG@bN6tLk``0@5nGXiD~72!{H2+n zeUl?BwI@Yyfm^#%5xn#hZo8v&S(1u5L7secIG8*RnV5nIUlM^St?T!gOQx7@amopt zKbnUW@HyAXiVEg{8XKJCSRA`#?`{N($sc=>W!BR1q0(dgknWdOi+eoJ@U-cf}wuta@Xw z!?&LR8HF{{g3dJBvw?BPD2pQaS&A??>3le<5pKH>1&&m8+Je3H42=CZr+Kw7K%4yO zryE3x&#!y*)@S+3UT61bLY)4J0}M)1Z)$i6KrE)2DCt?xv-;1(*=7z9rEB_{~1;|KIMgr z3he{KQTK|qh5+~jp~t-c3+&IDM&r_b=c^o~{#(QH=E3;nsDjEh{+Z zQTY;O0haY|+%!(#Rwg^d3-%>0vzqa#d}Ol;+8MNj>-n-rm7vA{r&SLzrWKd<7t+;y zZP4}~UCRe#Sn&-f|I(N2PQw4jMPW0laY}#`&wTUmkSsB#%D7ZTcd2hc;^>sl@Z{1l zGGSJJ;a;Act(H-L3UX_(CeuV*E~e)l_HV^0um9P#gk5ww?3$ZlI~WAn!eNDwiAM5! zEWc$BVy6n71yq<};e^vbaK3Pks*^=K|IZj99w^EO3uQN*Is(=f^$IlJx8ce2l&8JHGsQQ2a|MPSeU>fW*RARZ)DE0& znzs4i%o)25-2y95aDB&~&hr@99`61HoT1*p^g5xC?HZ^&?FQ~tzX?3&A!e^dHgJ*& zCZZX?zS*#}6_~bwBMLJ<<_KMe1P(A{A{u`moZ{FFs%l(ofqVnuU-6eErz2F?>qq&g z#R3<9K%APunzrdg&uLI(uFwZ=`_=w9XH8Ex$Re;)gkC>ba~f27f?XY!Bs-@Soctip ze88#oSqP{S;*P&LlZu??*fs&V5Thmr=w*KzT`rv8;=&b`>clhV+7w?5B zPRrbIFwO*S)^2D~0kkLK-S30P?4C%1#t?zCZV}5q12YY%AmIjj9@rV*te^b0`xg_? s?W@;;Yy%0;*o}p?94xl%(|_j9eDD2LH)_R!#|ANYy85}Sb4q9e0JN4O9{>OV literal 0 HcmV?d00001 diff --git a/commands/moderation/nuke.js b/commands/moderation/nuke.js index 08bfddf..21bdd03 100644 --- a/commands/moderation/nuke.js +++ b/commands/moderation/nuke.js @@ -29,7 +29,7 @@ module.exports.run = (message, args, client, prefix) => { .setStyle('DANGER') .setEmoji("❌") ) - message.channel.send({content: "Êtes-vous sûr de vouloir nettoyer " + `${message.channel.name} ? Cette action est irréversible.`, components: [ row ]}).then(async(valideMSG) => { + interaction({content: "Êtes-vous sûr de vouloir nettoyer " + `${message.channel.name} ? Cette action est irréversible.`, components: [ row ]}).then(async(valideMSG) => { const filter = (interaction) => interaction.user.id === message.author.id; diff --git a/events/interactionCreate.js b/events/interactionCreate.js index 9f53bcc..b0c6c33 100644 --- a/events/interactionCreate.js +++ b/events/interactionCreate.js @@ -89,7 +89,7 @@ module.exports = { if (!manager.checkModule({ module: category, guildId: interaction.guild.id })) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Module désactivé") - .setDescription(`Vous ne pouvez pas utiliser cette commande, car le module **${require('../assets/data/modules.json').find(x => x.value == category).name}** est désactivé sur ${interaction.guild.name}`) + .setDescription(`Vous ne pouvez pas utiliser cette commande, car le module **${require('../assets/data/modules.json').find(x => x.value == category).name}** est désactivé sur ${interaction.guild.name}.\n\nUtilisez \`/modules configurer module: ${require('../assets/data/modules.json').find(x => x.value == category).name} état: true\` pour l'activer`) .setColor('#ff0000') ] }).catch(() => {}); } diff --git a/slash-commands/economy/adminCoins.js b/slash-commands/economy/adminCoins.js index 26802c3..3c6ad7f 100644 --- a/slash-commands/economy/adminCoins.js +++ b/slash-commands/economy/adminCoins.js @@ -92,7 +92,7 @@ module.exports = { if (amount < 0) amount = parseInt(amount.toString().slice(1)); amount = amount.toFixed(0); if (isNaN(amount)) return interaction.reply({ embeds: [ package.embeds.invalidNumber(interaction.user) ] }).catch(() => {}); - if (!functions.checkPerms({ interaction, member, mod: interaction.member, checkBot: true, checkBotCompare: true, checkOwner: true })) return; + if (!functions.checkPerms({ interaction, member, mod: interaction.member, checkBot: true, checkBotCompare: true })) return; interaction.client.CoinsManager.addCoins({ user_id: member.id, guild_id: interaction.guild.id }, amount); @@ -109,7 +109,7 @@ module.exports = { if (amount < 0) amount = parseInt(amount.toString().slice(1)); amount = amount.toFixed(0); if (isNaN(amount)) return interaction.reply({ embeds: [ package.embeds.invalidNumber(interaction.user) ] }).catch(() => {}); - if (!functions.checkPerms({ mod: interaction.member, member: member, checkBot: true, checkBotCompare: true, checkOwner: true, interaction: interaction })) return; + if (!functions.checkPerms({ mod: interaction.member, member: member, checkBot: true, checkBotCompare: true, interaction: interaction })) return; const result = interaction.client.CoinsManager.removeCoins({ user_id: member.id, guild_id: interaction.guild.id }, amount); if (result == 'not enough coins' || result == false) return interaction.reply({ embeds: [ package.embeds.notEnoughCoins(member.user) ] }).catch(() => {}); diff --git a/slash-commands/fun/game.js b/slash-commands/fun/game.js index 8bc59cd..1b428ab 100644 --- a/slash-commands/fun/game.js +++ b/slash-commands/fun/game.js @@ -255,14 +255,15 @@ module.exports = { }; const filter = (m) => { + if (game == 'solo') { + if (m.author.id !== interaction.user.id) return false; + }; + if (m.content.toLowerCase() == 'haut haut bas bas gauche droite gauche droite b a') return true; let n = parseInt(m.content); if (isNaN(n)) return false; if (n < min) return false; if (n > max) return false; - if (game == 'solo') { - if (m.author.id !== interaction.user.id) return false; - }; return true; }; @@ -278,10 +279,17 @@ module.exports = { const number = functions.random(max, min); let count = 0; + let konami = {}; collector.on('collect', (message) => { count++; let num = parseInt(message.content); + if (konami[message.author.id] == true) num = number; + if (message.content.toLowerCase() == 'haut haut bas bas gauche droite gauche droite b a') { + functions.reply(message, 'KONAMI MODE ACTIVATED !'); + konami[message.author.id] = true; + return; + } if (num > number) { functions.reply(message, 'Mon nombre est plus petit'); diff --git a/slash-commands/misc/avatar.js b/slash-commands/information/avatar.js similarity index 100% rename from slash-commands/misc/avatar.js rename to slash-commands/information/avatar.js diff --git a/slash-commands/information/channelinfo.js b/slash-commands/information/channelinfo.js new file mode 100644 index 0000000..d1f3c7b --- /dev/null +++ b/slash-commands/information/channelinfo.js @@ -0,0 +1,74 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + dm: false, + dev: false + }, + configs: { + name: 'channelinfo', + description: "Affiche les informations d'un salon", + options: [ + { + name: 'salon', + description: "Salon dont vous voulez soutirer des informations", + required: false, + type: 'CHANNEL' + } + ] + }, + /** + * + * @param {Discord.CommandInteraction} interaction + */ + run: (interaction) => { + let channel = interaction.options.get('salon')?.channel ?? interaction.channel; + + let fields = [ + { + name: "Nom du salon", + value: channel.name, + inline: true + }, + { + name: "Identifiant", + value: `\`${channel.id}\``, + inline: true + }, + { + name: 'Sujet', + value: channel.topic ?? 'Pas de sujet', + inline: false + }, + { + name: "Type", + value: channel.type == 'GUILD_NEWS' ? "Annonces" : channel.type == 'GUILD_CATEGORY' ? 'catégorie' : channel.type == 'GUILD_NEWS_THREAD' ? 'Fil de salon des annonces' : channel.type == 'GUILD_PRIVATE_THREAD' ? 'Fil privé' : channel.type == 'GUILD_PUBLIC_THREAD' ? "Fil" : channel.type == 'GUILD_STAGE_VOICE' ? "Salon de conférence" : channel.type == 'GUILD_TEXT' ? "Salon textuel" : channel.type == 'GUILD_VOICE' ? 'Salon vocal' : "Inconnu", + inline: true + } + ]; + if (channel.parent) { + fields.push({ + name: "Catégorie", + value: `${channel.parent.name} ( \`${channel.parentId}\` )`, + inline: true + }); + }; + fields.push( + { + name: "Création", + value: ` ( )`, + inline: false + } + ); + + const embed = package.embeds.classic(interaction.user) + .setTitle(channel.name) + .setThumbnail('attachment://hashtag.png') + .setFields(fields) + .setColor(interaction.guild.me.displayHexColor) + interaction.reply({ embeds: [ embed ], files: [ './assets/images/hashtag.png' ] }) + } +} \ No newline at end of file diff --git a/slash-commands/information/roleinfo.js b/slash-commands/information/roleinfo.js new file mode 100644 index 0000000..fb532c6 --- /dev/null +++ b/slash-commands/information/roleinfo.js @@ -0,0 +1,81 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + permissions: [], + systems: [], + dev: false, + dm: false + }, + configs: { + name: 'roleinfo', + description: "Affiche les informations d'un rôle", + options: [ + { + name: "rôle", + description: "Rôle dont vous voulez vous informez", + required: false, + type: 'ROLE' + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + let role = interaction.options.get('rôle')?.role ?? interaction.member.roles.highest; + await interaction.deferReply(); + await interaction.guild.members.fetch(); + await interaction.guild.roles.fetch(); + + let up = interaction.guild.roles.cache.find(x => x.position == role.position + 1); + let down = interaction.guild.roles.cache.find(x => x.position == role.position - 1); + + const embed = package.embeds.classic(interaction.user) + .setTitle(role.name) + .setColor(role.hexColor) + .addFields( + { + name: 'Identifiant', + value: role.id, + inline: true + }, + { + name: "Couleur", + value: (role.hexColor.startsWith('#') ? '':"#") + role.hexColor, + inline: true + }, + { + name: "Création", + value: ` ( )`, + inline: true + }, + {name: '\u200b', value: "\u200b", inline: false}, + { + name: 'Séparé des autres membres', + value: role.hoist ? '✅':'❌', + inline: true + }, + { + name: 'Mentionnable', + value: role.mentionable ? '✅':'❌', + inline: true + }, + { + name: "Membres avec ce rôle", + value: `${role.members.size} membre${role.members.size > 1 ? 's':''} (soit ~${((role.members.size * 100) / interaction.guild.members.cache.size).toFixed(0)}% du serveur)`, + inline: true + }, + { + name: "Position", + value: (up ? `<@&${up.id}> >` : '') + `<@&${role.id}>` + (down ? down.id == interaction.guild.id ? `> @everyone`:`> <@&${down.id}>`:''), + inline: false + } + ); + + interaction.editReply({ embeds: [ embed ] }).catch(() => {}); + } +} \ No newline at end of file diff --git a/slash-commands/information/servericon.js b/slash-commands/information/servericon.js new file mode 100644 index 0000000..7befe5e --- /dev/null +++ b/slash-commands/information/servericon.js @@ -0,0 +1,29 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + dev: false, + dm: false, + permissions: [], + systems: [] + }, + configs: { + name: 'servericon', + description: "Affiche l'icône du serveur" + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: (interaction) => { + if (!interaction.guild.icon) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Pas d'icône") + .setDescription(`${interaction.guild.name} n'a pas d'icône`) + .setColor('#ff0000') + ] }).catch(() => {}); + + interaction.reply({ content: interaction.guild.iconURL({ dynamic: true, size: 4096 }) }).catch(() => {}); + } +} \ No newline at end of file diff --git a/slash-commands/information/userinfo.js b/slash-commands/information/userinfo.js new file mode 100644 index 0000000..c831c32 --- /dev/null +++ b/slash-commands/information/userinfo.js @@ -0,0 +1,73 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + permissions: [], + systems: [], + dev: false, + dm: false + }, + configs: { + name: 'userinfo', + description: "Affiche les informations d'un utilisateur", + options: [ + { + name: 'utilisateur', + description: "Utilisateur dont vous voulez être informé", + type: 'USER', + required: false + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run:(interaction) => { + let member = interaction.options.getMember('utilisateur') ?? interaction.member; + let user = interaction.options.getUser('utilisateur') ?? interaction.user; + let roles = member.roles.cache.filter(x => x.id !== interaction.guild.id); + + const embed = package.embeds.classic(user) + .setTitle(user.tag) + .setDescription(`<@${user.id}>`) + .setThumbnail(user.displayAvatarURL({ dynamic: false, format: 'png' })) + .addFields( + { + name: 'Identifiant', + value: `\`${user.id}\``, + inline: true + }, + { + name: 'Pseudo', + value: member?.nick ?? 'Pas de pseudo', + inline: true + }, + { + name: 'Création du compte', + value: ` ( )`, + inline: false + }, + { + name: 'Date d\'arrivée', + value: ` ( )`, + inline: false + }, + { + name: `Rôle${roles.length > 0 ? 's':''}`, + value: roles.map(x => `<@&${x.id}>`).join(' '), + inline: false + }, + { + name: `Permission${member.permissions.has('ADMINISTRATOR') ? '' : member.permissions.length > 0 ? 's':''}`, + value: member.permissions.has('ADMINISTRATOR') ? 'Administrateur' : member.permissions.map(x => package.perms[x]).join(', '), + inline: false + } + ) + .setColor(member.displayHexColor) + + interaction.reply({ embeds: [ embed ] }).catch(() => {}); + } +}; \ No newline at end of file diff --git a/slash-commands/moderation/channel.js b/slash-commands/moderation/channel.js index 60770bf..3478fce 100644 --- a/slash-commands/moderation/channel.js +++ b/slash-commands/moderation/channel.js @@ -235,9 +235,9 @@ module.exports = { .setTitle("Salon crée") .setDescription(`Salon crée par <@${interaction.user.id}>`) .setColor('ORANGE') - ] }); + ] }).catch(() => {}); }; - }); + }).catch(() => {}); }; if (subcommand == 'supprimer') { let channel = interaction.options.get('salon')?.channel || interaction.channel; diff --git a/slash-commands/moderation/filtre-case-action.js b/slash-commands/moderation/filtre-case-action.js index ad20a95..b11d21d 100644 --- a/slash-commands/moderation/filtre-case-action.js +++ b/slash-commands/moderation/filtre-case-action.js @@ -1,6 +1,7 @@ const Discord = require('discord.js'); const functions = require('../../assets/functions'); const package = functions.package(); +const moment = require('moment'); module.exports = { configs: { @@ -41,6 +42,14 @@ module.exports = { { name: 'Débanissement', value: "unban" + }, + { + name: "Modification de pseudo", + value: 'pseudo modifié' + }, + { + name: "Réinitialisation de pseudo", + value: 'pseudo réinitialisé' } ] } @@ -77,7 +86,7 @@ module.exports = { for (let i = 0; i < req.length; i++) { const warn = req[i]; - now.addField(action, `<@${warn.user_id}>\n> Donné par <@${warn.mod_id}>\n> Raison: \`${warn.reason}\`\n> Date: `, false); + now.addField(action, `<@${warn.user_id}>\n> Donné par <@${warn.mod_id}>\n> Raison: ${warn.reason}\n> Date: `, false); pile = false; @@ -106,7 +115,7 @@ module.exports = { .setDescription(`Voici la liste des logs de ${action}`) req.forEach((warn) => { - embed.addField(action, `<@${warn.user_id}>\n> Donné par <@${warn.mod_id}>\n> Raison: \`${warn.reason}\`\n> Date: `, false); + embed.addField(action, `<@${warn.user_id}>\n> Donné par <@${warn.mod_id}>\n> Raison: ${warn.reason}\n> Date: `, false); }); interaction.reply({ embeds: [ embed ] }); diff --git a/slash-commands/moderation/infractions.js b/slash-commands/moderation/infractions.js new file mode 100644 index 0000000..64b335e --- /dev/null +++ b/slash-commands/moderation/infractions.js @@ -0,0 +1,95 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); +const moment = require('moment'); + +module.exports = { + help: { + cd: 5, + permissions: ['manage_guild'], + dev: false, + dm: false + }, + configs: { + name: 'infractions', + description: "Affiche toutes les infractions d'un utilisateur", + options: [ + { + name: 'membre', + description: "Membre dont vous voulez voir les infractions", + required: false, + type: 'USER' + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + let member = interaction.options.getMember('membre') ?? interaction.member; + await interaction.reply({ embeds: [ package.embeds.waitForDb(interaction.user) ] }).catch(() => {}); + + interaction.client.db.query(`SELECT * FROM mod_cases WHERE user_id="${member.id}" AND guild_id="${interaction.guild.id}"`, (err, req) => { + if (err) { + functions.sendError(err, 'query fetch at /infractions', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + return; + }; + + if (req.length === 0) return message.channel.send({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Pas d'infractions") + .setDescription(`<@${member.id}> n'a aucune infraction sur ce serveur.`) + .setColor('GREEN') + ] }); + + if (req.length > 5) { + let now = package.embeds.classic(interaction.user) + .setTitle("Infractions") + .setDescription(`Voici la liste des infractions de <@${member.id}>.`) + .setColor('ORANGE') + + var embeds = []; + let pile = false; + let count = 0; + + for (let i = 0; i < req.length; i++) { + const warn = req[i]; + + now.addField(`Infraction`, `${warn.action}\n> Donné par <@${warn.mod_id}>\n> Raison: ${warn.reason}\n> Date: `, false); + + pile = false; + + count++; + if (count === 5) { + count=0; + pile = true; + embeds.push(now); + + now = null; + now = package.embeds.classic(interaction.user) + .setTitle("Infractions") + .setDescription(`Voici la liste des infractions de <@${member.id}>.`) + .setColor('ORANGE') + + } + }; + + if (!pile) embeds.push(now); + + functions.pagination(interaction.user, 'none', embeds, `infractions de ${member.user.tag}`, interaction); + } else { + const embed = package.embeds.classic(interaction.user) + .setTitle("Infractions") + .setColor('ORANGE') + .setDescription(`<@${member.id}> a **${req.length}** infractions`) + .setColor('ORANGE') + + req.forEach((warn) => { + embed.addField(`Infraction`, `${warn.action}\n> Donné par <@${warn.mod_id}>\n> Raison: ${warn.reason}\n> Date: `, false); + }); + + interaction.editReply({ embeds: [ embed ] }); + }; + }) + } +} \ No newline at end of file diff --git a/slash-commands/moderation/kick.js b/slash-commands/moderation/kick.js index f742749..47e4eeb 100644 --- a/slash-commands/moderation/kick.js +++ b/slash-commands/moderation/kick.js @@ -69,6 +69,6 @@ module.exports = { member.kick(reason).catch(() => {}); functions.log(interaction.guild, kicked); - functions.addCase(interaction.guild, member.id, interaction.user.id, reason, 'kick'); + functions.addCase(interaction.guild.id, member.id, interaction.user.id, reason, 'kick'); } } \ No newline at end of file diff --git a/slash-commands/moderation/logs.js b/slash-commands/moderation/logs.js index dd157aa..c32ec02 100644 --- a/slash-commands/moderation/logs.js +++ b/slash-commands/moderation/logs.js @@ -50,11 +50,11 @@ module.exports = { return; }; - if (req.length === 0) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + if (req.length == 0) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("🚫 Logs de modération") .setDescription(`Il n'y a aucun log de modération.`) .setColor('ORANGE') - ] }); + ] }).catch(() => {}); if (req.length > 5) { let now = package.embeds.classic(interaction.user) @@ -84,7 +84,7 @@ module.exports = { .setTitle("Logs de modération") .setDescription(`Voici les logs de modération (**${req.length.toLocaleString('fr-DE')}** logs).`) .setColor('ORANGE') - } + }; }; if (!pile) embeds.push(now); @@ -120,7 +120,7 @@ module.exports = { const log = req[0]; const modlog = package.embeds.classic(interaction.user) - .setTitle(modlog.action) + .setTitle(log.action) .addFields( { name: "Membre", diff --git a/slash-commands/moderation/notes.js b/slash-commands/moderation/notes.js new file mode 100644 index 0000000..63debc1 --- /dev/null +++ b/slash-commands/moderation/notes.js @@ -0,0 +1,207 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + permissions: ['manage_guild'], + systems: [], + dev: false, + dm: false + }, + configs: { + name: 'note', + description: "Système de notes de membres", + options: [ + { + name: 'lire', + description: "Lis la note d'un membre", + type: 'SUB_COMMAND', + options: [ + { + name: "membre", + type: 'USER', + description: "Membre dont vous voulez lire la note", + required: true + } + ] + }, + { + name: "écrire", + description: "Écrit une note pour un membre", + type: 'SUB_COMMAND', + options: [ + { + name: 'membre', + description: "Membre que vous voulez noter", + required: true, + type: 'USER' + }, + { + name: 'note', + description: "Note à mettre sur le membre", + required: true, + type: 'STRING' + } + ] + }, + { + name: "supprimer", + description: "Supprime la note d'un membre", + type: 'SUB_COMMAND', + options: [ + { + name: "membre", + description: "Membre dont vous voulez supprimer la note", + type: 'USER', + required: true + } + ] + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + const subcommand = interaction.options.getSubcommand(); + let member = interaction.options.getMember('membre'); + const condition = `WHERE guild_id="${interaction.guild.id}" AND user_id="${member.id}"`; + + if (!functions.checkPerms({ interaction, member, mod: interaction.member, checkOwner: true, checkBot: true, checkSelfUser: true })) return; + await interaction.reply({ embeds: [ package.embeds.waitForDb(interaction.user) ] }).catch(() => {}); + + interaction.client.db.query(`SELECT note FROM notes ${condition}`, (err, req) => { + if (err) { + functions.sendError(err, 'query fetch at /note', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + return; + }; + + if (subcommand == 'lire') { + if (req.length == 0) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Pas de notes") + .setDescription(`<@${member.id}> n'a pas de note`) + .setColor('#ff0000') + ] }).catch(() => {}); + + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Note") + .setDescription('```' + req[0].note + '```') + .setColor(member.displayHexColor) + ] }).catch(() => {}); + }; + if (subcommand == 'écrire') { + let note = interaction.options.getString('note'); + if (note.length > 255) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Note trop longue") + .setDescription(`Votre description fait **${note.length}** caractères, le maximum étant de **255**`) + .setColor('#ff0000') + ] }).catch(() => {}); + + note = note.replace('"', '\\"'); + let sql = `INSERT INTO notes (guild_id, user_id, note) VALUES ("${interaction.guild.id}", "${member.id}", "${note}")`; + if (req.length > 0) sql = `UPDATE notes SET note="${note}" ${condition}`; + + interaction.client.db.query(sql, (error) => { + if (error) { + functions.sendError(error, 'query set at /notes écrire', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + console.log(error); + return; + }; + + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Note modifiée") + .setDescription(`La note de <@${member.id}> a été modifiée en \`\`\`${note}\`\`\``) + .setColor(member.displayHexColor) + ] }).catch(() => {}); + const fields = [ + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: "Membre", + value: `<@${member.id}> ( ${member.user.tag} \`${member.id}\` )`, + inline: true + } + ]; + if (req.length > 0) { + fields.push({ + name: "Avant", + value: req[0].note, + inline: false + }, + { + name: "Après", + value: note, + inline: true + }) + } else { + fields.push({ + name: "Note", + value: note, + inline: false + }); + }; + + functions.log(interaction.guild, package.embeds.classic(interaction.user) + .setTitle("Note modifiée") + .setDescription(`Une note a été modifiée`) + .addFields(fields) + .setColor('YELLOW') + ); + }); + }; + if (subcommand == 'supprimer') { + if (req.length == 0) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Pas de notes") + .setDescription(`<@${member.id}> n'a pas de note`) + .setColor('#ff0000') + ] }).catch(() => {}); + + interaction.client.db.query(`DELETE FROM notes ${condition}`, (error) => { + if (error) { + functions.sendError(error, 'query set at /notes supprimer', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + console.log(error); + return; + }; + + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Note modifiée") + .setDescription(`La note de <@${member.id}> a été supprimée`) + .setColor(member.displayHexColor) + ] }).catch(() => {}); + const fields = [ + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: "Membre", + value: `<@${member.id}> ( ${member.user.tag} \`${member.id}\` )`, + inline: true + }, + { + name: "Note", + value: req[0].note, + inline: false + } + ]; + + functions.log(interaction.guild, package.embeds.classic(interaction.user) + .setTitle("Note supprimée") + .setDescription(`Une note a été supprimée`) + .addFields(fields) + .setColor('#ff0000') + ); + }) + }; + }); + } +}; \ No newline at end of file diff --git a/slash-commands/moderation/nuke.js b/slash-commands/moderation/nuke.js new file mode 100644 index 0000000..b388020 --- /dev/null +++ b/slash-commands/moderation/nuke.js @@ -0,0 +1,109 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + systems: [], + dev: false, + dm: false, + permissions: ['manage_channels'] + }, + configs: { + name: 'nuke', + description: "Nuke un salon", + options: [ + { + name: "salon", + description: "Salon à nuker", + type: 'CHANNEL', + required: true + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + let channel = interaction.options.getChannel('salon'); + if (channel.id == interaction.channel.id) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Salon invalide") + .setDescription(`Je ne peux pas nuker ce salon, car c'est celui dans lequel la commande a été effectuée.`) + .setColor('#ff0000') + ] }).catch(() => {}); + + if (!['GUILD_NEWS', 'GUILD_TEXT'].includes(channel.type)) return interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Salon invalide") + .setDescription(`Je ne peux nuker que des salons textuels`) + .setColor('#ff0000') + ] }).catch(() => {}); + + await interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Nuke") + .setDescription(`Le salon <#${channel.id}> sera nuké `) + .setColor('YELLOW') + ], components: [ new Discord.MessageActionRow({ components: [ new Discord.MessageButton({ label: 'Annuler', style: 'DANGER', customId: 'cancel' }) ] }) ] }).catch(() => {}); + const msg = await interaction.fetchReply(); + const collector = msg.createMessageComponentCollector({ fliter: x => x.user.id == interaction.user.id, max: 1, time: 5000 }); + + collector.on('end', async(collected) => { + if (collected.size == 1) return interaction.editReply({ embeds: [ package.embeds.cancel() ], components: [] }).catch(() => {}); + await interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Nuke") + .setDescription(`Le salon <#${channel.id}> est en cours de nettoyage ${package.emojis.loading}`) + .setColor('YELLOW') + ], components: [] }).catch(() => {}); + + const propreties = { + name: channel.name, + topic: channel.topic, + nsfw: channel.nsfw, + permissionOverwrites: channel.permissionOverwrites.cache, + type: channel.type, + rawPosition: channel.rawPosition, + position: channel.position, + calculatedPosition: channel.calculatedPosition + }; + if(channel.parent) propreties.parent = channel.parent; + + await channel.delete().catch(() => {}); + const channelN = await (interaction.guild.channels.create(channel.name, propreties).catch(() => {})); + channelN.setPosition(propreties.position); + + if (!channelN) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Erreur") + .setDescription(`Une erreur a eu lieu lors du nuke du salon`) + .setColor('#ff0000') + ], components: [] }).catch(() => {}); + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Salon nuké") + .setDescription(`Le salon <#${channelN.id}> a été nuké`) + .setColor("#00ff00") + ], components: [] }).catch(() => {}); + + channelN.send({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Nuke") + .setDescription(`Le salon a bien été réinitialisé !`) + .setColor(interaction.guild.me.displayHexColor) + ], components: [] }).catch(() => {}); + functions.log(interaction.guild, package.embeds.classic(interaction.user) + .setTitle("Nuke") + .setDescription(`Un [salon](https://discord.com/channels/${interaction.guild.id}/${channelN.id}) a été nuké`) + .addFields( + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: "Salon", + value: `<#${channelN.id}> ( ${channel.name} \`${channel.id}\` )`, + inline: true + } + ) + .setColor('#ff0000') + ) + }) + } +} \ No newline at end of file diff --git a/slash-commands/moderation/pseudo.js b/slash-commands/moderation/pseudo.js new file mode 100644 index 0000000..dee1eaa --- /dev/null +++ b/slash-commands/moderation/pseudo.js @@ -0,0 +1,115 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + dev: false, + dm: false, + permissions: ['manage_nicknames'] + }, + configs: { + name: 'pseudo', + description: "Gère le pseudo d'un membre", + options: [ + { + name: "définir", + description: "Définit le pseudo d'un membre", + type: 'SUB_COMMAND', + options: [ + { + name: "pseudo", + description: "Pseudo à donner au membre", + required: true, + type: 'STRING' + }, + { + name: 'membre', + description: "Membre à renommer", + required: false, + type: 'USER' + } + ] + }, + { + name: "réinitialiser", + description: "Réinitialise le pseudo d'un membre", + type: 'SUB_COMMAND', + options: [ + { + name: 'membre', + required: false, + description: "Membre à renommer", + type: 'USER' + } + ] + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: (interaction) => { + const subcommand = interaction.options.getSubcommand(); + const member = interaction.options.getMember('membre') ?? interaction.member; + + let before = member.nickname ?? member.user.username; + if (!functions.checkPerms({ interaction, member, mod: interaction.member, checkBotCompare: true, checkOwner: true })) return; + let nickname = interaction.options.get('pseudo')?.value ?? null; + + member.setNickname(nickname).catch(() => {}); + + let reset = subcommand == 'réinitialiser'; + interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle(`Pseudo ${reset ? 'réinitialisé':'modifié'}`) + .setDescription(reset ? `Le pseudo de <@${member.id}> a été réinitialisé`: `Le pseudo de <@${member.id}> a été changé en ${nickname}`) + .setColor(member.displayHexColor) + ] }).catch(() => {}); + + let action = reset ? 'pseudo réinitialisé':'pseudo modifié'; + + const fields = [ + { + name: 'Modérateur', + value: `<@${interaction.user.id}> ( ${interaction.user.tag} ${interaction.user.id} )`, + inline: true + }, + { + name: 'Membre', + value: `<@${member.id}> ( ${member.user.tag} ${member.id} )`, + inline: true + } + ]; + let embed = package.embeds.classic(interaction.user) + .setTitle(functions.capitalize(action)) + .setDescription(`Le pseudo de <@${member.id}> a été réinitialisé`) + .setColor('#ff0000') + + if (!reset) { + embed.setDescription(`Le pseudo de <@${member.id}> a été modifié`) + fields.push({name: '\u200b', value: '\u200b', inline: false}) + fields.push({ + name: "Avant", + value: before, + inline: true + }, + { + name: 'Après', + value: nickname, + inline: true + }); + } else { + fields.push({ + name: 'Pseudo', + value: before, + inline: true + }); + }; + + embed.addFields(fields); + functions.log(interaction.guild, embed); + + functions.addCase(interaction.guild.id, member.id, interaction.user.id, reset ? `Ancien pseudo : ${before}` : `Ancien pseudo : ${before}\n\nNouveau pseudo : ${nickname}`, action.toLowerCase()); + } +}; \ No newline at end of file diff --git a/slash-commands/moderation/warn.js b/slash-commands/moderation/warn.js index 42f73eb..b92f315 100644 --- a/slash-commands/moderation/warn.js +++ b/slash-commands/moderation/warn.js @@ -64,6 +64,7 @@ module.exports = { interaction.reply({ embeds: [ warn ] }); member.user.send({ embeds: [ warn ] }).catch(() => {}); + functions.log(interaction.guild, warn); } } \ No newline at end of file diff --git a/slash-commands/usefull/commande.js b/slash-commands/usefull/commande.js index 9d6b4d1..47de3e5 100644 --- a/slash-commands/usefull/commande.js +++ b/slash-commands/usefull/commande.js @@ -129,7 +129,7 @@ module.exports = { embed.addFields( { name: "Options", - value: command.configs.options.map(opt => `\`${opt.name}\` (${optionsTypes[opt.type]}) : ${opt.description}${opt.required == true ? ' - **requis**':''}`).join('\n'), + value: command.configs.options.map(opt => `\`${opt.name}\` (${optionsTypes[opt.type]}) : ${opt.description}${opt.required == true ? ' - **requis**':' - **optionnel**'}`).join('\n'), inline: true } ); @@ -173,7 +173,7 @@ module.exports = { }, { name: 'Options', - value: subCommand.options?.length > 0 ? subCommand.options.map(opt => `\`${opt.name}\` (${optionsTypes[opt.type]}) : ${opt.description}${opt.required == true ? ' - **requis**':''}`).join('\n') : "Pas d'options", + value: subCommand.options?.length > 0 ? subCommand.options.map(opt => `\`${opt.name}\` (${optionsTypes[opt.type]}) : ${opt.description}${opt.required == true ? ' - **requis**':' - **optionnel**'}`).join('\n') : "Pas d'options", inline: false } ); @@ -241,7 +241,7 @@ module.exports = { embed.addFields( { name: "Options", - value: command.configs.options.map(opt => `\`${opt.name}\` (${optionsTypes[opt.type]}) : ${opt.description}${opt.required == true ? ' - **requis**':''}`).join('\n'), + value: command.configs.options.map(opt => `\`${opt.name}\` (${optionsTypes[opt.type]}) : ${opt.description}${opt.required == true ? ' - **requis**':' - **optionnel**'}`).join('\n'), inline: true } ); From 9d290f8ba47ff5c8fccaafe0c73657d4a116f61d Mon Sep 17 00:00:00 2001 From: Greensky Date: Fri, 19 Aug 2022 17:43:34 +0200 Subject: [PATCH 10/14] Update modules.js --- slash-commands/configuration/modules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slash-commands/configuration/modules.js b/slash-commands/configuration/modules.js index 7c8dd44..aae76d9 100644 --- a/slash-commands/configuration/modules.js +++ b/slash-commands/configuration/modules.js @@ -83,7 +83,7 @@ module.exports = { ); }; if (subcommand == 'afficher') { - let data = modules.map(x => ({ name: x.name, value: interaction.client.ModulesManager.checkModule({ module: x.value, guildId: interaction.guild.id }) == false ? '✅ activé':'❌ désactivé', inline: false })); + let data = modules.map(x => ({ name: x.name, value: interaction.client.ModulesManager.checkModule({ module: x.value, guildId: interaction.guild.id }) == true ? '✅ activé':'❌ désactivé', inline: false })); const embed = package.embeds.classic(interaction.user) .setTitle("Modules") From 7d04415e4dd1f781c2ecb9fd66a4ca0791bf0307 Mon Sep 17 00:00:00 2001 From: Greensky-gs <72513011+Greensky-gs@users.noreply.github.com> Date: Sun, 21 Aug 2022 15:35:48 +0200 Subject: [PATCH 11/14] 1.5.4 pre-update --- assets/data/data.json | 4 +- assets/data/modules.json | 2 +- assets/embeds.js | 11 +++++- assets/functions.js | 2 +- assets/managers/ModulesManager.js | 2 +- assets/managers/giveawayManager.js | 2 + assets/managers/mailsManager.js | 41 ++++++++++--------- events/channelDelete.js | 11 ++++++ events/messageCreateMention.js | 29 +++++++++++++- slash-commands/configuration/configs.js | 4 +- slash-commands/fun/choix.js | 11 +++--- slash-commands/fun/mixnames.js | 52 +++++++++++++++++++++++++ slash-commands/misc/mailbox.js | 18 +++++++++ 13 files changed, 155 insertions(+), 34 deletions(-) create mode 100644 slash-commands/fun/mixnames.js create mode 100644 slash-commands/misc/mailbox.js diff --git a/assets/data/data.json b/assets/data/data.json index 08365c8..1dc1bbc 100644 --- a/assets/data/data.json +++ b/assets/data/data.json @@ -7,9 +7,9 @@ "errorChannel": "839497213113270322", "botID": "918137973202112592", "contactChannel": "827790768272834580", - "version": "1.5.3", + "version": "1.5.4", "beta_token": "OTE4MTM3OTczMjAyMTEyNTky.G5q2vD.tYpVroN28ovgVIPXUKR9GDVqmZexUEwneXTTLk", - "beta": false, + "beta": true, "doc": "https://bit.ly/3c37f8V", "link": "https://bit.ly/3NUdTvE", "error": { diff --git a/assets/data/modules.json b/assets/data/modules.json index f740707..27954f5 100644 --- a/assets/data/modules.json +++ b/assets/data/modules.json @@ -22,7 +22,7 @@ { "name": "Informations", "value": "information", - "default": false + "default": true }, { "name": "Divers", diff --git a/assets/embeds.js b/assets/embeds.js index 53a599a..3094b83 100644 --- a/assets/embeds.js +++ b/assets/embeds.js @@ -1,5 +1,5 @@ const emojis = require('./data/emojis.json'); -const { MessageEmbed, User, Message, Interaction, GuildMember } = require('discord.js'); +const { MessageEmbed, User, Message, Interaction, GuildMember, Guild } = require('discord.js'); const collections = require('./data/collects'); const data = require('./data/data.json'); @@ -55,6 +55,7 @@ module.exports = { .setTimestamp() if (guild.icon) embed.setFooter({ text: guild.name, iconURL: guild.iconURL({ dynamic: true })}) + else embed.setFooter({ text: guild.name }) return embed; }, /** @@ -274,5 +275,13 @@ ${Edata.winners.length == 0 ? 'Pas de gagnants' : Edata.winners.map(w => `<@${w. .setDescription(`Ce giveaway n'est pas terminé`) .setColor('#ff0000') } + }, + /** + * @param {Guild} guild + */ + logs: (guild) => { + return new MessageEmbed() + .setFooter({ text: guild.name, iconURL: guild.icon ? guild.iconURL({ dynamic: true }) : guild.client.user.avatarURL() }) + .setTimestamp() } } \ No newline at end of file diff --git a/assets/functions.js b/assets/functions.js index 6719d79..cd14377 100644 --- a/assets/functions.js +++ b/assets/functions.js @@ -466,7 +466,7 @@ module.exports = { if (typeof content == "string") data.content = content; else data.embeds = [ content ]; - if (row !== undefined) data.components = [ row ]; + if (row !== undefined && row.components.length > 0) data.components = [ row ]; return await message.channel.send(data).catch(() => {}); }, diff --git a/assets/managers/ModulesManager.js b/assets/managers/ModulesManager.js index 3ff31a7..24639c3 100644 --- a/assets/managers/ModulesManager.js +++ b/assets/managers/ModulesManager.js @@ -125,7 +125,7 @@ class ModulesManager { checkModule(data) { if (!this.cache.has(data.guildId)) { this.checkIfExists(data.guildId); - return false; + return this.params.find(x => x.name == data.module).state; }; let x = this.cache.get(data.guildId); diff --git a/assets/managers/giveawayManager.js b/assets/managers/giveawayManager.js index 9f9b762..9285614 100644 --- a/assets/managers/giveawayManager.js +++ b/assets/managers/giveawayManager.js @@ -183,6 +183,8 @@ class GiveawaysManager { */ async reroll(messageId) { let gw = this.ended.get(messageId); + if (typeof gw.participants == 'string') gw = this.formatToObject(gw); + if (!gw && this.giveaways.has(messageId)) return 'not ended'; if (!gw) return 'no giveaway'; diff --git a/assets/managers/mailsManager.js b/assets/managers/mailsManager.js index 952c0c3..7991de2 100644 --- a/assets/managers/mailsManager.js +++ b/assets/managers/mailsManager.js @@ -319,20 +319,28 @@ class MailManager { } /** * @param {Discord.User} user - * @param {Discord.TextChannel} channel + * @param {Discord.TextChannel | 'none'} channel + * @param {Discord.CommandInteraction} interaction */ - mailbox(user, channel) { + mailbox(user, channel, interaction) { + let sendFnt = async(params) => { + if (channel !== 'none') { + return await channel.send(params).catch(() => {}); + } else { + if (interaction.replied) { + await interaction.editReply(params).catch(() => {}); + } else { + await interaction.reply(params).catch(() => {}); + } + return await interaction.fetchReply(); + }; + }; this.db.query(`SELECT * FROM mails WHERE user_id="${user.id}"`, (err, mails) => { - if (err) return channel.send({ embeds: [ pack.embeds.errorSQL(user) ] }) & console.log(err); - if (mails.length === 0) return channel.send({ embeds: [ pack.embeds.classic(user) - .setTitle("Pas de mails") - .setDescription(`Vous n'avez aucun mails`) - .setColor('ORANGE') - ] }); + if (err) return sendFnt({ embeds: [ pack.embeds.errorSQL(user) ] }) & console.log(err); const row = this.generateMailBoxButtons(); - channel.send({ embeds: [ pack.embeds.classic(user) + sendFnt({ embeds: [ pack.embeds.classic(user) .setTitle("Boite mail") .setDescription(`Bienvenue dans votre boite mail`) .setColor('ORANGE') @@ -372,16 +380,11 @@ class MailManager { text = `\n\n:bulb: Vous pouvez désactiver les notifications de mail avec \`/mail-notifs disable\``; } - this.db.query(`SELECT prefix FROM prefixes WHERE guild_id="${message.guild ? message.guild.id : 'no guild'}"`, (er, re) => { - if (er) return functions.sendError(er, 'mail notif select prefix', message.author); - - let prefix = re.length > 0 ? re[0].prefix : pack.configs.default_prefix; - message.channel.send({ embeds: [ pack.embeds.classic(message.author) - .setTitle("Nouveau mail") - .setDescription(`Vous avez ${req.length} mail${req.length > 1 ? 's':''} non-lu.\n\nUtilisez la commande \`${prefix}mail\` pour le${req.length > 1 ? 's':''} consulter.${text}`) - .setColor('ORANGE') - ] }).catch(() => {}); - }) + message.channel.send({ embeds: [ pack.embeds.classic(message.author) + .setTitle("Nouveau mail") + .setDescription(`Vous avez ${req.length} mail${req.length > 1 ? 's':''} non-lu.\n\nUtilisez la commande \`/mailbox\` pour le${req.length > 1 ? 's':''} consulter.${text}`) + .setColor('ORANGE') + ] }).catch(() => {}); }; }) }); diff --git a/events/channelDelete.js b/events/channelDelete.js index c56730c..2d17928 100644 --- a/events/channelDelete.js +++ b/events/channelDelete.js @@ -23,5 +23,16 @@ module.exports = { channel.client.db.query(`UPDATE configs SET herobrine_channel="${chan.id}" WHERE guild_id="${channel.guild.id}"`, (e) => e?console.log:null); }); }); + + channel.guild.fetchAuditLogs({ type: 'CHANNEL_DELETE' }).then((entries) => { + let log = package.embeds.log(channel.guild) + .setTitle("Salon supprimé") + if (entries.entries.first().target.id == channel.id) { + log.setDescription(`Un salon a été supprimé`) + .setColor('#ff0000') + } else { + + } + }) } }; \ No newline at end of file diff --git a/events/messageCreateMention.js b/events/messageCreateMention.js index aab0d29..fb01873 100644 --- a/events/messageCreateMention.js +++ b/events/messageCreateMention.js @@ -1,3 +1,4 @@ +const { MessageActionRow, MessageButton } = require('discord.js'); const functions = require('../assets/functions'); const package = functions.package(); @@ -27,7 +28,33 @@ module.exports = { reponse.setURL('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); }; - functions.reply(message, reponse); + let row = new MessageActionRow(); + let buttons = []; + if (functions.random(10, 0) == 5) { + let support = new MessageButton() + .setLabel('Serveur de support') + .setStyle('LINK') + .setURL(package.configs.support) + buttons.push(support); + }; + if (functions.random(10, 0) == 5) { + let invite = new MessageButton() + .setLabel('Inviter Oracle') + .setStyle('LINK') + .setURL(package.configs.link) + + if (buttons.length == 0) { + buttons.push(invite) + } else { + if (functions.random(100, 0) >= 50) { + buttons.push(invite); + } else { + buttons.unshift(invite); + }; + }; + }; + row.addComponents(buttons); + functions.reply(message, reponse, row); if (message.guild) { if (functions.random(10000, 0) === 794) { diff --git a/slash-commands/configuration/configs.js b/slash-commands/configuration/configs.js index 20c4bef..8e8ad65 100644 --- a/slash-commands/configuration/configs.js +++ b/slash-commands/configuration/configs.js @@ -33,7 +33,7 @@ module.exports = { choices: configs.data.map((conf) => ({name: conf.name, value: conf.param})) }, { - name: "binaire", + name: "état", description: "État binaire du paramètre (si binaire)", required: false, type: 'BOOLEAN' @@ -60,7 +60,7 @@ module.exports = { run: (interaction) => { const subcommand = interaction.options.getSubcommand(); let types = { - boolean: 'binaire', + boolean: 'état', text: 'texte', channel: 'salon' }; diff --git a/slash-commands/fun/choix.js b/slash-commands/fun/choix.js index 8f82f0c..2e4f61c 100644 --- a/slash-commands/fun/choix.js +++ b/slash-commands/fun/choix.js @@ -33,14 +33,13 @@ module.exports = { */ run: (interaction) => { let props = []; - for (let i = 0; i < 9; i++) { - let name = `proposition${i + 1}`; - - if (interaction.options.get(name)) props.push(interaction.options.get(name).value); + for (let i = 0; i < 10; i++) { + props.push(interaction.options.get(`proposition${i + 1}`)?.value); }; + props = props.filter(x => ![undefined, null].includes(x)); - let choice = props[functions.random(0, props.length)]; + let choice = props[functions.random(props.length, 0)]; - interaction.reply({ content: `Mon choix est **${choice}**` }); + interaction.reply({ content: `Mon choix est **${choice}**` }).catch(() => {}); } } \ No newline at end of file diff --git a/slash-commands/fun/mixnames.js b/slash-commands/fun/mixnames.js new file mode 100644 index 0000000..0b435a8 --- /dev/null +++ b/slash-commands/fun/mixnames.js @@ -0,0 +1,52 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + dev: false, + dm: true + }, + configs: { + name: 'mixnames', + description: "Fait le mélange de deux pseudos", + options: [ + { + name: "utilisateur1", + description: "Premier utilisateur", + type: 'USER', + required: true + }, + { + name: 'utilisateur2', + description: "Deuxième utilisateur", + type: 'USER', + required: false + }, + { + name: "texte", + description: "Texte à la place du deuxième utilisateur", + type: 'STRING', + required: false + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: (interaction) => { + let first = interaction.options.getUser('utilisateur1').username; + let second = interaction.options.getUser('utilisateur2')?.username ?? interaction.options.get('texte')?.value ?? interaction.client.user.username; + + let mixed = ""; + let firstPart = first.substring(0, (first.length / 2).toFixed(0)); + let secondPart = second.substring((second.length / 2).toFixed(0)); + + interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Mix") + .setDescription(`Le mix de ${first} et de ${second} est \`${firstPart + secondPart}\``) + .setColor(interaction?.member?.displayHexColor ?? interaction?.guild?.me?.displayHexColor ?? 'ORANGE') + ] }).catch(() => {}); + } +} \ No newline at end of file diff --git a/slash-commands/misc/mailbox.js b/slash-commands/misc/mailbox.js new file mode 100644 index 0000000..a1bca5d --- /dev/null +++ b/slash-commands/misc/mailbox.js @@ -0,0 +1,18 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + dm: true, + dev: false + }, + configs: { + name: "mailbox", + description: "Ouvre votre boite mail" + }, + run: (interaction) => { + interaction.client.MailsManager.mailbox(interaction.user, 'none', interaction); + } +} \ No newline at end of file From 890f21252a58adcd0c4bc38d03edb91b007fd80b Mon Sep 17 00:00:00 2001 From: Greensky Date: Sun, 21 Aug 2022 17:58:58 +0200 Subject: [PATCH 12/14] 1.5.4 Update part 1 --- assets/data/channelTypes.json | 10 + assets/data/configs.json | 6 + assets/data/data.json | 1 + assets/data/objectgw.ts.ignore | 10 - assets/functions.js | 3 +- commands.json | 2597 +++++++++++++++++++++++++ events/channelCreate.js | 45 + events/channelDelete.js | 29 +- events/messageCreateMention.js | 20 +- events/messageDelete.js | 38 + events/ready.js | 3 +- slash-commands/fun/joke.js | 20 +- slash-commands/information/botinfo.js | 81 + slash-commands/misc/suggestion.js | 38 +- slash-commands/moderation/channel.js | 41 + slash-commands/usefull/help.js | 2 +- 16 files changed, 2912 insertions(+), 32 deletions(-) create mode 100644 assets/data/channelTypes.json delete mode 100644 assets/data/objectgw.ts.ignore create mode 100644 commands.json create mode 100644 events/channelCreate.js create mode 100644 slash-commands/information/botinfo.js diff --git a/assets/data/channelTypes.json b/assets/data/channelTypes.json new file mode 100644 index 0000000..4f04e43 --- /dev/null +++ b/assets/data/channelTypes.json @@ -0,0 +1,10 @@ +{ + "GUILD_TEXT": "salon textuel", + "GUILD_NEWS": "salon des annonces", + "GUILD_VOICE": "salon vocal", + "GUILD_STAGE_VOICE": "salon des conférences", + "GUILD_PRIVATE_THREAD": "fil privé", + "GUILD_PUBLIC_THREAD": "fil public", + "GUILD_NEWS_THREAD": "fil de salon des annonces", + "GUILD_CATEGORY": "catégorie" +} \ No newline at end of file diff --git a/assets/data/configs.json b/assets/data/configs.json index 8695d7a..e1da856 100644 --- a/assets/data/configs.json +++ b/assets/data/configs.json @@ -149,6 +149,12 @@ "type": "boolean", "description": "Active oudésactive le système de tickets", "param": "ticket_enable" + }, + { + "name": "Salon des suggestions", + "type": "channel", + "description": "Configurer le salon des suggestions", + "param": "suggest_channel" } ] } \ No newline at end of file diff --git a/assets/data/data.json b/assets/data/data.json index 1dc1bbc..1ae7949 100644 --- a/assets/data/data.json +++ b/assets/data/data.json @@ -12,6 +12,7 @@ "beta": true, "doc": "https://bit.ly/3c37f8V", "link": "https://bit.ly/3NUdTvE", + "topgg": "https://bit.ly/3pvu2hr", "error": { "id": "976874250260578404", "token": "LC8ld5MDeX1wh-DAtnhnBf9SsI8wevos2Q9N0PiqkhKWhzaT3G934trT9DqbCRQlLKkd", diff --git a/assets/data/objectgw.ts.ignore b/assets/data/objectgw.ts.ignore deleted file mode 100644 index 034e645..0000000 --- a/assets/data/objectgw.ts.ignore +++ /dev/null @@ -1,10 +0,0 @@ -export class gw { - public reward: String; - public winnerCount: Number; - public endsAt: Number; - public guild_id: String; - public channel_id: String; - public message_id: String; - public hoster_id: String; - public path: String; -}; \ No newline at end of file diff --git a/assets/functions.js b/assets/functions.js index cd14377..a7d3f82 100644 --- a/assets/functions.js +++ b/assets/functions.js @@ -25,7 +25,8 @@ module.exports = { perms: require('./data/perms.json'), personnages: require('./rpg/personnages.json'), configs: require('./data/data.json'), - rubis: require('./rpg/rubis.json') + rubis: require('./rpg/rubis.json'), + channelTypes: require('./data/channelTypes.json') } return package; diff --git a/commands.json b/commands.json new file mode 100644 index 0000000..896a110 --- /dev/null +++ b/commands.json @@ -0,0 +1,2597 @@ +[ + [ + { + "name": "config", + "description": "Configure Oracle sur votre serveur", + "options": [ + { + "name": "paramètres", + "description": "Affiche les paramètres configurables", + "type": "SUB_COMMAND" + }, + { + "name": "configurer", + "description": "Configure un paramètre", + "type": "SUB_COMMAND", + "options": [ + { + "name": "paramètre", + "description": "Paramètre à configurer", + "type": "STRING", + "required": true, + "choices": [ + { + "name": "Logs", + "value": "logs_enable" + }, + { + "name": "Messages d'arrivées", + "value": "join_enable" + }, + { + "name": "Messages de départs", + "value": "leave_enable" + }, + { + "name": "Salon d'arrivée", + "value": "join_channel" + }, + { + "name": "Salon de départ", + "value": "leave_channel" + }, + { + "name": "Message d'arrivée", + "value": "join_message" + }, + { + "name": "Message de départ", + "value": "leave_message" + }, + { + "name": "Salon des logs", + "value": "logs_channel" + }, + { + "name": "Salon de niveaux", + "value": "level_channel" + }, + { + "name": "Message de niveau", + "value": "level_message" + }, + { + "name": "Roles d'arrivée", + "value": "roles_enable" + }, + { + "name": "Système de GBan", + "value": "gban_enable" + }, + { + "name": "Système de compteur", + "value": "counting_enable" + }, + { + "name": "Salon de comptage", + "value": "counting_channel" + }, + { + "name": "Système de tickets", + "value": "ticket_enable" + }, + { + "name": "Salon des suggestions", + "value": "suggest_channel" + } + ] + }, + { + "name": "état", + "description": "État binaire du paramètre (si binaire)", + "required": false, + "type": "BOOLEAN" + }, + { + "name": "texte", + "description": "Texte du paramètre (si texte)", + "required": false, + "type": "STRING" + }, + { + "name": "salon", + "description": "Salon du paramètre (si salon)", + "type": "CHANNEL", + "required": false + } + ] + } + ] + }, + { + "name": "modules", + "description": "Gère les modules", + "options": [ + { + "name": "configurer", + "description": "Configure un module", + "type": "SUB_COMMAND", + "options": [ + { + "name": "module", + "description": "Module à configurer", + "type": "STRING", + "required": true, + "choices": [ + { + "name": "Économie", + "value": "economy" + }, + { + "name": "Modération", + "value": "moderation" + }, + { + "name": "Utilitaires", + "value": "usefull" + }, + { + "name": "Amusement", + "value": "fun" + }, + { + "name": "Informations", + "value": "information" + }, + { + "name": "Divers", + "value": "misc" + }, + { + "name": "Niveaux", + "value": "levels" + } + ] + }, + { + "name": "état", + "description": "État du module", + "type": "BOOLEAN", + "required": true + } + ] + }, + { + "name": "afficher", + "description": "Affiche l'état des modules sur le serveur", + "type": "SUB_COMMAND" + } + ] + } + ], + [ + { + "name": "admin-coins", + "description": "Gère les OraCoins sur le serveur", + "options": [ + { + "name": "ajouter", + "description": "Ajoute des OraCoins à un utilisateur", + "type": "SUB_COMMAND", + "options": [ + { + "name": "utilisateur", + "description": "Utilisateur à qui ajouter des OraCoins", + "type": "USER", + "required": true + }, + { + "name": "montant", + "description": "Montant d'OraCoins à ajouter", + "type": "INTEGER", + "required": true + } + ] + }, + { + "name": "retirer", + "description": "Retire des OraCoins à un utilisateur", + "type": "SUB_COMMAND", + "options": [ + { + "name": "utilisateur", + "description": "Utilisateur à qui retirer des OraCoins", + "type": "USER", + "required": true + }, + { + "name": "montant", + "description": "Montant d'OraCoins à ajouter", + "type": "INTEGER", + "required": true + } + ] + }, + { + "name": "réinitialiser", + "description": "Réinitialiser des OraCoins", + "type": "SUB_COMMAND_GROUP", + "options": [ + { + "name": "utilisateur", + "description": "Réinitialiser des OraCoins à un utilisateur", + "type": "SUB_COMMAND", + "options": [ + { + "name": "utilisateur", + "description": "Utilisateur à qui ajouter des OraCoins", + "type": "USER", + "required": true + } + ] + }, + { + "name": "serveur", + "description": "Réinitialiser les OraCoins du serveur", + "type": "SUB_COMMAND" + } + ] + } + ] + }, + { + "name": "banque", + "description": "Utilisez votre banque", + "options": [ + { + "name": "déposer", + "description": "Déposer des OraCoins dans votre banque", + "type": "SUB_COMMAND", + "options": [ + { + "name": "montant", + "description": "Montant d'OraCoins à déposer", + "type": "INTEGER", + "required": true + } + ] + }, + { + "name": "retirer", + "description": "Retirer des OraCoins de votre banque", + "type": "SUB_COMMAND", + "options": [ + { + "name": "montant", + "description": "Montant d'OraCoins à retirer", + "type": "INTEGER", + "required": true + } + ] + } + ] + }, + { + "name": "daily", + "description": "Récupère votre récompense quotidienne" + }, + { + "name": "inventaire", + "description": "Affiche votre inventaire" + }, + { + "name": "leaderboard", + "description": "Affiche le classement des OraCoins du serveur" + }, + { + "name": "loto", + "description": "Gère un loto sur le serveur", + "options": [ + { + "name": "gérer", + "description": "Gère le loto", + "type": "SUB_COMMAND_GROUP", + "options": [ + { + "name": "démarrer", + "description": "Lance le loto sur le serveur", + "type": "SUB_COMMAND", + "options": [ + { + "name": "récompense", + "description": "Récompense en OraCoins du loto", + "type": "INTEGER", + "required": true + }, + { + "name": "gagnants", + "description": "Nombre de numéro gagnants à tirer (minimum 5)", + "type": "INTEGER", + "required": true + }, + { + "name": "complémentaires", + "description": "Nombre de numéro complémentaires à tirer (minimum 2)", + "type": "INTEGER", + "required": true + }, + { + "name": "temps", + "description": "Temps avant la fin du loto (ex: 1d)", + "type": "STRING", + "required": true + } + ] + }, + { + "name": "tirage", + "description": "Fait le tirage du loto", + "type": "SUB_COMMAND" + } + ] + }, + { + "name": "participer", + "description": "Participez au loto en cours", + "type": "SUB_COMMAND", + "options": [ + { + "name": "gagnants", + "description": "Les numéro gagnants que vous jouez (ex: 15 68 46 75 12)", + "type": "STRING", + "required": true + }, + { + "name": "complémentaires", + "description": "Les numéro complémentaires que vous jouez (ex: 94 60)", + "required": true, + "type": "STRING" + } + ] + } + ] + }, + { + "name": "pay", + "description": "Donne un montant d'OraCoins à un utilisateur", + "options": [ + { + "name": "montant", + "type": "INTEGER", + "required": true, + "description": "Montant d'argent que vous voulez donner" + }, + { + "name": "utilisateur", + "required": true, + "description": "Utilisateur à qui vous voulez donner l'argent", + "type": "USER" + } + ] + }, + { + "name": "shop", + "description": "Utilisez le système de magasin", + "options": [ + { + "name": "item", + "type": "SUB_COMMAND_GROUP", + "description": "Ajoute des items au magasin", + "options": [ + { + "name": "ajouter", + "type": "SUB_COMMAND", + "description": "Ajouter un item au magasin", + "options": [ + { + "name": "nom", + "description": "Nom de l'item", + "type": "STRING", + "required": true + }, + { + "name": "type", + "description": "Type de l'item", + "type": "STRING", + "required": true, + "choices": [ + { + "name": "Rôle", + "value": "role" + }, + { + "name": "Étiquette", + "value": "text" + } + ] + }, + { + "name": "prix", + "description": "Prix de l'item", + "type": "INTEGER", + "required": true + }, + { + "name": "quantité", + "description": "Nombre d'items que vous voulez ajouter (laissez vide pour illimité)", + "type": "INTEGER", + "required": false + }, + { + "name": "description", + "description": "Description de l'étiquette (si étiquette)", + "type": "STRING", + "required": false + }, + { + "name": "role", + "description": "Rôle (si l'item est un rôle)", + "type": "ROLE", + "required": false + } + ] + }, + { + "name": "supprimer", + "description": "Supprime un item du magasin", + "type": "SUB_COMMAND", + "options": [ + { + "name": "identifiant", + "description": "Identifiant de l'item à supprimer", + "type": "STRING", + "required": true + } + ] + } + ] + }, + { + "name": "view", + "description": "Affiche le magasin", + "type": "SUB_COMMAND" + }, + { + "name": "acheter", + "description": "Achète un item du shop", + "type": "SUB_COMMAND", + "options": [ + { + "name": "identifiant", + "type": "STRING", + "description": "Identifiant de l'item à acheter", + "required": true + } + ] + } + ] + }, + { + "name": "stats", + "description": "Affiche les statistiques économiques d'un utilisateur", + "options": [ + { + "name": "utilisateur", + "description": "Utilisateur dont vous voulez voir les statistiques", + "required": false, + "type": "USER" + } + ] + }, + { + "name": "échange", + "description": "Effectue un échange", + "options": [ + { + "name": "utilisateur", + "description": "Utilisateur avec qui vous voulez échanger", + "type": "USER", + "required": true + }, + { + "name": "item", + "type": "STRING", + "required": true, + "description": "Nom de l'item que vous voulez échanger" + }, + { + "name": "prix", + "type": "INTEGER", + "required": true, + "description": "Prix auxquel vous souhaitez échanger" + } + ] + }, + { + "name": "weekly", + "description": "Récupère votre récompense hebdomadaire" + } + ], + [ + { + "name": "8ball", + "description": "Demande quelque chose à la boule de crystal", + "options": [ + { + "name": "question", + "description": "Question à poser à la boule de crystal", + "type": "STRING", + "required": true + }, + { + "name": "discret", + "description": "Fait en sorte que seul vous voie ce message.", + "required": false, + "autocomplete": false, + "type": "BOOLEAN" + } + ] + }, + { + "name": "choix", + "description": "Fais un choix parmis les propositions", + "options": [ + { + "name": "proposition1", + "description": "Définissez la proposition 1", + "type": "STRING", + "required": true + }, + { + "name": "proposition2", + "description": "Définissez la proposition 2", + "type": "STRING", + "required": true + }, + { + "name": "proposition3", + "description": "Définissez la proposition 3", + "type": "STRING", + "required": false + }, + { + "name": "proposition4", + "description": "Définissez la proposition 4", + "type": "STRING", + "required": false + }, + { + "name": "proposition5", + "description": "Définissez la proposition 5", + "type": "STRING", + "required": false + }, + { + "name": "proposition6", + "description": "Définissez la proposition 6", + "type": "STRING", + "required": false + }, + { + "name": "proposition7", + "description": "Définissez la proposition 7", + "type": "STRING", + "required": false + }, + { + "name": "proposition8", + "description": "Définissez la proposition 8", + "type": "STRING", + "required": false + }, + { + "name": "proposition9", + "description": "Définissez la proposition 9", + "type": "STRING", + "required": false + } + ] + }, + { + "name": "demineur", + "description": "Lance une partie de démineur", + "options": [ + { + "name": "discret", + "description": "Fait en sorte que seul vous coie ce message", + "required": false, + "autocomplete": false, + "type": "BOOLEAN" + } + ] + }, + { + "name": "game", + "description": "Joue a des jeux sur Oracle", + "options": [ + { + "name": "démineur", + "description": "Joue au démineur sur Oracle", + "type": "SUB_COMMAND" + }, + { + "name": "number", + "description": "Joue à guess the number", + "type": "SUB_COMMAND_GROUP", + "options": [ + { + "name": "multijoueur", + "description": "Joue en multijoueur", + "type": "SUB_COMMAND", + "options": [ + { + "name": "max", + "description": "Nombre maximum", + "type": "INTEGER", + "required": false + }, + { + "name": "min", + "description": "Nombre minimum", + "type": "INTEGER", + "required": false + } + ] + }, + { + "name": "solo", + "description": "Joue en solo", + "type": "SUB_COMMAND", + "options": [ + { + "name": "max", + "description": "Nombre maximum", + "type": "INTEGER", + "required": false + }, + { + "name": "min", + "description": "Nombre minimum", + "type": "INTEGER", + "required": false + } + ] + } + ] + }, + { + "name": "morpion", + "description": "Joue au morpion contre Oracle", + "type": "SUB_COMMAND" + }, + { + "name": "roulette-russe", + "description": "Joue à la roulette russe", + "type": "SUB_COMMAND", + "options": [ + { + "name": "expulsion", + "description": "⚠ Si vous perdez vous serez expulsé.", + "required": false, + "type": "BOOLEAN" + } + ] + }, + { + "name": "shifumi", + "description": "Joue au shifumi contre Oracle", + "type": "SUB_COMMAND", + "options": [ + { + "name": "signe", + "type": "STRING", + "required": true, + "description": "Signe que vous jouez", + "choices": [ + { + "name": "pierre", + "value": "0", + "emoji": "✊" + }, + { + "name": "papier", + "value": "1", + "emoji": "📜" + }, + { + "name": "ciseaux", + "value": "2", + "emoji": "✂" + } + ] + } + ] + }, + { + "name": "8ball", + "description": "Pose une question au bot", + "type": "SUB_COMMAND", + "options": [ + { + "name": "question", + "description": "La question que vous voulez me poser", + "required": true, + "type": "STRING" + } + ] + }, + { + "name": "dés", + "description": "Joue au dés", + "type": "SUB_COMMAND", + "options": [ + { + "name": "nombre", + "type": "INTEGER", + "description": "Nombre de dés (maximum 64)", + "required": false + }, + { + "name": "faces", + "type": "INTEGER", + "description": "Nombre de faces sur les dés", + "required": false + } + ] + } + ] + }, + { + "name": "blague", + "description": "Affiche une blague aléatoire", + "options": [ + { + "name": "global", + "description": "Blague de type global", + "type": "SUB_COMMAND" + }, + { + "name": "dev", + "description": "Blague de type dev", + "type": "SUB_COMMAND" + }, + { + "name": "dark", + "description": "Blague de type dark", + "type": "SUB_COMMAND" + }, + { + "name": "limit", + "description": "Blague de type limit", + "type": "SUB_COMMAND" + }, + { + "name": "beauf", + "description": "Blague de type beauf", + "type": "SUB_COMMAND" + }, + { + "name": "blondes", + "description": "Blague de type blondes", + "type": "SUB_COMMAND" + } + ] + }, + { + "name": "meme", + "description": "Envoie un meme" + }, + { + "name": "mixnames", + "description": "Fait le mélange de deux pseudos", + "options": [ + { + "name": "utilisateur1", + "description": "Premier utilisateur", + "type": "USER", + "required": true + }, + { + "name": "utilisateur2", + "description": "Deuxième utilisateur", + "type": "USER", + "required": false + }, + { + "name": "texte", + "description": "Texte à la place du deuxième utilisateur", + "type": "STRING", + "required": false + } + ] + }, + { + "name": "pof", + "description": "Fait un pile ou face", + "options": [ + { + "name": "pari", + "description": "Le choix du côté de la pièce", + "type": "STRING", + "required": true, + "choices": [ + { + "name": "Pile", + "value": "pile" + }, + { + "name": "Face", + "value": "face" + } + ] + } + ] + }, + { + "name": "cryptage", + "description": "Crypte ou décrypte un texte selon votre clé", + "options": [ + { + "name": "action", + "description": "Action à effectuer sur votre texte", + "required": true, + "type": "STRING", + "choices": [ + { + "name": "Chiffrer", + "value": "code" + }, + { + "name": "Déchiffrer", + "value": "decode" + } + ] + }, + { + "name": "texte", + "type": "STRING", + "required": true, + "description": "Texte à examiner" + }, + { + "name": "clé", + "required": true, + "description": "Clé de chiffrage/déchiffrage", + "type": "STRING" + } + ] + } + ], + [ + { + "name": "avatar", + "description": "Affiche la photo de profil d'une personne", + "options": [ + { + "name": "utilisateur", + "description": "Utilisateur dont vous voulez voir la photo de profil", + "type": "USER", + "required": false, + "autocomplete": false + } + ] + }, + { + "name": "botinfo", + "description": "Affiche quelques informations sur le bot" + }, + { + "name": "channelinfo", + "description": "Affiche les informations d'un salon", + "options": [ + { + "name": "salon", + "description": "Salon dont vous voulez soutirer des informations", + "required": false, + "type": "CHANNEL" + } + ] + }, + { + "name": "roleinfo", + "description": "Affiche les informations d'un rôle", + "options": [ + { + "name": "rôle", + "description": "Rôle dont vous voulez vous informez", + "required": false, + "type": "ROLE" + } + ] + }, + { + "name": "servericon", + "description": "Affiche l'icône du serveur" + }, + { + "name": "serverinfo", + "description": "Affiche les informations du serveur" + }, + { + "name": "userinfo", + "description": "Affiche les informations d'un utilisateur", + "options": [ + { + "name": "utilisateur", + "description": "Utilisateur dont vous voulez être informé", + "type": "USER", + "required": false + } + ] + } + ], + [ + { + "name": "classement", + "description": "Affiche le classement des niveaux du serveur" + }, + { + "name": "rank", + "description": "Affiche les informations de niveau d'un utilisateur", + "options": [ + { + "name": "utilisateur", + "description": "Utilisateur concerné", + "required": false, + "autocomplete": false, + "type": "USER" + }, + { + "name": "discret", + "description": "Fait en sorte que seul vous voie ce message.", + "required": false, + "autocomplete": false, + "type": "BOOLEAN" + } + ] + } + ], + [ + { + "name": "cmdpersonnalisée", + "description": "Gère les commandes personnalisées", + "options": [ + { + "name": "créer", + "description": "Créer une commande personnalisée", + "type": "SUB_COMMAND", + "options": [ + { + "name": "nom", + "description": "Nom de la commande", + "type": "STRING", + "required": true + }, + { + "name": "réponse", + "description": "Réponse du bot", + "type": "STRING", + "required": true + } + ] + }, + { + "name": "supprimer", + "description": "Supprime une commande personnalisée", + "type": "SUB_COMMAND", + "options": [ + { + "name": "nom", + "description": "Nom de la commande", + "type": "STRING", + "required": true + } + ] + }, + { + "name": "liste", + "description": "Affiche la liste des commandes personnalisées", + "type": "SUB_COMMAND" + } + ] + }, + { + "name": "documentation", + "description": "Envoie le lien de la documentation" + }, + { + "name": "drop", + "description": "Fait un drop dans le salon", + "options": [ + { + "name": "récompense", + "description": "Récompense du drop", + "type": "STRING", + "required": true + } + ] + }, + { + "name": "generatemdp", + "description": "Génère un mot de passe aléatoire", + "options": [ + { + "type": "INTEGER", + "name": "taille", + "description": "Nombre de caractères", + "required": true + }, + { + "type": "BOOLEAN", + "name": "majuscules", + "description": "Le mot de passe doit-il inclure des majuscules ?", + "required": true + }, + { + "type": "BOOLEAN", + "name": "nombres", + "description": "Le mot de passe contient-il des nombres ?", + "required": true + }, + { + "type": "BOOLEAN", + "name": "speciaux", + "description": "Le mot de passe doit-il contenir des caractères spéciaux", + "required": true + } + ] + }, + { + "name": "giveaway", + "description": "Giveaways", + "options": [ + { + "name": "create", + "description": "Crée un giveaway", + "type": "SUB_COMMAND", + "options": [ + { + "name": "récompense", + "description": "récompense données au(x) gagnant(s)", + "required": true, + "type": "STRING", + "autocomplete": false + }, + { + "name": "temps", + "type": "STRING", + "description": "Temps du giveaway", + "autocomplete": false, + "required": true + }, + { + "name": "gagnants", + "type": "INTEGER", + "required": true, + "autocomplete": false, + "description": "Nombre de gagnants au giveaway" + }, + { + "name": "salon", + "type": "CHANNEL", + "required": false, + "autocomplete": false, + "description": "Le salon dans lequel aura lieu le giveaway" + }, + { + "name": "bonus", + "type": "STRING", + "required": false, + "description": "Identifiants des rôles bonus (séparés par un espace)" + }, + { + "name": "requis", + "type": "STRING", + "required": false, + "description": "Identifiants des rôles requis (séparés par un espace)" + }, + { + "name": "interdits", + "type": "STRING", + "required": false, + "description": "Identifiants des rôles interdits (séparés par un espace)" + } + ] + }, + { + "name": "reroll", + "description": "Reroll un giveaway", + "type": "SUB_COMMAND", + "options": [ + { + "name": "id", + "description": "identifiant du message du giveaway dans le salon", + "required": true, + "type": "STRING", + "autocomplete": false + } + ] + }, + { + "name": "end", + "description": "Met fin à un giveaway", + "type": "SUB_COMMAND", + "options": [ + { + "name": "id", + "description": "Identifiant du message du giveaway dans le salon", + "required": true, + "autocomplete": false, + "type": "STRING" + } + ] + } + ] + }, + { + "name": "google", + "description": "Fait une recherche google", + "options": [ + { + "name": "recherche", + "required": true, + "autocomplete": false, + "description": "Le texte que vous souhaitez rechercher.", + "type": "STRING" + }, + { + "name": "discret", + "description": "Fait en sorte que seul vous voie ce message", + "autocomplete": false, + "required": false, + "type": "BOOLEAN" + } + ] + }, + { + "name": "mail-notifs", + "description": "Active ou désactive les notifications de mail", + "options": [ + { + "name": "enable", + "description": "Active les notifications de mail", + "type": "SUB_COMMAND" + }, + { + "name": "disable", + "description": "Désactive les notifications de mail", + "type": "SUB_COMMAND" + } + ] + }, + { + "name": "mail", + "description": "Envoie un mail à un utilisateur", + "options": [ + { + "name": "utilisateur", + "required": true, + "type": "USER", + "description": "Utilisateur qui recevra le mail" + }, + { + "name": "objet", + "description": "Objet du mail", + "required": true, + "type": "STRING" + }, + { + "name": "contenu", + "description": "Contenu du mail", + "type": "STRING", + "required": true + } + ] + }, + { + "name": "mailbox", + "description": "Ouvre votre boite mail" + }, + { + "name": "ping", + "description": "Pong", + "options": [ + { + "name": "discret", + "description": "Fait en sorte que vous seul voyez ce message.", + "type": "BOOLEAN", + "required": false, + "autocomplete": false + } + ] + }, + { + "name": "say", + "description": "Fait dire quelque chose à Oracle", + "options": [ + { + "name": "texte", + "type": "STRING", + "required": true, + "description": "Texte à faire répéter" + } + ] + }, + { + "name": "suggestion", + "description": "Fait une suggestion dans le salon de la commande", + "options": [ + { + "name": "suggestion", + "description": "Suggestion à proposer", + "type": "STRING", + "required": true + } + ] + } + ], + [ + { + "name": "autorole", + "description": "Gère les rôles donnés automatiquement à l'arrivée sur le serveur", + "options": [ + { + "name": "ajouter", + "description": "Ajoute un rôle automatiquement donné", + "type": "SUB_COMMAND", + "options": [ + { + "name": "rôle", + "description": "Rôle à ajouter", + "type": "ROLE", + "required": true + } + ] + }, + { + "name": "retirer", + "description": "Retirer un rôle automatiquement donné", + "type": "SUB_COMMAND", + "options": [ + { + "name": "rôle", + "description": "Rôle à retirer", + "type": "ROLE", + "required": true + } + ] + }, + { + "name": "liste", + "description": "Affiche la liste des rôles automatiques", + "type": "SUB_COMMAND" + } + ] + }, + { + "name": "ban", + "description": "Banni un membre pour une raison donnée", + "options": [ + { + "name": "membre", + "required": true, + "description": "L'utilisateur que vous voulez bannir", + "autocomplete": false, + "type": "USER" + }, + { + "name": "raison", + "required": true, + "description": "Raison du bannissement", + "autocomplete": false, + "type": "STRING" + } + ] + }, + { + "name": "censure", + "description": "Censure le pseudo d'un membre", + "options": [ + { + "name": "membre", + "description": "Membre à censurer", + "type": "USER", + "required": true + }, + { + "name": "raison", + "description": "Raison de la censure", + "type": "STRING", + "required": true + } + ] + }, + { + "name": "salon", + "description": "Gère les salons", + "options": [ + { + "name": "créer", + "type": "SUB_COMMAND", + "description": "Créer un salon", + "options": [ + { + "name": "nom", + "description": "Nom du salon", + "type": "STRING", + "required": true, + "autocomplete": false + }, + { + "name": "type", + "description": "Type du salon", + "type": "STRING", + "required": true, + "autocomplete": false, + "choices": [ + { + "name": "texte", + "value": "GUILD_TEXT" + }, + { + "name": "vocal", + "value": "GUILD_VOICE" + }, + { + "name": "catégorie", + "value": "GUILD_CATEGORY" + } + ] + }, + { + "name": "catégorie", + "type": "CHANNEL", + "required": false, + "autocomplete": false, + "description": "Catégorie dans laquelle le salon sera crée" + } + ] + }, + { + "name": "supprimer", + "type": "SUB_COMMAND", + "description": "Supprimer un salon", + "options": [ + { + "name": "salon", + "description": "Le salon à supprimer", + "required": false, + "type": "CHANNEL" + } + ] + }, + { + "name": "renommer", + "type": "SUB_COMMAND", + "description": "Renommer un salon", + "options": [ + { + "name": "nom", + "description": "Nouveau nom du salon", + "required": true, + "type": "STRING" + }, + { + "name": "salon", + "description": "Salon à renommer", + "required": false, + "type": "CHANNEL" + } + ] + }, + { + "name": "déplacer", + "type": "SUB_COMMAND", + "description": "Déplacer un salon.", + "options": [ + { + "name": "places", + "description": "Nombre de places pour déplacer le salon. Rentrez un nombre négatif ou un nombre positif.", + "required": true, + "type": "NUMBER" + }, + { + "name": "salon", + "description": "Salon à déplacer", + "required": false, + "type": "CHANNEL" + } + ] + }, + { + "name": "catégoriser", + "type": "SUB_COMMAND", + "description": "Catégoriser un salon", + "options": [ + { + "name": "catégorie", + "description": "Catégorie qui pendra le salon", + "required": false, + "type": "CHANNEL" + }, + { + "name": "salon", + "description": "Salon à catégoriser", + "required": false, + "type": "CHANNEL" + } + ] + }, + { + "name": "décrire", + "type": "SUB_COMMAND", + "description": "Configure la description d'un salon", + "options": [ + { + "name": "salon", + "description": "Salon à décrire", + "type": "CHANNEL", + "required": false + }, + { + "name": "description", + "type": "STRING", + "required": false, + "description": "Description à donner au salon (laisser vide pour réinitialiser)" + } + ] + }, + { + "name": "identifier", + "description": "Affiche l'identifiant d'un salon", + "type": "SUB_COMMAND", + "options": [ + { + "name": "salon", + "description": "Salon à identifier", + "type": "CHANNEL", + "required": false + }, + { + "name": "embed", + "description": "Affiche la réponse sous forme d'embed (plus compliqué pour copier/coller)", + "required": false, + "type": "BOOLEAN" + } + ] + } + ] + }, + { + "name": "clear", + "description": "Supprime un nombre de messages dans le salon", + "options": [ + { + "name": "messages", + "description": "Nombre de messages à supprimer", + "required": true, + "type": "INTEGER" + } + ] + }, + { + "name": "demote", + "description": "Dérank un utilisateur", + "options": [ + { + "name": "highest", + "description": "Enlève le rôle le plus haut d'un utilisateur", + "type": "SUB_COMMAND", + "options": [ + { + "name": "utilisateur", + "type": "USER", + "description": "Utilisateur à dérank", + "required": true + }, + { + "name": "raison", + "type": "STRING", + "description": "raison", + "required": true + } + ] + }, + { + "name": "full", + "description": "Retire tout les rôles d'un utilisateur", + "type": "SUB_COMMAND", + "options": [ + { + "name": "utilisateur", + "type": "USER", + "description": "Utilisateur à dérank", + "required": true + }, + { + "name": "raison", + "type": "STRING", + "description": "raison", + "required": true + } + ] + } + ] + }, + { + "name": "edit-case", + "description": "Modifie un log de modération sur le serveur", + "options": [ + { + "name": "numéro", + "description": "Numéro du log", + "required": true, + "autocomplete": false, + "type": "INTEGER" + }, + { + "name": "raison", + "description": "La nouvelle raison du log", + "required": true, + "type": "STRING", + "autocomplete": false + } + ] + }, + { + "name": "filtre-case-action", + "description": "Affiche tout les logs de modération concernant une action précisée", + "options": [ + { + "name": "action", + "description": "L'action a afficher", + "required": true, + "autocomplete": false, + "type": "STRING", + "choices": [ + { + "name": "Bannissements", + "value": "ban" + }, + { + "name": "Avertissements", + "value": "avertissement" + }, + { + "name": "Réduction au silence", + "value": "mute" + }, + { + "name": "Expulsion", + "value": "kick" + }, + { + "name": "Démutage", + "value": "unmute" + }, + { + "name": "Suppression d'avertissements", + "value": "unwarn" + }, + { + "name": "Débanissement", + "value": "unban" + }, + { + "name": "Modification de pseudo", + "value": "pseudo modifié" + }, + { + "name": "Réinitialisation de pseudo", + "value": "pseudo réinitialisé" + } + ] + } + ] + }, + { + "name": "infractions", + "description": "Affiche toutes les infractions d'un utilisateur", + "options": [ + { + "name": "membre", + "description": "Membre dont vous voulez voir les infractions", + "required": false, + "type": "USER" + } + ] + }, + { + "name": "kick", + "description": "Expulse un membre du serveur", + "options": [ + { + "name": "utilisateur", + "description": "La personne à expulser du serveur", + "type": "USER", + "required": true, + "autocomplete": false + }, + { + "name": "raison", + "description": "Raison de l'expulsion", + "type": "STRING", + "required": true, + "autocomplete": false + } + ] + }, + { + "name": "logs", + "description": "Gère les logs du serveur", + "options": [ + { + "name": "afficher", + "description": "Affiche les logs du serveur", + "type": "SUB_COMMAND" + }, + { + "name": "identifier", + "description": "Affiche un log spécifique", + "type": "SUB_COMMAND", + "options": [ + { + "name": "identifiant", + "description": "Identifiant du log que vous voulez voir", + "type": "STRING", + "required": true + } + ] + } + ] + }, + { + "name": "mute", + "description": "Mute un membre du serveur", + "options": [ + { + "name": "membre", + "type": "USER", + "description": "Membre à muter", + "required": true + }, + { + "name": "raison", + "type": "STRING", + "description": "Raison du mute", + "required": true + }, + { + "name": "durée", + "type": "INTEGER", + "description": "Durée du mute", + "required": false, + "choices": [ + { + "name": "5 minutes", + "value": 300000 + }, + { + "name": "10 minutes", + "value": 600000 + }, + { + "name": "20 minutes", + "value": 1200000 + }, + { + "name": "30 minutes", + "value": 1800000 + }, + { + "name": "45 minutes", + "value": 2700000 + }, + { + "name": "1 heure", + "value": 3600000 + }, + { + "name": "2 heures", + "value": 7200000 + }, + { + "name": "6 heures", + "value": 21600000 + }, + { + "name": "1 jour", + "value": 86400000 + } + ] + } + ] + }, + { + "name": "note", + "description": "Système de notes de membres", + "options": [ + { + "name": "lire", + "description": "Lis la note d'un membre", + "type": "SUB_COMMAND", + "options": [ + { + "name": "membre", + "type": "USER", + "description": "Membre dont vous voulez lire la note", + "required": true + } + ] + }, + { + "name": "écrire", + "description": "Écrit une note pour un membre", + "type": "SUB_COMMAND", + "options": [ + { + "name": "membre", + "description": "Membre que vous voulez noter", + "required": true, + "type": "USER" + }, + { + "name": "note", + "description": "Note à mettre sur le membre", + "required": true, + "type": "STRING" + } + ] + }, + { + "name": "supprimer", + "description": "Supprime la note d'un membre", + "type": "SUB_COMMAND", + "options": [ + { + "name": "membre", + "description": "Membre dont vous voulez supprimer la note", + "type": "USER", + "required": true + } + ] + } + ] + }, + { + "name": "nuke", + "description": "Nuke un salon", + "options": [ + { + "name": "salon", + "description": "Salon à nuker", + "type": "CHANNEL", + "required": true + } + ] + }, + { + "name": "prefixe", + "description": "Configure ou modifie le préfixe de votre serveur", + "options": [ + { + "name": "view", + "description": "Affiche le préfixe du serveur", + "type": "SUB_COMMAND" + }, + { + "name": "set", + "description": "Configure le préfixe du bot sur votre serveur", + "type": "SUB_COMMAND", + "options": [ + { + "name": "nouveau_prefixe", + "description": "Nouveau préfixe du bot", + "type": "STRING", + "required": true + } + ] + } + ] + }, + { + "name": "pseudo", + "description": "Gère le pseudo d'un membre", + "options": [ + { + "name": "définir", + "description": "Définit le pseudo d'un membre", + "type": "SUB_COMMAND", + "options": [ + { + "name": "pseudo", + "description": "Pseudo à donner au membre", + "required": true, + "type": "STRING" + }, + { + "name": "membre", + "description": "Membre à renommer", + "required": false, + "type": "USER" + } + ] + }, + { + "name": "réinitialiser", + "description": "Réinitialise le pseudo d'un membre", + "type": "SUB_COMMAND", + "options": [ + { + "name": "membre", + "required": false, + "description": "Membre à renommer", + "type": "USER" + } + ] + } + ] + }, + { + "name": "role-react", + "description": "Configure les rôles à réaction", + "options": [ + { + "name": "envoyer", + "description": "Envoie le message qui aura les réactions", + "type": "SUB_COMMAND", + "options": [ + { + "name": "embed", + "type": "BOOLEAN", + "required": true, + "description": "Définit si le message est un embed" + }, + { + "name": "contenu", + "type": "STRING", + "required": true, + "description": "Définit le contenu du message" + }, + { + "name": "salon", + "description": "Salon ou sera envoyé le message", + "required": true, + "type": "CHANNEL" + }, + { + "name": "titre", + "description": "Titre de l'embed (si embed)", + "required": false, + "type": "STRING" + }, + { + "name": "couleur", + "description": "Couleur de l'embed (si embed)", + "required": false, + "type": "STRING" + }, + { + "name": "image", + "description": "URL de l'image de l'embed (si embed)", + "type": "STRING", + "required": false + } + ] + }, + { + "name": "ajouter", + "description": "Ajoute un rôle", + "type": "SUB_COMMAND", + "options": [ + { + "name": "role", + "description": "Rôle à donner", + "type": "ROLE", + "required": true + }, + { + "name": "identifiant", + "description": "Identifiant du message (celui envoyé par la commande /role-react envoyer)", + "type": "STRING", + "required": true + }, + { + "name": "salon", + "description": "Salon du message", + "required": true, + "type": "CHANNEL" + }, + { + "name": "description", + "description": "Description du rôle à réaction", + "type": "STRING", + "required": true + } + ] + }, + { + "name": "supprime", + "description": "Supprime un rôle", + "type": "SUB_COMMAND", + "options": [ + { + "name": "role", + "description": "Rôle à enlever", + "type": "ROLE", + "required": true + }, + { + "name": "identifiant", + "description": "Identifiant du message (celui envoyé par la commande /role-react envoyer)", + "type": "STRING", + "required": true + }, + { + "name": "salon", + "description": "Salon du message", + "required": true, + "type": "CHANNEL" + } + ] + } + ] + }, + { + "name": "role", + "description": "Gère les rôles", + "options": [ + { + "name": "créer", + "description": "Créer un rôle", + "type": "SUB_COMMAND", + "options": [ + { + "name": "nom", + "description": "Nom du rôle", + "required": true, + "autocomplete": false, + "type": "STRING" + } + ] + }, + { + "name": "delete", + "description": "Supprime un rôle", + "type": "SUB_COMMAND", + "options": [ + { + "name": "role", + "required": true, + "autocomplete": false, + "type": "ROLE", + "description": "Le rôle à supprimer" + } + ] + }, + { + "name": "add", + "description": "Ajoute un rôle à un membre", + "type": "SUB_COMMAND", + "options": [ + { + "name": "utilisateur", + "description": "L'utilisateur qui aura le rôle.", + "required": true, + "autocomplete": false, + "type": "USER" + }, + { + "name": "role", + "description": "Le rôle à ajouter", + "required": true, + "autocomplete": false, + "type": "ROLE" + } + ] + }, + { + "name": "remove", + "description": "Retire un rôle à un membre", + "type": "SUB_COMMAND", + "options": [ + { + "name": "utilisateur", + "description": "Utilisateur qui perdra le rôle", + "required": true, + "autocomplete": false, + "type": "USER" + }, + { + "name": "role", + "description": "Le rôle à retirer", + "required": true, + "autocomplete": false, + "type": "ROLE" + } + ] + }, + { + "name": "renommer", + "description": "Renomme un rôle", + "type": "SUB_COMMAND", + "options": [ + { + "name": "rôle", + "description": "Rôle à renommer", + "required": true, + "type": "ROLE" + }, + { + "name": "nom", + "description": "Nom du rôle", + "required": true, + "type": "STRING" + } + ] + }, + { + "name": "déplacer", + "description": "Déplace un rôle", + "type": "SUB_COMMAND", + "options": [ + { + "name": "rôle", + "description": "Rôle à déplacer", + "required": true, + "type": "ROLE" + }, + { + "name": "places", + "description": "Nombre de places pour déplacer le rôle. Rentrez un nombre négatif ou un nombre positif.", + "required": true, + "type": "INTEGER" + } + ] + }, + { + "name": "coloriser", + "description": "Colorise un rôle", + "type": "SUB_COMMAND", + "options": [ + { + "name": "rôle", + "description": "Rôle à coloriser", + "type": "ROLE", + "required": true + }, + { + "name": "couleur", + "description": "Couleur à mettre sur le rôle. Donnez la en hexadecimal (ex: #ff0000)", + "type": "STRING", + "required": true + } + ] + }, + { + "name": "identifier", + "description": "Affiche l'identifiant d'un rôle", + "type": "SUB_COMMAND", + "options": [ + { + "name": "rôle", + "description": "Rôle à identifier", + "type": "ROLE", + "required": true + }, + { + "name": "embed", + "description": "Affiche la réponse sous forme d'embed (plus compliqué pour copier/coller)", + "required": false, + "type": "BOOLEAN" + } + ] + }, + { + "name": "permissions", + "description": "Gère les permissions d'un rôle", + "type": "SUB_COMMAND_GROUP", + "options": [ + { + "name": "accorder", + "description": "Accorde une permission à un rôle", + "type": "SUB_COMMAND", + "options": [ + { + "name": "rôle", + "description": "Rôle à gérer", + "type": "ROLE", + "required": true + }, + { + "name": "permission", + "description": "Permission à accorder", + "required": true, + "type": "STRING" + } + ] + }, + { + "name": "refuser", + "description": "Refuse une permission à un rôle", + "type": "SUB_COMMAND", + "options": [ + { + "name": "rôle", + "description": "Rôle à gérer", + "required": true, + "type": "ROLE" + }, + { + "name": "permission", + "description": "Permission à refuser", + "type": "STRING", + "required": true + } + ] + }, + { + "name": "liste", + "description": "Affiche la liste des permissions accordables", + "type": "SUB_COMMAND" + } + ] + } + ] + }, + { + "name": "snipe", + "description": "Affiche le dernier message supprimé dans le salon", + "options": [ + { + "name": "numéro", + "description": "Le numéro du snipe", + "required": false, + "autocomplete": false, + "type": "INTEGER" + } + ] + }, + { + "name": "ticket-create", + "description": "Crée un ticket" + }, + { + "name": "ticket", + "description": "Interagissez avec le système de tickets", + "options": [ + { + "name": "create", + "description": "Créer un ticket", + "type": "SUB_COMMAND_GROUP", + "options": [ + { + "name": "panel", + "description": "Créer un panel de ticket", + "type": "SUB_COMMAND", + "options": [ + { + "name": "sujet", + "description": "Sujet du panel de ticket", + "type": "STRING", + "required": true + }, + { + "name": "salon", + "description": "Salon du panel de ticket", + "required": true, + "type": "CHANNEL" + }, + { + "name": "description", + "description": "Description du ticket, son objectif.", + "required": true, + "type": "STRING" + }, + { + "name": "image", + "description": "Image affichée sur l'embe du ticket", + "required": false, + "type": "STRING" + } + ] + }, + { + "name": "ticket", + "description": "Créer un ticket", + "type": "SUB_COMMAND", + "options": [ + { + "name": "sujet", + "description": "Sujet du ticket", + "required": true, + "type": "STRING" + } + ] + } + ] + }, + { + "name": "rename", + "description": "Renomme le ticket", + "type": "SUB_COMMAND", + "options": [ + { + "name": "nom", + "description": "Nouveau nom du ticket", + "required": true, + "type": "STRING" + } + ] + }, + { + "name": "save", + "description": "Sauvegarde le ticket", + "type": "SUB_COMMAND" + }, + { + "name": "add", + "description": "Ajoute un utilisateur au ticket", + "type": "SUB_COMMAND", + "options": [ + { + "name": "utilisateur", + "description": "Utilisateur à ajouter au ticket", + "type": "USER", + "required": true + } + ] + }, + { + "name": "remove", + "description": "Retire un utilisateur du ticket", + "type": "SUB_COMMAND", + "options": [ + { + "name": "utilisateur", + "description": "Utilisateur à retirer du ticket", + "required": true, + "type": "USER" + } + ] + }, + { + "name": "close", + "description": "Ferme le ticket", + "type": "SUB_COMMAND" + }, + { + "name": "delete", + "description": "Supprime le ticket", + "type": "SUB_COMMAND" + }, + { + "name": "reopen", + "description": "Réouvre le ticket", + "type": "SUB_COMMAND" + }, + { + "name": "modrole", + "description": "Gère les rôles de modérateurs de tickets", + "type": "SUB_COMMAND_GROUP", + "options": [ + { + "name": "ajouter", + "type": "SUB_COMMAND", + "description": "Ajoute un rôle de modérateur de tickets", + "options": [ + { + "name": "rôle", + "type": "ROLE", + "description": "Rôle à ajouter", + "required": true + } + ] + }, + { + "name": "retirer", + "type": "SUB_COMMAND", + "description": "Retirer un rôle de modérateur de tickets", + "options": [ + { + "name": "rôle", + "type": "ROLE", + "description": "Rôle à retirer", + "required": true + } + ] + }, + { + "name": "liste", + "description": "Affiche la liste des rôles de modérateurs de tickets", + "type": "SUB_COMMAND" + } + ] + } + ] + }, + { + "name": "unwarn", + "description": "Enlève un avertissement à un utilisateur", + "options": [ + { + "name": "membre", + "type": "USER", + "description": "Membre qui aura un avertissement en moins", + "required": true + }, + { + "name": "identifiant", + "description": "Identifiant de l'avertissement (visible avec /logs afficher)", + "type": "INTEGER", + "required": true + } + ] + }, + { + "name": "warn", + "description": "Avertit un utilisateur", + "options": [ + { + "name": "utilisateur", + "description": "L'utilisateur en question", + "required": true, + "autocomplete": false, + "type": "USER" + }, + { + "name": "raison", + "description": "Raison de l'avertissement", + "required": true, + "autocomplete": false, + "type": "STRING" + } + ] + } + ], + [ + { + "name": "commande", + "description": "Affiche les informations concernant une commande", + "options": [ + { + "name": "commande", + "description": "Nom de la commande", + "required": true, + "autocomplete": false, + "type": "STRING" + }, + { + "name": "discret", + "description": "Fait en sorte que seul vous voit la réponse.", + "required": false, + "autocomplete": false, + "type": "BOOLEAN" + } + ] + }, + { + "name": "contact", + "description": "Prend contact avec mon développeur", + "options": [ + { + "name": "bug", + "description": "Le bug à signaler", + "type": "STRING", + "required": true, + "autocomplete": false + } + ] + }, + { + "name": "csc", + "description": "Gère les slash commandes personnalisées", + "options": [ + { + "name": "créer", + "description": "Créer une slash commande personnalisée", + "type": "SUB_COMMAND", + "options": [ + { + "name": "nom", + "description": "Nom de la commande", + "type": "STRING", + "required": true + }, + { + "name": "réponse", + "description": "Réponse de la commande", + "required": true, + "type": "STRING" + }, + { + "name": "embed", + "description": "Si la réponse doit être un embed", + "required": true, + "type": "BOOLEAN" + }, + { + "name": "titre", + "description": "Titre de l'embed", + "required": false, + "type": "STRING" + }, + { + "name": "couleur", + "description": "Couleur de l'embed (optionnel)", + "required": false, + "type": "STRING" + } + ] + }, + { + "name": "supprimer", + "description": "Supprimer une slash commande personnalisée", + "type": "SUB_COMMAND", + "options": [ + { + "name": "nom", + "description": "nom de la commande", + "required": true, + "type": "STRING" + } + ] + }, + { + "name": "liste", + "description": "Liste des slash commandes personnalisées du serveur", + "type": "SUB_COMMAND" + }, + { + "name": "variables", + "description": "Variables disponibles en réponse", + "type": "SUB_COMMAND" + } + ] + }, + { + "name": "avis", + "description": "Envoie votre avis sur le bot", + "options": [ + { + "name": "avis", + "description": "Votre avis", + "type": "STRING", + "required": true, + "autocomplete": false + } + ] + }, + { + "name": "help", + "description": "Affiche la page d'aide des commandes", + "options": [ + { + "name": "discret", + "description": "Fait en sorte que vous seul voyez ce message.", + "type": "BOOLEAN", + "required": false, + "autocomplete": false + } + ] + }, + { + "name": "invite", + "description": "Envoie le lien d'invitation du bot" + }, + { + "name": "rappel", + "description": "Gère vos rappels", + "options": [ + { + "name": "ajouter", + "description": "Ajoute un rappel", + "type": "SUB_COMMAND", + "options": [ + { + "name": "temps", + "description": "Le temps avant le rappel", + "type": "STRING", + "required": true + }, + { + "name": "contenu", + "description": "Contenu du rappel", + "required": true, + "type": "STRING" + } + ] + }, + { + "name": "retirer", + "description": "Retire un rappel", + "type": "SUB_COMMAND", + "options": [ + { + "name": "numéro", + "description": "Numéro du rappel à supprimer", + "type": "NUMBER", + "required": true + } + ] + }, + { + "name": "liste", + "type": "SUB_COMMAND", + "description": "Affiche la liste de vos rappels" + } + ] + }, + { + "name": "sondage", + "description": "Fait un sondage", + "options": [ + { + "name": "question", + "type": "STRING", + "required": true, + "description": "Question du sondage" + }, + { + "name": "proposition_1", + "type": "STRING", + "description": "Proposition 1 du sondage", + "required": true + }, + { + "name": "proposition_2", + "type": "STRING", + "description": "Proposition 2 du sondage", + "required": true + }, + { + "name": "proposition_3", + "type": "STRING", + "description": "Proposition 3 du sondage", + "required": false + }, + { + "name": "proposition_4", + "type": "STRING", + "description": "Proposition 4 du sondage", + "required": false + }, + { + "name": "proposition_5", + "type": "STRING", + "description": "Proposition 5 du sondage", + "required": false + }, + { + "name": "proposition_6", + "type": "STRING", + "description": "Proposition 6 du sondage", + "required": false + }, + { + "name": "proposition_7", + "type": "STRING", + "description": "Proposition 7 du sondage", + "required": false + }, + { + "name": "proposition_8", + "type": "STRING", + "description": "Proposition 8 du sondage", + "required": false + }, + { + "name": "proposition_9", + "type": "STRING", + "description": "Proposition 9 du sondage", + "required": false + }, + { + "name": "proposition_10", + "type": "STRING", + "description": "Proposition 10 du sondage", + "required": false + } + ] + }, + { + "name": "support", + "description": "Envoie le lien du serveur de support" + } + ] +] \ No newline at end of file diff --git a/events/channelCreate.js b/events/channelCreate.js new file mode 100644 index 0000000..65fac55 --- /dev/null +++ b/events/channelCreate.js @@ -0,0 +1,45 @@ +const Discord = require('discord.js'); +const functions = require('../assets/functions'); +const package = functions.package(); + +module.exports = { + event: 'channelCreate', + /** + * @param {Discord.NonThreadGuildBasedChannel} channel + */ + execute: (channel) => { + if (!channel.guild) return; + + channel.guild.fetchAuditLogs({ type: 'CHANNEL_CREATE' }).then((entries) => { + let log = package.embeds.log(channel.guild) + .setTitle("Salon crée") + .setColor('#00ff00') + + if (entries.entries.first().target.id == channel.id) { + const mod = entries.entries.first().executor; + log.setDescription(`Un [salon](https://discord.com/channels/${channel.guild.id}/${channel.id}) a été crée`) + .addFields( + { + name: "Modérateur", + value: `<@${mod.id}> ( ${mod.tag} \`${mod.id}\` )`, + inline: true + }, + { + name: 'Salon', + value: `<#${channel.id}> ( ${package.channelTypes[channel.type]} \`${channel.id}\` )`, + inline: true + }, + { + name: "Date", + value: ` ( )`, + inline: true + } + ) + } else { + log.setDescription(`Le salon <#${channel.id}> ( ${package.channelTypes[channel.type]} \`${channel.id}\` ) a été crée`) + }; + + functions.log(channel.guild, log); + }); + } +} \ No newline at end of file diff --git a/events/channelDelete.js b/events/channelDelete.js index 2d17928..57ac54b 100644 --- a/events/channelDelete.js +++ b/events/channelDelete.js @@ -27,12 +27,33 @@ module.exports = { channel.guild.fetchAuditLogs({ type: 'CHANNEL_DELETE' }).then((entries) => { let log = package.embeds.log(channel.guild) .setTitle("Salon supprimé") + .setColor('#ff0000') + if (entries.entries.first().target.id == channel.id) { + const mod = entries.entries.first().executor; log.setDescription(`Un salon a été supprimé`) - .setColor('#ff0000') + .addFields( + { + name: "Modérateur", + value: `<@${mod.id}> ( ${mod.tag} \`${mod.id}\` )`, + inline: true + }, + { + name: 'Salon', + value: `${channel.name} ( ${package.channelTypes[channel.type]} \`${channel.id}\` )`, + inline: true + }, + { + name: "Date", + value: ` ( )`, + inline: true + } + ) } else { - - } - }) + log.setDescription(`Le salon ${channel.name} ( ${package.channelTypes[channel.type]} \`${channel.id}\` ) a été supprimé`) + }; + + functions.log(channel.guild, log); + }); } }; \ No newline at end of file diff --git a/events/messageCreateMention.js b/events/messageCreateMention.js index fb01873..98b4a9d 100644 --- a/events/messageCreateMention.js +++ b/events/messageCreateMention.js @@ -15,8 +15,8 @@ module.exports = { }; let size = require('../assets/data/splash.json').length; - let splash = splashes[functions.random(splashes.length, 0)].replace('{username}', message.author.username); - splash.replace('{size}', size); + let splash = splashes[functions.random(splashes.length, 0)].replace('{username}', message.author.username) + .replace('{size}', size); const reponse = package.embeds.classic(message.author) .setTitle(splash) @@ -53,6 +53,22 @@ module.exports = { }; }; }; + if (functions.random(10, 0) == 5 && buttons.length < 2) { + let topgg = new MessageButton() + .setLabel('Page top.gg') + .setStyle('LINK') + .setURL(package.configs.topgg) + + if (buttons.length == 0) { + buttons.push(topgg) + } else { + if (functions.random(100, 0) >= 50) { + buttons.push(topgg); + } else { + buttons.unshift(topgg); + }; + }; + } row.addComponents(buttons); functions.reply(message, reponse, row); diff --git a/events/messageDelete.js b/events/messageDelete.js index c6bd257..e8dd9c3 100644 --- a/events/messageDelete.js +++ b/events/messageDelete.js @@ -16,5 +16,43 @@ module.exports = { } else { message.channel.snipes.set(message.channel.snipes.length, message); }; + + let log = package.embeds.classic(message.author) + .setTitle("Message supprimé") + .setColor('#ff0000') + .setDescription(`Un message de <@${message.author.id}> a été supprimé`) + .addFields( + { + name: "Message", + value: `\`${message.id}\`. Envoyé ( ) par <@${message.author.id}> ( ${message.author.tag} \`${message.author.id}\` )`, + inline: true + }, + { + name: "Salon", + value: `<#${message.channel.id}> ( ${message.channel.name} \`${message.channel.id}\` )`, + inline: true + }, + { + name: "Contenu", + value: message.content ?? message.embeds[0]?.description ?? "Pas de contenu", + inline: false + } + ); + message.guild.fetchAuditLogs({ type: 'MESSAGE_DELETE' }).then((result) => { + if (result.entries.first()?.target.id == message.id) { + const mod = result.entries.first().executor; + if (mod) { + const content = log.fields.splice(2, 1, { + name: "Modérateur", + value: `<@${mod.id}> ( ${mod.tag} \`${mod.id}\` )`, + inline: true + }); + + log.addField(content); + }; + }; + + functions.log(message.guild, log); + }) } } \ No newline at end of file diff --git a/events/ready.js b/events/ready.js index 5dfa2ce..0a2fe88 100644 --- a/events/ready.js +++ b/events/ready.js @@ -113,7 +113,8 @@ module.exports = { {name: "Passage en slash commandes !", type: 'WATCHING'}, {name: "Mentionnez moi pour des informations", type: 'WATCHING'}, {name: "%members% membres", type: 'WATCHING'}, - {name: 'une vidéo', type: 'STREAMING', url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'} + {name: 'une vidéo', type: 'STREAMING', url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'}, + {name: "ma page top.gg", type: 'WATCHING'} ]; setInterval(() => { diff --git a/slash-commands/fun/joke.js b/slash-commands/fun/joke.js index 38f69ba..980542f 100644 --- a/slash-commands/fun/joke.js +++ b/slash-commands/fun/joke.js @@ -4,6 +4,14 @@ const package = functions.package(); const blagueAPI = require('blagues-api'); const blagues = new blagueAPI(package.configs['blagues-api-token']); +const values = { + global: 'général', + dev: "développeur", + dark: "noir", + limit: "limite", + beauf: 'beauf', + blondes: 'blondes' +}; module.exports = { help: { @@ -16,13 +24,21 @@ module.exports = { configs: { name: 'blague', description: "Affiche une blague aléatoire", - options: Object.keys(blagues.categories).map((x) => ({name: x.toLowerCase(), description: `Blague de type ${x.toLowerCase()}`, type: 'SUB_COMMAND'})) + options: [ + { + name: 'type', + description: "Type de la blague", + required: true, + type: 'STRING', + choices: Object.keys(values).map(x => ({ name: x, value: values[x] })) + } + ] }, /** * @param {Discord.CommandInteraction} interaction */ run: async(interaction) => { - const type = interaction.options.getSubcommand().toUpperCase(); + const type = interaction.options.getString('type'); const blague = await blagues.randomCategorized(blagues.categories[type]); const embed = package.embeds.classic(interaction.user) diff --git a/slash-commands/information/botinfo.js b/slash-commands/information/botinfo.js new file mode 100644 index 0000000..f78a906 --- /dev/null +++ b/slash-commands/information/botinfo.js @@ -0,0 +1,81 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + dev: false, + dm: true + }, + configs: { + name: 'botinfo', + description: "Affiche quelques informations sur le bot" + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + await interaction.client.guilds.fetch(); + + const embed = package.embeds.classic(interaction.user) + .setThumbnail(interaction.client.user.avatarURL()) + .setTitle("Bot informations") + .setDescription(`Voici quelques informations me concernant`) + .addFields( + { + name: "Version", + value: package.configs.version, + inline: true + }, + { + name: "Serveurs", + value: interaction.client.guilds.cache.size.toLocaleString('fr-DE'), + inline: true + }, + { + name: "Utilisateurs", + value: interaction.client.guilds.cache.map(x =>x.memberCount).reduce((a, b) => a + b).toLocaleString('fr-DE'), + inline: true + }, + { + name: "\u200b", + value: '\u200b', + inline: false + }, + { + name: "Support", + value: `[invitation](${package.configs.support})`, + inline: true + }, + { + name: "Ajouter Oracle", + value: `[lien](${package.configs.link})`, + inline: true + }, + { + name: "Page top.gg", + value: `[Lien](${package.configs.topgg})`, + inline: true + }, + { + name: "Développeur", + inline: false, + value: `[${((await interaction.client.users.fetch(package.configs.gs)).tag)}](https://github.com/Greensky-gs)` + } + ) + .setColor(interaction?.guild?.me?.displayHexColor ?? 'ORANGE') + + let row = new Discord.MessageActionRow() + .addComponents( + new Discord.MessageButton() + .setLabel('Code source') + .setStyle('LINK') + .setURL('https://www.youtube.com/watch?v=dQw4w9WgXcQ') + ); + + let components = []; + if (functions.random(10, 0) == 4) components.push(row); + interaction.reply({ embeds: [ embed ], components }).catch(() => {}); + } +} \ No newline at end of file diff --git a/slash-commands/misc/suggestion.js b/slash-commands/misc/suggestion.js index 1b8cecf..011b826 100644 --- a/slash-commands/misc/suggestion.js +++ b/slash-commands/misc/suggestion.js @@ -1,6 +1,7 @@ const Discord = require('discord.js'); const { gsyes, gsno } = require('../../assets/data/emojis.json'); -const { classic } = require('../../assets/embeds.js'); +const { classic, errorSQL } = require('../../assets/embeds.js'); +const functions = require('../../assets/functions'); module.exports = { configs: { @@ -26,16 +27,31 @@ module.exports = { * @param {Discord.CommandInteraction} interaction */ run: (interaction) => { - if (!interaction.guild) return interaction.reply({ content: "Cette commande n'est disponible que dans un serveur" }); + const suggest = classic(interaction.user) + .setTitle("Suggestion") + .setDescription(`Nouvelle **suggestion** de <@${interaction.user.id}> :\n> ${interaction.options.getString('suggestion')}`) + .setColor(interaction.guild.me.displayHexColor); - interaction.reply({ embeds: [ classic(interaction.user) - .setTitle("Suggestion") - .setDescription(`Nouvelle **suggestion** de <@${interaction.user.id}> :\n> ${interaction.options.getString('suggestion')}`) - .setColor(interaction.guild.me.displayHexColor) - ] }).then(() => { - interaction.fetchReply().then(async(x) => { - [ gsyes, gsno ].forEach(async(y) => await x.react(y)); - }); - }); + interaction.client.db.query(`SELECT suggest_channel FROM configs WHERE guild_id="${interaction.guild.id}"`, (err, req) => { + if (err) { + functions.sendError(err, 'query fetch at /suggestion', interaction.user); + return interaction.reply({ embeds: [ errorSQL(interaction.user) ] }).catch(() => {}); + }; + const channel = interaction.guild.channels.cache.get(req[0]?.suggest_channel); + if (!channel) return interaction.reply({ embeds: [ classic(interaction.user) + .setTitle("Non configuré") + .setDescription(`Le salon de suggestions n'est pas configuré.\nUtilisez la commande \`/config configurer\``) + .setColor('#ff0000') + ] }).catch(() => {}); + + channel.send({ embeds: [ suggest ] }).then((x) => { + interaction.reply({ embeds: [ classic(interaction.user) + .setTitle("Suggestion envoyée") + .setDescription(`J'ai envoyé votre suggestion ( <#${channel.id}> )`) + .setColor('#00ff00') + ] }).catch(() => {}); + if (x) [ gsyes, gsno ].forEach(async(y) => await x.react(y)); + }).catch(() => {}); + }) } }; \ No newline at end of file diff --git a/slash-commands/moderation/channel.js b/slash-commands/moderation/channel.js index 3478fce..95d3484 100644 --- a/slash-commands/moderation/channel.js +++ b/slash-commands/moderation/channel.js @@ -237,6 +237,29 @@ module.exports = { .setColor('ORANGE') ] }).catch(() => {}); }; + + functions.log(interaction.guild, package.embeds.classic(interaction.user) + .setTitle("Salon crée") + .setDescription(`Le salon <#${channel.id}> a été crée par <@${interaction.user.id}> **(avec la commande \`/salon créer\`)**`) + .setColor('#00ff00') + .addFields( + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: "Salon", + value: `<#${channel.id}> ( ${package.channelTypes[channel.type]} \`${channel.id}\` )`, + inline: true + }, + { + name: "Date", + value: ` ( ${(Date.now() / 1000).toFixed(0)}:R> )`, + inline: true + } + ) + ); }).catch(() => {}); }; if (subcommand == 'supprimer') { @@ -258,6 +281,24 @@ module.exports = { .setDescription(`Le salon ${channel.name} a été supprimé`) .setColor('ORANGE') ], components: [] }); + + functions.log(interaction.guild, package.embeds.classic(interaction.user) + .setTitle("Salon supprimé") + .setDescription(`Le salon ${channel.name} ( ${package.channelTypes[channel.type]} \`${channel.id}\` ) a été supprimé **(avec la commande \`/salon supprimer\`)**`) + .addFields( + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: 'Salon', + value: `${channel.name} ( ${package.channelTypes[channel.type]} \`${channel.id}\` )`, + inline: true + } + ) + .setColor('#ff0000') + ); } else { reply.edit({ embeds: [ package.embeds.cancel() ], components: [] }).catch(() => {}); }; diff --git a/slash-commands/usefull/help.js b/slash-commands/usefull/help.js index f872b10..86f24cd 100644 --- a/slash-commands/usefull/help.js +++ b/slash-commands/usefull/help.js @@ -34,7 +34,7 @@ module.exports = { {name: 'Divers', emoji: '🎈', value: 'misc', description: "Commandes diverses"}, {name: 'Fun', emoji: '🥳', value: 'fun', description: "Commandes d'amusement"}, {name: 'Utilitaires', emoji: '⚙', description: "Commandes utiles", value: 'usefull'}, - {name: "Économie", emoji: '🪙', description: "Commandes d'économie", value: 'economy'}, + {name: "Économie", emoji: '💵', description: "Commandes d'économie", value: 'economy'}, {name: 'Information', emoji: 'ℹ️', description: "Commandes d'information", value: 'information'}, {name: "Configuration", emoji: '🔨', description: "Commandes de configuration d'Oracle", value: 'configuration'}, {name: "Niveaux", emoji: '🆙', description: "Commandes de niveaux", value: 'levels'} From e064c86c71cfb4584c554c875eb5dbf6f65348be Mon Sep 17 00:00:00 2001 From: Greensky Date: Mon, 22 Aug 2022 15:47:51 +0200 Subject: [PATCH 13/14] Pre v14 update --- .gitignore | 3 +- assets/data/data.json | 3 +- assets/embeds.js | 18 +- assets/functions.js | 110 +++- assets/managers/RolesReactManager.js | 6 +- assets/managers/assets/buttons.js | 14 +- assets/managers/assets/embeds.js | 22 +- assets/managers/mailsManager.js | 38 +- assets/managers/ticketsManager.js | 50 +- assets/morpion.js | 12 +- assets/tickets.js | 228 -------- commands/.devs/eval.js | 8 +- events/endSentence.js | 8 +- events/guildBanAdd.js | 2 +- events/guildMemberUpdate.js | 16 + events/messageCreate.js | 2 +- events/messageCreateMention.js | 16 +- events/ready.js | 9 +- index.js | 9 +- package-lock.json | 550 +++++++++++++----- package.json | 2 +- slash-commands/economy/adminCoins.js | 12 +- slash-commands/economy/banque.js | 2 +- slash-commands/economy/leaderboard.js | 13 +- slash-commands/economy/loto.js | 4 +- slash-commands/economy/pay.js | 8 +- slash-commands/economy/stats.js | 6 +- slash-commands/economy/trade.js | 8 +- slash-commands/information/avatar.js | 2 +- slash-commands/information/botinfo.js | 7 +- slash-commands/levels/levels.js | 20 +- slash-commands/misc/drop.js | 6 +- slash-commands/moderation/ban.js | 2 +- slash-commands/moderation/channel.js | 2 +- .../moderation/filtre-case-action.js | 4 + slash-commands/moderation/infractions.js | 2 +- slash-commands/moderation/softban.js | 77 +++ slash-commands/moderation/stickyroles.js | 224 +++++++ slash-commands/usefull/feedback.js | 4 +- 39 files changed, 967 insertions(+), 562 deletions(-) delete mode 100644 assets/tickets.js create mode 100644 events/guildMemberUpdate.js create mode 100644 slash-commands/moderation/softban.js create mode 100644 slash-commands/moderation/stickyroles.js diff --git a/.gitignore b/.gitignore index 7b216c4..ecaabc1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules/ assets/managers/rpManager.js private-slash-commands/*.js -script.js \ No newline at end of file +script.js +assets/data/tokens.json \ No newline at end of file diff --git a/assets/data/data.json b/assets/data/data.json index 1ae7949..136aa97 100644 --- a/assets/data/data.json +++ b/assets/data/data.json @@ -1,14 +1,13 @@ { - "token": "OTkxMzY1ODk4Nzc2NjI1MjA0.GVhCUd.YDI6iS1NQ75MkmmNjLVu77qvvqJ6T4FakVKn2g", "default_prefix": "+", "gs": "386479065307152384", "yz": "582211583938134028", + "swiz": "696324357940838492", "support": "https://discord.gg/Qt9Ns3uvYe", "errorChannel": "839497213113270322", "botID": "918137973202112592", "contactChannel": "827790768272834580", "version": "1.5.4", - "beta_token": "OTE4MTM3OTczMjAyMTEyNTky.G5q2vD.tYpVroN28ovgVIPXUKR9GDVqmZexUEwneXTTLk", "beta": true, "doc": "https://bit.ly/3c37f8V", "link": "https://bit.ly/3NUdTvE", diff --git a/assets/embeds.js b/assets/embeds.js index 3094b83..0eea9a1 100644 --- a/assets/embeds.js +++ b/assets/embeds.js @@ -1,16 +1,16 @@ const emojis = require('./data/emojis.json'); -const { MessageEmbed, User, Message, Interaction, GuildMember, Guild } = require('discord.js'); +const { User, Message, Interaction, GuildMember, Guild, EmbedBuilder, Embed } = require('discord.js'); const collections = require('./data/collects'); const data = require('./data/data.json'); /** * @param {User | GuildMember} user - * @returns {MessageEmbed} + * @returns {Embed} */ const generateBasic = (user) => { let u = user; if (u.guild) u = u.user; - return new MessageEmbed() + return new EmbedBuilder() .setTimestamp() .setFooter({ text: u.username.toString(), iconURL: u.avatarURL({dynamic: true})}) } @@ -18,10 +18,10 @@ const generateBasic = (user) => { module.exports = { /** * @param {User} user - * @returns {MessageEmbed} + * @returns {EmbedBuilder} */ noUser: (user) => { - return new MessageEmbed() + return new EmbedBuilder() .setTitle("🚫 Utilisateur introuvable") .setColor('DARK_RED') .setDescription(`Oops, cet utilisateur est introuvable, réessayez avec l'identifiant ou la mention.\n> Un [utilisateur](https://github.com/BotOracle/Documentation/blob/main/others/user.md) est attendu.`) @@ -51,7 +51,7 @@ module.exports = { * @param {Discord.Guild} guild */ log: (guild) => { - let embed = new MessageEmbed() + let embed = new EmbedBuilder() .setTimestamp() if (guild.icon) embed.setFooter({ text: guild.name, iconURL: guild.iconURL({ dynamic: true })}) @@ -69,7 +69,7 @@ module.exports = { .setColor('RED') }, cancel: () => { - return new MessageEmbed() + return new EmbedBuilder() .setTitle(`:bulb: Commande annulée`) .setColor('YELLOW') }, @@ -103,7 +103,7 @@ module.exports = { .setColor('RED') }, waitForReacts: () => { - return new MessageEmbed() + return new EmbedBuilder() .setDescription(`${emojis.loading} Patientez le temps de l'ajout des réactions`) .setColor('YELLOW') }, @@ -280,7 +280,7 @@ ${Edata.winners.length == 0 ? 'Pas de gagnants' : Edata.winners.map(w => `<@${w. * @param {Guild} guild */ logs: (guild) => { - return new MessageEmbed() + return new EmbedBuilder() .setFooter({ text: guild.name, iconURL: guild.icon ? guild.iconURL({ dynamic: true }) : guild.client.user.avatarURL() }) .setTimestamp() } diff --git a/assets/functions.js b/assets/functions.js index a7d3f82..2d12e55 100644 --- a/assets/functions.js +++ b/assets/functions.js @@ -50,22 +50,22 @@ module.exports = { let index = 0; let id = paginationName; - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .addComponents( - new Discord.MessageButton() + new Discord.ButtonBuilder() .setEmoji('◀') .setCustomId('arrière') - .setStyle('SECONDARY'), - new Discord.MessageButton() + .setStyle(Discord.ButtonStyle.Secondary), + new Discord.ButtonBuilder() .setEmoji('🔢') .setCustomId('select') - .setStyle('PRIMARY'), - new Discord.MessageButton() - .setStyle('SECONDARY') + .setStyle(Discord.ButtonStyle.Primary), + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Secondary) .setEmoji('▶') .setCustomId('avant'), - new Discord.MessageButton() - .setStyle('DANGER') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Danger) .setCustomId('close') .setEmoji('❌') ) @@ -214,7 +214,7 @@ module.exports = { /** * * @param {Discord.Guild} guild - * @param {Discord.MessageEmbed} embed + * @param {Discord.EmbedBuilder} embed * @param {Discord.TextChannel} test */ log: (guild, embed) => { @@ -294,7 +294,7 @@ module.exports = { return true; }, /** - * @param {{ mod: Discord.GuildMember, member: Discord.GuildMember, interaction: Discord.CommandInteraction, ?checkBotCompare: Boolean ?checkSelfUser: Boolean, ?checkOwner: Boolean, ?checkBot: Boolean, ?ownerValid: Boolean, ?all: Boolean }} data + * @param {{ mod: Discord.GuildMember, member: Discord.GuildMember, interaction: Discord.CommandInteraction, ?checkRole: { activated: Boolean, role: Discord.Role } ?checkBotCompare: Boolean ?checkSelfUser: Boolean, ?checkOwner: Boolean, ?checkBot: Boolean, ?ownerValid: Boolean, ?all: Boolean }} data */ checkPerms(data) { const send = (embed) => { @@ -316,6 +316,25 @@ module.exports = { send(embeds.notEnoughHiger(data.mod.user, data.member)); return false; }; + if (data.checkRole?.activated == true) { + let role = data.checkRole.role; + if (role.position >= data.mod.guild.me.roles.highest.position) { + send(embeds.classic(data.mod.user) + .setTitle("Rôle trop haut") + .setDescription(`Le rôle <@&${role.id}> est supérieur ou égal à moi`) + .setColor('#ff0000') + ); + return false; + }; + if (role.position >= data.mod.roles.highest.position) { + send(embeds.classic(data.mod) + .setTitle("Rôle trop haut") + .setDescription(`Le rôle <@&${role.id}> est trop haut pour vous.`) + .setColor('#ff0000') + ); + return false; + }; + } if (data.checkBotCompare == true && data.member.roles.position >= data.member.guild.me.roles.highest.position) { send(embeds.classic(data.mod.user) .setTitle("Pas assez élevé") @@ -375,16 +394,16 @@ module.exports = { */ rpgPagination(channel, user, pages) { const texts = pages; - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .addComponents( - new Discord.MessageButton() + new Discord.ButtonBuilder() .setCustomId('past') .setEmoji('⬅') - .setStyle('SECONDARY'), - new Discord.MessageButton() + .setStyle(Discord.ButtonStyle.Secondary), + new Discord.ButtonBuilder() .setCustomId('next') .setEmoji('➡') - .setStyle('SECONDARY') + .setStyle(Discord.ButtonStyle.Secondary) ); let index = 0; @@ -431,16 +450,16 @@ module.exports = { return xdata; }, generateChoiceButton(textConfirm, textCancel) { - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .addComponents( - new Discord.MessageButton() - .setStyle('SUCCESS') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Success) .setLabel(textConfirm || 'Valider') .setCustomId('confirm'), - new Discord.MessageButton() + new Discord.ButtonBuilder() .setCustomId('cancel') .setLabel(textCancel || 'Annuler') - .setStyle('DANGER') + .setStyle(Discord.ButtonStyle.Danger) ); return row; @@ -456,8 +475,8 @@ module.exports = { }, /** * @param {Discord.Message} message - * @param {String | Discord.MessageEmbed} content - * @param {Discord.MessageActionRow} row + * @param {String | Discord.EmbedBuilder} content + * @param {Discord.ActionRowBuilder} row */ reply: async(message, content, row) => { let data = { @@ -546,5 +565,50 @@ module.exports = { return specificCooldowns.get(`${userId}.${commandName}`).date; }, getCode: (userId, commandName) => userId + '.' + commandName + }, + stickyRoles: { + /** + * @param {Discord.Guild} guild + * @param {Discord.GuildMember} member + */ + loadSpecific(guild, member) { + const sql = `SELECT role_id FROM stickyroles WHERE user_id="${member.id}" AND guild_id="${guild.id}"`; + guild.client.db.query(sql, async(err, req) => { + if (err) return console.log(err); + if (req.length == 0) return; + + for (const rId of req) { + let role = await guild.roles.fetch(rId.role_id, { cache: true }); + if (role && !member.roles.cache.has(role)) member.roles.add(role).catch(() => {}); + }; + }); + }, + /** + * @param {Discord.Client} client + */ + load(client) { + client.db.query(`SELECT user_id, guild_id FROM stickyroles`, async(err, req) => { + if (err) return console.log(err); + if (req.length == 0) return; + + let guilds = new Discord.Collection(); + await client.guilds.fetch(); + + for (const data of req) { + if (!guilds.has(data.guild_id)) { + let guild = client.guilds.cache.get(data.guild_id); + if (guild) guilds.set(guild.id, guild); + }; + + let guild = guilds.get(data.guild_id); + if (!guild) return; + + let member = (await guild.members.fetch(data.user_id)); + if (member) { + this.loadSpecific(guild, member); + }; + } + }) + } } } \ No newline at end of file diff --git a/assets/managers/RolesReactManager.js b/assets/managers/RolesReactManager.js index de81716..a94e9b2 100644 --- a/assets/managers/RolesReactManager.js +++ b/assets/managers/RolesReactManager.js @@ -55,7 +55,7 @@ class RolesReactManager { * @param {{ guild: Discord.Guild, channel: Discord.BaseGuildTextChannel, content: Discord.MessageOptions }} data */ sendMessage(data) { - const components = new Discord.MessageActionRow() + const components = new Discord.ActionRowBuilder() .addComponents( new Discord.MessageSelectMenu() .setMaxValues(1) @@ -115,7 +115,7 @@ class RolesReactManager { selector.setMaxValues(1); selector.setMinValues(1); - data.message.edit({ components: [ new Discord.MessageActionRow().addComponents(selector) ] }).catch(() => {}); + data.message.edit({ components: [ new Discord.ActionRowBuilder().addComponents(selector) ] }).catch(() => {}); let { roles } = this.cache.get(data.guild.id).get(data.message.id); if (roles.length == 0) role = data.role.id; @@ -154,7 +154,7 @@ class RolesReactManager { selector.setMaxValues(1); selector.setMinValues(1); - data.message.edit({ components: [ new Discord.MessageActionRow().addComponents(selector) ] }).catch(() => {}); + data.message.edit({ components: [ new Discord.SelectMenuBuilder().addComponents(selector) ] }).catch(() => {}); let roleIndex = roles.indexOf(data.role.id); roles.splice(roleIndex, 1); diff --git a/assets/managers/assets/buttons.js b/assets/managers/assets/buttons.js index 570f957..a0a0ac8 100644 --- a/assets/managers/assets/buttons.js +++ b/assets/managers/assets/buttons.js @@ -1,28 +1,28 @@ -const { MessageButton, MessageActionRow } = require('discord.js'); +const { ButtonBuilder, ButtonStyle, ActionRowBuilder, ActionRow } = require('discord.js'); module.exports = { participate: () => { - const button = new MessageButton() + const button = new ButtonBuilder() .setCustomId('gw-participate') - .setStyle('SUCCESS') + .setStyle(ButtonStyle.Success) .setLabel("Participer") .setEmoji('🎉') return button; }, cancelParticipation: () => { - const button = new MessageButton() + const button = new ButtonBuilder() .setCustomId('gw-unparticipate') .setLabel("Annuler la participation") - .setStyle('DANGER') + .setStyle(ButtonStyle.Danger) return button }, /** - * @param {MessageActionRow[]} components + * @param {ActionRow[]} components */ getAsRow: (components) => { - const row = new MessageActionRow() + const row = new ActionRowBuilder() .addComponents(components) return row; diff --git a/assets/managers/assets/embeds.js b/assets/managers/assets/embeds.js index 26587fa..cf9f328 100644 --- a/assets/managers/assets/embeds.js +++ b/assets/managers/assets/embeds.js @@ -1,11 +1,11 @@ -const { MessageEmbed } = require('discord.js'); +const { EmbedBuilder } = require('discord.js'); module.exports = { /** * @param {{ reward: String, winnerCount: Number, hosterId: String, channel: TextChannel, time: Number, ?bonusRoles: String[], ?deniedRoles: String[], ?requiredRoles: String[] }} data */ giveaway: (data) => { - const embed = new MessageEmbed() + const embed = new EmbedBuilder() .setTitle("🎉 Giveaway 🎉") .setColor('#00ff00') .setDescription(`**${data.reward}** @@ -40,7 +40,7 @@ Finit `) return embed; }, ended: (data, winners) => { - const embed = new MessageEmbed() + const embed = new EmbedBuilder() .setTitle("🎉 Giveaway terminé 🎉") .setColor('#ff0000') .setDescription(`**${data.reward}** @@ -56,7 +56,7 @@ Finit `) let roles = deniedRoles; if (typeof roles == 'string') roles = JSON.parse(roles); - return new MessageEmbed() + return new EmbedBuilder() .setTitle("🚫 Accès refusé") .setDescription(`L'accès à [**ce giveaway**](${url}) vous est refusé car vous avez un ou plusieurs de ces rôles :\n${roles.map(x => `<@&${x}>`).join(' ')}`) .setColor('#ff0000') @@ -65,42 +65,42 @@ Finit `) let roles = requiredRoles; if (typeof roles == 'string') roles = JSON.parse(roles); - return new MessageEmbed() + return new EmbedBuilder() .setTitle("🚫 Accès refusé") .setDescription(`L'accès à [**ce giveaway**](${url}) vous est réfusé car vous n'avez pas un ou plusieurs de ces rôles :\n${roles.map(x => `<@&${x}>`).join(' ')}`) .setColor('#ff0000') }, entryAllowed: (url) => { - return new MessageEmbed() + return new EmbedBuilder() .setTitle("🎉 Accès autorisé") .setColor('#00ff00') .setDescription(`Votre participation à [**ce giveaway**](${url}) a été confirmée.\nBonne chance !`) }, alreadyParticipate: (url) => { - return new MessageEmbed() + return new EmbedBuilder() .setTitle("🚫 Déjà participé") .setDescription(`Vous participez déjà à [**ce giveaway**](${url}).`) .setColor('#ff0000') }, notParticipated: (url) => { - return new MessageEmbed() + return new EmbedBuilder() .setTitle("🚫 Pas de participation") .setDescription(`Vous n'avez pas participé à [**ce giveaway**](${url})`) .setColor('#ff0000') }, removeParticipation: (url) => { - return new MessageEmbed() + return new EmbedBuilder() .setTitle("❌ Participation annulée") .setDescription(`Votre participation à [**ce giveaway**](${url}) a été annulée.`) .setColor('#00ff00') }, winners: (winners, url) => { - if (winners.length == 0) return new MessageEmbed() + if (winners.length == 0) return new EmbedBuilder() .setTitle("Pas de gagnants") .setDescription(`Il n'y a aucun gagnants pour [**ce giveaway**](${url}).`) .setColor('#ff0000'); - return new MessageEmbed() + return new EmbedBuilder() .setTitle("🎉 Gagnants") .setDescription(`Le${winners.length > 1 ? 's':''} gagnant${winners.length > 1 ? 's':''} de [**ce giveaway**](${url}) ${winners.length > 1 ? 'sont':'est'} ${winners.map(x => `<@${x}>`).join(' ')}`) .setColor('#00ff00') diff --git a/assets/managers/mailsManager.js b/assets/managers/mailsManager.js index 7991de2..d27dfcd 100644 --- a/assets/managers/mailsManager.js +++ b/assets/managers/mailsManager.js @@ -77,24 +77,24 @@ class MailManager { }); } generateMailBoxButtons() { - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .addComponents( - new Discord.MessageButton() + new Discord.ButtonBuilder() .setLabel('Non-lus') - .setStyle('SUCCESS') + .setStyle(Discord.ButtonStyle.Success) .setCustomId('noread'), - new Discord.MessageButton() - .setStyle('SECONDARY') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Secondary) .setLabel('Lus') .setCustomId('read'), - new Discord.MessageButton() - .setStyle('PRIMARY') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Primary) .setLabel('Supprimer un mail') .setCustomId('delete') .setEmoji('🗑️') , - new Discord.MessageButton() - .setStyle('DANGER') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Danger) .setLabel('Annuler') .setCustomId('cancel') ); @@ -112,7 +112,7 @@ class MailManager { .setDescription(`Choisissez un mail`) .setColor('ORANGE') - const menu = new Discord.MessageSelectMenu() + const menu = new Discord.SelectMenuBuilder() .setCustomId('selector') .setMaxValues(1) .setMinValues(1) @@ -137,7 +137,7 @@ class MailManager { } ]); - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .addComponents( menu ) @@ -184,7 +184,7 @@ class MailManager { .setDescription(`Choisissez un mail`) .setColor('ORANGE') - const menu = new Discord.MessageSelectMenu() + const menu = new Discord.SelectMenuBuilder() .setCustomId('selector') .setMaxValues(1) .setMinValues(1) @@ -202,7 +202,7 @@ class MailManager { menu.addOptions(this.generateCancelButton()); - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .addComponents( menu ) @@ -253,16 +253,16 @@ class MailManager { menu.addOptions(this.generateCancelButton()); const confirm = (mailId, mailObject, isImportant) => { - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .addComponents( - new Discord.MessageButton() - .setStyle('SUCCESS') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Success) .setLabel('Valider') .setCustomId('confirm'), - new Discord.MessageButton() + new Discord.ButtonBuilder() .setCustomId('cancele') .setLabel('Annuler') - .setStyle('DANGER') + .setStyle(Discord.ButtonStyle.Danger) ) message.delete().catch(() => {}); message.channel.send({ components: [ row ], embeds: [ pack.embeds.classic(user) @@ -300,7 +300,7 @@ class MailManager { .setTitle("Supprimer un mail") .setDescription(`Choisissez un mail pour le supprimer`) .setColor('ORANGE') - ], components: [ new Discord.MessageActionRow().addComponents(menu) ] }).then((sent) => { + ], components: [ new Discord.ActionRowBuilder().addComponents(menu) ] }).then((sent) => { const collector = sent.createMessageComponentCollector({ filter: i => i.user.id === user.id, time: 120000, max: 1 }); collector.on('collect', /** @param {Discord.SelectMenuInteraction} interaction */(interaction) => { diff --git a/assets/managers/ticketsManager.js b/assets/managers/ticketsManager.js index e198b46..e34e492 100644 --- a/assets/managers/ticketsManager.js +++ b/assets/managers/ticketsManager.js @@ -47,7 +47,7 @@ class TicketsManager { if (data.channel.type !== 'GUILD_TEXT') return 'not a text channel'; if (!this.validString(data.subject)) return 'not a valid text'; - const panel = new Discord.MessageEmbed() + const panel = new Discord.EmbedBuilder() .setTitle("Panel de ticket") .setDescription(`__Sujet du ticket :__ ${data.subject}\n__Description :__\n${data.description}\n\nRappel :\n→ Pas de spam\n→ Pas de troll\n\nAppuyez sur le bouton pour ouvrir un ticket.`) .setColor(data.guild.me.displayHexColor) @@ -55,7 +55,7 @@ class TicketsManager { if (data.image) panel.setImage(data.image); - data.channel.send({ embeds: [ panel ], components: [ new Discord.MessageActionRow().addComponents(new Discord.MessageButton({ customId: 'ticket_panel', emoji: '📥', style: 'SECONDARY' })) ] }).then((sent) => { + data.channel.send({ embeds: [ panel ], components: [ new Discord.ActionRowBuilder().addComponents(new Discord.MessageButton({ customId: 'ticket_panel', emoji: '📥', style: 'SECONDARY' })) ] }).then((sent) => { const dataset = { message_id: sent.id, guild_id: sent.guild.id, @@ -81,21 +81,21 @@ class TicketsManager { let { roles } = this.configs.get(data.guild.id); if (!roles) roles = []; - const embed = new Discord.MessageEmbed() + const embed = new Discord.EmbedBuilder() .setTitle("Ticket") .setDescription(`Ticket ouvert par <@${data.user.id}>.\n__Sujet :__ ${data.sujet}`) .setColor(data.guild.me.displayHexColor) if (data.image) embed.setImage(data.image); - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .addComponents( - new Discord.MessageButton() - .setStyle('SECONDARY') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Secondary) .setCustomId('ticket-close') .setEmoji('🔐'), new Discord.MessageButton() - .setStyle("DANGER") + .setStyle(Discord.ButtonStyle.Danger) .setCustomId('mention-everyone') .setLabel('mentionner everyone') ) @@ -152,18 +152,18 @@ class TicketsManager { const menu = data.channel.messages.cache.get(ticket.message_id); if (!menu) return 'error: menu not found'; - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .addComponents( - new Discord.MessageButton() - .setStyle('SECONDARY') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Secondary) .setCustomId('ticket-reopen') .setEmoji('🔓'), - new Discord.MessageButton() - .setStyle('PRIMARY') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Primary) .setCustomId('ticket-save') .setEmoji('📜'), - new Discord.MessageButton() - .setStyle('DANGER') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Danger) .setCustomId('ticket-delete') .setEmoji('🗑') ) @@ -185,10 +185,10 @@ class TicketsManager { const menu = data.channel.messages.cache.get(ticket.message_id); if (!menu) return 'error: menu not found'; - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .addComponents( - new Discord.MessageButton() - .setStyle('SECONDARY') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Secondary) .setCustomId('ticket-close') .setEmoji('🔐') ); @@ -215,10 +215,10 @@ class TicketsManager { * @param {{ channel: Discord.GuildTextBasedChannel, menu: Discord.Message, user: Discord.User }} data */ pingEveryone(data) { - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .addComponents( - new Discord.MessageButton() - .setStyle('SECONDARY') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Secondary) .setCustomId('ticket-close') .setEmoji('🔐') ) @@ -308,15 +308,15 @@ class TicketsManager { .setDescription(`Êtes-vous sûr de vouloir mentionner everyone ?`) .setColor('YELLOW') ], components: [ - new Discord.MessageActionRow() + new Discord.ActionRowBuilder() .addComponents( - new Discord.MessageButton() + new Discord.ButtonBuilder() .setLabel('Oui') - .setStyle('SUCCESS') + .setStyle(Discord.ButtonStyle.Success) .setCustomId('yes'), new Discord.MessageButton() .setLabel('Non') - .setStyle('DANGER') + .setStyle(Discord.ButtonStyle.Danger) .setCustomId('no') ) ], ephemeral: true }); @@ -345,7 +345,7 @@ class TicketsManager { interaction.deferReply(); setTimeout(() => { - const attachment = new Discord.MessageAttachment() + const attachment = new Discord.AttachmentBuilder() .setFile(customId) .setName(`${interaction.channel.name}-ticket-save.html`) .setDescription(`Sauvegarde du ticket`) diff --git a/assets/morpion.js b/assets/morpion.js index cd05194..a0433e1 100644 --- a/assets/morpion.js +++ b/assets/morpion.js @@ -54,12 +54,12 @@ class Morpion { return embed; } generateButtons() { - let first = new Discord.MessageActionRow(); - let second = new Discord.MessageActionRow(); + let first = new Discord.ActionRowBuilder(); + let second = new Discord.ActionRowBuilder(); for (let i = 0;i<9;i++) { - const btn = new Discord.MessageButton() - .setStyle('SECONDARY') + const btn = new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Secondary) .setLabel(`Case ${i + 1}`) .setCustomId(i.toString()) @@ -69,8 +69,8 @@ class Morpion { }; second.addComponents( - new Discord.MessageButton() - .setStyle('DANGER') + new Discord.ButtonBuilder() + .setStyle(Discord.ButtonStyle.Danger) .setLabel('Abandonner') .setCustomId('cancel') ); diff --git a/assets/tickets.js b/assets/tickets.js deleted file mode 100644 index e5c42b4..0000000 --- a/assets/tickets.js +++ /dev/null @@ -1,228 +0,0 @@ -const Discord = require('discord.js'); -const functions = require('./functions'); -const package = functions.package(); - -/** - * @returns {Discord.Client} - */ -const Client = () => { - return require('../index.js').client; -}; - - -module.exports = { - /** - * - * @param {Discord.Guild} guild - * @param {Discord.User} user - */ - create: (guild, user, sujet) => { - guild.channels.create(`Ticket-${user.id}`, { - topic: `Ticket demandé par <@${user.id}>\n${sujet}`, - permissionOverwrites: [ - { - id: guild.roles.everyone.id, - deny: ["VIEW_CHANNEL"] - }, - { - id: user.id, - allow: ['VIEW_CHANNEL', 'ADD_REACTIONS', "SEND_MESSAGES"] - } - ] - }).then((channel) => { - const row = new Discord.MessageActionRow() - .addComponents( - new Discord.MessageButton() - .setLabel('Fermer') - .setCustomId('close-ticket') - .setStyle('SECONDARY') - ) - - channel.send({ embeds: [ package.embeds.classic(user) - .setTitle("Ticket") - .setDescription(`Ticket demandé par <@${user.id}>.\nCrée `) - .setColor('ORANGE') - ], components: [ row ] }).then((msg) => { - - const client = channel.client; - - client.db.query(`INSERT INTO tickets (guild_id, message_id, user_id, channel_id, type, subject) VALUES ("${guild.id}", "${msg.id}", "${user.id}", "${channel.id}", "ticket-message", "${sujet}")`, (err, req) => { - if (err) channel.send({ embeds: [ package.embeds.errorSQL(user) ] }) & console.log(err); - }); - - msg.channel.send({ content: `@everyone` }).catch(() => {}); - }); - }); - }, - close_ticket_panel: (guild, channel, user) => { - const row = new Discord.MessageActionRow() - .addComponents( - new Discord.MessageButton() - .setCustomId('confirm-close-ticket') - .setLabel('Confirm') - .setStyle('SUCCESS'), - new Discord.MessageButton() - .setLabel("Annuler") - .setCustomId('cancel-close-ticket') - .setStyle('DANGER') - ) - - channel.send({ embeds: [ package.embeds.classic(user) - .setTitle("Fermeture de ticket") - .setDescription(`Valider la fermeture du ticket`) - .setColor('ORANGE') - ], components: [ row ] }).then((x) => { - const client = guild.client; - client.db.query(`SELECT * FROM tickets WHERE channel_id="${channel.id}"`, (err, req) => { - if (err) channel.send({ embeds: [ package.embeds.errorSQL(user) ] }); - - let subject = "Unknown" - if (req.length) subject = req[0].subject; - - client.db.query(`INSERT INTO tickets (guild_id, message_id, user_id, channel_id, type, subject) VALUES ("${guild.id}", "${x.id}", "${user.id}", "${channel.id}", "close-ticket-panel", "${subject}")`, (e) => { - if (e) { - console.log(e); - channel.send({ embeds: [ package.embeds.errorSQL(user) ] }); - }; - }); - }); - }); - }, - /** - * - * @param {Discord.Guild} guild - * @param {Discord.TextChannel} channel - * @param {Discord.User} user - */ - close_ticket: (guild, channel, user) => { - channel.permissionOverwrites.edit(user, { - VIEW_CHANNEL: false, - SEND_MESSAGES: false, - ADD_REACTIONS: false, - READ_MESSAGE_HISTORY: false - }) - - const row = new Discord.MessageActionRow() - .addComponents( - new Discord.MessageButton() - .setLabel('Réouvrir') - .setCustomId('reopen-ticket') - .setStyle('PRIMARY'), - new Discord.MessageButton() - .setLabel('Sauvegarder') - .setStyle('SECONDARY') - .setCustomId('save-ticket'), - new Discord.MessageButton() - .setStyle('DANGER') - .setLabel('Supprimer le ticket') - .setCustomId('delete-ticket') - ) - - channel.send({ content: `Le ticket de <@${user.id}> a été fermé.`, components: [ row ] }).then((msg) => { - let content = ''; - for (let i = 0; i < 8; i++) { - let charact = user.username.charAt(i); - if (charact !== undefined) content+=charact; - }; - - channel.setName(`ticket-${content}-fermé`); - - const client = guild.client; - - client.db.query(`SELECT * FROM tickets WHERE channel_id="${channel.id}"`, (err, req) => { - if (err) channel.send({ embeds: [ package.embeds.errorSQL(user) ] }); - - let subject = "Unknown" - if (req.length) subject = req[0].subject; - - client.db.query(`INSERT INTO tickets (guild_id, message_id, user_id, channel_id, type, subject) VALUES ("${guild.id}", "${msg.id}", "${user.id}", "${channel.id}", "panel-closed-ticket", "${subject}")`, (e) => { - if (e) { - console.log(e); - channel.send({ embeds: [ package.embeds.errorSQL(user) ] }); - }; - }); - }); - }); - }, - /** - * @param {Discord.TextChannel} channel - * @param {Discord.User} user - */ - save_transcript: (channel, user) => { - const path = `./assets/transcripts/${channel.id}-${channel.guild.id}.txt`; - const fs = require('fs'); - - const writeTranscript = (toWrite) => { - fs.writeFileSync(path, toWrite); - }; - writeTranscript(""); - - let content = ` -Ticket de ${user.tag} -${channel.name}\n\n` - - channel.messages.cache.filter((x) => x.author && !x.author.bot).forEach((msg) => { - content+= `\n${msg.author.tag} : ${msg.content}`; - }); - - writeTranscript(content); - - const attachment = new Discord.MessageAttachment(path, 'transcript.txt'); - channel.send({ files: [ attachment ], content: `Voici la retranscription de la conversation.` }).catch(() => {}).then((x) => { - fs.rmSync(path); - }); - }, - /** - * @param {Discord.GuildChannel} channel - * @param {Discord.User} user User who opens the ticket - */ - reopen: (channel, user) => { - channel.permissionOverwrites.edit(user, { - VIEW_CHANNEL: true, - SEND_MESSAGES: true, - ADD_REACTIONS: true, - READ_MESSAGE_HISTORY: true - }) - - channel.setName(`ticket-${user.id}`); - channel.send({ content: `Le ticket de <@${user.id}> a été ré-ouvert.` }).catch((e) => console.log(e)); - }, - /** - * @param {Discord.TextChannel} channel Ticket - * @param {Discord.User} user - */ - delete: (channel, user) => { - const row = new Discord.MessageActionRow() - .addComponents( - new Discord.MessageButton() - .setCustomId('cancel-close-ticket-delete') - .setEmoji('❌') - .setStyle('DANGER') - ) - channel.send({ content: `Le ticket sera supprimé dans **10 secondes** si <@${user.id}> ne l'annule pas avant`, components: [ row ] }).then((msg) => { - const collector = msg.createMessageComponentCollector({ filter: (i) => i.user.id === user.id , time: 10000, max: 1}); - - collector.on('end', (collected) => { - msg.delete().catch(() => {}); - - if (collected.size != 0) return; - channel.delete().catch(() => {}); - - const client = channel.client; - client.db.query(`DELETE FROM tickets WHERE guild_id="${channel.guild.id}" AND channel_id="${channel.id}"`, (err, req) => { - if (err) console.log(err); - }); - }); - }) - }, - /** - * @returns {Boolean} - * @param {Discord.TextChannel} channel - */ - isTicket: (channel) => { - const files = reqTickets(channel.guild); - if (files.filter((x) => x.channel === channel.id && x.type === 'ticket-message').length == 0) return false; - - return true; - } -} \ No newline at end of file diff --git a/commands/.devs/eval.js b/commands/.devs/eval.js index e51711c..3304c4a 100644 --- a/commands/.devs/eval.js +++ b/commands/.devs/eval.js @@ -1,4 +1,4 @@ -const { token, gs } = require('../../assets/data/data.json') +const { gs } = require('../../assets/data/data.json') const emojis = require('../../assets/data/emojis.json') const functions = require('../../assets/functions'); @@ -12,19 +12,17 @@ const ms = require('ms'); module.exports.run = async (message, args, client, prefix) => { if (message.author.id !== gs) return - if (args.join(" ").includes(token)) return message.channel.send({content: `${emojis.gsno} Pas d'argument avec token`}); const content = args.join(' '); const result = new Promise((resolve, reject) => resolve(eval(content))); return result.then((output) => { if (typeof output !== 'string') output = require('util').inspect(output, { depth: 0 }); if (output.includes(token)) output = output.replace(token, 'T0K3N'); - return message.channel.send({ content: `\`\`\`${output}\`\`\`` }); + return message.channel?.send({ content: `\`\`\`${output}\`\`\`` }); }).catch(err => { if (err) { err = err.toString(); - if (err.includes(token)) err = err.replace(token, '`T0K3N`'); - return message.channel.send({ content: `\`\`\`${err}\`\`\`` }) + return message.channel?.send({ content: `\`\`\`${err}\`\`\`` }) } }); } diff --git a/events/endSentence.js b/events/endSentence.js index 2e20af7..b545bce 100644 --- a/events/endSentence.js +++ b/events/endSentence.js @@ -24,18 +24,18 @@ module.exports = { }); if (ctn) { - functions.lineReply(message.id, message.channel, '-' + ctn, false); + functions.reply(message.id, message.channel, '-' + ctn, false); }; }); if (message.content.toLowerCase().includes('rick roll')) { - functions.lineReply(message.id, message.channel, ``, false); + functions.reply(message.id, message.channel, ``, false); }; if (message.content.toLowerCase().includes('coffin dance')) { - functions.lineReply(message.id, message.channel, "https://tenor.com/view/dancing-coffin-coffin-dance-funeral-funny-farewell-gif-16737844", false); + functions.reply(message.id, message.channel, "https://tenor.com/view/dancing-coffin-coffin-dance-funeral-funny-farewell-gif-16737844", false); }; if (message.content.toLowerCase().includes('webdriver torso')) { - functions.lineReply(message.id, message.channel, `https://tenor.com/view/webdriver-torso-ulysses-gif-21664517`, false); + functions.reply(message.id, message.channel, `https://tenor.com/view/webdriver-torso-ulysses-gif-21664517`, false); } } }; \ No newline at end of file diff --git a/events/guildBanAdd.js b/events/guildBanAdd.js index b7e0b8f..6b0a057 100644 --- a/events/guildBanAdd.js +++ b/events/guildBanAdd.js @@ -16,7 +16,7 @@ module.exports = { }).then((logs) => { const log = logs.entries.first(); - const embed = new Discord.MessageEmbed() + const embed = new Discord.EmbedBuilder() .setTimestamp() .setFooter({ text: guild.name, iconURL: guild.iconURL({ dynamic: true }) ? guild.iconURL({ dynamic: true }) : log.target.displayAvatarURL({ dynamic: true }) }) .setTitle("Bannissement") diff --git a/events/guildMemberUpdate.js b/events/guildMemberUpdate.js new file mode 100644 index 0000000..8502ce1 --- /dev/null +++ b/events/guildMemberUpdate.js @@ -0,0 +1,16 @@ +const Discord = require('discord.js'); +const functions = require('../assets/functions'); +const package = functions.package(); + +module.exports = { + event: 'guildMemberUpdate', + /** + * @param {Discord.GuildMember} before + * @param {Discord.GuildMember} after + */ + execute: (before, after) => { + if (before.roles.cache.size !== after.roles.cache.size) { + functions.stickyRoles.loadSpecific(before.guild, after); + }; + } +} \ No newline at end of file diff --git a/events/messageCreate.js b/events/messageCreate.js index 619bfca..14ce069 100644 --- a/events/messageCreate.js +++ b/events/messageCreate.js @@ -5,7 +5,7 @@ const package = functions.package(); module.exports = { event: 'messageCreate', /** - * @param {Discord.Message} message + * @param {Discord.Message} message */ execute: (message) => { const client = message.client; diff --git a/events/messageCreateMention.js b/events/messageCreateMention.js index 98b4a9d..eb97382 100644 --- a/events/messageCreateMention.js +++ b/events/messageCreateMention.js @@ -1,4 +1,4 @@ -const { MessageActionRow, MessageButton } = require('discord.js'); +const { ButtonBuilder, ButtonStyle, ActionRowBuilder } = require('discord.js'); const functions = require('../assets/functions'); const package = functions.package(); @@ -28,19 +28,19 @@ module.exports = { reponse.setURL('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); }; - let row = new MessageActionRow(); + let row = new ActionRowBuilder(); let buttons = []; if (functions.random(10, 0) == 5) { - let support = new MessageButton() + let support = new ButtonBuilder() .setLabel('Serveur de support') - .setStyle('LINK') + .setStyle(ButtonStyle.Link) .setURL(package.configs.support) buttons.push(support); }; if (functions.random(10, 0) == 5) { - let invite = new MessageButton() + let invite = new ButtonBuilder() .setLabel('Inviter Oracle') - .setStyle('LINK') + .setStyle(ButtonStyle.Link) .setURL(package.configs.link) if (buttons.length == 0) { @@ -54,9 +54,9 @@ module.exports = { }; }; if (functions.random(10, 0) == 5 && buttons.length < 2) { - let topgg = new MessageButton() + let topgg = new ButtonBuilder() .setLabel('Page top.gg') - .setStyle('LINK') + .setStyle(ButtonStyle.Link) .setURL(package.configs.topgg) if (buttons.length == 0) { diff --git a/events/ready.js b/events/ready.js index 0a2fe88..7950d6f 100644 --- a/events/ready.js +++ b/events/ready.js @@ -1,8 +1,8 @@ -const { Client, MessageEmbed, Interaction } = require('discord.js'); +const { Client, EmbedBuilder, Interaction } = require('discord.js'); const { connect, beta, connectYeikzy, default_prefix } = require('../assets/data/data.json'); const commands = require('../assets/data/slashCommands'); const fs = require('fs'); -const { privateSlashCommandsBuilder, capitalize } = require('../assets/functions'); +const { privateSlashCommandsBuilder, capitalize, stickyRoles } = require('../assets/functions'); const cooldowns = require('../assets/data/collects').specificCooldowns; module.exports = { @@ -63,6 +63,7 @@ module.exports = { slashCommandsBuilder(); managerBuilder(); loadSpecificsCooldowns(); + stickyRoles.load(client) const dbl = require('dblapi.js'); client.dbl = new dbl(require('../assets/data/data.json').token, { @@ -84,7 +85,7 @@ module.exports = { client.fetchWebhook(connect.id, connect.token).then((web) => { if (!web) return; - const embed = new MessageEmbed() + const embed = new EmbedBuilder() .setTitle("Reconnexion") .setDescription(`Je viens de me reconnecter`) .setColor("ORANGE") @@ -95,7 +96,7 @@ module.exports = { client.fetchWebhook(connectYeikzy.id, connectYeikzy.token).then((web) => { if (!web) return; - const embed = new MessageEmbed() + const embed = new EmbedBuilder() .setTitle("Reconnexion") .setDescription(`Je viens de me reconnecter`) .setColor("ORANGE") diff --git a/index.js b/index.js index 455fccd..7b9cbbb 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,10 @@ const Discord = require('discord.js'); const fs = require('fs'); -const { Intents } = require('discord.js'); - +const { IntentsBitField } = require('discord.js'); const client = new Discord.Client({ partials: ['MESSAGE', 'CHANNEL', 'REACTION', 'USER'], - intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES,Intents.FLAGS.GUILD_MESSAGE_REACTIONS, Intents.FLAGS.DIRECT_MESSAGES, Intents.FLAGS.GUILD_MEMBERS, Intents.FLAGS.GUILDS, Intents.FLAGS.DIRECT_MESSAGE_REACTIONS] + intents: [ IntentsBitField.Flags.Guilds, IntentsBitField.Flags.GuildMessages,IntentsBitField.Flags.GuildMessageReactions, IntentsBitField.Flags.DirectMessages, IntentsBitField.Flags.GuildMembers, IntentsBitField.Flags.DirectMessageReactions, IntentsBitField.Flags.GuildBans, IntentsBitField.Flags.GuildVoiceStates ] }); const configs = require('./assets/data/data.json'); @@ -37,5 +36,7 @@ fs.readdirSync('./commands').filter(x => x.startsWith('.')).forEach((dirName) => fs.writeFileSync(`./assets/data/commands.json`, JSON.stringify(obj, '', 1)); -let token = configs.beta === true ? configs.beta_token : configs.token; +const tokens = require('./assets/data/tokens.json'); + +let token = configs.beta === true ? tokens.beta_token : tokens.token; client.login(token); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 666eba1..30c25c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "blagues-api": "^2.1.0", "dblapi.js": "^2.4.1", "discord-api-types": "^0.26.1", - "discord.js": "^13.6.0", + "discord.js": "^14.3.0", "fs": "^0.0.1-security", "moment": "^2.29.1", "ms": "^2.1.3", @@ -22,21 +22,25 @@ } }, "node_modules/@discordjs/builders": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.11.0.tgz", - "integrity": "sha512-ZTB8yJdJKrKlq44dpWkNUrAtEJEq0gqpb7ASdv4vmq6/mZal5kOv312hQ56I/vxwMre+VIkoHquNUAfnTbiYtg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.2.0.tgz", + "integrity": "sha512-ARy4BUTMU+S0ZI6605NDqfWO+qZqV2d/xfY32z3hVSsd9IaAKJBZ1ILTZLy87oIjW8+gUpQmk9Kt0ZP9bmmd8Q==", "dependencies": { - "@sindresorhus/is": "^4.2.0", - "discord-api-types": "^0.26.0", - "ts-mixer": "^6.0.0", - "tslib": "^2.3.1", - "zod": "^3.11.6" + "@sapphire/shapeshift": "^3.5.1", + "discord-api-types": "^0.37.3", + "fast-deep-equal": "^3.1.3", + "ts-mixer": "^6.0.1", + "tslib": "^2.4.0" }, "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" + "node": ">=16.9.0" } }, + "node_modules/@discordjs/builders/node_modules/discord-api-types": { + "version": "0.37.4", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.4.tgz", + "integrity": "sha512-QgqYlUokWM++hdwvAtgVNLjmFumPBzFy+uWnnfVDiwBXKm+5jXHJPk2lx2eilkv/706UpAJPLSk/uVCY9NocjA==" + }, "node_modules/@discordjs/collection": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.4.0.tgz", @@ -64,65 +68,50 @@ } }, "node_modules/@sapphire/async-queue": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.2.0.tgz", - "integrity": "sha512-O5ND5Ljpef86X5oy8zXorQ754TMjWALcPSAgPBu4+76HLtDTrNoDyzU2uGE2G4A8Wv51u0MXHzGQ0WZ4GMtpIw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", + "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" } }, - "node_modules/@sapphire/snowflake": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.1.0.tgz", - "integrity": "sha512-K+OiqXSx4clIaXcoaghrCV56zsm3bZZ5SBpgJkgvAKegFFdETMntHviUfypjt8xVleIuDaNyQA4APOIl3BMcxg==", + "node_modules/@sapphire/shapeshift": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.5.1.tgz", + "integrity": "sha512-7JFsW5IglyOIUQI1eE0g6h06D/Far6HqpcowRScgCiLSqTf3hhkPWCWotVTtVycnDCMYIwPeaw6IEPBomKC8pA==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "lodash.uniqwith": "^4.5.0" + }, "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" } }, - "node_modules/@sindresorhus/is": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.5.0.tgz", - "integrity": "sha512-ZzlL5VTnHZJl8wMWEaYk/13hwMNKLylTSPZRz8+0HIwfRTQMnFgUahDNRRV+rTmPADxQZYxna/nQcStNSCccKg==", + "node_modules/@sapphire/snowflake": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.2.2.tgz", + "integrity": "sha512-ula2O0kpSZtX9rKXNeQMrHwNd7E4jPDJYUXmEGTFdMRfyfMw+FPyh04oKMjAiDuOi64bYgVkOV3MjK+loImFhQ==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "node": ">=v14.0.0", + "npm": ">=7.0.0" } }, - "node_modules/@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" - }, - "node_modules/@types/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==", - "dependencies": { - "@types/node": "*", - "form-data": "^3.0.0" - } + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" }, - "node_modules/@types/node-fetch/node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } + "node_modules/@types/node": { + "version": "18.7.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.9.tgz", + "integrity": "sha512-0N5Y1XAdcl865nDdjbO0m3T6FdmQ4ijE89/urOHLREyTXbpMWbSafx9y7XIsgWGtwUP2iYTinLyyW3FatAxBLQ==" }, "node_modules/@types/ws": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.1.tgz", - "integrity": "sha512-UxlLOfkuQnT2YSBCNq0x86SGOUxas6gAySFeDe2DcnEnA8655UIPoCDorWZCugcvKIL8IUI4oueUfJ1hhZSE2A==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", "dependencies": { "@types/node": "*" } @@ -205,23 +194,75 @@ } }, "node_modules/discord.js": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.6.0.tgz", - "integrity": "sha512-tXNR8zgsEPxPBvGk3AQjJ9ljIIC6/LOPjzKwpwz8Y1Q2X66Vi3ZqFgRHYwnHKC0jC0F+l4LzxlhmOJsBZDNg9g==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.3.0.tgz", + "integrity": "sha512-CpIwoAAuELiHSgVKRMzsCADS6ZlJwAZ9RlvcJYdEgS00aW36dSvXyBgE+S3pigkc7G+jU6BEalMUWIJFveqrBQ==", "dependencies": { - "@discordjs/builders": "^0.11.0", - "@discordjs/collection": "^0.4.0", - "@sapphire/async-queue": "^1.1.9", - "@types/node-fetch": "^2.5.12", - "@types/ws": "^8.2.2", - "discord-api-types": "^0.26.0", - "form-data": "^4.0.0", - "node-fetch": "^2.6.1", - "ws": "^8.4.0" + "@discordjs/builders": "^1.2.0", + "@discordjs/collection": "^1.1.0", + "@discordjs/rest": "^1.1.0", + "@sapphire/snowflake": "^3.2.2", + "@types/ws": "^8.5.3", + "discord-api-types": "^0.37.3", + "fast-deep-equal": "^3.1.3", + "lodash.snakecase": "^4.1.1", + "tslib": "^2.4.0", + "undici": "^5.9.1", + "ws": "^8.8.1" }, "engines": { - "node": ">=16.6.0", - "npm": ">=7.0.0" + "node": ">=16.9.0" + } + }, + "node_modules/discord.js/node_modules/@discordjs/collection": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.1.0.tgz", + "integrity": "sha512-PQ2Bv6pnT7aGPCKWbvvNRww5tYCGpggIQVgpuF9TdDPeR6n6vQYxezXiLVOS9z2B62Dp4c+qepQ15SgJbLYtCQ==", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/discord.js/node_modules/@discordjs/rest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.1.0.tgz", + "integrity": "sha512-yCrthRTQeUyNThQEpCk7bvQJlwQmz6kU0tf3dcWBv2WX3Bncl41x7Wc+v5b5OsIxfNYq38PvVtWircu9jtYZug==", + "dependencies": { + "@discordjs/collection": "^1.0.1", + "@sapphire/async-queue": "^1.5.0", + "@sapphire/snowflake": "^3.2.2", + "discord-api-types": "^0.37.3", + "file-type": "^17.1.6", + "tslib": "^2.4.0", + "undici": "^5.9.1" + }, + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/discord.js/node_modules/discord-api-types": { + "version": "0.37.4", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.4.tgz", + "integrity": "sha512-QgqYlUokWM++hdwvAtgVNLjmFumPBzFy+uWnnfVDiwBXKm+5jXHJPk2lx2eilkv/706UpAJPLSk/uVCY9NocjA==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/file-type": { + "version": "17.1.6", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-17.1.6.tgz", + "integrity": "sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==", + "dependencies": { + "readable-web-to-node-stream": "^3.0.2", + "strtok3": "^7.0.0-alpha.9", + "token-types": "^5.0.0-alpha.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, "node_modules/follow-redirects": { @@ -261,6 +302,25 @@ "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -271,6 +331,16 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" + }, + "node_modules/lodash.uniqwith": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniqwith/-/lodash.uniqwith-4.5.0.tgz", + "integrity": "sha512-7lYL8bLopMoy4CTICbxygAUq6CdRJ36vFc80DucPueUee+d5NBRxz3FdT9Pes/HEx5mPoT9jwnsEJWz1N7uq7Q==" + }, "node_modules/mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", @@ -336,6 +406,18 @@ } } }, + "node_modules/peek-readable": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", + "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -355,6 +437,34 @@ "util-deprecate": "~1.0.1" } }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "dependencies": { + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -376,20 +486,60 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/strtok3": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", + "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/token-types": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", + "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, "node_modules/ts-mixer": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", - "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==" + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz", + "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==" }, "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/undici": { + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.9.1.tgz", + "integrity": "sha512-6fB3a+SNnWEm4CJbgo0/CWR8RGcOCQP68SF4X0mxtYTq2VNN8T88NYrWVBAeSX+zb7bny2dx2iYhP3XHi00omg==", + "engines": { + "node": ">=12.18" + } }, "node_modules/util-deprecate": { "version": "1.0.2", @@ -411,9 +561,9 @@ } }, "node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", "engines": { "node": ">=10.0.0" }, @@ -429,27 +579,26 @@ "optional": true } } - }, - "node_modules/zod": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.12.0.tgz", - "integrity": "sha512-w+mmntgEL4hDDL5NLFdN6Fq2DSzxfmlSoJqiYE1/CApO8EkOCxvJvRYEVf8Vr/lRs3i6gqoiyFM6KRcWqqdBzQ==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } }, "dependencies": { "@discordjs/builders": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.11.0.tgz", - "integrity": "sha512-ZTB8yJdJKrKlq44dpWkNUrAtEJEq0gqpb7ASdv4vmq6/mZal5kOv312hQ56I/vxwMre+VIkoHquNUAfnTbiYtg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.2.0.tgz", + "integrity": "sha512-ARy4BUTMU+S0ZI6605NDqfWO+qZqV2d/xfY32z3hVSsd9IaAKJBZ1ILTZLy87oIjW8+gUpQmk9Kt0ZP9bmmd8Q==", "requires": { - "@sindresorhus/is": "^4.2.0", - "discord-api-types": "^0.26.0", - "ts-mixer": "^6.0.0", - "tslib": "^2.3.1", - "zod": "^3.11.6" + "@sapphire/shapeshift": "^3.5.1", + "discord-api-types": "^0.37.3", + "fast-deep-equal": "^3.1.3", + "ts-mixer": "^6.0.1", + "tslib": "^2.4.0" + }, + "dependencies": { + "discord-api-types": { + "version": "0.37.4", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.4.tgz", + "integrity": "sha512-QgqYlUokWM++hdwvAtgVNLjmFumPBzFy+uWnnfVDiwBXKm+5jXHJPk2lx2eilkv/706UpAJPLSk/uVCY9NocjA==" + } } }, "@discordjs/collection": { @@ -472,50 +621,38 @@ } }, "@sapphire/async-queue": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.2.0.tgz", - "integrity": "sha512-O5ND5Ljpef86X5oy8zXorQ754TMjWALcPSAgPBu4+76HLtDTrNoDyzU2uGE2G4A8Wv51u0MXHzGQ0WZ4GMtpIw==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", + "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==" + }, + "@sapphire/shapeshift": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.5.1.tgz", + "integrity": "sha512-7JFsW5IglyOIUQI1eE0g6h06D/Far6HqpcowRScgCiLSqTf3hhkPWCWotVTtVycnDCMYIwPeaw6IEPBomKC8pA==", + "requires": { + "fast-deep-equal": "^3.1.3", + "lodash.uniqwith": "^4.5.0" + } }, "@sapphire/snowflake": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.1.0.tgz", - "integrity": "sha512-K+OiqXSx4clIaXcoaghrCV56zsm3bZZ5SBpgJkgvAKegFFdETMntHviUfypjt8xVleIuDaNyQA4APOIl3BMcxg==" + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.2.2.tgz", + "integrity": "sha512-ula2O0kpSZtX9rKXNeQMrHwNd7E4jPDJYUXmEGTFdMRfyfMw+FPyh04oKMjAiDuOi64bYgVkOV3MjK+loImFhQ==" }, - "@sindresorhus/is": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.5.0.tgz", - "integrity": "sha512-ZzlL5VTnHZJl8wMWEaYk/13hwMNKLylTSPZRz8+0HIwfRTQMnFgUahDNRRV+rTmPADxQZYxna/nQcStNSCccKg==" + "@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" }, "@types/node": { - "version": "17.0.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", - "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" - }, - "@types/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==", - "requires": { - "@types/node": "*", - "form-data": "^3.0.0" - }, - "dependencies": { - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - } - } + "version": "18.7.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.9.tgz", + "integrity": "sha512-0N5Y1XAdcl865nDdjbO0m3T6FdmQ4ijE89/urOHLREyTXbpMWbSafx9y7XIsgWGtwUP2iYTinLyyW3FatAxBLQ==" }, "@types/ws": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.1.tgz", - "integrity": "sha512-UxlLOfkuQnT2YSBCNq0x86SGOUxas6gAySFeDe2DcnEnA8655UIPoCDorWZCugcvKIL8IUI4oueUfJ1hhZSE2A==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", "requires": { "@types/node": "*" } @@ -584,19 +721,62 @@ "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==" }, "discord.js": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.6.0.tgz", - "integrity": "sha512-tXNR8zgsEPxPBvGk3AQjJ9ljIIC6/LOPjzKwpwz8Y1Q2X66Vi3ZqFgRHYwnHKC0jC0F+l4LzxlhmOJsBZDNg9g==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.3.0.tgz", + "integrity": "sha512-CpIwoAAuELiHSgVKRMzsCADS6ZlJwAZ9RlvcJYdEgS00aW36dSvXyBgE+S3pigkc7G+jU6BEalMUWIJFveqrBQ==", "requires": { - "@discordjs/builders": "^0.11.0", - "@discordjs/collection": "^0.4.0", - "@sapphire/async-queue": "^1.1.9", - "@types/node-fetch": "^2.5.12", - "@types/ws": "^8.2.2", - "discord-api-types": "^0.26.0", - "form-data": "^4.0.0", - "node-fetch": "^2.6.1", - "ws": "^8.4.0" + "@discordjs/builders": "^1.2.0", + "@discordjs/collection": "^1.1.0", + "@discordjs/rest": "^1.1.0", + "@sapphire/snowflake": "^3.2.2", + "@types/ws": "^8.5.3", + "discord-api-types": "^0.37.3", + "fast-deep-equal": "^3.1.3", + "lodash.snakecase": "^4.1.1", + "tslib": "^2.4.0", + "undici": "^5.9.1", + "ws": "^8.8.1" + }, + "dependencies": { + "@discordjs/collection": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.1.0.tgz", + "integrity": "sha512-PQ2Bv6pnT7aGPCKWbvvNRww5tYCGpggIQVgpuF9TdDPeR6n6vQYxezXiLVOS9z2B62Dp4c+qepQ15SgJbLYtCQ==" + }, + "@discordjs/rest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.1.0.tgz", + "integrity": "sha512-yCrthRTQeUyNThQEpCk7bvQJlwQmz6kU0tf3dcWBv2WX3Bncl41x7Wc+v5b5OsIxfNYq38PvVtWircu9jtYZug==", + "requires": { + "@discordjs/collection": "^1.0.1", + "@sapphire/async-queue": "^1.5.0", + "@sapphire/snowflake": "^3.2.2", + "discord-api-types": "^0.37.3", + "file-type": "^17.1.6", + "tslib": "^2.4.0", + "undici": "^5.9.1" + } + }, + "discord-api-types": { + "version": "0.37.4", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.4.tgz", + "integrity": "sha512-QgqYlUokWM++hdwvAtgVNLjmFumPBzFy+uWnnfVDiwBXKm+5jXHJPk2lx2eilkv/706UpAJPLSk/uVCY9NocjA==" + } + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "file-type": { + "version": "17.1.6", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-17.1.6.tgz", + "integrity": "sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==", + "requires": { + "readable-web-to-node-stream": "^3.0.2", + "strtok3": "^7.0.0-alpha.9", + "token-types": "^5.0.0-alpha.2" } }, "follow-redirects": { @@ -619,6 +799,11 @@ "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -629,6 +814,16 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" + }, + "lodash.uniqwith": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniqwith/-/lodash.uniqwith-4.5.0.tgz", + "integrity": "sha512-7lYL8bLopMoy4CTICbxygAUq6CdRJ36vFc80DucPueUee+d5NBRxz3FdT9Pes/HEx5mPoT9jwnsEJWz1N7uq7Q==" + }, "mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", @@ -671,6 +866,11 @@ "whatwg-url": "^5.0.0" } }, + "peek-readable": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", + "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -690,6 +890,26 @@ "util-deprecate": "~1.0.1" } }, + "readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "requires": { + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -708,20 +928,43 @@ "safe-buffer": "~5.1.0" } }, + "strtok3": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", + "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", + "requires": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^5.0.0" + } + }, + "token-types": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", + "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", + "requires": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + } + }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, "ts-mixer": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", - "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==" + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz", + "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==" }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "undici": { + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.9.1.tgz", + "integrity": "sha512-6fB3a+SNnWEm4CJbgo0/CWR8RGcOCQP68SF4X0mxtYTq2VNN8T88NYrWVBAeSX+zb7bny2dx2iYhP3XHi00omg==" }, "util-deprecate": { "version": "1.0.2", @@ -743,15 +986,10 @@ } }, "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", "requires": {} - }, - "zod": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.12.0.tgz", - "integrity": "sha512-w+mmntgEL4hDDL5NLFdN6Fq2DSzxfmlSoJqiYE1/CApO8EkOCxvJvRYEVf8Vr/lRs3i6gqoiyFM6KRcWqqdBzQ==" } } } diff --git a/package.json b/package.json index 708c51c..1ed8e22 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "blagues-api": "^2.1.0", "dblapi.js": "^2.4.1", "discord-api-types": "^0.26.1", - "discord.js": "^13.6.0", + "discord.js": "^14.3.0", "fs": "^0.0.1-security", "moment": "^2.29.1", "ms": "^2.1.3", diff --git a/slash-commands/economy/adminCoins.js b/slash-commands/economy/adminCoins.js index 3c6ad7f..96bcde8 100644 --- a/slash-commands/economy/adminCoins.js +++ b/slash-commands/economy/adminCoins.js @@ -129,9 +129,9 @@ module.exports = { .setTitle("Confirmation") .setDescription(`Confirmez-vous que vous voulez réinitialiser les ${package.configs.coins} de <@${member.id}>`) .setColor('YELLOW') - ], components: [ new Discord.MessageActionRow().addComponents( - new Discord.MessageButton({ label: 'Oui', customId: 'y', style: 'SUCCESS' }), - new Discord.MessageButton({ label: 'Non', customId: 'n', style: 'DANGER' }) + ], components: [ new Discord.ActionRowBuilder().addComponents( + new Discord.ButtonBuilder({ label: 'Oui', customId: 'y', style: Discord.ButtonStyle.Success }), + new Discord.ButtonBuilder({ label: 'Non', customId: 'n', style: Discord.ButtonStyle.Danger }) ) ] }).catch(() => {}); const msg = await interaction.fetchReply(); @@ -152,9 +152,9 @@ module.exports = { .setTitle("Confirmation") .setDescription(`Confirmez-vous que vous voulez réinitialiser les ${package.configs.coins} de ${interaction.guild.name}`) .setColor('YELLOW') - ], components: [ new Discord.MessageActionRow().addComponents( - new Discord.MessageButton({ label: 'Oui', customId: 'y', style: 'SUCCESS' }), - new Discord.MessageButton({ label: 'Non', customId: 'n', style: 'DANGER' }) + ], components: [ new Discord.ActionRowBuilder().addComponents( + new Discord.ButtonBuilder({ label: 'Oui', customId: 'y', style: Discord.ButtonStyle.Success }), + new Discord.ButtonBuilder({ label: 'Non', customId: 'n', style: Discord.ButtonStyle.Danger }) ) ] }).catch(() => {}); const msg = await interaction.fetchReply(); diff --git a/slash-commands/economy/banque.js b/slash-commands/economy/banque.js index 36abb05..1bcd318 100644 --- a/slash-commands/economy/banque.js +++ b/slash-commands/economy/banque.js @@ -85,7 +85,7 @@ module.exports = { interaction.reply({ embeds: [ package.embeds.classic(interaction.user) .setTitle(`Argent ${value.end}`) - .setDescription(`**${amount.toLocaleString('en').replace(/,/g, ' ')} ${package.configs.coins}** ont été **${value.end}** ${value.suffix} votre compte en banque`) + .setDescription(`**${amount.toLocaleString('fr-DE')} ${package.configs.coins}** ont été **${value.end}** ${value.suffix} votre compte en banque`) .setColor(interaction.member.displayHexColor) ] }).catch(() => {}); } diff --git a/slash-commands/economy/leaderboard.js b/slash-commands/economy/leaderboard.js index ca624d3..fa50c2e 100644 --- a/slash-commands/economy/leaderboard.js +++ b/slash-commands/economy/leaderboard.js @@ -38,7 +38,11 @@ module.exports = { let count = 0; stats.forEach((stat, i) => { - now.addField(`${i + 1}]`, `<@${stat.user}>\n${parseInt(stat.coins).toLocaleString('en').replace(/,/g, ' ')} ${package.configs.coins}`, false); + now.addFields({ + name: `${i + 1}]`, + value: `<@${stat.user}>\n${parseInt(stat.coins).toLocaleString('fr-DE')} ${package.configs.coins}`, + inline: false + }); pile = false; @@ -67,8 +71,11 @@ module.exports = { .setColor('ORANGE') stats.forEach((stat, i) => { - const x = stat.coins.toLocaleString('en'); - embed.addField(`${i + 1}]`, `<@${stat.user}>\n${x.replace(/,/g, ' ')}`, false); + const x = stat.coins.toLocaleString('fr-DE'); + embed.addFields({ + name: `${i + 1}]`, + value: `<@${stat.user}>\n${x}`, + inline: false}); }); interaction.reply({ embeds: [ embed ] }).catch(() => {}); diff --git a/slash-commands/economy/loto.js b/slash-commands/economy/loto.js index 96229d6..946dd57 100644 --- a/slash-commands/economy/loto.js +++ b/slash-commands/economy/loto.js @@ -86,7 +86,7 @@ module.exports = { const subcommand = interaction.options.getSubcommand(); if (subcommand == 'démarrer') { - if (!interaction.member.permissions.has('MANAGE_GUILD')) return interaction.reply({ embeds: [ package.embeds.missingPermission(interaction.user, "gérer le serveur") ] }).catch(() => {}); + if (!interaction.member.permissions.has(Discord.PermissionsBitField.Flags.ManageGuild)) return interaction.reply({ embeds: [ package.embeds.missingPermission(interaction.user, "gérer le serveur") ] }).catch(() => {}); const reward = parseInt(interaction.options.get('récompense').value); const numbers = parseInt(interaction.options.get('gagnants').value); const complementaries = parseInt(interaction.options.get('complémentaires').value); @@ -107,7 +107,7 @@ module.exports = { interaction.reply({ embeds: [ package.embeds.loto.started(interaction.user, numbers, complementaries, reward, time) ] }).catch(() => {}); }; if (subcommand == 'tirage') { - if (!interaction.member.permissions.has('MANAGE_GUILD')) return interaction.reply({ embeds: [ package.embeds.missingPermission(interaction.user, "gérer le serveur") ] }).catch(() => {}); + if (!interaction.member.permissions.has(Discord.PermissionsBitField.Flags.ManageGuild)) return interaction.reply({ embeds: [ package.embeds.missingPermission(interaction.user, "gérer le serveur") ] }).catch(() => {}); const result = interaction.client.LotoManager.end(interaction.guild.id); let embed; diff --git a/slash-commands/economy/pay.js b/slash-commands/economy/pay.js index 2c9045f..742e93c 100644 --- a/slash-commands/economy/pay.js +++ b/slash-commands/economy/pay.js @@ -42,10 +42,10 @@ module.exports = { await interaction.reply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Confirmation") - .setDescription(`Confirmez-vous que vous voulez donner **${amount.toLocaleString('en').replace(/,/g, ' ')} ${package.configs.coins}** à <@${user.id}> ?`) + .setDescription(`Confirmez-vous que vous voulez donner **${amount.toLocaleString('fr-DE')} ${package.configs.coins}** à <@${user.id}> ?`) .setColor('YELLOW') - ], components: [ new Discord.MessageActionRow() - .addComponents(new Discord.MessageButton({ label: 'Oui', style: 'SUCCESS', customId: 'y' }), new Discord.MessageButton({ label: 'Non', style: 'DANGER', customId: 'n' })) + ], components: [ new Discord.ActionRowBuilder() + .addComponents(new Discord.ButtonBuilder({ label: 'Oui', style: Discord.ButtonStyle.Success, customId: 'y' }), new Discord.ButtonBuilder({ label: 'Non', style: Discord.ButtonStyle.Danger, customId: 'n' })) ] }).catch(() => {}); const msg = await interaction.fetchReply(); @@ -58,7 +58,7 @@ module.exports = { interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Transaction effectuée") - .setDescription(`Vous avez donné **${amount.toLocaleString('en').replace(/,/g, ' ')}** ${package.configs.coins} à <@${user.id}>`) + .setDescription(`Vous avez donné **${amount.toLocaleString('fr-DE')}** ${package.configs.coins} à <@${user.id}>`) .setColor(interaction.member.displayHexColor) ], components: [] }).catch(() => {}); }); diff --git a/slash-commands/economy/stats.js b/slash-commands/economy/stats.js index f881247..c9a59a7 100644 --- a/slash-commands/economy/stats.js +++ b/slash-commands/economy/stats.js @@ -34,17 +34,17 @@ module.exports = { .addFields( { name: 'En poche', - value: parseInt(stats.coins).toLocaleString('en').replace(/,/g, ' ') + ' ' + package.configs.coins, + value: parseInt(stats.coins).toLocaleString('fr-DE') + ' ' + package.configs.coins, inline: true }, { name: 'Banque', - value: parseInt(stats.bank).toLocaleString('en').replace(/,/g, ' ') + ' ' + package.configs.coins, + value: parseInt(stats.bank).toLocaleString('fr-DE') + ' ' + package.configs.coins, inline: true }, { name: 'Total', - value: (parseInt(stats.coins) + parseInt(stats.bank)).toLocaleString('en').replace(/,/g, ' ') + ' ' + package.configs.coins + value: (parseInt(stats.coins) + parseInt(stats.bank)).toLocaleString('fr-DE') + ' ' + package.configs.coins } ) .setColor(interaction.guild.me.displayHexColor); diff --git a/slash-commands/economy/trade.js b/slash-commands/economy/trade.js index fd6b821..eef1829 100644 --- a/slash-commands/economy/trade.js +++ b/slash-commands/economy/trade.js @@ -63,10 +63,10 @@ module.exports = { let id = interaction.user.id; await interaction.reply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Confirmation de l'échange") - .setDescription(`Confirmez-vous que vous donnez **${itemName}** à <@${user.id}> en échange de **${price.toLocaleString('en').replace(/,/g, ' ')}** ${package.configs.coins} ?`) + .setDescription(`Confirmez-vous que vous donnez **${itemName}** à <@${user.id}> en échange de **${price.toLocaleString('fr-DE')}** ${package.configs.coins} ?`) .setColor('YELLOW') - ], components: [ new Discord.MessageActionRow() - .addComponents(new Discord.MessageButton({ label: 'Oui', style: 'SUCCESS', customId: 'y' }), new Discord.MessageButton({ label: 'Non', style: 'DANGER', customId: 'n' })) + ], components: [ new Discord.ActionRowBuilder() + .addComponents(new Discord.ButtonBuilder({ label: 'Oui', style: Discord.ButtonStyle.Success, customId: 'y' }), new Discord.ButtonBuilder({ label: 'Non', style: Discord.ButtonStyle.Danger, customId: 'n' })) ], content: `<@${id}>` }).catch(() => {}); const msg = await interaction.fetchReply(); @@ -81,7 +81,7 @@ module.exports = { id = user.id; await interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Confirmation de l'échange") - .setDescription(`Confirmez-vous que vous donnez **${price.toLocaleString('en').replace(/,/g, ' ')}** ${package.configs.coins} à <@${interaction.user.id}> en échange de **${itemName}** ?`) + .setDescription(`Confirmez-vous que vous donnez **${price.toLocaleString('fr-DE')}** ${package.configs.coins} à <@${interaction.user.id}> en échange de **${itemName}** ?`) .setColor('YELLOW') ], content: `<@${id}>` }).catch(() => {}); } else { diff --git a/slash-commands/information/avatar.js b/slash-commands/information/avatar.js index 30f8ad3..fff4a7b 100644 --- a/slash-commands/information/avatar.js +++ b/slash-commands/information/avatar.js @@ -28,6 +28,6 @@ module.exports = { run: (interaction) => { const user = interaction.options.get('utilisateur') ? interaction.options.get('utilisateur').user : interaction.user; - interaction.reply({ content: `Voici la photo de profil de **${user.username}**:\n**${user.displayAvatarURL({ dynamic: true, size: 4096 })}**` }); + interaction.reply({ content: user.displayAvatarURL({ dynamic: true, size: 4096 }) }); } } \ No newline at end of file diff --git a/slash-commands/information/botinfo.js b/slash-commands/information/botinfo.js index f78a906..cf7396d 100644 --- a/slash-commands/information/botinfo.js +++ b/slash-commands/information/botinfo.js @@ -16,6 +16,7 @@ module.exports = { * @param {Discord.CommandInteraction} interaction */ run: async(interaction) => { + await interaction.deferReply(); await interaction.client.guilds.fetch(); const embed = package.embeds.classic(interaction.user) @@ -59,9 +60,9 @@ module.exports = { inline: true }, { - name: "Développeur", + name: "Développeurs", inline: false, - value: `[${((await interaction.client.users.fetch(package.configs.gs)).tag)}](https://github.com/Greensky-gs)` + value: `[${((await interaction.client.users.fetch(package.configs.gs)).tag)}](https://github.com/Greensky-gs)\n[${((await interaction.client.users.fetch(package.configs.swiz)).tag)}](https://github.com/Swiizyy)` } ) .setColor(interaction?.guild?.me?.displayHexColor ?? 'ORANGE') @@ -76,6 +77,6 @@ module.exports = { let components = []; if (functions.random(10, 0) == 4) components.push(row); - interaction.reply({ embeds: [ embed ], components }).catch(() => {}); + interaction.editReply({ embeds: [ embed ], components }).catch(() => {}); } } \ No newline at end of file diff --git a/slash-commands/levels/levels.js b/slash-commands/levels/levels.js index 84b54c5..a96e6b0 100644 --- a/slash-commands/levels/levels.js +++ b/slash-commands/levels/levels.js @@ -35,13 +35,13 @@ module.exports = { .setColor('ORANGE') levels.forEach((lvl) => { - embed.addField( - (levels.indexOf(lvl) + 1).toString(), - `<@${lvl.user_id}> + embed.addField({ + name: (levels.indexOf(lvl) + 1).toString(), + value: `<@${lvl.user_id}> > Niveau **${parseInt(lvl.level).toLocaleString('fr-DE')}** > Avec un total de **${parseInt(lvl.total).toLocaleString('fr-DE')} messages**`, - false - ); + inline: false + }); }); interaction.reply({ embeds: [ embed ] }).catch(() => {}); @@ -58,13 +58,13 @@ module.exports = { for (let i = 0; i < levels.length; i++) { const lvl = levels[i]; - now.addField( - (levels.indexOf(lvl) + 1).toString(), - `<@${lvl.user_id}> + now.addField({ + name: (levels.indexOf(lvl) + 1).toString(), + value: `<@${lvl.user_id}> > Niveau **${parseInt(lvl.level).toLocaleString('fr-DE')}** > Avec un total de **${parseInt(lvl.total).toLocaleString('fr-DE')} messages**`, - false - ); + inline: false + }); pile = false; diff --git a/slash-commands/misc/drop.js b/slash-commands/misc/drop.js index af63cd3..4014820 100644 --- a/slash-commands/misc/drop.js +++ b/slash-commands/misc/drop.js @@ -33,13 +33,13 @@ module.exports = { .setDescription(`${package.emojis.gsdrop} Drop de <@${interaction.user.id}> !\n\nSoyez le premier à appuyer sur le bouton pour gagner !\n__**Récompense :**__ ${drop}`) .setColor(interaction.guild.me.displayHexColor) - const row = new Discord.MessageActionRow() + const row = new Discord.ActionRowBuilder() .setComponents( - new Discord.MessageButton() + new Discord.ButtonBuilder() .setCustomId('claim') .setLabel('Réclamer') .setEmoji(package.emojis.gsdrop) - .setStyle('SUCCESS') + .setStyle(Discord.ButtonStyle.Success) ); await interaction.reply({ embeds: [ embed ], components: [ row ] }).catch(() => {}); diff --git a/slash-commands/moderation/ban.js b/slash-commands/moderation/ban.js index 1f22e37..f35b766 100644 --- a/slash-commands/moderation/ban.js +++ b/slash-commands/moderation/ban.js @@ -34,7 +34,7 @@ module.exports = { * @param {Discord.CommandInteraction} interaction */ run: (interaction) => { - const member = interaction.options.get('member').member; + const member = interaction.options.get('membre').member; const reason = interaction.options.get('raison').value; if (reason.includes('"')) return interaction.reply({ embeds: [ package.embeds.guillement(interaction.user) ] }); diff --git a/slash-commands/moderation/channel.js b/slash-commands/moderation/channel.js index 95d3484..fcdca98 100644 --- a/slash-commands/moderation/channel.js +++ b/slash-commands/moderation/channel.js @@ -269,7 +269,7 @@ module.exports = { .setTitle("Supression") .setDescription(`<#${channel.id}> sera supprimé `) .setColor('ORANGE') - ], components: [ new Discord.MessageActionRow({ components: [ new Discord.MessageButton({ label: 'Annuler', style: 'DANGER', customId: 'cancel' }) ] }) ] }).then(() => { + ], components: [ new Discord.ActionRowBuilder({ components: [ new Discord.MessageButton({ label: 'Annuler', style: 'DANGER', customId: 'cancel' }) ] }) ] }).then(() => { interaction.fetchReply().then((reply) => { const collector = reply.createMessageComponentCollector({ filter: x => x.user.id == interaction.user.id, time: 5000, max: 1 }); diff --git a/slash-commands/moderation/filtre-case-action.js b/slash-commands/moderation/filtre-case-action.js index b11d21d..d69a8ae 100644 --- a/slash-commands/moderation/filtre-case-action.js +++ b/slash-commands/moderation/filtre-case-action.js @@ -19,6 +19,10 @@ module.exports = { name: 'Bannissements', value: 'ban' }, + { + name: 'Softbannissements', + value: 'softban' + }, { name: 'Avertissements', value: 'avertissement' diff --git a/slash-commands/moderation/infractions.js b/slash-commands/moderation/infractions.js index 64b335e..fe410d3 100644 --- a/slash-commands/moderation/infractions.js +++ b/slash-commands/moderation/infractions.js @@ -36,7 +36,7 @@ module.exports = { return; }; - if (req.length === 0) return message.channel.send({ embeds: [ package.embeds.classic(interaction.user) + if (req.length === 0) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) .setTitle("Pas d'infractions") .setDescription(`<@${member.id}> n'a aucune infraction sur ce serveur.`) .setColor('GREEN') diff --git a/slash-commands/moderation/softban.js b/slash-commands/moderation/softban.js new file mode 100644 index 0000000..9f40d1d --- /dev/null +++ b/slash-commands/moderation/softban.js @@ -0,0 +1,77 @@ +const { CommandInteraction } = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + dev: false, + dm: false, + permissions: ['BAN_MEMBERS'] + }, + configs: { + name: 'softban', + description: "Banni, puis débanni un membre du serveur", + options: [ + { + name: "membre", + description: "Membre à softbannir", + type: 'USER', + required: true + }, + { + name: 'raison', + description: "Raison du softban", + type: 'STRING', + required: true + } + ] + }, + /** + * @param {CommandInteraction} interaction + */ + run: async(interaction) => { + let member = interaction.options.getMember('membre'); + let raison = interaction.options.getString('raison').replace(/"/g, '\\"'); + + if (!functions.checkPerms({ interaction, member, mod: interaction.member, checkBotCompare: true, checkOwner: true, checkSelfUser: true })) return; + + await member.ban({ reason: raison }).catch(() => {}); + await interaction.guild.members.unban(member.user, raison); + + interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Softban") + .setDescription(`${member.user.tag} a été softbanni.`) + .setColor('#ff0000') + ] }).catch(() => {}); + + functions.addCase(interaction.guild.id, member.id, interaction.user.id, raison, 'softban'); + functions.log(interaction.guild, package.embeds.classic(interaction.user) + .setTitle("Softban") + .setDescription(`Un membre a été soft-banni`) + .setColor('#ff0000') + .addFields( + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: "Membre", + value: `<@${member.id}> ( ${member.user.tag} \`${member.id}\` )`, + inline: true + }, + { + name: "Raison", + value: raison.replace(/\\"/g, '"'), + inline: true + }, + { + name: 'Date', + value: ` ( )`, + inline: false + } + ) + ) + } +} \ No newline at end of file diff --git a/slash-commands/moderation/stickyroles.js b/slash-commands/moderation/stickyroles.js new file mode 100644 index 0000000..23c868b --- /dev/null +++ b/slash-commands/moderation/stickyroles.js @@ -0,0 +1,224 @@ +const Discord = require('discord.js'); +const functions = require('../../assets/functions'); +const package = functions.package(); + +module.exports = { + help: { + cd: 5, + dev: false, + dm: false, + permissions: ['manage_roles', 'manage_guild'] + }, + configs: { + name: 'stickyroles', + description: "Gère les rôles collants d'un membre", + options: [ + { + name: "info", + description: "Affiche les informations sur les rôles collants", + type: 'SUB_COMMAND' + }, + { + name: 'coller', + type: 'SUB_COMMAND', + description: "Ajoute un rôle collant à un membre", + options: [ + { + name: 'rôle', + description: "Rôle collant à coller", + type: 'ROLE', + required: true + }, + { + name: 'membre', + description: "Membre qui prendra le rôle collant", + type: 'USER', + required: true + } + ] + }, + { + name: 'décoller', + type: 'SUB_COMMAND', + description: "Retire un rôle collant à un membre", + options: [ + { + name: 'rôle', + description: "Rôle collant à décoller", + type: 'ROLE', + required: true + }, + { + name: 'membre', + description: "Membre qui perdra le rôle collant", + type: 'USER', + required: true + } + ] + }, + { + name: 'liste', + type: 'SUB_COMMAND', + description: "Affiche la liste des rôles collants d'un membre", + options: [ + { + name: 'membre', + type: 'USER', + description: "Membre dont vous voulez voir les rôles collants", + required: true + } + ] + } + ] + }, + /** + * @param {Discord.CommandInteraction} interaction + */ + run: async(interaction) => { + const subcommand = interaction.options.getSubcommand(); + if (subcommand == 'info') { + let components = []; + if (functions.random(10, 5) == 7) { + components.push(new Discord.MessageActionRow() + .setComponents( + new Discord.MessageButton({ + label: 'Serveur de support', + style: 'LINK', + url: package.configs.support + }) + ) + ); + }; + interaction.reply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôles collants") + .setDescription(`Les rôles collants sont des rôles attribués à des membres, qui ne sont pas enlevables.\n\nCes rôles sont collés au membre et ne peuvent être retirés qu'avec la commande \`/stickyroles décoller\``) + .setColor(interaction.guild.me.displayHexColor) + ], components }).catch(() => {}); + return; + }; + + await interaction.reply({ embeds: [ package.embeds.waitForDb(interaction.user) ] }).catch(() => {}); + let member = interaction.options.getMember('membre'); + interaction.client.db.query(`SELECT role_id FROM stickyroles WHERE guild_id="${interaction.guild.id}" AND user_id="${member.id}"`, (err, req) => { + if (err) { + functions.sendError(err, 'query fetch at /stickyroles ' + subcommand, interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + }; + + if (subcommand == 'coller') { + let role = interaction.options.getRole('rôle'); + if (!functions.checkPerms({ mod: interaction.member, member, interaction, checkBotCompare: true, checkOwner: true, checkSelfUser: true, checkRole: { activated: true, role } })) return; + + if (req.find(x => x.role_id == role.id)) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle déjà collant") + .setDescription(`Ce rôle est déjà collant pour <@${member.id}>`) + .setColor('#ff0000') + ] }).catch(() => {}); + + if (!member.roles.cache.has(role)) member.roles.add(role).catch(() => {}); + interaction.client.db.query(`INSERT INTO stickyroles (guild_id, user_id, role_id) VALUES ("${interaction.guild.id}", "${member.id}", "${role.id}")`, (error) => { + if (error) { + functions.sendError(error, 'query insert at /stickyroles coller', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + }; + + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle collé") + .setDescription(`Le rôle <@&${role.id}> a été collé à <@${member.id}>`) + .setColor(role.hexColor) + ] }).catch(() => {}); + functions.log(interaction.guild, package.embeds.logs(interaction.guild) + .setTitle("Rôle collé") + .setDescription(`Un rôle a été collé à un membre`) + .setFields( + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: "Membre", + value: `<@${member.id}> ( ${member.user.tag} \`${member.id}\` )`, + inline: true + }, + { + name: "Rôle", + value: `<@&${role.id}> ( @${role.name} \`${role.id}\` )`, + inline: true + }, + { + name: 'Date', + value: ` ( )`, + inline: false + } + ) + .setColor(role.hexColor) + ) + }) + }; + if (subcommand == 'décoller') { + let role = interaction.options.getRole('rôle'); + if (!functions.checkPerms({ mod: interaction.member, member, interaction, checkBotCompare: true, checkOwner: true, checkSelfUser: true, checkRole: { activated: true, role } })) return; + + if (!req.find(x => x.role_id == role.id)) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle non collé") + .setDescription(`Ce rôle n'est pas collé à <@${member.id}>`) + .setColor('#ff0000') + ] }).catch(() => {}); + + if (member.roles.cache.has(role)) member.roles.remove(role).catch(() => {}); + interaction.client.db.query(`DELETE FROM stickyroles WHERE guild_id="${interaction.guild.id}" AND user_id="${member.id}" AND role_id="${role.id}"`, (error) => { + if (error) { + functions.sendError(error, 'query delete at /stickyroles décoller', interaction.user); + interaction.editReply({ embeds: [ package.embeds.errorSQL(interaction.user) ] }).catch(() => {}); + }; + + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôle décollé") + .setDescription(`Le rôle <@&${role.id}> a été décollé à <@${member.id}>`) + .setColor(role.hexColor) + ] }).catch(() => {}); + functions.log(interaction.guild, package.embeds.logs(interaction.guild) + .setTitle("Rôle collé") + .setDescription(`Un rôle a été décollé à un membre`) + .setFields( + { + name: "Modérateur", + value: `<@${interaction.user.id}> ( ${interaction.user.tag} \`${interaction.user.id}\` )`, + inline: true + }, + { + name: "Membre", + value: `<@${member.id}> ( ${member.user.tag} \`${member.id}\` )`, + inline: true + }, + { + name: "Rôle", + value: `<@&${role.id}> ( @${role.name} \`${role.id}\` )`, + inline: true + }, + { + name: 'Date', + value: ` ( )`, + inline: false + } + ) + .setColor(role.hexColor) + ) + }) + }; + if (subcommand == 'liste') { + if (req.length == 0) return interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Pas de rôles collants") + .setDescription(`<@${member.id}> n'a pas de rôles collants`) + .setColor('#ff0000') + ] }).catch(() => {}); + interaction.editReply({ embeds: [ package.embeds.classic(interaction.user) + .setTitle("Rôles collants") + .setDescription(`Voici la liste des rôles collants de <@${member.id}> (${req.length.toLocaleString('fr-DE')})\n\n${req.map(x => `<@&${x.role_id}>`).join(' ')}`) + .setColor(member.displayHexColor) + ] }).catch(() => {}); + }; + }); + } +} \ No newline at end of file diff --git a/slash-commands/usefull/feedback.js b/slash-commands/usefull/feedback.js index 12f9c2c..5aa0caf 100644 --- a/slash-commands/usefull/feedback.js +++ b/slash-commands/usefull/feedback.js @@ -34,6 +34,8 @@ module.exports = { .setColor('ORANGE') interaction.client.channels.cache.get('946079273335279676').send({ embeds: [ embed ] }).catch(() => {}); - interaction.reply({ content: `Vous avez donné votre avis sur Oracle`, ephemeral: true }).catch(() => {}); + interaction.reply({ content: `Vous avez donné votre avis sur Oracle`, ephemeral: true, components: [ new Discord.MessageActionRow() + .addComponents(new Discord.MessageButton({ label: 'Donner un avis sur top.gg', style: 'LINK', url: package.configs.topgg })) + ] }).catch(() => {}); } } \ No newline at end of file From 5b896da860fc941a2b11522a6e28d4b56f6646ae Mon Sep 17 00:00:00 2001 From: Greensky-gs <72513011+Greensky-gs@users.noreply.github.com> Date: Sat, 13 Apr 2024 16:34:27 +0200 Subject: [PATCH 14/14] Update functions.js --- assets/functions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/functions.js b/assets/functions.js index 2d12e55..c933f89 100644 --- a/assets/functions.js +++ b/assets/functions.js @@ -521,6 +521,7 @@ module.exports = { async privateSlashCommandsBuilder(client) { const commands = require('./data/slashCommands'); + if (!fs.existsSync('./private-slash-commands')) fs.mkdirSync('./private-slash-commands') const commandFiles = fs.readdirSync('./private-slash-commands'); for (const file of commandFiles) { const props = require(`../private-slash-commands/${file}`); @@ -611,4 +612,4 @@ module.exports = { }) } } -} \ No newline at end of file +}