diff --git a/.idea/dataSources/b665a16e-11b3-4dcb-a3d1-1e939c97878d/entities/entities.dat.values b/.idea/dataSources/b665a16e-11b3-4dcb-a3d1-1e939c97878d/entities/entities.dat.values index e69de29b..399717e5 100644 Binary files a/.idea/dataSources/b665a16e-11b3-4dcb-a3d1-1e939c97878d/entities/entities.dat.values and b/.idea/dataSources/b665a16e-11b3-4dcb-a3d1-1e939c97878d/entities/entities.dat.values differ diff --git a/.idea/dataSources/b665a16e-11b3-4dcb-a3d1-1e939c97878d/entities/entities.dat.values.s b/.idea/dataSources/b665a16e-11b3-4dcb-a3d1-1e939c97878d/entities/entities.dat.values.s index e69de29b..2acd3a47 100644 --- a/.idea/dataSources/b665a16e-11b3-4dcb-a3d1-1e939c97878d/entities/entities.dat.values.s +++ b/.idea/dataSources/b665a16e-11b3-4dcb-a3d1-1e939c97878d/entities/entities.dat.values.s @@ -0,0 +1 @@ +νhΞQΐPΑPΒP \ No newline at end of file diff --git a/commands/blacklist/blacklist.js b/commands/blacklist/blacklist.js index c3b57cb8..683e46aa 100644 --- a/commands/blacklist/blacklist.js +++ b/commands/blacklist/blacklist.js @@ -78,7 +78,7 @@ module.exports = class Test extends Command { message.channel.send(lang.blacklist.successBanBl(memberUser)).then(async () => { try { if (client.botperso) { - await client.guilds.cache.filter(g => g.me.hasPermission('BAN_MEMBERS')).forEach(guild => { + await client.guilds.cache.filter(g => g.me.permissions.has('BAN_MEMBERS')).forEach(guild => { guild.members.ban(memberUser.id, {reason: `Blacklist par ${message.author.tag}`,}) }) diff --git a/commands/botOwner/botperso.js b/commands/botOwner/botperso.js index 3600d3a0..0c585ec9 100644 --- a/commands/botOwner/botperso.js +++ b/commands/botOwner/botperso.js @@ -4,13 +4,9 @@ const gdate = require('gdate') require('dotenv').config(); const prettyMilliseconds = require('pretty-ms'); const dateFormater = require('pm-date-formater'); -const importer = require('node-mysql-importer') -const password = require('secure-random-password'); -const bcrypt = require('bcryptjs'); const BotPerso = require('../../utils/BotPerso'); const fetch = require('node-fetch') const Command = require('../../structures/Handler/Command'); -const { Logger } = require('advanced-command-handler') const Discord = require('discord.js') module.exports = class Test extends Command{ constructor() { @@ -59,8 +55,6 @@ module.exports = class Test extends Command{ let yyyy = now.getFullYear(); const today = yyyy + '-' + mm + '-' + dd; if (create) { - const randomPassword = password.randomPassword({length: 8}) - let hashPass = await bcrypt.hash(randomPassword, 8) message.channel.send("<:720681705219817534:780540043033837622> \`SUCCÈS\` Mentionne le client !(timeout dans 30s & \`cancel\` pour annuler)") const responseClient = await message.channel.awaitMessages(m => m.author.id === message.author.id, { max: 1, @@ -101,8 +95,7 @@ module.exports = class Test extends Command{ const formattime = dateFormater.formatDate(new Date(time), 'yyyy-MM-dd'); console.log(time) const discordName = !member.nickname ? member.user.username : member.nickname; - const botpersoSqlPath = `/home/oneforall/assets/botperso.sql` - + try { const newBot = { diff --git a/commands/botOwner/test.js b/commands/botOwner/test.js index 887e36a7..1be6d4ac 100644 --- a/commands/botOwner/test.js +++ b/commands/botOwner/test.js @@ -1,11 +1,8 @@ const Command = require('../../structures/Handler/Command'); -const {Logger} = require('advanced-command-handler') -const Discord = require('discord.js') -const emojiEnable = { - true: "<:778348494712340561:781153837850820619>", - false: "<:778348495157329930:781189773645578311>" -} -const NumberFromEmoji = require('../../utils/emojiToNumber') +const {MessageActionRow, MessageSelectMenu} = require('discord.js') +const fetch = require("node-fetch"); +const colorNameToHex = require("colornames"); +const hexColorRegex = require("hex-color-regex"); module.exports = class Test extends Command { constructor() { @@ -18,8 +15,422 @@ module.exports = class Test extends Command { } async run(client, message, args) { + const lang = client.managers.guildManager.getAndCreateIfNotExists(message.guild.id).lang + let embed = { + description: lang.embedBuilder.descriptionRequired, + author: {}, + thumbnail: {}, + image: {}, + footer: {}, + } + let tempCopy = {} - console.log(!args[0].endsWith('s') && !args[0].endsWith('m')) + let defaultOptions = lang.embedBuilder.baseMenu + let page = 0; + const row = new MessageActionRow().addComponents( + new MessageSelectMenu() + .setCustomId('embed-builder') + .setPlaceholder('Create your embed') + .addOptions(defaultOptions) + ) + + const filter = (interaction) => interaction.customId === 'embed-builder' && interaction.user.id === message.author.id, + dureefiltrer = response => { + return response.author.id === message.author.id + }; + const panel = await message.channel.send({components: [row], embeds: [embed]}) + + const collector = panel.channel.createMessageComponentCollector({filter, time: 90000}); + collector.on('collect', async (interaction) => { + let options; + let placeHolder; + const value = interaction.values[0] + if (value === "back") { + page = 0; + return updateOptions(interaction) + } + if(value.includes('copy')){ + if(value === 'copy'){ + options = lang.embedBuilder.copyOptions + page = 1 + placeHolder = lang.embedBuilder.copyPlaceHolder + } + if(value === 'copy-channel'){ + const msg = await message.channel.send(lang.embedBuilder.copyMsg); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] + }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (receivedMsg.content !== 'cancel') { + const tempChannel = receivedMsg.mentions.channels.first() || message.guild.channels.cache.get(receivedMsg.content); + tempCopy.channel = tempChannel.id + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) + }) + } + if(value === 'copy-id'){ + if(! tempCopy.channel) return message.channel.send(lang.embedBuilder.errorChannel) + const msg = await message.channel.send(lang.embedBuilder.messageId); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] + }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (receivedMsg.content !== 'cancel') { + tempCopy.message = await message.guild.channels.cache.get(tempCopy.channel).messages.fetch(receivedMsg.content); + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) + }) + } + if(value === 'copy-valid'){ + if(!tempCopy.message) return message.channel.send(lang.embedBuilder.errorMessage(tempCopy.channel ? tempCopy.channel : 'Non dΓ©finie')); + embed = tempCopy.message.embeds[0]; + updateEmbed() + interaction.deferUpdate() + } + + } + if (value.includes('footer')) { + if (value === 'footer') { + options = lang.embedBuilder.footerOptions + page = 1 + placeHolder = lang.embedBuilder.footerPlaceHolder + } + if (value === 'footer-text') { + const msg = await message.channel.send(lang.embedBuilder.footerMsg); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] + }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (receivedMsg.content !== 'cancel') { + embed.footer.text = receivedMsg.content + } else { + delete embed.footer.text + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) + }) + } + if (value === 'footer-icon') { + const msg = await message.channel.send(lang.embedBuilder.footerUrl); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] + }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + + + if (receivedMsg.content !== 'cancel') { + if (receivedMsg.attachments.size > 0) { + const imgData = await imgUrImage(receivedMsg.attachments.first().url) + embed.footer.icon_url = imgData.data.link + } else if (receivedMsg.content) { + if (!receivedMsg.content.includes('i.imgur.com') && !receivedMsg.content.includes('tenor.com')) { + const imgData = await imgUrImage(receivedMsg.content) + embed.author.icon_url = imgData.data.link + + } else { + embed.footer.icon_url = msg.content + } + } + } else { + delete embed.footer.icon_url + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) + }) + } + updateEmbed() + } + if (value.includes('author')) { + if (value === 'author') { + + options = lang.embedBuilder.authorOptions + page = 1 + placeHolder = lang.embedBuilder.authorPlaceHoler + + } + if (value === 'author-text') { + const msg = await message.channel.send(lang.embedBuilder.authorMsg); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] + }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (receivedMsg.content !== 'cancel') { + embed.author.name = receivedMsg.content + } else { + delete embed.author.name + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) + }) + } + if (value === 'author-url') { + const msg = await message.channel.send(lang.embedBuilder.authorUrl); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] + }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + time: 60000, + + max: 1, + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (!receivedMsg.content.toLowerCase().startsWith('http') && !receivedMsg.content.toLowerCase().startsWith('https') && msg.content.toLowerCase() !== 'cancel') return message.channel.send(lang.embedBuilder.errorUrl).then((rp) => { + setTimeout(() => { + rp.delete() + }, 3000) + }) + if (receivedMsg.content !== 'cancel') { + embed.author.url = receivedMsg.content + } else { + delete embed.author.url + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) + }) + } + if (value === 'author-icon') { + const msg = await message.channel.send(lang.embedBuilder.authorIcon); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] + }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + + + if (receivedMsg.content !== 'cancel') { + if (receivedMsg.attachments.size > 0) { + const imgData = await imgUrImage(receivedMsg.attachments.first().url) + embed.author.icon_url = imgData.data.link + } else if (receivedMsg.content) { + if (!receivedMsg.content.includes('i.imgur.com') && !receivedMsg.content.includes('tenor.com')) { + const imgData = await imgUrImage(receivedMsg.content) + embed.author.icon_url = imgData.data.link + + } else { + embed.author.icon_url = msg.content + } + } + } else { + delete embed.author.icon_url + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) + }) + } + updateEmbed() + + } + if (value === 'author' || value === 'footer' || value === 'copy') updateOptions(interaction, placeHolder, options) + if (page === 0) { + const theOptions = defaultOptions.find(opts => opts.value === value); + if (theOptions.questionOnly) { + const toSend = lang.embedBuilder[`${value}Msg`] + if (!toSend) { + embed.timestamp = new Date() + updateEmbed() + return interaction.deferUpdate() + } + + const msg = await message.channel.send(toSend) + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] + }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (receivedMsg.content !== 'cancel') { + if (value === 'thumbnail' || value === 'image') { + if (receivedMsg.attachments.size > 0) { + const imgData = await imgUrImage(receivedMsg.attachments.first().url) + embed[value].url = imgData.data.link + } else if (receivedMsg.content) { + if (!receivedMsg.content.includes('i.imgur.com') && !receivedMsg.content.includes('tenor.com')) { + const imgData = await imgUrImage(receivedMsg.content) + embed[value].url = imgData.data.link + + } else { + embed[value].url = receivedMsg.content + } + } + } else if(value === 'color'){ + const color = colorNameToHex(receivedMsg.content.toLowerCase()) || hexColorCheck(receivedMsg.content) + if (!color) message.channel.send(lang.embedBuilder.errorColor) + embed[value] = color + }else{ + embed[value] = receivedMsg.content + + } + if(value === 'send'){ + const channel = receivedMsg.mentions.channels.first() || message.guild.channels.cache.get(receivedMsg.content); + if(channel){ + channel.send({embeds: [embed]}) + } + } + + } else { + if (value === 'thumbnail' || value === 'image') { + delete embed[value].url + } else { + + delete embed[value] + } + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + updateEmbed() + await panel.edit({ + components: [row] + }) + + + }) + + } + } + + + }); + const imgUrImage = async (image) => { + const request = await fetch(`https://api.imgur.com/3/upload/`, { + "credentials": "include", + "headers": { + "accept": "*/*", + "authorization": "Client-ID f09340971a82a72", + }, + "referrerPolicy": "no-referrer-when-downgrade", + 'body': `${image}`, + "method": "POST", + }) + return request.json() + } + + function updateOptions(interaction, placeHolder = 'Create your embed', options = defaultOptions) { + if (page !== 0) options.push({ + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + }) + row.components[0].spliceOptions(0, row.components[0].options.length, options).setPlaceholder(placeHolder) + return interaction.update({ + components: [row] + }) + } + + function updateEmbed() { + panel.edit({ + embeds: [embed] + }) + } + + function hexColorCheck(a) { + let check = hexColorRegex().test(a); + let checkVerify = false; + if (check) { + checkVerify = true; + } + return checkVerify; + } } } \ No newline at end of file diff --git a/commands/giveaway/gcreate.js b/commands/giveaway/gcreate.js index 41540148..50a624eb 100644 --- a/commands/giveaway/gcreate.js +++ b/commands/giveaway/gcreate.js @@ -77,12 +77,12 @@ module.exports = class Test extends Command { const msg = await message.channel.send(lang.loading) for (const em of emojis) await msg.react(em); msg.edit('', embed).then(async m => { - const collector = m.createReactionCollector(filter, {time: 900000}); + const collector = m.createReactionCollector({filter, time: 900000}); collector.on('collect', async r => { await r.users.remove(message.author); if (r.emoji.name === emojis[0]) { message.channel.send(lang.giveaway.create.question.time).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 30000, errors: ['time']}) + mp.channel.awaitMessages( {dureefiltrer,max: 1, time: 30000, errors: ['time']}) .then(cld => { const msg = cld.first(); if (!isValideTime(msg.content)) return message.channel.send(lang.giveaway.create.inccorectResponse.time).then((reply) => { diff --git a/commands/invite/invite.js b/commands/invite/invite.js index d073be17..fb01f20f 100644 --- a/commands/invite/invite.js +++ b/commands/invite/invite.js @@ -164,7 +164,7 @@ module.exports = class Test extends Command { msg.edit(embed) } } else if (args[0] === "sync") { - const newInv = await message.guild.fetchInvites() + const newInv = await message.guild.invites.fetch() await message.guild.members.fetch() const invitesCount = new Map(); for (const [code, invite] of newInv) { diff --git a/commands/misc/embedBuilder.js b/commands/misc/embedBuilder.js index 19476c55..a2fa3fa4 100644 --- a/commands/misc/embedBuilder.js +++ b/commands/misc/embedBuilder.js @@ -1,9 +1,10 @@ -const url = new Map(); + const fetch = require('node-fetch'); const colorNameToHex = require('colornames') let hexColorRegex = require('hex-color-regex'); const Command = require('../../structures/Handler/Command'); const Discord = require('discord.js') +const {MessageActionRow, MessageSelectMenu} = require("discord.js"); module.exports = class Test extends Command { constructor() { @@ -22,22 +23,7 @@ module.exports = class Test extends Command { } async run(client, message, args) { - const imgUrImage = async (image) => { - const request = await fetch(`https://api.imgur.com/3/upload/`, { - "credentials": "include", - "headers": { - "accept": "*/*", - "authorization": "Client-ID f09340971a82a72", - }, - "referrerPolicy": "no-referrer-when-downgrade", - 'body': `${image}`, - "method": "POST", - }) - return request.json() - } - const guildData = client.managers.guildManager.getAndCreateIfNotExists(message.guild.id); - const color = guildData.get('color') - const lang = guildData.lang; + const lang = client.managers.guildManager.getAndCreateIfNotExists(message.guild.id).lang let embed = { description: lang.embedBuilder.descriptionRequired, author: {}, @@ -45,351 +31,404 @@ module.exports = class Test extends Command { image: {}, footer: {}, } - const editEmbed = await message.channel.send({embed}) - const msg = await message.channel.send(lang.embedBuilder.loading) - const emojis = ['✏', 'πŸ“', 'πŸ—£', 'πŸ–', 'πŸ’Ά', 'πŸ–Ό', '🌐', '🎨', '⏲', 'Β©', '❌', 'βœ…',] - for (const em of emojis) await msg.react(em) - const embedBuilder = new Discord.MessageEmbed() - .setTitle(lang.embedBuilder.title) - .setDescription(lang.embedBuilder.description) - .addField(`\`✏\``, lang.embedBuilder.titleField, true) - .addField(`\`πŸ“\``, lang.embedBuilder.descriptionField, true) - .addField(`\`πŸ—£\``, lang.embedBuilder.authorField, true) - .addField(`\`πŸ–\``, lang.embedBuilder.footerField, true) - .addField(`\`πŸ’Ά\``, lang.embedBuilder.thumbnailField, true) - .addField(`\`πŸ–Ό\``, lang.embedBuilder.imageField, true) - .addField(`\`🌐\``, lang.embedBuilder.urlField, true) - .addField(`\`🎨\``, lang.embedBuilder.colorField, true) - .addField(`\`⏲\``, lang.embedBuilder.timestampField, true) - .addField(`\`Β©\``, lang.embedBuilder.copyField, true) - .addField(`\`❌\``, lang.embedBuilder.cancelField, true) - .addField(`\`βœ…\``, lang.embedBuilder.sendField, true) - .setTimestamp() - .setFooter(client.user.tag) - .setColor(color); - const filter = (reaction, user) => emojis.includes(reaction.emoji.name) && user.id === message.author.id, + let tempCopy = {} + + let defaultOptions = lang.embedBuilder.baseMenu + let page = 0; + const row = new MessageActionRow().addComponents( + new MessageSelectMenu() + .setCustomId('embed-builder') + .setPlaceholder('Create your embed') + .addOptions(defaultOptions) + ) + + const filter = (interaction) => interaction.customId === 'embed-builder' && interaction.user.id === message.author.id, dureefiltrer = response => { - return response.member.id === message.member.id + return response.author.id === message.author.id }; - msg.edit("", embedBuilder).then(async m => { - const collector = m.createReactionCollector(filter, {time: 900000}); - collector.on('collect', async r => { - await r.users.remove(message.author); - if (r.emoji.name === '✏') { - await message.channel.send(lang.embedBuilder.titleMsg).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first(); - embed.title = msg.content; - mp.delete() - updateEmbed() - await msg.delete() - }); + const panel = await message.channel.send({components: [row], embeds: [embed]}) + + const collector = panel.channel.createMessageComponentCollector({filter, time: 90000}); + collector.on('collect', async (interaction) => { + let options; + let placeHolder; + const value = interaction.values[0] + if (value === "back") { + page = 0; + return updateOptions(interaction) + } + if(value.includes('copy')){ + if(value === 'copy'){ + options = lang.embedBuilder.copyOptions + page = 1 + placeHolder = lang.embedBuilder.copyPlaceHolder + } + if(value === 'copy-channel'){ + const msg = await message.channel.send(lang.embedBuilder.copyMsg); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] }) - } else if (r.emoji.name === 'πŸ“') { - await message.channel.send(lang.embedBuilder.descriptionMsg).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first(); - embed.description = msg.content - mp.delete() - updateEmbed() - await msg.delete() - - }); + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (receivedMsg.content !== 'cancel') { + const tempChannel = receivedMsg.mentions.channels.first() || message.guild.channels.cache.get(receivedMsg.content); + tempCopy.channel = tempChannel.id + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) + }) + } + if(value === 'copy-id'){ + if(! tempCopy.channel) return message.channel.send(lang.embedBuilder.errorChannel) + const msg = await message.channel.send(lang.embedBuilder.messageId); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] }) - } else if (r.emoji.name === 'πŸ—£') { - await message.channel.send(lang.embedBuilder.authorMsg).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first(); - embed.author.name = msg.content - mp.delete() - updateEmbed() - await msg.delete() - await message.channel.send(lang.embedBuilder.authorUrl).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first(); - mp.delete() - await msg.delete() - if (!msg.content.toLowerCase().startsWith('http') && !msg.content.toLowerCase().startsWith('https') && msg.content.toLowerCase() !== 'no') return message.channel.send(lang.embedBuilder.errorUrl) - - if (msg.content.toLowerCase() !== 'no') { - embed.author.url = msg.content - } else { - delete embed.author.url - } - updateEmbed() - - await message.channel.send(lang.embedBuilder.authorIcon).then(mp => { - mp.channel.awaitMessages(dureefiltrer, { - max: 1, - time: 60000, - errors: ['time'] - }) - .then(async cld => { - let msg = cld.first(); - if (msg.content.toLowerCase() !== 'no') { - - if (msg.attachments.size > 0) { - const imgData = await imgUrImage(msg.attachments.first().url) - embed.author.icon_url = imgData.data.link - } else if (msg.content) { - if (!msg.content.includes('i.imgur.com') && !msg.content.includes('tenor.com')) { - const imgData = await imgUrImage(msg.content) - embed.author.icon_url = imgData.data.link - - } else { - embed.author.icon_url = msg.content - } - } - } else { - delete embed.author.icon_url - } - mp.delete() - updateEmbed() - await msg.delete() - }) - }) - - }); - }) - }); + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (receivedMsg.content !== 'cancel') { + tempCopy.message = await message.guild.channels.cache.get(tempCopy.channel).messages.fetch(receivedMsg.content); + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) }) - } else if (r.emoji.name === 'πŸ–') { - await message.channel.send(lang.embedBuilder.footerMsg).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first(); - embed.footer.text = msg.content - mp.delete() - updateEmbed() - await msg.delete() - await message.channel.send(lang.embedBuilder.footerUrl).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first(); - if (msg.content.toLowerCase() !== 'no') { - if (msg.attachments.size > 0) { - const imgData = await imgUrImage(msg.attachments.first().url) - embed.footer.icon_url = imgData.data.link - } else if (msg.content) { - if (!msg.content.includes('i.imgur.com') && !msg.content.includes('tenor.com')) { - const imgData = await imgUrImage(msg.content) - embed.footer.icon_url = imgData.data.link - } else { - embed.footer.icon_url = msg.content - } - } - } else { - delete embed.footer.icon_url - } - mp.delete() - updateEmbed() - await msg.delete() - - }); - }) - }); + } + if(value === 'copy-valid'){ + if(!tempCopy.message) return message.channel.send(lang.embedBuilder.errorMessage(tempCopy.channel ? tempCopy.channel : 'Non dΓ©finie')); + embed = tempCopy.message.embeds[0]; + updateEmbed() + interaction.deferUpdate() + } + + } + if (value.includes('footer')) { + if (value === 'footer') { + options = lang.embedBuilder.footerOptions + page = 1 + placeHolder = lang.embedBuilder.footerPlaceHolder + } + if (value === 'footer-text') { + const msg = await message.channel.send(lang.embedBuilder.footerMsg); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] }) - } else if (r.emoji.name === 'πŸ’Ά') { - await message.channel.send(lang.embedBuilder.thumbnailMsg).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first(); - if (msg.attachments.size > 0) { - const imgData = await imgUrImage(msg.attachments.first().url) - embed.thumbnail.url = imgData.data.link - } else if (msg.content) { - if (!msg.content.includes('i.imgur.com') && !msg.content.includes('tenor.com')) { - const imgData = await imgUrImage(msg.content) - embed.thumbnail.url = imgData.data.link - } else { - embed.thumbnail.url = msg.content - } - } - mp.delete() - updateEmbed() - await msg.delete() + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, - }); + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (receivedMsg.content !== 'cancel') { + embed.footer.text = receivedMsg.content + } else { + delete embed.footer.text + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) }) - } else if (r.emoji.name === 'πŸ–Ό') { - await message.channel.send(lang.embedBuilder.imageMsg).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first(); - if (msg.attachments.size > 0) { - const imgData = await imgUrImage(msg.attachments.first().url) - embed.image.url = imgData.data.link - } else if (msg.content) { - if (!msg.content.includes('i.imgur.com') && !msg.content.includes('tenor.com')) { - const imgData = await imgUrImage(msg.content) - embed.image.url = imgData.data.link - } else { - embed.image.url = msg.content - } + } + if (value === 'footer-icon') { + const msg = await message.channel.send(lang.embedBuilder.footerUrl); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] + }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + + + if (receivedMsg.content !== 'cancel') { + if (receivedMsg.attachments.size > 0) { + const imgData = await imgUrImage(receivedMsg.attachments.first().url) + embed.footer.icon_url = imgData.data.link + } else if (receivedMsg.content) { + if (!receivedMsg.content.includes('i.imgur.com') && !receivedMsg.content.includes('tenor.com')) { + const imgData = await imgUrImage(receivedMsg.content) + embed.author.icon_url = imgData.data.link + + } else { + embed.footer.icon_url = msg.content } - mp.delete() - updateEmbed() - await msg.delete() - }); + } + } else { + delete embed.footer.icon_url + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) }) - } else if (r.emoji.name === '🌐') { - await message.channel.send(lang.embedBuilder.urlMsg).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first() - if (!msg.content.toLowerCase().startsWith('http') && !msg.content.toLowerCase().startsWith('https')) return message.channel.send(lang.embedBuilder.errorUrl) - embed.url = msg.content - mp.delete() - updateEmbed() - await msg.delete() - - }); + } + updateEmbed() + } + if (value.includes('author')) { + if (value === 'author') { + + options = lang.embedBuilder.authorOptions + page = 1 + placeHolder = lang.embedBuilder.authorPlaceHoler + + } + if (value === 'author-text') { + const msg = await message.channel.send(lang.embedBuilder.authorMsg); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] }) - } else if (r.emoji.name === '🎨') { - await message.channel.send(lang.embedBuilder.colorMsg).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first(); - const color = colorNameToHex(msg.content.toLowerCase()) || hexColorCheck(msg.content) - await msg.delete() - mp.delete() - if (!color) return message.channel.send(lang.embedBuilder.errorColor) - embed.color = color - updateEmbed() - - }); + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (receivedMsg.content !== 'cancel') { + embed.author.name = receivedMsg.content + } else { + delete embed.author.name + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) }) - } else if (r.emoji.name === '⏲') { - embed.timestamp = new Date() - updateEmbed() - } else if (r.emoji.name === 'Β©') { - let ch; - let embedMsg; - await message.channel.send(lang.embedBuilder.copyMsg).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first(); - // if(isNaN(msg)) return message.channel.send(`Veuilez entrer un id valide !`).then(() =>{ - // msg.delete() - // }) - // embedMsg = message.guild.channels - ch = await msg.mentions.channels.first() || message.guild.channels.cache.get(msg.content) - await mp.delete(); - await msg.delete(); - - if (!ch || ch.deleted) return await message.channel.send(lang.embedBuilder.errorChannel) - - await message.channel.send(lang.embedBuilder.messageId).then(id => { - id.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msg = cld.first(); - if (isNaN(msg)) return message.channel.send(lang.embedBuilder.errorWrongId).then(() => { - mp.delete(); - msg.delete() - }) - try { - embedMsg = await ch.messages.fetch(msg.content) - mp.delete(); - // msg.delete() - // console.log(embedMsg.embeds[0].author.name) - embed = embedMsg.embeds[0] - updateEmbed() - - } catch (err) { - return await message.channel.send(lang.embedBuilder.errorMessage(ch)).then(async () => { - await mp.delete() - await msg.delete(); - }) - } - - }); - }) - }); + } + if (value === 'author-url') { + const msg = await message.channel.send(lang.embedBuilder.authorUrl); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] + }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + time: 60000, + max: 1, + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (!receivedMsg.content.toLowerCase().startsWith('http') && !receivedMsg.content.toLowerCase().startsWith('https') && msg.content.toLowerCase() !== 'cancel') return message.channel.send(lang.embedBuilder.errorUrl).then((rp) => { + setTimeout(() => { + rp.delete() + }, 3000) + }) + if (receivedMsg.content !== 'cancel') { + embed.author.url = receivedMsg.content + } else { + delete embed.author.url + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) + }) + } + if (value === 'author-icon') { + const msg = await message.channel.send(lang.embedBuilder.authorIcon); + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() - } else if (r.emoji.name === '❌') { - await message.channel.send(lang.embedBuilder.cancelMsg).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msG = cld.first(); - if (msG.content.toLowerCase() === lang.yes) { - await mp.delete() - await editEmbed.delete() - await msg.delete() - await msG.delete() - await message.delete() - } - if (msg.content.toLowerCase() === lang.no) { - mp.delete() - await msG.delete() + + if (receivedMsg.content !== 'cancel') { + if (receivedMsg.attachments.size > 0) { + const imgData = await imgUrImage(receivedMsg.attachments.first().url) + embed.author.icon_url = imgData.data.link + } else if (receivedMsg.content) { + if (!receivedMsg.content.includes('i.imgur.com') && !receivedMsg.content.includes('tenor.com')) { + const imgData = await imgUrImage(receivedMsg.content) + embed.author.icon_url = imgData.data.link + + } else { + embed.author.icon_url = msg.content } - }); + } + } else { + delete embed.author.icon_url + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + await panel.edit({ + components: [row] + }) }) - } else if (r.emoji.name === 'βœ…') { - await message.channel.send(lang.embedBuilder.sendMsg).then(mp => { - mp.channel.awaitMessages(dureefiltrer, {max: 1, time: 60000, errors: ['time']}) - .then(async cld => { - let msgs = cld.first(); - const channel = msgs.mentions.channels.first() || msgs.guild.channels.cache.get(msgs.content); - if (!client.botperso && !client.config.dev) { - if (embed.thumbnail.url) { - client.shard.broadcastEval(` - (async () => { - let channel = this.channels.cache.get('803206140858990632'); - let msg; - if (channel) { - msg = await channel.send('${embed.thumbnail.url}'); - } - return msg; - })(); - - `); - + } + updateEmbed() - } - if (embed.image.url) { - await client.cluster.broadcastEval(` - (async () => { - let channel = this.channels.cache.get('803206140858990632'); - let msg; - if (channel) { - msg = await channel.send('${embed.image.url}'); - } - return msg; - })(); - `); + } + if (value === 'author' || value === 'footer' || value === 'copy') updateOptions(interaction, placeHolder, options) + if (page === 0) { + const theOptions = defaultOptions.find(opts => opts.value === value); + if (theOptions.questionOnly) { + const toSend = lang.embedBuilder[`${value}Msg`] + if (!toSend) { + embed.timestamp = new Date() + updateEmbed() + return interaction.deferUpdate() + } + const msg = await message.channel.send(toSend) + row.components[0].setDisabled(true) + await panel.edit({ + components: [row] + }) + await interaction.deferUpdate() + await msg.channel.awaitMessages({ + filter: dureefiltrer, + limit: 1, + max: 1, + time: 60000, + errors: ['time'] + }).then(async (cld) => { + const receivedMsg = cld.first() + if (receivedMsg.content !== 'cancel') { + if (value === 'thumbnail' || value === 'image') { + if (receivedMsg.attachments.size > 0) { + const imgData = await imgUrImage(receivedMsg.attachments.first().url) + embed[value].url = imgData.data.link + } else if (receivedMsg.content) { + if (!receivedMsg.content.includes('i.imgur.com') && !receivedMsg.content.includes('tenor.com')) { + const imgData = await imgUrImage(receivedMsg.content) + embed[value].url = imgData.data.link + } else { + embed[value].url = receivedMsg.content } } + } else if(value === 'color'){ + const color = colorNameToHex(receivedMsg.content.toLowerCase()) || hexColorCheck(receivedMsg.content) + if (!color) message.channel.send(lang.embedBuilder.errorColor) + embed[value] = color + }else{ + embed[value] = receivedMsg.content + + } + if(value === 'send'){ + const channel = receivedMsg.mentions.channels.first() || message.guild.channels.cache.get(receivedMsg.content); + if(channel){ + channel.send({embeds: [embed]}) + } + } + + } else { + if (value === 'thumbnail' || value === 'image') { + delete embed[value].url + } else { + + delete embed[value] + } + } + msg.delete() + await receivedMsg.delete() + row.components[0].setDisabled(false) + updateEmbed() + await panel.edit({ + components: [row] + }) + - finishEmbed(channel) - await mp.delete() - await msg.delete(); - await msgs.delete(); - await editEmbed.delete(); - }); }) + } + } + + + }); + const imgUrImage = async (image) => { + const request = await fetch(`https://api.imgur.com/3/upload/`, { + "credentials": "include", + "headers": { + "accept": "*/*", + "authorization": "Client-ID f09340971a82a72", + }, + "referrerPolicy": "no-referrer-when-downgrade", + 'body': `${image}`, + "method": "POST", }) - collector.on('end', async (collected, reason) => { - if (reason === 'time') { - message.channel.send(lang.error.timeout) - } - }); - }) + return request.json() + } - function updateEmbed() { - editEmbed.edit({embed}) + function updateOptions(interaction, placeHolder = 'Create your embed', options = defaultOptions) { + if (page !== 0) options.push({ + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + }) + row.components[0].spliceOptions(0, row.components[0].options.length, options).setPlaceholder(placeHolder) + return interaction.update({ + components: [row] + }) } - function finishEmbed(channel) { - channel.send({embed}) + function updateEmbed() { + panel.edit({ + embeds: [embed] + }) } function hexColorCheck(a) { diff --git a/commands/misc/role.js b/commands/misc/role.js index 106fe220..15984441 100644 --- a/commands/misc/role.js +++ b/commands/misc/role.js @@ -23,7 +23,7 @@ module.exports = class Test extends Command{ const color = guildData.get('color') const add = args[0] === 'add'; const remove = args[0] === 'remove'; - // if(!message.member.hasPermission('MANAGE_ROLES')) return message.channel.send("<:720681441670725645:780539422479351809> \`ERREUR\` Vous n'avez pas la permission requise \`MANAGER_ROLES\`"); + // if(!message.member.permissions.has('MANAGE_ROLES')) return message.channel.send("<:720681441670725645:780539422479351809> \`ERREUR\` Vous n'avez pas la permission requise \`MANAGER_ROLES\`"); let member = message.mentions.members.first() || message.guild.members.cache.get(args[1]); let role = message.mentions.roles.first() || message.guild.roles.cache.get(args[2]); if(!role) return message.channel.send("Le rΓ΄le spΓ©cifiΓ© n'existe pas.") diff --git a/commands/moderation/alladmin.js b/commands/moderation/alladmin.js index 8d1b359b..4a354afb 100644 --- a/commands/moderation/alladmin.js +++ b/commands/moderation/alladmin.js @@ -23,7 +23,7 @@ module.exports = class Test extends Command { const color = guildData.get('color') const lang = guildData.lang; const admins = message.guild.members.cache.filter( - (m) => m.hasPermission('ADMINISTRATOR') + (m) => m.permissions.has('ADMINISTRATOR') ).map(m => tempdata.push(m.user.id)) diff --git a/commands/moderation/lockchannel.js b/commands/moderation/lockchannel.js index 1ea5d81a..e4e17bfc 100644 --- a/commands/moderation/lockchannel.js +++ b/commands/moderation/lockchannel.js @@ -25,7 +25,7 @@ module.exports = class Test extends Command { const guildData = client.managers.guildManager.getAndCreateIfNotExists(message.guild.id); const lang = guildData.lang; - // if(!message.member.hasPermission('MANAGE_CHANNELS')) return message.channel.send("<:720681441670725645:780539422479351809> \`ERREUR\` Vous n'avez pas la permission requise \`MANAGE_CHANNELS\`") + // if(!message.member.permissions.has('MANAGE_CHANNELS')) return message.channel.send("<:720681441670725645:780539422479351809> \`ERREUR\` Vous n'avez pas la permission requise \`MANAGE_CHANNELS\`") let isSetup =guildData.get('setup') if (!isSetup) return message.channel.send(lang.error.noSetup) const on = args[0] === 'on'; diff --git a/commands/moderation/unban.js b/commands/moderation/unban.js index b4b7bdad..8a679a89 100644 --- a/commands/moderation/unban.js +++ b/commands/moderation/unban.js @@ -21,7 +21,7 @@ module.exports = class Test extends Command { const guildData = client.managers.guildManager.getAndCreateIfNotExists(message.guild.id); const lang = guildData.lang; - // if(!message.member.hasPermission('BAN_MEMBERS')) return message.channel.send("<:720681441670725645:780539422479351809> \`ERREUR\` Vous n'avez pas la permission requise \`BAN_MEMBERS\`") + // if(!message.member.permissions.has('BAN_MEMBERS')) return message.channel.send("<:720681441670725645:780539422479351809> \`ERREUR\` Vous n'avez pas la permission requise \`BAN_MEMBERS\`") const color = guildData.get('color') if (args[0] === 'all') { const bans = await message.guild.fetchBans(); diff --git a/events/Command/message.js b/events/Command/message.js index 4465cde6..12f5a009 100644 --- a/events/Command/message.js +++ b/events/Command/message.js @@ -4,7 +4,7 @@ const DBL = require("dblapi.js"); module.exports = class message extends Event { constructor() { super({ - name: 'message', + name: 'messageCreate', }); } @@ -118,12 +118,12 @@ module.exports = class message extends Event { } else { if(!enable || !permHasCommand){ for (const commandPermissions of cmd.userPermissions) { - if (!message.member.hasPermission(commandPermissions) && message.guild.ownerID !== message.author.id) { + if (!message.member.permissions.has(commandPermissions) && message.guild.ownerID !== message.author.id) { return message.channel.send(lang.error.userPermissions(commandPermissions)) } } for (const commandPermissions of cmd.clientPermissions) { - if (!message.guild.me.hasPermission(commandPermissions)) { + if (!message.guild.me.permissions.has(commandPermissions)) { return message.channel.send(lang.error.clientPermissions(commandPermissions)) } } diff --git a/events/antiraid/antiBot.js b/events/antiraid/antiBot.js index 79752ec3..52e68189 100644 --- a/events/antiraid/antiBot.js +++ b/events/antiraid/antiBot.js @@ -14,7 +14,7 @@ module.exports = class AntiBot extends Event { async run(client, member) { if(!member.user.bot) return const guild = member.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color'); const antiraidConfig = guildData.get('antiraid'); @@ -38,7 +38,7 @@ module.exports = class AntiBot extends Event { if (isWlBypass && !isWl || !isWlBypass) { const executor = await guild.members.fetch(action.executor.id) const channel = guild.channels.cache.get(antiraidLog) - if(!guild.me.hasPermission("KICK_MEMBERS")){ + if(!guild.me.permissions.has("KICK_MEMBERS")){ if (channel && !channel.deleted) { channel.send(logs.botAdd(executor, member.user.username, member.id, color, "Je n'ai pas assΓ© de permissions")) } diff --git a/events/antiraid/antiDeco.js b/events/antiraid/antiDeco.js index 37a2caf3..eba692c5 100644 --- a/events/antiraid/antiDeco.js +++ b/events/antiraid/antiDeco.js @@ -12,7 +12,7 @@ module.exports = class Ready extends Event { async run(client, member, channel) { const guild = member.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); const color = guildData.get('color'); const antiraidConfig = guildData.get('antiraid'); diff --git a/events/antiraid/antiLink.js b/events/antiraid/antiLink.js index 73d78f94..d0e51b42 100644 --- a/events/antiraid/antiLink.js +++ b/events/antiraid/antiLink.js @@ -7,7 +7,7 @@ const spammer = new Collection() module.exports = class Message extends Event { constructor() { super({ - name: 'message', + name: 'messageCreate', }); } diff --git a/events/antiraid/antiMassBan.js b/events/antiraid/antiMassBan.js index 7a8b285c..58f3f525 100644 --- a/events/antiraid/antiMassBan.js +++ b/events/antiraid/antiMassBan.js @@ -9,7 +9,7 @@ module.exports = class Ready extends Event { } async run(client, guild, user) { - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color'); const antiraidConfig = guildData.get('antiraid'); diff --git a/events/antiraid/antiMassKick.js b/events/antiraid/antiMassKick.js index 9be19865..022d39d7 100644 --- a/events/antiraid/antiMassKick.js +++ b/events/antiraid/antiMassKick.js @@ -9,7 +9,7 @@ module.exports = class Ready extends Event{ } async run(client, member){ const guild = member.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color'); const antiraidConfig = guildData.get('antiraid'); diff --git a/events/antiraid/antiMassMention.js b/events/antiraid/antiMassMention.js index b1ba4d0a..8b97b376 100644 --- a/events/antiraid/antiMassMention.js +++ b/events/antiraid/antiMassMention.js @@ -5,7 +5,7 @@ const ms = require("ms"); module.exports = class Message extends Event { constructor() { super({ - name: 'message', + name: 'messageCreate', }); } @@ -31,12 +31,12 @@ module.exports = class Message extends Event { const limit = parsedLimit[0]; const time = ms(parsedLimit[1]); const { roles, members } = message.mentions; + if(!roles.size && !members.size) return const userData = client.managers.userManager.getAndCreateIfNotExists(`${message.guild.id}-${member.id}`); const { mentions } = userData.get('antiraidLimit') if (mentions.date) { const diff = new Date() - new Date(mentions.date) const counter = mentions.counter; - console.log(mentions) if (diff < time && counter < limit) { mentions.counter += roles.size; mentions.counter += members.size; diff --git a/events/antiraid/antiSpam.js b/events/antiraid/antiSpam.js index 856aae17..5571e6bb 100644 --- a/events/antiraid/antiSpam.js +++ b/events/antiraid/antiSpam.js @@ -9,7 +9,7 @@ const spammer = new Collection() module.exports = class Message extends Event{ constructor() { super({ - name: 'message', + name: 'messageCreate', }); } async run(client, message){ diff --git a/events/antiraid/channelCreate.js b/events/antiraid/channelCreate.js index f7f5c9d7..5e2f9ab8 100644 --- a/events/antiraid/channelCreate.js +++ b/events/antiraid/channelCreate.js @@ -12,7 +12,7 @@ module.exports = class channelCreate extends Event { async run(client, channel) { let guild = channel.guild if (channel.type === "dm") return; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color'); const antiraidConfig = guildData.get('antiraid'); diff --git a/events/antiraid/channelDelete.js b/events/antiraid/channelDelete.js index 0bea18a7..7fc53448 100644 --- a/events/antiraid/channelDelete.js +++ b/events/antiraid/channelDelete.js @@ -12,7 +12,7 @@ module.exports = class channelDelete extends Event { async run(client, channel) { let guild = channel.guild if (channel.type === "dm") return; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color'); const antiraidConfig = guildData.get('antiraid'); diff --git a/events/antiraid/channelUpdate.js b/events/antiraid/channelUpdate.js index 2bf44997..1f893592 100644 --- a/events/antiraid/channelUpdate.js +++ b/events/antiraid/channelUpdate.js @@ -10,7 +10,7 @@ module.exports = class channelUpdate extends Event { async run(client, oldChannel, newChannel) { let guild = oldChannel.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color') let antiraidLog = guildData.get('logs').antiraid; diff --git a/events/antiraid/guildMemberUpdate.js.none b/events/antiraid/guildMemberUpdate.js.none index 46c1b0ee..cb4acfa0 100644 --- a/events/antiraid/guildMemberUpdate.js.none +++ b/events/antiraid/guildMemberUpdate.js.none @@ -28,7 +28,7 @@ module.exports = class guildMemberUpdate extends Event { let guild = oldMember.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const color = guildEmbedColor.get(oldMember.guild.id) diff --git a/events/antiraid/guildUpdate.js b/events/antiraid/guildUpdate.js index 693e8f1a..3bc95657 100644 --- a/events/antiraid/guildUpdate.js +++ b/events/antiraid/guildUpdate.js @@ -9,7 +9,7 @@ module.exports = class guildUpdate extends Event { async run(client, oldGuild, newGuild) { - if (!oldGuild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!oldGuild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(oldGuild.id) const color = guildData.get('color') let {antiraidLog} = guildData.get('logs').antiraid; diff --git a/events/antiraid/guildVanityUpdate.js b/events/antiraid/guildVanityUpdate.js index a75e0c56..49954256 100644 --- a/events/antiraid/guildVanityUpdate.js +++ b/events/antiraid/guildVanityUpdate.js @@ -10,7 +10,7 @@ module.exports = class guildVanityUpdate extends Event { } async run(client, guild, oldVanityURL, newVanityURL) { - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color') let antiraidLog = guildData.get('logs').antiraid; diff --git a/events/antiraid/memberRoleAdd.js b/events/antiraid/memberRoleAdd.js index 35876844..e5d525a8 100644 --- a/events/antiraid/memberRoleAdd.js +++ b/events/antiraid/memberRoleAdd.js @@ -13,7 +13,7 @@ module.exports = class Ready extends Event { async run(client, member, role) { let guild = member.guild; if (!role.permissions.has("KICK_MEMBERS") || !role.permissions.has("BAN_MEMBERS") || !role.permissions.has("ADMINISTRATOR") || !role.permissions.has("MANAGE_CHANNELS") || !role.permissions.has("MANAGE_GUILD") || !role.permissions.has("MANAGE_ROLES") || !role.permissions.has("MENTION_EVERYONE")) return; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color') let antiraidLog = guildData.get('logs').antiraid; diff --git a/events/antiraid/memberRoleRemove.js b/events/antiraid/memberRoleRemove.js index 05455520..6cdc599d 100644 --- a/events/antiraid/memberRoleRemove.js +++ b/events/antiraid/memberRoleRemove.js @@ -13,7 +13,7 @@ module.exports = class Ready extends Event { async run(client, member, role) { let guild = member.guild; if (!role.permissions.has("KICK_MEMBERS") || !role.permissions.has("BAN_MEMBERS") || !role.permissions.has("ADMINISTRATOR") || !role.permissions.has("MANAGE_CHANNELS") || !role.permissions.has("MANAGE_GUILD") || !role.permissions.has("MANAGE_ROLES") || !role.permissions.has("MENTION_EVERYONE")) return; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color') let antiraidLog = guildData.get('logs').antiraid; diff --git a/events/antiraid/roleCreate.js b/events/antiraid/roleCreate.js index 89fc5fff..285cc616 100644 --- a/events/antiraid/roleCreate.js +++ b/events/antiraid/roleCreate.js @@ -11,7 +11,7 @@ module.exports = class roleCreate extends Event { async run(client, role) { if (role.managed) return; let guild = role.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color') let antiraidLog = guildData.get('logs').antiraid; diff --git a/events/antiraid/roleDelete.js b/events/antiraid/roleDelete.js index ccffa741..64b50332 100644 --- a/events/antiraid/roleDelete.js +++ b/events/antiraid/roleDelete.js @@ -11,7 +11,7 @@ module.exports = class roleDelete extends Event { async run(client, role) { if(role.managed) return; let guild = role.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color') let antiraidLog = guildData.get('logs').antiraid; diff --git a/events/antiraid/roleUpdate.js b/events/antiraid/roleUpdate.js index a5ded9d9..40cbaeb6 100644 --- a/events/antiraid/roleUpdate.js +++ b/events/antiraid/roleUpdate.js @@ -10,7 +10,7 @@ module.exports = class roleUpdate extends Event { async run(client, oldRole, newRole) { if (oldRole === newRole) return; const guild = oldRole.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; if (oldRole.managed && newRole.managed) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color') diff --git a/events/blacklist/role.js b/events/blacklist/role.js index 6814167c..0f03d2c0 100644 --- a/events/blacklist/role.js +++ b/events/blacklist/role.js @@ -14,7 +14,7 @@ module.exports = class Ready extends Event { const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); const {enable, blacklistedRoles} = guildData.get('blacklistRole'); if (!enable && !blacklistedRoles.length && !blacklistedRoles.includes(role.id)) return - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; let action = await guild.fetchAuditLogs({type: "MEMBER_ROLE_UPDATE"}).then(async (audit) => audit.entries.first()); if (action.executor.id === client.user.id) return Logger.log(`No sanction oneforall`, `${this.name}`, 'pink'); if (guild.ownerID === action.executor.id) return Logger.log(`No sanction crown`, `${this.name}`, 'pink'); diff --git a/events/create/guildCreate.js b/events/create/guildCreate.js index 82e8f375..2fdde20f 100644 --- a/events/create/guildCreate.js +++ b/events/create/guildCreate.js @@ -17,7 +17,7 @@ module.exports = class guildCreate extends Event { owners: client.botperso ? [] : [guild.ownerID] }).save() - const newInv = await guild.fetchInvites() + const newInv = await guild.invites.fetch() for (const [code, invite] of newInv) { guildData.cachedInv.set(code, invite) } diff --git a/events/invite/InviteAdd.js b/events/invite/InviteAdd.js index 488b92f9..a376cec8 100644 --- a/events/invite/InviteAdd.js +++ b/events/invite/InviteAdd.js @@ -20,7 +20,7 @@ module.exports = class Ready extends Event { const channel = guild.channels.cache.get(id); const lang = guildData.lang; const {cachedInv} = guildData; - const newInv = await guild.fetchInvites() + const newInv = await guild.invites.fetch() const usedInv = newInv.find(inv => cachedInv.get(inv.code) ? cachedInv.get(inv.code).uses < inv.uses : undefined); for (const [code, invite] of newInv) { diff --git a/events/invite/InviteRemove.js b/events/invite/InviteRemove.js index 9fab1d15..9cab0268 100644 --- a/events/invite/InviteRemove.js +++ b/events/invite/InviteRemove.js @@ -9,7 +9,7 @@ module.exports = class Ready extends Event{ async run(client, member){ const {guild} = member; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); - const guildInv = await guild.fetchInvites() + const guildInv = await guild.invites.fetch() for(const [code, invite] of guildInv){ guildData.cachedInv.set(code, invite) } diff --git a/events/invite/inviteCreate.js b/events/invite/inviteCreate.js index 8774574b..8281555b 100644 --- a/events/invite/inviteCreate.js +++ b/events/invite/inviteCreate.js @@ -11,7 +11,7 @@ module.exports = class inviteCreate extends Event { async run(client, invite) { const guild = invite.guild; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); - const guildInv = await guild.fetchInvites() + const guildInv = await guild.invites.fetch() for(const [code, invite] of guildInv){ guildData.cachedInv.set(code, invite) } diff --git a/events/invite/inviteDelete.js b/events/invite/inviteDelete.js index f0a1aa2b..5cea47da 100644 --- a/events/invite/inviteDelete.js +++ b/events/invite/inviteDelete.js @@ -11,7 +11,7 @@ module.exports = class inviteCreate extends Event { async run(client, invite) { const guild = invite.guild; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); - const guildInv = await guild.fetchInvites() + const guildInv = await guild.invites.fetch() for(const [code, invite] of guildInv){ guildData.cachedInv.set(code, invite) } diff --git a/events/logs/ban.js b/events/logs/ban.js index 66a30366..8a5dca26 100644 --- a/events/logs/ban.js +++ b/events/logs/ban.js @@ -10,7 +10,7 @@ module.exports = class Ready extends Event{ }); } async run(client, guild, user){ - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); let modLog = guildData.get('logs').mod; const { logs } = guildData.lang diff --git a/events/logs/channelCreate.js b/events/logs/channelCreate.js index bb770b4f..4ad50d9e 100644 --- a/events/logs/channelCreate.js +++ b/events/logs/channelCreate.js @@ -12,7 +12,7 @@ module.exports = class channelCreate extends Event { async run(client, channel) { if (channel.type === "dm") return; let guild = channel.guild - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); const color = guildData.get('color'); let modLog = guildData.get('logs').mod; diff --git a/events/logs/channelDelete.js b/events/logs/channelDelete.js index 2a6f6d14..755f522e 100644 --- a/events/logs/channelDelete.js +++ b/events/logs/channelDelete.js @@ -12,7 +12,7 @@ module.exports = class channelDelete extends Event { async run(client, channel) { if (channel.type === "dm") return; let guild = channel.guild - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); const color = guildData.get('color'); diff --git a/events/logs/channelUpdate.js b/events/logs/channelUpdate.js index 64fff603..b487a9b5 100644 --- a/events/logs/channelUpdate.js +++ b/events/logs/channelUpdate.js @@ -11,7 +11,7 @@ module.exports = class Ready extends Event{ } async run(client, oldChannel, newChannel){ const guild = oldChannel.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) let modLog = guildData.get('logs').mod; const { logs } = guildData.lang diff --git a/events/logs/guildNameUpdate.js b/events/logs/guildNameUpdate.js index 6202fa21..7dbb92bb 100644 --- a/events/logs/guildNameUpdate.js +++ b/events/logs/guildNameUpdate.js @@ -10,7 +10,7 @@ module.exports = class Ready extends Event{ }); } async run(client, oldGuild, newGuild){ - if (!oldGuild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!oldGuild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(oldGuild.id) let modLog = guildData.get('logs'); const { logs } = guildData.lang diff --git a/events/logs/guildVanityUpdate.js b/events/logs/guildVanityUpdate.js index 35d381c6..1679a175 100644 --- a/events/logs/guildVanityUpdate.js +++ b/events/logs/guildVanityUpdate.js @@ -8,7 +8,7 @@ module.exports = class guildVanityUpdate extends Event { } async run(client, guild, oldVanityURL, newVanityURL) { - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) let modLog = guildData.get('logs').mod; const { logs } = guildData.lang diff --git a/events/logs/kick.js b/events/logs/kick.js index 7d9bed7a..45250ce1 100644 --- a/events/logs/kick.js +++ b/events/logs/kick.js @@ -11,7 +11,7 @@ module.exports = class Ready extends Event{ } async run(client, member){ const { guild } = member - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); let modLog = guildData.get('logs').mod; const { logs } = guildData.lang diff --git a/events/logs/messageUpdate.js b/events/logs/messageUpdate.js index 628f006f..d289c127 100644 --- a/events/logs/messageUpdate.js +++ b/events/logs/messageUpdate.js @@ -8,7 +8,7 @@ module.exports = class messageUpdate extends Event { } async run(client, oldMessage, newMessage) { - if (!oldMessage.guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!oldMessage.guild.me.permissions.has("VIEW_AUDIT_LOG")) return; if (!oldMessage.guild) return; if (!oldMessage.author) return; if (oldMessage.author.bot || newMessage.author.bot) return; diff --git a/events/logs/roleAdd.js b/events/logs/roleAdd.js index 64ddc914..3b1085e0 100644 --- a/events/logs/roleAdd.js +++ b/events/logs/roleAdd.js @@ -13,7 +13,7 @@ module.exports = class Ready extends Event { async run(client, member, role) { let {guild} = member; if (!role.permissions.has("KICK_MEMBERS") || !role.permissions.has("BAN_MEMBERS") || !role.permissions.has("ADMINISTRATOR") || !role.permissions.has("MANAGE_CHANNELS") || !role.permissions.has("MANAGE_GUILD") || !role.permissions.has("MANAGE_ROLES") || !role.permissions.has("MENTION_EVERYONE")) return; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); const color = guildData.get('color') const modLog = guildData.get('logs').mod diff --git a/events/logs/roleCreate.js b/events/logs/roleCreate.js index 1a7148ce..5ac10d89 100644 --- a/events/logs/roleCreate.js +++ b/events/logs/roleCreate.js @@ -11,7 +11,7 @@ module.exports = class roleCreate extends Event { async run(client, role) { if (role.managed) return; let guild = role.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) const color = guildData.get('color'); let {logs} = guildData.lang diff --git a/events/logs/roleDelete.js b/events/logs/roleDelete.js index a1db652d..0eea519a 100644 --- a/events/logs/roleDelete.js +++ b/events/logs/roleDelete.js @@ -11,7 +11,7 @@ module.exports = class roleDelete extends Event { async run(client, role) { if (role.managed) return; let guild = role.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); const color = guildData.get('color') const modLog = guildData.get('logs').mod diff --git a/events/logs/roleRemove.js b/events/logs/roleRemove.js index d455b83c..a4f8045c 100644 --- a/events/logs/roleRemove.js +++ b/events/logs/roleRemove.js @@ -13,7 +13,7 @@ module.exports = class Ready extends Event { async run(client, member, role) { let guild = member.guild; if (!role.permissions.has("KICK_MEMBERS") || !role.permissions.has("BAN_MEMBERS") || !role.permissions.has("ADMINISTRATOR") || !role.permissions.has("MANAGE_CHANNELS") || !role.permissions.has("MANAGE_GUILD") || !role.permissions.has("MANAGE_ROLES") || !role.permissions.has("MENTION_EVERYONE")) return; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id); const color = guildData.get('color') const modLog = guildData.get('logs').mod diff --git a/events/logs/roleUpdate.js b/events/logs/roleUpdate.js index 80ac5ef0..6d1e3b67 100644 --- a/events/logs/roleUpdate.js +++ b/events/logs/roleUpdate.js @@ -12,7 +12,7 @@ module.exports = class Ready extends Event{ async run(client, oldRole, newRole){ const guild = oldRole.guild; if(!guild.config) return - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) let modLog = guildData.get('logs').mod; const { logs } = guildData.lang diff --git a/events/logs/unban.js b/events/logs/unban.js index 8b7c2893..9e5c06c3 100644 --- a/events/logs/unban.js +++ b/events/logs/unban.js @@ -11,7 +11,7 @@ module.exports = class Ready extends Event{ } async run(client, guild, user){ if(!guild.config) return - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) let modLog = guildData.get('logs'); const { logs } = guildData.lang diff --git a/events/logs/voiceChannel.js b/events/logs/voiceChannel.js index 731ca1a2..6a224fae 100644 --- a/events/logs/voiceChannel.js +++ b/events/logs/voiceChannel.js @@ -12,7 +12,7 @@ module.exports = class Ready extends Event { async run(client, oldState, newState) { const guild = oldState.guild; - if (!guild.me.hasPermission("VIEW_AUDIT_LOG")) return; + if (!guild.me.permissions.has("VIEW_AUDIT_LOG")) return; const guildData = client.managers.guildManager.getAndCreateIfNotExists(guild.id) let voiceLog = guildData.get('logs').voice; const {logs} = guildData.lang diff --git a/events/piconly/message.js b/events/piconly/message.js index 6182e996..35b9e110 100644 --- a/events/piconly/message.js +++ b/events/piconly/message.js @@ -2,7 +2,7 @@ const Event = require('../../structures/Handler/Event'); module.exports = class message extends Event { constructor() { super({ - name: 'message', + name: 'messageCreate', }); } diff --git a/events/reactionToMessages/index.js b/events/reactionToMessages/index.js index b2bd17cb..ed7fabf3 100644 --- a/events/reactionToMessages/index.js +++ b/events/reactionToMessages/index.js @@ -6,7 +6,7 @@ let now = new Date() module.exports = class Ready extends Event { constructor() { super({ - name: 'message', + name: 'messageCreate', }); } diff --git a/events/shards/disconnect.js b/events/shards/disconnect.js index 668b3c2c..e7c7f9dd 100644 --- a/events/shards/disconnect.js +++ b/events/shards/disconnect.js @@ -1,7 +1,7 @@ const StateManager = require('../../utils/StateManager'); const Discord = require('discord.js') -const hook = new Discord.WebhookClient('801060243785383936', 'foWpfz4X8OEwrZ4SQfOR1khPOH0YdF1AsHzjfIqFW_iRpTSqtPfDwFJYUOx91Y4xv5oq'); + // let all = new Map(); const Event = require('../../structures/Handler/Event'); @@ -14,7 +14,7 @@ module.exports = class messageReactionAdd extends Event { async run(client, event, id) { console.log(`Shard ${id} is disconnect with ${event}`) - hook.send(`\`[${new Date().toString().split(" ", 5).join(" ")}]\` <:464520569560498197:868814521949650984> Shard \`#${id + 1}\` est dΓ©connectΓ© \nβ–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬ `) + await client.shardWebhook.send(`\`[${new Date().toString().split(" ", 5).join(" ")}]\` <:464520569560498197:868814521949650984> Shard \`#${id + 1}\` est dΓ©connectΓ© \nβ–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬ `) } } diff --git a/events/shards/ready.js b/events/shards/ready.js index b2a5ab8f..2a1ea670 100644 --- a/events/shards/ready.js +++ b/events/shards/ready.js @@ -1,6 +1,3 @@ -const StateManager = require('../../utils/StateManager'); -const Discord = require('discord.js') -const hook = new Discord.WebhookClient('801060243785383936', 'foWpfz4X8OEwrZ4SQfOR1khPOH0YdF1AsHzjfIqFW_iRpTSqtPfDwFJYUOx91Y4xv5oq'); // let all = new Map(); const Event = require('../../structures/Handler/Event'); @@ -14,7 +11,7 @@ module.exports = class messageReactionAdd extends Event { async run(client, id, unavailableGuilds) { console.log(`Shard ${id} is ready with ${unavailableGuilds}`) if(client.config.dev) return; - hook.send(`\`[${new Date().toString().split(" ", 5).join(" ")}]\` <:464520569975603200:868814251186348042> Shard \`#${id+ 1}\` prΓͺt \nβ–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬`) + await client.shardWebhook.send(`\`[${new Date().toString().split(" ", 5).join(" ")}]\` <:464520569975603200:868814251186348042> Shard \`#${id + 1}\` prΓͺt \nβ–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬`) } } diff --git a/events/shards/reconnecting.js b/events/shards/reconnecting.js index 6efd6d3f..c05207b3 100644 --- a/events/shards/reconnecting.js +++ b/events/shards/reconnecting.js @@ -1,6 +1,4 @@ -const Discord = require('discord.js') -const hook = new Discord.WebhookClient('801060243785383936', 'foWpfz4X8OEwrZ4SQfOR1khPOH0YdF1AsHzjfIqFW_iRpTSqtPfDwFJYUOx91Y4xv5oq'); // let all = new Map(); const Event = require('../../structures/Handler/Event'); @@ -13,7 +11,8 @@ module.exports = class messageReactionAdd extends Event { async run(client, id) { console.log(`Shard ${id} is reconnecting`) - hook.send(`\`[${new Date().toString().split(" ", 5).join(" ")}]\` <:464520569862357002:868813759110590544> Shard \`#${id + 1}\` se reconnecte \nβ–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬ `) + if(client.config.dev || client.config.botperso) return + await client.shardWebhook.send(`\`[${new Date().toString().split(" ", 5).join(" ")}]\` <:464520569862357002:868813759110590544> Shard \`#${id + 1}\` se reconnecte \nβ–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬ `) } } diff --git a/events/shards/resume.js b/events/shards/resume.js index 69cae9f0..b51ca75d 100644 --- a/events/shards/resume.js +++ b/events/shards/resume.js @@ -1,6 +1,4 @@ -const Discord = require('discord.js') -const hook = new Discord.WebhookClient('801060243785383936', 'foWpfz4X8OEwrZ4SQfOR1khPOH0YdF1AsHzjfIqFW_iRpTSqtPfDwFJYUOx91Y4xv5oq'); // let all = new Map(); const Event = require('../../structures/Handler/Event'); @@ -13,7 +11,8 @@ module.exports = class messageReactionAdd extends Event { async run(client, id, event) { console.log(`Shard ${id} is resumed ${event}`) - hook.send(`\`[${new Date().toString().split(" ", 5).join(" ")}]\` <:464520569975603200:868814251186348042> Shard \`#${id + 1}\` prΓͺt \nβ–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬`) + if(client.config.dev || client.config.botperso) return + await client.shardWebhook.send(`\`[${new Date().toString().split(" ", 5).join(" ")}]\` <:464520569975603200:868814251186348042> Shard \`#${id + 1}\` prΓͺt \nβ–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬`) } } diff --git a/events/xp/message.js b/events/xp/message.js index f845ae91..6c7c2fc3 100644 --- a/events/xp/message.js +++ b/events/xp/message.js @@ -3,7 +3,7 @@ const Event = require('../../structures/Handler/Event'); module.exports = class Ready extends Event { constructor() { super({ - name: 'message', + name: 'messageCreate', }); } diff --git a/index.js b/index.js index 196244ef..664de2cd 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,5 @@ const moment = require('moment') -const express = require('express') - +const { Intents } = require('discord.js') require('dotenv').config(); require('discord-reply') const {OneForAll} = require('./structures/Client/OneForAll') @@ -20,7 +19,7 @@ if(!dev && !botperso) { }) } else - new OneForAll({partials: ['MESSAGE', 'CHANNEL', 'REACTION'], restTimeOffset: 0}) + new OneForAll({partials: ['MESSAGE', 'CHANNEL', 'REACTION'], restTimeOffset: 0, intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.DIRECT_MESSAGE_REACTIONS, Intents.FLAGS.GUILD_BANS, Intents.FLAGS.GUILD_EMOJIS_AND_STICKERS, Intents.FLAGS.GUILD_WEBHOOKS, Intents.FLAGS.GUILD_INVITES, Intents.FLAGS.GUILD_MEMBERS, Intents.FLAGS.GUILD_VOICE_STATES, Intents.FLAGS.GUILD_PRESENCES, Intents.FLAGS.GUILD_MESSAGES]}) require('events').EventEmitter.defaultMaxListeners = 0; diff --git a/lang/af.js b/lang/af.js index 27624ef1..cd2a9f12 100644 --- a/lang/af.js +++ b/lang/af.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/ar.js b/lang/ar.js index 0bb74dfe..59f4d137 100644 --- a/lang/ar.js +++ b/lang/ar.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/ca.js b/lang/ca.js index 0bb74dfe..59f4d137 100644 --- a/lang/ca.js +++ b/lang/ca.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/cs.js b/lang/cs.js index 0bb74dfe..59f4d137 100644 --- a/lang/cs.js +++ b/lang/cs.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/da.js b/lang/da.js index 0bb74dfe..59f4d137 100644 --- a/lang/da.js +++ b/lang/da.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/de.js b/lang/de.js index 7cc3674c..8eedac7a 100644 --- a/lang/de.js +++ b/lang/de.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Bot-Latenz: \`${ ping }\` ms, Api-Latenz: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819: 780727288903237663> Das PrΓ€fix fΓΌr diesen Server ist \`${ prefix }\`.\n <: desc2: 783422775821729792> Um weitere Informationen zu einem Befehl zu erhalten, geben Sie einfach \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Sie kΓΆnnen auch eingeben \`${ prefix }help commands\` oder reagiere mit πŸ“„ um alle meine Bestellungen zu bekommen.`, + information2: prefix => `<:778353230484471819: 780727288903237663> Das PrΓ€fix fΓΌr diesen Server ist \`${ prefix }\`.\n <: desc2: 783422775821729792> Um weitere Informationen zu einem Befehl zu erhalten, geben Sie einfach \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` oder reagiere mit πŸ“„ um alle meine Bestellungen zu bekommen.`, noCommand: args => `Ich kann den Befehl nicht finden ** __${ args }__ ** in meinen Bestellungen`, information: `Informationen und Befehle`, noAliases: `Keine Aliase`, @@ -63,7 +63,6 @@ module.exports = { > <:Headset-Stummschaltung: 801123005287628890> Headset-Stummschaltung: **${ muteHeadSetCount }** > <:stumm: 801122908445212723> Mikrofon stumm schalten: **${ muteCount }**\n\n<:sageata: 788796887121657877> Gesamtzahl der gesprochenen Personen: **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll ist ein Bot im Besitz von* \`TAKEFY#9831\`\n\n**Entwickler:**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideen & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Kommunikation\n` }, alladmins: { error: `Kein Administrator auf diesem Server.`, list: `Liste der Admins` @@ -73,11 +72,11 @@ module.exports = { errorRl: member => `<:720681441670725645: 780539422479351809> \ `FEHLER \` Sie kΓΆnnen nicht sperren **\`${ member.tag }\`** weil sie mehr Berechtigungen haben als du`, errorBanSelf: '<:720681441670725645: 780539422479351809> `FEHLER` Sie kΓΆnnen sich nicht selbst sperren', noReason: 'Kein konkreter Grund', - success: member => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ member.tag } a Γ©tΓ© ban.`, - error: member => `<:720681441670725645:780539422479351809> \`ERREUR\` DΓ©solΓ©, je ne suis pas arrivΓ© Γ  bannir ${ member.tag }`, - alreadyBan: member => `<:720681441670725645:780539422479351809> \`ERREUR\` **${ member.tag }** est dΓ©jΓ  banni`, - missingPerm: member => `<:720681441670725645:780539422479351809> \`ERREUR\` Je n'ai pas assΓ© de permission pour bannir **${ member.tag }**`, - dm: (guildName, bannerName) => `Vous avez Γ©tΓ© banni de ${ guildName } par ${ bannerName }` + success: member => `<:720681705219817534:780540043033837622> \`ERFOLG\` ${ member.tag } wurde gesperrt.`, + error: member => `<:720681441670725645:780539422479351809> \`FEHLER\` Entschuldigung, das Sperren war nicht erfolgreich ${ member.tag }`, + alreadyBan: member => `<:720681441670725645:780539422479351809> \`FEHLER\` **${ member.tag }** ist bereits gesperrt`, + missingPerm: member => `<:720681441670725645:780539422479351809> \`Fehler\` Ich habe keine ausreichenden Rechte zum sperren **${ member.tag }**`, + dm: (guildName, bannerName) => `Sie wurden gesperrt in:${ guildName }von:${ bannerName }` }, banlist: { title: guild => `Membre(s) banni sur le serveur __${ guild.name }__`, @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll ist ein Bot im Besitz von* \`TAKEFY#9831\`\n\n**Entwickler:**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideen & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Kommunikation\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,44 +1173,44 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { - time: `Quel est la durΓ©e du giveaway ?`, - channel: `Dans quel channel le giveaway doit Γͺtre lancΓ© ?`, - winnerCount: `Combien doit-il y avoir de gagnants ?`, - reaction: `Quel est la reaction pour le giveaway ?`, - prize: `Que voulez-vous faire gagner ?` + time: `Wie lang ist die Dauer des Giveaways?`, + channel: `In welchem Kanal soll das Giveaway stattfinden?`, + winnerCount: `Wie viele Gewinner soll es geben?`, + reaction: `Wie ist die Reaktion fΓΌr das Giveaway?`, + prize: `Was gibt es zu Gewinnen?` }, inccorectResponse: { - time: `La durΓ©e n'est pas valide\nExemple : \`30m\``, - channel: `Le channel est incorrect` + time: `Die Dauer ist nicht zulΓ€ssig\nBeispiel : \`30m\``, + channel: `Der Kanal ist inkorrekt` }, successMessage: { - time: time => `Le temps du giveaway est donc prΓ©vue pour **${ time }**`, - channel: channel => `Le giveaway sera lancΓ© de le salon ${ channel }`, - winnerCount: winner => `Le nombre de gagnant est maintenant dΓ©finie pour **${ winner }**`, - prize: prize => `Vous voulez faire gagner **${ prize }**`, - reaction: emoji => `La reaction pour le giveaway est maintenant ${ emoji }` + time: time => `Das Giveaway ist geplant fΓΌr: **${ time }**`, + channel: channel => `Das Giveaway wird vom Wohnzimmer aus gestartet ${ channel }`, + winnerCount: winner => `Die Anzahl der Gewinner ist festgelegt auf **${ winner }**`, + prize: prize => `Sie kΓΆnnen folgendes gewinnen: **${ prize }**`, + reaction: emoji => `Die Reaktion fΓΌr das Giveaway ist festgelegt auf: ${ emoji }` } }, messages: { @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/el.js b/lang/el.js index 0bb74dfe..59f4d137 100644 --- a/lang/el.js +++ b/lang/el.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/en.js b/lang/en.js index f14a6253..d6a22549 100644 --- a/lang/en.js +++ b/lang/en.js @@ -33,7 +33,7 @@ Sorry I did not manage to do that I did not have enough permission.`, success: (ping, client) => `Bot latency: \`${ ping }\` ms, API latency: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> The prefix for this server is \`${ prefix }\`.\n<:desc2:783422775821729792> To get more information about a command, just type \`${ prefix }help\` \`command\`.\n<:folder:783422648196923452> You can also type \`${ prefix }help commands\` or press on πŸ“„ to get all my commands.`, + information2: prefix => `<:778353230484471819:780727288903237663> The prefix for this server is \`${ prefix }\`.\n<:desc2:783422775821729792> To get more information about a command, just type \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` or press on πŸ“„ to get all my commands.`, noCommand: args => `I don't find this command (${ args }) in my commands`, information: `Information and commands`, noAliases: `No aliases`, @@ -66,7 +66,6 @@ Sorry I did not manage to do that I did not have enough permission.`, > <:mutecasque:801123005287628890> Headphone mute : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute microphone : **${ muteCount }**\n\n<:sageata:788796887121657877> Total of members in voice channel : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll is a bot owned by* \`TAKEFY#9831\`\n\n**Developer :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[rh#0002](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `There is 0 admins on server.`, list: `List of admins` @@ -104,39 +103,172 @@ Sorry I did not manage to do that I did not have enough permission.`, dero: { success: '<:720681705219817534:780540043033837622> `SUCCES` All waivers have been updated.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Loading... `, title: `Embed creation menu !`, description: ` Welcome to the embed creation menu ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Allows you to edit the title`, - descriptionField: `・Allows you to modify the description`, - authorField: `・Allows you to modify the author`, - footerField: `・Allows you to modify the footer`, - thumbnailField: `・Allows you to edit the thumbnail`, - imageField: `・Allows you to edit the image`, - urlField: `・Allows you to modify the url`, - colorField: `・Allows you to change the color`, - timestampField: `・Allows you to add a timestamp`, - copyField: `Copy an embed and edit it`, - cancelField: `・Allows to cancel the creation of the embed`, - sendField: `・Allows to send the embed with the bot`, - titleMsg: `✏ What title do you want for your embed ?`, - descriptionMsg: `πŸ“ What description do you want for your embed ?`, - authorMsg: `πŸ—£ Which author do you want for your embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– What footer do you want for your embed ?`, - footerUrl: `πŸ– What is the icon for the footer? ('no' if blank)`, - thumbnailMsg: `πŸ’Ά Which thumbnail do you want for your embed ?`, - imageMsg: `πŸ–Ό What image do you want for your embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 What url do you want for your embed ?`, - colorMsg: `🎨 What color do you want for your embed (\`HEX or rouge/vert/jaune/violet/rose/noir/blanc/bleu/orange/invisible\`)?`, - copyMsg: `Β© What is the channel where the embed is located (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© What is the id of the embed message (\`id\`)?`, - cancelMsg: `❌ Do you want to cancel the creation of the embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… In which channel do you want to send the embed \`mention ou id\`?`, errorUrl: `The url must start with __http/https__`, errorColor: `Please enter a valid color \`HEX or rouge/vert/jaune/violet/rose/noir/blanc/bleu/orange/invisible\``, - errorChannel: `I can't find this channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Please enter a valid id !`, errorMessage: ch => `I can't find the message in the channel ${ ch } !` }, @@ -246,7 +378,7 @@ Sorry I did not manage to do that I did not have enough permission.`, 2 ・ Configure the personalized status message that members should have.\n __Current message__ : **${ soutienMsg }** \n 3 ・ Enable or disable support \n - __Active__ : ${ isOnS } + __Active__ : ${ isOnS } `, roleQ: ` Mention the role the supporters will receive (cancel to cancel)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCES\` Supporters will now receive the role: ${ response }.`, @@ -322,6 +454,48 @@ Sorry I did not manage to do that I did not have enough permission.`, titleList: `<:778353230383546419:781153631881265173> List of owners` }, invite: { + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, countDesc: (tag, userInviteCount, inv) => ` **${ tag }** currently owns : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, @@ -333,7 +507,7 @@ Sorry I did not manage to do that I did not have enough permission.`, __Current message__ : **${ inviteMsg }** \n 3 ・ Help for the welcome message \n 4 ・ Activate or deactivate the welcome message \n - __Active__ : ${ isOnS } + __Active__ : ${ isOnS } `, chQ: ` Mention the channel where the welcome messages will be sent (cancel to cancel)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCES\` Welcome messages will now be sent to the channel ${ response }.`, @@ -344,17 +518,6 @@ Sorry I did not manage to do that I did not have enough permission.`, errorMsg: `<:720681441670725645:780539422479351809> \`ERROR\` I have not been able to change the welcome message to :`, timeout2M: '<:720681441670725645:780539422479351809> `ERROR` No response after 2 minutes operation will be canceled', helpTitle: `<:771462923855069204:784471984087236658> __Help on configuring the welcome message__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Do you want to activate welcome messages? Yes / No (cancel to cancel)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCES\` I have activated the welcome messages !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERROR\` I have not arrived to activate the welcome messages...`, @@ -381,7 +544,11 @@ Sorry I did not manage to do that I did not have enough permission.`, successChange: `You've correctly change your password !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll is a bot owned by* \`TAKEFY#9831\`\n\n**Developer :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[rh#0002](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `The bot language is now set to${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `The bot language is now set to${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERROR\` You need to provide an emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERROR\` You need to provide a name for the emoji`, @@ -400,10 +567,10 @@ Sorry I did not manage to do that I did not have enough permission.`, **1** ・ Ignore channels (**${ ignoreCh }**) **2** ・ Ignore roles (**${ ignoreRl }**) **3** ・ Ignore emojis (**${ ignoreEmo }**) - **4** ・ Ignore bans (**${ ignoreBans }**)\n - **❌** ・ Close menu - **βœ…** ・ Create the backup - + **4** ・ Ignore bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCES\` Backup creation canceled!`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCES\` I deleted the backup **${ backupId }** !`, @@ -502,6 +669,44 @@ Sorry I did not manage to do that I did not have enough permission.`, successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCES\` You have defined the channel for the boosts counter to ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Role reaction creation menu`, embedDescription: (channel, id, emoji, role) => ` \n @@ -523,6 +728,7 @@ Sorry I did not manage to do that I did not have enough permission.`, notText: `The channel should only be of the type **text**`, chQ: `πŸ“– What is the channel where you would like to have your reaction role ? (\`mention/id\`) (cancel to cancel)`, successCh: ch => `You have defined the channel to **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” What is the message id for your reaction role ? (\`id\`) (cancel to cancel)`, notId: `Please enter a valid id !`, noChannel: `You have not defined a channel so I could not retrieve the message`, @@ -545,16 +751,17 @@ Sorry I did not manage to do that I did not have enough permission.`, noEmoji: `You haven't set an emoji and role.`, alreadyReact: `A reaction role already exists with this message`, success: `The reaction role has been perfectly saved and created !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `You can't add a role with sensible permissions` }, tempvoc: { embedTitle: `Temporary voice creation menu`, - embedDescription: (tempname, enable) => ` - \n - Click on the reactions to be able to configure the temporary voice ! - - \`πŸ•³\` ・ Auto configure temporary voice - \`πŸ’¬\` ・ Change the name of the user's temporary room + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur ***${ tempname }***\n \`πŸ’¨\` ・ Activate / deactivate temporary voice **${ enable }**\n @@ -602,10 +809,10 @@ Sorry I did not manage to do that I did not have enough permission.`, kickDm: (amount, serverName) => `You were kicked by **${ serverName }** because you reached the warn limit with \`(${ amount })\` warn(s)`, muteDm: (amount, serverName) => `You have been muted from **${ serverName }** because you have reached the warn limit with \`(${ amount })\` warn (s)`, settingsTitle: `Warns configuration`, - description: (ban, kick, mute) => ` \n - Click on the reactions to be able to configure the warns! - To put no sanction, just put __0__ - \`πŸ’₯\` ・ Modify the number of warn before ban + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban ***${ ban }***\n \`πŸ’’\` ・ Modify the number of warn before kick ***${ kick }***\n @@ -638,21 +845,19 @@ Sorry I did not manage to do that I did not have enough permission.`, }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam ***${ streamBoost }***\n \`😢\` ・ Modifier le diviseur si un membre est mute ***${ muteDiviseur }***\n \`πŸ’Œ\` ・ ModifiΓ© le salon des logs **${ logs }**\n \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1176,26 @@ Sorry I did not manage to do that I did not have enough permission.`, inccorectWinner: `The number of winners is not valid \nExample usage: \`!gcreate 10m 1w Nitro ($ 9.99)\``, winnerMustRange: `The number of winners must be greater than 0 \nExample usage: \`!gcreate 10m 1w Nitro ($9.99)\``, noPrize: `The gain is invalid \nExample usage: \`!gcreate 10m 1w Nitro ($ 9.99)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `How long is the giveaway?`, @@ -1052,27 +1257,27 @@ Sorry I did not manage to do that I did not have enough permission.`, successDelete: channel => `Messages in ${ channel } will no longer receive reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1295,21 @@ Sorry I did not manage to do that I did not have enough permission.`, save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,24 +1330,6 @@ Sorry I did not manage to do that I did not have enough permission.`, success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `You must specify a role`, - noInvite: ` -You must specify a prompt number`, - notNumber: ` -You must specify a valid prompt number`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => ` -The role **${ role }** now added from *${ invite }* invite(s)`, - noOnOff: `You must specify on or off \n \`Example: !inviterole cumul on \``, - successCumul: isOn => ` -The cumulative roles are now **${ isOn }**.`, - doestNotExist: `the invite role does not exist`, - alreadyExist: `the invite role already exists`, - successRm: role => ` -the${ role } -has been removed from the invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/es.js b/lang/es.js index a11f771e..c9c6f453 100644 --- a/lang/es.js +++ b/lang/es.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -63,7 +63,6 @@ module.exports = { > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou rouge/vert/jaune/violet/rose/noir/blanc/bleu/orange/invisible\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`#0CAE45/rouge/vert/jaune/violet/rose/noir/blanc/bleu/orange/invisible\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -243,7 +375,7 @@ module.exports = { 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n __Message actuel__ : **${ soutienMsg }** \n 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -319,6 +451,48 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, countDesc: (tag, userInviteCount, inv) => ` **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, @@ -331,7 +505,7 @@ module.exports = { 3 ・ Aide sur le message de bienvenue \n 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -342,17 +516,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -379,7 +542,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -398,11 +565,10 @@ module.exports = { **1** ・ Ignorer les channels (**${ ignoreCh }**) **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -501,6 +667,44 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, embedDescription: (channel, id, emoji, role) => ` \n @@ -522,6 +726,7 @@ module.exports = { notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -544,17 +749,17 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur ***${ tempname }***\n \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire **${ enable }**\n @@ -602,11 +807,10 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban ***${ ban }***\n \`πŸ’’\` ・ Modifier le nombre de warn avant de kick ***${ kick }***\n @@ -639,21 +843,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam ***${ streamBoost }***\n \`😢\` ・ Modifier le diviseur si un membre est mute ***${ muteDiviseur }***\n \`πŸ’Œ\` ・ ModifiΓ© le salon des logs **${ logs }**\n \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -972,26 +1174,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1053,27 +1255,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1091,21 +1293,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1126,18 +1328,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/fi.js b/lang/fi.js index 0bb74dfe..59f4d137 100644 --- a/lang/fi.js +++ b/lang/fi.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/fr.js b/lang/fr.js index a982d4e3..59f4d137 100644 --- a/lang/fr.js +++ b/lang/fr.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -63,7 +63,6 @@ module.exports = { > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -243,7 +375,7 @@ module.exports = { 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n __Message actuel__ : **${ soutienMsg }** \n 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -319,6 +451,48 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, countDesc: (tag, userInviteCount, inv) => ` **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, @@ -330,7 +504,7 @@ module.exports = { __Message Actuel__ : ${ inviteMsg } \n 3 ・ Aide sur le message de bienvenue \n 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -401,7 +568,6 @@ module.exports = { **❌** ・ Fermer le menu **βœ…** ・ CrΓ©er la backup - `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -500,6 +666,44 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, embedDescription: (channel, id, emoji, role) => ` \n @@ -521,6 +725,7 @@ module.exports = { notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,6 +748,7 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { @@ -552,7 +758,6 @@ module.exports = { Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! \`πŸ•³\` ・ Auto configurer le vocal temporaire - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur ***${ tempname }***\n \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire @@ -604,7 +809,6 @@ module.exports = { description: (ban, kick, mute) => ` \n Cliquez sur les reactions pour pouvoir configurer les warns ! Pour mettre aucune sanction il suffit de mettre __0__ - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban ***${ ban }***\n \`πŸ’’\` ・ Modifier le nombre de warn avant de kick @@ -641,7 +845,6 @@ module.exports = { description: (streamBoost, muteDiviseur, logs, enable) => ` \n Cliquez sur les reactions pour pouvoir configurer les warns ! - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam ***${ streamBoost }***\n \`😢\` ・ Modifier le diviseur si un membre est mute @@ -650,7 +853,6 @@ module.exports = { **${ logs }**\n \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins **${ enable }** - \`❌\` ・ Fermer le menu\n \`βœ…\` ・ Sauvegarder la configuration `, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/he.js b/lang/he.js index 0bb74dfe..59f4d137 100644 --- a/lang/he.js +++ b/lang/he.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/hu.js b/lang/hu.js index 0bb74dfe..59f4d137 100644 --- a/lang/hu.js +++ b/lang/hu.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/it.js b/lang/it.js index 4e2a98dc..aa913225 100644 --- a/lang/it.js +++ b/lang/it.js @@ -12,7 +12,7 @@ module.exports = { error: { YesNo: `Veuillez rΓ©pondre par \`oui ou non\` uniquement !`, timeout: `Temps Γ©coulΓ© !`, - cooldown: time => `Veuillez executer la commande dans \`${ time }\` secondes.`, + cooldown: time => `Veuillez executer la commande dans \`${ time }\` secondi.`, noSetup: 'Vous devez setup le bot pour pouvoir utiliser cette commande (!setup)', NoYes: 'Vous devez rΓ©pondre uniquement avec oui ou non !', ownerOnly: `Seulement le propriΓ©taire du bot peut faire cette commande`, @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/ja.js b/lang/ja.js index 0bb74dfe..59f4d137 100644 --- a/lang/ja.js +++ b/lang/ja.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/ko.js b/lang/ko.js index 0bb74dfe..59f4d137 100644 --- a/lang/ko.js +++ b/lang/ko.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/nl.js b/lang/nl.js index 0bb74dfe..59f4d137 100644 --- a/lang/nl.js +++ b/lang/nl.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/no.js b/lang/no.js index 0bb74dfe..59f4d137 100644 --- a/lang/no.js +++ b/lang/no.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/pl.js b/lang/pl.js index 0bb74dfe..59f4d137 100644 --- a/lang/pl.js +++ b/lang/pl.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/pt.js b/lang/pt.js index 0bb74dfe..59f4d137 100644 --- a/lang/pt.js +++ b/lang/pt.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/ro.js b/lang/ro.js index 9a254011..30887c32 100644 --- a/lang/ro.js +++ b/lang/ro.js @@ -31,7 +31,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -58,13 +58,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -102,39 +101,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou rouge/vert/jaune/violet/rose/noir/blanc/bleu/orange/invisible\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`#0CAE45/rouge/vert/jaune/violet/rose/noir/blanc/bleu/orange/invisible\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -238,13 +370,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -275,20 +407,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -320,19 +452,61 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n __Message Actuel__ : ${ inviteMsg } \n 3 ・ Aide sur le message de bienvenue \n 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -343,17 +517,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -380,7 +543,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -395,15 +562,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -448,29 +614,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -502,27 +668,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -545,25 +750,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -603,19 +808,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -640,21 +844,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -973,26 +1175,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1054,27 +1256,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1092,21 +1294,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1127,18 +1329,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/ru.js b/lang/ru.js index 0bb74dfe..59f4d137 100644 --- a/lang/ru.js +++ b/lang/ru.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/sr.js b/lang/sr.js index 0bb74dfe..59f4d137 100644 --- a/lang/sr.js +++ b/lang/sr.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/sv.js b/lang/sv.js index 0bb74dfe..59f4d137 100644 --- a/lang/sv.js +++ b/lang/sv.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/tr.js b/lang/tr.js index bb81acb7..fd6f385e 100644 --- a/lang/tr.js +++ b/lang/tr.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `bot gecikmesi: \`${ ping }\`ms, l'api gecikmesi: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Bu sunucunun prefix \`${ prefix }\`.\n<:desc2:783422775821729792> Bir sipariş hakkΔ±nda daha fazla bilgi almak iΓ§in yazmanΔ±z yeterlidir \` ${ prefix }YardΔ±m\` \`komutlar\`.\n<:folder:783422648196923452> AyrΔ±ca yazabilirsiniz \`${ prefix }YardΔ±m komutlar\` veya tepki ile birlikteπŸ“„ tΓΌm siparişlerimi almak iΓ§in. `, + information2: prefix => `<:778353230484471819:780727288903237663> Bu sunucunun prefix \`${ prefix }\`.\n<:desc2:783422775821729792> Bir sipariş hakkΔ±nda daha fazla bilgi almak iΓ§in yazmanΔ±z yeterlidir \` ${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }YardΔ±m komutlar\` veya tepki ile birlikteπŸ“„ tΓΌm siparişlerimi almak iΓ§in. `, noCommand: args => `siparişi bulamΔ±yorum **__${ args }__** komutlarΔ±mda `, information: `Bilgi ve komutlar `, noAliases: `takma ad yok `, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/uk.js b/lang/uk.js index 0bb74dfe..59f4d137 100644 --- a/lang/uk.js +++ b/lang/uk.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/vi.js b/lang/vi.js index 0bb74dfe..59f4d137 100644 --- a/lang/vi.js +++ b/lang/vi.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/lang/zh.js b/lang/zh.js index 0bb74dfe..59f4d137 100644 --- a/lang/zh.js +++ b/lang/zh.js @@ -30,7 +30,7 @@ module.exports = { success: (ping, client) => `Latence du bot: \`${ ping }\` ms, Latence de l'api: \`${ Math.round(parseInt(client.ws.ping)) }\` ms` }, help: { - information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`commands\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, + information2: prefix => `<:778353230484471819:780727288903237663> Le prΓ©fixe de ce serveur est \`${ prefix }\`.\n<:desc2:783422775821729792> Pour obtenir plus d'informations sur une commande, tapez simplement \`${ prefix }help\` \`\`.\n<:folder:783422648196923452> Vous pouvez Γ©galement taper \`${ prefix }help commands\` ou rΓ©agir avec πŸ“„ pour obtenir toutes mes commandes.`, noCommand: args => `Je ne trouve pas la commande **__${ args }__** dans mes commandes`, information: `Information and commands`, noAliases: `Pas d'aliases`, @@ -57,13 +57,12 @@ module.exports = { inviteBot: { invite: `Inviter le bot` }, support: { support: `Serveur d'assistance` }, vocal: { - msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : - > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** - > <:stream:801122725602000946> En Stream : **${ streamingCount }** - > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** + msg: (count, muteCount, streamingCount, muteHeadSetCount, openMicCount) => `<:voc:801123036576612353> Statistique vocal : + > <:unmute:801122798629945354> Micro ouvert : **${ openMicCount }** + > <:stream:801122725602000946> En Stream : **${ streamingCount }** + > <:mutecasque:801123005287628890> Mute casque : **${ muteHeadSetCount }** > <:mutemic:801122908445212723> Mute micro : **${ muteCount }**\n\n<:sageata:788796887121657877> Total de personnes en vocal : **${ count }**` }, - authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, alladmins: { error: `Aucun admin sur ce serveur.`, list: `Liste des admins` @@ -101,39 +100,172 @@ module.exports = { dero: { success: '<:720681705219817534:780540043033837622> `SUCCÈS` Toutes les dΓ©rogattions ont Γ©tΓ© mis Γ  jour.' }, embedBuilder: { descriptionRequired: `La description est obligatoire`, + authorPlaceHoler: `Change l'auteur de votre embed`, + footerPlaceHolder: `Change le footer de votre embed`, + copyPlaceHolder: `Copier un embed`, + authorOptions: [ + { + label: 'Name', + value: 'author-text', + description: 'Change le nom de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Icon', + value: 'author-icon', + description: 'Change l\'icon de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Url', + value: 'author-url', + description: 'Change l\'url de l\'auteur', + emoji: 'πŸ—£' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + footerOptions: [ + { + label: 'Text', + value: 'footer-text', + description: 'Change le texte du footer', + emoji: 'πŸ–' + }, + { + label: 'Icon', + value: 'footer-icon', + description: 'Change l\'icon du footer', + emoji: 'πŸ–' + }, + { + label: 'Back', + value: 'back', + description: 'Go back to the default selection', + emoji: '↩' + } + ], + baseMenu: [ + { + label: 'Title', + value: 'title', + description: 'Changer le titre de votre embed', + emoji: '✏', + questionOnly: true + }, + { + label: 'Description', + value: 'description', + description: 'Changer la description de votre embed', + emoji: 'πŸ“', + questionOnly: true + }, + { + label: 'Author', + value: 'author', + description: 'Ajouter un auteur Γ  votre embed', + emoji: 'πŸ—£' + }, + { + label: 'Footer', + value: 'footer', + description: 'Ajouter un footer Γ  votre embed', + emoji: 'πŸ–' + }, + { + label: 'Miniature', + value: 'thumbnail', + description: 'Ajouter une miniature Γ  votre embed', + emoji: 'πŸ’Ά', + questionOnly: true + }, + { + label: 'Image', + value: 'image', + description: 'Ajouter une image Γ  votre embed', + emoji: 'πŸ–Ό', + questionOnly: true + }, + { + label: 'Url', + value: 'url', + description: 'Ajouter un url au titre de votre embed', + emoji: '🌐', + questionOnly: true + }, + { + label: 'Couleur', + value: 'color', + description: 'Changer la couleur de votre embed', + emoji: '🎨', + questionOnly: true + }, + { + label: 'Timestamp', + value: 'timestamp', + description: 'Changer le timestamp de votre embed', + emoji: '⏲', + questionOnly: true + }, + { + label: 'Copier un embed', + value: 'copy', + description: 'Copier un embed', + emoji: 'Β©' + }, + { + label: 'Envoyer l\'embed', + value: 'send', + description: 'Envoyer l\'embed dans un channel', + emoji: 'βœ…', + questionOnly: true + } + ], + copyOptions: [ + { + label: 'Channel', + value: 'copy-channel', + description: 'DΓ©finir le channel oΓΉ copier l\'embed', + emoji: 'Β©' + }, + { + label: 'Message', + value: 'copy-id', + description: 'DΓ©finir l\'id du message qu\'il faut copier', + emoji: 'Β©' + }, + { + label: 'Copier', + value: 'copy-valid', + description: 'Commencer Γ  copier l\'embed', + emoji: 'βœ…' + } + ], loading: `Chargement ... `, title: `Menu crΓ©ation d'embed !`, description: ` Bienvenue sur le menu de crΓ©ation d'embed ! \n Cliquez sur les reactions pour pouvoir personnaliser votre embed !`, - titleField: `・Permet de modifier le titre`, - descriptionField: `・Permet de modifier la description`, - authorField: `・Permet de modifier l'auteur`, - footerField: `・Permet de modifier le footer`, - thumbnailField: `・Permet de modifier la miniature`, - imageField: `・Permet de modifier l'image`, - urlField: `・Permet de modifier l'url`, - colorField: `・Permet de modifier la couleur`, - timestampField: `・Permet de ajouter un timestamp`, - copyField: `Copier un embed et l'editer`, - cancelField: `・Permet d'annuler la crΓ©ation de l'embed`, - sendField: `・Permet d'envoyer l'embed avec le bot`, - titleMsg: `✏ Quel titre voulez-vous pour votre embed ?`, - descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ?`, - authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ?`, - authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (no pour aucun)`, - footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ?`, - footerUrl: `πŸ– Quel est l'icon pour le footer (no pour aucun)`, - thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ?`, - imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ?`, + titleMsg: `✏ Quel titre voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + descriptionMsg: `πŸ“Quelle description voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorMsg: `πŸ—£ Quel auteur voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + authorUrl: `πŸ—£ Quel l'url voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + authorIcon: `πŸ—£ Quel est l'image voulez-vous pour l'auteur de l'embed ? (cancel pour annuler ou enlever)`, + footerMsg: `πŸ– Quel footer voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + footerUrl: `πŸ– Quel est l'icon pour le footer (cancel pour annuler ou enlever)`, + thumbnailMsg: `πŸ’Ά Quelle miniature voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, + imageMsg: `πŸ–Ό Quelle image voulez-vous pour votre embed ? (cancel pour annuler ou enlever)`, urlMsg: `🌐 Quel url voulez-vous pour votre embed ?`, - colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)?`, - copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)?`, + colorMsg: `🎨 Quelle couleur voulez-vous pour votre embed (\`HEX ou des couleurs en anglais\`)? (cancel pour annuler ou enlever)`, + copyMsg: `Β© Quel est le channel oΓΉ l'embed est situer (\`mention / id\`)? (cancel pour annuler ou enlever)`, messageId: `Β© Quel est l'id du message embed (\`id\`)?`, - cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)?`, + cancelMsg: `❌ Voulez-vous annuler la crΓ©ation de l'embed ? (\`oui/non\`)? (cancel pour annuler ou enlever)`, sendMsg: `βœ… Dans quel channel voulez-vous envoyer l'embed \`mention ou id\`?`, errorUrl: `L'url doit commencer par __http/https__`, errorColor: `Veuillez entrer une couleur valide \`hex ou des couleur en anglais\``, - errorChannel: `Je ne trouve pas ce channel !`, + errorChannel: `Vous devez entrer un channel valide !`, errorWrongId: `Veuilez entrer un id valide !`, errorMessage: ch => `Je ne trouve pas le message dans le channel ${ ch } !` }, @@ -237,13 +369,13 @@ module.exports = { voicemove: { success: author => `<:720681705219817534:780540043033837622> \`SUCCÈS\` ${ author }, dΓ©place moi dans le salon ou tu souhaite que je dΓ©place toutes les personnes du salon!` }, soutien: { title: `<:771462923855069204:784471984087236658> __ParamΓ¨tre du soutien__`, - description: (soutienId, soutienMsg, isOnS) => ` - 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n - __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n - 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n - __Message actuel__ : **${ soutienMsg }** \n - 3 ・ Activer ou dΓ©sactiver le soutien \n - __Actif__ : ${ isOnS } + description: (soutienId, soutienMsg, isOnS) => ` + 1 ・ Configurer le rΓ΄le qui sera donnΓ© au membre qui ont le status personnalisΓ© requis. \n + __RΓ΄le actuel__ : **${ soutienId !== 'Non dΓ©finie' ? `<@&${ soutienId }>` : soutienId }** \n + 2 ・ Configurer le message du status personnalisΓ© que les membres devront avoir.\n + __Message actuel__ : **${ soutienMsg }** \n + 3 ・ Activer ou dΓ©sactiver le soutien \n + __Actif__ : ${ isOnS } `, roleQ: ` Mentionnez le rΓ΄le que les soutiens receveront (cancel pour annuler)`, success: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les soutiens vont maintenant recevoir le rΓ΄le: ${ response }.`, @@ -274,20 +406,20 @@ module.exports = { }, setlogs: { embedTitle: `Configuration des logs`, - embedDescription: (raid, mod, voc, msg, react) => ` - \n - Pour dΓ©sactiver une log il suffit de mettre off comme channel ! - - 1 ・ Raid Logs - ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n - 2 ・ Logs modΓ©ration - ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n - 3 ・ Logs Vocal - ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n - 4 ・ Logs Message - ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n - ❌ ・ Fermer le menu\n - βœ… ・ Sauvegarder les logs + embedDescription: (raid, mod, voc, msg, react) => ` + \n + Pour dΓ©sactiver une log il suffit de mettre off comme channel ! + + 1 ・ Raid Logs + ***${ raid === 'Non dΓ©finie' ? raid : `<#${ raid }>` }***\n + 2 ・ Logs modΓ©ration + ***${ mod === 'Non dΓ©finie' ? mod : `<#${ mod }>` }***\n + 3 ・ Logs Vocal + ***${ voc === 'Non dΓ©finie' ? voc : `<#${ voc }>` }***\n + 4 ・ Logs Message + ***${ msg === 'Non dΓ©finie' ? msg : `<#${ msg }>` }***\n + ❌ ・ Fermer le menu\n + βœ… ・ Sauvegarder les logs `, errorNotChannel: `vous devez spΓ©cifier un channel ou une id valide`, raidChQ: `Quel est le salon pour les raids ?`, @@ -319,18 +451,60 @@ module.exports = { titleList: `<:778353230383546419:781153631881265173> Liste des owners` }, invite: { - countDesc: (tag, userInviteCount, inv) => ` - **${ tag }** possΓ¨de actuellement : \n + options: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le channel oΓΉ sera envoyΓ© le message', + emoji: 'πŸ†”' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir le message Γ  envoyer ', + emoji: 'πŸ•³' + }, + { + label: 'Variable', + value: 'help', + description: 'Affiche les variables possible ', + emoji: '❓' + }, + { + label: 'Activer', + value: 'enable', + description: 'Activer ou dΓ©sactiver les messages de bienvenue', + emoji: 'πŸ’˜' + }, + { + label: 'Sauvegarder', + value: 'save', + description: 'Sauvergarder la configuration', + emoji: 'βœ…' + } + ], + help: `{invitedTag} ・ Sert Γ  afficher le tag du membre qui a Γ©tΓ© invitΓ© + {inviterTag} ・ Sert Γ  afficher le tag du membre qui a invitΓ© + {inviterMention} ・ Sert Γ  mentionner le membre qui a invitΓ© + {invitedMention} ・ Sert Γ  mentionner le membre qui a Γ©tΓ© invitΓ© + {creation} ・ Sert Γ  afficher quand le membre qui a Γ©tΓ© invitΓ© a créé son compte + {count} ・ Sert Γ  afficher le nombre d'invitation que l'inviteur possΓ¨de + {fake} ・ Sert Γ  afficher le nombre d'invitation fake que l'inviteur possΓ¨de + {leave} ・ Sert Γ  afficher le nombre d'invitation leave que l'inviteur possΓ¨de + {memberTotal} ・ Sert Γ  afficher le nombre total de membres sur le serveur + `, + countDesc: (tag, userInviteCount, inv) => ` + **${ tag }** possΓ¨de actuellement : \n <:invite_oeople:785494680904138763> **${ userInviteCount }** ${ inv }. `, titleConfig: `<:771462923855069204:784471984087236658> __ParamΓ¨tre des invitations__`, - descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` - 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n - __Channel actuel__ : **<#${ inviteChannel }>**\n - 2 ・ Configurer le message de bienvenue\n - __Message Actuel__ : ${ inviteMsg } \n - 3 ・ Aide sur le message de bienvenue \n - 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n - __Actif__ : ${ isOnS } + descConfig: (inviteChannel, guild, isOnS, inviteMsg) => ` + 1 ・Configurer le channel oΓΉ les messages seront envoyΓ©s\n + __Channel actuel__ : **<#${ inviteChannel }>**\n + 2 ・ Configurer le message de bienvenue\n + __Message Actuel__ : ${ inviteMsg } \n + 3 ・ Aide sur le message de bienvenue \n + 4 ・ Activer ou dΓ©sactiver le message de bienvenue \n + __Actif__ : ${ isOnS } `, chQ: ` Mentionnez le channel oΓΉ les messages de bienvenue seront envoyΓ©s (cancel pour annuler)`, successCh: response => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Les messages de bienvenue vont maintenant Γͺtre envoyΓ© dans le channel ${ response }.`, @@ -341,17 +515,6 @@ module.exports = { errorMsg: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a changer le message de bienvenue en :`, timeout2M: '<:720681441670725645:780539422479351809> `ERREUR` Pas de rΓ©ponse aprΓ¨s 2 minutes opΓ©ration annulΓ©', helpTitle: `<:771462923855069204:784471984087236658> __Aide sur la configuration du message de bienvenue__`, - helpDesc: (invitedHelp, inviterHelp, invitedMention, inviterMention, accountCreate, countHelp, fakeHelp, leaveHelp, totalMemberHelp, space) => ` - ${ invitedHelp } \n - ${ inviterHelp } \n - ${ invitedMention }\n - ${ inviterMention }\n - ${ accountCreate }\n - ${ countHelp } \n - ${ fakeHelp }\n - ${ leaveHelp }\n - ${ totalMemberHelp } \n - ${ space } `, enableQ: ` Voulez-vous activer les messages de bienvenue ? Oui / Non (cancel pour annuler)`, successEnable: `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien activΓ© les messages de bienvenue !`, errorEnable: `<:720681441670725645:780539422479351809> \`ERREUR\` Je ne suis pas arrivΓ© a activΓ© les messages de bienvenue ...`, @@ -378,7 +541,11 @@ module.exports = { successChange: `Vous avez bien modifiΓ© votre mot de pass !` }, authorinfo: { description: `__**OneforAll**__\n\n*OneforAll est un bot appartenant Γ * \`TAKEFY#9831\`\n\n**DΓ©veloppeurs :**\n[TAKEFY#9831](https://discord.gg/h69YZHB7Nh) -> Bot & Host\n[baby#1337](https://discord.gg/h69YZHB7Nh) -> Ideas & Design\n[qzzzz#0101](https://discord.gg/h69YZHB7Nh) -> Communication\n` }, - setlang: { success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` }, + setlang: { + currentLang: lang => `En ce moment la langue du bot est **${ lang }**`, + errorInArgs: availableLang => `Vous devez choisir entre ces ${ availableLang.length } langues **(${ availableLang.join(', ').replace(/.js/g, '') })**`, + success: lang => `La langue du bot est maintenat dΓ©finie pour ${ lang }` + }, addemoji: { missingUrl: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un emoji`, missingName: `<:720681441670725645:780539422479351809> \`ERREUR\` Vous devez fournir un nom pour l'emoji`, @@ -393,15 +560,14 @@ module.exports = { }, backup: { configEmbedT: `<:server:783422366230380565> Configuration de la backups`, - configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` - **1** ・ Ignorer les channels (**${ ignoreCh }**) - **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) - **3** ・ Ignorer les emojis (**${ ignoreEmo }**) - **4** ・ Ignorer les bans (**${ ignoreBans }**)\n - **❌** ・ Fermer le menu - **βœ…** ・ CrΓ©er la backup - - + configEmbedDesc: (ignoreCh, ignoreRl, ignoreEmo, ignoreBans) => ` + **1** ・ Ignorer les channels (**${ ignoreCh }**) + **2** ・ Ignorer les rΓ΄les (**${ ignoreRl }**) + **3** ・ Ignorer les emojis (**${ ignoreEmo }**) + **4** ・ Ignorer les bans (**${ ignoreBans }**)\n + **❌** ・ Fermer le menu + **βœ…** ・ CrΓ©er la backup + `, cancel: `<:720681705219817534:780540043033837622> \`SUCCÈS\` CrΓ©ation de backup annulΓ©`, successDelete: backupId => `<:720681705219817534:780540043033837622> \`SUCCÈS\` J'ai bien supprimΓ© la backup **${ backupId }** !`, @@ -446,29 +612,29 @@ module.exports = { allbot: { title: bots => `Nombre de bots : ${ bots }` }, counter: { embedTitle: `ParamΓ¨tre des compteurs`, - embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` - \n - Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! - - \`πŸ‘₯\`・ Compteur de membres - ***${ member.name }***\n - \`πŸ€–\` ・ Compteur de robots - ***${ bot.name }***\n - \`πŸ”Š\`・ Compteur de membre en vocal - ***${ voice.name }***\n - \`🟒\` ・ Compteur de membre en ligne - ***${ online.name }***\n - \`β­•\` ・ Compteur de membre en hors-ligne - ***${ offline.name }***\n - \`πŸ“–\` ・ Compteur de salons - ***${ channel.name }***\n - \`✨\` ・ Compteur de roles - ***${ role.name }***\n - \`πŸ’ \` ・ Compteur de booster - ***${ booster.name }***\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les compteurs + embedDescription: ({member, bot, voice, online, offline, channel, role, booster}) => ` + \n + Pour dΓ©sactiver un compteur il suffit de mettre off comme channel ! + + \`πŸ‘₯\`・ Compteur de membres + ***${ member.name }***\n + \`πŸ€–\` ・ Compteur de robots + ***${ bot.name }***\n + \`πŸ”Š\`・ Compteur de membre en vocal + ***${ voice.name }***\n + \`🟒\` ・ Compteur de membre en ligne + ***${ online.name }***\n + \`β­•\` ・ Compteur de membre en hors-ligne + ***${ offline.name }***\n + \`πŸ“–\` ・ Compteur de salons + ***${ channel.name }***\n + \`✨\` ・ Compteur de roles + ***${ role.name }***\n + \`πŸ’ \` ・ Compteur de booster + ***${ booster.name }***\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les compteurs `, notVoice: `<:720681441670725645:780539422479351809> \`ERREUR\` Le channel souhaitΓ© n'est pas un channel vocal`, nameQ: `Quel doit Γͺtre le nom du **salon** \`ex : πŸ’₯・ Membres:\`?`, @@ -500,27 +666,66 @@ module.exports = { successBoostCh: ch => `<:720681705219817534:780540043033837622> \`SUCCÈS\` Vous avez dΓ©fini le salon pour le compteur de booster a ${ ch }` }, reactionRole: { + selectMenu: [ + { + label: 'Channel', + value: 'channel', + description: 'DΓ©finir le salon oΓΉ se situe le reaction role', + emoji: 'πŸ“–' + }, + { + label: 'Message', + value: 'message', + description: 'DΓ©finir l\'id du message ou mettre le reaction role', + emoji: 'πŸ†”' + }, + { + label: 'Ajoute un role', + value: 'add-role', + description: 'Ajouter un role', + emoji: 'πŸ’ ' + }, + { + label: 'Supprimer un role', + value: 'del-role', + description: 'Supprimer un role', + emoji: '🚫' + }, + { + label: 'Supprimer', + value: 'delete', + description: 'Supprimer un reaction role existant', + emoji: 'πŸ“›' + }, + { + label: 'Sauvergarde', + value: 'save', + description: 'Sauvegarder le reaction role', + emoji: 'βœ…' + } + ], embedTitle: `Menu de crΓ©ation du reaction rΓ΄le`, - embedDescription: (channel, id, emoji, role) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! - - \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le - ***${ channel }***\n - \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le - ***${ id }***\n - \`πŸ’ \` ・ Ajouter un rΓ΄le\n - **${ emoji.join(`\n`) }**\n - \`🚫\` ・ Supprimer un rΓ΄le\n - \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le reaction rΓ΄le + embedDescription: (channel, id, emoji, role) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le reaction rΓ΄le ! + + \`πŸ“–\` ・ Choisir le salon ou doit Γͺtre le reaction rΓ΄le + ***${ channel }***\n + \`πŸ†”\` ・ Definir l'id du message associΓ© au reaction rΓ΄le + ***${ id }***\n + \`πŸ’ \` ・ Ajouter un rΓ΄le\n + **${ emoji.join(`\n`) }**\n + \`🚫\` ・ Supprimer un rΓ΄le\n + \`πŸ“›\` ・ Supprimer un reaction rΓ΄le existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le reaction rΓ΄le `, notText: `Le salon doit Γͺtre uniquement du type **text**`, chQ: `πŸ“– Quel est le salon oΓΉ vous voudriez avoir votre reaction rΓ΄le ? (\`mention/id\`) (cancel pour annuler)`, successCh: ch => `Vous avez dΓ©finie le salon pour **${ ch }**`, + invalidChannel: `Le channel est invalide`, msgIdQ: `πŸ†” Quel est l'id du message pour votre reaction rΓ΄le ? (\`id\`) (cancel pour annuler)`, notId: `Veuillez entrer une id valide !`, noChannel: `Vous n'avez pas dΓ©fini de channel je n'ai donc pas pu rΓ©cuperer le message`, @@ -543,25 +748,25 @@ module.exports = { noEmoji: `Vous n'avez pas dΓ©finie d'emoji et de rΓ΄le.`, alreadyReact: `Un reaction rΓ΄le existe dΓ©jΓ  avec ce message`, success: `Le reaction rΓ΄le a Γ©tΓ© parfaitement sauvagardΓ© et crΓ©e !`, + notChannelReactrole: `Il n'y a pas de reactrole dans ce channel`, tryToPermsRole: `Vous ne pouvez pas ajouter un role ayant des permissions sensible` }, tempvoc: { embedTitle: `Menu de crΓ©ation d'un vocal temporaire`, - embedDescription: (tempname, enable) => ` - \n - Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! - - \`πŸ•³\` ・ Auto configurer le vocal temporaire - - \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur - ***${ tempname }***\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire - **${ enable }**\n - \`πŸ’₯\` ・ Supprimer un vocal temporaire existant - - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder le vocal temporaire + embedDescription: (tempname, enable) => ` + \n + Cliquez sur les reactions pour pouvoir configurer le vocal temporaire ! + + \`πŸ•³\` ・ Auto configurer le vocal temporaire + \`πŸ’¬\` ・ Changer le nom du salon temporaire de l'utilisateur + ***${ tempname }***\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le vocal temporaire + **${ enable }**\n + \`πŸ’₯\` ・ Supprimer un vocal temporaire existant + + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder le vocal temporaire `, loadingCreation: `CrΓ©ation en cours...`, autoCat: `Salon temporaire`, @@ -601,19 +806,18 @@ module.exports = { kickDm: (amount, serverName) => `Vous avez Γ©tΓ© kick de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, muteDm: (amount, serverName) => `Vous avez Γ©tΓ© mute de **${ serverName }** car vous avez atteind la limite de warn avec \`(${ amount })\` warn(s) `, settingsTitle: `Configuration des warns`, - description: (ban, kick, mute) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - Pour mettre aucune sanction il suffit de mettre __0__ - - \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban - ***${ ban }***\n - \`πŸ’’\` ・ Modifier le nombre de warn avant de kick - ***${ kick }***\n - \`😢\` ・ ModifiΓ© le nombre de warn avant de mute - **${ mute }**\n - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (ban, kick, mute) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + Pour mettre aucune sanction il suffit de mettre __0__ + \`πŸ’₯\` ・ Modifier le nombre de warn avant de ban + ***${ ban }***\n + \`πŸ’’\` ・ Modifier le nombre de warn avant de kick + ***${ kick }***\n + \`😢\` ・ ModifiΓ© le nombre de warn avant de mute + **${ mute }**\n + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, banQ: `Quel doit Γͺtre le nouveau nombre de warn avant de ban ? **Cancel pour annuler**`, onlyNumber: `Vous devez entrer uniquement des nombres`, @@ -638,21 +842,19 @@ module.exports = { }, coinSettings: { title: `Configuration du systΓ¨me de coins`, - description: (streamBoost, muteDiviseur, logs, enable) => ` \n - Cliquez sur les reactions pour pouvoir configurer les warns ! - - - \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam - ***${ streamBoost }***\n - \`😢\` ・ Modifier le diviseur si un membre est mute - ***${ muteDiviseur }***\n - \`πŸ’Œ\` ・ ModifiΓ© le salon des logs - **${ logs }**\n - \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder la configuration + description: (streamBoost, muteDiviseur, logs, enable) => ` \n + Cliquez sur les reactions pour pouvoir configurer les warns ! + + \`πŸŽ₯\` ・ Modifier le multiplicateur de coins quand un membre est en stream/cam + ***${ streamBoost }***\n + \`😢\` ・ Modifier le diviseur si un membre est mute + ***${ muteDiviseur }***\n + \`πŸ’Œ\` ・ ModifiΓ© le salon des logs + **${ logs }**\n + \`πŸŒ€\` ・Activer ou dΓ©sactiver le systΓ¨me de coins + **${ enable }** + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder la configuration `, onlyNumber: `Vous devez uniquement entrer des nombres`, streamBoostQ: `Quel doit Γͺtre le nouveau multiplicateur pour les membres en stream ? (cancel pour annuler)`, @@ -971,26 +1173,26 @@ module.exports = { inccorectWinner: `La nombre de gagnants n'est pas valide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, winnerMustRange: `Le nombre de gagnants doit Γͺtre supΓ©rieur Γ  0\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, noPrize: `Le gain est invalide\nExemple usage: \`!gcreate 10m 1w Nitro(9.99$)\``, - embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` - **INFORMATIONS:**\n\n - Cliquer πŸ•™ pour modifier la durΓ©e - Cliquer 🏷️ pour modifier le salon - Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants - Cliquer 🎁 pour modifier le gain - Cliquer πŸ”Š pour modifier la prΓ©sence vocal - Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur - Cliquer πŸ’« pour modifier la reaction du giveaway - Cliquer βœ… pour lancer le giveaway - - - **SETUP:** - - πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } - 🏷️ Salon **-** ${ channel } - πŸ•΅οΈ Nombre de gagnant **-** ${ winners } - πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } - πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } - πŸ’« Reaction **-** ${ reaction } + embed: (time = 'Non dΓ©finie', channel = 'Non dΓ©finie', winners = 0, voice = false, boost = false, reaction = 'πŸŽ‰', prize = 'Non dΓ©finie', color) => new Discord.MessageEmbed().setDescription(` + **INFORMATIONS:**\n\n + Cliquer πŸ•™ pour modifier la durΓ©e + Cliquer 🏷️ pour modifier le salon + Cliquer πŸ•΅οΈ pour modifier le nombre de gagnants + Cliquer 🎁 pour modifier le gain + Cliquer πŸ”Š pour modifier la prΓ©sence vocal + Cliquer πŸ” pour modifier l'obligation d'avoir booster le serveur + Cliquer πŸ’« pour modifier la reaction du giveaway + Cliquer βœ… pour lancer le giveaway + + + **SETUP:** + + πŸ•™ DurΓ©e **-** ${ time !== 'Non dΓ©finie' ? prettyMilliseconds(time) : time } + 🏷️ Salon **-** ${ channel } + πŸ•΅οΈ Nombre de gagnant **-** ${ winners } + πŸ”Š PrΓ©sence vocal obligatoire **-** ${ !voice ? 'Non' : voice } + πŸ” Boost serveur obligatoire **-** ${ !boost ? 'Non' : boost } + πŸ’« Reaction **-** ${ reaction } 🎁 Gain **-** ${ prize }`).setColor(color), question: { time: `Quel est la durΓ©e du giveaway ?`, @@ -1052,27 +1254,27 @@ module.exports = { successDelete: channel => `Les messages dans ${ channel } ne recevront plus de reactions` }, xpSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer l'xp ! - Pour le gain d'xp de options un nombre fixe exemple : **1** - ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** - - \`πŸ’¦\` ・ Modifier le gain d'xp par message - **${ config.xpPerMsg }**\n - \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal - **${ config.xpPerSVoc }**\n - \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) - **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) - **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** - \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) - **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n - \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer l'xp ! + Pour le gain d'xp de options un nombre fixe exemple : **1** + ou un nombre alΓ©atoire entre un minimum et maximum : **1-20** + + \`πŸ’¦\` ・ Modifier le gain d'xp par message + **${ config.xpPerMsg }**\n + \`πŸ’\` ・ Modifier le gain d'xp par seconde de prΓ©sence vocal + **${ config.xpPerSVoc }**\n + \`πŸ‰\` ・ Channels oΓΉ le gain d'xp est autorisΓ© (all pour tous) + **${ !config.allowChannels.length ? 'Aucun' : config.allowChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’€\` ・ Channels oΓΉ le gain d'xp est dΓ©sactivΓ© (all pour tous) + **${ !config.forbidChannels.length ? 'Aucun' : config.forbidChannels.map(ch => `<#${ ch }>`).join(', ') }\n** + \`πŸ’Ή\` ・ Channels oΓΉ le gain d'xp est multiplΓ© (all pour tous, 0 pour enelvΓ© le channel) + **${ config.multiplerChannels.length > 0 ? config.multiplerChannels.map(multi => `<#${ multi.channel }> - ${ multi.boost }`).join(', ') : 'Aucun' }**\n + \`πŸ’¨\` ・ ActivΓ© / dΓ©sactiver le gain d'xp\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { xpPerMsg: `Combien voulez-vous faire gagner d'xp par message ? (cancel pour annuler)`, @@ -1090,21 +1292,21 @@ module.exports = { save: `Configuration save` }, levelSettings: { - embed: (config, enable) => new Discord.MessageEmbed().setDescription(` - \n - Cliquez sur les reactions pour pouvoir configurer les niveaux ! - - \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) - **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n - \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind - **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n - \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind - - \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n - **${ enable }** - - \`❌\` ・ Fermer le menu\n - \`βœ…\` ・ Sauvegarder les paramΓ¨tre + embed: (config, enable) => new Discord.MessageEmbed().setDescription(` + \n + Cliquez sur les reactions pour pouvoir configurer les niveaux ! + + \`πŸ’Œ\` ・ Modifier le salon et le message qui sera envoyΓ© quand un membre augmente de niveau (off to disable) + **${ config.lvlMessage.channel === 'Non dΓ©finie' ? `Non dΓ©finie` : `<#${ config.lvlMessage.channel }>` } - **${ config.lvlMessage.message }\n + \`βž•\` ・ Ajouter un role qui sera ajoutΓ© quand un certain niveau sera atteind + **${ !config.roleLevel.length ? `Aucun` : config.roleLevel.map(roleLevel => `<@&${ roleLevel.role }> - ${ roleLevel.level }`).join(', ') }**\n + \`βž–\` ・ Enlever un role qui sera ajoutΓ© quand un certain niveau sera atteind + + \`πŸ’\` ・ ActivΓ© / dΓ©sactiver le fait de cumuluer les roles obtenu grace au niveau ou uniquement garder le plus haut\n + **${ enable }** + + \`❌\` ・ Fermer le menu\n + \`βœ…\` ・ Sauvegarder les paramΓ¨tre `).setFooter(`OneForAll - Xp`).setTimestamp().setTitle(`Configuration xp`), question: { channelQuestion: `Quel est le channel ou sera envoyΓ© les augmentations de niveau ? (cancel pour annuler)`, @@ -1125,18 +1327,6 @@ module.exports = { success: member => `L'xp de ${ member } a Γ©tΓ© reset`, errorNothingToReset: `Il n'y a personne a reset` }, - inviteRole: { - noRole: `Vous devez spΓ©cifier un role`, - noInvite: `Vous devez spΓ©cifier un nombre d'invite`, - notNumber: `Vous devez spΓ©cifier un nombre d'invite valide`, - listEmbed: inviteRole => new Discord.MessageEmbed().setDescription(!inviteRole.length ? `Aucun invite role` : inviteRole.map((inv, i) => `${ i + 1 } - <@&${ inv.role }> - ${ inv.invite } invite(s)`).join('\n')).setTimestamp().setTitle(`Liste des invites role (${ inviteRole.length })`), - success: (role, invite) => `Le role **${ role }** se maintenant ajoutΓ© a partir de *${ invite }* invite(s)`, - noOnOff: `Vous devez spΓ©cifier on ou off\n \`Exemple: !inviterole cumul on\``, - successCumul: isOn => `Le cumules des roles est maintenant **${ isOn }**.`, - doestNotExist: `L'invite role n'existe pas`, - alreadyExist: `L'invite role existe dΓ©jΓ `, - successRm: role => `Le ${ role } a Γ©tΓ© supprimΓ© des invite role` - }, blacklistRole: { noRole: `Vous devez spΓ©cifier un role`, alreadyBl: role => `Le role **${ role }** est dΓ©jΓ  dans la blacklist des rΓ΄les`, diff --git a/node_modules/@discordjs/collection/LICENSE b/node_modules/@discordjs/collection/LICENSE index 9997d13f..414073d2 100644 --- a/node_modules/@discordjs/collection/LICENSE +++ b/node_modules/@discordjs/collection/LICENSE @@ -175,7 +175,7 @@ END OF TERMS AND CONDITIONS - Copyright 2015 - 2020 Amish Shah + Copyright 2015 - 2021 Amish Shah Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/node_modules/@discordjs/collection/dist/index.d.ts b/node_modules/@discordjs/collection/dist/index.d.ts index a3323962..3bcd3f89 100644 --- a/node_modules/@discordjs/collection/dist/index.d.ts +++ b/node_modules/@discordjs/collection/dist/index.d.ts @@ -11,12 +11,9 @@ export interface CollectionConstructor { * @extends {Map} * @property {number} size - The amount of elements in this collection. */ -declare class Collection extends Map { - private _array; - private _keyArray; +export declare class Collection extends Map { static readonly default: typeof Collection; - ['constructor']: typeof Collection; - constructor(entries?: ReadonlyArray | null); + ['constructor']: CollectionConstructor; /** * Identical to [Map.get()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get). * Gets an element with the specified key, and returns its value, or `undefined` if the element does not exist. @@ -53,21 +50,17 @@ declare class Collection extends Map { */ clear(): void; /** - * Creates an ordered array of the values of this collection, and caches it internally. The array will only be - * reconstructed if an item is added to or removed from the collection, or if you change the length of the array - * itself. If you don't want this caching behavior, use `[...collection.values()]` or - * `Array.from(collection.values())` instead. - * @returns {Array} + * Checks if all of the elements exist in the collection. + * @param {...*} keys - The keys of the elements to check for + * @returns {boolean} `true` if all of the elements exist, `false` if at least one does not exist. */ - array(): V[]; + hasAll(...keys: K[]): boolean; /** - * Creates an ordered array of the keys of this collection, and caches it internally. The array will only be - * reconstructed if an item is added to or removed from the collection, or if you change the length of the array - * itself. If you don't want this caching behavior, use `[...collection.keys()]` or - * `Array.from(collection.keys())` instead. - * @returns {Array} + * Checks if any of the elements exist in the collection. + * @param {...*} keys - The keys of the elements to check for + * @returns {boolean} `true` if any of the elements exist, `false` if none exist. */ - keyArray(): K[]; + hasAny(...keys: K[]): boolean; /** * Obtains the first value(s) in this collection. * @param {number} [amount] Amount of values to obtain from the beginning @@ -85,8 +78,7 @@ declare class Collection extends Map { firstKey(): K | undefined; firstKey(amount: number): K[]; /** - * Obtains the last value(s) in this collection. This relies on {@link Collection#array}, and thus the caching - * mechanism applies here as well. + * Obtains the last value(s) in this collection. * @param {number} [amount] Amount of values to obtain from the end * @returns {*|Array<*>} A single value if no amount is provided or an array of values, starting from the start if * amount is negative @@ -94,8 +86,7 @@ declare class Collection extends Map { last(): V | undefined; last(amount: number): V[]; /** - * Obtains the last key(s) in this collection. This relies on {@link Collection#keyArray}, and thus the caching - * mechanism applies here as well. + * Obtains the last key(s) in this collection. * @param {number} [amount] Amount of keys to obtain from the end * @returns {*|Array<*>} A single key if no amount is provided or an array of keys, starting from the start if * amount is negative @@ -103,16 +94,14 @@ declare class Collection extends Map { lastKey(): K | undefined; lastKey(amount: number): K[]; /** - * Obtains unique random value(s) from this collection. This relies on {@link Collection#array}, and thus the caching - * mechanism applies here as well. + * Obtains unique random value(s) from this collection. * @param {number} [amount] Amount of values to obtain randomly * @returns {*|Array<*>} A single value if no amount is provided or an array of values */ random(): V; random(amount: number): V[]; /** - * Obtains unique random key(s) from this collection. This relies on {@link Collection#keyArray}, and thus the caching - * mechanism applies here as well. + * Obtains unique random key(s) from this collection. * @param {number} [amount] Amount of keys to obtain randomly * @returns {*|Array<*>} A single key if no amount is provided or an array */ @@ -129,8 +118,10 @@ declare class Collection extends Map { * @returns {*} * @example collection.find(user => user.username === 'Bob'); */ + find(fn: (value: V, key: K, collection: this) => value is V2): V2 | undefined; find(fn: (value: V, key: K, collection: this) => boolean): V | undefined; - find(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): V | undefined; + find(fn: (this: This, value: V, key: K, collection: this) => value is V2, thisArg: This): V2 | undefined; + find(fn: (this: This, value: V, key: K, collection: this) => boolean, thisArg: This): V | undefined; /** * Searches for the key of a single item where the given function returns a truthy value. This behaves like * [Array.findIndex()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex), @@ -140,8 +131,10 @@ declare class Collection extends Map { * @returns {*} * @example collection.findKey(user => user.username === 'Bob'); */ + findKey(fn: (value: V, key: K, collection: this) => key is K2): K2 | undefined; findKey(fn: (value: V, key: K, collection: this) => boolean): K | undefined; - findKey(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): K | undefined; + findKey(fn: (this: This, value: V, key: K, collection: this) => key is K2, thisArg: This): K2 | undefined; + findKey(fn: (this: This, value: V, key: K, collection: this) => boolean, thisArg: This): K | undefined; /** * Removes items that satisfy the provided filter function. * @param {Function} fn Function used to test (should return a boolean) @@ -159,8 +152,12 @@ declare class Collection extends Map { * @returns {Collection} * @example collection.filter(user => user.username === 'Bob'); */ - filter(fn: (value: V, key: K, collection: this) => boolean): this; - filter(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): this; + filter(fn: (value: V, key: K, collection: this) => key is K2): Collection; + filter(fn: (value: V, key: K, collection: this) => value is V2): Collection; + filter(fn: (value: V, key: K, collection: this) => boolean): Collection; + filter(fn: (this: This, value: V, key: K, collection: this) => key is K2, thisArg: This): Collection; + filter(fn: (this: This, value: V, key: K, collection: this) => value is V2, thisArg: This): Collection; + filter(fn: (this: This, value: V, key: K, collection: this) => boolean, thisArg: This): Collection; /** * Partitions the collection into two collections where the first collection * contains the items that passed and the second contains the items that failed. @@ -169,8 +166,12 @@ declare class Collection extends Map { * @returns {Collection[]} * @example const [big, small] = collection.partition(guild => guild.memberCount > 250); */ - partition(fn: (value: V, key: K, collection: this) => boolean): [this, this]; - partition(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): [this, this]; + partition(fn: (value: V, key: K, collection: this) => key is K2): [Collection, Collection, V>]; + partition(fn: (value: V, key: K, collection: this) => value is V2): [Collection, Collection>]; + partition(fn: (value: V, key: K, collection: this) => boolean): [Collection, Collection]; + partition(fn: (this: This, value: V, key: K, collection: this) => key is K2, thisArg: This): [Collection, Collection, V>]; + partition(fn: (this: This, value: V, key: K, collection: this) => value is V2, thisArg: This): [Collection, Collection>]; + partition(fn: (this: This, value: V, key: K, collection: this) => boolean, thisArg: This): [Collection, Collection]; /** * Maps each item into a Collection, then joins the results into a single Collection. Identical in behavior to * [Array.flatMap()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap). @@ -219,8 +220,12 @@ declare class Collection extends Map { * @returns {boolean} * @example collection.every(user => !user.bot); */ + every(fn: (value: V, key: K, collection: this) => key is K2): this is Collection; + every(fn: (value: V, key: K, collection: this) => value is V2): this is Collection; every(fn: (value: V, key: K, collection: this) => boolean): boolean; - every(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): boolean; + every(fn: (this: This, value: V, key: K, collection: this) => key is K2, thisArg: This): this is Collection; + every(fn: (this: This, value: V, key: K, collection: this) => value is V2, thisArg: This): this is Collection; + every(fn: (this: This, value: V, key: K, collection: this) => boolean, thisArg: This): boolean; /** * Applies a function to produce a single value. Identical in behavior to * [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce). @@ -264,14 +269,14 @@ declare class Collection extends Map { * @returns {Collection} * @example const newColl = someColl.clone(); */ - clone(): this; + clone(): Collection; /** * Combines this collection with others into a new collection. None of the source collections are modified. * @param {...Collection} collections Collections to merge * @returns {Collection} * @example const newColl = someColl.concat(someOtherColl, anotherColl, ohBoyAColl); */ - concat(...collections: Collection[]): this; + concat(...collections: Collection[]): Collection; /** * Checks if this collection shares identical items with another. * This is different to checking for equality using equal-signs, because @@ -290,7 +295,7 @@ declare class Collection extends Map { * @returns {Collection} * @example collection.sort((userA, userB) => userA.createdTimestamp - userB.createdTimestamp); */ - sort(compareFunction?: (firstValue: V, secondValue: V, firstKey: K, secondKey: K) => number): this; + sort(compareFunction?: Comparator): this; /** * The intersect method returns a new structure containing items where the keys are present in both original structures. * @param {Collection} other The other Collection to filter against @@ -313,7 +318,9 @@ declare class Collection extends Map { * @returns {Collection} * @example collection.sorted((userA, userB) => userA.createdTimestamp - userB.createdTimestamp); */ - sorted(compareFunction?: (firstValue: V, secondValue: V, firstKey: K, secondKey: K) => number): this; + sorted(compareFunction?: Comparator): Collection; + toJSON(): V[]; + private static defaultSort; } -export { Collection }; +export declare type Comparator = (firstValue: V, secondValue: V, firstKey: K, secondKey: K) => number; export default Collection; diff --git a/node_modules/@discordjs/collection/dist/index.js b/node_modules/@discordjs/collection/dist/index.js index 8c47cfda..e730c30e 100644 --- a/node_modules/@discordjs/collection/dist/index.js +++ b/node_modules/@discordjs/collection/dist/index.js @@ -8,23 +8,6 @@ exports.Collection = void 0; * @property {number} size - The amount of elements in this collection. */ class Collection extends Map { - constructor(entries) { - super(entries); - /** - * Cached array for the `array()` method - will be reset to `null` whenever `set()` or `delete()` are called - * @name Collection#_array - * @type {?Array} - * @private - */ - Object.defineProperty(this, '_array', { value: null, writable: true, configurable: true }); - /** - * Cached array for the `keyArray()` method - will be reset to `null` whenever `set()` or `delete()` are called - * @name Collection#_keyArray - * @type {?Array} - * @private - */ - Object.defineProperty(this, '_keyArray', { value: null, writable: true, configurable: true }); - } /** * Identical to [Map.get()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get). * Gets an element with the specified key, and returns its value, or `undefined` if the element does not exist. @@ -42,8 +25,6 @@ class Collection extends Map { * @returns {Collection} */ set(key, value) { - this._array = null; - this._keyArray = null; return super.set(key, value); } /** @@ -62,8 +43,6 @@ class Collection extends Map { * @returns {boolean} `true` if the element was removed, `false` if the element does not exist. */ delete(key) { - this._array = null; - this._keyArray = null; return super.delete(key); } /** @@ -75,28 +54,20 @@ class Collection extends Map { return super.clear(); } /** - * Creates an ordered array of the values of this collection, and caches it internally. The array will only be - * reconstructed if an item is added to or removed from the collection, or if you change the length of the array - * itself. If you don't want this caching behavior, use `[...collection.values()]` or - * `Array.from(collection.values())` instead. - * @returns {Array} + * Checks if all of the elements exist in the collection. + * @param {...*} keys - The keys of the elements to check for + * @returns {boolean} `true` if all of the elements exist, `false` if at least one does not exist. */ - array() { - if (!this._array || this._array.length !== this.size) - this._array = [...this.values()]; - return this._array; + hasAll(...keys) { + return keys.every((k) => super.has(k)); } /** - * Creates an ordered array of the keys of this collection, and caches it internally. The array will only be - * reconstructed if an item is added to or removed from the collection, or if you change the length of the array - * itself. If you don't want this caching behavior, use `[...collection.keys()]` or - * `Array.from(collection.keys())` instead. - * @returns {Array} + * Checks if any of the elements exist in the collection. + * @param {...*} keys - The keys of the elements to check for + * @returns {boolean} `true` if any of the elements exist, `false` if none exist. */ - keyArray() { - if (!this._keyArray || this._keyArray.length !== this.size) - this._keyArray = [...this.keys()]; - return this._keyArray; + hasAny(...keys) { + return keys.some((k) => super.has(k)); } first(amount) { if (typeof amount === 'undefined') @@ -117,7 +88,7 @@ class Collection extends Map { return Array.from({ length: amount }, () => iter.next().value); } last(amount) { - const arr = this.array(); + const arr = [...this.values()]; if (typeof amount === 'undefined') return arr[arr.length - 1]; if (amount < 0) @@ -127,7 +98,7 @@ class Collection extends Map { return arr.slice(-amount); } lastKey(amount) { - const arr = this.keyArray(); + const arr = [...this.keys()]; if (typeof amount === 'undefined') return arr[arr.length - 1]; if (amount < 0) @@ -137,22 +108,20 @@ class Collection extends Map { return arr.slice(-amount); } random(amount) { - let arr = this.array(); + const arr = [...this.values()]; if (typeof amount === 'undefined') return arr[Math.floor(Math.random() * arr.length)]; - if (arr.length === 0 || !amount) + if (!arr.length || !amount) return []; - arr = arr.slice(); - return Array.from({ length: amount }, () => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]); + return Array.from({ length: Math.min(amount, arr.length) }, () => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]); } randomKey(amount) { - let arr = this.keyArray(); + const arr = [...this.keys()]; if (typeof amount === 'undefined') return arr[Math.floor(Math.random() * arr.length)]; - if (arr.length === 0 || !amount) + if (!arr.length || !amount) return []; - arr = arr.slice(); - return Array.from({ length: amount }, () => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]); + return Array.from({ length: Math.min(amount, arr.length) }, () => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]); } find(fn, thisArg) { if (typeof thisArg !== 'undefined') @@ -195,8 +164,10 @@ class Collection extends Map { partition(fn, thisArg) { if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg); - // TODO: consider removing the from the constructors after TS 3.7.0 is released, as it infers it - const results = [new this.constructor[Symbol.species](), new this.constructor[Symbol.species]()]; + const results = [ + new this.constructor[Symbol.species](), + new this.constructor[Symbol.species](), + ]; for (const [key, val] of this) { if (fn(val, key, this)) { results[0].set(key, val); @@ -318,8 +289,9 @@ class Collection extends Map { * @returns {boolean} Whether the collections have identical contents */ equals(collection) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!collection) - return false; + return false; // runtime check if (this === collection) return true; if (this.size !== collection.size) @@ -341,13 +313,11 @@ class Collection extends Map { * @returns {Collection} * @example collection.sort((userA, userB) => userA.createdTimestamp - userB.createdTimestamp); */ - sort(compareFunction = (x, y) => Number(x > y) || Number(x === y) - 1) { + sort(compareFunction = Collection.defaultSort) { const entries = [...this.entries()]; entries.sort((a, b) => compareFunction(a[1], b[1], a[0], b[0])); // Perform clean-up super.clear(); - this._array = null; - this._keyArray = null; // Set the new entries for (const [k, v] of entries) { super.set(k, v); @@ -360,7 +330,12 @@ class Collection extends Map { * @returns {Collection} */ intersect(other) { - return other.filter((_, k) => this.has(k)); + const coll = new this.constructor[Symbol.species](); + for (const [k, v] of other) { + if (this.has(k)) + coll.set(k, v); + } + return coll; } /** * The difference method returns a new structure containing items where the key is present in one of the original structures but not the other. @@ -368,7 +343,16 @@ class Collection extends Map { * @returns {Collection} */ difference(other) { - return other.filter((_, k) => !this.has(k)).concat(this.filter((_, k) => !other.has(k))); + const coll = new this.constructor[Symbol.species](); + for (const [k, v] of other) { + if (!this.has(k)) + coll.set(k, v); + } + for (const [k, v] of this) { + if (!other.has(k)) + coll.set(k, v); + } + return coll; } /** * The sorted method sorts the items of a collection and returns it. @@ -380,13 +364,18 @@ class Collection extends Map { * @returns {Collection} * @example collection.sorted((userA, userB) => userA.createdTimestamp - userB.createdTimestamp); */ - sorted(compareFunction = (x, y) => Number(x > y) || Number(x === y) - 1) { - return new this.constructor[Symbol.species]([...this.entries()]) - .sort((av, bv, ak, bk) => compareFunction(av, bv, ak, bk)); + sorted(compareFunction = Collection.defaultSort) { + return new this.constructor[Symbol.species](this).sort((av, bv, ak, bk) => compareFunction(av, bv, ak, bk)); + } + toJSON() { + // toJSON is called recursively by JSON.stringify. + return [...this.values()]; + } + static defaultSort(firstValue, secondValue) { + return Number(firstValue > secondValue) || Number(firstValue === secondValue) - 1; } } exports.Collection = Collection; Collection.default = Collection; -module.exports = Collection; exports.default = Collection; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiLyIsInNvdXJjZXMiOlsiaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBUUE7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQWlCLFNBQVEsR0FBUztJQU12QyxZQUFtQixPQUErQztRQUNqRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFZjs7Ozs7V0FLRztRQUNILE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUUzRjs7Ozs7V0FLRztRQUNILE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMvRixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxHQUFHLENBQUMsR0FBTTtRQUNoQixPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLEdBQUcsQ0FBQyxHQUFNLEVBQUUsS0FBUTtRQUMxQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztRQUNuQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLEdBQUcsQ0FBQyxHQUFNO1FBQ2hCLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN2QixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxNQUFNLENBQUMsR0FBTTtRQUNuQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztRQUNuQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxLQUFLO1FBQ1gsT0FBTyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLEtBQUs7UUFDWCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxJQUFJLENBQUMsSUFBSTtZQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZGLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNwQixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksUUFBUTtRQUNkLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxJQUFJO1lBQUUsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDOUYsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ3ZCLENBQUM7SUFVTSxLQUFLLENBQUMsTUFBZTtRQUMzQixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVc7WUFBRSxPQUFPLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDckUsSUFBSSxNQUFNLEdBQUcsQ0FBQztZQUFFLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUMzQixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBTSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFVTSxRQUFRLENBQUMsTUFBZTtRQUM5QixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVc7WUFBRSxPQUFPLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDbkUsSUFBSSxNQUFNLEdBQUcsQ0FBQztZQUFFLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqRCxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN6QixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBTSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFXTSxJQUFJLENBQUMsTUFBZTtRQUMxQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDekIsSUFBSSxPQUFPLE1BQU0sS0FBSyxXQUFXO1lBQUUsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM5RCxJQUFJLE1BQU0sR0FBRyxDQUFDO1lBQUUsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQy9DLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDdkIsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQVdNLE9BQU8sQ0FBQyxNQUFlO1FBQzdCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM1QixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVc7WUFBRSxPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzlELElBQUksTUFBTSxHQUFHLENBQUM7WUFBRSxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUN2QixPQUFPLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBVU0sTUFBTSxDQUFDLE1BQWU7UUFDNUIsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3ZCLElBQUksT0FBTyxNQUFNLEtBQUssV0FBVztZQUFFLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDM0MsR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNsQixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBTSxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxRyxDQUFDO0lBVU0sU0FBUyxDQUFDLE1BQWU7UUFDL0IsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQzFCLElBQUksT0FBTyxNQUFNLEtBQUssV0FBVztZQUFFLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDM0MsR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNsQixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBTSxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxRyxDQUFDO0lBZU0sSUFBSSxDQUFDLEVBQW1ELEVBQUUsT0FBaUI7UUFDakYsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRTtZQUM5QixJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxPQUFPLEdBQUcsQ0FBQztTQUNuQztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ2xCLENBQUM7SUFhTSxPQUFPLENBQUMsRUFBbUQsRUFBRSxPQUFpQjtRQUNwRixJQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVc7WUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQzlCLElBQUksRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDO2dCQUFFLE9BQU8sR0FBRyxDQUFDO1NBQ25DO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDbEIsQ0FBQztJQVVNLEtBQUssQ0FBQyxFQUFtRCxFQUFFLE9BQWlCO1FBQ2xGLElBQUksT0FBTyxPQUFPLEtBQUssV0FBVztZQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFDL0IsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRTtZQUM5QixJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ3pDO1FBQ0QsT0FBTyxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztJQUNqQyxDQUFDO0lBYU0sTUFBTSxDQUFDLEVBQW1ELEVBQUUsT0FBaUI7UUFDbkYsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBZ0IsQ0FBQztRQUNyRSxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQzlCLElBQUksRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDO2dCQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBQzlDO1FBQ0QsT0FBTyxPQUFPLENBQUM7SUFDaEIsQ0FBQztJQVlNLFNBQVMsQ0FBQyxFQUFtRCxFQUFFLE9BQWlCO1FBQ3RGLElBQUksT0FBTyxPQUFPLEtBQUssV0FBVztZQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFELHVHQUF1RztRQUN2RyxNQUFNLE9BQU8sR0FBaUIsQ0FBQyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFnQixFQUFFLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQWdCLENBQUMsQ0FBQztRQUMzSSxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQzlCLElBQUksRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLEVBQUU7Z0JBQ3ZCLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO2FBQ3pCO2lCQUFNO2dCQUNOLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO2FBQ3pCO1NBQ0Q7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNoQixDQUFDO0lBWU0sT0FBTyxDQUFJLEVBQTRELEVBQUUsT0FBaUI7UUFDaEcsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDMUMsT0FBUSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUE2QixDQUFDLE1BQU0sQ0FBQyxHQUFHLFdBQVcsQ0FBQyxDQUFDO0lBQ2xHLENBQUM7SUFZTSxHQUFHLENBQUksRUFBNkMsRUFBRSxPQUFpQjtRQUM3RSxJQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVc7WUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDNUIsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFNLEVBQUU7WUFDaEQsTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDO1lBQ3ZDLE9BQU8sRUFBRSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDN0IsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0lBWU0sU0FBUyxDQUFJLEVBQTZDLEVBQUUsT0FBaUI7UUFDbkYsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBNEIsQ0FBQztRQUM5RSxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSTtZQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDakUsT0FBTyxJQUFJLENBQUM7SUFDYixDQUFDO0lBWU0sSUFBSSxDQUFDLEVBQW1ELEVBQUUsT0FBaUI7UUFDakYsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRTtZQUM5QixJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxPQUFPLElBQUksQ0FBQztTQUNwQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2QsQ0FBQztJQVlNLEtBQUssQ0FBQyxFQUFtRCxFQUFFLE9BQWlCO1FBQ2xGLElBQUksT0FBTyxPQUFPLEtBQUssV0FBVztZQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFELEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUU7WUFDOUIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxPQUFPLEtBQUssQ0FBQztTQUN0QztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2IsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0ksTUFBTSxDQUFJLEVBQTZELEVBQUUsWUFBZ0I7UUFDL0YsSUFBSSxXQUFlLENBQUM7UUFFcEIsSUFBSSxPQUFPLFlBQVksS0FBSyxXQUFXLEVBQUU7WUFDeEMsV0FBVyxHQUFHLFlBQVksQ0FBQztZQUMzQixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSTtnQkFBRSxXQUFXLEdBQUcsRUFBRSxDQUFDLFdBQVcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzdFLE9BQU8sV0FBVyxDQUFDO1NBQ25CO1FBQ0QsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUU7WUFDOUIsSUFBSSxLQUFLLEVBQUU7Z0JBQ1YsV0FBVyxHQUFHLEdBQW1CLENBQUM7Z0JBQ2xDLEtBQUssR0FBRyxLQUFLLENBQUM7Z0JBQ2QsU0FBUzthQUNUO1lBQ0QsV0FBVyxHQUFHLEVBQUUsQ0FBQyxXQUFXLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztTQUM5QztRQUVELHFCQUFxQjtRQUNyQixJQUFJLEtBQUssRUFBRTtZQUNWLE1BQU0sSUFBSSxTQUFTLENBQUMsa0RBQWtELENBQUMsQ0FBQztTQUN4RTtRQUVELE9BQU8sV0FBVyxDQUFDO0lBQ3BCLENBQUM7SUFpQk0sSUFBSSxDQUFDLEVBQWdELEVBQUUsT0FBaUI7UUFDOUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFnRCxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3hFLE9BQU8sSUFBSSxDQUFDO0lBQ2IsQ0FBQztJQWVNLEdBQUcsQ0FBQyxFQUE4QixFQUFFLE9BQWlCO1FBQzNELElBQUksT0FBTyxPQUFPLEtBQUssV0FBVztZQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFELEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNULE9BQU8sSUFBSSxDQUFDO0lBQ2IsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxLQUFLO1FBQ1gsT0FBTyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBUyxDQUFDO0lBQzNELENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxHQUFHLFdBQStCO1FBQy9DLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM3QixLQUFLLE1BQU0sSUFBSSxJQUFJLFdBQVcsRUFBRTtZQUMvQixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSTtnQkFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztTQUNyRDtRQUNELE9BQU8sT0FBTyxDQUFDO0lBQ2hCLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSSxNQUFNLENBQUMsVUFBNEI7UUFDekMsSUFBSSxDQUFDLFVBQVU7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUM5QixJQUFJLElBQUksS0FBSyxVQUFVO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDckMsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFVBQVUsQ0FBQyxJQUFJO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFDaEQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLElBQUksRUFBRTtZQUNoQyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxLQUFLLEtBQUssVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRTtnQkFDMUQsT0FBTyxLQUFLLENBQUM7YUFDYjtTQUNEO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDYixDQUFDO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0ksSUFBSSxDQUFDLGtCQUF3RixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQVUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQ3pKLE1BQU0sT0FBTyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNwQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBVSxFQUFFLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFeEUsbUJBQW1CO1FBQ25CLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNkLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBQ25CLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBRXRCLHNCQUFzQjtRQUN0QixLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksT0FBTyxFQUFFO1lBQzdCLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ2hCO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDYixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLFNBQVMsQ0FBQyxLQUF1QjtRQUN2QyxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxVQUFVLENBQUMsS0FBdUI7UUFDeEMsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFGLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSSxNQUFNLENBQUMsa0JBQXdGLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBVSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDM0osT0FBUSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBVTthQUN4RSxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzdELENBQUM7O0FBSU8sZ0NBQVU7QUFwakJLLGtCQUFPLEdBQXNCLFVBQVUsQ0FBQztBQW1qQmhFLE1BQU0sQ0FBQyxPQUFPLEdBQUcsVUFBVSxDQUFDO0FBRTVCLGtCQUFlLFVBQVUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBpbnRlcmZhY2UgQ29sbGVjdGlvbkNvbnN0cnVjdG9yIHtcblx0bmV3KCk6IENvbGxlY3Rpb248dW5rbm93biwgdW5rbm93bj47XG5cdG5ldzxLLCBWPihlbnRyaWVzPzogUmVhZG9ubHlBcnJheTxyZWFkb25seSBbSywgVl0+IHwgbnVsbCk6IENvbGxlY3Rpb248SywgVj47XG5cdG5ldzxLLCBWPihpdGVyYWJsZTogSXRlcmFibGU8cmVhZG9ubHkgW0ssIFZdPik6IENvbGxlY3Rpb248SywgVj47XG5cdHJlYWRvbmx5IHByb3RvdHlwZTogQ29sbGVjdGlvbjx1bmtub3duLCB1bmtub3duPjtcblx0cmVhZG9ubHkgW1N5bWJvbC5zcGVjaWVzXTogQ29sbGVjdGlvbkNvbnN0cnVjdG9yO1xufVxuXG4vKipcbiAqIEEgTWFwIHdpdGggYWRkaXRpb25hbCB1dGlsaXR5IG1ldGhvZHMuIFRoaXMgaXMgdXNlZCB0aHJvdWdob3V0IGRpc2NvcmQuanMgcmF0aGVyIHRoYW4gQXJyYXlzIGZvciBhbnl0aGluZyB0aGF0IGhhc1xuICogYW4gSUQsIGZvciBzaWduaWZpY2FudGx5IGltcHJvdmVkIHBlcmZvcm1hbmNlIGFuZCBlYXNlLW9mLXVzZS5cbiAqIEBleHRlbmRzIHtNYXB9XG4gKiBAcHJvcGVydHkge251bWJlcn0gc2l6ZSAtIFRoZSBhbW91bnQgb2YgZWxlbWVudHMgaW4gdGhpcyBjb2xsZWN0aW9uLlxuICovXG5jbGFzcyBDb2xsZWN0aW9uPEssIFY+IGV4dGVuZHMgTWFwPEssIFY+IHtcblx0cHJpdmF0ZSBfYXJyYXkhOiBWW10gfCBudWxsO1xuXHRwcml2YXRlIF9rZXlBcnJheSE6IEtbXSB8IG51bGw7XG5cdHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgZGVmYXVsdDogdHlwZW9mIENvbGxlY3Rpb24gPSBDb2xsZWN0aW9uO1xuXHRwdWJsaWMgWydjb25zdHJ1Y3RvciddOiB0eXBlb2YgQ29sbGVjdGlvbjtcblxuXHRwdWJsaWMgY29uc3RydWN0b3IoZW50cmllcz86IFJlYWRvbmx5QXJyYXk8cmVhZG9ubHkgW0ssIFZdPiB8IG51bGwpIHtcblx0XHRzdXBlcihlbnRyaWVzKTtcblxuXHRcdC8qKlxuXHRcdCAqIENhY2hlZCBhcnJheSBmb3IgdGhlIGBhcnJheSgpYCBtZXRob2QgLSB3aWxsIGJlIHJlc2V0IHRvIGBudWxsYCB3aGVuZXZlciBgc2V0KClgIG9yIGBkZWxldGUoKWAgYXJlIGNhbGxlZFxuXHRcdCAqIEBuYW1lIENvbGxlY3Rpb24jX2FycmF5XG5cdFx0ICogQHR5cGUgez9BcnJheX1cblx0XHQgKiBAcHJpdmF0ZVxuXHRcdCAqL1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnX2FycmF5JywgeyB2YWx1ZTogbnVsbCwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9KTtcblxuXHRcdC8qKlxuXHRcdCAqIENhY2hlZCBhcnJheSBmb3IgdGhlIGBrZXlBcnJheSgpYCBtZXRob2QgLSB3aWxsIGJlIHJlc2V0IHRvIGBudWxsYCB3aGVuZXZlciBgc2V0KClgIG9yIGBkZWxldGUoKWAgYXJlIGNhbGxlZFxuXHRcdCAqIEBuYW1lIENvbGxlY3Rpb24jX2tleUFycmF5XG5cdFx0ICogQHR5cGUgez9BcnJheX1cblx0XHQgKiBAcHJpdmF0ZVxuXHRcdCAqL1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnX2tleUFycmF5JywgeyB2YWx1ZTogbnVsbCwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZGVudGljYWwgdG8gW01hcC5nZXQoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvTWFwL2dldCkuXG5cdCAqIEdldHMgYW4gZWxlbWVudCB3aXRoIHRoZSBzcGVjaWZpZWQga2V5LCBhbmQgcmV0dXJucyBpdHMgdmFsdWUsIG9yIGB1bmRlZmluZWRgIGlmIHRoZSBlbGVtZW50IGRvZXMgbm90IGV4aXN0LlxuXHQgKiBAcGFyYW0geyp9IGtleSAtIFRoZSBrZXkgdG8gZ2V0IGZyb20gdGhpcyBjb2xsZWN0aW9uXG5cdCAqIEByZXR1cm5zIHsqIHwgdW5kZWZpbmVkfVxuXHQgKi9cblx0cHVibGljIGdldChrZXk6IEspOiBWIHwgdW5kZWZpbmVkIHtcblx0XHRyZXR1cm4gc3VwZXIuZ2V0KGtleSk7XG5cdH1cblxuXHQvKipcblx0ICogSWRlbnRpY2FsIHRvIFtNYXAuc2V0KCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL01hcC9zZXQpLlxuXHQgKiBTZXRzIGEgbmV3IGVsZW1lbnQgaW4gdGhlIGNvbGxlY3Rpb24gd2l0aCB0aGUgc3BlY2lmaWVkIGtleSBhbmQgdmFsdWUuXG5cdCAqIEBwYXJhbSB7Kn0ga2V5IC0gVGhlIGtleSBvZiB0aGUgZWxlbWVudCB0byBhZGRcblx0ICogQHBhcmFtIHsqfSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgZWxlbWVudCB0byBhZGRcblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqL1xuXHRwdWJsaWMgc2V0KGtleTogSywgdmFsdWU6IFYpOiB0aGlzIHtcblx0XHR0aGlzLl9hcnJheSA9IG51bGw7XG5cdFx0dGhpcy5fa2V5QXJyYXkgPSBudWxsO1xuXHRcdHJldHVybiBzdXBlci5zZXQoa2V5LCB2YWx1ZSk7XG5cdH1cblxuXHQvKipcblx0ICogSWRlbnRpY2FsIHRvIFtNYXAuaGFzKCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL01hcC9oYXMpLlxuXHQgKiBDaGVja3MgaWYgYW4gZWxlbWVudCBleGlzdHMgaW4gdGhlIGNvbGxlY3Rpb24uXG5cdCAqIEBwYXJhbSB7Kn0ga2V5IC0gVGhlIGtleSBvZiB0aGUgZWxlbWVudCB0byBjaGVjayBmb3Jcblx0ICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgZWxlbWVudCBleGlzdHMsIGBmYWxzZWAgaWYgaXQgZG9lcyBub3QgZXhpc3QuXG5cdCAqL1xuXHRwdWJsaWMgaGFzKGtleTogSyk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBzdXBlci5oYXMoa2V5KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZGVudGljYWwgdG8gW01hcC5kZWxldGUoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvTWFwL2RlbGV0ZSkuXG5cdCAqIERlbGV0ZXMgYW4gZWxlbWVudCBmcm9tIHRoZSBjb2xsZWN0aW9uLlxuXHQgKiBAcGFyYW0geyp9IGtleSAtIFRoZSBrZXkgdG8gZGVsZXRlIGZyb20gdGhlIGNvbGxlY3Rpb25cblx0ICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgZWxlbWVudCB3YXMgcmVtb3ZlZCwgYGZhbHNlYCBpZiB0aGUgZWxlbWVudCBkb2VzIG5vdCBleGlzdC5cblx0ICovXG5cdHB1YmxpYyBkZWxldGUoa2V5OiBLKTogYm9vbGVhbiB7XG5cdFx0dGhpcy5fYXJyYXkgPSBudWxsO1xuXHRcdHRoaXMuX2tleUFycmF5ID0gbnVsbDtcblx0XHRyZXR1cm4gc3VwZXIuZGVsZXRlKGtleSk7XG5cdH1cblxuXHQvKipcblx0ICogSWRlbnRpY2FsIHRvIFtNYXAuY2xlYXIoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvTWFwL2NsZWFyKS5cblx0ICogUmVtb3ZlcyBhbGwgZWxlbWVudHMgZnJvbSB0aGUgY29sbGVjdGlvbi5cblx0ICogQHJldHVybnMge3VuZGVmaW5lZH1cblx0ICovXG5cdHB1YmxpYyBjbGVhcigpOiB2b2lkIHtcblx0XHRyZXR1cm4gc3VwZXIuY2xlYXIoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGFuIG9yZGVyZWQgYXJyYXkgb2YgdGhlIHZhbHVlcyBvZiB0aGlzIGNvbGxlY3Rpb24sIGFuZCBjYWNoZXMgaXQgaW50ZXJuYWxseS4gVGhlIGFycmF5IHdpbGwgb25seSBiZVxuXHQgKiByZWNvbnN0cnVjdGVkIGlmIGFuIGl0ZW0gaXMgYWRkZWQgdG8gb3IgcmVtb3ZlZCBmcm9tIHRoZSBjb2xsZWN0aW9uLCBvciBpZiB5b3UgY2hhbmdlIHRoZSBsZW5ndGggb2YgdGhlIGFycmF5XG5cdCAqIGl0c2VsZi4gSWYgeW91IGRvbid0IHdhbnQgdGhpcyBjYWNoaW5nIGJlaGF2aW9yLCB1c2UgYFsuLi5jb2xsZWN0aW9uLnZhbHVlcygpXWAgb3Jcblx0ICogYEFycmF5LmZyb20oY29sbGVjdGlvbi52YWx1ZXMoKSlgIGluc3RlYWQuXG5cdCAqIEByZXR1cm5zIHtBcnJheX1cblx0ICovXG5cdHB1YmxpYyBhcnJheSgpOiBWW10ge1xuXHRcdGlmICghdGhpcy5fYXJyYXkgfHwgdGhpcy5fYXJyYXkubGVuZ3RoICE9PSB0aGlzLnNpemUpIHRoaXMuX2FycmF5ID0gWy4uLnRoaXMudmFsdWVzKCldO1xuXHRcdHJldHVybiB0aGlzLl9hcnJheTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGFuIG9yZGVyZWQgYXJyYXkgb2YgdGhlIGtleXMgb2YgdGhpcyBjb2xsZWN0aW9uLCBhbmQgY2FjaGVzIGl0IGludGVybmFsbHkuIFRoZSBhcnJheSB3aWxsIG9ubHkgYmVcblx0ICogcmVjb25zdHJ1Y3RlZCBpZiBhbiBpdGVtIGlzIGFkZGVkIHRvIG9yIHJlbW92ZWQgZnJvbSB0aGUgY29sbGVjdGlvbiwgb3IgaWYgeW91IGNoYW5nZSB0aGUgbGVuZ3RoIG9mIHRoZSBhcnJheVxuXHQgKiBpdHNlbGYuIElmIHlvdSBkb24ndCB3YW50IHRoaXMgY2FjaGluZyBiZWhhdmlvciwgdXNlIGBbLi4uY29sbGVjdGlvbi5rZXlzKCldYCBvclxuXHQgKiBgQXJyYXkuZnJvbShjb2xsZWN0aW9uLmtleXMoKSlgIGluc3RlYWQuXG5cdCAqIEByZXR1cm5zIHtBcnJheX1cblx0ICovXG5cdHB1YmxpYyBrZXlBcnJheSgpOiBLW10ge1xuXHRcdGlmICghdGhpcy5fa2V5QXJyYXkgfHwgdGhpcy5fa2V5QXJyYXkubGVuZ3RoICE9PSB0aGlzLnNpemUpIHRoaXMuX2tleUFycmF5ID0gWy4uLnRoaXMua2V5cygpXTtcblx0XHRyZXR1cm4gdGhpcy5fa2V5QXJyYXk7XG5cdH1cblxuXHQvKipcblx0ICogT2J0YWlucyB0aGUgZmlyc3QgdmFsdWUocykgaW4gdGhpcyBjb2xsZWN0aW9uLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gW2Ftb3VudF0gQW1vdW50IG9mIHZhbHVlcyB0byBvYnRhaW4gZnJvbSB0aGUgYmVnaW5uaW5nXG5cdCAqIEByZXR1cm5zIHsqfEFycmF5PCo+fSBBIHNpbmdsZSB2YWx1ZSBpZiBubyBhbW91bnQgaXMgcHJvdmlkZWQgb3IgYW4gYXJyYXkgb2YgdmFsdWVzLCBzdGFydGluZyBmcm9tIHRoZSBlbmQgaWZcblx0ICogYW1vdW50IGlzIG5lZ2F0aXZlXG5cdCAqL1xuXHRwdWJsaWMgZmlyc3QoKTogViB8IHVuZGVmaW5lZDtcblx0cHVibGljIGZpcnN0KGFtb3VudDogbnVtYmVyKTogVltdO1xuXHRwdWJsaWMgZmlyc3QoYW1vdW50PzogbnVtYmVyKTogViB8IFZbXSB8IHVuZGVmaW5lZCB7XG5cdFx0aWYgKHR5cGVvZiBhbW91bnQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gdGhpcy52YWx1ZXMoKS5uZXh0KCkudmFsdWU7XG5cdFx0aWYgKGFtb3VudCA8IDApIHJldHVybiB0aGlzLmxhc3QoYW1vdW50ICogLTEpO1xuXHRcdGFtb3VudCA9IE1hdGgubWluKHRoaXMuc2l6ZSwgYW1vdW50KTtcblx0XHRjb25zdCBpdGVyID0gdGhpcy52YWx1ZXMoKTtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbSh7IGxlbmd0aDogYW1vdW50IH0sICgpOiBWID0+IGl0ZXIubmV4dCgpLnZhbHVlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBPYnRhaW5zIHRoZSBmaXJzdCBrZXkocykgaW4gdGhpcyBjb2xsZWN0aW9uLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gW2Ftb3VudF0gQW1vdW50IG9mIGtleXMgdG8gb2J0YWluIGZyb20gdGhlIGJlZ2lubmluZ1xuXHQgKiBAcmV0dXJucyB7KnxBcnJheTwqPn0gQSBzaW5nbGUga2V5IGlmIG5vIGFtb3VudCBpcyBwcm92aWRlZCBvciBhbiBhcnJheSBvZiBrZXlzLCBzdGFydGluZyBmcm9tIHRoZSBlbmQgaWZcblx0ICogYW1vdW50IGlzIG5lZ2F0aXZlXG5cdCAqL1xuXHRwdWJsaWMgZmlyc3RLZXkoKTogSyB8IHVuZGVmaW5lZDtcblx0cHVibGljIGZpcnN0S2V5KGFtb3VudDogbnVtYmVyKTogS1tdO1xuXHRwdWJsaWMgZmlyc3RLZXkoYW1vdW50PzogbnVtYmVyKTogSyB8IEtbXSB8IHVuZGVmaW5lZCB7XG5cdFx0aWYgKHR5cGVvZiBhbW91bnQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gdGhpcy5rZXlzKCkubmV4dCgpLnZhbHVlO1xuXHRcdGlmIChhbW91bnQgPCAwKSByZXR1cm4gdGhpcy5sYXN0S2V5KGFtb3VudCAqIC0xKTtcblx0XHRhbW91bnQgPSBNYXRoLm1pbih0aGlzLnNpemUsIGFtb3VudCk7XG5cdFx0Y29uc3QgaXRlciA9IHRoaXMua2V5cygpO1xuXHRcdHJldHVybiBBcnJheS5mcm9tKHsgbGVuZ3RoOiBhbW91bnQgfSwgKCk6IEsgPT4gaXRlci5uZXh0KCkudmFsdWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE9idGFpbnMgdGhlIGxhc3QgdmFsdWUocykgaW4gdGhpcyBjb2xsZWN0aW9uLiBUaGlzIHJlbGllcyBvbiB7QGxpbmsgQ29sbGVjdGlvbiNhcnJheX0sIGFuZCB0aHVzIHRoZSBjYWNoaW5nXG5cdCAqIG1lY2hhbmlzbSBhcHBsaWVzIGhlcmUgYXMgd2VsbC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IFthbW91bnRdIEFtb3VudCBvZiB2YWx1ZXMgdG8gb2J0YWluIGZyb20gdGhlIGVuZFxuXHQgKiBAcmV0dXJucyB7KnxBcnJheTwqPn0gQSBzaW5nbGUgdmFsdWUgaWYgbm8gYW1vdW50IGlzIHByb3ZpZGVkIG9yIGFuIGFycmF5IG9mIHZhbHVlcywgc3RhcnRpbmcgZnJvbSB0aGUgc3RhcnQgaWZcblx0ICogYW1vdW50IGlzIG5lZ2F0aXZlXG5cdCAqL1xuXHRwdWJsaWMgbGFzdCgpOiBWIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgbGFzdChhbW91bnQ6IG51bWJlcik6IFZbXTtcblx0cHVibGljIGxhc3QoYW1vdW50PzogbnVtYmVyKTogViB8IFZbXSB8IHVuZGVmaW5lZCB7XG5cdFx0Y29uc3QgYXJyID0gdGhpcy5hcnJheSgpO1xuXHRcdGlmICh0eXBlb2YgYW1vdW50ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIGFyclthcnIubGVuZ3RoIC0gMV07XG5cdFx0aWYgKGFtb3VudCA8IDApIHJldHVybiB0aGlzLmZpcnN0KGFtb3VudCAqIC0xKTtcblx0XHRpZiAoIWFtb3VudCkgcmV0dXJuIFtdO1xuXHRcdHJldHVybiBhcnIuc2xpY2UoLWFtb3VudCk7XG5cdH1cblxuXHQvKipcblx0ICogT2J0YWlucyB0aGUgbGFzdCBrZXkocykgaW4gdGhpcyBjb2xsZWN0aW9uLiBUaGlzIHJlbGllcyBvbiB7QGxpbmsgQ29sbGVjdGlvbiNrZXlBcnJheX0sIGFuZCB0aHVzIHRoZSBjYWNoaW5nXG5cdCAqIG1lY2hhbmlzbSBhcHBsaWVzIGhlcmUgYXMgd2VsbC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IFthbW91bnRdIEFtb3VudCBvZiBrZXlzIHRvIG9idGFpbiBmcm9tIHRoZSBlbmRcblx0ICogQHJldHVybnMgeyp8QXJyYXk8Kj59IEEgc2luZ2xlIGtleSBpZiBubyBhbW91bnQgaXMgcHJvdmlkZWQgb3IgYW4gYXJyYXkgb2Yga2V5cywgc3RhcnRpbmcgZnJvbSB0aGUgc3RhcnQgaWZcblx0ICogYW1vdW50IGlzIG5lZ2F0aXZlXG5cdCAqL1xuXHRwdWJsaWMgbGFzdEtleSgpOiBLIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgbGFzdEtleShhbW91bnQ6IG51bWJlcik6IEtbXTtcblx0cHVibGljIGxhc3RLZXkoYW1vdW50PzogbnVtYmVyKTogSyB8IEtbXSB8IHVuZGVmaW5lZCB7XG5cdFx0Y29uc3QgYXJyID0gdGhpcy5rZXlBcnJheSgpO1xuXHRcdGlmICh0eXBlb2YgYW1vdW50ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIGFyclthcnIubGVuZ3RoIC0gMV07XG5cdFx0aWYgKGFtb3VudCA8IDApIHJldHVybiB0aGlzLmZpcnN0S2V5KGFtb3VudCAqIC0xKTtcblx0XHRpZiAoIWFtb3VudCkgcmV0dXJuIFtdO1xuXHRcdHJldHVybiBhcnIuc2xpY2UoLWFtb3VudCk7XG5cdH1cblxuXHQvKipcblx0ICogT2J0YWlucyB1bmlxdWUgcmFuZG9tIHZhbHVlKHMpIGZyb20gdGhpcyBjb2xsZWN0aW9uLiBUaGlzIHJlbGllcyBvbiB7QGxpbmsgQ29sbGVjdGlvbiNhcnJheX0sIGFuZCB0aHVzIHRoZSBjYWNoaW5nXG5cdCAqIG1lY2hhbmlzbSBhcHBsaWVzIGhlcmUgYXMgd2VsbC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IFthbW91bnRdIEFtb3VudCBvZiB2YWx1ZXMgdG8gb2J0YWluIHJhbmRvbWx5XG5cdCAqIEByZXR1cm5zIHsqfEFycmF5PCo+fSBBIHNpbmdsZSB2YWx1ZSBpZiBubyBhbW91bnQgaXMgcHJvdmlkZWQgb3IgYW4gYXJyYXkgb2YgdmFsdWVzXG5cdCAqL1xuXHRwdWJsaWMgcmFuZG9tKCk6IFY7XG5cdHB1YmxpYyByYW5kb20oYW1vdW50OiBudW1iZXIpOiBWW107XG5cdHB1YmxpYyByYW5kb20oYW1vdW50PzogbnVtYmVyKTogViB8IFZbXSB7XG5cdFx0bGV0IGFyciA9IHRoaXMuYXJyYXkoKTtcblx0XHRpZiAodHlwZW9mIGFtb3VudCA9PT0gJ3VuZGVmaW5lZCcpIHJldHVybiBhcnJbTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogYXJyLmxlbmd0aCldO1xuXHRcdGlmIChhcnIubGVuZ3RoID09PSAwIHx8ICFhbW91bnQpIHJldHVybiBbXTtcblx0XHRhcnIgPSBhcnIuc2xpY2UoKTtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbSh7IGxlbmd0aDogYW1vdW50IH0sICgpOiBWID0+IGFyci5zcGxpY2UoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogYXJyLmxlbmd0aCksIDEpWzBdKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBPYnRhaW5zIHVuaXF1ZSByYW5kb20ga2V5KHMpIGZyb20gdGhpcyBjb2xsZWN0aW9uLiBUaGlzIHJlbGllcyBvbiB7QGxpbmsgQ29sbGVjdGlvbiNrZXlBcnJheX0sIGFuZCB0aHVzIHRoZSBjYWNoaW5nXG5cdCAqIG1lY2hhbmlzbSBhcHBsaWVzIGhlcmUgYXMgd2VsbC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IFthbW91bnRdIEFtb3VudCBvZiBrZXlzIHRvIG9idGFpbiByYW5kb21seVxuXHQgKiBAcmV0dXJucyB7KnxBcnJheTwqPn0gQSBzaW5nbGUga2V5IGlmIG5vIGFtb3VudCBpcyBwcm92aWRlZCBvciBhbiBhcnJheVxuXHQgKi9cblx0cHVibGljIHJhbmRvbUtleSgpOiBLO1xuXHRwdWJsaWMgcmFuZG9tS2V5KGFtb3VudDogbnVtYmVyKTogS1tdO1xuXHRwdWJsaWMgcmFuZG9tS2V5KGFtb3VudD86IG51bWJlcik6IEsgfCBLW10ge1xuXHRcdGxldCBhcnIgPSB0aGlzLmtleUFycmF5KCk7XG5cdFx0aWYgKHR5cGVvZiBhbW91bnQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gYXJyW01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGFyci5sZW5ndGgpXTtcblx0XHRpZiAoYXJyLmxlbmd0aCA9PT0gMCB8fCAhYW1vdW50KSByZXR1cm4gW107XG5cdFx0YXJyID0gYXJyLnNsaWNlKCk7XG5cdFx0cmV0dXJuIEFycmF5LmZyb20oeyBsZW5ndGg6IGFtb3VudCB9LCAoKTogSyA9PiBhcnIuc3BsaWNlKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGFyci5sZW5ndGgpLCAxKVswXSk7XG5cdH1cblxuXHQvKipcblx0ICogU2VhcmNoZXMgZm9yIGEgc2luZ2xlIGl0ZW0gd2hlcmUgdGhlIGdpdmVuIGZ1bmN0aW9uIHJldHVybnMgYSB0cnV0aHkgdmFsdWUuIFRoaXMgYmVoYXZlcyBsaWtlXG5cdCAqIFtBcnJheS5maW5kKCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2ZpbmQpLlxuXHQgKiA8d2Fybj5BbGwgY29sbGVjdGlvbnMgdXNlZCBpbiBEaXNjb3JkLmpzIGFyZSBtYXBwZWQgdXNpbmcgdGhlaXIgYGlkYCBwcm9wZXJ0eSwgYW5kIGlmIHlvdSB3YW50IHRvIGZpbmQgYnkgaWQgeW91XG5cdCAqIHNob3VsZCB1c2UgdGhlIGBnZXRgIG1ldGhvZC4gU2VlXG5cdCAqIFtNRE5dKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL01hcC9nZXQpIGZvciBkZXRhaWxzLjwvd2Fybj5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIHRlc3Qgd2l0aCAoc2hvdWxkIHJldHVybiBib29sZWFuKVxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHsqfVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLmZpbmQodXNlciA9PiB1c2VyLnVzZXJuYW1lID09PSAnQm9iJyk7XG5cdCAqL1xuXHRwdWJsaWMgZmluZChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBWIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZDxUPihmbjogKHRoaXM6IFQsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc6IFQpOiBWIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc/OiB1bmtub3duKTogViB8IHVuZGVmaW5lZCB7XG5cdFx0aWYgKHR5cGVvZiB0aGlzQXJnICE9PSAndW5kZWZpbmVkJykgZm4gPSBmbi5iaW5kKHRoaXNBcmcpO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZm4odmFsLCBrZXksIHRoaXMpKSByZXR1cm4gdmFsO1xuXHRcdH1cblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNlYXJjaGVzIGZvciB0aGUga2V5IG9mIGEgc2luZ2xlIGl0ZW0gd2hlcmUgdGhlIGdpdmVuIGZ1bmN0aW9uIHJldHVybnMgYSB0cnV0aHkgdmFsdWUuIFRoaXMgYmVoYXZlcyBsaWtlXG5cdCAqIFtBcnJheS5maW5kSW5kZXgoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvZmluZEluZGV4KSxcblx0ICogYnV0IHJldHVybnMgdGhlIGtleSByYXRoZXIgdGhhbiB0aGUgcG9zaXRpb25hbCBpbmRleC5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIHRlc3Qgd2l0aCAoc2hvdWxkIHJldHVybiBib29sZWFuKVxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHsqfVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLmZpbmRLZXkodXNlciA9PiB1c2VyLnVzZXJuYW1lID09PSAnQm9iJyk7XG5cdCAqL1xuXHRwdWJsaWMgZmluZEtleShmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBLIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZEtleTxUPihmbjogKHRoaXM6IFQsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc6IFQpOiBLIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZEtleShmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc/OiB1bmtub3duKTogSyB8IHVuZGVmaW5lZCB7XG5cdFx0aWYgKHR5cGVvZiB0aGlzQXJnICE9PSAndW5kZWZpbmVkJykgZm4gPSBmbi5iaW5kKHRoaXNBcmcpO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZm4odmFsLCBrZXksIHRoaXMpKSByZXR1cm4ga2V5O1xuXHRcdH1cblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgaXRlbXMgdGhhdCBzYXRpc2Z5IHRoZSBwcm92aWRlZCBmaWx0ZXIgZnVuY3Rpb24uXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHVzZWQgdG8gdGVzdCAoc2hvdWxkIHJldHVybiBhIGJvb2xlYW4pXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge251bWJlcn0gVGhlIG51bWJlciBvZiByZW1vdmVkIGVudHJpZXNcblx0ICovXG5cdHB1YmxpYyBzd2VlcChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBudW1iZXI7XG5cdHB1YmxpYyBzd2VlcDxUPihmbjogKHRoaXM6IFQsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc6IFQpOiBudW1iZXI7XG5cdHB1YmxpYyBzd2VlcChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc/OiB1bmtub3duKTogbnVtYmVyIHtcblx0XHRpZiAodHlwZW9mIHRoaXNBcmcgIT09ICd1bmRlZmluZWQnKSBmbiA9IGZuLmJpbmQodGhpc0FyZyk7XG5cdFx0Y29uc3QgcHJldmlvdXNTaXplID0gdGhpcy5zaXplO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZm4odmFsLCBrZXksIHRoaXMpKSB0aGlzLmRlbGV0ZShrZXkpO1xuXHRcdH1cblx0XHRyZXR1cm4gcHJldmlvdXNTaXplIC0gdGhpcy5zaXplO1xuXHR9XG5cblx0LyoqXG5cdCAqIElkZW50aWNhbCB0b1xuXHQgKiBbQXJyYXkuZmlsdGVyKCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2ZpbHRlciksXG5cdCAqIGJ1dCByZXR1cm5zIGEgQ29sbGVjdGlvbiBpbnN0ZWFkIG9mIGFuIEFycmF5LlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gdGVzdCB3aXRoIChzaG91bGQgcmV0dXJuIGJvb2xlYW4pXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqIEBleGFtcGxlIGNvbGxlY3Rpb24uZmlsdGVyKHVzZXIgPT4gdXNlci51c2VybmFtZSA9PT0gJ0JvYicpO1xuXHQgKi9cblx0cHVibGljIGZpbHRlcihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiB0aGlzO1xuXHRwdWJsaWMgZmlsdGVyPFQ+KGZuOiAodGhpczogVCwgdmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gYm9vbGVhbiwgdGhpc0FyZzogVCk6IHRoaXM7XG5cdHB1YmxpYyBmaWx0ZXIoZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnPzogdW5rbm93bik6IHRoaXMge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRjb25zdCByZXN1bHRzID0gbmV3IHRoaXMuY29uc3RydWN0b3JbU3ltYm9sLnNwZWNpZXNdPEssIFY+KCkgYXMgdGhpcztcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykge1xuXHRcdFx0aWYgKGZuKHZhbCwga2V5LCB0aGlzKSkgcmVzdWx0cy5zZXQoa2V5LCB2YWwpO1xuXHRcdH1cblx0XHRyZXR1cm4gcmVzdWx0cztcblx0fVxuXG5cdC8qKlxuXHQgKiBQYXJ0aXRpb25zIHRoZSBjb2xsZWN0aW9uIGludG8gdHdvIGNvbGxlY3Rpb25zIHdoZXJlIHRoZSBmaXJzdCBjb2xsZWN0aW9uXG5cdCAqIGNvbnRhaW5zIHRoZSBpdGVtcyB0aGF0IHBhc3NlZCBhbmQgdGhlIHNlY29uZCBjb250YWlucyB0aGUgaXRlbXMgdGhhdCBmYWlsZWQuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHVzZWQgdG8gdGVzdCAoc2hvdWxkIHJldHVybiBhIGJvb2xlYW4pXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge0NvbGxlY3Rpb25bXX1cblx0ICogQGV4YW1wbGUgY29uc3QgW2JpZywgc21hbGxdID0gY29sbGVjdGlvbi5wYXJ0aXRpb24oZ3VpbGQgPT4gZ3VpbGQubWVtYmVyQ291bnQgPiAyNTApO1xuXHQgKi9cblx0cHVibGljIHBhcnRpdGlvbihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBbdGhpcywgdGhpc107XG5cdHB1YmxpYyBwYXJ0aXRpb248VD4oZm46ICh0aGlzOiBULCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnOiBUKTogW3RoaXMsIHRoaXNdO1xuXHRwdWJsaWMgcGFydGl0aW9uKGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gYm9vbGVhbiwgdGhpc0FyZz86IHVua25vd24pOiBbdGhpcywgdGhpc10ge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHQvLyBUT0RPOiBjb25zaWRlciByZW1vdmluZyB0aGUgPEssIFY+IGZyb20gdGhlIGNvbnN0cnVjdG9ycyBhZnRlciBUUyAzLjcuMCBpcyByZWxlYXNlZCwgYXMgaXQgaW5mZXJzIGl0XG5cdFx0Y29uc3QgcmVzdWx0czogW3RoaXMsIHRoaXNdID0gW25ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXTxLLCBWPigpIGFzIHRoaXMsIG5ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXTxLLCBWPigpIGFzIHRoaXNdO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZm4odmFsLCBrZXksIHRoaXMpKSB7XG5cdFx0XHRcdHJlc3VsdHNbMF0uc2V0KGtleSwgdmFsKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJlc3VsdHNbMV0uc2V0KGtleSwgdmFsKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHJlc3VsdHM7XG5cdH1cblxuXHQvKipcblx0ICogTWFwcyBlYWNoIGl0ZW0gaW50byBhIENvbGxlY3Rpb24sIHRoZW4gam9pbnMgdGhlIHJlc3VsdHMgaW50byBhIHNpbmdsZSBDb2xsZWN0aW9uLiBJZGVudGljYWwgaW4gYmVoYXZpb3IgdG9cblx0ICogW0FycmF5LmZsYXRNYXAoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvZmxhdE1hcCkuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHRoYXQgcHJvZHVjZXMgYSBuZXcgQ29sbGVjdGlvblxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLmZsYXRNYXAoZ3VpbGQgPT4gZ3VpbGQubWVtYmVycy5jYWNoZSk7XG5cdCAqL1xuXHRwdWJsaWMgZmxhdE1hcDxUPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IENvbGxlY3Rpb248SywgVD4pOiBDb2xsZWN0aW9uPEssIFQ+O1xuXHRwdWJsaWMgZmxhdE1hcDxULCBUaGlzPihmbjogKHRoaXM6IFRoaXMsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IENvbGxlY3Rpb248SywgVD4sIHRoaXNBcmc6IFRoaXMpOiBDb2xsZWN0aW9uPEssIFQ+O1xuXHRwdWJsaWMgZmxhdE1hcDxUPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IENvbGxlY3Rpb248SywgVD4sIHRoaXNBcmc/OiB1bmtub3duKTogQ29sbGVjdGlvbjxLLCBUPiB7XG5cdFx0Y29uc3QgY29sbGVjdGlvbnMgPSB0aGlzLm1hcChmbiwgdGhpc0FyZyk7XG5cdFx0cmV0dXJuIChuZXcgdGhpcy5jb25zdHJ1Y3RvcltTeW1ib2wuc3BlY2llc108SywgVD4oKSBhcyBDb2xsZWN0aW9uPEssIFQ+KS5jb25jYXQoLi4uY29sbGVjdGlvbnMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1hcHMgZWFjaCBpdGVtIHRvIGFub3RoZXIgdmFsdWUgaW50byBhbiBhcnJheS4gSWRlbnRpY2FsIGluIGJlaGF2aW9yIHRvXG5cdCAqIFtBcnJheS5tYXAoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvbWFwKS5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdGhhdCBwcm9kdWNlcyBhbiBlbGVtZW50IG9mIHRoZSBuZXcgYXJyYXksIHRha2luZyB0aHJlZSBhcmd1bWVudHNcblx0ICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBmdW5jdGlvblxuXHQgKiBAcmV0dXJucyB7QXJyYXl9XG5cdCAqIEBleGFtcGxlIGNvbGxlY3Rpb24ubWFwKHVzZXIgPT4gdXNlci50YWcpO1xuXHQgKi9cblx0cHVibGljIG1hcDxUPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IFQpOiBUW107XG5cdHB1YmxpYyBtYXA8VGhpcywgVD4oZm46ICh0aGlzOiBUaGlzLCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBULCB0aGlzQXJnOiBUaGlzKTogVFtdO1xuXHRwdWJsaWMgbWFwPFQ+KGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gVCwgdGhpc0FyZz86IHVua25vd24pOiBUW10ge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRjb25zdCBpdGVyID0gdGhpcy5lbnRyaWVzKCk7XG5cdFx0cmV0dXJuIEFycmF5LmZyb20oeyBsZW5ndGg6IHRoaXMuc2l6ZSB9LCAoKTogVCA9PiB7XG5cdFx0XHRjb25zdCBba2V5LCB2YWx1ZV0gPSBpdGVyLm5leHQoKS52YWx1ZTtcblx0XHRcdHJldHVybiBmbih2YWx1ZSwga2V5LCB0aGlzKTtcblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXBzIGVhY2ggaXRlbSB0byBhbm90aGVyIHZhbHVlIGludG8gYSBjb2xsZWN0aW9uLiBJZGVudGljYWwgaW4gYmVoYXZpb3IgdG9cblx0ICogW0FycmF5Lm1hcCgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9tYXApLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGFuIGVsZW1lbnQgb2YgdGhlIG5ldyBjb2xsZWN0aW9uLCB0YWtpbmcgdGhyZWUgYXJndW1lbnRzXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqIEBleGFtcGxlIGNvbGxlY3Rpb24ubWFwVmFsdWVzKHVzZXIgPT4gdXNlci50YWcpO1xuXHQgKi9cblx0cHVibGljIG1hcFZhbHVlczxUPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IFQpOiBDb2xsZWN0aW9uPEssIFQ+O1xuXHRwdWJsaWMgbWFwVmFsdWVzPFRoaXMsIFQ+KGZuOiAodGhpczogVGhpcywgdmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gVCwgdGhpc0FyZzogVGhpcyk6IENvbGxlY3Rpb248SywgVD47XG5cdHB1YmxpYyBtYXBWYWx1ZXM8VD4oZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBULCB0aGlzQXJnPzogdW5rbm93bik6IENvbGxlY3Rpb248SywgVD4ge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRjb25zdCBjb2xsID0gbmV3IHRoaXMuY29uc3RydWN0b3JbU3ltYm9sLnNwZWNpZXNdPEssIFQ+KCkgYXMgQ29sbGVjdGlvbjxLLCBUPjtcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykgY29sbC5zZXQoa2V5LCBmbih2YWwsIGtleSwgdGhpcykpO1xuXHRcdHJldHVybiBjb2xsO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGVyZSBleGlzdHMgYW4gaXRlbSB0aGF0IHBhc3NlcyBhIHRlc3QuIElkZW50aWNhbCBpbiBiZWhhdmlvciB0b1xuXHQgKiBbQXJyYXkuc29tZSgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9zb21lKS5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdXNlZCB0byB0ZXN0IChzaG91bGQgcmV0dXJuIGEgYm9vbGVhbilcblx0ICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBmdW5jdGlvblxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cblx0ICogQGV4YW1wbGUgY29sbGVjdGlvbi5zb21lKHVzZXIgPT4gdXNlci5kaXNjcmltaW5hdG9yID09PSAnMDAwMCcpO1xuXHQgKi9cblx0cHVibGljIHNvbWUoZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuKTogYm9vbGVhbjtcblx0cHVibGljIHNvbWU8VD4oZm46ICh0aGlzOiBULCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnOiBUKTogYm9vbGVhbjtcblx0cHVibGljIHNvbWUoZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnPzogdW5rbm93bik6IGJvb2xlYW4ge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykge1xuXHRcdFx0aWYgKGZuKHZhbCwga2V5LCB0aGlzKSkgcmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgYWxsIGl0ZW1zIHBhc3NlcyBhIHRlc3QuIElkZW50aWNhbCBpbiBiZWhhdmlvciB0b1xuXHQgKiBbQXJyYXkuZXZlcnkoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvZXZlcnkpLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB1c2VkIHRvIHRlc3QgKHNob3VsZCByZXR1cm4gYSBib29sZWFuKVxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLmV2ZXJ5KHVzZXIgPT4gIXVzZXIuYm90KTtcblx0ICovXG5cdHB1YmxpYyBldmVyeShmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBib29sZWFuO1xuXHRwdWJsaWMgZXZlcnk8VD4oZm46ICh0aGlzOiBULCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnOiBUKTogYm9vbGVhbjtcblx0cHVibGljIGV2ZXJ5KGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gYm9vbGVhbiwgdGhpc0FyZz86IHVua25vd24pOiBib29sZWFuIHtcblx0XHRpZiAodHlwZW9mIHRoaXNBcmcgIT09ICd1bmRlZmluZWQnKSBmbiA9IGZuLmJpbmQodGhpc0FyZyk7XG5cdFx0Zm9yIChjb25zdCBba2V5LCB2YWxdIG9mIHRoaXMpIHtcblx0XHRcdGlmICghZm4odmFsLCBrZXksIHRoaXMpKSByZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFwcGxpZXMgYSBmdW5jdGlvbiB0byBwcm9kdWNlIGEgc2luZ2xlIHZhbHVlLiBJZGVudGljYWwgaW4gYmVoYXZpb3IgdG9cblx0ICogW0FycmF5LnJlZHVjZSgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9yZWR1Y2UpLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB1c2VkIHRvIHJlZHVjZSwgdGFraW5nIGZvdXIgYXJndW1lbnRzOyBgYWNjdW11bGF0b3JgLCBgY3VycmVudFZhbHVlYCwgYGN1cnJlbnRLZXlgLFxuXHQgKiBhbmQgYGNvbGxlY3Rpb25gXG5cdCAqIEBwYXJhbSB7Kn0gW2luaXRpYWxWYWx1ZV0gU3RhcnRpbmcgdmFsdWUgZm9yIHRoZSBhY2N1bXVsYXRvclxuXHQgKiBAcmV0dXJucyB7Kn1cblx0ICogQGV4YW1wbGUgY29sbGVjdGlvbi5yZWR1Y2UoKGFjYywgZ3VpbGQpID0+IGFjYyArIGd1aWxkLm1lbWJlckNvdW50LCAwKTtcblx0ICovXG5cdHB1YmxpYyByZWR1Y2U8VD4oZm46IChhY2N1bXVsYXRvcjogVCwgdmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gVCwgaW5pdGlhbFZhbHVlPzogVCk6IFQge1xuXHRcdGxldCBhY2N1bXVsYXRvciE6IFQ7XG5cblx0XHRpZiAodHlwZW9mIGluaXRpYWxWYWx1ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRcdGFjY3VtdWxhdG9yID0gaW5pdGlhbFZhbHVlO1xuXHRcdFx0Zm9yIChjb25zdCBba2V5LCB2YWxdIG9mIHRoaXMpIGFjY3VtdWxhdG9yID0gZm4oYWNjdW11bGF0b3IsIHZhbCwga2V5LCB0aGlzKTtcblx0XHRcdHJldHVybiBhY2N1bXVsYXRvcjtcblx0XHR9XG5cdFx0bGV0IGZpcnN0ID0gdHJ1ZTtcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykge1xuXHRcdFx0aWYgKGZpcnN0KSB7XG5cdFx0XHRcdGFjY3VtdWxhdG9yID0gdmFsIGFzIHVua25vd24gYXMgVDtcblx0XHRcdFx0Zmlyc3QgPSBmYWxzZTtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHRhY2N1bXVsYXRvciA9IGZuKGFjY3VtdWxhdG9yLCB2YWwsIGtleSwgdGhpcyk7XG5cdFx0fVxuXG5cdFx0Ly8gTm8gaXRlbXMgaXRlcmF0ZWQuXG5cdFx0aWYgKGZpcnN0KSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCdSZWR1Y2Ugb2YgZW1wdHkgY29sbGVjdGlvbiB3aXRoIG5vIGluaXRpYWwgdmFsdWUnKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gYWNjdW11bGF0b3I7XG5cdH1cblxuXHQvKipcblx0ICogSWRlbnRpY2FsIHRvXG5cdCAqIFtNYXAuZm9yRWFjaCgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9NYXAvZm9yRWFjaCksXG5cdCAqIGJ1dCByZXR1cm5zIHRoZSBjb2xsZWN0aW9uIGluc3RlYWQgb2YgdW5kZWZpbmVkLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0byBleGVjdXRlIGZvciBlYWNoIGVsZW1lbnRcblx0ICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBmdW5jdGlvblxuXHQgKiBAcmV0dXJucyB7Q29sbGVjdGlvbn1cblx0ICogQGV4YW1wbGVcblx0ICogY29sbGVjdGlvblxuXHQgKiAgLmVhY2godXNlciA9PiBjb25zb2xlLmxvZyh1c2VyLnVzZXJuYW1lKSlcblx0ICogIC5maWx0ZXIodXNlciA9PiB1c2VyLmJvdClcblx0ICogIC5lYWNoKHVzZXIgPT4gY29uc29sZS5sb2codXNlci51c2VybmFtZSkpO1xuXHQgKi9cblx0cHVibGljIGVhY2goZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiB2b2lkKTogdGhpcztcblx0cHVibGljIGVhY2g8VD4oZm46ICh0aGlzOiBULCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiB2b2lkLCB0aGlzQXJnOiBUKTogdGhpcztcblx0cHVibGljIGVhY2goZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiB2b2lkLCB0aGlzQXJnPzogdW5rbm93bik6IHRoaXMge1xuXHRcdHRoaXMuZm9yRWFjaChmbiBhcyAodmFsdWU6IFYsIGtleTogSywgbWFwOiBNYXA8SywgVj4pID0+IHZvaWQsIHRoaXNBcmcpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJ1bnMgYSBmdW5jdGlvbiBvbiB0aGUgY29sbGVjdGlvbiBhbmQgcmV0dXJucyB0aGUgY29sbGVjdGlvbi5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gZXhlY3V0ZVxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKiBAZXhhbXBsZVxuXHQgKiBjb2xsZWN0aW9uXG5cdCAqICAudGFwKGNvbGwgPT4gY29uc29sZS5sb2coY29sbC5zaXplKSlcblx0ICogIC5maWx0ZXIodXNlciA9PiB1c2VyLmJvdClcblx0ICogIC50YXAoY29sbCA9PiBjb25zb2xlLmxvZyhjb2xsLnNpemUpKVxuXHQgKi9cblx0cHVibGljIHRhcChmbjogKGNvbGxlY3Rpb246IHRoaXMpID0+IHZvaWQpOiB0aGlzO1xuXHRwdWJsaWMgdGFwPFQ+KGZuOiAodGhpczogVCwgY29sbGVjdGlvbjogdGhpcykgPT4gdm9pZCwgdGhpc0FyZzogVCk6IHRoaXM7XG5cdHB1YmxpYyB0YXAoZm46IChjb2xsZWN0aW9uOiB0aGlzKSA9PiB2b2lkLCB0aGlzQXJnPzogdW5rbm93bik6IHRoaXMge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRmbih0aGlzKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGFuIGlkZW50aWNhbCBzaGFsbG93IGNvcHkgb2YgdGhpcyBjb2xsZWN0aW9uLlxuXHQgKiBAcmV0dXJucyB7Q29sbGVjdGlvbn1cblx0ICogQGV4YW1wbGUgY29uc3QgbmV3Q29sbCA9IHNvbWVDb2xsLmNsb25lKCk7XG5cdCAqL1xuXHRwdWJsaWMgY2xvbmUoKTogdGhpcyB7XG5cdFx0cmV0dXJuIG5ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXSh0aGlzKSBhcyB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbWJpbmVzIHRoaXMgY29sbGVjdGlvbiB3aXRoIG90aGVycyBpbnRvIGEgbmV3IGNvbGxlY3Rpb24uIE5vbmUgb2YgdGhlIHNvdXJjZSBjb2xsZWN0aW9ucyBhcmUgbW9kaWZpZWQuXG5cdCAqIEBwYXJhbSB7Li4uQ29sbGVjdGlvbn0gY29sbGVjdGlvbnMgQ29sbGVjdGlvbnMgdG8gbWVyZ2Vcblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqIEBleGFtcGxlIGNvbnN0IG5ld0NvbGwgPSBzb21lQ29sbC5jb25jYXQoc29tZU90aGVyQ29sbCwgYW5vdGhlckNvbGwsIG9oQm95QUNvbGwpO1xuXHQgKi9cblx0cHVibGljIGNvbmNhdCguLi5jb2xsZWN0aW9uczogQ29sbGVjdGlvbjxLLCBWPltdKTogdGhpcyB7XG5cdFx0Y29uc3QgbmV3Q29sbCA9IHRoaXMuY2xvbmUoKTtcblx0XHRmb3IgKGNvbnN0IGNvbGwgb2YgY29sbGVjdGlvbnMpIHtcblx0XHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiBjb2xsKSBuZXdDb2xsLnNldChrZXksIHZhbCk7XG5cdFx0fVxuXHRcdHJldHVybiBuZXdDb2xsO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGlzIGNvbGxlY3Rpb24gc2hhcmVzIGlkZW50aWNhbCBpdGVtcyB3aXRoIGFub3RoZXIuXG5cdCAqIFRoaXMgaXMgZGlmZmVyZW50IHRvIGNoZWNraW5nIGZvciBlcXVhbGl0eSB1c2luZyBlcXVhbC1zaWducywgYmVjYXVzZVxuXHQgKiB0aGUgY29sbGVjdGlvbnMgbWF5IGJlIGRpZmZlcmVudCBvYmplY3RzLCBidXQgY29udGFpbiB0aGUgc2FtZSBkYXRhLlxuXHQgKiBAcGFyYW0ge0NvbGxlY3Rpb259IGNvbGxlY3Rpb24gQ29sbGVjdGlvbiB0byBjb21wYXJlIHdpdGhcblx0ICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIGNvbGxlY3Rpb25zIGhhdmUgaWRlbnRpY2FsIGNvbnRlbnRzXG5cdCAqL1xuXHRwdWJsaWMgZXF1YWxzKGNvbGxlY3Rpb246IENvbGxlY3Rpb248SywgVj4pOiBib29sZWFuIHtcblx0XHRpZiAoIWNvbGxlY3Rpb24pIHJldHVybiBmYWxzZTtcblx0XHRpZiAodGhpcyA9PT0gY29sbGVjdGlvbikgcmV0dXJuIHRydWU7XG5cdFx0aWYgKHRoaXMuc2l6ZSAhPT0gY29sbGVjdGlvbi5zaXplKSByZXR1cm4gZmFsc2U7XG5cdFx0Zm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgdGhpcykge1xuXHRcdFx0aWYgKCFjb2xsZWN0aW9uLmhhcyhrZXkpIHx8IHZhbHVlICE9PSBjb2xsZWN0aW9uLmdldChrZXkpKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIHNvcnQgbWV0aG9kIHNvcnRzIHRoZSBpdGVtcyBvZiBhIGNvbGxlY3Rpb24gaW4gcGxhY2UgYW5kIHJldHVybnMgaXQuXG5cdCAqIFRoZSBzb3J0IGlzIG5vdCBuZWNlc3NhcmlseSBzdGFibGUgaW4gTm9kZSAxMCBvciBvbGRlci5cblx0ICogVGhlIGRlZmF1bHQgc29ydCBvcmRlciBpcyBhY2NvcmRpbmcgdG8gc3RyaW5nIFVuaWNvZGUgY29kZSBwb2ludHMuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJlRnVuY3Rpb25dIFNwZWNpZmllcyBhIGZ1bmN0aW9uIHRoYXQgZGVmaW5lcyB0aGUgc29ydCBvcmRlci5cblx0ICogSWYgb21pdHRlZCwgdGhlIGNvbGxlY3Rpb24gaXMgc29ydGVkIGFjY29yZGluZyB0byBlYWNoIGNoYXJhY3RlcidzIFVuaWNvZGUgY29kZSBwb2ludCB2YWx1ZSxcblx0ICogYWNjb3JkaW5nIHRvIHRoZSBzdHJpbmcgY29udmVyc2lvbiBvZiBlYWNoIGVsZW1lbnQuXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLnNvcnQoKHVzZXJBLCB1c2VyQikgPT4gdXNlckEuY3JlYXRlZFRpbWVzdGFtcCAtIHVzZXJCLmNyZWF0ZWRUaW1lc3RhbXApO1xuXHQgKi9cblx0cHVibGljIHNvcnQoY29tcGFyZUZ1bmN0aW9uOiAoZmlyc3RWYWx1ZTogViwgc2Vjb25kVmFsdWU6IFYsIGZpcnN0S2V5OiBLLCBzZWNvbmRLZXk6IEspID0+IG51bWJlciA9ICh4LCB5KTogbnVtYmVyID0+IE51bWJlcih4ID4geSkgfHwgTnVtYmVyKHggPT09IHkpIC0gMSk6IHRoaXMge1xuXHRcdGNvbnN0IGVudHJpZXMgPSBbLi4udGhpcy5lbnRyaWVzKCldO1xuXHRcdGVudHJpZXMuc29ydCgoYSwgYik6IG51bWJlciA9PiBjb21wYXJlRnVuY3Rpb24oYVsxXSwgYlsxXSwgYVswXSwgYlswXSkpO1xuXG5cdFx0Ly8gUGVyZm9ybSBjbGVhbi11cFxuXHRcdHN1cGVyLmNsZWFyKCk7XG5cdFx0dGhpcy5fYXJyYXkgPSBudWxsO1xuXHRcdHRoaXMuX2tleUFycmF5ID0gbnVsbDtcblxuXHRcdC8vIFNldCB0aGUgbmV3IGVudHJpZXNcblx0XHRmb3IgKGNvbnN0IFtrLCB2XSBvZiBlbnRyaWVzKSB7XG5cdFx0XHRzdXBlci5zZXQoaywgdik7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBpbnRlcnNlY3QgbWV0aG9kIHJldHVybnMgYSBuZXcgc3RydWN0dXJlIGNvbnRhaW5pbmcgaXRlbXMgd2hlcmUgdGhlIGtleXMgYXJlIHByZXNlbnQgaW4gYm90aCBvcmlnaW5hbCBzdHJ1Y3R1cmVzLlxuXHQgKiBAcGFyYW0ge0NvbGxlY3Rpb259IG90aGVyIFRoZSBvdGhlciBDb2xsZWN0aW9uIHRvIGZpbHRlciBhZ2FpbnN0XG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKi9cblx0cHVibGljIGludGVyc2VjdChvdGhlcjogQ29sbGVjdGlvbjxLLCBWPik6IENvbGxlY3Rpb248SywgVj4ge1xuXHRcdHJldHVybiBvdGhlci5maWx0ZXIoKF8sIGspID0+IHRoaXMuaGFzKGspKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgZGlmZmVyZW5jZSBtZXRob2QgcmV0dXJucyBhIG5ldyBzdHJ1Y3R1cmUgY29udGFpbmluZyBpdGVtcyB3aGVyZSB0aGUga2V5IGlzIHByZXNlbnQgaW4gb25lIG9mIHRoZSBvcmlnaW5hbCBzdHJ1Y3R1cmVzIGJ1dCBub3QgdGhlIG90aGVyLlxuXHQgKiBAcGFyYW0ge0NvbGxlY3Rpb259IG90aGVyIFRoZSBvdGhlciBDb2xsZWN0aW9uIHRvIGZpbHRlciBhZ2FpbnN0XG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKi9cblx0cHVibGljIGRpZmZlcmVuY2Uob3RoZXI6IENvbGxlY3Rpb248SywgVj4pOiBDb2xsZWN0aW9uPEssIFY+IHtcblx0XHRyZXR1cm4gb3RoZXIuZmlsdGVyKChfLCBrKSA9PiAhdGhpcy5oYXMoaykpLmNvbmNhdCh0aGlzLmZpbHRlcigoXywgaykgPT4gIW90aGVyLmhhcyhrKSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBzb3J0ZWQgbWV0aG9kIHNvcnRzIHRoZSBpdGVtcyBvZiBhIGNvbGxlY3Rpb24gYW5kIHJldHVybnMgaXQuXG5cdCAqIFRoZSBzb3J0IGlzIG5vdCBuZWNlc3NhcmlseSBzdGFibGUgaW4gTm9kZSAxMCBvciBvbGRlci5cblx0ICogVGhlIGRlZmF1bHQgc29ydCBvcmRlciBpcyBhY2NvcmRpbmcgdG8gc3RyaW5nIFVuaWNvZGUgY29kZSBwb2ludHMuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJlRnVuY3Rpb25dIFNwZWNpZmllcyBhIGZ1bmN0aW9uIHRoYXQgZGVmaW5lcyB0aGUgc29ydCBvcmRlci5cblx0ICogSWYgb21pdHRlZCwgdGhlIGNvbGxlY3Rpb24gaXMgc29ydGVkIGFjY29yZGluZyB0byBlYWNoIGNoYXJhY3RlcidzIFVuaWNvZGUgY29kZSBwb2ludCB2YWx1ZSxcblx0ICogYWNjb3JkaW5nIHRvIHRoZSBzdHJpbmcgY29udmVyc2lvbiBvZiBlYWNoIGVsZW1lbnQuXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLnNvcnRlZCgodXNlckEsIHVzZXJCKSA9PiB1c2VyQS5jcmVhdGVkVGltZXN0YW1wIC0gdXNlckIuY3JlYXRlZFRpbWVzdGFtcCk7XG5cdCAqL1xuXHRwdWJsaWMgc29ydGVkKGNvbXBhcmVGdW5jdGlvbjogKGZpcnN0VmFsdWU6IFYsIHNlY29uZFZhbHVlOiBWLCBmaXJzdEtleTogSywgc2Vjb25kS2V5OiBLKSA9PiBudW1iZXIgPSAoeCwgeSk6IG51bWJlciA9PiBOdW1iZXIoeCA+IHkpIHx8IE51bWJlcih4ID09PSB5KSAtIDEpOiB0aGlzIHtcblx0XHRyZXR1cm4gKG5ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXShbLi4udGhpcy5lbnRyaWVzKCldKSBhcyB0aGlzKVxuXHRcdFx0LnNvcnQoKGF2LCBidiwgYWssIGJrKSA9PiBjb21wYXJlRnVuY3Rpb24oYXYsIGJ2LCBhaywgYmspKTtcblx0fVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IENvbGxlY3Rpb247XG5leHBvcnQgeyBDb2xsZWN0aW9uIH07XG5leHBvcnQgZGVmYXVsdCBDb2xsZWN0aW9uO1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiLyIsInNvdXJjZXMiOlsiaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBUUE7Ozs7O0dBS0c7QUFDSCxNQUFhLFVBQWlCLFNBQVEsR0FBUztJQUk5Qzs7Ozs7T0FLRztJQUNJLEdBQUcsQ0FBQyxHQUFNO1FBQ2hCLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN2QixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksR0FBRyxDQUFDLEdBQU0sRUFBRSxLQUFRO1FBQzFCLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDOUIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksR0FBRyxDQUFDLEdBQU07UUFDaEIsT0FBTyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxHQUFNO1FBQ25CLE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLEtBQUs7UUFDWCxPQUFPLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBQyxHQUFHLElBQVM7UUFDekIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsR0FBRyxJQUFTO1FBQ3pCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFVTSxLQUFLLENBQUMsTUFBZTtRQUMzQixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVc7WUFBRSxPQUFPLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDckUsSUFBSSxNQUFNLEdBQUcsQ0FBQztZQUFFLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUMzQixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBTSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFVTSxRQUFRLENBQUMsTUFBZTtRQUM5QixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVc7WUFBRSxPQUFPLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDbkUsSUFBSSxNQUFNLEdBQUcsQ0FBQztZQUFFLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqRCxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN6QixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsR0FBTSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFVTSxJQUFJLENBQUMsTUFBZTtRQUMxQixNQUFNLEdBQUcsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDL0IsSUFBSSxPQUFPLE1BQU0sS0FBSyxXQUFXO1lBQUUsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM5RCxJQUFJLE1BQU0sR0FBRyxDQUFDO1lBQUUsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQy9DLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDdkIsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQVVNLE9BQU8sQ0FBQyxNQUFlO1FBQzdCLE1BQU0sR0FBRyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUM3QixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVc7WUFBRSxPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzlELElBQUksTUFBTSxHQUFHLENBQUM7WUFBRSxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUN2QixPQUFPLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBU00sTUFBTSxDQUFDLE1BQWU7UUFDNUIsTUFBTSxHQUFHLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQy9CLElBQUksT0FBTyxNQUFNLEtBQUssV0FBVztZQUFFLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTTtZQUFFLE9BQU8sRUFBRSxDQUFDO1FBQ3RDLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FDaEIsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQ3hDLEdBQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUNqRSxDQUFDO0lBQ0gsQ0FBQztJQVNNLFNBQVMsQ0FBQyxNQUFlO1FBQy9CLE1BQU0sR0FBRyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUM3QixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVc7WUFBRSxPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUN0RixJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUN0QyxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQ2hCLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUN4QyxHQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FDakUsQ0FBQztJQUNILENBQUM7SUFvQk0sSUFBSSxDQUFDLEVBQW1ELEVBQUUsT0FBaUI7UUFDakYsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRTtZQUM5QixJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxPQUFPLEdBQUcsQ0FBQztTQUNuQztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ2xCLENBQUM7SUFrQk0sT0FBTyxDQUFDLEVBQW1ELEVBQUUsT0FBaUI7UUFDcEYsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRTtZQUM5QixJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxPQUFPLEdBQUcsQ0FBQztTQUNuQztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ2xCLENBQUM7SUFVTSxLQUFLLENBQUMsRUFBbUQsRUFBRSxPQUFpQjtRQUNsRixJQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVc7WUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQy9CLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUU7WUFDOUIsSUFBSSxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUM7Z0JBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUN6QztRQUNELE9BQU8sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDakMsQ0FBQztJQXVCTSxNQUFNLENBQUMsRUFBbUQsRUFBRSxPQUFpQjtRQUNuRixJQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVc7WUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxNQUFNLE9BQU8sR0FBRyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFRLENBQUM7UUFDN0QsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRTtZQUM5QixJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztTQUM5QztRQUNELE9BQU8sT0FBTyxDQUFDO0lBQ2hCLENBQUM7SUE2Qk0sU0FBUyxDQUNmLEVBQW1ELEVBQ25ELE9BQWlCO1FBRWpCLElBQUksT0FBTyxPQUFPLEtBQUssV0FBVztZQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFELE1BQU0sT0FBTyxHQUF5QztZQUNyRCxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFRO1lBQzVDLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQVE7U0FDNUMsQ0FBQztRQUNGLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUU7WUFDOUIsSUFBSSxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsRUFBRTtnQkFDdkIsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7YUFDekI7aUJBQU07Z0JBQ04sT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7YUFDekI7U0FDRDtRQUNELE9BQU8sT0FBTyxDQUFDO0lBQ2hCLENBQUM7SUFlTSxPQUFPLENBQUksRUFBNEQsRUFBRSxPQUFpQjtRQUNoRyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMxQyxPQUFPLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQVEsQ0FBQyxNQUFNLENBQUMsR0FBRyxXQUFXLENBQUMsQ0FBQztJQUM1RSxDQUFDO0lBWU0sR0FBRyxDQUFJLEVBQTZDLEVBQUUsT0FBaUI7UUFDN0UsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzVCLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsR0FBTSxFQUFFO1lBQ2hELE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQztZQUN2QyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzdCLENBQUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQVlNLFNBQVMsQ0FBSSxFQUE2QyxFQUFFLE9BQWlCO1FBQ25GLElBQUksT0FBTyxPQUFPLEtBQUssV0FBVztZQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFELE1BQU0sSUFBSSxHQUFHLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQVEsQ0FBQztRQUMxRCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSTtZQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDakUsT0FBTyxJQUFJLENBQUM7SUFDYixDQUFDO0lBWU0sSUFBSSxDQUFDLEVBQW1ELEVBQUUsT0FBaUI7UUFDakYsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXO1lBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRTtZQUM5QixJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQztnQkFBRSxPQUFPLElBQUksQ0FBQztTQUNwQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2QsQ0FBQztJQXNCTSxLQUFLLENBQUMsRUFBbUQsRUFBRSxPQUFpQjtRQUNsRixJQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVc7WUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQzlCLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUM7Z0JBQUUsT0FBTyxLQUFLLENBQUM7U0FDdEM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNiLENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNJLE1BQU0sQ0FBSSxFQUE2RCxFQUFFLFlBQWdCO1FBQy9GLElBQUksV0FBZSxDQUFDO1FBRXBCLElBQUksT0FBTyxZQUFZLEtBQUssV0FBVyxFQUFFO1lBQ3hDLFdBQVcsR0FBRyxZQUFZLENBQUM7WUFDM0IsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUk7Z0JBQUUsV0FBVyxHQUFHLEVBQUUsQ0FBQyxXQUFXLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUM3RSxPQUFPLFdBQVcsQ0FBQztTQUNuQjtRQUNELElBQUksS0FBSyxHQUFHLElBQUksQ0FBQztRQUNqQixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQzlCLElBQUksS0FBSyxFQUFFO2dCQUNWLFdBQVcsR0FBRyxHQUFtQixDQUFDO2dCQUNsQyxLQUFLLEdBQUcsS0FBSyxDQUFDO2dCQUNkLFNBQVM7YUFDVDtZQUNELFdBQVcsR0FBRyxFQUFFLENBQUMsV0FBVyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDOUM7UUFFRCxxQkFBcUI7UUFDckIsSUFBSSxLQUFLLEVBQUU7WUFDVixNQUFNLElBQUksU0FBUyxDQUFDLGtEQUFrRCxDQUFDLENBQUM7U0FDeEU7UUFFRCxPQUFPLFdBQVcsQ0FBQztJQUNwQixDQUFDO0lBaUJNLElBQUksQ0FBQyxFQUFnRCxFQUFFLE9BQWlCO1FBQzlFLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBZ0QsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUN4RSxPQUFPLElBQUksQ0FBQztJQUNiLENBQUM7SUFlTSxHQUFHLENBQUMsRUFBOEIsRUFBRSxPQUFpQjtRQUMzRCxJQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVc7WUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDVCxPQUFPLElBQUksQ0FBQztJQUNiLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksS0FBSztRQUNYLE9BQU8sSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxNQUFNLENBQUMsR0FBRyxXQUErQjtRQUMvQyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDN0IsS0FBSyxNQUFNLElBQUksSUFBSSxXQUFXLEVBQUU7WUFDL0IsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUk7Z0JBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDckQ7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNoQixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksTUFBTSxDQUFDLFVBQTRCO1FBQ3pDLHVFQUF1RTtRQUN2RSxJQUFJLENBQUMsVUFBVTtZQUFFLE9BQU8sS0FBSyxDQUFDLENBQUMsZ0JBQWdCO1FBQy9DLElBQUksSUFBSSxLQUFLLFVBQVU7WUFBRSxPQUFPLElBQUksQ0FBQztRQUNyQyxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssVUFBVSxDQUFDLElBQUk7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUNoRCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQ2hDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEtBQUssS0FBSyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFO2dCQUMxRCxPQUFPLEtBQUssQ0FBQzthQUNiO1NBQ0Q7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNiLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSSxJQUFJLENBQUMsa0JBQW9DLFVBQVUsQ0FBQyxXQUFXO1FBQ3JFLE1BQU0sT0FBTyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNwQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBVSxFQUFFLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFeEUsbUJBQW1CO1FBQ25CLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUVkLHNCQUFzQjtRQUN0QixLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksT0FBTyxFQUFFO1lBQzdCLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ2hCO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDYixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLFNBQVMsQ0FBQyxLQUF1QjtRQUN2QyxNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFRLENBQUM7UUFDMUQsS0FBSyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLEtBQUssRUFBRTtZQUMzQixJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ2hDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDYixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLFVBQVUsQ0FBQyxLQUF1QjtRQUN4QyxNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFRLENBQUM7UUFDMUQsS0FBSyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLEtBQUssRUFBRTtZQUMzQixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDakM7UUFDRCxLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksSUFBSSxFQUFFO1lBQzFCLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztTQUNsQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2IsQ0FBQztJQUVEOzs7Ozs7Ozs7T0FTRztJQUNJLE1BQU0sQ0FBQyxrQkFBb0MsVUFBVSxDQUFDLFdBQVc7UUFDdkUsT0FBTyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDN0csQ0FBQztJQUVNLE1BQU07UUFDWixrREFBa0Q7UUFDbEQsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQUVPLE1BQU0sQ0FBQyxXQUFXLENBQUksVUFBYSxFQUFFLFdBQWM7UUFDMUQsT0FBTyxNQUFNLENBQUMsVUFBVSxHQUFHLFdBQVcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxVQUFVLEtBQUssV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ25GLENBQUM7O0FBNWxCRixnQ0E2bEJDO0FBNWxCdUIsa0JBQU8sR0FBc0IsVUFBVSxDQUFDO0FBZ21CaEUsa0JBQWUsVUFBVSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGludGVyZmFjZSBDb2xsZWN0aW9uQ29uc3RydWN0b3Ige1xuXHRuZXcgKCk6IENvbGxlY3Rpb248dW5rbm93biwgdW5rbm93bj47XG5cdG5ldyA8SywgVj4oZW50cmllcz86IFJlYWRvbmx5QXJyYXk8cmVhZG9ubHkgW0ssIFZdPiB8IG51bGwpOiBDb2xsZWN0aW9uPEssIFY+O1xuXHRuZXcgPEssIFY+KGl0ZXJhYmxlOiBJdGVyYWJsZTxyZWFkb25seSBbSywgVl0+KTogQ29sbGVjdGlvbjxLLCBWPjtcblx0cmVhZG9ubHkgcHJvdG90eXBlOiBDb2xsZWN0aW9uPHVua25vd24sIHVua25vd24+O1xuXHRyZWFkb25seSBbU3ltYm9sLnNwZWNpZXNdOiBDb2xsZWN0aW9uQ29uc3RydWN0b3I7XG59XG5cbi8qKlxuICogQSBNYXAgd2l0aCBhZGRpdGlvbmFsIHV0aWxpdHkgbWV0aG9kcy4gVGhpcyBpcyB1c2VkIHRocm91Z2hvdXQgZGlzY29yZC5qcyByYXRoZXIgdGhhbiBBcnJheXMgZm9yIGFueXRoaW5nIHRoYXQgaGFzXG4gKiBhbiBJRCwgZm9yIHNpZ25pZmljYW50bHkgaW1wcm92ZWQgcGVyZm9ybWFuY2UgYW5kIGVhc2Utb2YtdXNlLlxuICogQGV4dGVuZHMge01hcH1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBzaXplIC0gVGhlIGFtb3VudCBvZiBlbGVtZW50cyBpbiB0aGlzIGNvbGxlY3Rpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb2xsZWN0aW9uPEssIFY+IGV4dGVuZHMgTWFwPEssIFY+IHtcblx0cHVibGljIHN0YXRpYyByZWFkb25seSBkZWZhdWx0OiB0eXBlb2YgQ29sbGVjdGlvbiA9IENvbGxlY3Rpb247XG5cdHB1YmxpYyBbJ2NvbnN0cnVjdG9yJ106IENvbGxlY3Rpb25Db25zdHJ1Y3RvcjtcblxuXHQvKipcblx0ICogSWRlbnRpY2FsIHRvIFtNYXAuZ2V0KCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL01hcC9nZXQpLlxuXHQgKiBHZXRzIGFuIGVsZW1lbnQgd2l0aCB0aGUgc3BlY2lmaWVkIGtleSwgYW5kIHJldHVybnMgaXRzIHZhbHVlLCBvciBgdW5kZWZpbmVkYCBpZiB0aGUgZWxlbWVudCBkb2VzIG5vdCBleGlzdC5cblx0ICogQHBhcmFtIHsqfSBrZXkgLSBUaGUga2V5IHRvIGdldCBmcm9tIHRoaXMgY29sbGVjdGlvblxuXHQgKiBAcmV0dXJucyB7KiB8IHVuZGVmaW5lZH1cblx0ICovXG5cdHB1YmxpYyBnZXQoa2V5OiBLKTogViB8IHVuZGVmaW5lZCB7XG5cdFx0cmV0dXJuIHN1cGVyLmdldChrZXkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIElkZW50aWNhbCB0byBbTWFwLnNldCgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9NYXAvc2V0KS5cblx0ICogU2V0cyBhIG5ldyBlbGVtZW50IGluIHRoZSBjb2xsZWN0aW9uIHdpdGggdGhlIHNwZWNpZmllZCBrZXkgYW5kIHZhbHVlLlxuXHQgKiBAcGFyYW0geyp9IGtleSAtIFRoZSBrZXkgb2YgdGhlIGVsZW1lbnQgdG8gYWRkXG5cdCAqIEBwYXJhbSB7Kn0gdmFsdWUgLSBUaGUgdmFsdWUgb2YgdGhlIGVsZW1lbnQgdG8gYWRkXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKi9cblx0cHVibGljIHNldChrZXk6IEssIHZhbHVlOiBWKTogdGhpcyB7XG5cdFx0cmV0dXJuIHN1cGVyLnNldChrZXksIHZhbHVlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZGVudGljYWwgdG8gW01hcC5oYXMoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvTWFwL2hhcykuXG5cdCAqIENoZWNrcyBpZiBhbiBlbGVtZW50IGV4aXN0cyBpbiB0aGUgY29sbGVjdGlvbi5cblx0ICogQHBhcmFtIHsqfSBrZXkgLSBUaGUga2V5IG9mIHRoZSBlbGVtZW50IHRvIGNoZWNrIGZvclxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIHRoZSBlbGVtZW50IGV4aXN0cywgYGZhbHNlYCBpZiBpdCBkb2VzIG5vdCBleGlzdC5cblx0ICovXG5cdHB1YmxpYyBoYXMoa2V5OiBLKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHN1cGVyLmhhcyhrZXkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIElkZW50aWNhbCB0byBbTWFwLmRlbGV0ZSgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9NYXAvZGVsZXRlKS5cblx0ICogRGVsZXRlcyBhbiBlbGVtZW50IGZyb20gdGhlIGNvbGxlY3Rpb24uXG5cdCAqIEBwYXJhbSB7Kn0ga2V5IC0gVGhlIGtleSB0byBkZWxldGUgZnJvbSB0aGUgY29sbGVjdGlvblxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIHRoZSBlbGVtZW50IHdhcyByZW1vdmVkLCBgZmFsc2VgIGlmIHRoZSBlbGVtZW50IGRvZXMgbm90IGV4aXN0LlxuXHQgKi9cblx0cHVibGljIGRlbGV0ZShrZXk6IEspOiBib29sZWFuIHtcblx0XHRyZXR1cm4gc3VwZXIuZGVsZXRlKGtleSk7XG5cdH1cblxuXHQvKipcblx0ICogSWRlbnRpY2FsIHRvIFtNYXAuY2xlYXIoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvTWFwL2NsZWFyKS5cblx0ICogUmVtb3ZlcyBhbGwgZWxlbWVudHMgZnJvbSB0aGUgY29sbGVjdGlvbi5cblx0ICogQHJldHVybnMge3VuZGVmaW5lZH1cblx0ICovXG5cdHB1YmxpYyBjbGVhcigpOiB2b2lkIHtcblx0XHRyZXR1cm4gc3VwZXIuY2xlYXIoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgYWxsIG9mIHRoZSBlbGVtZW50cyBleGlzdCBpbiB0aGUgY29sbGVjdGlvbi5cblx0ICogQHBhcmFtIHsuLi4qfSBrZXlzIC0gVGhlIGtleXMgb2YgdGhlIGVsZW1lbnRzIHRvIGNoZWNrIGZvclxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIGFsbCBvZiB0aGUgZWxlbWVudHMgZXhpc3QsIGBmYWxzZWAgaWYgYXQgbGVhc3Qgb25lIGRvZXMgbm90IGV4aXN0LlxuXHQgKi9cblx0cHVibGljIGhhc0FsbCguLi5rZXlzOiBLW10pOiBib29sZWFuIHtcblx0XHRyZXR1cm4ga2V5cy5ldmVyeSgoaykgPT4gc3VwZXIuaGFzKGspKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgYW55IG9mIHRoZSBlbGVtZW50cyBleGlzdCBpbiB0aGUgY29sbGVjdGlvbi5cblx0ICogQHBhcmFtIHsuLi4qfSBrZXlzIC0gVGhlIGtleXMgb2YgdGhlIGVsZW1lbnRzIHRvIGNoZWNrIGZvclxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIGFueSBvZiB0aGUgZWxlbWVudHMgZXhpc3QsIGBmYWxzZWAgaWYgbm9uZSBleGlzdC5cblx0ICovXG5cdHB1YmxpYyBoYXNBbnkoLi4ua2V5czogS1tdKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIGtleXMuc29tZSgoaykgPT4gc3VwZXIuaGFzKGspKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBPYnRhaW5zIHRoZSBmaXJzdCB2YWx1ZShzKSBpbiB0aGlzIGNvbGxlY3Rpb24uXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBbYW1vdW50XSBBbW91bnQgb2YgdmFsdWVzIHRvIG9idGFpbiBmcm9tIHRoZSBiZWdpbm5pbmdcblx0ICogQHJldHVybnMgeyp8QXJyYXk8Kj59IEEgc2luZ2xlIHZhbHVlIGlmIG5vIGFtb3VudCBpcyBwcm92aWRlZCBvciBhbiBhcnJheSBvZiB2YWx1ZXMsIHN0YXJ0aW5nIGZyb20gdGhlIGVuZCBpZlxuXHQgKiBhbW91bnQgaXMgbmVnYXRpdmVcblx0ICovXG5cdHB1YmxpYyBmaXJzdCgpOiBWIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmlyc3QoYW1vdW50OiBudW1iZXIpOiBWW107XG5cdHB1YmxpYyBmaXJzdChhbW91bnQ/OiBudW1iZXIpOiBWIHwgVltdIHwgdW5kZWZpbmVkIHtcblx0XHRpZiAodHlwZW9mIGFtb3VudCA9PT0gJ3VuZGVmaW5lZCcpIHJldHVybiB0aGlzLnZhbHVlcygpLm5leHQoKS52YWx1ZTtcblx0XHRpZiAoYW1vdW50IDwgMCkgcmV0dXJuIHRoaXMubGFzdChhbW91bnQgKiAtMSk7XG5cdFx0YW1vdW50ID0gTWF0aC5taW4odGhpcy5zaXplLCBhbW91bnQpO1xuXHRcdGNvbnN0IGl0ZXIgPSB0aGlzLnZhbHVlcygpO1xuXHRcdHJldHVybiBBcnJheS5mcm9tKHsgbGVuZ3RoOiBhbW91bnQgfSwgKCk6IFYgPT4gaXRlci5uZXh0KCkudmFsdWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE9idGFpbnMgdGhlIGZpcnN0IGtleShzKSBpbiB0aGlzIGNvbGxlY3Rpb24uXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBbYW1vdW50XSBBbW91bnQgb2Yga2V5cyB0byBvYnRhaW4gZnJvbSB0aGUgYmVnaW5uaW5nXG5cdCAqIEByZXR1cm5zIHsqfEFycmF5PCo+fSBBIHNpbmdsZSBrZXkgaWYgbm8gYW1vdW50IGlzIHByb3ZpZGVkIG9yIGFuIGFycmF5IG9mIGtleXMsIHN0YXJ0aW5nIGZyb20gdGhlIGVuZCBpZlxuXHQgKiBhbW91bnQgaXMgbmVnYXRpdmVcblx0ICovXG5cdHB1YmxpYyBmaXJzdEtleSgpOiBLIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmlyc3RLZXkoYW1vdW50OiBudW1iZXIpOiBLW107XG5cdHB1YmxpYyBmaXJzdEtleShhbW91bnQ/OiBudW1iZXIpOiBLIHwgS1tdIHwgdW5kZWZpbmVkIHtcblx0XHRpZiAodHlwZW9mIGFtb3VudCA9PT0gJ3VuZGVmaW5lZCcpIHJldHVybiB0aGlzLmtleXMoKS5uZXh0KCkudmFsdWU7XG5cdFx0aWYgKGFtb3VudCA8IDApIHJldHVybiB0aGlzLmxhc3RLZXkoYW1vdW50ICogLTEpO1xuXHRcdGFtb3VudCA9IE1hdGgubWluKHRoaXMuc2l6ZSwgYW1vdW50KTtcblx0XHRjb25zdCBpdGVyID0gdGhpcy5rZXlzKCk7XG5cdFx0cmV0dXJuIEFycmF5LmZyb20oeyBsZW5ndGg6IGFtb3VudCB9LCAoKTogSyA9PiBpdGVyLm5leHQoKS52YWx1ZSk7XG5cdH1cblxuXHQvKipcblx0ICogT2J0YWlucyB0aGUgbGFzdCB2YWx1ZShzKSBpbiB0aGlzIGNvbGxlY3Rpb24uXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBbYW1vdW50XSBBbW91bnQgb2YgdmFsdWVzIHRvIG9idGFpbiBmcm9tIHRoZSBlbmRcblx0ICogQHJldHVybnMgeyp8QXJyYXk8Kj59IEEgc2luZ2xlIHZhbHVlIGlmIG5vIGFtb3VudCBpcyBwcm92aWRlZCBvciBhbiBhcnJheSBvZiB2YWx1ZXMsIHN0YXJ0aW5nIGZyb20gdGhlIHN0YXJ0IGlmXG5cdCAqIGFtb3VudCBpcyBuZWdhdGl2ZVxuXHQgKi9cblx0cHVibGljIGxhc3QoKTogViB8IHVuZGVmaW5lZDtcblx0cHVibGljIGxhc3QoYW1vdW50OiBudW1iZXIpOiBWW107XG5cdHB1YmxpYyBsYXN0KGFtb3VudD86IG51bWJlcik6IFYgfCBWW10gfCB1bmRlZmluZWQge1xuXHRcdGNvbnN0IGFyciA9IFsuLi50aGlzLnZhbHVlcygpXTtcblx0XHRpZiAodHlwZW9mIGFtb3VudCA9PT0gJ3VuZGVmaW5lZCcpIHJldHVybiBhcnJbYXJyLmxlbmd0aCAtIDFdO1xuXHRcdGlmIChhbW91bnQgPCAwKSByZXR1cm4gdGhpcy5maXJzdChhbW91bnQgKiAtMSk7XG5cdFx0aWYgKCFhbW91bnQpIHJldHVybiBbXTtcblx0XHRyZXR1cm4gYXJyLnNsaWNlKC1hbW91bnQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE9idGFpbnMgdGhlIGxhc3Qga2V5KHMpIGluIHRoaXMgY29sbGVjdGlvbi5cblx0ICogQHBhcmFtIHtudW1iZXJ9IFthbW91bnRdIEFtb3VudCBvZiBrZXlzIHRvIG9idGFpbiBmcm9tIHRoZSBlbmRcblx0ICogQHJldHVybnMgeyp8QXJyYXk8Kj59IEEgc2luZ2xlIGtleSBpZiBubyBhbW91bnQgaXMgcHJvdmlkZWQgb3IgYW4gYXJyYXkgb2Yga2V5cywgc3RhcnRpbmcgZnJvbSB0aGUgc3RhcnQgaWZcblx0ICogYW1vdW50IGlzIG5lZ2F0aXZlXG5cdCAqL1xuXHRwdWJsaWMgbGFzdEtleSgpOiBLIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgbGFzdEtleShhbW91bnQ6IG51bWJlcik6IEtbXTtcblx0cHVibGljIGxhc3RLZXkoYW1vdW50PzogbnVtYmVyKTogSyB8IEtbXSB8IHVuZGVmaW5lZCB7XG5cdFx0Y29uc3QgYXJyID0gWy4uLnRoaXMua2V5cygpXTtcblx0XHRpZiAodHlwZW9mIGFtb3VudCA9PT0gJ3VuZGVmaW5lZCcpIHJldHVybiBhcnJbYXJyLmxlbmd0aCAtIDFdO1xuXHRcdGlmIChhbW91bnQgPCAwKSByZXR1cm4gdGhpcy5maXJzdEtleShhbW91bnQgKiAtMSk7XG5cdFx0aWYgKCFhbW91bnQpIHJldHVybiBbXTtcblx0XHRyZXR1cm4gYXJyLnNsaWNlKC1hbW91bnQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE9idGFpbnMgdW5pcXVlIHJhbmRvbSB2YWx1ZShzKSBmcm9tIHRoaXMgY29sbGVjdGlvbi5cblx0ICogQHBhcmFtIHtudW1iZXJ9IFthbW91bnRdIEFtb3VudCBvZiB2YWx1ZXMgdG8gb2J0YWluIHJhbmRvbWx5XG5cdCAqIEByZXR1cm5zIHsqfEFycmF5PCo+fSBBIHNpbmdsZSB2YWx1ZSBpZiBubyBhbW91bnQgaXMgcHJvdmlkZWQgb3IgYW4gYXJyYXkgb2YgdmFsdWVzXG5cdCAqL1xuXHRwdWJsaWMgcmFuZG9tKCk6IFY7XG5cdHB1YmxpYyByYW5kb20oYW1vdW50OiBudW1iZXIpOiBWW107XG5cdHB1YmxpYyByYW5kb20oYW1vdW50PzogbnVtYmVyKTogViB8IFZbXSB7XG5cdFx0Y29uc3QgYXJyID0gWy4uLnRoaXMudmFsdWVzKCldO1xuXHRcdGlmICh0eXBlb2YgYW1vdW50ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIGFycltNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBhcnIubGVuZ3RoKV07XG5cdFx0aWYgKCFhcnIubGVuZ3RoIHx8ICFhbW91bnQpIHJldHVybiBbXTtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbShcblx0XHRcdHsgbGVuZ3RoOiBNYXRoLm1pbihhbW91bnQsIGFyci5sZW5ndGgpIH0sXG5cdFx0XHQoKTogViA9PiBhcnIuc3BsaWNlKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGFyci5sZW5ndGgpLCAxKVswXSxcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE9idGFpbnMgdW5pcXVlIHJhbmRvbSBrZXkocykgZnJvbSB0aGlzIGNvbGxlY3Rpb24uXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBbYW1vdW50XSBBbW91bnQgb2Yga2V5cyB0byBvYnRhaW4gcmFuZG9tbHlcblx0ICogQHJldHVybnMgeyp8QXJyYXk8Kj59IEEgc2luZ2xlIGtleSBpZiBubyBhbW91bnQgaXMgcHJvdmlkZWQgb3IgYW4gYXJyYXlcblx0ICovXG5cdHB1YmxpYyByYW5kb21LZXkoKTogSztcblx0cHVibGljIHJhbmRvbUtleShhbW91bnQ6IG51bWJlcik6IEtbXTtcblx0cHVibGljIHJhbmRvbUtleShhbW91bnQ/OiBudW1iZXIpOiBLIHwgS1tdIHtcblx0XHRjb25zdCBhcnIgPSBbLi4udGhpcy5rZXlzKCldO1xuXHRcdGlmICh0eXBlb2YgYW1vdW50ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIGFycltNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBhcnIubGVuZ3RoKV07XG5cdFx0aWYgKCFhcnIubGVuZ3RoIHx8ICFhbW91bnQpIHJldHVybiBbXTtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbShcblx0XHRcdHsgbGVuZ3RoOiBNYXRoLm1pbihhbW91bnQsIGFyci5sZW5ndGgpIH0sXG5cdFx0XHQoKTogSyA9PiBhcnIuc3BsaWNlKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGFyci5sZW5ndGgpLCAxKVswXSxcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNlYXJjaGVzIGZvciBhIHNpbmdsZSBpdGVtIHdoZXJlIHRoZSBnaXZlbiBmdW5jdGlvbiByZXR1cm5zIGEgdHJ1dGh5IHZhbHVlLiBUaGlzIGJlaGF2ZXMgbGlrZVxuXHQgKiBbQXJyYXkuZmluZCgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9maW5kKS5cblx0ICogPHdhcm4+QWxsIGNvbGxlY3Rpb25zIHVzZWQgaW4gRGlzY29yZC5qcyBhcmUgbWFwcGVkIHVzaW5nIHRoZWlyIGBpZGAgcHJvcGVydHksIGFuZCBpZiB5b3Ugd2FudCB0byBmaW5kIGJ5IGlkIHlvdVxuXHQgKiBzaG91bGQgdXNlIHRoZSBgZ2V0YCBtZXRob2QuIFNlZVxuXHQgKiBbTUROXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9NYXAvZ2V0KSBmb3IgZGV0YWlscy48L3dhcm4+XG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byB0ZXN0IHdpdGggKHNob3VsZCByZXR1cm4gYm9vbGVhbilcblx0ICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBmdW5jdGlvblxuXHQgKiBAcmV0dXJucyB7Kn1cblx0ICogQGV4YW1wbGUgY29sbGVjdGlvbi5maW5kKHVzZXIgPT4gdXNlci51c2VybmFtZSA9PT0gJ0JvYicpO1xuXHQgKi9cblx0cHVibGljIGZpbmQ8VjIgZXh0ZW5kcyBWPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IHZhbHVlIGlzIFYyKTogVjIgfCB1bmRlZmluZWQ7XG5cdHB1YmxpYyBmaW5kKGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gYm9vbGVhbik6IFYgfCB1bmRlZmluZWQ7XG5cdHB1YmxpYyBmaW5kPFRoaXMsIFYyIGV4dGVuZHMgVj4oXG5cdFx0Zm46ICh0aGlzOiBUaGlzLCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiB2YWx1ZSBpcyBWMixcblx0XHR0aGlzQXJnOiBUaGlzLFxuXHQpOiBWMiB8IHVuZGVmaW5lZDtcblx0cHVibGljIGZpbmQ8VGhpcz4oZm46ICh0aGlzOiBUaGlzLCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnOiBUaGlzKTogViB8IHVuZGVmaW5lZDtcblx0cHVibGljIGZpbmQoZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnPzogdW5rbm93bik6IFYgfCB1bmRlZmluZWQge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykge1xuXHRcdFx0aWYgKGZuKHZhbCwga2V5LCB0aGlzKSkgcmV0dXJuIHZhbDtcblx0XHR9XG5cdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZWFyY2hlcyBmb3IgdGhlIGtleSBvZiBhIHNpbmdsZSBpdGVtIHdoZXJlIHRoZSBnaXZlbiBmdW5jdGlvbiByZXR1cm5zIGEgdHJ1dGh5IHZhbHVlLiBUaGlzIGJlaGF2ZXMgbGlrZVxuXHQgKiBbQXJyYXkuZmluZEluZGV4KCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2ZpbmRJbmRleCksXG5cdCAqIGJ1dCByZXR1cm5zIHRoZSBrZXkgcmF0aGVyIHRoYW4gdGhlIHBvc2l0aW9uYWwgaW5kZXguXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byB0ZXN0IHdpdGggKHNob3VsZCByZXR1cm4gYm9vbGVhbilcblx0ICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBmdW5jdGlvblxuXHQgKiBAcmV0dXJucyB7Kn1cblx0ICogQGV4YW1wbGUgY29sbGVjdGlvbi5maW5kS2V5KHVzZXIgPT4gdXNlci51c2VybmFtZSA9PT0gJ0JvYicpO1xuXHQgKi9cblx0cHVibGljIGZpbmRLZXk8SzIgZXh0ZW5kcyBLPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGtleSBpcyBLMik6IEsyIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZEtleShmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBLIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZEtleTxUaGlzLCBLMiBleHRlbmRzIEs+KFxuXHRcdGZuOiAodGhpczogVGhpcywgdmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4ga2V5IGlzIEsyLFxuXHRcdHRoaXNBcmc6IFRoaXMsXG5cdCk6IEsyIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZEtleTxUaGlzPihmbjogKHRoaXM6IFRoaXMsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc6IFRoaXMpOiBLIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgZmluZEtleShmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc/OiB1bmtub3duKTogSyB8IHVuZGVmaW5lZCB7XG5cdFx0aWYgKHR5cGVvZiB0aGlzQXJnICE9PSAndW5kZWZpbmVkJykgZm4gPSBmbi5iaW5kKHRoaXNBcmcpO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZm4odmFsLCBrZXksIHRoaXMpKSByZXR1cm4ga2V5O1xuXHRcdH1cblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgaXRlbXMgdGhhdCBzYXRpc2Z5IHRoZSBwcm92aWRlZCBmaWx0ZXIgZnVuY3Rpb24uXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHVzZWQgdG8gdGVzdCAoc2hvdWxkIHJldHVybiBhIGJvb2xlYW4pXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge251bWJlcn0gVGhlIG51bWJlciBvZiByZW1vdmVkIGVudHJpZXNcblx0ICovXG5cdHB1YmxpYyBzd2VlcChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBudW1iZXI7XG5cdHB1YmxpYyBzd2VlcDxUPihmbjogKHRoaXM6IFQsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc6IFQpOiBudW1iZXI7XG5cdHB1YmxpYyBzd2VlcChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc/OiB1bmtub3duKTogbnVtYmVyIHtcblx0XHRpZiAodHlwZW9mIHRoaXNBcmcgIT09ICd1bmRlZmluZWQnKSBmbiA9IGZuLmJpbmQodGhpc0FyZyk7XG5cdFx0Y29uc3QgcHJldmlvdXNTaXplID0gdGhpcy5zaXplO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZm4odmFsLCBrZXksIHRoaXMpKSB0aGlzLmRlbGV0ZShrZXkpO1xuXHRcdH1cblx0XHRyZXR1cm4gcHJldmlvdXNTaXplIC0gdGhpcy5zaXplO1xuXHR9XG5cblx0LyoqXG5cdCAqIElkZW50aWNhbCB0b1xuXHQgKiBbQXJyYXkuZmlsdGVyKCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2ZpbHRlciksXG5cdCAqIGJ1dCByZXR1cm5zIGEgQ29sbGVjdGlvbiBpbnN0ZWFkIG9mIGFuIEFycmF5LlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gdGVzdCB3aXRoIChzaG91bGQgcmV0dXJuIGJvb2xlYW4pXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqIEBleGFtcGxlIGNvbGxlY3Rpb24uZmlsdGVyKHVzZXIgPT4gdXNlci51c2VybmFtZSA9PT0gJ0JvYicpO1xuXHQgKi9cblx0cHVibGljIGZpbHRlcjxLMiBleHRlbmRzIEs+KGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4ga2V5IGlzIEsyKTogQ29sbGVjdGlvbjxLMiwgVj47XG5cdHB1YmxpYyBmaWx0ZXI8VjIgZXh0ZW5kcyBWPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IHZhbHVlIGlzIFYyKTogQ29sbGVjdGlvbjxLLCBWMj47XG5cdHB1YmxpYyBmaWx0ZXIoZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuKTogQ29sbGVjdGlvbjxLLCBWPjtcblx0cHVibGljIGZpbHRlcjxUaGlzLCBLMiBleHRlbmRzIEs+KFxuXHRcdGZuOiAodGhpczogVGhpcywgdmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4ga2V5IGlzIEsyLFxuXHRcdHRoaXNBcmc6IFRoaXMsXG5cdCk6IENvbGxlY3Rpb248SzIsIFY+O1xuXHRwdWJsaWMgZmlsdGVyPFRoaXMsIFYyIGV4dGVuZHMgVj4oXG5cdFx0Zm46ICh0aGlzOiBUaGlzLCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiB2YWx1ZSBpcyBWMixcblx0XHR0aGlzQXJnOiBUaGlzLFxuXHQpOiBDb2xsZWN0aW9uPEssIFYyPjtcblx0cHVibGljIGZpbHRlcjxUaGlzPihmbjogKHRoaXM6IFRoaXMsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc6IFRoaXMpOiBDb2xsZWN0aW9uPEssIFY+O1xuXHRwdWJsaWMgZmlsdGVyKGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gYm9vbGVhbiwgdGhpc0FyZz86IHVua25vd24pOiBDb2xsZWN0aW9uPEssIFY+IHtcblx0XHRpZiAodHlwZW9mIHRoaXNBcmcgIT09ICd1bmRlZmluZWQnKSBmbiA9IGZuLmJpbmQodGhpc0FyZyk7XG5cdFx0Y29uc3QgcmVzdWx0cyA9IG5ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXTxLLCBWPigpO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZm4odmFsLCBrZXksIHRoaXMpKSByZXN1bHRzLnNldChrZXksIHZhbCk7XG5cdFx0fVxuXHRcdHJldHVybiByZXN1bHRzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBhcnRpdGlvbnMgdGhlIGNvbGxlY3Rpb24gaW50byB0d28gY29sbGVjdGlvbnMgd2hlcmUgdGhlIGZpcnN0IGNvbGxlY3Rpb25cblx0ICogY29udGFpbnMgdGhlIGl0ZW1zIHRoYXQgcGFzc2VkIGFuZCB0aGUgc2Vjb25kIGNvbnRhaW5zIHRoZSBpdGVtcyB0aGF0IGZhaWxlZC5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdXNlZCB0byB0ZXN0IChzaG91bGQgcmV0dXJuIGEgYm9vbGVhbilcblx0ICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBmdW5jdGlvblxuXHQgKiBAcmV0dXJucyB7Q29sbGVjdGlvbltdfVxuXHQgKiBAZXhhbXBsZSBjb25zdCBbYmlnLCBzbWFsbF0gPSBjb2xsZWN0aW9uLnBhcnRpdGlvbihndWlsZCA9PiBndWlsZC5tZW1iZXJDb3VudCA+IDI1MCk7XG5cdCAqL1xuXHRwdWJsaWMgcGFydGl0aW9uPEsyIGV4dGVuZHMgSz4oXG5cdFx0Zm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBrZXkgaXMgSzIsXG5cdCk6IFtDb2xsZWN0aW9uPEsyLCBWPiwgQ29sbGVjdGlvbjxFeGNsdWRlPEssIEsyPiwgVj5dO1xuXHRwdWJsaWMgcGFydGl0aW9uPFYyIGV4dGVuZHMgVj4oXG5cdFx0Zm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiB2YWx1ZSBpcyBWMixcblx0KTogW0NvbGxlY3Rpb248SywgVjI+LCBDb2xsZWN0aW9uPEssIEV4Y2x1ZGU8ViwgVjI+Pl07XG5cdHB1YmxpYyBwYXJ0aXRpb24oZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuKTogW0NvbGxlY3Rpb248SywgVj4sIENvbGxlY3Rpb248SywgVj5dO1xuXHRwdWJsaWMgcGFydGl0aW9uPFRoaXMsIEsyIGV4dGVuZHMgSz4oXG5cdFx0Zm46ICh0aGlzOiBUaGlzLCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBrZXkgaXMgSzIsXG5cdFx0dGhpc0FyZzogVGhpcyxcblx0KTogW0NvbGxlY3Rpb248SzIsIFY+LCBDb2xsZWN0aW9uPEV4Y2x1ZGU8SywgSzI+LCBWPl07XG5cdHB1YmxpYyBwYXJ0aXRpb248VGhpcywgVjIgZXh0ZW5kcyBWPihcblx0XHRmbjogKHRoaXM6IFRoaXMsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IHZhbHVlIGlzIFYyLFxuXHRcdHRoaXNBcmc6IFRoaXMsXG5cdCk6IFtDb2xsZWN0aW9uPEssIFYyPiwgQ29sbGVjdGlvbjxLLCBFeGNsdWRlPFYsIFYyPj5dO1xuXHRwdWJsaWMgcGFydGl0aW9uPFRoaXM+KFxuXHRcdGZuOiAodGhpczogVGhpcywgdmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gYm9vbGVhbixcblx0XHR0aGlzQXJnOiBUaGlzLFxuXHQpOiBbQ29sbGVjdGlvbjxLLCBWPiwgQ29sbGVjdGlvbjxLLCBWPl07XG5cdHB1YmxpYyBwYXJ0aXRpb24oXG5cdFx0Zm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLFxuXHRcdHRoaXNBcmc/OiB1bmtub3duLFxuXHQpOiBbQ29sbGVjdGlvbjxLLCBWPiwgQ29sbGVjdGlvbjxLLCBWPl0ge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRjb25zdCByZXN1bHRzOiBbQ29sbGVjdGlvbjxLLCBWPiwgQ29sbGVjdGlvbjxLLCBWPl0gPSBbXG5cdFx0XHRuZXcgdGhpcy5jb25zdHJ1Y3RvcltTeW1ib2wuc3BlY2llc108SywgVj4oKSxcblx0XHRcdG5ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXTxLLCBWPigpLFxuXHRcdF07XG5cdFx0Zm9yIChjb25zdCBba2V5LCB2YWxdIG9mIHRoaXMpIHtcblx0XHRcdGlmIChmbih2YWwsIGtleSwgdGhpcykpIHtcblx0XHRcdFx0cmVzdWx0c1swXS5zZXQoa2V5LCB2YWwpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmVzdWx0c1sxXS5zZXQoa2V5LCB2YWwpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gcmVzdWx0cztcblx0fVxuXG5cdC8qKlxuXHQgKiBNYXBzIGVhY2ggaXRlbSBpbnRvIGEgQ29sbGVjdGlvbiwgdGhlbiBqb2lucyB0aGUgcmVzdWx0cyBpbnRvIGEgc2luZ2xlIENvbGxlY3Rpb24uIElkZW50aWNhbCBpbiBiZWhhdmlvciB0b1xuXHQgKiBbQXJyYXkuZmxhdE1hcCgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9mbGF0TWFwKS5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdGhhdCBwcm9kdWNlcyBhIG5ldyBDb2xsZWN0aW9uXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqIEBleGFtcGxlIGNvbGxlY3Rpb24uZmxhdE1hcChndWlsZCA9PiBndWlsZC5tZW1iZXJzLmNhY2hlKTtcblx0ICovXG5cdHB1YmxpYyBmbGF0TWFwPFQ+KGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gQ29sbGVjdGlvbjxLLCBUPik6IENvbGxlY3Rpb248SywgVD47XG5cdHB1YmxpYyBmbGF0TWFwPFQsIFRoaXM+KFxuXHRcdGZuOiAodGhpczogVGhpcywgdmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gQ29sbGVjdGlvbjxLLCBUPixcblx0XHR0aGlzQXJnOiBUaGlzLFxuXHQpOiBDb2xsZWN0aW9uPEssIFQ+O1xuXHRwdWJsaWMgZmxhdE1hcDxUPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IENvbGxlY3Rpb248SywgVD4sIHRoaXNBcmc/OiB1bmtub3duKTogQ29sbGVjdGlvbjxLLCBUPiB7XG5cdFx0Y29uc3QgY29sbGVjdGlvbnMgPSB0aGlzLm1hcChmbiwgdGhpc0FyZyk7XG5cdFx0cmV0dXJuIG5ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXTxLLCBUPigpLmNvbmNhdCguLi5jb2xsZWN0aW9ucyk7XG5cdH1cblxuXHQvKipcblx0ICogTWFwcyBlYWNoIGl0ZW0gdG8gYW5vdGhlciB2YWx1ZSBpbnRvIGFuIGFycmF5LiBJZGVudGljYWwgaW4gYmVoYXZpb3IgdG9cblx0ICogW0FycmF5Lm1hcCgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9tYXApLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGFuIGVsZW1lbnQgb2YgdGhlIG5ldyBhcnJheSwgdGFraW5nIHRocmVlIGFyZ3VtZW50c1xuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHtBcnJheX1cblx0ICogQGV4YW1wbGUgY29sbGVjdGlvbi5tYXAodXNlciA9PiB1c2VyLnRhZyk7XG5cdCAqL1xuXHRwdWJsaWMgbWFwPFQ+KGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gVCk6IFRbXTtcblx0cHVibGljIG1hcDxUaGlzLCBUPihmbjogKHRoaXM6IFRoaXMsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IFQsIHRoaXNBcmc6IFRoaXMpOiBUW107XG5cdHB1YmxpYyBtYXA8VD4oZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBULCB0aGlzQXJnPzogdW5rbm93bik6IFRbXSB7XG5cdFx0aWYgKHR5cGVvZiB0aGlzQXJnICE9PSAndW5kZWZpbmVkJykgZm4gPSBmbi5iaW5kKHRoaXNBcmcpO1xuXHRcdGNvbnN0IGl0ZXIgPSB0aGlzLmVudHJpZXMoKTtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbSh7IGxlbmd0aDogdGhpcy5zaXplIH0sICgpOiBUID0+IHtcblx0XHRcdGNvbnN0IFtrZXksIHZhbHVlXSA9IGl0ZXIubmV4dCgpLnZhbHVlO1xuXHRcdFx0cmV0dXJuIGZuKHZhbHVlLCBrZXksIHRoaXMpO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1hcHMgZWFjaCBpdGVtIHRvIGFub3RoZXIgdmFsdWUgaW50byBhIGNvbGxlY3Rpb24uIElkZW50aWNhbCBpbiBiZWhhdmlvciB0b1xuXHQgKiBbQXJyYXkubWFwKCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L21hcCkuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHRoYXQgcHJvZHVjZXMgYW4gZWxlbWVudCBvZiB0aGUgbmV3IGNvbGxlY3Rpb24sIHRha2luZyB0aHJlZSBhcmd1bWVudHNcblx0ICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBmdW5jdGlvblxuXHQgKiBAcmV0dXJucyB7Q29sbGVjdGlvbn1cblx0ICogQGV4YW1wbGUgY29sbGVjdGlvbi5tYXBWYWx1ZXModXNlciA9PiB1c2VyLnRhZyk7XG5cdCAqL1xuXHRwdWJsaWMgbWFwVmFsdWVzPFQ+KGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4gVCk6IENvbGxlY3Rpb248SywgVD47XG5cdHB1YmxpYyBtYXBWYWx1ZXM8VGhpcywgVD4oZm46ICh0aGlzOiBUaGlzLCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBULCB0aGlzQXJnOiBUaGlzKTogQ29sbGVjdGlvbjxLLCBUPjtcblx0cHVibGljIG1hcFZhbHVlczxUPihmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IFQsIHRoaXNBcmc/OiB1bmtub3duKTogQ29sbGVjdGlvbjxLLCBUPiB7XG5cdFx0aWYgKHR5cGVvZiB0aGlzQXJnICE9PSAndW5kZWZpbmVkJykgZm4gPSBmbi5iaW5kKHRoaXNBcmcpO1xuXHRcdGNvbnN0IGNvbGwgPSBuZXcgdGhpcy5jb25zdHJ1Y3RvcltTeW1ib2wuc3BlY2llc108SywgVD4oKTtcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykgY29sbC5zZXQoa2V5LCBmbih2YWwsIGtleSwgdGhpcykpO1xuXHRcdHJldHVybiBjb2xsO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGVyZSBleGlzdHMgYW4gaXRlbSB0aGF0IHBhc3NlcyBhIHRlc3QuIElkZW50aWNhbCBpbiBiZWhhdmlvciB0b1xuXHQgKiBbQXJyYXkuc29tZSgpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9zb21lKS5cblx0ICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdXNlZCB0byB0ZXN0IChzaG91bGQgcmV0dXJuIGEgYm9vbGVhbilcblx0ICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBmdW5jdGlvblxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cblx0ICogQGV4YW1wbGUgY29sbGVjdGlvbi5zb21lKHVzZXIgPT4gdXNlci5kaXNjcmltaW5hdG9yID09PSAnMDAwMCcpO1xuXHQgKi9cblx0cHVibGljIHNvbWUoZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuKTogYm9vbGVhbjtcblx0cHVibGljIHNvbWU8VD4oZm46ICh0aGlzOiBULCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnOiBUKTogYm9vbGVhbjtcblx0cHVibGljIHNvbWUoZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnPzogdW5rbm93bik6IGJvb2xlYW4ge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykge1xuXHRcdFx0aWYgKGZuKHZhbCwga2V5LCB0aGlzKSkgcmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgYWxsIGl0ZW1zIHBhc3NlcyBhIHRlc3QuIElkZW50aWNhbCBpbiBiZWhhdmlvciB0b1xuXHQgKiBbQXJyYXkuZXZlcnkoKV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvZXZlcnkpLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB1c2VkIHRvIHRlc3QgKHNob3VsZCByZXR1cm4gYSBib29sZWFuKVxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLmV2ZXJ5KHVzZXIgPT4gIXVzZXIuYm90KTtcblx0ICovXG5cdHB1YmxpYyBldmVyeTxLMiBleHRlbmRzIEs+KGZuOiAodmFsdWU6IFYsIGtleTogSywgY29sbGVjdGlvbjogdGhpcykgPT4ga2V5IGlzIEsyKTogdGhpcyBpcyBDb2xsZWN0aW9uPEsyLCBWPjtcblx0cHVibGljIGV2ZXJ5PFYyIGV4dGVuZHMgVj4oZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiB2YWx1ZSBpcyBWMik6IHRoaXMgaXMgQ29sbGVjdGlvbjxLLCBWMj47XG5cdHB1YmxpYyBldmVyeShmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4pOiBib29sZWFuO1xuXHRwdWJsaWMgZXZlcnk8VGhpcywgSzIgZXh0ZW5kcyBLPihcblx0XHRmbjogKHRoaXM6IFRoaXMsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGtleSBpcyBLMixcblx0XHR0aGlzQXJnOiBUaGlzLFxuXHQpOiB0aGlzIGlzIENvbGxlY3Rpb248SzIsIFY+O1xuXHRwdWJsaWMgZXZlcnk8VGhpcywgVjIgZXh0ZW5kcyBWPihcblx0XHRmbjogKHRoaXM6IFRoaXMsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IHZhbHVlIGlzIFYyLFxuXHRcdHRoaXNBcmc6IFRoaXMsXG5cdCk6IHRoaXMgaXMgQ29sbGVjdGlvbjxLLCBWMj47XG5cdHB1YmxpYyBldmVyeTxUaGlzPihmbjogKHRoaXM6IFRoaXMsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IGJvb2xlYW4sIHRoaXNBcmc6IFRoaXMpOiBib29sZWFuO1xuXHRwdWJsaWMgZXZlcnkoZm46ICh2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBib29sZWFuLCB0aGlzQXJnPzogdW5rbm93bik6IGJvb2xlYW4ge1xuXHRcdGlmICh0eXBlb2YgdGhpc0FyZyAhPT0gJ3VuZGVmaW5lZCcpIGZuID0gZm4uYmluZCh0aGlzQXJnKTtcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykge1xuXHRcdFx0aWYgKCFmbih2YWwsIGtleSwgdGhpcykpIHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogQXBwbGllcyBhIGZ1bmN0aW9uIHRvIHByb2R1Y2UgYSBzaW5nbGUgdmFsdWUuIElkZW50aWNhbCBpbiBiZWhhdmlvciB0b1xuXHQgKiBbQXJyYXkucmVkdWNlKCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L3JlZHVjZSkuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHVzZWQgdG8gcmVkdWNlLCB0YWtpbmcgZm91ciBhcmd1bWVudHM7IGBhY2N1bXVsYXRvcmAsIGBjdXJyZW50VmFsdWVgLCBgY3VycmVudEtleWAsXG5cdCAqIGFuZCBgY29sbGVjdGlvbmBcblx0ICogQHBhcmFtIHsqfSBbaW5pdGlhbFZhbHVlXSBTdGFydGluZyB2YWx1ZSBmb3IgdGhlIGFjY3VtdWxhdG9yXG5cdCAqIEByZXR1cm5zIHsqfVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLnJlZHVjZSgoYWNjLCBndWlsZCkgPT4gYWNjICsgZ3VpbGQubWVtYmVyQ291bnQsIDApO1xuXHQgKi9cblx0cHVibGljIHJlZHVjZTxUPihmbjogKGFjY3VtdWxhdG9yOiBULCB2YWx1ZTogViwga2V5OiBLLCBjb2xsZWN0aW9uOiB0aGlzKSA9PiBULCBpbml0aWFsVmFsdWU/OiBUKTogVCB7XG5cdFx0bGV0IGFjY3VtdWxhdG9yITogVDtcblxuXHRcdGlmICh0eXBlb2YgaW5pdGlhbFZhbHVlICE9PSAndW5kZWZpbmVkJykge1xuXHRcdFx0YWNjdW11bGF0b3IgPSBpbml0aWFsVmFsdWU7XG5cdFx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgdGhpcykgYWNjdW11bGF0b3IgPSBmbihhY2N1bXVsYXRvciwgdmFsLCBrZXksIHRoaXMpO1xuXHRcdFx0cmV0dXJuIGFjY3VtdWxhdG9yO1xuXHRcdH1cblx0XHRsZXQgZmlyc3QgPSB0cnVlO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoZmlyc3QpIHtcblx0XHRcdFx0YWNjdW11bGF0b3IgPSB2YWwgYXMgdW5rbm93biBhcyBUO1xuXHRcdFx0XHRmaXJzdCA9IGZhbHNlO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdGFjY3VtdWxhdG9yID0gZm4oYWNjdW11bGF0b3IsIHZhbCwga2V5LCB0aGlzKTtcblx0XHR9XG5cblx0XHQvLyBObyBpdGVtcyBpdGVyYXRlZC5cblx0XHRpZiAoZmlyc3QpIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoJ1JlZHVjZSBvZiBlbXB0eSBjb2xsZWN0aW9uIHdpdGggbm8gaW5pdGlhbCB2YWx1ZScpO1xuXHRcdH1cblxuXHRcdHJldHVybiBhY2N1bXVsYXRvcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBJZGVudGljYWwgdG9cblx0ICogW01hcC5mb3JFYWNoKCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL01hcC9mb3JFYWNoKSxcblx0ICogYnV0IHJldHVybnMgdGhlIGNvbGxlY3Rpb24gaW5zdGVhZCBvZiB1bmRlZmluZWQuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHRvIGV4ZWN1dGUgZm9yIGVhY2ggZWxlbWVudFxuXHQgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBWYWx1ZSB0byB1c2UgYXMgYHRoaXNgIHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKiBAZXhhbXBsZVxuXHQgKiBjb2xsZWN0aW9uXG5cdCAqICAuZWFjaCh1c2VyID0+IGNvbnNvbGUubG9nKHVzZXIudXNlcm5hbWUpKVxuXHQgKiAgLmZpbHRlcih1c2VyID0+IHVzZXIuYm90KVxuXHQgKiAgLmVhY2godXNlciA9PiBjb25zb2xlLmxvZyh1c2VyLnVzZXJuYW1lKSk7XG5cdCAqL1xuXHRwdWJsaWMgZWFjaChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IHZvaWQpOiB0aGlzO1xuXHRwdWJsaWMgZWFjaDxUPihmbjogKHRoaXM6IFQsIHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IHZvaWQsIHRoaXNBcmc6IFQpOiB0aGlzO1xuXHRwdWJsaWMgZWFjaChmbjogKHZhbHVlOiBWLCBrZXk6IEssIGNvbGxlY3Rpb246IHRoaXMpID0+IHZvaWQsIHRoaXNBcmc/OiB1bmtub3duKTogdGhpcyB7XG5cdFx0dGhpcy5mb3JFYWNoKGZuIGFzICh2YWx1ZTogViwga2V5OiBLLCBtYXA6IE1hcDxLLCBWPikgPT4gdm9pZCwgdGhpc0FyZyk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogUnVucyBhIGZ1bmN0aW9uIG9uIHRoZSBjb2xsZWN0aW9uIGFuZCByZXR1cm5zIHRoZSBjb2xsZWN0aW9uLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0byBleGVjdXRlXG5cdCAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgZnVuY3Rpb25cblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqIEBleGFtcGxlXG5cdCAqIGNvbGxlY3Rpb25cblx0ICogIC50YXAoY29sbCA9PiBjb25zb2xlLmxvZyhjb2xsLnNpemUpKVxuXHQgKiAgLmZpbHRlcih1c2VyID0+IHVzZXIuYm90KVxuXHQgKiAgLnRhcChjb2xsID0+IGNvbnNvbGUubG9nKGNvbGwuc2l6ZSkpXG5cdCAqL1xuXHRwdWJsaWMgdGFwKGZuOiAoY29sbGVjdGlvbjogdGhpcykgPT4gdm9pZCk6IHRoaXM7XG5cdHB1YmxpYyB0YXA8VD4oZm46ICh0aGlzOiBULCBjb2xsZWN0aW9uOiB0aGlzKSA9PiB2b2lkLCB0aGlzQXJnOiBUKTogdGhpcztcblx0cHVibGljIHRhcChmbjogKGNvbGxlY3Rpb246IHRoaXMpID0+IHZvaWQsIHRoaXNBcmc/OiB1bmtub3duKTogdGhpcyB7XG5cdFx0aWYgKHR5cGVvZiB0aGlzQXJnICE9PSAndW5kZWZpbmVkJykgZm4gPSBmbi5iaW5kKHRoaXNBcmcpO1xuXHRcdGZuKHRoaXMpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYW4gaWRlbnRpY2FsIHNoYWxsb3cgY29weSBvZiB0aGlzIGNvbGxlY3Rpb24uXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKiBAZXhhbXBsZSBjb25zdCBuZXdDb2xsID0gc29tZUNvbGwuY2xvbmUoKTtcblx0ICovXG5cdHB1YmxpYyBjbG9uZSgpOiBDb2xsZWN0aW9uPEssIFY+IHtcblx0XHRyZXR1cm4gbmV3IHRoaXMuY29uc3RydWN0b3JbU3ltYm9sLnNwZWNpZXNdKHRoaXMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbWJpbmVzIHRoaXMgY29sbGVjdGlvbiB3aXRoIG90aGVycyBpbnRvIGEgbmV3IGNvbGxlY3Rpb24uIE5vbmUgb2YgdGhlIHNvdXJjZSBjb2xsZWN0aW9ucyBhcmUgbW9kaWZpZWQuXG5cdCAqIEBwYXJhbSB7Li4uQ29sbGVjdGlvbn0gY29sbGVjdGlvbnMgQ29sbGVjdGlvbnMgdG8gbWVyZ2Vcblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqIEBleGFtcGxlIGNvbnN0IG5ld0NvbGwgPSBzb21lQ29sbC5jb25jYXQoc29tZU90aGVyQ29sbCwgYW5vdGhlckNvbGwsIG9oQm95QUNvbGwpO1xuXHQgKi9cblx0cHVibGljIGNvbmNhdCguLi5jb2xsZWN0aW9uczogQ29sbGVjdGlvbjxLLCBWPltdKTogQ29sbGVjdGlvbjxLLCBWPiB7XG5cdFx0Y29uc3QgbmV3Q29sbCA9IHRoaXMuY2xvbmUoKTtcblx0XHRmb3IgKGNvbnN0IGNvbGwgb2YgY29sbGVjdGlvbnMpIHtcblx0XHRcdGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiBjb2xsKSBuZXdDb2xsLnNldChrZXksIHZhbCk7XG5cdFx0fVxuXHRcdHJldHVybiBuZXdDb2xsO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiB0aGlzIGNvbGxlY3Rpb24gc2hhcmVzIGlkZW50aWNhbCBpdGVtcyB3aXRoIGFub3RoZXIuXG5cdCAqIFRoaXMgaXMgZGlmZmVyZW50IHRvIGNoZWNraW5nIGZvciBlcXVhbGl0eSB1c2luZyBlcXVhbC1zaWducywgYmVjYXVzZVxuXHQgKiB0aGUgY29sbGVjdGlvbnMgbWF5IGJlIGRpZmZlcmVudCBvYmplY3RzLCBidXQgY29udGFpbiB0aGUgc2FtZSBkYXRhLlxuXHQgKiBAcGFyYW0ge0NvbGxlY3Rpb259IGNvbGxlY3Rpb24gQ29sbGVjdGlvbiB0byBjb21wYXJlIHdpdGhcblx0ICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIGNvbGxlY3Rpb25zIGhhdmUgaWRlbnRpY2FsIGNvbnRlbnRzXG5cdCAqL1xuXHRwdWJsaWMgZXF1YWxzKGNvbGxlY3Rpb246IENvbGxlY3Rpb248SywgVj4pOiBib29sZWFuIHtcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVubmVjZXNzYXJ5LWNvbmRpdGlvblxuXHRcdGlmICghY29sbGVjdGlvbikgcmV0dXJuIGZhbHNlOyAvLyBydW50aW1lIGNoZWNrXG5cdFx0aWYgKHRoaXMgPT09IGNvbGxlY3Rpb24pIHJldHVybiB0cnVlO1xuXHRcdGlmICh0aGlzLnNpemUgIT09IGNvbGxlY3Rpb24uc2l6ZSkgcmV0dXJuIGZhbHNlO1xuXHRcdGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIHRoaXMpIHtcblx0XHRcdGlmICghY29sbGVjdGlvbi5oYXMoa2V5KSB8fCB2YWx1ZSAhPT0gY29sbGVjdGlvbi5nZXQoa2V5KSkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBzb3J0IG1ldGhvZCBzb3J0cyB0aGUgaXRlbXMgb2YgYSBjb2xsZWN0aW9uIGluIHBsYWNlIGFuZCByZXR1cm5zIGl0LlxuXHQgKiBUaGUgc29ydCBpcyBub3QgbmVjZXNzYXJpbHkgc3RhYmxlIGluIE5vZGUgMTAgb3Igb2xkZXIuXG5cdCAqIFRoZSBkZWZhdWx0IHNvcnQgb3JkZXIgaXMgYWNjb3JkaW5nIHRvIHN0cmluZyBVbmljb2RlIGNvZGUgcG9pbnRzLlxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyZUZ1bmN0aW9uXSBTcGVjaWZpZXMgYSBmdW5jdGlvbiB0aGF0IGRlZmluZXMgdGhlIHNvcnQgb3JkZXIuXG5cdCAqIElmIG9taXR0ZWQsIHRoZSBjb2xsZWN0aW9uIGlzIHNvcnRlZCBhY2NvcmRpbmcgdG8gZWFjaCBjaGFyYWN0ZXIncyBVbmljb2RlIGNvZGUgcG9pbnQgdmFsdWUsXG5cdCAqIGFjY29yZGluZyB0byB0aGUgc3RyaW5nIGNvbnZlcnNpb24gb2YgZWFjaCBlbGVtZW50LlxuXHQgKiBAcmV0dXJucyB7Q29sbGVjdGlvbn1cblx0ICogQGV4YW1wbGUgY29sbGVjdGlvbi5zb3J0KCh1c2VyQSwgdXNlckIpID0+IHVzZXJBLmNyZWF0ZWRUaW1lc3RhbXAgLSB1c2VyQi5jcmVhdGVkVGltZXN0YW1wKTtcblx0ICovXG5cdHB1YmxpYyBzb3J0KGNvbXBhcmVGdW5jdGlvbjogQ29tcGFyYXRvcjxLLCBWPiA9IENvbGxlY3Rpb24uZGVmYXVsdFNvcnQpOiB0aGlzIHtcblx0XHRjb25zdCBlbnRyaWVzID0gWy4uLnRoaXMuZW50cmllcygpXTtcblx0XHRlbnRyaWVzLnNvcnQoKGEsIGIpOiBudW1iZXIgPT4gY29tcGFyZUZ1bmN0aW9uKGFbMV0sIGJbMV0sIGFbMF0sIGJbMF0pKTtcblxuXHRcdC8vIFBlcmZvcm0gY2xlYW4tdXBcblx0XHRzdXBlci5jbGVhcigpO1xuXG5cdFx0Ly8gU2V0IHRoZSBuZXcgZW50cmllc1xuXHRcdGZvciAoY29uc3QgW2ssIHZdIG9mIGVudHJpZXMpIHtcblx0XHRcdHN1cGVyLnNldChrLCB2KTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIGludGVyc2VjdCBtZXRob2QgcmV0dXJucyBhIG5ldyBzdHJ1Y3R1cmUgY29udGFpbmluZyBpdGVtcyB3aGVyZSB0aGUga2V5cyBhcmUgcHJlc2VudCBpbiBib3RoIG9yaWdpbmFsIHN0cnVjdHVyZXMuXG5cdCAqIEBwYXJhbSB7Q29sbGVjdGlvbn0gb3RoZXIgVGhlIG90aGVyIENvbGxlY3Rpb24gdG8gZmlsdGVyIGFnYWluc3Rcblx0ICogQHJldHVybnMge0NvbGxlY3Rpb259XG5cdCAqL1xuXHRwdWJsaWMgaW50ZXJzZWN0KG90aGVyOiBDb2xsZWN0aW9uPEssIFY+KTogQ29sbGVjdGlvbjxLLCBWPiB7XG5cdFx0Y29uc3QgY29sbCA9IG5ldyB0aGlzLmNvbnN0cnVjdG9yW1N5bWJvbC5zcGVjaWVzXTxLLCBWPigpO1xuXHRcdGZvciAoY29uc3QgW2ssIHZdIG9mIG90aGVyKSB7XG5cdFx0XHRpZiAodGhpcy5oYXMoaykpIGNvbGwuc2V0KGssIHYpO1xuXHRcdH1cblx0XHRyZXR1cm4gY29sbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgZGlmZmVyZW5jZSBtZXRob2QgcmV0dXJucyBhIG5ldyBzdHJ1Y3R1cmUgY29udGFpbmluZyBpdGVtcyB3aGVyZSB0aGUga2V5IGlzIHByZXNlbnQgaW4gb25lIG9mIHRoZSBvcmlnaW5hbCBzdHJ1Y3R1cmVzIGJ1dCBub3QgdGhlIG90aGVyLlxuXHQgKiBAcGFyYW0ge0NvbGxlY3Rpb259IG90aGVyIFRoZSBvdGhlciBDb2xsZWN0aW9uIHRvIGZpbHRlciBhZ2FpbnN0XG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKi9cblx0cHVibGljIGRpZmZlcmVuY2Uob3RoZXI6IENvbGxlY3Rpb248SywgVj4pOiBDb2xsZWN0aW9uPEssIFY+IHtcblx0XHRjb25zdCBjb2xsID0gbmV3IHRoaXMuY29uc3RydWN0b3JbU3ltYm9sLnNwZWNpZXNdPEssIFY+KCk7XG5cdFx0Zm9yIChjb25zdCBbaywgdl0gb2Ygb3RoZXIpIHtcblx0XHRcdGlmICghdGhpcy5oYXMoaykpIGNvbGwuc2V0KGssIHYpO1xuXHRcdH1cblx0XHRmb3IgKGNvbnN0IFtrLCB2XSBvZiB0aGlzKSB7XG5cdFx0XHRpZiAoIW90aGVyLmhhcyhrKSkgY29sbC5zZXQoaywgdik7XG5cdFx0fVxuXHRcdHJldHVybiBjb2xsO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBzb3J0ZWQgbWV0aG9kIHNvcnRzIHRoZSBpdGVtcyBvZiBhIGNvbGxlY3Rpb24gYW5kIHJldHVybnMgaXQuXG5cdCAqIFRoZSBzb3J0IGlzIG5vdCBuZWNlc3NhcmlseSBzdGFibGUgaW4gTm9kZSAxMCBvciBvbGRlci5cblx0ICogVGhlIGRlZmF1bHQgc29ydCBvcmRlciBpcyBhY2NvcmRpbmcgdG8gc3RyaW5nIFVuaWNvZGUgY29kZSBwb2ludHMuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJlRnVuY3Rpb25dIFNwZWNpZmllcyBhIGZ1bmN0aW9uIHRoYXQgZGVmaW5lcyB0aGUgc29ydCBvcmRlci5cblx0ICogSWYgb21pdHRlZCwgdGhlIGNvbGxlY3Rpb24gaXMgc29ydGVkIGFjY29yZGluZyB0byBlYWNoIGNoYXJhY3RlcidzIFVuaWNvZGUgY29kZSBwb2ludCB2YWx1ZSxcblx0ICogYWNjb3JkaW5nIHRvIHRoZSBzdHJpbmcgY29udmVyc2lvbiBvZiBlYWNoIGVsZW1lbnQuXG5cdCAqIEByZXR1cm5zIHtDb2xsZWN0aW9ufVxuXHQgKiBAZXhhbXBsZSBjb2xsZWN0aW9uLnNvcnRlZCgodXNlckEsIHVzZXJCKSA9PiB1c2VyQS5jcmVhdGVkVGltZXN0YW1wIC0gdXNlckIuY3JlYXRlZFRpbWVzdGFtcCk7XG5cdCAqL1xuXHRwdWJsaWMgc29ydGVkKGNvbXBhcmVGdW5jdGlvbjogQ29tcGFyYXRvcjxLLCBWPiA9IENvbGxlY3Rpb24uZGVmYXVsdFNvcnQpOiBDb2xsZWN0aW9uPEssIFY+IHtcblx0XHRyZXR1cm4gbmV3IHRoaXMuY29uc3RydWN0b3JbU3ltYm9sLnNwZWNpZXNdKHRoaXMpLnNvcnQoKGF2LCBidiwgYWssIGJrKSA9PiBjb21wYXJlRnVuY3Rpb24oYXYsIGJ2LCBhaywgYmspKTtcblx0fVxuXG5cdHB1YmxpYyB0b0pTT04oKSB7XG5cdFx0Ly8gdG9KU09OIGlzIGNhbGxlZCByZWN1cnNpdmVseSBieSBKU09OLnN0cmluZ2lmeS5cblx0XHRyZXR1cm4gWy4uLnRoaXMudmFsdWVzKCldO1xuXHR9XG5cblx0cHJpdmF0ZSBzdGF0aWMgZGVmYXVsdFNvcnQ8Vj4oZmlyc3RWYWx1ZTogViwgc2Vjb25kVmFsdWU6IFYpOiBudW1iZXIge1xuXHRcdHJldHVybiBOdW1iZXIoZmlyc3RWYWx1ZSA+IHNlY29uZFZhbHVlKSB8fCBOdW1iZXIoZmlyc3RWYWx1ZSA9PT0gc2Vjb25kVmFsdWUpIC0gMTtcblx0fVxufVxuXG5leHBvcnQgdHlwZSBDb21wYXJhdG9yPEssIFY+ID0gKGZpcnN0VmFsdWU6IFYsIHNlY29uZFZhbHVlOiBWLCBmaXJzdEtleTogSywgc2Vjb25kS2V5OiBLKSA9PiBudW1iZXI7XG5cbmV4cG9ydCBkZWZhdWx0IENvbGxlY3Rpb247XG4iXX0= \ No newline at end of file diff --git a/node_modules/@discordjs/collection/package.json b/node_modules/@discordjs/collection/package.json index ebb48988..f1151bb8 100644 --- a/node_modules/@discordjs/collection/package.json +++ b/node_modules/@discordjs/collection/package.json @@ -1,49 +1,105 @@ { - "name": "@discordjs/collection", - "version": "0.1.6", - "description": "Utility data structure used in Discord.js", - "main": "dist/index.js", - "types": "dist/index.d.ts", - "scripts": { - "lint": "eslint src --ext .ts", - "prebuild": "npm run lint", - "build": "rimraf dist/ && tsc", - "pretest": "npm run build", - "test": "node test/index.js", - "docs": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml --output docs/docs.json", - "docs:test": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/discordjs/collection.git" - }, - "keywords": [ - "map", - "collection", - "utility" - ], - "author": "Amish Shah ", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/discordjs/collection/issues" - }, - "homepage": "https://github.com/discordjs/collection#readme", - "devDependencies": { - "@babel/cli": "^7.8.4", - "@babel/core": "^7.8.4", - "@babel/preset-env": "^7.8.4", - "@babel/preset-typescript": "^7.8.3", - "@types/node": "^13.7.4", - "@typescript-eslint/eslint-plugin": "^2.21.0", - "@typescript-eslint/parser": "^2.21.0", - "discord.js-docgen": "discordjs/docgen#ts-patch", - "eslint": "^6.8.0", - "eslint-config-marine": "^6.0.0", - "jsdoc-babel": "^0.5.0", - "rimraf": "^3.0.2", - "typescript": "^3.8.2" - }, - "eslintConfig": { - "extends": "marine/node" - } + "name": "@discordjs/collection", + "version": "0.2.1", + "description": "Utility data structure used in Discord.js", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "lint": "eslint test src --ext .ts", + "lint:fix": "eslint test src --ext .ts --fix", + "prebuild": "npm run lint", + "build": "rimraf dist/ && tsc", + "pretest": "npm run build", + "test": "jest", + "docs": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml --output docs/docs.json", + "docs:test": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/discordjs/collection.git" + }, + "keywords": [ + "map", + "collection", + "utility" + ], + "files": [ + "!**/*.ts", + "**/*.d.ts", + "!package-lock.json" + ], + "author": "Amish Shah ", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/discordjs/collection/issues" + }, + "homepage": "https://github.com/discordjs/collection#readme", + "engines": { + "node": ">=14.0.0" + }, + "devDependencies": { + "@babel/cli": "^7.14.8", + "@babel/core": "^7.14.8", + "@babel/preset-env": "^7.14.8", + "@babel/preset-typescript": "^7.14.5", + "@commitlint/cli": "^13.1.0", + "@commitlint/config-angular": "^13.1.0", + "@types/jest": "^26.0.24", + "@types/node": "^16.4.8", + "@typescript-eslint/eslint-plugin": "^4.28.5", + "@typescript-eslint/parser": "^4.28.5", + "discord.js-docgen": "discordjs/docgen#ts-patch", + "eslint": "^7.32.0", + "eslint-config-marine": "^9.0.6", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^3.4.0", + "husky": "^4.3.7", + "jest": "^27.0.6", + "jsdoc-babel": "^0.5.0", + "lint-staged": "^11.1.1", + "prettier": "^2.3.2", + "rimraf": "^3.0.2", + "typescript": "^4.3.5" + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged", + "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" + } + }, + "lint-staged": { + "*.{ts,js}": [ + "eslint --fix" + ], + "*.{json,yml,yaml}": [ + "prettier --write" + ] + }, + "commitlint": { + "extends": [ + "@commitlint/config-angular" + ], + "rules": { + "type-enum": [ + 2, + "always", + [ + "chore", + "build", + "ci", + "docs", + "feat", + "fix", + "perf", + "refactor", + "revert", + "style", + "test", + "types", + "wip", + "src" + ] + ] + } + } } diff --git a/node_modules/bcryptjs/.npmignore b/node_modules/bcryptjs/.npmignore deleted file mode 100644 index e14a5749..00000000 --- a/node_modules/bcryptjs/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules/ -npm-debug.log -debug.log -doco/ -tests/bench.js -*.png diff --git a/node_modules/bcryptjs/.travis.yml b/node_modules/bcryptjs/.travis.yml deleted file mode 100644 index e2ed92d6..00000000 --- a/node_modules/bcryptjs/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: node_js - -node_js: - - 0.10 - - 0.12 - - 4 - - 6 - -before_script: npm -g install testjs - -env: - - CXX=g++-4.8 -addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-4.8 diff --git a/node_modules/bcryptjs/.vscode/settings.json b/node_modules/bcryptjs/.vscode/settings.json deleted file mode 100644 index 0c4a6693..00000000 --- a/node_modules/bcryptjs/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "vsicons.presets.angular": false -} \ No newline at end of file diff --git a/node_modules/bcryptjs/LICENSE b/node_modules/bcryptjs/LICENSE deleted file mode 100644 index 3f6395fa..00000000 --- a/node_modules/bcryptjs/LICENSE +++ /dev/null @@ -1,50 +0,0 @@ -bcrypt.js ---------- -Copyright (c) 2012 Nevins Bartolomeo -Copyright (c) 2012 Shane Girish -Copyright (c) 2014 Daniel Wirtz - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -isaac.js --------- -Copyright (c) 2012 Yves-Marie K. Rinquin - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/bcryptjs/README.md b/node_modules/bcryptjs/README.md deleted file mode 100644 index 3fd75170..00000000 --- a/node_modules/bcryptjs/README.md +++ /dev/null @@ -1,251 +0,0 @@ -bcrypt.js -========= -Optimized bcrypt in JavaScript with zero dependencies. Compatible to the C++ [bcrypt](https://npmjs.org/package/bcrypt) -binding on node.js and also working in the browser. - -build static donate ❀ - - -Security considerations ------------------------ -Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the -iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with -increasing computation power. ([see](http://en.wikipedia.org/wiki/Bcrypt)) - -While bcrypt.js is compatible to the C++ bcrypt binding, it is written in pure JavaScript and thus slower ([about 30%](https://github.com/dcodeIO/bcrypt.js/wiki/Benchmark)), effectively reducing the number of iterations that can be -processed in an equal time span. - -The maximum input length is 72 bytes (note that UTF8 encoded characters use up to 4 bytes) and the length of generated -hashes is 60 characters. - -Usage ------ -The library is compatible with CommonJS and AMD loaders and is exposed globally as `dcodeIO.bcrypt` if neither is -available. - -### node.js - -On node.js, the inbuilt [crypto module](http://nodejs.org/api/crypto.html)'s randomBytes interface is used to obtain -secure random numbers. - -`npm install bcryptjs` - -```js -var bcrypt = require('bcryptjs'); -... -``` - -### Browser - -In the browser, bcrypt.js relies on [Web Crypto API](http://www.w3.org/TR/WebCryptoAPI)'s getRandomValues -interface to obtain secure random numbers. If no cryptographically secure source of randomness is available, you may -specify one through [bcrypt.setRandomFallback](https://github.com/dcodeIO/bcrypt.js#setrandomfallbackrandom). - -```js -var bcrypt = dcodeIO.bcrypt; -... -``` - -or - -```js -require.config({ - paths: { "bcrypt": "/path/to/bcrypt.js" } -}); -require(["bcrypt"], function(bcrypt) { - ... -}); -``` - -Usage - Sync ------------- -To hash a password: - -```javascript -var bcrypt = require('bcryptjs'); -var salt = bcrypt.genSaltSync(10); -var hash = bcrypt.hashSync("B4c0/\/", salt); -// Store hash in your password DB. -``` - -To check a password: - -```javascript -// Load hash from your password DB. -bcrypt.compareSync("B4c0/\/", hash); // true -bcrypt.compareSync("not_bacon", hash); // false -``` - -Auto-gen a salt and hash: - -```javascript -var hash = bcrypt.hashSync('bacon', 8); -``` - -Usage - Async -------------- -To hash a password: - -```javascript -var bcrypt = require('bcryptjs'); -bcrypt.genSalt(10, function(err, salt) { - bcrypt.hash("B4c0/\/", salt, function(err, hash) { - // Store hash in your password DB. - }); -}); -``` - -To check a password: - -```javascript -// Load hash from your password DB. -bcrypt.compare("B4c0/\/", hash, function(err, res) { - // res === true -}); -bcrypt.compare("not_bacon", hash, function(err, res) { - // res === false -}); - -// As of bcryptjs 2.4.0, compare returns a promise if callback is omitted: -bcrypt.compare("B4c0/\/", hash).then((res) => { - // res === true -}); -``` - -Auto-gen a salt and hash: - -```javascript -bcrypt.hash('bacon', 8, function(err, hash) { -}); -``` - -**Note:** Under the hood, asynchronisation splits a crypto operation into small chunks. After the completion of a chunk, the execution of the next chunk is placed on the back of [JS event loop queue](https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop), thus efficiently sharing the computational resources with the other operations in the queue. - -API ---- -### setRandomFallback(random) - -Sets the pseudo random number generator to use as a fallback if neither node's `crypto` module nor the Web Crypto -API is available. Please note: It is highly important that the PRNG used is cryptographically secure and that it is -seeded properly! - -| Parameter | Type | Description -|-----------------|-----------------|--------------- -| random | *function(number):!Array.<number>* | Function taking the number of bytes to generate as its sole argument, returning the corresponding array of cryptographically secure random byte values. -| **@see** | | http://nodejs.org/api/crypto.html -| **@see** | | http://www.w3.org/TR/WebCryptoAPI/ - -**Hint:** You might use [isaac.js](https://github.com/rubycon/isaac.js) as a CSPRNG but you still have to make sure to -seed it properly. - -### genSaltSync(rounds=, seed_length=) - -Synchronously generates a salt. - -| Parameter | Type | Description -|-----------------|-----------------|--------------- -| rounds | *number* | Number of rounds to use, defaults to 10 if omitted -| seed_length | *number* | Not supported. -| **@returns** | *string* | Resulting salt -| **@throws** | *Error* | If a random fallback is required but not set - -### genSalt(rounds=, seed_length=, callback) - -Asynchronously generates a salt. - -| Parameter | Type | Description -|-----------------|-----------------|--------------- -| rounds | *number | function(Error, string=)* | Number of rounds to use, defaults to 10 if omitted -| seed_length | *number | function(Error, string=)* | Not supported. -| callback | *function(Error, string=)* | Callback receiving the error, if any, and the resulting salt -| **@returns** | *Promise* | If `callback` has been omitted -| **@throws** | *Error* | If `callback` is present but not a function - -### hashSync(s, salt=) - -Synchronously generates a hash for the given string. - -| Parameter | Type | Description -|-----------------|-----------------|--------------- -| s | *string* | String to hash -| salt | *number | string* | Salt length to generate or salt to use, default to 10 -| **@returns** | *string* | Resulting hash - -### hash(s, salt, callback, progressCallback=) - -Asynchronously generates a hash for the given string. - -| Parameter | Type | Description -|-----------------|-----------------|--------------- -| s | *string* | String to hash -| salt | *number | string* | Salt length to generate or salt to use -| callback | *function(Error, string=)* | Callback receiving the error, if any, and the resulting hash -| progressCallback | *function(number)* | Callback successively called with the percentage of rounds completed (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms. -| **@returns** | *Promise* | If `callback` has been omitted -| **@throws** | *Error* | If `callback` is present but not a function - -### compareSync(s, hash) - -Synchronously tests a string against a hash. - -| Parameter | Type | Description -|-----------------|-----------------|--------------- -| s | *string* | String to compare -| hash | *string* | Hash to test against -| **@returns** | *boolean* | true if matching, otherwise false -| **@throws** | *Error* | If an argument is illegal - -### compare(s, hash, callback, progressCallback=) - -Asynchronously compares the given data against the given hash. - -| Parameter | Type | Description -|-----------------|-----------------|--------------- -| s | *string* | Data to compare -| hash | *string* | Data to be compared to -| callback | *function(Error, boolean)* | Callback receiving the error, if any, otherwise the result -| progressCallback | *function(number)* | Callback successively called with the percentage of rounds completed (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms. -| **@returns** | *Promise* | If `callback` has been omitted -| **@throws** | *Error* | If `callback` is present but not a function - -### getRounds(hash) - -Gets the number of rounds used to encrypt the specified hash. - -| Parameter | Type | Description -|-----------------|-----------------|--------------- -| hash | *string* | Hash to extract the used number of rounds from -| **@returns** | *number* | Number of rounds used -| **@throws** | *Error* | If `hash` is not a string - -### getSalt(hash) - -Gets the salt portion from a hash. Does not validate the hash. - -| Parameter | Type | Description -|-----------------|-----------------|--------------- -| hash | *string* | Hash to extract the salt from -| **@returns** | *string* | Extracted salt part -| **@throws** | *Error* | If `hash` is not a string or otherwise invalid - - -Command line ------------- -`Usage: bcrypt [salt]` - -If the input has spaces inside, simply surround it with quotes. - -Downloads ---------- -* [Distributions](https://github.com/dcodeIO/bcrypt.js/tree/master/dist) -* [ZIP-Archive](https://github.com/dcodeIO/bcrypt.js/archive/master.zip) -* [Tarball](https://github.com/dcodeIO/bcrypt.js/tarball/master) - -Credits -------- -Based on work started by Shane Girish at [bcrypt-nodejs](https://github.com/shaneGirish/bcrypt-nodejs) (MIT-licensed), -which is itself based on [javascript-bcrypt](http://code.google.com/p/javascript-bcrypt/) (New BSD-licensed). - -License -------- -New-BSD / MIT ([see](https://github.com/dcodeIO/bcrypt.js/blob/master/LICENSE)) diff --git a/node_modules/bcryptjs/bin/bcrypt b/node_modules/bcryptjs/bin/bcrypt deleted file mode 100644 index 4cfc9d90..00000000 --- a/node_modules/bcryptjs/bin/bcrypt +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env node - -var path = require("path"), - bcrypt = require(path.join(__dirname, '..', 'index.js')), - pkg = require(path.join(__dirname, '..', 'package.json')); - -if (process.argv.length < 3) { - process.stderr.write([ // No dependencies, so we do it from hand. - "", - " |_ _ _ _ |_", - " |_)(_| \\/|_)|_ v"+pkg['version']+" (c) "+pkg['author'], - " / | " - ].join('\n')+'\n\n'+" Usage: "+path.basename(process.argv[1])+" [rounds|salt]\n"); - process.exit(1); -} else { - var salt; - if (process.argv.length > 3) { - salt = process.argv[3]; - var rounds = parseInt(salt, 10); - if (rounds == salt) - salt = bcrypt.genSaltSync(rounds); - } else - salt = bcrypt.genSaltSync(); - process.stdout.write(bcrypt.hashSync(process.argv[2], salt)+"\n"); -} diff --git a/node_modules/bcryptjs/bower.json b/node_modules/bcryptjs/bower.json deleted file mode 100644 index c1524053..00000000 --- a/node_modules/bcryptjs/bower.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "bcryptjs", - "description": "Optimized bcrypt in plain JavaScript with zero dependencies.", - "version": "2.4.3", - "main": "dist/bcrypt.min.js", - "license": "New-BSD", - "homepage": "http://dcode.io/", - "repository": { - "type": "git", - "url": "git://github.com/dcodeIO/bcrypt.js.git" - }, - "keywords": ["bcrypt", "password", "auth", "authentication", "encryption", "crypt", "crypto"], - "dependencies": {}, - "devDependencies": {}, - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ] -} diff --git a/node_modules/bcryptjs/dist/README.md b/node_modules/bcryptjs/dist/README.md deleted file mode 100644 index 4020f456..00000000 --- a/node_modules/bcryptjs/dist/README.md +++ /dev/null @@ -1,15 +0,0 @@ -Distributions -============= -bcrypt.js is available as the following distributions: - -* **[bcrypt.js](https://github.com/dcodeIO/bcrypt.js/blob/master/dist/bcrypt.js)** - contains the commented source code. - -* **[bcrypt.min.js](https://github.com/dcodeIO/bcrypt.js/blob/master/dist/bcrypt.min.js)** - has been compiled with Closure Compiler using advanced optimizations. - -* **[bcrypt.min.map](https://github.com/dcodeIO/bcrypt.js/blob/master/dist/bcrypt.min.map)** - contains the source map generated by Closure Compiler. - -* **[bcrypt.min.js.gz](https://github.com/dcodeIO/bcrypt.js/blob/master/dist/bcrypt.min.js.gz)** - has also been gzipped using `-9`. diff --git a/node_modules/bcryptjs/dist/bcrypt.js b/node_modules/bcryptjs/dist/bcrypt.js deleted file mode 100644 index a50dbeeb..00000000 --- a/node_modules/bcryptjs/dist/bcrypt.js +++ /dev/null @@ -1,1379 +0,0 @@ -/* - Copyright (c) 2012 Nevins Bartolomeo - Copyright (c) 2012 Shane Girish - Copyright (c) 2014 Daniel Wirtz - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @license bcrypt.js (c) 2013 Daniel Wirtz - * Released under the Apache License, Version 2.0 - * see: https://github.com/dcodeIO/bcrypt.js for details - */ -(function(global, factory) { - - /* AMD */ if (typeof define === 'function' && define["amd"]) - define([], factory); - /* CommonJS */ else if (typeof require === 'function' && typeof module === "object" && module && module["exports"]) - module["exports"] = factory(); - /* Global */ else - (global["dcodeIO"] = global["dcodeIO"] || {})["bcrypt"] = factory(); - -}(this, function() { - "use strict"; - - /** - * bcrypt namespace. - * @type {Object.} - */ - var bcrypt = {}; - - /** - * The random implementation to use as a fallback. - * @type {?function(number):!Array.} - * @inner - */ - var randomFallback = null; - - /** - * Generates cryptographically secure random bytes. - * @function - * @param {number} len Bytes length - * @returns {!Array.} Random bytes - * @throws {Error} If no random implementation is available - * @inner - */ - function random(len) { - /* node */ if (typeof module !== 'undefined' && module && module['exports']) - try { - return require("crypto")['randomBytes'](len); - } catch (e) {} - /* WCA */ try { - var a; (self['crypto']||self['msCrypto'])['getRandomValues'](a = new Uint32Array(len)); - return Array.prototype.slice.call(a); - } catch (e) {} - /* fallback */ if (!randomFallback) - throw Error("Neither WebCryptoAPI nor a crypto module is available. Use bcrypt.setRandomFallback to set an alternative"); - return randomFallback(len); - } - - // Test if any secure randomness source is available - var randomAvailable = false; - try { - random(1); - randomAvailable = true; - } catch (e) {} - - // Default fallback, if any - randomFallback = null; - /** - * Sets the pseudo random number generator to use as a fallback if neither node's `crypto` module nor the Web Crypto - * API is available. Please note: It is highly important that the PRNG used is cryptographically secure and that it - * is seeded properly! - * @param {?function(number):!Array.} random Function taking the number of bytes to generate as its - * sole argument, returning the corresponding array of cryptographically secure random byte values. - * @see http://nodejs.org/api/crypto.html - * @see http://www.w3.org/TR/WebCryptoAPI/ - */ - bcrypt.setRandomFallback = function(random) { - randomFallback = random; - }; - - /** - * Synchronously generates a salt. - * @param {number=} rounds Number of rounds to use, defaults to 10 if omitted - * @param {number=} seed_length Not supported. - * @returns {string} Resulting salt - * @throws {Error} If a random fallback is required but not set - * @expose - */ - bcrypt.genSaltSync = function(rounds, seed_length) { - rounds = rounds || GENSALT_DEFAULT_LOG2_ROUNDS; - if (typeof rounds !== 'number') - throw Error("Illegal arguments: "+(typeof rounds)+", "+(typeof seed_length)); - if (rounds < 4) - rounds = 4; - else if (rounds > 31) - rounds = 31; - var salt = []; - salt.push("$2a$"); - if (rounds < 10) - salt.push("0"); - salt.push(rounds.toString()); - salt.push('$'); - salt.push(base64_encode(random(BCRYPT_SALT_LEN), BCRYPT_SALT_LEN)); // May throw - return salt.join(''); - }; - - /** - * Asynchronously generates a salt. - * @param {(number|function(Error, string=))=} rounds Number of rounds to use, defaults to 10 if omitted - * @param {(number|function(Error, string=))=} seed_length Not supported. - * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting salt - * @returns {!Promise} If `callback` has been omitted - * @throws {Error} If `callback` is present but not a function - * @expose - */ - bcrypt.genSalt = function(rounds, seed_length, callback) { - if (typeof seed_length === 'function') - callback = seed_length, - seed_length = undefined; // Not supported. - if (typeof rounds === 'function') - callback = rounds, - rounds = undefined; - if (typeof rounds === 'undefined') - rounds = GENSALT_DEFAULT_LOG2_ROUNDS; - else if (typeof rounds !== 'number') - throw Error("illegal arguments: "+(typeof rounds)); - - function _async(callback) { - nextTick(function() { // Pretty thin, but salting is fast enough - try { - callback(null, bcrypt.genSaltSync(rounds)); - } catch (err) { - callback(err); - } - }); - } - - if (callback) { - if (typeof callback !== 'function') - throw Error("Illegal callback: "+typeof(callback)); - _async(callback); - } else - return new Promise(function(resolve, reject) { - _async(function(err, res) { - if (err) { - reject(err); - return; - } - resolve(res); - }); - }); - }; - - /** - * Synchronously generates a hash for the given string. - * @param {string} s String to hash - * @param {(number|string)=} salt Salt length to generate or salt to use, default to 10 - * @returns {string} Resulting hash - * @expose - */ - bcrypt.hashSync = function(s, salt) { - if (typeof salt === 'undefined') - salt = GENSALT_DEFAULT_LOG2_ROUNDS; - if (typeof salt === 'number') - salt = bcrypt.genSaltSync(salt); - if (typeof s !== 'string' || typeof salt !== 'string') - throw Error("Illegal arguments: "+(typeof s)+', '+(typeof salt)); - return _hash(s, salt); - }; - - /** - * Asynchronously generates a hash for the given string. - * @param {string} s String to hash - * @param {number|string} salt Salt length to generate or salt to use - * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting hash - * @param {function(number)=} progressCallback Callback successively called with the percentage of rounds completed - * (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms. - * @returns {!Promise} If `callback` has been omitted - * @throws {Error} If `callback` is present but not a function - * @expose - */ - bcrypt.hash = function(s, salt, callback, progressCallback) { - - function _async(callback) { - if (typeof s === 'string' && typeof salt === 'number') - bcrypt.genSalt(salt, function(err, salt) { - _hash(s, salt, callback, progressCallback); - }); - else if (typeof s === 'string' && typeof salt === 'string') - _hash(s, salt, callback, progressCallback); - else - nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof salt)))); - } - - if (callback) { - if (typeof callback !== 'function') - throw Error("Illegal callback: "+typeof(callback)); - _async(callback); - } else - return new Promise(function(resolve, reject) { - _async(function(err, res) { - if (err) { - reject(err); - return; - } - resolve(res); - }); - }); - }; - - /** - * Compares two strings of the same length in constant time. - * @param {string} known Must be of the correct length - * @param {string} unknown Must be the same length as `known` - * @returns {boolean} - * @inner - */ - function safeStringCompare(known, unknown) { - var right = 0, - wrong = 0; - for (var i=0, k=known.length; i} UTF8 bytes - * @inner - */ - function stringToBytes(str) { - var out = [], - i = 0; - utfx.encodeUTF16toUTF8(function() { - if (i >= str.length) return null; - return str.charCodeAt(i++); - }, function(b) { - out.push(b); - }); - return out; - } - - // A base64 implementation for the bcrypt algorithm. This is partly non-standard. - - /** - * bcrypt's own non-standard base64 dictionary. - * @type {!Array.} - * @const - * @inner - **/ - var BASE64_CODE = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(''); - - /** - * @type {!Array.} - * @const - * @inner - **/ - var BASE64_INDEX = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, - 1, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, - -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1]; - - /** - * @type {!function(...number):string} - * @inner - */ - var stringFromCharCode = String.fromCharCode; - - /** - * Encodes a byte array to base64 with up to len bytes of input. - * @param {!Array.} b Byte array - * @param {number} len Maximum input length - * @returns {string} - * @inner - */ - function base64_encode(b, len) { - var off = 0, - rs = [], - c1, c2; - if (len <= 0 || len > b.length) - throw Error("Illegal len: "+len); - while (off < len) { - c1 = b[off++] & 0xff; - rs.push(BASE64_CODE[(c1 >> 2) & 0x3f]); - c1 = (c1 & 0x03) << 4; - if (off >= len) { - rs.push(BASE64_CODE[c1 & 0x3f]); - break; - } - c2 = b[off++] & 0xff; - c1 |= (c2 >> 4) & 0x0f; - rs.push(BASE64_CODE[c1 & 0x3f]); - c1 = (c2 & 0x0f) << 2; - if (off >= len) { - rs.push(BASE64_CODE[c1 & 0x3f]); - break; - } - c2 = b[off++] & 0xff; - c1 |= (c2 >> 6) & 0x03; - rs.push(BASE64_CODE[c1 & 0x3f]); - rs.push(BASE64_CODE[c2 & 0x3f]); - } - return rs.join(''); - } - - /** - * Decodes a base64 encoded string to up to len bytes of output. - * @param {string} s String to decode - * @param {number} len Maximum output length - * @returns {!Array.} - * @inner - */ - function base64_decode(s, len) { - var off = 0, - slen = s.length, - olen = 0, - rs = [], - c1, c2, c3, c4, o, code; - if (len <= 0) - throw Error("Illegal len: "+len); - while (off < slen - 1 && olen < len) { - code = s.charCodeAt(off++); - c1 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; - code = s.charCodeAt(off++); - c2 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; - if (c1 == -1 || c2 == -1) - break; - o = (c1 << 2) >>> 0; - o |= (c2 & 0x30) >> 4; - rs.push(stringFromCharCode(o)); - if (++olen >= len || off >= slen) - break; - code = s.charCodeAt(off++); - c3 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; - if (c3 == -1) - break; - o = ((c2 & 0x0f) << 4) >>> 0; - o |= (c3 & 0x3c) >> 2; - rs.push(stringFromCharCode(o)); - if (++olen >= len || off >= slen) - break; - code = s.charCodeAt(off++); - c4 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; - o = ((c3 & 0x03) << 6) >>> 0; - o |= c4; - rs.push(stringFromCharCode(o)); - ++olen; - } - var res = []; - for (off = 0; off - * Released under the Apache License, Version 2.0 - * see: https://github.com/dcodeIO/utfx for details - */ - var utfx = function() { - "use strict"; - - /** - * utfx namespace. - * @inner - * @type {!Object.} - */ - var utfx = {}; - - /** - * Maximum valid code point. - * @type {number} - * @const - */ - utfx.MAX_CODEPOINT = 0x10FFFF; - - /** - * Encodes UTF8 code points to UTF8 bytes. - * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point - * respectively `null` if there are no more code points left or a single numeric code point. - * @param {!function(number)} dst Bytes destination as a function successively called with the next byte - */ - utfx.encodeUTF8 = function(src, dst) { - var cp = null; - if (typeof src === 'number') - cp = src, - src = function() { return null; }; - while (cp !== null || (cp = src()) !== null) { - if (cp < 0x80) - dst(cp&0x7F); - else if (cp < 0x800) - dst(((cp>>6)&0x1F)|0xC0), - dst((cp&0x3F)|0x80); - else if (cp < 0x10000) - dst(((cp>>12)&0x0F)|0xE0), - dst(((cp>>6)&0x3F)|0x80), - dst((cp&0x3F)|0x80); - else - dst(((cp>>18)&0x07)|0xF0), - dst(((cp>>12)&0x3F)|0x80), - dst(((cp>>6)&0x3F)|0x80), - dst((cp&0x3F)|0x80); - cp = null; - } - }; - - /** - * Decodes UTF8 bytes to UTF8 code points. - * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there - * are no more bytes left. - * @param {!function(number)} dst Code points destination as a function successively called with each decoded code point. - * @throws {RangeError} If a starting byte is invalid in UTF8 - * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the - * remaining bytes. - */ - utfx.decodeUTF8 = function(src, dst) { - var a, b, c, d, fail = function(b) { - b = b.slice(0, b.indexOf(null)); - var err = Error(b.toString()); - err.name = "TruncatedError"; - err['bytes'] = b; - throw err; - }; - while ((a = src()) !== null) { - if ((a&0x80) === 0) - dst(a); - else if ((a&0xE0) === 0xC0) - ((b = src()) === null) && fail([a, b]), - dst(((a&0x1F)<<6) | (b&0x3F)); - else if ((a&0xF0) === 0xE0) - ((b=src()) === null || (c=src()) === null) && fail([a, b, c]), - dst(((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F)); - else if ((a&0xF8) === 0xF0) - ((b=src()) === null || (c=src()) === null || (d=src()) === null) && fail([a, b, c ,d]), - dst(((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F)); - else throw RangeError("Illegal starting byte: "+a); - } - }; - - /** - * Converts UTF16 characters to UTF8 code points. - * @param {!function():number|null} src Characters source as a function returning the next char code respectively - * `null` if there are no more characters left. - * @param {!function(number)} dst Code points destination as a function successively called with each converted code - * point. - */ - utfx.UTF16toUTF8 = function(src, dst) { - var c1, c2 = null; - while (true) { - if ((c1 = c2 !== null ? c2 : src()) === null) - break; - if (c1 >= 0xD800 && c1 <= 0xDFFF) { - if ((c2 = src()) !== null) { - if (c2 >= 0xDC00 && c2 <= 0xDFFF) { - dst((c1-0xD800)*0x400+c2-0xDC00+0x10000); - c2 = null; continue; - } - } - } - dst(c1); - } - if (c2 !== null) dst(c2); - }; - - /** - * Converts UTF8 code points to UTF16 characters. - * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point - * respectively `null` if there are no more code points left or a single numeric code point. - * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. - * @throws {RangeError} If a code point is out of range - */ - utfx.UTF8toUTF16 = function(src, dst) { - var cp = null; - if (typeof src === 'number') - cp = src, src = function() { return null; }; - while (cp !== null || (cp = src()) !== null) { - if (cp <= 0xFFFF) - dst(cp); - else - cp -= 0x10000, - dst((cp>>10)+0xD800), - dst((cp%0x400)+0xDC00); - cp = null; - } - }; - - /** - * Converts and encodes UTF16 characters to UTF8 bytes. - * @param {!function():number|null} src Characters source as a function returning the next char code respectively `null` - * if there are no more characters left. - * @param {!function(number)} dst Bytes destination as a function successively called with the next byte. - */ - utfx.encodeUTF16toUTF8 = function(src, dst) { - utfx.UTF16toUTF8(src, function(cp) { - utfx.encodeUTF8(cp, dst); - }); - }; - - /** - * Decodes and converts UTF8 bytes to UTF16 characters. - * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there - * are no more bytes left. - * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. - * @throws {RangeError} If a starting byte is invalid in UTF8 - * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the remaining bytes. - */ - utfx.decodeUTF8toUTF16 = function(src, dst) { - utfx.decodeUTF8(src, function(cp) { - utfx.UTF8toUTF16(cp, dst); - }); - }; - - /** - * Calculates the byte length of an UTF8 code point. - * @param {number} cp UTF8 code point - * @returns {number} Byte length - */ - utfx.calculateCodePoint = function(cp) { - return (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; - }; - - /** - * Calculates the number of UTF8 bytes required to store UTF8 code points. - * @param {(!function():number|null)} src Code points source as a function returning the next code point respectively - * `null` if there are no more code points left. - * @returns {number} The number of UTF8 bytes required - */ - utfx.calculateUTF8 = function(src) { - var cp, l=0; - while ((cp = src()) !== null) - l += utfx.calculateCodePoint(cp); - return l; - }; - - /** - * Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes. - * @param {(!function():number|null)} src Characters source as a function returning the next char code respectively - * `null` if there are no more characters left. - * @returns {!Array.} The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1. - */ - utfx.calculateUTF16asUTF8 = function(src) { - var n=0, l=0; - utfx.UTF16toUTF8(src, function(cp) { - ++n; l += utfx.calculateCodePoint(cp); - }); - return [n,l]; - }; - - return utfx; - }(); - - Date.now = Date.now || function() { return +new Date; }; - - /** - * @type {number} - * @const - * @inner - */ - var BCRYPT_SALT_LEN = 16; - - /** - * @type {number} - * @const - * @inner - */ - var GENSALT_DEFAULT_LOG2_ROUNDS = 10; - - /** - * @type {number} - * @const - * @inner - */ - var BLOWFISH_NUM_ROUNDS = 16; - - /** - * @type {number} - * @const - * @inner - */ - var MAX_EXECUTION_TIME = 100; - - /** - * @type {Array.} - * @const - * @inner - */ - var P_ORIG = [ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, - 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, - 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, - 0xb5470917, 0x9216d5d9, 0x8979fb1b - ]; - - /** - * @type {Array.} - * @const - * @inner - */ - var S_ORIG = [ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, - 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, - 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, - 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, - 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, - 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, - 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, - 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, - 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, - 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, - 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, - 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, - 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, - 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, - 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, - 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, - 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, - 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, - 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, - 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, - 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, - 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, - 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, - 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, - 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, - 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, - 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, - 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, - 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, - 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, - 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, - 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, - 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, - 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, - 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, - 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, - 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, - 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, - 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, - 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, - 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, - 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, - 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, - 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, - 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, - 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, - 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, - 0x6e85076a, 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, - 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, - 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, - 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, - 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, - 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, - 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, - 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, - 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, - 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, - 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, - 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, - 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, - 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, - 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, - 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, - 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, - 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, - 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, - 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, - 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, - 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, - 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, - 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, - 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, - 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, - 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, - 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, - 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, - 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, - 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, - 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, - 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, - 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, - 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, - 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, - 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, - 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, - 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, - 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, - 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, - 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, - 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, - 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, - 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, - 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, - 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, - 0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7, 0xf64c261c, - 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, - 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, - 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, - 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, - 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, - 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, - 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, - 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, - 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, - 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, - 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, - 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, - 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, - 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, - 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, - 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, - 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, - 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, - 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, - 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, - 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, - 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, - 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, - 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, - 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, - 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, - 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, - 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, - 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, - 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, - 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, - 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, - 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, - 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, - 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, - 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, - 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, - 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, - 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, - 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, - 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, - 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, - 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, - 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, - 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, - 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, - 0x92638212, 0x670efa8e, 0x406000e0, 0x3a39ce37, 0xd3faf5cf, - 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, - 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, - 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, - 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, - 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, - 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, - 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, - 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, - 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, - 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, - 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, - 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, - 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, - 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, - 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, - 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, - 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, - 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, - 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, - 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, - 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, - 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, - 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, - 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, - 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, - 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, - 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, - 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, - 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, - 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, - 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, - 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, - 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, - 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, - 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, - 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, - 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, - 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, - 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, - 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, - 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, - 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, - 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, - 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, - 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, - 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 - ]; - - /** - * @type {Array.} - * @const - * @inner - */ - var C_ORIG = [ - 0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253, 0x63727944, - 0x6f756274 - ]; - - /** - * @param {Array.} lr - * @param {number} off - * @param {Array.} P - * @param {Array.} S - * @returns {Array.} - * @inner - */ - function _encipher(lr, off, P, S) { // This is our bottleneck: 1714/1905 ticks / 90% - see profile.txt - var n, - l = lr[off], - r = lr[off + 1]; - - l ^= P[0]; - - /* - for (var i=0, k=BLOWFISH_NUM_ROUNDS-2; i<=k;) - // Feistel substitution on left word - n = S[l >>> 24], - n += S[0x100 | ((l >> 16) & 0xff)], - n ^= S[0x200 | ((l >> 8) & 0xff)], - n += S[0x300 | (l & 0xff)], - r ^= n ^ P[++i], - // Feistel substitution on right word - n = S[r >>> 24], - n += S[0x100 | ((r >> 16) & 0xff)], - n ^= S[0x200 | ((r >> 8) & 0xff)], - n += S[0x300 | (r & 0xff)], - l ^= n ^ P[++i]; - */ - - //The following is an unrolled version of the above loop. - //Iteration 0 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[1]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[2]; - //Iteration 1 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[3]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[4]; - //Iteration 2 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[5]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[6]; - //Iteration 3 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[7]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[8]; - //Iteration 4 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[9]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[10]; - //Iteration 5 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[11]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[12]; - //Iteration 6 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[13]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[14]; - //Iteration 7 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[15]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[16]; - - lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1]; - lr[off + 1] = l; - return lr; - } - - /** - * @param {Array.} data - * @param {number} offp - * @returns {{key: number, offp: number}} - * @inner - */ - function _streamtoword(data, offp) { - for (var i = 0, word = 0; i < 4; ++i) - word = (word << 8) | (data[offp] & 0xff), - offp = (offp + 1) % data.length; - return { key: word, offp: offp }; - } - - /** - * @param {Array.} key - * @param {Array.} P - * @param {Array.} S - * @inner - */ - function _key(key, P, S) { - var offset = 0, - lr = [0, 0], - plen = P.length, - slen = S.length, - sw; - for (var i = 0; i < plen; i++) - sw = _streamtoword(key, offset), - offset = sw.offp, - P[i] = P[i] ^ sw.key; - for (i = 0; i < plen; i += 2) - lr = _encipher(lr, 0, P, S), - P[i] = lr[0], - P[i + 1] = lr[1]; - for (i = 0; i < slen; i += 2) - lr = _encipher(lr, 0, P, S), - S[i] = lr[0], - S[i + 1] = lr[1]; - } - - /** - * Expensive key schedule Blowfish. - * @param {Array.} data - * @param {Array.} key - * @param {Array.} P - * @param {Array.} S - * @inner - */ - function _ekskey(data, key, P, S) { - var offp = 0, - lr = [0, 0], - plen = P.length, - slen = S.length, - sw; - for (var i = 0; i < plen; i++) - sw = _streamtoword(key, offp), - offp = sw.offp, - P[i] = P[i] ^ sw.key; - offp = 0; - for (i = 0; i < plen; i += 2) - sw = _streamtoword(data, offp), - offp = sw.offp, - lr[0] ^= sw.key, - sw = _streamtoword(data, offp), - offp = sw.offp, - lr[1] ^= sw.key, - lr = _encipher(lr, 0, P, S), - P[i] = lr[0], - P[i + 1] = lr[1]; - for (i = 0; i < slen; i += 2) - sw = _streamtoword(data, offp), - offp = sw.offp, - lr[0] ^= sw.key, - sw = _streamtoword(data, offp), - offp = sw.offp, - lr[1] ^= sw.key, - lr = _encipher(lr, 0, P, S), - S[i] = lr[0], - S[i + 1] = lr[1]; - } - - /** - * Internaly crypts a string. - * @param {Array.} b Bytes to crypt - * @param {Array.} salt Salt bytes to use - * @param {number} rounds Number of rounds - * @param {function(Error, Array.=)=} callback Callback receiving the error, if any, and the resulting bytes. If - * omitted, the operation will be performed synchronously. - * @param {function(number)=} progressCallback Callback called with the current progress - * @returns {!Array.|undefined} Resulting bytes if callback has been omitted, otherwise `undefined` - * @inner - */ - function _crypt(b, salt, rounds, callback, progressCallback) { - var cdata = C_ORIG.slice(), - clen = cdata.length, - err; - - // Validate - if (rounds < 4 || rounds > 31) { - err = Error("Illegal number of rounds (4-31): "+rounds); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } else - throw err; - } - if (salt.length !== BCRYPT_SALT_LEN) { - err =Error("Illegal salt length: "+salt.length+" != "+BCRYPT_SALT_LEN); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } else - throw err; - } - rounds = (1 << rounds) >>> 0; - - var P, S, i = 0, j; - - //Use typed arrays when available - huge speedup! - if (Int32Array) { - P = new Int32Array(P_ORIG); - S = new Int32Array(S_ORIG); - } else { - P = P_ORIG.slice(); - S = S_ORIG.slice(); - } - - _ekskey(salt, b, P, S); - - /** - * Calcualtes the next round. - * @returns {Array.|undefined} Resulting array if callback has been omitted, otherwise `undefined` - * @inner - */ - function next() { - if (progressCallback) - progressCallback(i / rounds); - if (i < rounds) { - var start = Date.now(); - for (; i < rounds;) { - i = i + 1; - _key(b, P, S); - _key(salt, P, S); - if (Date.now() - start > MAX_EXECUTION_TIME) - break; - } - } else { - for (i = 0; i < 64; i++) - for (j = 0; j < (clen >> 1); j++) - _encipher(cdata, j << 1, P, S); - var ret = []; - for (i = 0; i < clen; i++) - ret.push(((cdata[i] >> 24) & 0xff) >>> 0), - ret.push(((cdata[i] >> 16) & 0xff) >>> 0), - ret.push(((cdata[i] >> 8) & 0xff) >>> 0), - ret.push((cdata[i] & 0xff) >>> 0); - if (callback) { - callback(null, ret); - return; - } else - return ret; - } - if (callback) - nextTick(next); - } - - // Async - if (typeof callback !== 'undefined') { - next(); - - // Sync - } else { - var res; - while (true) - if (typeof(res = next()) !== 'undefined') - return res || []; - } - } - - /** - * Internally hashes a string. - * @param {string} s String to hash - * @param {?string} salt Salt to use, actually never null - * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting hash. If omitted, - * hashing is perormed synchronously. - * @param {function(number)=} progressCallback Callback called with the current progress - * @returns {string|undefined} Resulting hash if callback has been omitted, otherwise `undefined` - * @inner - */ - function _hash(s, salt, callback, progressCallback) { - var err; - if (typeof s !== 'string' || typeof salt !== 'string') { - err = Error("Invalid string / salt: Not a string"); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } - else - throw err; - } - - // Validate the salt - var minor, offset; - if (salt.charAt(0) !== '$' || salt.charAt(1) !== '2') { - err = Error("Invalid salt version: "+salt.substring(0,2)); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } - else - throw err; - } - if (salt.charAt(2) === '$') - minor = String.fromCharCode(0), - offset = 3; - else { - minor = salt.charAt(2); - if ((minor !== 'a' && minor !== 'b' && minor !== 'y') || salt.charAt(3) !== '$') { - err = Error("Invalid salt revision: "+salt.substring(2,4)); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } else - throw err; - } - offset = 4; - } - - // Extract number of rounds - if (salt.charAt(offset + 2) > '$') { - err = Error("Missing salt rounds"); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } else - throw err; - } - var r1 = parseInt(salt.substring(offset, offset + 1), 10) * 10, - r2 = parseInt(salt.substring(offset + 1, offset + 2), 10), - rounds = r1 + r2, - real_salt = salt.substring(offset + 3, offset + 25); - s += minor >= 'a' ? "\x00" : ""; - - var passwordb = stringToBytes(s), - saltb = base64_decode(real_salt, BCRYPT_SALT_LEN); - - /** - * Finishes hashing. - * @param {Array.} bytes Byte array - * @returns {string} - * @inner - */ - function finish(bytes) { - var res = []; - res.push("$2"); - if (minor >= 'a') - res.push(minor); - res.push("$"); - if (rounds < 10) - res.push("0"); - res.push(rounds.toString()); - res.push("$"); - res.push(base64_encode(saltb, saltb.length)); - res.push(base64_encode(bytes, C_ORIG.length * 4 - 1)); - return res.join(''); - } - - // Sync - if (typeof callback == 'undefined') - return finish(_crypt(passwordb, saltb, rounds)); - - // Async - else { - _crypt(passwordb, saltb, rounds, function(err, bytes) { - if (err) - callback(err, null); - else - callback(null, finish(bytes)); - }, progressCallback); - } - } - - /** - * Encodes a byte array to base64 with up to len bytes of input, using the custom bcrypt alphabet. - * @function - * @param {!Array.} b Byte array - * @param {number} len Maximum input length - * @returns {string} - * @expose - */ - bcrypt.encodeBase64 = base64_encode; - - /** - * Decodes a base64 encoded string to up to len bytes of output, using the custom bcrypt alphabet. - * @function - * @param {string} s String to decode - * @param {number} len Maximum output length - * @returns {!Array.} - * @expose - */ - bcrypt.decodeBase64 = base64_decode; - - return bcrypt; -})); diff --git a/node_modules/bcryptjs/dist/bcrypt.min.js b/node_modules/bcryptjs/dist/bcrypt.min.js deleted file mode 100644 index 0fd2f1e0..00000000 --- a/node_modules/bcryptjs/dist/bcrypt.min.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - bcrypt.js (c) 2013 Daniel Wirtz - Released under the Apache License, Version 2.0 - see: https://github.com/dcodeIO/bcrypt.js for details -*/ -(function(u,r){"function"===typeof define&&define.amd?define([],r):"function"===typeof require&&"object"===typeof module&&module&&module.exports?module.exports=r():(u.dcodeIO=u.dcodeIO||{}).bcrypt=r()})(this,function(){function u(e){if("undefined"!==typeof module&&module&&module.exports)try{return require("crypto").randomBytes(e)}catch(d){}try{var c;(self.crypto||self.msCrypto).getRandomValues(c=new Uint32Array(e));return Array.prototype.slice.call(c)}catch(b){}if(!w)throw Error("Neither WebCryptoAPI nor a crypto module is available. Use bcrypt.setRandomFallback to set an alternative"); -return w(e)}function r(e,d){for(var c=0,b=0,a=0,f=e.length;ac?!1:0===b}function H(e){var d=[],c=0;I.encodeUTF16toUTF8(function(){return c>=e.length?null:e.charCodeAt(c++)},function(b){d.push(b)});return d}function x(e,d){var c=0,b=[],a,f;if(0>=d||d>e.length)throw Error("Illegal len: "+d);for(;c>2&63]);a=(a&3)<<4;if(c>=d){b.push(s[a&63]);break}f=e[c++]&255;a|=f>>4&15;b.push(s[a&63]);a=(f&15)<<2;if(c>=d){b.push(s[a& -63]);break}f=e[c++]&255;a|=f>>6&3;b.push(s[a&63]);b.push(s[f&63])}return b.join("")}function B(e,d){var c=0,b=e.length,a=0,f=[],g,m,h;if(0>=d)throw Error("Illegal len: "+d);for(;c>>0;h|=(m&48)>>4;f.push(z(h));if(++a>=d||c>=b)break;h=e.charCodeAt(c++);g=h>>0;h|=(g&60)>>2;f.push(z(h));if(++a>=d||c>=b)break;h=e.charCodeAt(c++);m=h>>0;h|=m;f.push(z(h));++a}b=[];for(c=0;c>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[1];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[2];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[3];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[4];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512| -f>>8&255];a+=b[768|f&255];g=g^a^c[5];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[6];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[7];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[8];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[9];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[10];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^ -c[11];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[12];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[13];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[14];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[15];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[16];e[d]=g^c[17];e[d+1]=f;return e}function t(e,d){for(var c=0,b=0;4>c;++c)b=b<<8|e[d]&255,d=(d+1)%e.length; -return{key:b,offp:d}}function C(e,d,c){for(var b=0,a=[0,0],f=d.length,g=c.length,m,h=0;hn;n++)for(y=0;y>1;y++)v(g,y<<1,l,k);h=[];for(n=0;n>24&255)>>>0),h.push((g[n]>>16&255)>>>0),h.push((g[n]>>8&255)>>>0),h.push((g[n]&255)>>>0);if(b){b(null,h);return}return h}b&&p(f)}var g=E.slice(),m=g.length,h;if(4>c||31>>0;var l,k,n=0,y;Int32Array?(l=new Int32Array(F),k=new Int32Array(G)):(l=F.slice(),k=G.slice());J(d,e,l,k);if("undefined"!==typeof b)f();else for(;;)if("undefined"!==typeof(h=f()))return h||[]}function A(e,d,c,b){function a(a){var b=[];b.push("$2");"a"<=f&&b.push(f);b.push("$");10>l&&b.push("0");b.push(l.toString());b.push("$");b.push(x(k,k.length));b.push(x(a,4* -E.length-1));return b.join("")}if("string"!==typeof e||"string"!==typeof d){b=Error("Invalid string / salt: Not a string");if(c){p(c.bind(this,b));return}throw b;}var f,g;if("$"!==d.charAt(0)||"2"!==d.charAt(1)){b=Error("Invalid salt version: "+d.substring(0,2));if(c){p(c.bind(this,b));return}throw b;}if("$"===d.charAt(2))f=String.fromCharCode(0),g=3;else{f=d.charAt(2);if("a"!==f&&"b"!==f&&"y"!==f||"$"!==d.charAt(3)){b=Error("Invalid salt revision: "+d.substring(2,4));if(c){p(c.bind(this,b));return}throw b; -}g=4}if("$"e?e=4:31e&&c.push("0");c.push(e.toString());c.push("$");c.push(x(u(16),16));return c.join("")};k.genSalt=function(e,d,c){function b(a){p(function(){try{a(null,k.genSaltSync(e))}catch(b){a(b)}})}"function"===typeof d&&(c=d,d=void 0);"function"===typeof e&&(c=e,e=void 0);if("undefined"===typeof e)e=10;else if("number"!==typeof e)throw Error("illegal arguments: "+typeof e);if(c){if("function"!==typeof c)throw Error("Illegal callback: "+ -typeof c);b(c)}else return new Promise(function(a,c){b(function(b,d){b?c(b):a(d)})})};k.hashSync=function(e,d){"undefined"===typeof d&&(d=10);"number"===typeof d&&(d=k.genSaltSync(d));if("string"!==typeof e||"string"!==typeof d)throw Error("Illegal arguments: "+typeof e+", "+typeof d);return A(e,d)};k.hash=function(e,d,c,b){function a(a){"string"===typeof e&&"number"===typeof d?k.genSalt(d,function(c,d){A(e,d,a,b)}):"string"===typeof e&&"string"===typeof d?A(e,d,a,b):p(a.bind(this,Error("Illegal arguments: "+ -typeof e+", "+typeof d)))}if(c){if("function"!==typeof c)throw Error("Illegal callback: "+typeof c);a(c)}else return new Promise(function(b,c){a(function(a,d){a?c(a):b(d)})})};k.compareSync=function(e,d){if("string"!==typeof e||"string"!==typeof d)throw Error("Illegal arguments: "+typeof e+", "+typeof d);return 60!==d.length?!1:r(k.hashSync(e,d.substr(0,d.length-31)),d)};k.compare=function(e,d,c,b){function a(a){"string"!==typeof e||"string"!==typeof d?p(a.bind(this,Error("Illegal arguments: "+typeof e+ -", "+typeof d))):60!==d.length?p(a.bind(this,null,!1)):k.hash(e,d.substr(0,29),function(b,c){b?a(b):a(null,r(c,d))},b)}if(c){if("function"!==typeof c)throw Error("Illegal callback: "+typeof c);a(c)}else return new Promise(function(b,c){a(function(a,d){a?c(a):b(d)})})};k.getRounds=function(e){if("string"!==typeof e)throw Error("Illegal arguments: "+typeof e);return parseInt(e.split("$")[2],10)};k.getSalt=function(e){if("string"!==typeof e)throw Error("Illegal arguments: "+typeof e);if(60!==e.length)throw Error("Illegal hash length: "+ -e.length+" != 60");return e.substring(0,29)};var p="undefined"!==typeof process&&process&&"function"===typeof process.nextTick?"function"===typeof setImmediate?setImmediate:process.nextTick:setTimeout,s="./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),q=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,54,55,56,57,58,59,60,61,62,63,-1,-1,-1,-1,-1,-1,-1,2,3,4,5,6,7,8,9,10,11,12, -13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,-1,-1,-1,-1,-1,-1,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,-1,-1,-1,-1,-1],z=String.fromCharCode,I=function(){var e={MAX_CODEPOINT:1114111,encodeUTF8:function(d,c){var b=null;"number"===typeof d&&(b=d,d=function(){return null});for(;null!==b||null!==(b=d());)128>b?c(b&127):(2048>b?c(b>>6&31|192):(65536>b?c(b>>12&15|224):(c(b>>18&7|240),c(b>>12&63|128)),c(b>>6&63|128)),c(b&63|128)),b=null},decodeUTF8:function(d,c){for(var b, -a,f,e,k=function(a){a=a.slice(0,a.indexOf(null));var b=Error(a.toString());b.name="TruncatedError";b.bytes=a;throw b;};null!==(b=d());)if(0===(b&128))c(b);else if(192===(b&224))null===(a=d())&&k([b,a]),c((b&31)<<6|a&63);else if(224===(b&240))null!==(a=d())&&null!==(f=d())||k([b,a,f]),c((b&15)<<12|(a&63)<<6|f&63);else if(240===(b&248))null!==(a=d())&&null!==(f=d())&&null!==(e=d())||k([b,a,f,e]),c((b&7)<<18|(a&63)<<12|(f&63)<<6|e&63);else throw RangeError("Illegal starting byte: "+b);},UTF16toUTF8:function(d, -c){for(var b,a=null;null!==(b=null!==a?a:d());)55296<=b&&57343>=b&&null!==(a=d())&&56320<=a&&57343>=a?(c(1024*(b-55296)+a-56320+65536),a=null):c(b);null!==a&&c(a)},UTF8toUTF16:function(d,c){var b=null;"number"===typeof d&&(b=d,d=function(){return null});for(;null!==b||null!==(b=d());)65535>=b?c(b):(b-=65536,c((b>>10)+55296),c(b%1024+56320)),b=null},encodeUTF16toUTF8:function(d,c){e.UTF16toUTF8(d,function(b){e.encodeUTF8(b,c)})},decodeUTF8toUTF16:function(d,c){e.decodeUTF8(d,function(b){e.UTF8toUTF16(b, -c)})},calculateCodePoint:function(d){return 128>d?1:2048>d?2:65536>d?3:4},calculateUTF8:function(d){for(var c,b=0;null!==(c=d());)b+=e.calculateCodePoint(c);return b},calculateUTF16asUTF8:function(d){var c=0,b=0;e.UTF16toUTF8(d,function(a){++c;b+=e.calculateCodePoint(a)});return[c,b]}};return e}();Date.now=Date.now||function(){return+new Date};var F=[608135816,2242054355,320440878,57701188,2752067618,698298832,137296536,3964562569,1160258022,953160567,3193202383,887688300,3232508343,3380367581,1065670069, -3041331479,2450970073,2306472731],G=[3509652390,2564797868,805139163,3491422135,3101798381,1780907670,3128725573,4046225305,614570311,3012652279,134345442,2240740374,1667834072,1901547113,2757295779,4103290238,227898511,1921955416,1904987480,2182433518,2069144605,3260701109,2620446009,720527379,3318853667,677414384,3393288472,3101374703,2390351024,1614419982,1822297739,2954791486,3608508353,3174124327,2024746970,1432378464,3864339955,2857741204,1464375394,1676153920,1439316330,715854006,3033291828, -289532110,2706671279,2087905683,3018724369,1668267050,732546397,1947742710,3462151702,2609353502,2950085171,1814351708,2050118529,680887927,999245976,1800124847,3300911131,1713906067,1641548236,4213287313,1216130144,1575780402,4018429277,3917837745,3693486850,3949271944,596196993,3549867205,258830323,2213823033,772490370,2760122372,1774776394,2652871518,566650946,4142492826,1728879713,2882767088,1783734482,3629395816,2517608232,2874225571,1861159788,326777828,3124490320,2130389656,2716951837,967770486, -1724537150,2185432712,2364442137,1164943284,2105845187,998989502,3765401048,2244026483,1075463327,1455516326,1322494562,910128902,469688178,1117454909,936433444,3490320968,3675253459,1240580251,122909385,2157517691,634681816,4142456567,3825094682,3061402683,2540495037,79693498,3249098678,1084186820,1583128258,426386531,1761308591,1047286709,322548459,995290223,1845252383,2603652396,3431023940,2942221577,3202600964,3727903485,1712269319,422464435,3234572375,1170764815,3523960633,3117677531,1434042557, -442511882,3600875718,1076654713,1738483198,4213154764,2393238008,3677496056,1014306527,4251020053,793779912,2902807211,842905082,4246964064,1395751752,1040244610,2656851899,3396308128,445077038,3742853595,3577915638,679411651,2892444358,2354009459,1767581616,3150600392,3791627101,3102740896,284835224,4246832056,1258075500,768725851,2589189241,3069724005,3532540348,1274779536,3789419226,2764799539,1660621633,3471099624,4011903706,913787905,3497959166,737222580,2514213453,2928710040,3937242737,1804850592, -3499020752,2949064160,2386320175,2390070455,2415321851,4061277028,2290661394,2416832540,1336762016,1754252060,3520065937,3014181293,791618072,3188594551,3933548030,2332172193,3852520463,3043980520,413987798,3465142937,3030929376,4245938359,2093235073,3534596313,375366246,2157278981,2479649556,555357303,3870105701,2008414854,3344188149,4221384143,3956125452,2067696032,3594591187,2921233993,2428461,544322398,577241275,1471733935,610547355,4027169054,1432588573,1507829418,2025931657,3646575487,545086370, -48609733,2200306550,1653985193,298326376,1316178497,3007786442,2064951626,458293330,2589141269,3591329599,3164325604,727753846,2179363840,146436021,1461446943,4069977195,705550613,3059967265,3887724982,4281599278,3313849956,1404054877,2845806497,146425753,1854211946,1266315497,3048417604,3681880366,3289982499,290971E4,1235738493,2632868024,2414719590,3970600049,1771706367,1449415276,3266420449,422970021,1963543593,2690192192,3826793022,1062508698,1531092325,1804592342,2583117782,2714934279,4024971509, -1294809318,4028980673,1289560198,2221992742,1669523910,35572830,157838143,1052438473,1016535060,1802137761,1753167236,1386275462,3080475397,2857371447,1040679964,2145300060,2390574316,1461121720,2956646967,4031777805,4028374788,33600511,2920084762,1018524850,629373528,3691585981,3515945977,2091462646,2486323059,586499841,988145025,935516892,3367335476,2599673255,2839830854,265290510,3972581182,2759138881,3795373465,1005194799,847297441,406762289,1314163512,1332590856,1866599683,4127851711,750260880, -613907577,1450815602,3165620655,3734664991,3650291728,3012275730,3704569646,1427272223,778793252,1343938022,2676280711,2052605720,1946737175,3164576444,3914038668,3967478842,3682934266,1661551462,3294938066,4011595847,840292616,3712170807,616741398,312560963,711312465,1351876610,322626781,1910503582,271666773,2175563734,1594956187,70604529,3617834859,1007753275,1495573769,4069517037,2549218298,2663038764,504708206,2263041392,3941167025,2249088522,1514023603,1998579484,1312622330,694541497,2582060303, -2151582166,1382467621,776784248,2618340202,3323268794,2497899128,2784771155,503983604,4076293799,907881277,423175695,432175456,1378068232,4145222326,3954048622,3938656102,3820766613,2793130115,2977904593,26017576,3274890735,3194772133,1700274565,1756076034,4006520079,3677328699,720338349,1533947780,354530856,688349552,3973924725,1637815568,332179504,3949051286,53804574,2852348879,3044236432,1282449977,3583942155,3416972820,4006381244,1617046695,2628476075,3002303598,1686838959,431878346,2686675385, -1700445008,1080580658,1009431731,832498133,3223435511,2605976345,2271191193,2516031870,1648197032,4164389018,2548247927,300782431,375919233,238389289,3353747414,2531188641,2019080857,1475708069,455242339,2609103871,448939670,3451063019,1395535956,2413381860,1841049896,1491858159,885456874,4264095073,4001119347,1565136089,3898914787,1108368660,540939232,1173283510,2745871338,3681308437,4207628240,3343053890,4016749493,1699691293,1103962373,3625875870,2256883143,3830138730,1031889488,3479347698,1535977030, -4236805024,3251091107,2132092099,1774941330,1199868427,1452454533,157007616,2904115357,342012276,595725824,1480756522,206960106,497939518,591360097,863170706,2375253569,3596610801,1814182875,2094937945,3421402208,1082520231,3463918190,2785509508,435703966,3908032597,1641649973,2842273706,3305899714,1510255612,2148256476,2655287854,3276092548,4258621189,236887753,3681803219,274041037,1734335097,3815195456,3317970021,1899903192,1026095262,4050517792,356393447,2410691914,3873677099,3682840055,3913112168, -2491498743,4132185628,2489919796,1091903735,1979897079,3170134830,3567386728,3557303409,857797738,1136121015,1342202287,507115054,2535736646,337727348,3213592640,1301675037,2528481711,1895095763,1721773893,3216771564,62756741,2142006736,835421444,2531993523,1442658625,3659876326,2882144922,676362277,1392781812,170690266,3921047035,1759253602,3611846912,1745797284,664899054,1329594018,3901205900,3045908486,2062866102,2865634940,3543621612,3464012697,1080764994,553557557,3656615353,3996768171,991055499, -499776247,1265440854,648242737,3940784050,980351604,3713745714,1749149687,3396870395,4211799374,3640570775,1161844396,3125318951,1431517754,545492359,4268468663,3499529547,1437099964,2702547544,3433638243,2581715763,2787789398,1060185593,1593081372,2418618748,4260947970,69676912,2159744348,86519011,2512459080,3838209314,1220612927,3339683548,133810670,1090789135,1078426020,1569222167,845107691,3583754449,4072456591,1091646820,628848692,1613405280,3757631651,526609435,236106946,48312990,2942717905, -3402727701,1797494240,859738849,992217954,4005476642,2243076622,3870952857,3732016268,765654824,3490871365,2511836413,1685915746,3888969200,1414112111,2273134842,3281911079,4080962846,172450625,2569994100,980381355,4109958455,2819808352,2716589560,2568741196,3681446669,3329971472,1835478071,660984891,3704678404,4045999559,3422617507,3040415634,1762651403,1719377915,3470491036,2693910283,3642056355,3138596744,1364962596,2073328063,1983633131,926494387,3423689081,2150032023,4096667949,1749200295,3328846651, -309677260,2016342300,1779581495,3079819751,111262694,1274766160,443224088,298511866,1025883608,3806446537,1145181785,168956806,3641502830,3584813610,1689216846,3666258015,3200248200,1692713982,2646376535,4042768518,1618508792,1610833997,3523052358,4130873264,2001055236,3610705100,2202168115,4028541809,2961195399,1006657119,2006996926,3186142756,1430667929,3210227297,1314452623,4074634658,4101304120,2273951170,1399257539,3367210612,3027628629,1190975929,2062231137,2333990788,2221543033,2438960610, -1181637006,548689776,2362791313,3372408396,3104550113,3145860560,296247880,1970579870,3078560182,3769228297,1714227617,3291629107,3898220290,166772364,1251581989,493813264,448347421,195405023,2709975567,677966185,3703036547,1463355134,2715995803,1338867538,1343315457,2802222074,2684532164,233230375,2599980071,2000651841,3277868038,1638401717,4028070440,3237316320,6314154,819756386,300326615,590932579,1405279636,3267499572,3150704214,2428286686,3959192993,3461946742,1862657033,1266418056,963775037, -2089974820,2263052895,1917689273,448879540,3550394620,3981727096,150775221,3627908307,1303187396,508620638,2975983352,2726630617,1817252668,1876281319,1457606340,908771278,3720792119,3617206836,2455994898,1729034894,1080033504,976866871,3556439503,2881648439,1522871579,1555064734,1336096578,3548522304,2579274686,3574697629,3205460757,3593280638,3338716283,3079412587,564236357,2993598910,1781952180,1464380207,3163844217,3332601554,1699332808,1393555694,1183702653,3581086237,1288719814,691649499,2847557200, -2895455976,3193889540,2717570544,1781354906,1676643554,2592534050,3230253752,1126444790,2770207658,2633158820,2210423226,2615765581,2414155088,3127139286,673620729,2805611233,1269405062,4015350505,3341807571,4149409754,1057255273,2012875353,2162469141,2276492801,2601117357,993977747,3918593370,2654263191,753973209,36408145,2530585658,25011837,3520020182,2088578344,530523599,2918365339,1524020338,1518925132,3760827505,3759777254,1202760957,3985898139,3906192525,674977740,4174734889,2031300136,2019492241, -3983892565,4153806404,3822280332,352677332,2297720250,60907813,90501309,3286998549,1016092578,2535922412,2839152426,457141659,509813237,4120667899,652014361,1966332200,2975202805,55981186,2327461051,676427537,3255491064,2882294119,3433927263,1307055953,942726286,933058658,2468411793,3933900994,4215176142,1361170020,2001714738,2830558078,3274259782,1222529897,1679025792,2729314320,3714953764,1770335741,151462246,3013232138,1682292957,1483529935,471910574,1539241949,458788160,3436315007,1807016891, -3718408830,978976581,1043663428,3165965781,1927990952,4200891579,2372276910,3208408903,3533431907,1412390302,2931980059,4132332400,1947078029,3881505623,4168226417,2941484381,1077988104,1320477388,886195818,18198404,3786409E3,2509781533,112762804,3463356488,1866414978,891333506,18488651,661792760,1628790961,3885187036,3141171499,876946877,2693282273,1372485963,791857591,2686433993,3759982718,3167212022,3472953795,2716379847,445679433,3561995674,3504004811,3574258232,54117162,3331405415,2381918588, -3769707343,4154350007,1140177722,4074052095,668550556,3214352940,367459370,261225585,2610173221,4209349473,3468074219,3265815641,314222801,3066103646,3808782860,282218597,3406013506,3773591054,379116347,1285071038,846784868,2669647154,3771962079,3550491691,2305946142,453669953,1268987020,3317592352,3279303384,3744833421,2610507566,3859509063,266596637,3847019092,517658769,3462560207,3443424879,370717030,4247526661,2224018117,4143653529,4112773975,2788324899,2477274417,1456262402,2901442914,1517677493, -1846949527,2295493580,3734397586,2176403920,1280348187,1908823572,3871786941,846861322,1172426758,3287448474,3383383037,1655181056,3139813346,901632758,1897031941,2986607138,3066810236,3447102507,1393639104,373351379,950779232,625454576,3124240540,4148612726,2007998917,544563296,2244738638,2330496472,2058025392,1291430526,424198748,50039436,29584100,3605783033,2429876329,2791104160,1057563949,3255363231,3075367218,3463963227,1469046755,985887462],E=[1332899944,1700884034,1701343084,1684370003,1668446532, -1869963892];k.encodeBase64=x;k.decodeBase64=B;return k}); diff --git a/node_modules/bcryptjs/dist/bcrypt.min.js.gz b/node_modules/bcryptjs/dist/bcrypt.min.js.gz deleted file mode 100644 index 6bde4bde..00000000 Binary files a/node_modules/bcryptjs/dist/bcrypt.min.js.gz and /dev/null differ diff --git a/node_modules/bcryptjs/dist/bcrypt.min.map b/node_modules/bcryptjs/dist/bcrypt.min.map deleted file mode 100644 index 35d0f837..00000000 --- a/node_modules/bcryptjs/dist/bcrypt.min.map +++ /dev/null @@ -1,8 +0,0 @@ -{ -"version":3, -"file":"", -"lineCount":48, -"mappings":"A;;;;;AAiCC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkB,CAES,UAAtB,GAAI,MAAOC,OAAX,EAAoCA,MAAA,IAApC,CACNA,MAAA,CAAO,EAAP,CAAWD,CAAX,CADM,CAEiC,UAAvB,GAAI,MAAOE,QAAX,EAAuD,QAAvD,GAAqC,MAAOC,OAA5C,EAAmEA,MAAnE,EAA6EA,MAAA,QAA7E,CAChBA,MAAA,QADgB,CACIH,CAAA,EADJ,CAGhB,CAACD,CAAA,QAAD,CAAqBA,CAAA,QAArB,EAA0C,EAA1C,QAHgB,CAG0CC,CAAA,EAPvC,CAA1B,CAAA,CASC,IATD,CASO,QAAQ,EAAG,CAwBfI,QAASA,EAAM,CAACC,CAAD,CAAM,CACN,GAAsB,WAAtB,GAAI,MAAOF,OAAX,EAAqCA,MAArC,EAA+CA,MAAA,QAA/C,CACP,GAAI,CACA,MAAOD,QAAA,CAAQ,QAAR,CAAA,YAAA,CAAiCG,CAAjC,CADP,CAEF,MAAOC,CAAP,CAAU,EACN,GAAI,CACV,IAAIC,CAAG,EAACC,IAAA,OAAD,EAAiBA,IAAA,SAAjB,iBAAA,CAAsDD,CAAtD,CAA0D,IAAIE,WAAJ,CAAgBJ,CAAhB,CAA1D,CACP,OAAOK,MAAAC,UAAAC,MAAAC,KAAA,CAA2BN,CAA3B,CAFG,CAGZ,MAAOD,CAAP,CAAU,EACG,GAAKQ,CAAAA,CAAL,CACX,KAAMC,MAAA,CAAM,2GAAN,CAAN;AACJ,MAAOD,EAAA,CAAeT,CAAf,CAXU,CA6KrBW,QAASA,EAAiB,CAACC,CAAD,CAAQC,CAAR,CAAiB,CAGvC,IAHuC,IACnCC,EAAQ,CAD2B,CAEnCC,EAAQ,CAF2B,CAG9BC,EAAE,CAH4B,CAGzBC,EAAEL,CAAAM,OAAhB,CAA8BF,CAA9B,CAAgCC,CAAhC,CAAmC,EAAED,CAArC,CACQJ,CAAAO,WAAA,CAAiBH,CAAjB,CAAJ,GAA4BH,CAAAM,WAAA,CAAmBH,CAAnB,CAA5B,CACI,EAAEF,CADN,CAGI,EAAEC,CAGV,OAAY,EAAZ,CAAID,CAAJ,CACW,CAAA,CADX,CAEiB,CAFjB,GAEOC,CAZgC,CAyH3CK,QAASA,EAAa,CAACC,CAAD,CAAM,CAAA,IACpBC,EAAM,EADc,CAEpBN,EAAI,CACRO,EAAAC,kBAAA,CAAuB,QAAQ,EAAG,CAC9B,MAAIR,EAAJ,EAASK,CAAAH,OAAT,CAA4B,IAA5B,CACOG,CAAAF,WAAA,CAAeH,CAAA,EAAf,CAFuB,CAAlC,CAGG,QAAQ,CAACS,CAAD,CAAI,CACXH,CAAAI,KAAA,CAASD,CAAT,CADW,CAHf,CAMA,OAAOH,EATiB,CAiD5BK,QAASA,EAAa,CAACF,CAAD,CAAIzB,CAAJ,CAAS,CAAA,IACvB4B,EAAM,CADiB,CAEvBC,EAAK,EAFkB,CAGvBC,CAHuB,CAGnBC,CACR,IAAW,CAAX,EAAI/B,CAAJ,EAAgBA,CAAhB,CAAsByB,CAAAP,OAAtB,CACI,KAAMR,MAAA,CAAM,eAAN,CAAsBV,CAAtB,CAAN,CACJ,IAAA,CAAO4B,CAAP,CAAa5B,CAAb,CAAA,CAAkB,CACd8B,CAAA,CAAKL,CAAA,CAAEG,CAAA,EAAF,CAAL,CAAgB,GAChBC,EAAAH,KAAA,CAAQM,CAAA,CAAaF,CAAb,EAAmB,CAAnB,CAAwB,EAAxB,CAAR,CACAA,EAAA,EAAMA,CAAN,CAAW,CAAX,GAAoB,CACpB,IAAIF,CAAJ,EAAW5B,CAAX,CAAgB,CACZ6B,CAAAH,KAAA,CAAQM,CAAA,CAAYF,CAAZ,CAAiB,EAAjB,CAAR,CACA,MAFY,CAIhBC,CAAA,CAAKN,CAAA,CAAEG,CAAA,EAAF,CAAL,CAAgB,GAChBE,EAAA,EAAOC,CAAP,EAAa,CAAb,CAAkB,EAClBF,EAAAH,KAAA,CAAQM,CAAA,CAAYF,CAAZ,CAAiB,EAAjB,CAAR,CACAA,EAAA,EAAMC,CAAN,CAAW,EAAX,GAAoB,CACpB,IAAIH,CAAJ,EAAW5B,CAAX,CAAgB,CACZ6B,CAAAH,KAAA,CAAQM,CAAA,CAAYF,CAAZ;AAAiB,EAAjB,CAAR,CACA,MAFY,CAIhBC,CAAA,CAAKN,CAAA,CAAEG,CAAA,EAAF,CAAL,CAAgB,GAChBE,EAAA,EAAOC,CAAP,EAAa,CAAb,CAAkB,CAClBF,EAAAH,KAAA,CAAQM,CAAA,CAAYF,CAAZ,CAAiB,EAAjB,CAAR,CACAD,EAAAH,KAAA,CAAQM,CAAA,CAAYD,CAAZ,CAAiB,EAAjB,CAAR,CAnBc,CAqBlB,MAAOF,EAAAI,KAAA,CAAQ,EAAR,CA3BoB,CAqC/BC,QAASA,EAAa,CAACC,CAAD,CAAInC,CAAJ,CAAS,CAAA,IACvB4B,EAAM,CADiB,CAEvBQ,EAAOD,CAAAjB,OAFgB,CAGvBmB,EAAO,CAHgB,CAIvBR,EAAK,EAJkB,CAKvBC,CALuB,CAKnBC,CALmB,CAKPO,CACpB,IAAW,CAAX,EAAItC,CAAJ,CACI,KAAMU,MAAA,CAAM,eAAN,CAAsBV,CAAtB,CAAN,CACJ,IAAA,CAAO4B,CAAP,CAAaQ,CAAb,CAAoB,CAApB,EAAyBC,CAAzB,CAAgCrC,CAAhC,CAAA,CAAqC,CACjCuC,CAAA,CAAOJ,CAAAhB,WAAA,CAAaS,CAAA,EAAb,CACPE,EAAA,CAAKS,CAAA,CAAOC,CAAAtB,OAAP,CAA6BsB,CAAA,CAAaD,CAAb,CAA7B,CAAmD,EACxDA,EAAA,CAAOJ,CAAAhB,WAAA,CAAaS,CAAA,EAAb,CACPG,EAAA,CAAKQ,CAAA,CAAOC,CAAAtB,OAAP,CAA6BsB,CAAA,CAAaD,CAAb,CAA7B,CAAmD,EACxD,IAAW,EAAX,EAAIT,CAAJ,EAAuB,EAAvB,EAAgBC,CAAhB,CACI,KACJO,EAAA,CAAKR,CAAL,EAAW,CAAX,GAAkB,CAClBQ,EAAA,GAAMP,CAAN,CAAW,EAAX,GAAoB,CACpBF,EAAAH,KAAA,CAAQe,CAAA,CAAmBH,CAAnB,CAAR,CACA,IAAI,EAAED,CAAN,EAAcrC,CAAd,EAAqB4B,CAArB,EAA4BQ,CAA5B,CACI,KACJG,EAAA,CAAOJ,CAAAhB,WAAA,CAAaS,CAAA,EAAb,CACPc,EAAA,CAAKH,CAAA,CAAOC,CAAAtB,OAAP,CAA6BsB,CAAA,CAAaD,CAAb,CAA7B,CAAmD,EACxD,IAAW,EAAX,EAAIG,CAAJ,CACI,KACJJ,EAAA,EAAMP,CAAN,CAAW,EAAX,GAAoB,CAApB,GAA2B,CAC3BO,EAAA,GAAMI,CAAN,CAAW,EAAX,GAAoB,CACpBb,EAAAH,KAAA,CAAQe,CAAA,CAAmBH,CAAnB,CAAR,CACA,IAAI,EAAED,CAAN,EAAcrC,CAAd,EAAqB4B,CAArB,EAA4BQ,CAA5B,CACI,KACJG,EAAA,CAAOJ,CAAAhB,WAAA,CAAaS,CAAA,EAAb,CACPe,EAAA,CAAKJ,CAAA,CAAOC,CAAAtB,OAAP;AAA6BsB,CAAA,CAAaD,CAAb,CAA7B,CAAmD,EACxDD,EAAA,EAAMI,CAAN,CAAW,CAAX,GAAoB,CAApB,GAA2B,CAC3BJ,EAAA,EAAKK,CACLd,EAAAH,KAAA,CAAQe,CAAA,CAAmBH,CAAnB,CAAR,CACA,GAAED,CA1B+B,CA4BjCO,CAAAA,CAAM,EACV,KAAKhB,CAAL,CAAW,CAAX,CAAcA,CAAd,CAAkBS,CAAlB,CAAwBT,CAAA,EAAxB,CACIgB,CAAAlB,KAAA,CAASG,CAAA,CAAGD,CAAH,CAAAT,WAAA,CAAmB,CAAnB,CAAT,CACJ,OAAOyB,EAvCoB,CAggB/BC,QAASA,EAAS,CAACC,CAAD,CAAKlB,CAAL,CAAUmB,CAAV,CAAaC,CAAb,CAAgB,CAAA,IAC1BC,CAD0B,CAE1BC,EAAIJ,CAAA,CAAGlB,CAAH,CAFsB,CAG1BuB,EAAIL,CAAA,CAAGlB,CAAH,CAAS,CAAT,CAHsB,CAK9BsB,EAAAA,CAAAA,CAAKH,CAAA,CAAE,CAAF,CAoBLE,EAAA,CAAKD,CAAA,CAAEE,CAAF,GAAQ,EAAR,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWE,CAAX,CAAe,GAAf,CACLC,EAAA,CAAAA,CAAA,CAAKF,CAAL,CAASF,CAAA,CAAE,CAAF,CACTE,EAAA,CAAKD,CAAA,CAAEG,CAAF,GAAQ,EAAR,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWG,CAAX,CAAe,GAAf,CACLD,EAAA,CAAAA,CAAA,CAAKD,CAAL,CAASF,CAAA,CAAE,CAAF,CAETE,EAAA,CAAKD,CAAA,CAAEE,CAAF,GAAQ,EAAR,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWE,CAAX,CAAe,GAAf,CACLC,EAAA,CAAAA,CAAA,CAAKF,CAAL,CAASF,CAAA,CAAE,CAAF,CACTE,EAAA,CAAKD,CAAA,CAAEG,CAAF,GAAQ,EAAR,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWG,CAAX,CAAe,GAAf,CACLD,EAAA,CAAAA,CAAA,CAAKD,CAAL,CAASF,CAAA,CAAE,CAAF,CAETE,EAAA,CAAKD,CAAA,CAAEE,CAAF,GAAQ,EAAR,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF;AAAYE,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWE,CAAX,CAAe,GAAf,CACLC,EAAA,CAAAA,CAAA,CAAKF,CAAL,CAASF,CAAA,CAAE,CAAF,CACTE,EAAA,CAAKD,CAAA,CAAEG,CAAF,GAAQ,EAAR,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWG,CAAX,CAAe,GAAf,CACLD,EAAA,CAAAA,CAAA,CAAKD,CAAL,CAASF,CAAA,CAAE,CAAF,CAETE,EAAA,CAAKD,CAAA,CAAEE,CAAF,GAAQ,EAAR,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWE,CAAX,CAAe,GAAf,CACLC,EAAA,CAAAA,CAAA,CAAKF,CAAL,CAASF,CAAA,CAAE,CAAF,CACTE,EAAA,CAAKD,CAAA,CAAEG,CAAF,GAAQ,EAAR,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWG,CAAX,CAAe,GAAf,CACLD,EAAA,CAAAA,CAAA,CAAKD,CAAL,CAASF,CAAA,CAAE,CAAF,CAETE,EAAA,CAAKD,CAAA,CAAEE,CAAF,GAAQ,EAAR,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWE,CAAX,CAAe,GAAf,CACLC,EAAA,CAAAA,CAAA,CAAKF,CAAL,CAASF,CAAA,CAAE,CAAF,CACTE,EAAA,CAAKD,CAAA,CAAEG,CAAF,GAAQ,EAAR,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWG,CAAX,CAAe,GAAf,CACLD,EAAA,CAAAA,CAAA,CAAKD,CAAL,CAASF,CAAA,CAAE,EAAF,CAETE,EAAA,CAAKD,CAAA,CAAEE,CAAF,GAAQ,EAAR,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWE,CAAX,CAAe,GAAf,CACLC,EAAA,CAAAA,CAAA,CAAKF,CAAL;AAASF,CAAA,CAAE,EAAF,CACTE,EAAA,CAAKD,CAAA,CAAEG,CAAF,GAAQ,EAAR,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWG,CAAX,CAAe,GAAf,CACLD,EAAA,CAAAA,CAAA,CAAKD,CAAL,CAASF,CAAA,CAAE,EAAF,CAETE,EAAA,CAAKD,CAAA,CAAEE,CAAF,GAAQ,EAAR,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWE,CAAX,CAAe,GAAf,CACLC,EAAA,CAAAA,CAAA,CAAKF,CAAL,CAASF,CAAA,CAAE,EAAF,CACTE,EAAA,CAAKD,CAAA,CAAEG,CAAF,GAAQ,EAAR,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWG,CAAX,CAAe,GAAf,CACLD,EAAA,CAAAA,CAAA,CAAKD,CAAL,CAASF,CAAA,CAAE,EAAF,CAETE,EAAA,CAAKD,CAAA,CAAEE,CAAF,GAAQ,EAAR,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYE,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLD,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWE,CAAX,CAAe,GAAf,CACLC,EAAA,CAAAA,CAAA,CAAKF,CAAL,CAASF,CAAA,CAAE,EAAF,CACTE,EAAA,CAAKD,CAAA,CAAEG,CAAF,GAAQ,EAAR,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,EAAjB,CAAuB,GAAvB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAYG,CAAZ,EAAiB,CAAjB,CAAsB,GAAtB,CACLF,EAAA,EAAKD,CAAA,CAAE,GAAF,CAAWG,CAAX,CAAe,GAAf,CACLD,EAAA,CAAAA,CAAA,CAAKD,CAAL,CAASF,CAAA,CAAE,EAAF,CAETD,EAAA,CAAGlB,CAAH,CAAA,CAAUuB,CAAV,CAAcJ,CAAA,CAAE,EAAF,CACdD,EAAA,CAAGlB,CAAH,CAAS,CAAT,CAAA,CAAcsB,CACd,OAAOJ,EAnHuB,CA4HlCM,QAASA,EAAa,CAACC,CAAD,CAAOC,CAAP,CAAa,CAC/B,IAD+B,IACtBtC,EAAI,CADkB,CACfuC,EAAO,CAAvB,CAA8B,CAA9B,CAA0BvC,CAA1B,CAAiC,EAAEA,CAAnC,CACIuC,CACA,CADQA,CACR,EADgB,CAChB,CADsBF,CAAA,CAAKC,CAAL,CACtB,CADmC,GACnC,CAAAA,CAAA,EAAQA,CAAR,CAAe,CAAf,EAAoBD,CAAAnC,OACxB;MAAO,CAAEsC,IAAKD,CAAP,CAAaD,KAAMA,CAAnB,CAJwB,CAanCG,QAASA,EAAI,CAACD,CAAD,CAAMT,CAAN,CAASC,CAAT,CAAY,CAMrB,IANqB,IACjBU,EAAS,CADQ,CAEjBZ,EAAK,CAAC,CAAD,CAAI,CAAJ,CAFY,CAGjBa,EAAOZ,CAAA7B,OAHU,CAIjBkB,EAAOY,CAAA9B,OAJU,CAKjB0C,CALiB,CAMZ5C,EAAI,CAAb,CAAgBA,CAAhB,CAAoB2C,CAApB,CAA0B3C,CAAA,EAA1B,CACI4C,CAEA,CAFKR,CAAA,CAAcI,CAAd,CAAmBE,CAAnB,CAEL,CADAA,CACA,CADSE,CAAAN,KACT,CAAAP,CAAA,CAAE/B,CAAF,CAAA,EAAc4C,CAAAJ,IAClB,KAAKxC,CAAL,CAAS,CAAT,CAAYA,CAAZ,CAAgB2C,CAAhB,CAAsB3C,CAAtB,EAA2B,CAA3B,CACI8B,CAEA,CAFKD,CAAA,CAAUC,CAAV,CAAc,CAAd,CAAiBC,CAAjB,CAAoBC,CAApB,CAEL,CADAD,CAAA,CAAE/B,CAAF,CACA,CADO8B,CAAA,CAAG,CAAH,CACP,CAAAC,CAAA,CAAE/B,CAAF,CAAM,CAAN,CAAA,CAAW8B,CAAA,CAAG,CAAH,CACf,KAAK9B,CAAL,CAAS,CAAT,CAAYA,CAAZ,CAAgBoB,CAAhB,CAAsBpB,CAAtB,EAA2B,CAA3B,CACI8B,CAEA,CAFKD,CAAA,CAAUC,CAAV,CAAc,CAAd,CAAiBC,CAAjB,CAAoBC,CAApB,CAEL,CADAA,CAAA,CAAEhC,CAAF,CACA,CADO8B,CAAA,CAAG,CAAH,CACP,CAAAE,CAAA,CAAEhC,CAAF,CAAM,CAAN,CAAA,CAAW8B,CAAA,CAAG,CAAH,CAjBM,CA4BzBe,QAASA,EAAO,CAACR,CAAD,CAAOG,CAAP,CAAYT,CAAZ,CAAeC,CAAf,CAAkB,CAM9B,IAN8B,IAC1BM,EAAO,CADmB,CAE1BR,EAAK,CAAC,CAAD,CAAI,CAAJ,CAFqB,CAG1Ba,EAAOZ,CAAA7B,OAHmB,CAI1BkB,EAAOY,CAAA9B,OAJmB,CAK1B0C,CAL0B,CAMrB5C,EAAI,CAAb,CAAgBA,CAAhB,CAAoB2C,CAApB,CAA0B3C,CAAA,EAA1B,CACI4C,CAEA,CAFKR,CAAA,CAAcI,CAAd,CAAmBF,CAAnB,CAEL,CADAA,CACA,CADOM,CAAAN,KACP,CAAAP,CAAA,CAAE/B,CAAF,CAAA,EAAc4C,CAAAJ,IAElB,KAAKxC,CAAL,CADAsC,CACA,CADO,CACP,CAAYtC,CAAZ,CAAgB2C,CAAhB,CAAsB3C,CAAtB,EAA2B,CAA3B,CACI4C,CAQA,CARKR,CAAA,CAAcC,CAAd,CAAoBC,CAApB,CAQL,CAPAA,CAOA,CAPOM,CAAAN,KAOP,CANAR,CAAA,CAAG,CAAH,CAMA,EANSc,CAAAJ,IAMT,CALAI,CAKA,CALKR,CAAA,CAAcC,CAAd,CAAoBC,CAApB,CAKL,CAJAA,CAIA,CAJOM,CAAAN,KAIP,CAHAR,CAAA,CAAG,CAAH,CAGA,EAHSc,CAAAJ,IAGT,CAFAV,CAEA,CAFKD,CAAA,CAAUC,CAAV,CAAc,CAAd,CAAiBC,CAAjB,CAAoBC,CAApB,CAEL,CADAD,CAAA,CAAE/B,CAAF,CACA,CADO8B,CAAA,CAAG,CAAH,CACP,CAAAC,CAAA,CAAE/B,CAAF,CAAM,CAAN,CAAA,CAAW8B,CAAA,CAAG,CAAH,CACf,KAAK9B,CAAL,CAAS,CAAT,CAAYA,CAAZ,CAAgBoB,CAAhB,CAAsBpB,CAAtB,EAA2B,CAA3B,CACI4C,CAQA,CARKR,CAAA,CAAcC,CAAd,CAAoBC,CAApB,CAQL,CAPAA,CAOA,CAPOM,CAAAN,KAOP,CANAR,CAAA,CAAG,CAAH,CAMA,EANSc,CAAAJ,IAMT,CALAI,CAKA,CALKR,CAAA,CAAcC,CAAd;AAAoBC,CAApB,CAKL,CAJAA,CAIA,CAJOM,CAAAN,KAIP,CAHAR,CAAA,CAAG,CAAH,CAGA,EAHSc,CAAAJ,IAGT,CAFAV,CAEA,CAFKD,CAAA,CAAUC,CAAV,CAAc,CAAd,CAAiBC,CAAjB,CAAoBC,CAApB,CAEL,CADAA,CAAA,CAAEhC,CAAF,CACA,CADO8B,CAAA,CAAG,CAAH,CACP,CAAAE,CAAA,CAAEhC,CAAF,CAAM,CAAN,CAAA,CAAW8B,CAAA,CAAG,CAAH,CA9Be,CA4ClCgB,QAASA,EAAM,CAACrC,CAAD,CAAIsC,CAAJ,CAAUC,CAAV,CAAkBC,CAAlB,CAA4BC,CAA5B,CAA8C,CA0CzDC,QAASA,EAAI,EAAG,CACRD,CAAJ,EACIA,CAAA,CAAiBlD,CAAjB,CAAqBgD,CAArB,CACJ,IAAIhD,CAAJ,CAAQgD,CAAR,CAEI,IADA,IAAII,EAAQC,IAAAC,IAAA,EACZ,CAAOtD,CAAP,CAAWgD,CAAX,EAIQ,EAHJhD,CAGI,EAHI,CAGJ,CAFJyC,CAAA,CAAKhC,CAAL,CAAQsB,CAAR,CAAWC,CAAX,CAEI,CADJS,CAAA,CAAKM,CAAL,CAAWhB,CAAX,CAAcC,CAAd,CACI,CAzfKuB,GAyfL,CAAAF,IAAAC,IAAA,EAAA,CAAaF,CAAb,CAJR,CAAA,EAFJ,IASO,CACH,IAAKpD,CAAL,CAAS,CAAT,CAAgB,EAAhB,CAAYA,CAAZ,CAAoBA,CAAA,EAApB,CACI,IAAKwD,CAAL,CAAS,CAAT,CAAYA,CAAZ,CAAiBC,CAAjB,EAAyB,CAAzB,CAA6BD,CAAA,EAA7B,CACI3B,CAAA,CAAU6B,CAAV,CAAiBF,CAAjB,EAAsB,CAAtB,CAAyBzB,CAAzB,CAA4BC,CAA5B,CACJ2B,EAAAA,CAAM,EACV,KAAK3D,CAAL,CAAS,CAAT,CAAYA,CAAZ,CAAgByD,CAAhB,CAAsBzD,CAAA,EAAtB,CACI2D,CAAAjD,KAAA,EAAWgD,CAAA,CAAM1D,CAAN,CAAX,EAAuB,EAAvB,CAA6B,GAA7B,IAAuC,CAAvC,CAGA,CAFA2D,CAAAjD,KAAA,EAAWgD,CAAA,CAAM1D,CAAN,CAAX,EAAuB,EAAvB,CAA6B,GAA7B,IAAuC,CAAvC,CAEA,CADA2D,CAAAjD,KAAA,EAAWgD,CAAA,CAAM1D,CAAN,CAAX,EAAuB,CAAvB,CAA4B,GAA5B,IAAsC,CAAtC,CACA,CAAA2D,CAAAjD,KAAA,EAAUgD,CAAA,CAAM1D,CAAN,CAAV,CAAqB,GAArB,IAA+B,CAA/B,CACJ,IAAIiD,CAAJ,CAAc,CACVA,CAAA,CAAS,IAAT,CAAeU,CAAf,CACA,OAFU,CAIV,MAAOA,EAdR,CAgBHV,CAAJ,EACIW,CAAA,CAAST,CAAT,CA7BQ,CA1CyC,IACrDO,EAAQG,CAAAtE,MAAA,EAD6C,CAErDkE,EAAOC,CAAAxD,OAF8C,CAGrD4D,CAGJ,IAAa,CAAb,CAAId,CAAJ,EAA2B,EAA3B,CAAkBA,CAAlB,CAA+B,CAC3Bc,CAAA,CAAMpE,KAAA,CAAM,mCAAN,CAA0CsD,CAA1C,CACN,IAAIC,CAAJ,CAAc,CACVW,CAAA,CAASX,CAAAc,KAAA,CAAc,IAAd;AAAoBD,CAApB,CAAT,CACA,OAFU,CAIV,KAAMA,EAAN,CANuB,CAQ/B,GAzekBE,EAyelB,GAAIjB,CAAA7C,OAAJ,CAAqC,CACjC4D,CAAA,CAAKpE,KAAA,CAAM,uBAAN,CAA8BqD,CAAA7C,OAA9B,CA1eS8D,QA0eT,CACL,IAAIf,CAAJ,CAAc,CACVW,CAAA,CAASX,CAAAc,KAAA,CAAc,IAAd,CAAoBD,CAApB,CAAT,CACA,OAFU,CAIV,KAAMA,EAAN,CAN6B,CAQrCd,CAAA,CAAU,CAAV,EAAeA,CAAf,GAA2B,CAtB8B,KAwBrDjB,CAxBqD,CAwBlDC,CAxBkD,CAwB/ChC,EAAI,CAxB2C,CAwBxCwD,CAGbS,WAAJ,EACIlC,CACA,CADI,IAAIkC,UAAJ,CAAeC,CAAf,CACJ,CAAAlC,CAAA,CAAI,IAAIiC,UAAJ,CAAeE,CAAf,CAFR,GAIIpC,CACA,CADImC,CAAA3E,MAAA,EACJ,CAAAyC,CAAA,CAAImC,CAAA5E,MAAA,EALR,CAQAsD,EAAA,CAAQE,CAAR,CAActC,CAAd,CAAiBsB,CAAjB,CAAoBC,CAApB,CAwCA,IAAwB,WAAxB,GAAI,MAAOiB,EAAX,CACIE,CAAA,EADJ,KAMI,KAAA,CAAA,CAAA,CACI,GAA6B,WAA7B,GAAI,OAAOvB,CAAP,CAAauB,CAAA,EAAb,CAAJ,CACI,MAAOvB,EAAP,EAAc,EAnF+B,CAiG7DwC,QAASA,EAAK,CAACjD,CAAD,CAAI4B,CAAJ,CAAUE,CAAV,CAAoBC,CAApB,CAAsC,CA+DhDmB,QAASA,EAAM,CAACC,CAAD,CAAQ,CACnB,IAAI1C,EAAM,EACVA,EAAAlB,KAAA,CAAS,IAAT,CACa,IAAb,EAAI6D,CAAJ,EACI3C,CAAAlB,KAAA,CAAS6D,CAAT,CACJ3C,EAAAlB,KAAA,CAAS,GAAT,CACa,GAAb,CAAIsC,CAAJ,EACIpB,CAAAlB,KAAA,CAAS,GAAT,CACJkB,EAAAlB,KAAA,CAASsC,CAAAwB,SAAA,EAAT,CACA5C,EAAAlB,KAAA,CAAS,GAAT,CACAkB,EAAAlB,KAAA,CAASC,CAAA,CAAc8D,CAAd,CAAqBA,CAAAvE,OAArB,CAAT,CACA0B,EAAAlB,KAAA,CAASC,CAAA,CAAc2D,CAAd,CAAqC,CAArC;AAAqBT,CAAA3D,OAArB,CAAyC,CAAzC,CAAT,CACA,OAAO0B,EAAAX,KAAA,CAAS,EAAT,CAZY,CA7DvB,GAAiB,QAAjB,GAAI,MAAOE,EAAX,EAA6C,QAA7C,GAA6B,MAAO4B,EAApC,CAAuD,CACnDe,CAAA,CAAMpE,KAAA,CAAM,qCAAN,CACN,IAAIuD,CAAJ,CAAc,CACVW,CAAA,CAASX,CAAAc,KAAA,CAAc,IAAd,CAAoBD,CAApB,CAAT,CACA,OAFU,CAKV,KAAMA,EAAN,CAP+C,CAFP,IAa5CS,CAb4C,CAarC7B,CACX,IAAuB,GAAvB,GAAIK,CAAA2B,OAAA,CAAY,CAAZ,CAAJ,EAAiD,GAAjD,GAA8B3B,CAAA2B,OAAA,CAAY,CAAZ,CAA9B,CAAsD,CAClDZ,CAAA,CAAMpE,KAAA,CAAM,wBAAN,CAA+BqD,CAAA4B,UAAA,CAAe,CAAf,CAAiB,CAAjB,CAA/B,CACN,IAAI1B,CAAJ,CAAc,CACVW,CAAA,CAASX,CAAAc,KAAA,CAAc,IAAd,CAAoBD,CAApB,CAAT,CACA,OAFU,CAKV,KAAMA,EAAN,CAP8C,CAStD,GAAuB,GAAvB,GAAIf,CAAA2B,OAAA,CAAY,CAAZ,CAAJ,CACIH,CACA,CADQK,MAAAC,aAAA,CAAoB,CAApB,CACR,CAAAnC,CAAA,CAAS,CAFb,KAGK,CACD6B,CAAA,CAAQxB,CAAA2B,OAAA,CAAY,CAAZ,CACR,IAAe,GAAf,GAAKH,CAAL,EAAgC,GAAhC,GAAsBA,CAAtB,EAAiD,GAAjD,GAAuCA,CAAvC,EAA4E,GAA5E,GAAyDxB,CAAA2B,OAAA,CAAY,CAAZ,CAAzD,CAAiF,CAC7EZ,CAAA,CAAMpE,KAAA,CAAM,yBAAN,CAAgCqD,CAAA4B,UAAA,CAAe,CAAf,CAAiB,CAAjB,CAAhC,CACN,IAAI1B,CAAJ,CAAc,CACVW,CAAA,CAASX,CAAAc,KAAA,CAAc,IAAd,CAAoBD,CAApB,CAAT,CACA,OAFU,CAIV,KAAMA,EAAN;AANyE,CAQjFpB,CAAA,CAAS,CAVR,CAcL,GAA8B,GAA9B,CAAIK,CAAA2B,OAAA,CAAYhC,CAAZ,CAAqB,CAArB,CAAJ,CAAmC,CAC/BoB,CAAA,CAAMpE,KAAA,CAAM,qBAAN,CACN,IAAIuD,CAAJ,CAAc,CACVW,CAAA,CAASX,CAAAc,KAAA,CAAc,IAAd,CAAoBD,CAApB,CAAT,CACA,OAFU,CAIV,KAAMA,EAAN,CAN2B,CAxCa,IAgD5CgB,EAAwD,EAAxDA,CAAKC,QAAA,CAAShC,CAAA4B,UAAA,CAAejC,CAAf,CAAuBA,CAAvB,CAAgC,CAAhC,CAAT,CAA6C,EAA7C,CAhDuC,CAiD5CsC,EAAKD,QAAA,CAAShC,CAAA4B,UAAA,CAAejC,CAAf,CAAwB,CAAxB,CAA2BA,CAA3B,CAAoC,CAApC,CAAT,CAAiD,EAAjD,CAjDuC,CAkD5CM,EAAS8B,CAAT9B,CAAcgC,CACdC,EAAAA,CAAYlC,CAAA4B,UAAA,CAAejC,CAAf,CAAwB,CAAxB,CAA2BA,CAA3B,CAAoC,EAApC,CAGZwC,EAAAA,CAAY9E,CAAA,CAFhBe,CAEgB,EAFF,GAAT,EAAAoD,CAAA,CAAe,MAAf,CAAwB,EAEb,EAAhB,KACIE,EAAQvD,CAAA,CAAc+D,CAAd,CAnnBMjB,EAmnBN,CAwBZ,IAAuB,WAAvB,EAAI,MAAOf,EAAX,CACI,MAAOoB,EAAA,CAAOvB,CAAA,CAAOoC,CAAP,CAAkBT,CAAlB,CAAyBzB,CAAzB,CAAP,CAIPF,EAAA,CAAOoC,CAAP,CAAkBT,CAAlB,CAAyBzB,CAAzB,CAAiC,QAAQ,CAACc,CAAD,CAAMQ,CAAN,CAAa,CAC9CR,CAAJ,CACIb,CAAA,CAASa,CAAT,CAAc,IAAd,CADJ,CAGIb,CAAA,CAAS,IAAT,CAAeoB,CAAA,CAAOC,CAAP,CAAf,CAJ8C,CAAtD,CAKGpB,CALH,CApF4C,CA/rCpD,IAAIiC,EAAS,EAAb,CAOI1F,EAAiB,IA0BrB,IAAI,CACAV,CAAA,CAAO,CAAP,CADA,CAGF,MAAOE,CAAP,CAAU,EAGZQ,CAAA,CAAiB,IAUjB0F,EAAAC,kBAAA,CAA2BC,QAAQ,CAACtG,CAAD,CAAS,CACxCU,CAAA,CAAiBV,CADuB,CAY5CoG,EAAAG,YAAA,CAAqBC,QAAQ,CAACvC,CAAD,CAASwC,CAAT,CAAsB,CAC/CxC,CAAA,CAASA,CAAT,EA4kB8ByC,EA3kB9B,IAAsB,QAAtB,GAAI,MAAOzC,EAAX,CACI,KAAMtD,MAAA,CAAM,qBAAN;AAA6B,MAAOsD,EAApC,CAA4C,IAA5C,CAAkD,MAAOwC,EAAzD,CAAN,CACS,CAAb,CAAIxC,CAAJ,CACIA,CADJ,CACa,CADb,CAEkB,EAFlB,CAESA,CAFT,GAGIA,CAHJ,CAGa,EAHb,CAIA,KAAID,EAAO,EACXA,EAAArC,KAAA,CAAU,MAAV,CACa,GAAb,CAAIsC,CAAJ,EACID,CAAArC,KAAA,CAAU,GAAV,CACJqC,EAAArC,KAAA,CAAUsC,CAAAwB,SAAA,EAAV,CACAzB,EAAArC,KAAA,CAAU,GAAV,CACAqC,EAAArC,KAAA,CAAUC,CAAA,CAAc5B,CAAA,CAwjBNiF,EAxjBM,CAAd,CAwjBQA,EAxjBR,CAAV,CACA,OAAOjB,EAAA9B,KAAA,CAAU,EAAV,CAfwC,CA2BnDkE,EAAAO,QAAA,CAAiBC,QAAQ,CAAC3C,CAAD,CAASwC,CAAT,CAAsBvC,CAAtB,CAAgC,CAYrD2C,QAASA,EAAM,CAAC3C,CAAD,CAAW,CACtBW,CAAA,CAAS,QAAQ,EAAG,CAChB,GAAI,CACAX,CAAA,CAAS,IAAT,CAAekC,CAAAG,YAAA,CAAmBtC,CAAnB,CAAf,CADA,CAEF,MAAOc,CAAP,CAAY,CACVb,CAAA,CAASa,CAAT,CADU,CAHE,CAApB,CADsB,CAXC,UAA3B,GAAI,MAAO0B,EAAX,GACIvC,CACA,CADWuC,CACX,CAAAA,CAAA,CAAcK,IAAAA,EAFlB,CAGsB,WAAtB,GAAI,MAAO7C,EAAX,GACIC,CACA,CADWD,CACX,CAAAA,CAAA,CAAS6C,IAAAA,EAFb,CAGA,IAAsB,WAAtB,GAAI,MAAO7C,EAAX,CACIA,CAAA,CA0iB0ByC,EA3iB9B,KAEK,IAAsB,QAAtB,GAAI,MAAOzC,EAAX,CACD,KAAMtD,MAAA,CAAM,qBAAN,CAA6B,MAAOsD,EAApC,CAAN,CAYJ,GAAIC,CAAJ,CAAc,CACV,GAAwB,UAAxB,GAAI,MAAOA,EAAX,CACI,KAAMvD,MAAA,CAAM,oBAAN;AAA2B,MAAOuD,EAAlC,CAAN,CACJ2C,CAAA,CAAO3C,CAAP,CAHU,CAAd,IAKI,OAAO,KAAI6C,OAAJ,CAAY,QAAQ,CAACC,CAAD,CAAUC,CAAV,CAAkB,CACzCJ,CAAA,CAAO,QAAQ,CAAC9B,CAAD,CAAMlC,CAAN,CAAW,CAClBkC,CAAJ,CACIkC,CAAA,CAAOlC,CAAP,CADJ,CAIAiC,CAAA,CAAQnE,CAAR,CALsB,CAA1B,CADyC,CAAtC,CA3B0C,CA6CzDuD,EAAAc,SAAA,CAAkBC,QAAQ,CAAC/E,CAAD,CAAI4B,CAAJ,CAAU,CACZ,WAApB,GAAI,MAAOA,EAAX,GACIA,CADJ,CAogB8B0C,EApgB9B,CAEoB,SAApB,GAAI,MAAO1C,EAAX,GACIA,CADJ,CACWoC,CAAAG,YAAA,CAAmBvC,CAAnB,CADX,CAEA,IAAiB,QAAjB,GAAI,MAAO5B,EAAX,EAA6C,QAA7C,GAA6B,MAAO4B,EAApC,CACI,KAAMrD,MAAA,CAAM,qBAAN,CAA6B,MAAOyB,EAApC,CAAuC,IAAvC,CAA6C,MAAO4B,EAApD,CAAN,CACJ,MAAOqB,EAAA,CAAMjD,CAAN,CAAS4B,CAAT,CAPyB,CAqBpCoC,EAAAgB,KAAA,CAAcC,QAAQ,CAACjF,CAAD,CAAI4B,CAAJ,CAAUE,CAAV,CAAoBC,CAApB,CAAsC,CAExD0C,QAASA,EAAM,CAAC3C,CAAD,CAAW,CACL,QAAjB,GAAI,MAAO9B,EAAX,EAA6C,QAA7C,GAA6B,MAAO4B,EAApC,CACIoC,CAAAO,QAAA,CAAe3C,CAAf,CAAqB,QAAQ,CAACe,CAAD,CAAMf,CAAN,CAAY,CACrCqB,CAAA,CAAMjD,CAAN,CAAS4B,CAAT,CAAeE,CAAf,CAAyBC,CAAzB,CADqC,CAAzC,CADJ,CAIsB,QAAjB,GAAI,MAAO/B,EAAX,EAA6C,QAA7C,GAA6B,MAAO4B,EAApC,CACDqB,CAAA,CAAMjD,CAAN,CAAS4B,CAAT,CAAeE,CAAf,CAAyBC,CAAzB,CADC,CAGDU,CAAA,CAASX,CAAAc,KAAA,CAAc,IAAd,CAAoBrE,KAAA,CAAM,qBAAN;AAA6B,MAAOyB,EAApC,CAAuC,IAAvC,CAA6C,MAAO4B,EAApD,CAApB,CAAT,CARkB,CAW1B,GAAIE,CAAJ,CAAc,CACV,GAAwB,UAAxB,GAAI,MAAOA,EAAX,CACI,KAAMvD,MAAA,CAAM,oBAAN,CAA2B,MAAOuD,EAAlC,CAAN,CACJ2C,CAAA,CAAO3C,CAAP,CAHU,CAAd,IAKI,OAAO,KAAI6C,OAAJ,CAAY,QAAQ,CAACC,CAAD,CAAUC,CAAV,CAAkB,CACzCJ,CAAA,CAAO,QAAQ,CAAC9B,CAAD,CAAMlC,CAAN,CAAW,CAClBkC,CAAJ,CACIkC,CAAA,CAAOlC,CAAP,CADJ,CAIAiC,CAAA,CAAQnE,CAAR,CALsB,CAA1B,CADyC,CAAtC,CAlB6C,CA2D5DuD,EAAAkB,YAAA,CAAqBC,QAAQ,CAACnF,CAAD,CAAIgF,CAAJ,CAAU,CACnC,GAAiB,QAAjB,GAAI,MAAOhF,EAAX,EAA6C,QAA7C,GAA6B,MAAOgF,EAApC,CACI,KAAMzG,MAAA,CAAM,qBAAN,CAA6B,MAAOyB,EAApC,CAAuC,IAAvC,CAA6C,MAAOgF,EAApD,CAAN,CACJ,MAAoB,GAApB,GAAIA,CAAAjG,OAAJ,CACW,CAAA,CADX,CAEOP,CAAA,CAAkBwF,CAAAc,SAAA,CAAgB9E,CAAhB,CAAmBgF,CAAAI,OAAA,CAAY,CAAZ,CAAeJ,CAAAjG,OAAf,CAA2B,EAA3B,CAAnB,CAAlB,CAAsEiG,CAAtE,CAL4B,CAmBvChB,EAAAqB,QAAA,CAAiBC,QAAQ,CAACtF,CAAD,CAAIgF,CAAJ,CAAUlD,CAAV,CAAoBC,CAApB,CAAsC,CAE3D0C,QAASA,EAAM,CAAC3C,CAAD,CAAW,CACL,QAAjB,GAAI,MAAO9B,EAAX,EAA6C,QAA7C,GAA6B,MAAOgF,EAApC,CACIvC,CAAA,CAASX,CAAAc,KAAA,CAAc,IAAd,CAAoBrE,KAAA,CAAM,qBAAN,CAA6B,MAAOyB,EAApC;AAAuC,IAAvC,CAA6C,MAAOgF,EAApD,CAApB,CAAT,CADJ,CAIoB,EAApB,GAAIA,CAAAjG,OAAJ,CACI0D,CAAA,CAASX,CAAAc,KAAA,CAAc,IAAd,CAAoB,IAApB,CAA0B,CAAA,CAA1B,CAAT,CADJ,CAIAoB,CAAAgB,KAAA,CAAYhF,CAAZ,CAAegF,CAAAI,OAAA,CAAY,CAAZ,CAAe,EAAf,CAAf,CAAmC,QAAQ,CAACzC,CAAD,CAAM4C,CAAN,CAAY,CAC/C5C,CAAJ,CACIb,CAAA,CAASa,CAAT,CADJ,CAGIb,CAAA,CAAS,IAAT,CAAetD,CAAA,CAAkB+G,CAAlB,CAAwBP,CAAxB,CAAf,CAJ+C,CAAvD,CAKGjD,CALH,CATsB,CAiB1B,GAAID,CAAJ,CAAc,CACV,GAAwB,UAAxB,GAAI,MAAOA,EAAX,CACI,KAAMvD,MAAA,CAAM,oBAAN,CAA2B,MAAOuD,EAAlC,CAAN,CACJ2C,CAAA,CAAO3C,CAAP,CAHU,CAAd,IAKI,OAAO,KAAI6C,OAAJ,CAAY,QAAQ,CAACC,CAAD,CAAUC,CAAV,CAAkB,CACzCJ,CAAA,CAAO,QAAQ,CAAC9B,CAAD,CAAMlC,CAAN,CAAW,CAClBkC,CAAJ,CACIkC,CAAA,CAAOlC,CAAP,CADJ,CAIAiC,CAAA,CAAQnE,CAAR,CALsB,CAA1B,CADyC,CAAtC,CAxBgD,CA0C/DuD,EAAAwB,UAAA,CAAmBC,QAAQ,CAACT,CAAD,CAAO,CAC9B,GAAoB,QAApB,GAAI,MAAOA,EAAX,CACI,KAAMzG,MAAA,CAAM,qBAAN,CAA6B,MAAOyG,EAApC,CAAN,CACJ,MAAOpB,SAAA,CAASoB,CAAAU,MAAA,CAAW,GAAX,CAAA,CAAgB,CAAhB,CAAT,CAA6B,EAA7B,CAHuB,CAalC1B,EAAA2B,QAAA,CAAiBC,QAAQ,CAACZ,CAAD,CAAO,CAC5B,GAAoB,QAApB,GAAI,MAAOA,EAAX,CACI,KAAMzG,MAAA,CAAM,qBAAN,CAA6B,MAAOyG,EAApC,CAAN,CACJ,GAAoB,EAApB,GAAIA,CAAAjG,OAAJ,CACI,KAAMR,MAAA,CAAM,uBAAN;AAA8ByG,CAAAjG,OAA9B,CAA0C,QAA1C,CAAN,CACJ,MAAOiG,EAAAxB,UAAA,CAAe,CAAf,CAAkB,EAAlB,CALqB,CAchC,KAAIf,EAA8B,WAAnB,GAAA,MAAOoD,QAAP,EAAkCA,OAAlC,EAAyE,UAAzE,GAA6C,MAAOA,QAAApD,SAApD,CACgB,UAAxB,GAAA,MAAOqD,aAAP,CAAqCA,YAArC,CAAoDD,OAAApD,SAD5C,CAETsD,UAFN,CA8BIlG,EAAc,kEAAA,MAAA,CAAA,EAAA,CA9BlB,CAqCIQ,EAAe,CAAE,EAAF,CAAM,EAAN,CAAU,EAAV,CAAc,EAAd,CAAkB,EAAlB,CAAsB,EAAtB,CAA0B,EAA1B,CAA8B,EAA9B,CAAkC,EAAlC,CAAsC,EAAtC,CAA0C,EAA1C,CAA8C,EAA9C,CAAkD,EAAlD,CACd,EADc,CACV,EADU,CACN,EADM,CACF,EADE,CACE,EADF,CACM,EADN,CACU,EADV,CACc,EADd,CACkB,EADlB,CACsB,EADtB,CAC0B,EAD1B,CAC8B,EAD9B,CACkC,EADlC,CACsC,EADtC,CAC0C,EAD1C,CAC8C,EAD9C,CACkD,EADlD,CAEd,EAFc,CAEV,EAFU,CAEN,EAFM,CAEF,EAFE,CAEE,EAFF,CAEM,EAFN,CAEU,EAFV,CAEc,EAFd,CAEkB,EAFlB,CAEsB,EAFtB,CAE0B,EAF1B,CAE8B,EAF9B,CAEkC,EAFlC,CAEsC,EAFtC,CAE0C,EAF1C,CAE8C,EAF9C,CAEiD,CAFjD,CAGf,CAHe,CAGZ,EAHY,CAGR,EAHQ,CAGJ,EAHI,CAGA,EAHA,CAGI,EAHJ,CAGQ,EAHR,CAGY,EAHZ,CAGgB,EAHhB,CAGoB,EAHpB,CAGwB,EAHxB,CAG6B,EAH7B,CAGiC,EAHjC,CAGqC,EAHrC,CAGyC,EAHzC,CAG6C,EAH7C,CAGiD,EAHjD,CAId,EAJc,CAIX,CAJW,CAIR,CAJQ,CAIL,CAJK,CAIF,CAJE,CAIC,CAJD,CAII,CAJJ,CAIO,CAJP,CAIU,CAJV,CAIa,EAJb,CAIiB,EAJjB,CAIqB,EAJrB;AAIyB,EAJzB,CAI6B,EAJ7B,CAIiC,EAJjC,CAIqC,EAJrC,CAIyC,EAJzC,CAI6C,EAJ7C,CAIiD,EAJjD,CAKf,EALe,CAKX,EALW,CAKP,EALO,CAKH,EALG,CAKC,EALD,CAKK,EALL,CAKS,EALT,CAKa,EALb,CAKkB,EALlB,CAKsB,EALtB,CAK0B,EAL1B,CAK8B,EAL9B,CAKkC,EALlC,CAKsC,EALtC,CAKyC,EALzC,CAK6C,EAL7C,CAKiD,EALjD,CAMf,EANe,CAMX,EANW,CAMP,EANO,CAMH,EANG,CAMC,EAND,CAMK,EANL,CAMS,EANT,CAMa,EANb,CAMiB,EANjB,CAMqB,EANrB,CAMyB,EANzB,CAM6B,EAN7B,CAMiC,EANjC,CAMqC,EANrC,CAMyC,EANzC,CAM6C,EAN7C,CAMiD,EANjD,CAOf,EAPe,CAOX,EAPW,CAOP,EAPO,CAOH,EAPG,CAOC,EAPD,CAOK,EAPL,CAOU,EAPV,CAOc,EAPd,CAOkB,EAPlB,CAOsB,EAPtB,CAO0B,EAP1B,CArCnB,CAkDIC,EAAqBmD,MAAAC,aAlDzB,CA+IItE,EAAO,QAAQ,EAAG,CAQlB,IAAIA,EAAO,CAON,cAAgB,OAPV,CAeN,WAAa4G,QAAQ,CAACC,CAAD,CAAMC,CAAN,CAAW,CACjC,IAAIC,EAAK,IACU,SAAnB,GAAI,MAAOF,EAAX,GACIE,CACA,CADKF,CACL,CAAAA,CAAA,CAAMA,QAAQ,EAAG,CAAE,MAAO,KAAT,CAFrB,CAGA,KAAA,CAAc,IAAd,GAAOE,CAAP,EAAuC,IAAvC,IAAuBA,CAAvB,CAA4BF,CAAA,EAA5B,EAAA,CACa,GAAT,CAAIE,CAAJ,CACID,CAAA,CAAIC,CAAJ,CAAO,GAAP,CADJ,EAEc,IAAT,CAAIA,CAAJ,CACDD,CAAA,CAAMC,CAAN,EAAU,CAAV,CAAa,EAAb,CAAmB,GAAnB,CADC,EAGS,KAAT,CAAIA,CAAJ,CACDD,CAAA,CAAMC,CAAN,EAAU,EAAV,CAAc,EAAd,CAAoB,GAApB,CADC,EAKDD,CAAA,CAAMC,CAAN,EAAU,EAAV,CAAc,CAAd,CAAoB,GAApB,CACA,CAAAD,CAAA,CAAMC,CAAN,EAAU,EAAV,CAAc,EAAd,CAAoB,GAApB,CANC,CAED,CAAAD,CAAA,CAAMC,CAAN,EAAU,CAAV,CAAa,EAAb,CAAmB,GAAnB,CALC,CAED,CAAAD,CAAA,CAAKC,CAAL,CAAQ,EAAR,CAAc,GAAd,CAJJ,CAcA,CAAAA,CAAA,CAAK,IApBwB,CAf1B,CAgDN,WAAaC,QAAQ,CAACH,CAAD,CAAMC,CAAN,CAAW,CAQjC,IARiC,IAC7BnI,CAD6B;AAC1BuB,CAD0B,CACvB+G,CADuB,CACpBC,CADoB,CACjBC,EAAOA,QAAQ,CAACjH,CAAD,CAAI,CAC/BA,CAAA,CAAIA,CAAAlB,MAAA,CAAQ,CAAR,CAAWkB,CAAAkH,QAAA,CAAU,IAAV,CAAX,CACJ,KAAI7D,EAAMpE,KAAA,CAAMe,CAAA+D,SAAA,EAAN,CACVV,EAAA8D,KAAA,CAAW,gBACX9D,EAAA,MAAA,CAAerD,CACf,MAAMqD,EAAN,CAL+B,CAOnC,CAAuB,IAAvB,IAAQ5E,CAAR,CAAYkI,CAAA,EAAZ,EAAA,CACI,GAAiB,CAAjB,IAAKlI,CAAL,CAAO,GAAP,EACImI,CAAA,CAAInI,CAAJ,CADJ,KAEK,IAAiB,GAAjB,IAAKA,CAAL,CAAO,GAAP,EACgB,IACjB,IADEuB,CACF,CADM2G,CAAA,EACN,GAD0BM,CAAA,CAAK,CAACxI,CAAD,CAAIuB,CAAJ,CAAL,CAC1B,CAAA4G,CAAA,EAAMnI,CAAN,CAAQ,EAAR,GAAe,CAAf,CAAqBuB,CAArB,CAAuB,EAAvB,CAFC,KAGA,IAAiB,GAAjB,IAAKvB,CAAL,CAAO,GAAP,EACc,IACf,IADEuB,CACF,CADI2G,CAAA,EACJ,GADqC,IACrC,IADwBI,CACxB,CAD0BJ,CAAA,EAC1B,GAD8CM,CAAA,CAAK,CAACxI,CAAD,CAAIuB,CAAJ,CAAO+G,CAAP,CAAL,CAC9C,CAAAH,CAAA,EAAMnI,CAAN,CAAQ,EAAR,GAAe,EAAf,EAAuBuB,CAAvB,CAAyB,EAAzB,GAAgC,CAAhC,CAAsC+G,CAAtC,CAAwC,EAAxC,CAFC,KAGA,IAAiB,GAAjB,IAAKtI,CAAL,CAAO,GAAP,EACc,IACf,IADEuB,CACF,CADI2G,CAAA,EACJ,GADqC,IACrC,IADwBI,CACxB,CAD0BJ,CAAA,EAC1B,GAD2D,IAC3D,IAD8CK,CAC9C,CADgDL,CAAA,EAChD,GADoEM,CAAA,CAAK,CAACxI,CAAD,CAAIuB,CAAJ,CAAO+G,CAAP,CAAUC,CAAV,CAAL,CACpE,CAAAJ,CAAA,EAAMnI,CAAN,CAAQ,CAAR,GAAe,EAAf,EAAuBuB,CAAvB,CAAyB,EAAzB,GAAgC,EAAhC,EAAwC+G,CAAxC,CAA0C,EAA1C,GAAiD,CAAjD,CAAuDC,CAAvD,CAAyD,EAAzD,CAFC,KAGA,MAAMI,WAAA,CAAW,yBAAX,CAAqC3I,CAArC,CAAN,CApBwB,CAhD1B,CA+EN,YAAc4I,QAAQ,CAACV,CAAD;AAAMC,CAAN,CAAW,CAElC,IAFkC,IAC9BvG,CAD8B,CAC1BC,EAAK,IACb,CAC4C,IAD5C,IACSD,CADT,CACqB,IAAP,GAAAC,CAAA,CAAcA,CAAd,CAAmBqG,CAAA,EADjC,EAAA,CAGc,KAAV,EAAItG,CAAJ,EAA0B,KAA1B,EAAoBA,CAApB,EACyB,IADzB,IACSC,CADT,CACcqG,CAAA,EADd,GAEkB,KAFlB,EAEYrG,CAFZ,EAEkC,KAFlC,EAE4BA,CAF5B,EAGYsG,CAAA,CAAgB,IAAhB,EAAKvG,CAAL,CAAQ,KAAR,EAAsBC,CAAtB,CAAyB,KAAzB,CAAgC,KAAhC,CACA,CAAAA,CAAA,CAAK,IAJjB,EAQAsG,CAAA,CAAIvG,CAAJ,CAEO,KAAX,GAAIC,CAAJ,EAAiBsG,CAAA,CAAItG,CAAJ,CAfiB,CA/E3B,CAwGN,YAAcgH,QAAQ,CAACX,CAAD,CAAMC,CAAN,CAAW,CAClC,IAAIC,EAAK,IACU,SAAnB,GAAI,MAAOF,EAAX,GACIE,CAAU,CAALF,CAAK,CAAAA,CAAA,CAAMA,QAAQ,EAAG,CAAE,MAAO,KAAT,CAD/B,CAEA,KAAA,CAAc,IAAd,GAAOE,CAAP,EAAuC,IAAvC,IAAuBA,CAAvB,CAA4BF,CAAA,EAA5B,EAAA,CACc,KAAV,EAAIE,CAAJ,CACID,CAAA,CAAIC,CAAJ,CADJ,EAGIA,CAEA,EAFM,KAEN,CADAD,CAAA,EAAKC,CAAL,EAAS,EAAT,EAAa,KAAb,CACA,CAAAD,CAAA,CAAKC,CAAL,CAAQ,IAAR,CAAe,KAAf,CALJ,CAMA,CAAAA,CAAA,CAAK,IAXyB,CAxG3B,CA6HN,kBAAoBU,QAAQ,CAACZ,CAAD,CAAMC,CAAN,CAAW,CACxC9G,CAAA0H,YAAA,CAAiBb,CAAjB,CAAsB,QAAQ,CAACE,CAAD,CAAK,CAC/B/G,CAAA2H,WAAA,CAAgBZ,CAAhB,CAAoBD,CAApB,CAD+B,CAAnC,CADwC,CA7HjC,CA2IN,kBAAoBc,QAAQ,CAACf,CAAD,CAAMC,CAAN,CAAW,CACxC9G,CAAA6H,WAAA,CAAgBhB,CAAhB,CAAqB,QAAQ,CAACE,CAAD,CAAK,CAC9B/G,CAAA8H,YAAA,CAAiBf,CAAjB;AAAqBD,CAArB,CAD8B,CAAlC,CADwC,CA3IjC,CAsJN,mBAAqBiB,QAAQ,CAAChB,CAAD,CAAK,CACnC,MAAa,IAAN,CAACA,CAAD,CAAc,CAAd,CAAwB,IAAN,CAACA,CAAD,CAAe,CAAf,CAAyB,KAAN,CAACA,CAAD,CAAiB,CAAjB,CAAqB,CAD9B,CAtJ5B,CAgKN,cAAgBiB,QAAQ,CAACnB,CAAD,CAAM,CAE/B,IAF+B,IAC3BE,CAD2B,CACvBpF,EAAE,CACV,CAAwB,IAAxB,IAAQoF,CAAR,CAAaF,CAAA,EAAb,EAAA,CACIlF,CAAA,EAAK3B,CAAAiI,mBAAA,CAAwBlB,CAAxB,CACT,OAAOpF,EAJwB,CAhKxB,CA6KN,qBAAuBuG,QAAQ,CAACrB,CAAD,CAAM,CAAA,IAClCnF,EAAE,CADgC,CAC7BC,EAAE,CACX3B,EAAA0H,YAAA,CAAiBb,CAAjB,CAAsB,QAAQ,CAACE,CAAD,CAAK,CAC/B,EAAErF,CAAGC,EAAA,EAAK3B,CAAAiI,mBAAA,CAAwBlB,CAAxB,CADqB,CAAnC,CAGA,OAAO,CAACrF,CAAD,CAAGC,CAAH,CAL+B,CA7K/B,CAqLX,OAAO3B,EA7LW,CAAX,EAgMX8C,KAAAC,IAAA,CAAWD,IAAAC,IAAX,EAAuB,QAAQ,EAAG,CAAE,MAAO,CAAC,IAAID,IAAd,CAmClC,KAAIa,EAAS,CACT,SADS,CACG,UADH,CACe,SADf,CAC2B,QAD3B,CACuC,UADvC,CAET,SAFS,CAEG,SAFH,CAEe,UAFf,CAE2B,UAF3B,CAEuC,SAFvC,CAGT,UAHS,CAGG,SAHH,CAGe,UAHf,CAG2B,UAH3B,CAGuC,UAHvC;AAIT,UAJS,CAIG,UAJH,CAIe,UAJf,CAAb,CAYIC,EAAS,CACT,UADS,CACG,UADH,CACe,SADf,CAC2B,UAD3B,CACuC,UADvC,CAET,UAFS,CAEG,UAFH,CAEe,UAFf,CAE2B,SAF3B,CAEuC,UAFvC,CAGT,SAHS,CAGG,UAHH,CAGe,UAHf,CAG2B,UAH3B,CAGuC,UAHvC,CAIT,UAJS,CAIG,SAJH,CAIe,UAJf,CAI2B,UAJ3B,CAIuC,UAJvC,CAKT,UALS,CAKG,UALH,CAKe,UALf,CAK2B,SAL3B,CAKuC,UALvC,CAMT,SANS,CAMG,UANH,CAMe,UANf,CAM2B,UAN3B,CAMuC,UANvC,CAOT,UAPS,CAOG,UAPH,CAOe,UAPf,CAO2B,UAP3B,CAOuC,UAPvC,CAQT,UARS,CAQG,UARH,CAQe,UARf,CAQ2B,UAR3B,CAQuC,UARvC,CAST,UATS,CASG,SATH,CASe,UATf;AAS2B,SAT3B,CASuC,UATvC,CAUT,UAVS,CAUG,UAVH,CAUe,UAVf,CAU2B,SAV3B,CAUuC,UAVvC,CAWT,UAXS,CAWG,UAXH,CAWe,UAXf,CAW2B,UAX3B,CAWuC,UAXvC,CAYT,SAZS,CAYG,SAZH,CAYe,UAZf,CAY2B,UAZ3B,CAYuC,UAZvC,CAaT,UAbS,CAaG,UAbH,CAae,UAbf,CAa2B,UAb3B,CAauC,UAbvC,CAcT,UAdS,CAcG,UAdH,CAce,UAdf,CAc2B,SAd3B,CAcuC,UAdvC,CAeT,SAfS,CAeG,UAfH,CAee,SAff,CAe2B,UAf3B,CAeuC,UAfvC,CAgBT,UAhBS,CAgBG,SAhBH,CAgBe,UAhBf,CAgB2B,UAhB3B,CAgBuC,UAhBvC,CAiBT,UAjBS,CAiBG,UAjBH,CAiBe,UAjBf,CAiB2B,UAjB3B,CAiBuC,UAjBvC,CAkBT,SAlBS,CAkBG,UAlBH,CAkBe,UAlBf,CAkB2B,UAlB3B,CAkBuC,SAlBvC;AAmBT,UAnBS,CAmBG,UAnBH,CAmBe,UAnBf,CAmB2B,UAnB3B,CAmBuC,UAnBvC,CAoBT,SApBS,CAoBG,UApBH,CAoBe,UApBf,CAoB2B,UApB3B,CAoBuC,UApBvC,CAqBT,UArBS,CAqBG,SArBH,CAqBe,SArBf,CAqB2B,UArB3B,CAqBuC,SArBvC,CAsBT,UAtBS,CAsBG,UAtBH,CAsBe,UAtBf,CAsB2B,SAtB3B,CAsBuC,UAtBvC,CAuBT,SAvBS,CAuBG,UAvBH,CAuBe,UAvBf,CAuB2B,UAvB3B,CAuBuC,UAvBvC,CAwBT,QAxBS,CAwBG,UAxBH,CAwBe,UAxBf,CAwB2B,UAxB3B,CAwBuC,SAxBvC,CAyBT,UAzBS,CAyBG,UAzBH,CAyBe,SAzBf,CAyB2B,SAzB3B,CAyBuC,UAzBvC,CA0BT,UA1BS,CA0BG,UA1BH,CA0Be,UA1Bf,CA0B2B,UA1B3B,CA0BuC,UA1BvC,CA2BT,UA3BS,CA2BG,SA3BH,CA2Be,UA3Bf,CA2B2B,UA3B3B,CA2BuC,UA3BvC,CA4BT,UA5BS,CA4BG,UA5BH;AA4Be,SA5Bf,CA4B2B,UA5B3B,CA4BuC,UA5BvC,CA6BT,UA7BS,CA6BG,UA7BH,CA6Be,UA7Bf,CA6B2B,UA7B3B,CA6BuC,UA7BvC,CA8BT,UA9BS,CA8BG,SA9BH,CA8Be,UA9Bf,CA8B2B,SA9B3B,CA8BuC,UA9BvC,CA+BT,UA/BS,CA+BG,UA/BH,CA+Be,UA/Bf,CA+B2B,UA/B3B,CA+BuC,SA/BvC,CAgCT,UAhCS,CAgCG,UAhCH,CAgCe,SAhCf,CAgC2B,UAhC3B,CAgCuC,UAhCvC,CAiCT,UAjCS,CAiCG,UAjCH,CAiCe,UAjCf,CAiC2B,UAjC3B,CAiCuC,SAjCvC,CAkCT,UAlCS,CAkCG,UAlCH,CAkCe,SAlCf,CAkC2B,UAlC3B,CAkCuC,UAlCvC,CAmCT,UAnCS,CAmCG,UAnCH,CAmCe,UAnCf,CAmC2B,UAnC3B,CAmCuC,UAnCvC,CAoCT,UApCS,CAoCG,UApCH,CAoCe,SApCf,CAoC2B,UApC3B,CAoCuC,SApCvC,CAqCT,UArCS,CAqCG,UArCH,CAqCe,UArCf,CAqC2B,UArC3B;AAqCuC,UArCvC,CAsCT,UAtCS,CAsCG,UAtCH,CAsCe,UAtCf,CAsC2B,UAtC3B,CAsCuC,UAtCvC,CAuCT,UAvCS,CAuCG,UAvCH,CAuCe,UAvCf,CAuC2B,UAvC3B,CAuCuC,UAvCvC,CAwCT,UAxCS,CAwCG,SAxCH,CAwCe,UAxCf,CAwC2B,UAxC3B,CAwCuC,UAxCvC,CAyCT,UAzCS,CAyCG,UAzCH,CAyCe,SAzCf,CAyC2B,UAzC3B,CAyCuC,UAzCvC,CA0CT,UA1CS,CA0CG,UA1CH,CA0Ce,UA1Cf,CA0C2B,SA1C3B,CA0CuC,UA1CvC,CA2CT,UA3CS,CA2CG,SA3CH,CA2Ce,UA3Cf,CA2C2B,UA3C3B,CA2CuC,UA3CvC,CA4CT,UA5CS,CA4CG,UA5CH,CA4Ce,UA5Cf,CA4C2B,UA5C3B,CA4CuC,UA5CvC,CA6CT,OA7CS,CA6CG,SA7CH,CA6Ce,SA7Cf,CA6C2B,UA7C3B,CA6CuC,SA7CvC,CA8CT,UA9CS,CA8CG,UA9CH,CA8Ce,UA9Cf,CA8C2B,UA9C3B,CA8CuC,UA9CvC,CA+CT,SA/CS;AA+CG,QA/CH,CA+Ce,UA/Cf,CA+C2B,UA/C3B,CA+CuC,SA/CvC,CAgDT,UAhDS,CAgDG,UAhDH,CAgDe,UAhDf,CAgD2B,SAhD3B,CAgDuC,UAhDvC,CAiDT,UAjDS,CAiDG,UAjDH,CAiDe,SAjDf,CAiD2B,UAjD3B,CAiDuC,SAjDvC,CAkDT,UAlDS,CAkDG,UAlDH,CAkDe,SAlDf,CAkD2B,UAlD3B,CAkDuC,UAlDvC,CAmDT,UAnDS,CAmDG,UAnDH,CAmDe,UAnDf,CAmD2B,UAnD3B,CAmDuC,SAnDvC,CAoDT,UApDS,CAoDG,UApDH,CAoDe,UApDf,CAoD2B,UApD3B,CAoDuC,UApDvC,CAqDT,QArDS,CAqDG,UArDH,CAqDe,UArDf,CAqD2B,UArD3B,CAqDuC,UArDvC,CAsDT,UAtDS,CAsDG,UAtDH,CAsDe,UAtDf,CAsD2B,SAtD3B,CAsDuC,UAtDvC,CAuDT,UAvDS,CAuDG,UAvDH,CAuDe,UAvDf,CAuD2B,UAvD3B,CAuDuC,UAvDvC,CAwDT,UAxDS,CAwDG,UAxDH,CAwDe,UAxDf;AAwD2B,UAxD3B,CAwDuC,UAxDvC,CAyDT,UAzDS,CAyDG,UAzDH,CAyDe,UAzDf,CAyD2B,QAzD3B,CAyDuC,SAzDvC,CA0DT,UA1DS,CA0DG,UA1DH,CA0De,UA1Df,CA0D2B,UA1D3B,CA0DuC,UA1DvC,CA2DT,UA3DS,CA2DG,UA3DH,CA2De,UA3Df,CA2D2B,UA3D3B,CA2DuC,UA3DvC,CA4DT,UA5DS,CA4DG,UA5DH,CA4De,UA5Df,CA4D2B,UA5D3B,CA4DuC,QA5DvC,CA6DT,UA7DS,CA6DG,UA7DH,CA6De,SA7Df,CA6D2B,UA7D3B,CA6DuC,UA7DvC,CA8DT,UA9DS,CA8DG,UA9DH,CA8De,SA9Df,CA8D2B,SA9D3B,CA8DuC,SA9DvC,CA+DT,UA/DS,CA+DG,UA/DH,CA+De,UA/Df,CA+D2B,SA/D3B,CA+DuC,UA/DvC,CAgET,UAhES,CAgEG,UAhEH,CAgEe,UAhEf,CAgE2B,SAhE3B,CAgEuC,SAhEvC,CAiET,UAjES,CAiEG,UAjEH,CAiEe,UAjEf,CAiE2B,UAjE3B,CAiEuC,SAjEvC;AAkET,SAlES,CAkEG,UAlEH,CAkEe,UAlEf,CAkE2B,UAlE3B,CAkEuC,UAlEvC,CAmET,UAnES,CAmEG,UAnEH,CAmEe,UAnEf,CAmE2B,SAnE3B,CAmEuC,UAnEvC,CAoET,UApES,CAoEG,UApEH,CAoEe,UApEf,CAoE2B,UApE3B,CAoEuC,UApEvC,CAqET,UArES,CAqEG,UArEH,CAqEe,UArEf,CAqE2B,UArE3B,CAqEuC,UArEvC,CAsET,SAtES,CAsEG,UAtEH,CAsEe,SAtEf,CAsE2B,SAtE3B,CAsEuC,SAtEvC,CAuET,UAvES,CAuEG,SAvEH,CAuEe,UAvEf,CAuE2B,SAvE3B,CAuEuC,UAvEvC,CAwET,UAxES,CAwEG,QAxEH,CAwEe,UAxEf,CAwE2B,UAxE3B,CAwEuC,UAxEvC,CAyET,UAzES,CAyEG,UAzEH,CAyEe,UAzEf,CAyE2B,SAzE3B,CAyEuC,UAzEvC,CA0ET,UA1ES,CA0EG,UA1EH,CA0Ee,UA1Ef,CA0E2B,UA1E3B,CA0EuC,UA1EvC,CA2ET,SA3ES,CA2EG,UA3EH;AA2Ee,UA3Ef,CA2E2B,UA3E3B,CA2EuC,SA3EvC,CA4ET,UA5ES,CA4EG,UA5EH,CA4Ee,UA5Ef,CA4E2B,UA5E3B,CA4EuC,SA5EvC,CA6ET,UA7ES,CA6EG,SA7EH,CA6Ee,SA7Ef,CA6E2B,SA7E3B,CA6EuC,UA7EvC,CA8ET,UA9ES,CA8EG,UA9EH,CA8Ee,UA9Ef,CA8E2B,UA9E3B,CA8EuC,UA9EvC,CA+ET,UA/ES,CA+EG,QA/EH,CA+Ee,UA/Ef,CA+E2B,UA/E3B,CA+EuC,UA/EvC,CAgFT,UAhFS,CAgFG,UAhFH,CAgFe,UAhFf,CAgF2B,SAhF3B,CAgFuC,UAhFvC,CAiFT,SAjFS,CAiFG,SAjFH,CAiFe,UAjFf,CAiF2B,UAjF3B,CAiFuC,SAjFvC,CAkFT,UAlFS,CAkFG,QAlFH,CAkFe,UAlFf,CAkF2B,UAlF3B,CAkFuC,UAlFvC,CAmFT,UAnFS,CAmFG,UAnFH,CAmFe,UAnFf,CAmF2B,UAnF3B,CAmFuC,UAnFvC,CAoFT,UApFS,CAoFG,UApFH,CAoFe,SApFf,CAoF2B,UApF3B;AAoFuC,UApFvC,CAqFT,UArFS,CAqFG,UArFH,CAqFe,SArFf,CAqF2B,UArF3B,CAqFuC,UArFvC,CAsFT,UAtFS,CAsFG,UAtFH,CAsFe,UAtFf,CAsF2B,UAtF3B,CAsFuC,UAtFvC,CAuFT,SAvFS,CAuFG,SAvFH,CAuFe,SAvFf,CAuF2B,UAvF3B,CAuFuC,UAvFvC,CAwFT,UAxFS,CAwFG,UAxFH,CAwFe,SAxFf,CAwF2B,UAxF3B,CAwFuC,SAxFvC,CAyFT,UAzFS,CAyFG,UAzFH,CAyFe,UAzFf,CAyF2B,UAzF3B,CAyFuC,UAzFvC,CA0FT,SA1FS,CA0FG,UA1FH,CA0Fe,UA1Ff,CA0F2B,UA1F3B,CA0FuC,UA1FvC,CA2FT,UA3FS,CA2FG,SA3FH,CA2Fe,UA3Ff,CA2F2B,UA3F3B,CA2FuC,UA3FvC,CA4FT,UA5FS,CA4FG,UA5FH,CA4Fe,UA5Ff,CA4F2B,UA5F3B,CA4FuC,UA5FvC,CA6FT,UA7FS,CA6FG,UA7FH,CA6Fe,UA7Ff,CA6F2B,UA7F3B,CA6FuC,UA7FvC,CA8FT,UA9FS;AA8FG,UA9FH,CA8Fe,UA9Ff,CA8F2B,UA9F3B,CA8FuC,UA9FvC,CA+FT,UA/FS,CA+FG,UA/FH,CA+Fe,SA/Ff,CA+F2B,UA/F3B,CA+FuC,SA/FvC,CAgGT,SAhGS,CAgGG,UAhGH,CAgGe,SAhGf,CAgG2B,SAhG3B,CAgGuC,SAhGvC,CAiGT,SAjGS,CAiGG,UAjGH,CAiGe,UAjGf,CAiG2B,UAjG3B,CAiGuC,UAjGvC,CAkGT,UAlGS,CAkGG,UAlGH,CAkGe,UAlGf,CAkG2B,UAlG3B,CAkGuC,SAlGvC,CAmGT,UAnGS,CAmGG,UAnGH,CAmGe,UAnGf,CAmG2B,UAnG3B,CAmGuC,UAnGvC,CAoGT,UApGS,CAoGG,UApGH,CAoGe,UApGf,CAoG2B,UApG3B,CAoGuC,SApGvC,CAqGT,UArGS,CAqGG,SArGH,CAqGe,UArGf,CAqG2B,UArG3B,CAqGuC,UArGvC,CAsGT,UAtGS,CAsGG,UAtGH,CAsGe,UAtGf,CAsG2B,SAtG3B,CAsGuC,UAtGvC,CAuGT,UAvGS,CAuGG,UAvGH,CAuGe,UAvGf;AAuG2B,UAvG3B,CAuGuC,UAvGvC,CAwGT,UAxGS,CAwGG,UAxGH,CAwGe,UAxGf,CAwG2B,UAxG3B,CAwGuC,UAxGvC,CAyGT,UAzGS,CAyGG,SAzGH,CAyGe,UAzGf,CAyG2B,UAzG3B,CAyGuC,SAzGvC,CA0GT,UA1GS,CA0GG,SA1GH,CA0Ge,UA1Gf,CA0G2B,UA1G3B,CA0GuC,UA1GvC,CA2GT,UA3GS,CA2GG,UA3GH,CA2Ge,UA3Gf,CA2G2B,QA3G3B,CA2GuC,UA3GvC,CA4GT,SA5GS,CA4GG,UA5GH,CA4Ge,UA5Gf,CA4G2B,UA5G3B,CA4GuC,UA5GvC,CA6GT,SA7GS,CA6GG,UA7GH,CA6Ge,SA7Gf,CA6G2B,UA7G3B,CA6GuC,UA7GvC,CA8GT,UA9GS,CA8GG,UA9GH,CA8Ge,SA9Gf,CA8G2B,UA9G3B,CA8GuC,UA9GvC,CA+GT,UA/GS,CA+GG,UA/GH,CA+Ge,UA/Gf,CA+G2B,UA/G3B,CA+GuC,UA/GvC,CAgHT,UAhHS,CAgHG,SAhHH,CAgHe,UAhHf,CAgH2B,UAhH3B,CAgHuC,SAhHvC;AAiHT,SAjHS,CAiHG,UAjHH,CAiHe,SAjHf,CAiH2B,UAjH3B,CAiHuC,SAjHvC,CAkHT,UAlHS,CAkHG,UAlHH,CAkHe,UAlHf,CAkH2B,UAlH3B,CAkHuC,UAlHvC,CAmHT,UAnHS,CAmHG,UAnHH,CAmHe,UAnHf,CAmH2B,SAnH3B,CAmHuC,UAnHvC,CAoHT,UApHS,CAoHG,UApHH,CAoHe,UApHf,CAoH2B,UApH3B,CAoHuC,UApHvC,CAqHT,UArHS,CAqHG,UArHH,CAqHe,UArHf,CAqH2B,UArH3B,CAqHuC,UArHvC,CAsHT,QAtHS,CAsHG,UAtHH,CAsHe,QAtHf,CAsH2B,UAtH3B,CAsHuC,UAtHvC,CAuHT,UAvHS,CAuHG,UAvHH,CAuHe,SAvHf,CAuH2B,UAvH3B,CAuHuC,UAvHvC,CAwHT,UAxHS,CAwHG,SAxHH,CAwHe,UAxHf,CAwH2B,UAxH3B,CAwHuC,UAxHvC,CAyHT,SAzHS,CAyHG,UAzHH,CAyHe,UAzHf,CAyH2B,SAzH3B,CAyHuC,SAzHvC,CA0HT,QA1HS,CA0HG,UA1HH;AA0He,UA1Hf,CA0H2B,UA1H3B,CA0HuC,SA1HvC,CA2HT,SA3HS,CA2HG,UA3HH,CA2He,UA3Hf,CA2H2B,UA3H3B,CA2HuC,UA3HvC,CA4HT,SA5HS,CA4HG,UA5HH,CA4He,UA5Hf,CA4H2B,UA5H3B,CA4HuC,UA5HvC,CA6HT,UA7HS,CA6HG,UA7HH,CA6He,UA7Hf,CA6H2B,UA7H3B,CA6HuC,SA7HvC,CA8HT,UA9HS,CA8HG,SA9HH,CA8He,UA9Hf,CA8H2B,UA9H3B,CA8HuC,UA9HvC,CA+HT,UA/HS,CA+HG,UA/HH,CA+He,UA/Hf,CA+H2B,UA/H3B,CA+HuC,SA/HvC,CAgIT,UAhIS,CAgIG,UAhIH,CAgIe,UAhIf,CAgI2B,UAhI3B,CAgIuC,UAhIvC,CAiIT,UAjIS,CAiIG,UAjIH,CAiIe,UAjIf,CAiI2B,UAjI3B,CAiIuC,UAjIvC,CAkIT,UAlIS,CAkIG,UAlIH,CAkIe,UAlIf,CAkI2B,SAlI3B,CAkIuC,UAlIvC,CAmIT,UAnIS,CAmIG,UAnIH,CAmIe,UAnIf,CAmI2B,UAnI3B;AAmIuC,SAnIvC,CAoIT,UApIS,CAoIG,UApIH,CAoIe,UApIf,CAoI2B,SApI3B,CAoIuC,UApIvC,CAqIT,SArIS,CAqIG,SArIH,CAqIe,UArIf,CAqI2B,UArI3B,CAqIuC,UArIvC,CAsIT,SAtIS,CAsIG,UAtIH,CAsIe,UAtIf,CAsI2B,UAtI3B,CAsIuC,UAtIvC,CAuIT,UAvIS,CAuIG,UAvIH,CAuIe,UAvIf,CAuI2B,UAvI3B,CAuIuC,UAvIvC,CAwIT,UAxIS,CAwIG,UAxIH,CAwIe,UAxIf,CAwI2B,UAxI3B,CAwIuC,UAxIvC,CAyIT,UAzIS,CAyIG,UAzIH,CAyIe,UAzIf,CAyI2B,UAzI3B,CAyIuC,UAzIvC,CA0IT,UA1IS,CA0IG,UA1IH,CA0Ie,UA1If,CA0I2B,UA1I3B,CA0IuC,UA1IvC,CA2IT,UA3IS,CA2IG,UA3IH,CA2Ie,UA3If,CA2I2B,UA3I3B,CA2IuC,UA3IvC,CA4IT,UA5IS,CA4IG,UA5IH,CA4Ie,UA5If,CA4I2B,UA5I3B,CA4IuC,UA5IvC;AA6IT,UA7IS,CA6IG,SA7IH,CA6Ie,UA7If,CA6I2B,UA7I3B,CA6IuC,UA7IvC,CA8IT,UA9IS,CA8IG,SA9IH,CA8Ie,UA9If,CA8I2B,UA9I3B,CA8IuC,UA9IvC,CA+IT,UA/IS,CA+IG,UA/IH,CA+Ie,UA/If,CA+I2B,SA/I3B,CA+IuC,UA/IvC,CAgJT,SAhJS,CAgJG,SAhJH,CAgJe,SAhJf,CAgJ2B,UAhJ3B,CAgJuC,SAhJvC,CAiJT,UAjJS,CAiJG,UAjJH,CAiJe,UAjJf,CAiJ2B,UAjJ3B,CAiJuC,UAjJvC,CAkJT,UAlJS,CAkJG,UAlJH,CAkJe,SAlJf,CAkJ2B,UAlJ3B,CAkJuC,UAlJvC,CAmJT,UAnJS,CAmJG,UAnJH,CAmJe,UAnJf,CAmJ2B,UAnJ3B,CAmJuC,OAnJvC,CAoJT,SApJS,CAoJG,SApJH,CAoJe,SApJf,CAoJ2B,UApJ3B,CAoJuC,UApJvC,CAqJT,UArJS,CAqJG,UArJH,CAqJe,UArJf,CAqJ2B,UArJ3B,CAqJuC,UArJvC,CAsJT,UAtJS,CAsJG,SAtJH;AAsJe,UAtJf,CAsJ2B,UAtJ3B,CAsJuC,UAtJvC,CAuJT,SAvJS,CAuJG,UAvJH,CAuJe,UAvJf,CAuJ2B,SAvJ3B,CAuJuC,UAvJvC,CAwJT,UAxJS,CAwJG,SAxJH,CAwJe,UAxJf,CAwJ2B,UAxJ3B,CAwJuC,UAxJvC,CAyJT,UAzJS,CAyJG,UAzJH,CAyJe,SAzJf,CAyJ2B,UAzJ3B,CAyJuC,UAzJvC,CA0JT,UA1JS,CA0JG,UA1JH,CA0Je,UA1Jf,CA0J2B,SA1J3B,CA0JuC,UA1JvC,CA2JT,UA3JS,CA2JG,UA3JH,CA2Je,UA3Jf,CA2J2B,UA3J3B,CA2JuC,UA3JvC,CA4JT,UA5JS,CA4JG,UA5JH,CA4Je,UA5Jf,CA4J2B,UA5J3B,CA4JuC,UA5JvC,CA6JT,UA7JS,CA6JG,SA7JH,CA6Je,UA7Jf,CA6J2B,UA7J3B,CA6JuC,UA7JvC,CA8JT,UA9JS,CA8JG,UA9JH,CA8Je,UA9Jf,CA8J2B,UA9J3B,CA8JuC,UA9JvC,CA+JT,UA/JS,CA+JG,UA/JH,CA+Je,SA/Jf,CA+J2B,UA/J3B;AA+JuC,UA/JvC,CAgKT,UAhKS,CAgKG,UAhKH,CAgKe,UAhKf,CAgK2B,UAhK3B,CAgKuC,UAhKvC,CAiKT,UAjKS,CAiKG,UAjKH,CAiKe,UAjKf,CAiK2B,UAjK3B,CAiKuC,UAjKvC,CAkKT,UAlKS,CAkKG,UAlKH,CAkKe,UAlKf,CAkK2B,SAlK3B,CAkKuC,UAlKvC,CAmKT,UAnKS,CAmKG,UAnKH,CAmKe,UAnKf,CAmK2B,UAnK3B,CAmKuC,UAnKvC,CAoKT,UApKS,CAoKG,UApKH,CAoKe,UApKf,CAoK2B,UApK3B,CAoKuC,SApKvC,CAqKT,UArKS,CAqKG,UArKH,CAqKe,SArKf,CAqK2B,QArK3B,CAqKuC,UArKvC,CAsKT,QAtKS,CAsKG,UAtKH,CAsKe,UAtKf,CAsK2B,SAtK3B,CAsKuC,UAtKvC,CAuKT,UAvKS,CAuKG,UAvKH,CAuKe,UAvKf,CAuK2B,UAvK3B,CAuKuC,UAvKvC,CAwKT,UAxKS,CAwKG,UAxKH,CAwKe,SAxKf,CAwK2B,UAxK3B,CAwKuC,UAxKvC,CAyKT,UAzKS;AAyKG,UAzKH,CAyKe,UAzKf,CAyK2B,UAzK3B,CAyKuC,SAzKvC,CA0KT,UA1KS,CA0KG,QA1KH,CA0Ke,QA1Kf,CA0K2B,UA1K3B,CA0KuC,UA1KvC,CA2KT,UA3KS,CA2KG,UA3KH,CA2Ke,SA3Kf,CA2K2B,SA3K3B,CA2KuC,UA3KvC,CA4KT,SA5KS,CA4KG,UA5KH,CA4Ke,UA5Kf,CA4K2B,QA5K3B,CA4KuC,UA5KvC,CA6KT,SA7KS,CA6KG,UA7KH,CA6Ke,UA7Kf,CA6K2B,UA7K3B,CA6KuC,UA7KvC,CA8KT,SA9KS,CA8KG,SA9KH,CA8Ke,UA9Kf,CA8K2B,UA9K3B,CA8KuC,UA9KvC,CA+KT,UA/KS,CA+KG,UA/KH,CA+Ke,UA/Kf,CA+K2B,UA/K3B,CA+KuC,UA/KvC,CAgLT,UAhLS,CAgLG,UAhLH,CAgLe,UAhLf,CAgL2B,UAhL3B,CAgLuC,SAhLvC,CAiLT,UAjLS,CAiLG,UAjLH,CAiLe,UAjLf,CAiL2B,SAjL3B,CAiLuC,UAjLvC,CAkLT,SAlLS,CAkLG,UAlLH,CAkLe,UAlLf;AAkL2B,UAlL3B,CAkLuC,SAlLvC,CAmLT,UAnLS,CAmLG,UAnLH,CAmLe,UAnLf,CAmL2B,UAnL3B,CAmLuC,UAnLvC,CAoLT,UApLS,CAoLG,UApLH,CAoLe,UApLf,CAoL2B,UApL3B,CAoLuC,UApLvC,CAqLT,UArLS,CAqLG,UArLH,CAqLe,UArLf,CAqL2B,UArL3B,CAqLuC,UArLvC,CAsLT,UAtLS,CAsLG,SAtLH,CAsLe,QAtLf,CAsL2B,SAtL3B,CAsLuC,UAtLvC,CAuLT,SAvLS,CAuLG,UAvLH,CAuLe,UAvLf,CAuL2B,SAvL3B,CAuLuC,QAvLvC,CAwLT,SAxLS,CAwLG,UAxLH,CAwLe,UAxLf,CAwL2B,UAxL3B,CAwLuC,SAxLvC,CAyLT,UAzLS,CAyLG,UAzLH,CAyLe,SAzLf,CAyL2B,UAzL3B,CAyLuC,UAzLvC,CA0LT,UA1LS,CA0LG,UA1LH,CA0Le,UA1Lf,CA0L2B,SA1L3B,CA0LuC,UA1LvC,CA2LT,UA3LS,CA2LG,UA3LH,CA2Le,QA3Lf,CA2L2B,UA3L3B,CA2LuC,UA3LvC;AA4LT,UA5LS,CA4LG,UA5LH,CA4Le,UA5Lf,CA4L2B,UA5L3B,CA4LuC,SA5LvC,CA6LT,UA7LS,CA6LG,SA7LH,CA6Le,SA7Lf,CA6L2B,UA7L3B,CA6LuC,UA7LvC,CA8LT,UA9LS,CA8LG,UA9LH,CA8Le,SA9Lf,CA8L2B,UA9L3B,CA8LuC,UA9LvC,CA+LT,SA/LS,CA+LG,UA/LH,CA+Le,UA/Lf,CA+L2B,SA/L3B,CA+LuC,UA/LvC,CAgMT,SAhMS,CAgMG,UAhMH,CAgMe,UAhMf,CAgM2B,UAhM3B,CAgMuC,UAhMvC,CAiMT,SAjMS,CAiMG,UAjMH,CAiMe,UAjMf,CAiM2B,UAjM3B,CAiMuC,UAjMvC,CAkMT,UAlMS,CAkMG,UAlMH,CAkMe,SAlMf,CAkM2B,UAlM3B,CAkMuC,SAlMvC,CAmMT,UAnMS,CAmMG,UAnMH,CAmMe,SAnMf,CAmM2B,UAnM3B,CAmMuC,UAnMvC,CAoMT,UApMS,CAoMG,UApMH,CAoMe,UApMf,CAoM2B,UApM3B,CAoMuC,UApMvC,CAqMT,UArMS,CAqMG,UArMH;AAqMe,UArMf,CAqM2B,UArM3B,CAqMuC,UArMvC,CAsMT,UAtMS,CAsMG,UAtMH,CAsMe,UAtMf,CAsM2B,UAtM3B,CAsMuC,SAtMvC,CAuMT,UAvMS,CAuMG,UAvMH,CAuMe,UAvMf,CAuM2B,UAvM3B,CAuMuC,UAvMvC,CAwMT,SAxMS,CAwMG,UAxMH,CAwMe,UAxMf,CAwM2B,UAxM3B,CAwMuC,UAxMvC,CAyMT,UAzMS,CAyMG,SAzMH,CAyMe,SAzMf,CAyM2B,SAzM3B,CAyMuC,UAzMvC,CA0MT,UA1MS,CA0MG,UA1MH,CA0Me,SA1Mf,CA0M2B,UA1M3B,CA0MuC,UA1MvC,CA2MT,UA3MS,CA2MG,UA3MH,CA2Me,SA3Mf,CA2M2B,QA3M3B,CA2MuC,QA3MvC,CA4MT,UA5MS,CA4MG,UA5MH,CA4Me,UA5Mf,CA4M2B,UA5M3B,CA4MuC,UA5MvC,CA6MT,UA7MS,CA6MG,UA7MH,CA6Me,UA7Mf,CA6M2B,SA7M3B,CAZb,CAiOIN,EAAS,CACT,UADS,CACG,UADH,CACe,UADf,CAC2B,UAD3B,CACuC,UADvC;AAET,UAFS,CAoabsB,EAAAuD,aAAA,CAAsB/H,CAUtBwE,EAAAwD,aAAA,CAAsBzH,CAEtB,OAAOiE,EAvzCQ,CATlB;", -"sources":["dist/bcrypt.js"], -"names":["global","factory","define","require","module","random","len","e","a","self","Uint32Array","Array","prototype","slice","call","randomFallback","Error","safeStringCompare","known","unknown","right","wrong","i","k","length","charCodeAt","stringToBytes","str","out","utfx","encodeUTF16toUTF8","b","push","base64_encode","off","rs","c1","c2","BASE64_CODE","join","base64_decode","s","slen","olen","o","code","BASE64_INDEX","stringFromCharCode","c3","c4","res","_encipher","lr","P","S","n","l","r","_streamtoword","data","offp","word","key","_key","offset","plen","sw","_ekskey","_crypt","salt","rounds","callback","progressCallback","next","start","Date","now","MAX_EXECUTION_TIME","j","clen","cdata","ret","nextTick","C_ORIG","err","bind","BCRYPT_SALT_LEN","Int32Array","P_ORIG","S_ORIG","_hash","finish","bytes","minor","toString","saltb","charAt","substring","String","fromCharCode","r1","parseInt","r2","real_salt","passwordb","bcrypt","setRandomFallback","bcrypt.setRandomFallback","genSaltSync","bcrypt.genSaltSync","seed_length","GENSALT_DEFAULT_LOG2_ROUNDS","genSalt","bcrypt.genSalt","_async","undefined","Promise","resolve","reject","hashSync","bcrypt.hashSync","hash","bcrypt.hash","compareSync","bcrypt.compareSync","substr","compare","bcrypt.compare","comp","getRounds","bcrypt.getRounds","split","getSalt","bcrypt.getSalt","process","setImmediate","setTimeout","utfx.encodeUTF8","src","dst","cp","utfx.decodeUTF8","c","d","fail","indexOf","name","RangeError","utfx.UTF16toUTF8","utfx.UTF8toUTF16","utfx.encodeUTF16toUTF8","UTF16toUTF8","encodeUTF8","utfx.decodeUTF8toUTF16","decodeUTF8","UTF8toUTF16","utfx.calculateCodePoint","utfx.calculateUTF8","calculateCodePoint","utfx.calculateUTF16asUTF8","encodeBase64","decodeBase64"] -} diff --git a/node_modules/bcryptjs/externs/bcrypt.js b/node_modules/bcryptjs/externs/bcrypt.js deleted file mode 100644 index c458f9d7..00000000 --- a/node_modules/bcryptjs/externs/bcrypt.js +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012 The Closure Compiler Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Definitions for bcrypt.js 2. - * @externs - * @author Daniel Wirtz - */ - -/** - * @type {Object.} - */ -var bcrypt = {}; - -/** - * @param {?function(number):!Array.} random - */ -bcrypt.setRandomFallback = function(random) {}; - -/** - * @param {number=} rounds - * @param {number=} seed_length - * @returns {string} - */ -bcrypt.genSaltSync = function(rounds, seed_length) {}; - -/** - * @param {(number|function(Error, ?string))=} rounds - * @param {(number|function(Error, ?string))=} seed_length - * @param {function(Error, string=)=} callback - */ -bcrypt.genSalt = function(rounds, seed_length, callback) {}; - -/** - * @param {string} s - * @param {(number|string)=} salt - * @returns {?string} - */ -bcrypt.hashSync = function(s, salt) {}; - -/** - * @param {string} s - * @param {number|string} salt - * @param {function(Error, string=)} callback - * @expose - */ -bcrypt.hash = function(s, salt, callback) {}; - -/** - * @param {string} s - * @param {string} hash - * @returns {boolean} - * @throws {Error} - */ -bcrypt.compareSync = function(s, hash) {}; - -/** - * @param {string} s - * @param {string} hash - * @param {function(Error, boolean)} callback - * @throws {Error} - */ -bcrypt.compare = function(s, hash, callback) {}; - -/** - * @param {string} hash - * @returns {number} - * @throws {Error} - */ -bcrypt.getRounds = function(hash) {}; - -/** - * @param {string} hash - * @returns {string} - * @throws {Error} - * @expose - */ -bcrypt.getSalt = function(hash) {}; diff --git a/node_modules/bcryptjs/externs/minimal-env.js b/node_modules/bcryptjs/externs/minimal-env.js deleted file mode 100644 index 0db9d4c0..00000000 --- a/node_modules/bcryptjs/externs/minimal-env.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @fileoverview Minimal environment for bcrypt.js. - * @externs - */ - -/** - * @param {string} moduleName - * returns {*} - */ -function require(moduleName) {} - -/** - * @constructor - * @private - */ -var Module = function() {}; - -/** - * @type {*} - */ -Module.prototype.exports; - -/** - * @type {Module} - */ -var module; - -/** - * @type {string} - */ -var __dirname; - -/** - * @type {Object.} - */ -var process = {}; - -/** - * @param {function()} func - */ -process.nextTick = function(func) {}; - -/** - * @param {string} s - * @constructor - * @extends Array - */ -var Buffer = function(s) {}; - -/** - BEGIN_NODE_INCLUDE - var crypto = require('crypto'); - END_NODE_INCLUDE - */ - -/** - * @type {Object.} - */ -var crypto = {}; - -/** - * @param {number} n - * @returns {Array.} - */ -crypto.randomBytes = function(n) {}; - -/** - * @type {Object.} - */ -window.crypto = {}; - -/** - * @param {Uint8Array|Int8Array|Uint16Array|Int16Array|Uint32Array|Int32Array} array - */ -window.crypto.getRandomValues = function(array) {}; - -/** - * @param {string} name - * @param {function(...[*]):*} constructor - */ -var define = function(name, constructor) {}; - -/** - * @type {boolean} - */ -define.amd; - -/** - * @param {...*} var_args - * @returns {string} - */ -String.fromCodePoint = function(var_args) {}; - -/** - * @param {number} offset - * @returns {number} - */ -String.prototype.codePointAt = function(offset) {}; diff --git a/node_modules/bcryptjs/index.js b/node_modules/bcryptjs/index.js deleted file mode 100644 index f11b4e70..00000000 --- a/node_modules/bcryptjs/index.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - Copyright (c) 2012 Nevins Bartolomeo - Copyright (c) 2012 Shane Girish - Copyright (c) 2013 Daniel Wirtz - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -module.exports = require("./dist/bcrypt.js"); diff --git a/node_modules/bcryptjs/package.json b/node_modules/bcryptjs/package.json deleted file mode 100644 index 97be5df6..00000000 --- a/node_modules/bcryptjs/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "bcryptjs", - "description": "Optimized bcrypt in plain JavaScript with zero dependencies. Compatible to 'bcrypt'.", - "version": "2.4.3", - "author": "Daniel Wirtz ", - "contributors": [ - "Shane Girish (https://github.com/shaneGirish)", - "Alex Murray <> (https://github.com/alexmurray)", - "Nicolas Pelletier <> (https://github.com/NicolasPelletier)", - "Josh Rogers <> (https://github.com/geekymole)", - "Noah Isaacson (https://github.com/nisaacson)" - ], - "repository": { - "type": "url", - "url": "https://github.com/dcodeIO/bcrypt.js.git" - }, - "bugs": { - "url": "https://github.com/dcodeIO/bcrypt.js/issues" - }, - "keywords": [ - "bcrypt", - "password", - "auth", - "authentication", - "encryption", - "crypt", - "crypto" - ], - "main": "index.js", - "browser": "dist/bcrypt.js", - "dependencies": {}, - "devDependencies": { - "testjs": "~1", - "closurecompiler": "~1", - "metascript": "~0.18", - "bcrypt": "latest", - "utfx": "~1" - }, - "license": "MIT", - "scripts": { - "test": "node node_modules/testjs/bin/testjs", - "build": "node scripts/build.js", - "compile": "node node_modules/closurecompiler/bin/ccjs dist/bcrypt.js --compilation_level=SIMPLE_OPTIMIZATIONS --create_source_map=dist/bcrypt.min.map > dist/bcrypt.min.js", - "compress": "gzip -c -9 dist/bcrypt.min.js > dist/bcrypt.min.js.gz", - "make": "npm run build && npm run compile && npm run compress && npm test" - } -} diff --git a/node_modules/bcryptjs/scripts/build.js b/node_modules/bcryptjs/scripts/build.js deleted file mode 100644 index 7b34ea48..00000000 --- a/node_modules/bcryptjs/scripts/build.js +++ /dev/null @@ -1,37 +0,0 @@ -var MetaScript = require("metascript"), - path = require("path"), - fs = require("fs"); - -var rootDir = path.join(__dirname, ".."), - srcDir = path.join(rootDir, "src"), - distDir = path.join(rootDir, "dist"), - pkg = require(path.join(rootDir, "package.json")), - filename; - -var scope = { - VERSION: pkg.version, - ISAAC: false -}; - -// Make standard build -console.log("Building bcrypt.js with scope", JSON.stringify(scope, null, 2)); -fs.writeFileSync( - path.join(distDir, "bcrypt.js"), - MetaScript.transform(fs.readFileSync(filename = path.join(srcDir, "wrap.js")), filename, scope, srcDir) -); - -// Make isaac build - see: https://github.com/dcodeIO/bcrypt.js/issues/16 -/* scope.ISAAC = true; -console.log("Building bcrypt-isaac.js with scope", JSON.stringify(scope, null, 2)); -fs.writeFileSync( - path.join(distDir, "bcrypt-isaac.js"), - MetaScript.transform(fs.readFileSync(filename = path.join(srcDir, "bcrypt.js")), filename, scope, srcDir) -); */ - -// Update bower.json -scope = { VERSION: pkg.version }; -console.log("Updating bower.json with scope", JSON.stringify(scope, null, 2)); -fs.writeFileSync( - path.join(rootDir, "bower.json"), - MetaScript.transform(fs.readFileSync(filename = path.join(srcDir, "bower.json")), filename, scope, srcDir) -); diff --git a/node_modules/bcryptjs/src/bcrypt.js b/node_modules/bcryptjs/src/bcrypt.js deleted file mode 100644 index 11dedc17..00000000 --- a/node_modules/bcryptjs/src/bcrypt.js +++ /dev/null @@ -1,327 +0,0 @@ -/** - * bcrypt namespace. - * @type {Object.} - */ -var bcrypt = {}; - -/** - * The random implementation to use as a fallback. - * @type {?function(number):!Array.} - * @inner - */ -var randomFallback = null; - -/** - * Generates cryptographically secure random bytes. - * @function - * @param {number} len Bytes length - * @returns {!Array.} Random bytes - * @throws {Error} If no random implementation is available - * @inner - */ -function random(len) { - /* node */ if (typeof module !== 'undefined' && module && module['exports']) - try { - return require("crypto")['randomBytes'](len); - } catch (e) {} - /* WCA */ try { - var a; (self['crypto']||self['msCrypto'])['getRandomValues'](a = new Uint32Array(len)); - return Array.prototype.slice.call(a); - } catch (e) {} - /* fallback */ if (!randomFallback) - throw Error("Neither WebCryptoAPI nor a crypto module is available. Use bcrypt.setRandomFallback to set an alternative"); - return randomFallback(len); -} - -// Test if any secure randomness source is available -var randomAvailable = false; -try { - random(1); - randomAvailable = true; -} catch (e) {} - -// Default fallback, if any -randomFallback = /*? if (ISAAC) { */function(len) { - for (var a=[], i=0; i} random Function taking the number of bytes to generate as its - * sole argument, returning the corresponding array of cryptographically secure random byte values. - * @see http://nodejs.org/api/crypto.html - * @see http://www.w3.org/TR/WebCryptoAPI/ - */ -bcrypt.setRandomFallback = function(random) { - randomFallback = random; -}; - -/** - * Synchronously generates a salt. - * @param {number=} rounds Number of rounds to use, defaults to 10 if omitted - * @param {number=} seed_length Not supported. - * @returns {string} Resulting salt - * @throws {Error} If a random fallback is required but not set - * @expose - */ -bcrypt.genSaltSync = function(rounds, seed_length) { - rounds = rounds || GENSALT_DEFAULT_LOG2_ROUNDS; - if (typeof rounds !== 'number') - throw Error("Illegal arguments: "+(typeof rounds)+", "+(typeof seed_length)); - if (rounds < 4) - rounds = 4; - else if (rounds > 31) - rounds = 31; - var salt = []; - salt.push("$2a$"); - if (rounds < 10) - salt.push("0"); - salt.push(rounds.toString()); - salt.push('$'); - salt.push(base64_encode(random(BCRYPT_SALT_LEN), BCRYPT_SALT_LEN)); // May throw - return salt.join(''); -}; - -/** - * Asynchronously generates a salt. - * @param {(number|function(Error, string=))=} rounds Number of rounds to use, defaults to 10 if omitted - * @param {(number|function(Error, string=))=} seed_length Not supported. - * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting salt - * @returns {!Promise} If `callback` has been omitted - * @throws {Error} If `callback` is present but not a function - * @expose - */ -bcrypt.genSalt = function(rounds, seed_length, callback) { - if (typeof seed_length === 'function') - callback = seed_length, - seed_length = undefined; // Not supported. - if (typeof rounds === 'function') - callback = rounds, - rounds = undefined; - if (typeof rounds === 'undefined') - rounds = GENSALT_DEFAULT_LOG2_ROUNDS; - else if (typeof rounds !== 'number') - throw Error("illegal arguments: "+(typeof rounds)); - - function _async(callback) { - nextTick(function() { // Pretty thin, but salting is fast enough - try { - callback(null, bcrypt.genSaltSync(rounds)); - } catch (err) { - callback(err); - } - }); - } - - if (callback) { - if (typeof callback !== 'function') - throw Error("Illegal callback: "+typeof(callback)); - _async(callback); - } else - return new Promise(function(resolve, reject) { - _async(function(err, res) { - if (err) { - reject(err); - return; - } - resolve(res); - }); - }); -}; - -/** - * Synchronously generates a hash for the given string. - * @param {string} s String to hash - * @param {(number|string)=} salt Salt length to generate or salt to use, default to 10 - * @returns {string} Resulting hash - * @expose - */ -bcrypt.hashSync = function(s, salt) { - if (typeof salt === 'undefined') - salt = GENSALT_DEFAULT_LOG2_ROUNDS; - if (typeof salt === 'number') - salt = bcrypt.genSaltSync(salt); - if (typeof s !== 'string' || typeof salt !== 'string') - throw Error("Illegal arguments: "+(typeof s)+', '+(typeof salt)); - return _hash(s, salt); -}; - -/** - * Asynchronously generates a hash for the given string. - * @param {string} s String to hash - * @param {number|string} salt Salt length to generate or salt to use - * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting hash - * @param {function(number)=} progressCallback Callback successively called with the percentage of rounds completed - * (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms. - * @returns {!Promise} If `callback` has been omitted - * @throws {Error} If `callback` is present but not a function - * @expose - */ -bcrypt.hash = function(s, salt, callback, progressCallback) { - - function _async(callback) { - if (typeof s === 'string' && typeof salt === 'number') - bcrypt.genSalt(salt, function(err, salt) { - _hash(s, salt, callback, progressCallback); - }); - else if (typeof s === 'string' && typeof salt === 'string') - _hash(s, salt, callback, progressCallback); - else - nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof salt)))); - } - - if (callback) { - if (typeof callback !== 'function') - throw Error("Illegal callback: "+typeof(callback)); - _async(callback); - } else - return new Promise(function(resolve, reject) { - _async(function(err, res) { - if (err) { - reject(err); - return; - } - resolve(res); - }); - }); -}; - -/** - * Compares two strings of the same length in constant time. - * @param {string} known Must be of the correct length - * @param {string} unknown Must be the same length as `known` - * @returns {boolean} - * @inner - */ -function safeStringCompare(known, unknown) { - var right = 0, - wrong = 0; - for (var i=0, k=known.length; i} b Byte array - * @param {number} len Maximum input length - * @returns {string} - * @expose - */ -bcrypt.encodeBase64 = base64_encode; - -/** - * Decodes a base64 encoded string to up to len bytes of output, using the custom bcrypt alphabet. - * @function - * @param {string} s String to decode - * @param {number} len Maximum output length - * @returns {!Array.} - * @expose - */ -bcrypt.decodeBase64 = base64_decode; diff --git a/node_modules/bcryptjs/src/bcrypt/impl.js b/node_modules/bcryptjs/src/bcrypt/impl.js deleted file mode 100644 index fb00aeee..00000000 --- a/node_modules/bcryptjs/src/bcrypt/impl.js +++ /dev/null @@ -1,669 +0,0 @@ -/** - * @type {number} - * @const - * @inner - */ -var BCRYPT_SALT_LEN = 16; - -/** - * @type {number} - * @const - * @inner - */ -var GENSALT_DEFAULT_LOG2_ROUNDS = 10; - -/** - * @type {number} - * @const - * @inner - */ -var BLOWFISH_NUM_ROUNDS = 16; - -/** - * @type {number} - * @const - * @inner - */ -var MAX_EXECUTION_TIME = 100; - -/** - * @type {Array.} - * @const - * @inner - */ -var P_ORIG = [ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, - 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, - 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, - 0xb5470917, 0x9216d5d9, 0x8979fb1b -]; - -/** - * @type {Array.} - * @const - * @inner - */ -var S_ORIG = [ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, - 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, - 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, - 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, - 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, - 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, - 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, - 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, - 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, - 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, - 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, - 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, - 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, - 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, - 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, - 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, - 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, - 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, - 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, - 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, - 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, - 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, - 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, - 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, - 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, - 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, - 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, - 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, - 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, - 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, - 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, - 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, - 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, - 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, - 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, - 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, - 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, - 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, - 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, - 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, - 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, - 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, - 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, - 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, - 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, - 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, - 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, - 0x6e85076a, 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, - 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, - 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, - 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, - 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, - 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, - 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, - 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, - 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, - 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, - 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, - 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, - 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, - 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, - 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, - 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, - 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, - 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, - 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, - 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, - 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, - 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, - 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, - 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, - 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, - 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, - 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, - 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, - 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, - 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, - 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, - 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, - 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, - 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, - 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, - 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, - 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, - 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, - 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, - 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, - 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, - 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, - 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, - 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, - 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, - 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, - 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, - 0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7, 0xf64c261c, - 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, - 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, - 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, - 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, - 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, - 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, - 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, - 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, - 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, - 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, - 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, - 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, - 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, - 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, - 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, - 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, - 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, - 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, - 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, - 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, - 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, - 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, - 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, - 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, - 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, - 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, - 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, - 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, - 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, - 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, - 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, - 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, - 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, - 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, - 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, - 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, - 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, - 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, - 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, - 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, - 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, - 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, - 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, - 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, - 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, - 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, - 0x92638212, 0x670efa8e, 0x406000e0, 0x3a39ce37, 0xd3faf5cf, - 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, - 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, - 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, - 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, - 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, - 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, - 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, - 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, - 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, - 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, - 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, - 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, - 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, - 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, - 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, - 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, - 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, - 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, - 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, - 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, - 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, - 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, - 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, - 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, - 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, - 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, - 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, - 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, - 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, - 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, - 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, - 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, - 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, - 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, - 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, - 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, - 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, - 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, - 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, - 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, - 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, - 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, - 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, - 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, - 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, - 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 -]; - -/** - * @type {Array.} - * @const - * @inner - */ -var C_ORIG = [ - 0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253, 0x63727944, - 0x6f756274 -]; - -/** - * @param {Array.} lr - * @param {number} off - * @param {Array.} P - * @param {Array.} S - * @returns {Array.} - * @inner - */ -function _encipher(lr, off, P, S) { // This is our bottleneck: 1714/1905 ticks / 90% - see profile.txt - var n, - l = lr[off], - r = lr[off + 1]; - - l ^= P[0]; - - /* - for (var i=0, k=BLOWFISH_NUM_ROUNDS-2; i<=k;) - // Feistel substitution on left word - n = S[l >>> 24], - n += S[0x100 | ((l >> 16) & 0xff)], - n ^= S[0x200 | ((l >> 8) & 0xff)], - n += S[0x300 | (l & 0xff)], - r ^= n ^ P[++i], - // Feistel substitution on right word - n = S[r >>> 24], - n += S[0x100 | ((r >> 16) & 0xff)], - n ^= S[0x200 | ((r >> 8) & 0xff)], - n += S[0x300 | (r & 0xff)], - l ^= n ^ P[++i]; - */ - - //The following is an unrolled version of the above loop. - //Iteration 0 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[1]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[2]; - //Iteration 1 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[3]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[4]; - //Iteration 2 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[5]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[6]; - //Iteration 3 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[7]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[8]; - //Iteration 4 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[9]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[10]; - //Iteration 5 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[11]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[12]; - //Iteration 6 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[13]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[14]; - //Iteration 7 - n = S[l >>> 24]; - n += S[0x100 | ((l >> 16) & 0xff)]; - n ^= S[0x200 | ((l >> 8) & 0xff)]; - n += S[0x300 | (l & 0xff)]; - r ^= n ^ P[15]; - n = S[r >>> 24]; - n += S[0x100 | ((r >> 16) & 0xff)]; - n ^= S[0x200 | ((r >> 8) & 0xff)]; - n += S[0x300 | (r & 0xff)]; - l ^= n ^ P[16]; - - lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1]; - lr[off + 1] = l; - return lr; -} - -/** - * @param {Array.} data - * @param {number} offp - * @returns {{key: number, offp: number}} - * @inner - */ -function _streamtoword(data, offp) { - for (var i = 0, word = 0; i < 4; ++i) - word = (word << 8) | (data[offp] & 0xff), - offp = (offp + 1) % data.length; - return { key: word, offp: offp }; -} - -/** - * @param {Array.} key - * @param {Array.} P - * @param {Array.} S - * @inner - */ -function _key(key, P, S) { - var offset = 0, - lr = [0, 0], - plen = P.length, - slen = S.length, - sw; - for (var i = 0; i < plen; i++) - sw = _streamtoword(key, offset), - offset = sw.offp, - P[i] = P[i] ^ sw.key; - for (i = 0; i < plen; i += 2) - lr = _encipher(lr, 0, P, S), - P[i] = lr[0], - P[i + 1] = lr[1]; - for (i = 0; i < slen; i += 2) - lr = _encipher(lr, 0, P, S), - S[i] = lr[0], - S[i + 1] = lr[1]; -} - -/** - * Expensive key schedule Blowfish. - * @param {Array.} data - * @param {Array.} key - * @param {Array.} P - * @param {Array.} S - * @inner - */ -function _ekskey(data, key, P, S) { - var offp = 0, - lr = [0, 0], - plen = P.length, - slen = S.length, - sw; - for (var i = 0; i < plen; i++) - sw = _streamtoword(key, offp), - offp = sw.offp, - P[i] = P[i] ^ sw.key; - offp = 0; - for (i = 0; i < plen; i += 2) - sw = _streamtoword(data, offp), - offp = sw.offp, - lr[0] ^= sw.key, - sw = _streamtoword(data, offp), - offp = sw.offp, - lr[1] ^= sw.key, - lr = _encipher(lr, 0, P, S), - P[i] = lr[0], - P[i + 1] = lr[1]; - for (i = 0; i < slen; i += 2) - sw = _streamtoword(data, offp), - offp = sw.offp, - lr[0] ^= sw.key, - sw = _streamtoword(data, offp), - offp = sw.offp, - lr[1] ^= sw.key, - lr = _encipher(lr, 0, P, S), - S[i] = lr[0], - S[i + 1] = lr[1]; -} - -/** - * Internaly crypts a string. - * @param {Array.} b Bytes to crypt - * @param {Array.} salt Salt bytes to use - * @param {number} rounds Number of rounds - * @param {function(Error, Array.=)=} callback Callback receiving the error, if any, and the resulting bytes. If - * omitted, the operation will be performed synchronously. - * @param {function(number)=} progressCallback Callback called with the current progress - * @returns {!Array.|undefined} Resulting bytes if callback has been omitted, otherwise `undefined` - * @inner - */ -function _crypt(b, salt, rounds, callback, progressCallback) { - var cdata = C_ORIG.slice(), - clen = cdata.length, - err; - - // Validate - if (rounds < 4 || rounds > 31) { - err = Error("Illegal number of rounds (4-31): "+rounds); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } else - throw err; - } - if (salt.length !== BCRYPT_SALT_LEN) { - err =Error("Illegal salt length: "+salt.length+" != "+BCRYPT_SALT_LEN); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } else - throw err; - } - rounds = (1 << rounds) >>> 0; - - var P, S, i = 0, j; - - //Use typed arrays when available - huge speedup! - if (Int32Array) { - P = new Int32Array(P_ORIG); - S = new Int32Array(S_ORIG); - } else { - P = P_ORIG.slice(); - S = S_ORIG.slice(); - } - - _ekskey(salt, b, P, S); - - /** - * Calcualtes the next round. - * @returns {Array.|undefined} Resulting array if callback has been omitted, otherwise `undefined` - * @inner - */ - function next() { - if (progressCallback) - progressCallback(i / rounds); - if (i < rounds) { - var start = Date.now(); - for (; i < rounds;) { - i = i + 1; - _key(b, P, S); - _key(salt, P, S); - if (Date.now() - start > MAX_EXECUTION_TIME) - break; - } - } else { - for (i = 0; i < 64; i++) - for (j = 0; j < (clen >> 1); j++) - _encipher(cdata, j << 1, P, S); - var ret = []; - for (i = 0; i < clen; i++) - ret.push(((cdata[i] >> 24) & 0xff) >>> 0), - ret.push(((cdata[i] >> 16) & 0xff) >>> 0), - ret.push(((cdata[i] >> 8) & 0xff) >>> 0), - ret.push((cdata[i] & 0xff) >>> 0); - if (callback) { - callback(null, ret); - return; - } else - return ret; - } - if (callback) - nextTick(next); - } - - // Async - if (typeof callback !== 'undefined') { - next(); - - // Sync - } else { - var res; - while (true) - if (typeof(res = next()) !== 'undefined') - return res || []; - } -} - -/** - * Internally hashes a string. - * @param {string} s String to hash - * @param {?string} salt Salt to use, actually never null - * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting hash. If omitted, - * hashing is perormed synchronously. - * @param {function(number)=} progressCallback Callback called with the current progress - * @returns {string|undefined} Resulting hash if callback has been omitted, otherwise `undefined` - * @inner - */ -function _hash(s, salt, callback, progressCallback) { - var err; - if (typeof s !== 'string' || typeof salt !== 'string') { - err = Error("Invalid string / salt: Not a string"); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } - else - throw err; - } - - // Validate the salt - var minor, offset; - if (salt.charAt(0) !== '$' || salt.charAt(1) !== '2') { - err = Error("Invalid salt version: "+salt.substring(0,2)); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } - else - throw err; - } - if (salt.charAt(2) === '$') - minor = String.fromCharCode(0), - offset = 3; - else { - minor = salt.charAt(2); - if ((minor !== 'a' && minor !== 'b' && minor !== 'y') || salt.charAt(3) !== '$') { - err = Error("Invalid salt revision: "+salt.substring(2,4)); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } else - throw err; - } - offset = 4; - } - - // Extract number of rounds - if (salt.charAt(offset + 2) > '$') { - err = Error("Missing salt rounds"); - if (callback) { - nextTick(callback.bind(this, err)); - return; - } else - throw err; - } - var r1 = parseInt(salt.substring(offset, offset + 1), 10) * 10, - r2 = parseInt(salt.substring(offset + 1, offset + 2), 10), - rounds = r1 + r2, - real_salt = salt.substring(offset + 3, offset + 25); - s += minor >= 'a' ? "\x00" : ""; - - var passwordb = stringToBytes(s), - saltb = base64_decode(real_salt, BCRYPT_SALT_LEN); - - /** - * Finishes hashing. - * @param {Array.} bytes Byte array - * @returns {string} - * @inner - */ - function finish(bytes) { - var res = []; - res.push("$2"); - if (minor >= 'a') - res.push(minor); - res.push("$"); - if (rounds < 10) - res.push("0"); - res.push(rounds.toString()); - res.push("$"); - res.push(base64_encode(saltb, saltb.length)); - res.push(base64_encode(bytes, C_ORIG.length * 4 - 1)); - return res.join(''); - } - - // Sync - if (typeof callback == 'undefined') - return finish(_crypt(passwordb, saltb, rounds)); - - // Async - else { - _crypt(passwordb, saltb, rounds, function(err, bytes) { - if (err) - callback(err, null); - else - callback(null, finish(bytes)); - }, progressCallback); - } -} diff --git a/node_modules/bcryptjs/src/bcrypt/prng/README.md b/node_modules/bcryptjs/src/bcrypt/prng/README.md deleted file mode 100644 index 4735aa67..00000000 --- a/node_modules/bcryptjs/src/bcrypt/prng/README.md +++ /dev/null @@ -1,5 +0,0 @@ -Because of [reasonable security doubts](https://github.com/dcodeIO/bcrypt.js/issues/16), these files, which used to be -a part of bcrypt-isaac.js, are no longer used but are kept here for reference only. - -What is required instead is a proper way to collect entropy sources (using an intermediate stream cipher) which is then -used to seed the CSPRNG. Pick one and use `bcrypt.setRandomFallback` instead. diff --git a/node_modules/bcryptjs/src/bcrypt/prng/accum.js b/node_modules/bcryptjs/src/bcrypt/prng/accum.js deleted file mode 100644 index 8ea77737..00000000 --- a/node_modules/bcryptjs/src/bcrypt/prng/accum.js +++ /dev/null @@ -1,133 +0,0 @@ -/* basic entropy accumulator */ -var accum = (function() { - - var pool, // randomness pool - time, // start timestamp - last; // last step timestamp - - /* initialize with default pool */ - function init() { - pool = []; - time = new Date().getTime(); - last = time; - // use Math.random - pool.push((Math.random() * 0xffffffff)|0); - // use current time - pool.push(time|0); - } - - /* perform one step */ - function step() { - if (!to) - return; - if (pool.length >= 255) { // stop at 255 values (1 more is added on fetch) - stop(); - return; - } - var now = new Date().getTime(); - // use actual time difference - pool.push(now-last); - // always compute, occasionally use Math.random - var rnd = (Math.random() * 0xffffffff)|0; - if (now % 2) - pool[pool.length-1] += rnd; - last = now; - to = setTimeout(step, 100+Math.random()*512); // use hypothetical time difference - } - - var to = null; - - /* starts accumulating */ - function start() { - if (to) return; - to = setTimeout(step, 100+Math.random()*512); - if (console.log) - console.log("bcrypt-isaac: collecting entropy..."); - // install collectors - if (typeof window !== 'undefined' && window && window.addEventListener) - window.addEventListener("load", loadCollector, false), - window.addEventListener("mousemove", mouseCollector, false), - window.addEventListener("touchmove", touchCollector, false); - else if (typeof document !== 'undefined' && document && document.attachEvent) - document.attachEvent("onload", loadCollector), - document.attachEvent("onmousemove", mouseCollector); - } - - /* stops accumulating */ - function stop() { - if (!to) return; - clearTimeout(to); to = null; - // uninstall collectors - if (typeof window !== 'undefined' && window && window.removeEventListener) - window.removeEventListener("load", loadCollector, false), - window.removeEventListener("mousemove", mouseCollector, false), - window.removeEventListener("touchmove", touchCollector, false); - else if (typeof document !== 'undefined' && document && document.detachEvent) - document.detachEvent("onload", loadCollector), - document.detachEvent("onmousemove", mouseCollector); - } - - /* fetches the randomness pool */ - function fetch() { - // add overall time difference - pool.push((new Date().getTime()-time)|0); - var res = pool; - init(); - if (console.log) - console.log("bcrypt-isaac: using "+res.length+"/256 samples of entropy"); - // console.log(res); - return res; - } - - /* adds the current time to the top of the pool */ - function addTime() { - pool[pool.length-1] += new Date().getTime() - time; - } - - /* page load collector */ - function loadCollector() { - if (!to || pool.length >= 255) - return; - pool.push(0); - addTime(); - } - - /* mouse events collector */ - function mouseCollector(ev) { - if (!to || pool.length >= 255) - return; - try { - var x = ev.x || ev.clientX || ev.offsetX || 0, - y = ev.y || ev.clientY || ev.offsetY || 0; - if (x != 0 || y != 0) - pool[pool.length-1] += ((x-mouseCollector.last[0]) ^ (y-mouseCollector.last[1])), - addTime(), - mouseCollector.last = [x,y]; - } catch (e) {} - } - mouseCollector.last = [0,0]; - - /* touch events collector */ - function touchCollector(ev) { - if (!to || pool.length >= 255) - return; - try { - var touch = ev.touches[0] || ev.changedTouches[0]; - var x = touch.pageX || touch.clientX || 0, - y = touch.pageY || touch.clientY || 0; - if (x != 0 || y != 0) - pool[pool.length-1] += (x-touchCollector.last[0]) ^ (y-touchCollector.last[1]), - addTime(), - touchCollector.last = [x,y]; - } catch (e) {} - } - touchCollector.last = [0,0]; - - init(); - return { - "start": start, - "stop": stop, - "fetch": fetch - } - -})(); diff --git a/node_modules/bcryptjs/src/bcrypt/prng/isaac.js b/node_modules/bcryptjs/src/bcrypt/prng/isaac.js deleted file mode 100644 index e33b0e51..00000000 --- a/node_modules/bcryptjs/src/bcrypt/prng/isaac.js +++ /dev/null @@ -1,140 +0,0 @@ -/* - isaac.js Copyright (c) 2012 Yves-Marie K. Rinquin - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* isaac module pattern */ -var isaac = (function(){ - - /* internal states */ - var m = Array(256), // internal memory - acc = 0, // accumulator - brs = 0, // last result - cnt = 0, // counter - r = Array(256), // result array - gnt = 0, // generation counter - isd = false; // initially seeded - - - /* 32-bit integer safe adder */ - function add(x, y) { - var lsb = (x & 0xffff) + (y & 0xffff), - msb = (x >>> 16) + (y >>> 16) + (lsb >>> 16); - return (msb << 16) | (lsb & 0xffff); - } - - /* initialisation */ - function reset() { - acc = brs = cnt = 0; - for (var i = 0; i < 256; ++i) - m[i] = r[i] = 0; - gnt = 0; - } - - /* seeding function */ - function seed(s) { - var a, b, c, d, e, f, g, h, i; - - /* seeding the seeds of love */ - a = b = c = d = e = f = g = h = 0x9e3779b9; /* the golden ratio */ - - if (s && typeof(s) === 'number') - s = [s]; - - if (s instanceof Array) { - reset(); - for (i = 0; i < s.length; ++i) - r[i & 0xff] += typeof(s[i]) === 'number' ? s[i] : 0; - } - - /* private: seed mixer */ - function seed_mix() { - a ^= b << 11; d = add(d, a); b = add(b, c); - b ^= c >>> 2; e = add(e, b); c = add(c, d); - c ^= d << 8; f = add(f, c); d = add(d, e); - d ^= e >>> 16; g = add(g, d); e = add(e, f); - e ^= f << 10; h = add(h, e); f = add(f, g); - f ^= g >>> 4; a = add(a, f); g = add(g, h); - g ^= h << 8; b = add(b, g); h = add(h, a); - h ^= a >>> 9; c = add(c, h); a = add(a, b); - } - - for (i = 0; i < 4; i++) /* scramble it */ - seed_mix(); - - for (i = 0; i < 256; i += 8) { - if (s) /* use all the information in the seed */ - a = add(a, r[i + 0]), b = add(b, r[i + 1]), - c = add(c, r[i + 2]), d = add(d, r[i + 3]), - e = add(e, r[i + 4]), f = add(f, r[i + 5]), - g = add(g, r[i + 6]), h = add(h, r[i + 7]); - seed_mix(); - /* fill in m[] with messy stuff */ - m[i + 0] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d; - m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h; - } - if (s) - /* do a second pass to make all of the seed affect all of m[] */ - for (i = 0; i < 256; i += 8) - a = add(a, m[i + 0]), b = add(b, m[i + 1]), - c = add(c, m[i + 2]), d = add(d, m[i + 3]), - e = add(e, m[i + 4]), f = add(f, m[i + 5]), - g = add(g, m[i + 6]), h = add(h, m[i + 7]), - seed_mix(), - /* fill in m[] with messy stuff (again) */ - m[i + 0] = a, m[i + 1] = b, m[i + 2] = c, m[i + 3] = d, - m[i + 4] = e, m[i + 5] = f, m[i + 6] = g, m[i + 7] = h; - prng(); /* fill in the first set of results */ - gnt = 256; /* prepare to use the first set of results */; - } - - /* isaac generator, n = number of run */ - function prng(n) { - var i, x, y; - n = n && typeof(n) === 'number' ? Math.abs(Math.floor(n)) : 1; - while (n--) { - cnt = add(cnt, 1); - brs = add(brs, cnt); - for(i = 0; i < 256; i++) { - switch(i & 3) { - case 0: acc ^= acc << 13; break; - case 1: acc ^= acc >>> 6; break; - case 2: acc ^= acc << 2; break; - case 3: acc ^= acc >>> 16; break; - } - acc = add(m[(i + 128) & 0xff], acc); x = m[i]; - m[i] = y = add(m[(x >>> 2) & 0xff], add(acc, brs)); - r[i] = brs = add(m[(y >>> 10) & 0xff], x); - } - } - } - - /* return a random number between */ - return function() { - if (!isd) // seed from accumulator - isd = true, - accum.stop(), - seed(accum.fetch()); - if (!gnt--) - prng(), gnt = 255; - return r[gnt]; - }; -})(); diff --git a/node_modules/bcryptjs/src/bcrypt/util.js b/node_modules/bcryptjs/src/bcrypt/util.js deleted file mode 100644 index a149f71b..00000000 --- a/node_modules/bcryptjs/src/bcrypt/util.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Continues with the callback on the next tick. - * @function - * @param {function(...[*])} callback Callback to execute - * @inner - */ -var nextTick = typeof process !== 'undefined' && process && typeof process.nextTick === 'function' - ? (typeof setImmediate === 'function' ? setImmediate : process.nextTick) - : setTimeout; - -/** - * Converts a JavaScript string to UTF8 bytes. - * @param {string} str String - * @returns {!Array.} UTF8 bytes - * @inner - */ -function stringToBytes(str) { - var out = [], - i = 0; - utfx.encodeUTF16toUTF8(function() { - if (i >= str.length) return null; - return str.charCodeAt(i++); - }, function(b) { - out.push(b); - }); - return out; -} - -//? include("util/base64.js"); - -//? include("../../node_modules/utfx/dist/utfx-embeddable.js"); - -Date.now = Date.now || function() { return +new Date; }; diff --git a/node_modules/bcryptjs/src/bcrypt/util/base64.js b/node_modules/bcryptjs/src/bcrypt/util/base64.js deleted file mode 100644 index deda4aff..00000000 --- a/node_modules/bcryptjs/src/bcrypt/util/base64.js +++ /dev/null @@ -1,115 +0,0 @@ -// A base64 implementation for the bcrypt algorithm. This is partly non-standard. - -/** - * bcrypt's own non-standard base64 dictionary. - * @type {!Array.} - * @const - * @inner - **/ -var BASE64_CODE = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(''); - -/** - * @type {!Array.} - * @const - * @inner - **/ -var BASE64_INDEX = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, - 1, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, - -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1]; - -/** - * @type {!function(...number):string} - * @inner - */ -var stringFromCharCode = String.fromCharCode; - -/** - * Encodes a byte array to base64 with up to len bytes of input. - * @param {!Array.} b Byte array - * @param {number} len Maximum input length - * @returns {string} - * @inner - */ -function base64_encode(b, len) { - var off = 0, - rs = [], - c1, c2; - if (len <= 0 || len > b.length) - throw Error("Illegal len: "+len); - while (off < len) { - c1 = b[off++] & 0xff; - rs.push(BASE64_CODE[(c1 >> 2) & 0x3f]); - c1 = (c1 & 0x03) << 4; - if (off >= len) { - rs.push(BASE64_CODE[c1 & 0x3f]); - break; - } - c2 = b[off++] & 0xff; - c1 |= (c2 >> 4) & 0x0f; - rs.push(BASE64_CODE[c1 & 0x3f]); - c1 = (c2 & 0x0f) << 2; - if (off >= len) { - rs.push(BASE64_CODE[c1 & 0x3f]); - break; - } - c2 = b[off++] & 0xff; - c1 |= (c2 >> 6) & 0x03; - rs.push(BASE64_CODE[c1 & 0x3f]); - rs.push(BASE64_CODE[c2 & 0x3f]); - } - return rs.join(''); -} - -/** - * Decodes a base64 encoded string to up to len bytes of output. - * @param {string} s String to decode - * @param {number} len Maximum output length - * @returns {!Array.} - * @inner - */ -function base64_decode(s, len) { - var off = 0, - slen = s.length, - olen = 0, - rs = [], - c1, c2, c3, c4, o, code; - if (len <= 0) - throw Error("Illegal len: "+len); - while (off < slen - 1 && olen < len) { - code = s.charCodeAt(off++); - c1 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; - code = s.charCodeAt(off++); - c2 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; - if (c1 == -1 || c2 == -1) - break; - o = (c1 << 2) >>> 0; - o |= (c2 & 0x30) >> 4; - rs.push(stringFromCharCode(o)); - if (++olen >= len || off >= slen) - break; - code = s.charCodeAt(off++); - c3 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; - if (c3 == -1) - break; - o = ((c2 & 0x0f) << 4) >>> 0; - o |= (c3 & 0x3c) >> 2; - rs.push(stringFromCharCode(o)); - if (++olen >= len || off >= slen) - break; - code = s.charCodeAt(off++); - c4 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; - o = ((c3 & 0x03) << 6) >>> 0; - o |= c4; - rs.push(stringFromCharCode(o)); - ++olen; - } - var res = []; - for (off = 0; off - Copyright (c) 2012 Shane Girish - Copyright (c) 2014 Daniel Wirtz - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @license bcrypt.js (c) 2013 Daniel Wirtz - * Released under the Apache License, Version 2.0 - * see: https://github.com/dcodeIO/bcrypt.js for details - */ -(function(global, factory) { - - /* AMD */ if (typeof define === 'function' && define["amd"]) - define([], factory); - /* CommonJS */ else if (typeof require === 'function' && typeof module === "object" && module && module["exports"]) - module["exports"] = factory(); - /* Global */ else - (global["dcodeIO"] = global["dcodeIO"] || {})["bcrypt"] = factory(); - -}(this, function() { - "use strict"; - - //? include("bcrypt.js"); - - return bcrypt; -})); diff --git a/node_modules/bcryptjs/tests/quickbrown.txt b/node_modules/bcryptjs/tests/quickbrown.txt deleted file mode 100644 index 81e850f2..00000000 --- a/node_modules/bcryptjs/tests/quickbrown.txt +++ /dev/null @@ -1,150 +0,0 @@ -Sentences that contain all letters commonly used in a language --------------------------------------------------------------- - -Markus Kuhn -- 2012-04-11 - -This is an example of a plain-text file encoded in UTF-8. - - -Danish (da) ---------- - - Quizdeltagerne spiste jordbΓ¦r med flΓΈde, mens cirkusklovnen - Wolther spillede pΓ₯ xylofon. - (= Quiz contestants were eating strawbery with cream while Wolther - the circus clown played on xylophone.) - -German (de) ------------ - - Falsches Üben von Xylophonmusik quΓ€lt jeden grâßeren Zwerg - (= Wrongful practicing of xylophone music tortures every larger dwarf) - - ZwΓΆlf BoxkΓ€mpfer jagten Eva quer ΓΌber den Sylter Deich - (= Twelve boxing fighters hunted Eva across the dike of Sylt) - - HeizΓΆlrΓΌckstoßabdΓ€mpfung - (= fuel oil recoil absorber) - (jqvwxy missing, but all non-ASCII letters in one word) - -Greek (el) ----------- - - Γα΢έΡς ΞΊΞ±α½Ά μυρτιὲς Ξ΄α½²Ξ½ ΞΈα½° βρῢ πιὰ στὸ χρυσαφὢ ξέφωτο - (= No more shall I see acacias or myrtles in the golden clearing) - - ΞžΞ΅ΟƒΞΊΞ΅Ο€Ξ¬ΞΆΟ‰ τὴν ΟˆΟ…Ο‡ΞΏΟ†ΞΈΟŒΟΞ± βδΡλυγμία - (= I uncover the soul-destroying abhorrence) - -English (en) ------------- - - The quick brown fox jumps over the lazy dog - -Spanish (es) ------------- - - El pingΓΌino Wenceslao hizo kilΓ³metros bajo exhaustiva lluvia y - frΓ­o, aΓ±oraba a su querido cachorro. - (Contains every letter and every accent, but not every combination - of vowel + acute.) - -French (fr) ------------ - - Portez ce vieux whisky au juge blond qui fume sur son Γle intΓ©rieure, Γ  - cΓ΄tΓ© de l'alcΓ΄ve ovoΓ―de, oΓΉ les bΓ»ches se consument dans l'Γ’tre, ce - qui lui permet de penser Γ  la cΓ¦nogenΓ¨se de l'Γͺtre dont il est question - dans la cause ambiguΓ« entendue Γ  MoΓΏ, dans un capharnaΓΌm qui, - pense-t-il, diminue çà et lΓ  la qualitΓ© de son Ε“uvre. - - l'Γle exiguΓ« - OΓΉ l'obΓ¨se jury mΓ»r - FΓͺte l'haΓ― volapΓΌk, - Γ‚ne ex aΓ©quo au whist, - Γ”tez ce vΕ“u déçu. - - Le cΕ“ur déçu mais l'Γ’me plutΓ΄t naΓ―ve, LouΓΏs rΓͺva de crapaΓΌter en - canoΓ« au delΓ  des Γles, prΓ¨s du mΓ€lstrΓΆm oΓΉ brΓ»lent les novΓ¦. - -Irish Gaelic (ga) ------------------ - - D'fhuascail Íosa, Úrmhac na hΓ“ighe Beannaithe, pΓ³r Γ‰ava agus Ádhaimh - -Hungarian (hu) --------------- - - ÁrvΓ­ztΕ±rΕ‘ tΓΌkΓΆrfΓΊrΓ³gΓ©p - (= flood-proof mirror-drilling machine, only all non-ASCII letters) - -Icelandic (is) --------------- - - KΓ¦mi nΓ½ ΓΆxi hΓ©r ykist ΓΎjΓ³fum nΓΊ bæði vΓ­l og Γ‘drepa - - SΓ¦vΓΆr grΓ©t Ñðan ΓΎvΓ­ ΓΊlpan var Γ³nΓ½t - (some ASCII letters missing) - -Japanese (jp) -------------- - - Hiragana: (Iroha) - - γ„γ‚γ―γ«γ»γΈγ¨γ‘γ‚Šγ¬γ‚‹γ‚’ - γ‚γ‹γ‚ˆγŸγ‚Œγγ€γ­γͺらむ - うゐγγŠγγ‚„γΎγ‘γ΅γ“γˆγ¦ - あさきゆめみしゑひもせす - - Katakana: - - γ‚€γƒ­γƒγƒ‹γƒ›γƒ˜γƒˆ チγƒͺγƒŒγƒ«γƒ² ワカヨタレソ γƒ„γƒγƒŠγƒ©γƒ  - γ‚¦γƒ°γƒŽγ‚ͺγ‚―γƒ€γƒž ケフコエテ γ‚’γ‚΅γ‚­γƒ¦γƒ‘γƒŸγ‚· ヱヒヒセスン - -Hebrew (iw) ------------ - - ? Χ“Χ’ בקרן שט בים ΧžΧΧ•Χ›Χ–Χ‘ Χ•ΧœΧ€ΧͺΧ’ מצא ΧœΧ• Χ—Χ‘Χ¨Χ” ΧΧ™Χš Χ”Χ§ΧœΧ™Χ˜Χ” - -Polish (pl) ------------ - - PchnΔ…Δ‡ w tΔ™ Ε‚Γ³dΕΊ jeΕΌa lub oΕ›m skrzyΕ„ fig - (= To push a hedgehog or eight bins of figs in this boat) - -Russian (ru) ------------- - - Π’ Ρ‡Π°Ρ‰Π°Ρ… юга ΠΆΠΈΠ» Π±Ρ‹ цитрус? Π”Π°, Π½ΠΎ Ρ„Π°Π»ΡŒΡˆΠΈΠ²Ρ‹ΠΉ экзСмпляр! - (= Would a citrus live in the bushes of south? Yes, but only a fake one!) - - БъСшь ΠΆΠ΅ Π΅Ρ‰Ρ‘ этих мягких французских Π±ΡƒΠ»ΠΎΠΊ Π΄Π° Π²Ρ‹ΠΏΠ΅ΠΉ Ρ‡Π°ΡŽ - (= Eat some more of these fresh French loafs and have some tea) - -Thai (th) ---------- - - [--------------------------|------------------------] - ๏ ΰΉ€ΰΈ›ΰΉ‡ΰΈ™ΰΈ‘ΰΈ™ΰΈΈΰΈ©ΰΈ’ΰΉŒΰΈͺΰΈΈΰΈ”ΰΈ›ΰΈ£ΰΈ°ΰΉ€ΰΈͺริฐเΰΈ₯ΰΈ΄ΰΈ¨ΰΈ„ΰΈΈΰΈ“ΰΈ„ΰΉˆΰΈ² ΰΈΰΈ§ΰΉˆΰΈ²ΰΈšΰΈ£ΰΈ£ΰΈ”ΰΈ²ΰΈΰΈΉΰΈ‡ΰΈͺΰΈ±ΰΈ•ΰΈ§ΰΉŒΰΉ€ΰΈ”ΰΈ£ΰΈ±ΰΈˆΰΈ‰ΰΈ²ΰΈ™ - ΰΈˆΰΈ‡ΰΈΰΉˆΰΈ²ΰΈŸΰΈ±ΰΈ™ΰΈžΰΈ±ΰΈ’ΰΈ™ΰΈ²ΰΈ§ΰΈ΄ΰΈŠΰΈ²ΰΈΰΈ²ΰΈ£ อฒ่าΰΈ₯ΰΉ‰ΰΈ²ΰΈ‡ΰΈœΰΈ₯ΰΈ²ΰΈΰΈ€ΰΉ…ΰΉ€ΰΈ‚ΰΉˆΰΈ™ΰΈ†ΰΉˆΰΈ²ΰΈšΰΈ΅ΰΈ‘ΰΈ²ΰΉƒΰΈ„ΰΈ£ - ΰΉ„ΰΈ‘ΰΉˆΰΈ–ΰΈ·ΰΈ­ΰΉ‚ΰΈ—ΰΈ©ΰΉ‚ΰΈΰΈ£ΰΈ˜ΰΉΰΈŠΰΉˆΰΈ‡ΰΈ‹ΰΈ±ΰΈ”ΰΈΰΈΆΰΈ”ΰΈΰΈ±ΰΈ”ΰΈ”ΰΉˆΰΈ² ΰΈ«ΰΈ±ΰΈ”ΰΈ­ΰΈ ΰΈ±ΰΈ’ΰΉ€ΰΈ«ΰΈ‘ΰΈ·ΰΈ­ΰΈ™ΰΈΰΈ΅ΰΈ¬ΰΈ²ΰΈ­ΰΈ±ΰΈŠΰΈŒΰΈ²ΰΈͺΰΈ±ΰΈ’ - ΰΈ›ΰΈΰΈ΄ΰΈšΰΈ±ΰΈ•ΰΈ΄ΰΈ›ΰΈ£ΰΈ°ΰΈžΰΈ€ΰΈ•ΰΈ΄ΰΈΰΈŽΰΈΰΈ³ΰΈ«ΰΈ™ΰΈ”ΰΉƒΰΈˆ ΰΈžΰΈΉΰΈ”ΰΈˆΰΈ²ΰΉƒΰΈ«ΰΉ‰ΰΈˆΰΉŠΰΈ°ΰΉ† ΰΈˆΰΉ‹ΰΈ²ΰΉ† ΰΈ™ΰΉˆΰΈ²ΰΈŸΰΈ±ΰΈ‡ΰΉ€ΰΈ­ΰΈ’ ΰΈ― - - [The copyright for the Thai example is owned by The Computer - Association of Thailand under the Royal Patronage of His Majesty the - King.] - -Turkish (tr) ------------- - - PijamalΔ± hasta, yağız şofΓΆre Γ§abucak gΓΌvendi. - (=Patient with pajamas, trusted swarthy driver quickly) - - -Special thanks to the people from all over the world who contributed -these sentences since 1999. - -A much larger collection of such pangrams is now available at - - http://en.wikipedia.org/wiki/List_of_pangrams - diff --git a/node_modules/bcryptjs/tests/suite.js b/node_modules/bcryptjs/tests/suite.js deleted file mode 100644 index 8c8afe19..00000000 --- a/node_modules/bcryptjs/tests/suite.js +++ /dev/null @@ -1,197 +0,0 @@ -var path = require("path"), - fs = require("fs"), - binding = require("bcrypt"), - bcrypt = require(path.join(__dirname, '..', 'index.js'))/*, - isaac = eval( - fs.readFileSync(path.join(__dirname, "..", "src", "bcrypt", "prng", "accum.js"))+ - fs.readFileSync(path.join(__dirname, "..", "src", "bcrypt", "prng", "isaac.js"))+ - " accum.start();"+ - " isaac" - )*/; - -module.exports = { - - "encodeBase64": function(test) { - var str = bcrypt.encodeBase64([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10], 16); - test.strictEqual(str, "..CA.uOD/eaGAOmJB.yMBu"); - test.done(); - }, - - "decodeBase64": function(test) { - var bytes = bcrypt.decodeBase64("..CA.uOD/eaGAOmJB.yMBv.", 16); - test.deepEqual(bytes, [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F]); - test.done(); - }, - - "genSaltSync": function(test) { - var salt = bcrypt.genSaltSync(10); - test.ok(salt); - test.ok(typeof salt == 'string'); - test.ok(salt.length > 0); - test.done(); - }, - - "genSalt": function(test) { - bcrypt.genSalt(10, function(err, salt) { - test.ok(salt); - test.ok(typeof salt == 'string'); - test.ok(salt.length > 0); - test.done(); - }); - }, - - "hashSync": function(test) { - test.doesNotThrow(function() { - bcrypt.hashSync("hello", 10); - }); - test.notEqual(bcrypt.hashSync("hello", 10), bcrypt.hashSync("hello", 10)); - test.done(); - }, - - "hash": function(test) { - bcrypt.hash("hello", 10, function(err, hash) { - test.notOk(err); - test.ok(hash); - test.done(); - }); - }, - - "compareSync": function(test) { - var salt1 = bcrypt.genSaltSync(), - hash1 = bcrypt.hashSync("hello", salt1); // $2a$ - var salt2 = bcrypt.genSaltSync().replace(/\$2a\$/, "$2y$"), - hash2 = bcrypt.hashSync("world", salt2); - var salt3 = bcrypt.genSaltSync().replace(/\$2a\$/, "$2b$"), - hash3 = bcrypt.hashSync("hello world", salt3); - - test.strictEqual(hash1.substring(0,4), "$2a$"); - test.ok(bcrypt.compareSync("hello", hash1)); - test.notOk(bcrypt.compareSync("hello", hash2)); - test.notOk(bcrypt.compareSync("hello", hash3)); - - test.strictEqual(hash2.substring(0,4), "$2y$"); - test.ok(bcrypt.compareSync("world", hash2)); - test.notOk(bcrypt.compareSync("world", hash1)); - test.notOk(bcrypt.compareSync("world", hash3)); - - test.strictEqual(hash3.substring(0,4), "$2b$"); - test.ok(bcrypt.compareSync("hello world", hash3)); - test.notOk(bcrypt.compareSync("hello world", hash1)); - test.notOk(bcrypt.compareSync("hello world", hash2)); - - test.done(); - }, - - "compare": function(test) { - var salt1 = bcrypt.genSaltSync(), - hash1 = bcrypt.hashSync("hello", salt1); // $2a$ - var salt2 = bcrypt.genSaltSync(); - salt2 = salt2.substring(0,2)+'y'+salt2.substring(3); // $2y$ - var hash2 = bcrypt.hashSync("world", salt2); - bcrypt.compare("hello", hash1, function(err, same) { - test.notOk(err); - test.ok(same); - bcrypt.compare("hello", hash2, function(err, same) { - test.notOk(err); - test.notOk(same); - bcrypt.compare("world", hash2, function(err, same) { - test.notOk(err); - test.ok(same); - bcrypt.compare("world", hash1, function(err, same) { - test.notOk(err); - test.notOk(same); - test.done(); - }); - }); - }); - }); - }, - - "getSalt": function(test) { - var hash1 = bcrypt.hashSync("hello", bcrypt.genSaltSync()); - var salt = bcrypt.getSalt(hash1); - var hash2 = bcrypt.hashSync("hello", salt); - test.equal(hash1, hash2); - test.done(); - }, - - "getRounds": function(test) { - var hash1 = bcrypt.hashSync("hello", bcrypt.genSaltSync()); - test.equal(bcrypt.getRounds(hash1), 10); - test.done(); - }, - - "progress": function(test) { - bcrypt.genSalt(12, function(err, salt) { - test.ok(!err); - var progress = []; - bcrypt.hash("hello world", salt, function(err, hash) { - test.ok(!err); - test.ok(typeof hash === 'string'); - test.ok(progress.length >= 2); - test.strictEqual(progress[0], 0); - test.strictEqual(progress[progress.length-1], 1); - test.done(); - }, function(n) { - progress.push(n); - }); - }); - }, - - "promise": function(test) { - bcrypt.genSalt(10) - .then(function(salt) { - bcrypt.hash("hello", salt) - .then(function(hash) { - test.ok(hash); - bcrypt.compare("hello", hash) - .then(function(result) { - test.ok(result); - bcrypt.genSalt(/* no args */) - .then(function(salt) { - test.ok(salt); - test.done(); - }, function(err) { - test.fail(err, null, "promise rejected"); - }); - }, function(err) { - test.fail(err, null, "promise rejected"); - }); - }, function(err) { - test.fail(err, null, 'promise rejected'); - }); - }, function(err) { - test.fail(err, null, "promise rejected"); - }); - }, - - "compat": { - "quickbrown": function(test) { - var pass = fs.readFileSync(path.join(__dirname, "quickbrown.txt"))+"", - salt = bcrypt.genSaltSync(), - hash1 = binding.hashSync(pass, salt), - hash2 = bcrypt.hashSync(pass, salt); - test.equal(hash1, hash2); - test.done(); - }, - - "roundsOOB": function(test) { - var salt1 = bcrypt.genSaltSync(0), // $10$ like not set - salt2 = binding.genSaltSync(0); - test.strictEqual(salt1.substring(0, 7), "$2a$10$"); - test.strictEqual(salt2.substring(0, 7), "$2a$10$"); - - salt1 = bcrypt.genSaltSync(3); // $04$ is lower cap - salt2 = bcrypt.genSaltSync(3); - test.strictEqual(salt1.substring(0, 7), "$2a$04$"); - test.strictEqual(salt2.substring(0, 7), "$2a$04$"); - - salt1 = bcrypt.genSaltSync(32); // $31$ is upper cap - salt2 = bcrypt.genSaltSync(32); - test.strictEqual(salt1.substring(0, 7), "$2a$31$"); - test.strictEqual(salt2.substring(0, 7), "$2a$31$"); - - test.done(); - } - } -}; diff --git a/node_modules/discord.js/.tern-project b/node_modules/discord.js/.tern-project deleted file mode 100644 index f5ce9480..00000000 --- a/node_modules/discord.js/.tern-project +++ /dev/null @@ -1,17 +0,0 @@ -{ - "ecmaVersion": 7, - "libs": [], - "loadEagerly": ["./src/*.js"], - "dontLoad": ["node_modules/**"], - "plugins": { - "es_modules": {}, - "node": {}, - "doc_comment": { - "fullDocs": true, - "strong": true - }, - "webpack": { - "configPath": "./webpack.config.js" - } - } -} diff --git a/node_modules/discord.js/LICENSE b/node_modules/discord.js/LICENSE index 9997d13f..414073d2 100644 --- a/node_modules/discord.js/LICENSE +++ b/node_modules/discord.js/LICENSE @@ -175,7 +175,7 @@ END OF TERMS AND CONDITIONS - Copyright 2015 - 2020 Amish Shah + Copyright 2015 - 2021 Amish Shah Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/node_modules/discord.js/README.md b/node_modules/discord.js/README.md index cbc2bb0e..55dd01c5 100644 --- a/node_modules/discord.js/README.md +++ b/node_modules/discord.js/README.md @@ -5,30 +5,14 @@


- Discord server + Discord server NPM version NPM downloads Build status - Dependencies Patreon

-

- npm installnfo -

-## Table of contents - -- [About](#about) -- [Installation](#installation) - - [Audio engines](#audio-engines) - - [Optional packages](#optional-packages) -- [Example Usage](#example-usage) -- [Links](#links) - - [Extensions](#extensions) -- [Contributing](#contributing) -- [Help](#help) - ## About discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to easily interact with the @@ -41,42 +25,33 @@ discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to ## Installation -**Node.js 12.0.0 or newer is required.** -Ignore any warnings about unmet peer dependencies, as they're all optional. +**Node.js 14.6.0 or newer is required.** -Without voice support: `npm install discord.js` -With voice support ([@discordjs/opus](https://www.npmjs.com/package/@discordjs/opus)): `npm install discord.js @discordjs/opus` -With voice support ([opusscript](https://www.npmjs.com/package/opusscript)): `npm install discord.js opusscript` - -### Audio engines - -The preferred audio engine is @discordjs/opus, as it performs significantly better than opusscript. When both are available, discord.js will automatically choose @discordjs/opus. -Using opusscript is only recommended for development environments where @discordjs/opus is tough to get working. -For production bots, using @discordjs/opus should be considered a necessity, especially if they're going to be running on multiple servers. +```sh-session +npm install discord.js +``` ### Optional packages - [zlib-sync](https://www.npmjs.com/package/zlib-sync) for WebSocket data compression and inflation (`npm install zlib-sync`) - [erlpack](https://github.com/discord/erlpack) for significantly faster WebSocket data (de)serialisation (`npm install discord/erlpack`) -- One of the following packages can be installed for faster voice packet encryption and decryption: - - [sodium](https://www.npmjs.com/package/sodium) (`npm install sodium`) - - [libsodium.js](https://www.npmjs.com/package/libsodium-wrappers) (`npm install libsodium-wrappers`) - [bufferutil](https://www.npmjs.com/package/bufferutil) for a much faster WebSocket connection (`npm install bufferutil`) - [utf-8-validate](https://www.npmjs.com/package/utf-8-validate) in combination with `bufferutil` for much faster WebSocket processing (`npm install utf-8-validate`) +- [@discordjs/voice](https://github.com/discordjs/voice) for interacting with the Discord Voice API ## Example usage ```js -const Discord = require('discord.js'); -const client = new Discord.Client(); +const { Client, Intents } = require('discord.js'); +const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] }); client.on('ready', () => { console.log(`Logged in as ${client.user.tag}!`); }); -client.on('message', msg => { - if (msg.content === 'ping') { - msg.reply('pong'); +client.on('messageCreate', message => { + if (message.content === 'ping') { + message.channel.send('pong'); } }); @@ -89,11 +64,11 @@ client.login('token'); - [Documentation](https://discord.js.org/#/docs/main/master/general/welcome) - [Guide](https://discordjs.guide/) ([source](https://github.com/discordjs/guide)) - this is still for stable See also the [Update Guide](https://discordjs.guide/additional-info/changes-in-v12.html), including updated and removed items in the library. -- [Discord.js Discord server](https://discord.gg/bRCvFy9) +- [Discord.js Discord server](https://discord.gg/djs) - [Discord API Discord server](https://discord.gg/discord-api) - [GitHub](https://github.com/discordjs/discord.js) - [NPM](https://www.npmjs.com/package/discord.js) -- [Related libraries](https://discordapi.com/unofficial/libs.html) +- [Related libraries](https://discord.com/developers/docs/topics/community-resources#libraries) ### Extensions @@ -108,4 +83,4 @@ See [the contribution guide](https://github.com/discordjs/discord.js/blob/master ## Help If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle -nudge in the right direction, please don't hesitate to join our official [Discord.js Server](https://discord.gg/bRCvFy9). +nudge in the right direction, please don't hesitate to join our official [Discord.js Server](https://discord.gg/djs). diff --git a/node_modules/discord.js/esm/discord.mjs b/node_modules/discord.js/esm/discord.mjs deleted file mode 100644 index 8ebf0865..00000000 --- a/node_modules/discord.js/esm/discord.mjs +++ /dev/null @@ -1,95 +0,0 @@ -import Discord from '../src/index.js'; - -export default Discord; - -export const { - BaseClient, - Client, - Shard, - ShardClientUtil, - ShardingManager, - WebhookClient, - ActivityFlags, - BitField, - Collection, - Constants, - DataResolver, - BaseManager, - DiscordAPIError, - HTTPError, - MessageFlags, - Intents, - Permissions, - Speaking, - Snowflake, - SnowflakeUtil, - Structures, - SystemChannelFlags, - UserFlags, - Util, - version, - ChannelManager, - GuildChannelManager, - GuildEmojiManager, - GuildEmojiRoleManager, - GuildMemberManager, - GuildMemberRoleManager, - GuildManager, - ReactionManager, - ReactionUserManager, - MessageManager, - PresenceManager, - RoleManager, - UserManager, - discordSort, - escapeMarkdown, - fetchRecommendedShards, - resolveColor, - resolveString, - splitMessage, - Application, - Base, - Activity, - APIMessage, - BaseGuildEmoji, - CategoryChannel, - Channel, - ClientApplication, - ClientUser, - Collector, - DMChannel, - Emoji, - Guild, - GuildAuditLogs, - GuildChannel, - GuildEmoji, - GuildMember, - GuildPreview, - GuildTemplate, - Integration, - Invite, - Message, - MessageAttachment, - MessageCollector, - MessageEmbed, - MessageMentions, - MessageReaction, - NewsChannel, - PermissionOverwrites, - Presence, - ClientPresence, - ReactionCollector, - ReactionEmoji, - RichPresenceAssets, - Role, - StoreChannel, - Team, - TeamMember, - TextChannel, - User, - VoiceChannel, - VoiceRegion, - VoiceState, - Webhook, - WebSocket -} = Discord; diff --git a/node_modules/discord.js/jsdoc.json b/node_modules/discord.js/jsdoc.json deleted file mode 100644 index 3bf2d096..00000000 --- a/node_modules/discord.js/jsdoc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "plugins": ["node_modules/jsdoc-strip-async-await"] -} diff --git a/node_modules/discord.js/package.json b/node_modules/discord.js/package.json index c0ff9ff1..6cf6c4c1 100644 --- a/node_modules/discord.js/package.json +++ b/node_modules/discord.js/package.json @@ -1,18 +1,17 @@ { "name": "discord.js", - "version": "12.5.3", + "version": "13.0.0-dev.t1627778678.74fc23b", "description": "A powerful library for interacting with the Discord API", - "main": "./src/index", + "main": "./src/index.js", + "module": "./src/index.mjs", "types": "./typings/index.d.ts", + "files": [ + "src", + "typings" + ], "exports": { - ".": [ - { - "require": "./src/index.js", - "import": "./esm/discord.mjs" - }, - "./src/index.js" - ], - "./esm": "./esm/discord.mjs" + "require": "./src/index.js", + "import": "./src/index.mjs" }, "scripts": { "test": "npm run lint && npm run docs:test && npm run lint:typings", @@ -23,12 +22,13 @@ "lint:fix": "eslint src --fix", "lint:typings": "tslint typings/index.d.ts", "prettier": "prettier --write src/**/*.js typings/**/*.ts", - "build:browser": "webpack", - "prepublishOnly": "npm run test && cross-env NODE_ENV=production npm run build:browser" + "prepublishOnly": "npm run test && gen-esm-wrapper ./src/index.js ./src/index.mjs", + "prepare": "is-ci || husky install", + "changelog": "conventional-changelog -p angular -i RELEASE_CHANGELOG.md -s" }, "repository": { "type": "git", - "url": "git+https://github.com/discordjs/discord.js.git" + "url": "https://github.com/discordjs/discord.js.git" }, "keywords": [ "discord", @@ -38,126 +38,46 @@ "node", "discordapp" ], - "author": "Amish Shah ", + "author": "Amish Shah ", "license": "Apache-2.0", "bugs": { "url": "https://github.com/discordjs/discord.js/issues" }, "homepage": "https://github.com/discordjs/discord.js#readme", - "runkitExampleFilename": "./docs/examples/ping.js", - "unpkg": "./webpack/discord.min.js", "dependencies": { - "@discordjs/collection": "^0.1.6", + "@discordjs/builders": "^0.3.0", + "@discordjs/collection": "^0.2.1", "@discordjs/form-data": "^3.0.1", + "@sapphire/async-queue": "^1.1.4", + "@types/ws": "^7.4.5", "abort-controller": "^3.0.0", + "discord-api-types": "^0.22.0", "node-fetch": "^2.6.1", - "prism-media": "^1.2.9", - "setimmediate": "^1.0.5", - "tweetnacl": "^1.0.3", - "ws": "^7.4.4" + "ws": "^7.5.1" }, "devDependencies": { - "@commitlint/cli": "^12.0.1", - "@commitlint/config-angular": "^12.0.1", - "@types/node": "^12.12.6", - "@types/ws": "^7.4.0", + "@commitlint/cli": "^12.1.4", + "@commitlint/config-angular": "^12.1.4", + "@discordjs/docgen": "^0.10.0", + "@types/node": "^14.17.4", + "conventional-changelog-cli": "^2.1.1", "cross-env": "^7.0.3", - "discord.js-docgen": "git+https://github.com/discordjs/docgen.git", - "dtslint": "^4.0.8", - "eslint": "^7.23.0", - "eslint-config-prettier": "^6.13.0", - "eslint-plugin-import": "^2.22.1", - "eslint-plugin-prettier": "^3.3.1", - "husky": "^4.3.0", - "jest": "^26.6.3", - "json-filter-loader": "^1.0.0", - "lint-staged": "^10.5.4", - "prettier": "^2.2.1", - "terser-webpack-plugin": "^4.2.3", + "dtslint": "^4.1.0", + "eslint": "^7.29.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-import": "^2.23.4", + "eslint-plugin-prettier": "^3.4.0", + "gen-esm-wrapper": "^1.1.2", + "husky": "^6.0.0", + "is-ci": "^3.0.0", + "jest": "^27.0.6", + "lint-staged": "^11.0.0", + "prettier": "^2.3.2", "tslint": "^6.1.3", - "typescript": "^4.2.3", - "webpack": "^4.44.2", - "webpack-cli": "^3.3.12" + "typescript": "^4.3.4" }, "engines": { - "node": ">=12.0.0" - }, - "browser": { - "@discordjs/opus": false, - "https": false, - "ws": false, - "erlpack": false, - "prism-media": false, - "opusscript": false, - "node-opus": false, - "tweetnacl": false, - "sodium": false, - "worker_threads": false, - "zlib-sync": false, - "src/sharding/Shard.js": false, - "src/sharding/ShardClientUtil.js": false, - "src/sharding/ShardingManager.js": false, - "src/client/voice/ClientVoiceManager.js": false, - "src/client/voice/VoiceBroadcast.js": false, - "src/client/voice/VoiceConnection.js": false, - "src/client/voice/dispatcher/BroadcastDispatcher.js": false, - "src/client/voice/dispatcher/StreamDispatcher.js": false, - "src/client/voice/networking/VoiceUDPClient.js": false, - "src/client/voice/networking/VoiceWebSocket.js": false, - "src/client/voice/player/AudioPlayer.js": false, - "src/client/voice/player/BasePlayer.js": false, - "src/client/voice/player/BroadcastAudioPlayer.js": false, - "src/client/voice/receiver/PacketHandler.js": false, - "src/client/voice/receiver/Receiver.js": false, - "src/client/voice/util/PlayInterface.js": false, - "src/client/voice/util/Secretbox.js": false, - "src/client/voice/util/Silence.js": false, - "src/client/voice/util/VolumeInterface.js": false - }, - "husky": { - "hooks": { - "pre-commit": "lint-staged", - "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" - } - }, - "lint-staged": { - "*.js": "eslint --fix", - "*.ts": "prettier --write" - }, - "commitlint": { - "extends": [ - "@commitlint/config-angular" - ], - "rules": { - "scope-case": [ - 2, - "always", - "pascal-case" - ], - "type-enum": [ - 2, - "always", - [ - "chore", - "build", - "ci", - "docs", - "feat", - "fix", - "perf", - "refactor", - "revert", - "style", - "test" - ] - ] - } - }, - "prettier": { - "singleQuote": true, - "printWidth": 120, - "trailingComma": "all", - "endOfLine": "lf", - "arrowParens": "avoid" + "node": ">=14.6.0", + "npm": ">=7.0.0" } } diff --git a/node_modules/discord.js/src/WebSocket.js b/node_modules/discord.js/src/WebSocket.js index 90dd51bb..c12db834 100644 --- a/node_modules/discord.js/src/WebSocket.js +++ b/node_modules/discord.js/src/WebSocket.js @@ -1,7 +1,5 @@ 'use strict'; -const { browser } = require('./util/Constants'); - let erlpack; try { @@ -9,15 +7,7 @@ try { if (!erlpack.pack) erlpack = null; } catch {} // eslint-disable-line no-empty -let TextDecoder; - -if (browser) { - TextDecoder = window.TextDecoder; // eslint-disable-line no-undef - exports.WebSocket = window.WebSocket; // eslint-disable-line no-undef -} else { - TextDecoder = require('util').TextDecoder; - exports.WebSocket = require('ws'); -} +exports.WebSocket = require('ws'); const ab = new TextDecoder(); @@ -42,7 +32,6 @@ exports.create = (gateway, query = {}, ...args) => { query = new URLSearchParams(query); if (q) new URLSearchParams(q).forEach((v, k) => query.set(k, v)); const ws = new exports.WebSocket(`${g}?${query}`, ...args); - if (browser) ws.binaryType = 'arraybuffer'; return ws; }; diff --git a/node_modules/discord.js/src/client/BaseClient.js b/node_modules/discord.js/src/client/BaseClient.js index 29abeca5..65dd1847 100644 --- a/node_modules/discord.js/src/client/BaseClient.js +++ b/node_modules/discord.js/src/client/BaseClient.js @@ -1,9 +1,8 @@ 'use strict'; -require('setimmediate'); const EventEmitter = require('events'); const RESTManager = require('../rest/RESTManager'); -const { DefaultOptions } = require('../util/Constants'); +const Options = require('../util/Options'); const Util = require('../util/Util'); /** @@ -14,32 +13,11 @@ class BaseClient extends EventEmitter { constructor(options = {}) { super(); - /** - * Timeouts set by {@link BaseClient#setTimeout} that are still active - * @type {Set} - * @private - */ - this._timeouts = new Set(); - - /** - * Intervals set by {@link BaseClient#setInterval} that are still active - * @type {Set} - * @private - */ - this._intervals = new Set(); - - /** - * Intervals set by {@link BaseClient#setImmediate} that are still active - * @type {Set} - * @private - */ - this._immediates = new Set(); - /** * The options the client was instantiated with * @type {ClientOptions} */ - this.options = Util.mergeDefault(DefaultOptions, options); + this.options = Util.mergeDefault(Options.createDefault(), options); /** * The REST manager of the client @@ -61,82 +39,10 @@ class BaseClient extends EventEmitter { /** * Destroys all assets used by the base client. + * @returns {void} */ destroy() { - for (const t of this._timeouts) this.clearTimeout(t); - for (const i of this._intervals) this.clearInterval(i); - for (const i of this._immediates) this.clearImmediate(i); - this._timeouts.clear(); - this._intervals.clear(); - this._immediates.clear(); - } - - /** - * Sets a timeout that will be automatically cancelled if the client is destroyed. - * @param {Function} fn Function to execute - * @param {number} delay Time to wait before executing (in milliseconds) - * @param {...*} args Arguments for the function - * @returns {Timeout} - */ - setTimeout(fn, delay, ...args) { - const timeout = setTimeout(() => { - fn(...args); - this._timeouts.delete(timeout); - }, delay); - this._timeouts.add(timeout); - return timeout; - } - - /** - * Clears a timeout. - * @param {Timeout} timeout Timeout to cancel - */ - clearTimeout(timeout) { - clearTimeout(timeout); - this._timeouts.delete(timeout); - } - - /** - * Sets an interval that will be automatically cancelled if the client is destroyed. - * @param {Function} fn Function to execute - * @param {number} delay Time to wait between executions (in milliseconds) - * @param {...*} args Arguments for the function - * @returns {Timeout} - */ - setInterval(fn, delay, ...args) { - const interval = setInterval(fn, delay, ...args); - this._intervals.add(interval); - return interval; - } - - /** - * Clears an interval. - * @param {Timeout} interval Interval to cancel - */ - clearInterval(interval) { - clearInterval(interval); - this._intervals.delete(interval); - } - - /** - * Sets an immediate that will be automatically cancelled if the client is destroyed. - * @param {Function} fn Function to execute - * @param {...*} args Arguments for the function - * @returns {Immediate} - */ - setImmediate(fn, ...args) { - const immediate = setImmediate(fn, ...args); - this._immediates.add(immediate); - return immediate; - } - - /** - * Clears an immediate. - * @param {Immediate} immediate Immediate to cancel - */ - clearImmediate(immediate) { - clearImmediate(immediate); - this._immediates.delete(immediate); + if (this.rest.sweepInterval) clearInterval(this.rest.sweepInterval); } /** diff --git a/node_modules/discord.js/src/client/Client.js b/node_modules/discord.js/src/client/Client.js index 5847f757..a28beb2e 100644 --- a/node_modules/discord.js/src/client/Client.js +++ b/node_modules/discord.js/src/client/Client.js @@ -1,27 +1,30 @@ 'use strict'; +const { Collection } = require('@discordjs/collection'); const BaseClient = require('./BaseClient'); const ActionsManager = require('./actions/ActionsManager'); const ClientVoiceManager = require('./voice/ClientVoiceManager'); const WebSocketManager = require('./websocket/WebSocketManager'); const { Error, TypeError, RangeError } = require('../errors'); +const BaseGuildEmojiManager = require('../managers/BaseGuildEmojiManager'); const ChannelManager = require('../managers/ChannelManager'); -const GuildEmojiManager = require('../managers/GuildEmojiManager'); const GuildManager = require('../managers/GuildManager'); const UserManager = require('../managers/UserManager'); const ShardClientUtil = require('../sharding/ShardClientUtil'); -const ClientApplication = require('../structures/ClientApplication'); +const ClientPresence = require('../structures/ClientPresence'); const GuildPreview = require('../structures/GuildPreview'); const GuildTemplate = require('../structures/GuildTemplate'); const Invite = require('../structures/Invite'); +const Sticker = require('../structures/Sticker'); +const StickerPack = require('../structures/StickerPack'); const VoiceRegion = require('../structures/VoiceRegion'); const Webhook = require('../structures/Webhook'); -const Collection = require('../util/Collection'); -const { Events, browser, DefaultOptions } = require('../util/Constants'); +const Widget = require('../structures/Widget'); +const { Events, InviteScopes, Status } = require('../util/Constants'); const DataResolver = require('../util/DataResolver'); const Intents = require('../util/Intents'); +const Options = require('../util/Options'); const Permissions = require('../util/Permissions'); -const Structures = require('../util/Structures'); /** * The main hub for interacting with the Discord API, and the starting point for any bot. @@ -29,27 +32,21 @@ const Structures = require('../util/Structures'); */ class Client extends BaseClient { /** - * @param {ClientOptions} [options] Options for the client + * @param {ClientOptions} options Options for the client */ - constructor(options = {}) { + constructor(options) { super(Object.assign({ _tokenType: 'Bot' }, options)); - // Obtain shard details from environment or if present, worker threads - let data = process.env; - try { - // Test if worker threads module is present and used - data = require('worker_threads').workerData || data; - } catch { - // Do nothing - } + const data = require('worker_threads').workerData ?? process.env; + const defaults = Options.createDefault(); - if (this.options.shards === DefaultOptions.shards) { + if (this.options.shards === defaults.shards) { if ('SHARDS' in data) { this.options.shards = JSON.parse(data.SHARDS); } } - if (this.options.shardCount === DefaultOptions.shardCount) { + if (this.options.shardCount === defaults.shardCount) { if ('SHARD_COUNT' in data) { this.options.shardCount = Number(data.SHARD_COUNT); } else if (Array.isArray(this.options.shards)) { @@ -75,6 +72,20 @@ class Client extends BaseClient { this._validateOptions(); + /** + * Functions called when a cache is garbage collected or the Client is destroyed + * @type {Set} + * @private + */ + this._cleanups = new Set(); + + /** + * The finalizers used to cleanup items. + * @type {FinalizationRegistry} + * @private + */ + this._finalizers = new FinalizationRegistry(this._finalize.bind(this)); + /** * The WebSocket manager of the client * @type {WebSocketManager} @@ -89,35 +100,34 @@ class Client extends BaseClient { this.actions = new ActionsManager(this); /** - * The voice manager of the client (`null` in browsers) - * @type {?ClientVoiceManager} + * The voice manager of the client + * @type {ClientVoiceManager} */ - this.voice = !browser ? new ClientVoiceManager(this) : null; + this.voice = new ClientVoiceManager(this); /** * Shard helpers for the client (only if the process was spawned from a {@link ShardingManager}) * @type {?ShardClientUtil} */ - this.shard = - !browser && process.env.SHARDING_MANAGER - ? ShardClientUtil.singleton(this, process.env.SHARDING_MANAGER_MODE) - : null; + this.shard = process.env.SHARDING_MANAGER + ? ShardClientUtil.singleton(this, process.env.SHARDING_MANAGER_MODE) + : null; /** - * All of the {@link User} objects that have been cached at any point, mapped by their IDs + * All of the {@link User} objects that have been cached at any point, mapped by their ids * @type {UserManager} */ this.users = new UserManager(this); /** - * All of the guilds the client is currently handling, mapped by their IDs - + * All of the guilds the client is currently handling, mapped by their ids - * as long as sharding isn't being used, this will be *every* guild the bot is a member of * @type {GuildManager} */ this.guilds = new GuildManager(this); /** - * All of the {@link Channel}s that the client is currently handling, mapped by their IDs - + * All of the {@link Channel}s that the client is currently handling, mapped by their ids - * as long as sharding isn't being used, this will be *every* channel in *every* guild the bot * is a member of. Note that DM channels will not be initially cached, and thus not be present * in the Manager without their explicit fetching or use. @@ -125,16 +135,15 @@ class Client extends BaseClient { */ this.channels = new ChannelManager(this); - const ClientPresence = Structures.get('ClientPresence'); /** * The presence of the Client * @private * @type {ClientPresence} */ - this.presence = new ClientPresence(this); + this.presence = new ClientPresence(this, this.options.presence); Object.defineProperty(this, 'token', { writable: true }); - if (!browser && !this.token && 'DISCORD_TOKEN' in process.env) { + if (!this.token && 'DISCORD_TOKEN' in process.env) { /** * Authorization token for the logged in bot. * If present, this defaults to `process.env.DISCORD_TOKEN` when instantiating the client @@ -152,6 +161,12 @@ class Client extends BaseClient { */ this.user = null; + /** + * The application of this bot + * @type {?ClientApplication} + */ + this.application = null; + /** * Time at which the client was last regarded as being in the `READY` state * (each time the client disconnects and successfully reconnects, this will be overwritten) @@ -160,17 +175,24 @@ class Client extends BaseClient { this.readyAt = null; if (this.options.messageSweepInterval > 0) { - this.setInterval(this.sweepMessages.bind(this), this.options.messageSweepInterval * 1000); + process.emitWarning( + 'The message sweeping client options are deprecated, use the makeCache option with LimitedCollection instead.', + 'DeprecationWarning', + ); + this.sweepMessageInterval = setInterval( + this.sweepMessages.bind(this), + this.options.messageSweepInterval * 1000, + ).unref(); } } /** - * All custom emojis that the client has access to, mapped by their IDs - * @type {GuildEmojiManager} + * All custom emojis that the client has access to, mapped by their ids + * @type {BaseGuildEmojiManager} * @readonly */ get emojis() { - const emojis = new GuildEmojiManager({ client: this }); + const emojis = new BaseGuildEmojiManager(this); for (const guild of this.guilds.cache.values()) { if (guild.available) for (const emoji of guild.emojis.cache.values()) emojis.cache.set(emoji.id, emoji); } @@ -183,7 +205,7 @@ class Client extends BaseClient { * @readonly */ get readyTimestamp() { - return this.readyAt ? this.readyAt.getTime() : null; + return this.readyAt?.getTime() ?? null; } /** @@ -228,12 +250,27 @@ class Client extends BaseClient { } } + /** + * Returns whether the client has logged in, indicative of being able to access + * properties such as `user` and `application`. + * @returns {boolean} + */ + isReady() { + return this.ws.status === Status.READY; + } + /** * Logs out, terminates the connection to Discord, and destroys the client. * @returns {void} */ destroy() { super.destroy(); + + for (const fn of this._cleanups) fn(); + this._cleanups.clear(); + + if (this.sweepMessageInterval) clearInterval(this.sweepMessageInterval); + this.ws.destroy(); this.token = null; } @@ -243,7 +280,7 @@ class Client extends BaseClient { * @param {InviteResolvable} invite Invite code or URL * @returns {Promise} * @example - * client.fetchInvite('https://discord.gg/bRCvFy9') + * client.fetchInvite('https://discord.gg/djs') * .then(invite => console.log(`Obtained invite with code: ${invite.code}`)) * .catch(console.error); */ @@ -251,7 +288,7 @@ class Client extends BaseClient { const code = DataResolver.resolveInviteCode(invite); return this.api .invites(code) - .get({ query: { with_counts: true } }) + .get({ query: { with_counts: true, with_expiration: true } }) .then(data => new Invite(this, data)); } @@ -274,7 +311,7 @@ class Client extends BaseClient { /** * Obtains a webhook from Discord. - * @param {Snowflake} id ID of the webhook + * @param {Snowflake} id The webhook's id * @param {string} [token] Token for the webhook * @returns {Promise} * @example @@ -286,7 +323,7 @@ class Client extends BaseClient { return this.api .webhooks(id, token) .get() - .then(data => new Webhook(this, data)); + .then(data => new Webhook(this, { token, ...data })); } /** @@ -305,6 +342,50 @@ class Client extends BaseClient { }); } + /** + * Obtains a sticker from Discord. + * @param {Snowflake} id The sticker's id + * @returns {Promise} + * @example + * client.fetchSticker('id') + * .then(sticker => console.log(`Obtained sticker with name: ${sticker.name}`)) + * .catch(console.error); + */ + async fetchSticker(id) { + const data = await this.api.stickers(id).get(); + return new Sticker(this, data); + } + + /** + * Obtains the list of sticker packs available to Nitro subscribers from Discord. + * @returns {Promise>} + * @example + * client.fetchPremiumStickerPacks() + * .then(packs => console.log(`Available sticker packs are: ${packs.map(pack => pack.name).join(', ')}`)) + * .catch(console.error); + */ + async fetchPremiumStickerPacks() { + const data = await this.api('sticker-packs').get(); + return new Collection(data.sticker_packs.map(p => [p.id, new StickerPack(this, p)])); + } + /** + * A last ditch cleanup function for garbage collection. + * @param {Function} options.cleanup The function called to GC + * @param {string} [options.message] The message to send after a successful GC + * @param {string} [options.name] The name of the item being GCed + */ + _finalize({ cleanup, message, name }) { + try { + cleanup(); + this._cleanups.delete(cleanup); + if (message) { + this.emit(Events.DEBUG, message); + } + } catch { + this.emit(Events.DEBUG, `Garbage collection failed on ${name ?? 'an unknown item'}.`); + } + } + /** * Sweeps all text-based channels' messages and removes the ones older than the max message lifetime. * If the message has been edited, the time of the edit is used rather than the time of the original message. @@ -336,7 +417,7 @@ class Client extends BaseClient { channels++; messages += channel.messages.cache.sweep( - message => now - (message.editedTimestamp || message.createdTimestamp) > lifetimeMs, + message => now - (message.editedTimestamp ?? message.createdTimestamp) > lifetimeMs, ); } @@ -347,24 +428,13 @@ class Client extends BaseClient { return messages; } - /** - * Obtains the OAuth Application of this bot from Discord. - * @returns {Promise} - */ - fetchApplication() { - return this.api.oauth2 - .applications('@me') - .get() - .then(app => new ClientApplication(this, app)); - } - /** * Obtains a guild preview from Discord, available for all guilds the bot is in and all Discoverable guilds. * @param {GuildResolvable} guild The guild to fetch the preview for * @returns {Promise} */ fetchGuildPreview(guild) { - const id = this.guilds.resolveID(guild); + const id = this.guilds.resolveId(guild); if (!id) throw new TypeError('INVALID_TYPE', 'guild', 'GuildResolvable'); return this.api .guilds(id) @@ -372,39 +442,86 @@ class Client extends BaseClient { .then(data => new GuildPreview(this, data)); } + /** + * Obtains the widget data of a guild from Discord, available for guilds with the widget enabled. + * @param {GuildResolvable} guild The guild to fetch the widget data for + * @returns {Promise} + */ + async fetchGuildWidget(guild) { + const id = this.guilds.resolveId(guild); + if (!id) throw new TypeError('INVALID_TYPE', 'guild', 'GuildResolvable'); + const data = await this.api.guilds(id, 'widget.json').get(); + return new Widget(this, data); + } + + /** + * Options for {@link Client#generateInvite}. + * @typedef {Object} InviteGenerationOptions + * @property {InviteScope[]} scopes Scopes that should be requested + * @property {PermissionResolvable} [permissions] Permissions to request + * @property {GuildResolvable} [guild] Guild to preselect + * @property {boolean} [disableGuildSelect] Whether to disable the guild selection + */ + /** * Generates a link that can be used to invite the bot to a guild. - * @param {InviteGenerationOptions|PermissionResolvable} [options] Permissions to request - * @returns {Promise} + * @param {InviteGenerationOptions} [options={}] Options for the invite + * @returns {string} * @example - * client.generateInvite({ - * permissions: ['SEND_MESSAGES', 'MANAGE_GUILD', 'MENTION_EVERYONE'], - * }) - * .then(link => console.log(`Generated bot invite link: ${link}`)) - * .catch(console.error); + * const link = client.generateInvite({ + * scopes: ['applications.commands'], + * }); + * console.log(`Generated application invite link: ${link}`); + * @example + * const link = client.generateInvite({ + * permissions: [ + * Permissions.FLAGS.SEND_MESSAGES, + * Permissions.FLAGS.MANAGE_GUILD, + * Permissions.FLAGS.MENTION_EVERYONE, + * ], + * scopes: ['bot'], + * }); + * console.log(`Generated bot invite link: ${link}`); */ - async generateInvite(options = {}) { - if (Array.isArray(options) || ['string', 'number'].includes(typeof options) || options instanceof Permissions) { - process.emitWarning( - 'Client#generateInvite: Generate invite with an options object instead of a PermissionResolvable', - 'DeprecationWarning', - ); - options = { permissions: options }; - } - const application = await this.fetchApplication(); + generateInvite(options = {}) { + if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true); + if (!this.application) throw new Error('CLIENT_NOT_READY', 'generate an invite link'); + const query = new URLSearchParams({ - client_id: application.id, - permissions: Permissions.resolve(options.permissions), - scope: 'bot', + client_id: this.application.id, }); - if (typeof options.disableGuildSelect === 'boolean') { - query.set('disable_guild_select', options.disableGuildSelect.toString()); + + const { scopes } = options; + if (typeof scopes === 'undefined') { + throw new TypeError('INVITE_MISSING_SCOPES'); + } + if (!Array.isArray(scopes)) { + throw new TypeError('INVALID_TYPE', 'scopes', 'Array of Invite Scopes', true); + } + if (!scopes.some(scope => ['bot', 'applications.commands'].includes(scope))) { + throw new TypeError('INVITE_MISSING_SCOPES'); } - if (typeof options.guild !== 'undefined') { - const guildID = this.guilds.resolveID(options.guild); - if (!guildID) throw new TypeError('INVALID_TYPE', 'options.guild', 'GuildResolvable'); - query.set('guild_id', guildID); + const invalidScope = scopes.find(scope => !InviteScopes.includes(scope)); + if (invalidScope) { + throw new TypeError('INVALID_ELEMENT', 'Array', 'scopes', invalidScope); } + query.set('scope', scopes.join(' ')); + + if (options.permissions) { + const permissions = Permissions.resolve(options.permissions); + if (permissions) query.set('permissions', permissions); + } + + if (options.disableGuildSelect) { + query.set('disable_guild_select', true); + } + + if (options.guild) { + const guildId = this.guilds.resolveId(options.guild); + if (!guildId) throw new TypeError('INVALID_TYPE', 'options.guild', 'GuildResolvable'); + query.set('guild_id', guildId); + } + return `${this.options.http.api}${this.api.oauth2.authorize}?${query}`; } @@ -431,8 +548,10 @@ class Client extends BaseClient { * @private */ _validateOptions(options = this.options) { - if (typeof options.ws.intents !== 'undefined') { - options.ws.intents = Intents.resolve(options.ws.intents); + if (typeof options.intents === 'undefined') { + throw new TypeError('CLIENT_MISSING_INTENTS'); + } else { + options.intents = Intents.resolve(options.intents); } if (typeof options.shardCount !== 'number' || isNaN(options.shardCount) || options.shardCount < 1) { throw new TypeError('CLIENT_INVALID_OPTION', 'shardCount', 'a number greater than or equal to 1'); @@ -441,8 +560,8 @@ class Client extends BaseClient { throw new TypeError('CLIENT_INVALID_OPTION', 'shards', "'auto', a number or array of numbers"); } if (options.shards && !options.shards.length) throw new RangeError('CLIENT_INVALID_PROVIDED_SHARDS'); - if (typeof options.messageCacheMaxSize !== 'number' || isNaN(options.messageCacheMaxSize)) { - throw new TypeError('CLIENT_INVALID_OPTION', 'messageCacheMaxSize', 'a number'); + if (typeof options.makeCache !== 'function') { + throw new TypeError('CLIENT_INVALID_OPTION', 'makeCache', 'a function'); } if (typeof options.messageCacheLifetime !== 'number' || isNaN(options.messageCacheLifetime)) { throw new TypeError('CLIENT_INVALID_OPTION', 'The messageCacheLifetime', 'a number'); @@ -450,18 +569,8 @@ class Client extends BaseClient { if (typeof options.messageSweepInterval !== 'number' || isNaN(options.messageSweepInterval)) { throw new TypeError('CLIENT_INVALID_OPTION', 'messageSweepInterval', 'a number'); } - if ( - typeof options.messageEditHistoryMaxSize !== 'number' || - isNaN(options.messageEditHistoryMaxSize) || - options.messageEditHistoryMaxSize < -1 - ) { - throw new TypeError('CLIENT_INVALID_OPTION', 'messageEditHistoryMaxSize', 'a number greater than or equal to -1'); - } - if (typeof options.fetchAllMembers !== 'boolean') { - throw new TypeError('CLIENT_INVALID_OPTION', 'fetchAllMembers', 'a boolean'); - } - if (typeof options.disableMentions !== 'string') { - throw new TypeError('CLIENT_INVALID_OPTION', 'disableMentions', 'a string'); + if (typeof options.invalidRequestWarningInterval !== 'number' || isNaN(options.invalidRequestWarningInterval)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'invalidRequestWarningInterval', 'a number'); } if (!Array.isArray(options.partials)) { throw new TypeError('CLIENT_INVALID_OPTION', 'partials', 'an Array'); @@ -472,25 +581,32 @@ class Client extends BaseClient { if (typeof options.restRequestTimeout !== 'number' || isNaN(options.restRequestTimeout)) { throw new TypeError('CLIENT_INVALID_OPTION', 'restRequestTimeout', 'a number'); } + if (typeof options.restGlobalRateLimit !== 'number' || isNaN(options.restGlobalRateLimit)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'restGlobalRateLimit', 'a number'); + } if (typeof options.restSweepInterval !== 'number' || isNaN(options.restSweepInterval)) { throw new TypeError('CLIENT_INVALID_OPTION', 'restSweepInterval', 'a number'); } if (typeof options.retryLimit !== 'number' || isNaN(options.retryLimit)) { throw new TypeError('CLIENT_INVALID_OPTION', 'retryLimit', 'a number'); } + if (typeof options.failIfNotExists !== 'boolean') { + throw new TypeError('CLIENT_INVALID_OPTION', 'failIfNotExists', 'a boolean'); + } + if (!Array.isArray(options.userAgentSuffix)) { + throw new TypeError('CLIENT_INVALID_OPTION', 'userAgentSuffix', 'an array of strings'); + } + if ( + typeof options.rejectOnRateLimit !== 'undefined' && + !(typeof options.rejectOnRateLimit === 'function' || Array.isArray(options.rejectOnRateLimit)) + ) { + throw new TypeError('CLIENT_INVALID_OPTION', 'rejectOnRateLimit', 'an array or a function'); + } } } module.exports = Client; -/** - * Options for {@link Client#generateInvite}. - * @typedef {Object} InviteGenerationOptions - * @property {PermissionResolvable} [permissions] Permissions to request - * @property {GuildResolvable} [guild] Guild to preselect - * @property {boolean} [disableGuildSelect] Whether to disable the guild selection - */ - /** * Emitted for general warnings. * @event Client#warn diff --git a/node_modules/discord.js/src/client/WebhookClient.js b/node_modules/discord.js/src/client/WebhookClient.js index cea66319..da441b18 100644 --- a/node_modules/discord.js/src/client/WebhookClient.js +++ b/node_modules/discord.js/src/client/WebhookClient.js @@ -1,6 +1,7 @@ 'use strict'; const BaseClient = require('./BaseClient'); +const { Error } = require('../errors'); const Webhook = require('../structures/Webhook'); /** @@ -10,20 +11,53 @@ const Webhook = require('../structures/Webhook'); */ class WebhookClient extends BaseClient { /** - * @param {Snowflake} id ID of the webhook - * @param {string} token Token of the webhook + * The data for the webhook client containing either an id and token or just a URL + * @typedef {Object} WebhookClientData + * @property {Snowflake} [id] The id of the webhook + * @property {string} [token] The token of the webhook + * @property {string} [url] The full url for the webhook client + */ + + /** + * @param {WebhookClientData} data The data of the webhook * @param {ClientOptions} [options] Options for the client * @example * // Create a new webhook and send a message - * const hook = new Discord.WebhookClient('1234', 'abcdef'); + * const hook = new Discord.WebhookClient({ id: '1234', token: 'abcdef' }); * hook.send('This will send a message').catch(console.error); */ - constructor(id, token, options) { + constructor(data, options) { super(options); Object.defineProperty(this, 'client', { value: this }); + let { id, token } = data; + + if ('url' in data) { + const url = data.url.match( + // eslint-disable-next-line no-useless-escape + /^https?:\/\/(?:canary|ptb)?\.?discord\.com\/api\/webhooks(?:\/v[0-9]\d*)?\/([^\/]+)\/([^\/]+)/i, + ); + + if (!url || url.length <= 1) throw new Error('WEBHOOK_URL_INVALID'); + + [, id, token] = url; + } + this.id = id; Object.defineProperty(this, 'token', { value: token, writable: true, configurable: true }); } + + // These are here only for documentation purposes - they are implemented by Webhook + /* eslint-disable no-empty-function */ + send() {} + sendSlackMessage() {} + fetchMessage() {} + edit() {} + editMessage() {} + delete() {} + deleteMessage() {} + get createdTimestamp() {} + get createdAt() {} + get url() {} } Webhook.applyToClass(WebhookClient); diff --git a/node_modules/discord.js/src/client/actions/Action.js b/node_modules/discord.js/src/client/actions/Action.js index 69e3b63a..10de5370 100644 --- a/node_modules/discord.js/src/client/actions/Action.js +++ b/node_modules/discord.js/src/client/actions/Action.js @@ -26,20 +26,20 @@ class GenericAction { getPayload(data, manager, id, partialType, cache) { const existing = manager.cache.get(id); if (!existing && this.client.options.partials.includes(partialType)) { - return manager.add(data, cache); + return manager._add(data, cache); } return existing; } getChannel(data) { - const id = data.channel_id || data.id; + const id = data.channel_id ?? data.id; return ( - data.channel || + data.channel ?? this.getPayload( { id, guild_id: data.guild_id, - recipients: [data.author || { id: data.user_id }], + recipients: [data.author ?? { id: data.user_id }], }, this.client.channels, id, @@ -49,14 +49,14 @@ class GenericAction { } getMessage(data, channel, cache) { - const id = data.message_id || data.id; + const id = data.message_id ?? data.id; return ( - data.message || + data.message ?? this.getPayload( { id, channel_id: channel.id, - guild_id: data.guild_id || (channel.guild ? channel.guild.id : null), + guild_id: data.guild_id ?? channel.guild?.id, }, channel.messages, id, @@ -67,12 +67,12 @@ class GenericAction { } getReaction(data, message, user) { - const id = data.emoji.id || decodeURIComponent(data.emoji.name); + const id = data.emoji.id ?? decodeURIComponent(data.emoji.name); return this.getPayload( { emoji: data.emoji, count: message.partial ? null : 0, - me: user ? user.id === this.client.user.id : false, + me: user?.id === this.client.user.id, }, message.reactions, id, @@ -86,16 +86,16 @@ class GenericAction { getUser(data) { const id = data.user_id; - return data.user || this.getPayload({ id }, this.client.users, id, PartialTypes.USER); + return data.user ?? this.getPayload({ id }, this.client.users, id, PartialTypes.USER); } getUserFromMember(data) { - if (data.guild_id && data.member && data.member.user) { + if (data.guild_id && data.member?.user) { const guild = this.client.guilds.cache.get(data.guild_id); if (guild) { - return guild.members.add(data.member).user; + return guild.members._add(data.member).user; } else { - return this.client.users.add(data.member.user); + return this.client.users._add(data.member.user); } } return this.getUser(data); diff --git a/node_modules/discord.js/src/client/actions/ActionsManager.js b/node_modules/discord.js/src/client/actions/ActionsManager.js index 4055795a..a40b5be0 100644 --- a/node_modules/discord.js/src/client/actions/ActionsManager.js +++ b/node_modules/discord.js/src/client/actions/ActionsManager.js @@ -1,42 +1,17 @@ 'use strict'; +const fs = require('fs'); + class ActionsManager { constructor(client) { this.client = client; - this.register(require('./MessageCreate')); - this.register(require('./MessageDelete')); - this.register(require('./MessageDeleteBulk')); - this.register(require('./MessageUpdate')); - this.register(require('./MessageReactionAdd')); - this.register(require('./MessageReactionRemove')); - this.register(require('./MessageReactionRemoveAll')); - this.register(require('./MessageReactionRemoveEmoji')); - this.register(require('./ChannelCreate')); - this.register(require('./ChannelDelete')); - this.register(require('./ChannelUpdate')); - this.register(require('./GuildDelete')); - this.register(require('./GuildUpdate')); - this.register(require('./InviteCreate')); - this.register(require('./InviteDelete')); - this.register(require('./GuildMemberRemove')); - this.register(require('./GuildMemberUpdate')); - this.register(require('./GuildBanRemove')); - this.register(require('./GuildRoleCreate')); - this.register(require('./GuildRoleDelete')); - this.register(require('./GuildRoleUpdate')); - this.register(require('./PresenceUpdate')); - this.register(require('./UserUpdate')); - this.register(require('./VoiceStateUpdate')); - this.register(require('./GuildEmojiCreate')); - this.register(require('./GuildEmojiDelete')); - this.register(require('./GuildEmojiUpdate')); - this.register(require('./GuildEmojisUpdate')); - this.register(require('./GuildRolesPositionUpdate')); - this.register(require('./GuildChannelsPositionUpdate')); - this.register(require('./GuildIntegrationsUpdate')); - this.register(require('./WebhooksUpdate')); - this.register(require('./TypingStart')); + const files = fs.readdirSync(__dirname); + + for (const file of files) { + if (['Action.js', 'ActionsManager.js'].includes(file)) continue; + this.register(require(`./${file}`)); + } } register(Action) { diff --git a/node_modules/discord.js/src/client/actions/ChannelCreate.js b/node_modules/discord.js/src/client/actions/ChannelCreate.js index fa60a0b3..68eb2dc0 100644 --- a/node_modules/discord.js/src/client/actions/ChannelCreate.js +++ b/node_modules/discord.js/src/client/actions/ChannelCreate.js @@ -7,12 +7,12 @@ class ChannelCreateAction extends Action { handle(data) { const client = this.client; const existing = client.channels.cache.has(data.id); - const channel = client.channels.add(data); + const channel = client.channels._add(data); if (!existing && channel) { /** - * Emitted whenever a channel is created. + * Emitted whenever a guild channel is created. * @event Client#channelCreate - * @param {DMChannel|GuildChannel} channel The channel that was created + * @param {GuildChannel} channel The channel that was created */ client.emit(Events.CHANNEL_CREATE, channel); } diff --git a/node_modules/discord.js/src/client/actions/ChannelDelete.js b/node_modules/discord.js/src/client/actions/ChannelDelete.js index 2956d72f..ad5cffd9 100644 --- a/node_modules/discord.js/src/client/actions/ChannelDelete.js +++ b/node_modules/discord.js/src/client/actions/ChannelDelete.js @@ -12,10 +12,10 @@ class ChannelDeleteAction extends Action { handle(data) { const client = this.client; - let channel = client.channels.cache.get(data.id); + const channel = client.channels.cache.get(data.id); if (channel) { - client.channels.remove(channel.id); + client.channels._remove(channel.id); channel.deleted = true; if (channel.messages && !(channel instanceof DMChannel)) { for (const message of channel.messages.cache.values()) { diff --git a/node_modules/discord.js/src/client/actions/ChannelUpdate.js b/node_modules/discord.js/src/client/actions/ChannelUpdate.js index 06bb71b8..1228eb83 100644 --- a/node_modules/discord.js/src/client/actions/ChannelUpdate.js +++ b/node_modules/discord.js/src/client/actions/ChannelUpdate.js @@ -12,11 +12,9 @@ class ChannelUpdateAction extends Action { if (channel) { const old = channel._update(data); - if (ChannelTypes[channel.type.toUpperCase()] !== data.type) { + if (ChannelTypes[channel.type] !== data.type) { const newChannel = Channel.create(this.client, data, channel.guild); for (const [id, message] of channel.messages.cache) newChannel.messages.cache.set(id, message); - newChannel._typing = new Map(channel._typing); - channel = newChannel; this.client.channels.cache.set(channel.id, channel); } @@ -24,6 +22,8 @@ class ChannelUpdateAction extends Action { old, updated: channel, }; + } else { + client.channels._add(data); } return {}; diff --git a/node_modules/discord.js/src/client/actions/GuildBanRemove.js b/node_modules/discord.js/src/client/actions/GuildBanRemove.js index fc28e113..51547359 100644 --- a/node_modules/discord.js/src/client/actions/GuildBanRemove.js +++ b/node_modules/discord.js/src/client/actions/GuildBanRemove.js @@ -1,20 +1,24 @@ 'use strict'; const Action = require('./Action'); +const GuildBan = require('../../structures/GuildBan'); const { Events } = require('../../util/Constants'); class GuildBanRemove extends Action { handle(data) { const client = this.client; const guild = client.guilds.cache.get(data.guild_id); - const user = client.users.add(data.user); + /** * Emitted whenever a member is unbanned from a guild. * @event Client#guildBanRemove - * @param {Guild} guild The guild that the unban occurred in - * @param {User} user The user that was unbanned + * @param {GuildBan} ban The ban that was removed */ - if (guild && user) client.emit(Events.GUILD_BAN_REMOVE, guild, user); + if (guild) { + const ban = guild.bans.cache.get(data.user.id) ?? new GuildBan(client, data, guild); + guild.bans.cache.delete(ban.user.id); + client.emit(Events.GUILD_BAN_REMOVE, ban); + } } } diff --git a/node_modules/discord.js/src/client/actions/GuildDelete.js b/node_modules/discord.js/src/client/actions/GuildDelete.js index 8bb630ff..b27d9022 100644 --- a/node_modules/discord.js/src/client/actions/GuildDelete.js +++ b/node_modules/discord.js/src/client/actions/GuildDelete.js @@ -14,10 +14,6 @@ class GuildDeleteAction extends Action { let guild = client.guilds.cache.get(data.id); if (guild) { - for (const channel of guild.channels.cache.values()) { - if (channel.type === 'text') channel.stopTyping(true); - } - if (data.unavailable) { // Guild is unavailable guild.available = false; @@ -36,8 +32,8 @@ class GuildDeleteAction extends Action { }; } - for (const channel of guild.channels.cache.values()) this.client.channels.remove(channel.id); - if (guild.voice && guild.voice.connection) guild.voice.connection.disconnect(); + for (const channel of guild.channels.cache.values()) this.client.channels._remove(channel.id); + client.voice.adapters.get(data.id)?.destroy(); // Delete guild client.guilds.cache.delete(guild.id); @@ -53,14 +49,14 @@ class GuildDeleteAction extends Action { this.deleted.set(guild.id, guild); this.scheduleForDeletion(guild.id); } else { - guild = this.deleted.get(data.id) || null; + guild = this.deleted.get(data.id) ?? null; } return { guild }; } scheduleForDeletion(id) { - this.client.setTimeout(() => this.deleted.delete(id), this.client.options.restWsBridgeTimeout); + setTimeout(() => this.deleted.delete(id), this.client.options.restWsBridgeTimeout).unref(); } } diff --git a/node_modules/discord.js/src/client/actions/GuildEmojiCreate.js b/node_modules/discord.js/src/client/actions/GuildEmojiCreate.js index f47ddd5f..ccc634cc 100644 --- a/node_modules/discord.js/src/client/actions/GuildEmojiCreate.js +++ b/node_modules/discord.js/src/client/actions/GuildEmojiCreate.js @@ -6,7 +6,7 @@ const { Events } = require('../../util/Constants'); class GuildEmojiCreateAction extends Action { handle(guild, createdEmoji) { const already = guild.emojis.cache.has(createdEmoji.id); - const emoji = guild.emojis.add(createdEmoji); + const emoji = guild.emojis._add(createdEmoji); /** * Emitted whenever a custom emoji is created in a guild. * @event Client#emojiCreate diff --git a/node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js b/node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js index 77119333..7829db1f 100644 --- a/node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js +++ b/node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js @@ -5,7 +5,7 @@ const Action = require('./Action'); class GuildEmojisUpdateAction extends Action { handle(data) { const guild = this.client.guilds.cache.get(data.guild_id); - if (!guild || !guild.emojis) return; + if (!guild?.emojis) return; const deletions = new Map(guild.emojis.cache); diff --git a/node_modules/discord.js/src/client/actions/GuildMemberUpdate.js b/node_modules/discord.js/src/client/actions/GuildMemberUpdate.js index 53ca4818..137351f4 100644 --- a/node_modules/discord.js/src/client/actions/GuildMemberUpdate.js +++ b/node_modules/discord.js/src/client/actions/GuildMemberUpdate.js @@ -9,7 +9,7 @@ class GuildMemberUpdateAction extends Action { if (data.user.username) { const user = client.users.cache.get(data.user.id); if (!user) { - client.users.add(data.user); + client.users._add(data.user); } else if (!user.equals(data.user)) { client.actions.UserUpdate.handle(data.user); } @@ -27,9 +27,9 @@ class GuildMemberUpdateAction extends Action { * @param {GuildMember} oldMember The member before the update * @param {GuildMember} newMember The member after the update */ - if (shard.status === Status.READY) client.emit(Events.GUILD_MEMBER_UPDATE, old, member); + if (shard.status === Status.READY && !member.equals(old)) client.emit(Events.GUILD_MEMBER_UPDATE, old, member); } else { - const newMember = guild.members.add(data); + const newMember = guild.members._add(data); /** * Emitted whenever a member becomes available in a large guild. * @event Client#guildMemberAvailable diff --git a/node_modules/discord.js/src/client/actions/GuildRoleCreate.js b/node_modules/discord.js/src/client/actions/GuildRoleCreate.js index d7d52144..102e0f63 100644 --- a/node_modules/discord.js/src/client/actions/GuildRoleCreate.js +++ b/node_modules/discord.js/src/client/actions/GuildRoleCreate.js @@ -10,7 +10,7 @@ class GuildRoleCreate extends Action { let role; if (guild) { const already = guild.roles.cache.has(data.role.id); - role = guild.roles.add(data.role); + role = guild.roles._add(data.role); /** * Emitted whenever a role is created. * @event Client#roleCreate diff --git a/node_modules/discord.js/src/client/actions/InviteCreate.js b/node_modules/discord.js/src/client/actions/InviteCreate.js index 34cfa845..ec6088d3 100644 --- a/node_modules/discord.js/src/client/actions/InviteCreate.js +++ b/node_modules/discord.js/src/client/actions/InviteCreate.js @@ -1,7 +1,6 @@ 'use strict'; const Action = require('./Action'); -const Invite = require('../../structures/Invite'); const { Events } = require('../../util/Constants'); class InviteCreateAction extends Action { @@ -12,7 +11,8 @@ class InviteCreateAction extends Action { if (!channel) return false; const inviteData = Object.assign(data, { channel, guild }); - const invite = new Invite(client, inviteData); + const invite = guild.invites._add(inviteData); + /** * Emitted when an invite is created. * This event only triggers if the client has `MANAGE_GUILD` permissions for the guild, diff --git a/node_modules/discord.js/src/client/actions/InviteDelete.js b/node_modules/discord.js/src/client/actions/InviteDelete.js index 96e22aa0..c6c039ca 100644 --- a/node_modules/discord.js/src/client/actions/InviteDelete.js +++ b/node_modules/discord.js/src/client/actions/InviteDelete.js @@ -13,6 +13,7 @@ class InviteDeleteAction extends Action { const inviteData = Object.assign(data, { channel, guild }); const invite = new Invite(client, inviteData); + guild.invites.cache.delete(invite.code); /** * Emitted when an invite is deleted. diff --git a/node_modules/discord.js/src/client/actions/MessageCreate.js b/node_modules/discord.js/src/client/actions/MessageCreate.js index 71387075..979a65cc 100644 --- a/node_modules/discord.js/src/client/actions/MessageCreate.js +++ b/node_modules/discord.js/src/client/actions/MessageCreate.js @@ -3,32 +3,36 @@ const Action = require('./Action'); const { Events } = require('../../util/Constants'); +let deprecationEmitted = false; + class MessageCreateAction extends Action { handle(data) { const client = this.client; - const channel = client.channels.cache.get(data.channel_id); + const channel = this.getChannel(data); if (channel) { const existing = channel.messages.cache.get(data.id); if (existing) return { message: existing }; - const message = channel.messages.add(data); - const user = message.author; - let member = message.member; - channel.lastMessageID = data.id; - if (user) { - user.lastMessageID = data.id; - user.lastMessageChannelID = channel.id; - } - if (member) { - member.lastMessageID = data.id; - member.lastMessageChannelID = channel.id; - } + const message = channel.messages._add(data); + channel.lastMessageId = data.id; /** * Emitted whenever a message is created. - * @event Client#message + * @event Client#messageCreate * @param {Message} message The created message */ client.emit(Events.MESSAGE_CREATE, message); + + /** + * Emitted whenever a message is created. + * @event Client#message + * @param {Message} message The created message + * @deprecated Use {@link Client#messageCreate} instead + */ + if (client.emit('message', message) && !deprecationEmitted) { + deprecationEmitted = true; + process.emitWarning('The message event is deprecated. Use messageCreate instead', 'DeprecationWarning'); + } + return { message }; } diff --git a/node_modules/discord.js/src/client/actions/MessageDeleteBulk.js b/node_modules/discord.js/src/client/actions/MessageDeleteBulk.js index 8686b1d3..8bda6951 100644 --- a/node_modules/discord.js/src/client/actions/MessageDeleteBulk.js +++ b/node_modules/discord.js/src/client/actions/MessageDeleteBulk.js @@ -1,7 +1,7 @@ 'use strict'; +const { Collection } = require('@discordjs/collection'); const Action = require('./Action'); -const Collection = require('../../util/Collection'); const { Events } = require('../../util/Constants'); class MessageDeleteBulkAction extends Action { @@ -31,7 +31,7 @@ class MessageDeleteBulkAction extends Action { /** * Emitted whenever messages are deleted in bulk. * @event Client#messageDeleteBulk - * @param {Collection} messages The deleted messages, mapped by their ID + * @param {Collection} messages The deleted messages, mapped by their id */ if (messages.size > 0) client.emit(Events.MESSAGE_BULK_DELETE, messages); return { messages }; diff --git a/node_modules/discord.js/src/client/actions/MessageReactionAdd.js b/node_modules/discord.js/src/client/actions/MessageReactionAdd.js index c7b01519..452ed6b1 100644 --- a/node_modules/discord.js/src/client/actions/MessageReactionAdd.js +++ b/node_modules/discord.js/src/client/actions/MessageReactionAdd.js @@ -1,7 +1,7 @@ 'use strict'; const Action = require('./Action'); -const { Events } = require('../../util/Constants'); +const { Events, VoiceBasedChannelTypes } = require('../../util/Constants'); const { PartialTypes } = require('../../util/Constants'); /* @@ -23,7 +23,7 @@ class MessageReactionAdd extends Action { // Verify channel const channel = this.getChannel(data); - if (!channel || channel.type === 'voice') return false; + if (!channel || VoiceBasedChannelTypes.includes(channel.type)) return false; // Verify message const message = this.getMessage(data, channel); @@ -31,9 +31,9 @@ class MessageReactionAdd extends Action { // Verify reaction if (message.partial && !this.client.options.partials.includes(PartialTypes.REACTION)) return false; - const existing = message.reactions.cache.get(data.emoji.id || data.emoji.name); - if (existing && existing.users.cache.has(user.id)) return { message, reaction: existing, user }; - const reaction = message.reactions.add({ + const existing = message.reactions.cache.get(data.emoji.id ?? data.emoji.name); + if (existing?.users.cache.has(user.id)) return { message, reaction: existing, user }; + const reaction = message.reactions._add({ emoji: data.emoji, count: message.partial ? null : 0, me: user.id === this.client.user.id, diff --git a/node_modules/discord.js/src/client/actions/MessageReactionRemove.js b/node_modules/discord.js/src/client/actions/MessageReactionRemove.js index 87402465..8b66899e 100644 --- a/node_modules/discord.js/src/client/actions/MessageReactionRemove.js +++ b/node_modules/discord.js/src/client/actions/MessageReactionRemove.js @@ -1,7 +1,7 @@ 'use strict'; const Action = require('./Action'); -const { Events } = require('../../util/Constants'); +const { Events, VoiceBasedChannelTypes } = require('../../util/Constants'); /* { user_id: 'id', @@ -20,7 +20,7 @@ class MessageReactionRemove extends Action { // Verify channel const channel = this.getChannel(data); - if (!channel || channel.type === 'voice') return false; + if (!channel || VoiceBasedChannelTypes.includes(channel.type)) return false; // Verify message const message = this.getMessage(data, channel); diff --git a/node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js b/node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js index 14b79bf0..404ef945 100644 --- a/node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js +++ b/node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js @@ -1,13 +1,13 @@ 'use strict'; const Action = require('./Action'); -const { Events } = require('../../util/Constants'); +const { Events, VoiceBasedChannelTypes } = require('../../util/Constants'); class MessageReactionRemoveAll extends Action { handle(data) { // Verify channel const channel = this.getChannel(data); - if (!channel || channel.type === 'voice') return false; + if (!channel || VoiceBasedChannelTypes.includes(channel.type)) return false; // Verify message const message = this.getMessage(data, channel); diff --git a/node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js b/node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js index 143702c0..8a8a71e2 100644 --- a/node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js +++ b/node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js @@ -1,19 +1,19 @@ 'use strict'; const Action = require('./Action'); -const { Events } = require('../../util/Constants'); +const { Events, VoiceBasedChannelTypes } = require('../../util/Constants'); class MessageReactionRemoveEmoji extends Action { handle(data) { const channel = this.getChannel(data); - if (!channel || channel.type === 'voice') return false; + if (!channel || VoiceBasedChannelTypes.includes(channel.type)) return false; const message = this.getMessage(data, channel); if (!message) return false; const reaction = this.getReaction(data, message); if (!reaction) return false; - if (!message.partial) message.reactions.cache.delete(reaction.emoji.id || reaction.emoji.name); + if (!message.partial) message.reactions.cache.delete(reaction.emoji.id ?? reaction.emoji.name); /** * Emitted when a bot removes an emoji reaction from a cached message. diff --git a/node_modules/discord.js/src/client/actions/MessageUpdate.js b/node_modules/discord.js/src/client/actions/MessageUpdate.js index 7667dea4..b0e0b8a4 100644 --- a/node_modules/discord.js/src/client/actions/MessageUpdate.js +++ b/node_modules/discord.js/src/client/actions/MessageUpdate.js @@ -9,7 +9,7 @@ class MessageUpdateAction extends Action { const { id, channel_id, guild_id, author, timestamp, type } = data; const message = this.getMessage({ id, channel_id, guild_id, author, timestamp, type }, channel); if (message) { - const old = message.patch(data); + const old = message._update(data, true); return { old, updated: message, diff --git a/node_modules/discord.js/src/client/actions/PresenceUpdate.js b/node_modules/discord.js/src/client/actions/PresenceUpdate.js index f74fbeb5..2e34c212 100644 --- a/node_modules/discord.js/src/client/actions/PresenceUpdate.js +++ b/node_modules/discord.js/src/client/actions/PresenceUpdate.js @@ -6,37 +6,35 @@ const { Events } = require('../../util/Constants'); class PresenceUpdateAction extends Action { handle(data) { let user = this.client.users.cache.get(data.user.id); - if (!user && data.user.username) user = this.client.users.add(data.user); + if (!user && data.user?.username) user = this.client.users._add(data.user); if (!user) return; - if (data.user && data.user.username) { + if (data.user?.username) { if (!user.equals(data.user)) this.client.actions.UserUpdate.handle(data.user); } const guild = this.client.guilds.cache.get(data.guild_id); if (!guild) return; - let oldPresence = guild.presences.cache.get(user.id); - if (oldPresence) oldPresence = oldPresence._clone(); + const oldPresence = guild.presences.cache.get(user.id)?._clone() ?? null; let member = guild.members.cache.get(user.id); if (!member && data.status !== 'offline') { - member = guild.members.add({ + member = guild.members._add({ user, - roles: data.roles, deaf: false, mute: false, }); this.client.emit(Events.GUILD_MEMBER_AVAILABLE, member); } - guild.presences.add(Object.assign(data, { guild })); - if (member && this.client.listenerCount(Events.PRESENCE_UPDATE)) { + const newPresence = guild.presences._add(Object.assign(data, { guild })); + if (this.client.listenerCount(Events.PRESENCE_UPDATE) && !newPresence.equals(oldPresence)) { /** * Emitted whenever a guild member's presence (e.g. status, activity) is changed. * @event Client#presenceUpdate * @param {?Presence} oldPresence The presence before the update, if one at all * @param {Presence} newPresence The presence after the update */ - this.client.emit(Events.PRESENCE_UPDATE, oldPresence, member.presence); + this.client.emit(Events.PRESENCE_UPDATE, oldPresence, newPresence); } } } diff --git a/node_modules/discord.js/src/client/actions/TypingStart.js b/node_modules/discord.js/src/client/actions/TypingStart.js index 7a35bc3f..af6bfada 100644 --- a/node_modules/discord.js/src/client/actions/TypingStart.js +++ b/node_modules/discord.js/src/client/actions/TypingStart.js @@ -1,8 +1,8 @@ 'use strict'; const Action = require('./Action'); -const { Events } = require('../../util/Constants'); -const textBasedChannelTypes = ['dm', 'text', 'news']; +const Typing = require('../../structures/Typing'); +const { Events, TextBasedChannelTypes } = require('../../util/Constants'); class TypingStart extends Action { handle(data) { @@ -10,49 +10,21 @@ class TypingStart extends Action { if (!channel) { return; } - if (!textBasedChannelTypes.includes(channel.type)) { + if (!TextBasedChannelTypes.includes(channel.type)) { this.client.emit(Events.WARN, `Discord sent a typing packet to a ${channel.type} channel ${channel.id}`); return; } const user = this.getUserFromMember(data); - const timestamp = new Date(data.timestamp * 1000); - if (channel && user) { - if (channel._typing.has(user.id)) { - const typing = channel._typing.get(user.id); - - typing.lastTimestamp = timestamp; - typing.elapsedTime = Date.now() - typing.since; - this.client.clearTimeout(typing.timeout); - typing.timeout = this.tooLate(channel, user); - } else { - const since = new Date(); - const lastTimestamp = new Date(); - channel._typing.set(user.id, { - user, - since, - lastTimestamp, - elapsedTime: Date.now() - since, - timeout: this.tooLate(channel, user), - }); - - /** - * Emitted whenever a user starts typing in a channel. - * @event Client#typingStart - * @param {Channel} channel The channel the user started typing in - * @param {User} user The user that started typing - */ - this.client.emit(Events.TYPING_START, channel, user); - } + /** + * Emitted whenever a user starts typing in a channel. + * @event Client#typingStart + * @param {Typing} typing The typing state + */ + this.client.emit(Events.TYPING_START, new Typing(channel, user, data)); } } - - tooLate(channel, user) { - return channel.client.setTimeout(() => { - channel._typing.delete(user.id); - }, 10000); - } } module.exports = TypingStart; diff --git a/node_modules/discord.js/src/client/actions/VoiceStateUpdate.js b/node_modules/discord.js/src/client/actions/VoiceStateUpdate.js index 406bd2fb..f750e048 100644 --- a/node_modules/discord.js/src/client/actions/VoiceStateUpdate.js +++ b/node_modules/discord.js/src/client/actions/VoiceStateUpdate.js @@ -1,32 +1,30 @@ 'use strict'; const Action = require('./Action'); +const VoiceState = require('../../structures/VoiceState'); const { Events } = require('../../util/Constants'); -const Structures = require('../../util/Structures'); class VoiceStateUpdate extends Action { handle(data) { const client = this.client; const guild = client.guilds.cache.get(data.guild_id); if (guild) { - const VoiceState = Structures.get('VoiceState'); // Update the state - const oldState = guild.voiceStates.cache.has(data.user_id) - ? guild.voiceStates.cache.get(data.user_id)._clone() - : new VoiceState(guild, { user_id: data.user_id }); + const oldState = + guild.voiceStates.cache.get(data.user_id)?._clone() ?? new VoiceState(guild, { user_id: data.user_id }); - const newState = guild.voiceStates.add(data); + const newState = guild.voiceStates._add(data); // Get the member let member = guild.members.cache.get(data.user_id); if (member && data.member) { member._patch(data.member); - } else if (data.member && data.member.user && data.member.joined_at) { - member = guild.members.add(data.member); + } else if (data.member?.user && data.member.joined_at) { + member = guild.members._add(data.member); } // Emit event - if (member && member.user.id === client.user.id) { + if (member?.user.id === client.user.id) { client.emit('debug', `[VOICE] received voice state update: ${JSON.stringify(data)}`); client.voice.onVoiceStateUpdate(data); } diff --git a/node_modules/discord.js/src/client/voice/ClientVoiceManager.js b/node_modules/discord.js/src/client/voice/ClientVoiceManager.js index 38c9f1dd..e6ea6ead 100644 --- a/node_modules/discord.js/src/client/voice/ClientVoiceManager.js +++ b/node_modules/discord.js/src/client/voice/ClientVoiceManager.js @@ -1,9 +1,6 @@ 'use strict'; -const VoiceBroadcast = require('./VoiceBroadcast'); -const VoiceConnection = require('./VoiceConnection'); -const { Error } = require('../../errors'); -const Collection = require('../../util/Collection'); +const { Events } = require('../../util/Constants'); /** * Manages voice connections for the client @@ -19,98 +16,29 @@ class ClientVoiceManager { Object.defineProperty(this, 'client', { value: client }); /** - * A collection mapping connection IDs to the Connection objects - * @type {Collection} + * Maps guild ids to voice adapters created for use with @discordjs/voice. + * @type {Map} */ - this.connections = new Collection(); + this.adapters = new Map(); - /** - * Active voice broadcasts that have been created - * @type {VoiceBroadcast[]} - */ - this.broadcasts = []; - } - - /** - * Creates a voice broadcast. - * @returns {VoiceBroadcast} - */ - createBroadcast() { - const broadcast = new VoiceBroadcast(this.client); - this.broadcasts.push(broadcast); - return broadcast; + client.on(Events.SHARD_DISCONNECT, (_, shardId) => { + for (const [guildId, adapter] of this.adapters.entries()) { + if (client.guilds.cache.get(guildId)?.shardId === shardId) { + adapter.destroy(); + } + } + }); } - onVoiceServer({ guild_id, token, endpoint }) { - this.client.emit('debug', `[VOICE] voiceServer guild: ${guild_id} token: ${token} endpoint: ${endpoint}`); - const connection = this.connections.get(guild_id); - if (connection) connection.setTokenAndEndpoint(token, endpoint); + onVoiceServer(payload) { + this.adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload); } - onVoiceStateUpdate({ guild_id, session_id, channel_id }) { - const connection = this.connections.get(guild_id); - this.client.emit('debug', `[VOICE] connection? ${!!connection}, ${guild_id} ${session_id} ${channel_id}`); - if (!connection) return; - if (!channel_id) { - connection._disconnect(); - this.connections.delete(guild_id); - return; - } - const channel = this.client.channels.cache.get(channel_id); - if (channel) { - connection.channel = channel; - connection.setSessionID(session_id); - } else { - this.client.emit('debug', `[VOICE] disconnecting from guild ${guild_id} as channel ${channel_id} is uncached`); - connection.disconnect(); + onVoiceStateUpdate(payload) { + if (payload.guild_id && payload.session_id && payload.user_id === this.client.user?.id) { + this.adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload); } } - - /** - * Sets up a request to join a voice channel. - * @param {VoiceChannel} channel The voice channel to join - * @returns {Promise} - * @private - */ - joinChannel(channel) { - return new Promise((resolve, reject) => { - if (!channel.joinable) { - throw new Error('VOICE_JOIN_CHANNEL', channel.full); - } - - let connection = this.connections.get(channel.guild.id); - - if (connection) { - if (connection.channel.id !== channel.id) { - this.connections.get(channel.guild.id).updateChannel(channel); - } - resolve(connection); - return; - } else { - connection = new VoiceConnection(this, channel); - connection.on('debug', msg => - this.client.emit('debug', `[VOICE (${channel.guild.id}:${connection.status})]: ${msg}`), - ); - connection.authenticate(); - this.connections.set(channel.guild.id, connection); - } - - connection.once('failed', reason => { - this.connections.delete(channel.guild.id); - reject(reason); - }); - - connection.on('error', reject); - - connection.once('authenticated', () => { - connection.once('ready', () => { - resolve(connection); - connection.removeListener('error', reject); - }); - connection.once('disconnect', () => this.connections.delete(channel.guild.id)); - }); - }); - } } module.exports = ClientVoiceManager; diff --git a/node_modules/discord.js/src/client/voice/VoiceBroadcast.js b/node_modules/discord.js/src/client/voice/VoiceBroadcast.js deleted file mode 100644 index 5755b52f..00000000 --- a/node_modules/discord.js/src/client/voice/VoiceBroadcast.js +++ /dev/null @@ -1,111 +0,0 @@ -'use strict'; - -const EventEmitter = require('events'); -const BroadcastAudioPlayer = require('./player/BroadcastAudioPlayer'); -const PlayInterface = require('./util/PlayInterface'); -const { Events } = require('../../util/Constants'); - -/** - * A voice broadcast can be played across multiple voice connections for improved shared-stream efficiency. - * - * Example usage: - * ```js - * const broadcast = client.voice.createBroadcast(); - * broadcast.play('./music.mp3'); - * // Play "music.mp3" in all voice connections that the client is in - * for (const connection of client.voice.connections.values()) { - * connection.play(broadcast); - * } - * ``` - * @implements {PlayInterface} - * @extends {EventEmitter} - */ -class VoiceBroadcast extends EventEmitter { - constructor(client) { - super(); - /** - * The client that created the broadcast - * @type {Client} - */ - this.client = client; - /** - * The subscribed StreamDispatchers of this broadcast - * @type {StreamDispatcher[]} - */ - this.subscribers = []; - this.player = new BroadcastAudioPlayer(this); - } - - /** - * The current master dispatcher, if any. This dispatcher controls all that is played by subscribed dispatchers. - * @type {?BroadcastDispatcher} - * @readonly - */ - get dispatcher() { - return this.player.dispatcher; - } - - /** - * Play an audio resource. - * @param {ReadableStream|string} resource The resource to play. - * @param {StreamOptions} [options] The options to play. - * @example - * // Play a local audio file - * broadcast.play('/home/hydrabolt/audio.mp3', { volume: 0.5 }); - * @example - * // Play a ReadableStream - * broadcast.play(ytdl('https://www.youtube.com/watch?v=ZlAU_w7-Xp8', { filter: 'audioonly' })); - * @example - * // Using different protocols: https://ffmpeg.org/ffmpeg-protocols.html - * broadcast.play('http://www.sample-videos.com/audio/mp3/wave.mp3'); - * @returns {BroadcastDispatcher} - */ - play() { - return null; - } - - /** - * Ends the broadcast, unsubscribing all subscribed channels and deleting the broadcast - */ - end() { - for (const dispatcher of this.subscribers) this.delete(dispatcher); - const index = this.client.voice.broadcasts.indexOf(this); - if (index !== -1) this.client.voice.broadcasts.splice(index, 1); - } - - add(dispatcher) { - const index = this.subscribers.indexOf(dispatcher); - if (index === -1) { - this.subscribers.push(dispatcher); - /** - * Emitted whenever a stream dispatcher subscribes to the broadcast. - * @event VoiceBroadcast#subscribe - * @param {StreamDispatcher} subscriber The subscribed dispatcher - */ - this.emit(Events.VOICE_BROADCAST_SUBSCRIBE, dispatcher); - return true; - } else { - return false; - } - } - - delete(dispatcher) { - const index = this.subscribers.indexOf(dispatcher); - if (index !== -1) { - this.subscribers.splice(index, 1); - dispatcher.destroy(); - /** - * Emitted whenever a stream dispatcher unsubscribes to the broadcast. - * @event VoiceBroadcast#unsubscribe - * @param {StreamDispatcher} dispatcher The unsubscribed dispatcher - */ - this.emit(Events.VOICE_BROADCAST_UNSUBSCRIBE, dispatcher); - return true; - } - return false; - } -} - -PlayInterface.applyToClass(VoiceBroadcast); - -module.exports = VoiceBroadcast; diff --git a/node_modules/discord.js/src/client/voice/VoiceConnection.js b/node_modules/discord.js/src/client/voice/VoiceConnection.js deleted file mode 100644 index c8942b4d..00000000 --- a/node_modules/discord.js/src/client/voice/VoiceConnection.js +++ /dev/null @@ -1,526 +0,0 @@ -'use strict'; - -const EventEmitter = require('events'); -const VoiceUDP = require('./networking/VoiceUDPClient'); -const VoiceWebSocket = require('./networking/VoiceWebSocket'); -const AudioPlayer = require('./player/AudioPlayer'); -const VoiceReceiver = require('./receiver/Receiver'); -const PlayInterface = require('./util/PlayInterface'); -const Silence = require('./util/Silence'); -const { Error } = require('../../errors'); -const { OPCodes, VoiceOPCodes, VoiceStatus, Events } = require('../../util/Constants'); -const Speaking = require('../../util/Speaking'); -const Util = require('../../util/Util'); - -// Workaround for Discord now requiring silence to be sent before being able to receive audio -class SingleSilence extends Silence { - _read() { - super._read(); - this.push(null); - } -} - -const SUPPORTED_MODES = ['xsalsa20_poly1305_lite', 'xsalsa20_poly1305_suffix', 'xsalsa20_poly1305']; - -/** - * Represents a connection to a guild's voice server. - * ```js - * // Obtained using: - * voiceChannel.join() - * .then(connection => { - * - * }); - * ``` - * @extends {EventEmitter} - * @implements {PlayInterface} - */ -class VoiceConnection extends EventEmitter { - constructor(voiceManager, channel) { - super(); - - /** - * The voice manager that instantiated this connection - * @type {ClientVoiceManager} - */ - this.voiceManager = voiceManager; - - /** - * The voice channel this connection is currently serving - * @type {VoiceChannel} - */ - this.channel = channel; - - /** - * The current status of the voice connection - * @type {VoiceStatus} - */ - this.status = VoiceStatus.AUTHENTICATING; - - /** - * Our current speaking state - * @type {Readonly} - */ - this.speaking = new Speaking().freeze(); - - /** - * The authentication data needed to connect to the voice server - * @type {Object} - * @private - */ - this.authentication = {}; - - /** - * The audio player for this voice connection - * @type {AudioPlayer} - */ - this.player = new AudioPlayer(this); - - this.player.on('debug', m => { - /** - * Debug info from the connection. - * @event VoiceConnection#debug - * @param {string} message The debug message - */ - this.emit('debug', `audio player - ${m}`); - }); - - this.player.on('error', e => { - /** - * Warning info from the connection. - * @event VoiceConnection#warn - * @param {string|Error} warning The warning - */ - this.emit('warn', e); - }); - - this.once('closing', () => this.player.destroy()); - - /** - * Map SSRC values to user IDs - * @type {Map} - * @private - */ - this.ssrcMap = new Map(); - - /** - * Tracks which users are talking - * @type {Map>} - * @private - */ - this._speaking = new Map(); - - /** - * Object that wraps contains the `ws` and `udp` sockets of this voice connection - * @type {Object} - * @private - */ - this.sockets = {}; - - /** - * The voice receiver of this connection - * @type {VoiceReceiver} - */ - this.receiver = new VoiceReceiver(this); - } - - /** - * The client that instantiated this connection - * @type {Client} - * @readonly - */ - get client() { - return this.voiceManager.client; - } - - /** - * The current stream dispatcher (if any) - * @type {?StreamDispatcher} - * @readonly - */ - get dispatcher() { - return this.player.dispatcher; - } - - /** - * Sets whether the voice connection should display as "speaking", "soundshare" or "none". - * @param {BitFieldResolvable} value The new speaking state - */ - setSpeaking(value) { - if (this.speaking.equals(value)) return; - if (this.status !== VoiceStatus.CONNECTED) return; - this.speaking = new Speaking(value).freeze(); - this.sockets.ws - .sendPacket({ - op: VoiceOPCodes.SPEAKING, - d: { - speaking: this.speaking.bitfield, - delay: 0, - ssrc: this.authentication.ssrc, - }, - }) - .catch(e => { - this.emit('debug', e); - }); - } - - /** - * The voice state of this connection - * @type {?VoiceState} - */ - get voice() { - return this.channel.guild.voice; - } - - /** - * Sends a request to the main gateway to join a voice channel. - * @param {Object} [options] The options to provide - * @returns {Promise} - * @private - */ - sendVoiceStateUpdate(options = {}) { - options = Util.mergeDefault( - { - guild_id: this.channel.guild.id, - channel_id: this.channel.id, - self_mute: this.voice ? this.voice.selfMute : false, - self_deaf: this.voice ? this.voice.selfDeaf : false, - }, - options, - ); - - this.emit('debug', `Sending voice state update: ${JSON.stringify(options)}`); - - return this.channel.guild.shard.send( - { - op: OPCodes.VOICE_STATE_UPDATE, - d: options, - }, - true, - ); - } - - /** - * Set the token and endpoint required to connect to the voice servers. - * @param {string} token The voice token - * @param {string} endpoint The voice endpoint - * @returns {void} - * @private - */ - setTokenAndEndpoint(token, endpoint) { - this.emit('debug', `Token "${token}" and endpoint "${endpoint}"`); - if (!endpoint) { - // Signifies awaiting endpoint stage - return; - } - - if (!token) { - this.authenticateFailed('VOICE_TOKEN_ABSENT'); - return; - } - - endpoint = endpoint.match(/([^:]*)/)[0]; - this.emit('debug', `Endpoint resolved as ${endpoint}`); - - if (!endpoint) { - this.authenticateFailed('VOICE_INVALID_ENDPOINT'); - return; - } - - if (this.status === VoiceStatus.AUTHENTICATING) { - this.authentication.token = token; - this.authentication.endpoint = endpoint; - this.checkAuthenticated(); - } else if (token !== this.authentication.token || endpoint !== this.authentication.endpoint) { - this.reconnect(token, endpoint); - } - } - - /** - * Sets the Session ID for the connection. - * @param {string} sessionID The voice session ID - * @private - */ - setSessionID(sessionID) { - this.emit('debug', `Setting sessionID ${sessionID} (stored as "${this.authentication.sessionID}")`); - if (!sessionID) { - this.authenticateFailed('VOICE_SESSION_ABSENT'); - return; - } - - if (this.status === VoiceStatus.AUTHENTICATING) { - this.authentication.sessionID = sessionID; - this.checkAuthenticated(); - } else if (sessionID !== this.authentication.sessionID) { - this.authentication.sessionID = sessionID; - /** - * Emitted when a new session ID is received. - * @event VoiceConnection#newSession - * @private - */ - this.emit('newSession', sessionID); - } - } - - /** - * Checks whether the voice connection is authenticated. - * @private - */ - checkAuthenticated() { - const { token, endpoint, sessionID } = this.authentication; - this.emit('debug', `Authenticated with sessionID ${sessionID}`); - if (token && endpoint && sessionID) { - this.status = VoiceStatus.CONNECTING; - /** - * Emitted when we successfully initiate a voice connection. - * @event VoiceConnection#authenticated - */ - this.emit('authenticated'); - this.connect(); - } - } - - /** - * Invoked when we fail to initiate a voice connection. - * @param {string} reason The reason for failure - * @private - */ - authenticateFailed(reason) { - this.client.clearTimeout(this.connectTimeout); - this.emit('debug', `Authenticate failed - ${reason}`); - if (this.status === VoiceStatus.AUTHENTICATING) { - /** - * Emitted when we fail to initiate a voice connection. - * @event VoiceConnection#failed - * @param {Error} error The encountered error - */ - this.emit('failed', new Error(reason)); - } else { - /** - * Emitted whenever the connection encounters an error. - * @event VoiceConnection#error - * @param {Error} error The encountered error - */ - this.emit('error', new Error(reason)); - } - this.status = VoiceStatus.DISCONNECTED; - } - - /** - * Move to a different voice channel in the same guild. - * @param {VoiceChannel} channel The channel to move to - * @private - */ - updateChannel(channel) { - this.channel = channel; - this.sendVoiceStateUpdate(); - } - - /** - * Attempts to authenticate to the voice server. - * @private - */ - authenticate() { - this.sendVoiceStateUpdate(); - this.connectTimeout = this.client.setTimeout(() => this.authenticateFailed('VOICE_CONNECTION_TIMEOUT'), 15000); - } - - /** - * Attempts to reconnect to the voice server (typically after a region change). - * @param {string} token The voice token - * @param {string} endpoint The voice endpoint - * @private - */ - reconnect(token, endpoint) { - this.authentication.token = token; - this.authentication.endpoint = endpoint; - this.speaking = new Speaking().freeze(); - this.status = VoiceStatus.RECONNECTING; - this.emit('debug', `Reconnecting to ${endpoint}`); - /** - * Emitted when the voice connection is reconnecting (typically after a region change). - * @event VoiceConnection#reconnecting - */ - this.emit('reconnecting'); - this.connect(); - } - - /** - * Disconnects the voice connection, causing a disconnect and closing event to be emitted. - */ - disconnect() { - this.emit('closing'); - this.emit('debug', 'disconnect() triggered'); - this.client.clearTimeout(this.connectTimeout); - const conn = this.voiceManager.connections.get(this.channel.guild.id); - if (conn === this) this.voiceManager.connections.delete(this.channel.guild.id); - this.sendVoiceStateUpdate({ - channel_id: null, - }); - this._disconnect(); - } - - /** - * Internally disconnects (doesn't send disconnect packet). - * @private - */ - _disconnect() { - this.cleanup(); - this.status = VoiceStatus.DISCONNECTED; - /** - * Emitted when the voice connection disconnects. - * @event VoiceConnection#disconnect - */ - this.emit('disconnect'); - } - - /** - * Cleans up after disconnect. - * @private - */ - cleanup() { - this.player.destroy(); - this.speaking = new Speaking().freeze(); - const { ws, udp } = this.sockets; - - this.emit('debug', 'Connection clean up'); - - if (ws) { - ws.removeAllListeners('error'); - ws.removeAllListeners('ready'); - ws.removeAllListeners('sessionDescription'); - ws.removeAllListeners('speaking'); - ws.shutdown(); - } - - if (udp) udp.removeAllListeners('error'); - - this.sockets.ws = null; - this.sockets.udp = null; - } - - /** - * Connect the voice connection. - * @private - */ - connect() { - this.emit('debug', `Connect triggered`); - if (this.status !== VoiceStatus.RECONNECTING) { - if (this.sockets.ws) throw new Error('WS_CONNECTION_EXISTS'); - if (this.sockets.udp) throw new Error('UDP_CONNECTION_EXISTS'); - } - - if (this.sockets.ws) this.sockets.ws.shutdown(); - if (this.sockets.udp) this.sockets.udp.shutdown(); - - this.sockets.ws = new VoiceWebSocket(this); - this.sockets.udp = new VoiceUDP(this); - - const { ws, udp } = this.sockets; - - ws.on('debug', msg => this.emit('debug', msg)); - udp.on('debug', msg => this.emit('debug', msg)); - ws.on('error', err => this.emit('error', err)); - udp.on('error', err => this.emit('error', err)); - ws.on('ready', this.onReady.bind(this)); - ws.on('sessionDescription', this.onSessionDescription.bind(this)); - ws.on('startSpeaking', this.onStartSpeaking.bind(this)); - - this.sockets.ws.connect(); - } - - /** - * Invoked when the voice websocket is ready. - * @param {Object} data The received data - * @private - */ - onReady(data) { - Object.assign(this.authentication, data); - for (let mode of data.modes) { - if (SUPPORTED_MODES.includes(mode)) { - this.authentication.mode = mode; - this.emit('debug', `Selecting the ${mode} mode`); - break; - } - } - this.sockets.udp.createUDPSocket(data.ip); - } - - /** - * Invoked when a session description is received. - * @param {Object} data The received data - * @private - */ - onSessionDescription(data) { - Object.assign(this.authentication, data); - this.status = VoiceStatus.CONNECTED; - const ready = () => { - this.client.clearTimeout(this.connectTimeout); - this.emit('debug', `Ready with authentication details: ${JSON.stringify(this.authentication)}`); - /** - * Emitted once the connection is ready, when a promise to join a voice channel resolves, - * the connection will already be ready. - * @event VoiceConnection#ready - */ - this.emit('ready'); - }; - if (this.dispatcher) { - ready(); - } else { - // This serves to provide support for voice receive, sending audio is required to receive it. - const dispatcher = this.play(new SingleSilence(), { type: 'opus', volume: false }); - dispatcher.once('finish', ready); - } - } - - onStartSpeaking({ user_id, ssrc, speaking }) { - this.ssrcMap.set(+ssrc, { - ...(this.ssrcMap.get(+ssrc) || {}), - userID: user_id, - speaking: speaking, - }); - } - - /** - * Invoked when a speaking event is received. - * @param {Object} data The received data - * @private - */ - onSpeaking({ user_id, speaking }) { - speaking = new Speaking(speaking).freeze(); - const guild = this.channel.guild; - const user = this.client.users.cache.get(user_id); - const old = this._speaking.get(user_id); - this._speaking.set(user_id, speaking); - /** - * Emitted whenever a user changes speaking state. - * @event VoiceConnection#speaking - * @param {User} user The user that has changed speaking state - * @param {Readonly} speaking The speaking state of the user - */ - if (this.status === VoiceStatus.CONNECTED) { - this.emit('speaking', user, speaking); - if (!speaking.has(Speaking.FLAGS.SPEAKING)) { - this.receiver.packets._stoppedSpeaking(user_id); - } - } - - if (guild && user && !speaking.equals(old)) { - const member = guild.member(user); - if (member) { - /** - * Emitted once a guild member changes speaking state. - * @event Client#guildMemberSpeaking - * @param {GuildMember} member The member that started/stopped speaking - * @param {Readonly} speaking The speaking state of the member - */ - this.client.emit(Events.GUILD_MEMBER_SPEAKING, member, speaking); - } - } - } - - play() {} // eslint-disable-line no-empty-function -} - -PlayInterface.applyToClass(VoiceConnection); - -module.exports = VoiceConnection; diff --git a/node_modules/discord.js/src/client/voice/dispatcher/BroadcastDispatcher.js b/node_modules/discord.js/src/client/voice/dispatcher/BroadcastDispatcher.js deleted file mode 100644 index ae8d412e..00000000 --- a/node_modules/discord.js/src/client/voice/dispatcher/BroadcastDispatcher.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -const StreamDispatcher = require('./StreamDispatcher'); - -/** - * The class that sends voice packet data to the voice connection. - * @implements {VolumeInterface} - * @extends {StreamDispatcher} - */ -class BroadcastDispatcher extends StreamDispatcher { - constructor(player, options, streams) { - super(player, options, streams); - this.broadcast = player.broadcast; - } - - _write(chunk, enc, done) { - if (!this.startTime) this.startTime = Date.now(); - for (const dispatcher of this.broadcast.subscribers) { - dispatcher._write(chunk, enc); - } - this._step(done); - } - - _destroy(err, cb) { - if (this.player.dispatcher === this) this.player.dispatcher = null; - const { streams } = this; - if (streams.opus) streams.opus.unpipe(this); - if (streams.ffmpeg) streams.ffmpeg.destroy(); - super._destroy(err, cb); - } - - /** - * Set the bitrate of the current Opus encoder if using a compatible Opus stream. - * @param {number} value New bitrate, in kbps - * If set to 'auto', 48kbps will be used - * @returns {boolean} true if the bitrate has been successfully changed. - */ - setBitrate(value) { - if (!value || !this.streams.opus || !this.streams.opus.setBitrate) return false; - const bitrate = value === 'auto' ? 48 : value; - this.streams.opus.setBitrate(bitrate * 1000); - return true; - } -} - -module.exports = BroadcastDispatcher; diff --git a/node_modules/discord.js/src/client/voice/dispatcher/StreamDispatcher.js b/node_modules/discord.js/src/client/voice/dispatcher/StreamDispatcher.js deleted file mode 100644 index bb1c7bba..00000000 --- a/node_modules/discord.js/src/client/voice/dispatcher/StreamDispatcher.js +++ /dev/null @@ -1,354 +0,0 @@ -'use strict'; - -const { Writable } = require('stream'); -const secretbox = require('../util/Secretbox'); -const Silence = require('../util/Silence'); -const VolumeInterface = require('../util/VolumeInterface'); - -const FRAME_LENGTH = 20; -const CHANNELS = 2; -const TIMESTAMP_INC = (48000 / 100) * CHANNELS; - -const MAX_NONCE_SIZE = 2 ** 32 - 1; -const nonce = Buffer.alloc(24); - -/** - * @external WritableStream - * @see {@link https://nodejs.org/api/stream.html#stream_class_stream_writable} - */ - -/** - * The class that sends voice packet data to the voice connection. - * ```js - * // Obtained using: - * voiceChannel.join().then(connection => { - * // You can play a file or a stream here: - * const dispatcher = connection.play('/home/hydrabolt/audio.mp3'); - * }); - * ``` - * @implements {VolumeInterface} - * @extends {WritableStream} - */ -class StreamDispatcher extends Writable { - constructor(player, { seek = 0, volume = 1, fec, plp, bitrate = 96, highWaterMark = 12 } = {}, streams) { - const streamOptions = { seek, volume, fec, plp, bitrate, highWaterMark }; - super(streamOptions); - /** - * The Audio Player that controls this dispatcher - * @type {AudioPlayer} - */ - this.player = player; - this.streamOptions = streamOptions; - this.streams = streams; - this.streams.silence = new Silence(); - - this._nonce = 0; - this._nonceBuffer = Buffer.alloc(24); - - /** - * The time that the stream was paused at (null if not paused) - * @type {?number} - */ - this.pausedSince = null; - this._writeCallback = null; - - /** - * The broadcast controlling this dispatcher, if any - * @type {?VoiceBroadcast} - */ - this.broadcast = this.streams.broadcast || null; - - this._pausedTime = 0; - this._silentPausedTime = 0; - this.count = 0; - - this.on('finish', () => { - this._cleanup(); - this._setSpeaking(0); - }); - - this.setVolume(volume); - this.setBitrate(bitrate); - if (typeof fec !== 'undefined') this.setFEC(fec); - if (typeof plp !== 'undefined') this.setPLP(plp); - - const streamError = (type, err) => { - /** - * Emitted when the dispatcher encounters an error. - * @event StreamDispatcher#error - */ - if (type && err) { - err.message = `${type} stream: ${err.message}`; - this.emit(this.player.dispatcher === this ? 'error' : 'debug', err); - } - this.destroy(); - }; - - this.on('error', () => streamError()); - if (this.streams.input) this.streams.input.on('error', err => streamError('input', err)); - if (this.streams.ffmpeg) this.streams.ffmpeg.on('error', err => streamError('ffmpeg', err)); - if (this.streams.opus) this.streams.opus.on('error', err => streamError('opus', err)); - if (this.streams.volume) this.streams.volume.on('error', err => streamError('volume', err)); - } - - get _sdata() { - return this.player.streamingData; - } - - _write(chunk, enc, done) { - if (!this.startTime) { - /** - * Emitted once the stream has started to play. - * @event StreamDispatcher#start - */ - this.emit('start'); - this.startTime = Date.now(); - } - this._playChunk(chunk); - this._step(done); - } - - _destroy(err, cb) { - this._cleanup(); - super._destroy(err, cb); - } - - _cleanup() { - if (this.player.dispatcher === this) this.player.dispatcher = null; - const { streams } = this; - if (streams.broadcast) streams.broadcast.delete(this); - if (streams.opus) streams.opus.destroy(); - if (streams.ffmpeg) streams.ffmpeg.destroy(); - } - - /** - * Pauses playback - * @param {boolean} [silence=false] Whether to play silence while paused to prevent audio glitches - */ - pause(silence = false) { - if (this.paused) return; - if (this.streams.opus) this.streams.opus.unpipe(this); - if (silence) { - this.streams.silence.pipe(this); - this._silence = true; - } else { - this._setSpeaking(0); - } - this.pausedSince = Date.now(); - } - - /** - * Whether or not playback is paused - * @type {boolean} - * @readonly - */ - get paused() { - return Boolean(this.pausedSince); - } - - /** - * Total time that this dispatcher has been paused in milliseconds - * @type {number} - * @readonly - */ - get pausedTime() { - return this._silentPausedTime + this._pausedTime + (this.paused ? Date.now() - this.pausedSince : 0); - } - - /** - * Resumes playback - */ - resume() { - if (!this.pausedSince) return; - this.streams.silence.unpipe(this); - if (this.streams.opus) this.streams.opus.pipe(this); - if (this._silence) { - this._silentPausedTime += Date.now() - this.pausedSince; - this._silence = false; - } else { - this._pausedTime += Date.now() - this.pausedSince; - } - this.pausedSince = null; - if (typeof this._writeCallback === 'function') this._writeCallback(); - } - - /** - * The time (in milliseconds) that the dispatcher has actually been playing audio for - * @type {number} - * @readonly - */ - get streamTime() { - return this.count * FRAME_LENGTH; - } - - /** - * The time (in milliseconds) that the dispatcher has been playing audio for, taking into account skips and pauses - * @type {number} - * @readonly - */ - get totalStreamTime() { - return Date.now() - this.startTime; - } - - /** - * Set the bitrate of the current Opus encoder if using a compatible Opus stream. - * @param {number} value New bitrate, in kbps - * If set to 'auto', the voice channel's bitrate will be used - * @returns {boolean} true if the bitrate has been successfully changed. - */ - setBitrate(value) { - if (!value || !this.bitrateEditable) return false; - const bitrate = value === 'auto' ? this.player.voiceConnection.channel.bitrate : value; - this.streams.opus.setBitrate(bitrate * 1000); - return true; - } - - /** - * Sets the expected packet loss percentage if using a compatible Opus stream. - * @param {number} value between 0 and 1 - * @returns {boolean} Returns true if it was successfully set. - */ - setPLP(value) { - if (!this.bitrateEditable) return false; - this.streams.opus.setPLP(value); - return true; - } - - /** - * Enables or disables forward error correction if using a compatible Opus stream. - * @param {boolean} enabled true to enable - * @returns {boolean} Returns true if it was successfully set. - */ - setFEC(enabled) { - if (!this.bitrateEditable) return false; - this.streams.opus.setFEC(enabled); - return true; - } - - _step(done) { - this._writeCallback = () => { - this._writeCallback = null; - done(); - }; - if (!this.streams.broadcast) { - const next = FRAME_LENGTH + this.count * FRAME_LENGTH - (Date.now() - this.startTime - this._pausedTime); - setTimeout(() => { - if ((!this.pausedSince || this._silence) && this._writeCallback) this._writeCallback(); - }, next); - } - this._sdata.sequence++; - this._sdata.timestamp += TIMESTAMP_INC; - if (this._sdata.sequence >= 2 ** 16) this._sdata.sequence = 0; - if (this._sdata.timestamp >= 2 ** 32) this._sdata.timestamp = 0; - this.count++; - } - - _final(callback) { - this._writeCallback = null; - callback(); - } - - _playChunk(chunk) { - if (this.player.dispatcher !== this || !this.player.voiceConnection.authentication.secret_key) return; - this._sendPacket(this._createPacket(this._sdata.sequence, this._sdata.timestamp, chunk)); - } - - _encrypt(buffer) { - const { secret_key, mode } = this.player.voiceConnection.authentication; - if (mode === 'xsalsa20_poly1305_lite') { - this._nonce++; - if (this._nonce > MAX_NONCE_SIZE) this._nonce = 0; - this._nonceBuffer.writeUInt32BE(this._nonce, 0); - return [secretbox.methods.close(buffer, this._nonceBuffer, secret_key), this._nonceBuffer.slice(0, 4)]; - } else if (mode === 'xsalsa20_poly1305_suffix') { - const random = secretbox.methods.random(24); - return [secretbox.methods.close(buffer, random, secret_key), random]; - } else { - return [secretbox.methods.close(buffer, nonce, secret_key)]; - } - } - - _createPacket(sequence, timestamp, buffer) { - const packetBuffer = Buffer.alloc(12); - packetBuffer[0] = 0x80; - packetBuffer[1] = 0x78; - - packetBuffer.writeUIntBE(sequence, 2, 2); - packetBuffer.writeUIntBE(timestamp, 4, 4); - packetBuffer.writeUIntBE(this.player.voiceConnection.authentication.ssrc, 8, 4); - - packetBuffer.copy(nonce, 0, 0, 12); - return Buffer.concat([packetBuffer, ...this._encrypt(buffer)]); - } - - _sendPacket(packet) { - /** - * Emitted whenever the dispatcher has debug information. - * @event StreamDispatcher#debug - * @param {string} info The debug info - */ - this._setSpeaking(1); - if (!this.player.voiceConnection.sockets.udp) { - this.emit('debug', 'Failed to send a packet - no UDP socket'); - return; - } - this.player.voiceConnection.sockets.udp.send(packet).catch(e => { - this._setSpeaking(0); - this.emit('debug', `Failed to send a packet - ${e}`); - }); - } - - _setSpeaking(value) { - if (typeof this.player.voiceConnection !== 'undefined') { - this.player.voiceConnection.setSpeaking(value); - } - /** - * Emitted when the dispatcher starts/stops speaking. - * @event StreamDispatcher#speaking - * @param {boolean} value Whether or not the dispatcher is speaking - */ - this.emit('speaking', value); - } - - get volumeEditable() { - return Boolean(this.streams.volume); - } - - /** - * Whether or not the Opus bitrate of this stream is editable - * @type {boolean} - * @readonly - */ - get bitrateEditable() { - return this.streams.opus && this.streams.opus.setBitrate; - } - - // Volume - get volume() { - return this.streams.volume ? this.streams.volume.volume : 1; - } - - setVolume(value) { - if (!this.streams.volume) return false; - /** - * Emitted when the volume of this dispatcher changes. - * @event StreamDispatcher#volumeChange - * @param {number} oldVolume The old volume of this dispatcher - * @param {number} newVolume The new volume of this dispatcher - */ - this.emit('volumeChange', this.volume, value); - this.streams.volume.setVolume(value); - return true; - } - - // Volume stubs for docs - /* eslint-disable no-empty-function*/ - get volumeDecibels() {} - get volumeLogarithmic() {} - setVolumeDecibels() {} - setVolumeLogarithmic() {} -} - -VolumeInterface.applyToClass(StreamDispatcher); - -module.exports = StreamDispatcher; diff --git a/node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js b/node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js deleted file mode 100644 index b86428ae..00000000 --- a/node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js +++ /dev/null @@ -1,154 +0,0 @@ -'use strict'; - -const udp = require('dgram'); -const EventEmitter = require('events'); -const { Error } = require('../../../errors'); -const { VoiceOPCodes } = require('../../../util/Constants'); - -/** - * Represents a UDP client for a Voice Connection. - * @extends {EventEmitter} - * @private - */ -class VoiceConnectionUDPClient extends EventEmitter { - constructor(voiceConnection) { - super(); - - /** - * The voice connection that this UDP client serves - * @type {VoiceConnection} - */ - this.voiceConnection = voiceConnection; - - /** - * The UDP socket - * @type {?Socket} - */ - this.socket = null; - - /** - * The address of the Discord voice server - * @type {?string} - */ - this.discordAddress = null; - - /** - * The local IP address - * @type {?string} - */ - this.localAddress = null; - - /** - * The local port - * @type {?string} - */ - this.localPort = null; - - this.voiceConnection.on('closing', this.shutdown.bind(this)); - } - - shutdown() { - this.emit('debug', `[UDP] shutdown requested`); - if (this.socket) { - this.socket.removeAllListeners('message'); - try { - this.socket.close(); - } finally { - this.socket = null; - } - } - } - - /** - * The port of the Discord voice server - * @type {number} - * @readonly - */ - get discordPort() { - return this.voiceConnection.authentication.port; - } - - /** - * Send a packet to the UDP client. - * @param {Object} packet The packet to send - * @returns {Promise} - */ - send(packet) { - return new Promise((resolve, reject) => { - if (!this.socket) throw new Error('UDP_SEND_FAIL'); - if (!this.discordAddress || !this.discordPort) throw new Error('UDP_ADDRESS_MALFORMED'); - this.socket.send(packet, 0, packet.length, this.discordPort, this.discordAddress, error => { - if (error) { - this.emit('debug', `[UDP] >> ERROR: ${error}`); - reject(error); - } else { - resolve(packet); - } - }); - }); - } - - async createUDPSocket(address) { - this.discordAddress = address; - const socket = (this.socket = udp.createSocket('udp4')); - socket.on('error', e => { - this.emit('debug', `[UDP] Error: ${e}`); - this.emit('error', e); - }); - socket.on('close', () => { - this.emit('debug', '[UDP] socket closed'); - }); - this.emit('debug', `[UDP] created socket`); - socket.once('message', message => { - this.emit('debug', `[UDP] message: [${[...message]}] (${message})`); - // Stop if the sockets have been deleted because the connection has been closed already - if (!this.voiceConnection.sockets.ws) return; - - const packet = parseLocalPacket(message); - if (packet.error) { - this.emit('debug', `[UDP] ERROR: ${packet.error}`); - this.emit('error', packet.error); - return; - } - - this.localAddress = packet.address; - this.localPort = packet.port; - - this.voiceConnection.sockets.ws.sendPacket({ - op: VoiceOPCodes.SELECT_PROTOCOL, - d: { - protocol: 'udp', - data: { - address: packet.address, - port: packet.port, - mode: this.voiceConnection.authentication.mode, - }, - }, - }); - - this.emit('debug', `[UDP] << ${JSON.stringify(packet)}`); - - socket.on('message', buffer => this.voiceConnection.receiver.packets.push(buffer)); - }); - - const blankMessage = Buffer.alloc(70); - blankMessage.writeUIntBE(this.voiceConnection.authentication.ssrc, 0, 4); - this.emit('debug', `Sending IP discovery packet: [${[...blankMessage]}]`); - await this.send(blankMessage); - this.emit('debug', `Successfully sent IP discovery packet`); - } -} - -function parseLocalPacket(message) { - try { - const packet = Buffer.from(message); - let address = ''; - for (let i = 4; i < packet.indexOf(0, i); i++) address += String.fromCharCode(packet[i]); - const port = parseInt(packet.readUIntLE(packet.length - 2, 2).toString(10), 10); - return { address, port }; - } catch (error) { - return { error }; - } -} - -module.exports = VoiceConnectionUDPClient; diff --git a/node_modules/discord.js/src/client/voice/networking/VoiceWebSocket.js b/node_modules/discord.js/src/client/voice/networking/VoiceWebSocket.js deleted file mode 100644 index db344010..00000000 --- a/node_modules/discord.js/src/client/voice/networking/VoiceWebSocket.js +++ /dev/null @@ -1,268 +0,0 @@ -'use strict'; - -const EventEmitter = require('events'); -const WebSocket = require('../../../WebSocket'); -const { Error } = require('../../../errors'); -const { OPCodes, VoiceOPCodes } = require('../../../util/Constants'); - -/** - * Represents a Voice Connection's WebSocket. - * @extends {EventEmitter} - * @private - */ -class VoiceWebSocket extends EventEmitter { - constructor(connection) { - super(); - /** - * The Voice Connection that this WebSocket serves - * @type {VoiceConnection} - */ - this.connection = connection; - - /** - * How many connection attempts have been made - * @type {number} - */ - this.attempts = 0; - - this.dead = false; - this.connection.on('closing', this.shutdown.bind(this)); - } - - /** - * The client of this voice WebSocket - * @type {Client} - * @readonly - */ - get client() { - return this.connection.client; - } - - shutdown() { - this.emit('debug', `[WS] shutdown requested`); - this.dead = true; - this.reset(); - } - - /** - * Resets the current WebSocket. - */ - reset() { - this.emit('debug', `[WS] reset requested`); - if (this.ws) { - if (this.ws.readyState !== WebSocket.CLOSED) this.ws.close(); - this.ws = null; - } - this.clearHeartbeat(); - } - - /** - * Starts connecting to the Voice WebSocket Server. - */ - connect() { - this.emit('debug', `[WS] connect requested`); - if (this.dead) return; - if (this.ws) this.reset(); - if (this.attempts >= 5) { - this.emit('debug', new Error('VOICE_CONNECTION_ATTEMPTS_EXCEEDED', this.attempts)); - return; - } - - this.attempts++; - - /** - * The actual WebSocket used to connect to the Voice WebSocket Server. - * @type {WebSocket} - */ - this.ws = WebSocket.create(`wss://${this.connection.authentication.endpoint}/`, { v: 4 }); - this.emit('debug', `[WS] connecting, ${this.attempts} attempts, ${this.ws.url}`); - this.ws.onopen = this.onOpen.bind(this); - this.ws.onmessage = this.onMessage.bind(this); - this.ws.onclose = this.onClose.bind(this); - this.ws.onerror = this.onError.bind(this); - } - - /** - * Sends data to the WebSocket if it is open. - * @param {string} data The data to send to the WebSocket - * @returns {Promise} - */ - send(data) { - this.emit('debug', `[WS] >> ${data}`); - return new Promise((resolve, reject) => { - if (!this.ws || this.ws.readyState !== WebSocket.OPEN) throw new Error('WS_NOT_OPEN', data); - this.ws.send(data, null, error => { - if (error) reject(error); - else resolve(data); - }); - }); - } - - /** - * JSON.stringify's a packet and then sends it to the WebSocket Server. - * @param {Object} packet The packet to send - * @returns {Promise} - */ - sendPacket(packet) { - try { - packet = JSON.stringify(packet); - } catch (error) { - return Promise.reject(error); - } - return this.send(packet); - } - - /** - * Called whenever the WebSocket opens. - */ - onOpen() { - this.emit('debug', `[WS] opened at gateway ${this.connection.authentication.endpoint}`); - this.sendPacket({ - op: OPCodes.DISPATCH, - d: { - server_id: this.connection.channel.guild.id, - user_id: this.client.user.id, - token: this.connection.authentication.token, - session_id: this.connection.authentication.sessionID, - }, - }).catch(() => { - this.emit('error', new Error('VOICE_JOIN_SOCKET_CLOSED')); - }); - } - - /** - * Called whenever a message is received from the WebSocket. - * @param {MessageEvent} event The message event that was received - * @returns {void} - */ - onMessage(event) { - try { - return this.onPacket(WebSocket.unpack(event.data, 'json')); - } catch (error) { - return this.onError(error); - } - } - - /** - * Called whenever the connection to the WebSocket server is lost. - */ - onClose() { - this.emit('debug', `[WS] closed`); - if (!this.dead) this.client.setTimeout(this.connect.bind(this), this.attempts * 1000); - } - - /** - * Called whenever an error occurs with the WebSocket. - * @param {Error} error The error that occurred - */ - onError(error) { - this.emit('debug', `[WS] Error: ${error}`); - this.emit('error', error); - } - - /** - * Called whenever a valid packet is received from the WebSocket. - * @param {Object} packet The received packet - */ - onPacket(packet) { - this.emit('debug', `[WS] << ${JSON.stringify(packet)}`); - switch (packet.op) { - case VoiceOPCodes.HELLO: - this.setHeartbeat(packet.d.heartbeat_interval); - break; - case VoiceOPCodes.READY: - /** - * Emitted once the voice WebSocket receives the ready packet. - * @param {Object} packet The received packet - * @event VoiceWebSocket#ready - */ - this.emit('ready', packet.d); - break; - /* eslint-disable no-case-declarations */ - case VoiceOPCodes.SESSION_DESCRIPTION: - packet.d.secret_key = new Uint8Array(packet.d.secret_key); - /** - * Emitted once the Voice Websocket receives a description of this voice session. - * @param {Object} packet The received packet - * @event VoiceWebSocket#sessionDescription - */ - this.emit('sessionDescription', packet.d); - break; - case VoiceOPCodes.CLIENT_CONNECT: - this.connection.ssrcMap.set(+packet.d.audio_ssrc, { - userID: packet.d.user_id, - speaking: 0, - hasVideo: Boolean(packet.d.video_ssrc), - }); - break; - case VoiceOPCodes.CLIENT_DISCONNECT: - const streamInfo = this.connection.receiver && this.connection.receiver.packets.streams.get(packet.d.user_id); - if (streamInfo) { - this.connection.receiver.packets.streams.delete(packet.d.user_id); - streamInfo.stream.push(null); - } - break; - case VoiceOPCodes.SPEAKING: - /** - * Emitted whenever a speaking packet is received. - * @param {Object} data - * @event VoiceWebSocket#startSpeaking - */ - this.emit('startSpeaking', packet.d); - break; - default: - /** - * Emitted when an unhandled packet is received. - * @param {Object} packet - * @event VoiceWebSocket#unknownPacket - */ - this.emit('unknownPacket', packet); - break; - } - } - - /** - * Sets an interval at which to send a heartbeat packet to the WebSocket. - * @param {number} interval The interval at which to send a heartbeat packet - */ - setHeartbeat(interval) { - if (!interval || isNaN(interval)) { - this.onError(new Error('VOICE_INVALID_HEARTBEAT')); - return; - } - if (this.heartbeatInterval) { - /** - * Emitted whenever the voice WebSocket encounters a non-fatal error. - * @param {string} warn The warning - * @event VoiceWebSocket#warn - */ - this.emit('warn', 'A voice heartbeat interval is being overwritten'); - this.client.clearInterval(this.heartbeatInterval); - } - this.heartbeatInterval = this.client.setInterval(this.sendHeartbeat.bind(this), interval); - } - - /** - * Clears a heartbeat interval, if one exists. - */ - clearHeartbeat() { - if (!this.heartbeatInterval) { - this.emit('warn', 'Tried to clear a heartbeat interval that does not exist'); - return; - } - this.client.clearInterval(this.heartbeatInterval); - this.heartbeatInterval = null; - } - - /** - * Sends a heartbeat packet. - */ - sendHeartbeat() { - this.sendPacket({ op: VoiceOPCodes.HEARTBEAT, d: Math.floor(Math.random() * 10e10) }).catch(() => { - this.emit('warn', 'Tried to send heartbeat, but connection is not open'); - this.clearHeartbeat(); - }); - } -} - -module.exports = VoiceWebSocket; diff --git a/node_modules/discord.js/src/client/voice/player/AudioPlayer.js b/node_modules/discord.js/src/client/voice/player/AudioPlayer.js deleted file mode 100644 index 6f719a73..00000000 --- a/node_modules/discord.js/src/client/voice/player/AudioPlayer.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -const BasePlayer = require('./BasePlayer'); - -/** - * An Audio Player for a Voice Connection. - * @private - * @extends {BasePlayer} - */ -class AudioPlayer extends BasePlayer { - constructor(voiceConnection) { - super(); - /** - * The voice connection that the player serves - * @type {VoiceConnection} - */ - this.voiceConnection = voiceConnection; - } - - playBroadcast(broadcast, options) { - const dispatcher = this.createDispatcher(options, { broadcast }); - broadcast.add(dispatcher); - return dispatcher; - } -} - -module.exports = AudioPlayer; diff --git a/node_modules/discord.js/src/client/voice/player/BasePlayer.js b/node_modules/discord.js/src/client/voice/player/BasePlayer.js deleted file mode 100644 index b968f82f..00000000 --- a/node_modules/discord.js/src/client/voice/player/BasePlayer.js +++ /dev/null @@ -1,92 +0,0 @@ -'use strict'; - -const EventEmitter = require('events'); -const { Readable: ReadableStream } = require('stream'); -const prism = require('prism-media'); -const StreamDispatcher = require('../dispatcher/StreamDispatcher'); - -const FFMPEG_ARGUMENTS = ['-analyzeduration', '0', '-loglevel', '0', '-f', 's16le', '-ar', '48000', '-ac', '2']; - -/** - * An Audio Player for a Voice Connection. - * @private - * @extends {EventEmitter} - */ -class BasePlayer extends EventEmitter { - constructor() { - super(); - - this.dispatcher = null; - - this.streamingData = { - channels: 2, - sequence: 0, - timestamp: 0, - }; - } - - destroy() { - this.destroyDispatcher(); - } - - destroyDispatcher() { - if (this.dispatcher) { - this.dispatcher.destroy(); - this.dispatcher = null; - } - } - - playUnknown(input, options) { - this.destroyDispatcher(); - - const isStream = input instanceof ReadableStream; - - const args = isStream ? FFMPEG_ARGUMENTS.slice() : ['-i', input, ...FFMPEG_ARGUMENTS]; - if (options.seek) args.unshift('-ss', String(options.seek)); - - const ffmpeg = new prism.FFmpeg({ args }); - const streams = { ffmpeg }; - if (isStream) { - streams.input = input; - input.pipe(ffmpeg); - } - return this.playPCMStream(ffmpeg, options, streams); - } - - playPCMStream(stream, options, streams = {}) { - this.destroyDispatcher(); - const opus = (streams.opus = new prism.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 })); - if (options && options.volume === false) { - stream.pipe(opus); - return this.playOpusStream(opus, options, streams); - } - streams.volume = new prism.VolumeTransformer({ type: 's16le', volume: options ? options.volume : 1 }); - stream.pipe(streams.volume).pipe(opus); - return this.playOpusStream(opus, options, streams); - } - - playOpusStream(stream, options, streams = {}) { - this.destroyDispatcher(); - streams.opus = stream; - if (options.volume !== false && !streams.input) { - streams.input = stream; - const decoder = new prism.opus.Decoder({ channels: 2, rate: 48000, frameSize: 960 }); - streams.volume = new prism.VolumeTransformer({ type: 's16le', volume: options ? options.volume : 1 }); - streams.opus = stream - .pipe(decoder) - .pipe(streams.volume) - .pipe(new prism.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 })); - } - const dispatcher = this.createDispatcher(options, streams); - streams.opus.pipe(dispatcher); - return dispatcher; - } - - createDispatcher(options, streams, broadcast) { - this.destroyDispatcher(); - const dispatcher = (this.dispatcher = new StreamDispatcher(this, options, streams, broadcast)); - return dispatcher; - } -} - -module.exports = BasePlayer; diff --git a/node_modules/discord.js/src/client/voice/player/BroadcastAudioPlayer.js b/node_modules/discord.js/src/client/voice/player/BroadcastAudioPlayer.js deleted file mode 100644 index 05197a4f..00000000 --- a/node_modules/discord.js/src/client/voice/player/BroadcastAudioPlayer.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; - -const BasePlayer = require('./BasePlayer'); -const BroadcastDispatcher = require('../dispatcher/BroadcastDispatcher'); - -/** - * An Audio Player for a Voice Connection. - * @private - * @extends {BasePlayer} - */ -class AudioPlayer extends BasePlayer { - constructor(broadcast) { - super(); - /** - * The broadcast that the player serves - * @type {VoiceBroadcast} - */ - this.broadcast = broadcast; - } - - createDispatcher(options, streams) { - this.destroyDispatcher(); - const dispatcher = (this.dispatcher = new BroadcastDispatcher(this, options, streams)); - return dispatcher; - } -} - -module.exports = AudioPlayer; diff --git a/node_modules/discord.js/src/client/voice/receiver/PacketHandler.js b/node_modules/discord.js/src/client/voice/receiver/PacketHandler.js deleted file mode 100644 index bf1a220a..00000000 --- a/node_modules/discord.js/src/client/voice/receiver/PacketHandler.js +++ /dev/null @@ -1,143 +0,0 @@ -'use strict'; - -const EventEmitter = require('events'); -const Speaking = require('../../../util/Speaking'); -const secretbox = require('../util/Secretbox'); -const { SILENCE_FRAME } = require('../util/Silence'); - -// The delay between packets when a user is considered to have stopped speaking -// https://github.com/discordjs/discord.js/issues/3524#issuecomment-540373200 -const DISCORD_SPEAKING_DELAY = 250; - -class Readable extends require('stream').Readable { - _read() {} // eslint-disable-line no-empty-function -} - -class PacketHandler extends EventEmitter { - constructor(receiver) { - super(); - this.nonce = Buffer.alloc(24); - this.receiver = receiver; - this.streams = new Map(); - this.speakingTimeouts = new Map(); - } - - get connection() { - return this.receiver.connection; - } - - _stoppedSpeaking(userID) { - const streamInfo = this.streams.get(userID); - if (streamInfo && streamInfo.end === 'silence') { - this.streams.delete(userID); - streamInfo.stream.push(null); - } - } - - makeStream(user, end) { - if (this.streams.has(user)) return this.streams.get(user).stream; - const stream = new Readable(); - stream.on('end', () => this.streams.delete(user)); - this.streams.set(user, { stream, end }); - return stream; - } - - parseBuffer(buffer) { - const { secret_key, mode } = this.receiver.connection.authentication; - - // Choose correct nonce depending on encryption - let end; - if (mode === 'xsalsa20_poly1305_lite') { - buffer.copy(this.nonce, 0, buffer.length - 4); - end = buffer.length - 4; - } else if (mode === 'xsalsa20_poly1305_suffix') { - buffer.copy(this.nonce, 0, buffer.length - 24); - end = buffer.length - 24; - } else { - buffer.copy(this.nonce, 0, 0, 12); - } - - // Open packet - let packet = secretbox.methods.open(buffer.slice(12, end), this.nonce, secret_key); - if (!packet) return new Error('Failed to decrypt voice packet'); - packet = Buffer.from(packet); - - // Strip RTP Header Extensions (one-byte only) - if (packet[0] === 0xbe && packet[1] === 0xde && packet.length > 4) { - const headerExtensionLength = packet.readUInt16BE(2); - let offset = 4; - for (let i = 0; i < headerExtensionLength; i++) { - const byte = packet[offset]; - offset++; - if (byte === 0) continue; - offset += 1 + (0b1111 & (byte >> 4)); - } - // Skip over undocumented Discord byte - offset++; - - packet = packet.slice(offset); - } - - return packet; - } - - push(buffer) { - const ssrc = buffer.readUInt32BE(8); - const userStat = this.connection.ssrcMap.get(ssrc); - if (!userStat) return; - - let opusPacket; - const streamInfo = this.streams.get(userStat.userID); - // If the user is in video, we need to check if the packet is just silence - if (userStat.hasVideo) { - opusPacket = this.parseBuffer(buffer); - if (opusPacket instanceof Error) { - // Only emit an error if we were actively receiving packets from this user - if (streamInfo) { - this.emit('error', opusPacket); - return; - } - } - if (SILENCE_FRAME.equals(opusPacket)) { - // If this is a silence frame, pretend we never received it - return; - } - } - - let speakingTimeout = this.speakingTimeouts.get(ssrc); - if (typeof speakingTimeout === 'undefined') { - // Ensure at least the speaking bit is set. - // As the object is by reference, it's only needed once per client re-connect. - if (userStat.speaking === 0) { - userStat.speaking = Speaking.FLAGS.SPEAKING; - } - this.connection.onSpeaking({ user_id: userStat.userID, ssrc: ssrc, speaking: userStat.speaking }); - speakingTimeout = this.receiver.connection.client.setTimeout(() => { - try { - this.connection.onSpeaking({ user_id: userStat.userID, ssrc: ssrc, speaking: 0 }); - this.receiver.connection.client.clearTimeout(speakingTimeout); - this.speakingTimeouts.delete(ssrc); - } catch { - // Connection already closed, ignore - } - }, DISCORD_SPEAKING_DELAY); - this.speakingTimeouts.set(ssrc, speakingTimeout); - } else { - speakingTimeout.refresh(); - } - - if (streamInfo) { - const { stream } = streamInfo; - if (!opusPacket) { - opusPacket = this.parseBuffer(buffer); - if (opusPacket instanceof Error) { - this.emit('error', opusPacket); - return; - } - } - stream.push(opusPacket); - } - } -} - -module.exports = PacketHandler; diff --git a/node_modules/discord.js/src/client/voice/receiver/Receiver.js b/node_modules/discord.js/src/client/voice/receiver/Receiver.js deleted file mode 100644 index 605d9927..00000000 --- a/node_modules/discord.js/src/client/voice/receiver/Receiver.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; - -const EventEmitter = require('events'); -const prism = require('prism-media'); -const PacketHandler = require('./PacketHandler'); -const { Error } = require('../../../errors'); - -/** - * Receives audio packets from a voice connection. - * @example - * const receiver = connection.createReceiver(); - * // opusStream is a ReadableStream - that means you could play it back to a voice channel if you wanted to! - * const opusStream = receiver.createStream(user); - */ -class VoiceReceiver extends EventEmitter { - constructor(connection) { - super(); - this.connection = connection; - this.packets = new PacketHandler(this); - /** - * Emitted whenever there is a warning - * @event VoiceReceiver#debug - * @param {Error|string} error The error or message to debug - */ - this.packets.on('error', err => this.emit('debug', err)); - } - - /** - * Options passed to `VoiceReceiver#createStream`. - * @typedef {Object} ReceiveStreamOptions - * @property {string} [mode='opus'] The mode for audio output. This defaults to opus, meaning discord.js won't decode - * the packets for you. You can set this to 'pcm' so that the stream's output will be 16-bit little-endian stereo - * audio - * @property {string} [end='silence'] When the stream should be destroyed. If `silence`, this will be when the user - * stops talking. Otherwise, if `manual`, this should be handled by you. - */ - - /** - * Creates a new audio receiving stream. If a stream already exists for a user, then that stream will be returned - * rather than generating a new one. - * @param {UserResolvable} user The user to start listening to. - * @param {ReceiveStreamOptions} options Options. - * @returns {ReadableStream} - */ - createStream(user, { mode = 'opus', end = 'silence' } = {}) { - user = this.connection.client.users.resolve(user); - if (!user) throw new Error('VOICE_USER_MISSING'); - const stream = this.packets.makeStream(user.id, end); - if (mode === 'pcm') { - const decoder = new prism.opus.Decoder({ channels: 2, rate: 48000, frameSize: 960 }); - stream.pipe(decoder); - return decoder; - } - return stream; - } -} - -module.exports = VoiceReceiver; diff --git a/node_modules/discord.js/src/client/voice/util/PlayInterface.js b/node_modules/discord.js/src/client/voice/util/PlayInterface.js deleted file mode 100644 index 9478ee8d..00000000 --- a/node_modules/discord.js/src/client/voice/util/PlayInterface.js +++ /dev/null @@ -1,94 +0,0 @@ -'use strict'; - -const { Readable } = require('stream'); -const prism = require('prism-media'); -const { Error } = require('../../../errors'); - -/** - * Options that can be passed to stream-playing methods: - * @typedef {Object} StreamOptions - * @property {StreamType} [type='unknown'] The type of stream. - * @property {number} [seek=0] The time to seek to, will be ignored when playing `ogg/opus` or `webm/opus` streams - * @property {number|boolean} [volume=1] The volume to play at. Set this to false to disable volume transforms for - * this stream to improve performance. - * @property {number} [plp] Expected packet loss percentage - * @property {boolean} [fec] Enabled forward error correction - * @property {number|string} [bitrate=96] The bitrate (quality) of the audio in kbps. - * If set to 'auto', the voice channel's bitrate will be used - * @property {number} [highWaterMark=12] The maximum number of opus packets to make and store before they are - * actually needed. See https://nodejs.org/en/docs/guides/backpressuring-in-streams/. Setting this value to - * 1 means that changes in volume will be more instant. - */ - -/** - * An option passed as part of `StreamOptions` specifying the type of the stream. - * * `unknown`: The default type, streams/input will be passed through to ffmpeg before encoding. - * Will play most streams. - * * `converted`: Play a stream of 16bit signed stereo PCM data, skipping ffmpeg. - * * `opus`: Play a stream of opus packets, skipping ffmpeg. You lose the ability to alter volume. - * * `ogg/opus`: Play an ogg file with the opus encoding, skipping ffmpeg. You lose the ability to alter volume. - * * `webm/opus`: Play a webm file with opus audio, skipping ffmpeg. You lose the ability to alter volume. - * @typedef {string} StreamType - */ - -/** - * An interface class to allow you to play audio over VoiceConnections and VoiceBroadcasts. - */ -class PlayInterface { - constructor(player) { - this.player = player; - } - - /** - * Play an audio resource. - * @param {VoiceBroadcast|ReadableStream|string} resource The resource to play. - * @param {StreamOptions} [options] The options to play. - * @example - * // Play a local audio file - * connection.play('/home/hydrabolt/audio.mp3', { volume: 0.5 }); - * @example - * // Play a ReadableStream - * connection.play(ytdl('https://www.youtube.com/watch?v=ZlAU_w7-Xp8', { quality: 'highestaudio' })); - * @example - * // Play a voice broadcast - * const broadcast = client.voice.createBroadcast(); - * broadcast.play('/home/hydrabolt/audio.mp3'); - * connection.play(broadcast); - * @example - * // Using different protocols: https://ffmpeg.org/ffmpeg-protocols.html - * connection.play('http://www.sample-videos.com/audio/mp3/wave.mp3'); - * @returns {StreamDispatcher} - */ - play(resource, options = {}) { - const VoiceBroadcast = require('../VoiceBroadcast'); - if (resource instanceof VoiceBroadcast) { - if (!this.player.playBroadcast) throw new Error('VOICE_PLAY_INTERFACE_NO_BROADCAST'); - return this.player.playBroadcast(resource, options); - } - if (resource instanceof Readable || typeof resource === 'string') { - const type = options.type || 'unknown'; - if (type === 'unknown') { - return this.player.playUnknown(resource, options); - } else if (type === 'converted') { - return this.player.playPCMStream(resource, options); - } else if (type === 'opus') { - return this.player.playOpusStream(resource, options); - } else if (type === 'ogg/opus') { - if (!(resource instanceof Readable)) throw new Error('VOICE_PRISM_DEMUXERS_NEED_STREAM'); - return this.player.playOpusStream(resource.pipe(new prism.opus.OggDemuxer()), options); - } else if (type === 'webm/opus') { - if (!(resource instanceof Readable)) throw new Error('VOICE_PRISM_DEMUXERS_NEED_STREAM'); - return this.player.playOpusStream(resource.pipe(new prism.opus.WebmDemuxer()), options); - } - } - throw new Error('VOICE_PLAY_INTERFACE_BAD_TYPE'); - } - - static applyToClass(structure) { - for (const prop of ['play']) { - Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(PlayInterface.prototype, prop)); - } - } -} - -module.exports = PlayInterface; diff --git a/node_modules/discord.js/src/client/voice/util/Secretbox.js b/node_modules/discord.js/src/client/voice/util/Secretbox.js deleted file mode 100644 index c16a4353..00000000 --- a/node_modules/discord.js/src/client/voice/util/Secretbox.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -const libs = { - sodium: sodium => ({ - open: sodium.api.crypto_secretbox_open_easy, - close: sodium.api.crypto_secretbox_easy, - random: n => sodium.randombytes_buf(n), - }), - 'libsodium-wrappers': sodium => ({ - open: sodium.crypto_secretbox_open_easy, - close: sodium.crypto_secretbox_easy, - random: n => sodium.randombytes_buf(n), - }), - tweetnacl: tweetnacl => ({ - open: tweetnacl.secretbox.open, - close: tweetnacl.secretbox, - random: n => tweetnacl.randomBytes(n), - }), -}; - -exports.methods = {}; - -(async () => { - for (const libName of Object.keys(libs)) { - try { - const lib = require(libName); - if (libName === 'libsodium-wrappers' && lib.ready) await lib.ready; // eslint-disable-line no-await-in-loop - exports.methods = libs[libName](lib); - break; - } catch {} // eslint-disable-line no-empty - } -})(); diff --git a/node_modules/discord.js/src/client/voice/util/Silence.js b/node_modules/discord.js/src/client/voice/util/Silence.js deleted file mode 100644 index 7930ae65..00000000 --- a/node_modules/discord.js/src/client/voice/util/Silence.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -const { Readable } = require('stream'); - -const SILENCE_FRAME = Buffer.from([0xf8, 0xff, 0xfe]); - -class Silence extends Readable { - _read() { - this.push(SILENCE_FRAME); - } -} - -Silence.SILENCE_FRAME = SILENCE_FRAME; - -module.exports = Silence; diff --git a/node_modules/discord.js/src/client/voice/util/VolumeInterface.js b/node_modules/discord.js/src/client/voice/util/VolumeInterface.js deleted file mode 100644 index 0dca04f1..00000000 --- a/node_modules/discord.js/src/client/voice/util/VolumeInterface.js +++ /dev/null @@ -1,103 +0,0 @@ -'use strict'; - -const EventEmitter = require('events'); - -/** - * An interface class for volume transformation. - * @extends {EventEmitter} - */ -class VolumeInterface extends EventEmitter { - constructor({ volume = 1 } = {}) { - super(); - this.setVolume(volume); - } - - /** - * Whether or not the volume of this stream is editable - * @type {boolean} - * @readonly - */ - get volumeEditable() { - return true; - } - - /** - * The current volume of the stream - * @type {number} - * @readonly - */ - get volume() { - return this._volume; - } - - /** - * The current volume of the stream in decibels - * @type {number} - * @readonly - */ - get volumeDecibels() { - return Math.log10(this.volume) * 20; - } - - /** - * The current volume of the stream from a logarithmic scale - * @type {number} - * @readonly - */ - get volumeLogarithmic() { - return Math.pow(this.volume, 1 / 1.660964); - } - - applyVolume(buffer, volume) { - volume = volume || this._volume; - if (volume === 1) return buffer; - - const out = Buffer.alloc(buffer.length); - for (let i = 0; i < buffer.length; i += 2) { - if (i >= buffer.length - 1) break; - const uint = Math.min(32767, Math.max(-32767, Math.floor(volume * buffer.readInt16LE(i)))); - out.writeInt16LE(uint, i); - } - - return out; - } - - /** - * Sets the volume relative to the input stream - i.e. 1 is normal, 0.5 is half, 2 is double. - * @param {number} volume The volume that you want to set - */ - setVolume(volume) { - /** - * Emitted when the volume of this interface changes. - * @event VolumeInterface#volumeChange - * @param {number} oldVolume The old volume of this interface - * @param {number} newVolume The new volume of this interface - */ - this.emit('volumeChange', this._volume, volume); - this._volume = volume; - } - - /** - * Sets the volume in decibels. - * @param {number} db The decibels - */ - setVolumeDecibels(db) { - this.setVolume(Math.pow(10, db / 20)); - } - - /** - * Sets the volume so that a perceived value of 0.5 is half the perceived volume etc. - * @param {number} value The value for the volume - */ - setVolumeLogarithmic(value) { - this.setVolume(Math.pow(value, 1.660964)); - } -} - -const props = ['volumeDecibels', 'volumeLogarithmic', 'setVolumeDecibels', 'setVolumeLogarithmic']; - -exports.applyToClass = function applyToClass(structure) { - for (const prop of props) { - Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(VolumeInterface.prototype, prop)); - } -}; diff --git a/node_modules/discord.js/src/client/websocket/WebSocketManager.js b/node_modules/discord.js/src/client/websocket/WebSocketManager.js index f892985f..60c10078 100644 --- a/node_modules/discord.js/src/client/websocket/WebSocketManager.js +++ b/node_modules/discord.js/src/client/websocket/WebSocketManager.js @@ -1,10 +1,10 @@ 'use strict'; const EventEmitter = require('events'); +const { Collection } = require('@discordjs/collection'); const WebSocketShard = require('./WebSocketShard'); const PacketHandlers = require('./handlers'); -const { Error: DJSError } = require('../../errors'); -const Collection = require('../../util/Collection'); +const { Error } = require('../../errors'); const { Events, ShardEvents, Status, WSCodes, WSEvents } = require('../../util/Constants'); const Util = require('../../util/Util'); @@ -68,7 +68,7 @@ class WebSocketManager extends EventEmitter { /** * An array of queued events before this WebSocketManager became ready - * @type {object[]} + * @type {Object[]} * @private * @name WebSocketManager#packetQueue */ @@ -76,7 +76,7 @@ class WebSocketManager extends EventEmitter { /** * The current status of this WebSocketManager - * @type {number} + * @type {Status} */ this.status = Status.IDLE; @@ -93,16 +93,6 @@ class WebSocketManager extends EventEmitter { * @private */ this.reconnecting = false; - - /** - * The current session limit of the client - * @private - * @type {?Object} - * @property {number} total Total number of identifies available - * @property {number} remaining Number of identifies remaining - * @property {number} reset_after Number of milliseconds after which the limit resets - */ - this.sessionStartLimit = null; } /** @@ -130,7 +120,7 @@ class WebSocketManager extends EventEmitter { * @private */ async connect() { - const invalidToken = new DJSError(WSCodes[4004]); + const invalidToken = new Error(WSCodes[4004]); const { url: gatewayURL, shards: recommendedShards, @@ -139,9 +129,7 @@ class WebSocketManager extends EventEmitter { throw error.httpStatus === 401 ? invalidToken : error; }); - this.sessionStartLimit = sessionStartLimit; - - const { total, remaining, reset_after } = sessionStartLimit; + const { total, remaining } = sessionStartLimit; this.debug(`Fetched Gateway Information URL: ${gatewayURL} @@ -165,8 +153,6 @@ class WebSocketManager extends EventEmitter { this.debug(`Spawning shards: ${shards.join(', ')}`); this.shardQueue = new Set(shards.map(id => new WebSocketShard(this, id))); - await this._handleSessionLimit(remaining, reset_after); - return this.createShards(); } @@ -188,8 +174,8 @@ class WebSocketManager extends EventEmitter { /** * Emitted when a shard turns ready. * @event Client#shardReady - * @param {number} id The shard ID that turned ready - * @param {?Set} unavailableGuilds Set of unavailable guild IDs, if any + * @param {number} id The shard id that turned ready + * @param {?Set} unavailableGuilds Set of unavailable guild ids, if any */ this.client.emit(Events.SHARD_READY, shard.id, unavailableGuilds); @@ -203,7 +189,7 @@ class WebSocketManager extends EventEmitter { * Emitted when a shard's WebSocket disconnects and will no longer reconnect. * @event Client#shardDisconnect * @param {CloseEvent} event The WebSocket close event - * @param {number} id The shard ID that disconnected + * @param {number} id The shard id that disconnected */ this.client.emit(Events.SHARD_DISCONNECT, event, shard.id); this.debug(WSCodes[event.code], shard); @@ -212,21 +198,21 @@ class WebSocketManager extends EventEmitter { if (UNRESUMABLE_CLOSE_CODES.includes(event.code)) { // These event codes cannot be resumed - shard.sessionID = null; + shard.sessionId = null; } /** * Emitted when a shard is attempting to reconnect or re-identify. * @event Client#shardReconnecting - * @param {number} id The shard ID that is attempting to reconnect + * @param {number} id The shard id that is attempting to reconnect */ this.client.emit(Events.SHARD_RECONNECTING, shard.id); this.shardQueue.add(shard); - if (shard.sessionID) { - this.debug(`Session ID is present, attempting an immediate reconnect...`, shard); - this.reconnect(true); + if (shard.sessionId) { + this.debug(`Session id is present, attempting an immediate reconnect...`, shard); + this.reconnect(); } else { shard.destroy({ reset: true, emit: false, log: false }); this.reconnect(); @@ -254,8 +240,8 @@ class WebSocketManager extends EventEmitter { try { await shard.connect(); } catch (error) { - if (error && error.code && UNRECOVERABLE_CLOSE_CODES.includes(error.code)) { - throw new DJSError(WSCodes[error.code]); + if (error?.code && UNRECOVERABLE_CLOSE_CODES.includes(error.code)) { + throw new Error(WSCodes[error.code]); // Undefined if session is invalid, error event for regular closes } else if (!error || error.code) { this.debug('Failed to connect to the gateway, requeueing...', shard); @@ -268,7 +254,6 @@ class WebSocketManager extends EventEmitter { if (this.shardQueue.size) { this.debug(`Shard Queue Size: ${this.shardQueue.size}; continuing in 5 seconds...`); await Util.delayFor(5000); - await this._handleSessionLimit(); return this.createShards(); } @@ -277,15 +262,13 @@ class WebSocketManager extends EventEmitter { /** * Handles reconnects for this manager. - * @param {boolean} [skipLimit=false] IF this reconnect should skip checking the session limit * @private * @returns {Promise} */ - async reconnect(skipLimit = false) { + async reconnect() { if (this.reconnecting || this.status !== Status.READY) return false; this.reconnecting = true; try { - if (!skipLimit) await this._handleSessionLimit(); await this.createShards(); } catch (error) { this.debug(`Couldn't reconnect or fetch information about the gateway. ${error}`); @@ -336,28 +319,6 @@ class WebSocketManager extends EventEmitter { for (const shard of this.shards.values()) shard.destroy({ closeCode: 1000, reset: true, emit: false, log: false }); } - /** - * Handles the timeout required if we cannot identify anymore. - * @param {number} [remaining] The amount of remaining identify sessions that can be done today - * @param {number} [resetAfter] The amount of time in which the identify counter resets - * @private - */ - async _handleSessionLimit(remaining, resetAfter) { - if (typeof remaining === 'undefined' && typeof resetAfter === 'undefined') { - const { session_start_limit } = await this.client.api.gateway.bot.get(); - this.sessionStartLimit = session_start_limit; - remaining = session_start_limit.remaining; - resetAfter = session_start_limit.reset_after; - this.debug(`Session Limit Information - Total: ${session_start_limit.total} - Remaining: ${remaining}`); - } - if (!remaining) { - this.debug(`Exceeded identify threshold. Will attempt a connection in ${resetAfter}ms`); - await Util.delayFor(resetAfter); - } - } - /** * Processes a packet and queues it if this WebSocketManager is not ready. * @param {Object} [packet] The packet to be handled @@ -375,9 +336,9 @@ class WebSocketManager extends EventEmitter { if (this.packetQueue.length) { const item = this.packetQueue.shift(); - this.client.setImmediate(() => { + setImmediate(() => { this.handlePacket(item.packet, item.shard); - }); + }).unref(); } if (packet && PacketHandlers[packet.t]) { @@ -391,27 +352,12 @@ class WebSocketManager extends EventEmitter { * Checks whether the client is ready to be marked as ready. * @private */ - async checkShardsReady() { + checkShardsReady() { if (this.status === Status.READY) return; if (this.shards.size !== this.totalShards || this.shards.some(s => s.status !== Status.READY)) { return; } - this.status = Status.NEARLY; - - if (this.client.options.fetchAllMembers) { - try { - const promises = this.client.guilds.cache.map(guild => { - if (guild.available) return guild.members.fetch(); - // Return empty promise if guild is unavailable - return Promise.resolve(); - }); - await Promise.all(promises); - } catch (err) { - this.debug(`Failed to fetch all members before ready! ${err}\n${err.stack}`); - } - } - this.triggerClientReady(); } @@ -427,8 +373,9 @@ class WebSocketManager extends EventEmitter { /** * Emitted when the client becomes ready to start working. * @event Client#ready + * @param {Client} client The client */ - this.client.emit(Events.CLIENT_READY); + this.client.emit(Events.CLIENT_READY, this.client); this.handlePacket(); } diff --git a/node_modules/discord.js/src/client/websocket/WebSocketShard.js b/node_modules/discord.js/src/client/websocket/WebSocketShard.js index f99c83f8..ab5b9216 100644 --- a/node_modules/discord.js/src/client/websocket/WebSocketShard.js +++ b/node_modules/discord.js/src/client/websocket/WebSocketShard.js @@ -2,18 +2,17 @@ const EventEmitter = require('events'); const WebSocket = require('../../WebSocket'); -const { browser, Status, Events, ShardEvents, OPCodes, WSEvents } = require('../../util/Constants'); +const { Status, Events, ShardEvents, Opcodes, WSEvents } = require('../../util/Constants'); +const Intents = require('../../util/Intents'); const STATUS_KEYS = Object.keys(Status); const CONNECTION_STATE = Object.keys(WebSocket.WebSocket); let zlib; -if (!browser) { - try { - zlib = require('zlib-sync'); - } catch {} // eslint-disable-line no-empty -} +try { + zlib = require('zlib-sync'); +} catch {} // eslint-disable-line no-empty /** * Represents a Shard's WebSocket connection @@ -29,7 +28,7 @@ class WebSocketShard extends EventEmitter { this.manager = manager; /** - * The ID of the shard + * The shard's id * @type {number} */ this.id = id; @@ -55,11 +54,11 @@ class WebSocketShard extends EventEmitter { this.closeSequence = 0; /** - * The current session ID of the shard + * The current session id of the shard * @type {?string} * @private */ - this.sessionID = null; + this.sessionId = null; /** * The previous heartbeat ping of the shard @@ -135,7 +134,7 @@ class WebSocketShard extends EventEmitter { Object.defineProperty(this, 'eventsAttached', { value: false, writable: true }); /** - * A set of guild IDs this shard expects to receive + * A set of guild ids this shard expects to receive * @name WebSocketShard#expectedGuilds * @type {?Set} * @private @@ -177,7 +176,7 @@ class WebSocketShard extends EventEmitter { connect() { const { gateway, client } = this.manager; - if (this.connection && this.connection.readyState === WebSocket.OPEN && this.status === Status.READY) { + if (this.connection?.readyState === WebSocket.OPEN && this.status === Status.READY) { return Promise.resolve(); } @@ -217,7 +216,7 @@ class WebSocketShard extends EventEmitter { this.once(ShardEvents.INVALID_SESSION, onInvalidOrDestroyed); this.once(ShardEvents.DESTROYED, onInvalidOrDestroyed); - if (this.connection && this.connection.readyState === WebSocket.OPEN) { + if (this.connection?.readyState === WebSocket.OPEN) { this.debug('An open connection was found, attempting an immediate identify.'); this.identify(); return; @@ -266,7 +265,7 @@ class WebSocketShard extends EventEmitter { * @private */ onOpen() { - this.debug(`[CONNECTED] ${this.connection.url} in ${Date.now() - this.connectedAt}ms`); + this.debug(`[CONNECTED] Took ${Date.now() - this.connectedAt}ms`); this.status = Status.NEARLY; } @@ -292,12 +291,12 @@ class WebSocketShard extends EventEmitter { let packet; try { packet = WebSocket.unpack(raw); - this.manager.client.emit(Events.RAW, packet, this.id); - if (packet.op === OPCodes.DISPATCH) this.manager.emit(packet.t, packet.d, this.id); } catch (err) { this.manager.client.emit(Events.SHARD_ERROR, err, this.id); return; } + this.manager.client.emit(Events.RAW, packet, this.id); + if (packet.op === Opcodes.DISPATCH) this.manager.emit(packet.t, packet.d, this.id); this.onPacket(packet); } @@ -307,14 +306,14 @@ class WebSocketShard extends EventEmitter { * @private */ onError(event) { - const error = event && event.error ? event.error : event; + const error = event?.error ?? event; if (!error) return; /** * Emitted whenever a shard's WebSocket encounters a connection error. * @event Client#shardError * @param {Error} error The encountered error - * @param {number} shardID The shard that encountered this error + * @param {number} shardId The shard that encountered this error */ this.manager.client.emit(Events.SHARD_ERROR, error, this.id); } @@ -346,7 +345,7 @@ class WebSocketShard extends EventEmitter { this.debug(`[CLOSE] Event Code: ${event.code} Clean : ${event.wasClean} - Reason : ${event.reason || 'No reason received'}`); + Reason : ${event.reason ?? 'No reason received'}`); this.setHeartbeatTimer(-1); this.setHelloTimeout(-1); @@ -383,10 +382,10 @@ class WebSocketShard extends EventEmitter { */ this.emit(ShardEvents.READY); - this.sessionID = packet.d.session_id; + this.sessionId = packet.d.session_id; this.expectedGuilds = new Set(packet.d.guilds.map(d => d.id)); this.status = Status.WAITING_FOR_GUILDS; - this.debug(`[READY] Session ${this.sessionID}.`); + this.debug(`[READY] Session ${this.sessionId}.`); this.lastHeartbeatAcked = true; this.sendHeartbeat('ReadyHeartbeat'); break; @@ -399,7 +398,7 @@ class WebSocketShard extends EventEmitter { this.status = Status.READY; const replayed = packet.s - this.closeSequence; - this.debug(`[RESUMED] Session ${this.sessionID} | Replayed ${replayed} events.`); + this.debug(`[RESUMED] Session ${this.sessionId} | Replayed ${replayed} events.`); this.lastHeartbeatAcked = true; this.sendHeartbeat('ResumeHeartbeat'); break; @@ -409,16 +408,16 @@ class WebSocketShard extends EventEmitter { if (packet.s > this.sequence) this.sequence = packet.s; switch (packet.op) { - case OPCodes.HELLO: + case Opcodes.HELLO: this.setHelloTimeout(-1); this.setHeartbeatTimer(packet.d.heartbeat_interval); this.identify(); break; - case OPCodes.RECONNECT: + case Opcodes.RECONNECT: this.debug('[RECONNECT] Discord asked us to reconnect'); this.destroy({ closeCode: 4000 }); break; - case OPCodes.INVALID_SESSION: + case Opcodes.INVALID_SESSION: this.debug(`[INVALID SESSION] Resumable: ${packet.d}.`); // If we can resume the session, do so immediately if (packet.d) { @@ -427,17 +426,17 @@ class WebSocketShard extends EventEmitter { } // Reset the sequence this.sequence = -1; - // Reset the session ID as it's invalid - this.sessionID = null; + // Reset the session id as it's invalid + this.sessionId = null; // Set the status to reconnecting this.status = Status.RECONNECTING; // Finally, emit the INVALID_SESSION event this.emit(ShardEvents.INVALID_SESSION); break; - case OPCodes.HEARTBEAT_ACK: + case Opcodes.HEARTBEAT_ACK: this.ackHeartbeat(); break; - case OPCodes.HEARTBEAT: + case Opcodes.HEARTBEAT: this.sendHeartbeat('HeartbeatRequest', true); break; default: @@ -456,7 +455,7 @@ class WebSocketShard extends EventEmitter { checkReady() { // Step 0. Clear the ready timeout, if it exists if (this.readyTimeout) { - this.manager.client.clearTimeout(this.readyTimeout); + clearTimeout(this.readyTimeout); this.readyTimeout = null; } // Step 1. If we don't have any other guilds pending, we are ready @@ -476,7 +475,7 @@ class WebSocketShard extends EventEmitter { return; } // Step 2. Create a 15s timeout that will mark the shard as ready if there are still unavailable guilds - this.readyTimeout = this.manager.client.setTimeout(() => { + this.readyTimeout = setTimeout(() => { this.debug(`Shard did not receive any more guild packets in 15 seconds. Unavailable guild count: ${this.expectedGuilds.size}`); @@ -485,7 +484,7 @@ class WebSocketShard extends EventEmitter { this.status = Status.READY; this.emit(ShardEvents.ALL_READY, this.expectedGuilds); - }, 15000); + }, 15000).unref(); } /** @@ -497,16 +496,16 @@ class WebSocketShard extends EventEmitter { if (time === -1) { if (this.helloTimeout) { this.debug('Clearing the HELLO timeout.'); - this.manager.client.clearTimeout(this.helloTimeout); + clearTimeout(this.helloTimeout); this.helloTimeout = null; } return; } this.debug('Setting a HELLO timeout for 20s.'); - this.helloTimeout = this.manager.client.setTimeout(() => { + this.helloTimeout = setTimeout(() => { this.debug('Did not receive HELLO in time. Destroying and connecting again.'); this.destroy({ reset: true, closeCode: 4009 }); - }, 20000); + }, 20000).unref(); } /** @@ -518,15 +517,15 @@ class WebSocketShard extends EventEmitter { if (time === -1) { if (this.heartbeatInterval) { this.debug('Clearing the heartbeat interval.'); - this.manager.client.clearInterval(this.heartbeatInterval); + clearInterval(this.heartbeatInterval); this.heartbeatInterval = null; } return; } this.debug(`Setting a heartbeat interval for ${time}ms.`); // Sanity checks - if (this.heartbeatInterval) this.manager.client.clearInterval(this.heartbeatInterval); - this.heartbeatInterval = this.manager.client.setInterval(() => this.sendHeartbeat(), time); + if (this.heartbeatInterval) clearInterval(this.heartbeatInterval); + this.heartbeatInterval = setInterval(() => this.sendHeartbeat(), time).unref(); } /** @@ -557,7 +556,7 @@ class WebSocketShard extends EventEmitter { this.debug(`[${tag}] Sending a heartbeat.`); this.lastHeartbeatAcked = false; this.lastPingTimestamp = Date.now(); - this.send({ op: OPCodes.HEARTBEAT, d: this.sequence }, true); + this.send({ op: Opcodes.HEARTBEAT, d: this.sequence }, true); } /** @@ -577,7 +576,7 @@ class WebSocketShard extends EventEmitter { * @returns {void} */ identify() { - return this.sessionID ? this.identifyResume() : this.identifyNew(); + return this.sessionId ? this.identifyResume() : this.identifyNew(); } /** @@ -596,12 +595,13 @@ class WebSocketShard extends EventEmitter { // Clone the identify payload and assign the token and shard info const d = { ...client.options.ws, + intents: Intents.resolve(client.options.intents), token: client.token, shard: [this.id, Number(client.options.shardCount)], }; - this.debug(`[IDENTIFY] Shard ${this.id}/${client.options.shardCount}`); - this.send({ op: OPCodes.IDENTIFY, d }, true); + this.debug(`[IDENTIFY] Shard ${this.id}/${client.options.shardCount} with intents: ${d.intents}`); + this.send({ op: Opcodes.IDENTIFY, d }, true); } /** @@ -609,23 +609,23 @@ class WebSocketShard extends EventEmitter { * @private */ identifyResume() { - if (!this.sessionID) { - this.debug('[RESUME] No session ID was present; identifying as a new session.'); + if (!this.sessionId) { + this.debug('[RESUME] No session id was present; identifying as a new session.'); this.identifyNew(); return; } this.status = Status.RESUMING; - this.debug(`[RESUME] Session ${this.sessionID}, sequence ${this.closeSequence}`); + this.debug(`[RESUME] Session ${this.sessionId}, sequence ${this.closeSequence}`); const d = { token: this.manager.client.token, - session_id: this.sessionID, + session_id: this.sessionId, seq: this.closeSequence, }; - this.send({ op: OPCodes.RESUME, d }, true); + this.send({ op: Opcodes.RESUME, d }, true); } /** @@ -648,9 +648,9 @@ class WebSocketShard extends EventEmitter { * @private */ _send(data) { - if (!this.connection || this.connection.readyState !== WebSocket.OPEN) { + if (this.connection?.readyState !== WebSocket.OPEN) { this.debug(`Tried to send packet '${JSON.stringify(data)}' but no WebSocket is available!`); - this.destroy({ close: 4000 }); + this.destroy({ closeCode: 4000 }); return; } @@ -668,10 +668,10 @@ class WebSocketShard extends EventEmitter { if (this.ratelimit.remaining === 0) return; if (this.ratelimit.queue.length === 0) return; if (this.ratelimit.remaining === this.ratelimit.total) { - this.ratelimit.timer = this.manager.client.setTimeout(() => { + this.ratelimit.timer = setTimeout(() => { this.ratelimit.remaining = this.ratelimit.total; this.processQueue(); - }, this.ratelimit.time); + }, this.ratelimit.time).unref(); } while (this.ratelimit.remaining > 0) { const item = this.ratelimit.queue.shift(); @@ -731,17 +731,17 @@ class WebSocketShard extends EventEmitter { // Step 4: Cache the old sequence (use to attempt a resume) if (this.sequence !== -1) this.closeSequence = this.sequence; - // Step 5: Reset the sequence and session ID if requested + // Step 5: Reset the sequence and session id if requested if (reset) { this.sequence = -1; - this.sessionID = null; + this.sessionId = null; } // Step 6: reset the ratelimit data this.ratelimit.remaining = this.ratelimit.total; this.ratelimit.queue.length = 0; if (this.ratelimit.timer) { - this.manager.client.clearTimeout(this.ratelimit.timer); + clearTimeout(this.ratelimit.timer); this.ratelimit.timer = null; } } diff --git a/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js index 13e6f0fa..35dd3ec0 100644 --- a/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js +++ b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js @@ -8,13 +8,13 @@ module.exports = (client, { d: data }) => { if (channel && !Number.isNaN(time.getTime())) { // Discord sends null for last_pin_timestamp if the last pinned message was removed - channel.lastPinTimestamp = time.getTime() || null; + channel.lastPinTimestamp = time.getTime() ?? null; /** * Emitted whenever the pins of a channel are updated. Due to the nature of the WebSocket event, * not much information can be provided easily here - you need to manually check the pins yourself. * @event Client#channelPinsUpdate - * @param {DMChannel|TextChannel} channel The channel that the pins update occurred in + * @param {DMChannel|TextChannel|NewsChannel} channel The channel that the pins update occurred in * @param {Date} time The time of the pins update */ client.emit(Events.CHANNEL_PINS_UPDATE, channel, time); diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js index 5d4a0965..d8dc0f9d 100644 --- a/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js @@ -1,16 +1,5 @@ 'use strict'; -const { Events } = require('../../../util/Constants'); - -module.exports = (client, { d: data }) => { - const guild = client.guilds.cache.get(data.guild_id); - const user = client.users.add(data.user); - - /** - * Emitted whenever a member is banned from a guild. - * @event Client#guildBanAdd - * @param {Guild} guild The guild that the ban occurred in - * @param {User} user The user that was banned - */ - if (guild && user) client.emit(Events.GUILD_BAN_ADD, guild, user); +module.exports = (client, packet) => { + client.actions.GuildBanAdd.handle(packet.d); }; diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js index 67432049..acff7c28 100644 --- a/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js @@ -2,34 +2,23 @@ const { Events, Status } = require('../../../util/Constants'); -module.exports = async (client, { d: data }, shard) => { +module.exports = (client, { d: data }, shard) => { let guild = client.guilds.cache.get(data.id); if (guild) { if (!guild.available && !data.unavailable) { // A newly available guild guild._patch(data); - // If the client was ready before and we had unavailable guilds, fetch them - if (client.ws.status === Status.READY && client.options.fetchAllMembers) { - await guild.members - .fetch() - .catch(err => client.emit(Events.DEBUG, `Failed to fetch all members: ${err}\n${err.stack}`)); - } } } else { // A new guild - data.shardID = shard.id; - guild = client.guilds.add(data); + data.shardId = shard.id; + guild = client.guilds._add(data); if (client.ws.status === Status.READY) { /** * Emitted whenever the client joins a guild. * @event Client#guildCreate * @param {Guild} guild The created guild */ - if (client.options.fetchAllMembers) { - await guild.members - .fetch() - .catch(err => client.emit(Events.DEBUG, `Failed to fetch all members: ${err}\n${err.stack}`)); - } client.emit(Events.GUILD_CREATE, guild); } } diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js index 2a04c68b..48cddea4 100644 --- a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js @@ -1,6 +1,6 @@ 'use strict'; -const Collection = require('../../../util/Collection'); +const { Collection } = require('@discordjs/collection'); const { Events } = require('../../../util/Constants'); module.exports = (client, { d: data }) => { @@ -8,9 +8,9 @@ module.exports = (client, { d: data }) => { if (!guild) return; const members = new Collection(); - for (const member of data.members) members.set(member.user.id, guild.members.add(member)); + for (const member of data.members) members.set(member.user.id, guild.members._add(member)); if (data.presences) { - for (const presence of data.presences) guild.presences.add(Object.assign(presence, { guild })); + for (const presence of data.presences) guild.presences._add(Object.assign(presence, { guild })); } /** * Emitted whenever a chunk of guild members is received (all members come from the same guild). diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js index 51287562..67590db2 100644 --- a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js +++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js @@ -6,7 +6,7 @@ module.exports = (client, { d: data }, shard) => { const guild = client.guilds.cache.get(data.guild_id); if (guild) { guild.memberCount++; - const member = guild.members.add(data); + const member = guild.members._add(data); if (shard.status === Status.READY) { /** * Emitted whenever a user joins a guild. diff --git a/node_modules/discord.js/src/client/websocket/handlers/READY.js b/node_modules/discord.js/src/client/websocket/handlers/READY.js index c38b681c..408bfa73 100644 --- a/node_modules/discord.js/src/client/websocket/handlers/READY.js +++ b/node_modules/discord.js/src/client/websocket/handlers/READY.js @@ -1,5 +1,6 @@ 'use strict'; +const ClientApplication = require('../../../structures/ClientApplication'); let ClientUser; module.exports = (client, { d: data }, shard) => { @@ -7,14 +8,19 @@ module.exports = (client, { d: data }, shard) => { client.user._patch(data.user); } else { if (!ClientUser) ClientUser = require('../../../structures/ClientUser'); - const clientUser = new ClientUser(client, data.user); - client.user = clientUser; - client.users.cache.set(clientUser.id, clientUser); + client.user = new ClientUser(client, data.user); + client.users.cache.set(client.user.id, client.user); } for (const guild of data.guilds) { - guild.shardID = shard.id; - client.guilds.add(guild); + guild.shardId = shard.id; + client.guilds._add(guild); + } + + if (client.application) { + client.application._patch(data.application); + } else { + client.application = new ClientApplication(client, data.application); } shard.checkReady(); diff --git a/node_modules/discord.js/src/client/websocket/handlers/RESUMED.js b/node_modules/discord.js/src/client/websocket/handlers/RESUMED.js index 5e5f403a..bf72d3aa 100644 --- a/node_modules/discord.js/src/client/websocket/handlers/RESUMED.js +++ b/node_modules/discord.js/src/client/websocket/handlers/RESUMED.js @@ -7,7 +7,7 @@ module.exports = (client, packet, shard) => { /** * Emitted when a shard resumes successfully. * @event Client#shardResume - * @param {number} id The shard ID that resumed + * @param {number} id The shard id that resumed * @param {number} replayedEvents The amount of replayed events */ client.emit(Events.SHARD_RESUME, shard.id, replayed); diff --git a/node_modules/discord.js/src/client/websocket/handlers/index.js b/node_modules/discord.js/src/client/websocket/handlers/index.js index d69c105f..1e499c6e 100644 --- a/node_modules/discord.js/src/client/websocket/handlers/index.js +++ b/node_modules/discord.js/src/client/websocket/handlers/index.js @@ -5,9 +5,7 @@ const { WSEvents } = require('../../../util/Constants'); const handlers = {}; for (const name of Object.keys(WSEvents)) { - try { - handlers[name] = require(`./${name}.js`); - } catch {} // eslint-disable-line no-empty + handlers[name] = require(`./${name}.js`); } module.exports = handlers; diff --git a/node_modules/discord.js/src/errors/DJSError.js b/node_modules/discord.js/src/errors/DJSError.js index 157ca660..af2ff097 100644 --- a/node_modules/discord.js/src/errors/DJSError.js +++ b/node_modules/discord.js/src/errors/DJSError.js @@ -39,7 +39,7 @@ function message(key, args) { const msg = messages.get(key); if (!msg) throw new Error(`An invalid error message key was used: ${key}.`); if (typeof msg === 'function') return msg(...args); - if (args === undefined || args.length === 0) return msg; + if (!args?.length) return msg; args.unshift(msg); return String(...args); } diff --git a/node_modules/discord.js/src/errors/Messages.js b/node_modules/discord.js/src/errors/Messages.js index a68cd2da..770f89d7 100644 --- a/node_modules/discord.js/src/errors/Messages.js +++ b/node_modules/discord.js/src/errors/Messages.js @@ -5,6 +5,8 @@ const { register } = require('./DJSError'); const Messages = { CLIENT_INVALID_OPTION: (prop, must) => `The ${prop} option must be ${must}`, CLIENT_INVALID_PROVIDED_SHARDS: 'None of the provided shards were valid.', + CLIENT_MISSING_INTENTS: 'Valid intents must be provided for the Client.', + CLIENT_NOT_READY: action => `The client needs to be logged in to ${action}.`, TOKEN_INVALID: 'An invalid token was provided.', TOKEN_MISSING: 'Request to use token, but token was unavailable to the client.', @@ -12,8 +14,9 @@ const Messages = { WS_CLOSE_REQUESTED: 'WebSocket closed due to user request.', WS_CONNECTION_EXISTS: 'There is already an existing WebSocket connection.', WS_NOT_OPEN: (data = 'data') => `Websocket not open to send ${data}`, + MANAGER_DESTROYED: 'Manager was destroyed.', - BITFIELD_INVALID: 'Invalid bitfield flag or number.', + BITFIELD_INVALID: bit => `Invalid bitfield flag or number: ${bit}.`, SHARDING_INVALID: 'Invalid shard settings were provided.', SHARDING_REQUIRED: 'This session would have handled too many guilds - Sharding is required.', @@ -21,6 +24,7 @@ const Messages = { DISALLOWED_INTENTS: 'Privileged intent provided is not enabled or whitelisted.', SHARDING_NO_SHARDS: 'No shards have been spawned.', SHARDING_IN_PROCESS: 'Shards are still being spawned.', + SHARDING_INVALID_EVAL_BROADCAST: 'Script to evaluate must be a function', SHARDING_SHARD_NOT_FOUND: id => `Shard ${id} could not be found.`, SHARDING_ALREADY_SPAWNED: count => `Already spawned ${count} shards.`, SHARDING_PROCESS_EXISTS: id => `Shard ${id} already has an active process.`, @@ -35,77 +39,114 @@ const Messages = { COLOR_RANGE: 'Color must be within the range 0 - 16777215 (0xFFFFFF).', COLOR_CONVERT: 'Unable to convert color to a number.', - EMBED_FIELD_NAME: 'MessageEmbed field names may not be empty.', - EMBED_FIELD_VALUE: 'MessageEmbed field values may not be empty.', + EMBED_TITLE: 'MessageEmbed title must be a string.', + EMBED_FIELD_NAME: 'MessageEmbed field names must be non-empty strings.', + EMBED_FIELD_VALUE: 'MessageEmbed field values must be non-empty strings.', + EMBED_FOOTER_TEXT: 'MessageEmbed footer text must be a string.', + EMBED_DESCRIPTION: 'MessageEmbed description must be a string.', + EMBED_AUTHOR_NAME: 'MessageEmbed author name must be a string.', + + BUTTON_LABEL: 'MessageButton label must be a string', + BUTTON_URL: 'MessageButton url must be a string', + BUTTON_CUSTOM_ID: 'MessageButton customId must be a string', + + SELECT_MENU_CUSTOM_ID: 'MessageSelectMenu customId must be a string', + SELECT_MENU_PLACEHOLDER: 'MessageSelectMenu placeholder must be a string', + SELECT_OPTION_LABEL: 'MessageSelectOption label must be a string', + SELECT_OPTION_VALUE: 'MessageSelectOption value must be a string', + SELECT_OPTION_DESCRIPTION: 'MessageSelectOption description must be a string', + + INTERACTION_COLLECTOR_ERROR: reason => `Collector received no interactions before ending with reason: ${reason}`, FILE_NOT_FOUND: file => `File could not be found: ${file}`, USER_NO_DMCHANNEL: 'No DM Channel exists!', - VOICE_INVALID_HEARTBEAT: 'Tried to set voice heartbeat but no valid interval was specified.', - VOICE_USER_MISSING: "Couldn't resolve the user to create stream.", - VOICE_JOIN_CHANNEL: (full = false) => - `You do not have permission to join this voice channel${full ? '; it is full.' : '.'}`, - VOICE_CONNECTION_TIMEOUT: 'Connection not established within 15 seconds.', - VOICE_TOKEN_ABSENT: 'Token not provided from voice server packet.', - VOICE_SESSION_ABSENT: 'Session ID not supplied.', - VOICE_INVALID_ENDPOINT: 'Invalid endpoint received.', - VOICE_NO_BROWSER: 'Voice connections are not available in browsers.', - VOICE_CONNECTION_ATTEMPTS_EXCEEDED: attempts => `Too many connection attempts (${attempts}).`, - VOICE_JOIN_SOCKET_CLOSED: 'Tried to send join packet, but the WebSocket is not open.', - VOICE_PLAY_INTERFACE_NO_BROADCAST: 'A broadcast cannot be played in this context.', - VOICE_PLAY_INTERFACE_BAD_TYPE: 'Unknown stream type', - VOICE_PRISM_DEMUXERS_NEED_STREAM: 'To play a webm/ogg stream, you need to pass a ReadableStream.', + VOICE_NOT_STAGE_CHANNEL: 'You are only allowed to do this in stage channels.', VOICE_STATE_UNCACHED_MEMBER: 'The member of this voice state is uncached.', - VOICE_STATE_NOT_OWN: 'You cannot self-deafen/mute on VoiceStates that do not belong to the ClientUser.', + VOICE_STATE_NOT_OWN: + 'You cannot self-deafen/mute/request to speak on VoiceStates that do not belong to the ClientUser.', VOICE_STATE_INVALID_TYPE: name => `${name} must be a boolean.`, - UDP_SEND_FAIL: 'Tried to send a UDP packet, but there is no socket available.', - UDP_ADDRESS_MALFORMED: 'Malformed UDP address or port.', - UDP_CONNECTION_EXISTS: 'There is already an existing UDP connection.', - REQ_RESOURCE_TYPE: 'The resource must be a string, Buffer or a valid file stream.', IMAGE_FORMAT: format => `Invalid image format: ${format}`, IMAGE_SIZE: size => `Invalid image size: ${size}`, MESSAGE_BULK_DELETE_TYPE: 'The messages must be an Array, Collection, or number.', - MESSAGE_NONCE_TYPE: 'Message nonce must fit in an unsigned 64-bit integer.', - - TYPING_COUNT: 'Count must be at least 1', + MESSAGE_NONCE_TYPE: 'Message nonce must be an integer or a string.', + MESSAGE_CONTENT_TYPE: 'Message content must be a non-empty string.', SPLIT_MAX_LEN: 'Chunk exceeds the max length and contains no split characters.', - BAN_RESOLVE_ID: (ban = false) => `Couldn't resolve the user ID to ${ban ? 'ban' : 'unban'}.`, - FETCH_BAN_RESOLVE_ID: "Couldn't resolve the user ID to fetch the ban.", + BAN_RESOLVE_ID: (ban = false) => `Couldn't resolve the user id to ${ban ? 'ban' : 'unban'}.`, + FETCH_BAN_RESOLVE_ID: "Couldn't resolve the user id to fetch the ban.", PRUNE_DAYS_TYPE: 'Days must be a number', GUILD_CHANNEL_RESOLVE: 'Could not resolve channel to a guild channel.', GUILD_VOICE_CHANNEL_RESOLVE: 'Could not resolve channel to a guild voice channel.', GUILD_CHANNEL_ORPHAN: 'Could not find a parent to this guild channel.', + GUILD_CHANNEL_UNOWNED: "The fetched channel does not belong to this manager's guild.", GUILD_OWNED: 'Guild is owned by the client.', GUILD_MEMBERS_TIMEOUT: "Members didn't arrive in time.", GUILD_UNCACHED_ME: 'The client user as a member of this guild is uncached.', + STAGE_CHANNEL_RESOLVE: 'Could not resolve channel to a stage channel.', INVALID_TYPE: (name, expected, an = false) => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`, + INVALID_ELEMENT: (type, name, elem) => `Supplied ${type} ${name} includes an invalid element: ${elem}`, + + MESSAGE_THREAD_PARENT: 'The message was not sent in a guild text or news channel', + MESSAGE_EXISTING_THREAD: 'The message already has a thread', WEBHOOK_MESSAGE: 'The message was not sent by a webhook.', + WEBHOOK_TOKEN_UNAVAILABLE: 'This action requires a webhook token, but none is available.', + WEBHOOK_URL_INVALID: 'The provided webhook URL is not valid.', + MESSAGE_REFERENCE_MISSING: 'The message does not reference another message', EMOJI_TYPE: 'Emoji must be a string or GuildEmoji/ReactionEmoji', EMOJI_MANAGED: 'Emoji is managed and has no Author.', - MISSING_MANAGE_EMOJIS_PERMISSION: guild => - `Client must have Manage Emoji permission in guild ${guild} to see emoji authors.`, + MISSING_MANAGE_EMOJIS_AND_STICKERS_PERMISSION: guild => + `Client must have Manage Emojis and Stickers permission in guild ${guild} to see emoji authors.`, + NOT_GUILD_STICKER: 'Sticker is a standard (non-guild) sticker and has no author.', - REACTION_RESOLVE_USER: "Couldn't resolve the user ID to remove from the reaction.", + REACTION_RESOLVE_USER: "Couldn't resolve the user id to remove from the reaction.", VANITY_URL: 'This guild does not have the VANITY_URL feature enabled.', + INVITE_RESOLVE_CODE: 'Could not resolve the code to fetch the invite.', + + INVITE_NOT_FOUND: 'Could not find the requested invite.', + DELETE_GROUP_DM_CHANNEL: "Bots don't have access to Group DM Channels and cannot delete them", FETCH_GROUP_DM_CHANNEL: "Bots don't have access to Group DM Channels and cannot fetch them", MEMBER_FETCH_NONCE_LENGTH: 'Nonce length must not exceed 32 characters.', + + GLOBAL_COMMAND_PERMISSIONS: + 'Permissions for global commands may only be fetched or modified by providing a GuildResolvable ' + + "or from a guild's application command manager.", + GUILD_UNCACHED_ROLE_RESOLVE: 'Cannot resolve roles from an arbitrary guild, provide an id instead', + + INTERACTION_ALREADY_REPLIED: 'This interaction has already been deferred or replied to.', + INTERACTION_NOT_REPLIED: 'This interaction has not been deferred or replied to.', + INTERACTION_EPHEMERAL_REPLIED: 'Ephemeral responses cannot be fetched or deleted.', + INTERACTION_FETCH_EPHEMERAL: 'Ephemeral responses cannot be fetched.', + + COMMAND_INTERACTION_OPTION_NOT_FOUND: name => `Required option "${name}" not found.`, + COMMAND_INTERACTION_OPTION_TYPE: (name, type, expected) => + `Option "${name}" is of type: ${type}; expected ${expected}.`, + COMMAND_INTERACTION_OPTION_EMPTY: (name, type) => + `Required option "${name}" is of type: ${type}; expected a non-empty value.`, + COMMAND_INTERACTION_OPTION_NO_SUB_COMMAND: 'No subcommand specified for interaction.', + COMMAND_INTERACTION_OPTION_NO_SUB_COMMAND_GROUP: 'No subcommand group specified for interaction.', + + INVITE_MISSING_SCOPES: 'At least one valid scope must be provided for the invite', + + NOT_IMPLEMENTED: (what, name) => `Method ${what} not implemented on ${name}.`, + + SWEEP_FILTER_RETURN: 'The return value of the sweepFilter function was not false or a Function', }; for (const [name, message] of Object.entries(Messages)) register(name, message); diff --git a/node_modules/discord.js/src/index.js b/node_modules/discord.js/src/index.js index 7319115f..29e2b76d 100644 --- a/node_modules/discord.js/src/index.js +++ b/node_modules/discord.js/src/index.js @@ -1,7 +1,5 @@ 'use strict'; -const Util = require('./util/Util'); - module.exports = { // "Root" classes (starting points) BaseClient: require('./client/BaseClient'), @@ -13,96 +11,140 @@ module.exports = { // Utilities ActivityFlags: require('./util/ActivityFlags'), + ApplicationFlags: require('./util/ApplicationFlags'), + BaseManager: require('./managers/BaseManager'), BitField: require('./util/BitField'), - Collection: require('./util/Collection'), + Collection: require('@discordjs/collection').Collection, Constants: require('./util/Constants'), DataResolver: require('./util/DataResolver'), - BaseManager: require('./managers/BaseManager'), DiscordAPIError: require('./rest/DiscordAPIError'), + Formatters: require('./util/Formatters'), HTTPError: require('./rest/HTTPError'), - MessageFlags: require('./util/MessageFlags'), Intents: require('./util/Intents'), + LimitedCollection: require('./util/LimitedCollection'), + MessageFlags: require('./util/MessageFlags'), + Options: require('./util/Options'), Permissions: require('./util/Permissions'), - Speaking: require('./util/Speaking'), - Snowflake: require('./util/Snowflake'), - SnowflakeUtil: require('./util/Snowflake'), - Structures: require('./util/Structures'), + RateLimitError: require('./rest/RateLimitError'), + SnowflakeUtil: require('./util/SnowflakeUtil'), SystemChannelFlags: require('./util/SystemChannelFlags'), + ThreadMemberFlags: require('./util/ThreadMemberFlags'), UserFlags: require('./util/UserFlags'), - Util: Util, + Util: require('./util/Util'), version: require('../package.json').version, // Managers + ApplicationCommandManager: require('./managers/ApplicationCommandManager'), + ApplicationCommandPermissionsManager: require('./managers/ApplicationCommandPermissionsManager'), + BaseGuildEmojiManager: require('./managers/BaseGuildEmojiManager'), + CachedManager: require('./managers/CachedManager'), ChannelManager: require('./managers/ChannelManager'), + ClientVoiceManager: require('./client/voice/ClientVoiceManager'), + DataManager: require('./managers/DataManager'), + GuildApplicationCommandManager: require('./managers/GuildApplicationCommandManager'), + GuildBanManager: require('./managers/GuildBanManager'), GuildChannelManager: require('./managers/GuildChannelManager'), GuildEmojiManager: require('./managers/GuildEmojiManager'), GuildEmojiRoleManager: require('./managers/GuildEmojiRoleManager'), + GuildInviteManager: require('./managers/GuildInviteManager'), + GuildManager: require('./managers/GuildManager'), GuildMemberManager: require('./managers/GuildMemberManager'), GuildMemberRoleManager: require('./managers/GuildMemberRoleManager'), - GuildManager: require('./managers/GuildManager'), - ReactionManager: require('./managers/ReactionManager'), - ReactionUserManager: require('./managers/ReactionUserManager'), + GuildStickerManager: require('./managers/GuildStickerManager'), MessageManager: require('./managers/MessageManager'), + PermissionOverwriteManager: require('./managers/PermissionOverwriteManager'), PresenceManager: require('./managers/PresenceManager'), + ReactionManager: require('./managers/ReactionManager'), + ReactionUserManager: require('./managers/ReactionUserManager'), RoleManager: require('./managers/RoleManager'), + StageInstanceManager: require('./managers/StageInstanceManager'), + ThreadManager: require('./managers/ThreadManager'), + ThreadMemberManager: require('./managers/ThreadMemberManager'), UserManager: require('./managers/UserManager'), - - // Shortcuts to Util methods - discordSort: Util.discordSort, - escapeMarkdown: Util.escapeMarkdown, - fetchRecommendedShards: Util.fetchRecommendedShards, - resolveColor: Util.resolveColor, - resolveString: Util.resolveString, - splitMessage: Util.splitMessage, + VoiceStateManager: require('./managers/VoiceStateManager'), + WebSocketManager: require('./client/websocket/WebSocketManager'), + WebSocketShard: require('./client/websocket/WebSocketShard'), // Structures + Activity: require('./structures/Presence').Activity, + AnonymousGuild: require('./structures/AnonymousGuild'), Application: require('./structures/interfaces/Application'), + ApplicationCommand: require('./structures/ApplicationCommand'), Base: require('./structures/Base'), - Activity: require('./structures/Presence').Activity, - APIMessage: require('./structures/APIMessage'), + BaseGuild: require('./structures/BaseGuild'), BaseGuildEmoji: require('./structures/BaseGuildEmoji'), + BaseGuildVoiceChannel: require('./structures/BaseGuildVoiceChannel'), + BaseMessageComponent: require('./structures/BaseMessageComponent'), + ButtonInteraction: require('./structures/ButtonInteraction'), CategoryChannel: require('./structures/CategoryChannel'), Channel: require('./structures/Channel'), ClientApplication: require('./structures/ClientApplication'), - get ClientUser() { - // This is a getter so that it properly extends any custom User class - return require('./structures/ClientUser'); - }, + ClientPresence: require('./structures/ClientPresence'), + ClientUser: require('./structures/ClientUser'), Collector: require('./structures/interfaces/Collector'), + CommandInteraction: require('./structures/CommandInteraction'), + CommandInteractionOptionResolver: require('./structures/CommandInteractionOptionResolver'), DMChannel: require('./structures/DMChannel'), Emoji: require('./structures/Emoji'), Guild: require('./structures/Guild'), GuildAuditLogs: require('./structures/GuildAuditLogs'), + GuildAuditLogsEntry: require('./structures/GuildAuditLogs').Entry, + GuildBan: require('./structures/GuildBan'), GuildChannel: require('./structures/GuildChannel'), GuildEmoji: require('./structures/GuildEmoji'), GuildMember: require('./structures/GuildMember'), GuildPreview: require('./structures/GuildPreview'), + GuildPreviewEmoji: require('./structures/GuildPreviewEmoji'), GuildTemplate: require('./structures/GuildTemplate'), Integration: require('./structures/Integration'), + IntegrationApplication: require('./structures/IntegrationApplication'), + Interaction: require('./structures/Interaction'), + InteractionCollector: require('./structures/InteractionCollector'), + InteractionWebhook: require('./structures/InteractionWebhook'), Invite: require('./structures/Invite'), + InviteStageInstance: require('./structures/InviteStageInstance'), + InviteGuild: require('./structures/InviteGuild'), Message: require('./structures/Message'), + MessageActionRow: require('./structures/MessageActionRow'), MessageAttachment: require('./structures/MessageAttachment'), + MessageButton: require('./structures/MessageButton'), MessageCollector: require('./structures/MessageCollector'), + MessageComponentInteraction: require('./structures/MessageComponentInteraction'), MessageEmbed: require('./structures/MessageEmbed'), MessageMentions: require('./structures/MessageMentions'), + MessagePayload: require('./structures/MessagePayload'), MessageReaction: require('./structures/MessageReaction'), + MessageSelectMenu: require('./structures/MessageSelectMenu'), NewsChannel: require('./structures/NewsChannel'), + OAuth2Guild: require('./structures/OAuth2Guild'), + PartialGroupDMChannel: require('./structures/PartialGroupDMChannel'), PermissionOverwrites: require('./structures/PermissionOverwrites'), Presence: require('./structures/Presence').Presence, - ClientPresence: require('./structures/ClientPresence'), ReactionCollector: require('./structures/ReactionCollector'), ReactionEmoji: require('./structures/ReactionEmoji'), RichPresenceAssets: require('./structures/Presence').RichPresenceAssets, Role: require('./structures/Role'), + SelectMenuInteraction: require('./structures/SelectMenuInteraction'), + StageChannel: require('./structures/StageChannel'), + StageInstance: require('./structures/StageInstance'), + Sticker: require('./structures/Sticker'), + StickerPack: require('./structures/StickerPack'), StoreChannel: require('./structures/StoreChannel'), Team: require('./structures/Team'), TeamMember: require('./structures/TeamMember'), TextChannel: require('./structures/TextChannel'), + ThreadChannel: require('./structures/ThreadChannel'), + ThreadMember: require('./structures/ThreadMember'), + Typing: require('./structures/Typing'), User: require('./structures/User'), VoiceChannel: require('./structures/VoiceChannel'), VoiceRegion: require('./structures/VoiceRegion'), VoiceState: require('./structures/VoiceState'), Webhook: require('./structures/Webhook'), + Widget: require('./structures/Widget'), + WidgetMember: require('./structures/WidgetMember'), + WelcomeChannel: require('./structures/WelcomeChannel'), + WelcomeScreen: require('./structures/WelcomeScreen'), WebSocket: require('./WebSocket'), }; diff --git a/node_modules/discord.js/src/managers/BaseManager.js b/node_modules/discord.js/src/managers/BaseManager.js index c11d1910..06514011 100644 --- a/node_modules/discord.js/src/managers/BaseManager.js +++ b/node_modules/discord.js/src/managers/BaseManager.js @@ -1,24 +1,11 @@ 'use strict'; -const Collection = require('../util/Collection'); -let Structures; - /** - * Manages the API methods of a data model and holds its cache. + * Manages the API methods of a data model. * @abstract */ class BaseManager { - constructor(client, iterable, holds, cacheType = Collection, ...cacheOptions) { - if (!Structures) Structures = require('../util/Structures'); - /** - * The data structure belonging to this manager - * @name BaseManager#holds - * @type {Function} - * @private - * @readonly - */ - Object.defineProperty(this, 'holds', { value: Structures.get(holds.name) || holds }); - + constructor(client) { /** * The client that instantiated this Manager * @name BaseManager#client @@ -26,55 +13,6 @@ class BaseManager { * @readonly */ Object.defineProperty(this, 'client', { value: client }); - - /** - * The type of Collection of the Manager - * @type {Collection} - */ - this.cacheType = cacheType; - - /** - * Holds the cache for the data model - * @type {Collection} - */ - this.cache = new cacheType(...cacheOptions); - if (iterable) for (const i of iterable) this.add(i); - } - - add(data, cache = true, { id, extras = [] } = {}) { - const existing = this.cache.get(id || data.id); - if (existing && existing._patch && cache) existing._patch(data); - if (existing) return existing; - - const entry = this.holds ? new this.holds(this.client, data, ...extras) : data; - if (cache) this.cache.set(id || entry.id, entry); - return entry; - } - - /** - * Resolves a data entry to a data Object. - * @param {string|Object} idOrInstance The id or instance of something in this Manager - * @returns {?Object} An instance from this Manager - */ - resolve(idOrInstance) { - if (idOrInstance instanceof this.holds) return idOrInstance; - if (typeof idOrInstance === 'string') return this.cache.get(idOrInstance) || null; - return null; - } - - /** - * Resolves a data entry to a instance ID. - * @param {string|Object} idOrInstance The id or instance of something in this Manager - * @returns {?Snowflake} - */ - resolveID(idOrInstance) { - if (idOrInstance instanceof this.holds) return idOrInstance.id; - if (typeof idOrInstance === 'string') return idOrInstance; - return null; - } - - valueOf() { - return this.cache; } } diff --git a/node_modules/discord.js/src/managers/ChannelManager.js b/node_modules/discord.js/src/managers/ChannelManager.js index 8d7d71e7..357c5af2 100644 --- a/node_modules/discord.js/src/managers/ChannelManager.js +++ b/node_modules/discord.js/src/managers/ChannelManager.js @@ -1,16 +1,16 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const CachedManager = require('./CachedManager'); const Channel = require('../structures/Channel'); -const { Events } = require('../util/Constants'); +const { Events, ThreadChannelTypes } = require('../util/Constants'); /** * A manager of channels belonging to a client - * @extends {BaseManager} + * @extends {CachedManager} */ -class ChannelManager extends BaseManager { +class ChannelManager extends CachedManager { constructor(client, iterable) { - super(client, iterable, Channel); + super(client, Channel, iterable); } /** @@ -19,29 +19,33 @@ class ChannelManager extends BaseManager { * @name ChannelManager#cache */ - add(data, guild, cache = true) { + _add(data, guild, { cache = true, allowUnknownGuild = false, fromInteraction = false } = {}) { const existing = this.cache.get(data.id); if (existing) { - if (existing._patch && cache) existing._patch(data); - if (guild) guild.channels.add(existing); + if (cache) existing._patch(data, fromInteraction); + guild?.channels?._add(existing); + if (ThreadChannelTypes.includes(existing.type)) { + existing.parent?.threads?._add(existing); + } return existing; } - const channel = Channel.create(this.client, data, guild); + const channel = Channel.create(this.client, data, guild, { allowUnknownGuild, fromInteraction }); if (!channel) { this.client.emit(Events.DEBUG, `Failed to find guild, or unknown type for channel ${data.id} ${data.type}`); return null; } - if (cache) this.cache.set(channel.id, channel); + if (cache && !allowUnknownGuild) this.cache.set(channel.id, channel); return channel; } - remove(id) { + _remove(id) { const channel = this.cache.get(id); - if (channel.guild) channel.guild.channels.cache.delete(id); + channel?.guild?.channels.cache.delete(id); + channel?.parent?.threads?.cache.delete(id); this.cache.delete(id); } @@ -62,34 +66,40 @@ class ChannelManager extends BaseManager { */ /** - * Resolves a ChannelResolvable to a channel ID string. - * @method resolveID + * Resolves a ChannelResolvable to a channel id string. + * @method resolveId * @memberof ChannelManager * @instance * @param {ChannelResolvable} channel The channel resolvable to resolve * @returns {?Snowflake} */ + /** + * Options for fetching a channel from discord + * @typedef {BaseFetchOptions} FetchChannelOptions + * @property {boolean} [allowUnknownGuild=false] Allows the channel to be returned even if the guild is not in cache, + * it will not be cached. Many of the properties and methods on the returned channel will throw errors + */ + /** * Obtains a channel from Discord, or the channel cache if it's already available. - * @param {Snowflake} id ID of the channel - * @param {boolean} [cache=true] Whether to cache the new channel object if it isn't already - * @param {boolean} [force=false] Whether to skip the cache check and request the API - * @returns {Promise} + * @param {Snowflake} id The channel's id + * @param {FetchChannelOptions} [options] Additional options for this fetch + * @returns {Promise} * @example * // Fetch a channel by its id * client.channels.fetch('222109930545610754') * .then(channel => console.log(channel.name)) * .catch(console.error); */ - async fetch(id, cache = true, force = false) { + async fetch(id, { allowUnknownGuild = false, cache = true, force = false } = {}) { if (!force) { const existing = this.cache.get(id); if (existing && !existing.partial) return existing; } const data = await this.client.api.channels(id).get(); - return this.add(data, null, cache); + return this._add(data, null, { cache, allowUnknownGuild }); } } diff --git a/node_modules/discord.js/src/managers/GuildChannelManager.js b/node_modules/discord.js/src/managers/GuildChannelManager.js index ab4f1f2d..db02c77f 100644 --- a/node_modules/discord.js/src/managers/GuildChannelManager.js +++ b/node_modules/discord.js/src/managers/GuildChannelManager.js @@ -1,17 +1,21 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const { Collection } = require('@discordjs/collection'); +const CachedManager = require('./CachedManager'); +const ThreadManager = require('./ThreadManager'); +const { Error } = require('../errors'); const GuildChannel = require('../structures/GuildChannel'); const PermissionOverwrites = require('../structures/PermissionOverwrites'); -const { ChannelTypes } = require('../util/Constants'); +const ThreadChannel = require('../structures/ThreadChannel'); +const { ChannelTypes, ThreadChannelTypes } = require('../util/Constants'); /** * Manages API methods for GuildChannels and stores their cache. - * @extends {BaseManager} + * @extends {CachedManager} */ -class GuildChannelManager extends BaseManager { +class GuildChannelManager extends CachedManager { constructor(guild, iterable) { - super(guild.client, iterable, GuildChannel); + super(guild.client, GuildChannel, iterable); /** * The guild this Manager belongs to @@ -20,13 +24,26 @@ class GuildChannelManager extends BaseManager { this.guild = guild; } + /** + * The number of channels in this managers cache excluding thread channels + * that do not count towards a guild's maximum channels restriction. + * @type {number} + * @readonly + */ + get channelCountWithoutThreads() { + return this.cache.reduce((acc, channel) => { + if (ThreadChannelTypes.includes(channel.type)) return acc; + return ++acc; + }, 0); + } + /** * The cache of this Manager - * @type {Collection} + * @type {Collection} * @name GuildChannelManager#cache */ - add(channel) { + _add(channel) { const existing = this.cache.get(channel.id); if (existing) return existing; this.cache.set(channel.id, channel); @@ -36,43 +53,52 @@ class GuildChannelManager extends BaseManager { /** * Data that can be resolved to give a Guild Channel object. This can be: * * A GuildChannel object + * * A ThreadChannel object * * A Snowflake - * @typedef {GuildChannel|Snowflake} GuildChannelResolvable + * @typedef {GuildChannel|ThreadChannel|Snowflake} GuildChannelResolvable */ /** * Resolves a GuildChannelResolvable to a Channel object. - * @method resolve - * @memberof GuildChannelManager - * @instance * @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve - * @returns {?GuildChannel} + * @returns {?(GuildChannel|ThreadChannel)} */ + resolve(channel) { + if (channel instanceof ThreadChannel) return super.resolve(channel.id); + return super.resolve(channel); + } /** - * Resolves a GuildChannelResolvable to a channel ID string. - * @method resolveID - * @memberof GuildChannelManager - * @instance + * Resolves a GuildChannelResolvable to a channel id. * @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve * @returns {?Snowflake} */ + resolveId(channel) { + if (channel instanceof ThreadChannel) return super.resolveId(channel.id); + return super.resolveId(channel); + } + + /** + * Options used to create a new channel in a guild. + * @typedef {Object} GuildChannelCreateOptions + * @property {string|number} [type='GUILD_TEXT'] The type of the new channel, either `GUILD_TEXT`, `GUILD_VOICE`, + * `GUILD_CATEGORY`, `GUILD_NEWS`, `GUILD_STORE`, or `GUILD_STAGE_VOICE` + * @property {string} [topic] The topic for the new channel + * @property {boolean} [nsfw] Whether the new channel is nsfw + * @property {number} [bitrate] Bitrate of the new channel in bits (only voice) + * @property {number} [userLimit] Maximum amount of users allowed in the new channel (only voice) + * @property {CategoryChannelResolvable} [parent] Parent of the new channel + * @property {OverwriteResolvable[]|Collection} [permissionOverwrites] + * Permission overwrites of the new channel + * @property {number} [position] Position of the new channel + * @property {number} [rateLimitPerUser] The ratelimit per user for the new channel + * @property {string} [reason] Reason for creating the new channel + */ /** * Creates a new channel in the guild. * @param {string} name The name of the new channel - * @param {Object} [options] Options - * @param {string} [options.type='text'] The type of the new channel, either `text`, `voice`, or `category` - * @param {string} [options.topic] The topic for the new channel - * @param {boolean} [options.nsfw] Whether the new channel is nsfw - * @param {number} [options.bitrate] Bitrate of the new channel in bits (only voice) - * @param {number} [options.userLimit] Maximum amount of users allowed in the new channel (only voice) - * @param {ChannelResolvable} [options.parent] Parent of the new channel - * @param {OverwriteResolvable[]|Collection} [options.permissionOverwrites] - * Permission overwrites of the new channel - * @param {number} [options.position] Position of the new channel - * @param {number} [options.rateLimitPerUser] The ratelimit per user for the channel - * @param {string} [options.reason] Reason for creating the channel + * @param {GuildChannelCreateOptions} [options={}] Options for creating the new channel * @returns {Promise} * @example * // Create a new text channel @@ -82,29 +108,20 @@ class GuildChannelManager extends BaseManager { * @example * // Create a new channel with permission overwrites * guild.channels.create('new-voice', { - * type: 'voice', + * type: 'GUILD_VOICE', * permissionOverwrites: [ * { * id: message.author.id, - * deny: ['VIEW_CHANNEL'], + * deny: [Permissions.FLAGS.VIEW_CHANNEL], * }, * ], * }) */ - async create(name, options = {}) { - let { - type, - topic, - nsfw, - bitrate, - userLimit, - parent, - permissionOverwrites, - position, - rateLimitPerUser, - reason, - } = options; - if (parent) parent = this.client.channels.resolveID(parent); + async create( + name, + { type, topic, nsfw, bitrate, userLimit, parent, permissionOverwrites, position, rateLimitPerUser, reason } = {}, + ) { + if (parent) parent = this.client.channels.resolveId(parent); if (permissionOverwrites) { permissionOverwrites = permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild)); } @@ -113,7 +130,7 @@ class GuildChannelManager extends BaseManager { data: { name, topic, - type: type ? ChannelTypes[type.toUpperCase()] : ChannelTypes.TEXT, + type: typeof type === 'number' ? type : ChannelTypes[type] ?? ChannelTypes.GUILD_TEXT, nsfw, bitrate, user_limit: userLimit, @@ -126,6 +143,61 @@ class GuildChannelManager extends BaseManager { }); return this.client.actions.ChannelCreate.handle(data).channel; } + + /** + * Obtains one or more guild channels from Discord, or the channel cache if they're already available. + * @param {Snowflake} [id] The channel's id + * @param {BaseFetchOptions} [options] Additional options for this fetch + * @returns {Promise>} + * @example + * // Fetch all channels from the guild (excluding threads) + * message.guild.channels.fetch() + * .then(channels => console.log(`There are ${channels.size} channels.`)) + * .catch(console.error); + * @example + * // Fetch a single channel + * message.guild.channels.fetch('222197033908436994') + * .then(channel => console.log(`The channel name is: ${channel.name}`)) + * .catch(console.error); + */ + async fetch(id, { cache = true, force = false } = {}) { + if (id && !force) { + const existing = this.cache.get(id); + if (existing) return existing; + } + + if (id) { + const data = await this.client.api.channels(id).get(); + // Since this is the guild manager, throw if on a different guild + if (this.guild.id !== data.guild_id) throw new Error('GUILD_CHANNEL_UNOWNED'); + return this.client.channels._add(data, this.guild, { cache }); + } + + const data = await this.client.api.guilds(this.guild.id).channels.get(); + const channels = new Collection(); + for (const channel of data) channels.set(channel.id, this.client.channels._add(channel, this.guild, { cache })); + return channels; + } + + /** + * Obtains all active thread channels in the guild from Discord + * @param {boolean} [cache=true] Whether to cache the fetched data + * @returns {Promise} + * @example + * // Fetch all threads from the guild + * message.guild.channels.fetchActiveThreads() + * .then(fetched => console.log(`There are ${fetched.threads.size} threads.`)) + * .catch(console.error); + */ + async fetchActiveThreads(cache = true) { + const raw = await this.client.api.guilds(this.guild.id).threads.active.get(); + return ThreadManager._mapThreads(raw, this.client, { guild: this.guild, cache }); + } } module.exports = GuildChannelManager; + +/** + * @external APIActiveThreadsList + * @see {@link https://discord.com/developers/docs/resources/guild#list-active-threads-response-body} + */ diff --git a/node_modules/discord.js/src/managers/GuildEmojiManager.js b/node_modules/discord.js/src/managers/GuildEmojiManager.js index acf3576e..6be10c72 100644 --- a/node_modules/discord.js/src/managers/GuildEmojiManager.js +++ b/node_modules/discord.js/src/managers/GuildEmojiManager.js @@ -1,20 +1,18 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const { Collection } = require('@discordjs/collection'); +const BaseGuildEmojiManager = require('./BaseGuildEmojiManager'); const { TypeError } = require('../errors'); -const GuildEmoji = require('../structures/GuildEmoji'); -const ReactionEmoji = require('../structures/ReactionEmoji'); -const Collection = require('../util/Collection'); const DataResolver = require('../util/DataResolver'); -const { parseEmoji } = require('../util/Util'); /** * Manages API methods for GuildEmojis and stores their cache. - * @extends {BaseManager} + * @extends {BaseGuildEmojiManager} */ -class GuildEmojiManager extends BaseManager { +class GuildEmojiManager extends BaseGuildEmojiManager { constructor(guild, iterable) { - super(guild.client, iterable, GuildEmoji); + super(guild.client, iterable); + /** * The guild this manager belongs to * @type {Guild} @@ -22,23 +20,22 @@ class GuildEmojiManager extends BaseManager { this.guild = guild; } + _add(data, cache) { + return super._add(data, cache, { extras: [this.guild] }); + } + /** - * The cache of GuildEmojis - * @type {Collection} - * @name GuildEmojiManager#cache + * Options used for creating an emoji in a guild. + * @typedef {Object} GuildEmojiCreateOptions + * @property {Collection|RoleResolvable[]} [roles] The roles to limit the emoji to + * @property {string} [reason] The reason for creating the emoji */ - add(data, cache) { - return super.add(data, cache, { extras: [this.guild] }); - } - /** * Creates a new custom emoji in the guild. * @param {BufferResolvable|Base64Resolvable} attachment The image for the emoji * @param {string} name The name for the emoji - * @param {Object} [options] Options - * @param {Collection|RoleResolvable[]} [options.roles] Roles to limit the emoji to - * @param {string} [options.reason] Reason for creating the emoji + * @param {GuildEmojiCreateOptions} [options] Options for creating the emoji * @returns {Promise} The created emoji * @example * // Create a new emoji from a url @@ -57,15 +54,14 @@ class GuildEmojiManager extends BaseManager { const data = { image: attachment, name }; if (roles) { + if (!Array.isArray(roles) && !(roles instanceof Collection)) { + throw new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true); + } data.roles = []; - for (let role of roles instanceof Collection ? roles.values() : roles) { - role = this.guild.roles.resolve(role); - if (!role) { - return Promise.reject( - new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true), - ); - } - data.roles.push(role.id); + for (const role of roles.values()) { + const resolvedRole = this.guild.roles.resolveId(role); + if (!resolvedRole) throw new TypeError('INVALID_ELEMENT', 'Array or Collection', 'options.roles', role); + data.roles.push(resolvedRole); } } @@ -76,59 +72,35 @@ class GuildEmojiManager extends BaseManager { } /** - * Data that can be resolved into an GuildEmoji object. This can be: - * * A custom emoji ID - * * A GuildEmoji object - * * A ReactionEmoji object - * @typedef {Snowflake|GuildEmoji|ReactionEmoji} EmojiResolvable - */ - - /** - * Resolves an EmojiResolvable to an Emoji object. - * @param {EmojiResolvable} emoji The Emoji resolvable to identify - * @returns {?GuildEmoji} - */ - resolve(emoji) { - if (emoji instanceof ReactionEmoji) return super.resolve(emoji.id); - return super.resolve(emoji); - } - - /** - * Resolves an EmojiResolvable to an Emoji ID string. - * @param {EmojiResolvable} emoji The Emoji resolvable to identify - * @returns {?Snowflake} - */ - resolveID(emoji) { - if (emoji instanceof ReactionEmoji) return emoji.id; - return super.resolveID(emoji); - } - - /** - * Data that can be resolved to give an emoji identifier. This can be: - * * The unicode representation of an emoji - * * The ``, `<:name:id>`, `:name:id` or `a:name:id` emoji identifier string of an emoji - * * An EmojiResolvable - * @typedef {string|EmojiResolvable} EmojiIdentifierResolvable - */ - - /** - * Resolves an EmojiResolvable to an emoji identifier. - * @param {EmojiIdentifierResolvable} emoji The emoji resolvable to resolve - * @returns {?string} + * Obtains one or more emojis from Discord, or the emoji cache if they're already available. + * @param {Snowflake} [id] The emoji's id + * @param {BaseFetchOptions} [options] Additional options for this fetch + * @returns {Promise>} + * @example + * // Fetch all emojis from the guild + * message.guild.emojis.fetch() + * .then(emojis => console.log(`There are ${emojis.size} emojis.`)) + * .catch(console.error); + * @example + * // Fetch a single emoji + * message.guild.emojis.fetch('222078108977594368') + * .then(emoji => console.log(`The emoji name is: ${emoji.name}`)) + * .catch(console.error); */ - resolveIdentifier(emoji) { - const emojiResolvable = this.resolve(emoji); - if (emojiResolvable) return emojiResolvable.identifier; - if (emoji instanceof ReactionEmoji) return emoji.identifier; - if (typeof emoji === 'string') { - const res = parseEmoji(emoji); - if (res && res.name.length) { - emoji = `${res.animated ? 'a:' : ''}${res.name}${res.id ? `:${res.id}` : ''}`; + async fetch(id, { cache = true, force = false } = {}) { + if (id) { + if (!force) { + const existing = this.cache.get(id); + if (existing) return existing; } - if (!emoji.includes('%')) return encodeURIComponent(emoji); - else return emoji; + const emoji = await this.client.api.guilds(this.guild.id).emojis(id).get(); + return this._add(emoji, cache); } - return null; + + const data = await this.client.api.guilds(this.guild.id).emojis.get(); + const emojis = new Collection(); + for (const emoji of data) emojis.set(emoji.id, this._add(emoji, cache)); + return emojis; } } diff --git a/node_modules/discord.js/src/managers/GuildEmojiRoleManager.js b/node_modules/discord.js/src/managers/GuildEmojiRoleManager.js index 038571fc..93748574 100644 --- a/node_modules/discord.js/src/managers/GuildEmojiRoleManager.js +++ b/node_modules/discord.js/src/managers/GuildEmojiRoleManager.js @@ -1,13 +1,18 @@ 'use strict'; +const { Collection } = require('@discordjs/collection'); +const DataManager = require('./DataManager'); const { TypeError } = require('../errors'); -const Collection = require('../util/Collection'); +const Role = require('../structures/Role'); /** * Manages API methods for roles belonging to emojis and stores their cache. + * @extends {DataManager} */ -class GuildEmojiRoleManager { +class GuildEmojiRoleManager extends DataManager { constructor(emoji) { + super(emoji.client, Role); + /** * The emoji belonging to this manager * @type {GuildEmoji} @@ -18,22 +23,6 @@ class GuildEmojiRoleManager { * @type {Guild} */ this.guild = emoji.guild; - /** - * The client belonging to this manager - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: emoji.client }); - } - - /** - * The filtered collection of roles of the guild emoji - * @type {Collection} - * @private - * @readonly - */ - get _roles() { - return this.guild.roles.cache.filter(role => this.emoji._roles.includes(role.id)); } /** @@ -42,7 +31,7 @@ class GuildEmojiRoleManager { * @readonly */ get cache() { - return this._roles; + return this.guild.roles.cache.filter(role => this.emoji._roles.includes(role.id)); } /** @@ -51,15 +40,18 @@ class GuildEmojiRoleManager { * @returns {Promise} */ add(roleOrRoles) { - if (roleOrRoles instanceof Collection) return this.add(roleOrRoles.keyArray()); - if (!Array.isArray(roleOrRoles)) return this.add([roleOrRoles]); - roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r)); + if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles]; - if (roleOrRoles.includes(null)) { - return Promise.reject(new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true)); + const resolvedRoles = []; + for (const role of roleOrRoles.values()) { + const resolvedRole = this.guild.roles.resolveId(role); + if (!resolvedRole) { + return Promise.reject(new TypeError('INVALID_ELEMENT', 'Array or Collection', 'roles', role)); + } + resolvedRoles.push(resolvedRole); } - const newRoles = [...new Set(roleOrRoles.concat(...this._roles.values()))]; + const newRoles = [...new Set(resolvedRoles.concat(...this.cache.values()))]; return this.set(newRoles); } @@ -69,21 +61,24 @@ class GuildEmojiRoleManager { * @returns {Promise} */ remove(roleOrRoles) { - if (roleOrRoles instanceof Collection) return this.remove(roleOrRoles.keyArray()); - if (!Array.isArray(roleOrRoles)) return this.remove([roleOrRoles]); - roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolveID(r)); + if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles]; - if (roleOrRoles.includes(null)) { - return Promise.reject(new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true)); + const resolvedRoleIds = []; + for (const role of roleOrRoles.values()) { + const roleId = this.guild.roles.resolveId(role); + if (!roleId) { + return Promise.reject(new TypeError('INVALID_ELEMENT', 'Array or Collection', 'roles', role)); + } + resolvedRoleIds.push(roleId); } - const newRoles = this._roles.keyArray().filter(role => !roleOrRoles.includes(role)); + const newRoles = [...this.cache.keys()].filter(id => !resolvedRoleIds.includes(id)); return this.set(newRoles); } /** * Sets the role(s) that can use this emoji. - * @param {Collection|RoleResolvable[]} roles The roles or role IDs to apply + * @param {Collection|RoleResolvable[]} roles The roles or role ids to apply * @returns {Promise} * @example * // Set the emoji's roles to a single role @@ -102,7 +97,7 @@ class GuildEmojiRoleManager { clone() { const clone = new this.constructor(this.emoji); - clone._patch(this._roles.keyArray().slice()); + clone._patch([...this.cache.keys()]); return clone; } @@ -114,6 +109,10 @@ class GuildEmojiRoleManager { _patch(roles) { this.emoji._roles = roles; } + + valueOf() { + return this.cache; + } } module.exports = GuildEmojiRoleManager; diff --git a/node_modules/discord.js/src/managers/GuildManager.js b/node_modules/discord.js/src/managers/GuildManager.js index b04a52c1..7d8535da 100644 --- a/node_modules/discord.js/src/managers/GuildManager.js +++ b/node_modules/discord.js/src/managers/GuildManager.js @@ -1,30 +1,33 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const { Collection } = require('@discordjs/collection'); +const CachedManager = require('./CachedManager'); const Guild = require('../structures/Guild'); const GuildChannel = require('../structures/GuildChannel'); const GuildEmoji = require('../structures/GuildEmoji'); const GuildMember = require('../structures/GuildMember'); const Invite = require('../structures/Invite'); +const OAuth2Guild = require('../structures/OAuth2Guild'); const Role = require('../structures/Role'); const { ChannelTypes, Events, VerificationLevels, - DefaultMessageNotifications, + DefaultMessageNotificationLevels, ExplicitContentFilterLevels, } = require('../util/Constants'); const DataResolver = require('../util/DataResolver'); const Permissions = require('../util/Permissions'); +const SystemChannelFlags = require('../util/SystemChannelFlags'); const { resolveColor } = require('../util/Util'); /** * Manages API methods for Guilds and stores their cache. - * @extends {BaseManager} + * @extends {CachedManager} */ -class GuildManager extends BaseManager { +class GuildManager extends CachedManager { constructor(client, iterable) { - super(client, iterable, Guild); + super(client, Guild, iterable); } /** @@ -47,20 +50,20 @@ class GuildManager extends BaseManager { /** * Partial data for a Role. * @typedef {Object} PartialRoleData - * @property {number} [id] The ID for this role, used to set channel overrides, + * @property {Snowflake|number} [id] The role's id, used to set channel overrides, * this is a placeholder and will be replaced by the API after consumption * @property {string} [name] The name of the role * @property {ColorResolvable} [color] The color of the role, either a hex string or a base 10 number * @property {boolean} [hoist] Whether or not the role should be hoisted * @property {number} [position] The position of the role - * @property {PermissionResolvable|number} [permissions] The permissions of the role + * @property {PermissionResolvable} [permissions] The permissions of the role * @property {boolean} [mentionable] Whether or not the role should be mentionable */ /** * Partial overwrite data. * @typedef {Object} PartialOverwriteData - * @property {number|Snowflake} id The Role or User ID for this overwrite + * @property {Snowflake|number} id The {@link Role} or {@link User} id for this overwrite * @property {string} [type] The type of this overwrite * @property {PermissionResolvable} [allow] The permissions to allow * @property {PermissionResolvable} [deny] The permissions to deny @@ -69,16 +72,16 @@ class GuildManager extends BaseManager { /** * Partial data for a Channel. * @typedef {Object} PartialChannelData - * @property {number} [id] The ID for this channel, used to set its parent, + * @property {Snowflake|number} [id] The channel's id, used to set its parent, * this is a placeholder and will be replaced by the API after consumption - * @property {number} [parentID] The parent ID for this channel - * @property {string} [type] The type of the channel + * @property {Snowflake|number} [parentId] The parent id for this channel + * @property {ChannelType} [type] The type of the channel * @property {string} name The name of the channel * @property {string} [topic] The topic of the text channel * @property {boolean} [nsfw] Whether the channel is NSFW * @property {number} [bitrate] The bitrate of the voice channel * @property {number} [userLimit] The user limit of the channel - * @property {PartialOverwriteData} [permissionOverwrites] + * @property {PartialOverwriteData[]} [permissionOverwrites] * Overwrites of the channel * @property {number} [rateLimitPerUser] The rate limit per user of the channel in seconds */ @@ -105,14 +108,14 @@ class GuildManager extends BaseManager { } /** - * Resolves a GuildResolvable to a Guild ID string. - * @method resolveID + * Resolves a {@link GuildResolvable} to a {@link Guild} id string. + * @method resolveId * @memberof GuildManager * @instance * @param {GuildResolvable} guild The guild resolvable to identify * @returns {?Snowflake} */ - resolveID(guild) { + resolveId(guild) { if ( guild instanceof GuildChannel || guild instanceof GuildMember || @@ -120,86 +123,93 @@ class GuildManager extends BaseManager { guild instanceof Role || (guild instanceof Invite && guild.guild) ) { - return super.resolveID(guild.guild.id); + return super.resolveId(guild.guild.id); } - return super.resolveID(guild); + return super.resolveId(guild); } + /** + * Options used to create a guild. + * @typedef {Object} GuildCreateOptions + * @property {Snowflake|number} [afkChannelId] The AFK channel's id + * @property {number} [afkTimeout] The AFK timeout in seconds + * @property {PartialChannelData[]} [channels=[]] The channels for this guild + * @property {DefaultMessageNotificationLevel|number} [defaultMessageNotifications] The default message notifications + * for the guild + * @property {ExplicitContentFilterLevel} [explicitContentFilter] The explicit content filter level for the guild + * @property {BufferResolvable|Base64Resolvable} [icon=null] The icon for the guild + * @property {PartialRoleData[]} [roles=[]] The roles for this guild, + * the first element of this array is used to change properties of the guild's everyone role. + * @property {Snowflake|number} [systemChannelId] The system channel's id + * @property {SystemChannelFlagsResolvable} [systemChannelFlags] The flags of the system channel + * @property {VerificationLevel} [verificationLevel] The verification level for the guild + */ + /** * Creates a guild. * This is only available to bots in fewer than 10 guilds. * @param {string} name The name of the guild - * @param {Object} [options] Options for the creating - * @param {number} [options.afkChannelID] The ID of the AFK channel - * @param {number} [options.afkTimeout] The AFK timeout in seconds - * @param {PartialChannelData[]} [options.channels] The channels for this guild - * @param {DefaultMessageNotifications} [options.defaultMessageNotifications] The default message notifications - * for the guild - * @param {ExplicitContentFilterLevel} [options.explicitContentFilter] The explicit content filter level for the guild - * @param {BufferResolvable|Base64Resolvable} [options.icon=null] The icon for the guild - * @param {string} [options.region] The region for the server, defaults to the closest one available - * @param {PartialRoleData[]} [options.roles] The roles for this guild, - * the first element of this array is used to change properties of the guild's everyone role. - * @param {number} [options.systemChannelID] The ID of the system channel - * @param {VerificationLevel} [options.verificationLevel] The verification level for the guild + * @param {GuildCreateOptions} [options] Options for creating the guild * @returns {Promise} The guild that was created */ async create( name, { - afkChannelID, + afkChannelId, afkTimeout, channels = [], defaultMessageNotifications, explicitContentFilter, icon = null, - region, roles = [], - systemChannelID, + systemChannelId, + systemChannelFlags, verificationLevel, } = {}, ) { icon = await DataResolver.resolveImage(icon); - if (typeof verificationLevel !== 'undefined' && typeof verificationLevel !== 'number') { - verificationLevel = VerificationLevels.indexOf(verificationLevel); + if (typeof verificationLevel === 'string') { + verificationLevel = VerificationLevels[verificationLevel]; } - if (typeof defaultMessageNotifications !== 'undefined' && typeof defaultMessageNotifications !== 'number') { - defaultMessageNotifications = DefaultMessageNotifications.indexOf(defaultMessageNotifications); + if (typeof defaultMessageNotifications === 'string') { + defaultMessageNotifications = DefaultMessageNotificationLevels[defaultMessageNotifications]; } - if (typeof explicitContentFilter !== 'undefined' && typeof explicitContentFilter !== 'number') { - explicitContentFilter = ExplicitContentFilterLevels.indexOf(explicitContentFilter); + if (typeof explicitContentFilter === 'string') { + explicitContentFilter = ExplicitContentFilterLevels[explicitContentFilter]; } for (const channel of channels) { if (channel.type) channel.type = ChannelTypes[channel.type.toUpperCase()]; - channel.parent_id = channel.parentID; - delete channel.parentID; + channel.parent_id = channel.parentId; + delete channel.parentId; if (!channel.permissionOverwrites) continue; for (const overwrite of channel.permissionOverwrites) { - if (overwrite.allow) overwrite.allow = Permissions.resolve(overwrite.allow); - if (overwrite.deny) overwrite.deny = Permissions.resolve(overwrite.deny); + if (overwrite.allow) overwrite.allow = Permissions.resolve(overwrite.allow).toString(); + if (overwrite.deny) overwrite.deny = Permissions.resolve(overwrite.deny).toString(); } channel.permission_overwrites = channel.permissionOverwrites; delete channel.permissionOverwrites; } for (const role of roles) { if (role.color) role.color = resolveColor(role.color); - if (role.permissions) role.permissions = Permissions.resolve(role.permissions); + if (role.permissions) role.permissions = Permissions.resolve(role.permissions).toString(); } + if (systemChannelFlags) systemChannelFlags = SystemChannelFlags.resolve(systemChannelFlags); + return new Promise((resolve, reject) => this.client.api.guilds .post({ data: { name, - region, icon, verification_level: verificationLevel, default_message_notifications: defaultMessageNotifications, explicit_content_filter: explicitContentFilter, roles, channels, - afk_channel_id: afkChannelID, + afk_channel_id: afkChannelId, afk_timeout: afkTimeout, - system_channel_id: systemChannelID, + system_channel_id: systemChannelId, + system_channel_flags: systemChannelFlags, }, }) .then(data => { @@ -207,7 +217,7 @@ class GuildManager extends BaseManager { const handleGuild = guild => { if (guild.id === data.id) { - this.client.clearTimeout(timeout); + clearTimeout(timeout); this.client.removeListener(Events.GUILD_CREATE, handleGuild); this.client.decrementMaxListeners(); resolve(guild); @@ -216,36 +226,50 @@ class GuildManager extends BaseManager { this.client.incrementMaxListeners(); this.client.on(Events.GUILD_CREATE, handleGuild); - const timeout = this.client.setTimeout(() => { + const timeout = setTimeout(() => { this.client.removeListener(Events.GUILD_CREATE, handleGuild); this.client.decrementMaxListeners(); - resolve(this.client.guilds.add(data)); - }, 10000); + resolve(this.client.guilds._add(data)); + }, 10000).unref(); return undefined; }, reject), ); } /** - * Obtains a guild from Discord, or the guild cache if it's already available. - * @param {Snowflake} id ID of the guild - * @param {boolean} [cache=true] Whether to cache the new guild object if it isn't already - * @param {boolean} [force=false] Whether to skip the cache check and request the API - * @returns {Promise} - * @example - * // Fetch a guild by its id - * client.guilds.fetch('222078108977594368') - * .then(guild => console.log(guild.name)) - * .catch(console.error); + * Options used to fetch a single guild. + * @typedef {BaseFetchOptions} FetchGuildOptions + * @property {GuildResolvable} guild The guild to fetch */ - async fetch(id, cache = true, force = false) { - if (!force) { - const existing = this.cache.get(id); - if (existing) return existing; + + /** + * Options used to fetch multiple guilds. + * @typedef {Object} FetchGuildsOptions + * @property {Snowflake} [before] Get guilds before this guild id + * @property {Snowflake} [after] Get guilds after this guild id + * @property {number} [limit=100] Maximum number of guilds to request (1-100) + */ + + /** + * Obtains one or multiple guilds from Discord, or the guild cache if it's already available. + * @param {GuildResolvable|FetchGuildOptions|FetchGuildsOptions} [options] The guild's id or options + * @returns {Promise>} + */ + async fetch(options = {}) { + const id = this.resolveId(options) ?? this.resolveId(options.guild); + + if (id) { + if (!options.force) { + const existing = this.cache.get(id); + if (existing) return existing; + } + + const data = await this.client.api.guilds(id).get({ query: { with_counts: true } }); + return this._add(data, options.cache); } - const data = await this.client.api.guilds(id).get({ query: { with_counts: true } }); - return this.add(data, cache); + const data = await this.client.api.users('@me').guilds.get({ query: options }); + return data.reduce((coll, guild) => coll.set(guild.id, new OAuth2Guild(this.client, guild)), new Collection()); } } diff --git a/node_modules/discord.js/src/managers/GuildMemberManager.js b/node_modules/discord.js/src/managers/GuildMemberManager.js index 8dfa2d8e..defced96 100644 --- a/node_modules/discord.js/src/managers/GuildMemberManager.js +++ b/node_modules/discord.js/src/managers/GuildMemberManager.js @@ -1,19 +1,22 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const { Collection } = require('@discordjs/collection'); +const CachedManager = require('./CachedManager'); const { Error, TypeError, RangeError } = require('../errors'); +const BaseGuildVoiceChannel = require('../structures/BaseGuildVoiceChannel'); const GuildMember = require('../structures/GuildMember'); -const Collection = require('../util/Collection'); -const { Events, OPCodes } = require('../util/Constants'); -const SnowflakeUtil = require('../util/Snowflake'); +const Role = require('../structures/Role'); +const { Events, Opcodes } = require('../util/Constants'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); /** * Manages API methods for GuildMembers and stores their cache. - * @extends {BaseManager} + * @extends {CachedManager} */ -class GuildMemberManager extends BaseManager { +class GuildMemberManager extends CachedManager { constructor(guild, iterable) { - super(guild.client, iterable, GuildMember); + super(guild.client, GuildMember, iterable); + /** * The guild this manager belongs to * @type {Guild} @@ -27,8 +30,8 @@ class GuildMemberManager extends BaseManager { * @name GuildMemberManager#cache */ - add(data, cache = true) { - return super.add(data, cache, { id: data.user.id, extras: [this.guild] }); + _add(data, cache = true) { + return super._add(data, cache, { id: data.user.id, extras: [this.guild] }); } /** @@ -39,36 +42,84 @@ class GuildMemberManager extends BaseManager { */ /** - * Resolves a GuildMemberResolvable to a GuildMember object. + * Resolves a {@link GuildMemberResolvable} to a {@link GuildMember} object. * @param {GuildMemberResolvable} member The user that is part of the guild * @returns {?GuildMember} */ resolve(member) { const memberResolvable = super.resolve(member); if (memberResolvable) return memberResolvable; - const userResolvable = this.client.users.resolveID(member); + const userResolvable = this.client.users.resolveId(member); if (userResolvable) return super.resolve(userResolvable); return null; } /** - * Resolves a GuildMemberResolvable to a member ID string. + * Resolves a {@link GuildMemberResolvable} to a member id. * @param {GuildMemberResolvable} member The user that is part of the guild * @returns {?Snowflake} */ - resolveID(member) { - const memberResolvable = super.resolveID(member); + resolveId(member) { + const memberResolvable = super.resolveId(member); if (memberResolvable) return memberResolvable; - const userResolvable = this.client.users.resolveID(member); + const userResolvable = this.client.users.resolveId(member); return this.cache.has(userResolvable) ? userResolvable : null; } + /** + * Options used to add a user to a guild using OAuth2. + * @typedef {Object} AddGuildMemberOptions + * @property {string} accessToken An OAuth2 access token for the user with the `guilds.join` scope granted to the + * bot's application + * @property {string} [nick] The nickname to give to the member (requires `MANAGE_NICKNAMES`) + * @property {Collection|RoleResolvable[]} [roles] The roles to add to the member + * (requires `MANAGE_ROLES`) + * @property {boolean} [mute] Whether the member should be muted (requires `MUTE_MEMBERS`) + * @property {boolean} [deaf] Whether the member should be deafened (requires `DEAFEN_MEMBERS`) + * @property {boolean} [force] Whehter to skip the cache check and call the API directly + * @property {boolean} [fetchWhenExisting=true] Whether to fetch the user if not cached and already a member + */ + + /** + * Adds a user to the guild using OAuth2. Requires the `CREATE_INSTANT_INVITE` permission. + * @param {UserResolvable} user The user to add to the guild + * @param {AddGuildMemberOptions} options Options for adding the user to the guild + * @returns {Promise} + */ + async add(user, options) { + const userId = this.client.users.resolveId(user); + if (!userId) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable'); + if (!options.force) { + const cachedUser = this.cache.get(userId); + if (cachedUser) return cachedUser; + } + const resolvedOptions = { + access_token: options.accessToken, + nick: options.nick, + mute: options.mute, + deaf: options.deaf, + }; + if (options.roles) { + if (!Array.isArray(options.roles) && !(options.roles instanceof Collection)) { + throw new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true); + } + const resolvedRoles = []; + for (const role of options.roles.values()) { + const resolvedRole = this.guild.roles.resolveId(role); + if (!resolvedRole) throw new TypeError('INVALID_ELEMENT', 'Array or Collection', 'options.roles', role); + resolvedRoles.push(resolvedRole); + } + resolvedOptions.roles = resolvedRoles; + } + const data = await this.client.api.guilds(this.guild.id).members(userId).put({ data: resolvedOptions }); + // Data is an empty buffer if the member is already part of the guild. + return data instanceof Buffer ? (options.fetchWhenExisting === false ? null : this.fetch(userId)) : this._add(data); + } + /** * Options used to fetch a single member from a guild. - * @typedef {Object} FetchMemberOptions + * @typedef {BaseFetchOptions} FetchMemberOptions * @property {UserResolvable} user The user to fetch - * @property {boolean} [cache=true] Whether or not to cache the fetched member - * @property {boolean} [force=false] Whether to skip the cache check and request the API */ /** @@ -122,29 +173,93 @@ class GuildMemberManager extends BaseManager { */ fetch(options) { if (!options) return this._fetchMany(); - const user = this.client.users.resolveID(options); + const user = this.client.users.resolveId(options); if (user) return this._fetchSingle({ user, cache: true }); if (options.user) { if (Array.isArray(options.user)) { - options.user = options.user.map(u => this.client.users.resolveID(u)); + options.user = options.user.map(u => this.client.users.resolveId(u)); return this._fetchMany(options); } else { - options.user = this.client.users.resolveID(options.user); + options.user = this.client.users.resolveId(options.user); } if (!options.limit && !options.withPresences) return this._fetchSingle(options); } return this._fetchMany(options); } + /** + * Options used for searching guild members. + * @typedef {Object} GuildSearchMembersOptions + * @property {string} query Filter members whose username or nickname start with this query + * @property {number} [limit=1] Maximum number of members to search + * @property {boolean} [cache=true] Whether or not to cache the fetched member(s) + */ + + /** + * Searches for members in the guild based on a query. + * @param {GuildSearchMembersOptions} options Options for searching members + * @returns {Promise>} + */ + async search({ query, limit = 1, cache = true } = {}) { + const data = await this.client.api.guilds(this.guild.id).members.search.get({ query: { query, limit } }); + return data.reduce((col, member) => col.set(member.user.id, this._add(member, cache)), new Collection()); + } + + /** + * Edits a member of the guild. + * The user must be a member of the guild + * @param {UserResolvable} user The member to edit + * @param {GuildMemberEditData} data The data to edit the member with + * @param {string} [reason] Reason for editing this user + * @returns {Promise} + */ + async edit(user, data, reason) { + const id = this.client.users.resolveId(user); + if (!id) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable'); + + // Clone the data object for immutability + const _data = { ...data }; + if (_data.channel) { + _data.channel = this.guild.channels.resolve(_data.channel); + if (!(_data.channel instanceof BaseGuildVoiceChannel)) { + throw new Error('GUILD_VOICE_CHANNEL_RESOLVE'); + } + _data.channel_id = _data.channel.id; + _data.channel = undefined; + } else if (_data.channel === null) { + _data.channel_id = null; + _data.channel = undefined; + } + if (_data.roles) _data.roles = _data.roles.map(role => (role instanceof Role ? role.id : role)); + let endpoint = this.client.api.guilds(this.guild.id); + if (id === this.client.user.id) { + const keys = Object.keys(_data); + if (keys.length === 1 && keys[0] === 'nick') endpoint = endpoint.members('@me').nick; + else endpoint = endpoint.members(id); + } else { + endpoint = endpoint.members(id); + } + const d = await endpoint.patch({ data: _data, reason }); + + const clone = this.cache.get(id)?._clone(); + clone?._patch(d); + return clone ?? this._add(d, false); + } + + /** + * Options used for pruning guild members. + * @typedef {Object} GuildPruneMembersOptions + * @property {number} [days=7] Number of days of inactivity required to kick + * @property {boolean} [dry=false] Get the number of users that will be kicked, without actually kicking them + * @property {boolean} [count=true] Whether or not to return the number of users that have been kicked. + * @property {RoleResolvable[]} [roles] Array of roles to bypass the "...and no roles" constraint when pruning + * @property {string} [reason] Reason for this prune + */ + /** * Prunes members from the guild based on how long they have been inactive. - * It's recommended to set options.count to `false` for large guilds. - * @param {Object} [options] Prune options - * @param {number} [options.days=7] Number of days of inactivity required to kick - * @param {boolean} [options.dry=false] Get number of users that will be kicked, without actually kicking them - * @param {boolean} [options.count=true] Whether or not to return the number of users that have been kicked. - * @param {RoleResolvable[]} [options.roles=[]] Array of roles to bypass the "...and no roles" constraint when pruning - * @param {string} [options.reason] Reason for this prune + * It's recommended to set `options.count` to `false` for large guilds. + * @param {GuildPruneMembersOptions} [options] Options for pruning * @returns {Promise} The number of members that were/will be kicked * @example * // See how many members will be pruned @@ -163,15 +278,15 @@ class GuildMemberManager extends BaseManager { * .catch(console.error); */ prune({ days = 7, dry = false, count: compute_prune_count = true, roles = [], reason } = {}) { - if (typeof days !== 'number') throw new TypeError('PRUNE_DAYS_TYPE'); + if (typeof days !== 'number') return Promise.reject(new TypeError('PRUNE_DAYS_TYPE')); const query = { days }; const resolvedRoles = []; for (const role of roles) { - const resolvedRole = this.guild.roles.resolveID(role); + const resolvedRole = this.guild.roles.resolveId(role); if (!resolvedRole) { - return Promise.reject(new TypeError('INVALID_TYPE', 'roles', 'Array of Roles or Snowflakes', true)); + return Promise.reject(new TypeError('INVALID_ELEMENT', 'Array', 'options.roles', role)); } resolvedRoles.push(resolvedRole); } @@ -194,37 +309,45 @@ class GuildMemberManager extends BaseManager { .then(data => data.pruned); } + /** + * Kicks a user from the guild. + * The user must be a member of the guild + * @param {UserResolvable} user The member to kick + * @param {string} [reason] Reason for kicking + * @returns {Promise} Result object will be resolved as specifically as possible. + * If the GuildMember cannot be resolved, the User will instead be attempted to be resolved. If that also cannot + * be resolved, the user's id will be the result. + * @example + * // Kick a user by id (or with a user/guild member object) + * guild.members.kick('84484653687267328') + * .then(user => console.log(`Kicked ${user.username ?? user.id ?? user} from ${guild.name}`)) + * .catch(console.error); + */ + async kick(user, reason) { + const id = this.client.users.resolveId(user); + if (!id) return Promise.reject(new TypeError('INVALID_TYPE', 'user', 'UserResolvable')); + + await this.client.api.guilds(this.guild.id).members(id).delete({ reason }); + + return this.resolve(user) ?? this.client.users.resolve(user) ?? id; + } + /** * Bans a user from the guild. * @param {UserResolvable} user The user to ban - * @param {Object} [options] Options for the ban - * @param {number} [options.days=0] Number of days of messages to delete, must be between 0 and 7 - * @param {string} [options.reason] Reason for banning + * @param {BanOptions} [options] Options for the ban * @returns {Promise} Result object will be resolved as specifically as possible. * If the GuildMember cannot be resolved, the User will instead be attempted to be resolved. If that also cannot - * be resolved, the user ID will be the result. + * be resolved, the user id will be the result. + * Internally calls the GuildBanManager#create method. * @example - * // Ban a user by ID (or with a user/guild member object) + * // Ban a user by id (or with a user/guild member object) * guild.members.ban('84484653687267328') - * .then(user => console.log(`Banned ${user.username || user.id || user} from ${guild.name}`)) + * .then(user => console.log(`Banned ${user.username ?? user.id ?? user} from ${guild.name}`)) * .catch(console.error); */ ban(user, options = { days: 0 }) { - if (options.days) options.delete_message_days = options.days; - const id = this.client.users.resolveID(user); - if (!id) return Promise.reject(new Error('BAN_RESOLVE_ID', true)); - return this.client.api - .guilds(this.guild.id) - .bans[id].put({ data: options }) - .then(() => { - if (user instanceof GuildMember) return user; - const _user = this.client.users.resolve(id); - if (_user) { - const member = this.resolve(_user); - return member || _user; - } - return id; - }); + return this.guild.bans.create(user, options); } /** @@ -232,19 +355,15 @@ class GuildMemberManager extends BaseManager { * @param {UserResolvable} user The user to unban * @param {string} [reason] Reason for unbanning user * @returns {Promise} + * Internally calls the GuildBanManager#remove method. * @example - * // Unban a user by ID (or with a user/guild member object) + * // Unban a user by id (or with a user/guild member object) * guild.members.unban('84484653687267328') * .then(user => console.log(`Unbanned ${user.username} from ${guild.name}`)) * .catch(console.error); */ unban(user, reason) { - const id = this.client.users.resolveID(user); - if (!id) return Promise.reject(new Error('BAN_RESOLVE_ID')); - return this.client.api - .guilds(this.guild.id) - .bans[id].delete({ reason }) - .then(() => this.client.users.resolve(user)); + return this.guild.bans.remove(user, reason); } _fetchSingle({ user, cache, force = false }) { @@ -257,7 +376,7 @@ class GuildMemberManager extends BaseManager { .guilds(this.guild.id) .members(user) .get() - .then(data => this.add(data, cache)); + .then(data => this._add(data, cache)); } _fetchMany({ @@ -277,7 +396,7 @@ class GuildMemberManager extends BaseManager { if (!query && !user_ids) query = ''; if (nonce.length > 32) throw new RangeError('MEMBER_FETCH_NONCE_LENGTH'); this.guild.shard.send({ - op: OPCodes.REQUEST_GUILD_MEMBERS, + op: Opcodes.REQUEST_GUILD_MEMBERS, d: { guild_id: this.guild.id, presences, @@ -288,7 +407,7 @@ class GuildMemberManager extends BaseManager { }, }); const fetchedMembers = new Collection(); - const option = query || limit || presences || user_ids; + const option = Boolean(query || limit || presences || user_ids); let i = 0; const handler = (members, _, chunk) => { timeout.refresh(); @@ -303,7 +422,7 @@ class GuildMemberManager extends BaseManager { (limit && fetchedMembers.size >= limit) || i === chunk.count ) { - this.client.clearTimeout(timeout); + clearTimeout(timeout); this.client.removeListener(Events.GUILD_MEMBERS_CHUNK, handler); this.client.decrementMaxListeners(); let fetched = option ? fetchedMembers : this.cache; @@ -311,11 +430,11 @@ class GuildMemberManager extends BaseManager { resolve(fetched); } }; - const timeout = this.client.setTimeout(() => { + const timeout = setTimeout(() => { this.client.removeListener(Events.GUILD_MEMBERS_CHUNK, handler); this.client.decrementMaxListeners(); reject(new Error('GUILD_MEMBERS_TIMEOUT')); - }, time); + }, time).unref(); this.client.incrementMaxListeners(); this.client.on(Events.GUILD_MEMBERS_CHUNK, handler); }); diff --git a/node_modules/discord.js/src/managers/GuildMemberRoleManager.js b/node_modules/discord.js/src/managers/GuildMemberRoleManager.js index 9fc6248f..e9304e32 100644 --- a/node_modules/discord.js/src/managers/GuildMemberRoleManager.js +++ b/node_modules/discord.js/src/managers/GuildMemberRoleManager.js @@ -1,35 +1,29 @@ 'use strict'; +const { Collection } = require('@discordjs/collection'); +const DataManager = require('./DataManager'); const { TypeError } = require('../errors'); -const Collection = require('../util/Collection'); +const Role = require('../structures/Role'); /** * Manages API methods for roles of a GuildMember and stores their cache. + * @extends {DataManager} */ -class GuildMemberRoleManager { +class GuildMemberRoleManager extends DataManager { constructor(member) { + super(member.client, Role); + /** * The GuildMember this manager belongs to * @type {GuildMember} */ this.member = member; + /** * The Guild this manager belongs to * @type {Guild} */ this.guild = member.guild; - Object.defineProperty(this, 'client', { value: member.client }); - } - - /** - * The filtered collection of roles of the member - * @type {Collection} - * @private - * @readonly - */ - get _roles() { - const everyone = this.guild.roles.everyone; - return this.guild.roles.cache.filter(role => this.member._roles.includes(role.id)).set(everyone.id, everyone); } /** @@ -38,7 +32,8 @@ class GuildMemberRoleManager { * @readonly */ get cache() { - return this._roles; + const everyone = this.guild.roles.everyone; + return this.guild.roles.cache.filter(role => this.member._roles.includes(role.id)).set(everyone.id, everyone); } /** @@ -47,7 +42,7 @@ class GuildMemberRoleManager { * @readonly */ get hoist() { - const hoistedRoles = this._roles.filter(role => role.hoist); + const hoistedRoles = this.cache.filter(role => role.hoist); if (!hoistedRoles.size) return null; return hoistedRoles.reduce((prev, role) => (!prev || role.comparePositionTo(prev) > 0 ? role : prev)); } @@ -58,7 +53,7 @@ class GuildMemberRoleManager { * @readonly */ get color() { - const coloredRoles = this._roles.filter(role => role.color); + const coloredRoles = this.cache.filter(role => role.color); if (!coloredRoles.size) return null; return coloredRoles.reduce((prev, role) => (!prev || role.comparePositionTo(prev) > 0 ? role : prev)); } @@ -69,7 +64,27 @@ class GuildMemberRoleManager { * @readonly */ get highest() { - return this._roles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this._roles.first()); + return this.cache.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this.cache.first()); + } + + /** + * The premium subscriber role of the guild, if present on the member + * @type {?Role} + * @readonly + */ + get premiumSubscriberRole() { + return this.cache.find(role => role.tags?.premiumSubscriberRole) ?? null; + } + + /** + * The managed role this member created when joining the guild, if any + * Only ever available on bots + * @type {?Role} + * @readonly + */ + get botRole() { + if (!this.member.user.bot) return null; + return this.cache.find(role => role.tags?.botId === this.member.user.id) ?? null; } /** @@ -80,23 +95,25 @@ class GuildMemberRoleManager { */ async add(roleOrRoles, reason) { if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) { - roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r)); - if (roleOrRoles.includes(null)) { - throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true); + const resolvedRoles = []; + for (const role of roleOrRoles.values()) { + const resolvedRole = this.guild.roles.resolveId(role); + if (!resolvedRole) throw new TypeError('INVALID_ELEMENT', 'Array or Collection', 'roles', role); + resolvedRoles.push(resolvedRole); } - const newRoles = [...new Set(roleOrRoles.concat(...this._roles.values()))]; + const newRoles = [...new Set(resolvedRoles.concat(...this.cache.values()))]; return this.set(newRoles, reason); } else { - roleOrRoles = this.guild.roles.resolve(roleOrRoles); + roleOrRoles = this.guild.roles.resolveId(roleOrRoles); if (roleOrRoles === null) { throw new TypeError('INVALID_TYPE', 'roles', 'Role, Snowflake or Array or Collection of Roles or Snowflakes'); } - await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles.id].put({ reason }); + await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles].put({ reason }); const clone = this.member._clone(); - clone._roles = [...this._roles.keys(), roleOrRoles.id]; + clone._roles = [...this.cache.keys(), roleOrRoles]; return clone; } } @@ -109,23 +126,25 @@ class GuildMemberRoleManager { */ async remove(roleOrRoles, reason) { if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) { - roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r)); - if (roleOrRoles.includes(null)) { - throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true); + const resolvedRoles = []; + for (const role of roleOrRoles.values()) { + const resolvedRole = this.guild.roles.resolveId(role); + if (!resolvedRole) throw new TypeError('INVALID_ELEMENT', 'Array or Collection', 'roles', role); + resolvedRoles.push(resolvedRole); } - const newRoles = this._roles.filter(role => !roleOrRoles.includes(role)); + const newRoles = this.cache.filter(role => !resolvedRoles.includes(role.id)); return this.set(newRoles, reason); } else { - roleOrRoles = this.guild.roles.resolve(roleOrRoles); + roleOrRoles = this.guild.roles.resolveId(roleOrRoles); if (roleOrRoles === null) { - throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true); + throw new TypeError('INVALID_TYPE', 'roles', 'Role, Snwoflake or Array or Collection of Roles or Snowflakes'); } - await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles.id].delete({ reason }); + await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles].delete({ reason }); const clone = this.member._clone(); - const newRoles = this._roles.filter(role => role.id !== roleOrRoles.id); + const newRoles = this.cache.filter(role => role.id !== roleOrRoles); clone._roles = [...newRoles.keys()]; return clone; } @@ -133,7 +152,7 @@ class GuildMemberRoleManager { /** * Sets the roles applied to the member. - * @param {Collection|RoleResolvable[]} roles The roles or role IDs to apply + * @param {Collection|RoleResolvable[]} roles The roles or role ids to apply * @param {string} [reason] Reason for applying the roles * @returns {Promise} * @example @@ -153,7 +172,7 @@ class GuildMemberRoleManager { clone() { const clone = new this.constructor(this.member); - clone.member._roles = [...this._roles.keyArray()]; + clone.member._roles = [...this.cache.keys()]; return clone; } } diff --git a/node_modules/discord.js/src/managers/MessageManager.js b/node_modules/discord.js/src/managers/MessageManager.js index 96a96435..4f61ab15 100644 --- a/node_modules/discord.js/src/managers/MessageManager.js +++ b/node_modules/discord.js/src/managers/MessageManager.js @@ -1,18 +1,19 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const { Collection } = require('@discordjs/collection'); +const CachedManager = require('./CachedManager'); const { TypeError } = require('../errors'); const Message = require('../structures/Message'); -const Collection = require('../util/Collection'); -const LimitedCollection = require('../util/LimitedCollection'); +const MessagePayload = require('../structures/MessagePayload'); /** * Manages API methods for Messages and holds their cache. - * @extends {BaseManager} + * @extends {CachedManager} */ -class MessageManager extends BaseManager { +class MessageManager extends CachedManager { constructor(channel, iterable) { - super(channel.client, iterable, Message, LimitedCollection, channel.client.options.messageCacheMaxSize); + super(channel.client, Message, iterable); + /** * The channel that the messages belong to * @type {TextBasedChannel} @@ -26,8 +27,8 @@ class MessageManager extends BaseManager { * @name MessageManager#cache */ - add(data, cache) { - return super.add(data, cache, { extras: [this.channel] }); + _add(data, cache) { + return super._add(data, cache, { extras: [this.channel] }); } /** @@ -35,18 +36,17 @@ class MessageManager extends BaseManager { * `after` are mutually exclusive. All the parameters are optional. * @typedef {Object} ChannelLogsQueryOptions * @property {number} [limit=50] Number of messages to acquire - * @property {Snowflake} [before] ID of a message to get the messages that were posted before it - * @property {Snowflake} [after] ID of a message to get the messages that were posted after it - * @property {Snowflake} [around] ID of a message to get the messages that were posted around it + * @property {Snowflake} [before] The message's id to get the messages that were posted before it + * @property {Snowflake} [after] The message's id to get the messages that were posted after it + * @property {Snowflake} [around] The message's id to get the messages that were posted around it */ /** * Gets a message, or messages, from this channel. * The returned Collection does not contain reaction users of the messages if they were not cached. * Those need to be fetched separately in such a case. - * @param {Snowflake|ChannelLogsQueryOptions} [message] The ID of the message to fetch, or query parameters. - * @param {boolean} [cache=true] Whether to cache the message(s) - * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @param {Snowflake|ChannelLogsQueryOptions} [message] The id of the message to fetch, or query parameters. + * @param {BaseFetchOptions} [options] Additional options for this fetch * @returns {Promise|Promise>} * @example * // Get message @@ -59,12 +59,12 @@ class MessageManager extends BaseManager { * .then(messages => console.log(`Received ${messages.size} messages`)) * .catch(console.error); * @example - * // Get messages and filter by user ID + * // Get messages and filter by user id * channel.messages.fetch() * .then(messages => console.log(`${messages.filter(m => m.author.id === '84484653687267328').size} messages`)) * .catch(console.error); */ - fetch(message, cache = true, force = false) { + fetch(message, { cache = true, force = false } = {}) { return typeof message === 'string' ? this._fetchId(message, cache, force) : this._fetchMany(message, cache); } @@ -83,7 +83,7 @@ class MessageManager extends BaseManager { fetchPinned(cache = true) { return this.client.api.channels[this.channel.id].pins.get().then(data => { const messages = new Collection(); - for (const message of data) messages.set(message.id, this.add(message, cache)); + for (const message of data) messages.set(message.id, this._add(message, cache)); return messages; }); } @@ -96,7 +96,7 @@ class MessageManager extends BaseManager { */ /** - * Resolves a MessageResolvable to a Message object. + * Resolves a {@link MessageResolvable} to a {@link Message} object. * @method resolve * @memberof MessageManager * @instance @@ -105,41 +105,121 @@ class MessageManager extends BaseManager { */ /** - * Resolves a MessageResolvable to a Message ID string. - * @method resolveID + * Resolves a {@link MessageResolvable} to a {@link Message} id. + * @method resolveId * @memberof MessageManager * @instance * @param {MessageResolvable} message The message resolvable to resolve * @returns {?Snowflake} */ + /** + * Edits a message, even if it's not cached. + * @param {MessageResolvable} message The message to edit + * @param {MessageEditOptions|MessagePayload} options The options to edit the message + * @returns {Promise} + */ + async edit(message, options) { + const messageId = this.resolveId(message); + if (!messageId) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable'); + + const { data, files } = await (options instanceof MessagePayload + ? options + : MessagePayload.create(message instanceof Message ? message : this, options) + ) + .resolveData() + .resolveFiles(); + const d = await this.client.api.channels[this.channel.id].messages[messageId].patch({ data, files }); + + const existing = this.cache.get(messageId); + if (existing) { + const clone = existing._clone(); + clone._patch(d); + return clone; + } + return this._add(d); + } + + /** + * Publishes a message in an announcement channel to all channels following it, even if it's not cached. + * @param {MessageResolvable} message The message to publish + * @returns {Promise} + */ + async crosspost(message) { + message = this.resolveId(message); + if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable'); + + const data = await this.client.api.channels(this.channel.id).messages(message).crosspost.post(); + return this.cache.get(data.id) ?? this._add(data); + } + + /** + * Pins a message to the channel's pinned messages, even if it's not cached. + * @param {MessageResolvable} message The message to pin + * @returns {Promise} + */ + async pin(message) { + message = this.resolveId(message); + if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable'); + + await this.client.api.channels(this.channel.id).pins(message).put(); + } + + /** + * Unins a message from the channel's pinned messages, even if it's not cached. + * @param {MessageResolvable} message The message to unpin + * @returns {Promise} + */ + async unpin(message) { + message = this.resolveId(message); + if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable'); + + await this.client.api.channels(this.channel.id).pins(message).delete(); + } + + /** + * Adds a reaction to a message, even if it's not cached. + * @param {MessageResolvable} message The messag to react to + * @param {EmojiIdentifierResolvable} emoji The emoji to react with + * @returns {Promise} + */ + async react(message, emoji) { + message = this.resolveId(message); + if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable'); + + emoji = this.client.emojis.resolveIdentifier(emoji); + if (!emoji) throw new TypeError('EMOJI_TYPE', 'emoji', 'EmojiIdentifierResolvable'); + + // eslint-disable-next-line newline-per-chained-call + await this.client.api.channels(this.channel.id).messages(message).reactions(emoji, '@me').put(); + } + /** * Deletes a message, even if it's not cached. * @param {MessageResolvable} message The message to delete - * @param {string} [reason] Reason for deleting this message, if it does not belong to the client user * @returns {Promise} */ - async delete(message, reason) { - message = this.resolveID(message); + async delete(message) { + message = this.resolveId(message); if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable'); - await this.client.api.channels(this.channel.id).messages(message).delete({ reason }); + await this.client.api.channels(this.channel.id).messages(message).delete(); } - async _fetchId(messageID, cache, force) { + async _fetchId(messageId, cache, force) { if (!force) { - const existing = this.cache.get(messageID); + const existing = this.cache.get(messageId); if (existing && !existing.partial) return existing; } - const data = await this.client.api.channels[this.channel.id].messages[messageID].get(); - return this.add(data, cache); + const data = await this.client.api.channels[this.channel.id].messages[messageId].get(); + return this._add(data, cache); } async _fetchMany(options = {}, cache) { const data = await this.client.api.channels[this.channel.id].messages.get({ query: options }); const messages = new Collection(); - for (const message of data) messages.set(message.id, this.add(message, cache)); + for (const message of data) messages.set(message.id, this._add(message, cache)); return messages; } } diff --git a/node_modules/discord.js/src/managers/PresenceManager.js b/node_modules/discord.js/src/managers/PresenceManager.js index c02fe044..2d648342 100644 --- a/node_modules/discord.js/src/managers/PresenceManager.js +++ b/node_modules/discord.js/src/managers/PresenceManager.js @@ -1,15 +1,15 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const CachedManager = require('./CachedManager'); const { Presence } = require('../structures/Presence'); /** * Manages API methods for Presences and holds their cache. - * @extends {BaseManager} + * @extends {CachedManager} */ -class PresenceManager extends BaseManager { +class PresenceManager extends CachedManager { constructor(client, iterable) { - super(client, iterable, Presence); + super(client, Presence, iterable); } /** @@ -18,9 +18,8 @@ class PresenceManager extends BaseManager { * @name PresenceManager#cache */ - add(data, cache) { - const existing = this.cache.get(data.user.id); - return existing ? existing.patch(data) : super.add(data, cache, { id: data.user.id }); + _add(data, cache) { + return super._add(data, cache, { id: data.user.id }); } /** @@ -32,26 +31,26 @@ class PresenceManager extends BaseManager { */ /** - * Resolves a PresenceResolvable to a Presence object. + * Resolves a {@link PresenceResolvable} to a {@link Presence} object. * @param {PresenceResolvable} presence The presence resolvable to resolve * @returns {?Presence} */ resolve(presence) { const presenceResolvable = super.resolve(presence); if (presenceResolvable) return presenceResolvable; - const UserResolvable = this.client.users.resolveID(presence); - return super.resolve(UserResolvable) || null; + const UserResolvable = this.client.users.resolveId(presence); + return super.resolve(UserResolvable); } /** - * Resolves a PresenceResolvable to a Presence ID string. + * Resolves a {@link PresenceResolvable} to a {@link Presence} id. * @param {PresenceResolvable} presence The presence resolvable to resolve * @returns {?Snowflake} */ - resolveID(presence) { - const presenceResolvable = super.resolveID(presence); + resolveId(presence) { + const presenceResolvable = super.resolveId(presence); if (presenceResolvable) return presenceResolvable; - const userResolvable = this.client.users.resolveID(presence); + const userResolvable = this.client.users.resolveId(presence); return this.cache.has(userResolvable) ? userResolvable : null; } } diff --git a/node_modules/discord.js/src/managers/ReactionManager.js b/node_modules/discord.js/src/managers/ReactionManager.js index e194d847..771e0541 100644 --- a/node_modules/discord.js/src/managers/ReactionManager.js +++ b/node_modules/discord.js/src/managers/ReactionManager.js @@ -1,15 +1,15 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const CachedManager = require('./CachedManager'); const MessageReaction = require('../structures/MessageReaction'); /** * Manages API methods for reactions and holds their cache. - * @extends {BaseManager} + * @extends {CachedManager} */ -class ReactionManager extends BaseManager { +class ReactionManager extends CachedManager { constructor(message, iterable) { - super(message.client, iterable, MessageReaction); + super(message.client, MessageReaction, iterable); /** * The message that this manager belongs to @@ -18,8 +18,8 @@ class ReactionManager extends BaseManager { this.message = message; } - add(data, cache) { - return super.add(data, cache, { id: data.emoji.id || data.emoji.name, extras: [this.message] }); + _add(data, cache) { + return super._add(data, cache, { id: data.emoji.id ?? data.emoji.name, extras: [this.message] }); } /** @@ -36,7 +36,7 @@ class ReactionManager extends BaseManager { */ /** - * Resolves a MessageReactionResolvable to a MessageReaction object. + * Resolves a {@link MessageReactionResolvable} to a {@link MessageReaction} object. * @method resolve * @memberof ReactionManager * @instance @@ -45,8 +45,8 @@ class ReactionManager extends BaseManager { */ /** - * Resolves a MessageReactionResolvable to a MessageReaction ID string. - * @method resolveID + * Resolves a {@link MessageReactionResolvable} to a {@link MessageReaction} id. + * @method resolveId * @memberof ReactionManager * @instance * @param {MessageReactionResolvable} reaction The MessageReaction to resolve diff --git a/node_modules/discord.js/src/managers/ReactionUserManager.js b/node_modules/discord.js/src/managers/ReactionUserManager.js index 1d93e42e..625aff2a 100644 --- a/node_modules/discord.js/src/managers/ReactionUserManager.js +++ b/node_modules/discord.js/src/managers/ReactionUserManager.js @@ -1,16 +1,18 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const { Collection } = require('@discordjs/collection'); +const CachedManager = require('./CachedManager'); const { Error } = require('../errors'); -const Collection = require('../util/Collection'); +const User = require('../structures/User'); /** * Manages API methods for users who reacted to a reaction and stores their cache. - * @extends {BaseManager} + * @extends {CachedManager} */ -class ReactionUserManager extends BaseManager { - constructor(client, iterable, reaction) { - super(client, iterable, { name: 'User' }); +class ReactionUserManager extends CachedManager { + constructor(reaction, iterable) { + super(reaction.client, User, iterable); + /** * The reaction that this manager belongs to * @type {MessageReaction} @@ -25,21 +27,25 @@ class ReactionUserManager extends BaseManager { */ /** - * Fetches the users that gave this reaction. Resolves with a collection of users, mapped by their IDs. - * @param {Object} [options] Options for fetching the users - * @param {number} [options.limit=100] The maximum amount of users to fetch, defaults to 100 - * @param {Snowflake} [options.before] Limit fetching users to those with an id lower than the supplied id - * @param {Snowflake} [options.after] Limit fetching users to those with an id greater than the supplied id + * Options used to fetch users who gave a reaction. + * @typedef {Object} FetchReactionUsersOptions + * @property {number} [limit=100] The maximum amount of users to fetch, defaults to `100` + * @property {Snowflake} [after] Limit fetching users to those with an id greater than the supplied id + */ + + /** + * Fetches all the users that gave this reaction. Resolves with a collection of users, mapped by their ids. + * @param {FetchReactionUsersOptions} [options] Options for fetching the users * @returns {Promise>} */ - async fetch({ limit = 100, after, before } = {}) { + async fetch({ limit = 100, after } = {}) { const message = this.reaction.message; const data = await this.client.api.channels[message.channel.id].messages[message.id].reactions[ this.reaction.emoji.identifier - ].get({ query: { limit, before, after } }); + ].get({ query: { limit, after } }); const users = new Collection(); for (const rawUser of data) { - const user = this.client.users.add(rawUser); + const user = this.client.users._add(rawUser); this.cache.set(user.id, user); users.set(user.id, user); } @@ -52,11 +58,11 @@ class ReactionUserManager extends BaseManager { * @returns {Promise} */ remove(user = this.client.user) { - const userID = this.client.users.resolveID(user); - if (!userID) return Promise.reject(new Error('REACTION_RESOLVE_USER')); + const userId = this.client.users.resolveId(user); + if (!userId) return Promise.reject(new Error('REACTION_RESOLVE_USER')); const message = this.reaction.message; return this.client.api.channels[message.channel.id].messages[message.id].reactions[this.reaction.emoji.identifier][ - userID === this.client.user.id ? '@me' : userID + userId === this.client.user.id ? '@me' : userId ] .delete() .then(() => this.reaction); diff --git a/node_modules/discord.js/src/managers/RoleManager.js b/node_modules/discord.js/src/managers/RoleManager.js index a1586b0f..65b67527 100644 --- a/node_modules/discord.js/src/managers/RoleManager.js +++ b/node_modules/discord.js/src/managers/RoleManager.js @@ -1,17 +1,20 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const { Collection } = require('@discordjs/collection'); +const CachedManager = require('./CachedManager'); +const { TypeError } = require('../errors'); const Role = require('../structures/Role'); const Permissions = require('../util/Permissions'); -const { resolveColor } = require('../util/Util'); +const { resolveColor, setPosition } = require('../util/Util'); /** * Manages API methods for roles and stores their cache. - * @extends {BaseManager} + * @extends {CachedManager} */ -class RoleManager extends BaseManager { +class RoleManager extends CachedManager { constructor(guild, iterable) { - super(guild.client, iterable, Role); + super(guild.client, Role, iterable); + /** * The guild belonging to this manager * @type {Guild} @@ -25,16 +28,15 @@ class RoleManager extends BaseManager { * @name RoleManager#cache */ - add(data, cache) { - return super.add(data, cache, { extras: [this.guild] }); + _add(data, cache) { + return super._add(data, cache, { extras: [this.guild] }); } /** - * Obtains one or more roles from Discord, or the role cache if they're already available. - * @param {Snowflake} [id] ID or IDs of the role(s) - * @param {boolean} [cache=true] Whether to cache the new roles objects if it weren't already - * @param {boolean} [force=false] Whether to skip the cache check and request the API - * @returns {Promise} + * Obtains a role from Discord, or the role cache if they're already available. + * @param {Snowflake} [id] The role's id + * @param {BaseFetchOptions} [options] Additional options for this fetch + * @returns {Promise>} * @example * // Fetch all roles from the guild * message.guild.roles.fetch() @@ -46,16 +48,17 @@ class RoleManager extends BaseManager { * .then(role => console.log(`The role color is: ${role.color}`)) * .catch(console.error); */ - async fetch(id, cache = true, force = false) { + async fetch(id, { cache = true, force = false } = {}) { if (id && !force) { const existing = this.cache.get(id); if (existing) return existing; } // We cannot fetch a single role, as of this commit's date, Discord API throws with 405 - const roles = await this.client.api.guilds(this.guild.id).roles.get(); - for (const role of roles) this.add(role, cache); - return id ? this.cache.get(id) || null : this; + const data = await this.client.api.guilds(this.guild.id).roles.get(); + const roles = new Collection(); + for (const role of data) roles.set(role.id, this._add(role, cache)); + return id ? roles.get(id) ?? null : roles; } /** @@ -66,7 +69,7 @@ class RoleManager extends BaseManager { */ /** - * Resolves a RoleResolvable to a Role object. + * Resolves a {@link RoleResolvable} to a {@link Role} object. * @method resolve * @memberof RoleManager * @instance @@ -75,20 +78,30 @@ class RoleManager extends BaseManager { */ /** - * Resolves a RoleResolvable to a role ID string. - * @method resolveID + * Resolves a {@link RoleResolvable} to a {@link Role} id. + * @method resolveId * @memberof RoleManager * @instance * @param {RoleResolvable} role The role resolvable to resolve * @returns {?Snowflake} */ + /** + * Options used to create a new role. + * @typedef {Object} CreateRoleOptions + * @property {string} [name] The name of the new role + * @property {ColorResolvable} [color] The data to create the role with + * @property {boolean} [hoist] Whether or not the new role should be hoisted + * @property {PermissionResolvable} [permissions] The permissions for the new role + * @property {number} [position] The position of the new role + * @property {boolean} [mentionable] Whether or not the new role should be mentionable + * @property {string} [reason] The reason for creating this role + */ + /** * Creates a new role in the guild with given information. * The position will silently reset to 1 if an invalid one is provided, or none. - * @param {Object} [options] Options - * @param {RoleData} [options.data] The data to create the role with - * @param {string} [options.reason] Reason for creating this role + * @param {CreateRoleOptions} [options] Options for creating the new role * @returns {Promise} * @example * // Create a new role @@ -98,32 +111,99 @@ class RoleManager extends BaseManager { * @example * // Create a new role with data and a reason * guild.roles.create({ - * data: { - * name: 'Super Cool People', - * color: 'BLUE', - * }, + * name: 'Super Cool Blue People', + * color: 'BLUE', * reason: 'we needed a role for Super Cool People', * }) * .then(console.log) * .catch(console.error); */ - create({ data = {}, reason } = {}) { - if (data.color) data.color = resolveColor(data.color); - if (data.permissions) data.permissions = Permissions.resolve(data.permissions); + create(options = {}) { + let { name, color, hoist, permissions, position, mentionable, reason } = options; + if (color) color = resolveColor(color); + if (typeof permissions !== 'undefined') permissions = new Permissions(permissions); - return this.guild.client.api + return this.client.api .guilds(this.guild.id) - .roles.post({ data, reason }) + .roles.post({ + data: { + name, + color, + hoist, + permissions, + mentionable, + }, + reason, + }) .then(r => { const { role } = this.client.actions.GuildRoleCreate.handle({ guild_id: this.guild.id, role: r, }); - if (data.position) return role.setPosition(data.position, reason); + if (position) return role.setPosition(position, reason); return role; }); } + /** + * Edits a role of the guild. + * @param {RoleResolvable} role The role to edit + * @param {RoleData} data The new data for the role + * @param {string} [reason] Reason for editing this role + * @returns {Promise} + * @example + * // Edit a role + * guild.roles.edit('222079219327434752', { name: 'buddies' }) + * .then(updated => console.log(`Edited role name to ${updated.name}`)) + * .catch(console.error); + */ + async edit(role, data, reason) { + role = this.resolve(role); + if (!role) throw new TypeError('INVALID_TYPE', 'role', 'RoleResolvable'); + + if (typeof data.position === 'number') { + const updatedRoles = await setPosition( + role, + data.position, + false, + this.guild._sortedRoles(), + this.client.api.guilds(this.guild.id).roles, + reason, + ); + + this.client.actions.GuildRolesPositionUpdate.handle({ + guild_id: this.guild.id, + roles: updatedRoles, + }); + } + + const _data = { + name: data.name, + color: typeof data.color === 'undefined' ? undefined : resolveColor(data.color), + hoist: data.hoist, + permissions: typeof data.permissions === 'undefined' ? undefined : new Permissions(data.permissions), + mentionable: data.mentionable, + }; + + const d = await this.client.api.guilds(this.guild.id).roles(role.id).patch({ data: _data, reason }); + + const clone = role._clone(); + clone._patch(d); + return clone; + } + + /** + * Gets the managed role a user created when joining the guild, if any + * Only ever available for bots + * @param {UserResolvable} user The user to access the bot role for + * @returns {?Role} + */ + botRoleFor(user) { + const userId = this.client.users.resolveId(user); + if (!userId) return null; + return this.cache.find(role => role.tags?.botId === userId) ?? null; + } + /** * The `@everyone` role of the guild * @type {Role} @@ -133,6 +213,15 @@ class RoleManager extends BaseManager { return this.cache.get(this.guild.id); } + /** + * The premium subscriber role of the guild, if any + * @type {?Role} + * @readonly + */ + get premiumSubscriberRole() { + return this.cache.find(role => role.tags?.premiumSubscriberRole) ?? null; + } + /** * The role with the highest position in the cache * @type {Role} diff --git a/node_modules/discord.js/src/managers/UserManager.js b/node_modules/discord.js/src/managers/UserManager.js index 89287150..dfbba9e8 100644 --- a/node_modules/discord.js/src/managers/UserManager.js +++ b/node_modules/discord.js/src/managers/UserManager.js @@ -1,17 +1,18 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const CachedManager = require('./CachedManager'); const GuildMember = require('../structures/GuildMember'); const Message = require('../structures/Message'); +const ThreadMember = require('../structures/ThreadMember'); const User = require('../structures/User'); /** * Manages API methods for users and stores their cache. - * @extends {BaseManager} + * @extends {CachedManager} */ -class UserManager extends BaseManager { +class UserManager extends CachedManager { constructor(client, iterable) { - super(client, iterable, User); + super(client, User, iterable); } /** @@ -26,46 +27,47 @@ class UserManager extends BaseManager { * * A Snowflake * * A Message object (resolves to the message author) * * A GuildMember object - * @typedef {User|Snowflake|Message|GuildMember} UserResolvable + * * A ThreadMember object + * @typedef {User|Snowflake|Message|GuildMember|ThreadMember} UserResolvable */ /** - * Resolves a UserResolvable to a User object. + * Resolves a {@link UserResolvable} to a {@link User} object. * @param {UserResolvable} user The UserResolvable to identify * @returns {?User} */ resolve(user) { - if (user instanceof GuildMember) return user.user; + if (user instanceof GuildMember || user instanceof ThreadMember) return user.user; if (user instanceof Message) return user.author; return super.resolve(user); } /** - * Resolves a UserResolvable to a user ID string. + * Resolves a {@link UserResolvable} to a {@link User} id. * @param {UserResolvable} user The UserResolvable to identify * @returns {?Snowflake} */ - resolveID(user) { + resolveId(user) { + if (user instanceof ThreadMember) return user.id; if (user instanceof GuildMember) return user.user.id; if (user instanceof Message) return user.author.id; - return super.resolveID(user); + return super.resolveId(user); } /** * Obtains a user from Discord, or the user cache if it's already available. - * @param {Snowflake} id ID of the user - * @param {boolean} [cache=true] Whether to cache the new user object if it isn't already - * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @param {Snowflake} id The user's id + * @param {BaseFetchOptions} [options] Additional options for this fetch * @returns {Promise} */ - async fetch(id, cache = true, force = false) { + async fetch(id, { cache = true, force = false } = {}) { if (!force) { const existing = this.cache.get(id); if (existing && !existing.partial) return existing; } const data = await this.client.api.users(id).get(); - return this.add(data, cache); + return this._add(data, cache); } } diff --git a/node_modules/discord.js/src/managers/VoiceStateManager.js b/node_modules/discord.js/src/managers/VoiceStateManager.js index 35045f7b..c42fdd2c 100644 --- a/node_modules/discord.js/src/managers/VoiceStateManager.js +++ b/node_modules/discord.js/src/managers/VoiceStateManager.js @@ -1,14 +1,16 @@ 'use strict'; -const BaseManager = require('./BaseManager'); +const CachedManager = require('./CachedManager'); +const VoiceState = require('../structures/VoiceState'); /** * Manages API methods for VoiceStates and stores their cache. - * @extends {BaseManager} + * @extends {CachedManager} */ -class VoiceStateManager extends BaseManager { +class VoiceStateManager extends CachedManager { constructor(guild, iterable) { - super(guild.client, iterable, { name: 'VoiceState' }); + super(guild.client, VoiceState, iterable); + /** * The guild this manager belongs to * @type {Guild} @@ -22,7 +24,7 @@ class VoiceStateManager extends BaseManager { * @name VoiceStateManager#cache */ - add(data, cache = true) { + _add(data, cache = true) { const existing = this.cache.get(data.user_id); if (existing) return existing._patch(data); diff --git a/node_modules/discord.js/src/rest/APIRequest.js b/node_modules/discord.js/src/rest/APIRequest.js index 837b38f1..d710c587 100644 --- a/node_modules/discord.js/src/rest/APIRequest.js +++ b/node_modules/discord.js/src/rest/APIRequest.js @@ -4,9 +4,9 @@ const https = require('https'); const FormData = require('@discordjs/form-data'); const AbortController = require('abort-controller'); const fetch = require('node-fetch'); -const { browser, UserAgent } = require('../util/Constants'); +const { UserAgent } = require('../util/Constants'); -if (https.Agent) var agent = new https.Agent({ keepAlive: true }); +const agent = new https.Agent({ keepAlive: true }); class APIRequest { constructor(rest, method, path, options) { @@ -17,10 +17,13 @@ class APIRequest { this.options = options; this.retries = 0; + const { userAgentSuffix } = this.client.options; + this.fullUserAgent = `${UserAgent}${userAgentSuffix.length ? `, ${userAgentSuffix.join(', ')}` : ''}`; + let queryString = ''; if (options.query) { const query = Object.entries(options.query) - .filter(([, value]) => ![null, 'null', 'undefined'].includes(value) && typeof value !== 'undefined') + .filter(([, value]) => value !== null && typeof value !== 'undefined') .flatMap(([key, value]) => (Array.isArray(value) ? value.map(v => [key, v]) : [[key, value]])); queryString = new URLSearchParams(query).toString(); } @@ -33,19 +36,30 @@ class APIRequest { ? this.client.options.http.api : `${this.client.options.http.api}/v${this.client.options.http.version}`; const url = API + this.path; - let headers = {}; + + let headers = { + ...this.client.options.http.headers, + 'User-Agent': this.fullUserAgent, + }; if (this.options.auth !== false) headers.Authorization = this.rest.getAuth(); if (this.options.reason) headers['X-Audit-Log-Reason'] = encodeURIComponent(this.options.reason); - if (!browser) headers['User-Agent'] = UserAgent; if (this.options.headers) headers = Object.assign(headers, this.options.headers); let body; if (this.options.files && this.options.files.length) { body = new FormData(); - for (const file of this.options.files) if (file && file.file) body.append(file.name, file.file, file.name); - if (typeof this.options.data !== 'undefined') body.append('payload_json', JSON.stringify(this.options.data)); - if (!browser) headers = Object.assign(headers, body.getHeaders()); + for (const file of this.options.files) { + if (file?.file) body.append(file.key ?? file.name, file.file, file.name); + } + if (typeof this.options.data !== 'undefined') { + if (this.options.dontUsePayloadJSON) { + for (const [key, value] of Object.entries(this.options.data)) body.append(key, value); + } else { + body.append('payload_json', JSON.stringify(this.options.data)); + } + } + headers = Object.assign(headers, body.getHeaders()); // eslint-disable-next-line eqeqeq } else if (this.options.data != null) { body = JSON.stringify(this.options.data); @@ -53,14 +67,14 @@ class APIRequest { } const controller = new AbortController(); - const timeout = this.client.setTimeout(() => controller.abort(), this.client.options.restRequestTimeout); + const timeout = setTimeout(() => controller.abort(), this.client.options.restRequestTimeout).unref(); return fetch(url, { method: this.method, headers, agent, body, signal: controller.signal, - }).finally(() => this.client.clearTimeout(timeout)); + }).finally(() => clearTimeout(timeout)); } } diff --git a/node_modules/discord.js/src/rest/APIRouter.js b/node_modules/discord.js/src/rest/APIRouter.js index e85c739f..b22b37f7 100644 --- a/node_modules/discord.js/src/rest/APIRouter.js +++ b/node_modules/discord.js/src/rest/APIRouter.js @@ -21,7 +21,7 @@ function buildRoute(manager) { for (let i = 0; i < route.length; i++) { // Reactions routes and sub-routes all share the same bucket if (route[i - 1] === 'reactions') break; - // Literal IDs should only be taken account if they are the Major ID (the Channel/Guild ID) + // Literal ids should only be taken account if they are the Major id (the Channel/Guild id) if (/\d{16,19}/g.test(route[i]) && !/channels|guilds/.test(route[i - 1])) routeBucket.push(':id'); // All other parts of the route should be considered as part of the bucket identifier else routeBucket.push(route[i]); diff --git a/node_modules/discord.js/src/rest/AsyncQueue.js b/node_modules/discord.js/src/rest/AsyncQueue.js deleted file mode 100644 index b465f6aa..00000000 --- a/node_modules/discord.js/src/rest/AsyncQueue.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2020 kyranet, discord.js - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -'use strict'; - -// TODO(kyranet, vladfrangu): replace this with discord.js v13's core AsyncQueue. - -/** - * An async queue that preserves the stack and prevents lock-ups. - * @private - */ -class AsyncQueue { - constructor() { - /** - * The promises array. - * @type {Array<{promise: Promise, resolve: Function}>} - * @private - */ - this.promises = []; - } - - /** - * The remaining amount of queued promises - * @type {number} - */ - get remaining() { - return this.promises.length; - } - - /** - * Waits for last promise and queues a new one. - * @returns {Promise} - * @example - * const queue = new AsyncQueue(); - * async function request(url, options) { - * await queue.wait(); - * try { - * const result = await fetch(url, options); - * // Do some operations with 'result' - * } finally { - * // Remove first entry from the queue and resolve for the next entry - * queue.shift(); - * } - * } - * - * request(someUrl1, someOptions1); // Will call fetch() immediately - * request(someUrl2, someOptions2); // Will call fetch() after the first finished - * request(someUrl3, someOptions3); // Will call fetch() after the second finished - */ - wait() { - const next = this.promises.length ? this.promises[this.promises.length - 1].promise : Promise.resolve(); - let resolve; - const promise = new Promise(res => { - resolve = res; - }); - - this.promises.push({ - resolve, - promise, - }); - - return next; - } - - /** - * Frees the queue's lock for the next item to process. - */ - shift() { - const deferred = this.promises.shift(); - if (typeof deferred !== 'undefined') deferred.resolve(); - } -} - -module.exports = AsyncQueue; diff --git a/node_modules/discord.js/src/rest/DiscordAPIError.js b/node_modules/discord.js/src/rest/DiscordAPIError.js index aebe513d..3137b7b3 100644 --- a/node_modules/discord.js/src/rest/DiscordAPIError.js +++ b/node_modules/discord.js/src/rest/DiscordAPIError.js @@ -5,23 +5,23 @@ * @extends Error */ class DiscordAPIError extends Error { - constructor(path, error, method, status) { + constructor(error, status, request) { super(); - const flattened = this.constructor.flattenErrors(error.errors || error).join('\n'); + const flattened = this.constructor.flattenErrors(error.errors ?? error).join('\n'); this.name = 'DiscordAPIError'; - this.message = error.message && flattened ? `${error.message}\n${flattened}` : error.message || flattened; + this.message = error.message && flattened ? `${error.message}\n${flattened}` : error.message ?? flattened; /** * The HTTP method used for the request * @type {string} */ - this.method = method; + this.method = request.method; /** * The path of the request relative to the HTTP endpoint * @type {string} */ - this.path = path; + this.path = request.path; /** * HTTP error code returned by Discord @@ -34,11 +34,20 @@ class DiscordAPIError extends Error { * @type {number} */ this.httpStatus = status; + + /** + * The data associated with the request that caused this error + * @type {HTTPErrorData} + */ + this.requestData = { + json: request.options.data, + files: request.options.files ?? [], + }; } /** * Flattens an errors object returned from the API into an array. - * @param {Object} obj Discord errors object + * @param {APIError} obj Discord errors object * @param {string} [key] Used internally to determine key names of nested fields * @returns {string[]} * @private @@ -52,7 +61,7 @@ class DiscordAPIError extends Error { if (v._errors) { messages.push(`${newKey}: ${v._errors.map(e => e.message).join(' ')}`); - } else if (v.code || v.message) { + } else if (v.code ?? v.message) { messages.push(`${v.code ? `${v.code}: ` : ''}${v.message}`.trim()); } else if (typeof v === 'string') { messages.push(v); @@ -66,3 +75,8 @@ class DiscordAPIError extends Error { } module.exports = DiscordAPIError; + +/** + * @external APIError + * @see {@link https://discord.com/developers/docs/reference#error-messages} + */ diff --git a/node_modules/discord.js/src/rest/HTTPError.js b/node_modules/discord.js/src/rest/HTTPError.js index 2911467f..f09ce5b1 100644 --- a/node_modules/discord.js/src/rest/HTTPError.js +++ b/node_modules/discord.js/src/rest/HTTPError.js @@ -5,7 +5,7 @@ * @extends Error */ class HTTPError extends Error { - constructor(message, name, code, method, path) { + constructor(message, name, code, request) { super(message); /** @@ -18,19 +18,43 @@ class HTTPError extends Error { * HTTP error code returned from the request * @type {number} */ - this.code = code || 500; + this.code = code ?? 500; /** * The HTTP method used for the request * @type {string} */ - this.method = method; + this.method = request.method; /** * The path of the request relative to the HTTP endpoint * @type {string} */ - this.path = path; + this.path = request.path; + + /** + * The HTTP data that was sent to Discord + * @typedef {Object} HTTPErrorData + * @property {*} json The JSON data that was sent + * @property {HTTPAttachmentData[]} files The files that were sent with this request, if any + */ + + /** + * The attachment data that is sent to Discord + * @typedef {Object} HTTPAttachmentData + * @property {string|Buffer|Stream} attachment The source of this attachment data + * @property {string} name The file name + * @property {Buffer|Stream} file The file buffer + */ + + /** + * The data associated with the request that caused this error + * @type {HTTPErrorData} + */ + this.requestData = { + json: request.options.data, + files: request.options.files ?? [], + }; } } diff --git a/node_modules/discord.js/src/rest/RESTManager.js b/node_modules/discord.js/src/rest/RESTManager.js index 799f6022..61fef747 100644 --- a/node_modules/discord.js/src/rest/RESTManager.js +++ b/node_modules/discord.js/src/rest/RESTManager.js @@ -1,10 +1,10 @@ 'use strict'; +const { Collection } = require('@discordjs/collection'); const APIRequest = require('./APIRequest'); const routeBuilder = require('./APIRouter'); const RequestHandler = require('./RequestHandler'); const { Error } = require('../errors'); -const Collection = require('../util/Collection'); const { Endpoints } = require('../util/Constants'); class RESTManager { @@ -13,11 +13,14 @@ class RESTManager { this.handlers = new Collection(); this.tokenPrefix = tokenPrefix; this.versioned = true; - this.globalTimeout = null; + this.globalLimit = client.options.restGlobalRateLimit > 0 ? client.options.restGlobalRateLimit : Infinity; + this.globalRemaining = this.globalLimit; + this.globalReset = null; + this.globalDelay = null; if (client.options.restSweepInterval > 0) { - client.setInterval(() => { + this.sweepInterval = setInterval(() => { this.handlers.sweep(handler => handler._inactive); - }, client.options.restSweepInterval * 1000); + }, client.options.restSweepInterval * 1000).unref(); } } @@ -26,7 +29,7 @@ class RESTManager { } getAuth() { - const token = this.client.token || this.client.accessToken; + const token = this.client.token ?? this.client.accessToken; if (token) return `${this.tokenPrefix} ${token}`; throw new Error('TOKEN_MISSING'); } diff --git a/node_modules/discord.js/src/rest/RequestHandler.js b/node_modules/discord.js/src/rest/RequestHandler.js index b15b2fa2..a523087e 100644 --- a/node_modules/discord.js/src/rest/RequestHandler.js +++ b/node_modules/discord.js/src/rest/RequestHandler.js @@ -1,17 +1,16 @@ 'use strict'; -const AsyncQueue = require('./AsyncQueue'); +const { AsyncQueue } = require('@sapphire/async-queue'); const DiscordAPIError = require('./DiscordAPIError'); const HTTPError = require('./HTTPError'); +const RateLimitError = require('./RateLimitError'); const { - Events: { RATE_LIMIT }, - browser, + Events: { DEBUG, RATE_LIMIT, INVALID_REQUEST_WARNING }, } = require('../util/Constants'); const Util = require('../util/Util'); function parseResponse(res) { if (res.headers.get('content-type').startsWith('application/json')) return res.json(); - if (browser) return res.blob(); return res.buffer(); } @@ -19,10 +18,23 @@ function getAPIOffset(serverDate) { return new Date(serverDate).getTime() - Date.now(); } -function calculateReset(reset, serverDate) { +function calculateReset(reset, resetAfter, serverDate) { + // Use direct reset time when available, server date becomes irrelevant in this case + if (resetAfter) { + return Date.now() + Number(resetAfter) * 1000; + } return new Date(Number(reset) * 1000).getTime() - getAPIOffset(serverDate); } +/* Invalid request limiting is done on a per-IP basis, not a per-token basis. + * The best we can do is track invalid counts process-wide (on the theory that + * users could have multiple bots run from one process) rather than per-bot. + * Therefore, store these at file scope here rather than in the client's + * RESTManager object. + */ +let invalidCount = 0; +let invalidCountResetTime = null; + class RequestHandler { constructor(manager) { this.manager = manager; @@ -30,7 +42,6 @@ class RequestHandler { this.reset = -1; this.remaining = -1; this.limit = -1; - this.retryAfter = -1; } async push(request) { @@ -42,47 +53,115 @@ class RequestHandler { } } + get globalLimited() { + return this.manager.globalRemaining <= 0 && Date.now() < this.manager.globalReset; + } + + get localLimited() { + return this.remaining <= 0 && Date.now() < this.reset; + } + get limited() { - return Boolean(this.manager.globalTimeout) || (this.remaining <= 0 && Date.now() < this.reset); + return this.globalLimited || this.localLimited; } get _inactive() { return this.queue.remaining === 0 && !this.limited; } + globalDelayFor(ms) { + return new Promise(resolve => { + setTimeout(() => { + this.manager.globalDelay = null; + resolve(); + }, ms).unref(); + }); + } + + /* + * Determines whether the request should be queued or whether a RateLimitError should be thrown + */ + async onRateLimit(request, limit, timeout, isGlobal) { + const { options } = this.manager.client; + if (!options.rejectOnRateLimit) return; + + const rateLimitData = { + timeout, + limit, + method: request.method, + path: request.path, + route: request.route, + global: isGlobal, + }; + const shouldThrow = + typeof options.rejectOnRateLimit === 'function' + ? await options.rejectOnRateLimit(rateLimitData) + : options.rejectOnRateLimit.some(route => rateLimitData.route.startsWith(route.toLowerCase())); + if (shouldThrow) { + throw new RateLimitError(rateLimitData); + } + } + async execute(request) { - // After calculations and requests have been done, pre-emptively stop further requests - if (this.limited) { - const timeout = this.reset + this.manager.client.options.restTimeOffset - Date.now(); + /* + * After calculations have been done, pre-emptively stop further requests + * Potentially loop until this task can run if e.g. the global rate limit is hit twice + */ + while (this.limited) { + const isGlobal = this.globalLimited; + let limit, timeout, delayPromise; + + if (isGlobal) { + // Set the variables based on the global rate limit + limit = this.manager.globalLimit; + timeout = this.manager.globalReset + this.manager.client.options.restTimeOffset - Date.now(); + } else { + // Set the variables based on the route-specific rate limit + limit = this.limit; + timeout = this.reset + this.manager.client.options.restTimeOffset - Date.now(); + } if (this.manager.client.listenerCount(RATE_LIMIT)) { /** * Emitted when the client hits a rate limit while making a request * @event Client#rateLimit - * @param {Object} rateLimitInfo Object containing the rate limit info - * @param {number} rateLimitInfo.timeout Timeout in ms - * @param {number} rateLimitInfo.limit Number of requests that can be made to this endpoint - * @param {string} rateLimitInfo.method HTTP method used for request that triggered this event - * @param {string} rateLimitInfo.path Path used for request that triggered this event - * @param {string} rateLimitInfo.route Route used for request that triggered this event + * @param {RateLimitData} rateLimitData Object containing the rate limit info */ this.manager.client.emit(RATE_LIMIT, { timeout, - limit: this.limit, + limit, method: request.method, path: request.path, route: request.route, + global: isGlobal, }); } - if (this.manager.globalTimeout) { - await this.manager.globalTimeout; + if (isGlobal) { + // If this is the first task to reach the global timeout, set the global delay + if (!this.manager.globalDelay) { + // The global delay function should clear the global delay state when it is resolved + this.manager.globalDelay = this.globalDelayFor(timeout); + } + delayPromise = this.manager.globalDelay; } else { - // Wait for the timeout to expire in order to avoid an actual 429 - await Util.delayFor(timeout); + delayPromise = Util.delayFor(timeout); } + + // Determine whether a RateLimitError should be thrown + await this.onRateLimit(request, limit, timeout, isGlobal); // eslint-disable-line no-await-in-loop + + // Wait for the timeout to expire in order to avoid an actual 429 + await delayPromise; // eslint-disable-line no-await-in-loop } + // As the request goes out, update the global usage information + if (!this.manager.globalReset || this.manager.globalReset < Date.now()) { + this.manager.globalReset = Date.now() + 1000; + this.manager.globalRemaining = this.manager.globalLimit; + } + this.manager.globalRemaining--; + // Perform the request let res; try { @@ -90,40 +169,78 @@ class RequestHandler { } catch (error) { // Retry the specified number of times for request abortions if (request.retries === this.manager.client.options.retryLimit) { - throw new HTTPError(error.message, error.constructor.name, error.status, request.method, request.path); + throw new HTTPError(error.message, error.constructor.name, error.status, request); } request.retries++; return this.execute(request); } + let sublimitTimeout; if (res && res.headers) { const serverDate = res.headers.get('date'); const limit = res.headers.get('x-ratelimit-limit'); const remaining = res.headers.get('x-ratelimit-remaining'); const reset = res.headers.get('x-ratelimit-reset'); - const retryAfter = res.headers.get('retry-after'); - + const resetAfter = res.headers.get('x-ratelimit-reset-after'); this.limit = limit ? Number(limit) : Infinity; this.remaining = remaining ? Number(remaining) : 1; - this.reset = reset ? calculateReset(reset, serverDate) : Date.now(); - this.retryAfter = retryAfter ? Number(retryAfter) : -1; - // https://github.com/discordapp/discord-api-docs/issues/182 - if (request.route.includes('reactions')) { + this.reset = reset || resetAfter ? calculateReset(reset, resetAfter, serverDate) : Date.now(); + + // https://github.com/discord/discord-api-docs/issues/182 + if (!resetAfter && request.route.includes('reactions')) { this.reset = new Date(serverDate).getTime() - getAPIOffset(serverDate) + 250; } - // Handle global ratelimit - if (res.headers.get('x-ratelimit-global')) { - // Set the manager's global timeout as the promise for other requests to "wait" - this.manager.globalTimeout = Util.delayFor(this.retryAfter); + // Handle retryAfter, which means we have actually hit a rate limit + let retryAfter = res.headers.get('retry-after'); + retryAfter = retryAfter ? Number(retryAfter) * 1000 : -1; + if (retryAfter > 0) { + // If the global ratelimit header is set, that means we hit the global rate limit + if (res.headers.get('x-ratelimit-global')) { + this.manager.globalRemaining = 0; + this.manager.globalReset = Date.now() + retryAfter; + } else if (!this.localLimited) { + /* + * This is a sublimit (e.g. 2 channel name changes/10 minutes) since the headers don't indicate a + * route-wide rate limit. Don't update remaining or reset to avoid rate limiting the whole + * endpoint, just set a reset time on the request itself to avoid retrying too soon. + */ + sublimitTimeout = retryAfter; + } + } + } + + // Count the invalid requests + if (res.status === 401 || res.status === 403 || res.status === 429) { + if (!invalidCountResetTime || invalidCountResetTime < Date.now()) { + invalidCountResetTime = Date.now() + 1000 * 60 * 10; + invalidCount = 0; + } + invalidCount++; - // Wait for the global timeout to resolve before continuing - await this.manager.globalTimeout; + const emitInvalid = + this.manager.client.listenerCount(INVALID_REQUEST_WARNING) && + this.manager.client.options.invalidRequestWarningInterval > 0 && + invalidCount % this.manager.client.options.invalidRequestWarningInterval === 0; + if (emitInvalid) { + /** + * @typedef {Object} InvalidRequestWarningData + * @property {number} count Number of invalid requests that have been made in the window + * @property {number} remainingTime Time in ms remaining before the count resets + */ - // Clean up global timeout - this.manager.globalTimeout = null; + /** + * Emitted periodically when the process sends invalid requests to let users avoid the + * 10k invalid requests in 10 minutes threshold that causes a ban + * @event Client#invalidRequestWarning + * @param {InvalidRequestWarningData} invalidRequestWarningData Object containing the invalid request info + */ + this.manager.client.emit(INVALID_REQUEST_WARNING, { + count: invalidCount, + remainingTime: invalidCountResetTime - Date.now(), + }); } } @@ -137,9 +254,36 @@ class RequestHandler { if (res.status >= 400 && res.status < 500) { // Handle ratelimited requests if (res.status === 429) { - // A ratelimit was hit - this should never happen - this.manager.client.emit('debug', `429 hit on route ${request.route}`); - await Util.delayFor(this.retryAfter); + const isGlobal = this.globalLimited; + let limit, timeout; + if (isGlobal) { + // Set the variables based on the global rate limit + limit = this.manager.globalLimit; + timeout = this.manager.globalReset + this.manager.client.options.restTimeOffset - Date.now(); + } else { + // Set the variables based on the route-specific rate limit + limit = this.limit; + timeout = this.reset + this.manager.client.options.restTimeOffset - Date.now(); + } + + this.manager.client.emit( + DEBUG, + `Hit a 429 while executing a request. + Global : ${isGlobal} + Method : ${request.method} + Path : ${request.path} + Route : ${request.route} + Limit : ${limit} + Timeout : ${timeout}ms + Sublimit: ${sublimitTimeout ? `${sublimitTimeout}ms` : 'None'}`, + ); + + await this.onRateLimit(request, limit, timeout, isGlobal); + + // If caused by a sublimit, wait it out here so other requests on the route can be handled + if (sublimitTimeout) { + await Util.delayFor(sublimitTimeout); + } return this.execute(request); } @@ -148,17 +292,17 @@ class RequestHandler { try { data = await parseResponse(res); } catch (err) { - throw new HTTPError(err.message, err.constructor.name, err.status, request.method, request.path); + throw new HTTPError(err.message, err.constructor.name, err.status, request); } - throw new DiscordAPIError(request.path, data, request.method, res.status); + throw new DiscordAPIError(data, res.status, request); } // Handle 5xx responses if (res.status >= 500 && res.status < 600) { // Retry the specified number of times for possible serverside issues if (request.retries === this.manager.client.options.retryLimit) { - throw new HTTPError(res.statusText, res.constructor.name, res.status, request.method, request.path); + throw new HTTPError(res.statusText, res.constructor.name, res.status, request); } request.retries++; diff --git a/node_modules/discord.js/src/sharding/Shard.js b/node_modules/discord.js/src/sharding/Shard.js index ecd535f6..e732686e 100644 --- a/node_modules/discord.js/src/sharding/Shard.js +++ b/node_modules/discord.js/src/sharding/Shard.js @@ -16,7 +16,7 @@ let Worker = null; class Shard extends EventEmitter { /** * @param {ShardingManager} manager Manager that is creating this shard - * @param {number} id ID of this shard + * @param {number} id The shard's id */ constructor(manager, id) { super(); @@ -31,7 +31,7 @@ class Shard extends EventEmitter { this.manager = manager; /** - * ID of the shard in the manager + * The shard's id in the manager * @type {number} */ this.id = id; @@ -40,7 +40,7 @@ class Shard extends EventEmitter { * Arguments for the shard's process (only when {@link ShardingManager#mode} is `process`) * @type {string[]} */ - this.args = manager.shardArgs || []; + this.args = manager.shardArgs ?? []; /** * Arguments for the shard's process executable (only when {@link ShardingManager#mode} is `process`) @@ -102,11 +102,11 @@ class Shard extends EventEmitter { /** * Forks a child process or creates a worker thread for the shard. * You should not need to call this manually. - * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready - * before resolving. (-1 or Infinity for no wait) + * @param {number} [timeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready + * before resolving (`-1` or `Infinity` for no wait) * @returns {Promise} */ - async spawn(spawnTimeout = 30000) { + async spawn(timeout = 30000) { if (this.process) throw new Error('SHARDING_PROCESS_EXISTS', this.id); if (this.worker) throw new Error('SHARDING_WORKER_EXISTS', this.id); @@ -127,14 +127,16 @@ class Shard extends EventEmitter { this._evals.clear(); this._fetches.clear(); + const child = this.process ?? this.worker; + /** * Emitted upon the creation of the shard's child process/worker. * @event Shard#spawn * @param {ChildProcess|Worker} process Child process/worker that was created */ - this.emit('spawn', this.process || this.worker); + this.emit('spawn', child); - if (spawnTimeout === -1 || spawnTimeout === Infinity) return this.process || this.worker; + if (timeout === -1 || timeout === Infinity) return child; await new Promise((resolve, reject) => { const cleanup = () => { clearTimeout(spawnTimeoutTimer); @@ -163,12 +165,12 @@ class Shard extends EventEmitter { reject(new Error('SHARDING_READY_TIMEOUT', this.id)); }; - const spawnTimeoutTimer = setTimeout(onTimeout, spawnTimeout); + const spawnTimeoutTimer = setTimeout(onTimeout, timeout); this.once('ready', onReady); this.once('disconnect', onDisconnect); this.once('death', onDeath); }); - return this.process || this.worker; + return child; } /** @@ -186,17 +188,24 @@ class Shard extends EventEmitter { this._handleExit(false); } + /** + * Options used to respawn a shard. + * @typedef {Object} ShardRespawnOptions + * @property {number} [delay=500] How long to wait between killing the process/worker and + * restarting it (in milliseconds) + * @property {number} [timeout=30000] The amount in milliseconds to wait until the {@link Client} + * has become ready before resolving (`-1` or `Infinity` for no wait) + */ + /** * Kills and restarts the shard's process/worker. - * @param {number} [delay=500] How long to wait between killing the process/worker and restarting it (in milliseconds) - * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready - * before resolving. (-1 or Infinity for no wait) + * @param {ShardRespawnOptions} [options] Options for respawning the shard * @returns {Promise} */ - async respawn(delay = 500, spawnTimeout) { + async respawn({ delay = 500, timeout = 30000 } = {}) { this.kill(); if (delay > 0) await Util.delayFor(delay); - return this.spawn(spawnTimeout); + return this.spawn(timeout); } /** @@ -235,10 +244,10 @@ class Shard extends EventEmitter { if (this._fetches.has(prop)) return this._fetches.get(prop); const promise = new Promise((resolve, reject) => { - const child = this.process || this.worker; + const child = this.process ?? this.worker; const listener = message => { - if (!message || message._fetchProp !== prop) return; + if (message?._fetchProp !== prop) return; child.removeListener('message', listener); this._fetches.delete(prop); resolve(message._result); @@ -269,10 +278,10 @@ class Shard extends EventEmitter { if (this._evals.has(script)) return this._evals.get(script); const promise = new Promise((resolve, reject) => { - const child = this.process || this.worker; + const child = this.process ?? this.worker; const listener = message => { - if (!message || message._eval !== script) return; + if (message?._eval !== script) return; child.removeListener('message', listener); this._evals.delete(script); if (!message._error) resolve(message._result); @@ -345,7 +354,7 @@ class Shard extends EventEmitter { // Shard is requesting an eval broadcast if (message._sEval) { const resp = { _sEval: message._sEval, _sEvalShard: message._sEvalShard }; - this.manager.broadcastEval(message._sEval, message._sEvalShard).then( + this.manager._performOnShards('eval', [message._sEval], message._sEvalShard).then( results => this.send({ ...resp, _result: results }), err => this.send({ ...resp, _error: Util.makePlainError(err) }), ); @@ -354,8 +363,8 @@ class Shard extends EventEmitter { // Shard is requesting a respawn of all shards if (message._sRespawnAll) { - const { shardDelay, respawnDelay, spawnTimeout } = message._sRespawnAll; - this.manager.respawnAll(shardDelay, respawnDelay, spawnTimeout).catch(() => { + const { shardDelay, respawnDelay, timeout } = message._sRespawnAll; + this.manager.respawnAll({ shardDelay, respawnDelay, timeout }).catch(() => { // Do nothing }); return; @@ -381,7 +390,7 @@ class Shard extends EventEmitter { * @event Shard#death * @param {ChildProcess|Worker} process Child process/worker that exited */ - this.emit('death', this.process || this.worker); + this.emit('death', this.process ?? this.worker); this.ready = false; this.process = null; diff --git a/node_modules/discord.js/src/sharding/ShardClientUtil.js b/node_modules/discord.js/src/sharding/ShardClientUtil.js index e6230421..f04a66e4 100644 --- a/node_modules/discord.js/src/sharding/ShardClientUtil.js +++ b/node_modules/discord.js/src/sharding/ShardClientUtil.js @@ -1,5 +1,6 @@ 'use strict'; +const { Error } = require('../errors'); const { Events } = require('../util/Constants'); const Util = require('../util/Util'); @@ -58,7 +59,7 @@ class ShardClientUtil { } /** - * Array of shard IDs of this client + * Array of shard ids of this client * @type {number[]} * @readonly */ @@ -108,10 +109,10 @@ class ShardClientUtil { */ fetchClientValues(prop, shard) { return new Promise((resolve, reject) => { - const parent = this.parentPort || process; + const parent = this.parentPort ?? process; const listener = message => { - if (!message || message._sFetchProp !== prop || message._sFetchPropShard !== shard) return; + if (message?._sFetchProp !== prop || message._sFetchPropShard !== shard) return; parent.removeListener('message', listener); if (!message._error) resolve(message._result); else reject(Util.makeError(message._error)); @@ -127,29 +128,33 @@ class ShardClientUtil { /** * Evaluates a script or function on all shards, or a given shard, in the context of the {@link Client}s. - * @param {string|Function} script JavaScript to run on each shard - * @param {number} [shard] Shard to run script on, all if undefined + * @param {Function} script JavaScript to run on each shard + * @param {BroadcastEvalOptions} [options={}] The options for the broadcast * @returns {Promise<*>|Promise>} Results of the script execution * @example - * client.shard.broadcastEval('this.guilds.cache.size') + * client.shard.broadcastEval(client => client.guilds.cache.size) * .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`)) * .catch(console.error); * @see {@link ShardingManager#broadcastEval} */ - broadcastEval(script, shard) { + broadcastEval(script, options = {}) { return new Promise((resolve, reject) => { - const parent = this.parentPort || process; - script = typeof script === 'function' ? `(${script})(this)` : script; + const parent = this.parentPort ?? process; + if (typeof script !== 'function') { + reject(new TypeError('SHARDING_INVALID_EVAL_BROADCAST')); + return; + } + script = `(${script})(this, ${JSON.stringify(options.context)})`; const listener = message => { - if (!message || message._sEval !== script || message._sEvalShard !== shard) return; + if (message?._sEval !== script || message._sEvalShard !== options.shard) return; parent.removeListener('message', listener); if (!message._error) resolve(message._result); else reject(Util.makeError(message._error)); }; parent.on('message', listener); - this.send({ _sEval: script, _sEvalShard: shard }).catch(err => { + this.send({ _sEval: script, _sEvalShard: options.shard }).catch(err => { parent.removeListener('message', listener); reject(err); }); @@ -158,16 +163,12 @@ class ShardClientUtil { /** * Requests a respawn of all shards. - * @param {number} [shardDelay=5000] How long to wait between shards (in milliseconds) - * @param {number} [respawnDelay=500] How long to wait between killing a shard's process/worker and restarting it - * (in milliseconds) - * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait for a shard to become ready before - * continuing to another. (-1 or Infinity for no wait) + * @param {MultipleShardRespawnOptions} [options] Options for respawning shards * @returns {Promise} Resolves upon the message being sent * @see {@link ShardingManager#respawnAll} */ - respawnAll(shardDelay = 5000, respawnDelay = 500, spawnTimeout = 30000) { - return this.send({ _sRespawnAll: { shardDelay, respawnDelay, spawnTimeout } }); + respawnAll({ shardDelay = 5000, respawnDelay = 500, timeout = 30000 } = {}) { + return this.send({ _sRespawnAll: { shardDelay, respawnDelay, timeout } }); } /** @@ -199,13 +200,14 @@ class ShardClientUtil { */ _respond(type, message) { this.send(message).catch(err => { - err.message = `Error when sending ${type} response to master process: ${err.message}`; + const error = new Error(`Error when sending ${type} response to master process: ${err.message}`); + error.stack = err.stack; /** * Emitted when the client encounters an error. * @event Client#error * @param {Error} error The error encountered */ - this.client.emit(Events.ERROR, err); + this.client.emit(Events.ERROR, error); }); } @@ -228,14 +230,14 @@ class ShardClientUtil { } /** - * Get the shard ID for a given guild ID. - * @param {Snowflake} guildID Snowflake guild ID to get shard ID for + * Get the shard id for a given guild id. + * @param {Snowflake} guildId Snowflake guild id to get shard id for * @param {number} shardCount Number of shards * @returns {number} */ - static shardIDForGuildID(guildID, shardCount) { - const shard = Number(BigInt(guildID) >> 22n) % shardCount; - if (shard < 0) throw new Error('SHARDING_SHARD_MISCALCULATION', shard, guildID, shardCount); + static shardIdForGuildId(guildId, shardCount) { + const shard = Number(BigInt(guildId) >> 22n) % shardCount; + if (shard < 0) throw new Error('SHARDING_SHARD_MISCALCULATION', shard, guildId, shardCount); return shard; } } diff --git a/node_modules/discord.js/src/sharding/ShardingManager.js b/node_modules/discord.js/src/sharding/ShardingManager.js index 9007c593..44bd4187 100644 --- a/node_modules/discord.js/src/sharding/ShardingManager.js +++ b/node_modules/discord.js/src/sharding/ShardingManager.js @@ -3,9 +3,9 @@ const EventEmitter = require('events'); const fs = require('fs'); const path = require('path'); +const { Collection } = require('@discordjs/collection'); const Shard = require('./Shard'); const { Error, TypeError, RangeError } = require('../errors'); -const Collection = require('../util/Collection'); const Util = require('../util/Util'); /** @@ -19,23 +19,28 @@ const Util = require('../util/Util'); */ class ShardingManager extends EventEmitter { /** - * The mode to spawn shards with for a {@link ShardingManager}: either "process" to use child processes, or + * The mode to spawn shards with for a {@link ShardingManager}. Either "process" to use child processes, or * "worker" to use [Worker threads](https://nodejs.org/api/worker_threads.html). - * @typedef {Object} ShardingManagerMode + * @typedef {string} ShardingManagerMode + */ + + /** + * The options to spawn shards with for a {@link ShardingManager}. + * @typedef {Object} ShardingManagerOptions + * @property {string|number} [totalShards='auto'] Number of total shards of all shard managers or "auto" + * @property {string|number[]} [shardList='auto'] List of shards to spawn or "auto" + * @property {ShardingManagerMode} [mode='process'] Which mode to use for shards + * @property {boolean} [respawn=true] Whether shards should automatically respawn upon exiting + * @property {string[]} [shardArgs=[]] Arguments to pass to the shard script when spawning + * (only available when mode is set to 'process') + * @property {string} [execArgv=[]] Arguments to pass to the shard script executable when spawning + * (only available when mode is set to 'process') + * @property {string} [token] Token to use for automatic shard count and passing to shards */ /** * @param {string} file Path to your shard script file - * @param {Object} [options] Options for the sharding manager - * @param {string|number} [options.totalShards='auto'] Number of total shards of all shard managers or "auto" - * @param {string|number[]} [options.shardList='auto'] List of shards to spawn or "auto" - * @param {ShardingManagerMode} [options.mode='process'] Which mode to use for shards - * @param {boolean} [options.respawn=true] Whether shards should automatically respawn upon exiting - * @param {string[]} [options.shardArgs=[]] Arguments to pass to the shard script when spawning - * (only available when using the `process` mode) - * @param {string[]} [options.execArgv=[]] Arguments to pass to the shard script executable when spawning - * (only available when using the `process` mode) - * @param {string} [options.token] Token to use for automatic shard count and passing to shards + * @param {ShardingManagerOptions} [options] Options for the sharding manager */ constructor(file, options = {}) { super(); @@ -65,16 +70,16 @@ class ShardingManager extends EventEmitter { * List of shards this sharding manager spawns * @type {string|number[]} */ - this.shardList = options.shardList || 'auto'; + this.shardList = options.shardList ?? 'auto'; if (this.shardList !== 'auto') { if (!Array.isArray(this.shardList)) { throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array.'); } this.shardList = [...new Set(this.shardList)]; - if (this.shardList.length < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'shardList', 'at least 1 ID.'); + if (this.shardList.length < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'shardList', 'at least 1 id.'); if ( this.shardList.some( - shardID => typeof shardID !== 'number' || isNaN(shardID) || !Number.isInteger(shardID) || shardID < 0, + shardId => typeof shardId !== 'number' || isNaN(shardId) || !Number.isInteger(shardId) || shardId < 0, ) ) { throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array of positive integers.'); @@ -127,7 +132,7 @@ class ShardingManager extends EventEmitter { * Token to use for obtaining the automatic shard count, and passing to shards * @type {?string} */ - this.token = options.token ? options.token.replace(/^Bot\s*/i, '') : null; + this.token = options.token?.replace(/^Bot\s*/i, '') ?? null; /** * A collection of shards that this manager has spawned @@ -143,7 +148,7 @@ class ShardingManager extends EventEmitter { /** * Creates a single shard. * Using this method is usually not necessary if you use the spawn method. - * @param {number} [id=this.shards.size] ID of the shard to create + * @param {number} [id=this.shards.size] Id of the shard to create * This is usually not necessary to manually specify. * @returns {Shard} Note that the created shard needs to be explicitly spawned using its spawn method. */ @@ -159,15 +164,20 @@ class ShardingManager extends EventEmitter { return shard; } + /** + * Option used to spawn multiple shards. + * @typedef {Object} MultipleShardSpawnOptions + * @property {number|string} [amount=this.totalShards] Number of shards to spawn + * @property {number} [delay=5500] How long to wait in between spawning each shard (in milliseconds) + * @property {number} [timeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready + */ + /** * Spawns multiple shards. - * @param {number|string} [amount=this.totalShards] Number of shards to spawn - * @param {number} [delay=5500] How long to wait in between spawning each shard (in milliseconds) - * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready - * before resolving. (-1 or Infinity for no wait) + * @param {MultipleShardSpawnOptions} [options] Options for spawning shards * @returns {Promise>} */ - async spawn(amount = this.totalShards, delay = 5500, spawnTimeout) { + async spawn({ amount = this.totalShards, delay = 5500, timeout = 30000 } = {}) { // Obtain/verify the number of shards to spawn if (amount === 'auto') { amount = await Util.fetchRecommendedShards(this.token); @@ -190,19 +200,19 @@ class ShardingManager extends EventEmitter { this.totalShards = amount; } - if (this.shardList.some(shardID => shardID >= amount)) { + if (this.shardList.some(shardId => shardId >= amount)) { throw new RangeError( 'CLIENT_INVALID_OPTION', 'Amount of shards', - 'bigger than the highest shardID in the shardList option.', + 'bigger than the highest shardId in the shardList option.', ); } // Spawn the shards - for (const shardID of this.shardList) { + for (const shardId of this.shardList) { const promises = []; - const shard = this.createShard(shardID); - promises.push(shard.spawn(spawnTimeout)); + const shard = this.createShard(shardId); + promises.push(shard.spawn(timeout)); if (delay > 0 && this.shards.size !== this.shardList.length) promises.push(Util.delayFor(delay)); await Promise.all(promises); // eslint-disable-line no-await-in-loop } @@ -221,14 +231,22 @@ class ShardingManager extends EventEmitter { return Promise.all(promises); } + /** + * Options for {@link ShardingManager#broadcastEval} and {@link ShardClientUtil#broadcastEval}. + * @typedef {Object} BroadcastEvalOptions + * @property {number} [shard] Shard to run script on, all if undefined + * @property {*} [context] The JSON-serializable values to call the script with + */ + /** * Evaluates a script on all shards, or a given shard, in the context of the {@link Client}s. - * @param {string} script JavaScript to run on each shard - * @param {number} [shard] Shard to run on, all if undefined + * @param {Function} script JavaScript to run on each shard + * @param {BroadcastEvalOptions} [options={}] The options for the broadcast * @returns {Promise<*>|Promise>} Results of the script execution */ - broadcastEval(script, shard) { - return this._performOnShards('eval', [script], shard); + broadcastEval(script, options = {}) { + if (typeof script !== 'function') return Promise.reject(new TypeError('SHARDING_INVALID_EVAL_BROADCAST')); + return this._performOnShards('eval', [`(${script})(this, ${JSON.stringify(options.context)})`], options.shard); } /** @@ -255,31 +273,38 @@ class ShardingManager extends EventEmitter { */ _performOnShards(method, args, shard) { if (this.shards.size === 0) return Promise.reject(new Error('SHARDING_NO_SHARDS')); - if (this.shards.size !== this.shardList.length) return Promise.reject(new Error('SHARDING_IN_PROCESS')); if (typeof shard === 'number') { if (this.shards.has(shard)) return this.shards.get(shard)[method](...args); return Promise.reject(new Error('SHARDING_SHARD_NOT_FOUND', shard)); } + if (this.shards.size !== this.shardList.length) return Promise.reject(new Error('SHARDING_IN_PROCESS')); + const promises = []; for (const sh of this.shards.values()) promises.push(sh[method](...args)); return Promise.all(promises); } /** - * Kills all running shards and respawns them. - * @param {number} [shardDelay=5000] How long to wait between shards (in milliseconds) - * @param {number} [respawnDelay=500] How long to wait between killing a shard's process and restarting it + * Options used to respawn all shards. + * @typedef {Object} MultipleShardRespawnOptions + * @property {number} [shardDelay=5000] How long to wait between shards (in milliseconds) + * @property {number} [respawnDelay=500] How long to wait between killing a shard's process and restarting it * (in milliseconds) - * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait for a shard to become ready before - * continuing to another. (-1 or Infinity for no wait) + * @property {number} [timeout=30000] The amount in milliseconds to wait for a shard to become ready before + * continuing to another (`-1` or `Infinity` for no wait) + */ + + /** + * Kills all running shards and respawns them. + * @param {MultipleShardRespawnOptions} [options] Options for respawning shards * @returns {Promise>} */ - async respawnAll(shardDelay = 5000, respawnDelay = 500, spawnTimeout) { + async respawnAll({ shardDelay = 5000, respawnDelay = 500, timeout = 30000 } = {}) { let s = 0; for (const shard of this.shards.values()) { - const promises = [shard.respawn(respawnDelay, spawnTimeout)]; + const promises = [shard.respawn({ respawnDelay, timeout })]; if (++s < this.shards.size && shardDelay > 0) promises.push(Util.delayFor(shardDelay)); await Promise.all(promises); // eslint-disable-line no-await-in-loop } diff --git a/node_modules/discord.js/src/structures/APIMessage.js b/node_modules/discord.js/src/structures/APIMessage.js deleted file mode 100644 index 3451bdb9..00000000 --- a/node_modules/discord.js/src/structures/APIMessage.js +++ /dev/null @@ -1,396 +0,0 @@ -'use strict'; - -const MessageAttachment = require('./MessageAttachment'); -const MessageEmbed = require('./MessageEmbed'); -const { RangeError } = require('../errors'); -const { browser } = require('../util/Constants'); -const DataResolver = require('../util/DataResolver'); -const MessageFlags = require('../util/MessageFlags'); -const Util = require('../util/Util'); - -/** - * Represents a message to be sent to the API. - */ -class APIMessage { - /** - * @param {MessageTarget} target - The target for this message to be sent to - * @param {MessageOptions|WebhookMessageOptions} options - Options passed in from send - */ - constructor(target, options) { - /** - * The target for this message to be sent to - * @type {MessageTarget} - */ - this.target = target; - - /** - * Options passed in from send - * @type {MessageOptions|WebhookMessageOptions} - */ - this.options = options; - - /** - * Data sendable to the API - * @type {?Object} - */ - this.data = null; - - /** - * Files sendable to the API - * @type {?Object[]} - */ - this.files = null; - } - - /** - * Whether or not the target is a webhook - * @type {boolean} - * @readonly - */ - get isWebhook() { - const Webhook = require('./Webhook'); - const WebhookClient = require('../client/WebhookClient'); - return this.target instanceof Webhook || this.target instanceof WebhookClient; - } - - /** - * Whether or not the target is a user - * @type {boolean} - * @readonly - */ - get isUser() { - const User = require('./User'); - const GuildMember = require('./GuildMember'); - return this.target instanceof User || this.target instanceof GuildMember; - } - - /** - * Whether or not the target is a message - * @type {boolean} - * @readonly - */ - get isMessage() { - const Message = require('./Message'); - return this.target instanceof Message; - } - - /** - * Makes the content of this message. - * @returns {?(string|string[])} - */ - makeContent() { - const GuildMember = require('./GuildMember'); - - let content; - if (this.options.content === null) { - content = ''; - } else if (typeof this.options.content !== 'undefined') { - content = Util.resolveString(this.options.content); - } - - if (typeof content !== 'string') return content; - - const disableMentions = - typeof this.options.disableMentions === 'undefined' - ? this.target.client.options.disableMentions - : this.options.disableMentions; - if (disableMentions === 'all') { - content = Util.removeMentions(content); - } else if (disableMentions === 'everyone') { - content = content.replace(/@([^<>@ ]*)/gmsu, (match, target) => { - if (target.match(/^[&!]?\d+$/)) { - return `@${target}`; - } else { - return `@\u200b${target}`; - } - }); - } - - const isSplit = typeof this.options.split !== 'undefined' && this.options.split !== false; - const isCode = typeof this.options.code !== 'undefined' && this.options.code !== false; - const splitOptions = isSplit ? { ...this.options.split } : undefined; - - let mentionPart = ''; - if (this.options.reply && !this.isUser && this.target.type !== 'dm') { - const id = this.target.client.users.resolveID(this.options.reply); - mentionPart = `<@${this.options.reply instanceof GuildMember && this.options.reply.nickname ? '!' : ''}${id}>, `; - if (isSplit) { - splitOptions.prepend = `${mentionPart}${splitOptions.prepend || ''}`; - } - } - - if (content || mentionPart) { - if (isCode) { - const codeName = typeof this.options.code === 'string' ? this.options.code : ''; - content = `${mentionPart}\`\`\`${codeName}\n${Util.cleanCodeBlockContent(content)}\n\`\`\``; - if (isSplit) { - splitOptions.prepend = `${splitOptions.prepend || ''}\`\`\`${codeName}\n`; - splitOptions.append = `\n\`\`\`${splitOptions.append || ''}`; - } - } else if (mentionPart) { - content = `${mentionPart}${content}`; - } - - if (isSplit) { - content = Util.splitMessage(content, splitOptions); - } - } - - return content; - } - - /** - * Resolves data. - * @returns {APIMessage} - */ - resolveData() { - if (this.data) return this; - - const content = this.makeContent(); - const tts = Boolean(this.options.tts); - - let nonce; - if (typeof this.options.nonce !== 'undefined') { - nonce = parseInt(this.options.nonce); - if (isNaN(nonce) || nonce < 0) throw new RangeError('MESSAGE_NONCE_TYPE'); - } - - const embedLikes = []; - if (this.isWebhook) { - if (this.options.embeds) { - embedLikes.push(...this.options.embeds); - } - } else if (this.options.embed) { - embedLikes.push(this.options.embed); - } - const embeds = embedLikes.map(e => new MessageEmbed(e).toJSON()); - - let username; - let avatarURL; - if (this.isWebhook) { - username = this.options.username || this.target.name; - if (this.options.avatarURL) avatarURL = this.options.avatarURL; - } - - let flags; - if (this.isMessage) { - // eslint-disable-next-line eqeqeq - flags = this.options.flags != null ? new MessageFlags(this.options.flags).bitfield : this.target.flags.bitfield; - } - - let allowedMentions = - typeof this.options.allowedMentions === 'undefined' - ? this.target.client.options.allowedMentions - : this.options.allowedMentions; - if (this.options.reply) { - const id = this.target.client.users.resolveID(this.options.reply); - if (allowedMentions) { - // Clone the object as not to alter the ClientOptions object - allowedMentions = Util.cloneObject(allowedMentions); - const parsed = allowedMentions.parse && allowedMentions.parse.includes('users'); - // Check if the mention won't be parsed, and isn't supplied in `users` - if (!parsed && !(allowedMentions.users && allowedMentions.users.includes(id))) { - if (!allowedMentions.users) allowedMentions.users = []; - allowedMentions.users.push(id); - } - } else { - allowedMentions = { users: [id] }; - } - } - - this.data = { - content, - tts, - nonce, - embed: this.options.embed === null ? null : embeds[0], - embeds, - username, - avatar_url: avatarURL, - allowed_mentions: typeof content === 'undefined' ? undefined : allowedMentions, - flags, - }; - return this; - } - - /** - * Resolves files. - * @returns {Promise} - */ - async resolveFiles() { - if (this.files) return this; - - const embedLikes = []; - if (this.isWebhook) { - if (this.options.embeds) { - embedLikes.push(...this.options.embeds); - } - } else if (this.options.embed) { - embedLikes.push(this.options.embed); - } - - const fileLikes = []; - if (this.options.files) { - fileLikes.push(...this.options.files); - } - for (const embed of embedLikes) { - if (embed.files) { - fileLikes.push(...embed.files); - } - } - - this.files = await Promise.all(fileLikes.map(f => this.constructor.resolveFile(f))); - return this; - } - - /** - * Converts this APIMessage into an array of APIMessages for each split content - * @returns {APIMessage[]} - */ - split() { - if (!this.data) this.resolveData(); - - if (!Array.isArray(this.data.content)) return [this]; - - const apiMessages = []; - - for (let i = 0; i < this.data.content.length; i++) { - let data; - let opt; - - if (i === this.data.content.length - 1) { - data = { ...this.data, content: this.data.content[i] }; - opt = { ...this.options, content: this.data.content[i] }; - } else { - data = { content: this.data.content[i], tts: this.data.tts, allowed_mentions: this.options.allowedMentions }; - opt = { content: this.data.content[i], tts: this.data.tts, allowedMentions: this.options.allowedMentions }; - } - - const apiMessage = new APIMessage(this.target, opt); - apiMessage.data = data; - apiMessages.push(apiMessage); - } - - return apiMessages; - } - - /** - * Resolves a single file into an object sendable to the API. - * @param {BufferResolvable|Stream|FileOptions|MessageAttachment} fileLike Something that could be resolved to a file - * @returns {Object} - */ - static async resolveFile(fileLike) { - let attachment; - let name; - - const findName = thing => { - if (typeof thing === 'string') { - return Util.basename(thing); - } - - if (thing.path) { - return Util.basename(thing.path); - } - - return 'file.jpg'; - }; - - const ownAttachment = - typeof fileLike === 'string' || - fileLike instanceof (browser ? ArrayBuffer : Buffer) || - typeof fileLike.pipe === 'function'; - if (ownAttachment) { - attachment = fileLike; - name = findName(attachment); - } else { - attachment = fileLike.attachment; - name = fileLike.name || findName(attachment); - } - - const resource = await DataResolver.resolveFile(attachment); - return { attachment, name, file: resource }; - } - - /** - * Partitions embeds and attachments. - * @param {Array} items Items to partition - * @returns {Array} - */ - static partitionMessageAdditions(items) { - const embeds = []; - const files = []; - for (const item of items) { - if (item instanceof MessageEmbed) { - embeds.push(item); - } else if (item instanceof MessageAttachment) { - files.push(item); - } - } - - return [embeds, files]; - } - - /** - * Transforms the user-level arguments into a final options object. Passing a transformed options object alone into - * this method will keep it the same, allowing for the reuse of the final options object. - * @param {StringResolvable} [content] Content to send - * @param {MessageOptions|WebhookMessageOptions|MessageAdditions} [options={}] Options to use - * @param {MessageOptions|WebhookMessageOptions} [extra={}] Extra options to add onto transformed options - * @param {boolean} [isWebhook=false] Whether or not to use WebhookMessageOptions as the result - * @returns {MessageOptions|WebhookMessageOptions} - */ - static transformOptions(content, options, extra = {}, isWebhook = false) { - if (!options && typeof content === 'object' && !Array.isArray(content)) { - options = content; - content = undefined; - } - - if (!options) { - options = {}; - } else if (options instanceof MessageEmbed) { - return isWebhook ? { content, embeds: [options], ...extra } : { content, embed: options, ...extra }; - } else if (options instanceof MessageAttachment) { - return { content, files: [options], ...extra }; - } - - if (Array.isArray(options)) { - const [embeds, files] = this.partitionMessageAdditions(options); - return isWebhook ? { content, embeds, files, ...extra } : { content, embed: embeds[0], files, ...extra }; - } else if (Array.isArray(content)) { - const [embeds, files] = this.partitionMessageAdditions(content); - if (embeds.length || files.length) { - return isWebhook ? { embeds, files, ...extra } : { embed: embeds[0], files, ...extra }; - } - } - - return { content, ...options, ...extra }; - } - - /** - * Creates an `APIMessage` from user-level arguments. - * @param {MessageTarget} target Target to send to - * @param {StringResolvable} [content] Content to send - * @param {MessageOptions|WebhookMessageOptions|MessageAdditions} [options={}] Options to use - * @param {MessageOptions|WebhookMessageOptions} [extra={}] - Extra options to add onto transformed options - * @returns {MessageOptions|WebhookMessageOptions} - */ - static create(target, content, options, extra = {}) { - const Webhook = require('./Webhook'); - const WebhookClient = require('../client/WebhookClient'); - - const isWebhook = target instanceof Webhook || target instanceof WebhookClient; - const transformed = this.transformOptions(content, options, extra, isWebhook); - return new this(target, transformed); - } -} - -module.exports = APIMessage; - -/** - * A target for a message. - * @typedef {TextChannel|DMChannel|User|GuildMember|Webhook|WebhookClient} MessageTarget - */ - -/** - * Additional items that can be sent with a message. - * @typedef {MessageEmbed|MessageAttachment|Array} MessageAdditions - */ diff --git a/node_modules/discord.js/src/structures/BaseGuildEmoji.js b/node_modules/discord.js/src/structures/BaseGuildEmoji.js index a2007c67..f7245f62 100644 --- a/node_modules/discord.js/src/structures/BaseGuildEmoji.js +++ b/node_modules/discord.js/src/structures/BaseGuildEmoji.js @@ -17,18 +17,10 @@ class BaseGuildEmoji extends Emoji { */ this.guild = guild; - this.requireColons = null; + this.requiresColons = null; this.managed = null; this.available = null; - /** - * Array of role ids this emoji is active for - * @name BaseGuildEmoji#_roles - * @type {Snowflake[]} - * @private - */ - Object.defineProperty(this, '_roles', { value: [], writable: true }); - this._patch(data); } @@ -58,8 +50,6 @@ class BaseGuildEmoji extends Emoji { */ this.available = data.available; } - - if (data.roles) this._roles = data.roles; } } diff --git a/node_modules/discord.js/src/structures/CategoryChannel.js b/node_modules/discord.js/src/structures/CategoryChannel.js index 4ba01406..c5727bb0 100644 --- a/node_modules/discord.js/src/structures/CategoryChannel.js +++ b/node_modules/discord.js/src/structures/CategoryChannel.js @@ -13,7 +13,7 @@ class CategoryChannel extends GuildChannel { * @readonly */ get children() { - return this.guild.channels.cache.filter(c => c.parentID === this.id); + return this.guild.channels.cache.filter(c => c.parentId === this.id); } /** @@ -22,10 +22,8 @@ class CategoryChannel extends GuildChannel { * @method setParent * @memberof CategoryChannel * @instance - * @param {?GuildChannel|Snowflake} channel Parent channel - * @param {Object} [options={}] Options to pass - * @param {boolean} [options.lockPermissions=true] Lock the permissions to what the parent's permissions are - * @param {string} [options.reason] Reason for modifying the parent of this channel + * @param {?CategoryChannelResolvable} channel The channel to set as parent + * @param {SetParentOptions} [options={}] The options for setting the parent * @returns {Promise} */ } diff --git a/node_modules/discord.js/src/structures/Channel.js b/node_modules/discord.js/src/structures/Channel.js index baa02ee6..40c154e9 100644 --- a/node_modules/discord.js/src/structures/Channel.js +++ b/node_modules/discord.js/src/structures/Channel.js @@ -1,8 +1,16 @@ 'use strict'; const Base = require('./Base'); -const { ChannelTypes } = require('../util/Constants'); -const Snowflake = require('../util/Snowflake'); +let CategoryChannel; +let DMChannel; +let NewsChannel; +let StageChannel; +let StoreChannel; +let TextChannel; +let ThreadChannel; +let VoiceChannel; +const { ChannelTypes, ThreadChannelTypes } = require('../util/Constants'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); /** * Represents any channel on Discord. @@ -10,22 +18,15 @@ const Snowflake = require('../util/Snowflake'); * @abstract */ class Channel extends Base { - constructor(client, data) { + constructor(client, data, immediatePatch = true) { super(client); - const type = Object.keys(ChannelTypes)[data.type]; + const type = ChannelTypes[data.type]; /** - * The type of the channel, either: - * * `dm` - a DM channel - * * `text` - a guild text channel - * * `voice` - a guild voice channel - * * `category` - a guild category channel - * * `news` - a guild news channel - * * `store` - a guild store channel - * * `unknown` - a generic channel of unknown type, could be Channel or GuildChannel - * @type {string} + * The type of the channel + * @type {ChannelType} */ - this.type = type ? type.toLowerCase() : 'unknown'; + this.type = type ?? 'UNKNOWN'; /** * Whether the channel has been deleted @@ -33,12 +34,12 @@ class Channel extends Base { */ this.deleted = false; - if (data) this._patch(data); + if (data && immediatePatch) this._patch(data); } _patch(data) { /** - * The unique ID of the channel + * The channel's id * @type {Snowflake} */ this.id = data.id; @@ -50,7 +51,7 @@ class Channel extends Base { * @readonly */ get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; + return SnowflakeUtil.deconstruct(this.id).timestamp; } /** @@ -62,6 +63,16 @@ class Channel extends Base { return new Date(this.createdTimestamp); } + /** + * Whether this Channel is a partial + * This is always false outside of DM channels. + * @type {boolean} + * @readonly + */ + get partial() { + return false; + } + /** * When concatenated with a string, this automatically returns the channel's mention instead of the Channel object. * @returns {string} @@ -91,63 +102,86 @@ class Channel extends Base { /** * Fetches this channel. - * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @param {boolean} [force=true] Whether to skip the cache check and request the API * @returns {Promise} */ - fetch(force = false) { - return this.client.channels.fetch(this.id, true, force); + fetch(force = true) { + return this.client.channels.fetch(this.id, { force }); } /** - * Indicates whether this channel is text-based. + * Indicates whether this channel is text-based + * ({@link TextChannel}, {@link DMChannel}, {@link NewsChannel} or {@link ThreadChannel}). * @returns {boolean} */ isText() { return 'messages' in this; } - static create(client, data, guild) { - const Structures = require('../util/Structures'); + /** + * Indicates whether this channel is a {@link ThreadChannel}. + * @returns {boolean} + */ + isThread() { + return ThreadChannelTypes.includes(this.type); + } + + static create(client, data, guild, { allowUnknownGuild, fromInteraction } = {}) { + if (!CategoryChannel) CategoryChannel = require('./CategoryChannel'); + if (!DMChannel) DMChannel = require('./DMChannel'); + if (!NewsChannel) NewsChannel = require('./NewsChannel'); + if (!StageChannel) StageChannel = require('./StageChannel'); + if (!StoreChannel) StoreChannel = require('./StoreChannel'); + if (!TextChannel) TextChannel = require('./TextChannel'); + if (!ThreadChannel) ThreadChannel = require('./ThreadChannel'); + if (!VoiceChannel) VoiceChannel = require('./VoiceChannel'); + let channel; if (!data.guild_id && !guild) { - if ((data.recipients && data.type !== ChannelTypes.GROUP) || data.type === ChannelTypes.DM) { - const DMChannel = Structures.get('DMChannel'); + if ((data.recipients && data.type !== ChannelTypes.GROUP_DM) || data.type === ChannelTypes.DM) { channel = new DMChannel(client, data); - } else if (data.type === ChannelTypes.GROUP) { + } else if (data.type === ChannelTypes.GROUP_DM) { const PartialGroupDMChannel = require('./PartialGroupDMChannel'); channel = new PartialGroupDMChannel(client, data); } } else { - guild = guild || client.guilds.cache.get(data.guild_id); - if (guild) { + if (!guild) guild = client.guilds.cache.get(data.guild_id); + + if (guild || allowUnknownGuild) { switch (data.type) { - case ChannelTypes.TEXT: { - const TextChannel = Structures.get('TextChannel'); - channel = new TextChannel(guild, data); + case ChannelTypes.GUILD_TEXT: { + channel = new TextChannel(guild, data, client); break; } - case ChannelTypes.VOICE: { - const VoiceChannel = Structures.get('VoiceChannel'); - channel = new VoiceChannel(guild, data); + case ChannelTypes.GUILD_VOICE: { + channel = new VoiceChannel(guild, data, client); break; } - case ChannelTypes.CATEGORY: { - const CategoryChannel = Structures.get('CategoryChannel'); - channel = new CategoryChannel(guild, data); + case ChannelTypes.GUILD_CATEGORY: { + channel = new CategoryChannel(guild, data, client); break; } - case ChannelTypes.NEWS: { - const NewsChannel = Structures.get('NewsChannel'); - channel = new NewsChannel(guild, data); + case ChannelTypes.GUILD_NEWS: { + channel = new NewsChannel(guild, data, client); break; } - case ChannelTypes.STORE: { - const StoreChannel = Structures.get('StoreChannel'); - channel = new StoreChannel(guild, data); + case ChannelTypes.GUILD_STORE: { + channel = new StoreChannel(guild, data, client); + break; + } + case ChannelTypes.GUILD_STAGE_VOICE: { + channel = new StageChannel(guild, data, client); + break; + } + case ChannelTypes.GUILD_NEWS_THREAD: + case ChannelTypes.GUILD_PUBLIC_THREAD: + case ChannelTypes.GUILD_PRIVATE_THREAD: { + channel = new ThreadChannel(guild, data, client, fromInteraction); + if (!allowUnknownGuild) channel.parent?.threads.cache.set(channel.id, channel); break; } } - if (channel) guild.channels.cache.set(channel.id, channel); + if (channel && !allowUnknownGuild) guild.channels?.cache.set(channel.id, channel); } } return channel; @@ -159,3 +193,8 @@ class Channel extends Base { } module.exports = Channel; + +/** + * @external APIChannel + * @see {@link https://discord.com/developers/docs/resources/channel#channel-object} + */ diff --git a/node_modules/discord.js/src/structures/ClientApplication.js b/node_modules/discord.js/src/structures/ClientApplication.js index 7e35b9ea..4eb95a6c 100644 --- a/node_modules/discord.js/src/structures/ClientApplication.js +++ b/node_modules/discord.js/src/structures/ClientApplication.js @@ -2,44 +2,85 @@ const Team = require('./Team'); const Application = require('./interfaces/Application'); +const ApplicationCommandManager = require('../managers/ApplicationCommandManager'); +const ApplicationFlags = require('../util/ApplicationFlags'); /** * Represents a Client OAuth2 Application. * @extends {Application} */ class ClientApplication extends Application { + constructor(client, data) { + super(client, data); + + /** + * The application command manager for this application + * @type {ApplicationCommandManager} + */ + this.commands = new ApplicationCommandManager(this.client); + } + _patch(data) { super._patch(data); /** - * The app's cover image + * The flags this application has + * @type {ApplicationFlags} + */ + this.flags = 'flags' in data ? new ApplicationFlags(data.flags).freeze() : this.flags; + + /** + * The hash of the application's cover image * @type {?string} */ - this.cover = data.cover_image || null; + this.cover = data.cover_image ?? this.cover ?? null; /** - * The app's RPC origins, if enabled + * The application's RPC origins, if enabled * @type {string[]} */ - this.rpcOrigins = data.rpc_origins || []; + this.rpcOrigins = data.rpc_origins ?? this.rpcOrigins ?? []; /** - * If this app's bot requires a code grant when using the OAuth2 flow + * If this application's bot requires a code grant when using the OAuth2 flow * @type {?boolean} */ - this.botRequireCodeGrant = typeof data.bot_require_code_grant !== 'undefined' ? data.bot_require_code_grant : null; + this.botRequireCodeGrant = data.bot_require_code_grant ?? this.botRequireCodeGrant ?? null; /** - * If this app's bot is public + * If this application's bot is public * @type {?boolean} */ - this.botPublic = typeof data.bot_public !== 'undefined' ? data.bot_public : null; + this.botPublic = data.bot_public ?? this.botPublic ?? null; /** * The owner of this OAuth application - * @type {?User|Team} + * @type {?(User|Team)} */ - this.owner = data.team ? new Team(this.client, data.team) : data.owner ? this.client.users.add(data.owner) : null; + this.owner = data.team + ? new Team(this.client, data.team) + : data.owner + ? this.client.users._add(data.owner) + : this.owner ?? null; + } + + /** + * Whether this application is partial + * @type {boolean} + * @readonly + */ + get partial() { + return !this.name; + } + + /** + * Obtains this application from Discord. + * @returns {Promise} + */ + async fetch() { + const app = await this.client.api.oauth2.applications('@me').get(); + this._patch(app); + return this; } } diff --git a/node_modules/discord.js/src/structures/ClientPresence.js b/node_modules/discord.js/src/structures/ClientPresence.js index a39ba006..f276c019 100644 --- a/node_modules/discord.js/src/structures/ClientPresence.js +++ b/node_modules/discord.js/src/structures/ClientPresence.js @@ -2,85 +2,61 @@ const { Presence } = require('./Presence'); const { TypeError } = require('../errors'); -const Collection = require('../util/Collection'); -const { ActivityTypes, OPCodes } = require('../util/Constants'); +const { ActivityTypes, Opcodes } = require('../util/Constants'); class ClientPresence extends Presence { /** * @param {Client} client The instantiating client - * @param {Object} [data={}] The data for the client presence + * @param {APIPresence} [data={}] The data for the client presence */ constructor(client, data = {}) { - super(client, Object.assign(data, { status: 'online', user: { id: null } })); + super(client, Object.assign(data, { status: data.status ?? 'online', user: { id: null } })); } - async set(presence) { - const packet = await this._parse(presence); - this.patch(packet); - if (typeof presence.shardID === 'undefined') { - this.client.ws.broadcast({ op: OPCodes.STATUS_UPDATE, d: packet }); - } else if (Array.isArray(presence.shardID)) { - for (const shardID of presence.shardID) { - this.client.ws.shards.get(shardID).send({ op: OPCodes.STATUS_UPDATE, d: packet }); + set(presence) { + const packet = this._parse(presence); + this._patch(packet); + if (typeof presence.shardId === 'undefined') { + this.client.ws.broadcast({ op: Opcodes.STATUS_UPDATE, d: packet }); + } else if (Array.isArray(presence.shardId)) { + for (const shardId of presence.shardId) { + this.client.ws.shards.get(shardId).send({ op: Opcodes.STATUS_UPDATE, d: packet }); } } else { - this.client.ws.shards.get(presence.shardID).send({ op: OPCodes.STATUS_UPDATE, d: packet }); + this.client.ws.shards.get(presence.shardId).send({ op: Opcodes.STATUS_UPDATE, d: packet }); } return this; } - async _parse({ status, since, afk, activity }) { - const applicationID = activity && (activity.application ? activity.application.id || activity.application : null); - let assets = new Collection(); - if (activity) { - if (typeof activity.name !== 'string') throw new TypeError('INVALID_TYPE', 'name', 'string'); - if (!activity.type) activity.type = 0; - if (activity.assets && applicationID) { - try { - const a = await this.client.api.oauth2.applications(applicationID).assets.get(); - for (const asset of a) assets.set(asset.name, asset.id); - } catch {} // eslint-disable-line no-empty - } - } - - const packet = { - afk: afk != null ? afk : false, // eslint-disable-line eqeqeq - since: since != null ? since : null, // eslint-disable-line eqeqeq - status: status || this.status, - game: activity - ? { - type: activity.type, - name: activity.name, - url: activity.url, - details: activity.details || undefined, - state: activity.state || undefined, - assets: activity.assets - ? { - large_text: activity.assets.largeText || undefined, - small_text: activity.assets.smallText || undefined, - large_image: assets.get(activity.assets.largeImage) || activity.assets.largeImage, - small_image: assets.get(activity.assets.smallImage) || activity.assets.smallImage, - } - : undefined, - timestamps: activity.timestamps || undefined, - party: activity.party || undefined, - application_id: applicationID || undefined, - secrets: activity.secrets || undefined, - instance: activity.instance || undefined, - } - : null, + _parse({ status, since, afk, activities }) { + const data = { + activities: [], + afk: typeof afk === 'boolean' ? afk : false, + since: typeof since === 'number' && !Number.isNaN(since) ? since : null, + status: status ?? this.status, }; - - if ((status || afk || since) && !activity) { - packet.game = this.activities[0] || null; - } - - if (packet.game) { - packet.game.type = - typeof packet.game.type === 'number' ? packet.game.type : ActivityTypes.indexOf(packet.game.type); + if (activities?.length) { + for (const [i, activity] of activities.entries()) { + if (typeof activity.name !== 'string') throw new TypeError('INVALID_TYPE', `activities[${i}].name`, 'string'); + if (!activity.type) activity.type = 0; + + data.activities.push({ + type: typeof activity.type === 'number' ? activity.type : ActivityTypes[activity.type], + name: activity.name, + url: activity.url, + }); + } + } else if (!activities && (status || afk || since) && this.activities.length) { + data.activities.push( + ...this.activities.map(a => ({ + name: a.name, + type: ActivityTypes[a.type], + url: a.url ?? undefined, + })), + ); } - return packet; + return data; } } diff --git a/node_modules/discord.js/src/structures/ClientUser.js b/node_modules/discord.js/src/structures/ClientUser.js index 65112b8c..cbf9be39 100644 --- a/node_modules/discord.js/src/structures/ClientUser.js +++ b/node_modules/discord.js/src/structures/ClientUser.js @@ -1,18 +1,13 @@ 'use strict'; +const User = require('./User'); const DataResolver = require('../util/DataResolver'); -const Structures = require('../util/Structures'); /** * Represents the logged in client's Discord user. * @extends {User} */ -class ClientUser extends Structures.get('User') { - constructor(client, data) { - super(client, data); - this._typing = new Map(); - } - +class ClientUser extends User { _patch(data) { super._patch(data); @@ -46,16 +41,17 @@ class ClientUser extends Structures.get('User') { return this.client.presence; } - edit(data) { - return this.client.api - .users('@me') - .patch({ data }) - .then(newData => { - this.client.token = newData.token; - const { updated } = this.client.actions.UserUpdate.handle(newData); - if (updated) return updated; - return this; - }); + /** + * Edits the logged in client. + * @param {APIModifyClientData} data The new data + * @param {string} [data.username] The new username + * @param {BufferResolvable|Base64Resolvable} [data.avatar] The new avatar + */ + async edit(data) { + const newData = await this.client.api.users('@me').patch({ data }); + this.client.token = newData.token; + const { updated } = this.client.actions.UserUpdate.handle(newData); + return updated ?? this; } /** @@ -88,27 +84,30 @@ class ClientUser extends Structures.get('User') { return this.edit({ avatar: await DataResolver.resolveImage(avatar) }); } + /** + * Options for setting activities + * @typedef {Object} ActivitiesOptions + * @property {string} [name] Name of the activity + * @property {ActivityType|number} [type] Type of the activity + * @property {string} [url] Twitch / YouTube stream URL + */ + /** * Data resembling a raw Discord presence. * @typedef {Object} PresenceData * @property {PresenceStatusData} [status] Status of the user * @property {boolean} [afk] Whether the user is AFK - * @property {Object} [activity] Activity the user is playing - * @property {string} [activity.name] Name of the activity - * @property {ActivityType|number} [activity.type] Type of the activity - * @property {string} [activity.url] Twitch / YouTube stream URL - * @property {?number|number[]} [shardID] Shard Id(s) to have the activity set on + * @property {ActivitiesOptions[]} [activities] Activity the user is playing + * @property {number|number[]} [shardId] Shard id(s) to have the activity set on */ /** * Sets the full presence of the client user. * @param {PresenceData} data Data for the presence - * @returns {Promise} + * @returns {Presence} * @example * // Set the client user's presence - * client.user.setPresence({ activity: { name: 'with discord.js' }, status: 'idle' }) - * .then(console.log) - * .catch(console.error); + * client.user.setPresence({ activities: [{ name: 'with discord.js' }], status: 'idle' }); */ setPresence(data) { return this.client.presence.set(data); @@ -126,53 +125,55 @@ class ClientUser extends Structures.get('User') { /** * Sets the status of the client user. * @param {PresenceStatusData} status Status to change to - * @param {?number|number[]} [shardID] Shard ID(s) to have the activity set on - * @returns {Promise} + * @param {number|number[]} [shardId] Shard id(s) to have the activity set on + * @returns {Presence} * @example * // Set the client user's status - * client.user.setStatus('idle') - * .then(console.log) - * .catch(console.error); + * client.user.setStatus('idle'); */ - setStatus(status, shardID) { - return this.setPresence({ status, shardID }); + setStatus(status, shardId) { + return this.setPresence({ status, shardId }); } /** * Options for setting an activity. - * @typedef ActivityOptions - * @type {Object} + * @typedef {Object} ActivityOptions + * @property {string} [name] Name of the activity * @property {string} [url] Twitch / YouTube stream URL * @property {ActivityType|number} [type] Type of the activity - * @property {?number|number[]} [shardID] Shard Id(s) to have the activity set on + * @property {number|number[]} [shardId] Shard Id(s) to have the activity set on */ /** * Sets the activity the client user is playing. * @param {string|ActivityOptions} [name] Activity being played, or options for setting the activity * @param {ActivityOptions} [options] Options for setting the activity - * @returns {Promise} + * @returns {Presence} * @example * // Set the client user's activity - * client.user.setActivity('discord.js', { type: 'WATCHING' }) - * .then(presence => console.log(`Activity set to ${presence.activities[0].name}`)) - * .catch(console.error); + * client.user.setActivity('discord.js', { type: 'WATCHING' }); */ setActivity(name, options = {}) { - if (!name) return this.setPresence({ activity: null, shardID: options.shardID }); + if (!name) return this.setPresence({ activities: [], shardId: options.shardId }); const activity = Object.assign({}, options, typeof name === 'object' ? name : { name }); - return this.setPresence({ activity, shardID: activity.shardID }); + return this.setPresence({ activities: [activity], shardId: activity.shardId }); } /** * Sets/removes the AFK flag for the client user. * @param {boolean} afk Whether or not the user is AFK - * @returns {Promise} + * @param {number|number[]} [shardId] Shard Id(s) to have the AFK flag set on + * @returns {Presence} */ - setAFK(afk) { - return this.setPresence({ afk }); + setAFK(afk, shardId) { + return this.setPresence({ afk, shardId }); } } module.exports = ClientUser; + +/** + * @external APIModifyClientData + * @see {@link https://discord.com/developers/docs/resources/user#modify-current-user-json-params} + */ diff --git a/node_modules/discord.js/src/structures/DMChannel.js b/node_modules/discord.js/src/structures/DMChannel.js index 48075974..7ebc159b 100644 --- a/node_modules/discord.js/src/structures/DMChannel.js +++ b/node_modules/discord.js/src/structures/DMChannel.js @@ -12,18 +12,19 @@ const MessageManager = require('../managers/MessageManager'); class DMChannel extends Channel { /** * @param {Client} client The instantiating client - * @param {Object} data The data for the DM channel + * @param {APIChannel} data The data for the DM channel */ constructor(client, data) { super(client, data); + // Override the channel type so partials have a known type - this.type = 'dm'; + this.type = 'DM'; + /** * A manager of the messages belonging to this channel * @type {MessageManager} */ this.messages = new MessageManager(this); - this._typing = new Map(); } _patch(data) { @@ -34,14 +35,14 @@ class DMChannel extends Channel { * The recipient on the other end of the DM * @type {User} */ - this.recipient = this.client.users.add(data.recipients[0]); + this.recipient = this.client.users._add(data.recipients[0]); } /** - * The ID of the last message in the channel, if one was sent + * The channel's last message id, if one was sent * @type {?Snowflake} */ - this.lastMessageID = data.last_message_id; + this.lastMessageId = data.last_message_id; /** * The timestamp when the last pinned message was pinned, if there was one @@ -56,15 +57,15 @@ class DMChannel extends Channel { * @readonly */ get partial() { - return typeof this.lastMessageID === 'undefined'; + return typeof this.lastMessageId === 'undefined'; } /** * Fetch this DMChannel. - * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @param {boolean} [force=true] Whether to skip the cache check and request the API * @returns {Promise} */ - fetch(force = false) { + fetch(force = true) { return this.recipient.createDM(force); } @@ -85,12 +86,11 @@ class DMChannel extends Channel { get lastMessage() {} get lastPinAt() {} send() {} - startTyping() {} - stopTyping() {} - get typing() {} - get typingCount() {} + sendTyping() {} createMessageCollector() {} awaitMessages() {} + createMessageComponentCollector() {} + awaitMessageComponent() {} // Doesn't work on DM channels; bulkDelete() {} } diff --git a/node_modules/discord.js/src/structures/Emoji.js b/node_modules/discord.js/src/structures/Emoji.js index 0214ea80..5c94d267 100644 --- a/node_modules/discord.js/src/structures/Emoji.js +++ b/node_modules/discord.js/src/structures/Emoji.js @@ -1,7 +1,15 @@ 'use strict'; const Base = require('./Base'); -const Snowflake = require('../util/Snowflake'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); + +/** + * Represents raw emoji data from the API + * @typedef {APIEmoji} RawEmoji + * @property {?Snowflake} id The emoji's id + * @property {?string} name The emoji's name + * @property {?boolean} animated Whether the emoji is animated + */ /** * Represents an emoji, see {@link GuildEmoji} and {@link ReactionEmoji}. @@ -11,19 +19,19 @@ class Emoji extends Base { constructor(client, emoji) { super(client); /** - * Whether this emoji is animated - * @type {boolean} + * Whether or not the emoji is animated + * @type {?boolean} */ - this.animated = emoji.animated; + this.animated = emoji.animated ?? null; /** - * The name of this emoji - * @type {string} + * The emoji's name + * @type {?string} */ - this.name = emoji.name; + this.name = emoji.name ?? null; /** - * The ID of this emoji + * The emoji's id * @type {?Snowflake} */ this.id = emoji.id; @@ -51,8 +59,7 @@ class Emoji extends Base { * @readonly */ get url() { - if (!this.id) return null; - return this.client.rest.cdn.Emoji(this.id, this.animated ? 'gif' : 'png'); + return this.id && this.client.rest.cdn.Emoji(this.id, this.animated ? 'gif' : 'png'); } /** @@ -61,8 +68,7 @@ class Emoji extends Base { * @readonly */ get createdTimestamp() { - if (!this.id) return null; - return Snowflake.deconstruct(this.id).timestamp; + return this.id && SnowflakeUtil.deconstruct(this.id).timestamp; } /** @@ -71,8 +77,7 @@ class Emoji extends Base { * @readonly */ get createdAt() { - if (!this.id) return null; - return new Date(this.createdTimestamp); + return this.id && new Date(this.createdTimestamp); } /** @@ -82,7 +87,7 @@ class Emoji extends Base { * @example * // Send a custom emoji from a guild: * const emoji = guild.emojis.cache.first(); - * msg.reply(`Hello! ${emoji}`); + * msg.channel.send(`Hello! ${emoji}`); * @example * // Send the emoji used in a reaction to the channel the reaction is part of * reaction.message.channel.send(`The emoji used was: ${reaction.emoji}`); @@ -93,7 +98,7 @@ class Emoji extends Base { toJSON() { return super.toJSON({ - guild: 'guildID', + guild: 'guildId', createdTimestamp: true, url: true, identifier: true, @@ -102,3 +107,8 @@ class Emoji extends Base { } module.exports = Emoji; + +/** + * @external APIEmoji + * @see {@link https://discord.com/developers/docs/resources/emoji#emoji-object} + */ diff --git a/node_modules/discord.js/src/structures/Guild.js b/node_modules/discord.js/src/structures/Guild.js index 46dc76a0..2ceefb27 100644 --- a/node_modules/discord.js/src/structures/Guild.js +++ b/node_modules/discord.js/src/structures/Guild.js @@ -1,32 +1,36 @@ 'use strict'; -const { deprecate } = require('util'); -const Base = require('./Base'); +const { Collection } = require('@discordjs/collection'); +const AnonymousGuild = require('./AnonymousGuild'); const GuildAuditLogs = require('./GuildAuditLogs'); const GuildPreview = require('./GuildPreview'); const GuildTemplate = require('./GuildTemplate'); const Integration = require('./Integration'); -const Invite = require('./Invite'); -const VoiceRegion = require('./VoiceRegion'); const Webhook = require('./Webhook'); -const { Error, TypeError } = require('../errors'); +const WelcomeScreen = require('./WelcomeScreen'); +const { Error } = require('../errors'); +const GuildApplicationCommandManager = require('../managers/GuildApplicationCommandManager'); +const GuildBanManager = require('../managers/GuildBanManager'); const GuildChannelManager = require('../managers/GuildChannelManager'); const GuildEmojiManager = require('../managers/GuildEmojiManager'); +const GuildInviteManager = require('../managers/GuildInviteManager'); const GuildMemberManager = require('../managers/GuildMemberManager'); +const GuildStickerManager = require('../managers/GuildStickerManager'); const PresenceManager = require('../managers/PresenceManager'); const RoleManager = require('../managers/RoleManager'); +const StageInstanceManager = require('../managers/StageInstanceManager'); const VoiceStateManager = require('../managers/VoiceStateManager'); -const Collection = require('../util/Collection'); const { - browser, ChannelTypes, - DefaultMessageNotifications, + DefaultMessageNotificationLevels, PartialTypes, VerificationLevels, ExplicitContentFilterLevels, + Status, + MFALevels, + PremiumTiers, } = require('../util/Constants'); const DataResolver = require('../util/DataResolver'); -const Snowflake = require('../util/Snowflake'); const SystemChannelFlags = require('../util/SystemChannelFlags'); const Util = require('../util/Util'); @@ -34,15 +38,17 @@ const Util = require('../util/Util'); * Represents a guild (or a server) on Discord. * It's recommended to see if a guild is available before performing operations or reading data from it. You can * check this with `guild.available`. - * @extends {Base} + * @extends {AnonymousGuild} */ -class Guild extends Base { - /** - * @param {Client} client The instantiating client - * @param {Object} data The data for the guild - */ +class Guild extends AnonymousGuild { constructor(client, data) { - super(client); + super(client, data, false); + + /** + * A manager of the application commands belonging to this guild + * @type {GuildApplicationCommandManager} + */ + this.commands = new GuildApplicationCommandManager(this); /** * A manager of the members belonging to this guild @@ -56,6 +62,12 @@ class Guild extends Base { */ this.channels = new GuildChannelManager(this); + /** + * A manager of the bans belonging to this guild + * @type {GuildBanManager} + */ + this.bans = new GuildBanManager(this); + /** * A manager of the roles belonging to this guild * @type {RoleManager} @@ -74,6 +86,18 @@ class Guild extends Base { */ this.voiceStates = new VoiceStateManager(this); + /** + * A manager of the stage instances of this guild + * @type {StageInstanceManager} + */ + this.stageInstances = new StageInstanceManager(this); + + /** + * A manager of the invites of this guild + * @type {GuildInviteManager} + */ + this.invites = new GuildInviteManager(this); + /** * Whether the bot has been removed from the guild * @type {boolean} @@ -87,12 +111,6 @@ class Guild extends Base { * @type {boolean} */ this.available = false; - - /** - * The Unique ID of the guild, useful for comparisons - * @type {Snowflake} - */ - this.id = data.id; } else { this._patch(data); if (!data.channels) this.available = false; @@ -102,7 +120,7 @@ class Guild extends Base { * The id of the shard this Guild belongs to. * @type {number} */ - this.shardID = data.shardID; + this.shardId = data.shardId; } /** @@ -111,7 +129,7 @@ class Guild extends Base { * @readonly */ get shard() { - return this.client.ws.shards.get(this.shardID); + return this.client.ws.shards.get(this.shardId); } /** @@ -120,23 +138,11 @@ class Guild extends Base { * @private */ _patch(data) { - /** - * The name of the guild - * @type {string} - */ + super._patch(data); + this.id = data.id; this.name = data.name; - - /** - * The hash of the guild icon - * @type {?string} - */ this.icon = data.icon; - - /** - * The hash of the guild invite splash image - * @type {?string} - */ - this.splash = data.splash; + this.available = !data.unavailable; /** * The hash of the guild discovery splash image @@ -144,23 +150,17 @@ class Guild extends Base { */ this.discoverySplash = data.discovery_splash; - /** - * The region the guild is located in - * @type {string} - */ - this.region = data.region; - /** * The full amount of members in this guild * @type {number} */ - this.memberCount = data.member_count || this.memberCount; + this.memberCount = data.member_count ?? this.memberCount; /** * Whether the guild is "large" (has more than large_threshold members, 50 by default) * @type {boolean} */ - this.large = Boolean('large' in data ? data.large : this.large); + this.large = Boolean(data.large ?? this.large); /** * An array of enabled guild features, here are the possible values: @@ -171,9 +171,17 @@ class Guild extends Base { * * DISCOVERABLE * * FEATURABLE * * INVITE_SPLASH + * * MEMBER_VERIFICATION_GATE_ENABLED + * * MONETIZATION_ENABLED + * * MORE_STICKERS * * NEWS * * PARTNERED + * * PREVIEW_ENABLED + * * PRIVATE_THREADS * * RELAY_ENABLED + * * SEVEN_DAY_THREAD_ARCHIVE + * * THREE_DAY_THREAD_ARCHIVE + * * TICKETED_EVENTS_ENABLED * * VANITY_URL * * VERIFIED * * VIP_REGIONS @@ -182,16 +190,10 @@ class Guild extends Base { */ /** - * An array of guild features partnered guilds have enabled - * @type {Features[]} - */ - this.features = data.features; - - /** - * The ID of the application that created this guild (if applicable) + * The id of the application that created this guild (if applicable) * @type {?Snowflake} */ - this.applicationID = data.application_id; + this.applicationId = data.application_id; /** * The time in seconds before a user is counted as "away from keyboard" @@ -200,38 +202,22 @@ class Guild extends Base { this.afkTimeout = data.afk_timeout; /** - * The ID of the voice channel where AFK members are moved + * The id of the voice channel where AFK members are moved * @type {?Snowflake} */ - this.afkChannelID = data.afk_channel_id; + this.afkChannelId = data.afk_channel_id; /** - * The ID of the system channel + * The system channel's id * @type {?Snowflake} */ - this.systemChannelID = data.system_channel_id; - - /** - * Whether embedded images are enabled on this guild - * @type {boolean} - * @deprecated - */ - this.embedEnabled = data.embed_enabled; - - /** - * The type of premium tier: - * * 0: NONE - * * 1: TIER_1 - * * 2: TIER_2 - * * 3: TIER_3 - * @typedef {number} PremiumTier - */ + this.systemChannelId = data.system_channel_id; /** - * The premium tier on this guild + * The premium tier of this guild * @type {PremiumTier} */ - this.premiumTier = data.premium_tier; + this.premiumTier = PremiumTiers[data.premium_tier]; if (typeof data.premium_subscription_count !== 'undefined') { /** @@ -251,27 +237,12 @@ class Guild extends Base { if (typeof data.widget_channel_id !== 'undefined') { /** - * The widget channel ID, if enabled + * The widget channel's id, if enabled * @type {?string} */ - this.widgetChannelID = data.widget_channel_id; - } - - if (typeof data.embed_channel_id !== 'undefined') { - /** - * The embed channel ID, if enabled - * @type {?string} - * @deprecated - */ - this.embedChannelID = data.embed_channel_id; + this.widgetChannelId = data.widget_channel_id; } - /** - * The verification level of the guild - * @type {VerificationLevel} - */ - this.verificationLevel = VerificationLevels[data.verification_level]; - /** * The explicit content filter level of the guild * @type {ExplicitContentFilterLevel} @@ -279,10 +250,10 @@ class Guild extends Base { this.explicitContentFilter = ExplicitContentFilterLevels[data.explicit_content_filter]; /** - * The required MFA level for the guild - * @type {number} + * The required MFA level for this guild + * @type {MFALevel} */ - this.mfaLevel = data.mfa_level; + this.mfaLevel = MFALevels[data.mfa_level]; /** * The timestamp the client user joined the guild at @@ -291,11 +262,10 @@ class Guild extends Base { this.joinedTimestamp = data.joined_at ? new Date(data.joined_at).getTime() : this.joinedTimestamp; /** - * The value set for the guild's default message notifications - * @type {DefaultMessageNotifications|number} + * The default message notification level of the guild + * @type {DefaultMessageNotificationLevel} */ - this.defaultMessageNotifications = - DefaultMessageNotifications[data.default_message_notifications] || data.default_message_notifications; + this.defaultMessageNotifications = DefaultMessageNotificationLevels[data.default_message_notifications]; /** * The value set for the guild's system channel flags @@ -319,7 +289,7 @@ class Guild extends Base { * You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter * @type {?number} */ - this.maximumPresences = data.max_presences || 25000; + this.maximumPresences = data.max_presences ?? 25000; } else if (typeof this.maximumPresences === 'undefined') { this.maximumPresences = null; } @@ -346,48 +316,24 @@ class Guild extends Base { this.approximatePresenceCount = null; } - /** - * The vanity invite code of the guild, if any - * @type {?string} - */ - this.vanityURLCode = data.vanity_url_code; - - /* eslint-disable max-len */ /** * The use count of the vanity URL code of the guild, if any * You will need to fetch this parameter using {@link Guild#fetchVanityData} if you want to receive it * @type {?number} */ this.vanityURLUses = null; - /* eslint-enable max-len */ - - /** - * The description of the guild, if any - * @type {?string} - */ - this.description = data.description; - - /** - * The hash of the guild banner - * @type {?string} - */ - this.banner = data.banner; - - this.id = data.id; - this.available = !data.unavailable; - this.features = data.features || this.features || []; /** - * The ID of the rules channel for the guild + * The rules channel's id for the guild * @type {?Snowflake} */ - this.rulesChannelID = data.rules_channel_id; + this.rulesChannelId = data.rules_channel_id; /** - * The ID of the community updates channel for the guild + * The community updates channel's id for the guild * @type {?Snowflake} */ - this.publicUpdatesChannelID = data.public_updates_channel_id; + this.publicUpdatesChannelId = data.public_updates_channel_id; /** * The preferred locale of the guild, defaults to `en-US` @@ -398,38 +344,51 @@ class Guild extends Base { if (data.channels) { this.channels.cache.clear(); for (const rawChannel of data.channels) { - this.client.channels.add(rawChannel, this); + this.client.channels._add(rawChannel, this); + } + } + + if (data.threads) { + for (const rawThread of data.threads) { + this.client.channels._add(rawThread, this); } } if (data.roles) { this.roles.cache.clear(); - for (const role of data.roles) this.roles.add(role); + for (const role of data.roles) this.roles._add(role); } if (data.members) { this.members.cache.clear(); - for (const guildUser of data.members) this.members.add(guildUser); + for (const guildUser of data.members) this.members._add(guildUser); } if (data.owner_id) { /** - * The user ID of this guild's owner + * The user id of this guild's owner * @type {Snowflake} */ - this.ownerID = data.owner_id; + this.ownerId = data.owner_id; } if (data.presences) { for (const presence of data.presences) { - this.presences.add(Object.assign(presence, { guild: this })); + this.presences._add(Object.assign(presence, { guild: this })); + } + } + + if (data.stage_instances) { + this.stageInstances.cache.clear(); + for (const stageInstance of data.stage_instances) { + this.stageInstances._add(stageInstance); } } if (data.voice_states) { this.voiceStates.cache.clear(); for (const voiceState of data.voice_states) { - this.voiceStates.add(voiceState); + this.voiceStates._add(voiceState); } } @@ -439,41 +398,36 @@ class Guild extends Base { * @type {GuildEmojiManager} */ this.emojis = new GuildEmojiManager(this); - if (data.emojis) for (const emoji of data.emojis) this.emojis.add(emoji); + if (data.emojis) for (const emoji of data.emojis) this.emojis._add(emoji); } else if (data.emojis) { this.client.actions.GuildEmojisUpdate.handle({ guild_id: this.id, emojis: data.emojis, }); } + + if (!this.stickers) { + /** + * A manager of the stickers belonging to this guild + * @type {GuildStickerManager} + */ + this.stickers = new GuildStickerManager(this); + if (data.stickers) for (const sticker of data.stickers) this.stickers._add(sticker); + } else if (data.stickers) { + this.client.actions.GuildStickersUpdate.handle({ + guild_id: this.id, + stickers: data.stickers, + }); + } } /** * The URL to this guild's banner. - * @param {ImageURLOptions} [options={}] Options for the Image URL + * @param {StaticImageURLOptions} [options={}] Options for the Image URL * @returns {?string} */ bannerURL({ format, size } = {}) { - if (!this.banner) return null; - return this.client.rest.cdn.Banner(this.id, this.banner, format, size); - } - - /** - * The timestamp the guild was created at - * @type {number} - * @readonly - */ - get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; - } - - /** - * The time the guild was created at - * @type {Date} - * @readonly - */ - get createdAt() { - return new Date(this.createdTimestamp); + return this.banner && this.client.rest.cdn.Banner(this.id, this.banner, format, size); } /** @@ -485,78 +439,39 @@ class Guild extends Base { return new Date(this.joinedTimestamp); } - /** - * If this guild is partnered - * @type {boolean} - * @readonly - */ - get partnered() { - return this.features.includes('PARTNERED'); - } - - /** - * If this guild is verified - * @type {boolean} - * @readonly - */ - get verified() { - return this.features.includes('VERIFIED'); - } - - /** - * The URL to this guild's icon. - * @param {ImageURLOptions} [options={}] Options for the Image URL - * @returns {?string} - */ - iconURL({ format, size, dynamic } = {}) { - if (!this.icon) return null; - return this.client.rest.cdn.Icon(this.id, this.icon, format, size, dynamic); - } - - /** - * The acronym that shows up in place of a guild icon. - * @type {string} - * @readonly - */ - get nameAcronym() { - return this.name - .replace(/'s /g, ' ') - .replace(/\w+/g, e => e[0]) - .replace(/\s/g, ''); - } - /** * The URL to this guild's invite splash image. - * @param {ImageURLOptions} [options={}] Options for the Image URL + * @param {StaticImageURLOptions} [options={}] Options for the Image URL * @returns {?string} */ splashURL({ format, size } = {}) { - if (!this.splash) return null; - return this.client.rest.cdn.Splash(this.id, this.splash, format, size); + return this.splash && this.client.rest.cdn.Splash(this.id, this.splash, format, size); } /** * The URL to this guild's discovery splash image. - * @param {ImageURLOptions} [options={}] Options for the Image URL + * @param {StaticImageURLOptions} [options={}] Options for the Image URL * @returns {?string} */ discoverySplashURL({ format, size } = {}) { - if (!this.discoverySplash) return null; - return this.client.rest.cdn.DiscoverySplash(this.id, this.discoverySplash, format, size); + return this.discoverySplash && this.client.rest.cdn.DiscoverySplash(this.id, this.discoverySplash, format, size); } /** - * The owner of the guild - * @type {?GuildMember} - * @readonly + * Options used to fetch the owner of a guild or a thread. + * @typedef {Object} FetchOwnerOptions + * @property {boolean} [cache=true] Whether or not to cache the fetched member + * @property {boolean} [force=false] Whether to skip the cache check and request the API */ - get owner() { - return ( - this.members.cache.get(this.ownerID) || - (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER) - ? this.members.add({ user: { id: this.ownerID } }, true) - : null) - ); + + /** + * Fetches the owner of the guild. + * If the member object isn't needed, use {@link Guild#ownerId} instead. + * @param {FetchOwnerOptions} [options] The options for fetching the member + * @returns {Promise} + */ + fetchOwner(options) { + return this.members.fetch({ ...options, user: this.ownerId }); } /** @@ -565,7 +480,7 @@ class Guild extends Base { * @readonly */ get afkChannel() { - return this.client.channels.cache.get(this.afkChannelID) || null; + return this.client.channels.resolve(this.afkChannelId); } /** @@ -574,7 +489,7 @@ class Guild extends Base { * @readonly */ get systemChannel() { - return this.client.channels.cache.get(this.systemChannelID) || null; + return this.client.channels.resolve(this.systemChannelId); } /** @@ -583,17 +498,7 @@ class Guild extends Base { * @readonly */ get widgetChannel() { - return this.client.channels.cache.get(this.widgetChannelID) || null; - } - - /** - * Embed channel for this guild - * @type {?TextChannel} - * @readonly - * @deprecated - */ - get embedChannel() { - return this.client.channels.cache.get(this.embedChannelID) || null; + return this.client.channels.resolve(this.widgetChannelId); } /** @@ -602,7 +507,7 @@ class Guild extends Base { * @readonly */ get rulesChannel() { - return this.client.channels.cache.get(this.rulesChannelID) || null; + return this.client.channels.resolve(this.rulesChannelId); } /** @@ -611,7 +516,7 @@ class Guild extends Base { * @readonly */ get publicUpdatesChannel() { - return this.client.channels.cache.get(this.publicUpdatesChannelID) || null; + return this.client.channels.resolve(this.publicUpdatesChannelId); } /** @@ -621,97 +526,16 @@ class Guild extends Base { */ get me() { return ( - this.members.cache.get(this.client.user.id) || + this.members.resolve(this.client.user.id) ?? (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER) - ? this.members.add({ user: { id: this.client.user.id } }, true) + ? this.members._add({ user: { id: this.client.user.id } }, true) : null) ); } - /** - * The voice state for the client user of this guild, if any - * @type {?VoiceState} - * @readonly - */ - get voice() { - return this.voiceStates.cache.get(this.client.user.id); - } - - /** - * Returns the GuildMember form of a User object, if the user is present in the guild. - * @param {UserResolvable} user The user that you want to obtain the GuildMember of - * @returns {?GuildMember} - * @example - * // Get the guild member of a user - * const member = guild.member(message.author); - */ - member(user) { - return this.members.resolve(user); - } - - /** - * Fetches this guild. - * @returns {Promise} - */ - fetch() { - return this.client.api - .guilds(this.id) - .get({ query: { with_counts: true } }) - .then(data => { - this._patch(data); - return this; - }); - } - - /** - * An object containing information about a guild member's ban. - * @typedef {Object} BanInfo - * @property {User} user User that was banned - * @property {?string} reason Reason the user was banned - */ - - /** - * Fetches information on a banned user from this guild. - * @param {UserResolvable} user The User to fetch the ban info of - * @returns {Promise} - */ - fetchBan(user) { - const id = this.client.users.resolveID(user); - if (!id) throw new Error('FETCH_BAN_RESOLVE_ID'); - return this.client.api - .guilds(this.id) - .bans(id) - .get() - .then(ban => ({ - reason: ban.reason, - user: this.client.users.add(ban.user), - })); - } - - /** - * Fetches a collection of banned users in this guild. - * @returns {Promise>} - */ - fetchBans() { - return this.client.api - .guilds(this.id) - .bans.get() - .then(bans => - bans.reduce((collection, ban) => { - collection.set(ban.user.id, { - reason: ban.reason, - user: this.client.users.add(ban.user), - }); - return collection; - }, new Collection()), - ); - } - /** * Fetches a collection of integrations to this guild. * Resolves with a collection mapping integrations by their ids. - * @param {Object} [options] Options for fetching integrations - * @param {boolean} [options.includeApplications] Whether to include bot and Oauth2 webhook integrations * @returns {Promise>} * @example * // Fetch integrations @@ -719,20 +543,12 @@ class Guild extends Base { * .then(integrations => console.log(`Fetched ${integrations.size} integrations`)) * .catch(console.error); */ - fetchIntegrations({ includeApplications = false } = {}) { - return this.client.api - .guilds(this.id) - .integrations.get({ - query: { - include_applications: includeApplications, - }, - }) - .then(data => - data.reduce( - (collection, integration) => collection.set(integration.id, new Integration(this.client, integration, this)), - new Collection(), - ), - ); + async fetchIntegrations() { + const data = await this.client.api.guilds(this.id).integrations.get(); + return data.reduce( + (collection, integration) => collection.set(integration.id, new Integration(this.client, integration, this)), + new Collection(), + ); } /** @@ -750,23 +566,12 @@ class Guild extends Base { } /** - * The data for creating an integration. - * @typedef {Object} IntegrationData - * @property {string} id The integration id - * @property {string} type The integration type - */ - - /** - * Creates an integration by attaching an integration object - * @param {IntegrationData} data The data for the integration - * @param {string} reason Reason for creating the integration - * @returns {Promise} + * Fetches the welcome screen for this guild. + * @returns {Promise} */ - createIntegration(data, reason) { - return this.client.api - .guilds(this.id) - .integrations.post({ data, reason }) - .then(() => this); + async fetchWelcomeScreen() { + const data = await this.client.api.guilds(this.id, 'welcome-screen').get(); + return new WelcomeScreen(this, data); } /** @@ -782,35 +587,6 @@ class Guild extends Base { .then(data => new GuildTemplate(this.client, data)); } - /** - * Fetches a collection of invites to this guild. - * Resolves with a collection mapping invites by their codes. - * @returns {Promise>} - * @example - * // Fetch invites - * guild.fetchInvites() - * .then(invites => console.log(`Fetched ${invites.size} invites`)) - * .catch(console.error); - * @example - * // Fetch invite creator by their id - * guild.fetchInvites() - * .then(invites => console.log(invites.find(invite => invite.inviter.id === '84484653687267328'))) - * .catch(console.error); - */ - fetchInvites() { - return this.client.api - .guilds(this.id) - .invites.get() - .then(inviteItems => { - const invites = new Collection(); - for (const inviteItem of inviteItems) { - const invite = new Invite(this.client, inviteItem); - invites.set(invite.code, invite); - } - return invites; - }); - } - /** * Obtains a guild preview for this guild from Discord. * @returns {Promise} @@ -822,23 +598,6 @@ class Guild extends Base { .then(data => new GuildPreview(this.client, data)); } - /** - * Fetches the vanity url invite code to this guild. - * Resolves with a string matching the vanity url invite code, not the full url. - * @returns {Promise} - * @deprecated - * @example - * // Fetch invites - * guild.fetchVanityCode() - * .then(code => { - * console.log(`Vanity URL: https://discord.gg/${code}`); - * }) - * .catch(console.error); - */ - fetchVanityCode() { - return this.fetchVanityData().then(vanity => vanity.code); - } - /** * An object containing information about a guild's vanity invite. * @typedef {Object} Vanity @@ -863,6 +622,7 @@ class Guild extends Base { throw new Error('VANITY_URL'); } const data = await this.client.api.guilds(this.id, 'vanity-url').get(); + this.vanityURLCode = data.code; this.vanityURLUses = data.uses; return data; @@ -889,74 +649,63 @@ class Guild extends Base { } /** - * Fetches available voice regions. - * @returns {Promise>} + * Fetches the guild widget data, requires the widget to be enabled. + * @returns {Promise} + * @example + * // Fetches the guild widget data + * guild.fetchWidget() + * .then(widget => console.log(`The widget shows ${widget.channels.size} channels`)) + * .catch(console.error); */ - fetchVoiceRegions() { - return this.client.api - .guilds(this.id) - .regions.get() - .then(res => { - const regions = new Collection(); - for (const region of res) regions.set(region.id, new VoiceRegion(region)); - return regions; - }); + fetchWidget() { + return this.client.fetchGuildWidget(this.id); } /** - * Data for the Guild Widget object - * @typedef {Object} GuildWidget + * Data for the Guild Widget Settings object + * @typedef {Object} GuildWidgetSettings * @property {boolean} enabled Whether the widget is enabled - * @property {?GuildChannel} channel The widget channel + * @property {?GuildChannel} channel The widget invite channel */ /** - * The Guild Widget object - * @typedef {Object} GuildWidgetData + * The Guild Widget Settings object + * @typedef {Object} GuildWidgetSettingsData * @property {boolean} enabled Whether the widget is enabled - * @property {?GuildChannelResolvable} channel The widget channel + * @property {?GuildChannelResolvable} channel The widget invite channel */ /** - * Fetches the guild embed. - * @returns {Promise} - * @deprecated - * @example - * // Fetches the guild embed - * guild.fetchEmbed() - * .then(embed => console.log(`The embed is ${embed.enabled ? 'enabled' : 'disabled'}`)) - * .catch(console.error); - */ - fetchEmbed() { - return this.fetchWidget(); - } - - /** - * Fetches the guild widget. - * @returns {Promise} + * Fetches the guild widget settings. + * @returns {Promise} * @example - * // Fetches the guild widget - * guild.fetchWidget() + * // Fetches the guild widget settings + * guild.fetchWidgetSettings() * .then(widget => console.log(`The widget is ${widget.enabled ? 'enabled' : 'disabled'}`)) * .catch(console.error); */ - async fetchWidget() { + async fetchWidgetSettings() { const data = await this.client.api.guilds(this.id).widget.get(); - this.widgetEnabled = this.embedEnabled = data.enabled; - this.widgetChannelID = this.embedChannelID = data.channel_id; + this.widgetEnabled = data.enabled; + this.widgetChannelId = data.channel_id; return { enabled: data.enabled, channel: data.channel_id ? this.channels.cache.get(data.channel_id) : null, }; } + /** + * Options used to fetch audit logs. + * @typedef {Object} GuildAuditLogsFetchOptions + * @property {Snowflake|GuildAuditLogsEntry} [before] Only return entries before this entry + * @property {number} [limit] The number of entries to return + * @property {UserResolvable} [user] Only return entries for actions made by this user + * @property {AuditLogAction|number} [type] Only return entries for this action type + */ + /** * Fetches audit logs for this guild. - * @param {Object} [options={}] Options for fetching audit logs - * @param {Snowflake|GuildAuditLogsEntry} [options.before] Limit to entries from before specified entry - * @param {number} [options.limit] Limit number of entries - * @param {UserResolvable} [options.user] Only show entries involving this user - * @param {AuditLogAction|number} [options.type] Only show entries involving this action type + * @param {GuildAuditLogsFetchOptions} [options={}] Options for fetching audit logs * @returns {Promise} * @example * // Output audit log entries @@ -974,67 +723,49 @@ class Guild extends Base { query: { before: options.before, limit: options.limit, - user_id: this.client.users.resolveID(options.user), + user_id: this.client.users.resolveId(options.user), action_type: options.type, }, }) .then(data => GuildAuditLogs.build(this, data)); } - /** - * Adds a user to the guild using OAuth2. Requires the `CREATE_INSTANT_INVITE` permission. - * @param {UserResolvable} user User to add to the guild - * @param {Object} options Options for the addition - * @param {string} options.accessToken An OAuth2 access token for the user with the `guilds.join` scope granted to the - * bot's application - * @param {string} [options.nick] Nickname to give the member (requires `MANAGE_NICKNAMES`) - * @param {Collection|RoleResolvable[]} [options.roles] Roles to add to the member - * (requires `MANAGE_ROLES`) - * @param {boolean} [options.mute] Whether the member should be muted (requires `MUTE_MEMBERS`) - * @param {boolean} [options.deaf] Whether the member should be deafened (requires `DEAFEN_MEMBERS`) - * @returns {Promise} - */ - async addMember(user, options) { - user = this.client.users.resolveID(user); - if (!user) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable'); - if (this.members.cache.has(user)) return this.members.cache.get(user); - options.access_token = options.accessToken; - if (options.roles) { - const roles = []; - for (let role of options.roles instanceof Collection ? options.roles.values() : options.roles) { - role = this.roles.resolve(role); - if (!role) { - throw new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true); - } - roles.push(role.id); - } - options.roles = roles; - } - const data = await this.client.api.guilds(this.id).members(user).put({ data: options }); - // Data is an empty buffer if the member is already part of the guild. - return data instanceof (browser ? ArrayBuffer : Buffer) ? this.members.fetch(user) : this.members.add(data); - } - /** * The data for editing a guild. * @typedef {Object} GuildEditData * @property {string} [name] The name of the guild - * @property {string} [region] The region of the guild * @property {VerificationLevel|number} [verificationLevel] The verification level of the guild * @property {ExplicitContentFilterLevel|number} [explicitContentFilter] The level of the explicit content filter - * @property {ChannelResolvable} [afkChannel] The AFK channel of the guild - * @property {ChannelResolvable} [systemChannel] The system channel of the guild + * @property {VoiceChannelResolvable} [afkChannel] The AFK channel of the guild + * @property {TextChannelResolvable} [systemChannel] The system channel of the guild * @property {number} [afkTimeout] The AFK timeout of the guild * @property {Base64Resolvable} [icon] The icon of the guild * @property {GuildMemberResolvable} [owner] The owner of the guild * @property {Base64Resolvable} [splash] The invite splash image of the guild * @property {Base64Resolvable} [discoverySplash] The discovery splash image of the guild * @property {Base64Resolvable} [banner] The banner of the guild - * @property {DefaultMessageNotifications|number} [defaultMessageNotifications] The default message notifications + * @property {DefaultMessageNotificationLevel|number} [defaultMessageNotifications] The default message notification + * level of the guild * @property {SystemChannelFlagsResolvable} [systemChannelFlags] The system channel flags of the guild - * @property {ChannelResolvable} [rulesChannel] The rules channel of the guild - * @property {ChannelResolvable} [publicUpdatesChannel] The community updates channel of the guild + * @property {TextChannelResolvable} [rulesChannel] The rules channel of the guild + * @property {TextChannelResolvable} [publicUpdatesChannel] The community updates channel of the guild * @property {string} [preferredLocale] The preferred locale of the guild + * @property {string} [description] The discovery description of the guild + * @property {Features[]} [features] The features of the guild + */ + + /** + * Data that can be resolved to a Text Channel object. This can be: + * * A TextChannel + * * A Snowflake + * @typedef {TextChannel|Snowflake} TextChannelResolvable + */ + + /** + * Data that can be resolved to a Voice Channel object. This can be: + * * A VoiceChannel + * * A Snowflake + * @typedef {VoiceChannel|Snowflake} VoiceChannelResolvable */ /** @@ -1043,33 +774,31 @@ class Guild extends Base { * @param {string} [reason] Reason for editing this guild * @returns {Promise} * @example - * // Set the guild name and region + * // Set the guild name * guild.edit({ * name: 'Discord Guild', - * region: 'london', * }) - * .then(updated => console.log(`New guild name ${updated} in region ${updated.region}`)) + * .then(updated => console.log(`New guild name ${updated}`)) * .catch(console.error); */ edit(data, reason) { const _data = {}; if (data.name) _data.name = data.name; - if (data.region) _data.region = data.region; if (typeof data.verificationLevel !== 'undefined') { _data.verification_level = typeof data.verificationLevel === 'number' - ? Number(data.verificationLevel) - : VerificationLevels.indexOf(data.verificationLevel); + ? data.verificationLevel + : VerificationLevels[data.verificationLevel]; } if (typeof data.afkChannel !== 'undefined') { - _data.afk_channel_id = this.client.channels.resolveID(data.afkChannel); + _data.afk_channel_id = this.client.channels.resolveId(data.afkChannel); } if (typeof data.systemChannel !== 'undefined') { - _data.system_channel_id = this.client.channels.resolveID(data.systemChannel); + _data.system_channel_id = this.client.channels.resolveId(data.systemChannel); } if (data.afkTimeout) _data.afk_timeout = Number(data.afkTimeout); if (typeof data.icon !== 'undefined') _data.icon = data.icon; - if (data.owner) _data.owner_id = this.client.users.resolveID(data.owner); + if (data.owner) _data.owner_id = this.client.users.resolveId(data.owner); if (data.splash) _data.splash = data.splash; if (data.discoverySplash) _data.discovery_splash = data.discoverySplash; if (data.banner) _data.banner = data.banner; @@ -1077,22 +806,28 @@ class Guild extends Base { _data.explicit_content_filter = typeof data.explicitContentFilter === 'number' ? data.explicitContentFilter - : ExplicitContentFilterLevels.indexOf(data.explicitContentFilter); + : ExplicitContentFilterLevels[data.explicitContentFilter]; } if (typeof data.defaultMessageNotifications !== 'undefined') { _data.default_message_notifications = - typeof data.defaultMessageNotifications === 'string' - ? DefaultMessageNotifications.indexOf(data.defaultMessageNotifications) - : data.defaultMessageNotifications; + typeof data.defaultMessageNotifications === 'number' + ? data.defaultMessageNotifications + : DefaultMessageNotificationLevels[data.defaultMessageNotifications]; } if (typeof data.systemChannelFlags !== 'undefined') { _data.system_channel_flags = SystemChannelFlags.resolve(data.systemChannelFlags); } if (typeof data.rulesChannel !== 'undefined') { - _data.rules_channel_id = this.client.channels.resolveID(data.rulesChannel); + _data.rules_channel_id = this.client.channels.resolveId(data.rulesChannel); } if (typeof data.publicUpdatesChannel !== 'undefined') { - _data.public_updates_channel_id = this.client.channels.resolveID(data.publicUpdatesChannel); + _data.public_updates_channel_id = this.client.channels.resolveId(data.publicUpdatesChannel); + } + if (typeof data.features !== 'undefined') { + _data.features = data.features; + } + if (typeof data.description !== 'undefined') { + _data.description = data.description; } if (data.preferredLocale) _data.preferred_locale = data.preferredLocale; return this.client.api @@ -1101,6 +836,76 @@ class Guild extends Base { .then(newData => this.client.actions.GuildUpdate.handle(newData).updated); } + /** + * Welcome channel data + * @typedef {Object} WelcomeChannelData + * @property {string} description The description to show for this welcome channel + * @property {GuildTextChannelResolvable} channel The channel to link for this welcome channel + * @property {EmojiIdentifierResolvable} [emoji] The emoji to display for this welcome channel + */ + + /** + * Welcome screen edit data + * @typedef {Object} WelcomeScreenEditData + * @property {boolean} [enabled] Whether the welcome screen is enabled + * @property {string} [description] The description for the welcome screen + * @property {WelcomeChannelData[]} [welcomeChannels] The welcome channel data for the welcome screen + */ + + /** + * Data that can be resolved to a GuildTextChannel object. This can be: + * * A TextChannel + * * A NewsChannel + * * A Snowflake + * @typedef {TextChannel|NewsChannel|Snowflake} GuildTextChannelResolvable + */ + + /** + * Data that can be resolved to a GuildVoiceChannel object. This can be: + * * A VoiceChannel + * * A StageChannel + * * A Snowflake + * @typedef {VoiceChannel|StageChannel|Snowflake} GuildVoiceChannelResolvable + */ + + /** + * Updates the guild's welcome screen + * @param {WelcomeScreenEditData} data Data to edit the welcome screen with + * @returns {Promise} + * @example + * guild.editWelcomeScreen({ + * description: 'Hello World', + * enabled: true, + * welcomeChannels: [ + * { + * description: 'foobar', + * channel: '222197033908436994', + * } + * ], + * }) + */ + async editWelcomeScreen(data) { + const { enabled, description, welcomeChannels } = data; + const welcome_channels = welcomeChannels?.map(welcomeChannelData => { + const emoji = this.emojis.resolve(welcomeChannelData.emoji); + return { + emoji_id: emoji && emoji.id, + emoji_name: emoji?.name ?? welcomeChannelData.emoji, + channel_id: this.channels.resolveId(welcomeChannelData.channel), + description: welcomeChannelData.description, + }; + }); + + const patchData = await this.client.api.guilds(this.id, 'welcome-screen').patch({ + data: { + welcome_channels, + description, + enabled, + }, + }); + return new WelcomeScreen(this, patchData); + } + /** * Edits the level of the explicit content filter. * @param {ExplicitContentFilterLevel|number} explicitContentFilter The new level of the explicit content filter @@ -1114,7 +919,7 @@ class Guild extends Base { /* eslint-disable max-len */ /** * Edits the setting of the default message notifications of the guild. - * @param {DefaultMessageNotifications|number} defaultMessageNotifications The new setting for the default message notifications + * @param {DefaultMessageNotificationLevel|number} defaultMessageNotifications The new default message notification level of the guild * @param {string} [reason] Reason for changing the setting of the default message notifications * @returns {Promise} */ @@ -1148,21 +953,6 @@ class Guild extends Base { return this.edit({ name }, reason); } - /** - * Edits the region of the guild. - * @param {string} region The new region of the guild - * @param {string} [reason] Reason for changing the guild's region - * @returns {Promise} - * @example - * // Edit the guild region - * guild.setRegion('london') - * .then(updated => console.log(`Updated guild region to ${updated.region}`)) - * .catch(console.error); - */ - setRegion(region, reason) { - return this.edit({ region }, reason); - } - /** * Edits the verification level of the guild. * @param {VerificationLevel|number} verificationLevel The new verification level of the guild @@ -1180,7 +970,7 @@ class Guild extends Base { /** * Edits the AFK channel of the guild. - * @param {ChannelResolvable} afkChannel The new AFK channel + * @param {VoiceChannelResolvable} afkChannel The new AFK channel * @param {string} [reason] Reason for changing the guild's AFK channel * @returns {Promise} * @example @@ -1195,7 +985,7 @@ class Guild extends Base { /** * Edits the system channel of the guild. - * @param {ChannelResolvable} systemChannel The new system channel + * @param {TextChannelResolvable} systemChannel The new system channel * @param {string} [reason] Reason for changing the guild's system channel * @returns {Promise} * @example @@ -1235,7 +1025,7 @@ class Guild extends Base { * .catch(console.error); */ async setIcon(icon, reason) { - return this.edit({ icon: await DataResolver.resolveImage(icon), reason }); + return this.edit({ icon: await DataResolver.resolveImage(icon) }, reason); } /** @@ -1265,7 +1055,7 @@ class Guild extends Base { * .catch(console.error); */ async setSplash(splash, reason) { - return this.edit({ splash: await DataResolver.resolveImage(splash), reason }); + return this.edit({ splash: await DataResolver.resolveImage(splash) }, reason); } /** @@ -1280,7 +1070,7 @@ class Guild extends Base { * .catch(console.error); */ async setDiscoverySplash(discoverySplash, reason) { - return this.edit({ discoverySplash: await DataResolver.resolveImage(discoverySplash), reason }); + return this.edit({ discoverySplash: await DataResolver.resolveImage(discoverySplash) }, reason); } /** @@ -1294,12 +1084,12 @@ class Guild extends Base { * .catch(console.error); */ async setBanner(banner, reason) { - return this.edit({ banner: await DataResolver.resolveImage(banner), reason }); + return this.edit({ banner: await DataResolver.resolveImage(banner) }, reason); } /** * Edits the rules channel of the guild. - * @param {ChannelResolvable} rulesChannel The new rules channel + * @param {TextChannelResolvable} rulesChannel The new rules channel * @param {string} [reason] Reason for changing the guild's rules channel * @returns {Promise} * @example @@ -1314,7 +1104,7 @@ class Guild extends Base { /** * Edits the community updates channel of the guild. - * @param {ChannelResolvable} publicUpdatesChannel The new community updates channel + * @param {TextChannelResolvable} publicUpdatesChannel The new community updates channel * @param {string} [reason] Reason for changing the guild's community updates channel * @returns {Promise} * @example @@ -1342,26 +1132,38 @@ class Guild extends Base { return this.edit({ preferredLocale }, reason); } + /** + * Data that can be resolved to give a Category Channel object. This can be: + * * A CategoryChannel object + * * A Snowflake + * @typedef {CategoryChannel|Snowflake} CategoryChannelResolvable + */ + /** * The data needed for updating a channel's position. * @typedef {Object} ChannelPosition - * @property {ChannelResolvable} channel Channel to update - * @property {number} position New position for the channel + * @property {GuildChannel|Snowflake} channel Channel to update + * @property {number} [position] New position for the channel + * @property {CategoryChannelResolvable} [parent] Parent channel for this channel + * @property {boolean} [lockPermissions] If the overwrites should be locked to the parents overwrites */ /** * Batch-updates the guild's channels' positions. + * Only one channel's parent can be changed at a time * @param {ChannelPosition[]} channelPositions Channel positions to update * @returns {Promise} * @example - * guild.setChannelPositions([{ channel: channelID, position: newChannelIndex }]) + * guild.setChannelPositions([{ channel: channelId, position: newChannelIndex }]) * .then(guild => console.log(`Updated channel positions for ${guild}`)) * .catch(console.error); */ setChannelPositions(channelPositions) { const updatedChannels = channelPositions.map(r => ({ - id: this.client.channels.resolveID(r.channel), + id: this.client.channels.resolveId(r.channel), position: r.position, + lock_permissions: r.lockPermissions, + parent_id: typeof r.parent !== 'undefined' ? this.channels.resolveId(r.parent) : undefined, })); return this.client.api @@ -1379,7 +1181,7 @@ class Guild extends Base { /** * The data needed for updating a guild role's position * @typedef {Object} GuildRolePosition - * @property {RoleResolveable} role The ID of the role + * @property {RoleResolvable} role The role's id * @property {number} position The position to update */ @@ -1388,14 +1190,14 @@ class Guild extends Base { * @param {GuildRolePosition[]} rolePositions Role positions to update * @returns {Promise} * @example - * guild.setRolePositions([{ role: roleID, position: updatedRoleIndex }]) - * .then(guild => console.log(`Role permissions updated for ${guild}`)) + * guild.setRolePositions([{ role: roleId, position: updatedRoleIndex }]) + * .then(guild => console.log(`Role positions updated for ${guild}`)) * .catch(console.error); */ setRolePositions(rolePositions) { // Make sure rolePositions are prepared for API rolePositions = rolePositions.map(o => ({ - id: this.roles.resolveID(o.role), + id: this.roles.resolveId(o.role), position: o.position, })); @@ -1415,29 +1217,18 @@ class Guild extends Base { } /** - * Edits the guild's embed. - * @param {GuildWidgetData} embed The embed for the guild - * @param {string} [reason] Reason for changing the guild's embed - * @returns {Promise} - * @deprecated - */ - setEmbed(embed, reason) { - return this.setWidget(embed, reason); - } - - /** - * Edits the guild's widget. - * @param {GuildWidgetData} widget The widget for the guild - * @param {string} [reason] Reason for changing the guild's widget + * Edits the guild's widget settings. + * @param {GuildWidgetSettingsData} settings The widget settings for the guild + * @param {string} [reason] Reason for changing the guild's widget settings * @returns {Promise} */ - setWidget(widget, reason) { + setWidgetSettings(settings, reason) { return this.client.api .guilds(this.id) .widget.patch({ data: { - enabled: widget.enabled, - channel_id: this.channels.resolveID(widget.channel), + enabled: settings.enabled, + channel_id: this.channels.resolveId(settings.channel), }, reason, }) @@ -1454,7 +1245,7 @@ class Guild extends Base { * .catch(console.error); */ leave() { - if (this.ownerID === this.client.user.id) return Promise.reject(new Error('GUILD_OWNED')); + if (this.ownerId === this.client.user.id) return Promise.reject(new Error('GUILD_OWNED')); return this.client.api .users('@me') .guilds(this.id) @@ -1486,45 +1277,23 @@ class Guild extends Base { * @returns {boolean} */ equals(guild) { - let equal = + return ( guild && guild instanceof this.constructor && this.id === guild.id && this.available === guild.available && this.splash === guild.splash && this.discoverySplash === guild.discoverySplash && - this.region === guild.region && this.name === guild.name && this.memberCount === guild.memberCount && this.large === guild.large && this.icon === guild.icon && - this.ownerID === guild.ownerID && + this.ownerId === guild.ownerId && this.verificationLevel === guild.verificationLevel && - this.embedEnabled === guild.embedEnabled && (this.features === guild.features || (this.features.length === guild.features.length && - this.features.every((feat, i) => feat === guild.features[i]))); - - if (equal) { - if (this.embedChannel) { - if (!guild.embedChannel || this.embedChannel.id !== guild.embedChannel.id) equal = false; - } else if (guild.embedChannel) { - equal = false; - } - } - - return equal; - } - - /** - * When concatenated with a string, this automatically returns the guild's name instead of the Guild object. - * @returns {string} - * @example - * // Logs: Hello from My Guild! - * console.log(`Hello from ${guild}!`); - */ - toString() { - return this.name; + this.features.every((feat, i) => feat === guild.features[i]))) + ); } toJSON() { @@ -1543,8 +1312,37 @@ class Guild extends Base { } /** - * Creates a collection of this guild's roles, sorted by their position and IDs. - * @returns {Collection} + * The voice state adapter for this guild that can be used with @discordjs/voice to play audio in voice + * and stage channels. + * @type {Function} + * @readonly + * @example + * const { joinVoiceChannel } = require('@discordjs/voice'); + * const voiceConnection = joinVoiceChannel({ + * channelId: channel.id, + * guildId: channel.guild.id, + * adapterCreator: channel.guild.voiceAdapterCreator, + * }); + */ + get voiceAdapterCreator() { + return methods => { + this.client.voice.adapters.set(this.id, methods); + return { + sendPayload: data => { + if (this.shard.status !== Status.READY) return false; + this.shard.send(data); + return true; + }, + destroy: () => { + this.client.voice.adapters.delete(this.id); + }, + }; + }; + } + + /** + * Creates a collection of this guild's roles, sorted by their position and ids. + * @returns {Collection} * @private */ _sortedRoles() { @@ -1552,18 +1350,18 @@ class Guild extends Base { } /** - * Creates a collection of this guild's or a specific category's channels, sorted by their position and IDs. + * Creates a collection of this guild's or a specific category's channels, sorted by their position and ids. * @param {GuildChannel} [channel] Category to get the channels of - * @returns {Collection} + * @returns {Collection} * @private */ _sortedChannels(channel) { - const category = channel.type === ChannelTypes.CATEGORY; + const category = channel.type === ChannelTypes.GUILD_CATEGORY; return Util.discordSort( this.channels.cache.filter( c => - (['text', 'news', 'store'].includes(channel.type) - ? ['text', 'news', 'store'].includes(c.type) + (['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_STORE'].includes(channel.type) + ? ['GUILD_TEXT', 'GUILD_NEWS', 'GUILD_STORE'].includes(c.type) : c.type === channel.type) && (category || c.parent === channel.parent), ), @@ -1571,13 +1369,9 @@ class Guild extends Base { } } -Guild.prototype.setEmbed = deprecate(Guild.prototype.setEmbed, 'Guild#setEmbed: Use setWidget instead'); - -Guild.prototype.fetchEmbed = deprecate(Guild.prototype.fetchEmbed, 'Guild#fetchEmbed: Use fetchWidget instead'); - -Guild.prototype.fetchVanityCode = deprecate( - Guild.prototype.fetchVanityCode, - 'Guild#fetchVanityCode: Use fetchVanityData() instead', -); - module.exports = Guild; + +/** + * @external APIGuild + * @see {@link https://discord.com/developers/docs/resources/guild#guild-object} + */ diff --git a/node_modules/discord.js/src/structures/GuildAuditLogs.js b/node_modules/discord.js/src/structures/GuildAuditLogs.js index 823b0037..f4f097f8 100644 --- a/node_modules/discord.js/src/structures/GuildAuditLogs.js +++ b/node_modules/discord.js/src/structures/GuildAuditLogs.js @@ -1,10 +1,13 @@ 'use strict'; +const { Collection } = require('@discordjs/collection'); const Integration = require('./Integration'); +const StageInstance = require('./StageInstance'); +const Sticker = require('./Sticker'); const Webhook = require('./Webhook'); -const Collection = require('../util/Collection'); -const { PartialTypes } = require('../util/Constants'); -const Snowflake = require('../util/Snowflake'); +const { OverwriteTypes, PartialTypes } = require('../util/Constants'); +const Permissions = require('../util/Permissions'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); const Util = require('../util/Util'); /** @@ -18,6 +21,9 @@ const Util = require('../util/Util'); * * EMOJI * * MESSAGE * * INTEGRATION + * * STAGE_INSTANCE + * * STICKER + * * THREAD * @typedef {string} AuditLogTargetType */ @@ -37,6 +43,9 @@ const Targets = { EMOJI: 'EMOJI', MESSAGE: 'MESSAGE', INTEGRATION: 'INTEGRATION', + STAGE_INSTANCE: 'STAGE_INSTANCE', + STICKER: 'STICKER', + THREAD: 'THREAD', UNKNOWN: 'UNKNOWN', }; @@ -78,7 +87,16 @@ const Targets = { * * INTEGRATION_CREATE: 80 * * INTEGRATION_UPDATE: 81 * * INTEGRATION_DELETE: 82 - * @typedef {?number|string} AuditLogAction + * * STAGE_INSTANCE_CREATE: 83 + * * STAGE_INSTANCE_UPDATE: 84 + * * STAGE_INSTANCE_DELETE: 85 + * * STICKER_CREATE: 90 + * * STICKER_UPDATE: 91 + * * STICKER_DELETE: 92 + * * THREAD_CREATE: 110 + * * THREAD_UPDATE: 111 + * * THREAD_DELETE: 112 + * @typedef {?(number|string)} AuditLogAction */ /** @@ -123,6 +141,15 @@ const Actions = { INTEGRATION_CREATE: 80, INTEGRATION_UPDATE: 81, INTEGRATION_DELETE: 82, + STAGE_INSTANCE_CREATE: 83, + STAGE_INSTANCE_UPDATE: 84, + STAGE_INSTANCE_DELETE: 85, + STICKER_CREATE: 90, + STICKER_UPDATE: 91, + STICKER_DELETE: 92, + THREAD_CREATE: 110, + THREAD_UPDATE: 111, + THREAD_DELETE: 112, }; /** @@ -130,7 +157,8 @@ const Actions = { */ class GuildAuditLogs { constructor(guild, data) { - if (data.users) for (const user of data.users) guild.client.users.add(user); + if (data.users) for (const user of data.users) guild.client.users._add(user); + if (data.threads) for (const thread of data.threads) guild.client.channels._add(thread, guild); /** * Cached webhooks * @type {Collection} @@ -178,15 +206,21 @@ class GuildAuditLogs { /** * The target of an entry. It can be one of: * * A guild + * * A channel * * A user * * A role - * * An emoji * * An invite * * A webhook + * * An emoji + * * A message * * An integration + * * A stage instance + * * A sticker + * * A thread * * An object with an id key if target was deleted * * An object where the keys represent either the new value or the old value - * @typedef {?Object|Guild|User|Role|GuildEmoji|Invite|Webhook|Integration} AuditLogEntryTarget + * @typedef {?(Object|Guild|Channel|User|Role|Invite|Webhook|GuildEmoji|Message|Integration|StageInstance|Sticker)} + * AuditLogEntryTarget */ /** @@ -203,7 +237,11 @@ class GuildAuditLogs { if (target < 60) return Targets.WEBHOOK; if (target < 70) return Targets.EMOJI; if (target < 80) return Targets.MESSAGE; - if (target < 90) return Targets.INTEGRATION; + if (target < 83) return Targets.INTEGRATION; + if (target < 86) return Targets.STAGE_INSTANCE; + if (target < 100) return Targets.STICKER; + if (target < 110) return Targets.UNKNOWN; + if (target < 120) return Targets.THREAD; return Targets.UNKNOWN; } @@ -234,6 +272,9 @@ class GuildAuditLogs { Actions.EMOJI_CREATE, Actions.MESSAGE_PIN, Actions.INTEGRATION_CREATE, + Actions.STAGE_INSTANCE_CREATE, + Actions.STICKER_CREATE, + Actions.THREAD_CREATE, ].includes(action) ) { return 'CREATE'; @@ -255,6 +296,9 @@ class GuildAuditLogs { Actions.MESSAGE_BULK_DELETE, Actions.MESSAGE_UNPIN, Actions.INTEGRATION_DELETE, + Actions.STAGE_INSTANCE_DELETE, + Actions.STICKER_DELETE, + Actions.THREAD_DELETE, ].includes(action) ) { return 'DELETE'; @@ -273,6 +317,9 @@ class GuildAuditLogs { Actions.WEBHOOK_UPDATE, Actions.EMOJI_UPDATE, Actions.INTEGRATION_UPDATE, + Actions.STAGE_INSTANCE_UPDATE, + Actions.STICKER_UPDATE, + Actions.THREAD_UPDATE, ].includes(action) ) { return 'UPDATE'; @@ -314,19 +361,21 @@ class GuildAuditLogsEntry { * The reason of this entry * @type {?string} */ - this.reason = data.reason || null; + this.reason = data.reason ?? null; /** * The user that executed this entry - * @type {User} + * @type {?User} */ - this.executor = guild.client.options.partials.includes(PartialTypes.USER) - ? guild.client.users.add({ id: data.user_id }) - : guild.client.users.cache.get(data.user_id); + this.executor = data.user_id + ? guild.client.options.partials.includes(PartialTypes.USER) + ? guild.client.users._add({ id: data.user_id }) + : guild.client.users.cache.get(data.user_id) + : null; /** * An entry in the audit log representing a specific change. - * @typedef {object} AuditLogChange + * @typedef {Object} AuditLogChange * @property {string} key The property that was changed, e.g. `nick` for nickname changes * @property {*} [old] The old value of the change, e.g. for nicknames, the old nickname * @property {*} [new] The new value of the change, e.g. for nicknames, the new nickname @@ -334,19 +383,19 @@ class GuildAuditLogsEntry { /** * Specific property changes - * @type {AuditLogChange[]} + * @type {?AuditLogChange[]} */ - this.changes = data.changes ? data.changes.map(c => ({ key: c.key, old: c.old_value, new: c.new_value })) : null; + this.changes = data.changes?.map(c => ({ key: c.key, old: c.old_value, new: c.new_value })) ?? null; /** - * The ID of this entry + * The entry's id * @type {Snowflake} */ this.id = data.id; /** * Any extra data from the entry - * @type {?Object|Role|GuildMember} + * @type {?(Object|Role|GuildMember)} */ this.extra = null; switch (data.action_type) { @@ -361,7 +410,7 @@ class GuildAuditLogsEntry { case Actions.MESSAGE_DELETE: case Actions.MESSAGE_BULK_DELETE: this.extra = { - channel: guild.channels.cache.get(data.options.channel_id) || { id: data.options.channel_id }, + channel: guild.channels.cache.get(data.options.channel_id) ?? { id: data.options.channel_id }, count: Number(data.options.count), }; break; @@ -369,8 +418,8 @@ class GuildAuditLogsEntry { case Actions.MESSAGE_PIN: case Actions.MESSAGE_UNPIN: this.extra = { - channel: guild.client.channels.cache.get(data.options.channel_id) || { id: data.options.channel_id }, - messageID: data.options.message_id, + channel: guild.client.channels.cache.get(data.options.channel_id) ?? { id: data.options.channel_id }, + messageId: data.options.message_id, }; break; @@ -383,16 +432,19 @@ class GuildAuditLogsEntry { case Actions.CHANNEL_OVERWRITE_CREATE: case Actions.CHANNEL_OVERWRITE_UPDATE: case Actions.CHANNEL_OVERWRITE_DELETE: - switch (data.options.type) { - case 'member': - this.extra = guild.members.cache.get(data.options.id) || { id: data.options.id, type: 'member' }; + switch (Number(data.options.type)) { + case OverwriteTypes.role: + this.extra = guild.roles.cache.get(data.options.id) ?? { + id: data.options.id, + name: data.options.role_name, + type: OverwriteTypes[OverwriteTypes.role], + }; break; - case 'role': - this.extra = guild.roles.cache.get(data.options.id) || { + case OverwriteTypes.member: + this.extra = guild.members.cache.get(data.options.id) ?? { id: data.options.id, - name: data.options.role_name, - type: 'role', + type: OverwriteTypes[OverwriteTypes.member], }; break; @@ -401,6 +453,14 @@ class GuildAuditLogsEntry { } break; + case Actions.STAGE_INSTANCE_CREATE: + case Actions.STAGE_INSTANCE_DELETE: + case Actions.STAGE_INSTANCE_UPDATE: + this.extra = { + channel: guild.client.channels.cache.get(data.options?.channel_id) ?? { id: data.options?.channel_id }, + }; + break; + default: break; } @@ -412,25 +472,25 @@ class GuildAuditLogsEntry { this.target = null; if (targetType === Targets.UNKNOWN) { this.target = this.changes.reduce((o, c) => { - o[c.key] = c.new || c.old; + o[c.key] = c.new ?? c.old; return o; }, {}); this.target.id = data.target_id; // MEMBER_DISCONNECT and similar types do not provide a target_id. } else if (targetType === Targets.USER && data.target_id) { this.target = guild.client.options.partials.includes(PartialTypes.USER) - ? guild.client.users.add({ id: data.target_id }) + ? guild.client.users._add({ id: data.target_id }) : guild.client.users.cache.get(data.target_id); } else if (targetType === Targets.GUILD) { this.target = guild.client.guilds.cache.get(data.target_id); } else if (targetType === Targets.WEBHOOK) { this.target = - logs.webhooks.get(data.target_id) || + logs.webhooks.get(data.target_id) ?? new Webhook( guild.client, this.changes.reduce( (o, c) => { - o[c.key] = c.new || c.old; + o[c.key] = c.new ?? c.old; return o; }, { @@ -441,14 +501,15 @@ class GuildAuditLogsEntry { ); } else if (targetType === Targets.INVITE) { this.target = guild.members.fetch(guild.client.user.id).then(me => { - if (me.permissions.has('MANAGE_GUILD')) { - const change = this.changes.find(c => c.key === 'code'); - return guild.fetchInvites().then(invites => { - this.target = invites.find(i => i.code === (change.new || change.old)); + if (me.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { + let change = this.changes.find(c => c.key === 'code'); + change = change.new ?? change.old; + return guild.invites.fetch().then(invites => { + this.target = invites.find(i => i.code === change) ?? null; }); } else { this.target = this.changes.reduce((o, c) => { - o[c.key] = c.new || c.old; + o[c.key] = c.new ?? c.old; return o; }, {}); return this.target; @@ -458,24 +519,64 @@ class GuildAuditLogsEntry { // Discord sends a channel id for the MESSAGE_BULK_DELETE action type. this.target = data.action_type === Actions.MESSAGE_BULK_DELETE - ? guild.channels.cache.get(data.target_id) || { id: data.target_id } + ? guild.channels.cache.get(data.target_id) ?? { id: data.target_id } : guild.client.users.cache.get(data.target_id); } else if (targetType === Targets.INTEGRATION) { this.target = - logs.integrations.get(data.target_id) || + logs.integrations.get(data.target_id) ?? new Integration( guild.client, this.changes.reduce( (o, c) => { - o[c.key] = c.new || c.old; + o[c.key] = c.new ?? c.old; return o; }, { id: data.target_id }, ), guild, ); + } else if (targetType === Targets.CHANNEL || targetType === Targets.THREAD) { + this.target = + guild.channels.cache.get(data.target_id) ?? + this.changes.reduce( + (o, c) => { + o[c.key] = c.new ?? c.old; + return o; + }, + { id: data.target_id }, + ); + } else if (targetType === Targets.STAGE_INSTANCE) { + this.target = + guild.stageInstances.cache.get(data.target_id) ?? + new StageInstance( + guild.client, + this.changes.reduce( + (o, c) => { + o[c.key] = c.new ?? c.old; + return o; + }, + { + id: data.target_id, + channel_id: data.options?.channel_id, + guild_id: guild.id, + }, + ), + ); + } else if (targetType === Targets.STICKER) { + this.target = + guild.stickers.cache.get(data.target_id) ?? + new Sticker( + guild.client, + this.changes.reduce( + (o, c) => { + o[c.key] = c.new ?? c.old; + return o; + }, + { id: data.target_id }, + ), + ); } else if (data.target_id) { - this.target = guild[`${targetType.toLowerCase()}s`].cache.get(data.target_id) || { id: data.target_id }; + this.target = guild[`${targetType.toLowerCase()}s`]?.cache.get(data.target_id) ?? { id: data.target_id }; } } @@ -485,7 +586,7 @@ class GuildAuditLogsEntry { * @readonly */ get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; + return SnowflakeUtil.deconstruct(this.id).timestamp; } /** diff --git a/node_modules/discord.js/src/structures/GuildChannel.js b/node_modules/discord.js/src/structures/GuildChannel.js index f397c3c3..0d711de2 100644 --- a/node_modules/discord.js/src/structures/GuildChannel.js +++ b/node_modules/discord.js/src/structures/GuildChannel.js @@ -1,11 +1,11 @@ 'use strict'; +const { Collection } = require('@discordjs/collection'); const Channel = require('./Channel'); -const Invite = require('./Invite'); const PermissionOverwrites = require('./PermissionOverwrites'); -const Role = require('./Role'); -const { Error, TypeError } = require('../errors'); -const Collection = require('../util/Collection'); +const { Error } = require('../errors'); +const PermissionOverwriteManager = require('../managers/PermissionOverwriteManager'); +const { ChannelTypes, VoiceBasedChannelTypes } = require('../util/Constants'); const Permissions = require('../util/Permissions'); const Util = require('../util/Util'); @@ -16,64 +16,93 @@ const Util = require('../util/Util'); * - {@link CategoryChannel} * - {@link NewsChannel} * - {@link StoreChannel} + * - {@link StageChannel} * @extends {Channel} * @abstract */ class GuildChannel extends Channel { /** * @param {Guild} guild The guild the guild channel is part of - * @param {Object} data The data for the guild channel + * @param {APIChannel} data The data for the guild channel + * @param {Client} [client] A safety parameter for the client that instantiated this */ - constructor(guild, data) { - super(guild.client, data); + constructor(guild, data, client) { + super(guild?.client ?? client, data, false); /** * The guild the channel is in * @type {Guild} */ this.guild = guild; - } - - _patch(data) { - super._patch(data); /** - * The name of the guild channel - * @type {string} + * The id of the guild the channel is in + * @type {Snowflake} */ - this.name = data.name; + this.guildId = guild?.id ?? data.guild_id; + this.parentId = this.parentId ?? null; /** - * The raw position of the channel from discord - * @type {number} + * A manager of permission overwrites that belong to this channel + * @type {PermissionOverwriteManager} */ - this.rawPosition = data.position; + this.permissionOverwrites = new PermissionOverwriteManager(this); - /** - * The ID of the category parent of this channel - * @type {?Snowflake} - */ - this.parentID = data.parent_id || null; + this._patch(data); + } - /** - * A map of permission overwrites in this channel for roles and users - * @type {Collection} - */ - this.permissionOverwrites = new Collection(); - if (data.permission_overwrites) { + _patch(data) { + super._patch(data); + + if ('name' in data) { + /** + * The name of the guild channel + * @type {string} + */ + this.name = data.name; + } + + if ('position' in data) { + /** + * The raw position of the channel from discord + * @type {number} + */ + this.rawPosition = data.position; + } + + if ('guild_id' in data) { + this.guildId = data.guild_id; + } + + if ('parent_id' in data) { + /** + * The id of the category parent of this channel + * @type {?Snowflake} + */ + this.parentId = data.parent_id; + } + + if ('permission_overwrites' in data) { + this.permissionOverwrites.cache.clear(); for (const overwrite of data.permission_overwrites) { - this.permissionOverwrites.set(overwrite.id, new PermissionOverwrites(this, overwrite)); + this.permissionOverwrites._add(overwrite); } } } + _clone() { + const clone = super._clone(); + clone.permissionOverwrites = new PermissionOverwriteManager(clone, this.permissionOverwrites.cache.values()); + return clone; + } + /** * The category parent of this channel * @type {?CategoryChannel} * @readonly */ get parent() { - return this.guild.channels.cache.get(this.parentID) || null; + return this.guild.channels.resolve(this.parentId); } /** @@ -83,13 +112,36 @@ class GuildChannel extends Channel { */ get permissionsLocked() { if (!this.parent) return null; - if (this.permissionOverwrites.size !== this.parent.permissionOverwrites.size) return false; - return this.permissionOverwrites.every((value, key) => { - const testVal = this.parent.permissionOverwrites.get(key); + + // Get all overwrites + const overwriteIds = new Set([ + ...this.permissionOverwrites.cache.keys(), + ...this.parent.permissionOverwrites.cache.keys(), + ]); + + // Compare all overwrites + return [...overwriteIds].every(key => { + const channelVal = this.permissionOverwrites.cache.get(key); + const parentVal = this.parent.permissionOverwrites.cache.get(key); + + // Handle empty overwrite + if ( + (!channelVal && + parentVal.deny.bitfield === Permissions.defaultBit && + parentVal.allow.bitfield === Permissions.defaultBit) || + (!parentVal && + channelVal.deny.bitfield === Permissions.defaultBit && + channelVal.allow.bitfield === Permissions.defaultBit) + ) { + return true; + } + + // Compare overwrites return ( - testVal !== undefined && - testVal.deny.bitfield === value.deny.bitfield && - testVal.allow.bitfield === value.allow.bitfield + typeof channelVal !== 'undefined' && + typeof parentVal !== 'undefined' && + channelVal.deny.bitfield === parentVal.deny.bitfield && + channelVal.allow.bitfield === parentVal.allow.bitfield ); }); } @@ -101,7 +153,7 @@ class GuildChannel extends Channel { */ get position() { const sorted = this.guild._sortedChannels(this); - return sorted.array().indexOf(sorted.get(this.id)); + return [...sorted.values()].indexOf(sorted.get(this.id)); } /** @@ -113,20 +165,19 @@ class GuildChannel extends Channel { const member = this.guild.members.resolve(memberOrRole); if (member) return this.memberPermissions(member); const role = this.guild.roles.resolve(memberOrRole); - if (role) return this.rolePermissions(role); - return null; + return role && this.rolePermissions(role); } overwritesFor(member, verified = false, roles = null) { if (!verified) member = this.guild.members.resolve(member); if (!member) return []; - roles = roles || member.roles.cache; + if (!roles) roles = member.roles.cache; const roleOverwrites = []; let memberOverwrites; let everyoneOverwrites; - for (const overwrite of this.permissionOverwrites.values()) { + for (const overwrite of this.permissionOverwrites.cache.values()) { if (overwrite.id === this.guild.id) { everyoneOverwrites = overwrite; } else if (roles.has(overwrite.id)) { @@ -150,7 +201,7 @@ class GuildChannel extends Channel { * @private */ memberPermissions(member) { - if (member.id === this.guild.ownerID) return new Permissions(Permissions.ALL).freeze(); + if (member.id === this.guild.ownerId) return new Permissions(Permissions.ALL).freeze(); const roles = member.roles.cache; const permissions = new Permissions(roles.map(role => role.permissions)); @@ -160,12 +211,12 @@ class GuildChannel extends Channel { const overwrites = this.overwritesFor(member, true, roles); return permissions - .remove(overwrites.everyone ? overwrites.everyone.deny : 0) - .add(overwrites.everyone ? overwrites.everyone.allow : 0) - .remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.deny) : 0) - .add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allow) : 0) - .remove(overwrites.member ? overwrites.member.deny : 0) - .add(overwrites.member ? overwrites.member.allow : 0) + .remove(overwrites.everyone?.deny ?? Permissions.defaultBit) + .add(overwrites.everyone?.allow ?? Permissions.defaultBit) + .remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.deny) : Permissions.defaultBit) + .add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allow) : Permissions.defaultBit) + .remove(overwrites.member?.deny ?? Permissions.defaultBit) + .add(overwrites.member?.allow ?? Permissions.defaultBit) .freeze(); } @@ -178,112 +229,38 @@ class GuildChannel extends Channel { rolePermissions(role) { if (role.permissions.has(Permissions.FLAGS.ADMINISTRATOR)) return new Permissions(Permissions.ALL).freeze(); - const everyoneOverwrites = this.permissionOverwrites.get(this.guild.id); - const roleOverwrites = this.permissionOverwrites.get(role.id); + const everyoneOverwrites = this.permissionOverwrites.cache.get(this.guild.id); + const roleOverwrites = this.permissionOverwrites.cache.get(role.id); return role.permissions - .remove(everyoneOverwrites ? everyoneOverwrites.deny : 0) - .add(everyoneOverwrites ? everyoneOverwrites.allow : 0) - .remove(roleOverwrites ? roleOverwrites.deny : 0) - .add(roleOverwrites ? roleOverwrites.allow : 0) + .remove(everyoneOverwrites?.deny ?? Permissions.defaultBit) + .add(everyoneOverwrites?.allow ?? Permissions.defaultBit) + .remove(roleOverwrites?.deny ?? Permissions.defaultBit) + .add(roleOverwrites?.allow ?? Permissions.defaultBit) .freeze(); } - /** - * Replaces the permission overwrites in this channel. - * @param {OverwriteResolvable[]|Collection} overwrites - * Permission overwrites the channel gets updated with - * @param {string} [reason] Reason for updating the channel overwrites - * @returns {Promise} - * @example - * channel.overwritePermissions([ - * { - * id: message.author.id, - * deny: ['VIEW_CHANNEL'], - * }, - * ], 'Needed to change permissions'); - */ - overwritePermissions(overwrites, reason) { - if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) { - return Promise.reject( - new TypeError('INVALID_TYPE', 'overwrites', 'Array or Collection of Permission Overwrites', true), - ); - } - return this.edit({ permissionOverwrites: overwrites, reason }).then(() => this); - } - - /** - * Updates Overwrites for a user or role in this channel. (creates if non-existent) - * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update - * @param {PermissionOverwriteOptions} options The options for the update - * @param {string} [reason] Reason for creating/editing this overwrite - * @returns {Promise} - * @example - * // Update or Create permission overwrites for a message author - * message.channel.updateOverwrite(message.author, { - * SEND_MESSAGES: false - * }) - * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id))) - * .catch(console.error); - */ - updateOverwrite(userOrRole, options, reason) { - userOrRole = this.guild.roles.resolve(userOrRole) || this.client.users.resolve(userOrRole); - if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role')); - - const existing = this.permissionOverwrites.get(userOrRole.id); - if (existing) return existing.update(options, reason).then(() => this); - return this.createOverwrite(userOrRole, options, reason); - } - - /** - * Overwrites the permissions for a user or role in this channel. (replaces if existent) - * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update - * @param {PermissionOverwriteOptions} options The options for the update - * @param {string} [reason] Reason for creating/editing this overwrite - * @returns {Promise} - * @example - * // Create or Replace permissions overwrites for a message author - * message.channel.createOverwrite(message.author, { - * SEND_MESSAGES: false - * }) - * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id))) - * .catch(console.error); - */ - createOverwrite(userOrRole, options, reason) { - userOrRole = this.guild.roles.resolve(userOrRole) || this.client.users.resolve(userOrRole); - if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role')); - - const type = userOrRole instanceof Role ? 'role' : 'member'; - const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options); - - return this.client.api - .channels(this.id) - .permissions[userOrRole.id].put({ - data: { id: userOrRole.id, type, allow: allow.bitfield, deny: deny.bitfield }, - reason, - }) - .then(() => this); - } - /** * Locks in the permission overwrites from the parent channel. * @returns {Promise} */ lockPermissions() { if (!this.parent) return Promise.reject(new Error('GUILD_CHANNEL_ORPHAN')); - const permissionOverwrites = this.parent.permissionOverwrites.map(overwrite => overwrite.toJSON()); + const permissionOverwrites = this.parent.permissionOverwrites.cache.map(overwrite => overwrite.toJSON()); return this.edit({ permissionOverwrites }); } /** - * A collection of members that can see this channel, mapped by their ID + * A collection of cached members of this channel, mapped by their ids. + * Members that can view this channel, if the channel is text based. + * Members in the channel, if the channel is voice based. * @type {Collection} * @readonly */ get members() { const members = new Collection(); for (const member of this.guild.members.cache.values()) { - if (this.permissionsFor(member).has('VIEW_CHANNEL', false)) { + if (this.permissionsFor(member).has(Permissions.FLAGS.VIEW_CHANNEL, false)) { members.set(member.id, member); } } @@ -294,17 +271,21 @@ class GuildChannel extends Channel { * The data for a guild channel. * @typedef {Object} ChannelData * @property {string} [name] The name of the channel + * @property {ChannelType} [type] The type of the the channel (only conversion between text and news is supported) * @property {number} [position] The position of the channel * @property {string} [topic] The topic of the text channel * @property {boolean} [nsfw] Whether the channel is NSFW * @property {number} [bitrate] The bitrate of the voice channel * @property {number} [userLimit] The user limit of the voice channel - * @property {?Snowflake} [parentID] The parent ID of the channel + * @property {?CategoryChannelResolvable} [parent] The parent of the channel * @property {boolean} [lockPermissions] * Lock the permissions of the channel to what the parent's permissions are * @property {OverwriteResolvable[]|Collection} [permissionOverwrites] * Permission overwrites for the channel * @property {number} [rateLimitPerUser] The ratelimit per user for the channel in seconds + * @property {ThreadAutoArchiveDuration} [defaultAutoArchiveDuration] + * The default auto archive duration for all new threads in this channel + * @property {?string} [rtcRegion] The RTC region of the channel */ /** @@ -319,6 +300,8 @@ class GuildChannel extends Channel { * .catch(console.error); */ async edit(data, reason) { + if (data.parent) data.parent = this.client.channels.resolveId(data.parent); + if (typeof data.position !== 'undefined') { await Util.setPosition( this, @@ -342,34 +325,39 @@ class GuildChannel extends Channel { } if (data.lockPermissions) { - if (data.parentID) { - const newParent = this.guild.channels.resolve(data.parentID); - if (newParent && newParent.type === 'category') { - permission_overwrites = newParent.permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild)); + if (data.parent) { + const newParent = this.guild.channels.resolve(data.parent); + if (newParent?.type === 'GUILD_CATEGORY') { + permission_overwrites = newParent.permissionOverwrites.cache.map(o => + PermissionOverwrites.resolve(o, this.guild), + ); } } else if (this.parent) { - permission_overwrites = this.parent.permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild)); + permission_overwrites = this.parent.permissionOverwrites.cache.map(o => + PermissionOverwrites.resolve(o, this.guild), + ); } } const newData = await this.client.api.channels(this.id).patch({ data: { - name: (data.name || this.name).trim(), + name: (data.name ?? this.name).trim(), + type: ChannelTypes[data.type], topic: data.topic, nsfw: data.nsfw, - bitrate: data.bitrate || this.bitrate, - user_limit: typeof data.userLimit !== 'undefined' ? data.userLimit : this.userLimit, - parent_id: data.parentID, + bitrate: data.bitrate ?? this.bitrate, + user_limit: data.userLimit ?? this.userLimit, + rtc_region: data.rtcRegion ?? this.rtcRegion, + parent_id: data.parent, lock_permissions: data.lockPermissions, rate_limit_per_user: data.rateLimitPerUser, + default_auto_archive_duration: data.defaultAutoArchiveDuration, permission_overwrites, }, reason, }); - const clone = this._clone(); - clone._patch(newData); - return clone; + return this.client.actions.ChannelUpdate.handle(newData).updated; } /** @@ -388,11 +376,16 @@ class GuildChannel extends Channel { } /** - * Sets the category parent of this channel. - * @param {?CategoryChannel|Snowflake} channel Parent channel - * @param {Object} [options={}] Options to pass - * @param {boolean} [options.lockPermissions=true] Lock the permissions to what the parent's permissions are - * @param {string} [options.reason] Reason for modifying the parent of this channel + * Options used to set parent of a channel. + * @typedef {Object} SetParentOptions + * @property {boolean} [lockPermissions=true] Whether to lock the permissions to what the parent's permissions are + * @property {string} [reason] The reason for modifying the parent of the channel + */ + + /** + * Sets the parent of this channel. + * @param {?CategoryChannelResolvable} channel The category channel to set as the parent + * @param {SetParentOptions} [options={}] The options for setting the parent * @returns {Promise} * @example * // Add a parent to a channel @@ -404,7 +397,7 @@ class GuildChannel extends Channel { return this.edit( { // eslint-disable-next-line no-prototype-builtins - parentID: channel !== null ? (channel.hasOwnProperty('id') ? channel.id : channel) : null, + parent: channel ?? null, lockPermissions, }, reason, @@ -426,12 +419,17 @@ class GuildChannel extends Channel { return this.edit({ topic }, reason); } + /** + * Options used to set position of a channel. + * @typedef {Object} SetChannelPositionOptions + * @param {boolean} [relative=false] Whether or not to change the position relative to its current value + * @param {string} [reason] The reason for changing the position + */ + /** * Sets a new position for the guild channel. * @param {number} position The new position for the guild channel - * @param {Object} [options] Options for setting position - * @param {boolean} [options.relative=false] Change the position relative to its current value - * @param {string} [options.reason] Reason for changing the position + * @param {SetChannelPositionOptions} [options] Options for setting position * @returns {Promise} * @example * // Set a new channel position @@ -457,14 +455,32 @@ class GuildChannel extends Channel { } /** - * Creates an invite to this guild channel. - * @param {Object} [options={}] Options for the invite - * @param {boolean} [options.temporary=false] Whether members that joined via the invite should be automatically + * Data that can be resolved to an Application. This can be: + * * An Application + * * An Activity with associated Application + * * A Snowflake + * @typedef {Application|Snowflake} ApplicationResolvable + */ + + /** + * Options used to create an invite to a guild channel. + * @typedef {Object} CreateInviteOptions + * @property {boolean} [temporary=false] Whether members that joined via the invite should be automatically * kicked after 24 hours if they have not yet received a role - * @param {number} [options.maxAge=86400] How long the invite should last (in seconds, 0 for forever) - * @param {number} [options.maxUses=0] Maximum number of uses - * @param {boolean} [options.unique=false] Create a unique invite, or use an existing one with similar settings - * @param {string} [options.reason] Reason for creating this + * @property {number} [maxAge=86400] How long the invite should last (in seconds, 0 for forever) + * @property {number} [maxUses=0] Maximum number of uses + * @property {boolean} [unique=false] Create a unique invite, or use an existing one with similar settings + * @property {UserResolvable} [targetUser] The user whose stream to display for this invite, + * required if `targetType` is 1, the user must be streaming in the channel + * @property {ApplicationResolvable} [targetApplication] The embedded application to open for this invite, + * required if `targetType` is 2, the application must have the `EMBEDDED` flag + * @property {TargetType} [targetType] The type of the target for this voice channel invite + * @property {string} [reason] The reason for creating the invite + */ + + /** + * Creates an invite to this guild channel. + * @param {CreateInviteOptions} [options={}] The options for creating the invite * @returns {Promise} * @example * // Create an invite to a channel @@ -472,75 +488,49 @@ class GuildChannel extends Channel { * .then(invite => console.log(`Created an invite with a code of ${invite.code}`)) * .catch(console.error); */ - createInvite({ temporary = false, maxAge = 86400, maxUses = 0, unique, reason } = {}) { - return this.client.api - .channels(this.id) - .invites.post({ - data: { - temporary, - max_age: maxAge, - max_uses: maxUses, - unique, - }, - reason, - }) - .then(invite => new Invite(this.client, invite)); + createInvite(options) { + return this.guild.invites.create(this.id, options); } /** * Fetches a collection of invites to this guild channel. * Resolves with a collection mapping invites by their codes. + * @param {boolean} [cache=true] Whether or not to cache the fetched invites * @returns {Promise>} */ - async fetchInvites() { - const inviteItems = await this.client.api.channels(this.id).invites.get(); - const invites = new Collection(); - for (const inviteItem of inviteItems) { - const invite = new Invite(this.client, inviteItem); - invites.set(invite.code, invite); - } - return invites; + fetchInvites(cache = true) { + return this.guild.invites.fetch({ channelId: this.id, cache }); } - /* eslint-disable max-len */ + /** + * Options used to clone a guild channel. + * @typedef {GuildChannelCreateOptions} GuildChannelCloneOptions + * @property {string} [name=this.name] Name of the new channel + */ + /** * Clones this channel. - * @param {Object} [options] The options - * @param {string} [options.name=this.name] Name of the new channel - * @param {OverwriteResolvable[]|Collection} [options.permissionOverwrites=this.permissionOverwrites] - * Permission overwrites of the new channel - * @param {string} [options.type=this.type] Type of the new channel - * @param {string} [options.topic=this.topic] Topic of the new channel (only text) - * @param {boolean} [options.nsfw=this.nsfw] Whether the new channel is nsfw (only text) - * @param {number} [options.bitrate=this.bitrate] Bitrate of the new channel in bits (only voice) - * @param {number} [options.userLimit=this.userLimit] Maximum amount of users allowed in the new channel (only voice) - * @param {number} [options.rateLimitPerUser=this.rateLimitPerUser] Ratelimit per user for the new channel (only text) - * @param {ChannelResolvable} [options.parent=this.parent] Parent of the new channel - * @param {string} [options.reason] Reason for cloning this channel + * @param {GuildChannelCloneOptions} [options] The options for cloning this channel * @returns {Promise} */ clone(options = {}) { - Util.mergeDefault( - { - name: this.name, - permissionOverwrites: this.permissionOverwrites, - topic: this.topic, - type: this.type, - nsfw: this.nsfw, - parent: this.parent, - bitrate: this.bitrate, - userLimit: this.userLimit, - rateLimitPerUser: this.rateLimitPerUser, - reason: null, - }, - options, - ); - return this.guild.channels.create(options.name, options); + return this.guild.channels.create(options.name ?? this.name, { + permissionOverwrites: this.permissionOverwrites.cache, + topic: this.topic, + type: this.type, + nsfw: this.nsfw, + parent: this.parent, + bitrate: this.bitrate, + userLimit: this.userLimit, + rateLimitPerUser: this.rateLimitPerUser, + position: this.position, + reason: null, + ...options, + }); } - /* eslint-enable max-len */ /** - * Checks if this channel has the same type, topic, position, name, overwrites and ID as another channel. + * Checks if this channel has the same type, topic, position, name, overwrites, and id as another channel. * In most cases, a simple `channel.id === channel2.id` will do, and is much faster too. * @param {GuildChannel} channel Channel to compare with * @returns {boolean} @@ -556,7 +546,7 @@ class GuildChannel extends Channel { if (equal) { if (this.permissionOverwrites && channel.permissionOverwrites) { - equal = this.permissionOverwrites.equals(channel.permissionOverwrites); + equal = this.permissionOverwrites.cache.equals(channel.permissionOverwrites.cache); } else { equal = !this.permissionOverwrites && !channel.permissionOverwrites; } @@ -571,7 +561,11 @@ class GuildChannel extends Channel { * @readonly */ get deletable() { - return this.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false); + return ( + this.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false) && + this.guild.rulesChannelId !== this.id && + this.guild.publicUpdatesChannelId !== this.id + ); } /** @@ -580,8 +574,8 @@ class GuildChannel extends Channel { * @readonly */ get manageable() { - if (this.client.user.id === this.guild.ownerID) return true; - if (this.type === 'voice') { + if (this.client.user.id === this.guild.ownerId) return true; + if (VoiceBasedChannelTypes.includes(this.type)) { if (!this.permissionsFor(this.client.user).has(Permissions.FLAGS.CONNECT, false)) { return false; } @@ -597,7 +591,7 @@ class GuildChannel extends Channel { * @readonly */ get viewable() { - if (this.client.user.id === this.guild.ownerID) return true; + if (this.client.user.id === this.guild.ownerId) return true; const permissions = this.permissionsFor(this.client.user); if (!permissions) return false; return permissions.has(Permissions.FLAGS.VIEW_CHANNEL, false); diff --git a/node_modules/discord.js/src/structures/GuildEmoji.js b/node_modules/discord.js/src/structures/GuildEmoji.js index a4ab2a56..00dd215b 100644 --- a/node_modules/discord.js/src/structures/GuildEmoji.js +++ b/node_modules/discord.js/src/structures/GuildEmoji.js @@ -12,7 +12,7 @@ const Permissions = require('../util/Permissions'); class GuildEmoji extends BaseGuildEmoji { /** * @param {Client} client The instantiating client - * @param {Object} data The data for the guild emoji + * @param {APIEmoji} data The data for the guild emoji * @param {Guild} guild The guild the guild emoji is part of */ constructor(client, data, guild) { @@ -23,6 +23,14 @@ class GuildEmoji extends BaseGuildEmoji { * @type {?User} */ this.author = null; + + /** + * Array of role ids this emoji is active for + * @name GuildEmoji#_roles + * @type {Snowflake[]} + * @private + */ + Object.defineProperty(this, '_roles', { value: [], writable: true }); } /** @@ -39,7 +47,9 @@ class GuildEmoji extends BaseGuildEmoji { _patch(data) { super._patch(data); - if (typeof data.user !== 'undefined') this.author = this.client.users.add(data.user); + + if (data.user) this.author = this.client.users._add(data.user); + if (data.roles) this._roles = data.roles; } /** @@ -49,7 +59,7 @@ class GuildEmoji extends BaseGuildEmoji { */ get deletable() { if (!this.guild.me) throw new Error('GUILD_UNCACHED_ME'); - return !this.managed && this.guild.me.hasPermission(Permissions.FLAGS.MANAGE_EMOJIS); + return !this.managed && this.guild.me.permissions.has(Permissions.FLAGS.MANAGE_EMOJIS_AND_STICKERS); } /** @@ -70,8 +80,8 @@ class GuildEmoji extends BaseGuildEmoji { throw new Error('EMOJI_MANAGED'); } else { if (!this.guild.me) throw new Error('GUILD_UNCACHED_ME'); - if (!this.guild.me.permissions.has(Permissions.FLAGS.MANAGE_EMOJIS)) { - throw new Error('MISSING_MANAGE_EMOJIS_PERMISSION', this.guild); + if (!this.guild.me.permissions.has(Permissions.FLAGS.MANAGE_EMOJIS_AND_STICKERS)) { + throw new Error('MISSING_MANAGE_EMOJIS_AND_STICKERS_PERMISSION', this.guild); } } const data = await this.client.api.guilds(this.guild.id).emojis(this.id).get(); @@ -98,7 +108,7 @@ class GuildEmoji extends BaseGuildEmoji { * .catch(console.error); */ edit(data, reason) { - const roles = data.roles ? data.roles.map(r => r.id || r) : undefined; + const roles = data.roles?.map(r => r.id ?? r); return this.client.api .guilds(this.guild.id) .emojis(this.id) @@ -141,8 +151,8 @@ class GuildEmoji extends BaseGuildEmoji { /** * Whether this emoji is the same as another one. - * @param {GuildEmoji|Object} other The emoji to compare it to - * @returns {boolean} Whether the emoji is equal to the given emoji or not + * @param {GuildEmoji|APIEmoji} other The emoji to compare it to + * @returns {boolean} */ equals(other) { if (other instanceof GuildEmoji) { @@ -150,6 +160,7 @@ class GuildEmoji extends BaseGuildEmoji { other.id === this.id && other.name === this.name && other.managed === this.managed && + other.available === this.available && other.requiresColons === this.requiresColons && other.roles.cache.size === this.roles.cache.size && other.roles.cache.every(role => this.roles.cache.has(role.id)) diff --git a/node_modules/discord.js/src/structures/GuildMember.js b/node_modules/discord.js/src/structures/GuildMember.js index 1bd0dfd1..81779a92 100644 --- a/node_modules/discord.js/src/structures/GuildMember.js +++ b/node_modules/discord.js/src/structures/GuildMember.js @@ -1,12 +1,11 @@ 'use strict'; const Base = require('./Base'); -const Role = require('./Role'); +const VoiceState = require('./VoiceState'); const TextBasedChannel = require('./interfaces/TextBasedChannel'); const { Error } = require('../errors'); const GuildMemberRoleManager = require('../managers/GuildMemberRoleManager'); const Permissions = require('../util/Permissions'); -let Structures; /** * Represents a member of a guild on Discord. @@ -16,7 +15,7 @@ let Structures; class GuildMember extends Base { /** * @param {Client} client The instantiating client - * @param {Object} data The data for the guild member + * @param {APIGuildMember} data The data for the guild member * @param {Guild} guild The guild the member is part of */ constructor(client, data, guild) { @@ -34,18 +33,6 @@ class GuildMember extends Base { */ this.joinedTimestamp = null; - /** - * The ID of the last message sent by the member in their guild, if one was sent - * @type {?Snowflake} - */ - this.lastMessageID = null; - - /** - * The ID of the channel for the last message sent by the member in their guild, if one was sent - * @type {?Snowflake} - */ - this.lastMessageChannelID = null; - /** * The timestamp of when the member used their Nitro boost on the guild, if it was used * @type {?number} @@ -64,6 +51,12 @@ class GuildMember extends Base { */ this.nickname = null; + /** + * Whether this member has yet to pass the guild's membership gate + * @type {boolean} + */ + this.pending = false; + this._roles = []; if (data) this._patch(data); } @@ -72,15 +65,18 @@ class GuildMember extends Base { if ('user' in data) { /** * The user that this guild member instance represents - * @type {User} + * @type {?User} */ - this.user = this.client.users.add(data.user, true); + this.user = this.client.users._add(data.user, true); } if ('nick' in data) this.nickname = data.nick; if ('joined_at' in data) this.joinedTimestamp = new Date(data.joined_at).getTime(); - if ('premium_since' in data) this.premiumSinceTimestamp = new Date(data.premium_since).getTime(); + if ('premium_since' in data) { + this.premiumSinceTimestamp = data.premium_since ? new Date(data.premium_since).getTime() : null; + } if ('roles' in data) this._roles = data.roles; + this.pending = data.pending ?? false; } _clone() { @@ -107,25 +103,13 @@ class GuildMember extends Base { return new GuildMemberRoleManager(this); } - /** - * The Message object of the last message sent by the member in their guild, if one was sent - * @type {?Message} - * @readonly - */ - get lastMessage() { - const channel = this.guild.channels.cache.get(this.lastMessageChannelID); - return (channel && channel.messages.cache.get(this.lastMessageID)) || null; - } - /** * The voice state of this member * @type {VoiceState} * @readonly */ get voice() { - if (!Structures) Structures = require('../util/Structures'); - const VoiceState = Structures.get('VoiceState'); - return this.guild.voiceStates.cache.get(this.id) || new VoiceState(this.guild, { user_id: this.id }); + return this.guild.voiceStates.cache.get(this.id) ?? new VoiceState(this.guild, { user_id: this.id }); } /** @@ -148,21 +132,11 @@ class GuildMember extends Base { /** * The presence of this guild member - * @type {Presence} + * @type {?Presence} * @readonly */ get presence() { - if (!Structures) Structures = require('../util/Structures'); - const Presence = Structures.get('Presence'); - return ( - this.guild.presences.cache.get(this.id) || - new Presence(this.client, { - user: { - id: this.id, - }, - guild: this.guild, - }) - ); + return this.guild.presences.resolve(this.id); } /** @@ -171,8 +145,7 @@ class GuildMember extends Base { * @readonly */ get displayColor() { - const role = this.roles.color; - return (role && role.color) || 0; + return this.roles.color?.color ?? 0; } /** @@ -181,12 +154,11 @@ class GuildMember extends Base { * @readonly */ get displayHexColor() { - const role = this.roles.color; - return (role && role.hexColor) || '#000000'; + return this.roles.color?.hexColor ?? '#000000'; } /** - * The ID of this member + * The member's id * @type {Snowflake} * @readonly */ @@ -200,16 +172,16 @@ class GuildMember extends Base { * @readonly */ get displayName() { - return this.nickname || this.user.username; + return this.nickname ?? this.user.username; } /** - * The overall set of permissions for this member, taking only roles into account + * The overall set of permissions for this member, taking only roles and owner status into account * @type {Readonly} * @readonly */ get permissions() { - if (this.user.id === this.guild.ownerID) return new Permissions(Permissions.ALL).freeze(); + if (this.user.id === this.guild.ownerId) return new Permissions(Permissions.ALL).freeze(); return new Permissions(this.roles.cache.map(role => role.permissions)).freeze(); } @@ -220,9 +192,9 @@ class GuildMember extends Base { * @readonly */ get manageable() { - if (this.user.id === this.guild.ownerID) return false; + if (this.user.id === this.guild.ownerId) return false; if (this.user.id === this.client.user.id) return false; - if (this.client.user.id === this.guild.ownerID) return true; + if (this.client.user.id === this.guild.ownerId) return true; if (!this.guild.me) throw new Error('GUILD_UNCACHED_ME'); return this.guild.me.roles.highest.comparePositionTo(this.roles.highest) > 0; } @@ -248,38 +220,24 @@ class GuildMember extends Base { /** * Returns `channel.permissionsFor(guildMember)`. Returns permissions for a member in a guild channel, * taking into account roles and permission overwrites. - * @param {ChannelResolvable} channel The guild channel to use as context + * @param {GuildChannelResolvable} channel The guild channel to use as context * @returns {Readonly} */ permissionsIn(channel) { channel = this.guild.channels.resolve(channel); if (!channel) throw new Error('GUILD_CHANNEL_RESOLVE'); - return channel.memberPermissions(this); - } - - /** - * Checks if any of this member's roles have a permission. - * @param {PermissionResolvable} permission Permission(s) to check for - * @param {Object} [options] Options - * @param {boolean} [options.checkAdmin=true] Whether to allow the administrator permission to override - * @param {boolean} [options.checkOwner=true] Whether to allow being the guild's owner to override - * @returns {boolean} - */ - hasPermission(permission, { checkAdmin = true, checkOwner = true } = {}) { - if (checkOwner && this.user.id === this.guild.ownerID) return true; - const permissions = new Permissions(this.roles.cache.map(role => role.permissions)); - return permissions.has(permission, checkAdmin); + return channel.permissionsFor(this); } /** * The data for editing a guild member. * @typedef {Object} GuildMemberEditData - * @property {string} [nick] The nickname to set for the member - * @property {Collection|RoleResolvable[]} [roles] The roles or role IDs to apply + * @property {?string} [nick] The nickname to set for the member + * @property {Collection|RoleResolvable[]} [roles] The roles or role ids to apply * @property {boolean} [mute] Whether or not the member should be muted * @property {boolean} [deaf] Whether or not the member should be deafened - * @property {ChannelResolvable|null} [channel] Channel to move member to (if they are connected to voice), or `null` - * if you want to kick them from voice + * @property {GuildVoiceChannelResolvable|null} [channel] Channel to move the member to + * (if they are connected to voice), or `null` if you want to disconnect them from voice */ /** @@ -288,38 +246,13 @@ class GuildMember extends Base { * @param {string} [reason] Reason for editing this user * @returns {Promise} */ - async edit(data, reason) { - if (data.channel) { - data.channel = this.guild.channels.resolve(data.channel); - if (!data.channel || data.channel.type !== 'voice') { - throw new Error('GUILD_VOICE_CHANNEL_RESOLVE'); - } - data.channel_id = data.channel.id; - data.channel = undefined; - } else if (data.channel === null) { - data.channel_id = null; - data.channel = undefined; - } - if (data.roles) data.roles = data.roles.map(role => (role instanceof Role ? role.id : role)); - let endpoint = this.client.api.guilds(this.guild.id); - if (this.user.id === this.client.user.id) { - const keys = Object.keys(data); - if (keys.length === 1 && keys[0] === 'nick') endpoint = endpoint.members('@me').nick; - else endpoint = endpoint.members(this.id); - } else { - endpoint = endpoint.members(this.id); - } - await endpoint.patch({ data, reason }); - - const clone = this._clone(); - data.user = this.user; - clone._patch(data); - return clone; + edit(data, reason) { + return this.guild.members.edit(this, data, reason); } /** * Sets the nickname for this member. - * @param {string} nick The nickname for the guild member + * @param {?string} nick The nickname for the guild member, or `null` if you want to reset their nickname * @param {string} [reason] Reason for setting the nickname * @returns {Promise} */ @@ -349,18 +282,12 @@ class GuildMember extends Base { * @returns {Promise} */ kick(reason) { - return this.client.api - .guilds(this.guild.id) - .members(this.user.id) - .delete({ reason }) - .then(() => this); + return this.guild.members.kick(this, reason); } /** * Bans this guild member. - * @param {Object} [options] Options for the ban - * @param {number} [options.days=0] Number of days of messages to delete, must be between 0 and 7 - * @param {string} [options.reason] Reason for banning + * @param {BanOptions} [options] Options for the ban * @returns {Promise} * @example * // ban a guild member @@ -374,13 +301,34 @@ class GuildMember extends Base { /** * Fetches this GuildMember. - * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @param {boolean} [force=true] Whether to skip the cache check and request the API * @returns {Promise} */ - fetch(force = false) { + fetch(force = true) { return this.guild.members.fetch({ user: this.id, cache: true, force }); } + /** + * Whether this guild member equals another guild member. It compares all properties, so for most + * comparison it is advisable to just compare `member.id === member2.id` as it is significantly faster + * and is often what most users need. + * @param {GuildMember} member The member to compare with + * @returns {boolean} + */ + equals(member) { + return ( + member instanceof this.constructor && + this.id === member.id && + this.partial === member.partial && + this.guild.id === member.guild.id && + this.joinedTimestamp === member.joinedTimestamp && + this.nickname === member.nickname && + this.pending === member.pending && + (this._roles === member._roles || + (this._roles.length === member._roles.length && this._roles.every((role, i) => role === member._roles[i]))) + ); + } + /** * When concatenated with a string, this automatically returns the user's mention instead of the GuildMember object. * @returns {string} @@ -394,12 +342,9 @@ class GuildMember extends Base { toJSON() { return super.toJSON({ - guild: 'guildID', - user: 'userID', + guild: 'guildId', + user: 'userId', displayName: true, - speaking: false, - lastMessage: false, - lastMessageID: false, roles: true, }); } @@ -412,3 +357,8 @@ class GuildMember extends Base { TextBasedChannel.applyToClass(GuildMember); module.exports = GuildMember; + +/** + * @external APIGuildMember + * @see {@link https://discord.com/developers/docs/resources/guild#guild-member-object} + */ diff --git a/node_modules/discord.js/src/structures/GuildPreview.js b/node_modules/discord.js/src/structures/GuildPreview.js index 76f53424..09a20617 100644 --- a/node_modules/discord.js/src/structures/GuildPreview.js +++ b/node_modules/discord.js/src/structures/GuildPreview.js @@ -1,8 +1,9 @@ 'use strict'; +const { Collection } = require('@discordjs/collection'); const Base = require('./Base'); const GuildPreviewEmoji = require('./GuildPreviewEmoji'); -const Collection = require('../util/Collection'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); /** * Represents the data about the guild any bot can preview, connected to the specified guild. @@ -75,7 +76,7 @@ class GuildPreview extends Base { * The description for this guild * @type {?string} */ - this.description = data.description || null; + this.description = data.description ?? null; if (!this.emojis) { /** @@ -90,25 +91,40 @@ class GuildPreview extends Base { this.emojis.set(emoji.id, new GuildPreviewEmoji(this.client, emoji, this)); } } + /** + * The timestamp this guild was created at + * @type {number} + * @readonly + */ + get createdTimestamp() { + return SnowflakeUtil.deconstruct(this.id).timestamp; + } + + /** + * The time this guild was created at + * @type {Date} + * @readonly + */ + get createdAt() { + return new Date(this.createdTimestamp); + } /** * The URL to this guild's splash. - * @param {ImageURLOptions} [options={}] Options for the Image URL + * @param {StaticImageURLOptions} [options={}] Options for the Image URL * @returns {?string} */ splashURL({ format, size } = {}) { - if (!this.splash) return null; - return this.client.rest.cdn.Splash(this.id, this.splash, format, size); + return this.splash && this.client.rest.cdn.Splash(this.id, this.splash, format, size); } /** * The URL to this guild's discovery splash. - * @param {ImageURLOptions} [options={}] Options for the Image URL + * @param {StaticImageURLOptions} [options={}] Options for the Image URL * @returns {?string} */ discoverySplashURL({ format, size } = {}) { - if (!this.discoverySplash) return null; - return this.client.rest.cdn.DiscoverySplash(this.id, this.discoverySplash, format, size); + return this.discoverySplash && this.client.rest.cdn.DiscoverySplash(this.id, this.discoverySplash, format, size); } /** @@ -117,8 +133,7 @@ class GuildPreview extends Base { * @returns {?string} */ iconURL({ format, size, dynamic } = {}) { - if (!this.icon) return null; - return this.client.rest.cdn.Icon(this.id, this.icon, format, size, dynamic); + return this.icon && this.client.rest.cdn.Icon(this.id, this.icon, format, size, dynamic); } /** diff --git a/node_modules/discord.js/src/structures/GuildPreviewEmoji.js b/node_modules/discord.js/src/structures/GuildPreviewEmoji.js index 4c709031..144b41d9 100644 --- a/node_modules/discord.js/src/structures/GuildPreviewEmoji.js +++ b/node_modules/discord.js/src/structures/GuildPreviewEmoji.js @@ -13,13 +13,14 @@ class GuildPreviewEmoji extends BaseGuildEmoji { * @name GuildPreviewEmoji#guild */ - /** - * Set of roles this emoji is active for - * @type {Set} - * @readonly - */ - get roles() { - return new Set(this._roles); + constructor(client, data, guild) { + super(client, data, guild); + + /** + * The roles this emoji is active for + * @type {Snowflake[]} + */ + this.roles = data.roles; } } diff --git a/node_modules/discord.js/src/structures/GuildTemplate.js b/node_modules/discord.js/src/structures/GuildTemplate.js index 7510bb95..09e94c4a 100644 --- a/node_modules/discord.js/src/structures/GuildTemplate.js +++ b/node_modules/discord.js/src/structures/GuildTemplate.js @@ -11,7 +11,7 @@ const DataResolver = require('../util/DataResolver'); class GuildTemplate extends Base { /** * @param {Client} client The instantiating client - * @param {Object} data The raw data for the template + * @param {APIGuildTemplate} data The raw data for the template */ constructor(client, data) { super(client); @@ -20,7 +20,7 @@ class GuildTemplate extends Base { /** * Builds or updates the template with the provided data. - * @param {Object} data The raw data for the template + * @param {APIGuildTemplate} data The raw data for the template * @returns {GuildTemplate} * @private */ @@ -50,16 +50,16 @@ class GuildTemplate extends Base { this.usageCount = data.usage_count; /** - * The ID of the user that created this template + * The id of the user that created this template * @type {Snowflake} */ - this.creatorID = data.creator_id; + this.creatorId = data.creator_id; /** * The user that created this template * @type {User} */ - this.creator = this.client.users.add(data.creator); + this.creator = this.client.users._add(data.creator); /** * The time of when this template was created at @@ -74,15 +74,14 @@ class GuildTemplate extends Base { this.updatedAt = new Date(data.updated_at); /** - * The ID of the guild that this template belongs to + * The id of the guild that this template belongs to * @type {Snowflake} */ - this.guildID = data.source_guild_id; + this.guildId = data.source_guild_id; /** * The data of the guild that this template would create - * @type {Object} - * @see {@link https://discord.com/developers/docs/resources/guild#guild-resource} + * @type {APIGuild} */ this.serializedGuild = data.serialized_source_guild; @@ -123,7 +122,7 @@ class GuildTemplate extends Base { const handleGuild = guild => { if (guild.id === data.id) { - client.clearTimeout(timeout); + clearTimeout(timeout); resolveGuild(guild); } }; @@ -131,20 +130,25 @@ class GuildTemplate extends Base { client.incrementMaxListeners(); client.on(Events.GUILD_CREATE, handleGuild); - const timeout = client.setTimeout(() => resolveGuild(client.guilds.add(data)), 10000); + const timeout = setTimeout(() => resolveGuild(client.guilds._add(data)), 10000).unref(); }); } /** - * Updates the metadata on this template. - * @param {Object} options Options for the template - * @param {string} [options.name] The name of this template - * @param {string} [options.description] The description of this template + * Options used to edit a guild template. + * @typedef {Object} EditGuildTemplateOptions + * @property {string} [name] The name of this template + * @property {string} [description] The description of this template + */ + + /** + * Updates the metadata of this template. + * @param {EditGuildTemplateOptions} [options] Options for editing the template * @returns {Promise} */ edit({ name, description } = {}) { return this.client.api - .guilds(this.guildID) + .guilds(this.guildId) .templates(this.code) .patch({ data: { name, description } }) .then(data => this._patch(data)); @@ -156,7 +160,7 @@ class GuildTemplate extends Base { */ delete() { return this.client.api - .guilds(this.guildID) + .guilds(this.guildId) .templates(this.code) .delete() .then(() => this); @@ -168,7 +172,7 @@ class GuildTemplate extends Base { */ sync() { return this.client.api - .guilds(this.guildID) + .guilds(this.guildId) .templates(this.code) .put() .then(data => this._patch(data)); @@ -198,7 +202,7 @@ class GuildTemplate extends Base { * @readonly */ get guild() { - return this.client.guilds.cache.get(this.guildID) || null; + return this.client.guilds.resolve(this.guildId); } /** @@ -222,4 +226,16 @@ class GuildTemplate extends Base { } } +/** + * Regular expression that globally matches guild template links + * @type {RegExp} + */ +GuildTemplate.GUILD_TEMPLATES_PATTERN = /discord(?:app)?\.(?:com\/template|new)\/([\w-]{2,255})/gi; + module.exports = GuildTemplate; + +/* eslint-disable max-len */ +/** + * @external APIGuildTemplate + * @see {@link https://discord.com/developers/docs/resources/guild-template#guild-template-object-guild-template-structure} + */ diff --git a/node_modules/discord.js/src/structures/Integration.js b/node_modules/discord.js/src/structures/Integration.js index a48019a6..644882ea 100644 --- a/node_modules/discord.js/src/structures/Integration.js +++ b/node_modules/discord.js/src/structures/Integration.js @@ -64,7 +64,7 @@ class Integration extends Base { * The user for this integration * @type {?User} */ - this.user = this.client.users.add(data.user); + this.user = this.client.users._add(data.user); } else { this.user = null; } @@ -83,6 +83,16 @@ class Integration extends Base { this._patch(data); } + /** + * All roles that are managed by this integration + * @type {Collection} + * @readonly + */ + get roles() { + const roles = this.guild.roles.cache; + return roles.filter(role => role.tags?.integrationId === this.id); + } + _patch(data) { /** * The behavior of expiring subscribers @@ -111,56 +121,6 @@ class Integration extends Base { } } - /** - * Sync this integration - * @returns {Promise} - */ - sync() { - this.syncing = true; - return this.client.api - .guilds(this.guild.id) - .integrations(this.id) - .post() - .then(() => { - this.syncing = false; - this.syncedAt = Date.now(); - return this; - }); - } - - /** - * The data for editing an integration. - * @typedef {Object} IntegrationEditData - * @property {number} [expireBehavior] The new behaviour of expiring subscribers - * @property {number} [expireGracePeriod] The new grace period before expiring subscribers - */ - - /** - * Edits this integration. - * @param {IntegrationEditData} data The data to edit this integration with - * @param {string} reason Reason for editing this integration - * @returns {Promise} - */ - edit(data, reason) { - if ('expireBehavior' in data) { - data.expire_behavior = data.expireBehavior; - data.expireBehavior = null; - } - if ('expireGracePeriod' in data) { - data.expire_grace_period = data.expireGracePeriod; - data.expireGracePeriod = null; - } - // The option enable_emoticons is only available for Twitch at this moment - return this.client.api - .guilds(this.guild.id) - .integrations(this.id) - .patch({ data, reason }) - .then(() => { - this._patch(data); - return this; - }); - } - /** * Deletes this integration. * @returns {Promise} @@ -176,9 +136,9 @@ class Integration extends Base { toJSON() { return super.toJSON({ - role: 'roleID', - guild: 'guildID', - user: 'userID', + role: 'roleId', + guild: 'guildId', + user: 'userId', }); } } diff --git a/node_modules/discord.js/src/structures/IntegrationApplication.js b/node_modules/discord.js/src/structures/IntegrationApplication.js index 40f433ab..d9a6d394 100644 --- a/node_modules/discord.js/src/structures/IntegrationApplication.js +++ b/node_modules/discord.js/src/structures/IntegrationApplication.js @@ -10,15 +10,53 @@ class IntegrationApplication extends Application { _patch(data) { super._patch(data); - if (typeof data.bot !== 'undefined') { - /** - * The bot {@link User user} for this application - * @type {?User} - */ - this.bot = this.client.users.add(data.bot); - } else if (!this.bot) { - this.bot = null; - } + /** + * The bot user for this application + * @type {?User} + */ + this.bot = data.bot ? this.client.users._add(data.bot) : this.bot ?? null; + + /** + * The url of the application's terms of service + * @type {?string} + */ + this.termsOfServiceURL = data.terms_of_service_url ?? this.termsOfServiceURL ?? null; + + /** + * The url of the application's privacy policy + * @type {?string} + */ + this.privacyPolicyURL = data.privacy_policy_url ?? this.privacyPolicyURL ?? null; + + /** + * The Array of RPC origin urls + * @type {string[]} + */ + this.rpcOrigins = data.rpc_origins ?? this.rpcOrigins ?? []; + + /** + * The application's summary + * @type {?string} + */ + this.summary = data.summary ?? this.summary ?? null; + + /** + * Whether the application can be default hooked by the client + * @type {?boolean} + */ + this.hook = data.hook ?? this.hook ?? null; + + /** + * The hash of the application's cover image + * @type {?string} + */ + this.cover = data.cover_image ?? this.cover ?? null; + + /** + * The hex-encoded key for verification in interactions and the GameSDK's GetTicket + * @type {?string} + */ + this.verifyKey = data.verify_key ?? this.verifyKey ?? null; } } diff --git a/node_modules/discord.js/src/structures/Invite.js b/node_modules/discord.js/src/structures/Invite.js index 68332668..95bad22b 100644 --- a/node_modules/discord.js/src/structures/Invite.js +++ b/node_modules/discord.js/src/structures/Invite.js @@ -1,6 +1,9 @@ 'use strict'; const Base = require('./Base'); +const IntegrationApplication = require('./IntegrationApplication'); +const InviteStageInstance = require('./InviteStageInstance'); +const { Error } = require('../errors'); const { Endpoints } = require('../util/Constants'); const Permissions = require('../util/Permissions'); @@ -16,11 +19,16 @@ class Invite extends Base { } _patch(data) { + const InviteGuild = require('./InviteGuild'); + const Guild = require('./Guild'); /** - * The guild the invite is for - * @type {?Guild} + * The guild the invite is for including welcome screen data if present + * @type {?(Guild|InviteGuild)} */ - this.guild = data.guild ? this.client.guilds.add(data.guild, false) : null; + this.guild = null; + if (data.guild) { + this.guild = data.guild instanceof Guild ? data.guild : new InviteGuild(this.client, data.guild); + } /** * The code for this invite @@ -32,73 +40,93 @@ class Invite extends Base { * The approximate number of online members of the guild this invite is for * @type {?number} */ - this.presenceCount = 'approximate_presence_count' in data ? data.approximate_presence_count : null; + this.presenceCount = data.approximate_presence_count ?? null; /** * The approximate total number of members of the guild this invite is for * @type {?number} */ - this.memberCount = 'approximate_member_count' in data ? data.approximate_member_count : null; + this.memberCount = data.approximate_member_count ?? null; /** * Whether or not this invite is temporary * @type {?boolean} */ - this.temporary = 'temporary' in data ? data.temporary : null; + this.temporary = data.temporary ?? null; /** * The maximum age of the invite, in seconds, 0 if never expires * @type {?number} */ - this.maxAge = 'max_age' in data ? data.max_age : null; + this.maxAge = data.max_age ?? null; /** * How many times this invite has been used * @type {?number} */ - this.uses = 'uses' in data ? data.uses : null; + this.uses = data.uses ?? null; /** * The maximum uses of this invite * @type {?number} */ - this.maxUses = 'max_uses' in data ? data.max_uses : null; + this.maxUses = data.max_uses ?? null; /** * The user who created this invite * @type {?User} */ - this.inviter = data.inviter ? this.client.users.add(data.inviter) : null; + this.inviter = data.inviter ? this.client.users._add(data.inviter) : null; /** - * The target user for this invite + * The user whose stream to display for this voice channel stream invite * @type {?User} */ - this.targetUser = data.target_user ? this.client.users.add(data.target_user) : null; + this.targetUser = data.target_user ? this.client.users._add(data.target_user) : null; /** - * The type of the target user: + * The embedded application to open for this voice channel embedded application invite + * @type {?IntegrationApplication} + */ + this.targetApplication = data.target_application + ? new IntegrationApplication(this.client, data.target_application) + : null; + + /** + * The type of the invite target: * * 1: STREAM - * @typedef {number} TargetUser + * * 2: EMBEDDED_APPLICATION + * @typedef {number} TargetType */ /** - * The target user type - * @type {?TargetUser} + * The target type + * @type {?TargetType} */ - this.targetUserType = typeof data.target_user_type === 'number' ? data.target_user_type : null; + this.targetType = data.target_type ?? null; /** * The channel the invite is for * @type {Channel} */ - this.channel = this.client.channels.add(data.channel, this.guild, false); + this.channel = this.client.channels._add(data.channel, this.guild, { cache: false }); /** * The timestamp the invite was created at * @type {?number} */ this.createdTimestamp = 'created_at' in data ? new Date(data.created_at).getTime() : null; + + this._expiresTimestamp = 'expires_at' in data ? new Date(data.expires_at).getTime() : null; + + /** + * The stage instance data if there is a public {@link StageInstance} in the stage channel this invite is for + * @type {?InviteStageInstance} + */ + this.stageInstance = + 'stage_instance' in data + ? new InviteStageInstance(this.client, data.stage_instance, this.channel.id, this.guild.id) + : null; } /** @@ -131,7 +159,10 @@ class Invite extends Base { * @readonly */ get expiresTimestamp() { - return this.createdTimestamp && this.maxAge ? this.createdTimestamp + this.maxAge * 1000 : null; + return ( + this._expiresTimestamp ?? + (this.createdTimestamp && this.maxAge ? this.createdTimestamp + this.maxAge * 1000 : null) + ); } /** @@ -180,9 +211,9 @@ class Invite extends Base { presenceCount: false, memberCount: false, uses: false, - channel: 'channelID', - inviter: 'inviterID', - guild: 'guildID', + channel: 'channelId', + inviter: 'inviterId', + guild: 'guildId', }); } @@ -191,4 +222,10 @@ class Invite extends Base { } } +/** + * Regular expression that globally matches Discord invite links + * @type {RegExp} + */ +Invite.INVITES_PATTERN = /discord(?:(?:app)?\.com\/invite|\.gg(?:\/invite)?)\/([\w-]{2,255})/gi; + module.exports = Invite; diff --git a/node_modules/discord.js/src/structures/Message.js b/node_modules/discord.js/src/structures/Message.js index 36c26f2d..536b628d 100644 --- a/node_modules/discord.js/src/structures/Message.js +++ b/node_modules/discord.js/src/structures/Message.js @@ -1,19 +1,22 @@ 'use strict'; -const APIMessage = require('./APIMessage'); +const { Collection } = require('@discordjs/collection'); const Base = require('./Base'); +const BaseMessageComponent = require('./BaseMessageComponent'); const ClientApplication = require('./ClientApplication'); +const InteractionCollector = require('./InteractionCollector'); const MessageAttachment = require('./MessageAttachment'); const Embed = require('./MessageEmbed'); const Mentions = require('./MessageMentions'); +const MessagePayload = require('./MessagePayload'); const ReactionCollector = require('./ReactionCollector'); -const { Error, TypeError } = require('../errors'); +const Sticker = require('./Sticker'); +const { Error } = require('../errors'); const ReactionManager = require('../managers/ReactionManager'); -const Collection = require('../util/Collection'); -const { MessageTypes } = require('../util/Constants'); +const { InteractionTypes, MessageTypes, SystemMessageTypes } = require('../util/Constants'); const MessageFlags = require('../util/MessageFlags'); const Permissions = require('../util/Permissions'); -const SnowflakeUtil = require('../util/Snowflake'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); const Util = require('../util/Util'); /** @@ -23,15 +26,15 @@ const Util = require('../util/Util'); class Message extends Base { /** * @param {Client} client The instantiating client - * @param {Object} data The data for the message - * @param {TextChannel|DMChannel|NewsChannel} channel The channel the message was sent in + * @param {APIMessage} data The data for the message + * @param {TextChannel|DMChannel|NewsChannel|ThreadChannel} channel The channel the message was sent in */ constructor(client, data, channel) { super(client); /** * The channel that the message was sent in - * @type {TextChannel|DMChannel|NewsChannel} + * @type {TextChannel|DMChannel|NewsChannel|ThreadChannel} */ this.channel = channel; @@ -44,9 +47,9 @@ class Message extends Base { if (data) this._patch(data); } - _patch(data) { + _patch(data, partial = false) { /** - * The ID of the message + * The message's id * @type {Snowflake} */ this.id = data.id; @@ -62,7 +65,7 @@ class Message extends Base { * Whether or not this message was sent by Discord, not actually a user (e.g. pin notifications) * @type {?boolean} */ - this.system = data.type !== 0; + this.system = SystemMessageTypes.includes(this.type); } else if (typeof this.type !== 'string') { this.system = null; this.type = null; @@ -83,7 +86,7 @@ class Message extends Base { * The author of the message * @type {?User} */ - this.author = this.client.users.add(data.author, !data.webhook_id); + this.author = this.client.users._add(data.author, !data.webhook_id); } else if (!this.author) { this.author = null; } @@ -108,121 +111,226 @@ class Message extends Base { this.tts = null; } - /** - * A random number or string used for checking message delivery - * This is only received after the message was sent successfully, and - * lost if re-fetched - * @type {?string} - */ - this.nonce = 'nonce' in data ? data.nonce : null; + if (!partial) { + /** + * A random number or string used for checking message delivery + * This is only received after the message was sent successfully, and + * lost if re-fetched + * @type {?string} + */ + this.nonce = 'nonce' in data ? data.nonce : null; + } - /** - * A list of embeds in the message - e.g. YouTube Player - * @type {MessageEmbed[]} - */ - this.embeds = (data.embeds || []).map(e => new Embed(e, true)); + if ('embeds' in data || !partial) { + /** + * A list of embeds in the message - e.g. YouTube Player + * @type {MessageEmbed[]} + */ + this.embeds = data.embeds?.map(e => new Embed(e, true)) ?? []; + } else { + this.embeds = this.embeds.slice(); + } - /** - * A collection of attachments in the message - e.g. Pictures - mapped by their ID - * @type {Collection} - */ - this.attachments = new Collection(); - if (data.attachments) { - for (const attachment of data.attachments) { - this.attachments.set(attachment.id, new MessageAttachment(attachment.url, attachment.filename, attachment)); + if ('components' in data || !partial) { + /** + * A list of MessageActionRows in the message + * @type {MessageActionRow[]} + */ + this.components = data.components?.map(c => BaseMessageComponent.create(c, this.client)) ?? []; + } else { + this.components = this.components.slice(); + } + + if ('attachments' in data || !partial) { + /** + * A collection of attachments in the message - e.g. Pictures - mapped by their ids + * @type {Collection} + */ + this.attachments = new Collection(); + if (data.attachments) { + for (const attachment of data.attachments) { + this.attachments.set(attachment.id, new MessageAttachment(attachment.url, attachment.filename, attachment)); + } } + } else { + this.attachments = new Collection(this.attachemnts); } - /** - * The timestamp the message was sent at - * @type {number} - */ - this.createdTimestamp = SnowflakeUtil.deconstruct(this.id).timestamp; + if ('sticker_items' in data || 'stickers' in data || !partial) { + /** + * A collection of stickers in the message + * @type {Collection} + */ + this.stickers = new Collection( + (data.sticker_items ?? data.stickers)?.map(s => [s.id, new Sticker(this.client, s)]), + ); + } else { + this.stickers = new Collection(this.stickers); + } - /** - * The timestamp the message was last edited at (if applicable) - * @type {?number} - */ - this.editedTimestamp = 'edited_timestamp' in data ? new Date(data.edited_timestamp).getTime() : null; + if (!partial) { + /** + * The timestamp the message was sent at + * @type {number} + */ + this.createdTimestamp = SnowflakeUtil.deconstruct(this.id).timestamp; + } - /** - * A manager of the reactions belonging to this message - * @type {ReactionManager} - */ - this.reactions = new ReactionManager(this); - if (data.reactions && data.reactions.length > 0) { - for (const reaction of data.reactions) { - this.reactions.add(reaction); - } + if ('edited_timestamp' in data || !partial) { + /** + * The timestamp the message was last edited at (if applicable) + * @type {?number} + */ + this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp).getTime() : null; } - /** - * All valid mentions that the message contains - * @type {MessageMentions} - */ - this.mentions = new Mentions(this, data.mentions, data.mention_roles, data.mention_everyone, data.mention_channels); + if ('reactions' in data || !partial) { + /** + * A manager of the reactions belonging to this message + * @type {ReactionManager} + */ + this.reactions = new ReactionManager(this); + if (data.reactions?.length > 0) { + for (const reaction of data.reactions) { + this.reactions._add(reaction); + } + } + } - /** - * ID of the webhook that sent the message, if applicable - * @type {?Snowflake} - */ - this.webhookID = data.webhook_id || null; + if (!partial) { + /** + * All valid mentions that the message contains + * @type {MessageMentions} + */ + this.mentions = new Mentions( + this, + data.mentions, + data.mention_roles, + data.mention_everyone, + data.mention_channels, + data.referenced_message?.author, + ); + } else { + this.mentions = new Mentions( + this, + data.mentions ?? this.mentions.users, + data.mention_roles ?? this.mentions.roles, + data.mention_everyone ?? this.mentions.everyone, + data.mention_channels ?? this.mentions.crosspostedChannels, + data.referenced_message?.author ?? this.mentions.repliedUser, + ); + } - /** - * Supplemental application information for group activities - * @type {?ClientApplication} - */ - this.application = data.application ? new ClientApplication(this.client, data.application) : null; + if ('webhook_id' in data || !partial) { + /** + * The id of the webhook that sent the message, if applicable + * @type {?Snowflake} + */ + this.webhookId = data.webhook_id ?? null; + } - /** - * Group activity - * @type {?MessageActivity} - */ - this.activity = data.activity - ? { - partyID: data.activity.party_id, - type: data.activity.type, - } - : null; + if ('application' in data || !partial) { + /** + * Supplemental application information for group activities + * @type {?ClientApplication} + */ + this.groupActivityApplication = data.application ? new ClientApplication(this.client, data.application) : null; + } - /** - * The previous versions of the message, sorted with the most recent first - * @type {Message[]} - * @private - */ - this._edits = []; + if ('application_id' in data || !partial) { + /** + * The id of the application of the interaction that sent this message, if any + * @type {?Snowflake} + */ + this.applicationId = data.application_id ?? null; + } + if ('activity' in data || !partial) { + /** + * Group activity + * @type {?MessageActivity} + */ + this.activity = data.activity + ? { + partyId: data.activity.party_id, + type: data.activity.type, + } + : null; + } + if ('thread' in data) { + this.client.channels._add(data.thread, this.guild); + } if (this.member && data.member) { this.member._patch(data.member); } else if (data.member && this.guild && this.author) { - this.guild.members.add(Object.assign(data.member, { user: this.author })); + this.guild.members._add(Object.assign(data.member, { user: this.author })); } - /** - * Flags that are applied to the message - * @type {Readonly} - */ - this.flags = new MessageFlags(data.flags).freeze(); + if ('flags' in data || !partial) { + /** + * Flags that are applied to the message + * @type {Readonly} + */ + this.flags = new MessageFlags(data.flags).freeze(); + } else { + this.flags = new MessageFlags(this.flags).freeze(); + } /** - * Reference data sent in a crossposted message. + * Reference data sent in a message that contains ids identifying the referenced message * @typedef {Object} MessageReference - * @property {string} channelID ID of the channel the message was crossposted from - * @property {?string} guildID ID of the guild the message was crossposted from - * @property {?string} messageID ID of the message that was crossposted + * @property {string} channelId The channel's id the message was referenced + * @property {?string} guildId The guild's id the message was referenced + * @property {?string} messageId The message's id that was referenced */ + if ('message_reference' in data || !partial) { + /** + * Message reference data + * @type {?MessageReference} + */ + this.reference = data.message_reference + ? { + channelId: data.message_reference.channel_id, + guildId: data.message_reference.guild_id, + messageId: data.message_reference.message_id, + } + : null; + } + + if (data.referenced_message) { + this.channel.messages._add(data.referenced_message); + } + /** - * Message reference data - * @type {?MessageReference} + * Partial data of the interaction that a message is a reply to + * @typedef {Object} MessageInteraction + * @property {Snowflake} id The interaction's id + * @property {InteractionType} type The type of the interaction + * @property {string} commandName The name of the interaction's application command + * @property {User} user The user that invoked the interaction */ - this.reference = data.message_reference - ? { - channelID: data.message_reference.channel_id, - guildID: data.message_reference.guild_id, - messageID: data.message_reference.message_id, - } - : null; + + if (data.interaction) { + /** + * Partial data of the interaction that this message is a reply to + * @type {?MessageInteraction} + */ + this.interaction = { + id: data.interaction.id, + type: InteractionTypes[data.interaction.type], + commandName: data.interaction.name, + user: this.client.users._add(data.interaction.user), + }; + } else if (!this.interaction) { + this.interaction = null; + } + } + + _update(data, partial = false) { + const clone = this._clone(); + this._patch(data, partial); + return clone; } /** @@ -234,49 +342,6 @@ class Message extends Base { return typeof this.content !== 'string' || !this.author; } - /** - * Updates the message and returns the old message. - * @param {Object} data Raw Discord message update data - * @returns {Message} - * @private - */ - patch(data) { - const clone = this._clone(); - const { messageEditHistoryMaxSize } = this.client.options; - if (messageEditHistoryMaxSize !== 0) { - const editsLimit = messageEditHistoryMaxSize === -1 ? Infinity : messageEditHistoryMaxSize; - if (this._edits.unshift(clone) > editsLimit) this._edits.pop(); - } - - if ('edited_timestamp' in data) this.editedTimestamp = new Date(data.edited_timestamp).getTime(); - if ('content' in data) this.content = data.content; - if ('pinned' in data) this.pinned = data.pinned; - if ('tts' in data) this.tts = data.tts; - if ('embeds' in data) this.embeds = data.embeds.map(e => new Embed(e, true)); - else this.embeds = this.embeds.slice(); - - if ('attachments' in data) { - this.attachments = new Collection(); - for (const attachment of data.attachments) { - this.attachments.set(attachment.id, new MessageAttachment(attachment.url, attachment.filename, attachment)); - } - } else { - this.attachments = new Collection(this.attachments); - } - - this.mentions = new Mentions( - this, - 'mentions' in data ? data.mentions : this.mentions.users, - 'mention_roles' in data ? data.mention_roles : this.mentions.roles, - 'mention_everyone' in data ? data.mention_everyone : this.mentions.everyone, - 'mention_channels' in data ? data.mention_channels : this.mentions.crosspostedChannels, - ); - - this.flags = new MessageFlags('flags' in data ? data.flags : 0).freeze(); - - return clone; - } - /** * Represents the author of the message as a guild member. * Only available if the message comes from a guild where the author is still a member @@ -284,7 +349,7 @@ class Message extends Base { * @readonly */ get member() { - return this.guild ? this.guild.member(this.author) || null : null; + return this.guild?.members.resolve(this.author) ?? null; } /** @@ -311,7 +376,27 @@ class Message extends Base { * @readonly */ get guild() { - return this.channel.guild || null; + return this.channel.guild ?? null; + } + + /** + * Whether this message has a thread associated with it + * @type {boolean} + * @readonly + */ + get hasThread() { + return this.flags.has(MessageFlags.FLAGS.HAS_THREAD); + } + + /** + * The thread started by this message + * This property is not suitable for checking whether a message has a thread, + * use {@link Message#hasThread} instead. + * @type {?ThreadChannel} + * @readonly + */ + get thread() { + return this.channel.threads.resolve(this.id); } /** @@ -326,28 +411,27 @@ class Message extends Base { /** * The message contents with all mentions replaced by the equivalent text. * If mentions cannot be resolved to a name, the relevant mention in the message content will not be converted. - * @type {string} + * @type {?string} * @readonly */ get cleanContent() { // eslint-disable-next-line eqeqeq - return this.content != null ? Util.cleanContent(this.content, this) : null; + return this.content != null ? Util.cleanContent(this.content, this.channel) : null; } /** * Creates a reaction collector. - * @param {CollectorFilter} filter The filter to apply * @param {ReactionCollectorOptions} [options={}] Options to send to the collector * @returns {ReactionCollector} * @example * // Create a reaction collector - * const filter = (reaction, user) => reaction.emoji.name === 'πŸ‘Œ' && user.id === 'someID'; - * const collector = message.createReactionCollector(filter, { time: 15000 }); + * const filter = (reaction, user) => reaction.emoji.name === 'πŸ‘Œ' && user.id === 'someId'; + * const collector = message.createReactionCollector({ filter, time: 15000 }); * collector.on('collect', r => console.log(`Collected ${r.emoji.name}`)); * collector.on('end', collected => console.log(`Collected ${collected.size} items`)); */ - createReactionCollector(filter, options = {}) { - return new ReactionCollector(this, filter, options); + createReactionCollector(options = {}) { + return new ReactionCollector(this, options); } /** @@ -359,36 +443,82 @@ class Message extends Base { /** * Similar to createReactionCollector but in promise form. * Resolves with a collection of reactions that pass the specified filter. - * @param {CollectorFilter} filter The filter function to use * @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector * @returns {Promise>} * @example * // Create a reaction collector - * const filter = (reaction, user) => reaction.emoji.name === 'πŸ‘Œ' && user.id === 'someID' - * message.awaitReactions(filter, { time: 15000 }) + * const filter = (reaction, user) => reaction.emoji.name === 'πŸ‘Œ' && user.id === 'someId' + * message.awaitReactions({ filter, time: 15000 }) * .then(collected => console.log(`Collected ${collected.size} reactions`)) * .catch(console.error); */ - awaitReactions(filter, options = {}) { + awaitReactions(options = {}) { return new Promise((resolve, reject) => { - const collector = this.createReactionCollector(filter, options); + const collector = this.createReactionCollector(options); collector.once('end', (reactions, reason) => { - if (options.errors && options.errors.includes(reason)) reject(reactions); + if (options.errors?.includes(reason)) reject(reactions); else resolve(reactions); }); }); } /** - * An array of cached versions of the message, including the current version - * Sorted from latest (first) to oldest (last) - * @type {Message[]} - * @readonly + * @typedef {CollectorOptions} MessageComponentCollectorOptions + * @property {MessageComponentType} [componentType] The type of component to listen for + * @property {number} [max] The maximum total amount of interactions to collect + * @property {number} [maxComponents] The maximum number of components to collect + * @property {number} [maxUsers] The maximum number of users to interact + */ + + /** + * Creates a message component interaction collector. + * @param {MessageComponentCollectorOptions} [options={}] Options to send to the collector + * @returns {InteractionCollector} + * @example + * // Create a message component interaction collector + * const filter = (interaction) => interaction.customId === 'button' && interaction.user.id === 'someId'; + * const collector = message.createMessageComponentCollector({ filter, time: 15000 }); + * collector.on('collect', i => console.log(`Collected ${i.customId}`)); + * collector.on('end', collected => console.log(`Collected ${collected.size} items`)); + */ + createMessageComponentCollector(options = {}) { + return new InteractionCollector(this.client, { + ...options, + interactionType: InteractionTypes.MESSAGE_COMPONENT, + message: this, + }); + } + + /** + * An object containing the same properties as CollectorOptions, but a few more: + * @typedef {Object} AwaitMessageComponentOptions + * @property {CollectorFilter} [filter] The filter applied to this collector + * @property {number} [time] Time to wait for an interaction before rejecting + * @property {MessageComponentType} [componentType] The type of component interaction to collect + */ + + /** + * Collects a single component interaction that passes the filter. + * The Promise will reject if the time expires. + * @param {AwaitMessageComponentOptions} [options={}] Options to pass to the internal collector + * @returns {Promise} + * @example + * // Collect a message component interaction + * const filter = (interaction) => interaction.customId === 'button' && interaction.user.id === 'someId'; + * message.awaitMessageComponent({ filter, time: 15000 }) + * .then(interaction => console.log(`${interaction.customId} was clicked!`)) + * .catch(console.error); */ - get edits() { - const copy = this._edits.slice(); - copy.unshift(this); - return copy; + awaitMessageComponent(options = {}) { + const _options = { ...options, max: 1 }; + return new Promise((resolve, reject) => { + const collector = this.createMessageComponentCollector(_options); + collector.once('end', (interactions, reason) => { + const interaction = interactions.first(); + if (interaction) resolve(interaction); + else reject(new Error('INTERACTION_COLLECTOR_ERROR', reason)); + }); + }); } /** @@ -406,10 +536,10 @@ class Message extends Base { * @readonly */ get deletable() { - return ( + return Boolean( !this.deleted && - (this.author.id === this.client.user.id || - (this.guild && this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES, false))) + (this.author.id === this.client.user.id || + this.channel.permissionsFor?.(this.client.user)?.has(Permissions.FLAGS.MANAGE_MESSAGES)), ); } @@ -425,6 +555,19 @@ class Message extends Base { ); } + /** + * Fetches the Message this crosspost/reply/pin-add references, if available to the client + * @returns {Promise} + */ + async fetchReference() { + if (!this.reference) throw new Error('MESSAGE_REFERENCE_MISSING'); + const { channelId, messageId } = this.reference; + const channel = this.client.channels.resolve(channelId); + if (!channel) throw new Error('GUILD_CHANNEL_RESOLVE'); + const message = await channel.messages.fetch(messageId); + return message; + } + /** * Whether the message is crosspostable by the client user * @type {boolean} @@ -432,7 +575,7 @@ class Message extends Base { */ get crosspostable() { return ( - this.channel.type === 'news' && + this.channel.type === 'GUILD_NEWS' && !this.flags.has(MessageFlags.FLAGS.CROSSPOSTED) && this.type === 'DEFAULT' && this.channel.viewable && @@ -443,18 +586,22 @@ class Message extends Base { } /** - * Options that can be passed into editMessage. + * Options that can be passed into {@link Message#edit}. * @typedef {Object} MessageEditOptions - * @property {string} [content] Content to be edited - * @property {MessageEmbed|Object} [embed] An embed to be added/edited - * @property {string|boolean} [code] Language for optional codeblock formatting to apply + * @property {?string} [content] Content to be edited + * @property {MessageEmbed[]|APIEmbed[]} [embeds] Embeds to be added/edited * @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content + * @property {MessageFlags} [flags] Which flags to set for the message. Only `SUPPRESS_EMBEDS` can be edited. + * @property {MessageAttachment[]} [attachments] An array of attachments to keep, + * all attachments will be kept if omitted + * @property {FileOptions[]|BufferResolvable[]|MessageAttachment[]} [files] Files to add to the message + * @property {MessageActionRow[]|MessageActionRowOptions[]} [components] + * Action rows containing interactive components for the message (buttons, select menus) */ /** * Edits the content of the message. - * @param {StringResolvable|APIMessage} [content] The new content for the message - * @param {MessageEditOptions|MessageEmbed} [options] The options to provide + * @param {string|MessagePayload|MessageEditOptions} options The options to provide * @returns {Promise} * @example * // Update the content of a message @@ -462,14 +609,8 @@ class Message extends Base { * .then(msg => console.log(`Updated the content of a message to ${msg.content}`)) * .catch(console.error); */ - edit(content, options) { - const { data } = - content instanceof APIMessage ? content.resolveData() : APIMessage.create(this, content, options).resolveData(); - return this.client.api.channels[this.channel.id].messages[this.id].patch({ data }).then(d => { - const clone = this._clone(); - clone._patch(d); - return clone; - }); + edit(options) { + return this.channel.messages.edit(this, options); } /** @@ -477,53 +618,40 @@ class Message extends Base { * @returns {Promise} * @example * // Crosspost a message - * if (message.channel.type === 'news') { + * if (message.channel.type === 'GUILD_NEWS') { * message.crosspost() * .then(() => console.log('Crossposted message')) * .catch(console.error); * } */ - async crosspost() { - await this.client.api.channels(this.channel.id).messages(this.id).crosspost.post(); - return this; + crosspost() { + return this.channel.messages.crosspost(this.id); } /** * Pins this message to the channel's pinned messages. - * @param {Object} [options] Options for pinning - * @param {string} [options.reason] Reason for pinning * @returns {Promise} * @example - * // Pin a message with a reason - * message.pin({ reason: 'important' }) + * // Pin a message + * message.pin() * .then(console.log) * .catch(console.error) */ - pin(options) { - return this.client.api - .channels(this.channel.id) - .pins(this.id) - .put(options) - .then(() => this); + pin() { + return this.channel.messages.pin(this.id).then(() => this); } /** * Unpins this message from the channel's pinned messages. - * @param {Object} [options] Options for unpinning - * @param {string} [options.reason] Reason for unpinning * @returns {Promise} * @example - * // Unpin a message with a reason - * message.unpin({ reason: 'no longer relevant' }) + * // Unpin a message + * message.unpin() * .then(console.log) * .catch(console.error) */ - unpin(options) { - return this.client.api - .channels(this.channel.id) - .pins(this.id) - .delete(options) - .then(() => this); + unpin() { + return this.channel.messages.unpin(this.id).then(() => this); } /** @@ -541,78 +669,94 @@ class Message extends Base { * .then(console.log) * .catch(console.error); */ - react(emoji) { + async react(emoji) { emoji = this.client.emojis.resolveIdentifier(emoji); - if (!emoji) throw new TypeError('EMOJI_TYPE'); - - return this.client.api - .channels(this.channel.id) - .messages(this.id) - .reactions(emoji, '@me') - .put() - .then( - () => - this.client.actions.MessageReactionAdd.handle({ - user: this.client.user, - channel: this.channel, - message: this, - emoji: Util.parseEmoji(emoji), - }).reaction, - ); + await this.channel.messages.react(this.id, emoji); + return this.client.actions.MessageReactionAdd.handle({ + user: this.client.user, + channel: this.channel, + message: this, + emoji: Util.parseEmoji(emoji), + }).reaction; } /** * Deletes the message. - * @param {Object} [options] Options - * @param {number} [options.timeout=0] How long to wait to delete the message in milliseconds - * @param {string} [options.reason] Reason for deleting this message, if it does not belong to the client user * @returns {Promise} * @example * // Delete a message - * message.delete({ timeout: 5000 }) - * .then(msg => console.log(`Deleted message from ${msg.author.username} after 5 seconds`)) + * message.delete() + * .then(msg => console.log(`Deleted message from ${msg.author.username}`)) * .catch(console.error); */ - delete(options = {}) { - if (typeof options !== 'object') return Promise.reject(new TypeError('INVALID_TYPE', 'options', 'object', true)); - const { timeout = 0, reason } = options; - if (timeout <= 0) { - return this.channel.messages.delete(this.id, reason).then(() => this); - } else { - return new Promise(resolve => { - this.client.setTimeout(() => { - resolve(this.delete({ reason })); - }, timeout); - }); - } + async delete() { + await this.channel.messages.delete(this.id); + return this; } /** - * Replies to the message. - * @param {StringResolvable|APIMessage} [content=''] The content for the message - * @param {MessageOptions|MessageAdditions} [options={}] The options to provide + * Options provided when sending a message as an inline reply. + * @typedef {BaseMessageOptions} ReplyMessageOptions + * @property {boolean} [failIfNotExists=true] Whether to error if the referenced message + * does not exist (creates a standard message in this case when false) + */ + + /** + * Send an inline reply to this message. + * @param {string|MessagePayload|ReplyMessageOptions} options The options to provide * @returns {Promise} * @example * // Reply to a message - * message.reply('Hey, I\'m a reply!') - * .then(() => console.log(`Sent a reply to ${message.author.username}`)) + * message.reply('This is a reply!') + * .then(() => console.log(`Replied to message "${message.content}"`)) * .catch(console.error); */ - reply(content, options) { - return this.channel.send( - content instanceof APIMessage - ? content - : APIMessage.transformOptions(content, options, { reply: this.member || this.author }), - ); + reply(options) { + let data; + + if (options instanceof MessagePayload) { + data = options; + } else { + data = MessagePayload.create(this, options, { + reply: { + messageReference: this, + failIfNotExists: options?.failIfNotExists ?? this.client.options.failIfNotExists, + }, + }); + } + return this.channel.send(data); + } + + /** + * Options for starting a thread on a message. + * @typedef {Object} StartThreadOptions + * @property {string} name The name of the new thread + * @property {ThreadAutoArchiveDuration} autoArchiveDuration The amount of time (in minutes) after which the thread + * should automatically archive in case of no recent activity + * @property {string} [reason] Reason for creating the thread + */ + + /** + * Create a new public thread from this message + * @see ThreadManager#create + * @param {StartThreadOptions} [options] Options for starting a thread on this message + * @returns {Promise} + */ + startThread(options = {}) { + if (!['GUILD_TEXT', 'GUILD_NEWS'].includes(this.channel.type)) { + return Promise.reject(new Error('MESSAGE_THREAD_PARENT')); + } + if (this.hasThread) return Promise.reject(new Error('MESSAGE_EXISTING_THREAD')); + return this.channel.threads.create({ ...options, startMessage: this }); } /** * Fetch this message. - * @param {boolean} [force=false] Whether to skip the cache check and request the API + * @param {boolean} [force=true] Whether to skip the cache check and request the API * @returns {Promise} */ - fetch(force = false) { - return this.channel.messages.fetch(this.id, true, force); + fetch(force = true) { + return this.channel.messages.fetch(this.id, { force }); } /** @@ -620,12 +764,12 @@ class Message extends Base { * @returns {Promise} */ fetchWebhook() { - if (!this.webhookID) return Promise.reject(new Error('WEBHOOK_MESSAGE')); - return this.client.fetchWebhook(this.webhookID); + if (!this.webhookId) return Promise.reject(new Error('WEBHOOK_MESSAGE')); + return this.client.fetchWebhook(this.webhookId); } /** - * Suppresses or unsuppresses embeds on a message + * Suppresses or unsuppresses embeds on a message. * @param {boolean} [suppress=true] If the embeds should be suppressed or not * @returns {Promise} */ @@ -641,12 +785,20 @@ class Message extends Base { return this.edit({ flags }); } + /** + * Removes the attachments from this message. + * @returns {Promise} + */ + removeAttachments() { + return this.edit({ attachments: [] }); + } + /** * Used mainly internally. Whether two messages are identical in properties. If you want to compare messages * without checking all the properties, use `message.id === message2.id`, which is much more efficient. This * method allows you to see if there are differences in content, embeds, attachments, nonce and tts properties. * @param {Message} message The message to compare it to - * @param {Object} rawData Raw data passed through the WebSocket about this message + * @param {APIMessage} rawData Raw data passed through the WebSocket about this message * @returns {boolean} */ equals(message, rawData) { @@ -686,10 +838,10 @@ class Message extends Base { toJSON() { return super.toJSON({ - channel: 'channelID', - author: 'authorID', - application: 'applicationID', - guild: 'guildID', + channel: 'channelId', + author: 'authorId', + groupActivityApplication: 'groupActivityApplicationId', + guild: 'guildId', cleanContent: true, member: false, reactions: false, diff --git a/node_modules/discord.js/src/structures/MessageAttachment.js b/node_modules/discord.js/src/structures/MessageAttachment.js index f5fb723b..6bac7a70 100644 --- a/node_modules/discord.js/src/structures/MessageAttachment.js +++ b/node_modules/discord.js/src/structures/MessageAttachment.js @@ -9,7 +9,7 @@ class MessageAttachment { /** * @param {BufferResolvable|Stream} attachment The file * @param {string} [name=null] The name of the file, if any - * @param {Object} [data] Extra data + * @param {APIAttachment} [data] Extra data */ constructor(attachment, name = null, data) { this.attachment = attachment; @@ -45,7 +45,7 @@ class MessageAttachment { _patch(data) { /** - * The ID of this attachment + * The attachment's id * @type {Snowflake} */ this.id = data.id; @@ -72,13 +72,19 @@ class MessageAttachment { * The height of this attachment (if an image or video) * @type {?number} */ - this.height = typeof data.height !== 'undefined' ? data.height : null; + this.height = data.height ?? null; /** * The width of this attachment (if an image or video) * @type {?number} */ - this.width = typeof data.width !== 'undefined' ? data.width : null; + this.width = data.width ?? null; + + /** + * This media type of this attachment + * @type {?string} + */ + this.contentType = data.content_type ?? null; } /** @@ -96,3 +102,8 @@ class MessageAttachment { } module.exports = MessageAttachment; + +/** + * @external APIAttachment + * @see {@link https://discord.com/developers/docs/resources/channel#attachment-object} + */ diff --git a/node_modules/discord.js/src/structures/MessageCollector.js b/node_modules/discord.js/src/structures/MessageCollector.js index 740928d9..9eb13d8a 100644 --- a/node_modules/discord.js/src/structures/MessageCollector.js +++ b/node_modules/discord.js/src/structures/MessageCollector.js @@ -17,12 +17,11 @@ const { Events } = require('../util/Constants'); class MessageCollector extends Collector { /** * @param {TextChannel|DMChannel} channel The channel - * @param {CollectorFilter} filter The filter to be applied to this collector * @param {MessageCollectorOptions} options The options to be applied to this collector * @emits MessageCollector#message */ - constructor(channel, filter, options = {}) { - super(channel.client, filter, options); + constructor(channel, options = {}) { + super(channel.client, options); /** * The channel @@ -91,11 +90,11 @@ class MessageCollector extends Collector { } /** - * Checks after un/collection to see if the collector is done. - * @returns {?string} - * @private + * The reason this collector has ended with, or null if it hasn't ended yet + * @type {?string} + * @readonly */ - endReason() { + get endReason() { if (this.options.max && this.collected.size >= this.options.max) return 'limit'; if (this.options.maxProcessed && this.received === this.options.maxProcessed) return 'processedLimit'; return null; @@ -120,7 +119,7 @@ class MessageCollector extends Collector { * @returns {void} */ _handleGuildDeletion(guild) { - if (this.channel.guild && guild.id === this.channel.guild.id) { + if (guild.id === this.channel.guild?.id) { this.stop('guildDelete'); } } diff --git a/node_modules/discord.js/src/structures/MessageEmbed.js b/node_modules/discord.js/src/structures/MessageEmbed.js index ef007a55..d335248f 100644 --- a/node_modules/discord.js/src/structures/MessageEmbed.js +++ b/node_modules/discord.js/src/structures/MessageEmbed.js @@ -11,7 +11,30 @@ class MessageEmbed { * @name MessageEmbed * @kind constructor * @memberof MessageEmbed - * @param {MessageEmbed|Object} [data={}] MessageEmbed to clone or raw embed data + * @param {MessageEmbed|MessageEmbedOptions} [data={}] MessageEmbed to clone or raw embed data + */ + + /** + * A `Partial` object is a representation of any existing object. + * This object contains between 0 and all of the original objects parameters. + * This is true regardless of whether the parameters are optional in the base object. + * @typedef {Object} Partial + */ + + /** + * Represents the possible options for a MessageEmbed + * @typedef {Object} MessageEmbedOptions + * @property {string} [title] The title of this embed + * @property {string} [description] The description of this embed + * @property {string} [url] The URL of this embed + * @property {Date|number} [timestamp] The timestamp of this embed + * @property {ColorResolvable} [color] The color of this embed + * @property {EmbedFieldData[]} [fields] The fields of this embed + * @property {Partial} [author] The author of this embed + * @property {Partial} [thumbnail] The thumbnail of this embed + * @property {Partial} [image] The image of this embed + * @property {Partial} [video] The video of this embed + * @property {Partial} [footer] The footer of this embed */ constructor(data = {}, skipValidation = false) { @@ -28,26 +51,27 @@ class MessageEmbed { * * `article` - an article embed * * `link` - a link embed * @type {string} + * @deprecated */ - this.type = data.type || 'rich'; + this.type = data.type ?? 'rich'; /** * The title of this embed * @type {?string} */ - this.title = 'title' in data ? data.title : null; + this.title = data.title ?? null; /** * The description of this embed * @type {?string} */ - this.description = 'description' in data ? data.description : null; + this.description = data.description ?? null; /** * The URL of this embed * @type {?string} */ - this.url = 'url' in data ? data.url : null; + this.url = data.url ?? null; /** * The color of this embed @@ -94,7 +118,7 @@ class MessageEmbed { this.thumbnail = data.thumbnail ? { url: data.thumbnail.url, - proxyURL: data.thumbnail.proxyURL || data.thumbnail.proxy_url, + proxyURL: data.thumbnail.proxyURL ?? data.thumbnail.proxy_url, height: data.thumbnail.height, width: data.thumbnail.width, } @@ -116,7 +140,7 @@ class MessageEmbed { this.image = data.image ? { url: data.image.url, - proxyURL: data.image.proxyURL || data.image.proxy_url, + proxyURL: data.image.proxyURL ?? data.image.proxy_url, height: data.image.height, width: data.image.width, } @@ -139,7 +163,7 @@ class MessageEmbed { this.video = data.video ? { url: data.video.url, - proxyURL: data.video.proxyURL || data.video.proxy_url, + proxyURL: data.video.proxyURL ?? data.video.proxy_url, height: data.video.height, width: data.video.width, } @@ -162,8 +186,8 @@ class MessageEmbed { ? { name: data.author.name, url: data.author.url, - iconURL: data.author.iconURL || data.author.icon_url, - proxyIconURL: data.author.proxyIconURL || data.author.proxy_icon_url, + iconURL: data.author.iconURL ?? data.author.icon_url, + proxyIconURL: data.author.proxyIconURL ?? data.author.proxy_icon_url, } : null; @@ -200,16 +224,10 @@ class MessageEmbed { this.footer = data.footer ? { text: data.footer.text, - iconURL: data.footer.iconURL || data.footer.icon_url, - proxyIconURL: data.footer.proxyIconURL || data.footer.proxy_icon_url, + iconURL: data.footer.iconURL ?? data.footer.icon_url, + proxyIconURL: data.footer.proxyIconURL ?? data.footer.proxy_icon_url, } : null; - - /** - * The files of this embed - * @type {Array} - */ - this.files = data.files || []; } /** @@ -231,25 +249,26 @@ class MessageEmbed { } /** - * The accumulated length for the embed title, description, fields and footer text + * The accumulated length for the embed title, description, fields, footer text, and author name * @type {number} * @readonly */ get length() { return ( - (this.title ? this.title.length : 0) + - (this.description ? this.description.length : 0) + + (this.title?.length ?? 0) + + (this.description?.length ?? 0) + (this.fields.length >= 1 ? this.fields.reduce((prev, curr) => prev + curr.name.length + curr.value.length, 0) : 0) + - (this.footer ? this.footer.text.length : 0) + (this.footer?.text.length ?? 0) + + (this.author?.name.length ?? 0) ); } /** * Adds a field to the embed (max 25). - * @param {StringResolvable} name The name of this field - * @param {StringResolvable} value The value of this field + * @param {string} name The name of this field + * @param {string} value The value of this field * @param {boolean} [inline=false] If this field will be displayed inline * @returns {MessageEmbed} */ @@ -280,25 +299,24 @@ class MessageEmbed { } /** - * Sets the file to upload alongside the embed. This file can be accessed via `attachment://fileName.extension` when - * setting an embed image or author/footer icons. Multiple files can be attached. - * @param {Array} files Files to attach + * Sets the embed's fields (max 25). + * @param {...EmbedFieldData|EmbedFieldData[]} fields The fields to set * @returns {MessageEmbed} */ - attachFiles(files) { - this.files = this.files.concat(files); + setFields(...fields) { + this.spliceFields(0, this.fields.length, fields); return this; } /** * Sets the author of this embed. - * @param {StringResolvable} name The name of the author + * @param {string} name The name of the author * @param {string} [iconURL] The icon URL of the author * @param {string} [url] The URL of the author * @returns {MessageEmbed} */ setAuthor(name, iconURL, url) { - this.author = { name: Util.resolveString(name), iconURL, url }; + this.author = { name: Util.verifyString(name, RangeError, 'EMBED_AUTHOR_NAME'), iconURL, url }; return this; } @@ -314,24 +332,22 @@ class MessageEmbed { /** * Sets the description of this embed. - * @param {StringResolvable} description The description + * @param {string} description The description * @returns {MessageEmbed} */ setDescription(description) { - description = Util.resolveString(description); - this.description = description; + this.description = Util.verifyString(description, RangeError, 'EMBED_DESCRIPTION'); return this; } /** * Sets the footer of this embed. - * @param {StringResolvable} text The text of the footer + * @param {string} text The text of the footer * @param {string} [iconURL] The icon URL of the footer * @returns {MessageEmbed} */ setFooter(text, iconURL) { - text = Util.resolveString(text); - this.footer = { text, iconURL }; + this.footer = { text: Util.verifyString(text, RangeError, 'EMBED_FOOTER_TEXT'), iconURL }; return this; } @@ -368,12 +384,11 @@ class MessageEmbed { /** * Sets the title of this embed. - * @param {StringResolvable} title The title + * @param {string} title The title * @returns {MessageEmbed} */ setTitle(title) { - title = Util.resolveString(title); - this.title = title; + this.title = Util.verifyString(title, RangeError, 'EMBED_TITLE'); return this; } @@ -389,7 +404,7 @@ class MessageEmbed { /** * Transforms the embed to a plain object. - * @returns {Object} The raw data of this embed + * @returns {APIEmbed} The raw data of this embed */ toJSON() { return { @@ -397,46 +412,42 @@ class MessageEmbed { type: 'rich', description: this.description, url: this.url, - timestamp: this.timestamp ? new Date(this.timestamp) : null, + timestamp: this.timestamp && new Date(this.timestamp), color: this.color, fields: this.fields, thumbnail: this.thumbnail, image: this.image, - author: this.author - ? { - name: this.author.name, - url: this.author.url, - icon_url: this.author.iconURL, - } - : null, - footer: this.footer - ? { - text: this.footer.text, - icon_url: this.footer.iconURL, - } - : null, + author: this.author && { + name: this.author.name, + url: this.author.url, + icon_url: this.author.iconURL, + }, + footer: this.footer && { + text: this.footer.text, + icon_url: this.footer.iconURL, + }, }; } /** * Normalizes field input and resolves strings. - * @param {StringResolvable} name The name of the field - * @param {StringResolvable} value The value of the field + * @param {string} name The name of the field + * @param {string} value The value of the field * @param {boolean} [inline=false] Set the field to display inline * @returns {EmbedField} */ static normalizeField(name, value, inline = false) { - name = Util.resolveString(name); - if (!name) throw new RangeError('EMBED_FIELD_NAME'); - value = Util.resolveString(value); - if (!value) throw new RangeError('EMBED_FIELD_VALUE'); - return { name, value, inline }; + return { + name: Util.verifyString(name, RangeError, 'EMBED_FIELD_NAME', false), + value: Util.verifyString(value, RangeError, 'EMBED_FIELD_VALUE', false), + inline, + }; } /** * @typedef {Object} EmbedFieldData - * @property {StringResolvable} name The name of this field - * @property {StringResolvable} value The value of this field + * @property {string} name The name of this field + * @property {string} value The value of this field * @property {boolean} [inline] If this field will be displayed inline */ @@ -449,13 +460,14 @@ class MessageEmbed { return fields .flat(2) .map(field => - this.normalizeField( - field && field.name, - field && field.value, - field && typeof field.inline === 'boolean' ? field.inline : false, - ), + this.normalizeField(field.name, field.value, typeof field.inline === 'boolean' ? field.inline : false), ); } } module.exports = MessageEmbed; + +/** + * @external APIEmbed + * @see {@link https://discord.com/developers/docs/resources/channel#embed-object} + */ diff --git a/node_modules/discord.js/src/structures/MessageMentions.js b/node_modules/discord.js/src/structures/MessageMentions.js index 2ed24c09..cd2c697d 100644 --- a/node_modules/discord.js/src/structures/MessageMentions.js +++ b/node_modules/discord.js/src/structures/MessageMentions.js @@ -1,6 +1,6 @@ 'use strict'; -const Collection = require('../util/Collection'); +const { Collection } = require('@discordjs/collection'); const { ChannelTypes } = require('../util/Constants'); const Util = require('../util/Util'); @@ -8,7 +8,7 @@ const Util = require('../util/Util'); * Keeps track of mentions in a {@link Message}. */ class MessageMentions { - constructor(message, users, roles, everyone, crosspostedChannels) { + constructor(message, users, roles, everyone, crosspostedChannels, repliedUser) { /** * The client the message is from * @type {Client} @@ -49,9 +49,9 @@ class MessageMentions { this.users = new Collection(); for (const mention of users) { if (mention.member && message.guild) { - message.guild.members.add(Object.assign(mention.member, { user: mention })); + message.guild.members._add(Object.assign(mention.member, { user: mention })); } - const user = message.client.users.add(mention); + const user = message.client.users._add(mention); this.users.set(user.id, user); } } @@ -87,7 +87,7 @@ class MessageMentions { /** * Cached channels for {@link MessageMentions#channels} - * @type {?Collection} + * @type {?Collection} * @private */ this._channels = null; @@ -95,10 +95,10 @@ class MessageMentions { /** * Crossposted channel data. * @typedef {Object} CrosspostedChannel - * @property {string} channelID ID of the mentioned channel - * @property {string} guildID ID of the guild that has the channel - * @property {string} type Type of the channel - * @property {string} name The name of the channel + * @property {string} channelId The mentioned channel's id + * @property {string} guildId The id of the guild that has the channel + * @property {string} type The channel's type + * @property {string} name The channel's name */ if (crosspostedChannels) { @@ -115,9 +115,9 @@ class MessageMentions { for (const d of crosspostedChannels) { const type = channelTypes[d.type]; this.crosspostedChannels.set(d.id, { - channelID: d.id, - guildID: d.guild_id, - type: type ? type.toLowerCase() : 'unknown', + channelId: d.id, + guildId: d.guild_id, + type: type ?? 'UNKNOWN', name: d.name, }); } @@ -125,10 +125,16 @@ class MessageMentions { } else { this.crosspostedChannels = new Collection(); } + + /** + * The author of the message that this message is a reply to + * @type {?User} + */ + this.repliedUser = repliedUser ? this.client.users._add(repliedUser) : null; } /** - * Any members that were mentioned (only in {@link TextChannel}s) + * Any members that were mentioned (only in {@link Guild}s) * Order as received from the API, not as they appear in the message content * @type {?Collection} * @readonly @@ -138,7 +144,7 @@ class MessageMentions { if (!this.guild) return null; this._members = new Collection(); this.users.forEach(user => { - const member = this.guild.member(user); + const member = this.guild.members.resolve(user); if (member) this._members.set(member.user.id, member); }); return this._members; @@ -147,7 +153,7 @@ class MessageMentions { /** * Any channels that were mentioned * Order as they appear first in the message content - * @type {Collection} + * @type {Collection} * @readonly */ get channels() { @@ -161,14 +167,19 @@ class MessageMentions { return this._channels; } + /** + * Options used to check for a mention. + * @typedef {Object} MessageMentionsHasOptions + * @property {boolean} [ignoreDirect=false] Whether to ignore direct mentions to the item + * @property {boolean} [ignoreRoles=false] Whether to ignore role mentions to a guild member + * @property {boolean} [ignoreEveryone=false] Whether to ignore everyone/here mentions + */ + /** * Checks if a user, guild member, role, or channel is mentioned. - * Takes into account user mentions, role mentions, and @everyone/@here mentions. - * @param {UserResolvable|RoleResolvable|GuildChannelResolvable} data User/Role/Channel to check - * @param {Object} [options] Options - * @param {boolean} [options.ignoreDirect=false] - Whether to ignore direct mentions to the item - * @param {boolean} [options.ignoreRoles=false] - Whether to ignore role mentions to a guild member - * @param {boolean} [options.ignoreEveryone=false] - Whether to ignore everyone/here mentions + * Takes into account user mentions, role mentions, and `@everyone`/`@here` mentions. + * @param {UserResolvable|RoleResolvable|ChannelResolvable} data The User/Role/Channel to check for + * @param {MessageMentionsHasOptions} [options] The options for the check * @returns {boolean} */ has(data, { ignoreDirect = false, ignoreRoles = false, ignoreEveryone = false } = {}) { @@ -180,11 +191,9 @@ class MessageMentions { if (!ignoreDirect) { const id = - this.client.users.resolveID(data) || - (this.guild && this.guild.roles.resolveID(data)) || - this.client.channels.resolveID(data); + this.guild?.roles.resolveId(data) ?? this.client.channels.resolveId(data) ?? this.client.users.resolveId(data); - return this.users.has(id) || this.channels.has(id) || this.roles.has(id); + return typeof id === 'string' && (this.users.has(id) || this.channels.has(id) || this.roles.has(id)); } return false; diff --git a/node_modules/discord.js/src/structures/MessageReaction.js b/node_modules/discord.js/src/structures/MessageReaction.js index 134ef5f9..69043570 100644 --- a/node_modules/discord.js/src/structures/MessageReaction.js +++ b/node_modules/discord.js/src/structures/MessageReaction.js @@ -11,7 +11,7 @@ const Util = require('../util/Util'); class MessageReaction { /** * @param {Client} client The instantiating client - * @param {Object} data The data for the message reaction + * @param {APIReaction} data The data for the message reaction * @param {Message} message The message the reaction refers to */ constructor(client, data, message) { @@ -22,17 +22,24 @@ class MessageReaction { * @readonly */ Object.defineProperty(this, 'client', { value: client }); + /** * The message that this reaction refers to * @type {Message} */ this.message = message; + /** + * Whether the client has given this reaction + * @type {boolean} + */ + this.me = data.me; + /** * A manager of the users that have given this reaction * @type {ReactionUserManager} */ - this.users = new ReactionUserManager(client, undefined, this); + this.users = new ReactionUserManager(this); this._emoji = new ReactionEmoji(this, data.emoji); @@ -48,12 +55,6 @@ class MessageReaction { */ this.count = data.count; } - - /** - * Whether the client has given this reaction - * @type {boolean} - */ - this.me = data.me; } /** @@ -105,14 +106,14 @@ class MessageReaction { */ async fetch() { const message = await this.message.fetch(); - const existing = message.reactions.cache.get(this.emoji.id || this.emoji.name); + const existing = message.reactions.cache.get(this.emoji.id ?? this.emoji.name); // The reaction won't get set when it has been completely removed - this._patch(existing || { count: 0 }); + this._patch(existing ?? { count: 0 }); return this; } toJSON() { - return Util.flatten(this, { emoji: 'emojiID', message: 'messageID' }); + return Util.flatten(this, { emoji: 'emojiId', message: 'messageId' }); } _add(user) { @@ -128,9 +129,14 @@ class MessageReaction { if (!this.me || user.id !== this.message.client.user.id) this.count--; if (user.id === this.message.client.user.id) this.me = false; if (this.count <= 0 && this.users.cache.size === 0) { - this.message.reactions.cache.delete(this.emoji.id || this.emoji.name); + this.message.reactions.cache.delete(this.emoji.id ?? this.emoji.name); } } } module.exports = MessageReaction; + +/** + * @external APIReaction + * @see {@link https://discord.com/developers/docs/resources/channel#reaction-object} + */ diff --git a/node_modules/discord.js/src/structures/NewsChannel.js b/node_modules/discord.js/src/structures/NewsChannel.js index 33197190..453141b9 100644 --- a/node_modules/discord.js/src/structures/NewsChannel.js +++ b/node_modules/discord.js/src/structures/NewsChannel.js @@ -21,16 +21,16 @@ class NewsChannel extends TextChannel { * @param {string} [reason] Reason for creating the webhook * @returns {Promise} * @example - * if (channel.type === 'news') { + * if (channel.type === 'GUILD_NEWS') { * channel.addFollower('222197033908436994', 'Important announcements') * .then(() => console.log('Added follower')) * .catch(console.error); * } */ async addFollower(channel, reason) { - const channelID = this.guild.channels.resolveID(channel); - if (!channelID) throw new Error('GUILD_CHANNEL_RESOLVE'); - await this.client.api.channels(this.id).followers.post({ data: { webhook_channel_id: channelID }, reason }); + const channelId = this.guild.channels.resolveId(channel); + if (!channelId) throw new Error('GUILD_CHANNEL_RESOLVE'); + await this.client.api.channels(this.id).followers.post({ data: { webhook_channel_id: channelId }, reason }); return this; } } diff --git a/node_modules/discord.js/src/structures/PartialGroupDMChannel.js b/node_modules/discord.js/src/structures/PartialGroupDMChannel.js index e398f235..4950fcb3 100644 --- a/node_modules/discord.js/src/structures/PartialGroupDMChannel.js +++ b/node_modules/discord.js/src/structures/PartialGroupDMChannel.js @@ -26,12 +26,11 @@ class PartialGroupDMChannel extends Channel { /** * The URL to this channel's icon. - * @param {ImageURLOptions} [options={}] Options for the Image URL + * @param {StaticImageURLOptions} [options={}] Options for the Image URL * @returns {?string} */ iconURL({ format, size } = {}) { - if (!this.icon) return null; - return this.client.rest.cdn.GDMIcon(this.id, this.icon, format, size); + return this.icon && this.client.rest.cdn.GDMIcon(this.id, this.icon, format, size); } delete() { diff --git a/node_modules/discord.js/src/structures/PermissionOverwrites.js b/node_modules/discord.js/src/structures/PermissionOverwrites.js index bbc7cd13..d810b42d 100644 --- a/node_modules/discord.js/src/structures/PermissionOverwrites.js +++ b/node_modules/discord.js/src/structures/PermissionOverwrites.js @@ -1,82 +1,72 @@ 'use strict'; +const Base = require('./Base'); const Role = require('./Role'); const { TypeError } = require('../errors'); +const { OverwriteTypes } = require('../util/Constants'); const Permissions = require('../util/Permissions'); -const Util = require('../util/Util'); /** * Represents a permission overwrite for a role or member in a guild channel. + * @extends {Base} */ -class PermissionOverwrites { - constructor(guildChannel, data) { +class PermissionOverwrites extends Base { + constructor(client, data, channel) { + super(client); + /** * The GuildChannel this overwrite is for * @name PermissionOverwrites#channel * @type {GuildChannel} * @readonly */ - Object.defineProperty(this, 'channel', { value: guildChannel }); + Object.defineProperty(this, 'channel', { value: channel }); if (data) this._patch(data); } _patch(data) { /** - * The ID of this overwrite, either a user ID or a role ID + * The overwrite's id, either a {@link User} or a {@link Role} id * @type {Snowflake} */ this.id = data.id; - /** - * The type of a permission overwrite. It can be one of: - * * member - * * role - * @typedef {string} OverwriteType - */ - /** * The type of this overwrite * @type {OverwriteType} */ - this.type = data.type; + this.type = typeof data.type === 'number' ? OverwriteTypes[data.type] : data.type; /** * The permissions that are denied for the user or role. * @type {Readonly} */ - this.deny = new Permissions(data.deny).freeze(); + this.deny = new Permissions(BigInt(data.deny)).freeze(); /** * The permissions that are allowed for the user or role. * @type {Readonly} */ - this.allow = new Permissions(data.allow).freeze(); + this.allow = new Permissions(BigInt(data.allow)).freeze(); } /** - * Updates this permissionOverwrites. + * Edits this Permission Overwrite. * @param {PermissionOverwriteOptions} options The options for the update * @param {string} [reason] Reason for creating/editing this overwrite * @returns {Promise} * @example * // Update permission overwrites - * permissionOverwrites.update({ + * permissionOverwrites.edit({ * SEND_MESSAGES: false * }) * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id))) * .catch(console.error); */ - update(options, reason) { - const { allow, deny } = this.constructor.resolveOverwriteOptions(options, this); - - return this.channel.client.api - .channels(this.channel.id) - .permissions[this.id].put({ - data: { id: this.id, type: this.type, allow: allow.bitfield, deny: deny.bitfield }, - reason, - }) - .then(() => this); + async edit(options, reason) { + await this.channel.permissionOverwrites.upsert(this.id, options, { type: OverwriteTypes[this.type], reason }, this); + return this; } /** @@ -84,12 +74,18 @@ class PermissionOverwrites { * @param {string} [reason] Reason for deleting this overwrite * @returns {Promise} */ - delete(reason) { - return this.channel.client.api.channels[this.channel.id].permissions[this.id].delete({ reason }).then(() => this); + async delete(reason) { + await this.channel.permissionOverwrites.delete(this.id, reason); + return this; } toJSON() { - return Util.flatten(this); + return { + id: this.id, + type: OverwriteTypes[this.type], + allow: this.allow, + deny: this.deny, + }; } /** @@ -105,7 +101,7 @@ class PermissionOverwrites { */ /** - * @typedef {object} ResolvedOverwriteOptions + * @typedef {Object} ResolvedOverwriteOptions * @property {Permissions} allow The allowed permissions * @property {Permissions} deny The denied permissions */ @@ -113,9 +109,7 @@ class PermissionOverwrites { /** * Resolves bitfield permissions overwrites from an object. * @param {PermissionOverwriteOptions} options The options for the update - * @param {Object} initialPermissions The initial permissions - * @param {PermissionResolvable} initialPermissions.allow Initial allowed permissions - * @param {PermissionResolvable} initialPermissions.deny Initial denied permissions + * @param {ResolvedOverwriteOptions} initialPermissions The initial permissions * @returns {ResolvedOverwriteOptions} */ static resolveOverwriteOptions(options, { allow, deny } = {}) { @@ -124,14 +118,14 @@ class PermissionOverwrites { for (const [perm, value] of Object.entries(options)) { if (value === true) { - allow.add(Permissions.FLAGS[perm]); - deny.remove(Permissions.FLAGS[perm]); + allow.add(perm); + deny.remove(perm); } else if (value === false) { - allow.remove(Permissions.FLAGS[perm]); - deny.add(Permissions.FLAGS[perm]); + allow.remove(perm); + deny.add(perm); } else if (value === null) { - allow.remove(Permissions.FLAGS[perm]); - deny.remove(Permissions.FLAGS[perm]); + allow.remove(perm); + deny.remove(perm); } } @@ -142,9 +136,9 @@ class PermissionOverwrites { * The raw data for a permission overwrite * @typedef {Object} RawOverwriteData * @property {Snowflake} id The id of the overwrite - * @property {number} allow The permissions to allow - * @property {number} deny The permissions to deny - * @property {OverwriteType} type The type of this OverwriteData + * @property {string} allow The permissions to allow + * @property {string} deny The permissions to deny + * @property {number} type The type of this OverwriteData */ /** @@ -164,24 +158,29 @@ class PermissionOverwrites { /** * Resolves an overwrite into {@link RawOverwriteData}. * @param {OverwriteResolvable} overwrite The overwrite-like data to resolve - * @param {Guild} guild The guild to resolve from + * @param {Guild} [guild] The guild to resolve from * @returns {RawOverwriteData} */ static resolve(overwrite, guild) { if (overwrite instanceof this) return overwrite.toJSON(); - if (typeof overwrite.id === 'string' && ['role', 'member'].includes(overwrite.type)) { - return { ...overwrite, allow: Permissions.resolve(overwrite.allow), deny: Permissions.resolve(overwrite.deny) }; + if (typeof overwrite.id === 'string' && overwrite.type in OverwriteTypes) { + return { + id: overwrite.id, + type: OverwriteTypes[overwrite.type], + allow: Permissions.resolve(overwrite.allow ?? Permissions.defaultBit).toString(), + deny: Permissions.resolve(overwrite.deny ?? Permissions.defaultBit).toString(), + }; } - const userOrRole = guild.roles.resolve(overwrite.id) || guild.client.users.resolve(overwrite.id); + const userOrRole = guild.roles.resolve(overwrite.id) ?? guild.client.users.resolve(overwrite.id); if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role'); - const type = userOrRole instanceof Role ? 'role' : 'member'; + const type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member; return { id: userOrRole.id, type, - allow: Permissions.resolve(overwrite.allow), - deny: Permissions.resolve(overwrite.deny), + allow: Permissions.resolve(overwrite.allow ?? Permissions.defaultBit).toString(), + deny: Permissions.resolve(overwrite.deny ?? Permissions.defaultBit).toString(), }; } } diff --git a/node_modules/discord.js/src/structures/Presence.js b/node_modules/discord.js/src/structures/Presence.js index 2ae6b8c0..424cba2b 100644 --- a/node_modules/discord.js/src/structures/Presence.js +++ b/node_modules/discord.js/src/structures/Presence.js @@ -1,5 +1,6 @@ 'use strict'; +const Base = require('./Base'); const Emoji = require('./Emoji'); const ActivityFlags = require('../util/ActivityFlags'); const { ActivityTypes } = require('../util/Constants'); @@ -8,7 +9,7 @@ const Util = require('../util/Util'); /** * Activity sent in a message. * @typedef {Object} MessageActivity - * @property {string} [partyID] Id of the party represented in activity + * @property {string} [partyId] Id of the party represented in activity * @property {number} [type] Type of activity sent */ @@ -31,33 +32,29 @@ const Util = require('../util/Util'); /** * Represents a user's presence. + * @extends {Base} */ -class Presence { +class Presence extends Base { /** * @param {Client} client The instantiating client - * @param {Object} [data={}] The data for the presence + * @param {APIPresence} [data={}] The data for the presence */ constructor(client, data = {}) { + super(client); + /** - * The client that instantiated this - * @name Presence#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - /** - * The user ID of this presence + * The presence's user id * @type {Snowflake} */ - this.userID = data.user.id; + this.userId = data.user.id; /** - * The guild of this presence + * The guild this presence is in * @type {?Guild} */ - this.guild = data.guild || null; + this.guild = data.guild ?? null; - this.patch(data); + this._patch(data); } /** @@ -66,7 +63,7 @@ class Presence { * @readonly */ get user() { - return this.client.users.cache.get(this.userID) || null; + return this.client.users.resolve(this.userId); } /** @@ -75,27 +72,21 @@ class Presence { * @readonly */ get member() { - return this.guild.members.cache.get(this.userID) || null; + return this.guild.members.resolve(this.userId); } - patch(data) { + _patch(data) { /** * The status of this presence * @type {PresenceStatus} */ - this.status = data.status || this.status || 'offline'; - - if (data.activities) { - /** - * The activities of this presence - * @type {Activity[]} - */ - this.activities = data.activities.map(activity => new Activity(this, activity)); - } else if (data.activity || data.game) { - this.activities = [new Activity(this, data.game || data.activity)]; - } else { - this.activities = []; - } + this.status = data.status ?? this.status ?? 'offline'; + + /** + * The activities of this presence + * @type {Activity[]} + */ + this.activities = data.activities?.map(activity => new Activity(this, activity)) ?? []; /** * The devices this presence is on @@ -104,14 +95,14 @@ class Presence { * @property {?ClientPresenceStatus} mobile The current presence in the mobile application * @property {?ClientPresenceStatus} desktop The current presence in the desktop application */ - this.clientStatus = data.client_status || null; + this.clientStatus = data.client_status ?? null; return this; } _clone() { const clone = Object.assign(Object.create(this), this); - if (this.activities) clone.activities = this.activities.map(activity => activity._clone()); + clone.activities = this.activities.map(activity => activity._clone()); return clone; } @@ -127,9 +118,9 @@ class Presence { this.status === presence.status && this.activities.length === presence.activities.length && this.activities.every((activity, index) => activity.equals(presence.activities[index])) && - this.clientStatus.web === presence.clientStatus.web && - this.clientStatus.mobile === presence.clientStatus.mobile && - this.clientStatus.desktop === presence.clientStatus.desktop) + this.clientStatus?.web === presence.clientStatus?.web && + this.clientStatus?.mobile === presence.clientStatus?.mobile && + this.clientStatus?.desktop === presence.clientStatus?.desktop) ); } @@ -138,6 +129,14 @@ class Presence { } } +/** + * The platform of this activity: + * * **`desktop`** + * * **`samsung`** - playing on Samsung Galaxy + * * **`xbox`** - playing on Xbox Live + * @typedef {string} ActivityPlatform + */ + /** * Represents an activity that is part of a user's presence. */ @@ -146,40 +145,46 @@ class Activity { Object.defineProperty(this, 'presence', { value: presence }); /** - * The name of the activity being played + * The activity's id + * @type {string} + */ + this.id = data.id; + + /** + * The activity's name * @type {string} */ this.name = data.name; /** - * The type of the activity status + * The activity status's type * @type {ActivityType} */ - this.type = ActivityTypes[data.type]; + this.type = typeof data.type === 'number' ? ActivityTypes[data.type] : data.type; /** * If the activity is being streamed, a link to the stream * @type {?string} */ - this.url = data.url || null; + this.url = data.url ?? null; /** * Details about the activity * @type {?string} */ - this.details = data.details || null; + this.details = data.details ?? null; /** * State of the activity * @type {?string} */ - this.state = data.state || null; + this.state = data.state ?? null; /** - * Application ID associated with this activity + * The id of the application associated with this activity * @type {?Snowflake} */ - this.applicationID = data.application_id || null; + this.applicationId = data.application_id ?? null; /** * Timestamps for the activity @@ -194,13 +199,25 @@ class Activity { } : null; + /** + * The Spotify song's id + * @type {?string} + */ + this.syncId = data.sync_id ?? null; + + /** + * The platform the game is being played on + * @type {?ActivityPlatform} + */ + this.platform = data.platform ?? null; + /** * Party of the activity * @type {?Object} - * @property {?string} id ID of the party + * @property {?string} id The party's id * @property {number[]} size Size of the party as `[current, max]` */ - this.party = data.party || null; + this.party = data.party ?? null; /** * Assets for rich presence @@ -208,8 +225,6 @@ class Activity { */ this.assets = data.assets ? new RichPresenceAssets(this, data.assets) : null; - this.syncID = data.sync_id; - /** * Flags that describe the activity * @type {Readonly} @@ -222,6 +237,18 @@ class Activity { */ this.emoji = data.emoji ? new Emoji(presence.client, data.emoji) : null; + /** + * The game's or Spotify session's id + * @type {?string} + */ + this.sessionId = data.session_id ?? null; + + /** + * The labels of the buttons of this rich presence + * @type {string[]} + */ + this.buttons = data.buttons ?? []; + /** * Creation date of the activity * @type {number} @@ -237,7 +264,12 @@ class Activity { equals(activity) { return ( this === activity || - (activity && this.name === activity.name && this.type === activity.type && this.url === activity.url) + (activity && + this.name === activity.name && + this.type === activity.type && + this.url === activity.url && + this.state === activity.state && + this.details === activity.details) ); } @@ -274,47 +306,45 @@ class RichPresenceAssets { * Hover text for the large image * @type {?string} */ - this.largeText = assets.large_text || null; + this.largeText = assets.large_text ?? null; /** * Hover text for the small image * @type {?string} */ - this.smallText = assets.small_text || null; + this.smallText = assets.small_text ?? null; /** - * ID of the large image asset + * The large image asset's id * @type {?Snowflake} */ - this.largeImage = assets.large_image || null; + this.largeImage = assets.large_image ?? null; /** - * ID of the small image asset + * The small image asset's id * @type {?Snowflake} */ - this.smallImage = assets.small_image || null; + this.smallImage = assets.small_image ?? null; } /** * Gets the URL of the small image asset - * @param {Object} [options] Options for the image url - * @param {string} [options.format] Format of the image - * @param {number} [options.size] Size of the image + * @param {StaticImageURLOptions} [options] Options for the image url * @returns {?string} The small image URL */ smallImageURL({ format, size } = {}) { - if (!this.smallImage) return null; - return this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID, this.smallImage, { - format, - size, - }); + return ( + this.smallImage && + this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationId, this.smallImage, { + format, + size, + }) + ); } /** * Gets the URL of the large image asset - * @param {Object} [options] Options for the image url - * @param {string} [options.format] Format of the image - * @param {number} [options.size] Size of the image + * @param {StaticImageURLOptions} [options] Options for the image url * @returns {?string} The large image URL */ largeImageURL({ format, size } = {}) { @@ -324,7 +354,7 @@ class RichPresenceAssets { } else if (/^twitch:/.test(this.largeImage)) { return `https://static-cdn.jtvnw.net/previews-ttv/live_user_${this.largeImage.slice(7)}.png`; } - return this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID, this.largeImage, { + return this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationId, this.largeImage, { format, size, }); @@ -334,3 +364,9 @@ class RichPresenceAssets { exports.Presence = Presence; exports.Activity = Activity; exports.RichPresenceAssets = RichPresenceAssets; + +/* eslint-disable max-len */ +/** + * @external APIPresence + * @see {@link https://discord.com/developers/docs/rich-presence/how-to#updating-presence-update-presence-payload-fields} + */ diff --git a/node_modules/discord.js/src/structures/ReactionCollector.js b/node_modules/discord.js/src/structures/ReactionCollector.js index e0fa316f..3c0588d5 100644 --- a/node_modules/discord.js/src/structures/ReactionCollector.js +++ b/node_modules/discord.js/src/structures/ReactionCollector.js @@ -1,7 +1,7 @@ 'use strict'; +const { Collection } = require('@discordjs/collection'); const Collector = require('./interfaces/Collector'); -const Collection = require('../util/Collection'); const { Events } = require('../util/Constants'); /** @@ -20,11 +20,10 @@ const { Events } = require('../util/Constants'); class ReactionCollector extends Collector { /** * @param {Message} message The message upon which to collect reactions - * @param {CollectorFilter} filter The filter to apply to this collector * @param {ReactionCollectorOptions} [options={}] The options to apply to this collector */ - constructor(message, filter, options = {}) { - super(message.client, filter, options); + constructor(message, options = {}) { + super(message.client, options); /** * The message upon which to collect reactions @@ -81,10 +80,11 @@ class ReactionCollector extends Collector { /** * Handles an incoming reaction for possible collection. * @param {MessageReaction} reaction The reaction to possibly collect - * @returns {?Snowflake|string} + * @param {User} user The user that added the reaction + * @returns {Promise} * @private */ - collect(reaction) { + async collect(reaction, user) { /** * Emitted whenever a reaction is collected. * @event ReactionCollector#collect @@ -92,6 +92,19 @@ class ReactionCollector extends Collector { * @param {User} user The user that added the reaction */ if (reaction.message.id !== this.message.id) return null; + + /** + * Emitted whenever a reaction is newly created on a message. Will emit only when a new reaction is + * added to the message, as opposed to {@link Collector#collect} which which will + * be emitted even when a reaction has already been added to the message. + * @event ReactionCollector#create + * @param {MessageReaction} reaction The reaction that was added + * @param {User} user The user that added the reaction + */ + if (reaction.count === 1 && (await this.filter(reaction, user, this.collected))) { + this.emit('create', reaction, user); + } + return ReactionCollector.key(reaction); } @@ -99,7 +112,7 @@ class ReactionCollector extends Collector { * Handles a reaction deletion for possible disposal. * @param {MessageReaction} reaction The reaction to possibly dispose of * @param {User} user The user that removed the reaction - * @returns {?Snowflake|string} + * @returns {?(Snowflake|string)} */ dispose(reaction, user) { /** @@ -132,7 +145,12 @@ class ReactionCollector extends Collector { this.checkEnd(); } - endReason() { + /** + * The reason this collector has ended with, or null if it hasn't ended yet + * @type {?string} + * @readonly + */ + get endReason() { if (this.options.max && this.total >= this.options.max) return 'limit'; if (this.options.maxEmojis && this.collected.size >= this.options.maxEmojis) return 'emojiLimit'; if (this.options.maxUsers && this.users.size >= this.options.maxUsers) return 'userLimit'; @@ -170,7 +188,7 @@ class ReactionCollector extends Collector { * @returns {void} */ _handleGuildDeletion(guild) { - if (this.message.guild && guild.id === this.message.guild.id) { + if (guild.id === this.message.guild?.id) { this.stop('guildDelete'); } } @@ -181,7 +199,7 @@ class ReactionCollector extends Collector { * @returns {Snowflake|string} */ static key(reaction) { - return reaction.emoji.id || reaction.emoji.name; + return reaction.emoji.id ?? reaction.emoji.name; } } diff --git a/node_modules/discord.js/src/structures/Role.js b/node_modules/discord.js/src/structures/Role.js index 94ee2f09..897ad48c 100644 --- a/node_modules/discord.js/src/structures/Role.js +++ b/node_modules/discord.js/src/structures/Role.js @@ -3,7 +3,7 @@ const Base = require('./Base'); const { Error, TypeError } = require('../errors'); const Permissions = require('../util/Permissions'); -const Snowflake = require('../util/Snowflake'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); const Util = require('../util/Util'); /** @@ -13,7 +13,7 @@ const Util = require('../util/Util'); class Role extends Base { /** * @param {Client} client The instantiating client - * @param {Object} data The data for the role + * @param {APIRole} data The data for the role * @param {Guild} guild The guild the role is part of */ constructor(client, data, guild) { @@ -30,7 +30,7 @@ class Role extends Base { _patch(data) { /** - * The ID of the role (unique to the guild it is part of) + * The role's id (unique to the guild it is part of) * @type {Snowflake} */ this.id = data.id; @@ -63,7 +63,7 @@ class Role extends Base { * The permissions of the role * @type {Readonly} */ - this.permissions = new Permissions(data.permissions).freeze(); + this.permissions = new Permissions(BigInt(data.permissions)).freeze(); /** * Whether or not the role is managed by an external service @@ -82,6 +82,26 @@ class Role extends Base { * @type {boolean} */ this.deleted = false; + + /** + * The tags this role has + * @type {?Object} + * @property {Snowflake} [botId] The id of the bot this role belongs to + * @property {Snowflake} [integrationId] The id of the integration this role belongs to + * @property {true} [premiumSubscriberRole] Whether this is the guild's premium subscription role + */ + this.tags = data.tags ? {} : null; + if (data.tags) { + if ('bot_id' in data.tags) { + this.tags.botId = data.tags.bot_id; + } + if ('integration_id' in data.tags) { + this.tags.integrationId = data.tags.integration_id; + } + if ('premium_subscriber' in data.tags) { + this.tags.premiumSubscriberRole = true; + } + } } /** @@ -90,7 +110,7 @@ class Role extends Base { * @readonly */ get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; + return SnowflakeUtil.deconstruct(this.id).timestamp; } /** @@ -127,7 +147,7 @@ class Role extends Base { */ get editable() { if (this.managed) return false; - const clientMember = this.guild.member(this.client.user); + const clientMember = this.guild.members.resolve(this.client.user); if (!clientMember.permissions.has(Permissions.FLAGS.MANAGE_ROLES)) return false; return clientMember.roles.highest.comparePositionTo(this) > 0; } @@ -139,7 +159,7 @@ class Role extends Base { */ get position() { const sorted = this.guild._sortedRoles(); - return sorted.array().indexOf(sorted.get(this.id)); + return [...sorted.values()].indexOf(sorted.get(this.id)); } /** @@ -176,46 +196,14 @@ class Role extends Base { * .then(updated => console.log(`Edited role name to ${updated.name}`)) * .catch(console.error); */ - async edit(data, reason) { - if (typeof data.permissions !== 'undefined') data.permissions = Permissions.resolve(data.permissions); - else data.permissions = this.permissions.bitfield; - if (typeof data.position !== 'undefined') { - await Util.setPosition( - this, - data.position, - false, - this.guild._sortedRoles(), - this.client.api.guilds(this.guild.id).roles, - reason, - ).then(updatedRoles => { - this.client.actions.GuildRolesPositionUpdate.handle({ - guild_id: this.guild.id, - roles: updatedRoles, - }); - }); - } - return this.client.api.guilds[this.guild.id].roles[this.id] - .patch({ - data: { - name: data.name || this.name, - color: data.color !== null ? Util.resolveColor(data.color || this.color) : null, - hoist: typeof data.hoist !== 'undefined' ? data.hoist : this.hoist, - permissions: data.permissions, - mentionable: typeof data.mentionable !== 'undefined' ? data.mentionable : this.mentionable, - }, - reason, - }) - .then(role => { - const clone = this._clone(); - clone._patch(role); - return clone; - }); + edit(data, reason) { + return this.guild.roles.edit(this, data, reason); } /** * Returns `channel.permissionsFor(role)`. Returns permissions for a role in a guild channel, * taking into account permission overwrites. - * @param {ChannelResolvable} channel The guild channel to use as context + * @param {GuildChannel|Snowflake} channel The guild channel to use as context * @returns {Readonly} */ permissionsIn(channel) { @@ -276,12 +264,12 @@ class Role extends Base { * @returns {Promise} * @example * // Set the permissions of the role - * role.setPermissions(['KICK_MEMBERS', 'BAN_MEMBERS']) + * role.setPermissions([Permissions.FLAGS.KICK_MEMBERS, Permissions.FLAGS.BAN_MEMBERS]) * .then(updated => console.log(`Updated permissions to ${updated.permissions.bitfield}`)) * .catch(console.error); * @example * // Remove all permissions from a role - * role.setPermissions(0) + * role.setPermissions(0n) * .then(updated => console.log(`Updated permissions to ${updated.permissions.bitfield}`)) * .catch(console.error); */ @@ -305,11 +293,16 @@ class Role extends Base { } /** - * Sets the position of the role. - * @param {number} position The position of the role - * @param {Object} [options] Options for setting position - * @param {boolean} [options.relative=false] Change the position relative to its current value - * @param {string} [options.reason] Reason for changing the position + * Options used to set position of a role. + * @typedef {Object} SetRolePositionOptions + * @property {boolean} [relative=false] Whether to change the position relative to its current value or not + * @property {string} [reason] The reason for changing the position + */ + + /** + * Sets the new position of the role. + * @param {number} position The new position for the role + * @param {SetRolePositionOptions} [options] Options for setting the position * @returns {Promise} * @example * // Set the position of the role @@ -401,3 +394,8 @@ class Role extends Base { } module.exports = Role; + +/** + * @external APIRole + * @see {@link https://discord.com/developers/docs/topics/permissions#role-object} + */ diff --git a/node_modules/discord.js/src/structures/StoreChannel.js b/node_modules/discord.js/src/structures/StoreChannel.js index 1c518a7f..26aea930 100644 --- a/node_modules/discord.js/src/structures/StoreChannel.js +++ b/node_modules/discord.js/src/structures/StoreChannel.js @@ -8,16 +8,16 @@ const GuildChannel = require('./GuildChannel'); */ class StoreChannel extends GuildChannel { /** - * @param {*} guild The guild the store channel is part of - * @param {*} data The data for the store channel + * @param {Guild} guild The guild the store channel is part of + * @param {APIChannel} data The data for the store channel + * @param {Client} [client] A safety parameter for the client that instantiated this */ - constructor(guild, data) { - super(guild, data); + constructor(guild, data, client) { + super(guild, data, client); /** * If the guild considers this channel NSFW * @type {boolean} - * @readonly */ this.nsfw = Boolean(data.nsfw); } @@ -25,7 +25,9 @@ class StoreChannel extends GuildChannel { _patch(data) { super._patch(data); - if (typeof data.nsfw !== 'undefined') this.nsfw = Boolean(data.nsfw); + if ('nsfw' in data) { + this.nsfw = Boolean(data.nsfw); + } } } diff --git a/node_modules/discord.js/src/structures/Team.js b/node_modules/discord.js/src/structures/Team.js index a28c5a23..9207478a 100644 --- a/node_modules/discord.js/src/structures/Team.js +++ b/node_modules/discord.js/src/structures/Team.js @@ -1,9 +1,9 @@ 'use strict'; +const { Collection } = require('@discordjs/collection'); const Base = require('./Base'); const TeamMember = require('./TeamMember'); -const Collection = require('../util/Collection'); -const Snowflake = require('../util/Snowflake'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); /** * Represents a Client OAuth2 Application Team. @@ -17,7 +17,7 @@ class Team extends Base { _patch(data) { /** - * The ID of the Team + * The Team's id * @type {Snowflake} */ this.id = data.id; @@ -32,13 +32,13 @@ class Team extends Base { * The Team's icon hash * @type {?string} */ - this.icon = data.icon || null; + this.icon = data.icon ?? null; /** * The Team's owner id - * @type {?string} + * @type {?Snowflake} */ - this.ownerID = data.owner_user_id || null; + this.ownerId = data.owner_user_id ?? null; /** * The Team's members @@ -58,7 +58,7 @@ class Team extends Base { * @readonly */ get owner() { - return this.members.get(this.ownerID) || null; + return this.members.get(this.ownerId) ?? null; } /** @@ -67,7 +67,7 @@ class Team extends Base { * @readonly */ get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; + return SnowflakeUtil.deconstruct(this.id).timestamp; } /** @@ -81,7 +81,7 @@ class Team extends Base { /** * A link to the teams's icon. - * @param {ImageURLOptions} [options={}] Options for the Image URL + * @param {StaticImageURLOptions} [options={}] Options for the Image URL * @returns {?string} URL to the icon */ iconURL({ format, size } = {}) { diff --git a/node_modules/discord.js/src/structures/TeamMember.js b/node_modules/discord.js/src/structures/TeamMember.js index ba7ecd26..52753fa6 100644 --- a/node_modules/discord.js/src/structures/TeamMember.js +++ b/node_modules/discord.js/src/structures/TeamMember.js @@ -29,7 +29,7 @@ class TeamMember extends Base { /** * The permissions this Team Member has with regard to the team - * @type {MembershipStates} + * @type {MembershipState} */ this.membershipState = MembershipStates[data.membership_state]; @@ -37,11 +37,11 @@ class TeamMember extends Base { * The user for this Team Member * @type {User} */ - this.user = this.client.users.add(data.user); + this.user = this.client.users._add(data.user); } /** - * The ID of the Team Member + * The Team Member's id * @type {Snowflake} * @readonly */ diff --git a/node_modules/discord.js/src/structures/TextChannel.js b/node_modules/discord.js/src/structures/TextChannel.js index b92e0c7e..f88060b2 100644 --- a/node_modules/discord.js/src/structures/TextChannel.js +++ b/node_modules/discord.js/src/structures/TextChannel.js @@ -1,10 +1,11 @@ 'use strict'; +const { Collection } = require('@discordjs/collection'); const GuildChannel = require('./GuildChannel'); const Webhook = require('./Webhook'); const TextBasedChannel = require('./interfaces/TextBasedChannel'); const MessageManager = require('../managers/MessageManager'); -const Collection = require('../util/Collection'); +const ThreadManager = require('../managers/ThreadManager'); const DataResolver = require('../util/DataResolver'); /** @@ -15,59 +16,96 @@ const DataResolver = require('../util/DataResolver'); class TextChannel extends GuildChannel { /** * @param {Guild} guild The guild the text channel is part of - * @param {Object} data The data for the text channel + * @param {APIChannel} data The data for the text channel + * @param {Client} [client] A safety parameter for the client that instantiated this */ - constructor(guild, data) { - super(guild, data); + constructor(guild, data, client) { + super(guild, data, client); /** * A manager of the messages sent to this channel * @type {MessageManager} */ this.messages = new MessageManager(this); + /** + * A manager of the threads belonging to this channel + * @type {ThreadManager} + */ + this.threads = new ThreadManager(this); + /** * If the guild considers this channel NSFW * @type {boolean} - * @readonly */ this.nsfw = Boolean(data.nsfw); - this._typing = new Map(); } _patch(data) { super._patch(data); - /** - * The topic of the text channel - * @type {?string} - */ - this.topic = data.topic; + if ('topic' in data) { + /** + * The topic of the text channel + * @type {?string} + */ + this.topic = data.topic; + } - if (typeof data.nsfw !== 'undefined') this.nsfw = Boolean(data.nsfw); + if ('nsfw' in data) { + this.nsfw = Boolean(data.nsfw); + } - /** - * The ID of the last message sent in this channel, if one was sent - * @type {?Snowflake} - */ - this.lastMessageID = data.last_message_id; + if ('last_message_id' in data) { + /** + * The last message id sent in the channel, if one was sent + * @type {?Snowflake} + */ + this.lastMessageId = data.last_message_id; + } - /** - * The ratelimit per user for this channel in seconds - * @type {number} - */ - this.rateLimitPerUser = data.rate_limit_per_user || 0; + if ('rate_limit_per_user' in data) { + /** + * The ratelimit per user for this channel in seconds + * It is not currently possible to set a rate limit per user on a `NewsChannel`. + * @type {number} + */ + this.rateLimitPerUser = data.rate_limit_per_user; + } - /** - * The timestamp when the last pinned message was pinned, if there was one - * @type {?number} - */ - this.lastPinTimestamp = data.last_pin_timestamp ? new Date(data.last_pin_timestamp).getTime() : null; + if ('last_pin_timestamp' in data) { + /** + * The timestamp when the last pinned message was pinned, if there was one + * @type {?number} + */ + this.lastPinTimestamp = data.last_pin_timestamp ? new Date(data.last_pin_timestamp).getTime() : null; + } - if (data.messages) for (const message of data.messages) this.messages.add(message); + if ('default_auto_archive_duration' in data) { + /** + * The default auto archive duration for newly created threads in this channel + * @type {?ThreadAutoArchiveDuration} + */ + this.defaultAutoArchiveDuration = data.default_auto_archive_duration; + } + + if ('messages' in data) { + for (const message of data.messages) this.messages._add(message); + } + } + + /** + * Sets the default auto archive duration for all newly created threads in this channel. + * @param {ThreadAutoArchiveDuration} defaultAutoArchiveDuration The new default auto archive duration + * @param {string} [reason] Reason for changing the channel's default auto archive duration + * @returns {Promise} + */ + setDefaultAutoArchiveDuration(defaultAutoArchiveDuration, reason) { + return this.edit({ defaultAutoArchiveDuration }, reason); } /** * Sets the rate limit per user for this channel. + * It is not currently possible to set the rate limit per user on a `NewsChannel`. * @param {number} rateLimitPerUser The new ratelimit in seconds * @param {string} [reason] Reason for changing the channel's ratelimits * @returns {Promise} @@ -86,6 +124,16 @@ class TextChannel extends GuildChannel { return this.edit({ nsfw }, reason); } + /** + * Sets the type of this channel (only conversion between text and news is supported) + * @param {string} type The new channel type + * @param {string} [reason] Reason for changing the channel's type + * @returns {Promise} + */ + setType(type, reason) { + return this.edit({ type }, reason); + } + /** * Fetches all webhooks for the channel. * @returns {Promise>} @@ -103,13 +151,18 @@ class TextChannel extends GuildChannel { }); } + /** + * Options used to create a {@link Webhook} for {@link TextChannel} and {@link NewsChannel}. + * @typedef {Object} ChannelWebhookCreateOptions + * @property {BufferResolvable|Base64Resolvable} [avatar] Avatar for the webhook + * @property {string} [reason] Reason for creating the webhook + */ + /** * Creates a webhook for the channel. * @param {string} name The name of the webhook - * @param {Object} [options] Options for creating the webhook - * @param {BufferResolvable|Base64Resolvable} [options.avatar] Avatar for the webhook - * @param {string} [options.reason] Reason for creating the webhook - * @returns {Promise} webhook The created webhook + * @param {ChannelWebhookCreateOptions} [options] Options for creating the webhook + * @returns {Promise} Returns the created Webhook * @example * // Create a webhook for the current channel * channel.createWebhook('Snek', { @@ -139,12 +192,11 @@ class TextChannel extends GuildChannel { get lastMessage() {} get lastPinAt() {} send() {} - startTyping() {} - stopTyping() {} - get typing() {} - get typingCount() {} + sendTyping() {} createMessageCollector() {} awaitMessages() {} + createMessageComponentCollector() {} + awaitMessageComponent() {} bulkDelete() {} } diff --git a/node_modules/discord.js/src/structures/User.js b/node_modules/discord.js/src/structures/User.js index d2766f1c..b7731e69 100644 --- a/node_modules/discord.js/src/structures/User.js +++ b/node_modules/discord.js/src/structures/User.js @@ -3,11 +3,9 @@ const Base = require('./Base'); const TextBasedChannel = require('./interfaces/TextBasedChannel'); const { Error } = require('../errors'); -const Snowflake = require('../util/Snowflake'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); const UserFlags = require('../util/UserFlags'); -let Structures; - /** * Represents a user on Discord. * @implements {TextBasedChannel} @@ -16,19 +14,21 @@ let Structures; class User extends Base { /** * @param {Client} client The instantiating client - * @param {Object} data The data for the user + * @param {APIUser} data The data for the user */ constructor(client, data) { super(client); /** - * The ID of the user + * The user's id * @type {Snowflake} */ this.id = data.id; + this.bot = null; + this.system = null; - this.locale = null; + this.flags = null; this._patch(data); @@ -45,12 +45,14 @@ class User extends Base { this.username = null; } - if ('bot' in data || typeof this.bot !== 'boolean') { + if ('bot' in data) { /** * Whether or not the user is a bot - * @type {boolean} + * @type {?boolean} */ this.bot = Boolean(data.bot); + } else if (!this.partial && typeof this.bot !== 'boolean') { + this.bot = false; } if ('discriminator' in data) { @@ -65,7 +67,7 @@ class User extends Base { if ('avatar' in data) { /** - * The ID of the user's avatar + * The user avatar's hash * @type {?string} */ this.avatar = data.avatar; @@ -79,14 +81,8 @@ class User extends Base { * @type {?boolean} */ this.system = Boolean(data.system); - } - - if ('locale' in data) { - /** - * The locale of the user's client (ISO 639-1) - * @type {?string} - */ - this.locale = data.locale; + } else if (!this.partial && typeof this.system !== 'boolean') { + this.system = false; } if ('public_flags' in data) { @@ -96,18 +92,6 @@ class User extends Base { */ this.flags = new UserFlags(data.public_flags); } - - /** - * The ID of the last message sent by the user, if one was sent - * @type {?Snowflake} - */ - this.lastMessageID = null; - - /** - * The ID of the channel for the last message sent by the user, if one was sent - * @type {?Snowflake} - */ - this.lastMessageChannelID = null; } /** @@ -125,7 +109,7 @@ class User extends Base { * @readonly */ get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; + return SnowflakeUtil.deconstruct(this.id).timestamp; } /** @@ -137,30 +121,6 @@ class User extends Base { return new Date(this.createdTimestamp); } - /** - * The Message object of the last message sent by the user, if one was sent - * @type {?Message} - * @readonly - */ - get lastMessage() { - const channel = this.client.channels.cache.get(this.lastMessageChannelID); - return (channel && channel.messages.cache.get(this.lastMessageID)) || null; - } - - /** - * The presence of this user - * @type {Presence} - * @readonly - */ - get presence() { - for (const guild of this.client.guilds.cache.values()) { - if (guild.presences.cache.has(this.id)) return guild.presences.cache.get(this.id); - } - if (!Structures) Structures = require('../util/Structures'); - const Presence = Structures.get('Presence'); - return new Presence(this.client, { user: { id: this.id } }); - } - /** * A link to the user's avatar. * @param {ImageURLOptions} [options={}] Options for the Image URL @@ -187,7 +147,7 @@ class User extends Base { * @returns {string} */ displayAvatarURL(options) { - return this.avatarURL(options) || this.defaultAvatarURL; + return this.avatarURL(options) ?? this.defaultAvatarURL; } /** @@ -199,43 +159,13 @@ class User extends Base { return typeof this.username === 'string' ? `${this.username}#${this.discriminator}` : null; } - /** - * Checks whether the user is typing in a channel. - * @param {ChannelResolvable} channel The channel to check in - * @returns {boolean} - */ - typingIn(channel) { - channel = this.client.channels.resolve(channel); - return channel._typing.has(this.id); - } - - /** - * Gets the time that the user started typing. - * @param {ChannelResolvable} channel The channel to get the time in - * @returns {?Date} - */ - typingSinceIn(channel) { - channel = this.client.channels.resolve(channel); - return channel._typing.has(this.id) ? new Date(channel._typing.get(this.id).since) : null; - } - - /** - * Gets the amount of time the user has been typing in a channel for (in milliseconds), or -1 if they're not typing. - * @param {ChannelResolvable} channel The channel to get the time in - * @returns {number} - */ - typingDurationIn(channel) { - channel = this.client.channels.resolve(channel); - return channel._typing.has(this.id) ? channel._typing.get(this.id).elapsedTime : -1; - } - /** * The DM between the client's user and this user * @type {?DMChannel} * @readonly */ get dmChannel() { - return this.client.channels.cache.find(c => c.type === 'dm' && c.recipient.id === this.id) || null; + return this.client.channels.cache.find(c => c.type === 'DM' && c.recipient.id === this.id) ?? null; } /** @@ -254,7 +184,7 @@ class User extends Base { recipient_id: this.id, }, }); - return this.client.actions.ChannelCreate.handle(data).channel; + return this.client.channels._add(data); } /** @@ -264,12 +194,13 @@ class User extends Base { async deleteDM() { const { dmChannel } = this; if (!dmChannel) throw new Error('USER_NO_DMCHANNEL'); - const data = await this.client.api.channels(dmChannel.id).delete(); - return this.client.actions.ChannelDelete.handle(data).channel; + await this.client.api.channels(dmChannel.id).delete(); + this.client.channels._remove(dmChannel.id); + return dmChannel; } /** - * Checks if the user is equal to another. It compares ID, username, discriminator, avatar, and bot flags. + * Checks if the user is equal to another. It compares id, username, discriminator, avatar, and bot flags. * It is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties. * @param {User} user User to compare with * @returns {boolean} @@ -287,7 +218,7 @@ class User extends Base { /** * Fetches this user's flags. - * @param {boolean} [force=false] Whether to skip the cache check and request the AP + * @param {boolean} [force=false] Whether to skip the cache check and request the API * @returns {Promise} */ async fetchFlags(force = false) { @@ -299,11 +230,11 @@ class User extends Base { /** * Fetches this user. - * @param {boolean} [force=false] Whether to skip the cache check and request the AP + * @param {boolean} [force=true] Whether to skip the cache check and request the API * @returns {Promise} */ - fetch(force = false) { - return this.client.users.fetch(this.id, true, force); + fetch(force = true) { + return this.client.users.fetch(this.id, { force }); } /** @@ -323,8 +254,6 @@ class User extends Base { createdTimestamp: true, defaultAvatarURL: true, tag: true, - lastMessage: false, - lastMessageID: false, }, ...props, ); @@ -341,3 +270,8 @@ class User extends Base { TextBasedChannel.applyToClass(User); module.exports = User; + +/** + * @external APIUser + * @see {@link https://discord.com/developers/docs/resources/user#user-object} + */ diff --git a/node_modules/discord.js/src/structures/VoiceChannel.js b/node_modules/discord.js/src/structures/VoiceChannel.js index 2b9eb9e1..58122c1b 100644 --- a/node_modules/discord.js/src/structures/VoiceChannel.js +++ b/node_modules/discord.js/src/structures/VoiceChannel.js @@ -1,55 +1,13 @@ 'use strict'; -const GuildChannel = require('./GuildChannel'); -const { Error } = require('../errors'); -const Collection = require('../util/Collection'); -const { browser } = require('../util/Constants'); +const BaseGuildVoiceChannel = require('./BaseGuildVoiceChannel'); const Permissions = require('../util/Permissions'); /** * Represents a guild voice channel on Discord. - * @extends {GuildChannel} + * @extends {BaseGuildVoiceChannel} */ -class VoiceChannel extends GuildChannel { - _patch(data) { - super._patch(data); - /** - * The bitrate of this voice channel - * @type {number} - */ - this.bitrate = data.bitrate; - - /** - * The maximum amount of users allowed in this channel - 0 means unlimited. - * @type {number} - */ - this.userLimit = data.user_limit; - } - - /** - * The members in this voice channel - * @type {Collection} - * @readonly - */ - get members() { - const coll = new Collection(); - for (const state of this.guild.voiceStates.cache.values()) { - if (state.channelID === this.id && state.member) { - coll.set(state.id, state.member); - } - } - return coll; - } - - /** - * Checks if the voice channel is full - * @type {boolean} - * @readonly - */ - get full() { - return this.userLimit > 0 && this.members.size >= this.userLimit; - } - +class VoiceChannel extends BaseGuildVoiceChannel { /** * Whether the channel is deletable by the client user * @type {boolean} @@ -74,9 +32,7 @@ class VoiceChannel extends GuildChannel { * @readonly */ get joinable() { - if (browser) return false; - if (!this.viewable) return false; - if (!this.permissionsFor(this.client.user).has(Permissions.FLAGS.CONNECT, false)) return false; + if (!super.joinable) return false; if (this.full && !this.permissionsFor(this.client.user).has(Permissions.FLAGS.MOVE_MEMBERS, false)) return false; return true; } @@ -121,30 +77,17 @@ class VoiceChannel extends GuildChannel { } /** - * Attempts to join this voice channel. - * @returns {Promise} + * Sets the RTC region of the channel. + * @name VoiceChannel#setRTCRegion + * @param {?string} region The new region of the channel. Set to `null` to remove a specific region for the channel + * @returns {Promise} * @example - * // Join a voice channel - * voiceChannel.join() - * .then(connection => console.log('Connected!')) - * .catch(console.error); - */ - join() { - if (browser) return Promise.reject(new Error('VOICE_NO_BROWSER')); - return this.client.voice.joinChannel(this); - } - - /** - * Leaves this voice channel. + * // Set the RTC region to europe + * voiceChannel.setRTCRegion('europe'); * @example - * // Leave a voice channel - * voiceChannel.leave(); + * // Remove a fixed region for this channel - let Discord decide automatically + * voiceChannel.setRTCRegion(null); */ - leave() { - if (browser) return; - const connection = this.client.voice.connections.get(this.guild.id); - if (connection && connection.channel.id === this.id) connection.disconnect(); - } } module.exports = VoiceChannel; diff --git a/node_modules/discord.js/src/structures/VoiceRegion.js b/node_modules/discord.js/src/structures/VoiceRegion.js index 9626195d..fe399b49 100644 --- a/node_modules/discord.js/src/structures/VoiceRegion.js +++ b/node_modules/discord.js/src/structures/VoiceRegion.js @@ -8,7 +8,7 @@ const Util = require('../util/Util'); class VoiceRegion { constructor(data) { /** - * The ID of the region + * The region's id * @type {string} */ this.id = data.id; diff --git a/node_modules/discord.js/src/structures/VoiceState.js b/node_modules/discord.js/src/structures/VoiceState.js index 731c7ef4..6cca9940 100644 --- a/node_modules/discord.js/src/structures/VoiceState.js +++ b/node_modules/discord.js/src/structures/VoiceState.js @@ -2,7 +2,6 @@ const Base = require('./Base'); const { Error, TypeError } = require('../errors'); -const { browser } = require('../util/Constants'); /** * Represents the voice state for a Guild Member. @@ -10,7 +9,7 @@ const { browser } = require('../util/Constants'); class VoiceState extends Base { /** * @param {Guild} guild The guild the voice state is part of - * @param {Object} data The data for the voice state + * @param {APIVoiceState} data The data for the voice state */ constructor(guild, data) { super(guild.client); @@ -20,7 +19,7 @@ class VoiceState extends Base { */ this.guild = guild; /** - * The ID of the member of this voice state + * The id of the member of this voice state * @type {Snowflake} */ this.id = data.user_id; @@ -32,42 +31,54 @@ class VoiceState extends Base { * Whether this member is deafened server-wide * @type {?boolean} */ - this.serverDeaf = 'deaf' in data ? data.deaf : null; + this.serverDeaf = data.deaf ?? null; /** * Whether this member is muted server-wide * @type {?boolean} */ - this.serverMute = 'mute' in data ? data.mute : null; + this.serverMute = data.mute ?? null; /** * Whether this member is self-deafened * @type {?boolean} */ - this.selfDeaf = 'self_deaf' in data ? data.self_deaf : null; + this.selfDeaf = data.self_deaf ?? null; /** * Whether this member is self-muted * @type {?boolean} */ - this.selfMute = 'self_mute' in data ? data.self_mute : null; + this.selfMute = data.self_mute ?? null; /** * Whether this member's camera is enabled * @type {?boolean} */ - this.selfVideo = 'self_video' in data ? data.self_video : null; + this.selfVideo = data.self_video ?? null; /** - * The session ID of this member's connection + * The session id for this member's connection * @type {?string} */ - this.sessionID = 'session_id' in data ? data.session_id : null; + this.sessionId = data.session_id ?? null; /** * Whether this member is streaming using "Go Live" * @type {boolean} */ - this.streaming = data.self_stream || false; + this.streaming = data.self_stream ?? false; /** - * The ID of the voice channel that this member is in + * The {@link VoiceChannel} or {@link StageChannel} id the member is in * @type {?Snowflake} */ - this.channelID = data.channel_id || null; + this.channelId = data.channel_id ?? null; + /** + * Whether this member is suppressed from speaking. This property is specific to stage channels only. + * @type {boolean} + */ + this.suppress = data.suppress; + /** + * The time at which the member requested to speak. This property is specific to stage channels only. + * @type {?number} + */ + this.requestToSpeakTimestamp = data.request_to_speak_timestamp + ? new Date(data.request_to_speak_timestamp).getTime() + : null; return this; } @@ -77,26 +88,16 @@ class VoiceState extends Base { * @readonly */ get member() { - return this.guild.members.cache.get(this.id) || null; + return this.guild.members.cache.get(this.id) ?? null; } /** * The channel that the member is connected to - * @type {?VoiceChannel} + * @type {?(VoiceChannel|StageChannel)} * @readonly */ get channel() { - return this.guild.channels.cache.get(this.channelID) || null; - } - - /** - * If this is a voice state of the client user, then this will refer to the active VoiceConnection for this guild - * @type {?VoiceConnection} - * @readonly - */ - get connection() { - if (browser || this.id !== this.client.user.id) return null; - return this.client.voice.connections.get(this.guild.id) || null; + return this.guild.channels.cache.get(this.channelId) ?? null; } /** @@ -117,16 +118,6 @@ class VoiceState extends Base { return this.serverMute || this.selfMute; } - /** - * Whether this member is currently speaking. A boolean if the information is available (aka - * the bot is connected to any voice channel in the guild), otherwise this is null - * @type {?boolean} - * @readonly - */ - get speaking() { - return this.channel && this.channel.connection ? Boolean(this.channel.connection._speaking.get(this.id)) : null; - } - /** * Mutes/unmutes the member of this voice state. * @param {boolean} mute Whether or not the member should be muted @@ -134,7 +125,7 @@ class VoiceState extends Base { * @returns {Promise} */ setMute(mute, reason) { - return this.member ? this.member.edit({ mute }, reason) : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); + return this.member?.edit({ mute }, reason) ?? Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); } /** @@ -144,57 +135,84 @@ class VoiceState extends Base { * @returns {Promise} */ setDeaf(deaf, reason) { - return this.member ? this.member.edit({ deaf }, reason) : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); + return this.member?.edit({ deaf }, reason) ?? Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); } /** - * Kicks the member from the voice channel. - * @param {string} [reason] Reason for kicking member from the channel + * Disconnects the member from the channel. + * @param {string} [reason] Reason for disconnecting the member from the channel * @returns {Promise} */ - kick(reason) { + disconnect(reason) { return this.setChannel(null, reason); } /** * Moves the member to a different channel, or disconnects them from the one they're in. - * @param {ChannelResolvable|null} [channel] Channel to move the member to, or `null` if you want to disconnect them - * from voice. + * @param {VoiceChannelResolvable|null} channel Channel to move the member to, or `null` if you want to disconnect + * them from voice. * @param {string} [reason] Reason for moving member to another channel or disconnecting * @returns {Promise} */ setChannel(channel, reason) { - return this.member - ? this.member.edit({ channel }, reason) - : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); + return this.member?.edit({ channel }, reason) ?? Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); } /** - * Self-mutes/unmutes the bot for this voice state. - * @param {boolean} mute Whether or not the bot should be self-muted - * @returns {Promise} true if the voice state was successfully updated, otherwise false + * Toggles the request to speak in the channel. + * Only applicable for stage channels and for the client's own voice state. + * @param {boolean} request Whether or not the client is requesting to become a speaker. + * @example + * // Making the client request to speak in a stage channel (raise its hand) + * guild.me.voice.setRequestToSpeak(true); + * @example + * // Making the client cancel a request to speak + * guild.me.voice.setRequestToSpeak(false); + * @returns {Promise} */ - async setSelfMute(mute) { - if (this.id !== this.client.user.id) throw new Error('VOICE_STATE_NOT_OWN'); - if (typeof mute !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'mute'); - if (!this.connection) return false; - this.selfMute = mute; - await this.connection.sendVoiceStateUpdate(); - return true; + async setRequestToSpeak(request) { + if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL'); + + if (this.client.user.id !== this.id) throw new Error('VOICE_STATE_NOT_OWN'); + + await this.client.api.guilds(this.guild.id, 'voice-states', '@me').patch({ + data: { + channel_id: this.channelId, + request_to_speak_timestamp: request ? new Date().toISOString() : null, + }, + }); } /** - * Self-deafens/undeafens the bot for this voice state. - * @param {boolean} deaf Whether or not the bot should be self-deafened - * @returns {Promise} true if the voice state was successfully updated, otherwise false + * Suppress/unsuppress the user. Only applicable for stage channels. + * @param {boolean} suppressed - Whether or not the user should be suppressed. + * @example + * // Making the client a speaker + * guild.me.voice.setSuppressed(false); + * @example + * // Making the client an audience member + * guild.me.voice.setSuppressed(true); + * @example + * // Inviting another user to speak + * voiceState.setSuppressed(false); + * @example + * // Moving another user to the audience, or cancelling their invite to speak + * voiceState.setSuppressed(true); + * @returns {Promise} */ - async setSelfDeaf(deaf) { - if (this.id !== this.client.user.id) return new Error('VOICE_STATE_NOT_OWN'); - if (typeof deaf !== 'boolean') return new TypeError('VOICE_STATE_INVALID_TYPE', 'deaf'); - if (!this.connection) return false; - this.selfDeaf = deaf; - await this.connection.sendVoiceStateUpdate(); - return true; + async setSuppressed(suppressed) { + if (typeof suppressed !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'suppressed'); + + if (this.channel?.type !== 'GUILD_STAGE_VOICE') throw new Error('VOICE_NOT_STAGE_CHANNEL'); + + const target = this.client.user.id === this.id ? '@me' : this.id; + + await this.client.api.guilds(this.guild.id, 'voice-states', target).patch({ + data: { + channel_id: this.channelId, + suppress: suppressed, + }, + }); } toJSON() { @@ -204,10 +222,15 @@ class VoiceState extends Base { serverMute: true, selfDeaf: true, selfMute: true, - sessionID: true, - channelID: 'channel', + sessionId: true, + channelId: 'channel', }); } } module.exports = VoiceState; + +/** + * @external APIVoiceState + * @see {@link https://discord.com/developers/docs/resources/voice#voice-state-object} + */ diff --git a/node_modules/discord.js/src/structures/Webhook.js b/node_modules/discord.js/src/structures/Webhook.js index d0cf7c6e..61960bcd 100644 --- a/node_modules/discord.js/src/structures/Webhook.js +++ b/node_modules/discord.js/src/structures/Webhook.js @@ -1,10 +1,10 @@ 'use strict'; -const APIMessage = require('./APIMessage'); -const Channel = require('./Channel'); +const MessagePayload = require('./MessagePayload'); +const { Error } = require('../errors'); const { WebhookTypes } = require('../util/Constants'); const DataResolver = require('../util/DataResolver'); -const Snowflake = require('../util/Snowflake'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); /** * Represents a webhook. @@ -29,11 +29,11 @@ class Webhook { this.name = data.name; /** - * The token for the webhook + * The token for the webhook, unavailable for follower webhooks and webhooks owned by another application. * @name Webhook#token * @type {?string} */ - Object.defineProperty(this, 'token', { value: data.token || null, writable: true, configurable: true }); + Object.defineProperty(this, 'token', { value: data.token ?? null, writable: true, configurable: true }); /** * The avatar for the webhook @@ -42,14 +42,14 @@ class Webhook { this.avatar = data.avatar; /** - * The ID of the webhook + * The webhook's id * @type {Snowflake} */ this.id = data.id; /** * The type of the webhook - * @type {WebhookTypes} + * @type {WebhookType} */ this.type = WebhookTypes[data.type]; @@ -57,54 +57,70 @@ class Webhook { * The guild the webhook belongs to * @type {Snowflake} */ - this.guildID = data.guild_id; + this.guildId = data.guild_id; /** * The channel the webhook belongs to * @type {Snowflake} */ - this.channelID = data.channel_id; - - if (data.user) { - /** - * The owner of the webhook - * @type {?User|Object} - */ - this.owner = this.client.users ? this.client.users.cache.get(data.user.id) : data.user; - } else { - this.owner = null; - } + this.channelId = data.channel_id; + + /** + * The owner of the webhook + * @type {?(User|APIUser)} + */ + this.owner = data.user ? this.client.users?._add(data.user) ?? data.user : null; + + /** + * The source guild of the webhook + * @type {?(Guild|APIGuild)} + */ + this.sourceGuild = data.source_guild + ? this.client.guilds?._add(data.source_guild, false) ?? data.source_guild + : null; + + /** + * The source channel of the webhook + * @type {?(Channel|APIChannel)} + */ + this.sourceChannel = this.client.channels?.resolve(data.source_channel?.id) ?? data.source_channel ?? null; } /** * Options that can be passed into send. - * @typedef {Object} WebhookMessageOptions + * @typedef {BaseMessageOptions} WebhookMessageOptions * @property {string} [username=this.name] Username override for the message * @property {string} [avatarURL] Avatar URL override for the message - * @property {boolean} [tts=false] Whether or not the message should be spoken aloud - * @property {string} [nonce=''] The nonce for the message - * @property {Object[]} [embeds] An array of embeds for the message - * @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content - * (see [here](https://discord.com/developers/docs/resources/channel#embed-object) for more details) - * @property {DisableMentionType} [disableMentions=this.client.options.disableMentions] Whether or not all mentions or - * everyone/here mentions should be sanitized to prevent unexpected mentions - * @property {FileOptions[]|string[]} [files] Files to send with the message - * @property {string|boolean} [code] Language for optional codeblock formatting to apply - * @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if - * it exceeds the character limit. If an object is provided, these are the options for splitting the message. + * @property {Snowflake} [threadId] The id of the thread in the channel to send to. + * For interaction webhooks, this property is ignored + */ + + /** + * Options that can be passed into editMessage. + * @typedef {Object} WebhookEditMessageOptions + * @property {MessageEmbed[]|APIEmbed[]} [embeds] See {@link WebhookMessageOptions#embeds} + * @property {string} [content] See {@link BaseMessageOptions#content} + * @property {FileOptions[]|BufferResolvable[]|MessageAttachment[]} [files] See {@link BaseMessageOptions#files} + * @property {MessageMentionOptions} [allowedMentions] See {@link BaseMessageOptions#allowedMentions} + * @property {MessageActionRow[]|MessageActionRowOptions[]} [components] + * Action rows containing interactive components for the message (buttons, select menus) */ /** * Sends a message with this webhook. - * @param {StringResolvable|APIMessage} [content=''] The content to send - * @param {WebhookMessageOptions|MessageAdditions} [options={}] The options to provide - * @returns {Promise} + * @param {string|MessagePayload|WebhookMessageOptions} options The options to provide + * @returns {Promise} * @example * // Send a basic message * webhook.send('hello!') * .then(message => console.log(`Sent message: ${message.content}`)) * .catch(console.error); * @example + * // Send a basic message in a thread + * webhook.send({ content: 'hello!', threadId: '836856309672348295' }) + * .then(message => console.log(`Sent message: ${message.content}`)) + * .catch(console.error); + * @example * // Send a remote file * webhook.send({ * files: ['https://cdn.discordapp.com/icons/222078108977594368/6e1019b3179d71046e463a75915e7244.png?size=2048'] @@ -123,7 +139,8 @@ class Webhook { * .catch(console.error); * @example * // Send an embed with a local image inside - * webhook.send('This is an embed', { + * webhook.send({ + * content: 'This is an embed', * embeds: [{ * thumbnail: { * url: 'attachment://file.jpg' @@ -137,32 +154,27 @@ class Webhook { * .then(console.log) * .catch(console.error); */ - async send(content, options) { - let apiMessage; + async send(options) { + if (!this.token) throw new Error('WEBHOOK_TOKEN_UNAVAILABLE'); - if (content instanceof APIMessage) { - apiMessage = content.resolveData(); + let messagePayload; + + if (options instanceof MessagePayload) { + messagePayload = options.resolveData(); } else { - apiMessage = APIMessage.create(this, content, options).resolveData(); - if (Array.isArray(apiMessage.data.content)) { - return Promise.all(apiMessage.split().map(this.send.bind(this))); - } + messagePayload = MessagePayload.create(this, options).resolveData(); } - const { data, files } = await apiMessage.resolveFiles(); + const { data, files } = await messagePayload.resolveFiles(); return this.client.api .webhooks(this.id, this.token) .post({ data, files, - query: { wait: true }, + query: { thread_id: messagePayload.options.threadId, wait: true }, auth: false, }) - .then(d => { - const channel = this.client.channels ? this.client.channels.cache.get(d.channel_id) : undefined; - if (!channel) return d; - return channel.messages.add(d, false); - }); + .then(d => this.client.channels?.cache.get(d.channel_id)?.messages._add(d, false) ?? d); } /** @@ -181,8 +193,11 @@ class Webhook { * 'ts': Date.now() / 1000 * }] * }).catch(console.error); + * @see {@link https://api.slack.com/messaging/webhooks} */ sendSlackMessage(body) { + if (!this.token) throw new Error('WEBHOOK_TOKEN_UNAVAILABLE'); + return this.client.api .webhooks(this.id, this.token) .slack.post({ @@ -194,19 +209,24 @@ class Webhook { } /** - * Edits the webhook. - * @param {Object} options Options - * @param {string} [options.name=this.name] New name for this webhook - * @param {BufferResolvable} [options.avatar] New avatar for this webhook - * @param {ChannelResolvable} [options.channel] New channel for this webhook - * @param {string} [reason] Reason for editing this webhook + * Options used to edit a {@link Webhook}. + * @typedef {Object} WebhookEditData + * @property {string} [name=this.name] The new name for the webhook + * @property {BufferResolvable} [avatar] The new avatar for the webhook + * @property {GuildTextChannelResolvable} [channel] The new channel for the webhook + */ + + /** + * Edits this webhook. + * @param {WebhookEditData} options Options for editing the webhook + * @param {string} [reason] Reason for editing the webhook * @returns {Promise} */ async edit({ name = this.name, avatar, channel }, reason) { - if (avatar && typeof avatar === 'string' && !avatar.startsWith('data:')) { + if (avatar && !(typeof avatar === 'string' && avatar.startsWith('data:'))) { avatar = await DataResolver.resolveImage(avatar); } - if (channel) channel = channel instanceof Channel ? channel.id : channel; + if (channel) channel = channel?.id ?? channel; const data = await this.client.api.webhooks(this.id, channel ? undefined : this.token).patch({ data: { name, avatar, channel_id: channel }, reason, @@ -214,25 +234,87 @@ class Webhook { this.name = data.name; this.avatar = data.avatar; - this.channelID = data.channel_id; + this.channelId = data.channel_id; return this; } + /** + * Gets a message that was sent by this webhook. + * @param {Snowflake|'@original'} message The id of the message to fetch + * @param {boolean} [cache=true] Whether to cache the message + * @returns {Promise} Returns the raw message data if the webhook was instantiated as a + * {@link WebhookClient} or if the channel is uncached, otherwise a {@link Message} will be returned + */ + async fetchMessage(message, cache = true) { + if (!this.token) throw new Error('WEBHOOK_TOKEN_UNAVAILABLE'); + + const data = await this.client.api.webhooks(this.id, this.token).messages(message).get(); + return this.client.channels?.cache.get(data.channel_id)?.messages._add(data, cache) ?? data; + } + + /** + * Edits a message that was sent by this webhook. + * @param {MessageResolvable|'@original'} message The message to edit + * @param {string|MessagePayload|WebhookEditMessageOptions} options The options to provide + * @returns {Promise} Returns the raw message data if the webhook was instantiated as a + * {@link WebhookClient} or if the channel is uncached, otherwise a {@link Message} will be returned + */ + async editMessage(message, options) { + if (!this.token) throw new Error('WEBHOOK_TOKEN_UNAVAILABLE'); + + let messagePayload; + + if (options instanceof MessagePayload) messagePayload = options; + else messagePayload = MessagePayload.create(this, options); + + const { data, files } = await messagePayload.resolveData().resolveFiles(); + + const d = await this.client.api + .webhooks(this.id, this.token) + .messages(typeof message === 'string' ? message : message.id) + .patch({ data, files }); + + const messageManager = this.client.channels?.cache.get(d.channel_id)?.messages; + if (!messageManager) return d; + + const existing = messageManager.cache.get(d.id); + if (!existing) return messageManager._add(d); + + const clone = existing._clone(); + clone._patch(d); + return clone; + } + /** * Deletes the webhook. * @param {string} [reason] Reason for deleting this webhook - * @returns {Promise} + * @returns {Promise} + */ + async delete(reason) { + await this.client.api.webhooks(this.id, this.token).delete({ reason }); + } + + /** + * Delete a message that was sent by this webhook. + * @param {MessageResolvable|'@original'} message The message to delete + * @returns {Promise} */ - delete(reason) { - return this.client.api.webhooks(this.id, this.token).delete({ reason }); + async deleteMessage(message) { + if (!this.token) throw new Error('WEBHOOK_TOKEN_UNAVAILABLE'); + + await this.client.api + .webhooks(this.id, this.token) + .messages(typeof message === 'string' ? message : message.id) + .delete(); } + /** * The timestamp the webhook was created at * @type {number} * @readonly */ get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; + return SnowflakeUtil.deconstruct(this.id).timestamp; } /** @@ -255,7 +337,7 @@ class Webhook { /** * A link to the webhook's avatar. - * @param {ImageURLOptions} [options={}] Options for the Image URL + * @param {StaticImageURLOptions} [options={}] Options for the Image URL * @returns {?string} */ avatarURL({ format, size } = {}) { @@ -263,8 +345,20 @@ class Webhook { return this.client.rest.cdn.Avatar(this.id, this.avatar, format, size); } - static applyToClass(structure) { - for (const prop of ['send', 'sendSlackMessage', 'edit', 'delete', 'createdTimestamp', 'createdAt', 'url']) { + static applyToClass(structure, ignore = []) { + for (const prop of [ + 'send', + 'sendSlackMessage', + 'fetchMessage', + 'edit', + 'editMessage', + 'delete', + 'deleteMessage', + 'createdTimestamp', + 'createdAt', + 'url', + ]) { + if (ignore.includes(prop)) continue; Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(Webhook.prototype, prop)); } } diff --git a/node_modules/discord.js/src/structures/interfaces/Application.js b/node_modules/discord.js/src/structures/interfaces/Application.js index 9781bfa7..4518d63a 100644 --- a/node_modules/discord.js/src/structures/interfaces/Application.js +++ b/node_modules/discord.js/src/structures/interfaces/Application.js @@ -1,7 +1,7 @@ 'use strict'; const { ClientApplicationAssetTypes, Endpoints } = require('../../util/Constants'); -const Snowflake = require('../../util/Snowflake'); +const SnowflakeUtil = require('../../util/SnowflakeUtil'); const Base = require('../Base'); const AssetTypes = Object.keys(ClientApplicationAssetTypes); @@ -18,41 +18,41 @@ class Application extends Base { _patch(data) { /** - * The ID of the app + * The application's id * @type {Snowflake} */ this.id = data.id; /** - * The name of the app - * @type {string} + * The name of the application + * @type {?string} */ - this.name = data.name; + this.name = data.name ?? this.name ?? null; /** - * The app's description - * @type {string} + * The application's description + * @type {?string} */ - this.description = data.description; + this.description = data.description ?? this.description ?? null; /** - * The app's icon hash - * @type {string} + * The application's icon hash + * @type {?string} */ - this.icon = data.icon; + this.icon = data.icon ?? this.icon ?? null; } /** - * The timestamp the app was created at + * The timestamp the application was created at * @type {number} * @readonly */ get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; + return SnowflakeUtil.deconstruct(this.id).timestamp; } /** - * The time the app was created at + * The time the application was created at * @type {Date} * @readonly */ @@ -62,7 +62,7 @@ class Application extends Base { /** * A link to the application's icon. - * @param {ImageURLOptions} [options={}] Options for the Image URL + * @param {StaticImageURLOptions} [options={}] Options for the Image URL * @returns {?string} URL to the icon */ iconURL({ format, size } = {}) { @@ -72,10 +72,10 @@ class Application extends Base { /** * A link to this application's cover image. - * @param {ImageURLOptions} [options={}] Options for the Image URL + * @param {StaticImageURLOptions} [options={}] Options for the Image URL * @returns {?string} URL to the cover image */ - coverImage({ format, size } = {}) { + coverURL({ format, size } = {}) { if (!this.cover) return null; return Endpoints.CDN(this.client.options.http.cdn).AppIcon(this.id, this.cover, { format, size }); } @@ -83,13 +83,13 @@ class Application extends Base { /** * Asset data. * @typedef {Object} ApplicationAsset - * @property {Snowflake} id The asset ID - * @property {string} name The asset name - * @property {string} type The asset type + * @property {Snowflake} id The asset's id + * @property {string} name The asset's name + * @property {string} type The asset's type */ /** - * Gets the clients rich presence assets. + * Gets the application's rich presence assets. * @returns {Promise>} */ fetchAssets() { @@ -108,7 +108,7 @@ class Application extends Base { /** * When concatenated with a string, this automatically returns the application's name instead of the * Oauth2Application object. - * @returns {string} + * @returns {?string} * @example * // Logs: Application name: My App * console.log(`Application name: ${application}`); diff --git a/node_modules/discord.js/src/structures/interfaces/Collector.js b/node_modules/discord.js/src/structures/interfaces/Collector.js index 969b3d2c..4742227c 100644 --- a/node_modules/discord.js/src/structures/interfaces/Collector.js +++ b/node_modules/discord.js/src/structures/interfaces/Collector.js @@ -1,7 +1,8 @@ 'use strict'; const EventEmitter = require('events'); -const Collection = require('../../util/Collection'); +const { Collection } = require('@discordjs/collection'); +const { TypeError } = require('../../errors'); const Util = require('../../util/Util'); /** @@ -15,6 +16,7 @@ const Util = require('../../util/Util'); /** * Options to be applied to the collector. * @typedef {Object} CollectorOptions + * @property {CollectorFilter} [filter] The filter applied to this collector * @property {number} [time] How long to run the collector for in milliseconds * @property {number} [idle] How long to stop the collector after inactivity in milliseconds * @property {boolean} [dispose=false] Whether to dispose data when it's deleted @@ -25,7 +27,7 @@ const Util = require('../../util/Util'); * @abstract */ class Collector extends EventEmitter { - constructor(client, filter, options = {}) { + constructor(client, options = {}) { super(); /** @@ -39,8 +41,9 @@ class Collector extends EventEmitter { /** * The filter applied to this collector * @type {CollectorFilter} + * @returns {boolean|Promise} */ - this.filter = filter; + this.filter = options.filter ?? (() => true); /** * The options of this collector @@ -74,20 +77,25 @@ class Collector extends EventEmitter { */ this._idletimeout = null; + if (typeof this.filter !== 'function') { + throw new TypeError('INVALID_TYPE', 'options.filter', 'function'); + } + this.handleCollect = this.handleCollect.bind(this); this.handleDispose = this.handleDispose.bind(this); - if (options.time) this._timeout = this.client.setTimeout(() => this.stop('time'), options.time); - if (options.idle) this._idletimeout = this.client.setTimeout(() => this.stop('idle'), options.idle); + if (options.time) this._timeout = setTimeout(() => this.stop('time'), options.time).unref(); + if (options.idle) this._idletimeout = setTimeout(() => this.stop('idle'), options.idle).unref(); } /** * Call this to handle an event as a collectable element. Accepts any event data as parameters. * @param {...*} args The arguments emitted by the listener + * @returns {Promise} * @emits Collector#collect */ async handleCollect(...args) { - const collect = this.collect(...args); + const collect = await this.collect(...args); if (collect && (await this.filter(...args, this.collected))) { this.collected.set(collect, args[0]); @@ -100,8 +108,8 @@ class Collector extends EventEmitter { this.emit('collect', ...args); if (this._idletimeout) { - this.client.clearTimeout(this._idletimeout); - this._idletimeout = this.client.setTimeout(() => this.stop('idle'), this.options.idle); + clearTimeout(this._idletimeout); + this._idletimeout = setTimeout(() => this.stop('idle'), this.options.idle).unref(); } } this.checkEnd(); @@ -110,13 +118,14 @@ class Collector extends EventEmitter { /** * Call this to remove an element from the collection. Accepts any event data as parameters. * @param {...*} args The arguments emitted by the listener + * @returns {Promise} * @emits Collector#dispose */ - handleDispose(...args) { + async handleDispose(...args) { if (!this.options.dispose) return; const dispose = this.dispose(...args); - if (!dispose || !this.filter(...args) || !this.collected.has(dispose)) return; + if (!dispose || !(await this.filter(...args)) || !this.collected.has(dispose)) return; this.collected.delete(dispose); /** @@ -170,11 +179,11 @@ class Collector extends EventEmitter { if (this.ended) return; if (this._timeout) { - this.client.clearTimeout(this._timeout); + clearTimeout(this._timeout); this._timeout = null; } if (this._idletimeout) { - this.client.clearTimeout(this._idletimeout); + clearTimeout(this._idletimeout); this._idletimeout = null; } this.ended = true; @@ -189,19 +198,25 @@ class Collector extends EventEmitter { } /** - * Resets the collectors timeout and idle timer. - * @param {Object} [options] Options - * @param {number} [options.time] How long to run the collector for in milliseconds - * @param {number} [options.idle] How long to stop the collector after inactivity in milliseconds + * Options used to reset timeout and idle timer of a {@link Collector}. + * @typedef {Object} CollectorResetTimerOptions + * @property {number} [time] How long to run the collector for (in milliseconds) + * @property {number} [idle] How long to wait to stop the collector after inactivity (in milliseconds) + */ + + /** + * Resets the collector's timeout and idle timer. + * @param {CollectorResetTimerOptions} [options] Options for reseting + */ resetTimer({ time, idle } = {}) { if (this._timeout) { - this.client.clearTimeout(this._timeout); - this._timeout = this.client.setTimeout(() => this.stop('time'), time || this.options.time); + clearTimeout(this._timeout); + this._timeout = setTimeout(() => this.stop('time'), time ?? this.options.time).unref(); } if (this._idletimeout) { - this.client.clearTimeout(this._idletimeout); - this._idletimeout = this.client.setTimeout(() => this.stop('idle'), idle || this.options.idle); + clearTimeout(this._idletimeout); + this._idletimeout = setTimeout(() => this.stop('idle'), idle ?? this.options.idle).unref(); } } @@ -209,7 +224,7 @@ class Collector extends EventEmitter { * Checks whether the collector should end, and if so, ends it. */ checkEnd() { - const reason = this.endReason(); + const reason = this.endReason; if (reason) this.stop(reason); } @@ -248,13 +263,21 @@ class Collector extends EventEmitter { return Util.flatten(this); } - /* eslint-disable no-empty-function, valid-jsdoc */ + /* eslint-disable no-empty-function */ + /** + * The reason this collector has ended with, or null if it hasn't ended yet + * @type {?string} + * @readonly + * @abstract + */ + get endReason() {} + /** * Handles incoming events from the `handleCollect` function. Returns null if the event should not * be collected, or returns an object describing the data that should be stored. * @see Collector#handleCollect * @param {...*} args Any args the event listener emits - * @returns {?{key, value}} Data to insert into collection, if any + * @returns {?(*|Promise)} Data to insert into collection, if any * @abstract */ collect() {} @@ -268,14 +291,7 @@ class Collector extends EventEmitter { * @abstract */ dispose() {} - - /** - * The reason this collector has ended or will end with. - * @returns {?string} Reason to end the collector, if any - * @abstract - */ - endReason() {} - /* eslint-enable no-empty-function, valid-jsdoc */ + /* eslint-enable no-empty-function */ } module.exports = Collector; diff --git a/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js b/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js index f5269e97..de4d2bc2 100644 --- a/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js +++ b/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js @@ -2,10 +2,12 @@ /* eslint-disable import/order */ const MessageCollector = require('../MessageCollector'); -const APIMessage = require('../APIMessage'); -const Snowflake = require('../../util/Snowflake'); -const Collection = require('../../util/Collection'); -const { RangeError, TypeError } = require('../../errors'); +const MessagePayload = require('../MessagePayload'); +const SnowflakeUtil = require('../../util/SnowflakeUtil'); +const { Collection } = require('@discordjs/collection'); +const { InteractionTypes } = require('../../util/Constants'); +const { TypeError, Error } = require('../../errors'); +const InteractionCollector = require('../InteractionCollector'); /** * Interface for classes that have text-channel-like features. @@ -20,10 +22,10 @@ class TextBasedChannel { this.messages = new MessageManager(this); /** - * The ID of the last message in the channel, if one was sent + * The channel's last message id, if one was sent * @type {?Snowflake} */ - this.lastMessageID = null; + this.lastMessageId = null; /** * The timestamp when the last pinned message was pinned, if there was one @@ -38,7 +40,7 @@ class TextBasedChannel { * @readonly */ get lastMessage() { - return this.messages.cache.get(this.lastMessageID) || null; + return this.messages.resolve(this.lastMessageId); } /** @@ -51,21 +53,25 @@ class TextBasedChannel { } /** - * Options provided when sending or editing a message. - * @typedef {Object} MessageOptions + * Base options provided when sending. + * @typedef {Object} BaseMessageOptions * @property {boolean} [tts=false] Whether or not the message should be spoken aloud * @property {string} [nonce=''] The nonce for the message * @property {string} [content=''] The content for the message - * @property {MessageEmbed|Object} [embed] An embed for the message + * @property {MessageEmbed[]|APIEmbed[]} [embeds] The embeds for the message * (see [here](https://discord.com/developers/docs/resources/channel#embed-object) for more details) * @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content - * @property {DisableMentionType} [disableMentions=this.client.options.disableMentions] Whether or not all mentions or - * everyone/here mentions should be sanitized to prevent unexpected mentions - * @property {FileOptions[]|BufferResolvable[]} [files] Files to send with the message - * @property {string|boolean} [code] Language for optional codeblock formatting to apply - * @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if - * it exceeds the character limit. If an object is provided, these are the options for splitting the message - * @property {UserResolvable} [reply] User to reply to (prefixes the message with a mention, except in DMs) + * (see [here](https://discord.com/developers/docs/resources/channel#allowed-mentions-object) for more details) + * @property {FileOptions[]|BufferResolvable[]|MessageAttachment[]} [files] Files to send with the message + * @property {MessageActionRow[]|MessageActionRowOptions[]} [components] + * Action rows containing interactive components for the message (buttons, select menus) + * @property {StickerResolvable[]} [stickers=[]] Stickers to send in the message + */ + + /** + * Options provided when sending or editing a message. + * @typedef {BaseMessageOptions} MessageOptions + * @property {ReplyOptions} [reply] The options for replying to a message */ /** @@ -74,6 +80,7 @@ class TextBasedChannel { * @property {MessageMentionTypes[]} [parse] Types of mentions to be parsed * @property {Snowflake[]} [users] Snowflakes of Users to be parsed as mentions * @property {Snowflake[]} [roles] Snowflakes of Roles to be parsed as mentions + * @property {boolean} [repliedUser=true] Whether the author of the Message being replied to should be pinged */ /** @@ -84,14 +91,6 @@ class TextBasedChannel { * @typedef {string} MessageMentionTypes */ - /** - * The type of mentions to disable. - * - `none` - * - `all` - * - `everyone` - * @typedef {string} DisableMentionType - */ - /** * @typedef {Object} FileOptions * @property {BufferResolvable} attachment File to attach @@ -99,19 +98,17 @@ class TextBasedChannel { */ /** - * Options for splitting a message. - * @typedef {Object} SplitOptions - * @property {number} [maxLength=2000] Maximum character length per message piece - * @property {string} [char='\n'] Character to split the message with - * @property {string} [prepend=''] Text to prepend to every piece except the first - * @property {string} [append=''] Text to append to every piece except the last + * Options for sending a message with a reply. + * @typedef {Object} ReplyOptions + * @param {MessageResolvable} messageReference The message to reply to (must be in the same channel and not system) + * @param {boolean} [failIfNotExists=true] Whether to error if the referenced message + * does not exist (creates a standard message in this case when false) */ /** * Sends a message to this channel. - * @param {StringResolvable|APIMessage} [content=''] The content to send - * @param {MessageOptions|MessageAdditions} [options={}] The options to provide - * @returns {Promise} + * @param {string|MessagePayload|MessageOptions} options The options to provide + * @returns {Promise} * @example * // Send a basic message * channel.send('hello!') @@ -136,145 +133,75 @@ class TextBasedChannel { * .catch(console.error); * @example * // Send an embed with a local image inside - * channel.send('This is an embed', { - * embed: { - * thumbnail: { - * url: 'attachment://file.jpg' + * channel.send({ + * content: 'This is an embed', + * embeds: [ + * { + * thumbnail: { + * url: 'attachment://file.jpg' * } - * }, - * files: [{ - * attachment: 'entire/path/to/file.jpg', - * name: 'file.jpg' - * }] + * } + * ], + * files: [{ + * attachment: 'entire/path/to/file.jpg', + * name: 'file.jpg' + * }] * }) * .then(console.log) * .catch(console.error); */ - async send(content, options) { + async send(options) { const User = require('../User'); const GuildMember = require('../GuildMember'); if (this instanceof User || this instanceof GuildMember) { - return this.createDM().then(dm => dm.send(content, options)); + return this.createDM().then(dm => dm.send(options)); } - let apiMessage; + let messagePayload; - if (content instanceof APIMessage) { - apiMessage = content.resolveData(); + if (options instanceof MessagePayload) { + messagePayload = options.resolveData(); } else { - apiMessage = APIMessage.create(this, content, options).resolveData(); - if (Array.isArray(apiMessage.data.content)) { - return Promise.all(apiMessage.split().map(this.send.bind(this))); - } + messagePayload = MessagePayload.create(this, options).resolveData(); } - const { data, files } = await apiMessage.resolveFiles(); - return this.client.api.channels[this.id].messages - .post({ data, files }) - .then(d => this.client.actions.MessageCreate.handle(d).message); - } + const { data, files } = await messagePayload.resolveFiles(); + const d = await this.client.api.channels[this.id].messages.post({ data, files }); - /** - * Starts a typing indicator in the channel. - * @param {number} [count=1] The number of times startTyping should be considered to have been called - * @returns {Promise} Resolves once the bot stops typing gracefully, or rejects when an error occurs - * @example - * // Start typing in a channel, or increase the typing count by one - * channel.startTyping(); - * @example - * // Start typing in a channel with a typing count of five, or set it to five - * channel.startTyping(5); - */ - startTyping(count) { - if (typeof count !== 'undefined' && count < 1) throw new RangeError('TYPING_COUNT'); - if (this.client.user._typing.has(this.id)) { - const entry = this.client.user._typing.get(this.id); - entry.count = count || entry.count + 1; - return entry.promise; + const existing = this.messages.cache.get(d.id); + if (existing) { + const clone = existing._clone(); + clone._patch(d); + return clone; } - - const entry = {}; - entry.promise = new Promise((resolve, reject) => { - const endpoint = this.client.api.channels[this.id].typing; - Object.assign(entry, { - count: count || 1, - interval: this.client.setInterval(() => { - endpoint.post().catch(error => { - this.client.clearInterval(entry.interval); - this.client.user._typing.delete(this.id); - reject(error); - }); - }, 9000), - resolve, - }); - endpoint.post().catch(error => { - this.client.clearInterval(entry.interval); - this.client.user._typing.delete(this.id); - reject(error); - }); - this.client.user._typing.set(this.id, entry); - }); - return entry.promise; + return this.messages._add(d); } /** - * Stops the typing indicator in the channel. - * The indicator will only stop if this is called as many times as startTyping(). - * It can take a few seconds for the client user to stop typing. - * @param {boolean} [force=false] Whether or not to reset the call count and force the indicator to stop + * Sends a typing indicator in the channel. + * @returns {Promise} Resolves upon the typing status being sent * @example - * // Reduce the typing count by one and stop typing if it reached 0 - * channel.stopTyping(); - * @example - * // Force typing to fully stop regardless of typing count - * channel.stopTyping(true); + * // Start typing in a channel + * channel.sendTyping(); */ - stopTyping(force = false) { - if (this.client.user._typing.has(this.id)) { - const entry = this.client.user._typing.get(this.id); - entry.count--; - if (entry.count <= 0 || force) { - this.client.clearInterval(entry.interval); - this.client.user._typing.delete(this.id); - entry.resolve(); - } - } - } - - /** - * Whether or not the typing indicator is being shown in the channel - * @type {boolean} - * @readonly - */ - get typing() { - return this.client.user._typing.has(this.id); - } - - /** - * Number of times `startTyping` has been called - * @type {number} - * @readonly - */ - get typingCount() { - if (this.client.user._typing.has(this.id)) return this.client.user._typing.get(this.id).count; - return 0; + async sendTyping() { + await this.client.api.channels(this.id).typing.post(); } /** * Creates a Message Collector. - * @param {CollectorFilter} filter The filter to create the collector with * @param {MessageCollectorOptions} [options={}] The options to pass to the collector * @returns {MessageCollector} * @example * // Create a message collector * const filter = m => m.content.includes('discord'); - * const collector = channel.createMessageCollector(filter, { time: 15000 }); + * const collector = channel.createMessageCollector({ filter, time: 15000 }); * collector.on('collect', m => console.log(`Collected ${m.content}`)); * collector.on('end', collected => console.log(`Collected ${collected.size} items`)); */ - createMessageCollector(filter, options = {}) { - return new MessageCollector(this, filter, options); + createMessageCollector(options = {}) { + return new MessageCollector(this, options); } /** @@ -286,22 +213,21 @@ class TextBasedChannel { /** * Similar to createMessageCollector but in promise form. * Resolves with a collection of messages that pass the specified filter. - * @param {CollectorFilter} filter The filter function to use * @param {AwaitMessagesOptions} [options={}] Optional options to pass to the internal collector * @returns {Promise>} * @example * // Await !vote messages * const filter = m => m.content.startsWith('!vote'); * // Errors: ['time'] treats ending because of the time limit as an error - * channel.awaitMessages(filter, { max: 4, time: 60000, errors: ['time'] }) + * channel.awaitMessages({ filter, max: 4, time: 60000, errors: ['time'] }) * .then(collected => console.log(collected.size)) * .catch(collected => console.log(`After a minute, only ${collected.size} out of 4 voted.`)); */ - awaitMessages(filter, options = {}) { + awaitMessages(options = {}) { return new Promise((resolve, reject) => { - const collector = this.createMessageCollector(filter, options); + const collector = this.createMessageCollector(options); collector.once('end', (collection, reason) => { - if (options.errors && options.errors.includes(reason)) { + if (options.errors?.includes(reason)) { reject(collection); } else { resolve(collection); @@ -310,12 +236,55 @@ class TextBasedChannel { }); } + /** + * Creates a button interaction collector. + * @param {MessageComponentCollectorOptions} [options={}] Options to send to the collector + * @returns {InteractionCollector} + * @example + * // Create a button interaction collector + * const filter = (interaction) => interaction.customId === 'button' && interaction.user.id === 'someId'; + * const collector = channel.createMessageComponentCollector({ filter, time: 15000 }); + * collector.on('collect', i => console.log(`Collected ${i.customId}`)); + * collector.on('end', collected => console.log(`Collected ${collected.size} items`)); + */ + createMessageComponentCollector(options = {}) { + return new InteractionCollector(this.client, { + ...options, + interactionType: InteractionTypes.MESSAGE_COMPONENT, + channel: this, + }); + } + + /** + * Collects a single component interaction that passes the filter. + * The Promise will reject if the time expires. + * @param {AwaitMessageComponentOptions} [options={}] Options to pass to the internal collector + * @returns {Promise} + * @example + * // Collect a message component interaction + * const filter = (interaction) => interaction.customId === 'button' && interaction.user.id === 'someId'; + * channel.awaitMessageComponent({ filter, time: 15000 }) + * .then(interaction => console.log(`${interaction.customId} was clicked!`)) + * .catch(console.error); + */ + awaitMessageComponent(options = {}) { + const _options = { ...options, max: 1 }; + return new Promise((resolve, reject) => { + const collector = this.createMessageComponentCollector(_options); + collector.once('end', (interactions, reason) => { + const interaction = interactions.first(); + if (interaction) resolve(interaction); + else reject(new Error('INTERACTION_COLLECTOR_ERROR', reason)); + }); + }); + } + /** * Bulk deletes given messages that are newer than two weeks. * @param {Collection|MessageResolvable[]|number} messages * Messages or number of messages to delete * @param {boolean} [filterOld=false] Filter messages to remove those which are older than two weeks automatically - * @returns {Promise>} Deleted messages + * @returns {Promise>} Returns the deleted messages * @example * // Bulk delete messages * channel.bulkDelete(5) @@ -324,23 +293,23 @@ class TextBasedChannel { */ async bulkDelete(messages, filterOld = false) { if (Array.isArray(messages) || messages instanceof Collection) { - let messageIDs = messages instanceof Collection ? messages.keyArray() : messages.map(m => m.id || m); + let messageIds = messages instanceof Collection ? [...messages.keys()] : messages.map(m => m.id ?? m); if (filterOld) { - messageIDs = messageIDs.filter(id => Date.now() - Snowflake.deconstruct(id).date.getTime() < 1209600000); + messageIds = messageIds.filter(id => Date.now() - SnowflakeUtil.deconstruct(id).timestamp < 1209600000); } - if (messageIDs.length === 0) return new Collection(); - if (messageIDs.length === 1) { - await this.client.api.channels(this.id).messages(messageIDs[0]).delete(); + if (messageIds.length === 0) return new Collection(); + if (messageIds.length === 1) { + await this.client.api.channels(this.id).messages(messageIds[0]).delete(); const message = this.client.actions.MessageDelete.getMessage( { - message_id: messageIDs[0], + message_id: messageIds[0], }, this, ); return message ? new Collection([[message.id, message]]) : new Collection(); } - await this.client.api.channels[this.id].messages['bulk-delete'].post({ data: { messages: messageIDs } }); - return messageIDs.reduce( + await this.client.api.channels[this.id].messages['bulk-delete'].post({ data: { messages: messageIds } }); + return messageIds.reduce( (col, id) => col.set( id, @@ -368,12 +337,11 @@ class TextBasedChannel { 'lastMessage', 'lastPinAt', 'bulkDelete', - 'startTyping', - 'stopTyping', - 'typing', - 'typingCount', + 'sendTyping', 'createMessageCollector', 'awaitMessages', + 'createMessageComponentCollector', + 'awaitMessageComponent', ); } for (const prop of props) { diff --git a/node_modules/discord.js/src/util/BitField.js b/node_modules/discord.js/src/util/BitField.js index 4d03aa6a..889dbf27 100644 --- a/node_modules/discord.js/src/util/BitField.js +++ b/node_modules/discord.js/src/util/BitField.js @@ -7,12 +7,12 @@ const { RangeError } = require('../errors'); */ class BitField { /** - * @param {BitFieldResolvable} [bits=0] Bit(s) to read from + * @param {BitFieldResolvable} [bits=this.constructor.defaultBit] Bit(s) to read from */ - constructor(bits) { + constructor(bits = this.constructor.defaultBit) { /** * Bitfield of the packed bits - * @type {number} + * @type {number|bigint} */ this.bitfield = this.constructor.resolve(bits); } @@ -23,7 +23,7 @@ class BitField { * @returns {boolean} */ any(bit) { - return (this.bitfield & this.constructor.resolve(bit)) !== 0; + return (this.bitfield & this.constructor.resolve(bit)) !== this.constructor.defaultBit; } /** @@ -41,7 +41,6 @@ class BitField { * @returns {boolean} */ has(bit) { - if (Array.isArray(bit)) return bit.every(p => this.has(p)); bit = this.constructor.resolve(bit); return (this.bitfield & bit) === bit; } @@ -53,8 +52,7 @@ class BitField { * @returns {string[]} */ missing(bits, ...hasParams) { - if (!Array.isArray(bits)) bits = new this.constructor(bits).toArray(false); - return bits.filter(p => !this.has(p, ...hasParams)); + return new this.constructor(bits).remove(this).toArray(...hasParams); } /** @@ -71,7 +69,7 @@ class BitField { * @returns {BitField} These bits or new BitField if the instance is frozen. */ add(...bits) { - let total = 0; + let total = this.constructor.defaultBit; for (const bit of bits) { total |= this.constructor.resolve(bit); } @@ -86,7 +84,7 @@ class BitField { * @returns {BitField} These bits or new BitField if the instance is frozen. */ remove(...bits) { - let total = 0; + let total = this.constructor.defaultBit; for (const bit of bits) { total |= this.constructor.resolve(bit); } @@ -117,7 +115,7 @@ class BitField { } toJSON() { - return this.bitfield; + return typeof this.bitfield === 'number' ? this.bitfield : this.bitfield.toString(); } valueOf() { @@ -130,26 +128,28 @@ class BitField { /** * Data that can be resolved to give a bitfield. This can be: - * * A string (see {@link BitField.FLAGS}) - * * A bit number + * * A bit number (this can be a number literal or a value taken from {@link BitField.FLAGS}) + * * A string bit number * * An instance of BitField * * An Array of BitFieldResolvable - * @typedef {string|number|BitField|BitFieldResolvable[]} BitFieldResolvable + * @typedef {number|string|bigint|BitField|BitFieldResolvable[]} BitFieldResolvable */ /** * Resolves bitfields to their numeric form. - * @param {BitFieldResolvable} [bit=0] - bit(s) to resolve - * @returns {number} + * @param {BitFieldResolvable} [bit] - bit(s) to resolve + * @returns {number|bigint} */ - static resolve(bit = 0) { - if (typeof bit === 'number' && bit >= 0) return bit; + static resolve(bit) { + const { defaultBit } = this; + if (typeof defaultBit === typeof bit && bit >= defaultBit) return bit; if (bit instanceof BitField) return bit.bitfield; - if (Array.isArray(bit)) return bit.map(p => this.resolve(p)).reduce((prev, p) => prev | p, 0); - if (typeof bit === 'string' && typeof this.FLAGS[bit] !== 'undefined') return this.FLAGS[bit]; - const error = new RangeError('BITFIELD_INVALID'); - error.bit = bit; - throw error; + if (Array.isArray(bit)) return bit.map(p => this.resolve(p)).reduce((prev, p) => prev | p, defaultBit); + if (typeof bit === 'string') { + if (typeof this.FLAGS[bit] !== 'undefined') return this.FLAGS[bit]; + if (!isNaN(bit)) return typeof defaultBit === 'bigint' ? BigInt(bit) : Number(bit); + } + throw new RangeError('BITFIELD_INVALID', bit); } } @@ -161,4 +161,10 @@ class BitField { */ BitField.FLAGS = {}; +/** + * @type {number|bigint} + * @private + */ +BitField.defaultBit = 0; + module.exports = BitField; diff --git a/node_modules/discord.js/src/util/Collection.js b/node_modules/discord.js/src/util/Collection.js deleted file mode 100644 index 3219fb8a..00000000 --- a/node_modules/discord.js/src/util/Collection.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -const BaseCollection = require('@discordjs/collection'); -const Util = require('./Util'); - -class Collection extends BaseCollection { - toJSON() { - return this.map(e => (typeof e.toJSON === 'function' ? e.toJSON() : Util.flatten(e))); - } -} - -module.exports = Collection; - -/** - * @external Collection - * @see {@link https://discord.js.org/#/docs/collection/master/class/Collection} - */ diff --git a/node_modules/discord.js/src/util/Constants.js b/node_modules/discord.js/src/util/Constants.js index 82699922..92874b01 100644 --- a/node_modules/discord.js/src/util/Constants.js +++ b/node_modules/discord.js/src/util/Constants.js @@ -2,99 +2,8 @@ const Package = (exports.Package = require('../../package.json')); const { Error, RangeError } = require('../errors'); -const browser = (exports.browser = typeof window !== 'undefined'); - -/** - * Options for a client. - * @typedef {Object} ClientOptions - * @property {number|number[]|string} [shards] ID of the shard to run, or an array of shard IDs. If not specified, - * the client will spawn {@link ClientOptions#shardCount} shards. If set to `auto`, it will fetch the - * recommended amount of shards from Discord and spawn that amount - * @property {number} [shardCount=1] The total amount of shards used by all processes of this bot - * (e.g. recommended shard count, shard count of the ShardingManager) - * @property {number} [messageCacheMaxSize=200] Maximum number of messages to cache per channel - * (-1 or Infinity for unlimited - don't do this without message sweeping, otherwise memory usage will climb - * indefinitely) - * @property {number} [messageCacheLifetime=0] How long a message should stay in the cache until it is considered - * sweepable (in seconds, 0 for forever) - * @property {number} [messageSweepInterval=0] How frequently to remove messages from the cache that are older than - * the message cache lifetime (in seconds, 0 for never) - * @property {number} [messageEditHistoryMaxSize=-1] Maximum number of previous versions to hold for an edited message - * (-1 or Infinity for unlimited - don't do this without sweeping, otherwise memory usage may climb indefinitely.) - * @property {boolean} [fetchAllMembers=false] Whether to cache all guild members and users upon startup, as well as - * upon joining a guild (should be avoided whenever possible) - * @property {DisableMentionType} [disableMentions='none'] Default value for {@link MessageOptions#disableMentions} - * @property {MessageMentionOptions} [allowedMentions] Default value for {@link MessageOptions#allowedMentions} - * @property {PartialType[]} [partials] Structures allowed to be partial. This means events can be emitted even when - * they're missing all the data for a particular structure. See the "Partials" topic listed in the sidebar for some - * important usage information, as partials require you to put checks in place when handling data. - * @property {number} [restWsBridgeTimeout=5000] Maximum time permitted between REST responses and their - * corresponding websocket events - * @property {number} [restTimeOffset=500] Extra time in milliseconds to wait before continuing to make REST - * requests (higher values will reduce rate-limiting errors on bad connections) - * @property {number} [restRequestTimeout=15000] Time to wait before cancelling a REST request, in milliseconds - * @property {number} [restSweepInterval=60] How frequently to delete inactive request buckets, in seconds - * (or 0 for never) - * @property {number} [retryLimit=1] How many times to retry on 5XX errors (Infinity for indefinite amount of retries) - * @property {PresenceData} [presence] Presence data to use upon login - * @property {WebsocketOptions} [ws] Options for the WebSocket - * @property {HTTPOptions} [http] HTTP options - */ -exports.DefaultOptions = { - shardCount: 1, - messageCacheMaxSize: 200, - messageCacheLifetime: 0, - messageSweepInterval: 0, - messageEditHistoryMaxSize: -1, - fetchAllMembers: false, - disableMentions: 'none', - partials: [], - restWsBridgeTimeout: 5000, - restRequestTimeout: 15000, - retryLimit: 1, - restTimeOffset: 500, - restSweepInterval: 60, - presence: {}, - - /** - * WebSocket options (these are left as snake_case to match the API) - * @typedef {Object} WebsocketOptions - * @property {number} [large_threshold=50] Number of members in a guild after which offline users will no longer be - * sent in the initial guild member list, must be between 50 and 250 - * @property {IntentsResolvable} [intents] Intents to enable for this connection - */ - ws: { - large_threshold: 50, - compress: false, - properties: { - $os: browser ? 'browser' : process.platform, - $browser: 'discord.js', - $device: 'discord.js', - }, - version: 6, - }, - - /** - * HTTP options - * @typedef {Object} HTTPOptions - * @property {number} [version=7] API version to use - * @property {string} [api='https://discord.com/api'] Base url of the API - * @property {string} [cdn='https://cdn.discordapp.com'] Base url of the CDN - * @property {string} [invite='https://discord.gg'] Base url of invites - * @property {string} [template='https://discord.new'] Base url of templates - */ - http: { - version: 7, - api: 'https://discord.com/api', - cdn: 'https://cdn.discordapp.com', - invite: 'https://discord.gg', - template: 'https://discord.new', - }, -}; -exports.UserAgent = browser - ? null - : `DiscordBot (${Package.homepage.split('#')[0]}, ${Package.version}) Node.js/${process.version}`; +exports.UserAgent = `DiscordBot (${Package.homepage.split('#')[0]}, ${Package.version}) Node.js/${process.version}`; exports.WSCodes = { 1000: 'WS_CLOSE_REQUESTED', @@ -114,44 +23,54 @@ function makeImageUrl(root, { format = 'webp', size } = {}) { if (size && !AllowedImageSizes.includes(size)) throw new RangeError('IMAGE_SIZE', size); return `${root}.${format}${size ? `?size=${size}` : ''}`; } + /** * Options for Image URLs. - * @typedef {Object} ImageURLOptions - * @property {string} [format] One of `webp`, `png`, `jpg`, `jpeg`, `gif`. If no format is provided, - * defaults to `webp`. + * @typedef {StaticImageURLOptions} ImageURLOptions * @property {boolean} [dynamic] If true, the format will dynamically change to `gif` for - * animated avatars; the default is false. + * animated avatars; the default is false + */ + +/** + * Options for static Image URLs. + * @typedef {Object} StaticImageURLOptions + * @property {string} [format] One of `webp`, `png`, `jpg`, `jpeg`, `gif`. If no format is provided, + * defaults to `webp` * @property {number} [size] One of `16`, `32`, `64`, `128`, `256`, `512`, `1024`, `2048`, `4096` */ exports.Endpoints = { CDN(root) { return { - Emoji: (emojiID, format = 'png') => `${root}/emojis/${emojiID}.${format}`, + Emoji: (emojiId, format = 'png') => `${root}/emojis/${emojiId}.${format}`, Asset: name => `${root}/assets/${name}`, DefaultAvatar: discriminator => `${root}/embed/avatars/${discriminator}.png`, - Avatar: (userID, hash, format = 'webp', size, dynamic = false) => { + Avatar: (userId, hash, format = 'webp', size, dynamic = false) => { if (dynamic) format = hash.startsWith('a_') ? 'gif' : format; - return makeImageUrl(`${root}/avatars/${userID}/${hash}`, { format, size }); + return makeImageUrl(`${root}/avatars/${userId}/${hash}`, { format, size }); }, - Banner: (guildID, hash, format = 'webp', size) => - makeImageUrl(`${root}/banners/${guildID}/${hash}`, { format, size }), - Icon: (guildID, hash, format = 'webp', size, dynamic = false) => { + Banner: (guildId, hash, format = 'webp', size) => + makeImageUrl(`${root}/banners/${guildId}/${hash}`, { format, size }), + Icon: (guildId, hash, format = 'webp', size, dynamic = false) => { if (dynamic) format = hash.startsWith('a_') ? 'gif' : format; - return makeImageUrl(`${root}/icons/${guildID}/${hash}`, { format, size }); + return makeImageUrl(`${root}/icons/${guildId}/${hash}`, { format, size }); }, - AppIcon: (clientID, hash, { format = 'webp', size } = {}) => - makeImageUrl(`${root}/app-icons/${clientID}/${hash}`, { size, format }), - AppAsset: (clientID, hash, { format = 'webp', size } = {}) => - makeImageUrl(`${root}/app-assets/${clientID}/${hash}`, { size, format }), - GDMIcon: (channelID, hash, format = 'webp', size) => - makeImageUrl(`${root}/channel-icons/${channelID}/${hash}`, { size, format }), - Splash: (guildID, hash, format = 'webp', size) => - makeImageUrl(`${root}/splashes/${guildID}/${hash}`, { size, format }), - DiscoverySplash: (guildID, hash, format = 'webp', size) => - makeImageUrl(`${root}/discovery-splashes/${guildID}/${hash}`, { size, format }), - TeamIcon: (teamID, hash, { format = 'webp', size } = {}) => - makeImageUrl(`${root}/team-icons/${teamID}/${hash}`, { size, format }), + AppIcon: (clientId, hash, { format = 'webp', size } = {}) => + makeImageUrl(`${root}/app-icons/${clientId}/${hash}`, { size, format }), + AppAsset: (clientId, hash, { format = 'webp', size } = {}) => + makeImageUrl(`${root}/app-assets/${clientId}/${hash}`, { size, format }), + StickerPackBanner: (bannerId, format = 'webp', size) => + makeImageUrl(`${root}/app-assets/710982414301790216/store/${bannerId}`, { size, format }), + GDMIcon: (channelId, hash, format = 'webp', size) => + makeImageUrl(`${root}/channel-icons/${channelId}/${hash}`, { size, format }), + Splash: (guildId, hash, format = 'webp', size) => + makeImageUrl(`${root}/splashes/${guildId}/${hash}`, { size, format }), + DiscoverySplash: (guildId, hash, format = 'webp', size) => + makeImageUrl(`${root}/discovery-splashes/${guildId}/${hash}`, { size, format }), + TeamIcon: (teamId, hash, { format = 'webp', size } = {}) => + makeImageUrl(`${root}/team-icons/${teamId}/${hash}`, { size, format }), + Sticker: (stickerId, stickerFormat) => + `${root}/stickers/${stickerId}.${stickerFormat === 'LOTTIE' ? 'json' : 'png'}`, }; }, invite: (root, code) => `${root}/${code}`, @@ -183,24 +102,7 @@ exports.Status = { RESUMING: 8, }; -/** - * The current status of a voice connection. Here are the available statuses: - * * CONNECTED: 0 - * * CONNECTING: 1 - * * AUTHENTICATING: 2 - * * RECONNECTING: 3 - * * DISCONNECTED: 4 - * @typedef {number} VoiceStatus - */ -exports.VoiceStatus = { - CONNECTED: 0, - CONNECTING: 1, - AUTHENTICATING: 2, - RECONNECTING: 3, - DISCONNECTED: 4, -}; - -exports.OPCodes = { +exports.Opcodes = { DISPATCH: 0, HEARTBEAT: 1, IDENTIFY: 2, @@ -215,31 +117,21 @@ exports.OPCodes = { HEARTBEAT_ACK: 11, }; -exports.VoiceOPCodes = { - IDENTIFY: 0, - SELECT_PROTOCOL: 1, - READY: 2, - HEARTBEAT: 3, - SESSION_DESCRIPTION: 4, - SPEAKING: 5, - HELLO: 8, - CLIENT_CONNECT: 12, - CLIENT_DISCONNECT: 13, -}; - exports.Events = { RATE_LIMIT: 'rateLimit', + INVALID_REQUEST_WARNING: 'invalidRequestWarning', CLIENT_READY: 'ready', + APPLICATION_COMMAND_CREATE: 'applicationCommandCreate', + APPLICATION_COMMAND_DELETE: 'applicationCommandDelete', + APPLICATION_COMMAND_UPDATE: 'applicationCommandUpdate', GUILD_CREATE: 'guildCreate', GUILD_DELETE: 'guildDelete', GUILD_UPDATE: 'guildUpdate', GUILD_UNAVAILABLE: 'guildUnavailable', - GUILD_AVAILABLE: 'guildAvailable', GUILD_MEMBER_ADD: 'guildMemberAdd', GUILD_MEMBER_REMOVE: 'guildMemberRemove', GUILD_MEMBER_UPDATE: 'guildMemberUpdate', GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable', - GUILD_MEMBER_SPEAKING: 'guildMemberSpeaking', GUILD_MEMBERS_CHUNK: 'guildMembersChunk', GUILD_INTEGRATIONS_UPDATE: 'guildIntegrationsUpdate', GUILD_ROLE_CREATE: 'roleCreate', @@ -256,7 +148,7 @@ exports.Events = { CHANNEL_DELETE: 'channelDelete', CHANNEL_UPDATE: 'channelUpdate', CHANNEL_PINS_UPDATE: 'channelPinsUpdate', - MESSAGE_CREATE: 'message', + MESSAGE_CREATE: 'messageCreate', MESSAGE_DELETE: 'messageDelete', MESSAGE_UPDATE: 'messageUpdate', MESSAGE_BULK_DELETE: 'messageDeleteBulk', @@ -264,15 +156,19 @@ exports.Events = { MESSAGE_REACTION_REMOVE: 'messageReactionRemove', MESSAGE_REACTION_REMOVE_ALL: 'messageReactionRemoveAll', MESSAGE_REACTION_REMOVE_EMOJI: 'messageReactionRemoveEmoji', + THREAD_CREATE: 'threadCreate', + THREAD_DELETE: 'threadDelete', + THREAD_UPDATE: 'threadUpdate', + THREAD_LIST_SYNC: 'threadListSync', + THREAD_MEMBER_UPDATE: 'threadMemberUpdate', + THREAD_MEMBERS_UPDATE: 'threadMembersUpdate', USER_UPDATE: 'userUpdate', PRESENCE_UPDATE: 'presenceUpdate', VOICE_SERVER_UPDATE: 'voiceServerUpdate', VOICE_STATE_UPDATE: 'voiceStateUpdate', - VOICE_BROADCAST_SUBSCRIBE: 'subscribe', - VOICE_BROADCAST_UNSUBSCRIBE: 'unsubscribe', TYPING_START: 'typingStart', - TYPING_STOP: 'typingStop', WEBHOOKS_UPDATE: 'webhookUpdate', + INTERACTION_CREATE: 'interactionCreate', ERROR: 'error', WARN: 'warn', DEBUG: 'debug', @@ -283,6 +179,12 @@ exports.Events = { SHARD_RESUME: 'shardResume', INVALIDATED: 'invalidated', RAW: 'raw', + STAGE_INSTANCE_CREATE: 'stageInstanceCreate', + STAGE_INSTANCE_UPDATE: 'stageInstanceUpdate', + STAGE_INSTANCE_DELETE: 'stageInstanceDelete', + GUILD_STICKER_CREATE: 'stickerCreate', + GUILD_STICKER_DELETE: 'stickerDelete', + GUILD_STICKER_UPDATE: 'stickerUpdate', }; exports.ShardEvents = { @@ -301,8 +203,8 @@ exports.ShardEvents = { * * GUILD_MEMBER * * MESSAGE * * REACTION - * Partials require you to put checks in place when handling data, read the Partials topic listed in the - * sidebar for more information. + * Partials require you to put checks in place when handling data. See the "Partial Structures" topic on the + * [guide](https://discordjs.guide/popular-topics/partials.html) for more information. * @typedef {string} PartialType */ exports.PartialTypes = keyMirror(['USER', 'CHANNEL', 'GUILD_MEMBER', 'MESSAGE', 'REACTION']); @@ -311,6 +213,9 @@ exports.PartialTypes = keyMirror(['USER', 'CHANNEL', 'GUILD_MEMBER', 'MESSAGE', * The type of a websocket message event, e.g. `MESSAGE_CREATE`. Here are the available events: * * READY * * RESUMED + * * APPLICATION_COMMAND_CREATE + * * APPLICATION_COMMAND_DELETE + * * APPLICATION_COMMAND_UPDATE * * GUILD_CREATE * * GUILD_DELETE * * GUILD_UPDATE @@ -339,17 +244,31 @@ exports.PartialTypes = keyMirror(['USER', 'CHANNEL', 'GUILD_MEMBER', 'MESSAGE', * * MESSAGE_REACTION_REMOVE * * MESSAGE_REACTION_REMOVE_ALL * * MESSAGE_REACTION_REMOVE_EMOJI + * * THREAD_CREATE + * * THREAD_UPDATE + * * THREAD_DELETE + * * THREAD_LIST_SYNC + * * THREAD_MEMBER_UPDATE + * * THREAD_MEMBERS_UPDATE * * USER_UPDATE * * PRESENCE_UPDATE * * TYPING_START * * VOICE_STATE_UPDATE * * VOICE_SERVER_UPDATE * * WEBHOOKS_UPDATE + * * INTERACTION_CREATE + * * STAGE_INSTANCE_CREATE + * * STAGE_INSTANCE_UPDATE + * * STAGE_INSTANCE_DELETE + * * GUILD_STICKERS_UPDATE * @typedef {string} WSEventType */ exports.WSEvents = keyMirror([ 'READY', 'RESUMED', + 'APPLICATION_COMMAND_CREATE', + 'APPLICATION_COMMAND_DELETE', + 'APPLICATION_COMMAND_UPDATE', 'GUILD_CREATE', 'GUILD_DELETE', 'GUILD_UPDATE', @@ -378,14 +297,57 @@ exports.WSEvents = keyMirror([ 'MESSAGE_REACTION_REMOVE', 'MESSAGE_REACTION_REMOVE_ALL', 'MESSAGE_REACTION_REMOVE_EMOJI', + 'THREAD_CREATE', + 'THREAD_UPDATE', + 'THREAD_DELETE', + 'THREAD_LIST_SYNC', + 'THREAD_MEMBER_UPDATE', + 'THREAD_MEMBERS_UPDATE', 'USER_UPDATE', 'PRESENCE_UPDATE', 'TYPING_START', 'VOICE_STATE_UPDATE', 'VOICE_SERVER_UPDATE', 'WEBHOOKS_UPDATE', + 'INTERACTION_CREATE', + 'STAGE_INSTANCE_CREATE', + 'STAGE_INSTANCE_UPDATE', + 'STAGE_INSTANCE_DELETE', + 'GUILD_STICKERS_UPDATE', ]); +/** + * A valid scope to request when generating an invite link. + * Scopes that require whitelist are not considered valid for this generator + * * `applications.builds.read`: allows reading build data for a users applications + * * `applications.commands`: allows this bot to create commands in the server + * * `applications.entitlements`: allows reading entitlements for a users applications + * * `applications.store.update`: allows reading and updating of store data for a users applications + * * `bot`: makes the bot join the selected guild + * * `connections`: makes the endpoint for getting a users connections available + * * `email`: allows the `/users/@me` endpoint return with an email + * * `identify`: allows the `/users/@me` endpoint without an email + * * `guilds`: makes the `/users/@me/guilds` endpoint available for a user + * * `guilds.join`: allows the bot to join the user to any guild it is in using Guild#addMember + * * `gdm.join`: allows joining the user to a group dm + * * `webhook.incoming`: generates a webhook to a channel + * @typedef {string} InviteScope + */ +exports.InviteScopes = [ + 'applications.builds.read', + 'applications.commands', + 'applications.entitlements', + 'applications.store.update', + 'bot', + 'connections', + 'email', + 'identify', + 'guilds', + 'guilds.join', + 'gdm.join', + 'webhook.incoming', +]; + /** * The type of a message, e.g. `DEFAULT`. Here are the available types: * * DEFAULT @@ -403,6 +365,13 @@ exports.WSEvents = keyMirror([ * * CHANNEL_FOLLOW_ADD * * GUILD_DISCOVERY_DISQUALIFIED * * GUILD_DISCOVERY_REQUALIFIED + * * GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING + * * GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING + * * THREAD_CREATED + * * REPLY + * * APPLICATION_COMMAND + * * THREAD_STARTER_MESSAGE + * * GUILD_INVITE_REMINDER * @typedef {string} MessageType */ exports.MessageTypes = [ @@ -422,30 +391,106 @@ exports.MessageTypes = [ null, 'GUILD_DISCOVERY_DISQUALIFIED', 'GUILD_DISCOVERY_REQUALIFIED', + 'GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING', + 'GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING', + 'THREAD_CREATED', + 'REPLY', + 'APPLICATION_COMMAND', + 'THREAD_STARTER_MESSAGE', + 'GUILD_INVITE_REMINDER', ]; /** - * Bots cannot set a `CUSTOM_STATUS`, it is only for custom statuses received from users + * The types of messages that are `System`. The available types are `MessageTypes` excluding: + * * DEFAULT + * * REPLY + * * APPLICATION_COMMAND + * @typedef {string} SystemMessageType + */ +exports.SystemMessageTypes = exports.MessageTypes.filter( + type => type && !['DEFAULT', 'REPLY', 'APPLICATION_COMMAND'].includes(type), +); + +/** + * Bots cannot set a `CUSTOM` activity type, it is only for custom statuses received from users * The type of an activity of a users presence, e.g. `PLAYING`. Here are the available types: * * PLAYING * * STREAMING * * LISTENING * * WATCHING - * * CUSTOM_STATUS + * * CUSTOM * * COMPETING * @typedef {string} ActivityType */ -exports.ActivityTypes = ['PLAYING', 'STREAMING', 'LISTENING', 'WATCHING', 'CUSTOM_STATUS', 'COMPETING']; +exports.ActivityTypes = createEnum(['PLAYING', 'STREAMING', 'LISTENING', 'WATCHING', 'CUSTOM', 'COMPETING']); -exports.ChannelTypes = { - TEXT: 0, - DM: 1, - VOICE: 2, - GROUP: 3, - CATEGORY: 4, - NEWS: 5, - STORE: 6, -}; +/** + * All available channel types: + * * `GUILD_TEXT` - a guild text channel + * * `DM` - a DM channel + * * `GUILD_VOICE` - a guild voice channel + * * `GROUP_DM` - a group DM channel + * * `GUILD_CATEGORY` - a guild category channel + * * `GUILD_NEWS` - a guild news channel + * * `GUILD_STORE` - a guild store channel + * * `GUILD_NEWS_THREAD` - a guild news channel's public thread channel + * * `GUILD_PUBLIC_THREAD` - a guild text channel's public thread channel + * * `GUILD_PRIVATE_THREAD` - a guild text channel's private thread channel + * * `GUILD_STAGE_VOICE` - a guild stage voice channel + * * `UNKNOWN` - a generic channel of unknown type, could be Channel or GuildChannel + * @typedef {string} ChannelType + */ +exports.ChannelTypes = createEnum([ + 'GUILD_TEXT', + 'DM', + 'GUILD_VOICE', + 'GROUP_DM', + 'GUILD_CATEGORY', + 'GUILD_NEWS', + 'GUILD_STORE', + ...Array(3).fill(null), + // 10 + 'GUILD_NEWS_THREAD', + 'GUILD_PUBLIC_THREAD', + 'GUILD_PRIVATE_THREAD', + 'GUILD_STAGE_VOICE', +]); + +/** + * The types of channels that are text-based. The available types are: + * * DM + * * GUILD_TEXT + * * GUILD_NEWS + * * GUILD_NEWS_THREAD + * * GUILD_PUBLIC_THREAD + * * GUILD_PRIVATE_THREAD + * @typedef {string} TextBasedChannelTypes + */ +exports.TextBasedChannelTypes = [ + 'DM', + 'GUILD_TEXT', + 'GUILD_NEWS', + 'GUILD_NEWS_THREAD', + 'GUILD_PUBLIC_THREAD', + 'GUILD_PRIVATE_THREAD', +]; + +/** + * The types of channels that are threads. The available types are: + * * GUILD_NEWS_THREAD + * * GUILD_PUBLIC_THREAD + * * GUILD_PRIVATE_THREAD + * @typedef {string} ThreadChannelTypes + */ +exports.ThreadChannelTypes = ['GUILD_NEWS_THREAD', 'GUILD_PUBLIC_THREAD', 'GUILD_PRIVATE_THREAD']; + +/** + * The types of channels that are voice-based. The available types are: + * * GUILD_VOICE + * * GUILD_STAGE_VOICE + * @typedef {string} VoiceBasedChannelTypes + */ +exports.VoiceBasedChannelTypes = ['GUILD_VOICE', 'GUILD_STAGE_VOICE']; exports.ClientApplicationAssetTypes = { SMALL: 1, @@ -456,14 +501,15 @@ exports.Colors = { DEFAULT: 0x000000, WHITE: 0xffffff, AQUA: 0x1abc9c, - GREEN: 0x2ecc71, + GREEN: 0x57f287, BLUE: 0x3498db, - YELLOW: 0xffff00, + YELLOW: 0xfee75c, PURPLE: 0x9b59b6, LUMINOUS_VIVID_PINK: 0xe91e63, + FUCHSIA: 0xeb459e, GOLD: 0xf1c40f, ORANGE: 0xe67e22, - RED: 0xe74c3c, + RED: 0xed4245, GREY: 0x95a5a6, NAVY: 0x34495e, DARK_AQUA: 0x11806a, @@ -478,7 +524,7 @@ exports.Colors = { DARKER_GREY: 0x7f8c8d, LIGHT_GREY: 0xbcc0c0, DARK_NAVY: 0x2c3e50, - BLURPLE: 0x7289da, + BLURPLE: 0x5865f2, GREYPLE: 0x99aab5, DARK_BUT_NOT_BLACK: 0x2c2f33, NOT_QUITE_BLACK: 0x23272a, @@ -491,7 +537,7 @@ exports.Colors = { * * ALL_MEMBERS * @typedef {string} ExplicitContentFilterLevel */ -exports.ExplicitContentFilterLevels = ['DISABLED', 'MEMBERS_WITHOUT_ROLES', 'ALL_MEMBERS']; +exports.ExplicitContentFilterLevels = createEnum(['DISABLED', 'MEMBERS_WITHOUT_ROLES', 'ALL_MEMBERS']); /** * The value set for the verification levels for a guild: @@ -502,7 +548,7 @@ exports.ExplicitContentFilterLevels = ['DISABLED', 'MEMBERS_WITHOUT_ROLES', 'ALL * * VERY_HIGH * @typedef {string} VerificationLevel */ -exports.VerificationLevels = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'VERY_HIGH']; +exports.VerificationLevels = createEnum(['NONE', 'LOW', 'MEDIUM', 'HIGH', 'VERY_HIGH']); /** * An error encountered while performing an API request. Here are the potential errors: @@ -521,26 +567,62 @@ exports.VerificationLevels = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'VERY_HIGH']; * * UNKNOWN_USER * * UNKNOWN_EMOJI * * UNKNOWN_WEBHOOK + * * UNKNOWN_WEBHOOK_SERVICE + * * UNKNOWN_SESSION * * UNKNOWN_BAN + * * UNKNOWN_SKU + * * UNKNOWN_STORE_LISTING + * * UNKNOWN_ENTITLEMENT + * * UNKNOWN_BUILD + * * UNKNOWN_LOBBY + * * UNKNOWN_BRANCH + * * UNKNOWN_STORE_DIRECTORY_LAYOUT + * * UNKNOWN_REDISTRIBUTABLE + * * UNKNOWN_GIFT_CODE * * UNKNOWN_GUILD_TEMPLATE + * * UNKNOWN_DISCOVERABLE_SERVER_CATEGORY + * * UNKNOWN_STICKER + * * UNKNOWN_INTERACTION + * * UNKNOWN_APPLICATION_COMMAND + * * UNKNOWN_APPLICATION_COMMAND_PERMISSIONS + * * UNKNOWN_STAGE_INSTANCE + * * UNKNOWN_GUILD_MEMBER_VERIFICATION_FORM + * * UNKNOWN_GUILD_WELCOME_SCREEN * * BOT_PROHIBITED_ENDPOINT * * BOT_ONLY_ENDPOINT + * * CANNOT_SEND_EXPLICIT_CONTENT + * * NOT_AUTHORIZED + * * SLOWMODE_RATE_LIMIT + * * ACCOUNT_OWNER_ONLY + * * ANNOUNCEMENT_EDIT_LIMIT_EXCEEDED * * CHANNEL_HIT_WRITE_RATELIMIT + * * CONTENT_NOT_ALLOWED * * MAXIMUM_GUILDS * * MAXIMUM_FRIENDS * * MAXIMUM_PINS + * * MAXIMUM_RECIPIENTS * * MAXIMUM_ROLES * * MAXIMUM_WEBHOOKS + * * MAXIMUM_EMOJIS * * MAXIMUM_REACTIONS * * MAXIMUM_CHANNELS * * MAXIMUM_ATTACHMENTS * * MAXIMUM_INVITES + * * MAXIMUM_ANIMATED_EMOJIS + * * MAXIMUM_SERVER_MEMBERS + * * MAXIMUM_NUMBER_OF_SERVER_CATEGORIES * * GUILD_ALREADY_HAS_TEMPLATE + * * MAXIMUM_THREAD_PARTICIPANTS + * * MAXIMUM_NON_GUILD_MEMBERS_BANS + * * MAXIMUM_BAN_FETCHES + * * MAXIMUM_NUMBER_OF_STICKERS_REACHED * * UNAUTHORIZED * * ACCOUNT_VERIFICATION_REQUIRED + * * DIRECT_MESSAGES_TOO_FAST * * REQUEST_ENTITY_TOO_LARGE * * FEATURE_TEMPORARILY_DISABLED * * USER_BANNED + * * TARGET_USER_NOT_CONNECTED_TO_VOICE * * ALREADY_CROSSPOSTED * * MISSING_ACCESS * * INVALID_ACCOUNT_TYPE @@ -561,14 +643,32 @@ exports.VerificationLevels = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'VERY_HIGH']; * * CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL * * INVALID_OR_TAKEN_INVITE_CODE * * CANNOT_EXECUTE_ON_SYSTEM_MESSAGE + * * CANNOT_EXECUTE_ON_CHANNEL_TYPE * * INVALID_OAUTH_TOKEN + * * MISSING_OAUTH_SCOPE + * * INVALID_WEBHOOK_TOKEN + * * INVALID_ROLE + * * INVALID_RECIPIENTS * * BULK_DELETE_MESSAGE_TOO_OLD * * INVALID_FORM_BODY * * INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT * * INVALID_API_VERSION + * * CANNOT_SELF_REDEEM_GIFT + * * PAYMENT_SOURCE_REQUIRED * * CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL + * * INVALID_STICKER_SENT + * * INVALID_OPERATION_ON_ARCHIVED_THREAD + * * INVALID_THREAD_NOTIFICATION_SETTINGS + * * PARAMETER_EARLIER_THAN_CREATION + * * TWO_FACTOR_REQUIRED + * * NO_USERS_WITH_DISCORDTAG_EXIST * * REACTION_BLOCKED * * RESOURCE_OVERLOADED + * * STAGE_ALREADY_OPEN + * * MESSAGE_ALREADY_HAS_THREAD + * * THREAD_LOCKED + * * MAXIMUM_ACTIVE_THREADS + * * MAXIMUM_ACTIVE_ANNOUCEMENT_THREAD * @typedef {string} APIError */ exports.APIErrors = { @@ -587,26 +687,63 @@ exports.APIErrors = { UNKNOWN_USER: 10013, UNKNOWN_EMOJI: 10014, UNKNOWN_WEBHOOK: 10015, + UNKNOWN_WEBHOOK_SERVICE: 10016, + UNKNOWN_SESSION: 10020, UNKNOWN_BAN: 10026, + UNKNOWN_SKU: 10027, + UNKNOWN_STORE_LISTING: 10028, + UNKNOWN_ENTITLEMENT: 10029, + UNKNOWN_BUILD: 10030, + UNKNOWN_LOBBY: 10031, + UNKNOWN_BRANCH: 10032, + UNKNOWN_STORE_DIRECTORY_LAYOUT: 10033, + UNKNOWN_REDISTRIBUTABLE: 10036, + UNKNOWN_GIFT_CODE: 10038, UNKNOWN_GUILD_TEMPLATE: 10057, + UNKNOWN_DISCOVERABLE_SERVER_CATEGORY: 10059, + UNKNOWN_STICKER: 10060, + UNKNOWN_INTERACTION: 10062, + UNKNOWN_APPLICATION_COMMAND: 10063, + UNKNOWN_APPLICATION_COMMAND_PERMISSIONS: 10066, + UNKNOWN_STAGE_INSTANCE: 10067, + UNKNOWN_GUILD_MEMBER_VERIFICATION_FORM: 10068, + UNKNOWN_GUILD_WELCOME_SCREEN: 10069, BOT_PROHIBITED_ENDPOINT: 20001, BOT_ONLY_ENDPOINT: 20002, + CANNOT_SEND_EXPLICIT_CONTENT: 20009, + NOT_AUTHORIZED: 20012, + SLOWMODE_RATE_LIMIT: 20016, + ACCOUNT_OWNER_ONLY: 20018, + ANNOUNCEMENT_EDIT_LIMIT_EXCEEDED: 20022, CHANNEL_HIT_WRITE_RATELIMIT: 20028, + CONTENT_NOT_ALLOWED: 20031, + GUILD_PREMIUM_LEVEL_TOO_LOW: 20035, MAXIMUM_GUILDS: 30001, MAXIMUM_FRIENDS: 30002, MAXIMUM_PINS: 30003, + MAXIMUM_RECIPIENTS: 30004, MAXIMUM_ROLES: 30005, MAXIMUM_WEBHOOKS: 30007, + MAXIMUM_EMOJIS: 30008, MAXIMUM_REACTIONS: 30010, MAXIMUM_CHANNELS: 30013, MAXIMUM_ATTACHMENTS: 30015, MAXIMUM_INVITES: 30016, + MAXIMUM_ANIMATED_EMOJIS: 30018, + MAXIMUM_SERVER_MEMBERS: 30019, + MAXIMUM_NUMBER_OF_SERVER_CATEGORIES: 30030, GUILD_ALREADY_HAS_TEMPLATE: 30031, + MAXIMUM_THREAD_PARTICIPANTS: 30033, + MAXIMUM_NON_GUILD_MEMBERS_BANS: 30035, + MAXIMUM_BAN_FETCHES: 30037, + MAXIMUM_NUMBER_OF_STICKERS_REACHED: 30039, UNAUTHORIZED: 40001, ACCOUNT_VERIFICATION_REQUIRED: 40002, + DIRECT_MESSAGES_TOO_FAST: 40003, REQUEST_ENTITY_TOO_LARGE: 40005, FEATURE_TEMPORARILY_DISABLED: 40006, USER_BANNED: 40007, + TARGET_USER_NOT_CONNECTED_TO_VOICE: 40032, ALREADY_CROSSPOSTED: 40033, MISSING_ACCESS: 50001, INVALID_ACCOUNT_TYPE: 50002, @@ -627,52 +764,259 @@ exports.APIErrors = { CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: 50019, INVALID_OR_TAKEN_INVITE_CODE: 50020, CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: 50021, + CANNOT_EXECUTE_ON_CHANNEL_TYPE: 50024, INVALID_OAUTH_TOKEN: 50025, + MISSING_OAUTH_SCOPE: 50026, + INVALID_WEBHOOK_TOKEN: 50027, + INVALID_ROLE: 50028, + INVALID_RECIPIENTS: 50033, BULK_DELETE_MESSAGE_TOO_OLD: 50034, INVALID_FORM_BODY: 50035, INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: 50036, INVALID_API_VERSION: 50041, + FILE_UPLOADED_EXCEEDS_MAXIMUM_SIZE: 50045, + INVALID_FILE_UPLOADED: 50046, + CANNOT_SELF_REDEEM_GIFT: 50054, + PAYMENT_SOURCE_REQUIRED: 50070, CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL: 50074, + INVALID_STICKER_SENT: 50081, + INVALID_OPERATION_ON_ARCHIVED_THREAD: 50083, + INVALID_THREAD_NOTIFICATION_SETTINGS: 50084, + PARAMETER_EARLIER_THAN_CREATION: 50085, + TWO_FACTOR_REQUIRED: 60003, + NO_USERS_WITH_DISCORDTAG_EXIST: 80004, REACTION_BLOCKED: 90001, RESOURCE_OVERLOADED: 130000, + STAGE_ALREADY_OPEN: 150006, + MESSAGE_ALREADY_HAS_THREAD: 160004, + THREAD_LOCKED: 160005, + MAXIMUM_ACTIVE_THREADS: 160006, + MAXIMUM_ACTIVE_ANNOUNCEMENT_THREADS: 160007, + INVALID_JSON_FOR_UPLOADED_LOTTIE_FILE: 170001, + UPLOADED_LOTTIES_CANNOT_CONTAIN_RASTERIZED_IMAGES: 170002, + STICKER_MAXIMUM_FRAMERATE_EXCEEDED: 170003, + STICKER_FRAME_COUNT_EXCEEDS_MAXIMUM_OF_1000_FRAMES: 170004, + LOTTIE_ANIMATION_MAXIMUM_DIMENSIONS_EXCEEDED: 170005, + STICKER_FRAME_RATE_IS_TOO_SMALL_OR_TOO_LARGE: 170006, + STICKER_ANIMATION_DURATION_EXCEEDS_MAXIMUM_OF_5_SECONDS: 170007, }; /** - * The value set for a guild's default message notifications, e.g. `ALL`. Here are the available types: - * * ALL - * * MENTIONS - * @typedef {string} DefaultMessageNotifications + * The value set for a guild's default message notifications, e.g. `ALL_MESSAGES`. Here are the available types: + * * ALL_MESSAGES + * * ONLY_MENTIONS + * @typedef {string} DefaultMessageNotificationLevel */ -exports.DefaultMessageNotifications = ['ALL', 'MENTIONS']; +exports.DefaultMessageNotificationLevels = createEnum(['ALL_MESSAGES', 'ONLY_MENTIONS']); /** * The value set for a team members's membership state: * * INVITED * * ACCEPTED - * @typedef {string} MembershipStates + * @typedef {string} MembershipState */ -exports.MembershipStates = [ - // They start at 1 - null, - 'INVITED', - 'ACCEPTED', -]; +exports.MembershipStates = createEnum([null, 'INVITED', 'ACCEPTED']); /** * The value set for a webhook's type: * * Incoming * * Channel Follower - * @typedef {string} WebhookTypes + * @typedef {string} WebhookType + */ +exports.WebhookTypes = createEnum([null, 'Incoming', 'Channel Follower']); + +/** + * The value set for a sticker's type: + * * STANDARD + * * GUILD + * @typedef {string} StickerType + */ +exports.StickerTypes = createEnum([null, 'STANDARD', 'GUILD']); + +/** + * The value set for a sticker's format type: + * * PNG + * * APNG + * * LOTTIE + * @typedef {string} StickerFormatType + */ +exports.StickerFormatTypes = createEnum([null, 'PNG', 'APNG', 'LOTTIE']); + +/** + * An overwrite type: + * * role + * * member + * @typedef {string} OverwriteType */ -exports.WebhookTypes = [ - // They start at 1 +exports.OverwriteTypes = createEnum(['role', 'member']); + +/** + * The type of an {@link ApplicationCommandOption} object: + * * SUB_COMMAND + * * SUB_COMMAND_GROUP + * * STRING + * * INTEGER + * * BOOLEAN + * * USER + * * CHANNEL + * * ROLE + * * MENTIONABLE + * * NUMBER + * @typedef {string} ApplicationCommandOptionType + */ +exports.ApplicationCommandOptionTypes = createEnum([ null, - 'Incoming', - 'Channel Follower', -]; + 'SUB_COMMAND', + 'SUB_COMMAND_GROUP', + 'STRING', + 'INTEGER', + 'BOOLEAN', + 'USER', + 'CHANNEL', + 'ROLE', + 'MENTIONABLE', + 'NUMBER', +]); + +/** + * The type of an {@link ApplicationCommandPermissions} object: + * * ROLE + * * USER + * @typedef {string} ApplicationCommandPermissionType + */ +exports.ApplicationCommandPermissionTypes = createEnum([null, 'ROLE', 'USER']); + +/** + * The type of an {@link Interaction} object: + * * PING + * * APPLICATION_COMMAND + * * MESSAGE_COMPONENT + * @typedef {string} InteractionType + */ +exports.InteractionTypes = createEnum([null, 'PING', 'APPLICATION_COMMAND', 'MESSAGE_COMPONENT']); + +/** + * The type of an interaction response: + * * PONG + * * CHANNEL_MESSAGE_WITH_SOURCE + * * DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE + * * DEFERRED_MESSAGE_UPDATE + * * UPDATE_MESSAGE + * @typedef {string} InteractionResponseType + */ +exports.InteractionResponseTypes = createEnum([ + null, + 'PONG', + null, + null, + 'CHANNEL_MESSAGE_WITH_SOURCE', + 'DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE', + 'DEFERRED_MESSAGE_UPDATE', + 'UPDATE_MESSAGE', +]); + +/** + * The type of a message component + * * ACTION_ROW + * * BUTTON + * * SELECT_MENU + * @typedef {string} MessageComponentType + */ +exports.MessageComponentTypes = createEnum([null, 'ACTION_ROW', 'BUTTON', 'SELECT_MENU']); + +/** + * The style of a message button + * * PRIMARY + * * SECONDARY + * * SUCCESS + * * DANGER + * * LINK + * @typedef {string} MessageButtonStyle + */ +exports.MessageButtonStyles = createEnum([null, 'PRIMARY', 'SECONDARY', 'SUCCESS', 'DANGER', 'LINK']); + +/** + * The required MFA level for a guild + * * NONE + * * ELEVATED + * @typedef {string} MFALevel + */ +exports.MFALevels = createEnum(['NONE', 'ELEVATED']); + +/** + * NSFW level of a Guild: + * * DEFAULT + * * EXPLICIT + * * SAFE + * * AGE_RESTRICTED + * @typedef {string} NSFWLevel + */ +exports.NSFWLevels = createEnum(['DEFAULT', 'EXPLICIT', 'SAFE', 'AGE_RESTRICTED']); + +/** + * Privacy level of a {@link StageInstance} object: + * * PUBLIC + * * GUILD_ONLY + * @typedef {string} PrivacyLevel + */ +exports.PrivacyLevels = createEnum([null, 'PUBLIC', 'GUILD_ONLY']); + +/** + * The premium tier (Server Boost level) of a guild: + * * NONE + * * TIER_1 + * * TIER_2 + * * TIER_3 + * @typedef {string} PremiumTier + */ +exports.PremiumTiers = createEnum(['NONE', 'TIER_1', 'TIER_2', 'TIER_3']); + +exports._cleanupSymbol = Symbol('djsCleanup'); function keyMirror(arr) { let tmp = Object.create(null); for (const value of arr) tmp[value] = value; return tmp; } + +function createEnum(keys) { + const obj = {}; + for (const [index, key] of keys.entries()) { + if (key === null) continue; + obj[key] = index; + obj[index] = key; + } + return obj; +} + +/** + * @typedef {Object} Constants Constants that can be used in an enum or object-like way. + * @property {ActivityType} ActivityTypes The type of an activity of a users presence. + * @property {APIError} APIErrors An error encountered while performing an API request. + * @property {ApplicationCommandOptionType} ApplicationCommandOptionTypes + * The type of an {@link ApplicationCommandOption} object. + * @property {ApplicationCommandPermissionType} ApplicationCommandPermissionTypes + * The type of an {@link ApplicationCommandPermissions} object. + * @property {ChannelType} ChannelTypes All available channel types. + * @property {DefaultMessageNotificationLevel} DefaultMessageNotificationLevels + * The value set for a guild's default message notifications. + * @property {ExplicitContentFilterLevel} ExplicitContentFilterLevels + * The value set for the explicit content filter levels for a guild. + * @property {InteractionResponseType} InteractionResponseTypes The type of an interaction response. + * @property {InteractionType} InteractionTypes The type of an {@link Interaction} object. + * @property {MembershipState} MembershipStates The value set for a team members's membership state. + * @property {MessageButtonStyle} MessageButtonStyles The style of a message button. + * @property {MessageComponentType} MessageComponentTypes The type of a message component. + * @property {MFALevel} MFALevels The required MFA level for a guild. + * @property {NSFWLevel} NSFWLevels NSFW level of a guild. + * @property {OverwriteType} OverwriteTypes An overwrite type. + * @property {PartialType} PartialTypes The type of Structure allowed to be a partial. + * @property {PremiumTier} PremiumTiers The premium tier (Server Boost level) of a guild. + * @property {PrivacyLevel} PrivacyLevels Privacy level of a {@link StageInstance} object. + * @property {Status} Status The available statuses of the client. + * @property {StickerFormatType} StickerFormatTypes The value set for a sticker's format type. + * @property {StickerType} StickerTypes The value set for a sticker's type. + * @property {VerificationLevel} VerificationLevels The value set for the verification levels for a guild. + * @property {WebhookType} WebhookTypes The value set for a webhook's type. + * @property {WSEventType} WSEvents The type of a websocket message event. + */ diff --git a/node_modules/discord.js/src/util/DataResolver.js b/node_modules/discord.js/src/util/DataResolver.js index fbddbd5a..20d4abc3 100644 --- a/node_modules/discord.js/src/util/DataResolver.js +++ b/node_modules/discord.js/src/util/DataResolver.js @@ -5,18 +5,13 @@ const path = require('path'); const stream = require('stream'); const fetch = require('node-fetch'); const { Error: DiscordError, TypeError } = require('../errors'); -const { browser } = require('../util/Constants'); -const Util = require('../util/Util'); +const Invite = require('../structures/Invite'); /** * The DataResolver identifies different objects and tries to resolve a specific piece of information from them. * @private */ -class DataResolver { - constructor() { - throw new Error(`The ${this.constructor.name} class may not be instantiated.`); - } - +class DataResolver extends null { /** * Data that can be resolved to give an invite code. This can be: * * An invite code @@ -38,8 +33,7 @@ class DataResolver { * @returns {string} */ static resolveCode(data, regex) { - const match = regex.exec(data); - return match ? match[1] || data : data; + return data.matchAll(regex).next().value?.[1] ?? data; } /** @@ -48,7 +42,7 @@ class DataResolver { * @returns {string} */ static resolveInviteCode(data) { - return this.resolveCode(data, /discord(?:(?:app)?\.com\/invite|\.gg(?:\/invite)?)\/([\w-]{2,255})/i); + return this.resolveCode(data, Invite.INVITES_PATTERN); } /** @@ -57,7 +51,8 @@ class DataResolver { * @returns {string} */ static resolveGuildTemplateCode(data) { - return this.resolveCode(data, /discord(?:app)?\.(?:com\/template|new)\/([\w-]{2,255})/i); + const GuildTemplate = require('../structures/GuildTemplate'); + return this.resolveCode(data, GuildTemplate.GUILD_TEMPLATES_PATTERN); } /** @@ -110,26 +105,21 @@ class DataResolver { * @returns {Promise} */ static async resolveFile(resource) { - if (!browser && Buffer.isBuffer(resource)) return resource; - if (browser && resource instanceof ArrayBuffer) return Util.convertToBuffer(resource); - // eslint-disable-next-line no-undef - if (browser && resource instanceof Blob) return resource; - if (resource instanceof stream.Readable) return resource; - + if (Buffer.isBuffer(resource) || resource instanceof stream.Readable) return resource; if (typeof resource === 'string') { if (/^https?:\/\//.test(resource)) { const res = await fetch(resource); - return browser ? res.blob() : res.body; - } else if (!browser) { - return new Promise((resolve, reject) => { - const file = path.resolve(resource); - fs.stat(file, (err, stats) => { - if (err) return reject(err); - if (!stats.isFile()) return reject(new DiscordError('FILE_NOT_FOUND', file)); - return resolve(fs.createReadStream(file)); - }); - }); + return res.body; } + + return new Promise((resolve, reject) => { + const file = path.resolve(resource); + fs.stat(file, (err, stats) => { + if (err) return reject(err); + if (!stats.isFile()) return reject(new DiscordError('FILE_NOT_FOUND', file)); + return resolve(fs.createReadStream(file)); + }); + }); } throw new TypeError('REQ_RESOURCE_TYPE'); diff --git a/node_modules/discord.js/src/util/Intents.js b/node_modules/discord.js/src/util/Intents.js index e627c8bc..a47ca755 100644 --- a/node_modules/discord.js/src/util/Intents.js +++ b/node_modules/discord.js/src/util/Intents.js @@ -28,7 +28,7 @@ class Intents extends BitField {} * * `GUILDS` * * `GUILD_MEMBERS` * * `GUILD_BANS` - * * `GUILD_EMOJIS` + * * `GUILD_EMOJIS_AND_STICKERS` * * `GUILD_INTEGRATIONS` * * `GUILD_WEBHOOKS` * * `GUILD_INVITES` @@ -47,7 +47,7 @@ Intents.FLAGS = { GUILDS: 1 << 0, GUILD_MEMBERS: 1 << 1, GUILD_BANS: 1 << 2, - GUILD_EMOJIS: 1 << 3, + GUILD_EMOJIS_AND_STICKERS: 1 << 3, GUILD_INTEGRATIONS: 1 << 4, GUILD_WEBHOOKS: 1 << 5, GUILD_INVITES: 1 << 6, @@ -61,23 +61,4 @@ Intents.FLAGS = { DIRECT_MESSAGE_TYPING: 1 << 14, }; -/** - * Bitfield representing all privileged intents - * @type {number} - * @see {@link https://discord.com/developers/docs/topics/gateway#privileged-intents} - */ -Intents.PRIVILEGED = Intents.FLAGS.GUILD_MEMBERS | Intents.FLAGS.GUILD_PRESENCES; - -/** - * Bitfield representing all intents combined - * @type {number} - */ -Intents.ALL = Object.values(Intents.FLAGS).reduce((acc, p) => acc | p, 0); - -/** - * Bitfield representing all non-privileged intents - * @type {number} - */ -Intents.NON_PRIVILEGED = Intents.ALL & ~Intents.PRIVILEGED; - module.exports = Intents; diff --git a/node_modules/discord.js/src/util/LimitedCollection.js b/node_modules/discord.js/src/util/LimitedCollection.js index caa49780..f2266b2e 100644 --- a/node_modules/discord.js/src/util/LimitedCollection.js +++ b/node_modules/discord.js/src/util/LimitedCollection.js @@ -1,31 +1,151 @@ 'use strict'; -const Collection = require('./Collection.js'); +const { Collection } = require('@discordjs/collection'); +const { _cleanupSymbol } = require('./Constants.js'); +const { TypeError } = require('../errors/DJSError.js'); /** - * A Collection which holds a max amount of entries. The first key is deleted if the Collection has - * reached max size. + * @typedef {Function} SweepFilter + * @param {LimitedCollection} collection The collection being swept + * @returns {Function|null} Return `null` to skip sweeping, otherwise a function passed to `sweep()`, + * See {@link [Collection#sweep](https://discord.js.org/#/docs/collection/master/class/Collection?scrollTo=sweep)} + * for the definition of this function. + */ + +/** + * Options for defining the behavior of a LimitedCollection + * @typedef {Object} LimitedCollectionOptions + * @property {?number} [maxSize=0] The maximum size of the Collection + * @property {?Function} [keepOverLimit=null] A function, which is passed the value and key of an entry, ran to decide + * to keep an entry past the maximum size + * @property {?SweepFilter} [sweepFilter=null] A function ran every `sweepInterval` to determine how to sweep + * @property {?number} [sweepInterval=0] How frequently, in seconds, to sweep the collection. + */ + +/** + * A Collection which holds a max amount of entries and sweeps periodically. * @extends {Collection} - * @param {number} [maxSize=0] The maximum size of the Collection + * @param {LimitedCollectionOptions} [options={}] Options for constructing the Collection. * @param {Iterable} [iterable=null] Optional entries passed to the Map constructor. - * @private */ class LimitedCollection extends Collection { - constructor(maxSize = 0, iterable = null) { + constructor(options = {}, iterable) { + if (typeof options !== 'object' || options === null) { + throw new TypeError('INVALID_TYPE', 'options', 'object', true); + } + const { maxSize = Infinity, keepOverLimit = null, sweepInterval = 0, sweepFilter = null } = options; + + if (typeof maxSize !== 'number') { + throw new TypeError('INVALID_TYPE', 'maxSize', 'number'); + } + if (keepOverLimit !== null && typeof keepOverLimit !== 'function') { + throw new TypeError('INVALID_TYPE', 'keepOverLimit', 'function'); + } + if (typeof sweepInterval !== 'number') { + throw new TypeError('INVALID_TYPE', 'sweepInterval', 'number'); + } + if (sweepFilter !== null && typeof sweepFilter !== 'function') { + throw new TypeError('INVALID_TYPE', 'sweepFilter', 'function'); + } + super(iterable); + /** * The max size of the Collection. * @type {number} */ this.maxSize = maxSize; + + /** + * A function called to check if an entry should be kept when the Collection is at max size. + * @type {?Function} + */ + this.keepOverLimit = keepOverLimit; + + /** + * A function called every sweep interval that returns a function passed to `sweep`. + * @type {?SweepFilter} + */ + this.sweepFilter = sweepFilter; + + /** + * The id of the interval being used to sweep. + * @type {?Timeout} + */ + this.interval = + sweepInterval > 0 && sweepInterval !== Infinity && sweepFilter + ? setInterval(() => { + const sweepFn = this.sweepFilter(this); + if (sweepFn === null) return; + if (typeof sweepFn !== 'function') throw new TypeError('SWEEP_FILTER_RETURN'); + this.sweep(sweepFn); + }, sweepInterval * 1000).unref() + : null; } set(key, value) { if (this.maxSize === 0) return this; - if (this.size >= this.maxSize && !this.has(key)) this.delete(this.firstKey()); + if (this.size >= this.maxSize && !this.has(key)) { + for (const [k, v] of this.entries()) { + const keep = this.keepOverLimit?.(v, k, this) ?? false; + if (!keep) { + this.delete(k); + break; + } + } + } return super.set(key, value); } + /** + * Options for generating a filter function based on lifetime + * @typedef {Object} LifetimeFilterOptions + * @property {number} [lifetime=14400] How long an entry should stay in the collection before it is considered + * sweepable. + * @property {Function} [getComparisonTimestamp=`e => e.createdTimestamp`] A function that takes an entry, key, + * and the collection and returns a timestamp to compare against in order to determine the lifetime of the entry. + * @property {Function} [excludeFromSweep=`() => false`] A function that takes an entry, key, and the collection + * and returns a boolean, `true` when the entry should not be checked for sweepability. + */ + + /** + * Create a sweepFilter function that uses a lifetime to determine sweepability. + * @param {LifetimeFilterOptions} [options={}] The options used to generate the filter function + * @returns {SweepFilter} + */ + static filterByLifetime({ + lifetime = 14400, + getComparisonTimestamp = e => e?.createdTimestamp, + excludeFromSweep = () => false, + } = {}) { + if (typeof lifetime !== 'number') { + throw new TypeError('INVALID_TYPE', 'lifetime', 'number'); + } + if (typeof getComparisonTimestamp !== 'function') { + throw new TypeError('INVALID_TYPE', 'getComparisonTimestamp', 'function'); + } + if (typeof excludeFromSweep !== 'function') { + throw new TypeError('INVALID_TYPE', 'excludeFromSweep', 'function'); + } + return () => { + if (lifetime <= 0) return null; + const lifetimeMs = lifetime * 1000; + const now = Date.now(); + return (entry, key, coll) => { + if (excludeFromSweep(entry, key, coll)) { + return false; + } + const comparisonTimestamp = getComparisonTimestamp(entry, key, coll); + if (!comparisonTimestamp || typeof comparisonTimestamp !== 'number') return false; + return now - comparisonTimestamp > lifetimeMs; + }; + }; + } + + [_cleanupSymbol]() { + return this.interval ? () => clearInterval(this.interval) : null; + } + static get [Symbol.species]() { return Collection; } diff --git a/node_modules/discord.js/src/util/MessageFlags.js b/node_modules/discord.js/src/util/MessageFlags.js index 536cbd88..b91a1fc2 100644 --- a/node_modules/discord.js/src/util/MessageFlags.js +++ b/node_modules/discord.js/src/util/MessageFlags.js @@ -3,7 +3,7 @@ const BitField = require('./BitField'); /** - * Data structure that makes it easy to interact with an {@link Message#flags} bitfield. + * Data structure that makes it easy to interact with a {@link Message#flags} bitfield. * @extends {BitField} */ class MessageFlags extends BitField {} @@ -15,6 +15,12 @@ class MessageFlags extends BitField {} * @param {BitFieldResolvable} [bits=0] Bit(s) to read from */ +/** + * Bitfield of the packed bits + * @type {number} + * @name MessageFlags#bitfield + */ + /** * Numeric message flags. All available properties: * * `CROSSPOSTED` @@ -22,6 +28,9 @@ class MessageFlags extends BitField {} * * `SUPPRESS_EMBEDS` * * `SOURCE_MESSAGE_DELETED` * * `URGENT` + * * `HAS_THREAD` + * * `EPHEMERAL` + * * `LOADING` * @type {Object} * @see {@link https://discord.com/developers/docs/resources/channel#message-object-message-flags} */ @@ -31,6 +40,9 @@ MessageFlags.FLAGS = { SUPPRESS_EMBEDS: 1 << 2, SOURCE_MESSAGE_DELETED: 1 << 3, URGENT: 1 << 4, + HAS_THREAD: 1 << 5, + EPHEMERAL: 1 << 6, + LOADING: 1 << 7, }; module.exports = MessageFlags; diff --git a/node_modules/discord.js/src/util/Permissions.js b/node_modules/discord.js/src/util/Permissions.js index 98a28389..fceb0527 100644 --- a/node_modules/discord.js/src/util/Permissions.js +++ b/node_modules/discord.js/src/util/Permissions.js @@ -10,10 +10,9 @@ const BitField = require('./BitField'); */ class Permissions extends BitField { /** - * @name Permissions - * @kind constructor - * @memberof Permissions - * @param {PermissionResolvable} [bits=0] Bit(s) to read from + * Bitfield of the packed bits + * @type {bigint} + * @name Permissions#bitfield */ /** @@ -22,9 +21,19 @@ class Permissions extends BitField { * * A permission number * * An instance of Permissions * * An Array of PermissionResolvable - * @typedef {string|number|Permissions|PermissionResolvable[]} PermissionResolvable + * @typedef {string|bigint|Permissions|PermissionResolvable[]} PermissionResolvable */ + /** + * Gets all given bits that are missing from the bitfield. + * @param {BitFieldResolvable} bits Bit(s) to check for + * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override + * @returns {string[]} + */ + missing(bits, checkAdmin = true) { + return checkAdmin && this.has(this.constructor.FLAGS.ADMINISTRATOR) ? [] : super.missing(bits, checkAdmin); + } + /** * Checks whether the bitfield has a permission, or any of multiple permissions. * @param {PermissionResolvable} permission Permission(s) to check for @@ -78,54 +87,75 @@ class Permissions extends BitField { * * `MANAGE_NICKNAMES` (change other members' nicknames) * * `MANAGE_ROLES` * * `MANAGE_WEBHOOKS` - * * `MANAGE_EMOJIS` - * @type {Object} + * * `MANAGE_EMOJIS_AND_STICKERS` + * * `USE_APPLICATION_COMMANDS` + * * `REQUEST_TO_SPEAK` + * * `MANAGE_THREADS` + * * `USE_PUBLIC_THREADS` + * * `USE_PRIVATE_THREADS` + * * `USE_EXTERNAL_STICKERS` (use stickers from different guilds) + * @type {Object} * @see {@link https://discord.com/developers/docs/topics/permissions} */ Permissions.FLAGS = { - CREATE_INSTANT_INVITE: 1 << 0, - KICK_MEMBERS: 1 << 1, - BAN_MEMBERS: 1 << 2, - ADMINISTRATOR: 1 << 3, - MANAGE_CHANNELS: 1 << 4, - MANAGE_GUILD: 1 << 5, - ADD_REACTIONS: 1 << 6, - VIEW_AUDIT_LOG: 1 << 7, - PRIORITY_SPEAKER: 1 << 8, - STREAM: 1 << 9, - VIEW_CHANNEL: 1 << 10, - SEND_MESSAGES: 1 << 11, - SEND_TTS_MESSAGES: 1 << 12, - MANAGE_MESSAGES: 1 << 13, - EMBED_LINKS: 1 << 14, - ATTACH_FILES: 1 << 15, - READ_MESSAGE_HISTORY: 1 << 16, - MENTION_EVERYONE: 1 << 17, - USE_EXTERNAL_EMOJIS: 1 << 18, - VIEW_GUILD_INSIGHTS: 1 << 19, - CONNECT: 1 << 20, - SPEAK: 1 << 21, - MUTE_MEMBERS: 1 << 22, - DEAFEN_MEMBERS: 1 << 23, - MOVE_MEMBERS: 1 << 24, - USE_VAD: 1 << 25, - CHANGE_NICKNAME: 1 << 26, - MANAGE_NICKNAMES: 1 << 27, - MANAGE_ROLES: 1 << 28, - MANAGE_WEBHOOKS: 1 << 29, - MANAGE_EMOJIS: 1 << 30, + CREATE_INSTANT_INVITE: 1n << 0n, + KICK_MEMBERS: 1n << 1n, + BAN_MEMBERS: 1n << 2n, + ADMINISTRATOR: 1n << 3n, + MANAGE_CHANNELS: 1n << 4n, + MANAGE_GUILD: 1n << 5n, + ADD_REACTIONS: 1n << 6n, + VIEW_AUDIT_LOG: 1n << 7n, + PRIORITY_SPEAKER: 1n << 8n, + STREAM: 1n << 9n, + VIEW_CHANNEL: 1n << 10n, + SEND_MESSAGES: 1n << 11n, + SEND_TTS_MESSAGES: 1n << 12n, + MANAGE_MESSAGES: 1n << 13n, + EMBED_LINKS: 1n << 14n, + ATTACH_FILES: 1n << 15n, + READ_MESSAGE_HISTORY: 1n << 16n, + MENTION_EVERYONE: 1n << 17n, + USE_EXTERNAL_EMOJIS: 1n << 18n, + VIEW_GUILD_INSIGHTS: 1n << 19n, + CONNECT: 1n << 20n, + SPEAK: 1n << 21n, + MUTE_MEMBERS: 1n << 22n, + DEAFEN_MEMBERS: 1n << 23n, + MOVE_MEMBERS: 1n << 24n, + USE_VAD: 1n << 25n, + CHANGE_NICKNAME: 1n << 26n, + MANAGE_NICKNAMES: 1n << 27n, + MANAGE_ROLES: 1n << 28n, + MANAGE_WEBHOOKS: 1n << 29n, + MANAGE_EMOJIS_AND_STICKERS: 1n << 30n, + USE_APPLICATION_COMMANDS: 1n << 31n, + REQUEST_TO_SPEAK: 1n << 32n, + MANAGE_THREADS: 1n << 34n, + USE_PUBLIC_THREADS: 1n << 35n, + USE_PRIVATE_THREADS: 1n << 36n, + USE_EXTERNAL_STICKERS: 1n << 37n, }; /** * Bitfield representing every permission combined - * @type {number} + * @type {bigint} */ -Permissions.ALL = Object.values(Permissions.FLAGS).reduce((all, p) => all | p, 0); +Permissions.ALL = Object.values(Permissions.FLAGS).reduce((all, p) => all | p, 0n); /** * Bitfield representing the default permissions for users - * @type {number} + * @type {bigint} */ -Permissions.DEFAULT = 104324673; +Permissions.DEFAULT = BigInt(104324673); + +/** + * Bitfield representing the permissions required for moderators of stage channels + * @type {bigint} + */ +Permissions.STAGE_MODERATOR = + Permissions.FLAGS.MANAGE_CHANNELS | Permissions.FLAGS.MUTE_MEMBERS | Permissions.FLAGS.MOVE_MEMBERS; + +Permissions.defaultBit = BigInt(0); module.exports = Permissions; diff --git a/node_modules/discord.js/src/util/Snowflake.js b/node_modules/discord.js/src/util/Snowflake.js deleted file mode 100644 index bf1309c7..00000000 --- a/node_modules/discord.js/src/util/Snowflake.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict'; - -const Util = require('../util/Util'); - -// Discord epoch (2015-01-01T00:00:00.000Z) -const EPOCH = 1420070400000; -let INCREMENT = 0; - -/** - * A container for useful snowflake-related methods. - */ -class SnowflakeUtil { - constructor() { - throw new Error(`The ${this.constructor.name} class may not be instantiated.`); - } - - /** - * A Twitter snowflake, except the epoch is 2015-01-01T00:00:00.000Z - * ``` - * If we have a snowflake '266241948824764416' we can represent it as binary: - * - * 64 22 17 12 0 - * 000000111011000111100001101001000101000000 00001 00000 000000000000 - * number of ms since Discord epoch worker pid increment - * ``` - * @typedef {string} Snowflake - */ - - /** - * Generates a Discord snowflake. - * This hardcodes the worker ID as 1 and the process ID as 0. - * @param {number|Date} [timestamp=Date.now()] Timestamp or date of the snowflake to generate - * @returns {Snowflake} The generated snowflake - */ - static generate(timestamp = Date.now()) { - if (timestamp instanceof Date) timestamp = timestamp.getTime(); - if (typeof timestamp !== 'number' || isNaN(timestamp)) { - throw new TypeError( - `"timestamp" argument must be a number (received ${isNaN(timestamp) ? 'NaN' : typeof timestamp})`, - ); - } - if (INCREMENT >= 4095) INCREMENT = 0; - const BINARY = `${(timestamp - EPOCH).toString(2).padStart(42, '0')}0000100000${(INCREMENT++) - .toString(2) - .padStart(12, '0')}`; - return Util.binaryToID(BINARY); - } - - /** - * A deconstructed snowflake. - * @typedef {Object} DeconstructedSnowflake - * @property {number} timestamp Timestamp the snowflake was created - * @property {Date} date Date the snowflake was created - * @property {number} workerID Worker ID in the snowflake - * @property {number} processID Process ID in the snowflake - * @property {number} increment Increment in the snowflake - * @property {string} binary Binary representation of the snowflake - */ - - /** - * Deconstructs a Discord snowflake. - * @param {Snowflake} snowflake Snowflake to deconstruct - * @returns {DeconstructedSnowflake} Deconstructed snowflake - */ - static deconstruct(snowflake) { - const BINARY = Util.idToBinary(snowflake).toString(2).padStart(64, '0'); - const res = { - timestamp: parseInt(BINARY.substring(0, 42), 2) + EPOCH, - workerID: parseInt(BINARY.substring(42, 47), 2), - processID: parseInt(BINARY.substring(47, 52), 2), - increment: parseInt(BINARY.substring(52, 64), 2), - binary: BINARY, - }; - Object.defineProperty(res, 'date', { - get: function get() { - return new Date(this.timestamp); - }, - enumerable: true, - }); - return res; - } - - /** - * Discord's epoch value (2015-01-01T00:00:00.000Z). - * @type {number} - * @readonly - */ - static get EPOCH() { - return EPOCH; - } -} - -module.exports = SnowflakeUtil; diff --git a/node_modules/discord.js/src/util/Speaking.js b/node_modules/discord.js/src/util/Speaking.js deleted file mode 100644 index 5fda560e..00000000 --- a/node_modules/discord.js/src/util/Speaking.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; - -const BitField = require('./BitField'); - -/** - * Data structure that makes it easy to interact with a {@link VoiceConnection#speaking} - * and {@link guildMemberSpeaking} event bitfields. - * @extends {BitField} - */ -class Speaking extends BitField {} - -/** - * @name Speaking - * @kind constructor - * @memberof Speaking - * @param {BitFieldResolvable} [bits=0] Bit(s) to read from - */ - -/** - * Numeric speaking flags. All available properties: - * * `SPEAKING` - * * `SOUNDSHARE` - * * `PRIORITY_SPEAKING` - * @type {Object} - * @see {@link https://discord.com/developers/docs/topics/voice-connections#speaking} - */ -Speaking.FLAGS = { - SPEAKING: 1 << 0, - SOUNDSHARE: 1 << 1, - PRIORITY_SPEAKING: 1 << 2, -}; - -module.exports = Speaking; diff --git a/node_modules/discord.js/src/util/Structures.js b/node_modules/discord.js/src/util/Structures.js deleted file mode 100644 index 0c6ab35c..00000000 --- a/node_modules/discord.js/src/util/Structures.js +++ /dev/null @@ -1,112 +0,0 @@ -'use strict'; - -/** - * An extendable structure: - * * **`GuildEmoji`** - * * **`DMChannel`** - * * **`TextChannel`** - * * **`VoiceChannel`** - * * **`CategoryChannel`** - * * **`NewsChannel`** - * * **`StoreChannel`** - * * **`GuildMember`** - * * **`Guild`** - * * **`Message`** - * * **`MessageReaction`** - * * **`Presence`** - * * **`ClientPresence`** - * * **`VoiceState`** - * * **`Role`** - * * **`User`** - * @typedef {string} ExtendableStructure - */ - -/** - * Allows for the extension of built-in Discord.js structures that are instantiated by {@link BaseManager Managers}. - */ -class Structures { - constructor() { - throw new Error(`The ${this.constructor.name} class may not be instantiated.`); - } - - /** - * Retrieves a structure class. - * @param {string} structure Name of the structure to retrieve - * @returns {Function} - */ - static get(structure) { - if (typeof structure === 'string') return structures[structure]; - throw new TypeError(`"structure" argument must be a string (received ${typeof structure})`); - } - - /** - * Extends a structure. - * Make sure to extend all structures before instantiating your client. - * Extending after doing so may not work as expected. - * @param {ExtendableStructure} structure Name of the structure class to extend - * @param {Function} extender Function that takes the base class to extend as its only parameter and returns the - * extended class/prototype - * @returns {Function} Extended class/prototype returned from the extender - * @example - * const { Structures } = require('discord.js'); - * - * Structures.extend('Guild', Guild => { - * class CoolGuild extends Guild { - * constructor(client, data) { - * super(client, data); - * this.cool = true; - * } - * } - * - * return CoolGuild; - * }); - */ - static extend(structure, extender) { - if (!structures[structure]) throw new RangeError(`"${structure}" is not a valid extensible structure.`); - if (typeof extender !== 'function') { - const received = `(received ${typeof extender})`; - throw new TypeError( - `"extender" argument must be a function that returns the extended structure class/prototype ${received}.`, - ); - } - - const extended = extender(structures[structure]); - if (typeof extended !== 'function') { - const received = `(received ${typeof extended})`; - throw new TypeError(`The extender function must return the extended structure class/prototype ${received}.`); - } - - if (!(extended.prototype instanceof structures[structure])) { - const prototype = Object.getPrototypeOf(extended); - const received = `${extended.name || 'unnamed'}${prototype.name ? ` extends ${prototype.name}` : ''}`; - throw new Error( - 'The class/prototype returned from the extender function must extend the existing structure class/prototype' + - ` (received function ${received}; expected extension of ${structures[structure].name}).`, - ); - } - - structures[structure] = extended; - return extended; - } -} - -const structures = { - GuildEmoji: require('../structures/GuildEmoji'), - DMChannel: require('../structures/DMChannel'), - TextChannel: require('../structures/TextChannel'), - VoiceChannel: require('../structures/VoiceChannel'), - CategoryChannel: require('../structures/CategoryChannel'), - NewsChannel: require('../structures/NewsChannel'), - StoreChannel: require('../structures/StoreChannel'), - GuildMember: require('../structures/GuildMember'), - Guild: require('../structures/Guild'), - Message: require('../structures/Message'), - MessageReaction: require('../structures/MessageReaction'), - Presence: require('../structures/Presence').Presence, - ClientPresence: require('../structures/ClientPresence'), - VoiceState: require('../structures/VoiceState'), - Role: require('../structures/Role'), - User: require('../structures/User'), -}; - -module.exports = Structures; diff --git a/node_modules/discord.js/src/util/SystemChannelFlags.js b/node_modules/discord.js/src/util/SystemChannelFlags.js index 4d08b760..c4d16a6d 100644 --- a/node_modules/discord.js/src/util/SystemChannelFlags.js +++ b/node_modules/discord.js/src/util/SystemChannelFlags.js @@ -17,6 +17,12 @@ class SystemChannelFlags extends BitField {} * @param {SystemChannelFlagsResolvable} [bits=0] Bit(s) to read from */ +/** + * Bitfield of the packed bits + * @type {number} + * @name SystemChannelFlags#bitfield + */ + /** * Data that can be resolved to give a sytem channel flag bitfield. This can be: * * A string (see {@link SystemChannelFlags.FLAGS}) @@ -28,13 +34,15 @@ class SystemChannelFlags extends BitField {} /** * Numeric system channel flags. All available properties: - * * `WELCOME_MESSAGE_DISABLED` - * * `BOOST_MESSAGE_DISABLED` + * * `SUPPRESS_JOIN_NOTIFICATIONS` (Suppress member join notifications) + * * `SUPPRESS_PREMIUM_SUBSCRIPTIONS` (Suppress server boost notifications) + * * `SUPPRESS_GUILD_REMINDER_NOTIFICATIONS` (Suppress server setup tips) * @type {Object} */ SystemChannelFlags.FLAGS = { - WELCOME_MESSAGE_DISABLED: 1 << 0, - BOOST_MESSAGE_DISABLED: 1 << 1, + SUPPRESS_JOIN_NOTIFICATIONS: 1 << 0, + SUPPRESS_PREMIUM_SUBSCRIPTIONS: 1 << 1, + SUPPRESS_GUILD_REMINDER_NOTIFICATIONS: 1 << 2, }; module.exports = SystemChannelFlags; diff --git a/node_modules/discord.js/src/util/UserFlags.js b/node_modules/discord.js/src/util/UserFlags.js index 82c03edb..1661eaa1 100644 --- a/node_modules/discord.js/src/util/UserFlags.js +++ b/node_modules/discord.js/src/util/UserFlags.js @@ -14,11 +14,16 @@ class UserFlags extends BitField {} * @param {BitFieldResolvable} [bits=0] Bit(s) to read from */ +/** + * Bitfield of the packed bits + * @type {number} + * @name UserFlags#bitfield + */ + /** * Numeric user flags. All available properties: * * `DISCORD_EMPLOYEE` * * `PARTNERED_SERVER_OWNER` - * * `DISCORD_PARTNER` **(deprecated)** * * `HYPESQUAD_EVENTS` * * `BUGHUNTER_LEVEL_1` * * `HOUSE_BRAVERY` @@ -26,18 +31,16 @@ class UserFlags extends BitField {} * * `HOUSE_BALANCE` * * `EARLY_SUPPORTER` * * `TEAM_USER` - * * `SYSTEM` * * `BUGHUNTER_LEVEL_2` * * `VERIFIED_BOT` * * `EARLY_VERIFIED_BOT_DEVELOPER` - * * `VERIFIED_DEVELOPER` **(deprecated)** + * * `DISCORD_CERTIFIED_MODERATOR` * @type {Object} * @see {@link https://discord.com/developers/docs/resources/user#user-object-user-flags} */ UserFlags.FLAGS = { DISCORD_EMPLOYEE: 1 << 0, PARTNERED_SERVER_OWNER: 1 << 1, - DISCORD_PARTNER: 1 << 1, HYPESQUAD_EVENTS: 1 << 2, BUGHUNTER_LEVEL_1: 1 << 3, HOUSE_BRAVERY: 1 << 6, @@ -45,11 +48,10 @@ UserFlags.FLAGS = { HOUSE_BALANCE: 1 << 8, EARLY_SUPPORTER: 1 << 9, TEAM_USER: 1 << 10, - SYSTEM: 1 << 12, BUGHUNTER_LEVEL_2: 1 << 14, VERIFIED_BOT: 1 << 16, - EARLY_VERIFIED_DEVELOPER: 1 << 17, - VERIFIED_DEVELOPER: 1 << 17, + EARLY_VERIFIED_BOT_DEVELOPER: 1 << 17, + DISCORD_CERTIFIED_MODERATOR: 1 << 18, }; module.exports = UserFlags; diff --git a/node_modules/discord.js/src/util/Util.js b/node_modules/discord.js/src/util/Util.js index d1909fd9..44fc59f4 100644 --- a/node_modules/discord.js/src/util/Util.js +++ b/node_modules/discord.js/src/util/Util.js @@ -1,20 +1,18 @@ 'use strict'; const { parse } = require('path'); +const { Collection } = require('@discordjs/collection'); const fetch = require('node-fetch'); -const { Colors, DefaultOptions, Endpoints } = require('./Constants'); +const { Colors, Endpoints } = require('./Constants'); +const Options = require('./Options'); const { Error: DiscordError, RangeError, TypeError } = require('../errors'); const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k); const isObject = d => typeof d === 'object' && d !== null; /** - * Contains various general-purpose utility methods. These functions are also available on the base `Discord` object. + * Contains various general-purpose utility methods. */ -class Util { - constructor() { - throw new Error(`The ${this.constructor.name} class may not be instantiated.`); - } - +class Util extends null { /** * Flatten an object. Any properties that are collections will get converted to an array of keys. * @param {Object} obj The object to flatten. @@ -41,9 +39,9 @@ class Util { const valueOf = elemIsObj && typeof element.valueOf === 'function' ? element.valueOf() : null; // If it's a Collection, make the array of keys - if (element instanceof require('./Collection')) out[newProp] = Array.from(element.keys()); + if (element instanceof Collection) out[newProp] = Array.from(element.keys()); // If the valueOf is a Collection, use its array of keys - else if (valueOf instanceof require('./Collection')) out[newProp] = Array.from(valueOf.keys()); + else if (valueOf instanceof Collection) out[newProp] = Array.from(valueOf.keys()); // If it's an array, flatten each element else if (Array.isArray(element)) out[newProp] = element.map(e => Util.flatten(e)); // If it's an object with a primitive `valueOf`, use that value @@ -55,17 +53,39 @@ class Util { return out; } + /** + * Options for splitting a message. + * @typedef {Object} SplitOptions + * @property {number} [maxLength=2000] Maximum character length per message piece + * @property {string|string[]|RegExp|RegExp[]} [char='\n'] Character(s) or Regex(s) to split the message with, + * an array can be used to split multiple times + * @property {string} [prepend=''] Text to prepend to every piece except the first + * @property {string} [append=''] Text to append to every piece except the last + */ + /** * Splits a string into multiple chunks at a designated character that do not exceed a specific length. - * @param {StringResolvable} text Content to split + * @param {string} text Content to split * @param {SplitOptions} [options] Options controlling the behavior of the split * @returns {string[]} */ static splitMessage(text, { maxLength = 2000, char = '\n', prepend = '', append = '' } = {}) { - text = Util.resolveString(text); + text = Util.verifyString(text, RangeError, 'MESSAGE_CONTENT_TYPE', false); if (text.length <= maxLength) return [text]; - const splitText = text.split(char); - if (splitText.some(chunk => chunk.length > maxLength)) throw new RangeError('SPLIT_MAX_LEN'); + let splitText = [text]; + if (Array.isArray(char)) { + while (char.length > 0 && splitText.some(elem => elem.length > maxLength)) { + const currentChar = char.shift(); + if (currentChar instanceof RegExp) { + splitText = splitText.flatMap(chunk => chunk.match(currentChar)); + } else { + splitText = splitText.flatMap(chunk => chunk.split(currentChar)); + } + } + } else { + splitText = text.split(char); + } + if (splitText.some(elem => elem.length > maxLength)) throw new RangeError('SPLIT_MAX_LEN'); const messages = []; let msg = ''; for (const chunk of splitText) { @@ -78,19 +98,24 @@ class Util { return messages.concat(msg).filter(m => m); } + /** + * Options used to escape markdown. + * @typedef {Object} EscapeMarkdownOptions + * @property {boolean} [codeBlock=true] Whether to escape code blocks or not + * @property {boolean} [inlineCode=true] Whether to escape inline code or not + * @property {boolean} [bold=true] Whether to escape bolds or not + * @property {boolean} [italic=true] Whether to escape italics or not + * @property {boolean} [underline=true] Whether to escape underlines or not + * @property {boolean} [strikethrough=true] Whether to escape strikethroughs or not + * @property {boolean} [spoiler=true] Whether to escape spoilers or not + * @property {boolean} [codeBlockContent=true] Whether to escape text inside code blocks or not + * @property {boolean} [inlineCodeContent=true] Whether to escape text inside inline code or not + */ + /** * Escapes any Discord-flavour markdown in a string. * @param {string} text Content to escape - * @param {Object} [options={}] What types of markdown to escape - * @param {boolean} [options.codeBlock=true] Whether to escape code blocks or not - * @param {boolean} [options.inlineCode=true] Whether to escape inline code or not - * @param {boolean} [options.bold=true] Whether to escape bolds or not - * @param {boolean} [options.italic=true] Whether to escape italics or not - * @param {boolean} [options.underline=true] Whether to escape underlines or not - * @param {boolean} [options.strikethrough=true] Whether to escape strikethroughs or not - * @param {boolean} [options.spoiler=true] Whether to escape spoilers or not - * @param {boolean} [options.codeBlockContent=true] Whether to escape text inside code blocks or not - * @param {boolean} [options.inlineCodeContent=true] Whether to escape text inside inline code or not + * @param {EscapeMarkdownOptions} [options={}] Options for escaping the markdown * @returns {string} */ static escapeMarkdown( @@ -230,15 +255,22 @@ class Util { return text.replace(/\|\|/g, '\\|\\|'); } + /** + * @typedef {Object} FetchRecommendedShardsOptions + * @property {number} [guildsPerShard=1000] Number of guilds assigned per shard + * @property {number} [multipleOf=1] The multiple the shard count should round up to. (16 for large bot sharding) + */ + /** * Gets the recommended shard count from Discord. * @param {string} token Discord auth token - * @param {number} [guildsPerShard=1000] Number of guilds per shard + * @param {FetchRecommendedShardsOptions} [options] Options for fetching the recommended shard count * @returns {Promise} The recommended number of shards */ - static fetchRecommendedShards(token, guildsPerShard = 1000) { + static fetchRecommendedShards(token, { guildsPerShard = 1000, multipleOf = 1 } = {}) { if (!token) throw new DiscordError('TOKEN_MISSING'); - return fetch(`${DefaultOptions.http.api}/v${DefaultOptions.http.version}${Endpoints.botGateway}`, { + const defaults = Options.createDefault(); + return fetch(`${defaults.http.api}/v${defaults.http.version}${Endpoints.botGateway}`, { method: 'GET', headers: { Authorization: `Bot ${token.replace(/^Bot\s*/i, '')}` }, }) @@ -247,24 +279,37 @@ class Util { if (res.status === 401) throw new DiscordError('TOKEN_INVALID'); throw res; }) - .then(data => data.shards * (1000 / guildsPerShard)); + .then(data => Math.ceil((data.shards * (1000 / guildsPerShard)) / multipleOf) * multipleOf); } /** * Parses emoji info out of a string. The string must be one of: - * * A UTF-8 emoji (no ID) - * * A URL-encoded UTF-8 emoji (no ID) + * * A UTF-8 emoji (no id) + * * A URL-encoded UTF-8 emoji (no id) * * A Discord custom emoji (`<:name:id>` or ``) * @param {string} text Emoji string to parse - * @returns {Object} Object with `animated`, `name`, and `id` properties + * @returns {APIEmoji} Object with `animated`, `name`, and `id` properties * @private */ static parseEmoji(text) { if (text.includes('%')) text = decodeURIComponent(text); if (!text.includes(':')) return { animated: false, name: text, id: null }; - const m = text.match(/?/); - if (!m) return null; - return { animated: Boolean(m[1]), name: m[2], id: m[3] || null }; + const match = text.match(/?/); + return match && { animated: Boolean(match[1]), name: match[2], id: match[3] ?? null }; + } + + /** + * Resolves a partial emoji object from an {@link EmojiIdentifierResolvable}, without checking a Client. + * @param {EmojiIdentifierResolvable} emoji Emoji identifier to resolve + * @returns {?RawEmoji} + * @private + */ + static resolvePartialEmoji(emoji) { + if (!emoji) return null; + if (typeof emoji === 'string') return /^\d{17,19}$/.test(emoji) ? { id: emoji } : Util.parseEmoji(emoji); + const { id, name, animated } = emoji; + if (!id && !name) return null; + return { id, name, animated }; } /** @@ -298,35 +343,16 @@ class Util { } /** - * Converts an ArrayBuffer or string to a Buffer. - * @param {ArrayBuffer|string} ab ArrayBuffer to convert - * @returns {Buffer} - * @private - */ - static convertToBuffer(ab) { - if (typeof ab === 'string') ab = Util.str2ab(ab); - return Buffer.from(ab); - } - - /** - * Converts a string to an ArrayBuffer. - * @param {string} str String to convert - * @returns {ArrayBuffer} - * @private + * Options used to make an error object. + * @typedef {Object} MakeErrorOptions + * @property {string} name Error type + * @property {string} message Message for the error + * @property {string} stack Stack for the error */ - static str2ab(str) { - const buffer = new ArrayBuffer(str.length * 2); - const view = new Uint16Array(buffer); - for (var i = 0, strLen = str.length; i < strLen; i++) view[i] = str.charCodeAt(i); - return buffer; - } /** * Makes an Error from a plain info object. - * @param {Object} obj Error info - * @param {string} obj.name Error type - * @param {string} obj.message Message for the error - * @param {string} obj.stack Stack for the error + * @param {MakeErrorOptions} obj Error info * @returns {Error} * @private */ @@ -340,7 +366,7 @@ class Util { /** * Makes a plain error info object from an Error. * @param {Error} err Error to get info from - * @returns {Object} + * @returns {MakeErrorOptions} * @private */ static makePlainError(err) { @@ -371,22 +397,22 @@ class Util { } /** - * Data that can be resolved to give a string. This can be: - * * A string - * * An array (joined with a new line delimiter to give a string) - * * Any value - * @typedef {string|Array|*} StringResolvable - */ - - /** - * Resolves a StringResolvable to a string. - * @param {StringResolvable} data The string resolvable to resolve + * Verifies the provided data is a string, otherwise throws provided error. + * @param {string} data The string resolvable to resolve + * @param {Function} [error] The Error constructor to instantiate. Defaults to Error + * @param {string} [errorMessage] The error message to throw with. Defaults to "Expected string, got instead." + * @param {boolean} [allowEmpty=true] Whether an empty string should be allowed * @returns {string} */ - static resolveString(data) { - if (typeof data === 'string') return data; - if (Array.isArray(data)) return data.join('\n'); - return String(data); + static verifyString( + data, + error = Error, + errorMessage = `Expected a string, got ${data} instead.`, + allowEmpty = true, + ) { + if (typeof data !== 'string') throw new error(errorMessage); + if (!allowEmpty && data.length === 0) throw new error(errorMessage); + return data; } /** @@ -403,11 +429,11 @@ class Util { * - `YELLOW` * - `PURPLE` * - `LUMINOUS_VIVID_PINK` + * - `FUCHSIA` * - `GOLD` * - `ORANGE` * - `RED` * - `GREY` - * - `DARKER_GREY` * - `NAVY` * - `DARK_AQUA` * - `DARK_GREEN` @@ -418,6 +444,7 @@ class Util { * - `DARK_ORANGE` * - `DARK_RED` * - `DARK_GREY` + * - `DARKER_GREY` * - `LIGHT_GREY` * - `DARK_NAVY` * - `BLURPLE` @@ -437,7 +464,7 @@ class Util { if (typeof color === 'string') { if (color === 'RANDOM') return Math.floor(Math.random() * (0xffffff + 1)); if (color === 'DEFAULT') return 0; - color = Colors[color] || parseInt(color.replace('#', ''), 16); + color = Colors[color] ?? parseInt(color.replace('#', ''), 16); } else if (Array.isArray(color)) { color = (color[0] << 16) + (color[1] << 8) + color[2]; } @@ -449,7 +476,7 @@ class Util { } /** - * Sorts by Discord's position and ID. + * Sorts by Discord's position and id. * @param {Collection} collection Collection of objects to sort * @returns {Collection} */ @@ -470,11 +497,11 @@ class Util { * @param {Collection} sorted A collection of the objects sorted properly * @param {APIRouter} route Route to call PATCH on * @param {string} [reason] Reason for the change - * @returns {Promise} Updated item list, with `id` and `position` properties + * @returns {Promise} Updated item list, with `id` and `position` properties * @private */ static setPosition(item, position, relative, sorted, route, reason) { - let updatedItems = sorted.array(); + let updatedItems = [...sorted.values()]; Util.moveElementInArray(updatedItems, item, position, relative); updatedItems = updatedItems.map((r, i) => ({ id: r.id, position: i })); return route.patch({ data: updatedItems, reason }).then(() => updatedItems); @@ -488,7 +515,7 @@ class Util { * @private */ static basename(path, ext) { - let res = parse(path); + const res = parse(path); return ext && res.ext.startsWith(ext) ? res.name : res.base.split('?')[0]; } @@ -519,7 +546,7 @@ class Util { * @returns {Snowflake} * @private */ - static binaryToID(num) { + static binaryToId(num) { let dec = ''; while (num.length > 50) { @@ -555,49 +582,36 @@ class Util { /** * The content to have all mentions replaced by the equivalent text. * @param {string} str The string to be converted - * @param {Message} message The message object to reference + * @param {Channel} channel The channel the string was sent in * @returns {string} */ - static cleanContent(str, message) { + static cleanContent(str, channel) { str = str .replace(/<@!?[0-9]+>/g, input => { const id = input.replace(/<|!|>|@/g, ''); - if (message.channel.type === 'dm') { - const user = message.client.users.cache.get(id); + if (channel.type === 'DM') { + const user = channel.client.users.cache.get(id); return user ? Util.removeMentions(`@${user.username}`) : input; } - const member = message.channel.guild.members.cache.get(id); + const member = channel.guild.members.cache.get(id); if (member) { return Util.removeMentions(`@${member.displayName}`); } else { - const user = message.client.users.cache.get(id); + const user = channel.client.users.cache.get(id); return user ? Util.removeMentions(`@${user.username}`) : input; } }) .replace(/<#[0-9]+>/g, input => { - const channel = message.client.channels.cache.get(input.replace(/<|#|>/g, '')); - return channel ? `#${channel.name}` : input; + const mentionedChannel = channel.client.channels.cache.get(input.replace(/<|#|>/g, '')); + return mentionedChannel ? `#${mentionedChannel.name}` : input; }) .replace(/<@&[0-9]+>/g, input => { - if (message.channel.type === 'dm') return input; - const role = message.guild.roles.cache.get(input.replace(/<|@|>|&/g, '')); + if (channel.type === 'DM') return input; + const role = channel.guild.roles.cache.get(input.replace(/<|@|>|&/g, '')); return role ? `@${role.name}` : input; }); - if (message.client.options.disableMentions === 'everyone') { - str = str.replace(/@([^<>@ ]*)/gmsu, (match, target) => { - if (target.match(/^[&!]?\d+$/)) { - return `@${target}`; - } else { - return `@\u200b${target}`; - } - }); - } - if (message.client.options.disableMentions === 'all') { - return Util.removeMentions(str); - } else { - return str; - } + return str; } /** diff --git a/node_modules/discord.js/typings/index.d.ts b/node_modules/discord.js/typings/index.d.ts index e0be3c61..2639fb12 100644 --- a/node_modules/discord.js/typings/index.d.ts +++ b/node_modules/discord.js/typings/index.d.ts @@ -1,3255 +1,4648 @@ -declare enum ChannelType { - text = 0, - dm = 1, - voice = 2, - group = 3, - category = 4, - news = 5, - store = 6, - unknown = 7, -} - -declare module 'discord.js' { - import BaseCollection from '@discordjs/collection'; - import { ChildProcess } from 'child_process'; - import { EventEmitter } from 'events'; - import { PathLike } from 'fs'; - import { Readable, Stream, Writable } from 'stream'; - import * as WebSocket from 'ws'; - - export const version: string; - - //#region Classes - - export class Activity { - constructor(presence: Presence, data?: object); - public applicationID: Snowflake | null; - public assets: RichPresenceAssets | null; - public readonly createdAt: Date; - public createdTimestamp: number; - public details: string | null; - public emoji: Emoji | null; - public flags: Readonly; - public name: string; - public party: { - id: string | null; - size: [number, number]; - } | null; - public state: string | null; - public timestamps: { - start: Date | null; - end: Date | null; - } | null; - public type: ActivityType; - public url: string | null; - public equals(activity: Activity): boolean; - } - - export class ActivityFlags extends BitField { - public static FLAGS: Record; - public static resolve(bit?: BitFieldResolvable): number; - } - - export class APIMessage { - constructor(target: MessageTarget, options: MessageOptions | WebhookMessageOptions); - public data: object | null; - public readonly isUser: boolean; - public readonly isWebhook: boolean; - public files: object[] | null; - public options: MessageOptions | WebhookMessageOptions; - public target: MessageTarget; - - public static create( - target: MessageTarget, - content: APIMessageContentResolvable, - options?: undefined, - extra?: MessageOptions | WebhookMessageOptions, - ): APIMessage; - public static create( - target: MessageTarget, - content: StringResolvable, - options: MessageOptions | WebhookMessageOptions | MessageAdditions, - extra?: MessageOptions | WebhookMessageOptions, - ): APIMessage; - public static partitionMessageAdditions( - items: readonly (MessageEmbed | MessageAttachment)[], - ): [MessageEmbed[], MessageAttachment[]]; - public static resolveFile(fileLike: BufferResolvable | Stream | FileOptions | MessageAttachment): Promise; - public static transformOptions( - content: APIMessageContentResolvable, - options?: undefined, - extra?: MessageOptions | WebhookMessageOptions, - isWebhook?: boolean, - ): MessageOptions | WebhookMessageOptions; - public static transformOptions( - content: StringResolvable, - options: MessageOptions | WebhookMessageOptions | MessageAdditions, - extra?: MessageOptions | WebhookMessageOptions, - isWebhook?: boolean, - ): MessageOptions | WebhookMessageOptions; - - public makeContent(): string | string[] | undefined; - public resolve(): Promise; - public resolveData(): this; - public resolveFiles(): Promise; - public split(): APIMessage[]; - } - - export abstract class Application { - constructor(client: Client, data: object); - public readonly createdAt: Date; - public readonly createdTimestamp: number; - public description: string; - public icon: string; - public id: Snowflake; - public name: string; - public coverImage(options?: ImageURLOptions): string; - public fetchAssets(): Promise; - public iconURL(options?: ImageURLOptions): string; - public toJSON(): object; - public toString(): string; - } - - export class Base { - constructor(client: Client); - public readonly client: Client; - public toJSON(...props: { [key: string]: boolean | string }[]): object; - public valueOf(): string; - } - - export class BaseClient extends EventEmitter { - constructor(options?: ClientOptions); - private _timeouts: Set; - private _intervals: Set; - private _immediates: Set; - private readonly api: object; - private rest: object; - private decrementMaxListeners(): void; - private incrementMaxListeners(): void; - - public options: ClientOptions; - public clearInterval(interval: NodeJS.Timeout): void; - public clearTimeout(timeout: NodeJS.Timeout): void; - public clearImmediate(timeout: NodeJS.Immediate): void; - public destroy(): void; - public setInterval(fn: (...args: any[]) => void, delay: number, ...args: any[]): NodeJS.Timeout; - public setTimeout(fn: (...args: any[]) => void, delay: number, ...args: any[]): NodeJS.Timeout; - public setImmediate(fn: (...args: any[]) => void, ...args: any[]): NodeJS.Immediate; - public toJSON(...props: { [key: string]: boolean | string }[]): object; - } - - export class BaseGuildEmoji extends Emoji { - constructor(client: Client, data: object, guild: Guild); - private _roles: string[]; - - public available: boolean | null; - public readonly createdAt: Date; - public readonly createdTimestamp: number; - public guild: Guild | GuildPreview; - public id: Snowflake; - public managed: boolean | null; - public requiresColons: boolean | null; - } - - class BroadcastDispatcher extends VolumeMixin(StreamDispatcher) { - public broadcast: VoiceBroadcast; - } - - export class BitField { - constructor(bits?: BitFieldResolvable); - public bitfield: number; - public add(...bits: BitFieldResolvable[]): BitField; - public any(bit: BitFieldResolvable): boolean; - public equals(bit: BitFieldResolvable): boolean; - public freeze(): Readonly>; - public has(bit: BitFieldResolvable): boolean; - public missing(bits: BitFieldResolvable, ...hasParam: readonly unknown[]): S[]; - public remove(...bits: BitFieldResolvable[]): BitField; - public serialize(...hasParam: readonly unknown[]): Record; - public toArray(...hasParam: readonly unknown[]): S[]; - public toJSON(): number; - public valueOf(): number; - public [Symbol.iterator](): IterableIterator; - public static FLAGS: object; - public static resolve(bit?: BitFieldResolvable): number; - } - - export class CategoryChannel extends GuildChannel { - public readonly children: Collection; - public type: 'category'; - } - - export class Channel extends Base { - constructor(client: Client, data?: object); - public readonly createdAt: Date; - public readonly createdTimestamp: number; - public deleted: boolean; - public id: Snowflake; - public type: keyof typeof ChannelType; - public delete(reason?: string): Promise; - public fetch(force?: boolean): Promise; - public isText(): this is TextChannel | DMChannel | NewsChannel; - public toString(): string; - } - - export class Client extends BaseClient { - constructor(options?: ClientOptions); - private actions: object; - private _eval(script: string): any; - private _validateOptions(options?: ClientOptions): void; - - public channels: ChannelManager; - public readonly emojis: GuildEmojiManager; - public guilds: GuildManager; - public readyAt: Date | null; - public readonly readyTimestamp: number | null; - public shard: ShardClientUtil | null; - public token: string | null; - public readonly uptime: number | null; - public user: ClientUser | null; - public users: UserManager; - public voice: ClientVoiceManager | null; - public ws: WebSocketManager; - public destroy(): void; - public fetchApplication(): Promise; - public fetchGuildPreview(guild: GuildResolvable): Promise; - public fetchInvite(invite: InviteResolvable): Promise; - public fetchGuildTemplate(template: GuildTemplateResolvable): Promise; - public fetchVoiceRegions(): Promise>; - public fetchWebhook(id: Snowflake, token?: string): Promise; - public generateInvite(options?: InviteGenerationOptions | PermissionResolvable): Promise; - public login(token?: string): Promise; - public sweepMessages(lifetime?: number): number; - public toJSON(): object; - - public on(event: K, listener: (...args: ClientEvents[K]) => void): this; - public on( - event: Exclude, - listener: (...args: any[]) => void, - ): this; - - public once(event: K, listener: (...args: ClientEvents[K]) => void): this; - public once( - event: Exclude, - listener: (...args: any[]) => void, - ): this; - - public emit(event: K, ...args: ClientEvents[K]): boolean; - public emit(event: Exclude, ...args: any[]): boolean; - - public off(event: K, listener: (...args: ClientEvents[K]) => void): this; - public off( - event: Exclude, - listener: (...args: any[]) => void, - ): this; - - public removeAllListeners(event?: K): this; - public removeAllListeners(event?: Exclude): this; - } - - export class ClientApplication extends Application { - public botPublic: boolean | null; - public botRequireCodeGrant: boolean | null; - public cover: string | null; - public owner: User | Team | null; - public rpcOrigins: string[]; - } - - export class ClientUser extends User { - public mfaEnabled: boolean; - public verified: boolean; - public setActivity(options?: ActivityOptions): Promise; - public setActivity(name: string, options?: ActivityOptions): Promise; - public setAFK(afk: boolean): Promise; - public setAvatar(avatar: BufferResolvable | Base64Resolvable): Promise; - public setPresence(data: PresenceData): Promise; - public setStatus(status: PresenceStatusData, shardID?: number | number[]): Promise; - public setUsername(username: string): Promise; - } - - export class ClientVoiceManager { - constructor(client: Client); - public readonly client: Client; - public connections: Collection; - public broadcasts: VoiceBroadcast[]; - - private joinChannel(channel: VoiceChannel): Promise; - - public createBroadcast(): VoiceBroadcast; - } - - export abstract class Collector extends EventEmitter { - constructor(client: Client, filter: CollectorFilter, options?: CollectorOptions); - private _timeout: NodeJS.Timeout | null; - private _idletimeout: NodeJS.Timeout | null; - - public readonly client: Client; - public collected: Collection; - public ended: boolean; - public filter: CollectorFilter; - public readonly next: Promise; - public options: CollectorOptions; - public checkEnd(): void; - public handleCollect(...args: any[]): void; - public handleDispose(...args: any[]): void; - public stop(reason?: string): void; - public resetTimer(options?: { time?: number; idle?: number }): void; - public [Symbol.asyncIterator](): AsyncIterableIterator; - public toJSON(): object; - - protected listener: (...args: any[]) => void; - public abstract collect(...args: any[]): K; - public abstract dispose(...args: any[]): K; - public abstract endReason(): void; - - public on(event: 'collect' | 'dispose', listener: (...args: any[]) => void): this; - public on(event: 'end', listener: (collected: Collection, reason: string) => void): this; - - public once(event: 'collect' | 'dispose', listener: (...args: any[]) => void): this; - public once(event: 'end', listener: (collected: Collection, reason: string) => void): this; - } - - type AllowedImageFormat = 'webp' | 'png' | 'jpg' | 'jpeg' | 'gif'; - - export const Constants: { - Package: { - name: string; - version: string; - description: string; - author: string; - license: string; - main: PathLike; - types: PathLike; - homepage: string; - keywords: string[]; - bugs: { url: string }; - repository: { type: string; url: string }; - browser: { [key: string]: boolean }; - scripts: { [key: string]: string }; - engines: { [key: string]: string }; - dependencies: { [key: string]: string }; - peerDependencies: { [key: string]: string }; - devDependencies: { [key: string]: string }; - [key: string]: any; - }; - browser: boolean; - DefaultOptions: ClientOptions; - UserAgent: string | null; - Endpoints: { - botGateway: string; - invite: (root: string, code: string) => string; - CDN: ( - root: string, - ) => { - Asset: (name: string) => string; - DefaultAvatar: (id: string | number) => string; - Emoji: (emojiID: string, format: 'png' | 'gif') => string; - Avatar: (userID: string | number, hash: string, format: 'default' | AllowedImageFormat, size: number) => string; - Banner: (guildID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; - Icon: (userID: string | number, hash: string, format: 'default' | AllowedImageFormat, size: number) => string; - AppIcon: (userID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; - AppAsset: (userID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; - GDMIcon: (userID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; - Splash: (guildID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; - DiscoverySplash: (guildID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; - TeamIcon: (teamID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; - }; - }; - WSCodes: { - 1000: 'WS_CLOSE_REQUESTED'; - 4004: 'TOKEN_INVALID'; - 4010: 'SHARDING_INVALID'; - 4011: 'SHARDING_REQUIRED'; - }; - Events: { - RATE_LIMIT: 'rateLimit'; - CLIENT_READY: 'ready'; - RESUMED: 'resumed'; - GUILD_CREATE: 'guildCreate'; - GUILD_DELETE: 'guildDelete'; - GUILD_UPDATE: 'guildUpdate'; - INVITE_CREATE: 'inviteCreate'; - INVITE_DELETE: 'inviteDelete'; - GUILD_UNAVAILABLE: 'guildUnavailable'; - GUILD_MEMBER_ADD: 'guildMemberAdd'; - GUILD_MEMBER_REMOVE: 'guildMemberRemove'; - GUILD_MEMBER_UPDATE: 'guildMemberUpdate'; - GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable'; - GUILD_MEMBER_SPEAKING: 'guildMemberSpeaking'; - GUILD_MEMBERS_CHUNK: 'guildMembersChunk'; - GUILD_INTEGRATIONS_UPDATE: 'guildIntegrationsUpdate'; - GUILD_ROLE_CREATE: 'roleCreate'; - GUILD_ROLE_DELETE: 'roleDelete'; - GUILD_ROLE_UPDATE: 'roleUpdate'; - GUILD_EMOJI_CREATE: 'emojiCreate'; - GUILD_EMOJI_DELETE: 'emojiDelete'; - GUILD_EMOJI_UPDATE: 'emojiUpdate'; - GUILD_BAN_ADD: 'guildBanAdd'; - GUILD_BAN_REMOVE: 'guildBanRemove'; - CHANNEL_CREATE: 'channelCreate'; - CHANNEL_DELETE: 'channelDelete'; - CHANNEL_UPDATE: 'channelUpdate'; - CHANNEL_PINS_UPDATE: 'channelPinsUpdate'; - MESSAGE_CREATE: 'message'; - MESSAGE_DELETE: 'messageDelete'; - MESSAGE_UPDATE: 'messageUpdate'; - MESSAGE_BULK_DELETE: 'messageDeleteBulk'; - MESSAGE_REACTION_ADD: 'messageReactionAdd'; - MESSAGE_REACTION_REMOVE: 'messageReactionRemove'; - MESSAGE_REACTION_REMOVE_ALL: 'messageReactionRemoveAll'; - USER_UPDATE: 'userUpdate'; - PRESENCE_UPDATE: 'presenceUpdate'; - VOICE_STATE_UPDATE: 'voiceStateUpdate'; - VOICE_BROADCAST_SUBSCRIBE: 'subscribe'; - VOICE_BROADCAST_UNSUBSCRIBE: 'unsubscribe'; - TYPING_START: 'typingStart'; - WEBHOOKS_UPDATE: 'webhookUpdate'; - DISCONNECT: 'disconnect'; - RECONNECTING: 'reconnecting'; - ERROR: 'error'; - WARN: 'warn'; - DEBUG: 'debug'; - SHARD_DISCONNECT: 'shardDisconnect'; - SHARD_ERROR: 'shardError'; - SHARD_RECONNECTING: 'shardReconnecting'; - SHARD_READY: 'shardReady'; - SHARD_RESUME: 'shardResume'; - INVALIDATED: 'invalidated'; - RAW: 'raw'; - }; - ShardEvents: { - CLOSE: 'close'; - DESTROYED: 'destroyed'; - INVALID_SESSION: 'invalidSession'; - READY: 'ready'; - RESUMED: 'resumed'; - }; - PartialTypes: { - [K in PartialTypes]: K; - }; - WSEvents: { - [K in WSEventType]: K; - }; - Colors: { - DEFAULT: 0x000000; - WHITE: 0xffffff; - AQUA: 0x1abc9c; - GREEN: 0x2ecc71; - BLUE: 0x3498db; - YELLOW: 0xffff00; - PURPLE: 0x9b59b6; - LUMINOUS_VIVID_PINK: 0xe91e63; - GOLD: 0xf1c40f; - ORANGE: 0xe67e22; - RED: 0xe74c3c; - GREY: 0x95a5a6; - NAVY: 0x34495e; - DARK_AQUA: 0x11806a; - DARK_GREEN: 0x1f8b4c; - DARK_BLUE: 0x206694; - DARK_PURPLE: 0x71368a; - DARK_VIVID_PINK: 0xad1457; - DARK_GOLD: 0xc27c0e; - DARK_ORANGE: 0xa84300; - DARK_RED: 0x992d22; - DARK_GREY: 0x979c9f; - DARKER_GREY: 0x7f8c8d; - LIGHT_GREY: 0xbcc0c0; - DARK_NAVY: 0x2c3e50; - BLURPLE: 0x7289da; - GREYPLE: 0x99aab5; - DARK_BUT_NOT_BLACK: 0x2c2f33; - NOT_QUITE_BLACK: 0x23272a; - }; - Status: { - READY: 0; - CONNECTING: 1; - RECONNECTING: 2; - IDLE: 3; - NEARLY: 4; - DISCONNECTED: 5; - }; - OPCodes: { - DISPATCH: 0; - HEARTBEAT: 1; - IDENTIFY: 2; - STATUS_UPDATE: 3; - VOICE_STATE_UPDATE: 4; - VOICE_GUILD_PING: 5; - RESUME: 6; - RECONNECT: 7; - REQUEST_GUILD_MEMBERS: 8; - INVALID_SESSION: 9; - HELLO: 10; - HEARTBEAT_ACK: 11; - }; - APIErrors: APIErrors; - VoiceStatus: { - CONNECTED: 0; - CONNECTING: 1; - AUTHENTICATING: 2; - RECONNECTING: 3; - DISCONNECTED: 4; - }; - VoiceOPCodes: { - IDENTIFY: 0; - SELECT_PROTOCOL: 1; - READY: 2; - HEARTBEAT: 3; - SESSION_DESCRIPTION: 4; - SPEAKING: 5; - HELLO: 8; - CLIENT_CONNECT: 12; - CLIENT_DISCONNECT: 13; - }; - ChannelTypes: { - TEXT: 0; - DM: 1; - VOICE: 2; - GROUP: 3; - CATEGORY: 4; - NEWS: 5; - STORE: 6; - }; - ClientApplicationAssetTypes: { - SMALL: 1; - BIG: 2; - }; - MessageTypes: MessageType[]; - ActivityTypes: ActivityType[]; - ExplicitContentFilterLevels: ExplicitContentFilterLevel[]; - DefaultMessageNotifications: DefaultMessageNotifications[]; - VerificationLevels: VerificationLevel[]; - MembershipStates: 'INVITED' | 'ACCEPTED'; +import { + blockQuote, + bold, + codeBlock, + hideLinkEmbed, + hyperlink, + inlineCode, + italic, + quote, + strikethrough, + time, + TimestampStyles, + TimestampStylesString, + underscore, + spoiler, +} from '@discordjs/builders'; +import { Collection } from '@discordjs/collection'; +import { ChildProcess } from 'child_process'; +import { + APIActionRowComponent, + APIApplicationCommand, + APIApplicationCommandInteractionData, + APIApplicationCommandInteractionDataOption, + APIApplicationCommandPermission, + APIAuditLogChange, + APIEmoji, + APIInteractionDataResolvedChannel, + APIInteractionDataResolvedGuildMember, + APIInteractionGuildMember, + APIMessage, + APIMessageComponent, + APIOverwrite, + APIPartialChannel, + APIPartialEmoji, + APIPartialGuild, + APIRole, + APITemplateSerializedSourceGuild, + APIUser, + GatewayVoiceServerUpdateDispatchData, + GatewayVoiceStateUpdateDispatchData, + Snowflake, +} from 'discord-api-types/v9'; +import { EventEmitter } from 'events'; +import { Stream } from 'stream'; +import { MessagePort, Worker } from 'worker_threads'; +import * as WebSocket from 'ws'; +import { + ActivityTypes, + ApplicationCommandOptionTypes, + ApplicationCommandPermissionTypes, + ChannelTypes, + DefaultMessageNotificationLevels, + ExplicitContentFilterLevels, + InteractionResponseTypes, + InteractionTypes, + InviteTargetType, + MembershipStates, + MessageButtonStyles, + MessageComponentTypes, + MFALevels, + NSFWLevels, + OverwriteTypes, + PremiumTiers, + PrivacyLevels, + StickerFormatTypes, + StickerTypes, + VerificationLevels, + WebhookTypes, +} from './enums'; +import { + RawActivityData, + RawAnonymousGuildData, + RawApplicationCommandData, + RawApplicationData, + RawBaseGuildData, + RawChannelData, + RawClientApplicationData, + RawCommandInteractionData, + RawDMChannelData, + RawEmojiData, + RawGuildAuditLogData, + RawGuildAuditLogEntryData, + RawGuildBanData, + RawGuildChannelData, + RawGuildData, + RawGuildEmojiData, + RawGuildMemberData, + RawGuildPreviewData, + RawGuildTemplateData, + RawIntegrationApplicationData, + RawIntegrationData, + RawInteractionData, + RawInviteData, + RawInviteGuildData, + RawInviteStageInstance, + RawMessageAttachementData, + RawMessageButtonInteractionData, + RawMessageComponentInteractionData, + RawMessageData, + RawMessagePayloadData, + RawMessageReactionData, + RawMessageSelectMenuInteractionData, + RawOAuth2GuildData, + RawPartialGroupDMChannelData, + RawPartialMessageData, + RawPermissionOverwriteData, + RawPresenceData, + RawReactionEmojiData, + RawRichPresenceAssets, + RawRoleData, + RawStageInstanceData, + RawStickerData, + RawStickerPackData, + RawTeamData, + RawTeamMemberData, + RawThreadChannelData, + RawThreadMemberData, + RawTypingData, + RawUserData, + RawVoiceRegionData, + RawVoiceStateData, + RawWebhookData, + RawWelcomeChannelData, + RawWelcomeScreenData, + RawWidgetData, + RawWidgetMemberData, +} from './rawDataTypes'; + +//#region Classes + +export class Activity { + public constructor(presence: Presence, data?: RawActivityData); + public applicationId: Snowflake | null; + public assets: RichPresenceAssets | null; + public buttons: string[]; + public readonly createdAt: Date; + public createdTimestamp: number; + public details: string | null; + public emoji: Emoji | null; + public flags: Readonly; + public id: Snowflake; + public name: string; + public party: { + id: string | null; + size: [number, number]; + } | null; + public platform: ActivityPlatform | null; + public sessionId: string | null; + public state: string | null; + public syncId: string | null; + public timestamps: { + start: Date | null; + end: Date | null; + } | null; + public type: ActivityType; + public url: string | null; + public equals(activity: Activity): boolean; +} + +export class ActivityFlags extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; +} + +export abstract class AnonymousGuild extends BaseGuild { + public constructor(client: Client, data: RawAnonymousGuildData, immediatePatch?: boolean); + public banner: string | null; + public description: string | null; + public nsfwLevel: NSFWLevel; + public splash: string | null; + public vanityURLCode: string | null; + public verificationLevel: VerificationLevel; + public bannerURL(options?: StaticImageURLOptions): string | null; + public splashURL(options?: StaticImageURLOptions): string | null; +} + +export abstract class Application extends Base { + public constructor(client: Client, data: RawApplicationData); + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public description: string | null; + public icon: string | null; + public id: Snowflake; + public name: string | null; + public coverURL(options?: StaticImageURLOptions): string | null; + public fetchAssets(): Promise; + public iconURL(options?: StaticImageURLOptions): string | null; + public toJSON(): unknown; + public toString(): string | null; +} + +export class ApplicationCommand extends Base { + public constructor(client: Client, data: RawApplicationCommandData, guild?: Guild, guildId?: Snowflake); + public applicationId: Snowflake; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public defaultPermission: boolean; + public description: string; + public guild: Guild | null; + public guildId: Snowflake | null; + public readonly manager: ApplicationCommandManager; + public id: Snowflake; + public name: string; + public options: ApplicationCommandOption[]; + public permissions: ApplicationCommandPermissionsManager< + PermissionsFetchType, + PermissionsFetchType, + PermissionsFetchType, + Guild | null, + Snowflake + >; + public delete(): Promise>; + public edit(data: ApplicationCommandData): Promise>; + private static transformOption(option: ApplicationCommandOptionData, received?: boolean): unknown; +} + +export type ApplicationResolvable = Application | Activity | Snowflake; + +export class ApplicationFlags extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; +} + +export class Base { + public constructor(client: Client); + public readonly client: Client; + public toJSON(...props: Record[]): unknown; + public valueOf(): string; +} + +export class BaseClient extends EventEmitter { + public constructor(options?: ClientOptions | WebhookClientOptions); + private readonly api: unknown; + private rest: unknown; + private decrementMaxListeners(): void; + private incrementMaxListeners(): void; + + public options: ClientOptions | WebhookClientOptions; + public destroy(): void; + public toJSON(...props: Record[]): unknown; +} + +export abstract class BaseGuild extends Base { + public constructor(client: Client, data: RawBaseGuildData); + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public features: GuildFeatures[]; + public icon: string | null; + public id: Snowflake; + public name: string; + public readonly nameAcronym: string; + public readonly partnered: boolean; + public readonly verified: boolean; + public fetch(): Promise; + public iconURL(options?: ImageURLOptions): string | null; + public toString(): string; +} + +export class BaseGuildEmoji extends Emoji { + public constructor(client: Client, data: RawGuildEmojiData, guild: Guild | GuildPreview); + public available: boolean | null; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public guild: Guild | GuildPreview; + public id: Snowflake; + public managed: boolean | null; + public requiresColons: boolean | null; +} + +export class BaseGuildVoiceChannel extends GuildChannel { + public constructor(guild: Guild, data?: RawGuildChannelData); + public readonly members: Collection; + public readonly full: boolean; + public readonly joinable: boolean; + public rtcRegion: string | null; + public bitrate: number; + public userLimit: number; + public setRTCRegion(region: string | null): Promise; +} + +export class BaseMessageComponent { + public constructor(data?: BaseMessageComponent | BaseMessageComponentOptions); + public type: MessageComponentType | null; + private static create( + data: MessageComponentOptions, + client?: Client | WebhookClient, + skipValidation?: boolean, + ): MessageComponent | undefined; + private static resolveType(type: MessageComponentTypeResolvable): MessageComponentType; +} + +export class BitField { + public constructor(bits?: BitFieldResolvable); + public bitfield: N; + public add(...bits: BitFieldResolvable[]): BitField; + public any(bit: BitFieldResolvable): boolean; + public equals(bit: BitFieldResolvable): boolean; + public freeze(): Readonly>; + public has(bit: BitFieldResolvable): boolean; + public missing(bits: BitFieldResolvable, ...hasParams: readonly unknown[]): S[]; + public remove(...bits: BitFieldResolvable[]): BitField; + public serialize(...hasParams: readonly unknown[]): Record; + public toArray(...hasParams: readonly unknown[]): S[]; + public toJSON(): N extends number ? number : string; + public valueOf(): N; + public [Symbol.iterator](): IterableIterator; + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number | bigint; +} + +export class ButtonInteraction extends MessageComponentInteraction { + public constructor(client: Client, data: RawMessageButtonInteractionData); + public componentType: 'BUTTON'; +} + +export class CategoryChannel extends GuildChannel { + public readonly children: Collection; + public type: 'GUILD_CATEGORY'; +} + +export type CategoryChannelResolvable = Snowflake | CategoryChannel; + +export class Channel extends Base { + public constructor(client: Client, data?: RawChannelData, immediatePatch?: boolean); + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public deleted: boolean; + public id: Snowflake; + public readonly partial: false; + public type: keyof typeof ChannelTypes; + public delete(): Promise; + public fetch(force?: boolean): Promise; + public isText(): this is TextChannel | DMChannel | NewsChannel | ThreadChannel; + public isThread(): this is ThreadChannel; + public toString(): ChannelMention; +} + +type If = T extends true ? A : T extends false ? B : A | B; + +export class Client extends BaseClient { + public constructor(options: ClientOptions); + private actions: unknown; + private _eval(script: string): unknown; + private _validateOptions(options: ClientOptions): void; + + public application: If; + public channels: ChannelManager; + public readonly emojis: BaseGuildEmojiManager; + public guilds: GuildManager; + public options: ClientOptions; + public readyAt: If; + public readonly readyTimestamp: If; + public shard: ShardClientUtil | null; + public token: If; + public uptime: If; + public user: If; + public users: UserManager; + public voice: ClientVoiceManager; + public ws: WebSocketManager; + public destroy(): void; + public fetchGuildPreview(guild: GuildResolvable): Promise; + public fetchInvite(invite: InviteResolvable): Promise; + public fetchGuildTemplate(template: GuildTemplateResolvable): Promise; + public fetchVoiceRegions(): Promise>; + public fetchSticker(id: Snowflake): Promise; + public fetchPremiumStickerPacks(): Promise>; + public fetchWebhook(id: Snowflake, token?: string): Promise; + public fetchGuildWidget(guild: GuildResolvable): Promise; + public generateInvite(options?: InviteGenerationOptions): string; + public login(token?: string): Promise; + public isReady(): this is Client; + public sweepMessages(lifetime?: number): number; + public toJSON(): unknown; + + public on(event: K, listener: (...args: ClientEvents[K]) => Awaited): this; + public on( + event: Exclude, + listener: (...args: any[]) => Awaited, + ): this; + + public once(event: K, listener: (...args: ClientEvents[K]) => Awaited): this; + public once( + event: Exclude, + listener: (...args: any[]) => Awaited, + ): this; + + public emit(event: K, ...args: ClientEvents[K]): boolean; + public emit(event: Exclude, ...args: unknown[]): boolean; + + public off(event: K, listener: (...args: ClientEvents[K]) => Awaited): this; + public off( + event: Exclude, + listener: (...args: any[]) => Awaited, + ): this; + + public removeAllListeners(event?: K): this; + public removeAllListeners(event?: Exclude): this; +} + +export class ClientApplication extends Application { + public constructor(client: Client, data: RawClientApplicationData); + public botPublic: boolean | null; + public botRequireCodeGrant: boolean | null; + public commands: ApplicationCommandManager; + public cover: string | null; + public flags: Readonly; + public owner: User | Team | null; + public readonly partial: boolean; + public rpcOrigins: string[]; + public fetch(): Promise; +} + +export class ClientUser extends User { + public mfaEnabled: boolean; + public verified: boolean; + public edit(data: ClientUserEditData): Promise; + public setActivity(options?: ActivityOptions): Presence; + public setActivity(name: string, options?: ActivityOptions): Presence; + public setAFK(afk: boolean, shardId?: number | number[]): Presence; + public setAvatar(avatar: BufferResolvable | Base64Resolvable): Promise; + public setPresence(data: PresenceData): Presence; + public setStatus(status: PresenceStatusData, shardId?: number | number[]): Presence; + public setUsername(username: string): Promise; +} + +export class Options extends null { + private constructor(); + public static createDefaultOptions(): ClientOptions; + public static cacheWithLimits(settings?: CacheWithLimitsOptions): CacheFactory; + public static cacheEverything(): CacheFactory; +} + +export class ClientVoiceManager { + public constructor(client: Client); + public readonly client: Client; + public adapters: Map; +} + +export { Collection } from '@discordjs/collection'; + +export abstract class Collector extends EventEmitter { + public constructor(client: Client, options?: CollectorOptions<[V, ...F]>); + private _timeout: NodeJS.Timeout | null; + private _idletimeout: NodeJS.Timeout | null; + + public readonly client: Client; + public collected: Collection; + public ended: boolean; + public abstract readonly endReason: string | null; + public filter: CollectorFilter<[V, ...F]>; + public readonly next: Promise; + public options: CollectorOptions<[V, ...F]>; + public checkEnd(): void; + public handleCollect(...args: unknown[]): Promise; + public handleDispose(...args: unknown[]): Promise; + public stop(reason?: string): void; + public resetTimer(options?: CollectorResetTimerOptions): void; + public [Symbol.asyncIterator](): AsyncIterableIterator; + public toJSON(): unknown; + + protected listener: (...args: any[]) => void; + public abstract collect(...args: unknown[]): K | null | Promise; + public abstract dispose(...args: unknown[]): K | null; + + public on(event: 'collect' | 'dispose', listener: (...args: [V, ...F]) => Awaited): this; + public on(event: 'end', listener: (collected: Collection, reason: string) => Awaited): this; + + public once(event: 'collect' | 'dispose', listener: (...args: [V, ...F]) => Awaited): this; + public once(event: 'end', listener: (collected: Collection, reason: string) => Awaited): this; +} + +export class CommandInteraction extends Interaction { + public constructor(client: Client, data: RawCommandInteractionData); + public readonly command: ApplicationCommand | ApplicationCommand<{ guild: GuildResolvable }> | null; + public readonly channel: TextChannel | DMChannel | NewsChannel | PartialDMChannel | ThreadChannel | null; + public channelId: Snowflake; + public commandId: Snowflake; + public commandName: string; + public deferred: boolean; + public ephemeral: boolean | null; + public options: CommandInteractionOptionResolver; + public replied: boolean; + public webhook: InteractionWebhook; + public defer(options: InteractionDeferOptions & { fetchReply: true }): Promise; + public defer(options?: InteractionDeferOptions): Promise; + public deleteReply(): Promise; + public editReply(options: string | MessagePayload | WebhookEditMessageOptions): Promise; + public fetchReply(): Promise; + public followUp(options: string | MessagePayload | InteractionReplyOptions): Promise; + public reply(options: InteractionReplyOptions & { fetchReply: true }): Promise; + public reply(options: string | MessagePayload | InteractionReplyOptions): Promise; + private transformOption( + option: APIApplicationCommandInteractionDataOption, + resolved: APIApplicationCommandInteractionData['resolved'], + ): CommandInteractionOption; +} + +export class CommandInteractionOptionResolver { + public constructor(client: Client, options: CommandInteractionOption[]); + public readonly client: Client; + public readonly data: readonly CommandInteractionOption[]; + private _group: string | null; + private _hoistedOptions: CommandInteractionOption[]; + private _subcommand: string | null; + private _getTypedOption( + name: string, + type: ApplicationCommandOptionType, + properties: (keyof ApplicationCommandOption)[], + required: true, + ): CommandInteractionOption; + private _getTypedOption( + name: string, + type: ApplicationCommandOptionType, + properties: (keyof ApplicationCommandOption)[], + required: boolean, + ): CommandInteractionOption | null; + + public get(name: string, required: true): CommandInteractionOption; + public get(name: string, required?: boolean): CommandInteractionOption | null; + + public getSubcommand(required?: true): string; + public getSubcommand(required: boolean): string | null; + public getSubcommandGroup(required?: true): string; + public getSubcommandGroup(required: boolean): string | null; + public getBoolean(name: string, required: true): boolean; + public getBoolean(name: string, required?: boolean): boolean | null; + public getChannel(name: string, required: true): NonNullable; + public getChannel(name: string, required?: boolean): NonNullable | null; + public getString(name: string, required: true): string; + public getString(name: string, required?: boolean): string | null; + public getInteger(name: string, required: true): number; + public getInteger(name: string, required?: boolean): number | null; + public getNumber(name: string, required: true): number; + public getNumber(name: string, required?: boolean): number | null; + public getUser(name: string, required: true): NonNullable; + public getUser(name: string, required?: boolean): NonNullable | null; + public getMember(name: string, required: true): NonNullable; + public getMember(name: string, required?: boolean): NonNullable | null; + public getRole(name: string, required: true): NonNullable; + public getRole(name: string, required?: boolean): NonNullable | null; + public getMentionable( + name: string, + required: true, + ): NonNullable; + public getMentionable( + name: string, + required?: boolean, + ): NonNullable | null; +} + +export class DataResolver extends null { + private constructor(); + public static resolveBase64(data: Base64Resolvable): string; + public static resolveCode(data: string, regx: RegExp): string; + public static resolveFile(resource: BufferResolvable | Stream): Promise; + public static resolveFileAsBuffer(resource: BufferResolvable | Stream): Promise; + public static resolveImage(resource: BufferResolvable | Base64Resolvable): Promise; + public static resolveInviteCode(data: InviteResolvable): string; + public static resolveGuildTemplateCode(data: GuildTemplateResolvable): string; +} + +export class DiscordAPIError extends Error { + public constructor(error: unknown, status: number, request: unknown); + private static flattenErrors(obj: unknown, key: string): string[]; + + public code: number; + public method: string; + public path: string; + public httpStatus: number; + public requestData: HTTPErrorData; +} + +export class DMChannel extends TextBasedChannel(Channel, ['bulkDelete']) { + public constructor(client: Client, data?: RawDMChannelData); + public messages: MessageManager; + public recipient: User; + public type: 'DM'; + public fetch(force?: boolean): Promise; +} + +export class Emoji extends Base { + public constructor(client: Client, emoji: RawEmojiData); + public animated: boolean | null; + public readonly createdAt: Date | null; + public readonly createdTimestamp: number | null; + public deleted: boolean; + public id: Snowflake | null; + public name: string | null; + public readonly identifier: string; + public readonly url: string | null; + public toJSON(): unknown; + public toString(): string; +} + +export class Guild extends AnonymousGuild { + public constructor(client: Client, data: RawGuildData); + private _sortedRoles(): Collection; + private _sortedChannels(channel: Channel): Collection; + + public readonly afkChannel: VoiceChannel | null; + public afkChannelId: Snowflake | null; + public afkTimeout: number; + public applicationId: Snowflake | null; + public approximateMemberCount: number | null; + public approximatePresenceCount: number | null; + public available: boolean; + public bans: GuildBanManager; + public channels: GuildChannelManager; + public commands: GuildApplicationCommandManager; + public defaultMessageNotifications: DefaultMessageNotificationLevel | number; + public deleted: boolean; + public discoverySplash: string | null; + public emojis: GuildEmojiManager; + public explicitContentFilter: ExplicitContentFilterLevel; + public invites: GuildInviteManager; + public readonly joinedAt: Date; + public joinedTimestamp: number; + public large: boolean; + public maximumMembers: number | null; + public maximumPresences: number | null; + public readonly me: GuildMember | null; + public memberCount: number; + public members: GuildMemberManager; + public mfaLevel: MFALevel; + public ownerId: Snowflake; + public preferredLocale: string; + public premiumSubscriptionCount: number | null; + public premiumTier: PremiumTier; + public presences: PresenceManager; + public readonly publicUpdatesChannel: TextChannel | null; + public publicUpdatesChannelId: Snowflake | null; + public roles: RoleManager; + public readonly rulesChannel: TextChannel | null; + public rulesChannelId: Snowflake | null; + public readonly shard: WebSocketShard; + public shardId: number; + public stageInstances: StageInstanceManager; + public stickers: GuildStickerManager; + public readonly systemChannel: TextChannel | null; + public systemChannelFlags: Readonly; + public systemChannelId: Snowflake | null; + public vanityURLUses: number | null; + public readonly voiceAdapterCreator: InternalDiscordGatewayAdapterCreator; + public readonly voiceStates: VoiceStateManager; + public readonly widgetChannel: TextChannel | null; + public widgetChannelId: Snowflake | null; + public widgetEnabled: boolean | null; + public createTemplate(name: string, description?: string): Promise; + public delete(): Promise; + public discoverySplashURL(options?: StaticImageURLOptions): string | null; + public edit(data: GuildEditData, reason?: string): Promise; + public editWelcomeScreen(data: WelcomeScreenEditData): Promise; + public equals(guild: Guild): boolean; + public fetchAuditLogs(options?: GuildAuditLogsFetchOptions): Promise; + public fetchIntegrations(): Promise>; + public fetchOwner(options?: FetchOwnerOptions): Promise; + public fetchPreview(): Promise; + public fetchTemplates(): Promise>; + public fetchVanityData(): Promise; + public fetchWebhooks(): Promise>; + public fetchWelcomeScreen(): Promise; + public fetchWidget(): Promise; + public fetchWidgetSettings(): Promise; + public leave(): Promise; + public setAFKChannel(afkChannel: VoiceChannelResolvable | null, reason?: string): Promise; + public setAFKTimeout(afkTimeout: number, reason?: string): Promise; + public setBanner(banner: Base64Resolvable | null, reason?: string): Promise; + public setChannelPositions(channelPositions: readonly ChannelPosition[]): Promise; + public setDefaultMessageNotifications( + defaultMessageNotifications: DefaultMessageNotificationLevel | number, + reason?: string, + ): Promise; + public setDiscoverySplash(discoverySplash: Base64Resolvable | null, reason?: string): Promise; + public setExplicitContentFilter( + explicitContentFilter: ExplicitContentFilterLevel | number, + reason?: string, + ): Promise; + public setIcon(icon: Base64Resolvable | null, reason?: string): Promise; + public setName(name: string, reason?: string): Promise; + public setOwner(owner: GuildMemberResolvable, reason?: string): Promise; + public setPreferredLocale(preferredLocale: string, reason?: string): Promise; + public setPublicUpdatesChannel(publicUpdatesChannel: TextChannelResolvable | null, reason?: string): Promise; + public setRolePositions(rolePositions: readonly RolePosition[]): Promise; + public setRulesChannel(rulesChannel: TextChannelResolvable | null, reason?: string): Promise; + public setSplash(splash: Base64Resolvable | null, reason?: string): Promise; + public setSystemChannel(systemChannel: TextChannelResolvable | null, reason?: string): Promise; + public setSystemChannelFlags(systemChannelFlags: SystemChannelFlagsResolvable, reason?: string): Promise; + public setVerificationLevel(verificationLevel: VerificationLevel | number, reason?: string): Promise; + public setWidgetSettings(settings: GuildWidgetSettingsData, reason?: string): Promise; + public toJSON(): unknown; +} + +export class GuildAuditLogs { + public constructor(guild: Guild, data: RawGuildAuditLogData); + private webhooks: Collection; + private integrations: Collection; + + public entries: Collection; + + public static Actions: GuildAuditLogsActions; + public static Targets: GuildAuditLogsTargets; + public static Entry: typeof GuildAuditLogsEntry; + public static actionType(action: number): GuildAuditLogsActionType; + public static build(...args: unknown[]): Promise; + public static targetType(target: number): GuildAuditLogsTarget; + public toJSON(): unknown; +} + +export class GuildAuditLogsEntry { + public constructor(logs: GuildAuditLogs, guild: Guild, data: RawGuildAuditLogEntryData); + public action: GuildAuditLogsAction; + public actionType: GuildAuditLogsActionType; + public changes: AuditLogChange[] | null; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public executor: User | null; + public extra: unknown | Role | GuildMember | null; + public id: Snowflake; + public reason: string | null; + public target: + | Guild + | GuildChannel + | User + | Role + | GuildEmoji + | Invite + | Webhook + | Message + | Integration + | StageInstance + | Sticker + | ThreadChannel + | { id: Snowflake } + | null; + public targetType: GuildAuditLogsTarget; + public toJSON(): unknown; +} + +export class GuildBan extends Base { + public constructor(client: Client, data: RawGuildBanData, guild: Guild); + public guild: Guild; + public user: User; + public readonly partial: boolean; + public reason?: string | null; + public fetch(force?: boolean): Promise; +} + +export class GuildChannel extends Channel { + public constructor(guild: Guild, data?: RawGuildChannelData, client?: Client); + private memberPermissions(member: GuildMember): Readonly; + private rolePermissions(role: Role): Readonly; + + public readonly calculatedPosition: number; + public readonly deletable: boolean; + public guild: Guild; + public guildId: Snowflake; + public readonly manageable: boolean; + public readonly members: Collection; + public name: string; + public readonly parent: CategoryChannel | null; + public parentId: Snowflake | null; + public permissionOverwrites: PermissionOverwriteManager; + public readonly permissionsLocked: boolean | null; + public readonly position: number; + public rawPosition: number; + public type: Exclude; + public readonly viewable: boolean; + public clone(options?: GuildChannelCloneOptions): Promise; + public createInvite(options?: CreateInviteOptions): Promise; + public edit(data: ChannelData, reason?: string): Promise; + public equals(channel: GuildChannel): boolean; + public fetchInvites(cache?: boolean): Promise>; + public lockPermissions(): Promise; + public permissionsFor(memberOrRole: GuildMember | Role): Readonly; + public permissionsFor(memberOrRole: GuildMemberResolvable | RoleResolvable): Readonly | null; + public setName(name: string, reason?: string): Promise; + public setParent(channel: CategoryChannelResolvable | null, options?: SetParentOptions): Promise; + public setPosition(position: number, options?: SetChannelPositionOptions): Promise; + public setTopic(topic: string | null, reason?: string): Promise; + public isText(): this is TextChannel | NewsChannel; +} + +export class GuildEmoji extends BaseGuildEmoji { + public constructor(client: Client, data: RawGuildEmojiData, guild: Guild); + private _roles: Snowflake[]; + + public readonly deletable: boolean; + public guild: Guild; + public author: User | null; + public readonly roles: GuildEmojiRoleManager; + public readonly url: string; + public delete(reason?: string): Promise; + public edit(data: GuildEmojiEditData, reason?: string): Promise; + public equals(other: GuildEmoji | unknown): boolean; + public fetchAuthor(): Promise; + public setName(name: string, reason?: string): Promise; +} + +export class GuildMember extends PartialTextBasedChannel(Base) { + public constructor(client: Client, data: RawGuildMemberData, guild: Guild); + public readonly bannable: boolean; + public deleted: boolean; + public readonly displayColor: number; + public readonly displayHexColor: HexColorString; + public readonly displayName: string; + public guild: Guild; + public readonly id: Snowflake; + public pending: boolean; + public readonly joinedAt: Date | null; + public joinedTimestamp: number | null; + public readonly kickable: boolean; + public readonly manageable: boolean; + public nickname: string | null; + public readonly partial: false; + public readonly permissions: Readonly; + public readonly premiumSince: Date | null; + public premiumSinceTimestamp: number | null; + public readonly presence: Presence | null; + public readonly roles: GuildMemberRoleManager; + public user: User; + public readonly voice: VoiceState; + public ban(options?: BanOptions): Promise; + public fetch(force?: boolean): Promise; + public createDM(force?: boolean): Promise; + public deleteDM(): Promise; + public edit(data: GuildMemberEditData, reason?: string): Promise; + public kick(reason?: string): Promise; + public permissionsIn(channel: GuildChannelResolvable): Readonly; + public setNickname(nickname: string | null, reason?: string): Promise; + public toJSON(): unknown; + public toString(): MemberMention; + public valueOf(): string; +} + +export class GuildPreview extends Base { + public constructor(client: Client, data: RawGuildPreviewData); + public approximateMemberCount: number; + public approximatePresenceCount: number; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public description: string | null; + public discoverySplash: string | null; + public emojis: Collection; + public features: GuildFeatures[]; + public icon: string | null; + public id: Snowflake; + public name: string; + public splash: string | null; + public discoverySplashURL(options?: StaticImageURLOptions): string | null; + public iconURL(options?: ImageURLOptions): string | null; + public splashURL(options?: StaticImageURLOptions): string | null; + public fetch(): Promise; + public toJSON(): unknown; + public toString(): string; +} + +export class GuildTemplate extends Base { + public constructor(client: Client, data: RawGuildTemplateData); + public readonly createdTimestamp: number; + public readonly updatedTimestamp: number; + public readonly url: string; + public code: string; + public name: string; + public description: string | null; + public usageCount: number; + public creator: User; + public creatorId: Snowflake; + public createdAt: Date; + public updatedAt: Date; + public guild: Guild | null; + public guildId: Snowflake; + public serializedGuild: APITemplateSerializedSourceGuild; + public unSynced: boolean | null; + public createGuild(name: string, icon?: BufferResolvable | Base64Resolvable): Promise; + public delete(): Promise; + public edit(options?: EditGuildTemplateOptions): Promise; + public sync(): Promise; + public static GUILD_TEMPLATES_PATTERN: RegExp; +} + +export class GuildPreviewEmoji extends BaseGuildEmoji { + public constructor(client: Client, data: RawGuildEmojiData, guild: GuildPreview); + public guild: GuildPreview; + public roles: Snowflake[]; +} + +export class HTTPError extends Error { + public constructor(message: string, name: string, code: number, request: unknown); + public code: number; + public method: string; + public name: string; + public path: string; + public requestData: HTTPErrorData; +} + +// tslint:disable-next-line:no-empty-interface - Merge RateLimitData into RateLimitError to not have to type it again +export interface RateLimitError extends RateLimitData {} +export class RateLimitError extends Error { + public constructor(data: RateLimitData); + public name: 'RateLimitError'; +} + +export class Integration extends Base { + public constructor(client: Client, data: RawIntegrationData, guild: Guild); + public account: IntegrationAccount; + public application: IntegrationApplication | null; + public enabled: boolean; + public expireBehavior: number; + public expireGracePeriod: number; + public guild: Guild; + public id: Snowflake; + public name: string; + public role: Role; + public readonly roles: Collection; + public syncedAt: number; + public syncing: boolean; + public type: string; + public user: User | null; + public delete(reason?: string): Promise; +} + +export class IntegrationApplication extends Application { + public constructor(client: Client, data: RawIntegrationApplicationData); + public bot: User | null; + public termsOfServiceURL: string | null; + public privacyPolicyURL: string | null; + public rpcOrigins: string[]; + public summary: string | null; + public hook: boolean | null; + public cover: string | null; + public verifyKey: string | null; +} + +export class Intents extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; +} + +export class Interaction extends Base { + public constructor(client: Client, data: RawInteractionData); + public applicationId: Snowflake; + public readonly channel: Channel | PartialDMChannel | null; + public channelId: Snowflake | null; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public readonly guild: Guild | null; + public guildId: Snowflake | null; + public id: Snowflake; + public member: GuildMember | APIInteractionGuildMember | null; + public readonly token: string; + public type: InteractionType; + public user: User; + public version: number; + public inGuild(): this is this & { guildId: Snowflake; member: GuildMember | APIInteractionGuildMember }; + public isButton(): this is ButtonInteraction; + public isCommand(): this is CommandInteraction; + public isMessageComponent(): this is MessageComponentInteraction; + public isSelectMenu(): this is SelectMenuInteraction; +} + +export class InteractionCollector extends Collector { + public constructor(client: Client, options?: InteractionCollectorOptions); + private _handleMessageDeletion(message: Message): void; + private _handleChannelDeletion(channel: GuildChannel): void; + private _handleGuildDeletion(guild: Guild): void; + + public channel: TextChannel | NewsChannel | DMChannel | null; + public componentType: MessageComponentType | null; + public readonly endReason: string | null; + public guild: Guild | null; + public interactionType: InteractionType | null; + public message: Message | null; + public options: InteractionCollectorOptions; + public total: number; + public users: Collection; + + public collect(interaction: Interaction): Snowflake; + public empty(): void; + public dispose(interaction: Interaction): Snowflake; + public on(event: 'collect' | 'dispose', listener: (interaction: T) => Awaited): this; + public on(event: 'end', listener: (collected: Collection, reason: string) => Awaited): this; + public on(event: string, listener: (...args: any[]) => Awaited): this; + + public once(event: 'collect' | 'dispose', listener: (interaction: T) => Awaited): this; + public once(event: 'end', listener: (collected: Collection, reason: string) => Awaited): this; + public once(event: string, listener: (...args: any[]) => Awaited): this; +} + +export class InteractionWebhook extends PartialWebhookMixin() { + public constructor(client: Client, id: Snowflake, token: string); + public token: string; + public send(options: string | MessagePayload | InteractionReplyOptions): Promise; +} + +export class Invite extends Base { + public constructor(client: Client, data: RawInviteData); + public channel: GuildChannel | PartialGroupDMChannel; + public code: string; + public readonly deletable: boolean; + public readonly createdAt: Date | null; + public createdTimestamp: number | null; + public readonly expiresAt: Date | null; + public readonly expiresTimestamp: number | null; + public guild: InviteGuild | Guild | null; + public inviter: User | null; + public maxAge: number | null; + public maxUses: number | null; + public memberCount: number; + public presenceCount: number; + public targetApplication: IntegrationApplication | null; + public targetUser: User | null; + public targetType: InviteTargetType | null; + public temporary: boolean | null; + public readonly url: string; + public uses: number | null; + public delete(reason?: string): Promise; + public toJSON(): unknown; + public toString(): string; + public static INVITES_PATTERN: RegExp; + public stageInstance: InviteStageInstance | null; +} + +export class InviteStageInstance extends Base { + public constructor(client: Client, data: RawInviteStageInstance, channelId: Snowflake, guildId: Snowflake); + public channelId: Snowflake; + public guildId: Snowflake; + public members: Collection; + public topic: string; + public participantCount: number; + public speakerCount: number; + public readonly channel: StageChannel | null; + public readonly guild: Guild | null; +} + +export class InviteGuild extends AnonymousGuild { + public constructor(client: Client, data: RawInviteGuildData); + public welcomeScreen: WelcomeScreen | null; +} + +export class LimitedCollection extends Collection { + public constructor(options?: LimitedCollectionOptions, iterable?: Iterable); + public maxSize: number; + public keepOverLimit: ((value: V, key: K, collection: this) => boolean) | null; + public interval: NodeJS.Timeout | null; + public sweepFilter: SweepFilter | null; + + public static filterByLifetime(options?: LifetimeFilterOptions): SweepFilter; +} + +export class Message extends Base { + public constructor( + client: Client, + data: RawMessageData, + channel: TextChannel | DMChannel | NewsChannel | ThreadChannel, + ); + private _patch(data: RawPartialMessageData, partial: true): Message; + private _patch(data: RawMessageData, partial?: boolean): Message; + private _update(data: RawPartialMessageData, partial: true): Message; + private _update(data: RawMessageData, partial?: boolean): Message; + + public activity: MessageActivity | null; + public applicationId: Snowflake | null; + public attachments: Collection; + public author: User; + public channel: TextChannel | DMChannel | NewsChannel | ThreadChannel; + public readonly cleanContent: string; + public components: MessageActionRow[]; + public content: string; + public readonly createdAt: Date; + public createdTimestamp: number; + public readonly crosspostable: boolean; + public readonly deletable: boolean; + public deleted: boolean; + public readonly editable: boolean; + public readonly editedAt: Date | null; + public editedTimestamp: number | null; + public embeds: MessageEmbed[]; + public groupActivityApplication: ClientApplication | null; + public readonly guild: Guild | null; + public readonly hasThread: boolean; + public id: Snowflake; + public interaction: MessageInteraction | null; + public readonly member: GuildMember | null; + public mentions: MessageMentions; + public nonce: string | number | null; + public readonly partial: false; + public readonly pinnable: boolean; + public pinned: boolean; + public reactions: ReactionManager; + public stickers: Collection; + public system: boolean; + public readonly thread: ThreadChannel | null; + public tts: boolean; + public type: MessageType; + public readonly url: string; + public webhookId: Snowflake | null; + public flags: Readonly; + public reference: MessageReference | null; + public awaitMessageComponent( + options?: AwaitMessageComponentOptions, + ): Promise; + public awaitReactions(options?: AwaitReactionsOptions): Promise>; + public createReactionCollector(options?: ReactionCollectorOptions): ReactionCollector; + public createMessageComponentCollector( + options?: InteractionCollectorOptions, + ): InteractionCollector; + public delete(): Promise; + public edit(content: string | MessageEditOptions | MessagePayload): Promise; + public equals(message: Message, rawData: unknown): boolean; + public fetchReference(): Promise; + public fetchWebhook(): Promise; + public crosspost(): Promise; + public fetch(force?: boolean): Promise; + public pin(): Promise; + public react(emoji: EmojiIdentifierResolvable): Promise; + public removeAttachments(): Promise; + public reply(options: string | MessagePayload | ReplyMessageOptions): Promise; + public startThread(options: StartThreadOptions): Promise; + public suppressEmbeds(suppress?: boolean): Promise; + public toJSON(): unknown; + public toString(): string; + public unpin(): Promise; +} + +export class MessageActionRow extends BaseMessageComponent { + public constructor(data?: MessageActionRow | MessageActionRowOptions); + public type: 'ACTION_ROW'; + public components: MessageActionRowComponent[]; + public addComponents( + ...components: MessageActionRowComponentResolvable[] | MessageActionRowComponentResolvable[][] + ): this; + public spliceComponents( + index: number, + deleteCount: number, + ...components: MessageActionRowComponentResolvable[] | MessageActionRowComponentResolvable[][] + ): this; + public toJSON(): unknown; +} + +export class MessageAttachment { + public constructor(attachment: BufferResolvable | Stream, name?: string, data?: RawMessageAttachementData); + + public attachment: BufferResolvable | Stream; + public contentType: string | null; + public height: number | null; + public id: Snowflake; + public name: string | null; + public proxyURL: string; + public size: number; + public readonly spoiler: boolean; + public url: string; + public width: number | null; + public setFile(attachment: BufferResolvable | Stream, name?: string): this; + public setName(name: string): this; + public toJSON(): unknown; +} + +export class MessageButton extends BaseMessageComponent { + public constructor(data?: MessageButton | MessageButtonOptions); + public customId: string | null; + public disabled: boolean; + public emoji: APIPartialEmoji | null; + public label: string | null; + public style: MessageButtonStyle | null; + public type: 'BUTTON'; + public url: string | null; + public setCustomId(customId: string): this; + public setDisabled(disabled: boolean): this; + public setEmoji(emoji: EmojiIdentifierResolvable): this; + public setLabel(label: string): this; + public setStyle(style: MessageButtonStyleResolvable): this; + public setURL(url: string): this; + public toJSON(): unknown; + private static resolveStyle(style: MessageButtonStyleResolvable): MessageButtonStyle; +} + +export class MessageCollector extends Collector { + public constructor(channel: TextChannel | DMChannel | ThreadChannel, options?: MessageCollectorOptions); + private _handleChannelDeletion(channel: GuildChannel): void; + private _handleGuildDeletion(guild: Guild): void; + + public channel: TextChannel | DMChannel | ThreadChannel; + public readonly endReason: string | null; + public options: MessageCollectorOptions; + public received: number; + + public collect(message: Message): Snowflake | null; + public dispose(message: Message): Snowflake | null; +} + +export class MessageComponentInteraction extends Interaction { + public constructor(client: Client, data: RawMessageComponentInteractionData); + public readonly channel: TextChannel | DMChannel | NewsChannel | PartialDMChannel | ThreadChannel | null; + public readonly component: MessageActionRowComponent | Exclude | null; + public componentType: MessageComponentType; + public customId: string; + public deferred: boolean; + public ephemeral: boolean | null; + public message: Message | APIMessage; + public replied: boolean; + public webhook: InteractionWebhook; + public defer(options: InteractionDeferOptions & { fetchReply: true }): Promise; + public defer(options?: InteractionDeferOptions): Promise; + public deferUpdate(options: InteractionDeferUpdateOptions & { fetchReply: true }): Promise; + public deferUpdate(options?: InteractionDeferUpdateOptions): Promise; + public deleteReply(): Promise; + public editReply(options: string | MessagePayload | WebhookEditMessageOptions): Promise; + public fetchReply(): Promise; + public followUp(options: string | MessagePayload | InteractionReplyOptions): Promise; + public reply(options: InteractionReplyOptions & { fetchReply: true }): Promise; + public reply(options: string | MessagePayload | InteractionReplyOptions): Promise; + public update(options: InteractionUpdateOptions & { fetchReply: true }): Promise; + public update(options: string | MessagePayload | InteractionUpdateOptions): Promise; + + public static resolveType(type: MessageComponentTypeResolvable): MessageComponentType; +} + +export class MessageEmbed { + public constructor(data?: MessageEmbed | MessageEmbedOptions); + public author: MessageEmbedAuthor | null; + public color: number | null; + public readonly createdAt: Date | null; + public description: string | null; + public fields: EmbedField[]; + public footer: MessageEmbedFooter | null; + public readonly hexColor: HexColorString | null; + public image: MessageEmbedImage | null; + public readonly length: number; + public provider: MessageEmbedProvider | null; + public thumbnail: MessageEmbedThumbnail | null; + public timestamp: number | null; + public title: string | null; + /** @deprecated */ + public type: string; + public url: string | null; + public readonly video: MessageEmbedVideo | null; + public addField(name: string, value: string, inline?: boolean): this; + public addFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): this; + public setFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): this; + public setAuthor(name: string, iconURL?: string, url?: string): this; + public setColor(color: ColorResolvable): this; + public setDescription(description: string): this; + public setFooter(text: string, iconURL?: string): this; + public setImage(url: string): this; + public setThumbnail(url: string): this; + public setTimestamp(timestamp?: Date | number): this; + public setTitle(title: string): this; + public setURL(url: string): this; + public spliceFields(index: number, deleteCount: number, ...fields: EmbedFieldData[] | EmbedFieldData[][]): this; + public toJSON(): unknown; + + public static normalizeField(name: string, value: string, inline?: boolean): Required; + public static normalizeFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): Required[]; +} + +export class MessageFlags extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; +} + +export class MessageMentions { + public constructor( + message: Message, + users: APIUser[] | Collection, + roles: Snowflake[] | Collection, + everyone: boolean, + repliedUser?: APIUser | User, + ); + private _channels: Collection | null; + private readonly _content: string; + private _members: Collection | null; + + public readonly channels: Collection; + public readonly client: Client; + public everyone: boolean; + public readonly guild: Guild; + public has(data: UserResolvable | RoleResolvable | ChannelResolvable, options?: MessageMentionsHasOptions): boolean; + public readonly members: Collection | null; + public repliedUser: User | null; + public roles: Collection; + public users: Collection; + public crosspostedChannels: Collection; + public toJSON(): unknown; + + public static CHANNELS_PATTERN: RegExp; + public static EVERYONE_PATTERN: RegExp; + public static ROLES_PATTERN: RegExp; + public static USERS_PATTERN: RegExp; +} + +export class MessagePayload { + public constructor(target: MessageTarget, options: MessageOptions | WebhookMessageOptions); + public data: RawMessagePayloadData | null; + public readonly isUser: boolean; + public readonly isWebhook: boolean; + public readonly isMessage: boolean; + public readonly isMessageManager: boolean; + public readonly isInteraction: boolean; + public files: unknown[] | null; + public options: MessageOptions | WebhookMessageOptions; + public target: MessageTarget; + + public static create( + target: MessageTarget, + options: string | MessageOptions | WebhookMessageOptions, + extra?: MessageOptions | WebhookMessageOptions, + ): MessagePayload; + public static resolveFile(fileLike: BufferResolvable | Stream | FileOptions | MessageAttachment): Promise; + + public makeContent(): string | undefined; + public resolveData(): this; + public resolveFiles(): Promise; +} + +export class MessageReaction { + public constructor(client: Client, data: RawMessageReactionData, message: Message); + private _emoji: GuildEmoji | ReactionEmoji; + + public readonly client: Client; + public count: number; + public readonly emoji: GuildEmoji | ReactionEmoji; + public me: boolean; + public message: Message | PartialMessage; + public readonly partial: false; + public users: ReactionUserManager; + public remove(): Promise; + public fetch(): Promise; + public toJSON(): unknown; +} + +export class MessageSelectMenu extends BaseMessageComponent { + public constructor(data?: MessageSelectMenu | MessageSelectMenuOptions); + public customId: string | null; + public disabled: boolean; + public maxValues: number | null; + public minValues: number | null; + public options: MessageSelectOption[]; + public placeholder: string | null; + public type: 'SELECT_MENU'; + public addOptions(...options: MessageSelectOptionData[] | MessageSelectOptionData[][]): this; + public setCustomId(customId: string): this; + public setDisabled(disabled: boolean): this; + public setMaxValues(maxValues: number): this; + public setMinValues(minValues: number): this; + public setPlaceholder(placeholder: string): this; + public spliceOptions( + index: number, + deleteCount: number, + ...options: MessageSelectOptionData[] | MessageSelectOptionData[][] + ): this; + public toJSON(): unknown; +} + +export class NewsChannel extends TextBasedChannel(GuildChannel) { + public constructor(guild: Guild, data?: RawGuildChannelData); + public defaultAutoArchiveDuration?: ThreadAutoArchiveDuration; + public messages: MessageManager; + public nsfw: boolean; + public threads: ThreadManager; + public topic: string | null; + public type: 'GUILD_NEWS'; + public createWebhook(name: string, options?: ChannelWebhookCreateOptions): Promise; + public setDefaultAutoArchiveDuration( + defaultAutoArchiveDuration: ThreadAutoArchiveDuration, + reason?: string, + ): Promise; + public setNSFW(nsfw: boolean, reason?: string): Promise; + public setType(type: Pick, reason?: string): Promise; + public fetchWebhooks(): Promise>; + public addFollower(channel: GuildChannelResolvable, reason?: string): Promise; +} + +export class OAuth2Guild extends BaseGuild { + public constructor(client: Client, data: RawOAuth2GuildData); + public owner: boolean; + public permissions: Readonly; +} + +export class PartialGroupDMChannel extends Channel { + public constructor(client: Client, data: RawPartialGroupDMChannelData); + public name: string; + public icon: string | null; + public iconURL(options?: StaticImageURLOptions): string | null; +} + +export class PermissionOverwrites extends Base { + public constructor(client: Client, data: RawPermissionOverwriteData, channel: GuildChannel); + public allow: Readonly; + public readonly channel: GuildChannel; + public deny: Readonly; + public id: Snowflake; + public type: OverwriteType; + public edit(options: PermissionOverwriteOptions, reason?: string): Promise; + public delete(reason?: string): Promise; + public toJSON(): unknown; + public static resolveOverwriteOptions( + options: PermissionOverwriteOptions, + initialPermissions: { allow?: PermissionResolvable; deny?: PermissionResolvable }, + ): ResolvedOverwriteOptions; + public static resolve(overwrite: OverwriteResolvable, guild: Guild): APIOverwrite; +} + +export class Permissions extends BitField { + public any(permission: PermissionResolvable, checkAdmin?: boolean): boolean; + public has(permission: PermissionResolvable, checkAdmin?: boolean): boolean; + public missing(bits: BitFieldResolvable, checkAdmin?: boolean): PermissionString[]; + public serialize(checkAdmin?: boolean): Record; + public toArray(checkAdmin?: boolean): PermissionString[]; + + public static ALL: bigint; + public static DEFAULT: bigint; + public static STAGE_MODERATOR: bigint; + public static FLAGS: PermissionFlags; + public static resolve(permission?: PermissionResolvable): bigint; +} + +export class Presence extends Base { + public constructor(client: Client, data?: RawPresenceData); + public activities: Activity[]; + public clientStatus: ClientPresenceStatusData | null; + public guild: Guild | null; + public readonly member: GuildMember | null; + public status: PresenceStatus; + public readonly user: User | null; + public userId: Snowflake; + public equals(presence: Presence): boolean; +} + +export class ReactionCollector extends Collector { + public constructor(message: Message, options?: ReactionCollectorOptions); + private _handleChannelDeletion(channel: GuildChannel): void; + private _handleGuildDeletion(guild: Guild): void; + private _handleMessageDeletion(message: Message): void; + + public readonly endReason: string | null; + public message: Message; + public options: ReactionCollectorOptions; + public total: number; + public users: Collection; + + public static key(reaction: MessageReaction): Snowflake | string; + + public collect(reaction: MessageReaction, user: User): Promise; + public dispose(reaction: MessageReaction, user: User): Snowflake | string | null; + public empty(): void; + + public on(event: 'collect' | 'dispose' | 'remove', listener: (reaction: MessageReaction, user: User) => void): this; + public on(event: 'end', listener: (collected: Collection, reason: string) => void): this; + public on(event: string, listener: (...args: any[]) => void): this; + + public once(event: 'collect' | 'dispose' | 'remove', listener: (reaction: MessageReaction, user: User) => void): this; + public once( + event: 'end', + listener: (collected: Collection, reason: string) => void, + ): this; + public once(event: string, listener: (...args: any[]) => void): this; +} + +export class ReactionEmoji extends Emoji { + public constructor(reaction: MessageReaction, emoji: RawReactionEmojiData); + public reaction: MessageReaction; + public toJSON(): unknown; +} + +export class RichPresenceAssets { + public constructor(activity: Activity, assets: RawRichPresenceAssets); + public largeImage: Snowflake | null; + public largeText: string | null; + public smallImage: Snowflake | null; + public smallText: string | null; + public largeImageURL(options?: StaticImageURLOptions): string | null; + public smallImageURL(options?: StaticImageURLOptions): string | null; +} + +export class Role extends Base { + public constructor(client: Client, data: RawRoleData, guild: Guild); + public color: number; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public deleted: boolean; + public readonly editable: boolean; + public guild: Guild; + public readonly hexColor: HexColorString; + public hoist: boolean; + public id: Snowflake; + public managed: boolean; + public readonly members: Collection; + public mentionable: boolean; + public name: string; + public permissions: Readonly; + public readonly position: number; + public rawPosition: number; + public tags: RoleTagData | null; + public comparePositionTo(role: Role): number; + public delete(reason?: string): Promise; + public edit(data: RoleData, reason?: string): Promise; + public equals(role: Role): boolean; + public permissionsIn(channel: GuildChannel | Snowflake): Readonly; + public setColor(color: ColorResolvable, reason?: string): Promise; + public setHoist(hoist: boolean, reason?: string): Promise; + public setMentionable(mentionable: boolean, reason?: string): Promise; + public setName(name: string, reason?: string): Promise; + public setPermissions(permissions: PermissionResolvable, reason?: string): Promise; + public setPosition(position: number, options?: SetRolePositionOptions): Promise; + public toJSON(): unknown; + public toString(): RoleMention; + + public static comparePositions(role1: Role, role2: Role): number; +} + +export class SelectMenuInteraction extends MessageComponentInteraction { + public constructor(client: Client, data: RawMessageSelectMenuInteractionData); + public componentType: 'SELECT_MENU'; + public values: string[]; +} + +export class Shard extends EventEmitter { + public constructor(manager: ShardingManager, id: number); + private _evals: Map>; + private _exitListener: (...args: any[]) => void; + private _fetches: Map>; + private _handleExit(respawn?: boolean): void; + private _handleMessage(message: unknown): void; + + public args: string[]; + public execArgv: string[]; + public env: unknown; + public id: number; + public manager: ShardingManager; + public process: ChildProcess | null; + public ready: boolean; + public worker: Worker | null; + public eval(script: string): Promise; + public eval(fn: (client: Client) => T): Promise; + public fetchClientValue(prop: string): Promise; + public kill(): void; + public respawn(options?: { delay?: number; timeout?: number }): Promise; + public send(message: unknown): Promise; + public spawn(timeout?: number): Promise; + + public on(event: 'spawn' | 'death', listener: (child: ChildProcess) => Awaited): this; + public on(event: 'disconnect' | 'ready' | 'reconnecting', listener: () => Awaited): this; + public on(event: 'error', listener: (error: Error) => Awaited): this; + public on(event: 'message', listener: (message: any) => Awaited): this; + public on(event: string, listener: (...args: any[]) => Awaited): this; + + public once(event: 'spawn' | 'death', listener: (child: ChildProcess) => Awaited): this; + public once(event: 'disconnect' | 'ready' | 'reconnecting', listener: () => Awaited): this; + public once(event: 'error', listener: (error: Error) => Awaited): this; + public once(event: 'message', listener: (message: any) => Awaited): this; + public once(event: string, listener: (...args: any[]) => Awaited): this; +} + +export class ShardClientUtil { + public constructor(client: Client, mode: ShardingManagerMode); + private _handleMessage(message: unknown): void; + private _respond(type: string, message: unknown): void; + + public client: Client; + public readonly count: number; + public readonly ids: number[]; + public mode: ShardingManagerMode; + public parentPort: MessagePort | null; + public broadcastEval(fn: (client: Client) => Awaited): Promise[]>; + public broadcastEval(fn: (client: Client) => Awaited, options: { shard: number }): Promise>; + public broadcastEval( + fn: (client: Client, context: Serialized

) => Awaited, + options: { context: P }, + ): Promise[]>; + public broadcastEval( + fn: (client: Client, context: Serialized

) => Awaited, + options: { context: P; shard: number }, + ): Promise>; + public fetchClientValues(prop: string): Promise; + public fetchClientValues(prop: string, shard: number): Promise; + public respawnAll(options?: MultipleShardRespawnOptions): Promise; + public send(message: unknown): Promise; + + public static singleton(client: Client, mode: ShardingManagerMode): ShardClientUtil; + public static shardIdForGuildId(guildId: Snowflake, shardCount: number): number; +} + +export class ShardingManager extends EventEmitter { + public constructor(file: string, options?: ShardingManagerOptions); + private _performOnShards(method: string, args: unknown[]): Promise; + private _performOnShards(method: string, args: unknown[], shard: number): Promise; + + public file: string; + public respawn: boolean; + public shardArgs: string[]; + public shards: Collection; + public token: string | null; + public totalShards: number | 'auto'; + public shardList: number[] | 'auto'; + public broadcast(message: unknown): Promise; + public broadcastEval(fn: (client: Client) => Awaited): Promise[]>; + public broadcastEval(fn: (client: Client) => Awaited, options: { shard: number }): Promise>; + public broadcastEval( + fn: (client: Client, context: Serialized

) => Awaited, + options: { context: P }, + ): Promise[]>; + public broadcastEval( + fn: (client: Client, context: Serialized

) => Awaited, + options: { context: P; shard: number }, + ): Promise>; + public createShard(id: number): Shard; + public fetchClientValues(prop: string): Promise; + public fetchClientValues(prop: string, shard: number): Promise; + public respawnAll(options?: MultipleShardRespawnOptions): Promise>; + public spawn(options?: MultipleShardSpawnOptions): Promise>; + + public on(event: 'shardCreate', listener: (shard: Shard) => Awaited): this; + + public once(event: 'shardCreate', listener: (shard: Shard) => Awaited): this; +} + +export interface FetchRecommendedShardsOptions { + guildsPerShard?: number; + multipleOf?: number; +} + +export class SnowflakeUtil extends null { + private constructor(); + public static deconstruct(snowflake: Snowflake): DeconstructedSnowflake; + public static generate(timestamp?: number | Date): Snowflake; + public static readonly EPOCH: number; +} + +export class StageChannel extends BaseGuildVoiceChannel { + public topic: string | null; + public type: 'GUILD_STAGE_VOICE'; + public readonly stageInstance: StageInstance | null; + public createStageInstance(options: StageInstanceCreateOptions): Promise; +} + +export class StageInstance extends Base { + public constructor(client: Client, data: RawStageInstanceData, channel: StageChannel); + public id: Snowflake; + public deleted: boolean; + public guildId: Snowflake; + public channelId: Snowflake; + public topic: string; + public privacyLevel: PrivacyLevel; + public discoverableDisabled: boolean; + public readonly channel: StageChannel | null; + public readonly guild: Guild | null; + public edit(options: StageInstanceEditOptions): Promise; + public delete(): Promise; + public setTopic(topic: string): Promise; + public readonly createdTimestamp: number; + public readonly createdAt: Date; +} + +export class Sticker extends Base { + public constructor(client: Client, data: RawStickerData); + public readonly createdTimestamp: number; + public readonly createdAt: Date; + public available: boolean | null; + public description: string | null; + public format: StickerFormatType; + public readonly guild: Guild | null; + public guildId: Snowflake | null; + public id: Snowflake; + public name: string; + public packId: Snowflake | null; + public readonly partial: boolean; + public sortValue: number | null; + public tags: string[] | null; + public type: StickerType | null; + public user: User | null; + public readonly url: string; + public fetch(): Promise; + public fetchPack(): Promise; + public fetchUser(): Promise; + public edit(data?: GuildStickerEditData, reason?: string): Promise; + public delete(reason?: string): Promise; + public equals(other: Sticker | unknown): boolean; +} + +export class StickerPack extends Base { + public constructor(client: Client, data: RawStickerPackData); + public readonly createdTimestamp: number; + public readonly createdAt: Date; + public bannerId: Snowflake; + public readonly coverSticker: Sticker | null; + public coverStickerId: Snowflake | null; + public description: string; + public id: Snowflake; + public name: string; + public skuId: Snowflake; + public stickers: Collection; + public bannerURL(options?: StaticImageURLOptions): string; +} + +export class StoreChannel extends GuildChannel { + public constructor(guild: Guild, data?: RawGuildChannelData, client?: Client); + public nsfw: boolean; + public type: 'GUILD_STORE'; +} + +export class SystemChannelFlags extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; +} + +export class Team extends Base { + public constructor(client: Client, data: RawTeamData); + public id: Snowflake; + public name: string; + public icon: string | null; + public ownerId: Snowflake | null; + public members: Collection; + + public readonly owner: TeamMember | null; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + + public iconURL(options?: StaticImageURLOptions): string | null; + public toJSON(): unknown; + public toString(): string; +} + +export class TeamMember extends Base { + public constructor(team: Team, data: RawTeamMemberData); + public team: Team; + public readonly id: Snowflake; + public permissions: string[]; + public membershipState: MembershipState; + public user: User; + + public toString(): UserMention; +} + +export class TextChannel extends TextBasedChannel(GuildChannel) { + public constructor(guild: Guild, data?: RawGuildChannelData, client?: Client); + public defaultAutoArchiveDuration?: ThreadAutoArchiveDuration; + public messages: MessageManager; + public nsfw: boolean; + public type: 'GUILD_TEXT'; + public rateLimitPerUser: number; + public threads: ThreadManager; + public topic: string | null; + public createWebhook(name: string, options?: ChannelWebhookCreateOptions): Promise; + public setDefaultAutoArchiveDuration( + defaultAutoArchiveDuration: ThreadAutoArchiveDuration, + reason?: string, + ): Promise; + public setNSFW(nsfw: boolean, reason?: string): Promise; + public setRateLimitPerUser(rateLimitPerUser: number, reason?: string): Promise; + public setType(type: Pick, reason?: string): Promise; + public fetchWebhooks(): Promise>; +} + +export class ThreadChannel extends TextBasedChannel(Channel) { + public constructor(guild: Guild, data?: RawThreadChannelData, client?: Client, fromInteraction?: boolean); + public archived: boolean | null; + public readonly archivedAt: Date | null; + public archiveTimestamp: number | null; + public autoArchiveDuration: ThreadAutoArchiveDuration | null; + public readonly editable: boolean; + public guild: Guild; + public guildId: Snowflake; + public readonly guildMembers: Collection; + public readonly joinable: boolean; + public readonly joined: boolean; + public locked: boolean | null; + public readonly manageable: boolean; + public readonly sendable: boolean; + public memberCount: number | null; + public messageCount: number | null; + public messages: MessageManager; + public members: ThreadMemberManager; + public name: string; + public ownerId: Snowflake | null; + public readonly parent: TextChannel | NewsChannel | null; + public parentId: Snowflake | null; + public rateLimitPerUser: number | null; + public type: ThreadChannelTypes; + public readonly unarchivable: boolean; + public delete(reason?: string): Promise; + public edit(data: ThreadEditData, reason?: string): Promise; + public join(): Promise; + public leave(): Promise; + public permissionsFor(memberOrRole: GuildMember | Role): Readonly; + public permissionsFor(memberOrRole: GuildMemberResolvable | RoleResolvable): Readonly | null; + public fetchOwner(options?: FetchOwnerOptions): Promise; + public setArchived(archived?: boolean, reason?: string): Promise; + public setAutoArchiveDuration( + autoArchiveDuration: ThreadAutoArchiveDuration, + reason?: string, + ): Promise; + public setLocked(locked?: boolean, reason?: string): Promise; + public setName(name: string, reason?: string): Promise; + public setRateLimitPerUser(rateLimitPerUser: number, reason?: string): Promise; +} + +export class ThreadMember extends Base { + public constructor(thread: ThreadChannel, data?: RawThreadMemberData); + public flags: ThreadMemberFlags; + public readonly guildMember: GuildMember | null; + public id: Snowflake; + public readonly joinedAt: Date | null; + public joinedTimestamp: number | null; + public readonly manageable: boolean; + public thread: ThreadChannel; + public readonly user: User | null; + public remove(reason?: string): Promise; +} + +export class ThreadMemberFlags extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; +} + +export class Typing extends Base { + public constructor( + channel: TextChannel | PartialDMChannel | NewsChannel | ThreadChannel, + user: PartialUser, + data?: RawTypingData, + ); + public channel: TextChannel | PartialDMChannel | NewsChannel | ThreadChannel; + public user: PartialUser; + public startedTimestamp: number; + public readonly startedAt: Date; + public readonly guild: Guild | null; + public readonly member: GuildMember | null; + public inGuild(): this is this & { + channel: TextChannel | NewsChannel | ThreadChannel; + readonly guild: Guild; }; +} - export class DataResolver { - public static resolveBase64(data: Base64Resolvable): string; - public static resolveCode(data: string, regx: RegExp): string; - public static resolveFile(resource: BufferResolvable | Stream): Promise; - public static resolveFileAsBuffer(resource: BufferResolvable | Stream): Promise; - public static resolveImage(resource: BufferResolvable | Base64Resolvable): Promise; - public static resolveInviteCode(data: InviteResolvable): string; - public static resolveGuildTemplateCode(data: GuildTemplateResolvable): string; - } - - export class DiscordAPIError extends Error { - constructor(path: string, error: object, method: string, httpStatus: number); - private static flattenErrors(obj: object, key: string): string[]; - - public code: number; - public method: string; - public path: string; - public httpStatus: number; - } - - export class DMChannel extends TextBasedChannel(Channel, ['bulkDelete']) { - constructor(client: Client, data?: object); - public messages: MessageManager; - public recipient: User; - public readonly partial: false; - public type: 'dm'; - public fetch(force?: boolean): Promise; - } - - export class Emoji extends Base { - constructor(client: Client, emoji: object); - public animated: boolean; - public readonly createdAt: Date | null; - public readonly createdTimestamp: number | null; - public deleted: boolean; - public id: Snowflake | null; - public name: string; - public readonly identifier: string; - public readonly url: string | null; - public toJSON(): object; - public toString(): string; - } - - export class Guild extends Base { - constructor(client: Client, data: object); - private _sortedRoles(): Collection; - private _sortedChannels(channel: Channel): Collection; - private _memberSpeakUpdate(user: Snowflake, speaking: boolean): void; - - public readonly afkChannel: VoiceChannel | null; - public afkChannelID: Snowflake | null; - public afkTimeout: number; - public applicationID: Snowflake | null; - public approximateMemberCount: number | null; - public approximatePresenceCount: number | null; - public available: boolean; - public banner: string | null; - public channels: GuildChannelManager; - public readonly createdAt: Date; - public readonly createdTimestamp: number; - public defaultMessageNotifications: DefaultMessageNotifications | number; - public deleted: boolean; - public description: string | null; - public discoverySplash: string | null; - public embedChannel: GuildChannel | null; - public embedChannelID: Snowflake | null; - public embedEnabled: boolean; - public emojis: GuildEmojiManager; - public explicitContentFilter: ExplicitContentFilterLevel; - public features: GuildFeatures[]; - public icon: string | null; - public id: Snowflake; - public readonly joinedAt: Date; - public joinedTimestamp: number; - public large: boolean; - public maximumMembers: number | null; - public maximumPresences: number | null; - public readonly me: GuildMember | null; - public memberCount: number; - public members: GuildMemberManager; - public mfaLevel: number; - public name: string; - public readonly nameAcronym: string; - public readonly owner: GuildMember | null; - public ownerID: Snowflake; - public readonly partnered: boolean; - public preferredLocale: string; - public premiumSubscriptionCount: number | null; - public premiumTier: PremiumTier; - public presences: PresenceManager; - public readonly publicUpdatesChannel: TextChannel | null; - public publicUpdatesChannelID: Snowflake | null; - public region: string; - public roles: RoleManager; - public readonly rulesChannel: TextChannel | null; - public rulesChannelID: Snowflake | null; - public readonly shard: WebSocketShard; - public shardID: number; - public splash: string | null; - public readonly systemChannel: TextChannel | null; - public systemChannelFlags: Readonly; - public systemChannelID: Snowflake | null; - public vanityURLCode: string | null; - public vanityURLUses: number | null; - public verificationLevel: VerificationLevel; - public readonly verified: boolean; - public readonly voice: VoiceState | null; - public readonly voiceStates: VoiceStateManager; - public readonly widgetChannel: TextChannel | null; - public widgetChannelID: Snowflake | null; - public widgetEnabled: boolean | null; - public addMember(user: UserResolvable, options: AddGuildMemberOptions): Promise; - public bannerURL(options?: ImageURLOptions): string | null; - public createIntegration(data: IntegrationData, reason?: string): Promise; - public createTemplate(name: string, description?: string): Promise; - public delete(): Promise; - public discoverySplashURL(options?: ImageURLOptions): string | null; - public edit(data: GuildEditData, reason?: string): Promise; - public equals(guild: Guild): boolean; - public fetch(): Promise; - public fetchAuditLogs(options?: GuildAuditLogsFetchOptions): Promise; - public fetchBan(user: UserResolvable): Promise<{ user: User; reason: string }>; - public fetchBans(): Promise>; - public fetchEmbed(): Promise; - public fetchIntegrations(options?: FetchIntegrationsOptions): Promise>; - public fetchInvites(): Promise>; - public fetchPreview(): Promise; - public fetchTemplates(): Promise>; - public fetchVanityCode(): Promise; - public fetchVanityData(): Promise<{ code: string; uses: number }>; - public fetchVoiceRegions(): Promise>; - public fetchWebhooks(): Promise>; - public fetchWidget(): Promise; - public iconURL(options?: ImageURLOptions & { dynamic?: boolean }): string | null; - public leave(): Promise; - public member(user: UserResolvable): GuildMember | null; - public setAFKChannel(afkChannel: ChannelResolvable | null, reason?: string): Promise; - public setAFKTimeout(afkTimeout: number, reason?: string): Promise; - public setBanner(banner: Base64Resolvable | null, reason?: string): Promise; - public setChannelPositions(channelPositions: readonly ChannelPosition[]): Promise; - public setDefaultMessageNotifications( - defaultMessageNotifications: DefaultMessageNotifications | number, - reason?: string, - ): Promise; - public setDiscoverySplash(discoverySplash: Base64Resolvable | null, reason?: string): Promise; - public setEmbed(embed: GuildWidgetData, reason?: string): Promise; - public setExplicitContentFilter( - explicitContentFilter: ExplicitContentFilterLevel | number, - reason?: string, - ): Promise; - public setIcon(icon: Base64Resolvable | null, reason?: string): Promise; - public setName(name: string, reason?: string): Promise; - public setOwner(owner: GuildMemberResolvable, reason?: string): Promise; - public setPreferredLocale(preferredLocale: string, reason?: string): Promise; - public setPublicUpdatesChannel(publicUpdatesChannel: ChannelResolvable | null, reason?: string): Promise; - public setRegion(region: string, reason?: string): Promise; - public setRolePositions(rolePositions: readonly RolePosition[]): Promise; - public setRulesChannel(rulesChannel: ChannelResolvable | null, reason?: string): Promise; - public setSplash(splash: Base64Resolvable | null, reason?: string): Promise; - public setSystemChannel(systemChannel: ChannelResolvable | null, reason?: string): Promise; - public setSystemChannelFlags(systemChannelFlags: SystemChannelFlagsResolvable, reason?: string): Promise; - public setVerificationLevel(verificationLevel: VerificationLevel | number, reason?: string): Promise; - public setWidget(widget: GuildWidgetData, reason?: string): Promise; - public splashURL(options?: ImageURLOptions): string | null; - public toJSON(): object; - public toString(): string; - } - - export class GuildAuditLogs { - constructor(guild: Guild, data: object); - private webhooks: Collection; - private integrations: Collection; - - public entries: Collection; - - public static Actions: GuildAuditLogsActions; - public static Targets: GuildAuditLogsTargets; - public static Entry: typeof GuildAuditLogsEntry; - public static actionType(action: number): GuildAuditLogsActionType; - public static build(...args: any[]): Promise; - public static targetType(target: number): GuildAuditLogsTarget; - public toJSON(): object; - } - - class GuildAuditLogsEntry { - constructor(logs: GuildAuditLogs, guild: Guild, data: object); - public action: GuildAuditLogsAction; - public actionType: GuildAuditLogsActionType; - public changes: AuditLogChange[] | null; - public readonly createdAt: Date; - public readonly createdTimestamp: number; - public executor: User; - public extra: object | Role | GuildMember | null; - public id: Snowflake; - public reason: string | null; - public target: - | Guild - | GuildChannel - | User - | Role - | GuildEmoji - | Invite - | Webhook - | Message - | Integration - | { id: Snowflake } - | null; - public targetType: GuildAuditLogsTarget; - public toJSON(): object; - } - - export class GuildChannel extends Channel { - constructor(guild: Guild, data?: object); - private memberPermissions(member: GuildMember): Readonly; - private rolePermissions(role: Role): Readonly; - - public readonly calculatedPosition: number; - public readonly deletable: boolean; - public guild: Guild; - public readonly manageable: boolean; - public readonly members: Collection; - public name: string; - public readonly parent: CategoryChannel | null; - public parentID: Snowflake | null; - public permissionOverwrites: Collection; - public readonly permissionsLocked: boolean | null; - public readonly position: number; - public rawPosition: number; - public type: Exclude; - public readonly viewable: boolean; - public clone(options?: GuildChannelCloneOptions): Promise; - public createInvite(options?: InviteOptions): Promise; - public createOverwrite( - userOrRole: RoleResolvable | UserResolvable, - options: PermissionOverwriteOption, - reason?: string, - ): Promise; - public edit(data: ChannelData, reason?: string): Promise; - public equals(channel: GuildChannel): boolean; - public fetchInvites(): Promise>; - public lockPermissions(): Promise; - public overwritePermissions( - overwrites: readonly OverwriteResolvable[] | Collection, - reason?: string, - ): Promise; - public permissionsFor(memberOrRole: GuildMemberResolvable | RoleResolvable): Readonly | null; - public setName(name: string, reason?: string): Promise; - public setParent( - channel: CategoryChannel | Snowflake | null, - options?: { lockPermissions?: boolean; reason?: string }, - ): Promise; - public setPosition(position: number, options?: { relative?: boolean; reason?: string }): Promise; - public setTopic(topic: string | null, reason?: string): Promise; - public updateOverwrite( - userOrRole: RoleResolvable | UserResolvable, - options: PermissionOverwriteOption, - reason?: string, - ): Promise; - public isText(): this is TextChannel | NewsChannel; - } - - export class GuildEmoji extends BaseGuildEmoji { - public readonly deletable: boolean; - public guild: Guild; - public author: User | null; - public readonly roles: GuildEmojiRoleManager; - public readonly url: string; - public delete(reason?: string): Promise; - public edit(data: GuildEmojiEditData, reason?: string): Promise; - public equals(other: GuildEmoji | object): boolean; - public fetchAuthor(): Promise; - public setName(name: string, reason?: string): Promise; - } - - export class GuildMember extends PartialTextBasedChannel(Base) { - constructor(client: Client, data: object, guild: Guild); - public readonly bannable: boolean; - public deleted: boolean; - public readonly displayColor: number; - public readonly displayHexColor: string; - public readonly displayName: string; - public guild: Guild; - public readonly id: Snowflake; - public readonly joinedAt: Date | null; - public joinedTimestamp: number | null; - public readonly kickable: boolean; - public lastMessageChannelID: Snowflake | null; - public readonly manageable: boolean; - public nickname: string | null; - public readonly partial: false; - public readonly permissions: Readonly; - public readonly premiumSince: Date | null; - public premiumSinceTimestamp: number | null; - public readonly presence: Presence; - public readonly roles: GuildMemberRoleManager; - public user: User; - public readonly voice: VoiceState; - public ban(options?: BanOptions): Promise; - public fetch(force?: boolean): Promise; - public createDM(force?: boolean): Promise; - public deleteDM(): Promise; - public edit(data: GuildMemberEditData, reason?: string): Promise; - public hasPermission( - permission: PermissionResolvable, - options?: { checkAdmin?: boolean; checkOwner?: boolean }, - ): boolean; - public kick(reason?: string): Promise; - public permissionsIn(channel: ChannelResolvable): Readonly; - public setNickname(nickname: string, reason?: string): Promise; - public toJSON(): object; - public toString(): string; - public valueOf(): string; - } - - export class GuildPreview extends Base { - constructor(client: Client, data: object); - public approximateMemberCount: number; - public approximatePresenceCount: number; - public description: string | null; - public discoverySplash: string | null; - public emojis: Collection; - public features: GuildFeatures[]; - public icon: string | null; - public id: string; - public name: string; - public splash: string | null; - public discoverySplashURL(options?: ImageURLOptions): string | null; - public iconURL(options?: ImageURLOptions & { dynamic?: boolean }): string | null; - public splashURL(options?: ImageURLOptions): string | null; - public fetch(): Promise; - public toJSON(): object; - public toString(): string; - } - - export class GuildTemplate extends Base { - constructor(client: Client, data: object); - public readonly createdTimestamp: number; - public readonly updatedTimestamp: number; - public readonly url: string; - public code: string; - public name: string; - public description: string | null; - public usageCount: number; - public creator: User; - public creatorID: Snowflake; - public createdAt: Date; - public updatedAt: Date; - public guild: Guild | null; - public guildID: Snowflake; - public serializedGuild: object; - public unSynced: boolean | null; - public createGuild(name: string, icon?: BufferResolvable | Base64Resolvable): Promise; - public delete(): Promise; - public edit(options?: { name?: string; description?: string }): Promise; - public sync(): Promise; - } - - export class GuildPreviewEmoji extends BaseGuildEmoji { - constructor(client: Client, data: object, guild: GuildPreview); - public guild: GuildPreview; - public readonly roles: Set; - } - - export class HTTPError extends Error { - constructor(message: string, name: string, code: number, method: string, path: string); - public code: number; - public method: string; - public name: string; - public path: string; - } - - export class Integration extends Base { - constructor(client: Client, data: object, guild: Guild); - public account: IntegrationAccount; - public application: IntegrationApplication | null; - public enabled: boolean; - public expireBehavior: number; - public expireGracePeriod: number; - public guild: Guild; - public id: Snowflake; - public name: string; - public role: Role; - public syncedAt: number; - public syncing: boolean; - public type: string; - public user: User | null; - public delete(reason?: string): Promise; - public edit(data: IntegrationEditData, reason?: string): Promise; - public sync(): Promise; - } - - export class IntegrationApplication extends Application { - public bot: User | null; - } - - export class Intents extends BitField { - public static FLAGS: Record; - public static PRIVILEGED: number; - public static ALL: number; - public static NON_PRIVILEGED: number; - public static resolve(bit?: BitFieldResolvable): number; - } - - export class Invite extends Base { - constructor(client: Client, data: object); - public channel: GuildChannel | PartialGroupDMChannel; - public code: string; - public readonly deletable: boolean; - public readonly createdAt: Date | null; - public createdTimestamp: number | null; - public readonly expiresAt: Date | null; - public readonly expiresTimestamp: number | null; - public guild: Guild | null; - public inviter: User | null; - public maxAge: number | null; - public maxUses: number | null; - public memberCount: number; - public presenceCount: number; - public targetUser: User | null; - public targetUserType: TargetUser | null; - public temporary: boolean | null; - public readonly url: string; - public uses: number | null; - public delete(reason?: string): Promise; - public toJSON(): object; - public toString(): string; - } - - export class Message extends Base { - constructor(client: Client, data: object, channel: TextChannel | DMChannel | NewsChannel); - private _edits: Message[]; - private patch(data: object): Message; - - public activity: MessageActivity | null; - public application: ClientApplication | null; - public attachments: Collection; - public author: User; - public channel: TextChannel | DMChannel | NewsChannel; - public readonly cleanContent: string; - public content: string; - public readonly createdAt: Date; - public createdTimestamp: number; - public readonly deletable: boolean; - public deleted: boolean; - public readonly editable: boolean; - public readonly editedAt: Date | null; - public editedTimestamp: number | null; - public readonly edits: Message[]; - public embeds: MessageEmbed[]; - public readonly guild: Guild | null; - public id: Snowflake; - public readonly member: GuildMember | null; - public mentions: MessageMentions; - public nonce: string | null; - public readonly partial: false; - public readonly pinnable: boolean; - public pinned: boolean; - public reactions: ReactionManager; - public system: boolean; - public tts: boolean; - public type: MessageType; - public readonly url: string; - public webhookID: Snowflake | null; - public flags: Readonly; - public reference: MessageReference | null; - public awaitReactions( - filter: CollectorFilter, - options?: AwaitReactionsOptions, - ): Promise>; - public createReactionCollector(filter: CollectorFilter, options?: ReactionCollectorOptions): ReactionCollector; - public delete(options?: { timeout?: number; reason?: string }): Promise; - public edit( - content: APIMessageContentResolvable | MessageEditOptions | MessageEmbed | APIMessage, - ): Promise; - public edit(content: StringResolvable, options: MessageEditOptions | MessageEmbed): Promise; - public equals(message: Message, rawData: object): boolean; - public fetchWebhook(): Promise; - public crosspost(): Promise; - public fetch(force?: boolean): Promise; - public pin(options?: { reason?: string }): Promise; - public react(emoji: EmojiIdentifierResolvable): Promise; - public reply( - content: APIMessageContentResolvable | (MessageOptions & { split?: false }) | MessageAdditions, - ): Promise; - public reply(options: MessageOptions & { split: true | SplitOptions }): Promise; - public reply(options: MessageOptions | APIMessage): Promise; - public reply( - content: StringResolvable, - options: (MessageOptions & { split?: false }) | MessageAdditions, - ): Promise; - public reply( - content: StringResolvable, - options: MessageOptions & { split: true | SplitOptions }, - ): Promise; - public reply(content: StringResolvable, options: MessageOptions): Promise; - public suppressEmbeds(suppress?: boolean): Promise; - public toJSON(): object; - public toString(): string; - public unpin(options?: { reason?: string }): Promise; - } - - export class MessageAttachment { - constructor(attachment: BufferResolvable | Stream, name?: string, data?: object); - - public attachment: BufferResolvable | Stream; - public height: number | null; - public id: Snowflake; - public name: string | null; - public proxyURL: string; - public size: number; - public readonly spoiler: boolean; - public url: string; - public width: number | null; - public setFile(attachment: BufferResolvable | Stream, name?: string): this; - public setName(name: string): this; - public toJSON(): object; - } - - export class MessageCollector extends Collector { - constructor(channel: TextChannel | DMChannel, filter: CollectorFilter, options?: MessageCollectorOptions); - private _handleChannelDeletion(channel: GuildChannel): void; - private _handleGuildDeletion(guild: Guild): void; - - public channel: Channel; - public options: MessageCollectorOptions; - public received: number; - - public collect(message: Message): Snowflake; - public dispose(message: Message): Snowflake; - public endReason(): string; - } - - export class MessageEmbed { - constructor(data?: MessageEmbed | MessageEmbedOptions); - public author: MessageEmbedAuthor | null; - public color: number | null; - public readonly createdAt: Date | null; - public description: string | null; - public fields: EmbedField[]; - public files: (MessageAttachment | string | FileOptions)[]; - public footer: MessageEmbedFooter | null; - public readonly hexColor: string | null; - public image: MessageEmbedImage | null; - public readonly length: number; - public provider: MessageEmbedProvider | null; - public thumbnail: MessageEmbedThumbnail | null; - public timestamp: number | null; - public title: string | null; - public type: string; - public url: string | null; - public readonly video: MessageEmbedVideo | null; - public addField(name: StringResolvable, value: StringResolvable, inline?: boolean): this; - public addFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): this; - public attachFiles(file: (MessageAttachment | FileOptions | string)[]): this; - public setAuthor(name: StringResolvable, iconURL?: string, url?: string): this; - public setColor(color: ColorResolvable): this; - public setDescription(description: StringResolvable): this; - public setFooter(text: StringResolvable, iconURL?: string): this; - public setImage(url: string): this; - public setThumbnail(url: string): this; - public setTimestamp(timestamp?: Date | number): this; - public setTitle(title: StringResolvable): this; - public setURL(url: string): this; - public spliceFields(index: number, deleteCount: number, ...fields: EmbedFieldData[] | EmbedFieldData[][]): this; - public toJSON(): object; - - public static normalizeField( - name: StringResolvable, - value: StringResolvable, - inline?: boolean, - ): Required; - public static normalizeFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): Required[]; - } - - export class MessageFlags extends BitField { - public static FLAGS: Record; - public static resolve(bit?: BitFieldResolvable): number; - } - - export class MessageMentions { - constructor( - message: Message, - users: object[] | Collection, - roles: Snowflake[] | Collection, - everyone: boolean, - ); - private _channels: Collection | null; - private readonly _content: string; - private _members: Collection | null; - - public readonly channels: Collection; - public readonly client: Client; - public everyone: boolean; - public readonly guild: Guild; - public has( - data: UserResolvable | RoleResolvable | GuildChannelResolvable, - options?: { - ignoreDirect?: boolean; - ignoreRoles?: boolean; - ignoreEveryone?: boolean; - }, - ): boolean; - public readonly members: Collection | null; - public roles: Collection; - public users: Collection; - public crosspostedChannels: Collection; - public toJSON(): object; - - public static CHANNELS_PATTERN: RegExp; - public static EVERYONE_PATTERN: RegExp; - public static ROLES_PATTERN: RegExp; - public static USERS_PATTERN: RegExp; - } - - export class MessageReaction { - constructor(client: Client, data: object, message: Message); - private _emoji: GuildEmoji | ReactionEmoji; - - public readonly client: Client; - public count: number | null; - public readonly emoji: GuildEmoji | ReactionEmoji; - public me: boolean; - public message: Message; - public readonly partial: boolean; - public users: ReactionUserManager; - public remove(): Promise; - public fetch(): Promise; - public toJSON(): object; - } - - export class NewsChannel extends TextBasedChannel(GuildChannel) { - constructor(guild: Guild, data?: object); - public messages: MessageManager; - public nsfw: boolean; - public topic: string | null; - public type: 'news'; - public createWebhook( - name: string, - options?: { avatar?: BufferResolvable | Base64Resolvable; reason?: string }, - ): Promise; - public setNSFW(nsfw: boolean, reason?: string): Promise; - public fetchWebhooks(): Promise>; - public addFollower(channel: GuildChannelResolvable, reason?: string): Promise; - } - - export class PartialGroupDMChannel extends Channel { - constructor(client: Client, data: object); - public name: string; - public icon: string | null; - public iconURL(options?: ImageURLOptions): string | null; - } - - export class PermissionOverwrites { - constructor(guildChannel: GuildChannel, data?: object); - public allow: Readonly; - public readonly channel: GuildChannel; - public deny: Readonly; - public id: Snowflake; - public type: OverwriteType; - public update(options: PermissionOverwriteOption, reason?: string): Promise; - public delete(reason?: string): Promise; - public toJSON(): object; - public static resolveOverwriteOptions( - options: ResolvedOverwriteOptions, - initialPermissions: { allow?: PermissionResolvable; deny?: PermissionResolvable }, - ): ResolvedOverwriteOptions; - public static resolve(overwrite: OverwriteResolvable, guild: Guild): RawOverwriteData; - } - - export class Permissions extends BitField { - public any(permission: PermissionResolvable, checkAdmin?: boolean): boolean; - public has(permission: PermissionResolvable, checkAdmin?: boolean): boolean; - public missing(bits: BitFieldResolvable, checkAdmin?: boolean): PermissionString[]; - public serialize(checkAdmin?: boolean): Record; - public toArray(checkAdmin?: boolean): PermissionString[]; - - public static ALL: number; - public static DEFAULT: number; - public static FLAGS: PermissionFlags; - public static resolve(permission?: PermissionResolvable): number; - } - - export class Presence { - constructor(client: Client, data?: object); - public activities: Activity[]; - public clientStatus: ClientPresenceStatusData | null; - public guild: Guild | null; - public readonly member: GuildMember | null; - public status: PresenceStatus; - public readonly user: User | null; - public userID: Snowflake; - public equals(presence: Presence): boolean; - } - - export class ReactionCollector extends Collector { - constructor(message: Message, filter: CollectorFilter, options?: ReactionCollectorOptions); - private _handleChannelDeletion(channel: GuildChannel): void; - private _handleGuildDeletion(guild: Guild): void; - private _handleMessageDeletion(message: Message): void; - - public message: Message; - public options: ReactionCollectorOptions; - public total: number; - public users: Collection; - - public static key(reaction: MessageReaction): Snowflake | string; - - public collect(reaction: MessageReaction): Snowflake | string; - public dispose(reaction: MessageReaction, user: User): Snowflake | string; - public empty(): void; - public endReason(): string | null; - - public on(event: 'collect' | 'dispose' | 'remove', listener: (reaction: MessageReaction, user: User) => void): this; - public on( - event: 'end', - listener: (collected: Collection, reason: string) => void, - ): this; - public on(event: string, listener: (...args: any[]) => void): this; - - public once( - event: 'collect' | 'dispose' | 'remove', - listener: (reaction: MessageReaction, user: User) => void, - ): this; - public once( - event: 'end', - listener: (collected: Collection, reason: string) => void, - ): this; - public once(event: string, listener: (...args: any[]) => void): this; - } - - export class ReactionEmoji extends Emoji { - constructor(reaction: MessageReaction, emoji: object); - public reaction: MessageReaction; - public toJSON(): object; - } - - export class RichPresenceAssets { - constructor(activity: Activity, assets: object); - public largeImage: Snowflake | null; - public largeText: string | null; - public smallImage: Snowflake | null; - public smallText: string | null; - public largeImageURL(options?: ImageURLOptions): string | null; - public smallImageURL(options?: ImageURLOptions): string | null; - } - - export class Role extends Base { - constructor(client: Client, data: object, guild: Guild); - public color: number; - public readonly createdAt: Date; - public readonly createdTimestamp: number; - public deleted: boolean; - public readonly editable: boolean; - public guild: Guild; - public readonly hexColor: string; - public hoist: boolean; - public id: Snowflake; - public managed: boolean; - public readonly members: Collection; - public mentionable: boolean; - public name: string; - public permissions: Readonly; - public readonly position: number; - public rawPosition: number; - public comparePositionTo(role: Role): number; - public delete(reason?: string): Promise; - public edit(data: RoleData, reason?: string): Promise; - public equals(role: Role): boolean; - public permissionsIn(channel: ChannelResolvable): Readonly; - public setColor(color: ColorResolvable, reason?: string): Promise; - public setHoist(hoist: boolean, reason?: string): Promise; - public setMentionable(mentionable: boolean, reason?: string): Promise; - public setName(name: string, reason?: string): Promise; - public setPermissions(permissions: PermissionResolvable, reason?: string): Promise; - public setPosition(position: number, options?: { relative?: boolean; reason?: string }): Promise; - public toJSON(): object; - public toString(): string; - - public static comparePositions(role1: Role, role2: Role): number; - } - - export class Shard extends EventEmitter { - constructor(manager: ShardingManager, id: number); - private _evals: Map>; - private _exitListener: (...args: any[]) => void; - private _fetches: Map>; - private _handleExit(respawn?: boolean): void; - private _handleMessage(message: any): void; - - public args: string[]; - public execArgv: string[]; - public env: object; - public id: number; - public manager: ShardingManager; - public process: ChildProcess | null; - public ready: boolean; - public worker: any | null; - public eval(script: string): Promise; - public eval(fn: (client: Client) => T): Promise; - public fetchClientValue(prop: string): Promise; - public kill(): void; - public respawn(delay?: number, spawnTimeout?: number): Promise; - public send(message: any): Promise; - public spawn(spawnTimeout?: number): Promise; - - public on(event: 'spawn' | 'death', listener: (child: ChildProcess) => void): this; - public on(event: 'disconnect' | 'ready' | 'reconnecting', listener: () => void): this; - public on(event: 'error', listener: (error: Error) => void): this; - public on(event: 'message', listener: (message: any) => void): this; - public on(event: string, listener: (...args: any[]) => void): this; - - public once(event: 'spawn' | 'death', listener: (child: ChildProcess) => void): this; - public once(event: 'disconnect' | 'ready' | 'reconnecting', listener: () => void): this; - public once(event: 'error', listener: (error: Error) => void): this; - public once(event: 'message', listener: (message: any) => void): this; - public once(event: string, listener: (...args: any[]) => void): this; - } - - export class ShardClientUtil { - constructor(client: Client, mode: ShardingManagerMode); - private _handleMessage(message: any): void; - private _respond(type: string, message: any): void; - - public client: Client; - public readonly count: number; - public readonly ids: number[]; - public mode: ShardingManagerMode; - public parentPort: any | null; - public broadcastEval(script: string): Promise; - public broadcastEval(script: string, shard: number): Promise; - public broadcastEval(fn: (client: Client) => T): Promise; - public broadcastEval(fn: (client: Client) => T, shard: number): Promise; - public fetchClientValues(prop: string): Promise; - public fetchClientValues(prop: string, shard: number): Promise; - public respawnAll(shardDelay?: number, respawnDelay?: number, spawnTimeout?: number): Promise; - public send(message: any): Promise; - - public static singleton(client: Client, mode: ShardingManagerMode): ShardClientUtil; - public static shardIDForGuildID(guildID: Snowflake, shardCount: number): number; - } - - export class ShardingManager extends EventEmitter { - constructor( - file: string, - options?: { - totalShards?: number | 'auto'; - shardList?: number[] | 'auto'; - mode?: ShardingManagerMode; - respawn?: boolean; - shardArgs?: string[]; - token?: string; - execArgv?: string[]; - }, - ); - private _performOnShards(method: string, args: any[]): Promise; - private _performOnShards(method: string, args: any[], shard: number): Promise; - - public file: string; - public respawn: boolean; - public shardArgs: string[]; - public shards: Collection; - public token: string | null; - public totalShards: number | 'auto'; - public broadcast(message: any): Promise; - public broadcastEval(script: string): Promise; - public broadcastEval(script: string, shard: number): Promise; - public createShard(id: number): Shard; - public fetchClientValues(prop: string): Promise; - public fetchClientValues(prop: string, shard: number): Promise; - public respawnAll( - shardDelay?: number, - respawnDelay?: number, - spawnTimeout?: number, - ): Promise>; - public spawn(amount?: number | 'auto', delay?: number, spawnTimeout?: number): Promise>; - - public on(event: 'shardCreate', listener: (shard: Shard) => void): this; - - public once(event: 'shardCreate', listener: (shard: Shard) => void): this; - } - - export class SnowflakeUtil { - public static deconstruct(snowflake: Snowflake): DeconstructedSnowflake; - public static generate(timestamp?: number | Date): Snowflake; - public static readonly EPOCH: number; - } - - export class Speaking extends BitField { - public static FLAGS: Record; - public static resolve(bit?: BitFieldResolvable): number; - } - - export class StoreChannel extends GuildChannel { - constructor(guild: Guild, data?: object); - public nsfw: boolean; - public type: 'store'; - } - - class StreamDispatcher extends VolumeMixin(Writable) { - constructor(player: object, options?: StreamOptions, streams?: object); - public readonly bitrateEditable: boolean; - public broadcast: VoiceBroadcast | null; - public readonly paused: boolean; - public pausedSince: number | null; - public readonly pausedTime: number; - public player: object; - public readonly streamTime: number; - public readonly totalStreamTime: number; - - public pause(silence?: boolean): void; - public resume(): void; - public setBitrate(value: number | 'auto'): boolean; - public setFEC(enabled: boolean): boolean; - public setPLP(value: number): boolean; - - public on(event: 'close' | 'drain' | 'finish' | 'start', listener: () => void): this; - public on(event: 'debug', listener: (info: string) => void): this; - public on(event: 'error', listener: (err: Error) => void): this; - public on(event: 'pipe' | 'unpipe', listener: (src: Readable) => void): this; - public on(event: 'speaking', listener: (speaking: boolean) => void): this; - public on(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this; - public on(event: string, listener: (...args: any[]) => void): this; - - public once(event: 'close' | 'drain' | 'finish' | 'start', listener: () => void): this; - public once(event: 'debug', listener: (info: string) => void): this; - public once(event: 'error', listener: (err: Error) => void): this; - public once(event: 'pipe' | 'unpipe', listener: (src: Readable) => void): this; - public once(event: 'speaking', listener: (speaking: boolean) => void): this; - public once(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this; - public once(event: string, listener: (...args: any[]) => void): this; - } - - export class Structures { - public static get(structure: K): Extendable[K]; - public static get(structure: string): (...args: any[]) => void; - public static extend( - structure: K, - extender: (baseClass: Extendable[K]) => T, - ): T; - public static extend void>( - structure: string, - extender: (baseClass: typeof Function) => T, - ): T; - } - - export class SystemChannelFlags extends BitField { - public static FLAGS: Record; - public static resolve(bit?: BitFieldResolvable): number; - } - - export class Team extends Base { - constructor(client: Client, data: object); - public id: Snowflake; - public name: string; - public icon: string | null; - public ownerID: Snowflake | null; - public members: Collection; - - public readonly owner: TeamMember; - public readonly createdAt: Date; - public readonly createdTimestamp: number; - - public iconURL(options?: ImageURLOptions): string; - public toJSON(): object; - public toString(): string; - } - - export class TeamMember extends Base { - constructor(team: Team, data: object); - public team: Team; - public readonly id: Snowflake; - public permissions: string[]; - public membershipState: MembershipStates; - public user: User; - - public toString(): string; - } - - export class TextChannel extends TextBasedChannel(GuildChannel) { - constructor(guild: Guild, data?: object); - public messages: MessageManager; - public nsfw: boolean; - public type: 'text'; - public rateLimitPerUser: number; - public topic: string | null; - public createWebhook( - name: string, - options?: { avatar?: BufferResolvable | Base64Resolvable; reason?: string }, - ): Promise; - public setNSFW(nsfw: boolean, reason?: string): Promise; - public setRateLimitPerUser(rateLimitPerUser: number, reason?: string): Promise; - public fetchWebhooks(): Promise>; - } - - export class User extends PartialTextBasedChannel(Base) { - constructor(client: Client, data: object); - public avatar: string | null; - public bot: boolean; - public readonly createdAt: Date; - public readonly createdTimestamp: number; - public discriminator: string; - public readonly defaultAvatarURL: string; - public readonly dmChannel: DMChannel | null; - public flags: Readonly | null; - public id: Snowflake; - public lastMessageID: Snowflake | null; - public locale: string | null; - public readonly partial: false; - public readonly presence: Presence; - public system: boolean | null; - public readonly tag: string; - public username: string; - public avatarURL(options?: ImageURLOptions & { dynamic?: boolean }): string | null; - public createDM(): Promise; - public deleteDM(): Promise; - public displayAvatarURL(options?: ImageURLOptions & { dynamic?: boolean }): string; - public equals(user: User): boolean; - public fetch(force?: boolean): Promise; - public fetchFlags(force?: boolean): Promise; - public toString(): string; - public typingDurationIn(channel: ChannelResolvable): number; - public typingIn(channel: ChannelResolvable): boolean; - public typingSinceIn(channel: ChannelResolvable): Date; - } - - export class UserFlags extends BitField { - public static FLAGS: Record; - public static resolve(bit?: BitFieldResolvable): number; - } - - export class Util { - public static basename(path: string, ext?: string): string; - public static binaryToID(num: string): Snowflake; - public static cleanContent(str: string, message: Message): string; - public static removeMentions(str: string): string; - public static cloneObject(obj: object): object; - public static convertToBuffer(ab: ArrayBuffer | string): Buffer; - public static delayFor(ms: number): Promise; - public static discordSort( - collection: Collection, - ): Collection; - public static escapeMarkdown(text: string, options?: EscapeMarkdownOptions): string; - public static escapeCodeBlock(text: string): string; - public static escapeInlineCode(text: string): string; - public static escapeBold(text: string): string; - public static escapeItalic(text: string): string; - public static escapeUnderline(text: string): string; - public static escapeStrikethrough(text: string): string; - public static escapeSpoiler(text: string): string; - public static cleanCodeBlockContent(text: string): string; - public static fetchRecommendedShards(token: string, guildsPerShard?: number): Promise; - public static flatten(obj: object, ...props: { [key: string]: boolean | string }[]): object; - public static idToBinary(num: Snowflake): string; - public static makeError(obj: { name: string; message: string; stack: string }): Error; - public static makePlainError(err: Error): { name: string; message: string; stack: string }; - public static mergeDefault(def: object, given: object): object; - public static moveElementInArray(array: any[], element: any, newIndex: number, offset?: boolean): number; - public static parseEmoji(text: string): { animated: boolean; name: string; id: string | null } | null; - public static resolveColor(color: ColorResolvable): number; - public static resolveString(data: StringResolvable): string; - public static setPosition( - item: T, - position: number, - relative: boolean, - sorted: Collection, - route: object, - reason?: string, - ): Promise<{ id: Snowflake; position: number }[]>; - public static splitMessage(text: StringResolvable, options?: SplitOptions): string[]; - public static str2ab(str: string): ArrayBuffer; - } - - class VoiceBroadcast extends EventEmitter { - constructor(client: Client); - public client: Client; - public subscribers: StreamDispatcher[]; - public readonly dispatcher: BroadcastDispatcher | null; - public play(input: string | Readable, options?: StreamOptions): BroadcastDispatcher; - public end(): void; - - public on(event: 'end', listener: () => void): this; - public on(event: 'subscribe' | 'unsubscribe', listener: (dispatcher: StreamDispatcher) => void): this; - public on(event: string, listener: (...args: any[]) => void): this; - - public once(event: 'end', listener: () => void): this; - public once(event: 'subscribe' | 'unsubscribe', listener: (dispatcher: StreamDispatcher) => void): this; - public once(event: string, listener: (...args: any[]) => void): this; - } - - export class VoiceChannel extends GuildChannel { - constructor(guild: Guild, data?: object); - public bitrate: number; - public readonly editable: boolean; - public readonly full: boolean; - public readonly joinable: boolean; - public readonly speakable: boolean; - public type: 'voice'; - public userLimit: number; - public join(): Promise; - public leave(): void; - public setBitrate(bitrate: number, reason?: string): Promise; - public setUserLimit(userLimit: number, reason?: string): Promise; - } - - class VoiceConnection extends EventEmitter { - constructor(voiceManager: ClientVoiceManager, channel: VoiceChannel); - private authentication: object; - private sockets: object; - private ssrcMap: Map; - private _speaking: Map>; - private _disconnect(): void; - private authenticate(): void; - private authenticateFailed(reason: string): void; - private checkAuthenticated(): void; - private cleanup(): void; - private connect(): void; - private onReady(data: object): void; - private onSessionDescription(mode: string, secret: string): void; - private onSpeaking(data: object): void; - private reconnect(token: string, endpoint: string): void; - private sendVoiceStateUpdate(options: object): Promise; - private setSessionID(sessionID: string): void; - private setTokenAndEndpoint(token: string, endpoint: string): void; - private updateChannel(channel: VoiceChannel): void; - - public channel: VoiceChannel; - public readonly client: Client; - public readonly dispatcher: StreamDispatcher; - public player: object; - public receiver: VoiceReceiver; - public speaking: Readonly; - public status: VoiceStatus; - public readonly voice: VoiceState | null; - public voiceManager: ClientVoiceManager; - public disconnect(): void; - public play(input: VoiceBroadcast | Readable | string, options?: StreamOptions): StreamDispatcher; - public setSpeaking(value: BitFieldResolvable): void; - - public on(event: 'authenticated' | 'closing' | 'newSession' | 'ready' | 'reconnecting', listener: () => void): this; - public on(event: 'debug', listener: (message: string) => void): this; - public on(event: 'error' | 'failed' | 'disconnect', listener: (error: Error) => void): this; - public on(event: 'speaking', listener: (user: User, speaking: Readonly) => void): this; - public on(event: 'warn', listener: (warning: string | Error) => void): this; - public on(event: string, listener: (...args: any[]) => void): this; - - public once( - event: 'authenticated' | 'closing' | 'newSession' | 'ready' | 'reconnecting', - listener: () => void, - ): this; - public once(event: 'debug', listener: (message: string) => void): this; - public once(event: 'error' | 'failed' | 'disconnect', listener: (error: Error) => void): this; - public once(event: 'speaking', listener: (user: User, speaking: Readonly) => void): this; - public once(event: 'warn', listener: (warning: string | Error) => void): this; - public once(event: string, listener: (...args: any[]) => void): this; - } - - class VoiceReceiver extends EventEmitter { - constructor(connection: VoiceConnection); - public createStream( - user: UserResolvable, - options?: { mode?: 'opus' | 'pcm'; end?: 'silence' | 'manual' }, - ): Readable; - - public on(event: 'debug', listener: (error: Error | string) => void): this; - public on(event: string, listener: (...args: any[]) => void): this; - - public once(event: 'debug', listener: (error: Error | string) => void): this; - public once(event: string, listener: (...args: any[]) => void): this; - } - - export class VoiceRegion { - constructor(data: object); - public custom: boolean; - public deprecated: boolean; - public id: string; - public name: string; - public optimal: boolean; - public vip: boolean; - public toJSON(): object; - } - - export class VoiceState extends Base { - constructor(guild: Guild, data: object); - public readonly channel: VoiceChannel | null; - public channelID: Snowflake | null; - public readonly connection: VoiceConnection | null; - public readonly deaf: boolean | null; - public guild: Guild; - public id: Snowflake; - public readonly member: GuildMember | null; - public readonly mute: boolean | null; - public selfDeaf: boolean | null; - public selfMute: boolean | null; - public serverDeaf: boolean | null; - public serverMute: boolean | null; - public sessionID: string | null; - public streaming: boolean; - public selfVideo: boolean; - public readonly speaking: boolean | null; - - public setDeaf(deaf: boolean, reason?: string): Promise; - public setMute(mute: boolean, reason?: string): Promise; - public kick(reason?: string): Promise; - public setChannel(channel: ChannelResolvable | null, reason?: string): Promise; - public setSelfDeaf(deaf: boolean): Promise; - public setSelfMute(mute: boolean): Promise; - } - - class VolumeInterface extends EventEmitter { - constructor(options?: { volume?: number }); - public readonly volume: number; - public readonly volumeDecibels: number; - public readonly volumeEditable: boolean; - public readonly volumeLogarithmic: number; - public setVolume(volume: number): void; - public setVolumeDecibels(db: number): void; - public setVolumeLogarithmic(value: number): void; - - public on(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this; - - public once(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this; - } - - export class Webhook extends WebhookMixin() { - constructor(client: Client, data?: object); - public avatar: string; - public avatarURL(options?: ImageURLOptions): string | null; - public channelID: Snowflake; - public client: Client; - public guildID: Snowflake; - public name: string; - public owner: User | object | null; - public token: string | null; - public type: WebhookTypes; - } - - export class WebhookClient extends WebhookMixin(BaseClient) { - constructor(id: string, token: string, options?: ClientOptions); - public client: this; - public token: string; - } - - export class WebSocketManager extends EventEmitter { - constructor(client: Client); - private totalShards: number | string; - private shardQueue: Set; - private packetQueue: object[]; - private destroyed: boolean; - private reconnecting: boolean; - private sessionStartLimit: { total: number; remaining: number; reset_after: number } | null; - - public readonly client: Client; - public gateway: string | null; - public shards: Collection; - public status: Status; - public readonly ping: number; - - public on(event: WSEventType, listener: (data: any, shardID: number) => void): this; - public once(event: WSEventType, listener: (data: any, shardID: number) => void): this; - - private debug(message: string, shard?: WebSocketShard): void; - private connect(): Promise; - private createShards(): Promise; - private reconnect(): Promise; - private broadcast(packet: object): void; - private destroy(): void; - private _handleSessionLimit(remaining?: number, resetAfter?: number): Promise; - private handlePacket(packet?: object, shard?: WebSocketShard): boolean; - private checkShardsReady(): Promise; - private triggerClientReady(): void; - } - - export class WebSocketShard extends EventEmitter { - constructor(manager: WebSocketManager, id: number); - private sequence: number; - private closeSequence: number; - private sessionID: string | null; - private lastPingTimestamp: number; - private lastHeartbeatAcked: boolean; - private ratelimit: { queue: object[]; total: number; remaining: number; time: 60e3; timer: NodeJS.Timeout | null }; - private connection: WebSocket | null; - private helloTimeout: NodeJS.Timeout | null; - private eventsAttached: boolean; - private expectedGuilds: Set | null; - private readyTimeout: NodeJS.Timeout | null; - - public manager: WebSocketManager; - public id: number; - public status: Status; - public ping: number; - - private debug(message: string): void; - private connect(): Promise; - private onOpen(): void; - private onMessage(event: MessageEvent): void; - private onError(error: ErrorEvent | object): void; - private onClose(event: CloseEvent): void; - private onPacket(packet: object): void; - private checkReady(): void; - private setHelloTimeout(time?: number): void; - private setHeartbeatTimer(time: number): void; - private sendHeartbeat(): void; - private ackHeartbeat(): void; - private identify(): void; - private identifyNew(): void; - private identifyResume(): void; - private _send(data: object): void; - private processQueue(): void; - private destroy(destroyOptions?: { closeCode?: number; reset?: boolean; emit?: boolean; log?: boolean }): void; - private _cleanupConnection(): void; - private _emitDestroyed(): void; - - public send(data: object): void; - public on(event: 'ready' | 'resumed' | 'invalidSession', listener: () => void): this; - public on(event: 'close', listener: (event: CloseEvent) => void): this; - public on(event: 'allReady', listener: (unavailableGuilds?: Set) => void): this; - public on(event: string, listener: (...args: any[]) => void): this; - - public once(event: 'ready' | 'resumed' | 'invalidSession', listener: () => void): this; - public once(event: 'close', listener: (event: CloseEvent) => void): this; - public once(event: 'allReady', listener: (unavailableGuilds?: Set) => void): this; - public once(event: string, listener: (...args: any[]) => void): this; - } - - //#endregion - - //#region Collections - - export class Collection extends BaseCollection { - public flatMap( - fn: (value: V, key: K, collection: this) => Collection, - thisArg?: unknown, - ): Collection; - public flatMap( - fn: (this: This, value: V, key: K, collection: this) => Collection, - thisArg: This, - ): Collection; - public mapValues(fn: (value: V, key: K, collection: this) => T, thisArg?: unknown): Collection; - public mapValues( - fn: (this: This, value: V, key: K, collection: this) => T, - thisArg: This, - ): Collection; - public toJSON(): object; - } - - //#endregion - - //#region Managers - - export class ChannelManager extends BaseManager { - constructor(client: Client, iterable: Iterable); - public fetch(id: Snowflake, cache?: boolean, force?: boolean): Promise; - } - - export abstract class BaseManager { - constructor(client: Client, iterable: Iterable, holds: Constructable, cacheType: Collection); - public holds: Constructable; - public cache: Collection; - public cacheType: Collection; - public readonly client: Client; - public add(data: any, cache?: boolean, { id, extras }?: { id: K; extras: any[] }): Holds; - public resolve(resolvable: R): Holds | null; - public resolveID(resolvable: R): K | null; - public valueOf(): Collection; - } - - export class GuildChannelManager extends BaseManager { - constructor(guild: Guild, iterable?: Iterable); - public guild: Guild; - public create(name: string, options: GuildCreateChannelOptions & { type: 'voice' }): Promise; - public create(name: string, options: GuildCreateChannelOptions & { type: 'category' }): Promise; - public create(name: string, options?: GuildCreateChannelOptions & { type?: 'text' }): Promise; - public create( - name: string, - options: GuildCreateChannelOptions, - ): Promise; - } - - export class GuildEmojiManager extends BaseManager { - constructor(guild: Guild, iterable?: Iterable); - public guild: Guild; - public create( - attachment: BufferResolvable | Base64Resolvable, - name: string, - options?: GuildEmojiCreateOptions, - ): Promise; - public resolveIdentifier(emoji: EmojiIdentifierResolvable): string | null; - } - - export class GuildEmojiRoleManager { - constructor(emoji: GuildEmoji); - public emoji: GuildEmoji; - public guild: Guild; - public cache: Collection; - public add( - roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, - ): Promise; - public set(roles: readonly RoleResolvable[] | Collection): Promise; - public remove( - roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, - ): Promise; - } - - export class GuildManager extends BaseManager { - constructor(client: Client, iterable?: Iterable); - public create(name: string, options?: GuildCreateOptions): Promise; - public fetch(id: Snowflake, cache?: boolean, force?: boolean): Promise; - } - - export class GuildMemberManager extends BaseManager { - constructor(guild: Guild, iterable?: Iterable); - public guild: Guild; - public ban(user: UserResolvable, options?: BanOptions): Promise; - public fetch( - options: UserResolvable | FetchMemberOptions | (FetchMembersOptions & { user: UserResolvable }), - ): Promise; - public fetch(options?: FetchMembersOptions): Promise>; - public prune(options: GuildPruneMembersOptions & { dry?: false; count: false }): Promise; - public prune(options?: GuildPruneMembersOptions): Promise; - public unban(user: UserResolvable, reason?: string): Promise; - } - - export class GuildMemberRoleManager extends OverridableManager { - constructor(member: GuildMember); - public readonly hoist: Role | null; - public readonly color: Role | null; - public readonly highest: Role; - public member: GuildMember; - public guild: Guild; - - public add( - roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, - reason?: string, - ): Promise; - public set(roles: readonly RoleResolvable[] | Collection, reason?: string): Promise; - public remove( - roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, - reason?: string, - ): Promise; - } - - export class MessageManager extends BaseManager { - constructor(channel: TextChannel | DMChannel, iterable?: Iterable); - public channel: TextBasedChannelFields; - public cache: Collection; - public fetch(message: Snowflake, cache?: boolean, force?: boolean): Promise; - public fetch( - options?: ChannelLogsQueryOptions, - cache?: boolean, - force?: boolean, - ): Promise>; - public fetchPinned(cache?: boolean): Promise>; - public delete(message: MessageResolvable, reason?: string): Promise; - } - - // Hacky workaround because changing the signature of an overridden method errors - class OverridableManager extends BaseManager { - public add(data: any, cache: any): any; - public set(key: any): any; - } - - export class PresenceManager extends BaseManager { - constructor(client: Client, iterable?: Iterable); - } - - export class ReactionManager extends BaseManager { - constructor(message: Message, iterable?: Iterable); - public message: Message; - public removeAll(): Promise; - } - - export class ReactionUserManager extends BaseManager { - constructor(client: Client, iterable: Iterable | undefined, reaction: MessageReaction); - public reaction: MessageReaction; - public fetch(options?: { - limit?: number; - after?: Snowflake; - before?: Snowflake; - }): Promise>; - public remove(user?: UserResolvable): Promise; - } - - export class RoleManager extends BaseManager { - constructor(guild: Guild, iterable?: Iterable); - public readonly everyone: Role; - public readonly highest: Role; - public guild: Guild; - - public create(options?: { data?: RoleData; reason?: string }): Promise; - public fetch(id: Snowflake, cache?: boolean, force?: boolean): Promise; - public fetch(id?: Snowflake, cache?: boolean, force?: boolean): Promise; - } - - export class UserManager extends BaseManager { - constructor(client: Client, iterable?: Iterable); - public fetch(id: Snowflake, cache?: boolean, force?: boolean): Promise; - } - - export class VoiceStateManager extends BaseManager { - constructor(guild: Guild, iterable?: Iterable); - public guild: Guild; - } - - //#endregion - - //#region Mixins - - // Model the TextBasedChannel mixin system, allowing application of these fields - // to the classes that use these methods without having to manually add them - // to each of those classes - - type Constructable = new (...args: any[]) => T; - function PartialTextBasedChannel(Base?: Constructable): Constructable; - function TextBasedChannel( - Base?: Constructable, - ignore?: I[], - ): Constructable>; - - interface PartialTextBasedChannelFields { - lastMessageID: Snowflake | null; - readonly lastMessage: Message | null; - send( - content: APIMessageContentResolvable | (MessageOptions & { split?: false }) | MessageAdditions, - ): Promise; - send(options: MessageOptions & { split: true | SplitOptions }): Promise; - send(options: MessageOptions | APIMessage): Promise; - send(content: StringResolvable, options: (MessageOptions & { split?: false }) | MessageAdditions): Promise; - send(content: StringResolvable, options: MessageOptions & { split: true | SplitOptions }): Promise; - send(content: StringResolvable, options: MessageOptions): Promise; - } - - interface TextBasedChannelFields extends PartialTextBasedChannelFields { - _typing: Map; - lastPinTimestamp: number | null; - readonly lastPinAt: Date | null; - typing: boolean; - typingCount: number; - awaitMessages(filter: CollectorFilter, options?: AwaitMessagesOptions): Promise>; - bulkDelete( - messages: Collection | readonly MessageResolvable[] | number, - filterOld?: boolean, - ): Promise>; - createMessageCollector(filter: CollectorFilter, options?: MessageCollectorOptions): MessageCollector; - startTyping(count?: number): Promise; - stopTyping(force?: boolean): void; - } - - function WebhookMixin(Base?: Constructable): Constructable; - - function VolumeMixin(base: Constructable): Constructable; - - interface WebhookFields { - id: Snowflake; - readonly createdAt: Date; - readonly createdTimestamp: number; - readonly url: string; - delete(reason?: string): Promise; - edit(options: WebhookEditData): Promise; - send( - content: APIMessageContentResolvable | (WebhookMessageOptions & { split?: false }) | MessageAdditions, - ): Promise; - send(options: WebhookMessageOptions & { split: true | SplitOptions }): Promise; - send(options: WebhookMessageOptions | APIMessage): Promise; - send( - content: StringResolvable, - options: (WebhookMessageOptions & { split?: false }) | MessageAdditions, - ): Promise; - send( - content: StringResolvable, - options: WebhookMessageOptions & { split: true | SplitOptions }, - ): Promise; - send(content: StringResolvable, options: WebhookMessageOptions): Promise; - sendSlackMessage(body: object): Promise; - } - - //#endregion - - //#region Typedefs - - type ActivityFlagsString = 'INSTANCE' | 'JOIN' | 'SPECTATE' | 'JOIN_REQUEST' | 'SYNC' | 'PLAY'; - - interface ActivityOptions { - name?: string; - url?: string; - type?: ActivityType | number; - shardID?: number | readonly number[]; - } - - type ActivityType = 'PLAYING' | 'STREAMING' | 'LISTENING' | 'WATCHING' | 'CUSTOM_STATUS' | 'COMPETING'; - - interface AddGuildMemberOptions { - accessToken: string; - nick?: string; - roles?: Collection | RoleResolvable[]; - mute?: boolean; - deaf?: boolean; - } - - interface APIErrors { - UNKNOWN_ACCOUNT: 10001; - UNKNOWN_APPLICATION: 10002; - UNKNOWN_CHANNEL: 10003; - UNKNOWN_GUILD: 10004; - UNKNOWN_INTEGRATION: 10005; - UNKNOWN_INVITE: 10006; - UNKNOWN_MEMBER: 10007; - UNKNOWN_MESSAGE: 10008; - UNKNOWN_OVERWRITE: 10009; - UNKNOWN_PROVIDER: 10010; - UNKNOWN_ROLE: 10011; - UNKNOWN_TOKEN: 10012; - UNKNOWN_USER: 10013; - UNKNOWN_EMOJI: 10014; - UNKNOWN_WEBHOOK: 10015; - UNKNOWN_BAN: 10026; - UNKNOWN_GUILD_TEMPLATE: 10057; - BOT_PROHIBITED_ENDPOINT: 20001; - BOT_ONLY_ENDPOINT: 20002; - CHANNEL_HIT_WRITE_RATELIMIT: 20028; - MAXIMUM_GUILDS: 30001; - MAXIMUM_FRIENDS: 30002; - MAXIMUM_PINS: 30003; - MAXIMUM_ROLES: 30005; - MAXIMUM_WEBHOOKS: 30007; - MAXIMUM_REACTIONS: 30010; - MAXIMUM_CHANNELS: 30013; - MAXIMUM_ATTACHMENTS: 30015; - MAXIMUM_INVITES: 30016; - GUILD_ALREADY_HAS_TEMPLATE: 30031; - UNAUTHORIZED: 40001; - ACCOUNT_VERIFICATION_REQUIRED: 40002; - REQUEST_ENTITY_TOO_LARGE: 40005; - FEATURE_TEMPORARILY_DISABLED: 40006; - USER_BANNED: 40007; - ALREADY_CROSSPOSTED: 40033; - MISSING_ACCESS: 50001; - INVALID_ACCOUNT_TYPE: 50002; - CANNOT_EXECUTE_ON_DM: 50003; - EMBED_DISABLED: 50004; - CANNOT_EDIT_MESSAGE_BY_OTHER: 50005; - CANNOT_SEND_EMPTY_MESSAGE: 50006; - CANNOT_MESSAGE_USER: 50007; - CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: 50008; - CHANNEL_VERIFICATION_LEVEL_TOO_HIGH: 50009; - OAUTH2_APPLICATION_BOT_ABSENT: 50010; - MAXIMUM_OAUTH2_APPLICATIONS: 50011; - INVALID_OAUTH_STATE: 50012; - MISSING_PERMISSIONS: 50013; - INVALID_AUTHENTICATION_TOKEN: 50014; - NOTE_TOO_LONG: 50015; - INVALID_BULK_DELETE_QUANTITY: 50016; - CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: 50019; - INVALID_OR_TAKEN_INVITE_CODE: 50020; - CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: 50021; - INVALID_OAUTH_TOKEN: 50025; - BULK_DELETE_MESSAGE_TOO_OLD: 50034; - INVALID_FORM_BODY: 50035; - INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: 50036; - INVALID_API_VERSION: 50041; - CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL: 50074; - REACTION_BLOCKED: 90001; - RESOURCE_OVERLOADED: 130000; - } - - type APIMessageContentResolvable = string | number | boolean | bigint | symbol | readonly StringResolvable[]; - - interface ApplicationAsset { - name: string; - id: Snowflake; - type: 'BIG' | 'SMALL'; - } - - interface AuditLogChange { - key: string; - old?: any; - new?: any; - } - - interface AwaitMessagesOptions extends MessageCollectorOptions { - errors?: string[]; - } - - interface AwaitReactionsOptions extends ReactionCollectorOptions { - errors?: string[]; - } - - interface BanOptions { - days?: number; - reason?: string; - } - - type Base64Resolvable = Buffer | Base64String; - - type Base64String = string; - - type BitFieldResolvable = - | RecursiveReadonlyArray>> - | T - | number - | Readonly>; - - type BufferResolvable = Buffer | string; - - interface ChannelCreationOverwrites { - allow?: PermissionResolvable | number; - deny?: PermissionResolvable | number; - id: RoleResolvable | UserResolvable; - } - - interface ChannelData { - name?: string; - position?: number; - topic?: string; - nsfw?: boolean; - bitrate?: number; - userLimit?: number; - parentID?: Snowflake | null; - rateLimitPerUser?: number; - lockPermissions?: boolean; - permissionOverwrites?: readonly OverwriteResolvable[] | Collection; - } - - interface ChannelLogsQueryOptions { - limit?: number; - before?: Snowflake; - after?: Snowflake; - around?: Snowflake; - } - - interface ChannelPosition { - channel: ChannelResolvable; - position: number; - } - - type ChannelResolvable = Channel | Snowflake; - - interface ClientEvents { - channelCreate: [Channel]; - channelDelete: [Channel | PartialDMChannel]; - channelPinsUpdate: [Channel | PartialDMChannel, Date]; - channelUpdate: [Channel, Channel]; - debug: [string]; - warn: [string]; - disconnect: [any, number]; - emojiCreate: [GuildEmoji]; - emojiDelete: [GuildEmoji]; - emojiUpdate: [GuildEmoji, GuildEmoji]; - error: [Error]; - guildBanAdd: [Guild, User]; - guildBanRemove: [Guild, User]; - guildCreate: [Guild]; - guildDelete: [Guild]; - guildUnavailable: [Guild]; - guildIntegrationsUpdate: [Guild]; - guildMemberAdd: [GuildMember]; - guildMemberAvailable: [GuildMember | PartialGuildMember]; - guildMemberRemove: [GuildMember | PartialGuildMember]; - guildMembersChunk: [ - Collection, - Guild, - { count: number; index: number; nonce: string | undefined }, - ]; - guildMemberSpeaking: [GuildMember | PartialGuildMember, Readonly]; - guildMemberUpdate: [GuildMember | PartialGuildMember, GuildMember]; - guildUpdate: [Guild, Guild]; - inviteCreate: [Invite]; - inviteDelete: [Invite]; - message: [Message]; - messageDelete: [Message | PartialMessage]; - messageReactionRemoveAll: [Message | PartialMessage]; - messageReactionRemoveEmoji: [MessageReaction]; - messageDeleteBulk: [Collection]; - messageReactionAdd: [MessageReaction, User | PartialUser]; - messageReactionRemove: [MessageReaction, User | PartialUser]; - messageUpdate: [Message | PartialMessage, Message | PartialMessage]; - presenceUpdate: [Presence | undefined, Presence]; - rateLimit: [RateLimitData]; - ready: []; - invalidated: []; - roleCreate: [Role]; - roleDelete: [Role]; - roleUpdate: [Role, Role]; - typingStart: [Channel | PartialDMChannel, User | PartialUser]; - userUpdate: [User | PartialUser, User]; - voiceStateUpdate: [VoiceState, VoiceState]; - webhookUpdate: [TextChannel]; - shardDisconnect: [CloseEvent, number]; - shardError: [Error, number]; - shardReady: [number, Set | undefined]; - shardReconnecting: [number]; - shardResume: [number, number]; - } - - interface ClientOptions { - shards?: number | number[] | 'auto'; - shardCount?: number; - messageCacheMaxSize?: number; - messageCacheLifetime?: number; - messageSweepInterval?: number; - messageEditHistoryMaxSize?: number; - fetchAllMembers?: boolean; - disableMentions?: 'none' | 'all' | 'everyone'; - allowedMentions?: MessageMentionOptions; - partials?: PartialTypes[]; - restWsBridgeTimeout?: number; - restTimeOffset?: number; - restRequestTimeout?: number; - restSweepInterval?: number; - retryLimit?: number; - presence?: PresenceData; - ws?: WebSocketOptions; - http?: HTTPOptions; - } - - type ClientPresenceStatus = 'online' | 'idle' | 'dnd'; - - interface ClientPresenceStatusData { - web?: ClientPresenceStatus; - mobile?: ClientPresenceStatus; - desktop?: ClientPresenceStatus; - } - - interface CloseEvent { - wasClean: boolean; - code: number; - reason: string; - target: WebSocket; - } - - type CollectorFilter = (...args: any[]) => boolean | Promise; - - interface CollectorOptions { - time?: number; - idle?: number; - dispose?: boolean; - } - - type ColorResolvable = - | 'DEFAULT' - | 'WHITE' - | 'AQUA' - | 'GREEN' - | 'BLUE' - | 'YELLOW' - | 'PURPLE' - | 'LUMINOUS_VIVID_PINK' - | 'GOLD' - | 'ORANGE' - | 'RED' - | 'GREY' - | 'DARKER_GREY' - | 'NAVY' - | 'DARK_AQUA' - | 'DARK_GREEN' - | 'DARK_BLUE' - | 'DARK_PURPLE' - | 'DARK_VIVID_PINK' - | 'DARK_GOLD' - | 'DARK_ORANGE' - | 'DARK_RED' - | 'DARK_GREY' - | 'LIGHT_GREY' - | 'DARK_NAVY' - | 'BLURPLE' - | 'GREYPLE' - | 'DARK_BUT_NOT_BLACK' - | 'NOT_QUITE_BLACK' - | 'RANDOM' - | [number, number, number] - | number - | string; - - interface CrosspostedChannel { - channelID: Snowflake; - guildID: Snowflake; - type: keyof typeof ChannelType; - name: string; - } +export class User extends PartialTextBasedChannel(Base) { + public constructor(client: Client, data: RawUserData); + public avatar: string | null; + public bot: boolean; + public readonly createdAt: Date; + public readonly createdTimestamp: number; + public discriminator: string; + public readonly defaultAvatarURL: string; + public readonly dmChannel: DMChannel | null; + public flags: Readonly | null; + public id: Snowflake; + public readonly partial: false; + public system: boolean; + public readonly tag: string; + public username: string; + public avatarURL(options?: ImageURLOptions): string | null; + public createDM(): Promise; + public deleteDM(): Promise; + public displayAvatarURL(options?: ImageURLOptions): string; + public equals(user: User): boolean; + public fetch(force?: boolean): Promise; + public fetchFlags(force?: boolean): Promise; + public toString(): UserMention; +} - interface DeconstructedSnowflake { - timestamp: number; - readonly date: Date; - workerID: number; - processID: number; - increment: number; - binary: string; - } +export class UserFlags extends BitField { + public static FLAGS: Record; + public static resolve(bit?: BitFieldResolvable): number; +} - type DefaultMessageNotifications = 'ALL' | 'MENTIONS'; +export class Util extends null { + private constructor(); + public static basename(path: string, ext?: string): string; + public static binaryToId(num: string): Snowflake; + public static cleanContent(str: string, channel: Channel): string; + public static removeMentions(str: string): string; + public static cloneObject(obj: unknown): unknown; + public static delayFor(ms: number): Promise; + public static discordSort( + collection: Collection, + ): Collection; + public static escapeMarkdown(text: string, options?: EscapeMarkdownOptions): string; + public static escapeCodeBlock(text: string): string; + public static escapeInlineCode(text: string): string; + public static escapeBold(text: string): string; + public static escapeItalic(text: string): string; + public static escapeUnderline(text: string): string; + public static escapeStrikethrough(text: string): string; + public static escapeSpoiler(text: string): string; + public static cleanCodeBlockContent(text: string): string; + public static fetchRecommendedShards(token: string, options?: FetchRecommendedShardsOptions): Promise; + public static flatten(obj: unknown, ...props: Record[]): unknown; + public static idToBinary(num: Snowflake): string; + public static makeError(obj: MakeErrorOptions): Error; + public static makePlainError(err: Error): MakeErrorOptions; + public static mergeDefault(def: unknown, given: unknown): unknown; + public static moveElementInArray(array: unknown[], element: unknown, newIndex: number, offset?: boolean): number; + public static parseEmoji(text: string): { animated: boolean; name: string; id: Snowflake | null } | null; + public static resolveColor(color: ColorResolvable): number; + public static resolvePartialEmoji(emoji: EmojiIdentifierResolvable): Partial | null; + public static verifyString(data: string, error?: typeof Error, errorMessage?: string, allowEmpty?: boolean): string; + public static setPosition( + item: T, + position: number, + relative: boolean, + sorted: Collection, + route: unknown, + reason?: string, + ): Promise<{ id: Snowflake; position: number }[]>; + public static splitMessage(text: string, options?: SplitOptions): string[]; +} - interface EmbedField { - name: string; - value: string; - inline: boolean; - } - - interface EmbedFieldData { - name: StringResolvable; - value: StringResolvable; - inline?: boolean; - } - - type EmojiIdentifierResolvable = string | EmojiResolvable; - - type EmojiResolvable = Snowflake | GuildEmoji | ReactionEmoji; - - interface ErrorEvent { - error: any; - message: string; - type: string; - target: WebSocket; - } - - interface EscapeMarkdownOptions { - codeBlock?: boolean; - inlineCode?: boolean; - bold?: boolean; - italic?: boolean; - underline?: boolean; - strikethrough?: boolean; - spoiler?: boolean; - inlineCodeContent?: boolean; - codeBlockContent?: boolean; - } - - type ExplicitContentFilterLevel = 'DISABLED' | 'MEMBERS_WITHOUT_ROLES' | 'ALL_MEMBERS'; - - interface Extendable { - GuildEmoji: typeof GuildEmoji; - DMChannel: typeof DMChannel; - TextChannel: typeof TextChannel; - VoiceChannel: typeof VoiceChannel; - CategoryChannel: typeof CategoryChannel; - NewsChannel: typeof NewsChannel; - StoreChannel: typeof StoreChannel; - GuildMember: typeof GuildMember; - Guild: typeof Guild; - Message: typeof Message; - MessageReaction: typeof MessageReaction; - Presence: typeof Presence; - VoiceState: typeof VoiceState; - Role: typeof Role; - User: typeof User; - } - - interface FetchIntegrationsOptions { - includeApplications?: boolean; - } - - interface FetchMemberOptions { - user: UserResolvable; - cache?: boolean; - force?: boolean; - } - - interface FetchMembersOptions { - user?: UserResolvable | UserResolvable[]; - query?: string; - limit?: number; - withPresences?: boolean; - time?: number; - nonce?: string; - force?: boolean; - } - - interface FileOptions { - attachment: BufferResolvable | Stream; - name?: string; - } - - type GuildAuditLogsAction = keyof GuildAuditLogsActions; - - interface GuildAuditLogsActions { - ALL?: null; - GUILD_UPDATE?: number; - CHANNEL_CREATE?: number; - CHANNEL_UPDATE?: number; - CHANNEL_DELETE?: number; - CHANNEL_OVERWRITE_CREATE?: number; - CHANNEL_OVERWRITE_UPDATE?: number; - CHANNEL_OVERWRITE_DELETE?: number; - MEMBER_KICK?: number; - MEMBER_PRUNE?: number; - MEMBER_BAN_ADD?: number; - MEMBER_BAN_REMOVE?: number; - MEMBER_UPDATE?: number; - MEMBER_ROLE_UPDATE?: number; - MEMBER_MOVE?: number; - MEMBER_DISCONNECT?: number; - BOT_ADD?: number; - ROLE_CREATE?: number; - ROLE_UPDATE?: number; - ROLE_DELETE?: number; - INVITE_CREATE?: number; - INVITE_UPDATE?: number; - INVITE_DELETE?: number; - WEBHOOK_CREATE?: number; - WEBHOOK_UPDATE?: number; - WEBHOOK_DELETE?: number; - EMOJI_CREATE?: number; - EMOJI_UPDATE?: number; - EMOJI_DELETE?: number; - MESSAGE_DELETE?: number; - MESSAGE_BULK_DELETE?: number; - MESSAGE_PIN?: number; - MESSAGE_UNPIN?: number; - INTEGRATION_CREATE?: number; - INTEGRATION_UPDATE?: number; - INTEGRATION_DELETE?: number; - } - - type GuildAuditLogsActionType = 'CREATE' | 'DELETE' | 'UPDATE' | 'ALL'; - - interface GuildAuditLogsFetchOptions { - before?: Snowflake | GuildAuditLogsEntry; - limit?: number; - user?: UserResolvable; - type?: GuildAuditLogsAction | number; - } - - type GuildAuditLogsTarget = keyof GuildAuditLogsTargets; - - interface GuildAuditLogsTargets { - ALL?: string; - GUILD?: string; - CHANNEL?: string; - USER?: string; - ROLE?: string; - INVITE?: string; - WEBHOOK?: string; - EMOJI?: string; - MESSAGE?: string; - INTEGRATION?: string; - UNKNOWN?: string; - } - - type GuildChannelResolvable = Snowflake | GuildChannel; - - interface GuildCreateChannelOptions { - permissionOverwrites?: OverwriteResolvable[] | Collection; - topic?: string; - type?: Exclude< - keyof typeof ChannelType | ChannelType, - 'dm' | 'group' | 'unknown' | ChannelType.dm | ChannelType.group | ChannelType.unknown - >; - nsfw?: boolean; - parent?: ChannelResolvable; - bitrate?: number; - userLimit?: number; - rateLimitPerUser?: number; - position?: number; - reason?: string; - } - - interface GuildChannelCloneOptions extends GuildCreateChannelOptions { - name?: string; - } - - interface GuildCreateOptions { - afkChannelID?: number; - afkTimeout?: number; - channels?: PartialChannelData[]; - defaultMessageNotifications?: DefaultMessageNotifications | number; - explicitContentFilter?: ExplicitContentFilterLevel | number; - icon?: BufferResolvable | Base64Resolvable | null; - region?: string; - roles?: PartialRoleData[]; - systemChannelID?: number; - verificationLevel?: VerificationLevel | number; - } - - interface GuildWidget { - enabled: boolean; - channel: GuildChannel | null; - } - - interface GuildEditData { - name?: string; - region?: string; - verificationLevel?: VerificationLevel | number; - explicitContentFilter?: ExplicitContentFilterLevel | number; - defaultMessageNotifications?: DefaultMessageNotifications | number; - afkChannel?: ChannelResolvable; - systemChannel?: ChannelResolvable; - systemChannelFlags?: SystemChannelFlagsResolvable; - afkTimeout?: number; - icon?: Base64Resolvable; - owner?: GuildMemberResolvable; - splash?: Base64Resolvable; - discoverySplash?: Base64Resolvable; - banner?: Base64Resolvable; - rulesChannel?: ChannelResolvable; - publicUpdatesChannel?: ChannelResolvable; - preferredLocale?: string; - } - - interface GuildEmojiCreateOptions { - roles?: Collection | RoleResolvable[]; - reason?: string; - } - - interface GuildEmojiEditData { - name?: string; - roles?: Collection | RoleResolvable[]; - } - - type GuildFeatures = - | 'ANIMATED_ICON' - | 'BANNER' - | 'COMMERCE' - | 'COMMUNITY' - | 'DISCOVERABLE' - | 'FEATURABLE' - | 'INVITE_SPLASH' - | 'NEWS' - | 'PARTNERED' - | 'RELAY_ENABLED' - | 'VANITY_URL' - | 'VERIFIED' - | 'VIP_REGIONS' - | 'WELCOME_SCREEN_ENABLED'; - - interface GuildMemberEditData { - nick?: string; - roles?: Collection | readonly RoleResolvable[]; - mute?: boolean; - deaf?: boolean; - channel?: ChannelResolvable | null; - } - - type GuildMemberResolvable = GuildMember | UserResolvable; - - type GuildResolvable = Guild | GuildChannel | GuildMember | GuildEmoji | Invite | Role | Snowflake; - - interface GuildPruneMembersOptions { - count?: boolean; - days?: number; - dry?: boolean; - reason?: string; - roles?: RoleResolvable[]; - } - - interface GuildWidgetData { - enabled: boolean; - channel: GuildChannelResolvable | null; - } - - interface HTTPOptions { - api?: string; - version?: number; - host?: string; - cdn?: string; - invite?: string; - template?: string; - } - - type ImageSize = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096; - - interface ImageURLOptions { - format?: AllowedImageFormat; - size?: ImageSize; - } - - interface IntegrationData { - id: string; - type: string; - } +export class Formatters extends null { + public static blockQuote: typeof blockQuote; + public static bold: typeof bold; + public static codeBlock: typeof codeBlock; + public static hideLinkEmbed: typeof hideLinkEmbed; + public static hyperlink: typeof hyperlink; + public static inlineCode: typeof inlineCode; + public static italic: typeof italic; + public static quote: typeof quote; + public static strikethrough: typeof strikethrough; + public static time: typeof time; + public static TimestampStyles: typeof TimestampStyles; + public static TimestampStylesString: TimestampStylesString; + public static underscore: typeof underscore; + public static spoiler: typeof spoiler; +} - interface IntegrationEditData { - expireBehavior?: number; - expireGracePeriod?: number; - } +export class VoiceChannel extends BaseGuildVoiceChannel { + public readonly editable: boolean; + public readonly speakable: boolean; + public type: 'GUILD_VOICE'; + public setBitrate(bitrate: number, reason?: string): Promise; + public setUserLimit(userLimit: number, reason?: string): Promise; +} - interface IntegrationAccount { - id: string; - name: string; - } - - type IntentsString = - | 'GUILDS' - | 'GUILD_MEMBERS' - | 'GUILD_BANS' - | 'GUILD_EMOJIS' - | 'GUILD_INTEGRATIONS' - | 'GUILD_WEBHOOKS' - | 'GUILD_INVITES' - | 'GUILD_VOICE_STATES' - | 'GUILD_PRESENCES' - | 'GUILD_MESSAGES' - | 'GUILD_MESSAGE_REACTIONS' - | 'GUILD_MESSAGE_TYPING' - | 'DIRECT_MESSAGES' - | 'DIRECT_MESSAGE_REACTIONS' - | 'DIRECT_MESSAGE_TYPING'; - - interface InviteGenerationOptions { - permissions?: PermissionResolvable; - guild?: GuildResolvable; - disableGuildSelect?: boolean; - } - - interface InviteOptions { - temporary?: boolean; - maxAge?: number; - maxUses?: number; - unique?: boolean; - reason?: string; - } - - type InviteResolvable = string; - - type GuildTemplateResolvable = string; - - type MembershipStates = 'INVITED' | 'ACCEPTED'; - - type MessageAdditions = MessageEmbed | MessageAttachment | (MessageEmbed | MessageAttachment)[]; - - interface MessageActivity { - partyID: string; - type: number; - } - - interface MessageCollectorOptions extends CollectorOptions { - max?: number; - maxProcessed?: number; - } - - interface MessageEditOptions { - content?: StringResolvable; - embed?: MessageEmbed | MessageEmbedOptions | null; - code?: string | boolean; - flags?: BitFieldResolvable; - allowedMentions?: MessageMentionOptions; - } - - interface MessageEmbedAuthor { - name?: string; - url?: string; - iconURL?: string; - proxyIconURL?: string; - } - - interface MessageEmbedFooter { - text?: string; - iconURL?: string; - proxyIconURL?: string; - } - - interface MessageEmbedImage { - url: string; - proxyURL?: string; - height?: number; - width?: number; - } - - interface MessageEmbedOptions { - title?: string; - description?: string; - url?: string; - timestamp?: Date | number; - color?: ColorResolvable; - fields?: EmbedFieldData[]; - files?: (MessageAttachment | string | FileOptions)[]; - author?: Partial & { icon_url?: string; proxy_icon_url?: string }; - thumbnail?: Partial & { proxy_url?: string }; - image?: Partial & { proxy_url?: string }; - video?: Partial & { proxy_url?: string }; - footer?: Partial & { icon_url?: string; proxy_icon_url?: string }; - } - - interface MessageEmbedProvider { +export class VoiceRegion { + public constructor(data: RawVoiceRegionData); + public custom: boolean; + public deprecated: boolean; + public id: string; + public name: string; + public optimal: boolean; + public vip: boolean; + public toJSON(): unknown; +} + +export class VoiceState extends Base { + public constructor(guild: Guild, data: RawVoiceStateData); + public readonly channel: VoiceChannel | StageChannel | null; + public channelId: Snowflake | null; + public readonly deaf: boolean | null; + public guild: Guild; + public id: Snowflake; + public readonly member: GuildMember | null; + public readonly mute: boolean | null; + public selfDeaf: boolean | null; + public selfMute: boolean | null; + public serverDeaf: boolean | null; + public serverMute: boolean | null; + public sessionId: string | null; + public streaming: boolean; + public selfVideo: boolean | null; + public suppress: boolean; + public requestToSpeakTimestamp: number | null; + + public setDeaf(deaf: boolean, reason?: string): Promise; + public setMute(mute: boolean, reason?: string): Promise; + public disconnect(reason?: string): Promise; + public setChannel(channel: VoiceChannelResolvable | null, reason?: string): Promise; + public setRequestToSpeak(request: boolean): Promise; + public setSuppressed(suppressed: boolean): Promise; +} + +export class Webhook extends WebhookMixin() { + public constructor(client: Client, data?: RawWebhookData); + public avatar: string; + public avatarURL(options?: StaticImageURLOptions): string | null; + public channelId: Snowflake; + public client: Client; + public guildId: Snowflake; + public name: string; + public owner: User | APIUser | null; + public sourceGuild: Guild | APIPartialGuild | null; + public sourceChannel: Channel | APIPartialChannel | null; + public token: string | null; + public type: WebhookType; +} + +export class WebhookClient extends WebhookMixin(BaseClient) { + public constructor(data: WebhookClientData, options?: WebhookClientOptions); + public client: this; + public options: WebhookClientOptions; + public token: string; + public editMessage( + message: MessageResolvable, + options: string | MessagePayload | WebhookEditMessageOptions, + ): Promise; + public fetchMessage(message: Snowflake, cache?: boolean): Promise; + public send(options: string | MessagePayload | WebhookMessageOptions): Promise; +} + +export class WebSocketManager extends EventEmitter { + public constructor(client: Client); + private totalShards: number | string; + private shardQueue: Set; + private packetQueue: unknown[]; + private destroyed: boolean; + private reconnecting: boolean; + + public readonly client: Client; + public gateway: string | null; + public shards: Collection; + public status: Status; + public readonly ping: number; + + public on(event: WSEventType, listener: (data: any, shardId: number) => void): this; + public once(event: WSEventType, listener: (data: any, shardId: number) => void): this; + + private debug(message: string, shard?: WebSocketShard): void; + private connect(): Promise; + private createShards(): Promise; + private reconnect(): Promise; + private broadcast(packet: unknown): void; + private destroy(): void; + private handlePacket(packet?: unknown, shard?: WebSocketShard): boolean; + private checkShardsReady(): void; + private triggerClientReady(): void; +} + +export class WebSocketShard extends EventEmitter { + public constructor(manager: WebSocketManager, id: number); + private sequence: number; + private closeSequence: number; + private sessionId: string | null; + private lastPingTimestamp: number; + private lastHeartbeatAcked: boolean; + private ratelimit: { queue: unknown[]; total: number; remaining: number; time: 60e3; timer: NodeJS.Timeout | null }; + private connection: WebSocket | null; + private helloTimeout: NodeJS.Timeout | null; + private eventsAttached: boolean; + private expectedGuilds: Set | null; + private readyTimeout: NodeJS.Timeout | null; + + public manager: WebSocketManager; + public id: number; + public status: Status; + public ping: number; + + private debug(message: string): void; + private connect(): Promise; + private onOpen(): void; + private onMessage(event: MessageEvent): void; + private onError(error: ErrorEvent | unknown): void; + private onClose(event: CloseEvent): void; + private onPacket(packet: unknown): void; + private checkReady(): void; + private setHelloTimeout(time?: number): void; + private setHeartbeatTimer(time: number): void; + private sendHeartbeat(): void; + private ackHeartbeat(): void; + private identify(): void; + private identifyNew(): void; + private identifyResume(): void; + private _send(data: unknown): void; + private processQueue(): void; + private destroy(destroyOptions?: { closeCode?: number; reset?: boolean; emit?: boolean; log?: boolean }): void; + private _cleanupConnection(): void; + private _emitDestroyed(): void; + + public send(data: unknown, important?: boolean): void; + + public on(event: 'ready' | 'resumed' | 'invalidSession', listener: () => Awaited): this; + public on(event: 'close', listener: (event: CloseEvent) => Awaited): this; + public on(event: 'allReady', listener: (unavailableGuilds?: Set) => Awaited): this; + public on(event: string, listener: (...args: any[]) => Awaited): this; + + public once(event: 'ready' | 'resumed' | 'invalidSession', listener: () => Awaited): this; + public once(event: 'close', listener: (event: CloseEvent) => Awaited): this; + public once(event: 'allReady', listener: (unavailableGuilds?: Set) => Awaited): this; + public once(event: string, listener: (...args: any[]) => Awaited): this; +} + +export class Widget extends Base { + public constructor(client: Client, data: RawWidgetData); + private _patch(data: RawWidgetData): void; + public fetch(): Promise; + public id: Snowflake; + public instantInvite?: string; + public channels: Collection; + public members: Collection; + public presenceCount: number; +} + +export class WidgetMember extends Base { + public constructor(client: Client, data: RawWidgetMemberData); + public id: string; + public username: string; + public discriminator: string; + public avatar?: string; + public status: PresenceStatus; + public deaf?: boolean; + public mute?: boolean; + public selfDeaf?: boolean; + public selfMute?: boolean; + public suppress?: boolean; + public channelId?: Snowflake; + public avatarURL: string; + public activity?: WidgetActivity; +} + +export class WelcomeChannel extends Base { + constructor(guild: Guild, data: RawWelcomeChannelData); + private _emoji: Omit; + public channelId: Snowflake; + public guild: Guild | InviteGuild; + public description: string; + public readonly channel: TextChannel | NewsChannel | null; + public readonly emoji: GuildEmoji | Emoji; +} + +export class WelcomeScreen extends Base { + constructor(guild: Guild, data: RawWelcomeScreenData); + public readonly enabled: boolean; + public guild: Guild | InviteGuild; + public description: string | null; + public welcomeChannels: Collection; +} + +//#endregion + +//#region Constants + +export const Constants: { + Package: { name: string; - url: string; - } - - interface MessageEmbedThumbnail { - url: string; - proxyURL?: string; - height?: number; - width?: number; - } - - interface MessageEmbedVideo { - url?: string; - proxyURL?: string; - height?: number; - width?: number; - } - - interface MessageEvent { - data: WebSocket.Data; - type: string; - target: WebSocket; - } - - type MessageFlagsString = 'CROSSPOSTED' | 'IS_CROSSPOST' | 'SUPPRESS_EMBEDS' | 'SOURCE_MESSAGE_DELETED' | 'URGENT'; - - interface MessageMentionOptions { - parse?: MessageMentionTypes[]; - roles?: Snowflake[]; - users?: Snowflake[]; - } - - type MessageMentionTypes = 'roles' | 'users' | 'everyone'; - - interface MessageOptions { - tts?: boolean; - nonce?: string; - content?: StringResolvable; - embed?: MessageEmbed | MessageEmbedOptions; - disableMentions?: 'none' | 'all' | 'everyone'; - allowedMentions?: MessageMentionOptions; - files?: (FileOptions | BufferResolvable | Stream | MessageAttachment)[]; - code?: string | boolean; - split?: boolean | SplitOptions; - reply?: UserResolvable; - } - - type MessageReactionResolvable = MessageReaction | Snowflake; - - interface MessageReference { - channelID: string; - guildID: string; - messageID: string | null; - } - - type MessageResolvable = Message | Snowflake; - - type MessageTarget = TextChannel | NewsChannel | DMChannel | User | GuildMember | Webhook | WebhookClient; - - type MessageType = - | 'DEFAULT' - | 'RECIPIENT_ADD' - | 'RECIPIENT_REMOVE' - | 'CALL' - | 'CHANNEL_NAME_CHANGE' - | 'CHANNEL_ICON_CHANGE' - | 'PINS_ADD' - | 'GUILD_MEMBER_JOIN' - | 'USER_PREMIUM_GUILD_SUBSCRIPTION' - | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1' - | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2' - | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3' - | 'CHANNEL_FOLLOW_ADD' - | 'GUILD_DISCOVERY_DISQUALIFIED' - | 'GUILD_DISCOVERY_REQUALIFIED'; - - interface OverwriteData { - allow?: PermissionResolvable; - deny?: PermissionResolvable; - id: GuildMemberResolvable | RoleResolvable; - type?: OverwriteType; - } - - type OverwriteResolvable = PermissionOverwrites | OverwriteData; - - type OverwriteType = 'member' | 'role'; - - interface PermissionFlags extends Record {} - - interface PermissionObject extends Record {} - - interface PermissionOverwriteOption extends Partial> {} - - type PermissionResolvable = BitFieldResolvable; - - type PermissionString = - | 'CREATE_INSTANT_INVITE' - | 'KICK_MEMBERS' - | 'BAN_MEMBERS' - | 'ADMINISTRATOR' - | 'MANAGE_CHANNELS' - | 'MANAGE_GUILD' - | 'ADD_REACTIONS' - | 'VIEW_AUDIT_LOG' - | 'PRIORITY_SPEAKER' - | 'STREAM' - | 'VIEW_CHANNEL' - | 'SEND_MESSAGES' - | 'SEND_TTS_MESSAGES' - | 'MANAGE_MESSAGES' - | 'EMBED_LINKS' - | 'ATTACH_FILES' - | 'READ_MESSAGE_HISTORY' - | 'MENTION_EVERYONE' - | 'USE_EXTERNAL_EMOJIS' - | 'VIEW_GUILD_INSIGHTS' - | 'CONNECT' - | 'SPEAK' - | 'MUTE_MEMBERS' - | 'DEAFEN_MEMBERS' - | 'MOVE_MEMBERS' - | 'USE_VAD' - | 'CHANGE_NICKNAME' - | 'MANAGE_NICKNAMES' - | 'MANAGE_ROLES' - | 'MANAGE_WEBHOOKS' - | 'MANAGE_EMOJIS'; - - interface RecursiveArray extends ReadonlyArray> {} - - type RecursiveReadonlyArray = ReadonlyArray>; - - interface PermissionOverwriteOptions { - allow: PermissionResolvable; - deny: PermissionResolvable; - id: UserResolvable | RoleResolvable; - } - - type PremiumTier = number; - - interface PresenceData { - status?: PresenceStatusData; - afk?: boolean; - activity?: { - name?: string; - type?: ActivityType | number; - url?: string; + version: string; + description: string; + author: string; + license: string; + main: string; + types: string; + homepage: string; + keywords: string[]; + bugs: { url: string }; + repository: { type: string; url: string }; + scripts: Record; + engines: Record; + dependencies: Record; + peerDependencies: Record; + devDependencies: Record; + [key: string]: unknown; + }; + UserAgent: string; + Endpoints: { + botGateway: string; + invite: (root: string, code: string) => string; + CDN: (root: string) => { + Asset: (name: string) => string; + DefaultAvatar: (id: Snowflake | number) => string; + Emoji: (emojiId: Snowflake, format: 'png' | 'gif') => string; + Avatar: ( + userId: Snowflake | number, + hash: string, + format: 'default' | AllowedImageFormat, + size: number, + ) => string; + Banner: (guildId: Snowflake | number, hash: string, format: AllowedImageFormat, size: number) => string; + Icon: (userId: Snowflake | number, hash: string, format: 'default' | AllowedImageFormat, size: number) => string; + AppIcon: (userId: Snowflake | number, hash: string, format: AllowedImageFormat, size: number) => string; + AppAsset: (userId: Snowflake | number, hash: string, format: AllowedImageFormat, size: number) => string; + StickerPackBanner: (bannerId: Snowflake, format: AllowedImageFormat, size: number) => string; + GDMIcon: (userId: Snowflake | number, hash: string, format: AllowedImageFormat, size: number) => string; + Splash: (guildId: Snowflake | number, hash: string, format: AllowedImageFormat, size: number) => string; + DiscoverySplash: (guildId: Snowflake | number, hash: string, format: AllowedImageFormat, size: number) => string; + TeamIcon: (teamId: Snowflake | number, hash: string, format: AllowedImageFormat, size: number) => string; + Sticker: (stickerId: Snowflake, stickerFormat: StickerFormatType) => string; }; - shardID?: number | number[]; - } + }; + WSCodes: { + 1000: 'WS_CLOSE_REQUESTED'; + 4004: 'TOKEN_INVALID'; + 4010: 'SHARDING_INVALID'; + 4011: 'SHARDING_REQUIRED'; + }; + Events: ConstantsEvents; + ShardEvents: ConstantsShardEvents; + PartialTypes: { + [K in PartialTypes]: K; + }; + WSEvents: { + [K in WSEventType]: K; + }; + Colors: ConstantsColors; + Status: ConstantsStatus; + Opcodes: ConstantsOpcodes; + APIErrors: APIErrors; + ChannelTypes: typeof ChannelTypes; + ThreadChannelTypes: ThreadChannelTypes[]; + TextBasedChannelTypes: TextBasedChannelTypes[]; + VoiceBasedChannelTypes: VoiceBasedChannelTypes[]; + ClientApplicationAssetTypes: ConstantsClientApplicationAssetTypes; + InviteScopes: InviteScope[]; + MessageTypes: MessageType[]; + SystemMessageTypes: SystemMessageType[]; + ActivityTypes: typeof ActivityTypes; + StickerTypes: typeof StickerTypes; + StickerFormatTypes: typeof StickerFormatTypes; + OverwriteTypes: typeof OverwriteTypes; + ExplicitContentFilterLevels: typeof ExplicitContentFilterLevels; + DefaultMessageNotificationLevels: typeof DefaultMessageNotificationLevels; + VerificationLevels: typeof VerificationLevels; + MembershipStates: typeof MembershipStates; + ApplicationCommandOptionTypes: typeof ApplicationCommandOptionTypes; + ApplicationCommandPermissionTypes: typeof ApplicationCommandPermissionTypes; + InteractionTypes: typeof InteractionTypes; + InteractionResponseTypes: typeof InteractionResponseTypes; + MessageComponentTypes: typeof MessageComponentTypes; + MessageButtonStyles: typeof MessageButtonStyles; + MFALevels: typeof MFALevels; + NSFWLevels: typeof NSFWLevels; + PrivacyLevels: typeof PrivacyLevels; + WebhookTypes: typeof WebhookTypes; + PremiumTiers: typeof PremiumTiers; +}; + +export const version: string; + +//#endregion + +//#region Managers + +export abstract class BaseManager { + public constructor(client: Client); + public readonly client: Client; +} - type PresenceResolvable = Presence | UserResolvable | Snowflake; +export abstract class DataManager extends BaseManager { + public constructor(client: Client, holds: Constructable); + public readonly holds: Constructable; + public readonly cache: Collection; + public resolve(resolvable: Holds): Holds; + public resolve(resolvable: R): Holds | null; + public resolveId(resolvable: K | Holds): K; + public resolveId(resolvable: R): K | null; + public valueOf(): Collection; +} - type Partialize = { - readonly client: Client; - readonly createdAt: Date; - readonly createdTimestamp: number; - deleted: boolean; - id: string; - partial: true; - fetch(): Promise; - } & { - [K in keyof Omit< - T, - 'client' | 'createdAt' | 'createdTimestamp' | 'id' | 'partial' | 'fetch' | 'deleted' | O - >]: T[K] extends Function ? T[K] : T[K] | null; // tslint:disable-line:ban-types - }; +export abstract class CachedManager extends DataManager { + public constructor(client: Client, holds: Constructable); + private _add(data: unknown, cache?: boolean, { id, extras }?: { id: K; extras: unknown[] }): Holds; +} - interface PartialDMChannel - extends Partialize< - DMChannel, - 'lastMessage' | 'lastMessageID' | 'messages' | 'recipient' | 'type' | 'typing' | 'typingCount' - > { - lastMessage: null; - lastMessageID: undefined; - messages: MessageManager; - recipient: User | PartialUser; - type: 'dm'; - readonly typing: boolean; - readonly typingCount: number; - } - - interface PartialChannelData { - id?: number; - name: string; - topic?: string; - type?: ChannelType; - parentID?: number; - permissionOverwrites?: { - id: number | Snowflake; - type?: OverwriteType; - allow?: PermissionResolvable; - deny?: PermissionResolvable; - }[]; - } - - interface PartialGuildMember - extends Partialize< - GuildMember, - | 'bannable' - | 'displayColor' - | 'displayHexColor' - | 'displayName' - | 'guild' - | 'kickable' - | 'permissions' - | 'roles' - | 'manageable' - | 'presence' - | 'voice' - > { - readonly bannable: boolean; - readonly displayColor: number; - readonly displayHexColor: string; - readonly displayName: string; - guild: Guild; - readonly manageable: boolean; - joinedAt: null; - joinedTimestamp: null; - readonly kickable: boolean; - readonly permissions: GuildMember['permissions']; - readonly presence: GuildMember['presence']; - readonly roles: GuildMember['roles']; - readonly voice: GuildMember['voice']; - } - - interface PartialMessage - extends Partialize< - Message, - | 'attachments' - | 'channel' - | 'deletable' - | 'crosspostable' - | 'editable' - | 'mentions' - | 'pinnable' - | 'url' - | 'flags' - | 'edits' - | 'embeds' - > { - attachments: Message['attachments']; - channel: Message['channel']; - readonly deletable: boolean; - readonly crosspostable: boolean; - readonly editable: boolean; - readonly edits: Message['edits']; - embeds: Message['embeds']; - flags: Message['flags']; - mentions: Message['mentions']; - readonly pinnable: boolean; - reactions: Message['reactions']; - readonly url: string; - } - - interface PartialRoleData extends RoleData { - id?: number; - } - - type PartialTypes = 'USER' | 'CHANNEL' | 'GUILD_MEMBER' | 'MESSAGE' | 'REACTION'; - - interface PartialUser - extends Omit, 'deleted'> { - bot: User['bot']; - flags: User['flags']; - locale: User['locale']; - system: User['system']; - readonly tag: null; - username: null; - } - - type PresenceStatusData = ClientPresenceStatus | 'invisible'; - - type PresenceStatus = PresenceStatusData | 'offline'; - - interface RateLimitData { - timeout: number; - limit: number; - timeDifference: number; - method: string; - path: string; - route: string; - } - - interface RawOverwriteData { - id: Snowflake; - allow: number; - deny: number; - type: OverwriteType; - } - - interface ReactionCollectorOptions extends CollectorOptions { - max?: number; - maxEmojis?: number; - maxUsers?: number; - } - - interface ResolvedOverwriteOptions { - allow: Permissions; - deny: Permissions; - } - - interface RoleData { - name?: string; - color?: ColorResolvable; - hoist?: boolean; - position?: number; - permissions?: PermissionResolvable; - mentionable?: boolean; - } - - interface RolePosition { - role: RoleResolvable; - position: number; - } - - type RoleResolvable = Role | string; - - type ShardingManagerMode = 'process' | 'worker'; - - type Snowflake = string; - - interface SplitOptions { - maxLength?: number; - char?: string; - prepend?: string; - append?: string; - } - - type Status = number; - - interface StreamOptions { - type?: StreamType; - seek?: number; - volume?: number | boolean; - plp?: number; - fec?: boolean; - bitrate?: number | 'auto'; - highWaterMark?: number; - } - - type SpeakingString = 'SPEAKING' | 'SOUNDSHARE' | 'PRIORITY_SPEAKING'; - - type StreamType = 'unknown' | 'converted' | 'opus' | 'ogg/opus' | 'webm/opus'; - - type StringResolvable = string | string[] | any; - - type SystemChannelFlagsString = 'WELCOME_MESSAGE_DISABLED' | 'BOOST_MESSAGE_DISABLED'; - - type SystemChannelFlagsResolvable = BitFieldResolvable; - - type TargetUser = number; - - interface TypingData { - user: User | PartialUser; - since: Date; - lastTimestamp: Date; - elapsedTime: number; - timeout: NodeJS.Timeout; - } - - type UserFlagsString = - | 'DISCORD_EMPLOYEE' - | 'PARTNERED_SERVER_OWNER' - | 'DISCORD_PARTNER' - | 'HYPESQUAD_EVENTS' - | 'BUGHUNTER_LEVEL_1' - | 'HOUSE_BRAVERY' - | 'HOUSE_BRILLIANCE' - | 'HOUSE_BALANCE' - | 'EARLY_SUPPORTER' - | 'TEAM_USER' - | 'SYSTEM' - | 'BUGHUNTER_LEVEL_2' - | 'VERIFIED_BOT' - | 'EARLY_VERIFIED_DEVELOPER' - | 'VERIFIED_DEVELOPER'; - - type UserResolvable = User | Snowflake | Message | GuildMember; - - type VerificationLevel = 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH' | 'VERY_HIGH'; - - type VoiceStatus = number; - - interface WebhookEditData { - name?: string; - avatar?: BufferResolvable; - channel?: ChannelResolvable; - reason?: string; - } - - interface WebhookMessageOptions { - username?: string; - avatarURL?: string; - tts?: boolean; - nonce?: string; - embeds?: (MessageEmbed | object)[]; - disableMentions?: 'none' | 'all' | 'everyone'; - allowedMentions?: MessageMentionOptions; - files?: (FileOptions | BufferResolvable | Stream | MessageAttachment)[]; - code?: string | boolean; - split?: boolean | SplitOptions; - } - - type WebhookTypes = 'Incoming' | 'Channel Follower'; - - interface WebSocketOptions { - large_threshold?: number; - compress?: boolean; - intents?: BitFieldResolvable | number; - properties?: WebSocketProperties; - } - - interface WebSocketProperties { - $os?: string; - $browser?: string; - $device?: string; - } - - type WSEventType = - | 'READY' - | 'RESUMED' - | 'GUILD_CREATE' - | 'GUILD_DELETE' - | 'GUILD_UPDATE' - | 'INVITE_CREATE' - | 'INVITE_DELETE' - | 'GUILD_MEMBER_ADD' - | 'GUILD_MEMBER_REMOVE' - | 'GUILD_MEMBER_UPDATE' - | 'GUILD_MEMBERS_CHUNK' - | 'GUILD_ROLE_CREATE' - | 'GUILD_ROLE_DELETE' - | 'GUILD_ROLE_UPDATE' - | 'GUILD_BAN_ADD' - | 'GUILD_BAN_REMOVE' - | 'GUILD_EMOJIS_UPDATE' - | 'GUILD_INTEGRATIONS_UPDATE' - | 'CHANNEL_CREATE' - | 'CHANNEL_DELETE' - | 'CHANNEL_UPDATE' - | 'CHANNEL_PINS_UPDATE' - | 'MESSAGE_CREATE' - | 'MESSAGE_DELETE' - | 'MESSAGE_UPDATE' - | 'MESSAGE_DELETE_BULK' - | 'MESSAGE_REACTION_ADD' - | 'MESSAGE_REACTION_REMOVE' - | 'MESSAGE_REACTION_REMOVE_ALL' - | 'MESSAGE_REACTION_REMOVE_EMOJI' - | 'USER_UPDATE' - | 'PRESENCE_UPDATE' - | 'TYPING_START' - | 'VOICE_STATE_UPDATE' - | 'VOICE_SERVER_UPDATE' - | 'WEBHOOKS_UPDATE'; - - //#endregion +export class ApplicationCommandManager< + ApplicationCommandType = ApplicationCommand<{ guild: GuildResolvable }>, + PermissionsOptionsExtras = { guild: GuildResolvable }, + PermissionsGuildType = null, +> extends CachedManager { + public constructor(client: Client, iterable?: Iterable); + public permissions: ApplicationCommandPermissionsManager< + { command?: ApplicationCommandResolvable } & PermissionsOptionsExtras, + { command: ApplicationCommandResolvable } & PermissionsOptionsExtras, + PermissionsOptionsExtras, + PermissionsGuildType, + null + >; + private commandPath({ id, guildId }: { id?: Snowflake; guildId?: Snowflake }): unknown; + public create(command: ApplicationCommandData): Promise; + public create(command: ApplicationCommandData, guildId: Snowflake): Promise; + public delete(command: ApplicationCommandResolvable, guildId?: Snowflake): Promise; + public edit(command: ApplicationCommandResolvable, data: ApplicationCommandData): Promise; + public edit( + command: ApplicationCommandResolvable, + data: ApplicationCommandData, + guildId: Snowflake, + ): Promise; + public fetch( + id: Snowflake, + options: FetchApplicationCommandOptions & { guildId: Snowflake }, + ): Promise; + public fetch(id: Snowflake, options?: FetchApplicationCommandOptions): Promise; + public fetch( + id?: Snowflake, + options?: FetchApplicationCommandOptions, + ): Promise>; + public set(commands: ApplicationCommandData[]): Promise>; + public set( + commands: ApplicationCommandData[], + guildId: Snowflake, + ): Promise>; + private static transformCommand( + command: ApplicationCommandData, + ): Omit; +} + +export class ApplicationCommandPermissionsManager< + BaseOptions, + FetchSingleOptions, + FullPermissionsOptions, + GuildType, + CommandIdType, +> extends BaseManager { + public constructor(manager: ApplicationCommandManager | GuildApplicationCommandManager | ApplicationCommand); + private manager: ApplicationCommandManager | GuildApplicationCommandManager | ApplicationCommand; + + public client: Client; + public commandId: CommandIdType; + public guild: GuildType; + public guildId: Snowflake | null; + public add( + options: FetchSingleOptions & { permissions: ApplicationCommandPermissionData[] }, + ): Promise; + public has(options: FetchSingleOptions & { permissionId: UserResolvable | RoleResolvable }): Promise; + public fetch(options: FetchSingleOptions): Promise; + public fetch(options: BaseOptions): Promise>; + public remove( + options: + | (FetchSingleOptions & { + users: UserResolvable | UserResolvable[]; + roles?: RoleResolvable | RoleResolvable[]; + }) + | (FetchSingleOptions & { + users?: UserResolvable | UserResolvable[]; + roles: RoleResolvable | RoleResolvable[]; + }), + ): Promise; + public set( + options: FetchSingleOptions & { permissions: ApplicationCommandPermissionData[] }, + ): Promise; + public set( + options: FullPermissionsOptions & { + fullPermissions: GuildApplicationCommandPermissionData[]; + }, + ): Promise>; + private permissionsPath(guildId: Snowflake, commandId?: Snowflake): unknown; + private static transformPermissions( + permissions: ApplicationCommandPermissionData, + received: true, + ): Omit & { type: keyof ApplicationCommandPermissionTypes }; + private static transformPermissions(permissions: ApplicationCommandPermissionData): APIApplicationCommandPermission; +} + +export class BaseGuildEmojiManager extends CachedManager { + public constructor(client: Client, iterable?: Iterable); + public resolveIdentifier(emoji: EmojiIdentifierResolvable): string | null; } + +export class ChannelManager extends CachedManager { + public constructor(client: Client, iterable: Iterable); + public fetch(id: Snowflake, options?: FetchChannelOptions): Promise; +} + +export class GuildApplicationCommandManager extends ApplicationCommandManager { + public constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; + public create(command: ApplicationCommandData): Promise; + public delete(command: ApplicationCommandResolvable): Promise; + public edit(command: ApplicationCommandResolvable, data: ApplicationCommandData): Promise; + public fetch(id: Snowflake, options?: BaseFetchOptions): Promise; + public fetch(id?: undefined, options?: BaseFetchOptions): Promise>; + public set(commands: ApplicationCommandData[]): Promise>; +} + +export class GuildChannelManager extends CachedManager< + Snowflake, + GuildChannel | ThreadChannel, + GuildChannelResolvable +> { + public constructor(guild: Guild, iterable?: Iterable); + public readonly channelCountWithoutThreads: number; + public guild: Guild; + public create(name: string, options: GuildChannelCreateOptions & { type: 'GUILD_VOICE' }): Promise; + public create( + name: string, + options: GuildChannelCreateOptions & { type: 'GUILD_CATEGORY' }, + ): Promise; + public create(name: string, options?: GuildChannelCreateOptions & { type?: 'GUILD_TEXT' }): Promise; + public create(name: string, options: GuildChannelCreateOptions & { type: 'GUILD_NEWS' }): Promise; + public create(name: string, options: GuildChannelCreateOptions & { type: 'GUILD_STORE' }): Promise; + public create( + name: string, + options: GuildChannelCreateOptions & { type: 'GUILD_STAGE_VOICE' }, + ): Promise; + public create( + name: string, + options: GuildChannelCreateOptions, + ): Promise; + public fetch( + id: Snowflake, + options?: BaseFetchOptions, + ): Promise; + public fetch( + id?: undefined, + options?: BaseFetchOptions, + ): Promise< + Collection + >; + public fetchActiveThreads(cache?: boolean): Promise; +} + +export class GuildEmojiManager extends BaseGuildEmojiManager { + public constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; + public create( + attachment: BufferResolvable | Base64Resolvable, + name: string, + options?: GuildEmojiCreateOptions, + ): Promise; + public fetch(id: Snowflake, options?: BaseFetchOptions): Promise; + public fetch(id?: undefined, options?: BaseFetchOptions): Promise>; +} + +export class GuildEmojiRoleManager extends DataManager { + public constructor(emoji: GuildEmoji); + public emoji: GuildEmoji; + public guild: Guild; + public add( + roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, + ): Promise; + public set(roles: readonly RoleResolvable[] | Collection): Promise; + public remove( + roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, + ): Promise; +} + +export class GuildManager extends CachedManager { + public constructor(client: Client, iterable?: Iterable); + public create(name: string, options?: GuildCreateOptions): Promise; + public fetch(options: Snowflake | FetchGuildOptions): Promise; + public fetch(options?: FetchGuildsOptions): Promise>; +} + +export class GuildMemberManager extends CachedManager { + public constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; + public add( + user: UserResolvable, + options: AddGuildMemberOptions & { fetchWhenExisting: false }, + ): Promise; + public add(user: UserResolvable, options: AddGuildMemberOptions): Promise; + public ban(user: UserResolvable, options?: BanOptions): Promise; + public edit(user: UserResolvable, data: GuildMemberEditData, reason?: string): Promise; + public fetch( + options: UserResolvable | FetchMemberOptions | (FetchMembersOptions & { user: UserResolvable }), + ): Promise; + public fetch(options?: FetchMembersOptions): Promise>; + public kick(user: UserResolvable, reason?: string): Promise; + public prune(options: GuildPruneMembersOptions & { dry?: false; count: false }): Promise; + public prune(options?: GuildPruneMembersOptions): Promise; + public search(options: GuildSearchMembersOptions): Promise>; + public unban(user: UserResolvable, reason?: string): Promise; +} + +export class GuildBanManager extends CachedManager { + public constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; + public create(user: UserResolvable, options?: BanOptions): Promise; + public fetch(options: UserResolvable | FetchBanOptions): Promise; + public fetch(options?: FetchBansOptions): Promise>; + public remove(user: UserResolvable, reason?: string): Promise; +} + +export class GuildInviteManager extends DataManager { + public constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; + public create(channel: GuildChannelResolvable, options?: CreateInviteOptions): Promise; + public fetch(options: InviteResolvable | FetchInviteOptions): Promise; + public fetch(options?: FetchInvitesOptions): Promise>; + public delete(invite: InviteResolvable, reason?: string): Promise; +} + +export class GuildStickerManager extends CachedManager { + public constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; + public create( + file: BufferResolvable | Stream | FileOptions | MessageAttachment, + name: string, + tags: string, + options?: GuildStickerCreateOptions, + ): Promise; + public edit(sticker: StickerResolvable, data?: GuildStickerEditData, reason?: string): Promise; + public delete(sticker: StickerResolvable, reason?: string): Promise; + public fetch(id: Snowflake, options?: BaseFetchOptions): Promise; + public fetch(id?: Snowflake, options?: BaseFetchOptions): Promise>; +} + +export class GuildMemberRoleManager extends DataManager { + public constructor(member: GuildMember); + public readonly hoist: Role | null; + public readonly color: Role | null; + public readonly highest: Role; + public readonly premiumSubscriberRole: Role | null; + public readonly botRole: Role | null; + public member: GuildMember; + public guild: Guild; + + public add( + roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, + reason?: string, + ): Promise; + public set(roles: readonly RoleResolvable[] | Collection, reason?: string): Promise; + public remove( + roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection, + reason?: string, + ): Promise; +} + +export class MessageManager extends CachedManager { + public constructor(channel: TextChannel | DMChannel | ThreadChannel, iterable?: Iterable); + public channel: TextBasedChannelFields; + public cache: Collection; + public crosspost(message: MessageResolvable): Promise; + public delete(message: MessageResolvable): Promise; + public edit(message: MessageResolvable, options: MessagePayload | MessageEditOptions): Promise; + public fetch(message: Snowflake, options?: BaseFetchOptions): Promise; + public fetch( + options?: ChannelLogsQueryOptions, + cacheOptions?: BaseFetchOptions, + ): Promise>; + public fetchPinned(cache?: boolean): Promise>; + public react(message: MessageResolvable, emoji: EmojiIdentifierResolvable): Promise; + public pin(message: MessageResolvable): Promise; + public unpin(message: MessageResolvable): Promise; +} + +export class PermissionOverwriteManager extends CachedManager< + Snowflake, + PermissionOverwrites, + PermissionOverwriteResolvable +> { + public constructor(client: Client, iterable?: Iterable); + public set( + overwrites: readonly OverwriteResolvable[] | Collection, + reason?: string, + ): Promise; + private upsert( + userOrRole: RoleResolvable | UserResolvable, + options: PermissionOverwriteOptions, + overwriteOptions?: GuildChannelOverwriteOptions, + existing?: PermissionOverwrites, + ): Promise; + public create( + userOrRole: RoleResolvable | UserResolvable, + options: PermissionOverwriteOptions, + overwriteOptions?: GuildChannelOverwriteOptions, + ): Promise; + public edit( + userOrRole: RoleResolvable | UserResolvable, + options: PermissionOverwriteOptions, + overwriteOptions?: GuildChannelOverwriteOptions, + ): Promise; + public delete(userOrRole: RoleResolvable | UserResolvable, reason?: string): Promise; +} + +export class PresenceManager extends CachedManager { + public constructor(client: Client, iterable?: Iterable); +} + +export class ReactionManager extends CachedManager { + public constructor(message: Message, iterable?: Iterable); + public message: Message; + public removeAll(): Promise; +} + +export class ReactionUserManager extends CachedManager { + public constructor(reaction: MessageReaction, iterable?: Iterable); + public reaction: MessageReaction; + public fetch(options?: FetchReactionUsersOptions): Promise>; + public remove(user?: UserResolvable): Promise; +} + +export class RoleManager extends CachedManager { + public constructor(guild: Guild, iterable?: Iterable); + public readonly everyone: Role; + public readonly highest: Role; + public guild: Guild; + public readonly premiumSubscriberRole: Role | null; + public botRoleFor(user: UserResolvable): Role | null; + public fetch(id: Snowflake, options?: BaseFetchOptions): Promise; + public fetch(id?: undefined, options?: BaseFetchOptions): Promise>; + public create(options?: CreateRoleOptions): Promise; + public edit(role: RoleResolvable, options: RoleData, reason?: string): Promise; +} + +export class StageInstanceManager extends CachedManager { + public constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; + public create(channel: StageChannel | Snowflake, options: StageInstanceCreateOptions): Promise; + public fetch(channel: StageChannel | Snowflake, options?: BaseFetchOptions): Promise; + public edit(channel: StageChannel | Snowflake, options: StageInstanceEditOptions): Promise; + public delete(channel: StageChannel | Snowflake): Promise; +} + +export class ThreadManager extends CachedManager { + public constructor(channel: TextChannel | NewsChannel, iterable?: Iterable); + public channel: TextChannel | NewsChannel; + public create(options: ThreadCreateOptions): Promise; + public fetch(options: ThreadChannelResolvable, cacheOptions?: BaseFetchOptions): Promise; + public fetch(options?: FetchThreadsOptions, cacheOptions?: { cache?: boolean }): Promise; + public fetchArchived(options?: FetchArchivedThreadOptions, cache?: boolean): Promise; + public fetchActive(cache?: boolean): Promise; +} + +export class ThreadMemberManager extends CachedManager { + public constructor(thread: ThreadChannel, iterable?: Iterable); + public thread: ThreadChannel; + public add(member: UserResolvable | '@me', reason?: string): Promise; + public fetch(cache?: boolean): Promise>; + public remove(id: Snowflake | '@me', reason?: string): Promise; +} + +export class UserManager extends CachedManager { + public constructor(client: Client, iterable?: Iterable); + public fetch(id: Snowflake, options?: BaseFetchOptions): Promise; +} + +export class VoiceStateManager extends CachedManager { + public constructor(guild: Guild, iterable?: Iterable); + public guild: Guild; +} + +//#endregion + +//#region Mixins + +// Model the TextBasedChannel mixin system, allowing application of these fields +// to the classes that use these methods without having to manually add them +// to each of those classes + +export type Constructable = new (...args: any[]) => T; +export function PartialTextBasedChannel(Base?: Constructable): Constructable; +export function TextBasedChannel( + Base?: Constructable, + ignore?: I[], +): Constructable>; + +export interface PartialTextBasedChannelFields { + send(options: string | MessagePayload | MessageOptions): Promise; +} + +export interface TextBasedChannelFields extends PartialTextBasedChannelFields { + lastMessageId: Snowflake | null; + readonly lastMessage: Message | null; + lastPinTimestamp: number | null; + readonly lastPinAt: Date | null; + awaitMessageComponent( + options?: AwaitMessageComponentOptions, + ): Promise; + awaitMessages(options?: AwaitMessagesOptions): Promise>; + bulkDelete( + messages: Collection | readonly MessageResolvable[] | number, + filterOld?: boolean, + ): Promise>; + createMessageComponentCollector( + options?: InteractionCollectorOptions, + ): InteractionCollector; + createMessageCollector(options?: MessageCollectorOptions): MessageCollector; + sendTyping(): Promise; +} + +export function PartialWebhookMixin(Base?: Constructable): Constructable; +export function WebhookMixin(Base?: Constructable): Constructable; + +export interface PartialWebhookFields { + id: Snowflake; + readonly url: string; + deleteMessage(message: MessageResolvable | APIMessage | '@original'): Promise; + editMessage( + message: MessageResolvable | '@original', + options: string | MessagePayload | WebhookEditMessageOptions, + ): Promise; + fetchMessage(message: Snowflake | '@original', cache?: boolean): Promise; + send(options: string | MessagePayload | WebhookMessageOptions): Promise; +} + +export interface WebhookFields extends PartialWebhookFields { + readonly createdAt: Date; + readonly createdTimestamp: number; + delete(reason?: string): Promise; + edit(options: WebhookEditData, reason?: string): Promise; + sendSlackMessage(body: unknown): Promise; +} + +//#endregion + +//#region Typedefs + +export type ActivityFlagsString = 'INSTANCE' | 'JOIN' | 'SPECTATE' | 'JOIN_REQUEST' | 'SYNC' | 'PLAY'; + +export type ActivitiesOptions = Omit; + +export interface ActivityOptions { + name?: string; + url?: string; + type?: ActivityType | number; + shardId?: number | readonly number[]; +} + +export type ActivityPlatform = 'desktop' | 'samsung' | 'xbox'; + +export type ActivityType = keyof typeof ActivityTypes; + +export interface AddGuildMemberOptions { + accessToken: string; + nick?: string; + roles?: Collection | RoleResolvable[]; + mute?: boolean; + deaf?: boolean; + force?: boolean; + fetchWhenExisting?: boolean; +} + +export type AllowedImageFormat = 'webp' | 'png' | 'jpg' | 'jpeg' | 'gif'; + +export type AllowedPartial = User | Channel | GuildMember | Message | MessageReaction; + +export type AllowedThreadTypeForNewsChannel = 'GUILD_NEWS_THREAD' | 10; + +export type AllowedThreadTypeForTextChannel = 'GUILD_PUBLIC_THREAD' | 'GUILD_PRIVATE_THREAD' | 11 | 12; + +export interface APIErrors { + UNKNOWN_ACCOUNT: 10001; + UNKNOWN_APPLICATION: 10002; + UNKNOWN_CHANNEL: 10003; + UNKNOWN_GUILD: 10004; + UNKNOWN_INTEGRATION: 10005; + UNKNOWN_INVITE: 10006; + UNKNOWN_MEMBER: 10007; + UNKNOWN_MESSAGE: 10008; + UNKNOWN_OVERWRITE: 10009; + UNKNOWN_PROVIDER: 10010; + UNKNOWN_ROLE: 10011; + UNKNOWN_TOKEN: 10012; + UNKNOWN_USER: 10013; + UNKNOWN_EMOJI: 10014; + UNKNOWN_WEBHOOK: 10015; + UNKNOWN_WEBHOOK_SERVICE: 10016; + UNKNOWN_SESSION: 10020; + UNKNOWN_BAN: 10026; + UNKNOWN_SKU: 10027; + UNKNOWN_STORE_LISTING: 10028; + UNKNOWN_ENTITLEMENT: 10029; + UNKNOWN_BUILD: 10030; + UNKNOWN_LOBBY: 10031; + UNKNOWN_BRANCH: 10032; + UNKNOWN_STORE_DIRECTORY_LAYOUT: 10033; + UNKNOWN_REDISTRIBUTABLE: 10036; + UNKNOWN_GIFT_CODE: 10038; + UNKNOWN_GUILD_TEMPLATE: 10057; + UNKNOWN_DISCOVERABLE_SERVER_CATEGORY: 10059; + UNKNOWN_STICKER: 10060; + UNKNOWN_INTERACTION: 10062; + UNKNOWN_APPLICATION_COMMAND: 10063; + UNKNOWN_APPLICATION_COMMAND_PERMISSIONS: 10066; + UNKNOWN_STAGE_INSTANCE: 10067; + UNKNOWN_GUILD_MEMBER_VERIFICATION_FORM: 10068; + UNKNOWN_GUILD_WELCOME_SCREEN: 10069; + BOT_PROHIBITED_ENDPOINT: 20001; + BOT_ONLY_ENDPOINT: 20002; + CANNOT_SEND_EXPLICIT_CONTENT: 20009; + NOT_AUTHORIZED: 20012; + SLOWMODE_RATE_LIMIT: 20016; + ACCOUNT_OWNER_ONLY: 20018; + ANNOUNCEMENT_EDIT_LIMIT_EXCEEDED: 20022; + CHANNEL_HIT_WRITE_RATELIMIT: 20028; + CONTENT_NOT_ALLOWED: 20031; + GUILD_PREMIUM_LEVEL_TOO_LOW: 20035; + MAXIMUM_GUILDS: 30001; + MAXIMUM_FRIENDS: 30002; + MAXIMUM_PINS: 30003; + MAXIMUM_RECIPIENTS: 30004; + MAXIMUM_ROLES: 30005; + MAXIMUM_WEBHOOKS: 30007; + MAXIMUM_EMOJIS: 30008; + MAXIMUM_REACTIONS: 30010; + MAXIMUM_CHANNELS: 30013; + MAXIMUM_ATTACHMENTS: 30015; + MAXIMUM_INVITES: 30016; + MAXIMUM_ANIMATED_EMOJIS: 30018; + MAXIMUM_SERVER_MEMBERS: 30019; + MAXIMUM_NUMBER_OF_SERVER_CATEGORIES: 30030; + GUILD_ALREADY_HAS_TEMPLATE: 30031; + MAXIMUM_THREAD_PARICIPANTS: 30033; + MAXIMUM_NON_GUILD_MEMBERS_BANS: 30035; + MAXIMUM_BAN_FETCHES: 30037; + MAXIMUM_NUMBER_OF_STICKERS_REACHED: 30039; + UNAUTHORIZED: 40001; + ACCOUNT_VERIFICATION_REQUIRED: 40002; + DIRECT_MESSAGES_TOO_FAST: 40003; + REQUEST_ENTITY_TOO_LARGE: 40005; + FEATURE_TEMPORARILY_DISABLED: 40006; + USER_BANNED: 40007; + TARGET_USER_NOT_CONNECTED_TO_VOICE: 40032; + ALREADY_CROSSPOSTED: 40033; + MISSING_ACCESS: 50001; + INVALID_ACCOUNT_TYPE: 50002; + CANNOT_EXECUTE_ON_DM: 50003; + EMBED_DISABLED: 50004; + CANNOT_EDIT_MESSAGE_BY_OTHER: 50005; + CANNOT_SEND_EMPTY_MESSAGE: 50006; + CANNOT_MESSAGE_USER: 50007; + CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: 50008; + CHANNEL_VERIFICATION_LEVEL_TOO_HIGH: 50009; + OAUTH2_APPLICATION_BOT_ABSENT: 50010; + MAXIMUM_OAUTH2_APPLICATIONS: 50011; + INVALID_OAUTH_STATE: 50012; + MISSING_PERMISSIONS: 50013; + INVALID_AUTHENTICATION_TOKEN: 50014; + NOTE_TOO_LONG: 50015; + INVALID_BULK_DELETE_QUANTITY: 50016; + CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: 50019; + INVALID_OR_TAKEN_INVITE_CODE: 50020; + CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: 50021; + CANNOT_EXECUTE_ON_CHANNEL_TYPE: 50024; + INVALID_OAUTH_TOKEN: 50025; + MISSING_OAUTH_SCOPE: 50026; + INVALID_WEBHOOK_TOKEN: 50027; + INVALID_ROLE: 50028; + INVALID_RECIPIENTS: 50033; + BULK_DELETE_MESSAGE_TOO_OLD: 50034; + INVALID_FORM_BODY: 50035; + INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: 50036; + INVALID_API_VERSION: 50041; + FILE_UPLOADED_EXCEEDS_MAXIMUM_SIZE: 50045; + INVALID_FILE_UPLOADED: 50046; + CANNOT_SELF_REDEEM_GIFT: 50054; + PAYMENT_SOURCE_REQUIRED: 50070; + CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL: 50074; + INVALID_STICKER_SENT: 50081; + INVALID_THREAD_ARCHIVE_STATE: 50083; + INVALID_THREAD_NOTIFICATION_SETTINGS: 50084; + PARAMETER_EARLIER_THAN_CREATION: 50085; + TWO_FACTOR_REQUIRED: 60003; + NO_USERS_WITH_DISCORDTAG_EXIST: 80004; + REACTION_BLOCKED: 90001; + RESOURCE_OVERLOADED: 130000; + STAGE_ALREADY_OPEN: 150006; + MESSAGE_ALREADY_HAS_THREAD: 160004; + THREAD_LOCKED: 160005; + MAXIMUM_ACTIVE_THREADS: 160006; + MAXIMUM_ACTIVE_ANNOUNCEMENT_THREADS: 160007; + INVALID_JSON_FOR_UPLOADED_LOTTIE_FILE: 170001; + UPLOADED_LOTTIES_CANNOT_CONTAIN_RASTERIZED_IMAGES: 170002; + STICKER_MAXIMUM_FRAMERATE_EXCEEDED: 170003; + STICKER_FRAME_COUNT_EXCEEDS_MAXIMUM_OF_1000_FRAMES: 170004; + LOTTIE_ANIMATION_MAXIMUM_DIMENSIONS_EXCEEDED: 170005; + STICKER_FRAME_RATE_IS_TOO_SMALL_OR_TOO_LARGE: 170006; + STICKER_ANIMATION_DURATION_EXCEEDS_MAXIMUM_OF_5_SECONDS: 170007; +} + +export interface ApplicationAsset { + name: string; + id: Snowflake; + type: 'BIG' | 'SMALL'; +} + +export interface ApplicationCommandData { + name: string; + description: string; + options?: ApplicationCommandOptionData[]; + defaultPermission?: boolean; +} + +export interface ApplicationCommandOptionData { + type: ApplicationCommandOptionType | ApplicationCommandOptionTypes; + name: string; + description: string; + required?: boolean; + choices?: ApplicationCommandOptionChoice[]; + options?: this[]; +} + +export interface ApplicationCommandOption extends ApplicationCommandOptionData { + type: ApplicationCommandOptionType; +} + +export interface ApplicationCommandOptionChoice { + name: string; + value: string | number; +} + +export type ApplicationCommandOptionType = keyof typeof ApplicationCommandOptionTypes; + +export interface ApplicationCommandPermissionData { + id: Snowflake; + type: ApplicationCommandPermissionType | ApplicationCommandPermissionTypes; + permission: boolean; +} + +export interface ApplicationCommandPermissions extends ApplicationCommandPermissionData { + type: ApplicationCommandPermissionType; +} + +export type ApplicationCommandPermissionType = keyof typeof ApplicationCommandPermissionTypes; + +export type ApplicationCommandResolvable = ApplicationCommand | Snowflake; + +export type ApplicationFlagsString = + | 'MANAGED_EMOJI' + | 'GROUP_DM_CREATE' + | 'RPC_HAS_CONNECTED' + | 'GATEWAY_PRESENCE' + | 'GATEWAY_PRESENCE_LIMITED' + | 'GATEWAY_GUILD_MEMBERS' + | 'GATEWAY_GUILD_MEMBERS_LIMITED' + | 'VERIFICATION_PENDING_GUILD_LIMIT' + | 'EMBEDDED'; + +export interface AuditLogChange { + key: APIAuditLogChange['key']; + old?: APIAuditLogChange['old_value']; + new?: APIAuditLogChange['new_value']; +} + +export type Awaited = T | PromiseLike; + +export type AwaitMessageComponentOptions = Omit< + MessageComponentCollectorOptions, + 'max' | 'maxComponents' | 'maxUsers' +>; + +export interface AwaitMessagesOptions extends MessageCollectorOptions { + errors?: string[]; +} + +export interface AwaitReactionsOptions extends ReactionCollectorOptions { + errors?: string[]; +} + +export interface BanOptions { + days?: number; + reason?: string; +} + +export type Base64Resolvable = Buffer | Base64String; + +export type Base64String = string; + +export interface BaseFetchOptions { + cache?: boolean; + force?: boolean; +} + +export interface BaseMessageComponentOptions { + type?: MessageComponentType | MessageComponentTypes; +} + +export type BitFieldResolvable = + | RecursiveReadonlyArray>> + | T + | N + | `${bigint}` + | Readonly>; + +export type BufferResolvable = Buffer | string; + +export interface Caches { + ApplicationCommandManager: [manager: typeof ApplicationCommandManager, holds: typeof ApplicationCommand]; + BaseGuildEmojiManager: [manager: typeof BaseGuildEmojiManager, holds: typeof GuildEmoji]; + ChannelManager: [manager: typeof ChannelManager, holds: typeof Channel]; + GuildChannelManager: [manager: typeof GuildChannelManager, holds: typeof GuildChannel]; + GuildManager: [manager: typeof GuildManager, holds: typeof Guild]; + GuildMemberManager: [manager: typeof GuildMemberManager, holds: typeof GuildMember]; + GuildBanManager: [manager: typeof GuildBanManager, holds: typeof GuildBan]; + MessageManager: [manager: typeof MessageManager, holds: typeof Message]; + PermissionOverwriteManager: [manager: typeof PermissionOverwriteManager, holds: typeof PermissionOverwrites]; + PresenceManager: [manager: typeof PresenceManager, holds: typeof Presence]; + ReactionManager: [manager: typeof ReactionManager, holds: typeof MessageReaction]; + ReactionUserManager: [manager: typeof ReactionUserManager, holds: typeof User]; + RoleManager: [manager: typeof RoleManager, holds: typeof Role]; + StageInstanceManager: [manager: typeof StageInstanceManager, holds: typeof StageInstance]; + ThreadManager: [manager: typeof ThreadManager, holds: typeof ThreadChannel]; + ThreadMemberManager: [manager: typeof ThreadMemberManager, holds: typeof ThreadMember]; + UserManager: [manager: typeof UserManager, holds: typeof User]; + VoiceStateManager: [manager: typeof VoiceStateManager, holds: typeof VoiceState]; +} + +export type CacheConstructors = { + [K in keyof Caches]: Caches[K][0] & { name: K }; +}; + +// This doesn't actually work the way it looks 😒. +// Narrowing the type of `manager.name` doesn't propagate type information to `holds` and the return type. +export type CacheFactory = ( + manager: CacheConstructors[keyof Caches], + holds: Caches[typeof manager['name']][1], +) => typeof manager['prototype'] extends DataManager ? Collection : never; + +export type CacheWithLimitsOptions = { + [K in keyof Caches]?: Caches[K][0]['prototype'] extends DataManager + ? LimitedCollectionOptions | number + : never; +}; + +export interface ChannelCreationOverwrites { + allow?: PermissionResolvable; + deny?: PermissionResolvable; + id: RoleResolvable | UserResolvable; +} + +export interface ChannelData { + name?: string; + type?: Pick; + position?: number; + topic?: string; + nsfw?: boolean; + bitrate?: number; + userLimit?: number; + parent?: CategoryChannelResolvable | null; + rateLimitPerUser?: number; + lockPermissions?: boolean; + permissionOverwrites?: readonly OverwriteResolvable[] | Collection; + defaultAutoArchiveDuration?: ThreadAutoArchiveDuration; + rtcRegion?: string | null; +} + +export interface ChannelLogsQueryOptions { + limit?: number; + before?: Snowflake; + after?: Snowflake; + around?: Snowflake; +} + +export type ChannelMention = `<#${Snowflake}>`; + +export interface ChannelPosition { + channel: GuildChannel | Snowflake; + lockPermissions?: boolean; + parent?: CategoryChannelResolvable | null; + position?: number; +} + +export type GuildTextChannelResolvable = TextChannel | NewsChannel | Snowflake; +export type ChannelResolvable = Channel | Snowflake; + +export interface ChannelWebhookCreateOptions { + avatar?: BufferResolvable | Base64Resolvable; + reason?: string; +} + +export interface ClientEvents { + applicationCommandCreate: [command: ApplicationCommand]; + applicationCommandDelete: [command: ApplicationCommand]; + applicationCommandUpdate: [oldCommand: ApplicationCommand | null, newCommand: ApplicationCommand]; + channelCreate: [channel: GuildChannel]; + channelDelete: [channel: DMChannel | GuildChannel]; + channelPinsUpdate: [channel: TextChannel | NewsChannel | DMChannel | PartialDMChannel, date: Date]; + channelUpdate: [oldChannel: DMChannel | GuildChannel, newChannel: DMChannel | GuildChannel]; + debug: [message: string]; + warn: [message: string]; + emojiCreate: [emoji: GuildEmoji]; + emojiDelete: [emoji: GuildEmoji]; + emojiUpdate: [oldEmoji: GuildEmoji, newEmoji: GuildEmoji]; + error: [error: Error]; + guildBanAdd: [ban: GuildBan]; + guildBanRemove: [ban: GuildBan]; + guildCreate: [guild: Guild]; + guildDelete: [guild: Guild]; + guildUnavailable: [guild: Guild]; + guildIntegrationsUpdate: [guild: Guild]; + guildMemberAdd: [member: GuildMember]; + guildMemberAvailable: [member: GuildMember | PartialGuildMember]; + guildMemberRemove: [member: GuildMember | PartialGuildMember]; + guildMembersChunk: [ + members: Collection, + guild: Guild, + data: { count: number; index: number; nonce: string | undefined }, + ]; + guildMemberUpdate: [oldMember: GuildMember | PartialGuildMember, newMember: GuildMember]; + guildUpdate: [oldGuild: Guild, newGuild: Guild]; + inviteCreate: [invite: Invite]; + inviteDelete: [invite: Invite]; + /** @deprecated Use messageCreate instead */ + message: [message: Message]; + messageCreate: [message: Message]; + messageDelete: [message: Message | PartialMessage]; + messageReactionRemoveAll: [message: Message | PartialMessage]; + messageReactionRemoveEmoji: [reaction: MessageReaction | PartialMessageReaction]; + messageDeleteBulk: [messages: Collection]; + messageReactionAdd: [message: MessageReaction | PartialMessageReaction, user: User | PartialUser]; + messageReactionRemove: [reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser]; + messageUpdate: [oldMessage: Message | PartialMessage, newMessage: Message | PartialMessage]; + presenceUpdate: [oldPresence: Presence | null, newPresence: Presence]; + rateLimit: [rateLimitData: RateLimitData]; + invalidRequestWarning: [invalidRequestWarningData: InvalidRequestWarningData]; + ready: [client: Client]; + invalidated: []; + roleCreate: [role: Role]; + roleDelete: [role: Role]; + roleUpdate: [oldRole: Role, newRole: Role]; + threadCreate: [thread: ThreadChannel]; + threadDelete: [thread: ThreadChannel]; + threadListSync: [threads: Collection]; + threadMemberUpdate: [oldMember: ThreadMember, newMember: ThreadMember]; + threadMembersUpdate: [ + oldMembers: Collection, + mewMembers: Collection, + ]; + threadUpdate: [oldThread: ThreadChannel, newThread: ThreadChannel]; + typingStart: [typing: Typing]; + userUpdate: [oldUser: User | PartialUser, newUser: User]; + voiceStateUpdate: [oldState: VoiceState, newState: VoiceState]; + webhookUpdate: [channel: TextChannel]; + /** @deprecated Use interactionCreate instead */ + interaction: [interaction: Interaction]; + interactionCreate: [interaction: Interaction]; + shardDisconnect: [closeEvent: CloseEvent, shardId: number]; + shardError: [error: Error, shardId: number]; + shardReady: [shardId: number, unavailableGuilds: Set | undefined]; + shardReconnecting: [shardId: number]; + shardResume: [shardId: number, replayedEvents: number]; + stageInstanceCreate: [stageInstance: StageInstance]; + stageInstanceUpdate: [oldStageInstance: StageInstance | null, newStageInstance: StageInstance]; + stageInstanceDelete: [stageInstance: StageInstance]; + stickerCreate: [sticker: Sticker]; + stickerDelete: [sticker: Sticker]; + stickerUpdate: [oldSticker: Sticker, newSticker: Sticker]; +} + +export interface ClientOptions { + shards?: number | number[] | 'auto'; + shardCount?: number; + makeCache?: CacheFactory; + /** @deprecated Use `makeCache` with a `LimitedCollection` for `MessageManager` instead. */ + messageCacheLifetime?: number; + /** @deprecated Use `makeCache` with a `LimitedCollection` for `MessageManager` instead. */ + messageSweepInterval?: number; + allowedMentions?: MessageMentionOptions; + invalidRequestWarningInterval?: number; + partials?: PartialTypes[]; + restWsBridgeTimeout?: number; + restTimeOffset?: number; + restRequestTimeout?: number; + restGlobalRateLimit?: number; + restSweepInterval?: number; + retryLimit?: number; + failIfNotExists?: boolean; + userAgentSuffix?: string[]; + presence?: PresenceData; + intents: BitFieldResolvable; + ws?: WebSocketOptions; + http?: HTTPOptions; + rejectOnRateLimit?: string[] | ((data: RateLimitData) => boolean | Promise); +} + +export type ClientPresenceStatus = 'online' | 'idle' | 'dnd'; + +export interface ClientPresenceStatusData { + web?: ClientPresenceStatus; + mobile?: ClientPresenceStatus; + desktop?: ClientPresenceStatus; +} + +export interface ClientUserEditData { + username?: string; + avatar?: BufferResolvable | Base64Resolvable; +} + +export interface CloseEvent { + wasClean: boolean; + code: number; + reason: string; + target: WebSocket; +} + +export type CollectorFilter = (...args: T) => boolean | Promise; + +export interface CollectorOptions { + filter?: CollectorFilter; + time?: number; + idle?: number; + dispose?: boolean; +} + +export interface CollectorResetTimerOptions { + time?: number; + idle?: number; +} + +export type ColorResolvable = + | 'DEFAULT' + | 'WHITE' + | 'AQUA' + | 'GREEN' + | 'BLUE' + | 'YELLOW' + | 'PURPLE' + | 'LUMINOUS_VIVID_PINK' + | 'FUCHSIA' + | 'GOLD' + | 'ORANGE' + | 'RED' + | 'GREY' + | 'DARKER_GREY' + | 'NAVY' + | 'DARK_AQUA' + | 'DARK_GREEN' + | 'DARK_BLUE' + | 'DARK_PURPLE' + | 'DARK_VIVID_PINK' + | 'DARK_GOLD' + | 'DARK_ORANGE' + | 'DARK_RED' + | 'DARK_GREY' + | 'LIGHT_GREY' + | 'DARK_NAVY' + | 'BLURPLE' + | 'GREYPLE' + | 'DARK_BUT_NOT_BLACK' + | 'NOT_QUITE_BLACK' + | 'RANDOM' + | readonly [number, number, number] + | number + | HexColorString; + +export interface CommandInteractionOption { + name: string; + type: ApplicationCommandOptionType; + value?: string | number | boolean; + options?: CommandInteractionOption[]; + user?: User; + member?: GuildMember | APIInteractionDataResolvedGuildMember; + channel?: GuildChannel | APIInteractionDataResolvedChannel; + role?: Role | APIRole; +} + +export interface ConstantsClientApplicationAssetTypes { + SMALL: 1; + BIG: 2; +} + +export interface ConstantsColors { + DEFAULT: 0x000000; + WHITE: 0xffffff; + AQUA: 0x1abc9c; + GREEN: 0x57f287; + BLUE: 0x3498db; + YELLOW: 0xfee75c; + PURPLE: 0x9b59b6; + LUMINOUS_VIVID_PINK: 0xe91e63; + FUCHSIA: 0xeb459e; + GOLD: 0xf1c40f; + ORANGE: 0xe67e22; + RED: 0xed4245; + GREY: 0x95a5a6; + NAVY: 0x34495e; + DARK_AQUA: 0x11806a; + DARK_GREEN: 0x1f8b4c; + DARK_BLUE: 0x206694; + DARK_PURPLE: 0x71368a; + DARK_VIVID_PINK: 0xad1457; + DARK_GOLD: 0xc27c0e; + DARK_ORANGE: 0xa84300; + DARK_RED: 0x992d22; + DARK_GREY: 0x979c9f; + DARKER_GREY: 0x7f8c8d; + LIGHT_GREY: 0xbcc0c0; + DARK_NAVY: 0x2c3e50; + BLURPLE: 0x5865f2; + GREYPLE: 0x99aab5; + DARK_BUT_NOT_BLACK: 0x2c2f33; + NOT_QUITE_BLACK: 0x23272a; +} + +export interface ConstantsEvents { + RATE_LIMIT: 'rateLimit'; + INVALID_REQUEST_WARNING: 'invalidRequestWarning'; + CLIENT_READY: 'ready'; + APPLICATION_COMMAND_CREATE: 'applicationCommandCreate'; + APPLICATION_COMMAND_DELETE: 'applicationCommandDelete'; + APPLICATION_COMMAND_UPDATE: 'applicationCommandUpdate'; + GUILD_CREATE: 'guildCreate'; + GUILD_DELETE: 'guildDelete'; + GUILD_UPDATE: 'guildUpdate'; + INVITE_CREATE: 'inviteCreate'; + INVITE_DELETE: 'inviteDelete'; + GUILD_UNAVAILABLE: 'guildUnavailable'; + GUILD_MEMBER_ADD: 'guildMemberAdd'; + GUILD_MEMBER_REMOVE: 'guildMemberRemove'; + GUILD_MEMBER_UPDATE: 'guildMemberUpdate'; + GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable'; + GUILD_MEMBERS_CHUNK: 'guildMembersChunk'; + GUILD_INTEGRATIONS_UPDATE: 'guildIntegrationsUpdate'; + GUILD_ROLE_CREATE: 'roleCreate'; + GUILD_ROLE_DELETE: 'roleDelete'; + GUILD_ROLE_UPDATE: 'roleUpdate'; + GUILD_EMOJI_CREATE: 'emojiCreate'; + GUILD_EMOJI_DELETE: 'emojiDelete'; + GUILD_EMOJI_UPDATE: 'emojiUpdate'; + GUILD_BAN_ADD: 'guildBanAdd'; + GUILD_BAN_REMOVE: 'guildBanRemove'; + CHANNEL_CREATE: 'channelCreate'; + CHANNEL_DELETE: 'channelDelete'; + CHANNEL_UPDATE: 'channelUpdate'; + CHANNEL_PINS_UPDATE: 'channelPinsUpdate'; + MESSAGE_CREATE: 'messageCreate'; + MESSAGE_DELETE: 'messageDelete'; + MESSAGE_UPDATE: 'messageUpdate'; + MESSAGE_BULK_DELETE: 'messageDeleteBulk'; + MESSAGE_REACTION_ADD: 'messageReactionAdd'; + MESSAGE_REACTION_REMOVE: 'messageReactionRemove'; + MESSAGE_REACTION_REMOVE_ALL: 'messageReactionRemoveAll'; + MESSAGE_REACTION_REMOVE_EMOJI: 'messageReactionRemoveEmoji'; + THREAD_CREATE: 'threadCreate'; + THREAD_DELETE: 'threadDelete'; + THREAD_UPDATE: 'threadUpdate'; + THREAD_LIST_SYNC: 'threadListSync'; + THREAD_MEMBER_UPDATE: 'threadMemberUpdate'; + THREAD_MEMBERS_UPDATE: 'threadMembersUpdate'; + USER_UPDATE: 'userUpdate'; + PRESENCE_UPDATE: 'presenceUpdate'; + VOICE_SERVER_UPDATE: 'voiceServerUpdate'; + VOICE_STATE_UPDATE: 'voiceStateUpdate'; + TYPING_START: 'typingStart'; + WEBHOOKS_UPDATE: 'webhookUpdate'; + INTERACTION_CREATE: 'interactionCreate'; + ERROR: 'error'; + WARN: 'warn'; + DEBUG: 'debug'; + SHARD_DISCONNECT: 'shardDisconnect'; + SHARD_ERROR: 'shardError'; + SHARD_RECONNECTING: 'shardReconnecting'; + SHARD_READY: 'shardReady'; + SHARD_RESUME: 'shardResume'; + INVALIDATED: 'invalidated'; + RAW: 'raw'; + STAGE_INSTANCE_CREATE: 'stageInstanceCreate'; + STAGE_INSTANCE_UPDATE: 'stageInstanceUpdate'; + STAGE_INSTANCE_DELETE: 'stageInstanceDelete'; + GUILD_STICKER_CREATE: 'stickerCreate'; + GUILD_STICKER_DELETE: 'stickerDelete'; + GUILD_STICKER_UPDATE: 'stickerUpdate'; +} + +export interface ConstantsOpcodes { + DISPATCH: 0; + HEARTBEAT: 1; + IDENTIFY: 2; + STATUS_UPDATE: 3; + VOICE_STATE_UPDATE: 4; + VOICE_GUILD_PING: 5; + RESUME: 6; + RECONNECT: 7; + REQUEST_GUILD_MEMBERS: 8; + INVALID_SESSION: 9; + HELLO: 10; + HEARTBEAT_ACK: 11; +} + +export interface ConstantsShardEvents { + CLOSE: 'close'; + DESTROYED: 'destroyed'; + INVALID_SESSION: 'invalidSession'; + READY: 'ready'; + RESUMED: 'resumed'; +} + +export interface ConstantsStatus { + READY: 0; + CONNECTING: 1; + RECONNECTING: 2; + IDLE: 3; + NEARLY: 4; + DISCONNECTED: 5; +} + +export interface CreateRoleOptions extends RoleData { + reason?: string; +} + +export interface StageInstanceCreateOptions { + topic: string; + privacyLevel?: PrivacyLevel | number; +} + +export interface CrosspostedChannel { + channelId: Snowflake; + guildId: Snowflake; + type: keyof typeof ChannelTypes; + name: string; +} + +export type DateResolvable = Date | number | string; + +export interface DeconstructedSnowflake { + timestamp: number; + readonly date: Date; + workerId: number; + processId: number; + increment: number; + binary: string; +} + +export type DefaultMessageNotificationLevel = keyof typeof DefaultMessageNotificationLevels; + +export interface EditGuildTemplateOptions { + name?: string; + description?: string; +} + +export interface EmbedField { + name: string; + value: string; + inline: boolean; +} + +export interface EmbedFieldData { + name: string; + value: string; + inline?: boolean; +} + +export type EmojiIdentifierResolvable = string | EmojiResolvable; + +export type EmojiResolvable = Snowflake | GuildEmoji | ReactionEmoji; + +export interface ErrorEvent { + error: unknown; + message: string; + type: string; + target: WebSocket; +} + +export interface EscapeMarkdownOptions { + codeBlock?: boolean; + inlineCode?: boolean; + bold?: boolean; + italic?: boolean; + underline?: boolean; + strikethrough?: boolean; + spoiler?: boolean; + inlineCodeContent?: boolean; + codeBlockContent?: boolean; +} + +export type ExplicitContentFilterLevel = keyof typeof ExplicitContentFilterLevels; + +export interface FetchApplicationCommandOptions extends BaseFetchOptions { + guildId?: Snowflake; +} + +export interface FetchArchivedThreadOptions { + type?: 'public' | 'private'; + fetchAll?: boolean; + before?: ThreadChannelResolvable | DateResolvable; + limit?: number; +} + +export interface FetchBanOptions extends BaseFetchOptions { + user: UserResolvable; +} + +export interface FetchBansOptions { + cache: boolean; +} + +export interface FetchChannelOptions extends BaseFetchOptions { + allowUnknownGuild?: boolean; +} + +export interface FetchedThreads { + threads: Collection; + hasMore?: boolean; +} + +export interface FetchGuildOptions extends BaseFetchOptions { + guild: GuildResolvable; +} + +export interface FetchGuildsOptions { + before?: Snowflake; + after?: Snowflake; + limit?: number; +} + +interface FetchInviteOptions extends BaseFetchOptions { + code: string; +} + +interface FetchInvitesOptions { + channelId?: GuildChannelResolvable; + cache?: boolean; +} + +export interface FetchMemberOptions extends BaseFetchOptions { + user: UserResolvable; +} + +export interface FetchMembersOptions { + user?: UserResolvable | UserResolvable[]; + query?: string; + limit?: number; + withPresences?: boolean; + time?: number; + nonce?: string; + force?: boolean; +} + +export type FetchOwnerOptions = Omit; + +export interface FetchReactionUsersOptions { + limit?: number; + after?: Snowflake; +} + +export interface FetchThreadsOptions { + archived?: FetchArchivedThreadOptions; + active?: boolean; +} + +export interface FileOptions { + attachment: BufferResolvable | Stream; + name?: string; +} + +export interface GuildApplicationCommandPermissionData { + id: Snowflake; + permissions: ApplicationCommandPermissionData[]; +} + +export type GuildAuditLogsAction = keyof GuildAuditLogsActions; + +export interface GuildAuditLogsActions { + ALL?: null; + GUILD_UPDATE?: number; + CHANNEL_CREATE?: number; + CHANNEL_UPDATE?: number; + CHANNEL_DELETE?: number; + CHANNEL_OVERWRITE_CREATE?: number; + CHANNEL_OVERWRITE_UPDATE?: number; + CHANNEL_OVERWRITE_DELETE?: number; + MEMBER_KICK?: number; + MEMBER_PRUNE?: number; + MEMBER_BAN_ADD?: number; + MEMBER_BAN_REMOVE?: number; + MEMBER_UPDATE?: number; + MEMBER_ROLE_UPDATE?: number; + MEMBER_MOVE?: number; + MEMBER_DISCONNECT?: number; + BOT_ADD?: number; + ROLE_CREATE?: number; + ROLE_UPDATE?: number; + ROLE_DELETE?: number; + INVITE_CREATE?: number; + INVITE_UPDATE?: number; + INVITE_DELETE?: number; + WEBHOOK_CREATE?: number; + WEBHOOK_UPDATE?: number; + WEBHOOK_DELETE?: number; + EMOJI_CREATE?: number; + EMOJI_UPDATE?: number; + EMOJI_DELETE?: number; + MESSAGE_DELETE?: number; + MESSAGE_BULK_DELETE?: number; + MESSAGE_PIN?: number; + MESSAGE_UNPIN?: number; + INTEGRATION_CREATE?: number; + INTEGRATION_UPDATE?: number; + INTEGRATION_DELETE?: number; + STAGE_INSTANCE_CREATE?: number; + STAGE_INSTANCE_UPDATE?: number; + STAGE_INSTANCE_DELETE?: number; + STICKER_CREATE?: number; + STICKER_UPDATE?: number; + STICKER_DELETE?: number; + THREAD_CREATE?: number; + THREAD_UPDATE?: number; + THREAD_DELETE?: number; +} + +export type GuildAuditLogsActionType = 'CREATE' | 'DELETE' | 'UPDATE' | 'ALL'; + +export interface GuildAuditLogsFetchOptions { + before?: Snowflake | GuildAuditLogsEntry; + limit?: number; + user?: UserResolvable; + type?: GuildAuditLogsAction | number; +} + +export type GuildAuditLogsTarget = keyof GuildAuditLogsTargets; + +export interface GuildAuditLogsTargets { + ALL?: string; + GUILD?: string; + CHANNEL?: string; + USER?: string; + ROLE?: string; + INVITE?: string; + WEBHOOK?: string; + EMOJI?: string; + MESSAGE?: string; + INTEGRATION?: string; + STAGE_INSTANCE?: string; + STICKER?: string; + THREAD?: string; + UNKNOWN?: string; +} + +export type GuildBanResolvable = GuildBan | UserResolvable; + +export interface GuildChannelOverwriteOptions { + reason?: string; + type?: number; +} + +export type GuildChannelResolvable = Snowflake | GuildChannel | ThreadChannel; + +export interface GuildChannelCreateOptions { + permissionOverwrites?: OverwriteResolvable[] | Collection; + topic?: string; + type?: Exclude< + keyof typeof ChannelTypes | ChannelTypes, + | 'DM' + | 'GROUP_DM' + | 'UNKNOWN' + | 'GUILD_PUBLIC_THREAD' + | 'GUILD_PRIVATE_THREAD' + | ChannelTypes.DM + | ChannelTypes.GROUP_DM + | ChannelTypes.UNKNOWN + | ChannelTypes.GUILD_PUBLIC_THREAD + | ChannelTypes.GUILD_PRIVATE_THREAD + >; + nsfw?: boolean; + parent?: CategoryChannelResolvable; + bitrate?: number; + userLimit?: number; + rateLimitPerUser?: number; + position?: number; + reason?: string; +} + +export interface GuildChannelCloneOptions extends GuildChannelCreateOptions { + name?: string; +} + +export interface GuildChannelOverwriteOptions { + reason?: string; + type?: number; +} + +export interface GuildCreateOptions { + afkChannelId?: Snowflake | number; + afkTimeout?: number; + channels?: PartialChannelData[]; + defaultMessageNotifications?: DefaultMessageNotificationLevel | number; + explicitContentFilter?: ExplicitContentFilterLevel | number; + icon?: BufferResolvable | Base64Resolvable | null; + roles?: PartialRoleData[]; + systemChannelFlags?: SystemChannelFlagsResolvable; + systemChannelId?: Snowflake | number; + verificationLevel?: VerificationLevel | number; +} + +export interface GuildWidgetSettings { + enabled: boolean; + channel: GuildChannel | null; +} + +export interface GuildEditData { + name?: string; + verificationLevel?: VerificationLevel | number; + explicitContentFilter?: ExplicitContentFilterLevel | number; + defaultMessageNotifications?: DefaultMessageNotificationLevel | number; + afkChannel?: VoiceChannelResolvable; + systemChannel?: TextChannelResolvable; + systemChannelFlags?: SystemChannelFlagsResolvable; + afkTimeout?: number; + icon?: Base64Resolvable; + owner?: GuildMemberResolvable; + splash?: Base64Resolvable; + discoverySplash?: Base64Resolvable; + banner?: Base64Resolvable; + rulesChannel?: TextChannelResolvable; + publicUpdatesChannel?: TextChannelResolvable; + preferredLocale?: string; + description?: string | null; + features?: GuildFeatures[]; +} + +export interface GuildEmojiCreateOptions { + roles?: Collection | RoleResolvable[]; + reason?: string; +} + +export interface GuildEmojiEditData { + name?: string; + roles?: Collection | RoleResolvable[]; +} + +export interface GuildStickerCreateOptions { + description?: string | null; + reason?: string; +} + +export interface GuildStickerEditData { + name?: string; + description?: string | null; + tags?: string; +} + +export type GuildFeatures = + | 'ANIMATED_ICON' + | 'BANNER' + | 'COMMERCE' + | 'COMMUNITY' + | 'DISCOVERABLE' + | 'FEATURABLE' + | 'INVITE_SPLASH' + | 'MEMBER_VERIFICATION_GATE_ENABLED' + | 'MONETIZATION_ENABLED' + | 'MORE_STICKERS' + | 'NEWS' + | 'PARTNERED' + | 'PREVIEW_ENABLED' + | 'PRIVATE_THREADS' + | 'RELAY_ENABLED' + | 'SEVEN_DAY_THREAD_ARCHIVE' + | 'THREE_DAY_THREAD_ARCHIVE' + | 'TICKETED_EVENTS_ENABLED' + | 'VANITY_URL' + | 'VERIFIED' + | 'VIP_REGIONS' + | 'WELCOME_SCREEN_ENABLED'; + +export interface GuildMemberEditData { + nick?: string | null; + roles?: Collection | readonly RoleResolvable[]; + mute?: boolean; + deaf?: boolean; + channel?: GuildVoiceChannelResolvable | null; +} + +export type GuildMemberResolvable = GuildMember | UserResolvable; + +export type GuildResolvable = Guild | GuildChannel | GuildMember | GuildEmoji | Invite | Role | Snowflake; + +export interface GuildPruneMembersOptions { + count?: boolean; + days?: number; + dry?: boolean; + reason?: string; + roles?: RoleResolvable[]; +} + +export interface GuildWidgetSettingsData { + enabled: boolean; + channel: GuildChannelResolvable | null; +} + +export interface GuildSearchMembersOptions { + query: string; + limit?: number; + cache?: boolean; +} + +export type GuildTemplateResolvable = string; + +export type GuildVoiceChannelResolvable = VoiceChannel | StageChannel | Snowflake; + +export type HexColorString = `#${string}`; + +export interface HTTPAttachmentData { + attachment: string | Buffer | Stream; + name: string; + file: Buffer | Stream; +} + +export interface HTTPErrorData { + json: unknown; + files: HTTPAttachmentData[]; +} + +export interface HTTPOptions { + api?: string; + version?: number; + host?: string; + cdn?: string; + invite?: string; + template?: string; + headers?: Record; +} + +export type ImageSize = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096; + +export interface ImageURLOptions extends StaticImageURLOptions { + dynamic?: boolean; +} + +export interface IntegrationAccount { + id: string | Snowflake; + name: string; +} + +export interface InteractionCollectorOptions extends CollectorOptions<[T]> { + channel?: TextChannel | DMChannel | NewsChannel | ThreadChannel; + componentType?: MessageComponentType | MessageComponentTypes; + guild?: Guild; + interactionType?: InteractionType | InteractionTypes; + max?: number; + maxComponents?: number; + maxUsers?: number; + message?: Message; +} + +export interface InteractionDeferOptions { + ephemeral?: boolean; + fetchReply?: boolean; +} + +export type InteractionDeferUpdateOptions = Omit; + +export interface InteractionReplyOptions extends Omit { + ephemeral?: boolean; + fetchReply?: boolean; +} + +export type InteractionResponseType = keyof typeof InteractionResponseTypes; + +export type InteractionType = keyof typeof InteractionTypes; + +export interface InteractionUpdateOptions extends MessageEditOptions { + fetchReply?: boolean; +} + +export type IntentsString = + | 'GUILDS' + | 'GUILD_MEMBERS' + | 'GUILD_BANS' + | 'GUILD_EMOJIS_AND_STICKERS' + | 'GUILD_INTEGRATIONS' + | 'GUILD_WEBHOOKS' + | 'GUILD_INVITES' + | 'GUILD_VOICE_STATES' + | 'GUILD_PRESENCES' + | 'GUILD_MESSAGES' + | 'GUILD_MESSAGE_REACTIONS' + | 'GUILD_MESSAGE_TYPING' + | 'DIRECT_MESSAGES' + | 'DIRECT_MESSAGE_REACTIONS' + | 'DIRECT_MESSAGE_TYPING'; + +export interface InviteGenerationOptions { + permissions?: PermissionResolvable; + guild?: GuildResolvable; + disableGuildSelect?: boolean; + scopes: InviteScope[]; +} + +export interface CreateInviteOptions { + temporary?: boolean; + maxAge?: number; + maxUses?: number; + unique?: boolean; + reason?: string; + targetApplication?: ApplicationResolvable; + targetUser?: UserResolvable; + targetType?: InviteTargetType; +} + +export type InviteResolvable = string; + +export type InviteScope = + | 'applications.builds.read' + | 'applications.commands' + | 'applications.entitlements' + | 'applications.store.update' + | 'bot' + | 'connections' + | 'email' + | 'identify' + | 'guilds' + | 'guilds.join' + | 'gdm.join' + | 'webhook.incoming'; + +export interface LifetimeFilterOptions { + excludeFromSweep?: (value: V, key: K, collection: LimitedCollection) => boolean; + getComparisonTimestamp?: (value: V, key: K, collection: LimitedCollection) => number; + lifetime?: number; +} + +export interface MakeErrorOptions { + name: string; + message: string; + stack: string; +} + +export type MemberMention = UserMention | `<@!${Snowflake}>`; + +export type MembershipState = keyof typeof MembershipStates; + +export type MessageActionRowComponent = MessageButton | MessageSelectMenu; + +export type MessageActionRowComponentOptions = MessageButtonOptions | MessageSelectMenuOptions; + +export type MessageActionRowComponentResolvable = MessageActionRowComponent | MessageActionRowComponentOptions; + +export interface MessageActionRowOptions extends BaseMessageComponentOptions { + components: MessageActionRowComponentResolvable[]; +} + +export interface MessageActivity { + partyId: string; + type: number; +} + +export type MessageAdditions = MessageEmbed | MessageAttachment | (MessageEmbed | MessageAttachment)[]; + +export interface BaseButtonOptions extends BaseMessageComponentOptions { + disabled?: boolean; + emoji?: EmojiIdentifierResolvable; + label?: string; +} + +export type MessageButtonOptions = BaseButtonOptions & + ( + | { + style: Exclude; + customId: string; + } + | { + style: 'LINK' | MessageButtonStyles.LINK; + url: string; + } + ); + +export type MessageButtonStyle = keyof typeof MessageButtonStyles; + +export type MessageButtonStyleResolvable = MessageButtonStyle | MessageButtonStyles; + +export interface MessageCollectorOptions extends CollectorOptions<[Message]> { + max?: number; + maxProcessed?: number; +} + +export type MessageComponent = BaseMessageComponent | MessageActionRow | MessageButton | MessageSelectMenu; + +export type MessageComponentCollectorOptions = Omit< + InteractionCollectorOptions, + 'channel' | 'message' | 'guild' | 'interactionType' +>; + +export type MessageComponentOptions = + | BaseMessageComponentOptions + | MessageActionRowOptions + | MessageButtonOptions + | MessageSelectMenuOptions; + +export type MessageComponentType = keyof typeof MessageComponentTypes; + +export type MessageComponentTypeResolvable = MessageComponentType | MessageComponentTypes; + +export interface MessageEditOptions { + attachments?: MessageAttachment[]; + content?: string | null; + embeds?: (MessageEmbed | MessageEmbedOptions)[] | null; + files?: (FileOptions | BufferResolvable | Stream | MessageAttachment)[]; + flags?: BitFieldResolvable; + allowedMentions?: MessageMentionOptions; + components?: (MessageActionRow | MessageActionRowOptions)[]; +} + +export interface MessageEmbedAuthor { + name?: string; + url?: string; + iconURL?: string; + proxyIconURL?: string; +} + +export interface MessageEmbedFooter { + text?: string; + iconURL?: string; + proxyIconURL?: string; +} + +export interface MessageEmbedImage { + url: string; + proxyURL?: string; + height?: number; + width?: number; +} + +export interface MessageEmbedOptions { + title?: string; + description?: string; + url?: string; + timestamp?: Date | number; + color?: ColorResolvable; + fields?: EmbedFieldData[]; + author?: Partial & { icon_url?: string; proxy_icon_url?: string }; + thumbnail?: Partial & { proxy_url?: string }; + image?: Partial & { proxy_url?: string }; + video?: Partial & { proxy_url?: string }; + footer?: Partial & { icon_url?: string; proxy_icon_url?: string }; +} + +export interface MessageEmbedProvider { + name: string; + url: string; +} + +export interface MessageEmbedThumbnail { + url: string; + proxyURL?: string; + height?: number; + width?: number; +} + +export interface MessageEmbedVideo { + url?: string; + proxyURL?: string; + height?: number; + width?: number; +} + +export interface MessageEvent { + data: WebSocket.Data; + type: string; + target: WebSocket; +} + +export type MessageFlagsString = + | 'CROSSPOSTED' + | 'IS_CROSSPOST' + | 'SUPPRESS_EMBEDS' + | 'SOURCE_MESSAGE_DELETED' + | 'URGENT' + | 'HAS_THREAD' + | 'EPHEMERAL' + | 'LOADING'; + +export interface MessageInteraction { + id: Snowflake; + type: InteractionType; + commandName: string; + user: User; +} + +export interface MessageMentionsHasOptions { + ignoreDirect?: boolean; + ignoreRoles?: boolean; + ignoreEveryone?: boolean; +} + +export interface MessageMentionOptions { + parse?: MessageMentionTypes[]; + roles?: Snowflake[]; + users?: Snowflake[]; + repliedUser?: boolean; +} + +export type MessageMentionTypes = 'roles' | 'users' | 'everyone'; + +export interface MessageOptions { + tts?: boolean; + nonce?: string | number; + content?: string | null; + embeds?: (MessageEmbed | MessageEmbedOptions)[]; + components?: (MessageActionRow | MessageActionRowOptions)[]; + allowedMentions?: MessageMentionOptions; + files?: (FileOptions | BufferResolvable | Stream | MessageAttachment)[]; + reply?: ReplyOptions; + stickers?: StickerResolvable[]; +} + +export type MessageReactionResolvable = + | MessageReaction + | Snowflake + | `${string}:${Snowflake}` + | `<:${string}:${Snowflake}>` + | `` + | string; + +export interface MessageReference { + channelId: Snowflake; + guildId: Snowflake; + messageId: Snowflake | null; +} + +export type MessageResolvable = Message | Snowflake; + +export interface MessageSelectMenuOptions extends BaseMessageComponentOptions { + customId?: string; + disabled?: boolean; + maxValues?: number; + minValues?: number; + options?: MessageSelectOptionData[]; + placeholder?: string; +} + +export interface MessageSelectOption { + default: boolean; + description: string | null; + emoji: APIPartialEmoji | null; + label: string; + value: string; +} + +export interface MessageSelectOptionData { + default?: boolean; + description?: string; + emoji?: EmojiIdentifierResolvable; + label: string; + value: string; +} + +export type MessageTarget = + | Interaction + | InteractionWebhook + | TextChannel + | NewsChannel + | ThreadChannel + | DMChannel + | User + | GuildMember + | Webhook + | WebhookClient + | Message + | MessageManager; + +export type MessageType = + | 'DEFAULT' + | 'RECIPIENT_ADD' + | 'RECIPIENT_REMOVE' + | 'CALL' + | 'CHANNEL_NAME_CHANGE' + | 'CHANNEL_ICON_CHANGE' + | 'PINS_ADD' + | 'GUILD_MEMBER_JOIN' + | 'USER_PREMIUM_GUILD_SUBSCRIPTION' + | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1' + | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2' + | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3' + | 'CHANNEL_FOLLOW_ADD' + | 'GUILD_DISCOVERY_DISQUALIFIED' + | 'GUILD_DISCOVERY_REQUALIFIED' + | 'GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING' + | 'GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING' + | 'THREAD_CREATED' + | 'REPLY' + | 'APPLICATION_COMMAND' + | 'THREAD_STARTER_MESSAGE' + | 'GUILD_INVITE_REMINDER'; + +export type MFALevel = keyof typeof MFALevels; + +export interface MultipleShardRespawnOptions { + shardDelay?: number; + respawnDelay?: number; + timeout?: number; +} + +export interface MultipleShardSpawnOptions { + amount?: number | 'auto'; + delay?: number; + timeout?: number; +} + +export type NSFWLevel = keyof typeof NSFWLevels; + +export interface OverwriteData { + allow?: PermissionResolvable; + deny?: PermissionResolvable; + id: GuildMemberResolvable | RoleResolvable; + type?: OverwriteType; +} + +export type OverwriteResolvable = PermissionOverwrites | OverwriteData; + +export type OverwriteType = 'member' | 'role'; + +export type PermissionFlags = Record; + +export type PermissionOverwriteOptions = Partial>; + +export type PermissionResolvable = BitFieldResolvable; + +export type PermissionOverwriteResolvable = UserResolvable | RoleResolvable | PermissionOverwrites; + +export type PermissionString = + | 'CREATE_INSTANT_INVITE' + | 'KICK_MEMBERS' + | 'BAN_MEMBERS' + | 'ADMINISTRATOR' + | 'MANAGE_CHANNELS' + | 'MANAGE_GUILD' + | 'ADD_REACTIONS' + | 'VIEW_AUDIT_LOG' + | 'PRIORITY_SPEAKER' + | 'STREAM' + | 'VIEW_CHANNEL' + | 'SEND_MESSAGES' + | 'SEND_TTS_MESSAGES' + | 'MANAGE_MESSAGES' + | 'EMBED_LINKS' + | 'ATTACH_FILES' + | 'READ_MESSAGE_HISTORY' + | 'MENTION_EVERYONE' + | 'USE_EXTERNAL_EMOJIS' + | 'VIEW_GUILD_INSIGHTS' + | 'CONNECT' + | 'SPEAK' + | 'MUTE_MEMBERS' + | 'DEAFEN_MEMBERS' + | 'MOVE_MEMBERS' + | 'USE_VAD' + | 'CHANGE_NICKNAME' + | 'MANAGE_NICKNAMES' + | 'MANAGE_ROLES' + | 'MANAGE_WEBHOOKS' + | 'MANAGE_EMOJIS_AND_STICKERS' + | 'USE_APPLICATION_COMMANDS' + | 'REQUEST_TO_SPEAK' + | 'MANAGE_THREADS' + | 'USE_PUBLIC_THREADS' + | 'USE_PRIVATE_THREADS' + | 'USE_EXTERNAL_STICKERS'; + +export type RecursiveArray = ReadonlyArray>; + +export type RecursiveReadonlyArray = ReadonlyArray>; + +export type PremiumTier = keyof typeof PremiumTiers; + +export interface PresenceData { + status?: PresenceStatusData; + afk?: boolean; + activities?: ActivitiesOptions[]; + shardId?: number | number[]; +} + +export type PresenceResolvable = Presence | UserResolvable | Snowflake; + +export interface PartialChannelData { + id?: Snowflake | number; + name: string; + topic?: string; + type?: ChannelTypes; + parentId?: Snowflake | number; + permissionOverwrites?: PartialOverwriteData[]; +} + +export type Partialize< + T extends AllowedPartial, + N extends keyof T | null = null, + M extends keyof T | null = null, + E extends keyof T | '' = '', +> = { + readonly client: Client; + id: Snowflake; + partial: true; +} & { + [K in keyof Omit]: K extends N ? null : K extends M ? T[K] | null : T[K]; +}; + +export interface PartialDMChannel extends Partialize { + lastMessageId: undefined; +} + +export interface PartialGuildMember extends Partialize {} + +export interface PartialMessage + extends Partialize {} + +export interface PartialMessageReaction extends Partialize {} + +export interface PartialOverwriteData { + id: Snowflake | number; + type?: OverwriteType; + allow?: PermissionResolvable; + deny?: PermissionResolvable; +} + +export interface PartialRoleData extends RoleData { + id?: Snowflake | number; +} + +export type PartialTypes = 'USER' | 'CHANNEL' | 'GUILD_MEMBER' | 'MESSAGE' | 'REACTION'; + +export interface PartialUser extends Partialize {} + +export type PresenceStatusData = ClientPresenceStatus | 'invisible'; + +export type PresenceStatus = PresenceStatusData | 'offline'; + +export type PrivacyLevel = keyof typeof PrivacyLevels; + +export interface RateLimitData { + timeout: number; + limit: number; + method: string; + path: string; + route: string; + global: boolean; +} + +export interface InvalidRequestWarningData { + count: number; + remainingTime: number; +} + +export interface ReactionCollectorOptions extends CollectorOptions<[MessageReaction, User]> { + max?: number; + maxEmojis?: number; + maxUsers?: number; +} + +export interface ReplyOptions { + messageReference: MessageResolvable; + failIfNotExists?: boolean; +} + +export interface ReplyMessageOptions extends Omit { + failIfNotExists?: boolean; +} + +export interface ResolvedOverwriteOptions { + allow: Permissions; + deny: Permissions; +} + +export interface RoleData { + name?: string; + color?: ColorResolvable; + hoist?: boolean; + position?: number; + permissions?: PermissionResolvable; + mentionable?: boolean; +} + +export type RoleMention = '@everyone' | `<@&${Snowflake}>`; + +export interface RolePosition { + role: RoleResolvable; + position: number; +} + +export type RoleResolvable = Role | Snowflake; + +export interface RoleTagData { + botId?: Snowflake; + integrationId?: Snowflake; + premiumSubscriberRole?: true; +} + +export interface SetChannelPositionOptions { + relative?: boolean; + reason?: string; +} + +export interface SetParentOptions { + lockPermissions?: boolean; + reason?: string; +} + +export interface SetRolePositionOptions { + relative?: boolean; + reason?: string; +} + +export type ShardingManagerMode = 'process' | 'worker'; + +export interface ShardingManagerOptions { + totalShards?: number | 'auto'; + shardList?: number[] | 'auto'; + mode?: ShardingManagerMode; + respawn?: boolean; + shardArgs?: string[]; + token?: string; + execArgv?: string[]; +} + +export { Snowflake }; + +export interface SplitOptions { + maxLength?: number; + char?: string | string[] | RegExp | RegExp[]; + prepend?: string; + append?: string; +} + +export interface StaticImageURLOptions { + format?: AllowedImageFormat; + size?: ImageSize; +} + +export type StageInstanceResolvable = StageInstance | Snowflake; + +export interface StartThreadOptions { + name: string; + autoArchiveDuration: ThreadAutoArchiveDuration; + reason?: string; +} + +export type Status = number; + +export type StickerFormatType = keyof typeof StickerFormatTypes; + +export type StickerResolvable = Sticker | Snowflake; + +export type StickerType = keyof typeof StickerTypes; + +export type SystemChannelFlagsString = + | 'SUPPRESS_JOIN_NOTIFICATIONS' + | 'SUPPRESS_PREMIUM_SUBSCRIPTIONS' + | 'SUPPRESS_GUILD_REMINDER_NOTIFICATIONS'; + +export type SystemChannelFlagsResolvable = BitFieldResolvable; + +export type SystemMessageType = Exclude; + +export interface StageInstanceEditOptions { + topic?: string; + privacyLevel?: PrivacyLevel | number; +} + +export type SweepFilter = ( + collection: LimitedCollection, +) => ((value: V, key: K, collection: LimitedCollection) => boolean) | null; + +export interface LimitedCollectionOptions { + maxSize?: number; + keepOverLimit?: (value: V, key: K, collection: LimitedCollection) => boolean; + sweepFilter?: SweepFilter; + sweepInterval?: number; +} + +export type TextBasedChannelTypes = + | 'DM' + | 'GUILD_TEXT' + | 'GUILD_NEWS' + | 'GUILD_NEWS_THREAD' + | 'GUILD_PUBLIC_THREAD' + | 'GUILD_PRIVATE_THREAD'; + +export type TextChannelResolvable = Snowflake | TextChannel; + +export type ThreadAutoArchiveDuration = 60 | 1440 | 4320 | 10080; + +export type ThreadChannelResolvable = ThreadChannel | Snowflake; + +export type ThreadChannelTypes = 'GUILD_NEWS_THREAD' | 'GUILD_PUBLIC_THREAD' | 'GUILD_PRIVATE_THREAD'; + +export interface ThreadCreateOptions extends StartThreadOptions { + startMessage?: MessageResolvable; + type?: AllowedThreadType; +} + +export interface ThreadEditData { + name?: string; + archived?: boolean; + autoArchiveDuration?: ThreadAutoArchiveDuration; + rateLimitPerUser?: number; + locked?: boolean; +} + +export type ThreadMemberFlagsString = ''; + +export type ThreadMemberResolvable = ThreadMember | UserResolvable; + +export type UserFlagsString = + | 'DISCORD_EMPLOYEE' + | 'PARTNERED_SERVER_OWNER' + | 'HYPESQUAD_EVENTS' + | 'BUGHUNTER_LEVEL_1' + | 'HOUSE_BRAVERY' + | 'HOUSE_BRILLIANCE' + | 'HOUSE_BALANCE' + | 'EARLY_SUPPORTER' + | 'TEAM_USER' + | 'BUGHUNTER_LEVEL_2' + | 'VERIFIED_BOT' + | 'EARLY_VERIFIED_BOT_DEVELOPER' + | 'DISCORD_CERTIFIED_MODERATOR'; + +export type UserMention = `<@${Snowflake}>`; + +export type UserResolvable = User | Snowflake | Message | GuildMember | ThreadMember; + +export interface Vanity { + code: string | null; + uses: number | null; +} + +export type VerificationLevel = keyof typeof VerificationLevels; + +export type VoiceBasedChannelTypes = 'GUILD_VOICE' | 'GUILD_STAGE_VOICE'; + +export type VoiceChannelResolvable = Snowflake | VoiceChannel; + +export type WebhookClientData = WebhookClientDataIdWithToken | WebhookClientDataURL; + +export interface WebhookClientDataIdWithToken { + token: string; + id: string; + id: Snowflake; + token: string; +} + +export interface WebhookClientDataURL { + url: string; +} + +export type WebhookClientOptions = Pick< + ClientOptions, + 'allowedMentions' | 'restTimeOffset' | 'restRequestTimeout' | 'retryLimit' | 'http' +>; + +export interface WebhookEditData { + name?: string; + avatar?: BufferResolvable; + channel?: GuildTextChannelResolvable; +} + +export type WebhookEditMessageOptions = Pick< + WebhookMessageOptions, + 'content' | 'embeds' | 'files' | 'allowedMentions' | 'components' +>; + +export interface WebhookMessageOptions extends Omit { + username?: string; + avatarURL?: string; + threadId?: Snowflake; +} + +export type WebhookType = keyof typeof WebhookTypes; + +export interface WebSocketOptions { + large_threshold?: number; + compress?: boolean; + properties?: WebSocketProperties; +} + +export interface WebSocketProperties { + $os?: string; + $browser?: string; + $device?: string; +} + +export interface WidgetActivity { + name: string; +} + +export interface WidgetChannel { + id: Snowflake; + name: string; + position: number; +} + +export interface WelcomeChannelData { + description: string; + channel: GuildChannelResolvable; + emoji?: EmojiIdentifierResolvable; +} + +export interface WelcomeScreenEditData { + enabled?: boolean; + description?: string; + welcomeChannels?: WelcomeChannelData[]; +} + +export type WSEventType = + | 'READY' + | 'RESUMED' + | 'APPLICATION_COMMAND_CREATE' + | 'APPLICATION_COMMAND_DELETE' + | 'APPLICATION_COMMAND_UPDATE' + | 'GUILD_CREATE' + | 'GUILD_DELETE' + | 'GUILD_UPDATE' + | 'INVITE_CREATE' + | 'INVITE_DELETE' + | 'GUILD_MEMBER_ADD' + | 'GUILD_MEMBER_REMOVE' + | 'GUILD_MEMBER_UPDATE' + | 'GUILD_MEMBERS_CHUNK' + | 'GUILD_ROLE_CREATE' + | 'GUILD_ROLE_DELETE' + | 'GUILD_ROLE_UPDATE' + | 'GUILD_BAN_ADD' + | 'GUILD_BAN_REMOVE' + | 'GUILD_EMOJIS_UPDATE' + | 'GUILD_INTEGRATIONS_UPDATE' + | 'CHANNEL_CREATE' + | 'CHANNEL_DELETE' + | 'CHANNEL_UPDATE' + | 'CHANNEL_PINS_UPDATE' + | 'MESSAGE_CREATE' + | 'MESSAGE_DELETE' + | 'MESSAGE_UPDATE' + | 'MESSAGE_DELETE_BULK' + | 'MESSAGE_REACTION_ADD' + | 'MESSAGE_REACTION_REMOVE' + | 'MESSAGE_REACTION_REMOVE_ALL' + | 'MESSAGE_REACTION_REMOVE_EMOJI' + | 'THREAD_CREATE' + | 'THREAD_UPDATE' + | 'THREAD_DELETE' + | 'THREAD_LIST_SYNC' + | 'THREAD_MEMBER_UPDATE' + | 'THREAD_MEMBERS_UPDATE' + | 'USER_UPDATE' + | 'PRESENCE_UPDATE' + | 'TYPING_START' + | 'VOICE_STATE_UPDATE' + | 'VOICE_SERVER_UPDATE' + | 'WEBHOOKS_UPDATE' + | 'INTERACTION_CREATE' + | 'STAGE_INSTANCE_CREATE' + | 'STAGE_INSTANCE_UPDATE' + | 'STAGE_INSTANCE_DELETE' + | 'GUILD_STICKERS_UPDATE'; + +export type Serialized = T extends symbol | bigint | (() => any) + ? never + : T extends number | string | boolean | undefined + ? T + : T extends { toJSON(): infer R } + ? R + : T extends ReadonlyArray + ? Serialized[] + : T extends ReadonlyMap | ReadonlySet + ? {} + : { [K in keyof T]: Serialized }; + +//#endregion + +//#region Voice + +/** + * @internal Use `DiscordGatewayAdapterLibraryMethods` from `@discordjs/voice` instead. + */ +export interface InternalDiscordGatewayAdapterLibraryMethods { + onVoiceServerUpdate(data: GatewayVoiceServerUpdateDispatchData): void; + onVoiceStateUpdate(data: GatewayVoiceStateUpdateDispatchData): void; + destroy(): void; +} + +/** + * @internal Use `DiscordGatewayAdapterImplementerMethods` from `@discordjs/voice` instead. + */ +export interface InternalDiscordGatewayAdapterImplementerMethods { + sendPayload(payload: unknown): boolean; + destroy(): void; +} + +/** + * @internal Use `DiscordGatewayAdapterCreator` from `@discordjs/voice` instead. + */ +export type InternalDiscordGatewayAdapterCreator = ( + methods: InternalDiscordGatewayAdapterLibraryMethods, +) => InternalDiscordGatewayAdapterImplementerMethods; + +//#endregion diff --git a/node_modules/discord.js/typings/index.ts b/node_modules/discord.js/typings/index.ts deleted file mode 100644 index db7abe7c..00000000 --- a/node_modules/discord.js/typings/index.ts +++ /dev/null @@ -1,53 +0,0 @@ -/// - -import { Client, Message, MessageAttachment, MessageEmbed } from 'discord.js'; - -const client: Client = new Client(); - -client.on('ready', () => { - console.log(`Client is logged in as ${client.user!.tag} and ready!`); -}); - -client.on('guildCreate', g => { - const channel = g.channels.cache.random(); - if (!channel) return; - - channel.setName('foo').then(updatedChannel => { - console.log(`New channel name: ${updatedChannel.name}`); - }); -}); - -client.on('messageReactionRemoveAll', async message => { - console.log(`messageReactionRemoveAll - id: ${message.id} (${message.id.length})`); - - if (message.partial) message = await message.fetch(); - - console.log(`messageReactionRemoveAll - content: ${message.content}`); -}); - -// These are to check that stuff is the right type -declare const assertIsMessage: (m: Promise) => void; -declare const assertIsMessageArray: (m: Promise) => void; - -client.on('message', ({ channel }) => { - assertIsMessage(channel.send('string')); - assertIsMessage(channel.send({})); - assertIsMessage(channel.send({ embed: {} })); - assertIsMessage(channel.send({ another: 'property' }, {})); - - const attachment = new MessageAttachment('file.png'); - const embed = new MessageEmbed(); - assertIsMessage(channel.send(attachment)); - assertIsMessage(channel.send(embed)); - assertIsMessage(channel.send([attachment, embed])); - - assertIsMessageArray(channel.send(Symbol('another primitive'), { split: true })); - assertIsMessageArray(channel.send({ split: true })); - - // @ts-expect-error - channel.send(); - // @ts-expect-error - channel.send({ another: 'property' }); -}); - -client.login('absolutely-valid-token'); diff --git a/node_modules/discord.js/webpack/discord.min.js b/node_modules/discord.js/webpack/discord.min.js deleted file mode 100644 index 96b0f1c4..00000000 --- a/node_modules/discord.js/webpack/discord.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see discord.min.js.LICENSE.txt */ -!function webpackUniversalModuleDefinition(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Discord=t():e.Discord=t()}(window,(function(){return function(e){var t={};function __webpack_require__(i){if(t[i])return t[i].exports;var s=t[i]={i:i,l:!1,exports:{}};return e[i].call(s.exports,s,s.exports,__webpack_require__),s.l=!0,s.exports}return __webpack_require__.m=e,__webpack_require__.c=t,__webpack_require__.d=function(e,t,i){__webpack_require__.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},__webpack_require__.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.t=function(e,t){if(1&t&&(e=__webpack_require__(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(__webpack_require__.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)__webpack_require__.d(i,s,function(t){return e[t]}.bind(null,s));return i},__webpack_require__.n=function(e){var t=e&&e.__esModule?function getDefault(){return e.default}:function getModuleExports(){return e};return __webpack_require__.d(t,"a",t),t},__webpack_require__.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},__webpack_require__.p="",__webpack_require__(__webpack_require__.s=102)}([function(e,t,i){"use strict";(function(e){const s=t.Package=i(61),{Error:n,RangeError:r}=i(2),o=t.browser="undefined"!=typeof window;t.DefaultOptions={shardCount:1,messageCacheMaxSize:200,messageCacheLifetime:0,messageSweepInterval:0,messageEditHistoryMaxSize:-1,fetchAllMembers:!1,disableMentions:"none",partials:[],restWsBridgeTimeout:5e3,restRequestTimeout:15e3,retryLimit:1,restTimeOffset:500,restSweepInterval:60,presence:{},ws:{large_threshold:50,compress:!1,properties:{$os:o?"browser":e.platform,$browser:"discord.js",$device:"discord.js"},version:6},http:{version:7,api:"https://discord.com/api",cdn:"https://cdn.discordapp.com",invite:"https://discord.gg",template:"https://discord.new"}},t.UserAgent=o?null:`DiscordBot (${s.homepage.split("#")[0]}, ${s.version}) Node.js/${e.version}`,t.WSCodes={1e3:"WS_CLOSE_REQUESTED",4004:"TOKEN_INVALID",4010:"SHARDING_INVALID",4011:"SHARDING_REQUIRED",4013:"INVALID_INTENTS",4014:"DISALLOWED_INTENTS"};const a=["webp","png","jpg","jpeg","gif"],c=Array.from({length:9},((e,t)=>2**(t+4)));function makeImageUrl(e,{format:t="webp",size:i}={}){if(t&&!a.includes(t))throw new n("IMAGE_FORMAT",t);if(i&&!c.includes(i))throw new r("IMAGE_SIZE",i);return`${e}.${t}${i?"?size="+i:""}`}function keyMirror(e){let t=Object.create(null);for(const i of e)t[i]=i;return t}t.Endpoints={CDN:e=>({Emoji:(t,i="png")=>`${e}/emojis/${t}.${i}`,Asset:t=>`${e}/assets/${t}`,DefaultAvatar:t=>`${e}/embed/avatars/${t}.png`,Avatar:(t,i,s="webp",n,r=!1)=>(r&&(s=i.startsWith("a_")?"gif":s),makeImageUrl(`${e}/avatars/${t}/${i}`,{format:s,size:n})),Banner:(t,i,s="webp",n)=>makeImageUrl(`${e}/banners/${t}/${i}`,{format:s,size:n}),Icon:(t,i,s="webp",n,r=!1)=>(r&&(s=i.startsWith("a_")?"gif":s),makeImageUrl(`${e}/icons/${t}/${i}`,{format:s,size:n})),AppIcon:(t,i,{format:s="webp",size:n}={})=>makeImageUrl(`${e}/app-icons/${t}/${i}`,{size:n,format:s}),AppAsset:(t,i,{format:s="webp",size:n}={})=>makeImageUrl(`${e}/app-assets/${t}/${i}`,{size:n,format:s}),GDMIcon:(t,i,s="webp",n)=>makeImageUrl(`${e}/channel-icons/${t}/${i}`,{size:n,format:s}),Splash:(t,i,s="webp",n)=>makeImageUrl(`${e}/splashes/${t}/${i}`,{size:n,format:s}),DiscoverySplash:(t,i,s="webp",n)=>makeImageUrl(`${e}/discovery-splashes/${t}/${i}`,{size:n,format:s}),TeamIcon:(t,i,{format:s="webp",size:n}={})=>makeImageUrl(`${e}/team-icons/${t}/${i}`,{size:n,format:s})}),invite:(e,t)=>`${e}/${t}`,botGateway:"/gateway/bot"},t.Status={READY:0,CONNECTING:1,RECONNECTING:2,IDLE:3,NEARLY:4,DISCONNECTED:5,WAITING_FOR_GUILDS:6,IDENTIFYING:7,RESUMING:8},t.VoiceStatus={CONNECTED:0,CONNECTING:1,AUTHENTICATING:2,RECONNECTING:3,DISCONNECTED:4},t.OPCodes={DISPATCH:0,HEARTBEAT:1,IDENTIFY:2,STATUS_UPDATE:3,VOICE_STATE_UPDATE:4,VOICE_GUILD_PING:5,RESUME:6,RECONNECT:7,REQUEST_GUILD_MEMBERS:8,INVALID_SESSION:9,HELLO:10,HEARTBEAT_ACK:11},t.VoiceOPCodes={IDENTIFY:0,SELECT_PROTOCOL:1,READY:2,HEARTBEAT:3,SESSION_DESCRIPTION:4,SPEAKING:5,HELLO:8,CLIENT_CONNECT:12,CLIENT_DISCONNECT:13},t.Events={RATE_LIMIT:"rateLimit",CLIENT_READY:"ready",GUILD_CREATE:"guildCreate",GUILD_DELETE:"guildDelete",GUILD_UPDATE:"guildUpdate",GUILD_UNAVAILABLE:"guildUnavailable",GUILD_AVAILABLE:"guildAvailable",GUILD_MEMBER_ADD:"guildMemberAdd",GUILD_MEMBER_REMOVE:"guildMemberRemove",GUILD_MEMBER_UPDATE:"guildMemberUpdate",GUILD_MEMBER_AVAILABLE:"guildMemberAvailable",GUILD_MEMBER_SPEAKING:"guildMemberSpeaking",GUILD_MEMBERS_CHUNK:"guildMembersChunk",GUILD_INTEGRATIONS_UPDATE:"guildIntegrationsUpdate",GUILD_ROLE_CREATE:"roleCreate",GUILD_ROLE_DELETE:"roleDelete",INVITE_CREATE:"inviteCreate",INVITE_DELETE:"inviteDelete",GUILD_ROLE_UPDATE:"roleUpdate",GUILD_EMOJI_CREATE:"emojiCreate",GUILD_EMOJI_DELETE:"emojiDelete",GUILD_EMOJI_UPDATE:"emojiUpdate",GUILD_BAN_ADD:"guildBanAdd",GUILD_BAN_REMOVE:"guildBanRemove",CHANNEL_CREATE:"channelCreate",CHANNEL_DELETE:"channelDelete",CHANNEL_UPDATE:"channelUpdate",CHANNEL_PINS_UPDATE:"channelPinsUpdate",MESSAGE_CREATE:"message",MESSAGE_DELETE:"messageDelete",MESSAGE_UPDATE:"messageUpdate",MESSAGE_BULK_DELETE:"messageDeleteBulk",MESSAGE_REACTION_ADD:"messageReactionAdd",MESSAGE_REACTION_REMOVE:"messageReactionRemove",MESSAGE_REACTION_REMOVE_ALL:"messageReactionRemoveAll",MESSAGE_REACTION_REMOVE_EMOJI:"messageReactionRemoveEmoji",USER_UPDATE:"userUpdate",PRESENCE_UPDATE:"presenceUpdate",VOICE_SERVER_UPDATE:"voiceServerUpdate",VOICE_STATE_UPDATE:"voiceStateUpdate",VOICE_BROADCAST_SUBSCRIBE:"subscribe",VOICE_BROADCAST_UNSUBSCRIBE:"unsubscribe",TYPING_START:"typingStart",TYPING_STOP:"typingStop",WEBHOOKS_UPDATE:"webhookUpdate",ERROR:"error",WARN:"warn",DEBUG:"debug",SHARD_DISCONNECT:"shardDisconnect",SHARD_ERROR:"shardError",SHARD_RECONNECTING:"shardReconnecting",SHARD_READY:"shardReady",SHARD_RESUME:"shardResume",INVALIDATED:"invalidated",RAW:"raw"},t.ShardEvents={CLOSE:"close",DESTROYED:"destroyed",INVALID_SESSION:"invalidSession",READY:"ready",RESUMED:"resumed",ALL_READY:"allReady"},t.PartialTypes=keyMirror(["USER","CHANNEL","GUILD_MEMBER","MESSAGE","REACTION"]),t.WSEvents=keyMirror(["READY","RESUMED","GUILD_CREATE","GUILD_DELETE","GUILD_UPDATE","INVITE_CREATE","INVITE_DELETE","GUILD_MEMBER_ADD","GUILD_MEMBER_REMOVE","GUILD_MEMBER_UPDATE","GUILD_MEMBERS_CHUNK","GUILD_INTEGRATIONS_UPDATE","GUILD_ROLE_CREATE","GUILD_ROLE_DELETE","GUILD_ROLE_UPDATE","GUILD_BAN_ADD","GUILD_BAN_REMOVE","GUILD_EMOJIS_UPDATE","CHANNEL_CREATE","CHANNEL_DELETE","CHANNEL_UPDATE","CHANNEL_PINS_UPDATE","MESSAGE_CREATE","MESSAGE_DELETE","MESSAGE_UPDATE","MESSAGE_DELETE_BULK","MESSAGE_REACTION_ADD","MESSAGE_REACTION_REMOVE","MESSAGE_REACTION_REMOVE_ALL","MESSAGE_REACTION_REMOVE_EMOJI","USER_UPDATE","PRESENCE_UPDATE","TYPING_START","VOICE_STATE_UPDATE","VOICE_SERVER_UPDATE","WEBHOOKS_UPDATE"]),t.MessageTypes=["DEFAULT","RECIPIENT_ADD","RECIPIENT_REMOVE","CALL","CHANNEL_NAME_CHANGE","CHANNEL_ICON_CHANGE","PINS_ADD","GUILD_MEMBER_JOIN","USER_PREMIUM_GUILD_SUBSCRIPTION","USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1","USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2","USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3","CHANNEL_FOLLOW_ADD",null,"GUILD_DISCOVERY_DISQUALIFIED","GUILD_DISCOVERY_REQUALIFIED"],t.ActivityTypes=["PLAYING","STREAMING","LISTENING","WATCHING","CUSTOM_STATUS","COMPETING"],t.ChannelTypes={TEXT:0,DM:1,VOICE:2,GROUP:3,CATEGORY:4,NEWS:5,STORE:6},t.ClientApplicationAssetTypes={SMALL:1,BIG:2},t.Colors={DEFAULT:0,WHITE:16777215,AQUA:1752220,GREEN:3066993,BLUE:3447003,YELLOW:16776960,PURPLE:10181046,LUMINOUS_VIVID_PINK:15277667,GOLD:15844367,ORANGE:15105570,RED:15158332,GREY:9807270,NAVY:3426654,DARK_AQUA:1146986,DARK_GREEN:2067276,DARK_BLUE:2123412,DARK_PURPLE:7419530,DARK_VIVID_PINK:11342935,DARK_GOLD:12745742,DARK_ORANGE:11027200,DARK_RED:10038562,DARK_GREY:9936031,DARKER_GREY:8359053,LIGHT_GREY:12370112,DARK_NAVY:2899536,BLURPLE:7506394,GREYPLE:10070709,DARK_BUT_NOT_BLACK:2895667,NOT_QUITE_BLACK:2303786},t.ExplicitContentFilterLevels=["DISABLED","MEMBERS_WITHOUT_ROLES","ALL_MEMBERS"],t.VerificationLevels=["NONE","LOW","MEDIUM","HIGH","VERY_HIGH"],t.APIErrors={UNKNOWN_ACCOUNT:10001,UNKNOWN_APPLICATION:10002,UNKNOWN_CHANNEL:10003,UNKNOWN_GUILD:10004,UNKNOWN_INTEGRATION:10005,UNKNOWN_INVITE:10006,UNKNOWN_MEMBER:10007,UNKNOWN_MESSAGE:10008,UNKNOWN_OVERWRITE:10009,UNKNOWN_PROVIDER:10010,UNKNOWN_ROLE:10011,UNKNOWN_TOKEN:10012,UNKNOWN_USER:10013,UNKNOWN_EMOJI:10014,UNKNOWN_WEBHOOK:10015,UNKNOWN_BAN:10026,UNKNOWN_GUILD_TEMPLATE:10057,BOT_PROHIBITED_ENDPOINT:20001,BOT_ONLY_ENDPOINT:20002,CHANNEL_HIT_WRITE_RATELIMIT:20028,MAXIMUM_GUILDS:30001,MAXIMUM_FRIENDS:30002,MAXIMUM_PINS:30003,MAXIMUM_ROLES:30005,MAXIMUM_WEBHOOKS:30007,MAXIMUM_REACTIONS:30010,MAXIMUM_CHANNELS:30013,MAXIMUM_ATTACHMENTS:30015,MAXIMUM_INVITES:30016,GUILD_ALREADY_HAS_TEMPLATE:30031,UNAUTHORIZED:40001,ACCOUNT_VERIFICATION_REQUIRED:40002,REQUEST_ENTITY_TOO_LARGE:40005,FEATURE_TEMPORARILY_DISABLED:40006,USER_BANNED:40007,ALREADY_CROSSPOSTED:40033,MISSING_ACCESS:50001,INVALID_ACCOUNT_TYPE:50002,CANNOT_EXECUTE_ON_DM:50003,EMBED_DISABLED:50004,CANNOT_EDIT_MESSAGE_BY_OTHER:50005,CANNOT_SEND_EMPTY_MESSAGE:50006,CANNOT_MESSAGE_USER:50007,CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL:50008,CHANNEL_VERIFICATION_LEVEL_TOO_HIGH:50009,OAUTH2_APPLICATION_BOT_ABSENT:50010,MAXIMUM_OAUTH2_APPLICATIONS:50011,INVALID_OAUTH_STATE:50012,MISSING_PERMISSIONS:50013,INVALID_AUTHENTICATION_TOKEN:50014,NOTE_TOO_LONG:50015,INVALID_BULK_DELETE_QUANTITY:50016,CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL:50019,INVALID_OR_TAKEN_INVITE_CODE:50020,CANNOT_EXECUTE_ON_SYSTEM_MESSAGE:50021,INVALID_OAUTH_TOKEN:50025,BULK_DELETE_MESSAGE_TOO_OLD:50034,INVALID_FORM_BODY:50035,INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT:50036,INVALID_API_VERSION:50041,CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL:50074,REACTION_BLOCKED:90001,RESOURCE_OVERLOADED:13e4},t.DefaultMessageNotifications=["ALL","MENTIONS"],t.MembershipStates=[null,"INVITED","ACCEPTED"],t.WebhookTypes=[null,"Incoming","Channel Follower"]}).call(this,i(15))},function(e,t,i){"use strict";const{PartialTypes:s}=i(0);e.exports=class GenericAction{constructor(e){this.client=e}handle(e){return e}getPayload(e,t,i,s,n){const r=t.cache.get(i);return!r&&this.client.options.partials.includes(s)?t.add(e,n):r}getChannel(e){const t=e.channel_id||e.id;return e.channel||this.getPayload({id:t,guild_id:e.guild_id,recipients:[e.author||{id:e.user_id}]},this.client.channels,t,s.CHANNEL)}getMessage(e,t,i){const n=e.message_id||e.id;return e.message||this.getPayload({id:n,channel_id:t.id,guild_id:e.guild_id||(t.guild?t.guild.id:null)},t.messages,n,s.MESSAGE,i)}getReaction(e,t,i){const n=e.emoji.id||decodeURIComponent(e.emoji.name);return this.getPayload({emoji:e.emoji,count:t.partial?null:0,me:!!i&&i.id===this.client.user.id},t.reactions,n,s.REACTION)}getMember(e,t){return this.getPayload(e,t.members,e.user.id,s.GUILD_MEMBER)}getUser(e){const t=e.user_id;return e.user||this.getPayload({id:t},this.client.users,t,s.USER)}getUserFromMember(e){if(e.guild_id&&e.member&&e.member.user){const t=this.client.guilds.cache.get(e.guild_id);return t?t.members.add(e.member).user:this.client.users.add(e.member.user)}return this.getUser(e)}}},function(e,t,i){"use strict";e.exports=i(62),e.exports.Messages=i(105)},function(e,t,i){"use strict";const s=i(106),n=i(4);e.exports=class Collection extends s{toJSON(){return this.map((e=>"function"==typeof e.toJSON?e.toJSON():n.flatten(e)))}}},function(e,t,i){"use strict";(function(t){const{parse:s}=i(35),n=i(36),{Colors:r,DefaultOptions:o,Endpoints:a}=i(0),{Error:c,RangeError:l,TypeError:h}=i(2),isObject=e=>"object"==typeof e&&null!==e;class Util{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static flatten(e,...t){if(!isObject(e))return e;const s=Object.keys(e).filter((e=>!e.startsWith("_"))).map((e=>({[e]:!0})));t=s.length?Object.assign(...s,...t):Object.assign({},...t);const n={};for(let[s,r]of Object.entries(t)){if(!r)continue;r=!0===r?s:r;const t=e[s],o=isObject(t),a=o&&"function"==typeof t.valueOf?t.valueOf():null;t instanceof i(3)?n[r]=Array.from(t.keys()):a instanceof i(3)?n[r]=Array.from(a.keys()):Array.isArray(t)?n[r]=t.map((e=>Util.flatten(e))):"object"!=typeof a?n[r]=a:o||(n[r]=t)}return n}static splitMessage(e,{maxLength:t=2e3,char:i="\n",prepend:s="",append:n=""}={}){if((e=Util.resolveString(e)).length<=t)return[e];const r=e.split(i);if(r.some((e=>e.length>t)))throw new l("SPLIT_MAX_LEN");const o=[];let a="";for(const e of r)a&&(a+i+e+n).length>t&&(o.push(a+n),a=s),a+=(a&&a!==s?i:"")+e;return o.concat(a).filter((e=>e))}static escapeMarkdown(e,{codeBlock:t=!0,inlineCode:i=!0,bold:s=!0,italic:n=!0,underline:r=!0,strikethrough:o=!0,spoiler:a=!0,codeBlockContent:c=!0,inlineCodeContent:l=!0}={}){return c?l?(i&&(e=Util.escapeInlineCode(e)),t&&(e=Util.escapeCodeBlock(e)),n&&(e=Util.escapeItalic(e)),s&&(e=Util.escapeBold(e)),r&&(e=Util.escapeUnderline(e)),o&&(e=Util.escapeStrikethrough(e)),a&&(e=Util.escapeSpoiler(e)),e):e.split(/(?<=^|[^`])`(?=[^`]|$)/g).map(((e,i,c)=>i%2&&i!==c.length-1?e:Util.escapeMarkdown(e,{codeBlock:t,bold:s,italic:n,underline:r,strikethrough:o,spoiler:a}))).join(i?"\\`":"`"):e.split("```").map(((e,t,c)=>t%2&&t!==c.length-1?e:Util.escapeMarkdown(e,{inlineCode:i,bold:s,italic:n,underline:r,strikethrough:o,spoiler:a,inlineCodeContent:l}))).join(t?"\\`\\`\\`":"```")}static escapeCodeBlock(e){return e.replace(/```/g,"\\`\\`\\`")}static escapeInlineCode(e){return e.replace(/(?<=^|[^`])`(?=[^`]|$)/g,"\\`")}static escapeItalic(e){let t=0;return e=e.replace(/(?<=^|[^*])\*([^*]|\*\*|$)/g,((e,i)=>"**"===i?++t%2?"\\*"+i:i+"\\*":"\\*"+i)),t=0,e.replace(/(?<=^|[^_])_([^_]|__|$)/g,((e,i)=>"__"===i?++t%2?"\\_"+i:i+"\\_":"\\_"+i))}static escapeBold(e){let t=0;return e.replace(/\*\*(\*)?/g,((e,i)=>i?++t%2?i+"\\*\\*":"\\*\\*"+i:"\\*\\*"))}static escapeUnderline(e){let t=0;return e.replace(/__(_)?/g,((e,i)=>i?++t%2?i+"\\_\\_":"\\_\\_"+i:"\\_\\_"))}static escapeStrikethrough(e){return e.replace(/~~/g,"\\~\\~")}static escapeSpoiler(e){return e.replace(/\|\|/g,"\\|\\|")}static fetchRecommendedShards(e,t=1e3){if(!e)throw new c("TOKEN_MISSING");return n(`${o.http.api}/v${o.http.version}${a.botGateway}`,{method:"GET",headers:{Authorization:"Bot "+e.replace(/^Bot\s*/i,"")}}).then((e=>{if(e.ok)return e.json();if(401===e.status)throw new c("TOKEN_INVALID");throw e})).then((e=>e.shards*(1e3/t)))}static parseEmoji(e){if(e.includes("%")&&(e=decodeURIComponent(e)),!e.includes(":"))return{animated:!1,name:e,id:null};const t=e.match(/?/);return t?{animated:Boolean(t[1]),name:t[2],id:t[3]||null}:null}static cloneObject(e){return Object.assign(Object.create(e),e)}static mergeDefault(e,t){if(!t)return e;for(const n in e)i=t,s=n,Object.prototype.hasOwnProperty.call(i,s)&&void 0!==t[n]?t[n]===Object(t[n])&&(t[n]=Util.mergeDefault(e[n],t[n])):t[n]=e[n];var i,s;return t}static convertToBuffer(e){return"string"==typeof e&&(e=Util.str2ab(e)),t.from(e)}static str2ab(e){const t=new ArrayBuffer(2*e.length),i=new Uint16Array(t);for(var s=0,n=e.length;s-1&&i16777215)throw new l("COLOR_RANGE");if(e&&isNaN(e))throw new h("COLOR_CONVERT");return e}static discordSort(e){return e.sorted(((e,t)=>e.rawPosition-t.rawPosition||parseInt(t.id.slice(0,-10))-parseInt(e.id.slice(0,-10))||parseInt(t.id.slice(10))-parseInt(e.id.slice(10))))}static setPosition(e,t,i,s,n,r){let o=s.array();return Util.moveElementInArray(o,e,t,i),o=o.map(((e,t)=>({id:e.id,position:t}))),n.patch({data:o,reason:r}).then((()=>o))}static basename(e,t){let i=s(e);return t&&i.ext.startsWith(t)?i.name:i.base.split("?")[0]}static idToBinary(e){let t="",i=parseInt(e.slice(0,-10))||0,s=parseInt(e.slice(-10));for(;s>0||i>0;)t=String(1&s)+t,s=Math.floor(s/2),i>0&&(s+=i%2*5e9,i=Math.floor(i/2));return t}static binaryToID(e){let t="";for(;e.length>50;){const i=parseInt(e.slice(0,-32),2),s=parseInt((i%10).toString(2)+e.slice(-32),2);t=(s%10).toString()+t,e=Math.floor(i/10).toString(2)+Math.floor(s/10).toString(2).padStart(32,"0")}for(e=parseInt(e,2);e>0;)t=(e%10).toString()+t,e=Math.floor(e/10);return t}static removeMentions(e){return e.replace(/@/g,"@​")}static cleanContent(e,t){return e=e.replace(/<@!?[0-9]+>/g,(e=>{const i=e.replace(/<|!|>|@/g,"");if("dm"===t.channel.type){const s=t.client.users.cache.get(i);return s?Util.removeMentions("@"+s.username):e}const s=t.channel.guild.members.cache.get(i);if(s)return Util.removeMentions("@"+s.displayName);{const s=t.client.users.cache.get(i);return s?Util.removeMentions("@"+s.username):e}})).replace(/<#[0-9]+>/g,(e=>{const i=t.client.channels.cache.get(e.replace(/<|#|>/g,""));return i?"#"+i.name:e})).replace(/<@&[0-9]+>/g,(e=>{if("dm"===t.channel.type)return e;const i=t.guild.roles.cache.get(e.replace(/<|@|>|&/g,""));return i?"@"+i.name:e})),"everyone"===t.client.options.disableMentions&&(e=e.replace(/@([^<>@ ]*)/gmus,((e,t)=>t.match(/^[&!]?\d+$/)?"@"+t:"@​"+t))),"all"===t.client.options.disableMentions?Util.removeMentions(e):e}static cleanCodeBlockContent(e){return e.replace(/```/g,"`​``")}static delayFor(e){return new Promise((t=>{setTimeout(t,e)}))}}e.exports=Util}).call(this,i(14).Buffer)},function(e,t,i){"use strict";const s=i(4);e.exports=class Base{constructor(e){Object.defineProperty(this,"client",{value:e})}_clone(){return Object.assign(Object.create(this),this)}_patch(e){return e}_update(e){const t=this._clone();return this._patch(e),t}toJSON(...e){return s.flatten(this,...e)}valueOf(){return this.id}}},function(e,t,i){"use strict";const s=i(4),n=14200704e5;let r=0;e.exports=class SnowflakeUtil{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static generate(e=Date.now()){if(e instanceof Date&&(e=e.getTime()),"number"!=typeof e||isNaN(e))throw new TypeError(`"timestamp" argument must be a number (received ${isNaN(e)?"NaN":typeof e})`);r>=4095&&(r=0);const t=`${(e-n).toString(2).padStart(42,"0")}0000100000${(r++).toString(2).padStart(12,"0")}`;return s.binaryToID(t)}static deconstruct(e){const t=s.idToBinary(e).toString(2).padStart(64,"0"),i={timestamp:parseInt(t.substring(0,42),2)+n,workerID:parseInt(t.substring(42,47),2),processID:parseInt(t.substring(47,52),2),increment:parseInt(t.substring(52,64),2),binary:t};return Object.defineProperty(i,"date",{get:function get(){return new Date(this.timestamp)},enumerable:!0}),i}static get EPOCH(){return n}}},function(e,t,i){"use strict";const s=i(3);let n;e.exports=class BaseManager{constructor(e,t,r,o=s,...a){if(n||(n=i(10)),Object.defineProperty(this,"holds",{value:n.get(r.name)||r}),Object.defineProperty(this,"client",{value:e}),this.cacheType=o,this.cache=new o(...a),t)for(const e of t)this.add(e)}add(e,t=!0,{id:i,extras:s=[]}={}){const n=this.cache.get(i||e.id);if(n&&n._patch&&t&&n._patch(e),n)return n;const r=this.holds?new this.holds(this.client,e,...s):e;return t&&this.cache.set(i||r.id,r),r}resolve(e){return e instanceof this.holds?e:"string"==typeof e&&this.cache.get(e)||null}resolveID(e){return e instanceof this.holds?e.id:"string"==typeof e?e:null}valueOf(){return this.cache}}},function(e,t,i){"use strict";const s=i(12);class Permissions extends s{any(e,t=!0){return t&&super.has(this.constructor.FLAGS.ADMINISTRATOR)||super.any(e)}has(e,t=!0){return t&&super.has(this.constructor.FLAGS.ADMINISTRATOR)||super.has(e)}}Permissions.FLAGS={CREATE_INSTANT_INVITE:1,KICK_MEMBERS:2,BAN_MEMBERS:4,ADMINISTRATOR:8,MANAGE_CHANNELS:16,MANAGE_GUILD:32,ADD_REACTIONS:64,VIEW_AUDIT_LOG:128,PRIORITY_SPEAKER:256,STREAM:512,VIEW_CHANNEL:1024,SEND_MESSAGES:2048,SEND_TTS_MESSAGES:4096,MANAGE_MESSAGES:8192,EMBED_LINKS:16384,ATTACH_FILES:32768,READ_MESSAGE_HISTORY:65536,MENTION_EVERYONE:1<<17,USE_EXTERNAL_EMOJIS:1<<18,VIEW_GUILD_INSIGHTS:1<<19,CONNECT:1<<20,SPEAK:1<<21,MUTE_MEMBERS:1<<22,DEAFEN_MEMBERS:1<<23,MOVE_MEMBERS:1<<24,USE_VAD:1<<25,CHANGE_NICKNAME:1<<26,MANAGE_NICKNAMES:1<<27,MANAGE_ROLES:1<<28,MANAGE_WEBHOOKS:1<<29,MANAGE_EMOJIS:1<<30},Permissions.ALL=Object.values(Permissions.FLAGS).reduce(((e,t)=>e|t),0),Permissions.DEFAULT=104324673,e.exports=Permissions},function(e,t,i){"use strict";(function(t){const s=i(35),n=i(35),r=i(127),o=i(36),{Error:a,TypeError:c}=i(2),{browser:l}=i(0),h=i(4);class DataResolver{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static resolveCode(e,t){const i=t.exec(e);return i&&i[1]||e}static resolveInviteCode(e){return this.resolveCode(e,/discord(?:(?:app)?\.com\/invite|\.gg(?:\/invite)?)\/([\w-]{2,255})/i)}static resolveGuildTemplateCode(e){return this.resolveCode(e,/discord(?:app)?\.(?:com\/template|new)\/([\w-]{2,255})/i)}static async resolveImage(e){if(!e)return null;if("string"==typeof e&&e.startsWith("data:"))return e;const t=await this.resolveFileAsBuffer(e);return DataResolver.resolveBase64(t)}static resolveBase64(e){return t.isBuffer(e)?"data:image/jpg;base64,"+e.toString("base64"):e}static async resolveFile(e){if(!l&&t.isBuffer(e))return e;if(l&&e instanceof ArrayBuffer)return h.convertToBuffer(e);if(l&&e instanceof Blob)return e;if(e instanceof r.Readable)return e;if("string"==typeof e){if(/^https?:\/\//.test(e)){const t=await o(e);return l?t.blob():t.body}if(!l)return new Promise(((t,i)=>{const r=n.resolve(e);s.stat(r,((e,n)=>e?i(e):n.isFile()?t(s.createReadStream(r)):i(new a("FILE_NOT_FOUND",r))))}))}throw new c("REQ_RESOURCE_TYPE")}static async resolveFileAsBuffer(e){const i=await this.resolveFile(e);if(t.isBuffer(i))return i;const s=[];for await(const e of i)s.push(e);return t.concat(s)}}e.exports=DataResolver}).call(this,i(14).Buffer)},function(e,t,i){"use strict";const s={GuildEmoji:i(25),DMChannel:i(39),TextChannel:i(41),VoiceChannel:i(81),CategoryChannel:i(82),NewsChannel:i(83),StoreChannel:i(84),GuildMember:i(11),Guild:i(54),Message:i(28),MessageReaction:i(52),Presence:i(24).Presence,ClientPresence:i(93),VoiceState:i(94),Role:i(20),User:i(27)};e.exports=class Structures{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static get(e){if("string"==typeof e)return s[e];throw new TypeError(`"structure" argument must be a string (received ${typeof e})`)}static extend(e,t){if(!s[e])throw new RangeError(`"${e}" is not a valid extensible structure.`);if("function"!=typeof t){throw new TypeError(`"extender" argument must be a function that returns the extended structure class/prototype ${`(received ${typeof t})`}.`)}const i=t(s[e]);if("function"!=typeof i){throw new TypeError(`The extender function must return the extended structure class/prototype ${`(received ${typeof i})`}.`)}if(!(i.prototype instanceof s[e])){const t=Object.getPrototypeOf(i),n=`${i.name||"unnamed"}${t.name?" extends "+t.name:""}`;throw new Error(`The class/prototype returned from the extender function must extend the existing structure class/prototype (received function ${n}; expected extension of ${s[e].name}).`)}return s[e]=i,i}}},function(e,t,i){"use strict";const s=i(5),n=i(20),r=i(33),{Error:o}=i(2),a=i(73),c=i(8);let l;class GuildMember extends s{constructor(e,t,i){super(e),this.guild=i,this.joinedTimestamp=null,this.lastMessageID=null,this.lastMessageChannelID=null,this.premiumSinceTimestamp=null,this.deleted=!1,this.nickname=null,this._roles=[],t&&this._patch(t)}_patch(e){"user"in e&&(this.user=this.client.users.add(e.user,!0)),"nick"in e&&(this.nickname=e.nick),"joined_at"in e&&(this.joinedTimestamp=new Date(e.joined_at).getTime()),"premium_since"in e&&(this.premiumSinceTimestamp=new Date(e.premium_since).getTime()),"roles"in e&&(this._roles=e.roles)}_clone(){const e=super._clone();return e._roles=this._roles.slice(),e}get partial(){return!this.joinedTimestamp}get roles(){return new a(this)}get lastMessage(){const e=this.guild.channels.cache.get(this.lastMessageChannelID);return e&&e.messages.cache.get(this.lastMessageID)||null}get voice(){l||(l=i(10));const e=l.get("VoiceState");return this.guild.voiceStates.cache.get(this.id)||new e(this.guild,{user_id:this.id})}get joinedAt(){return this.joinedTimestamp?new Date(this.joinedTimestamp):null}get premiumSince(){return this.premiumSinceTimestamp?new Date(this.premiumSinceTimestamp):null}get presence(){l||(l=i(10));const e=l.get("Presence");return this.guild.presences.cache.get(this.id)||new e(this.client,{user:{id:this.id},guild:this.guild})}get displayColor(){const e=this.roles.color;return e&&e.color||0}get displayHexColor(){const e=this.roles.color;return e&&e.hexColor||"#000000"}get id(){return this.user.id}get displayName(){return this.nickname||this.user.username}get permissions(){return this.user.id===this.guild.ownerID?new c(c.ALL).freeze():new c(this.roles.cache.map((e=>e.permissions))).freeze()}get manageable(){if(this.user.id===this.guild.ownerID)return!1;if(this.user.id===this.client.user.id)return!1;if(this.client.user.id===this.guild.ownerID)return!0;if(!this.guild.me)throw new o("GUILD_UNCACHED_ME");return this.guild.me.roles.highest.comparePositionTo(this.roles.highest)>0}get kickable(){return this.manageable&&this.guild.me.permissions.has(c.FLAGS.KICK_MEMBERS)}get bannable(){return this.manageable&&this.guild.me.permissions.has(c.FLAGS.BAN_MEMBERS)}permissionsIn(e){if(!(e=this.guild.channels.resolve(e)))throw new o("GUILD_CHANNEL_RESOLVE");return e.memberPermissions(this)}hasPermission(e,{checkAdmin:t=!0,checkOwner:i=!0}={}){if(i&&this.user.id===this.guild.ownerID)return!0;return new c(this.roles.cache.map((e=>e.permissions))).has(e,t)}async edit(e,t){if(e.channel){if(e.channel=this.guild.channels.resolve(e.channel),!e.channel||"voice"!==e.channel.type)throw new o("GUILD_VOICE_CHANNEL_RESOLVE");e.channel_id=e.channel.id,e.channel=void 0}else null===e.channel&&(e.channel_id=null,e.channel=void 0);e.roles&&(e.roles=e.roles.map((e=>e instanceof n?e.id:e)));let i=this.client.api.guilds(this.guild.id);if(this.user.id===this.client.user.id){const t=Object.keys(e);i=1===t.length&&"nick"===t[0]?i.members("@me").nick:i.members(this.id)}else i=i.members(this.id);await i.patch({data:e,reason:t});const s=this._clone();return e.user=this.user,s._patch(e),s}setNickname(e,t){return this.edit({nick:e},t)}createDM(){return this.user.createDM()}deleteDM(){return this.user.deleteDM()}kick(e){return this.client.api.guilds(this.guild.id).members(this.user.id).delete({reason:e}).then((()=>this))}ban(e){return this.guild.members.ban(this,e)}fetch(e=!1){return this.guild.members.fetch({user:this.id,cache:!0,force:e})}toString(){return`<@${this.nickname?"!":""}${this.user.id}>`}toJSON(){return super.toJSON({guild:"guildID",user:"userID",displayName:!0,speaking:!1,lastMessage:!1,lastMessageID:!1,roles:!0})}send(){}}r.applyToClass(GuildMember),e.exports=GuildMember},function(e,t,i){"use strict";const{RangeError:s}=i(2);class BitField{constructor(e){this.bitfield=this.constructor.resolve(e)}any(e){return 0!=(this.bitfield&this.constructor.resolve(e))}equals(e){return this.bitfield===this.constructor.resolve(e)}has(e){return Array.isArray(e)?e.every((e=>this.has(e))):(e=this.constructor.resolve(e),(this.bitfield&e)===e)}missing(e,...t){return Array.isArray(e)||(e=new this.constructor(e).toArray(!1)),e.filter((e=>!this.has(e,...t)))}freeze(){return Object.freeze(this)}add(...e){let t=0;for(const i of e)t|=this.constructor.resolve(i);return Object.isFrozen(this)?new this.constructor(this.bitfield|t):(this.bitfield|=t,this)}remove(...e){let t=0;for(const i of e)t|=this.constructor.resolve(i);return Object.isFrozen(this)?new this.constructor(this.bitfield&~t):(this.bitfield&=~t,this)}serialize(...e){const t={};for(const[i,s]of Object.entries(this.constructor.FLAGS))t[i]=this.has(s,...e);return t}toArray(...e){return Object.keys(this.constructor.FLAGS).filter((t=>this.has(t,...e)))}toJSON(){return this.bitfield}valueOf(){return this.bitfield}*[Symbol.iterator](){yield*this.toArray()}static resolve(e=0){if("number"==typeof e&&e>=0)return e;if(e instanceof BitField)return e.bitfield;if(Array.isArray(e))return e.map((e=>this.resolve(e))).reduce(((e,t)=>e|t),0);if("string"==typeof e&&void 0!==this.FLAGS[e])return this.FLAGS[e];const t=new s("BITFIELD_INVALID");throw t.bit=e,t}}BitField.FLAGS={},e.exports=BitField},function(e,t,i){"use strict";const s=i(30),n=i(17),{WebhookTypes:r}=i(0),o=i(9),a=i(6);class Webhook{constructor(e,t){Object.defineProperty(this,"client",{value:e}),t&&this._patch(t)}_patch(e){this.name=e.name,Object.defineProperty(this,"token",{value:e.token||null,writable:!0,configurable:!0}),this.avatar=e.avatar,this.id=e.id,this.type=r[e.type],this.guildID=e.guild_id,this.channelID=e.channel_id,e.user?this.owner=this.client.users?this.client.users.cache.get(e.user.id):e.user:this.owner=null}async send(e,t){let i;if(e instanceof s)i=e.resolveData();else if(i=s.create(this,e,t).resolveData(),Array.isArray(i.data.content))return Promise.all(i.split().map(this.send.bind(this)));const{data:n,files:r}=await i.resolveFiles();return this.client.api.webhooks(this.id,this.token).post({data:n,files:r,query:{wait:!0},auth:!1}).then((e=>{const t=this.client.channels?this.client.channels.cache.get(e.channel_id):void 0;return t?t.messages.add(e,!1):e}))}sendSlackMessage(e){return this.client.api.webhooks(this.id,this.token).slack.post({query:{wait:!0},auth:!1,data:e}).then((e=>"ok"===e.toString()))}async edit({name:e=this.name,avatar:t,channel:i},s){t&&"string"==typeof t&&!t.startsWith("data:")&&(t=await o.resolveImage(t)),i&&(i=i instanceof n?i.id:i);const r=await this.client.api.webhooks(this.id,i?void 0:this.token).patch({data:{name:e,avatar:t,channel_id:i},reason:s});return this.name=r.name,this.avatar=r.avatar,this.channelID=r.channel_id,this}delete(e){return this.client.api.webhooks(this.id,this.token).delete({reason:e})}get createdTimestamp(){return a.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get url(){return this.client.options.http.api+this.client.api.webhooks(this.id,this.token)}avatarURL({format:e,size:t}={}){return this.avatar?this.client.rest.cdn.Avatar(this.id,this.avatar,e,t):null}static applyToClass(e){for(const t of["send","sendSlackMessage","edit","delete","createdTimestamp","createdAt","url"])Object.defineProperty(e.prototype,t,Object.getOwnPropertyDescriptor(Webhook.prototype,t))}}e.exports=Webhook},function(e,t,i){"use strict";(function(e){var s=i(103),n=i(104),r=i(60);function kMaxLength(){return Buffer.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function createBuffer(e,t){if(kMaxLength()=kMaxLength())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+kMaxLength().toString(16)+" bytes");return 0|e}function byteLength(e,t){if(Buffer.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var i=e.length;if(0===i)return 0;for(var s=!1;;)switch(t){case"ascii":case"latin1":case"binary":return i;case"utf8":case"utf-8":case void 0:return utf8ToBytes(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*i;case"hex":return i>>>1;case"base64":return base64ToBytes(e).length;default:if(s)return utf8ToBytes(e).length;t=(""+t).toLowerCase(),s=!0}}function slowToString(e,t,i){var s=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===i||i>this.length)&&(i=this.length),i<=0)return"";if((i>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return hexSlice(this,t,i);case"utf8":case"utf-8":return utf8Slice(this,t,i);case"ascii":return asciiSlice(this,t,i);case"latin1":case"binary":return latin1Slice(this,t,i);case"base64":return base64Slice(this,t,i);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return utf16leSlice(this,t,i);default:if(s)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),s=!0}}function swap(e,t,i){var s=e[t];e[t]=e[i],e[i]=s}function bidirectionalIndexOf(e,t,i,s,n){if(0===e.length)return-1;if("string"==typeof i?(s=i,i=0):i>2147483647?i=2147483647:i<-2147483648&&(i=-2147483648),i=+i,isNaN(i)&&(i=n?0:e.length-1),i<0&&(i=e.length+i),i>=e.length){if(n)return-1;i=e.length-1}else if(i<0){if(!n)return-1;i=0}if("string"==typeof t&&(t=Buffer.from(t,s)),Buffer.isBuffer(t))return 0===t.length?-1:arrayIndexOf(e,t,i,s,n);if("number"==typeof t)return t&=255,Buffer.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?n?Uint8Array.prototype.indexOf.call(e,t,i):Uint8Array.prototype.lastIndexOf.call(e,t,i):arrayIndexOf(e,[t],i,s,n);throw new TypeError("val must be string, number or Buffer")}function arrayIndexOf(e,t,i,s,n){var r,o=1,a=e.length,c=t.length;if(void 0!==s&&("ucs2"===(s=String(s).toLowerCase())||"ucs-2"===s||"utf16le"===s||"utf-16le"===s)){if(e.length<2||t.length<2)return-1;o=2,a/=2,c/=2,i/=2}function read(e,t){return 1===o?e[t]:e.readUInt16BE(t*o)}if(n){var l=-1;for(r=i;ra&&(i=a-c),r=i;r>=0;r--){for(var h=!0,u=0;un&&(s=n):s=n;var r=t.length;if(r%2!=0)throw new TypeError("Invalid hex string");s>r/2&&(s=r/2);for(var o=0;o>8,n=i%256,r.push(n),r.push(s);return r}(t,e.length-i),e,i,s)}function base64Slice(e,t,i){return 0===t&&i===e.length?s.fromByteArray(e):s.fromByteArray(e.slice(t,i))}function utf8Slice(e,t,i){i=Math.min(e.length,i);for(var s=[],n=t;n239?4:h>223?3:h>191?2:1;if(n+d<=i)switch(d){case 1:h<128&&(u=h);break;case 2:128==(192&(r=e[n+1]))&&(l=(31&h)<<6|63&r)>127&&(u=l);break;case 3:r=e[n+1],a=e[n+2],128==(192&r)&&128==(192&a)&&(l=(15&h)<<12|(63&r)<<6|63&a)>2047&&(l<55296||l>57343)&&(u=l);break;case 4:r=e[n+1],a=e[n+2],c=e[n+3],128==(192&r)&&128==(192&a)&&128==(192&c)&&(l=(15&h)<<18|(63&r)<<12|(63&a)<<6|63&c)>65535&&l<1114112&&(u=l)}null===u?(u=65533,d=1):u>65535&&(u-=65536,s.push(u>>>10&1023|55296),u=56320|1023&u),s.push(u),n+=d}return function decodeCodePointsArray(e){var t=e.length;if(t<=o)return String.fromCharCode.apply(String,e);var i="",s=0;for(;s0&&(e=this.toString("hex",0,i).match(/.{2}/g).join(" "),this.length>i&&(e+=" ... ")),""},Buffer.prototype.compare=function compare(e,t,i,s,n){if(!Buffer.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===i&&(i=e?e.length:0),void 0===s&&(s=0),void 0===n&&(n=this.length),t<0||i>e.length||s<0||n>this.length)throw new RangeError("out of range index");if(s>=n&&t>=i)return 0;if(s>=n)return-1;if(t>=i)return 1;if(this===e)return 0;for(var r=(n>>>=0)-(s>>>=0),o=(i>>>=0)-(t>>>=0),a=Math.min(r,o),c=this.slice(s,n),l=e.slice(t,i),h=0;hn)&&(i=n),e.length>0&&(i<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");s||(s="utf8");for(var r=!1;;)switch(s){case"hex":return hexWrite(this,e,t,i);case"utf8":case"utf-8":return utf8Write(this,e,t,i);case"ascii":return asciiWrite(this,e,t,i);case"latin1":case"binary":return latin1Write(this,e,t,i);case"base64":return base64Write(this,e,t,i);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return ucs2Write(this,e,t,i);default:if(r)throw new TypeError("Unknown encoding: "+s);s=(""+s).toLowerCase(),r=!0}},Buffer.prototype.toJSON=function toJSON(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var o=4096;function asciiSlice(e,t,i){var s="";i=Math.min(e.length,i);for(var n=t;ns)&&(i=s);for(var n="",r=t;ri)throw new RangeError("Trying to access beyond buffer length")}function checkInt(e,t,i,s,n,r){if(!Buffer.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>n||te.length)throw new RangeError("Index out of range")}function objectWriteUInt16(e,t,i,s){t<0&&(t=65535+t+1);for(var n=0,r=Math.min(e.length-i,2);n>>8*(s?n:1-n)}function objectWriteUInt32(e,t,i,s){t<0&&(t=4294967295+t+1);for(var n=0,r=Math.min(e.length-i,4);n>>8*(s?n:3-n)&255}function checkIEEE754(e,t,i,s,n,r){if(i+s>e.length)throw new RangeError("Index out of range");if(i<0)throw new RangeError("Index out of range")}function writeFloat(e,t,i,s,r){return r||checkIEEE754(e,0,i,4),n.write(e,t,i,s,23,4),i+4}function writeDouble(e,t,i,s,r){return r||checkIEEE754(e,0,i,8),n.write(e,t,i,s,52,8),i+8}Buffer.prototype.slice=function slice(e,t){var i,s=this.length;if((e=~~e)<0?(e+=s)<0&&(e=0):e>s&&(e=s),(t=void 0===t?s:~~t)<0?(t+=s)<0&&(t=0):t>s&&(t=s),t0&&(n*=256);)s+=this[e+--t]*n;return s},Buffer.prototype.readUInt8=function readUInt8(e,t){return t||checkOffset(e,1,this.length),this[e]},Buffer.prototype.readUInt16LE=function readUInt16LE(e,t){return t||checkOffset(e,2,this.length),this[e]|this[e+1]<<8},Buffer.prototype.readUInt16BE=function readUInt16BE(e,t){return t||checkOffset(e,2,this.length),this[e]<<8|this[e+1]},Buffer.prototype.readUInt32LE=function readUInt32LE(e,t){return t||checkOffset(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},Buffer.prototype.readUInt32BE=function readUInt32BE(e,t){return t||checkOffset(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},Buffer.prototype.readIntLE=function readIntLE(e,t,i){e|=0,t|=0,i||checkOffset(e,t,this.length);for(var s=this[e],n=1,r=0;++r=(n*=128)&&(s-=Math.pow(2,8*t)),s},Buffer.prototype.readIntBE=function readIntBE(e,t,i){e|=0,t|=0,i||checkOffset(e,t,this.length);for(var s=t,n=1,r=this[e+--s];s>0&&(n*=256);)r+=this[e+--s]*n;return r>=(n*=128)&&(r-=Math.pow(2,8*t)),r},Buffer.prototype.readInt8=function readInt8(e,t){return t||checkOffset(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},Buffer.prototype.readInt16LE=function readInt16LE(e,t){t||checkOffset(e,2,this.length);var i=this[e]|this[e+1]<<8;return 32768&i?4294901760|i:i},Buffer.prototype.readInt16BE=function readInt16BE(e,t){t||checkOffset(e,2,this.length);var i=this[e+1]|this[e]<<8;return 32768&i?4294901760|i:i},Buffer.prototype.readInt32LE=function readInt32LE(e,t){return t||checkOffset(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},Buffer.prototype.readInt32BE=function readInt32BE(e,t){return t||checkOffset(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},Buffer.prototype.readFloatLE=function readFloatLE(e,t){return t||checkOffset(e,4,this.length),n.read(this,e,!0,23,4)},Buffer.prototype.readFloatBE=function readFloatBE(e,t){return t||checkOffset(e,4,this.length),n.read(this,e,!1,23,4)},Buffer.prototype.readDoubleLE=function readDoubleLE(e,t){return t||checkOffset(e,8,this.length),n.read(this,e,!0,52,8)},Buffer.prototype.readDoubleBE=function readDoubleBE(e,t){return t||checkOffset(e,8,this.length),n.read(this,e,!1,52,8)},Buffer.prototype.writeUIntLE=function writeUIntLE(e,t,i,s){(e=+e,t|=0,i|=0,s)||checkInt(this,e,t,i,Math.pow(2,8*i)-1,0);var n=1,r=0;for(this[t]=255&e;++r=0&&(r*=256);)this[t+n]=e/r&255;return t+i},Buffer.prototype.writeUInt8=function writeUInt8(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,1,255,0),Buffer.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},Buffer.prototype.writeUInt16LE=function writeUInt16LE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,2,65535,0),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):objectWriteUInt16(this,e,t,!0),t+2},Buffer.prototype.writeUInt16BE=function writeUInt16BE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,2,65535,0),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):objectWriteUInt16(this,e,t,!1),t+2},Buffer.prototype.writeUInt32LE=function writeUInt32LE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,4,4294967295,0),Buffer.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):objectWriteUInt32(this,e,t,!0),t+4},Buffer.prototype.writeUInt32BE=function writeUInt32BE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,4,4294967295,0),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):objectWriteUInt32(this,e,t,!1),t+4},Buffer.prototype.writeIntLE=function writeIntLE(e,t,i,s){if(e=+e,t|=0,!s){var n=Math.pow(2,8*i-1);checkInt(this,e,t,i,n-1,-n)}var r=0,o=1,a=0;for(this[t]=255&e;++r>0)-a&255;return t+i},Buffer.prototype.writeIntBE=function writeIntBE(e,t,i,s){if(e=+e,t|=0,!s){var n=Math.pow(2,8*i-1);checkInt(this,e,t,i,n-1,-n)}var r=i-1,o=1,a=0;for(this[t+r]=255&e;--r>=0&&(o*=256);)e<0&&0===a&&0!==this[t+r+1]&&(a=1),this[t+r]=(e/o>>0)-a&255;return t+i},Buffer.prototype.writeInt8=function writeInt8(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,1,127,-128),Buffer.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},Buffer.prototype.writeInt16LE=function writeInt16LE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,2,32767,-32768),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):objectWriteUInt16(this,e,t,!0),t+2},Buffer.prototype.writeInt16BE=function writeInt16BE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,2,32767,-32768),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):objectWriteUInt16(this,e,t,!1),t+2},Buffer.prototype.writeInt32LE=function writeInt32LE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,4,2147483647,-2147483648),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):objectWriteUInt32(this,e,t,!0),t+4},Buffer.prototype.writeInt32BE=function writeInt32BE(e,t,i){return e=+e,t|=0,i||checkInt(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),Buffer.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):objectWriteUInt32(this,e,t,!1),t+4},Buffer.prototype.writeFloatLE=function writeFloatLE(e,t,i){return writeFloat(this,e,t,!0,i)},Buffer.prototype.writeFloatBE=function writeFloatBE(e,t,i){return writeFloat(this,e,t,!1,i)},Buffer.prototype.writeDoubleLE=function writeDoubleLE(e,t,i){return writeDouble(this,e,t,!0,i)},Buffer.prototype.writeDoubleBE=function writeDoubleBE(e,t,i){return writeDouble(this,e,t,!1,i)},Buffer.prototype.copy=function copy(e,t,i,s){if(i||(i=0),s||0===s||(s=this.length),t>=e.length&&(t=e.length),t||(t=0),s>0&&s=this.length)throw new RangeError("sourceStart out of bounds");if(s<0)throw new RangeError("sourceEnd out of bounds");s>this.length&&(s=this.length),e.length-t=0;--n)e[n+t]=this[n+i];else if(r<1e3||!Buffer.TYPED_ARRAY_SUPPORT)for(n=0;n>>=0,i=void 0===i?this.length:i>>>0,e||(e=0),"number"==typeof e)for(r=t;r55295&&i<57344){if(!n){if(i>56319){(t-=3)>-1&&r.push(239,191,189);continue}if(o+1===s){(t-=3)>-1&&r.push(239,191,189);continue}n=i;continue}if(i<56320){(t-=3)>-1&&r.push(239,191,189),n=i;continue}i=65536+(n-55296<<10|i-56320)}else n&&(t-=3)>-1&&r.push(239,191,189);if(n=null,i<128){if((t-=1)<0)break;r.push(i)}else if(i<2048){if((t-=2)<0)break;r.push(i>>6|192,63&i|128)}else if(i<65536){if((t-=3)<0)break;r.push(i>>12|224,i>>6&63|128,63&i|128)}else{if(!(i<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;r.push(i>>18|240,i>>12&63|128,i>>6&63|128,63&i|128)}}return r}function base64ToBytes(e){return s.toByteArray(function base64clean(e){if((e=function stringtrim(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(a,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function blitBuffer(e,t,i,s){for(var n=0;n=t.length||n>=e.length);++n)t[n+i]=e[n];return n}}).call(this,i(22))},function(e,t){var i,s,n=e.exports={};function defaultSetTimout(){throw new Error("setTimeout has not been defined")}function defaultClearTimeout(){throw new Error("clearTimeout has not been defined")}function runTimeout(e){if(i===setTimeout)return setTimeout(e,0);if((i===defaultSetTimout||!i)&&setTimeout)return i=setTimeout,setTimeout(e,0);try{return i(e,0)}catch(t){try{return i.call(null,e,0)}catch(t){return i.call(this,e,0)}}}!function(){try{i="function"==typeof setTimeout?setTimeout:defaultSetTimout}catch(e){i=defaultSetTimout}try{s="function"==typeof clearTimeout?clearTimeout:defaultClearTimeout}catch(e){s=defaultClearTimeout}}();var r,o=[],a=!1,c=-1;function cleanUpNextTick(){a&&r&&(a=!1,r.length?o=r.concat(o):c=-1,o.length&&drainQueue())}function drainQueue(){if(!a){var e=runTimeout(cleanUpNextTick);a=!0;for(var t=o.length;t;){for(r=o,o=[];++c1)for(var i=1;i0&&o.length>n&&!o.warned){o.warned=!0;var a=new Error("Possible EventEmitter memory leak detected. "+o.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");a.name="MaxListenersExceededWarning",a.emitter=e,a.type=t,a.count=o.length,function ProcessEmitWarning(e){console&&console.warn&&console.warn(e)}(a)}return e}function onceWrapper(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function _onceWrap(e,t,i){var s={fired:!1,wrapFn:void 0,target:e,type:t,listener:i},n=onceWrapper.bind(s);return n.listener=i,s.wrapFn=n,n}function _listeners(e,t,i){var s=e._events;if(void 0===s)return[];var n=s[t];return void 0===n?[]:"function"==typeof n?i?[n.listener||n]:[n]:i?function unwrapListeners(e){for(var t=new Array(e.length),i=0;i0&&(o=t[0]),o instanceof Error)throw o;var a=new Error("Unhandled error."+(o?" ("+o.message+")":""));throw a.context=o,a}var c=n[e];if(void 0===c)return!1;if("function"==typeof c)r(c,this,t);else{var l=c.length,h=arrayClone(c,l);for(i=0;i=0;r--)if(i[r]===t||i[r].listener===t){o=i[r].listener,n=r;break}if(n<0)return this;0===n?i.shift():function spliceOne(e,t){for(;t+1=0;s--)this.removeListener(e,t[s]);return this},EventEmitter.prototype.listeners=function listeners(e){return _listeners(this,e,!0)},EventEmitter.prototype.rawListeners=function rawListeners(e){return _listeners(this,e,!1)},EventEmitter.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):listenerCount.call(e,t)},EventEmitter.prototype.listenerCount=listenerCount,EventEmitter.prototype.eventNames=function eventNames(){return this._eventsCount>0?s(this._events):[]}},function(e,t,i){"use strict";const s=i(5),{ChannelTypes:n}=i(0),r=i(6);e.exports=class Channel extends s{constructor(e,t){super(e);const i=Object.keys(n)[t.type];this.type=i?i.toLowerCase():"unknown",this.deleted=!1,t&&this._patch(t)}_patch(e){this.id=e.id}get createdTimestamp(){return r.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}toString(){return`<#${this.id}>`}delete(){return this.client.api.channels(this.id).delete().then((()=>this))}fetch(e=!1){return this.client.channels.fetch(this.id,!0,e)}isText(){return"messages"in this}static create(e,t,s){const r=i(10);let o;if(t.guild_id||s){if(s=s||e.guilds.cache.get(t.guild_id)){switch(t.type){case n.TEXT:o=new(r.get("TextChannel"))(s,t);break;case n.VOICE:o=new(r.get("VoiceChannel"))(s,t);break;case n.CATEGORY:o=new(r.get("CategoryChannel"))(s,t);break;case n.NEWS:o=new(r.get("NewsChannel"))(s,t);break;case n.STORE:o=new(r.get("StoreChannel"))(s,t);break}o&&s.channels.cache.set(o.id,o)}}else if(t.recipients&&t.type!==n.GROUP||t.type===n.DM){o=new(r.get("DMChannel"))(e,t)}else if(t.type===n.GROUP){o=new(i(143))(e,t)}return o}toJSON(...e){return super.toJSON({createdTimestamp:!0},...e)}}},function(e,t,i){"use strict";const s=i(17),n=i(19),r=i(42),o=i(20),{Error:a,TypeError:c}=i(2),l=i(3),h=i(8),u=i(4);e.exports=class GuildChannel extends s{constructor(e,t){super(e.client,t),this.guild=e}_patch(e){if(super._patch(e),this.name=e.name,this.rawPosition=e.position,this.parentID=e.parent_id||null,this.permissionOverwrites=new l,e.permission_overwrites)for(const t of e.permission_overwrites)this.permissionOverwrites.set(t.id,new r(this,t))}get parent(){return this.guild.channels.cache.get(this.parentID)||null}get permissionsLocked(){return this.parent?this.permissionOverwrites.size===this.parent.permissionOverwrites.size&&this.permissionOverwrites.every(((e,t)=>{const i=this.parent.permissionOverwrites.get(t);return void 0!==i&&i.deny.bitfield===e.deny.bitfield&&i.allow.bitfield===e.allow.bitfield})):null}get position(){const e=this.guild._sortedChannels(this);return e.array().indexOf(e.get(this.id))}permissionsFor(e){const t=this.guild.members.resolve(e);if(t)return this.memberPermissions(t);const i=this.guild.roles.resolve(e);return i?this.rolePermissions(i):null}overwritesFor(e,t=!1,i=null){if(t||(e=this.guild.members.resolve(e)),!e)return[];i=i||e.roles.cache;const s=[];let n,r;for(const t of this.permissionOverwrites.values())t.id===this.guild.id?r=t:i.has(t.id)?s.push(t):t.id===e.id&&(n=t);return{everyone:r,roles:s,member:n}}memberPermissions(e){if(e.id===this.guild.ownerID)return new h(h.ALL).freeze();const t=e.roles.cache,i=new h(t.map((e=>e.permissions)));if(i.has(h.FLAGS.ADMINISTRATOR))return new h(h.ALL).freeze();const s=this.overwritesFor(e,!0,t);return i.remove(s.everyone?s.everyone.deny:0).add(s.everyone?s.everyone.allow:0).remove(s.roles.length>0?s.roles.map((e=>e.deny)):0).add(s.roles.length>0?s.roles.map((e=>e.allow)):0).remove(s.member?s.member.deny:0).add(s.member?s.member.allow:0).freeze()}rolePermissions(e){if(e.permissions.has(h.FLAGS.ADMINISTRATOR))return new h(h.ALL).freeze();const t=this.permissionOverwrites.get(this.guild.id),i=this.permissionOverwrites.get(e.id);return e.permissions.remove(t?t.deny:0).add(t?t.allow:0).remove(i?i.deny:0).add(i?i.allow:0).freeze()}overwritePermissions(e,t){return Array.isArray(e)||e instanceof l?this.edit({permissionOverwrites:e,reason:t}).then((()=>this)):Promise.reject(new c("INVALID_TYPE","overwrites","Array or Collection of Permission Overwrites",!0))}updateOverwrite(e,t,i){if(!(e=this.guild.roles.resolve(e)||this.client.users.resolve(e)))return Promise.reject(new c("INVALID_TYPE","parameter","User nor a Role"));const s=this.permissionOverwrites.get(e.id);return s?s.update(t,i).then((()=>this)):this.createOverwrite(e,t,i)}createOverwrite(e,t,i){if(!(e=this.guild.roles.resolve(e)||this.client.users.resolve(e)))return Promise.reject(new c("INVALID_TYPE","parameter","User nor a Role"));const s=e instanceof o?"role":"member",{allow:n,deny:a}=r.resolveOverwriteOptions(t);return this.client.api.channels(this.id).permissions[e.id].put({data:{id:e.id,type:s,allow:n.bitfield,deny:a.bitfield},reason:i}).then((()=>this))}lockPermissions(){if(!this.parent)return Promise.reject(new a("GUILD_CHANNEL_ORPHAN"));const e=this.parent.permissionOverwrites.map((e=>e.toJSON()));return this.edit({permissionOverwrites:e})}get members(){const e=new l;for(const t of this.guild.members.cache.values())this.permissionsFor(t).has("VIEW_CHANNEL",!1)&&e.set(t.id,t);return e}async edit(e,t){let i;if(void 0!==e.position&&await u.setPosition(this,e.position,!1,this.guild._sortedChannels(this),this.client.api.guilds(this.guild.id).channels,t).then((e=>{this.client.actions.GuildChannelsPositionUpdate.handle({guild_id:this.guild.id,channels:e})})),e.permissionOverwrites&&(i=e.permissionOverwrites.map((e=>r.resolve(e,this.guild)))),e.lockPermissions)if(e.parentID){const t=this.guild.channels.resolve(e.parentID);t&&"category"===t.type&&(i=t.permissionOverwrites.map((e=>r.resolve(e,this.guild))))}else this.parent&&(i=this.parent.permissionOverwrites.map((e=>r.resolve(e,this.guild))));const s=await this.client.api.channels(this.id).patch({data:{name:(e.name||this.name).trim(),topic:e.topic,nsfw:e.nsfw,bitrate:e.bitrate||this.bitrate,user_limit:void 0!==e.userLimit?e.userLimit:this.userLimit,parent_id:e.parentID,lock_permissions:e.lockPermissions,rate_limit_per_user:e.rateLimitPerUser,permission_overwrites:i},reason:t}),n=this._clone();return n._patch(s),n}setName(e,t){return this.edit({name:e},t)}setParent(e,{lockPermissions:t=!0,reason:i}={}){return this.edit({parentID:null!==e?e.hasOwnProperty("id")?e.id:e:null,lockPermissions:t},i)}setTopic(e,t){return this.edit({topic:e},t)}setPosition(e,{relative:t,reason:i}={}){return u.setPosition(this,e,t,this.guild._sortedChannels(this),this.client.api.guilds(this.guild.id).channels,i).then((e=>(this.client.actions.GuildChannelsPositionUpdate.handle({guild_id:this.guild.id,channels:e}),this)))}createInvite({temporary:e=!1,maxAge:t=86400,maxUses:i=0,unique:s,reason:r}={}){return this.client.api.channels(this.id).invites.post({data:{temporary:e,max_age:t,max_uses:i,unique:s},reason:r}).then((e=>new n(this.client,e)))}async fetchInvites(){const e=await this.client.api.channels(this.id).invites.get(),t=new l;for(const i of e){const e=new n(this.client,i);t.set(e.code,e)}return t}clone(e={}){return u.mergeDefault({name:this.name,permissionOverwrites:this.permissionOverwrites,topic:this.topic,type:this.type,nsfw:this.nsfw,parent:this.parent,bitrate:this.bitrate,userLimit:this.userLimit,rateLimitPerUser:this.rateLimitPerUser,reason:null},e),this.guild.channels.create(e.name,e)}equals(e){let t=e&&this.id===e.id&&this.type===e.type&&this.topic===e.topic&&this.position===e.position&&this.name===e.name;return t&&(t=this.permissionOverwrites&&e.permissionOverwrites?this.permissionOverwrites.equals(e.permissionOverwrites):!this.permissionOverwrites&&!e.permissionOverwrites),t}get deletable(){return this.permissionsFor(this.client.user).has(h.FLAGS.MANAGE_CHANNELS,!1)}get manageable(){if(this.client.user.id===this.guild.ownerID)return!0;if("voice"===this.type){if(!this.permissionsFor(this.client.user).has(h.FLAGS.CONNECT,!1))return!1}else if(!this.viewable)return!1;return this.permissionsFor(this.client.user).has(h.FLAGS.MANAGE_CHANNELS,!1)}get viewable(){if(this.client.user.id===this.guild.ownerID)return!0;const e=this.permissionsFor(this.client.user);return!!e&&e.has(h.FLAGS.VIEW_CHANNEL,!1)}delete(e){return this.client.api.channels(this.id).delete({reason:e}).then((()=>this))}}},function(e,t,i){"use strict";const s=i(5),{Endpoints:n}=i(0),r=i(8);e.exports=class Invite extends s{constructor(e,t){super(e),this._patch(t)}_patch(e){this.guild=e.guild?this.client.guilds.add(e.guild,!1):null,this.code=e.code,this.presenceCount="approximate_presence_count"in e?e.approximate_presence_count:null,this.memberCount="approximate_member_count"in e?e.approximate_member_count:null,this.temporary="temporary"in e?e.temporary:null,this.maxAge="max_age"in e?e.max_age:null,this.uses="uses"in e?e.uses:null,this.maxUses="max_uses"in e?e.max_uses:null,this.inviter=e.inviter?this.client.users.add(e.inviter):null,this.targetUser=e.target_user?this.client.users.add(e.target_user):null,this.targetUserType="number"==typeof e.target_user_type?e.target_user_type:null,this.channel=this.client.channels.add(e.channel,this.guild,!1),this.createdTimestamp="created_at"in e?new Date(e.created_at).getTime():null}get createdAt(){return this.createdTimestamp?new Date(this.createdTimestamp):null}get deletable(){const e=this.guild;if(!e||!this.client.guilds.cache.has(e.id))return!1;if(!e.me)throw new Error("GUILD_UNCACHED_ME");return this.channel.permissionsFor(this.client.user).has(r.FLAGS.MANAGE_CHANNELS,!1)||e.me.permissions.has(r.FLAGS.MANAGE_GUILD)}get expiresTimestamp(){return this.createdTimestamp&&this.maxAge?this.createdTimestamp+1e3*this.maxAge:null}get expiresAt(){const{expiresTimestamp:e}=this;return e?new Date(e):null}get url(){return n.invite(this.client.options.http.invite,this.code)}delete(e){return this.client.api.invites[this.code].delete({reason:e}).then((()=>this))}toString(){return this.url}toJSON(){return super.toJSON({url:!0,expiresTimestamp:!0,presenceCount:!1,memberCount:!1,uses:!1,channel:"channelID",inviter:"inviterID",guild:"guildID"})}valueOf(){return this.code}}},function(e,t,i){"use strict";const s=i(5),{Error:n,TypeError:r}=i(2),o=i(8),a=i(6),c=i(4);e.exports=class Role extends s{constructor(e,t,i){super(e),this.guild=i,t&&this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.color=e.color,this.hoist=e.hoist,this.rawPosition=e.position,this.permissions=new o(e.permissions).freeze(),this.managed=e.managed,this.mentionable=e.mentionable,this.deleted=!1}get createdTimestamp(){return a.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get hexColor(){return"#"+this.color.toString(16).padStart(6,"0")}get members(){return this.guild.members.cache.filter((e=>e.roles.cache.has(this.id)))}get editable(){if(this.managed)return!1;const e=this.guild.member(this.client.user);return!!e.permissions.has(o.FLAGS.MANAGE_ROLES)&&e.roles.highest.comparePositionTo(this)>0}get position(){const e=this.guild._sortedRoles();return e.array().indexOf(e.get(this.id))}comparePositionTo(e){if(!(e=this.guild.roles.resolve(e)))throw new r("INVALID_TYPE","role","Role nor a Snowflake");return this.constructor.comparePositions(this,e)}async edit(e,t){return void 0!==e.permissions?e.permissions=o.resolve(e.permissions):e.permissions=this.permissions.bitfield,void 0!==e.position&&await c.setPosition(this,e.position,!1,this.guild._sortedRoles(),this.client.api.guilds(this.guild.id).roles,t).then((e=>{this.client.actions.GuildRolesPositionUpdate.handle({guild_id:this.guild.id,roles:e})})),this.client.api.guilds[this.guild.id].roles[this.id].patch({data:{name:e.name||this.name,color:null!==e.color?c.resolveColor(e.color||this.color):null,hoist:void 0!==e.hoist?e.hoist:this.hoist,permissions:e.permissions,mentionable:void 0!==e.mentionable?e.mentionable:this.mentionable},reason:t}).then((e=>{const t=this._clone();return t._patch(e),t}))}permissionsIn(e){if(!(e=this.guild.channels.resolve(e)))throw new n("GUILD_CHANNEL_RESOLVE");return e.rolePermissions(this)}setName(e,t){return this.edit({name:e},t)}setColor(e,t){return this.edit({color:e},t)}setHoist(e,t){return this.edit({hoist:e},t)}setPermissions(e,t){return this.edit({permissions:e},t)}setMentionable(e,t){return this.edit({mentionable:e},t)}setPosition(e,{relative:t,reason:i}={}){return c.setPosition(this,e,t,this.guild._sortedRoles(),this.client.api.guilds(this.guild.id).roles,i).then((e=>(this.client.actions.GuildRolesPositionUpdate.handle({guild_id:this.guild.id,roles:e}),this)))}delete(e){return this.client.api.guilds[this.guild.id].roles[this.id].delete({reason:e}).then((()=>(this.client.actions.GuildRoleDelete.handle({guild_id:this.guild.id,role_id:this.id}),this)))}equals(e){return e&&this.id===e.id&&this.name===e.name&&this.color===e.color&&this.hoist===e.hoist&&this.position===e.position&&this.permissions.bitfield===e.permissions.bitfield&&this.managed===e.managed}toString(){return this.id===this.guild.id?"@everyone":`<@&${this.id}>`}toJSON(){return super.toJSON({createdTimestamp:!0})}static comparePositions(e,t){return e.position===t.position?t.id-e.id:e.position-t.position}}},function(e,t,i){"use strict";var s=i(31),n=Object.keys||function(e){var t=[];for(var i in e)t.push(i);return t};e.exports=Duplex;var r=Object.create(i(26));r.inherits=i(23);var o=i(67),a=i(46);r.inherits(Duplex,o);for(var c=n(a.prototype),l=0;lnew Activity(this,e))):e.activity||e.game?this.activities=[new Activity(this,e.game||e.activity)]:this.activities=[],this.clientStatus=e.client_status||null,this}_clone(){const e=Object.assign(Object.create(this),this);return this.activities&&(e.activities=this.activities.map((e=>e._clone()))),e}equals(e){return this===e||e&&this.status===e.status&&this.activities.length===e.activities.length&&this.activities.every(((t,i)=>t.equals(e.activities[i])))&&this.clientStatus.web===e.clientStatus.web&&this.clientStatus.mobile===e.clientStatus.mobile&&this.clientStatus.desktop===e.clientStatus.desktop}toJSON(){return o.flatten(this)}},t.Activity=Activity,t.RichPresenceAssets=RichPresenceAssets},function(e,t,i){"use strict";const s=i(40),{Error:n}=i(2),r=i(66),o=i(8);class GuildEmoji extends s{constructor(e,t,i){super(e,t,i),this.author=null}_clone(){const e=super._clone();return e._roles=this._roles.slice(),e}_patch(e){super._patch(e),void 0!==e.user&&(this.author=this.client.users.add(e.user))}get deletable(){if(!this.guild.me)throw new n("GUILD_UNCACHED_ME");return!this.managed&&this.guild.me.hasPermission(o.FLAGS.MANAGE_EMOJIS)}get roles(){return new r(this)}async fetchAuthor(){if(this.managed)throw new n("EMOJI_MANAGED");if(!this.guild.me)throw new n("GUILD_UNCACHED_ME");if(!this.guild.me.permissions.has(o.FLAGS.MANAGE_EMOJIS))throw new n("MISSING_MANAGE_EMOJIS_PERMISSION",this.guild);const e=await this.client.api.guilds(this.guild.id).emojis(this.id).get();return this._patch(e),this.author}edit(e,t){const i=e.roles?e.roles.map((e=>e.id||e)):void 0;return this.client.api.guilds(this.guild.id).emojis(this.id).patch({data:{name:e.name,roles:i},reason:t}).then((e=>{const t=this._clone();return t._patch(e),t}))}setName(e,t){return this.edit({name:e},t)}delete(e){return this.client.api.guilds(this.guild.id).emojis(this.id).delete({reason:e}).then((()=>this))}equals(e){return e instanceof GuildEmoji?e.id===this.id&&e.name===this.name&&e.managed===this.managed&&e.requiresColons===this.requiresColons&&e.roles.cache.size===this.roles.cache.size&&e.roles.cache.every((e=>this.roles.cache.has(e.id))):e.id===this.id&&e.name===this.name&&e.roles.length===this.roles.cache.size&&e.roles.every((e=>this.roles.cache.has(e)))}}e.exports=GuildEmoji},function(e,t,i){(function(e){function objectToString(e){return Object.prototype.toString.call(e)}t.isArray=function isArray(e){return Array.isArray?Array.isArray(e):"[object Array]"===objectToString(e)},t.isBoolean=function isBoolean(e){return"boolean"==typeof e},t.isNull=function isNull(e){return null===e},t.isNullOrUndefined=function isNullOrUndefined(e){return null==e},t.isNumber=function isNumber(e){return"number"==typeof e},t.isString=function isString(e){return"string"==typeof e},t.isSymbol=function isSymbol(e){return"symbol"==typeof e},t.isUndefined=function isUndefined(e){return void 0===e},t.isRegExp=function isRegExp(e){return"[object RegExp]"===objectToString(e)},t.isObject=function isObject(e){return"object"==typeof e&&null!==e},t.isDate=function isDate(e){return"[object Date]"===objectToString(e)},t.isError=function isError(e){return"[object Error]"===objectToString(e)||e instanceof Error},t.isFunction=function isFunction(e){return"function"==typeof e},t.isPrimitive=function isPrimitive(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=e.isBuffer}).call(this,i(14).Buffer)},function(e,t,i){"use strict";const s=i(5),n=i(33),{Error:r}=i(2),o=i(6),a=i(80);let c;class User extends s{constructor(e,t){super(e),this.id=t.id,this.system=null,this.locale=null,this.flags=null,this._patch(t)}_patch(e){"username"in e?this.username=e.username:"string"!=typeof this.username&&(this.username=null),("bot"in e||"boolean"!=typeof this.bot)&&(this.bot=Boolean(e.bot)),"discriminator"in e?this.discriminator=e.discriminator:"string"!=typeof this.discriminator&&(this.discriminator=null),"avatar"in e?this.avatar=e.avatar:"string"!=typeof this.avatar&&(this.avatar=null),"system"in e&&(this.system=Boolean(e.system)),"locale"in e&&(this.locale=e.locale),"public_flags"in e&&(this.flags=new a(e.public_flags)),this.lastMessageID=null,this.lastMessageChannelID=null}get partial(){return"string"!=typeof this.username}get createdTimestamp(){return o.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get lastMessage(){const e=this.client.channels.cache.get(this.lastMessageChannelID);return e&&e.messages.cache.get(this.lastMessageID)||null}get presence(){for(const e of this.client.guilds.cache.values())if(e.presences.cache.has(this.id))return e.presences.cache.get(this.id);c||(c=i(10));return new(c.get("Presence"))(this.client,{user:{id:this.id}})}avatarURL({format:e,size:t,dynamic:i}={}){return this.avatar?this.client.rest.cdn.Avatar(this.id,this.avatar,e,t,i):null}get defaultAvatarURL(){return this.client.rest.cdn.DefaultAvatar(this.discriminator%5)}displayAvatarURL(e){return this.avatarURL(e)||this.defaultAvatarURL}get tag(){return"string"==typeof this.username?`${this.username}#${this.discriminator}`:null}typingIn(e){return(e=this.client.channels.resolve(e))._typing.has(this.id)}typingSinceIn(e){return(e=this.client.channels.resolve(e))._typing.has(this.id)?new Date(e._typing.get(this.id).since):null}typingDurationIn(e){return(e=this.client.channels.resolve(e))._typing.has(this.id)?e._typing.get(this.id).elapsedTime:-1}get dmChannel(){return this.client.channels.cache.find((e=>"dm"===e.type&&e.recipient.id===this.id))||null}async createDM(e=!1){if(!e){const{dmChannel:e}=this;if(e&&!e.partial)return e}const t=await this.client.api.users(this.client.user.id).channels.post({data:{recipient_id:this.id}});return this.client.actions.ChannelCreate.handle(t).channel}async deleteDM(){const{dmChannel:e}=this;if(!e)throw new r("USER_NO_DMCHANNEL");const t=await this.client.api.channels(e.id).delete();return this.client.actions.ChannelDelete.handle(t).channel}equals(e){return e&&this.id===e.id&&this.username===e.username&&this.discriminator===e.discriminator&&this.avatar===e.avatar}async fetchFlags(e=!1){if(this.flags&&!e)return this.flags;const t=await this.client.api.users(this.id).get();return this._patch(t),this.flags}fetch(e=!1){return this.client.users.fetch(this.id,!0,e)}toString(){return`<@${this.id}>`}toJSON(...e){const t=super.toJSON({createdTimestamp:!0,defaultAvatarURL:!0,tag:!0,lastMessage:!1,lastMessageID:!1},...e);return t.avatarURL=this.avatarURL(),t.displayAvatarURL=this.displayAvatarURL(),t}send(){}}n.applyToClass(User),e.exports=User},function(e,t,i){"use strict";const s=i(30),n=i(5),r=i(50),o=i(43),a=i(44),c=i(76),l=i(77),{Error:h,TypeError:u}=i(2),d=i(78),f=i(3),{MessageTypes:p}=i(0),m=i(47),g=i(8),E=i(6),_=i(4);e.exports=class Message extends n{constructor(e,t,i){super(e),this.channel=i,this.deleted=!1,t&&this._patch(t)}_patch(e){if(this.id=e.id,"type"in e?(this.type=p[e.type],this.system=0!==e.type):"string"!=typeof this.type&&(this.system=null,this.type=null),"content"in e?this.content=e.content:"string"!=typeof this.content&&(this.content=null),"author"in e?this.author=this.client.users.add(e.author,!e.webhook_id):this.author||(this.author=null),"pinned"in e?this.pinned=Boolean(e.pinned):"boolean"!=typeof this.pinned&&(this.pinned=null),"tts"in e?this.tts=e.tts:"boolean"!=typeof this.tts&&(this.tts=null),this.nonce="nonce"in e?e.nonce:null,this.embeds=(e.embeds||[]).map((e=>new a(e,!0))),this.attachments=new f,e.attachments)for(const t of e.attachments)this.attachments.set(t.id,new o(t.url,t.filename,t));if(this.createdTimestamp=E.deconstruct(this.id).timestamp,this.editedTimestamp="edited_timestamp"in e?new Date(e.edited_timestamp).getTime():null,this.reactions=new d(this),e.reactions&&e.reactions.length>0)for(const t of e.reactions)this.reactions.add(t);this.mentions=new c(this,e.mentions,e.mention_roles,e.mention_everyone,e.mention_channels),this.webhookID=e.webhook_id||null,this.application=e.application?new r(this.client,e.application):null,this.activity=e.activity?{partyID:e.activity.party_id,type:e.activity.type}:null,this._edits=[],this.member&&e.member?this.member._patch(e.member):e.member&&this.guild&&this.author&&this.guild.members.add(Object.assign(e.member,{user:this.author})),this.flags=new m(e.flags).freeze(),this.reference=e.message_reference?{channelID:e.message_reference.channel_id,guildID:e.message_reference.guild_id,messageID:e.message_reference.message_id}:null}get partial(){return"string"!=typeof this.content||!this.author}patch(e){const t=this._clone(),{messageEditHistoryMaxSize:i}=this.client.options;if(0!==i){const e=-1===i?1/0:i;this._edits.unshift(t)>e&&this._edits.pop()}if("edited_timestamp"in e&&(this.editedTimestamp=new Date(e.edited_timestamp).getTime()),"content"in e&&(this.content=e.content),"pinned"in e&&(this.pinned=e.pinned),"tts"in e&&(this.tts=e.tts),this.embeds="embeds"in e?e.embeds.map((e=>new a(e,!0))):this.embeds.slice(),"attachments"in e){this.attachments=new f;for(const t of e.attachments)this.attachments.set(t.id,new o(t.url,t.filename,t))}else this.attachments=new f(this.attachments);return this.mentions=new c(this,"mentions"in e?e.mentions:this.mentions.users,"mention_roles"in e?e.mention_roles:this.mentions.roles,"mention_everyone"in e?e.mention_everyone:this.mentions.everyone,"mention_channels"in e?e.mention_channels:this.mentions.crosspostedChannels),this.flags=new m("flags"in e?e.flags:0).freeze(),t}get member(){return this.guild&&this.guild.member(this.author)||null}get createdAt(){return new Date(this.createdTimestamp)}get editedAt(){return this.editedTimestamp?new Date(this.editedTimestamp):null}get guild(){return this.channel.guild||null}get url(){return`https://discord.com/channels/${this.guild?this.guild.id:"@me"}/${this.channel.id}/${this.id}`}get cleanContent(){return null!=this.content?_.cleanContent(this.content,this):null}createReactionCollector(e,t={}){return new l(this,e,t)}awaitReactions(e,t={}){return new Promise(((i,s)=>{this.createReactionCollector(e,t).once("end",((e,n)=>{t.errors&&t.errors.includes(n)?s(e):i(e)}))}))}get edits(){const e=this._edits.slice();return e.unshift(this),e}get editable(){return this.author.id===this.client.user.id}get deletable(){return!this.deleted&&(this.author.id===this.client.user.id||this.guild&&this.channel.permissionsFor(this.client.user).has(g.FLAGS.MANAGE_MESSAGES,!1))}get pinnable(){return"DEFAULT"===this.type&&(!this.guild||this.channel.permissionsFor(this.client.user).has(g.FLAGS.MANAGE_MESSAGES,!1))}get crosspostable(){return"news"===this.channel.type&&!this.flags.has(m.FLAGS.CROSSPOSTED)&&"DEFAULT"===this.type&&this.channel.viewable&&this.channel.permissionsFor(this.client.user).has(g.FLAGS.SEND_MESSAGES)&&(this.author.id===this.client.user.id||this.channel.permissionsFor(this.client.user).has(g.FLAGS.MANAGE_MESSAGES))}edit(e,t){const{data:i}=e instanceof s?e.resolveData():s.create(this,e,t).resolveData();return this.client.api.channels[this.channel.id].messages[this.id].patch({data:i}).then((e=>{const t=this._clone();return t._patch(e),t}))}async crosspost(){return await this.client.api.channels(this.channel.id).messages(this.id).crosspost.post(),this}pin(e){return this.client.api.channels(this.channel.id).pins(this.id).put(e).then((()=>this))}unpin(e){return this.client.api.channels(this.channel.id).pins(this.id).delete(e).then((()=>this))}react(e){if(!(e=this.client.emojis.resolveIdentifier(e)))throw new u("EMOJI_TYPE");return this.client.api.channels(this.channel.id).messages(this.id).reactions(e,"@me").put().then((()=>this.client.actions.MessageReactionAdd.handle({user:this.client.user,channel:this.channel,message:this,emoji:_.parseEmoji(e)}).reaction))}delete(e={}){if("object"!=typeof e)return Promise.reject(new u("INVALID_TYPE","options","object",!0));const{timeout:t=0,reason:i}=e;return t<=0?this.channel.messages.delete(this.id,i).then((()=>this)):new Promise((e=>{this.client.setTimeout((()=>{e(this.delete({reason:i}))}),t)}))}reply(e,t){return this.channel.send(e instanceof s?e:s.transformOptions(e,t,{reply:this.member||this.author}))}fetch(e=!1){return this.channel.messages.fetch(this.id,!0,e)}fetchWebhook(){return this.webhookID?this.client.fetchWebhook(this.webhookID):Promise.reject(new h("WEBHOOK_MESSAGE"))}suppressEmbeds(e=!0){const t=new m(this.flags.bitfield);return e?t.add(m.FLAGS.SUPPRESS_EMBEDS):t.remove(m.FLAGS.SUPPRESS_EMBEDS),this.edit({flags:t})}equals(e,t){if(!e)return!1;if(!e.author&&!e.attachments)return this.id===e.id&&this.embeds.length===e.embeds.length;let i=this.id===e.id&&this.author.id===e.author.id&&this.content===e.content&&this.tts===e.tts&&this.nonce===e.nonce&&this.embeds.length===e.embeds.length&&this.attachments.length===e.attachments.length;return i&&t&&(i=this.mentions.everyone===e.mentions.everyone&&this.createdTimestamp===new Date(t.timestamp).getTime()&&this.editedTimestamp===new Date(t.edited_timestamp).getTime()),i}toString(){return this.content}toJSON(){return super.toJSON({channel:"channelID",author:"authorID",application:"applicationID",guild:"guildID",cleanContent:!0,member:!1,reactions:!1})}}},function(e,t,i){"use strict";const s=i(5),n=i(6);e.exports=class Emoji extends s{constructor(e,t){super(e),this.animated=t.animated,this.name=t.name,this.id=t.id,this.deleted=!1}get identifier(){return this.id?`${this.animated?"a:":""}${this.name}:${this.id}`:encodeURIComponent(this.name)}get url(){return this.id?this.client.rest.cdn.Emoji(this.id,this.animated?"gif":"png"):null}get createdTimestamp(){return this.id?n.deconstruct(this.id).timestamp:null}get createdAt(){return this.id?new Date(this.createdTimestamp):null}toString(){return this.id?`<${this.animated?"a":""}:${this.name}:${this.id}>`:this.name}toJSON(){return super.toJSON({guild:"guildID",createdTimestamp:!0,url:!0,identifier:!0})}}},function(e,t,i){"use strict";(function(t){const s=i(43),n=i(44),{RangeError:r}=i(2),{browser:o}=i(0),a=i(9),c=i(47),l=i(4);class APIMessage{constructor(e,t){this.target=e,this.options=t,this.data=null,this.files=null}get isWebhook(){const e=i(13),t=i(48);return this.target instanceof e||this.target instanceof t}get isUser(){const e=i(27),t=i(11);return this.target instanceof e||this.target instanceof t}get isMessage(){const e=i(28);return this.target instanceof e}makeContent(){const e=i(11);let t;if(null===this.options.content?t="":void 0!==this.options.content&&(t=l.resolveString(this.options.content)),"string"!=typeof t)return t;const s=void 0===this.options.disableMentions?this.target.client.options.disableMentions:this.options.disableMentions;"all"===s?t=l.removeMentions(t):"everyone"===s&&(t=t.replace(/@([^<>@ ]*)/gmus,((e,t)=>t.match(/^[&!]?\d+$/)?"@"+t:"@​"+t)));const n=void 0!==this.options.split&&!1!==this.options.split,r=void 0!==this.options.code&&!1!==this.options.code,o=n?{...this.options.split}:void 0;let a="";if(this.options.reply&&!this.isUser&&"dm"!==this.target.type){const t=this.target.client.users.resolveID(this.options.reply);a=`<@${this.options.reply instanceof e&&this.options.reply.nickname?"!":""}${t}>, `,n&&(o.prepend=`${a}${o.prepend||""}`)}if(t||a){if(r){const e="string"==typeof this.options.code?this.options.code:"";t=`${a}\`\`\`${e}\n${l.cleanCodeBlockContent(t)}\n\`\`\``,n&&(o.prepend=`${o.prepend||""}\`\`\`${e}\n`,o.append="\n```"+(o.append||""))}else a&&(t=`${a}${t}`);n&&(t=l.splitMessage(t,o))}return t}resolveData(){if(this.data)return this;const e=this.makeContent(),t=Boolean(this.options.tts);let i;if(void 0!==this.options.nonce&&(i=parseInt(this.options.nonce),isNaN(i)||i<0))throw new r("MESSAGE_NONCE_TYPE");const s=[];this.isWebhook?this.options.embeds&&s.push(...this.options.embeds):this.options.embed&&s.push(this.options.embed);const o=s.map((e=>new n(e).toJSON()));let a,h,u;this.isWebhook&&(a=this.options.username||this.target.name,this.options.avatarURL&&(h=this.options.avatarURL)),this.isMessage&&(u=null!=this.options.flags?new c(this.options.flags).bitfield:this.target.flags.bitfield);let d=void 0===this.options.allowedMentions?this.target.client.options.allowedMentions:this.options.allowedMentions;if(this.options.reply){const e=this.target.client.users.resolveID(this.options.reply);if(d){d=l.cloneObject(d);d.parse&&d.parse.includes("users")||d.users&&d.users.includes(e)||(d.users||(d.users=[]),d.users.push(e))}else d={users:[e]}}return this.data={content:e,tts:t,nonce:i,embed:null===this.options.embed?null:o[0],embeds:o,username:a,avatar_url:h,allowed_mentions:void 0===e?void 0:d,flags:u},this}async resolveFiles(){if(this.files)return this;const e=[];this.isWebhook?this.options.embeds&&e.push(...this.options.embeds):this.options.embed&&e.push(this.options.embed);const t=[];this.options.files&&t.push(...this.options.files);for(const i of e)i.files&&t.push(...i.files);return this.files=await Promise.all(t.map((e=>this.constructor.resolveFile(e)))),this}split(){if(this.data||this.resolveData(),!Array.isArray(this.data.content))return[this];const e=[];for(let t=0;t"string"==typeof e?l.basename(e):e.path?l.basename(e.path):"file.jpg";"string"==typeof e||e instanceof(o?ArrayBuffer:t)||"function"==typeof e.pipe?(i=e,s=findName(i)):(i=e.attachment,s=e.name||findName(i));return{attachment:i,name:s,file:await a.resolveFile(i)}}static partitionMessageAdditions(e){const t=[],i=[];for(const r of e)r instanceof n?t.push(r):r instanceof s&&i.push(r);return[t,i]}static transformOptions(e,t,i={},r=!1){if(t||"object"!=typeof e||Array.isArray(e)||(t=e,e=void 0),t){if(t instanceof n)return r?{content:e,embeds:[t],...i}:{content:e,embed:t,...i};if(t instanceof s)return{content:e,files:[t],...i}}else t={};if(Array.isArray(t)){const[s,n]=this.partitionMessageAdditions(t);return r?{content:e,embeds:s,files:n,...i}:{content:e,embed:s[0],files:n,...i}}if(Array.isArray(e)){const[t,s]=this.partitionMessageAdditions(e);if(t.length||s.length)return r?{embeds:t,files:s,...i}:{embed:t[0],files:s,...i}}return{content:e,...t,...i}}static create(e,t,s,n={}){const r=i(13),o=i(48),a=e instanceof r||e instanceof o;return new this(e,this.transformOptions(t,s,n,a))}}e.exports=APIMessage}).call(this,i(14).Buffer)},function(e,t,i){"use strict";(function(t){void 0===t||!t.version||0===t.version.indexOf("v0.")||0===t.version.indexOf("v1.")&&0!==t.version.indexOf("v1.8.")?e.exports={nextTick:function nextTick(e,i,s,n){if("function"!=typeof e)throw new TypeError('"callback" argument must be a function');var r,o,a=arguments.length;switch(a){case 0:case 1:return t.nextTick(e);case 2:return t.nextTick((function afterTickOne(){e.call(null,i)}));case 3:return t.nextTick((function afterTickTwo(){e.call(null,i,s)}));case 4:return t.nextTick((function afterTickThree(){e.call(null,i,s,n)}));default:for(r=new Array(a-1),o=0;oi.send(e,t)));let o;if(e instanceof n)o=e.resolveData();else if(o=n.create(this,e,t).resolveData(),Array.isArray(o.data.content))return Promise.all(o.split().map(this.send.bind(this)));const{data:a,files:c}=await o.resolveFiles();return this.client.api.channels[this.id].messages.post({data:a,files:c}).then((e=>this.client.actions.MessageCreate.handle(e).message))}startTyping(e){if(void 0!==e&&e<1)throw new a("TYPING_COUNT");if(this.client.user._typing.has(this.id)){const t=this.client.user._typing.get(this.id);return t.count=e||t.count+1,t.promise}const t={};return t.promise=new Promise(((i,s)=>{const n=this.client.api.channels[this.id].typing;Object.assign(t,{count:e||1,interval:this.client.setInterval((()=>{n.post().catch((e=>{this.client.clearInterval(t.interval),this.client.user._typing.delete(this.id),s(e)}))}),9e3),resolve:i}),n.post().catch((e=>{this.client.clearInterval(t.interval),this.client.user._typing.delete(this.id),s(e)})),this.client.user._typing.set(this.id,t)})),t.promise}stopTyping(e=!1){if(this.client.user._typing.has(this.id)){const t=this.client.user._typing.get(this.id);t.count--,(t.count<=0||e)&&(this.client.clearInterval(t.interval),this.client.user._typing.delete(this.id),t.resolve())}}get typing(){return this.client.user._typing.has(this.id)}get typingCount(){return this.client.user._typing.has(this.id)?this.client.user._typing.get(this.id).count:0}createMessageCollector(e,t={}){return new s(this,e,t)}awaitMessages(e,t={}){return new Promise(((i,s)=>{this.createMessageCollector(e,t).once("end",((e,n)=>{t.errors&&t.errors.includes(n)?s(e):i(e)}))}))}async bulkDelete(e,t=!1){if(Array.isArray(e)||e instanceof o){let i=e instanceof o?e.keyArray():e.map((e=>e.id||e));if(t&&(i=i.filter((e=>Date.now()-r.deconstruct(e).date.getTime()<12096e5))),0===i.length)return new o;if(1===i.length){await this.client.api.channels(this.id).messages(i[0]).delete();const e=this.client.actions.MessageDelete.getMessage({message_id:i[0]},this);return e?new o([[e.id,e]]):new o}return await this.client.api.channels[this.id].messages["bulk-delete"].post({data:{messages:i}}),i.reduce(((e,t)=>e.set(t,this.client.actions.MessageDeleteBulk.getMessage({message_id:t},this))),new o)}if(!isNaN(e)){const i=await this.messages.fetch({limit:e});return this.bulkDelete(i,t)}throw new c("MESSAGE_BULK_DELETE_TYPE")}static applyToClass(e,t=!1,i=[]){const s=["send"];t&&s.push("lastMessage","lastPinAt","bulkDelete","startTyping","stopTyping","typing","typingCount","createMessageCollector","awaitMessages");for(const t of s)i.includes(t)||Object.defineProperty(e.prototype,t,Object.getOwnPropertyDescriptor(TextBasedChannel.prototype,t))}}e.exports=TextBasedChannel;const l=i(34)},function(e,t,i){"use strict";const s=i(7),{TypeError:n}=i(2),r=i(28),o=i(3),a=i(137);e.exports=class MessageManager extends s{constructor(e,t){super(e.client,t,r,a,e.client.options.messageCacheMaxSize),this.channel=e}add(e,t){return super.add(e,t,{extras:[this.channel]})}fetch(e,t=!0,i=!1){return"string"==typeof e?this._fetchId(e,t,i):this._fetchMany(e,t)}fetchPinned(e=!0){return this.client.api.channels[this.channel.id].pins.get().then((t=>{const i=new o;for(const s of t)i.set(s.id,this.add(s,e));return i}))}async delete(e,t){if(!(e=this.resolveID(e)))throw new n("INVALID_TYPE","message","MessageResolvable");await this.client.api.channels(this.channel.id).messages(e).delete({reason:t})}async _fetchId(e,t,i){if(!i){const t=this.cache.get(e);if(t&&!t.partial)return t}const s=await this.client.api.channels[this.channel.id].messages[e].get();return this.add(s,t)}async _fetchMany(e={},t){const i=await this.client.api.channels[this.channel.id].messages.get({query:e}),s=new o;for(const e of i)s.set(e.id,this.add(e,t));return s}}},function(e,t){},function(e,t,i){"use strict";var s=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if(void 0!==s)return s;throw new Error("unable to locate global object")}();e.exports=t=s.fetch,s.fetch&&(t.default=s.fetch.bind(s)),t.Headers=s.Headers,t.Request=s.Request,t.Response=s.Response},function(e,t,i){"use strict";(function(t,s){i(63);const n=i(16),r=i(107),{DefaultOptions:o}=i(0),a=i(4);e.exports=class BaseClient extends n{constructor(e={}){super(),this._timeouts=new Set,this._intervals=new Set,this._immediates=new Set,this.options=a.mergeDefault(o,e),this.rest=new r(this,e._tokenType)}get api(){return this.rest.api}destroy(){for(const e of this._timeouts)this.clearTimeout(e);for(const e of this._intervals)this.clearInterval(e);for(const e of this._immediates)this.clearImmediate(e);this._timeouts.clear(),this._intervals.clear(),this._immediates.clear()}setTimeout(e,t,...i){const s=setTimeout((()=>{e(...i),this._timeouts.delete(s)}),t);return this._timeouts.add(s),s}clearTimeout(e){clearTimeout(e),this._timeouts.delete(e)}setInterval(e,t,...i){const s=setInterval(e,t,...i);return this._intervals.add(s),s}clearInterval(e){clearInterval(e),this._intervals.delete(e)}setImmediate(e,...i){const s=t(e,...i);return this._immediates.add(s),s}clearImmediate(e){s(e),this._immediates.delete(e)}incrementMaxListeners(){const e=this.getMaxListeners();0!==e&&this.setMaxListeners(e+1)}decrementMaxListeners(){const e=this.getMaxListeners();0!==e&&this.setMaxListeners(e-1)}toJSON(...e){return a.flatten(this,{domain:!1},...e)}}}).call(this,i(38).setImmediate,i(38).clearImmediate)},function(e,t,i){(function(e){var s=void 0!==e&&e||"undefined"!=typeof self&&self||window,n=Function.prototype.apply;function Timeout(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new Timeout(n.call(setTimeout,s,arguments),clearTimeout)},t.setInterval=function(){return new Timeout(n.call(setInterval,s,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},Timeout.prototype.unref=Timeout.prototype.ref=function(){},Timeout.prototype.close=function(){this._clearFn.call(s,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout((function onTimeout(){e._onTimeout&&e._onTimeout()}),t))},i(63),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,i(22))},function(e,t,i){"use strict";const s=i(17),n=i(33),r=i(34);class DMChannel extends s{constructor(e,t){super(e,t),this.type="dm",this.messages=new r(this),this._typing=new Map}_patch(e){super._patch(e),e.recipients&&(this.recipient=this.client.users.add(e.recipients[0])),this.lastMessageID=e.last_message_id,this.lastPinTimestamp=e.last_pin_timestamp?new Date(e.last_pin_timestamp).getTime():null}get partial(){return void 0===this.lastMessageID}fetch(e=!1){return this.recipient.createDM(e)}toString(){return this.recipient.toString()}get lastMessage(){}get lastPinAt(){}send(){}startTyping(){}stopTyping(){}get typing(){}get typingCount(){}createMessageCollector(){}awaitMessages(){}}n.applyToClass(DMChannel,!0,["bulkDelete"]),e.exports=DMChannel},function(e,t,i){"use strict";const s=i(29);e.exports=class BaseGuildEmoji extends s{constructor(e,t,i){super(e,t),this.guild=i,this.requireColons=null,this.managed=null,this.available=null,Object.defineProperty(this,"_roles",{value:[],writable:!0}),this._patch(t)}_patch(e){e.name&&(this.name=e.name),void 0!==e.require_colons&&(this.requiresColons=e.require_colons),void 0!==e.managed&&(this.managed=e.managed),void 0!==e.available&&(this.available=e.available),e.roles&&(this._roles=e.roles)}}},function(e,t,i){"use strict";const s=i(18),n=i(13),r=i(33),o=i(34),a=i(3),c=i(9);class TextChannel extends s{constructor(e,t){super(e,t),this.messages=new o(this),this.nsfw=Boolean(t.nsfw),this._typing=new Map}_patch(e){if(super._patch(e),this.topic=e.topic,void 0!==e.nsfw&&(this.nsfw=Boolean(e.nsfw)),this.lastMessageID=e.last_message_id,this.rateLimitPerUser=e.rate_limit_per_user||0,this.lastPinTimestamp=e.last_pin_timestamp?new Date(e.last_pin_timestamp).getTime():null,e.messages)for(const t of e.messages)this.messages.add(t)}setRateLimitPerUser(e,t){return this.edit({rateLimitPerUser:e},t)}setNSFW(e,t){return this.edit({nsfw:e},t)}fetchWebhooks(){return this.client.api.channels[this.id].webhooks.get().then((e=>{const t=new a;for(const i of e)t.set(i.id,new n(this.client,i));return t}))}async createWebhook(e,{avatar:t,reason:i}={}){return"string"!=typeof t||t.startsWith("data:")||(t=await c.resolveImage(t)),this.client.api.channels[this.id].webhooks.post({data:{name:e,avatar:t},reason:i}).then((e=>new n(this.client,e)))}get lastMessage(){}get lastPinAt(){}send(){}startTyping(){}stopTyping(){}get typing(){}get typingCount(){}createMessageCollector(){}awaitMessages(){}bulkDelete(){}}r.applyToClass(TextChannel,!0),e.exports=TextChannel},function(e,t,i){"use strict";const s=i(20),{TypeError:n}=i(2),r=i(8),o=i(4);e.exports=class PermissionOverwrites{constructor(e,t){Object.defineProperty(this,"channel",{value:e}),t&&this._patch(t)}_patch(e){this.id=e.id,this.type=e.type,this.deny=new r(e.deny).freeze(),this.allow=new r(e.allow).freeze()}update(e,t){const{allow:i,deny:s}=this.constructor.resolveOverwriteOptions(e,this);return this.channel.client.api.channels(this.channel.id).permissions[this.id].put({data:{id:this.id,type:this.type,allow:i.bitfield,deny:s.bitfield},reason:t}).then((()=>this))}delete(e){return this.channel.client.api.channels[this.channel.id].permissions[this.id].delete({reason:e}).then((()=>this))}toJSON(){return o.flatten(this)}static resolveOverwriteOptions(e,{allow:t,deny:i}={}){t=new r(t),i=new r(i);for(const[s,n]of Object.entries(e))!0===n?(t.add(r.FLAGS[s]),i.remove(r.FLAGS[s])):!1===n?(t.remove(r.FLAGS[s]),i.add(r.FLAGS[s])):null===n&&(t.remove(r.FLAGS[s]),i.remove(r.FLAGS[s]));return{allow:t,deny:i}}static resolve(e,t){if(e instanceof this)return e.toJSON();if("string"==typeof e.id&&["role","member"].includes(e.type))return{...e,allow:r.resolve(e.allow),deny:r.resolve(e.deny)};const i=t.roles.resolve(e.id)||t.client.users.resolve(e.id);if(!i)throw new n("INVALID_TYPE","parameter","User nor a Role");const o=i instanceof s?"role":"member";return{id:i.id,type:o,allow:r.resolve(e.allow),deny:r.resolve(e.deny)}}}},function(e,t,i){"use strict";const s=i(4);e.exports=class MessageAttachment{constructor(e,t=null,i){this.attachment=e,this.name=t,i&&this._patch(i)}setFile(e,t=null){return this.attachment=e,this.name=t,this}setName(e){return this.name=e,this}_patch(e){this.id=e.id,this.size=e.size,this.url=e.url,this.proxyURL=e.proxy_url,this.height=void 0!==e.height?e.height:null,this.width=void 0!==e.width?e.width:null}get spoiler(){return s.basename(this.url).startsWith("SPOILER_")}toJSON(){return s.flatten(this)}}},function(e,t,i){"use strict";const{RangeError:s}=i(2),n=i(4);e.exports=class MessageEmbed{constructor(e={},t=!1){this.setup(e,t)}setup(e,t){this.type=e.type||"rich",this.title="title"in e?e.title:null,this.description="description"in e?e.description:null,this.url="url"in e?e.url:null,this.color="color"in e?n.resolveColor(e.color):null,this.timestamp="timestamp"in e?new Date(e.timestamp).getTime():null,this.fields=[],e.fields&&(this.fields=t?e.fields.map(n.cloneObject):this.constructor.normalizeFields(e.fields)),this.thumbnail=e.thumbnail?{url:e.thumbnail.url,proxyURL:e.thumbnail.proxyURL||e.thumbnail.proxy_url,height:e.thumbnail.height,width:e.thumbnail.width}:null,this.image=e.image?{url:e.image.url,proxyURL:e.image.proxyURL||e.image.proxy_url,height:e.image.height,width:e.image.width}:null,this.video=e.video?{url:e.video.url,proxyURL:e.video.proxyURL||e.video.proxy_url,height:e.video.height,width:e.video.width}:null,this.author=e.author?{name:e.author.name,url:e.author.url,iconURL:e.author.iconURL||e.author.icon_url,proxyIconURL:e.author.proxyIconURL||e.author.proxy_icon_url}:null,this.provider=e.provider?{name:e.provider.name,url:e.provider.name}:null,this.footer=e.footer?{text:e.footer.text,iconURL:e.footer.iconURL||e.footer.icon_url,proxyIconURL:e.footer.proxyIconURL||e.footer.proxy_icon_url}:null,this.files=e.files||[]}get createdAt(){return this.timestamp?new Date(this.timestamp):null}get hexColor(){return this.color?"#"+this.color.toString(16).padStart(6,"0"):null}get length(){return(this.title?this.title.length:0)+(this.description?this.description.length:0)+(this.fields.length>=1?this.fields.reduce(((e,t)=>e+t.name.length+t.value.length),0):0)+(this.footer?this.footer.text.length:0)}addField(e,t,i){return this.addFields({name:e,value:t,inline:i})}addFields(...e){return this.fields.push(...this.constructor.normalizeFields(e)),this}spliceFields(e,t,...i){return this.fields.splice(e,t,...this.constructor.normalizeFields(...i)),this}attachFiles(e){return this.files=this.files.concat(e),this}setAuthor(e,t,i){return this.author={name:n.resolveString(e),iconURL:t,url:i},this}setColor(e){return this.color=n.resolveColor(e),this}setDescription(e){return e=n.resolveString(e),this.description=e,this}setFooter(e,t){return e=n.resolveString(e),this.footer={text:e,iconURL:t},this}setImage(e){return this.image={url:e},this}setThumbnail(e){return this.thumbnail={url:e},this}setTimestamp(e=Date.now()){return e instanceof Date&&(e=e.getTime()),this.timestamp=e,this}setTitle(e){return e=n.resolveString(e),this.title=e,this}setURL(e){return this.url=e,this}toJSON(){return{title:this.title,type:"rich",description:this.description,url:this.url,timestamp:this.timestamp?new Date(this.timestamp):null,color:this.color,fields:this.fields,thumbnail:this.thumbnail,image:this.image,author:this.author?{name:this.author.name,url:this.author.url,icon_url:this.author.iconURL}:null,footer:this.footer?{text:this.footer.text,icon_url:this.footer.iconURL}:null}}static normalizeField(e,t,i=!1){if(!(e=n.resolveString(e)))throw new s("EMBED_FIELD_NAME");if(!(t=n.resolveString(t)))throw new s("EMBED_FIELD_VALUE");return{name:e,value:t,inline:i}}static normalizeFields(...e){return e.flat(2).map((e=>this.normalizeField(e&&e.name,e&&e.value,!(!e||"boolean"!=typeof e.inline)&&e.inline)))}}},function(e,t,i){(t=e.exports=i(67)).Stream=t,t.Readable=t,t.Writable=i(46),t.Duplex=i(21),t.Transform=i(71),t.PassThrough=i(132)},function(e,t,i){"use strict";(function(t,s,n){var r=i(31);function CorkedRequest(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function onCorkedFinish(e,t,i){var s=e.entry;e.entry=null;for(;s;){var n=s.callback;t.pendingcb--,n(i),s=s.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=Writable;var o,a=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?s:r.nextTick;Writable.WritableState=WritableState;var c=Object.create(i(26));c.inherits=i(23);var l={deprecate:i(131)},h=i(68),u=i(32).Buffer,d=n.Uint8Array||function(){};var f,p=i(69);function nop(){}function WritableState(e,t){o=o||i(21),e=e||{};var s=t instanceof o;this.objectMode=!!e.objectMode,s&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var n=e.highWaterMark,c=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=n||0===n?n:s&&(c||0===c)?c:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var h=!1===e.decodeStrings;this.decodeStrings=!h,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function onwrite(e,t){var i=e._writableState,s=i.sync,n=i.writecb;if(function onwriteStateUpdate(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(i),t)!function onwriteError(e,t,i,s,n){--t.pendingcb,i?(r.nextTick(n,s),r.nextTick(finishMaybe,e,t),e._writableState.errorEmitted=!0,e.emit("error",s)):(n(s),e._writableState.errorEmitted=!0,e.emit("error",s),finishMaybe(e,t))}(e,i,s,t,n);else{var o=needFinish(i);o||i.corked||i.bufferProcessing||!i.bufferedRequest||clearBuffer(e,i),s?a(afterWrite,e,i,o,n):afterWrite(e,i,o,n)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new CorkedRequest(this)}function Writable(e){if(o=o||i(21),!(f.call(Writable,this)||this instanceof o))return new Writable(e);this._writableState=new WritableState(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),h.call(this)}function doWrite(e,t,i,s,n,r,o){t.writelen=s,t.writecb=o,t.writing=!0,t.sync=!0,i?e._writev(n,t.onwrite):e._write(n,r,t.onwrite),t.sync=!1}function afterWrite(e,t,i,s){i||function onwriteDrain(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,s(),finishMaybe(e,t)}function clearBuffer(e,t){t.bufferProcessing=!0;var i=t.bufferedRequest;if(e._writev&&i&&i.next){var s=t.bufferedRequestCount,n=new Array(s),r=t.corkedRequestsFree;r.entry=i;for(var o=0,a=!0;i;)n[o]=i,i.isBuf||(a=!1),i=i.next,o+=1;n.allBuffers=a,doWrite(e,t,!0,t.length,n,"",r.finish),t.pendingcb++,t.lastBufferedRequest=null,r.next?(t.corkedRequestsFree=r.next,r.next=null):t.corkedRequestsFree=new CorkedRequest(t),t.bufferedRequestCount=0}else{for(;i;){var c=i.chunk,l=i.encoding,h=i.callback;if(doWrite(e,t,!1,t.objectMode?1:c.length,c,l,h),i=i.next,t.bufferedRequestCount--,t.writing)break}null===i&&(t.lastBufferedRequest=null)}t.bufferedRequest=i,t.bufferProcessing=!1}function needFinish(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function callFinal(e,t){e._final((function(i){t.pendingcb--,i&&e.emit("error",i),t.prefinished=!0,e.emit("prefinish"),finishMaybe(e,t)}))}function finishMaybe(e,t){var i=needFinish(t);return i&&(!function prefinish(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,r.nextTick(callFinal,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),i}c.inherits(Writable,h),WritableState.prototype.getBuffer=function getBuffer(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(WritableState.prototype,"buffer",{get:l.deprecate((function(){return this.getBuffer()}),"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(f=Function.prototype[Symbol.hasInstance],Object.defineProperty(Writable,Symbol.hasInstance,{value:function(e){return!!f.call(this,e)||this===Writable&&(e&&e._writableState instanceof WritableState)}})):f=function(e){return e instanceof this},Writable.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},Writable.prototype.write=function(e,t,i){var s=this._writableState,n=!1,o=!s.objectMode&&function _isUint8Array(e){return u.isBuffer(e)||e instanceof d}(e);return o&&!u.isBuffer(e)&&(e=function _uint8ArrayToBuffer(e){return u.from(e)}(e)),"function"==typeof t&&(i=t,t=null),o?t="buffer":t||(t=s.defaultEncoding),"function"!=typeof i&&(i=nop),s.ended?function writeAfterEnd(e,t){var i=new Error("write after end");e.emit("error",i),r.nextTick(t,i)}(this,i):(o||function validChunk(e,t,i,s){var n=!0,o=!1;return null===i?o=new TypeError("May not write null values to stream"):"string"==typeof i||void 0===i||t.objectMode||(o=new TypeError("Invalid non-string/buffer chunk")),o&&(e.emit("error",o),r.nextTick(s,o),n=!1),n}(this,s,e,i))&&(s.pendingcb++,n=function writeOrBuffer(e,t,i,s,n,r){if(!i){var o=function decodeChunk(e,t,i){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=u.from(t,i));return t}(t,s,n);s!==o&&(i=!0,n="buffer",s=o)}var a=t.objectMode?1:s.length;t.length+=a;var c=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(Writable.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Writable.prototype._write=function(e,t,i){i(new Error("_write() is not implemented"))},Writable.prototype._writev=null,Writable.prototype.end=function(e,t,i){var s=this._writableState;"function"==typeof e?(i=e,e=null,t=null):"function"==typeof t&&(i=t,t=null),null!=e&&this.write(e,t),s.corked&&(s.corked=1,this.uncork()),s.ending||s.finished||function endWritable(e,t,i){t.ending=!0,finishMaybe(e,t),i&&(t.finished?r.nextTick(i):e.once("finish",i));t.ended=!0,e.writable=!1}(this,s,i)},Object.defineProperty(Writable.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),Writable.prototype.destroy=p.destroy,Writable.prototype._undestroy=p.undestroy,Writable.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,i(15),i(38).setImmediate,i(22))},function(e,t,i){"use strict";const s=i(12);class MessageFlags extends s{}MessageFlags.FLAGS={CROSSPOSTED:1,IS_CROSSPOST:2,SUPPRESS_EMBEDS:4,SOURCE_MESSAGE_DELETED:8,URGENT:16},e.exports=MessageFlags},function(e,t,i){"use strict";const s=i(37),n=i(13);class WebhookClient extends s{constructor(e,t,i){super(i),Object.defineProperty(this,"client",{value:this}),this.id=e,Object.defineProperty(this,"token",{value:t,writable:!0,configurable:!0})}}n.applyToClass(WebhookClient),e.exports=WebhookClient},function(e,t,i){"use strict";const s=i(16),n=i(3),r=i(4);class Collector extends s{constructor(e,t,i={}){super(),Object.defineProperty(this,"client",{value:e}),this.filter=t,this.options=i,this.collected=new n,this.ended=!1,this._timeout=null,this._idletimeout=null,this.handleCollect=this.handleCollect.bind(this),this.handleDispose=this.handleDispose.bind(this),i.time&&(this._timeout=this.client.setTimeout((()=>this.stop("time")),i.time)),i.idle&&(this._idletimeout=this.client.setTimeout((()=>this.stop("idle")),i.idle))}async handleCollect(...e){const t=this.collect(...e);t&&await this.filter(...e,this.collected)&&(this.collected.set(t,e[0]),this.emit("collect",...e),this._idletimeout&&(this.client.clearTimeout(this._idletimeout),this._idletimeout=this.client.setTimeout((()=>this.stop("idle")),this.options.idle))),this.checkEnd()}handleDispose(...e){if(!this.options.dispose)return;const t=this.dispose(...e);t&&this.filter(...e)&&this.collected.has(t)&&(this.collected.delete(t),this.emit("dispose",...e),this.checkEnd())}get next(){return new Promise(((e,t)=>{if(this.ended)return void t(this.collected);const cleanup=()=>{this.removeListener("collect",onCollect),this.removeListener("end",onEnd)},onCollect=t=>{cleanup(),e(t)},onEnd=()=>{cleanup(),t(this.collected)};this.on("collect",onCollect),this.on("end",onEnd)}))}stop(e="user"){this.ended||(this._timeout&&(this.client.clearTimeout(this._timeout),this._timeout=null),this._idletimeout&&(this.client.clearTimeout(this._idletimeout),this._idletimeout=null),this.ended=!0,this.emit("end",this.collected,e))}resetTimer({time:e,idle:t}={}){this._timeout&&(this.client.clearTimeout(this._timeout),this._timeout=this.client.setTimeout((()=>this.stop("time")),e||this.options.time)),this._idletimeout&&(this.client.clearTimeout(this._idletimeout),this._idletimeout=this.client.setTimeout((()=>this.stop("idle")),t||this.options.idle))}checkEnd(){const e=this.endReason();e&&this.stop(e)}async*[Symbol.asyncIterator](){const e=[],onCollect=t=>e.push(t);this.on("collect",onCollect);try{for(;e.length||!this.ended;)e.length?yield e.shift():await new Promise((e=>{const tick=()=>(this.removeListener("collect",tick),this.removeListener("end",tick),e());this.on("collect",tick),this.on("end",tick)}))}finally{this.removeListener("collect",onCollect)}}toJSON(){return r.flatten(this)}collect(){}dispose(){}endReason(){}}e.exports=Collector},function(e,t,i){"use strict";const s=i(74),n=i(51);e.exports=class ClientApplication extends n{_patch(e){super._patch(e),this.cover=e.cover_image||null,this.rpcOrigins=e.rpc_origins||[],this.botRequireCodeGrant=void 0!==e.bot_require_code_grant?e.bot_require_code_grant:null,this.botPublic=void 0!==e.bot_public?e.bot_public:null,this.owner=e.team?new s(this.client,e.team):e.owner?this.client.users.add(e.owner):null}}},function(e,t,i){"use strict";const{ClientApplicationAssetTypes:s,Endpoints:n}=i(0),r=i(6),o=i(5),a=Object.keys(s);e.exports=class Application extends o{constructor(e,t){super(e),this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.description=e.description,this.icon=e.icon}get createdTimestamp(){return r.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}iconURL({format:e,size:t}={}){return this.icon?this.client.rest.cdn.AppIcon(this.id,this.icon,{format:e,size:t}):null}coverImage({format:e,size:t}={}){return this.cover?n.CDN(this.client.options.http.cdn).AppIcon(this.id,this.cover,{format:e,size:t}):null}fetchAssets(){return this.client.api.oauth2.applications(this.id).assets.get().then((e=>e.map((e=>({id:e.id,name:e.name,type:a[e.type-1]})))))}toString(){return this.name}toJSON(){return super.toJSON({createdTimestamp:!0})}}},function(e,t,i){"use strict";const s=i(25),n=i(53),r=i(79),o=i(4);e.exports=class MessageReaction{constructor(e,t,i){Object.defineProperty(this,"client",{value:e}),this.message=i,this.users=new r(e,void 0,this),this._emoji=new n(this,t.emoji),this._patch(t)}_patch(e){null==this.count&&(this.count=e.count),this.me=e.me}async remove(){return await this.client.api.channels(this.message.channel.id).messages(this.message.id).reactions(this._emoji.identifier).delete(),this}get emoji(){if(this._emoji instanceof s)return this._emoji;if(this._emoji.id){const e=this.message.client.emojis.cache;if(e.has(this._emoji.id)){const t=e.get(this._emoji.id);return this._emoji=t,t}}return this._emoji}get partial(){return null===this.count}async fetch(){const e=(await this.message.fetch()).reactions.cache.get(this.emoji.id||this.emoji.name);return this._patch(e||{count:0}),this}toJSON(){return o.flatten(this,{emoji:"emojiID",message:"messageID"})}_add(e){this.partial||(this.users.cache.set(e.id,e),this.me&&e.id===this.message.client.user.id&&0!==this.count||this.count++,this.me||(this.me=e.id===this.message.client.user.id))}_remove(e){this.partial||(this.users.cache.delete(e.id),this.me&&e.id===this.message.client.user.id||this.count--,e.id===this.message.client.user.id&&(this.me=!1),this.count<=0&&0===this.users.cache.size&&this.message.reactions.cache.delete(this.emoji.id||this.emoji.name))}}},function(e,t,i){"use strict";const s=i(29),n=i(4);e.exports=class ReactionEmoji extends s{constructor(e,t){super(e.message.client,t),this.reaction=e}toJSON(){return n.flatten(this,{identifier:!0})}valueOf(){return this.id}}},function(e,t,i){"use strict";(function(t){const{deprecate:s}=i(85),n=i(5),r=i(86),o=i(56),a=i(57),c=i(55),l=i(19),h=i(58),u=i(13),{Error:d,TypeError:f}=i(2),p=i(87),m=i(59),g=i(88),E=i(89),_=i(91),y=i(142),b=i(3),{browser:v,ChannelTypes:w,DefaultMessageNotifications:S,PartialTypes:I,VerificationLevels:A,ExplicitContentFilterLevels:T}=i(0),D=i(9),R=i(6),N=i(92),L=i(4);class Guild extends n{constructor(e,t){super(e),this.members=new g(this),this.channels=new p(this),this.roles=new _(this),this.presences=new E(this.client),this.voiceStates=new y(this),this.deleted=!1,t&&(t.unavailable?(this.available=!1,this.id=t.id):(this._patch(t),t.channels||(this.available=!1)),this.shardID=t.shardID)}get shard(){return this.client.ws.shards.get(this.shardID)}_patch(e){if(this.name=e.name,this.icon=e.icon,this.splash=e.splash,this.discoverySplash=e.discovery_splash,this.region=e.region,this.memberCount=e.member_count||this.memberCount,this.large=Boolean("large"in e?e.large:this.large),this.features=e.features,this.applicationID=e.application_id,this.afkTimeout=e.afk_timeout,this.afkChannelID=e.afk_channel_id,this.systemChannelID=e.system_channel_id,this.embedEnabled=e.embed_enabled,this.premiumTier=e.premium_tier,void 0!==e.premium_subscription_count&&(this.premiumSubscriptionCount=e.premium_subscription_count),void 0!==e.widget_enabled&&(this.widgetEnabled=e.widget_enabled),void 0!==e.widget_channel_id&&(this.widgetChannelID=e.widget_channel_id),void 0!==e.embed_channel_id&&(this.embedChannelID=e.embed_channel_id),this.verificationLevel=A[e.verification_level],this.explicitContentFilter=T[e.explicit_content_filter],this.mfaLevel=e.mfa_level,this.joinedTimestamp=e.joined_at?new Date(e.joined_at).getTime():this.joinedTimestamp,this.defaultMessageNotifications=S[e.default_message_notifications]||e.default_message_notifications,this.systemChannelFlags=new N(e.system_channel_flags).freeze(),void 0!==e.max_members?this.maximumMembers=e.max_members:void 0===this.maximumMembers&&(this.maximumMembers=null),void 0!==e.max_presences?this.maximumPresences=e.max_presences||25e3:void 0===this.maximumPresences&&(this.maximumPresences=null),void 0!==e.approximate_member_count?this.approximateMemberCount=e.approximate_member_count:void 0===this.approximateMemberCount&&(this.approximateMemberCount=null),void 0!==e.approximate_presence_count?this.approximatePresenceCount=e.approximate_presence_count:void 0===this.approximatePresenceCount&&(this.approximatePresenceCount=null),this.vanityURLCode=e.vanity_url_code,this.vanityURLUses=null,this.description=e.description,this.banner=e.banner,this.id=e.id,this.available=!e.unavailable,this.features=e.features||this.features||[],this.rulesChannelID=e.rules_channel_id,this.publicUpdatesChannelID=e.public_updates_channel_id,this.preferredLocale=e.preferred_locale,e.channels){this.channels.cache.clear();for(const t of e.channels)this.client.channels.add(t,this)}if(e.roles){this.roles.cache.clear();for(const t of e.roles)this.roles.add(t)}if(e.members){this.members.cache.clear();for(const t of e.members)this.members.add(t)}if(e.owner_id&&(this.ownerID=e.owner_id),e.presences)for(const t of e.presences)this.presences.add(Object.assign(t,{guild:this}));if(e.voice_states){this.voiceStates.cache.clear();for(const t of e.voice_states)this.voiceStates.add(t)}if(this.emojis)e.emojis&&this.client.actions.GuildEmojisUpdate.handle({guild_id:this.id,emojis:e.emojis});else if(this.emojis=new m(this),e.emojis)for(const t of e.emojis)this.emojis.add(t)}bannerURL({format:e,size:t}={}){return this.banner?this.client.rest.cdn.Banner(this.id,this.banner,e,t):null}get createdTimestamp(){return R.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get joinedAt(){return new Date(this.joinedTimestamp)}get partnered(){return this.features.includes("PARTNERED")}get verified(){return this.features.includes("VERIFIED")}iconURL({format:e,size:t,dynamic:i}={}){return this.icon?this.client.rest.cdn.Icon(this.id,this.icon,e,t,i):null}get nameAcronym(){return this.name.replace(/'s /g," ").replace(/\w+/g,(e=>e[0])).replace(/\s/g,"")}splashURL({format:e,size:t}={}){return this.splash?this.client.rest.cdn.Splash(this.id,this.splash,e,t):null}discoverySplashURL({format:e,size:t}={}){return this.discoverySplash?this.client.rest.cdn.DiscoverySplash(this.id,this.discoverySplash,e,t):null}get owner(){return this.members.cache.get(this.ownerID)||(this.client.options.partials.includes(I.GUILD_MEMBER)?this.members.add({user:{id:this.ownerID}},!0):null)}get afkChannel(){return this.client.channels.cache.get(this.afkChannelID)||null}get systemChannel(){return this.client.channels.cache.get(this.systemChannelID)||null}get widgetChannel(){return this.client.channels.cache.get(this.widgetChannelID)||null}get embedChannel(){return this.client.channels.cache.get(this.embedChannelID)||null}get rulesChannel(){return this.client.channels.cache.get(this.rulesChannelID)||null}get publicUpdatesChannel(){return this.client.channels.cache.get(this.publicUpdatesChannelID)||null}get me(){return this.members.cache.get(this.client.user.id)||(this.client.options.partials.includes(I.GUILD_MEMBER)?this.members.add({user:{id:this.client.user.id}},!0):null)}get voice(){return this.voiceStates.cache.get(this.client.user.id)}member(e){return this.members.resolve(e)}fetch(){return this.client.api.guilds(this.id).get({query:{with_counts:!0}}).then((e=>(this._patch(e),this)))}fetchBan(e){const t=this.client.users.resolveID(e);if(!t)throw new d("FETCH_BAN_RESOLVE_ID");return this.client.api.guilds(this.id).bans(t).get().then((e=>({reason:e.reason,user:this.client.users.add(e.user)})))}fetchBans(){return this.client.api.guilds(this.id).bans.get().then((e=>e.reduce(((e,t)=>(e.set(t.user.id,{reason:t.reason,user:this.client.users.add(t.user)}),e)),new b)))}fetchIntegrations({includeApplications:e=!1}={}){return this.client.api.guilds(this.id).integrations.get({query:{include_applications:e}}).then((e=>e.reduce(((e,t)=>e.set(t.id,new c(this.client,t,this))),new b)))}fetchTemplates(){return this.client.api.guilds(this.id).templates.get().then((e=>e.reduce(((e,t)=>e.set(t.code,new a(this.client,t))),new b)))}createIntegration(e,t){return this.client.api.guilds(this.id).integrations.post({data:e,reason:t}).then((()=>this))}createTemplate(e,t){return this.client.api.guilds(this.id).templates.post({data:{name:e,description:t}}).then((e=>new a(this.client,e)))}fetchInvites(){return this.client.api.guilds(this.id).invites.get().then((e=>{const t=new b;for(const i of e){const e=new l(this.client,i);t.set(e.code,e)}return t}))}fetchPreview(){return this.client.api.guilds(this.id).preview.get().then((e=>new o(this.client,e)))}fetchVanityCode(){return this.fetchVanityData().then((e=>e.code))}async fetchVanityData(){if(!this.features.includes("VANITY_URL"))throw new d("VANITY_URL");const e=await this.client.api.guilds(this.id,"vanity-url").get();return this.vanityURLUses=e.uses,e}fetchWebhooks(){return this.client.api.guilds(this.id).webhooks.get().then((e=>{const t=new b;for(const i of e)t.set(i.id,new u(this.client,i));return t}))}fetchVoiceRegions(){return this.client.api.guilds(this.id).regions.get().then((e=>{const t=new b;for(const i of e)t.set(i.id,new h(i));return t}))}fetchEmbed(){return this.fetchWidget()}async fetchWidget(){const e=await this.client.api.guilds(this.id).widget.get();return this.widgetEnabled=this.embedEnabled=e.enabled,this.widgetChannelID=this.embedChannelID=e.channel_id,{enabled:e.enabled,channel:e.channel_id?this.channels.cache.get(e.channel_id):null}}fetchAuditLogs(e={}){return e.before&&e.before instanceof r.Entry&&(e.before=e.before.id),"string"==typeof e.type&&(e.type=r.Actions[e.type]),this.client.api.guilds(this.id)["audit-logs"].get({query:{before:e.before,limit:e.limit,user_id:this.client.users.resolveID(e.user),action_type:e.type}}).then((e=>r.build(this,e)))}async addMember(e,i){if(!(e=this.client.users.resolveID(e)))throw new f("INVALID_TYPE","user","UserResolvable");if(this.members.cache.has(e))return this.members.cache.get(e);if(i.access_token=i.accessToken,i.roles){const e=[];for(let t of i.roles instanceof b?i.roles.values():i.roles){if(t=this.roles.resolve(t),!t)throw new f("INVALID_TYPE","options.roles","Array or Collection of Roles or Snowflakes",!0);e.push(t.id)}i.roles=e}const s=await this.client.api.guilds(this.id).members(e).put({data:i});return s instanceof(v?ArrayBuffer:t)?this.members.fetch(e):this.members.add(s)}edit(e,t){const i={};return e.name&&(i.name=e.name),e.region&&(i.region=e.region),void 0!==e.verificationLevel&&(i.verification_level="number"==typeof e.verificationLevel?Number(e.verificationLevel):A.indexOf(e.verificationLevel)),void 0!==e.afkChannel&&(i.afk_channel_id=this.client.channels.resolveID(e.afkChannel)),void 0!==e.systemChannel&&(i.system_channel_id=this.client.channels.resolveID(e.systemChannel)),e.afkTimeout&&(i.afk_timeout=Number(e.afkTimeout)),void 0!==e.icon&&(i.icon=e.icon),e.owner&&(i.owner_id=this.client.users.resolveID(e.owner)),e.splash&&(i.splash=e.splash),e.discoverySplash&&(i.discovery_splash=e.discoverySplash),e.banner&&(i.banner=e.banner),void 0!==e.explicitContentFilter&&(i.explicit_content_filter="number"==typeof e.explicitContentFilter?e.explicitContentFilter:T.indexOf(e.explicitContentFilter)),void 0!==e.defaultMessageNotifications&&(i.default_message_notifications="string"==typeof e.defaultMessageNotifications?S.indexOf(e.defaultMessageNotifications):e.defaultMessageNotifications),void 0!==e.systemChannelFlags&&(i.system_channel_flags=N.resolve(e.systemChannelFlags)),void 0!==e.rulesChannel&&(i.rules_channel_id=this.client.channels.resolveID(e.rulesChannel)),void 0!==e.publicUpdatesChannel&&(i.public_updates_channel_id=this.client.channels.resolveID(e.publicUpdatesChannel)),e.preferredLocale&&(i.preferred_locale=e.preferredLocale),this.client.api.guilds(this.id).patch({data:i,reason:t}).then((e=>this.client.actions.GuildUpdate.handle(e).updated))}setExplicitContentFilter(e,t){return this.edit({explicitContentFilter:e},t)}setDefaultMessageNotifications(e,t){return this.edit({defaultMessageNotifications:e},t)}setSystemChannelFlags(e,t){return this.edit({systemChannelFlags:e},t)}setName(e,t){return this.edit({name:e},t)}setRegion(e,t){return this.edit({region:e},t)}setVerificationLevel(e,t){return this.edit({verificationLevel:e},t)}setAFKChannel(e,t){return this.edit({afkChannel:e},t)}setSystemChannel(e,t){return this.edit({systemChannel:e},t)}setAFKTimeout(e,t){return this.edit({afkTimeout:e},t)}async setIcon(e,t){return this.edit({icon:await D.resolveImage(e),reason:t})}setOwner(e,t){return this.edit({owner:e},t)}async setSplash(e,t){return this.edit({splash:await D.resolveImage(e),reason:t})}async setDiscoverySplash(e,t){return this.edit({discoverySplash:await D.resolveImage(e),reason:t})}async setBanner(e,t){return this.edit({banner:await D.resolveImage(e),reason:t})}setRulesChannel(e,t){return this.edit({rulesChannel:e},t)}setPublicUpdatesChannel(e,t){return this.edit({publicUpdatesChannel:e},t)}setPreferredLocale(e,t){return this.edit({preferredLocale:e},t)}setChannelPositions(e){const t=e.map((e=>({id:this.client.channels.resolveID(e.channel),position:e.position})));return this.client.api.guilds(this.id).channels.patch({data:t}).then((()=>this.client.actions.GuildChannelsPositionUpdate.handle({guild_id:this.id,channels:t}).guild))}setRolePositions(e){return e=e.map((e=>({id:this.roles.resolveID(e.role),position:e.position}))),this.client.api.guilds(this.id).roles.patch({data:e}).then((()=>this.client.actions.GuildRolesPositionUpdate.handle({guild_id:this.id,roles:e}).guild))}setEmbed(e,t){return this.setWidget(e,t)}setWidget(e,t){return this.client.api.guilds(this.id).widget.patch({data:{enabled:e.enabled,channel_id:this.channels.resolveID(e.channel)},reason:t}).then((()=>this))}leave(){return this.ownerID===this.client.user.id?Promise.reject(new d("GUILD_OWNED")):this.client.api.users("@me").guilds(this.id).delete().then((()=>this.client.actions.GuildDelete.handle({id:this.id}).guild))}delete(){return this.client.api.guilds(this.id).delete().then((()=>this.client.actions.GuildDelete.handle({id:this.id}).guild))}equals(e){let t=e&&e instanceof this.constructor&&this.id===e.id&&this.available===e.available&&this.splash===e.splash&&this.discoverySplash===e.discoverySplash&&this.region===e.region&&this.name===e.name&&this.memberCount===e.memberCount&&this.large===e.large&&this.icon===e.icon&&this.ownerID===e.ownerID&&this.verificationLevel===e.verificationLevel&&this.embedEnabled===e.embedEnabled&&(this.features===e.features||this.features.length===e.features.length&&this.features.every(((t,i)=>t===e.features[i])));return t&&(this.embedChannel?e.embedChannel&&this.embedChannel.id===e.embedChannel.id||(t=!1):e.embedChannel&&(t=!1)),t}toString(){return this.name}toJSON(){const e=super.toJSON({available:!1,createdTimestamp:!0,nameAcronym:!0,presences:!1,voiceStates:!1});return e.iconURL=this.iconURL(),e.splashURL=this.splashURL(),e.discoverySplashURL=this.discoverySplashURL(),e.bannerURL=this.bannerURL(),e}_sortedRoles(){return L.discordSort(this.roles.cache)}_sortedChannels(e){const t=e.type===w.CATEGORY;return L.discordSort(this.channels.cache.filter((i=>(["text","news","store"].includes(e.type)?["text","news","store"].includes(i.type):i.type===e.type)&&(t||i.parent===e.parent))))}}Guild.prototype.setEmbed=s(Guild.prototype.setEmbed,"Guild#setEmbed: Use setWidget instead"),Guild.prototype.fetchEmbed=s(Guild.prototype.fetchEmbed,"Guild#fetchEmbed: Use fetchWidget instead"),Guild.prototype.fetchVanityCode=s(Guild.prototype.fetchVanityCode,"Guild#fetchVanityCode: Use fetchVanityData() instead"),e.exports=Guild}).call(this,i(14).Buffer)},function(e,t,i){"use strict";const s=i(5),n=i(140);e.exports=class Integration extends s{constructor(e,t,i){super(e),this.guild=i,this.id=t.id,this.name=t.name,this.type=t.type,this.enabled=t.enabled,this.syncing=t.syncing,this.role=this.guild.roles.cache.get(t.role_id),t.user?this.user=this.client.users.add(t.user):this.user=null,this.account=t.account,this.syncedAt=t.synced_at,this._patch(t)}_patch(e){this.expireBehavior=e.expire_behavior,this.expireGracePeriod=e.expire_grace_period,"application"in e?this.application?this.application._patch(e.application):this.application=new n(this.client,e.application):this.application||(this.application=null)}sync(){return this.syncing=!0,this.client.api.guilds(this.guild.id).integrations(this.id).post().then((()=>(this.syncing=!1,this.syncedAt=Date.now(),this)))}edit(e,t){return"expireBehavior"in e&&(e.expire_behavior=e.expireBehavior,e.expireBehavior=null),"expireGracePeriod"in e&&(e.expire_grace_period=e.expireGracePeriod,e.expireGracePeriod=null),this.client.api.guilds(this.guild.id).integrations(this.id).patch({data:e,reason:t}).then((()=>(this._patch(e),this)))}delete(e){return this.client.api.guilds(this.guild.id).integrations(this.id).delete({reason:e}).then((()=>this))}toJSON(){return super.toJSON({role:"roleID",guild:"guildID",user:"userID"})}}},function(e,t,i){"use strict";const s=i(5),n=i(141),r=i(3);e.exports=class GuildPreview extends s{constructor(e,t){super(e),t&&this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.icon=e.icon,this.splash=e.splash,this.discoverySplash=e.discovery_splash,this.features=e.features,this.approximateMemberCount=e.approximate_member_count,this.approximatePresenceCount=e.approximate_presence_count,this.description=e.description||null,this.emojis?this.emojis.clear():this.emojis=new r;for(const t of e.emojis)this.emojis.set(t.id,new n(this.client,t,this))}splashURL({format:e,size:t}={}){return this.splash?this.client.rest.cdn.Splash(this.id,this.splash,e,t):null}discoverySplashURL({format:e,size:t}={}){return this.discoverySplash?this.client.rest.cdn.DiscoverySplash(this.id,this.discoverySplash,e,t):null}iconURL({format:e,size:t,dynamic:i}={}){return this.icon?this.client.rest.cdn.Icon(this.id,this.icon,e,t,i):null}fetch(){return this.client.api.guilds(this.id).preview.get().then((e=>(this._patch(e),this)))}toString(){return this.name}toJSON(){const e=super.toJSON();return e.iconURL=this.iconURL(),e.splashURL=this.splashURL(),e}}},function(e,t,i){"use strict";const s=i(5),{Events:n}=i(0),r=i(9);e.exports=class GuildTemplate extends s{constructor(e,t){super(e),this._patch(t)}_patch(e){return this.code=e.code,this.name=e.name,this.description=e.description,this.usageCount=e.usage_count,this.creatorID=e.creator_id,this.creator=this.client.users.add(e.creator),this.createdAt=new Date(e.created_at),this.updatedAt=new Date(e.updated_at),this.guildID=e.source_guild_id,this.serializedGuild=e.serialized_source_guild,this.unSynced="is_dirty"in e?Boolean(e.is_dirty):null,this}async createGuild(e,t){const{client:i}=this,s=await i.api.guilds.templates(this.code).post({data:{name:e,icon:await r.resolveImage(t)}});return new Promise((e=>{const t=i.guilds.cache.get(s.id);if(t)return e(t);const resolveGuild=t=>{i.off(n.GUILD_CREATE,handleGuild),i.decrementMaxListeners(),e(t)},handleGuild=e=>{e.id===s.id&&(i.clearTimeout(r),resolveGuild(e))};i.incrementMaxListeners(),i.on(n.GUILD_CREATE,handleGuild);const r=i.setTimeout((()=>resolveGuild(i.guilds.add(s))),1e4)}))}edit({name:e,description:t}={}){return this.client.api.guilds(this.guildID).templates(this.code).patch({data:{name:e,description:t}}).then((e=>this._patch(e)))}delete(){return this.client.api.guilds(this.guildID).templates(this.code).delete().then((()=>this))}sync(){return this.client.api.guilds(this.guildID).templates(this.code).put().then((e=>this._patch(e)))}get createdTimestamp(){return this.createdAt.getTime()}get updatedTimestamp(){return this.updatedAt.getTime()}get guild(){return this.client.guilds.cache.get(this.guildID)||null}get url(){return`${this.client.options.http.template}/${this.code}`}toString(){return this.code}}},function(e,t,i){"use strict";const s=i(4);e.exports=class VoiceRegion{constructor(e){this.id=e.id,this.name=e.name,this.vip=e.vip,this.deprecated=e.deprecated,this.optimal=e.optimal,this.custom=e.custom}toJSON(){return s.flatten(this)}}},function(e,t,i){"use strict";const s=i(7),{TypeError:n}=i(2),r=i(25),o=i(53),a=i(3),c=i(9),{parseEmoji:l}=i(4);e.exports=class GuildEmojiManager extends s{constructor(e,t){super(e.client,t,r),this.guild=e}add(e,t){return super.add(e,t,{extras:[this.guild]})}async create(e,t,{roles:i,reason:s}={}){if(!(e=await c.resolveImage(e)))throw new n("REQ_RESOURCE_TYPE");const r={image:e,name:t};if(i){r.roles=[];for(let e of i instanceof a?i.values():i){if(e=this.guild.roles.resolve(e),!e)return Promise.reject(new n("INVALID_TYPE","options.roles","Array or Collection of Roles or Snowflakes",!0));r.roles.push(e.id)}}return this.client.api.guilds(this.guild.id).emojis.post({data:r,reason:s}).then((e=>this.client.actions.GuildEmojiCreate.handle(this.guild,e).emoji))}resolve(e){return e instanceof o?super.resolve(e.id):super.resolve(e)}resolveID(e){return e instanceof o?e.id:super.resolveID(e)}resolveIdentifier(e){const t=this.resolve(e);if(t)return t.identifier;if(e instanceof o)return e.identifier;if("string"==typeof e){const t=l(e);return t&&t.name.length&&(e=`${t.animated?"a:":""}${t.name}${t.id?":"+t.id:""}`),e.includes("%")?e:encodeURIComponent(e)}return null}}},function(e,t){var i={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==i.call(e)}},function(e,t){e.exports={version:"12.5.3",homepage:"https://github.com/discordjs/discord.js#readme"}},function(e,t,i){"use strict";const s=Symbol("code"),n=new Map;function makeDiscordjsError(e){return class DiscordjsError extends e{constructor(e,...t){super(function message(e,t){if("string"!=typeof e)throw new Error("Error message key must be a string");const i=n.get(e);if(!i)throw new Error(`An invalid error message key was used: ${e}.`);return"function"==typeof i?i(...t):void 0===t||0===t.length?i:(t.unshift(i),String(...t))}(e,t)),this[s]=e,Error.captureStackTrace&&Error.captureStackTrace(this,DiscordjsError)}get name(){return`${super.name} [${this[s]}]`}get code(){return this[s]}}}e.exports={register:function register(e,t){n.set(e,"function"==typeof t?t:String(t))},Error:makeDiscordjsError(Error),TypeError:makeDiscordjsError(TypeError),RangeError:makeDiscordjsError(RangeError)}},function(e,t,i){(function(e,t){!function(e,i){"use strict";if(!e.setImmediate){var s,n=1,r={},o=!1,a=e.document,c=Object.getPrototypeOf&&Object.getPrototypeOf(e);c=c&&c.setTimeout?c:e,"[object process]"==={}.toString.call(e.process)?function installNextTickImplementation(){s=function(e){t.nextTick((function(){runIfPresent(e)}))}}():!function canUsePostMessage(){if(e.postMessage&&!e.importScripts){var t=!0,i=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=i,t}}()?e.MessageChannel?function installMessageChannelImplementation(){var e=new MessageChannel;e.port1.onmessage=function(e){runIfPresent(e.data)},s=function(t){e.port2.postMessage(t)}}():a&&"onreadystatechange"in a.createElement("script")?function installReadyStateChangeImplementation(){var e=a.documentElement;s=function(t){var i=a.createElement("script");i.onreadystatechange=function(){runIfPresent(t),i.onreadystatechange=null,e.removeChild(i),i=null},e.appendChild(i)}}():function installSetTimeoutImplementation(){s=function(e){setTimeout(runIfPresent,0,e)}}():function installPostMessageImplementation(){var t="setImmediate$"+Math.random()+"$",onGlobalMessage=function(i){i.source===e&&"string"==typeof i.data&&0===i.data.indexOf(t)&&runIfPresent(+i.data.slice(t.length))};e.addEventListener?e.addEventListener("message",onGlobalMessage,!1):e.attachEvent("onmessage",onGlobalMessage),s=function(i){e.postMessage(t+i,"*")}}(),c.setImmediate=function setImmediate(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),i=0;ie.message)).join(" ")}`):n.code||n.message?i.push(`${n.code?n.code+": ":""}${n.message}`.trim()):"string"==typeof n?i.push(n):i=i.concat(this.flattenErrors(n,e))}return i}}e.exports=DiscordAPIError},function(e,t,i){"use strict";class HTTPError extends Error{constructor(e,t,i,s,n){super(e),this.name=t,this.code=i||500,this.method=s,this.path=n}}e.exports=HTTPError},function(e,t,i){"use strict";const{TypeError:s}=i(2),n=i(3);e.exports=class GuildEmojiRoleManager{constructor(e){this.emoji=e,this.guild=e.guild,Object.defineProperty(this,"client",{value:e.client})}get _roles(){return this.guild.roles.cache.filter((e=>this.emoji._roles.includes(e.id)))}get cache(){return this._roles}add(e){if(e instanceof n)return this.add(e.keyArray());if(!Array.isArray(e))return this.add([e]);if((e=e.map((e=>this.guild.roles.resolve(e)))).includes(null))return Promise.reject(new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0));const t=[...new Set(e.concat(...this._roles.values()))];return this.set(t)}remove(e){if(e instanceof n)return this.remove(e.keyArray());if(!Array.isArray(e))return this.remove([e]);if((e=e.map((e=>this.guild.roles.resolveID(e)))).includes(null))return Promise.reject(new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0));const t=this._roles.keyArray().filter((t=>!e.includes(t)));return this.set(t)}set(e){return this.emoji.edit({roles:e})}clone(){const e=new this.constructor(this.emoji);return e._patch(this._roles.keyArray().slice()),e}_patch(e){this.emoji._roles=e}}},function(e,t,i){"use strict";(function(t,s){var n=i(31);e.exports=Readable;var r,o=i(60);Readable.ReadableState=ReadableState;i(16).EventEmitter;var EElistenerCount=function(e,t){return e.listeners(t).length},a=i(68),c=i(32).Buffer,l=t.Uint8Array||function(){};var h=Object.create(i(26));h.inherits=i(23);var u=i(128),d=void 0;d=u&&u.debuglog?u.debuglog("stream"):function(){};var f,p=i(129),m=i(69);h.inherits(Readable,a);var g=["error","close","destroy","pause","resume"];function ReadableState(e,t){e=e||{};var s=t instanceof(r=r||i(21));this.objectMode=!!e.objectMode,s&&(this.objectMode=this.objectMode||!!e.readableObjectMode);var n=e.highWaterMark,o=e.readableHighWaterMark,a=this.objectMode?16:16384;this.highWaterMark=n||0===n?n:s&&(o||0===o)?o:a,this.highWaterMark=Math.floor(this.highWaterMark),this.buffer=new p,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(f||(f=i(70).StringDecoder),this.decoder=new f(e.encoding),this.encoding=e.encoding)}function Readable(e){if(r=r||i(21),!(this instanceof Readable))return new Readable(e);this._readableState=new ReadableState(e,this),this.readable=!0,e&&("function"==typeof e.read&&(this._read=e.read),"function"==typeof e.destroy&&(this._destroy=e.destroy)),a.call(this)}function readableAddChunk(e,t,i,s,n){var r,o=e._readableState;null===t?(o.reading=!1,function onEofChunk(e,t){if(t.ended)return;if(t.decoder){var i=t.decoder.end();i&&i.length&&(t.buffer.push(i),t.length+=t.objectMode?1:i.length)}t.ended=!0,emitReadable(e)}(e,o)):(n||(r=function chunkInvalid(e,t){var i;(function _isUint8Array(e){return c.isBuffer(e)||e instanceof l})(t)||"string"==typeof t||void 0===t||e.objectMode||(i=new TypeError("Invalid non-string/buffer chunk"));return i}(o,t)),r?e.emit("error",r):o.objectMode||t&&t.length>0?("string"==typeof t||o.objectMode||Object.getPrototypeOf(t)===c.prototype||(t=function _uint8ArrayToBuffer(e){return c.from(e)}(t)),s?o.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):addChunk(e,o,t,!0):o.ended?e.emit("error",new Error("stream.push() after EOF")):(o.reading=!1,o.decoder&&!i?(t=o.decoder.write(t),o.objectMode||0!==t.length?addChunk(e,o,t,!1):maybeReadMore(e,o)):addChunk(e,o,t,!1))):s||(o.reading=!1));return function needMoreData(e){return!e.ended&&(e.needReadable||e.lengtht.highWaterMark&&(t.highWaterMark=function computeNewHighWaterMark(e){return e>=E?e=E:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function emitReadable(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(d("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?n.nextTick(emitReadable_,e):emitReadable_(e))}function emitReadable_(e){d("emit readable"),e.emit("readable"),flow(e)}function maybeReadMore(e,t){t.readingMore||(t.readingMore=!0,n.nextTick(maybeReadMore_,e,t))}function maybeReadMore_(e,t){for(var i=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(i=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):i=function fromListPartial(e,t,i){var s;er.length?r.length:e;if(o===r.length?n+=r:n+=r.slice(0,e),0===(e-=o)){o===r.length?(++s,i.next?t.head=i.next:t.head=t.tail=null):(t.head=i,i.data=r.slice(o));break}++s}return t.length-=s,n}(e,t):function copyFromBuffer(e,t){var i=c.allocUnsafe(e),s=t.head,n=1;s.data.copy(i),e-=s.data.length;for(;s=s.next;){var r=s.data,o=e>r.length?r.length:e;if(r.copy(i,i.length-e,0,o),0===(e-=o)){o===r.length?(++n,s.next?t.head=s.next:t.head=t.tail=null):(t.head=s,s.data=r.slice(o));break}++n}return t.length-=n,i}(e,t);return s}(e,t.buffer,t.decoder),i);var i}function endReadable(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,n.nextTick(endReadableNT,t,e))}function endReadableNT(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function indexOf(e,t){for(var i=0,s=e.length;i=t.highWaterMark||t.ended))return d("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?endReadable(this):emitReadable(this),null;if(0===(e=howMuchToRead(e,t))&&t.ended)return 0===t.length&&endReadable(this),null;var s,n=t.needReadable;return d("need readable",n),(0===t.length||t.length-e0?fromList(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),i!==e&&t.ended&&endReadable(this)),null!==s&&this.emit("data",s),s},Readable.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},Readable.prototype.pipe=function(e,t){var i=this,r=this._readableState;switch(r.pipesCount){case 0:r.pipes=e;break;case 1:r.pipes=[r.pipes,e];break;default:r.pipes.push(e)}r.pipesCount+=1,d("pipe count=%d opts=%j",r.pipesCount,t);var a=(!t||!1!==t.end)&&e!==s.stdout&&e!==s.stderr?onend:unpipe;function onunpipe(t,s){d("onunpipe"),t===i&&s&&!1===s.hasUnpiped&&(s.hasUnpiped=!0,function cleanup(){d("cleanup"),e.removeListener("close",onclose),e.removeListener("finish",onfinish),e.removeListener("drain",c),e.removeListener("error",onerror),e.removeListener("unpipe",onunpipe),i.removeListener("end",onend),i.removeListener("end",unpipe),i.removeListener("data",ondata),l=!0,!r.awaitDrain||e._writableState&&!e._writableState.needDrain||c()}())}function onend(){d("onend"),e.end()}r.endEmitted?n.nextTick(a):i.once("end",a),e.on("unpipe",onunpipe);var c=function pipeOnDrain(e){return function(){var t=e._readableState;d("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&EElistenerCount(e,"data")&&(t.flowing=!0,flow(e))}}(i);e.on("drain",c);var l=!1;var h=!1;function ondata(t){d("ondata"),h=!1,!1!==e.write(t)||h||((1===r.pipesCount&&r.pipes===e||r.pipesCount>1&&-1!==indexOf(r.pipes,e))&&!l&&(d("false write response, pause",i._readableState.awaitDrain),i._readableState.awaitDrain++,h=!0),i.pause())}function onerror(t){d("onerror",t),unpipe(),e.removeListener("error",onerror),0===EElistenerCount(e,"error")&&e.emit("error",t)}function onclose(){e.removeListener("finish",onfinish),unpipe()}function onfinish(){d("onfinish"),e.removeListener("close",onclose),unpipe()}function unpipe(){d("unpipe"),i.unpipe(e)}return i.on("data",ondata),function prependListener(e,t,i){if("function"==typeof e.prependListener)return e.prependListener(t,i);e._events&&e._events[t]?o(e._events[t])?e._events[t].unshift(i):e._events[t]=[i,e._events[t]]:e.on(t,i)}(e,"error",onerror),e.once("close",onclose),e.once("finish",onfinish),e.emit("pipe",i),r.flowing||(d("pipe resume"),i.resume()),e},Readable.prototype.unpipe=function(e){var t=this._readableState,i={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes||(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,i)),this;if(!e){var s=t.pipes,n=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var r=0;r>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function utf8FillLast(e){var t=this.lastTotal-this.lastNeed,i=function utf8CheckExtraBytes(e,t,i){if(128!=(192&t[0]))return e.lastNeed=0,"οΏ½";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"οΏ½";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"οΏ½"}}(this,e);return void 0!==i?i:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function utf16Text(e,t){if((e.length-t)%2==0){var i=e.toString("utf16le",t);if(i){var s=i.charCodeAt(i.length-1);if(s>=55296&&s<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],i.slice(0,-1)}return i}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function utf16End(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var i=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,i)}return t}function base64Text(e,t){var i=(e.length-t)%3;return 0===i?e.toString("base64",t):(this.lastNeed=3-i,this.lastTotal=3,1===i?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-i))}function base64End(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function simpleWrite(e){return e.toString(this.encoding)}function simpleEnd(e){return e&&e.length?this.write(e):""}t.StringDecoder=StringDecoder,StringDecoder.prototype.write=function(e){if(0===e.length)return"";var t,i;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";i=this.lastNeed,this.lastNeed=0}else i=0;return i=0)return n>0&&(e.lastNeed=n-1),n;if(--s=0)return n>0&&(e.lastNeed=n-2),n;if(--s=0)return n>0&&(2===n?n=0:e.lastNeed=n-3),n;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=i;var s=e.length-(i-this.lastNeed);return e.copy(this.lastChar,0,s),e.toString("utf8",t,s)},StringDecoder.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,i){"use strict";e.exports=Transform;var s=i(21),n=Object.create(i(26));function afterTransform(e,t){var i=this._transformState;i.transforming=!1;var s=i.writecb;if(!s)return this.emit("error",new Error("write callback called multiple times"));i.writechunk=null,i.writecb=null,null!=t&&this.push(t),s(e);var n=this._readableState;n.reading=!1,(n.needReadable||n.length{for(const t of e.values())this.handleDispose(t)};this._handleChannelDeletion=this._handleChannelDeletion.bind(this),this._handleGuildDeletion=this._handleGuildDeletion.bind(this),this.client.incrementMaxListeners(),this.client.on(n.MESSAGE_CREATE,this.handleCollect),this.client.on(n.MESSAGE_DELETE,this.handleDispose),this.client.on(n.MESSAGE_BULK_DELETE,bulkDeleteListener),this.client.on(n.CHANNEL_DELETE,this._handleChannelDeletion),this.client.on(n.GUILD_DELETE,this._handleGuildDeletion),this.once("end",(()=>{this.client.removeListener(n.MESSAGE_CREATE,this.handleCollect),this.client.removeListener(n.MESSAGE_DELETE,this.handleDispose),this.client.removeListener(n.MESSAGE_BULK_DELETE,bulkDeleteListener),this.client.removeListener(n.CHANNEL_DELETE,this._handleChannelDeletion),this.client.removeListener(n.GUILD_DELETE,this._handleGuildDeletion),this.client.decrementMaxListeners()}))}collect(e){return e.channel.id!==this.channel.id?null:(this.received++,e.id)}dispose(e){return e.channel.id===this.channel.id?e.id:null}endReason(){return this.options.max&&this.collected.size>=this.options.max?"limit":this.options.maxProcessed&&this.received===this.options.maxProcessed?"processedLimit":null}_handleChannelDeletion(e){e.id===this.channel.id&&this.stop("channelDelete")}_handleGuildDeletion(e){this.channel.guild&&e.id===this.channel.guild.id&&this.stop("guildDelete")}}},function(e,t,i){"use strict";const{TypeError:s}=i(2),n=i(3);e.exports=class GuildMemberRoleManager{constructor(e){this.member=e,this.guild=e.guild,Object.defineProperty(this,"client",{value:e.client})}get _roles(){const e=this.guild.roles.everyone;return this.guild.roles.cache.filter((e=>this.member._roles.includes(e.id))).set(e.id,e)}get cache(){return this._roles}get hoist(){const e=this._roles.filter((e=>e.hoist));return e.size?e.reduce(((e,t)=>!e||t.comparePositionTo(e)>0?t:e)):null}get color(){const e=this._roles.filter((e=>e.color));return e.size?e.reduce(((e,t)=>!e||t.comparePositionTo(e)>0?t:e)):null}get highest(){return this._roles.reduce(((e,t)=>t.comparePositionTo(e)>0?t:e),this._roles.first())}async add(e,t){if(e instanceof n||Array.isArray(e)){if((e=e.map((e=>this.guild.roles.resolve(e)))).includes(null))throw new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0);const i=[...new Set(e.concat(...this._roles.values()))];return this.set(i,t)}{if(null===(e=this.guild.roles.resolve(e)))throw new s("INVALID_TYPE","roles","Role, Snowflake or Array or Collection of Roles or Snowflakes");await this.client.api.guilds[this.guild.id].members[this.member.id].roles[e.id].put({reason:t});const i=this.member._clone();return i._roles=[...this._roles.keys(),e.id],i}}async remove(e,t){if(e instanceof n||Array.isArray(e)){if((e=e.map((e=>this.guild.roles.resolve(e)))).includes(null))throw new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0);const i=this._roles.filter((t=>!e.includes(t)));return this.set(i,t)}{if(null===(e=this.guild.roles.resolve(e)))throw new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0);await this.client.api.guilds[this.guild.id].members[this.member.id].roles[e.id].delete({reason:t});const i=this.member._clone(),n=this._roles.filter((t=>t.id!==e.id));return i._roles=[...n.keys()],i}}set(e,t){return this.member.edit({roles:e},t)}clone(){const e=new this.constructor(this.member);return e.member._roles=[...this._roles.keyArray()],e}}},function(e,t,i){"use strict";const s=i(5),n=i(75),r=i(3),o=i(6);e.exports=class Team extends s{constructor(e,t){super(e),this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.icon=e.icon||null,this.ownerID=e.owner_user_id||null,this.members=new r;for(const t of e.members){const e=new n(this,t);this.members.set(e.id,e)}}get owner(){return this.members.get(this.ownerID)||null}get createdTimestamp(){return o.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}iconURL({format:e,size:t}={}){return this.icon?this.client.rest.cdn.TeamIcon(this.id,this.icon,{format:e,size:t}):null}toString(){return this.name}toJSON(){return super.toJSON({createdTimestamp:!0})}}},function(e,t,i){"use strict";const s=i(5),{MembershipStates:n}=i(0);e.exports=class TeamMember extends s{constructor(e,t){super(e.client),this.team=e,this._patch(t)}_patch(e){this.permissions=e.permissions,this.membershipState=n[e.membership_state],this.user=this.client.users.add(e.user)}get id(){return this.user.id}toString(){return this.user.toString()}}},function(e,t,i){"use strict";const s=i(3),{ChannelTypes:n}=i(0),r=i(4);class MessageMentions{constructor(e,t,i,r,o){if(Object.defineProperty(this,"client",{value:e.client}),Object.defineProperty(this,"guild",{value:e.guild}),Object.defineProperty(this,"_content",{value:e.content}),this.everyone=Boolean(r),t)if(t instanceof s)this.users=new s(t);else{this.users=new s;for(const i of t){i.member&&e.guild&&e.guild.members.add(Object.assign(i.member,{user:i}));const t=e.client.users.add(i);this.users.set(t.id,t)}}else this.users=new s;if(i)if(i instanceof s)this.roles=new s(i);else{this.roles=new s;for(const t of i){const i=e.channel.guild.roles.cache.get(t);i&&this.roles.set(i.id,i)}}else this.roles=new s;if(this._members=null,this._channels=null,o)if(o instanceof s)this.crosspostedChannels=new s(o);else{this.crosspostedChannels=new s;const e=Object.keys(n);for(const t of o){const i=e[t.type];this.crosspostedChannels.set(t.id,{channelID:t.id,guildID:t.guild_id,type:i?i.toLowerCase():"unknown",name:t.name})}}else this.crosspostedChannels=new s}get members(){return this._members?this._members:this.guild?(this._members=new s,this.users.forEach((e=>{const t=this.guild.member(e);t&&this._members.set(t.user.id,t)})),this._members):null}get channels(){if(this._channels)return this._channels;let e;for(this._channels=new s;null!==(e=this.constructor.CHANNELS_PATTERN.exec(this._content));){const t=this.client.channels.cache.get(e[1]);t&&this._channels.set(t.id,t)}return this._channels}has(e,{ignoreDirect:t=!1,ignoreRoles:s=!1,ignoreEveryone:n=!1}={}){if(!n&&this.everyone)return!0;const r=i(11);if(!s&&e instanceof r)for(const t of this.roles.values())if(e.roles.cache.has(t.id))return!0;if(!t){const t=this.client.users.resolveID(e)||this.guild&&this.guild.roles.resolveID(e)||this.client.channels.resolveID(e);return this.users.has(t)||this.channels.has(t)||this.roles.has(t)}return!1}toJSON(){return r.flatten(this,{members:!0,channels:!0})}}MessageMentions.EVERYONE_PATTERN=/@(everyone|here)/g,MessageMentions.USERS_PATTERN=/<@!?(\d{17,19})>/g,MessageMentions.ROLES_PATTERN=/<@&(\d{17,19})>/g,MessageMentions.CHANNELS_PATTERN=/<#(\d{17,19})>/g,e.exports=MessageMentions},function(e,t,i){"use strict";const s=i(49),n=i(3),{Events:r}=i(0);class ReactionCollector extends s{constructor(e,t,i={}){super(e.client,t,i),this.message=e,this.users=new n,this.total=0,this.empty=this.empty.bind(this),this._handleChannelDeletion=this._handleChannelDeletion.bind(this),this._handleGuildDeletion=this._handleGuildDeletion.bind(this),this._handleMessageDeletion=this._handleMessageDeletion.bind(this),this.client.incrementMaxListeners(),this.client.on(r.MESSAGE_REACTION_ADD,this.handleCollect),this.client.on(r.MESSAGE_REACTION_REMOVE,this.handleDispose),this.client.on(r.MESSAGE_REACTION_REMOVE_ALL,this.empty),this.client.on(r.MESSAGE_DELETE,this._handleMessageDeletion),this.client.on(r.CHANNEL_DELETE,this._handleChannelDeletion),this.client.on(r.GUILD_DELETE,this._handleGuildDeletion),this.once("end",(()=>{this.client.removeListener(r.MESSAGE_REACTION_ADD,this.handleCollect),this.client.removeListener(r.MESSAGE_REACTION_REMOVE,this.handleDispose),this.client.removeListener(r.MESSAGE_REACTION_REMOVE_ALL,this.empty),this.client.removeListener(r.MESSAGE_DELETE,this._handleMessageDeletion),this.client.removeListener(r.CHANNEL_DELETE,this._handleChannelDeletion),this.client.removeListener(r.GUILD_DELETE,this._handleGuildDeletion),this.client.decrementMaxListeners()})),this.on("collect",((e,t)=>{this.total++,this.users.set(t.id,t)})),this.on("remove",((e,t)=>{this.total--,this.collected.some((e=>e.users.cache.has(t.id)))||this.users.delete(t.id)}))}collect(e){return e.message.id!==this.message.id?null:ReactionCollector.key(e)}dispose(e,t){return e.message.id!==this.message.id?null:(this.collected.has(ReactionCollector.key(e))&&this.users.has(t.id)&&this.emit("remove",e,t),e.count?null:ReactionCollector.key(e))}empty(){this.total=0,this.collected.clear(),this.users.clear(),this.checkEnd()}endReason(){return this.options.max&&this.total>=this.options.max?"limit":this.options.maxEmojis&&this.collected.size>=this.options.maxEmojis?"emojiLimit":this.options.maxUsers&&this.users.size>=this.options.maxUsers?"userLimit":null}_handleMessageDeletion(e){e.id===this.message.id&&this.stop("messageDelete")}_handleChannelDeletion(e){e.id===this.message.channel.id&&this.stop("channelDelete")}_handleGuildDeletion(e){this.message.guild&&e.id===this.message.guild.id&&this.stop("guildDelete")}static key(e){return e.emoji.id||e.emoji.name}}e.exports=ReactionCollector},function(e,t,i){"use strict";const s=i(7),n=i(52);e.exports=class ReactionManager extends s{constructor(e,t){super(e.client,t,n),this.message=e}add(e,t){return super.add(e,t,{id:e.emoji.id||e.emoji.name,extras:[this.message]})}removeAll(){return this.client.api.channels(this.message.channel.id).messages(this.message.id).reactions.delete().then((()=>this.message))}}},function(e,t,i){"use strict";const s=i(7),{Error:n}=i(2),r=i(3);e.exports=class ReactionUserManager extends s{constructor(e,t,i){super(e,t,{name:"User"}),this.reaction=i}async fetch({limit:e=100,after:t,before:i}={}){const s=this.reaction.message,n=await this.client.api.channels[s.channel.id].messages[s.id].reactions[this.reaction.emoji.identifier].get({query:{limit:e,before:i,after:t}}),o=new r;for(const e of n){const t=this.client.users.add(e);this.cache.set(t.id,t),o.set(t.id,t)}return o}remove(e=this.client.user){const t=this.client.users.resolveID(e);if(!t)return Promise.reject(new n("REACTION_RESOLVE_USER"));const i=this.reaction.message;return this.client.api.channels[i.channel.id].messages[i.id].reactions[this.reaction.emoji.identifier][t===this.client.user.id?"@me":t].delete().then((()=>this.reaction))}}},function(e,t,i){"use strict";const s=i(12);class UserFlags extends s{}UserFlags.FLAGS={DISCORD_EMPLOYEE:1,PARTNERED_SERVER_OWNER:2,DISCORD_PARTNER:2,HYPESQUAD_EVENTS:4,BUGHUNTER_LEVEL_1:8,HOUSE_BRAVERY:64,HOUSE_BRILLIANCE:128,HOUSE_BALANCE:256,EARLY_SUPPORTER:512,TEAM_USER:1024,SYSTEM:4096,BUGHUNTER_LEVEL_2:16384,VERIFIED_BOT:65536,EARLY_VERIFIED_DEVELOPER:1<<17,VERIFIED_DEVELOPER:1<<17},e.exports=UserFlags},function(e,t,i){"use strict";const s=i(18),{Error:n}=i(2),r=i(3),{browser:o}=i(0),a=i(8);e.exports=class VoiceChannel extends s{_patch(e){super._patch(e),this.bitrate=e.bitrate,this.userLimit=e.user_limit}get members(){const e=new r;for(const t of this.guild.voiceStates.cache.values())t.channelID===this.id&&t.member&&e.set(t.id,t.member);return e}get full(){return this.userLimit>0&&this.members.size>=this.userLimit}get deletable(){return super.deletable&&this.permissionsFor(this.client.user).has(a.FLAGS.CONNECT,!1)}get editable(){return this.manageable&&this.permissionsFor(this.client.user).has(a.FLAGS.CONNECT,!1)}get joinable(){return!o&&(!!this.viewable&&(!!this.permissionsFor(this.client.user).has(a.FLAGS.CONNECT,!1)&&!(this.full&&!this.permissionsFor(this.client.user).has(a.FLAGS.MOVE_MEMBERS,!1))))}get speakable(){return this.permissionsFor(this.client.user).has(a.FLAGS.SPEAK,!1)}setBitrate(e,t){return this.edit({bitrate:e},t)}setUserLimit(e,t){return this.edit({userLimit:e},t)}join(){return o?Promise.reject(new n("VOICE_NO_BROWSER")):this.client.voice.joinChannel(this)}leave(){if(o)return;const e=this.client.voice.connections.get(this.guild.id);e&&e.channel.id===this.id&&e.disconnect()}}},function(e,t,i){"use strict";const s=i(18);e.exports=class CategoryChannel extends s{get children(){return this.guild.channels.cache.filter((e=>e.parentID===this.id))}}},function(e,t,i){"use strict";const s=i(41),{Error:n}=i(2);e.exports=class NewsChannel extends s{_patch(e){super._patch(e),this.rateLimitPerUser=void 0}async addFollower(e,t){const i=this.guild.channels.resolveID(e);if(!i)throw new n("GUILD_CHANNEL_RESOLVE");return await this.client.api.channels(this.id).followers.post({data:{webhook_channel_id:i},reason:t}),this}}},function(e,t,i){"use strict";const s=i(18);e.exports=class StoreChannel extends s{constructor(e,t){super(e,t),this.nsfw=Boolean(t.nsfw)}_patch(e){super._patch(e),void 0!==e.nsfw&&(this.nsfw=Boolean(e.nsfw))}}},function(e,t,i){(function(e){var s=Object.getOwnPropertyDescriptors||function getOwnPropertyDescriptors(e){for(var t=Object.keys(e),i={},s=0;s=r)return e;switch(e){case"%s":return String(s[i++]);case"%d":return Number(s[i++]);case"%j":try{return JSON.stringify(s[i++])}catch(e){return"[Circular]"}default:return e}})),a=s[i];i=3&&(s.depth=arguments[2]),arguments.length>=4&&(s.colors=arguments[3]),isBoolean(i)?s.showHidden=i:i&&t._extend(s,i),isUndefined(s.showHidden)&&(s.showHidden=!1),isUndefined(s.depth)&&(s.depth=2),isUndefined(s.colors)&&(s.colors=!1),isUndefined(s.customInspect)&&(s.customInspect=!0),s.colors&&(s.stylize=stylizeWithColor),formatValue(s,e,s.depth)}function stylizeWithColor(e,t){var i=inspect.styles[t];return i?"["+inspect.colors[i][0]+"m"+e+"["+inspect.colors[i][1]+"m":e}function stylizeNoColor(e,t){return e}function formatValue(e,i,s){if(e.customInspect&&i&&isFunction(i.inspect)&&i.inspect!==t.inspect&&(!i.constructor||i.constructor.prototype!==i)){var n=i.inspect(s,e);return isString(n)||(n=formatValue(e,n,s)),n}var r=function formatPrimitive(e,t){if(isUndefined(t))return e.stylize("undefined","undefined");if(isString(t)){var i="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(i,"string")}if(isNumber(t))return e.stylize(""+t,"number");if(isBoolean(t))return e.stylize(""+t,"boolean");if(isNull(t))return e.stylize("null","null")}(e,i);if(r)return r;var o=Object.keys(i),a=function arrayToHash(e){var t={};return e.forEach((function(e,i){t[e]=!0})),t}(o);if(e.showHidden&&(o=Object.getOwnPropertyNames(i)),isError(i)&&(o.indexOf("message")>=0||o.indexOf("description")>=0))return formatError(i);if(0===o.length){if(isFunction(i)){var c=i.name?": "+i.name:"";return e.stylize("[Function"+c+"]","special")}if(isRegExp(i))return e.stylize(RegExp.prototype.toString.call(i),"regexp");if(isDate(i))return e.stylize(Date.prototype.toString.call(i),"date");if(isError(i))return formatError(i)}var l,h="",u=!1,d=["{","}"];(isArray(i)&&(u=!0,d=["[","]"]),isFunction(i))&&(h=" [Function"+(i.name?": "+i.name:"")+"]");return isRegExp(i)&&(h=" "+RegExp.prototype.toString.call(i)),isDate(i)&&(h=" "+Date.prototype.toUTCString.call(i)),isError(i)&&(h=" "+formatError(i)),0!==o.length||u&&0!=i.length?s<0?isRegExp(i)?e.stylize(RegExp.prototype.toString.call(i),"regexp"):e.stylize("[Object]","special"):(e.seen.push(i),l=u?function formatArray(e,t,i,s,n){for(var r=[],o=0,a=t.length;o=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1}),0)>60)return i[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+i[1];return i[0]+t+" "+e.join(", ")+" "+i[1]}(l,h,d)):d[0]+h+d[1]}function formatError(e){return"["+Error.prototype.toString.call(e)+"]"}function formatProperty(e,t,i,s,n,r){var o,a,c;if((c=Object.getOwnPropertyDescriptor(t,n)||{value:t[n]}).get?a=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(a=e.stylize("[Setter]","special")),hasOwnProperty(s,n)||(o="["+n+"]"),a||(e.seen.indexOf(c.value)<0?(a=isNull(i)?formatValue(e,c.value,null):formatValue(e,c.value,i-1)).indexOf("\n")>-1&&(a=r?a.split("\n").map((function(e){return" "+e})).join("\n").substr(2):"\n"+a.split("\n").map((function(e){return" "+e})).join("\n")):a=e.stylize("[Circular]","special")),isUndefined(o)){if(r&&n.match(/^\d+$/))return a;(o=JSON.stringify(""+n)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(o=o.substr(1,o.length-2),o=e.stylize(o,"name")):(o=o.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),o=e.stylize(o,"string"))}return o+": "+a}function isArray(e){return Array.isArray(e)}function isBoolean(e){return"boolean"==typeof e}function isNull(e){return null===e}function isNumber(e){return"number"==typeof e}function isString(e){return"string"==typeof e}function isUndefined(e){return void 0===e}function isRegExp(e){return isObject(e)&&"[object RegExp]"===objectToString(e)}function isObject(e){return"object"==typeof e&&null!==e}function isDate(e){return isObject(e)&&"[object Date]"===objectToString(e)}function isError(e){return isObject(e)&&("[object Error]"===objectToString(e)||e instanceof Error)}function isFunction(e){return"function"==typeof e}function objectToString(e){return Object.prototype.toString.call(e)}function pad(e){return e<10?"0"+e.toString(10):e.toString(10)}t.debuglog=function(i){if(isUndefined(r)&&(r=e.env.NODE_DEBUG||""),i=i.toUpperCase(),!o[i])if(new RegExp("\\b"+i+"\\b","i").test(r)){var s=e.pid;o[i]=function(){var e=t.format.apply(t,arguments);console.error("%s %d: %s",i,s,e)}}else o[i]=function(){};return o[i]},t.inspect=inspect,inspect.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},inspect.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},t.isArray=isArray,t.isBoolean=isBoolean,t.isNull=isNull,t.isNullOrUndefined=function isNullOrUndefined(e){return null==e},t.isNumber=isNumber,t.isString=isString,t.isSymbol=function isSymbol(e){return"symbol"==typeof e},t.isUndefined=isUndefined,t.isRegExp=isRegExp,t.isObject=isObject,t.isDate=isDate,t.isError=isError,t.isFunction=isFunction,t.isPrimitive=function isPrimitive(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=i(138);var a=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function timestamp(){var e=new Date,t=[pad(e.getHours()),pad(e.getMinutes()),pad(e.getSeconds())].join(":");return[e.getDate(),a[e.getMonth()],t].join(" ")}function hasOwnProperty(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){console.log("%s - %s",timestamp(),t.format.apply(t,arguments))},t.inherits=i(139),t._extend=function(e,t){if(!t||!isObject(t))return e;for(var i=Object.keys(t),s=i.length;s--;)e[i[s]]=t[i[s]];return e};var c="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function callbackifyOnRejected(e,t){if(!e){var i=new Error("Promise was rejected with a falsy value");i.reason=e,e=i}return t(e)}t.promisify=function promisify(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');if(c&&e[c]){var t;if("function"!=typeof(t=e[c]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,c,{value:t,enumerable:!1,writable:!1,configurable:!0}),t}function t(){for(var t,i,s=new Promise((function(e,s){t=e,i=s})),n=[],r=0;re.target))).then((()=>t))}static targetType(e){return e<10?l.GUILD:e<20?l.CHANNEL:e<30?l.USER:e<40?l.ROLE:e<50?l.INVITE:e<60?l.WEBHOOK:e<70?l.EMOJI:e<80?l.MESSAGE:e<90?l.INTEGRATION:l.UNKNOWN}static actionType(e){return[h.CHANNEL_CREATE,h.CHANNEL_OVERWRITE_CREATE,h.MEMBER_BAN_REMOVE,h.BOT_ADD,h.ROLE_CREATE,h.INVITE_CREATE,h.WEBHOOK_CREATE,h.EMOJI_CREATE,h.MESSAGE_PIN,h.INTEGRATION_CREATE].includes(e)?"CREATE":[h.CHANNEL_DELETE,h.CHANNEL_OVERWRITE_DELETE,h.MEMBER_KICK,h.MEMBER_PRUNE,h.MEMBER_BAN_ADD,h.MEMBER_DISCONNECT,h.ROLE_DELETE,h.INVITE_DELETE,h.WEBHOOK_DELETE,h.EMOJI_DELETE,h.MESSAGE_DELETE,h.MESSAGE_BULK_DELETE,h.MESSAGE_UNPIN,h.INTEGRATION_DELETE].includes(e)?"DELETE":[h.GUILD_UPDATE,h.CHANNEL_UPDATE,h.CHANNEL_OVERWRITE_UPDATE,h.MEMBER_UPDATE,h.MEMBER_ROLE_UPDATE,h.MEMBER_MOVE,h.ROLE_UPDATE,h.INVITE_UPDATE,h.WEBHOOK_UPDATE,h.EMOJI_UPDATE,h.INTEGRATION_UPDATE].includes(e)?"UPDATE":"ALL"}toJSON(){return c.flatten(this)}}class GuildAuditLogsEntry{constructor(e,t,i){const r=GuildAuditLogs.targetType(i.action_type);switch(this.targetType=r,this.actionType=GuildAuditLogs.actionType(i.action_type),this.action=Object.keys(h).find((e=>h[e]===i.action_type)),this.reason=i.reason||null,this.executor=t.client.options.partials.includes(o.USER)?t.client.users.add({id:i.user_id}):t.client.users.cache.get(i.user_id),this.changes=i.changes?i.changes.map((e=>({key:e.key,old:e.old_value,new:e.new_value}))):null,this.id=i.id,this.extra=null,i.action_type){case h.MEMBER_PRUNE:this.extra={removed:Number(i.options.members_removed),days:Number(i.options.delete_member_days)};break;case h.MEMBER_MOVE:case h.MESSAGE_DELETE:case h.MESSAGE_BULK_DELETE:this.extra={channel:t.channels.cache.get(i.options.channel_id)||{id:i.options.channel_id},count:Number(i.options.count)};break;case h.MESSAGE_PIN:case h.MESSAGE_UNPIN:this.extra={channel:t.client.channels.cache.get(i.options.channel_id)||{id:i.options.channel_id},messageID:i.options.message_id};break;case h.MEMBER_DISCONNECT:this.extra={count:Number(i.options.count)};break;case h.CHANNEL_OVERWRITE_CREATE:case h.CHANNEL_OVERWRITE_UPDATE:case h.CHANNEL_OVERWRITE_DELETE:switch(i.options.type){case"member":this.extra=t.members.cache.get(i.options.id)||{id:i.options.id,type:"member"};break;case"role":this.extra=t.roles.cache.get(i.options.id)||{id:i.options.id,name:i.options.role_name,type:"role"}}}this.target=null,r===l.UNKNOWN?(this.target=this.changes.reduce(((e,t)=>(e[t.key]=t.new||t.old,e)),{}),this.target.id=i.target_id):r===l.USER&&i.target_id?this.target=t.client.options.partials.includes(o.USER)?t.client.users.add({id:i.target_id}):t.client.users.cache.get(i.target_id):r===l.GUILD?this.target=t.client.guilds.cache.get(i.target_id):r===l.WEBHOOK?this.target=e.webhooks.get(i.target_id)||new n(t.client,this.changes.reduce(((e,t)=>(e[t.key]=t.new||t.old,e)),{id:i.target_id,guild_id:t.id})):r===l.INVITE?this.target=t.members.fetch(t.client.user.id).then((e=>{if(e.permissions.has("MANAGE_GUILD")){const e=this.changes.find((e=>"code"===e.key));return t.fetchInvites().then((t=>{this.target=t.find((t=>t.code===(e.new||e.old)))}))}return this.target=this.changes.reduce(((e,t)=>(e[t.key]=t.new||t.old,e)),{}),this.target})):r===l.MESSAGE?this.target=i.action_type===h.MESSAGE_BULK_DELETE?t.channels.cache.get(i.target_id)||{id:i.target_id}:t.client.users.cache.get(i.target_id):r===l.INTEGRATION?this.target=e.integrations.get(i.target_id)||new s(t.client,this.changes.reduce(((e,t)=>(e[t.key]=t.new||t.old,e)),{id:i.target_id}),t):i.target_id&&(this.target=t[r.toLowerCase()+"s"].cache.get(i.target_id)||{id:i.target_id})}get createdTimestamp(){return a.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}toJSON(){return c.flatten(this,{createdTimestamp:!0})}}GuildAuditLogs.Actions=h,GuildAuditLogs.Targets=l,GuildAuditLogs.Entry=GuildAuditLogsEntry,e.exports=GuildAuditLogs},function(e,t,i){"use strict";const s=i(7),n=i(18),r=i(42),{ChannelTypes:o}=i(0);e.exports=class GuildChannelManager extends s{constructor(e,t){super(e.client,t,n),this.guild=e}add(e){const t=this.cache.get(e.id);return t||(this.cache.set(e.id,e),e)}async create(e,t={}){let{type:i,topic:s,nsfw:n,bitrate:a,userLimit:c,parent:l,permissionOverwrites:h,position:u,rateLimitPerUser:d,reason:f}=t;l&&(l=this.client.channels.resolveID(l)),h&&(h=h.map((e=>r.resolve(e,this.guild))));const p=await this.client.api.guilds(this.guild.id).channels.post({data:{name:e,topic:s,type:i?o[i.toUpperCase()]:o.TEXT,nsfw:n,bitrate:a,user_limit:c,parent_id:l,position:u,permission_overwrites:h,rate_limit_per_user:d},reason:f});return this.client.actions.ChannelCreate.handle(p).channel}}},function(e,t,i){"use strict";const s=i(7),{Error:n,TypeError:r,RangeError:o}=i(2),a=i(11),c=i(3),{Events:l,OPCodes:h}=i(0),u=i(6);e.exports=class GuildMemberManager extends s{constructor(e,t){super(e.client,t,a),this.guild=e}add(e,t=!0){return super.add(e,t,{id:e.user.id,extras:[this.guild]})}resolve(e){const t=super.resolve(e);if(t)return t;const i=this.client.users.resolveID(e);return i?super.resolve(i):null}resolveID(e){const t=super.resolveID(e);if(t)return t;const i=this.client.users.resolveID(e);return this.cache.has(i)?i:null}fetch(e){if(!e)return this._fetchMany();const t=this.client.users.resolveID(e);if(t)return this._fetchSingle({user:t,cache:!0});if(e.user){if(Array.isArray(e.user))return e.user=e.user.map((e=>this.client.users.resolveID(e))),this._fetchMany(e);if(e.user=this.client.users.resolveID(e.user),!e.limit&&!e.withPresences)return this._fetchSingle(e)}return this._fetchMany(e)}prune({days:e=7,dry:t=!1,count:i=!0,roles:s=[],reason:n}={}){if("number"!=typeof e)throw new r("PRUNE_DAYS_TYPE");const o={days:e},a=[];for(const e of s){const t=this.guild.roles.resolveID(e);if(!t)return Promise.reject(new r("INVALID_TYPE","roles","Array of Roles or Snowflakes",!0));a.push(t)}a.length&&(o.include_roles=t?a.join(","):a);const c=this.client.api.guilds(this.guild.id).prune;return t?c.get({query:o,reason:n}).then((e=>e.pruned)):c.post({data:{...o,compute_prune_count:i},reason:n}).then((e=>e.pruned))}ban(e,t={days:0}){t.days&&(t.delete_message_days=t.days);const i=this.client.users.resolveID(e);return i?this.client.api.guilds(this.guild.id).bans[i].put({data:t}).then((()=>{if(e instanceof a)return e;const t=this.client.users.resolve(i);if(t){return this.resolve(t)||t}return i})):Promise.reject(new n("BAN_RESOLVE_ID",!0))}unban(e,t){const i=this.client.users.resolveID(e);return i?this.client.api.guilds(this.guild.id).bans[i].delete({reason:t}).then((()=>this.client.users.resolve(e))):Promise.reject(new n("BAN_RESOLVE_ID"))}_fetchSingle({user:e,cache:t,force:i=!1}){if(!i){const t=this.cache.get(e);if(t&&!t.partial)return Promise.resolve(t)}return this.client.api.guilds(this.guild.id).members(e).get().then((e=>this.add(e,t)))}_fetchMany({limit:e=0,withPresences:t=!1,user:i,query:s,time:r=12e4,nonce:a=u.generate(),force:d=!1}={}){return new Promise(((u,f)=>{if(!(this.guild.memberCount!==this.cache.size||s||e||t||i||d))return void u(this.cache);if(s||i||(s=""),a.length>32)throw new o("MEMBER_FETCH_NONCE_LENGTH");this.guild.shard.send({op:h.REQUEST_GUILD_MEMBERS,d:{guild_id:this.guild.id,presences:t,user_ids:i,query:s,nonce:a,limit:e}});const p=new c,m=s||e||t||i;let g=0;const handler=(t,s,n)=>{if(E.refresh(),n.nonce===a){g++;for(const e of t.values())m&&p.set(e.id,e);if(this.guild.memberCount<=this.cache.size||m&&t.size<1e3||e&&p.size>=e||g===n.count){this.client.clearTimeout(E),this.client.removeListener(l.GUILD_MEMBERS_CHUNK,handler),this.client.decrementMaxListeners();let e=m?p:this.cache;i&&!Array.isArray(i)&&e.size&&(e=e.first()),u(e)}}},E=this.client.setTimeout((()=>{this.client.removeListener(l.GUILD_MEMBERS_CHUNK,handler),this.client.decrementMaxListeners(),f(new n("GUILD_MEMBERS_TIMEOUT"))}),r);this.client.incrementMaxListeners(),this.client.on(l.GUILD_MEMBERS_CHUNK,handler)}))}}},function(e,t,i){"use strict";const s=i(7),{Presence:n}=i(24);e.exports=class PresenceManager extends s{constructor(e,t){super(e,t,n)}add(e,t){const i=this.cache.get(e.user.id);return i?i.patch(e):super.add(e,t,{id:e.user.id})}resolve(e){const t=super.resolve(e);if(t)return t;const i=this.client.users.resolveID(e);return super.resolve(i)||null}resolveID(e){const t=super.resolveID(e);if(t)return t;const i=this.client.users.resolveID(e);return this.cache.has(i)?i:null}}},function(e,t,i){"use strict";const s=i(12);class ActivityFlags extends s{}ActivityFlags.FLAGS={INSTANCE:1,JOIN:2,SPECTATE:4,JOIN_REQUEST:8,SYNC:16,PLAY:32},e.exports=ActivityFlags},function(e,t,i){"use strict";const s=i(7),n=i(20),r=i(8),{resolveColor:o}=i(4);e.exports=class RoleManager extends s{constructor(e,t){super(e.client,t,n),this.guild=e}add(e,t){return super.add(e,t,{extras:[this.guild]})}async fetch(e,t=!0,i=!1){if(e&&!i){const t=this.cache.get(e);if(t)return t}const s=await this.client.api.guilds(this.guild.id).roles.get();for(const e of s)this.add(e,t);return e?this.cache.get(e)||null:this}create({data:e={},reason:t}={}){return e.color&&(e.color=o(e.color)),e.permissions&&(e.permissions=r.resolve(e.permissions)),this.guild.client.api.guilds(this.guild.id).roles.post({data:e,reason:t}).then((i=>{const{role:s}=this.client.actions.GuildRoleCreate.handle({guild_id:this.guild.id,role:i});return e.position?s.setPosition(e.position,t):s}))}get everyone(){return this.cache.get(this.guild.id)}get highest(){return this.cache.reduce(((e,t)=>t.comparePositionTo(e)>0?t:e),this.cache.first())}}},function(e,t,i){"use strict";const s=i(12);class SystemChannelFlags extends s{}SystemChannelFlags.FLAGS={WELCOME_MESSAGE_DISABLED:1,BOOST_MESSAGE_DISABLED:2},e.exports=SystemChannelFlags},function(e,t,i){"use strict";const{Presence:s}=i(24),{TypeError:n}=i(2),r=i(3),{ActivityTypes:o,OPCodes:a}=i(0);e.exports=class ClientPresence extends s{constructor(e,t={}){super(e,Object.assign(t,{status:"online",user:{id:null}}))}async set(e){const t=await this._parse(e);if(this.patch(t),void 0===e.shardID)this.client.ws.broadcast({op:a.STATUS_UPDATE,d:t});else if(Array.isArray(e.shardID))for(const i of e.shardID)this.client.ws.shards.get(i).send({op:a.STATUS_UPDATE,d:t});else this.client.ws.shards.get(e.shardID).send({op:a.STATUS_UPDATE,d:t});return this}async _parse({status:e,since:t,afk:i,activity:s}){const a=s&&(s.application?s.application.id||s.application:null);let c=new r;if(s){if("string"!=typeof s.name)throw new n("INVALID_TYPE","name","string");if(s.type||(s.type=0),s.assets&&a)try{const e=await this.client.api.oauth2.applications(a).assets.get();for(const t of e)c.set(t.name,t.id)}catch{}}const l={afk:null!=i&&i,since:null!=t?t:null,status:e||this.status,game:s?{type:s.type,name:s.name,url:s.url,details:s.details||void 0,state:s.state||void 0,assets:s.assets?{large_text:s.assets.largeText||void 0,small_text:s.assets.smallText||void 0,large_image:c.get(s.assets.largeImage)||s.assets.largeImage,small_image:c.get(s.assets.smallImage)||s.assets.smallImage}:void 0,timestamps:s.timestamps||void 0,party:s.party||void 0,application_id:a||void 0,secrets:s.secrets||void 0,instance:s.instance||void 0}:null};return(e||i||t)&&!s&&(l.game=this.activities[0]||null),l.game&&(l.game.type="number"==typeof l.game.type?l.game.type:o.indexOf(l.game.type)),l}}},function(e,t,i){"use strict";const s=i(5),{Error:n,TypeError:r}=i(2),{browser:o}=i(0);e.exports=class VoiceState extends s{constructor(e,t){super(e.client),this.guild=e,this.id=t.user_id,this._patch(t)}_patch(e){return this.serverDeaf="deaf"in e?e.deaf:null,this.serverMute="mute"in e?e.mute:null,this.selfDeaf="self_deaf"in e?e.self_deaf:null,this.selfMute="self_mute"in e?e.self_mute:null,this.selfVideo="self_video"in e?e.self_video:null,this.sessionID="session_id"in e?e.session_id:null,this.streaming=e.self_stream||!1,this.channelID=e.channel_id||null,this}get member(){return this.guild.members.cache.get(this.id)||null}get channel(){return this.guild.channels.cache.get(this.channelID)||null}get connection(){return o||this.id!==this.client.user.id?null:this.client.voice.connections.get(this.guild.id)||null}get deaf(){return this.serverDeaf||this.selfDeaf}get mute(){return this.serverMute||this.selfMute}get speaking(){return this.channel&&this.channel.connection?Boolean(this.channel.connection._speaking.get(this.id)):null}setMute(e,t){return this.member?this.member.edit({mute:e},t):Promise.reject(new n("VOICE_STATE_UNCACHED_MEMBER"))}setDeaf(e,t){return this.member?this.member.edit({deaf:e},t):Promise.reject(new n("VOICE_STATE_UNCACHED_MEMBER"))}kick(e){return this.setChannel(null,e)}setChannel(e,t){return this.member?this.member.edit({channel:e},t):Promise.reject(new n("VOICE_STATE_UNCACHED_MEMBER"))}async setSelfMute(e){if(this.id!==this.client.user.id)throw new n("VOICE_STATE_NOT_OWN");if("boolean"!=typeof e)throw new r("VOICE_STATE_INVALID_TYPE","mute");return!!this.connection&&(this.selfMute=e,await this.connection.sendVoiceStateUpdate(),!0)}async setSelfDeaf(e){return this.id!==this.client.user.id?new n("VOICE_STATE_NOT_OWN"):"boolean"!=typeof e?new r("VOICE_STATE_INVALID_TYPE","deaf"):!!this.connection&&(this.selfDeaf=e,await this.connection.sendVoiceStateUpdate(),!0)}toJSON(){return super.toJSON({id:!0,serverDeaf:!0,serverMute:!0,selfDeaf:!0,selfMute:!0,sessionID:!0,channelID:"channel"})}}},function(e,t,i){"use strict";(function(e){const{browser:s}=i(0);let n,r;try{n=i(170),n.pack||(n=null)}catch{}s?(r=window.TextDecoder,t.WebSocket=window.WebSocket):(r=i(85).TextDecoder,t.WebSocket=i(171));const o=new r;t.encoding=n?"etf":"json",t.pack=n?n.pack:JSON.stringify,t.unpack=(i,s)=>"json"===t.encoding||"json"===s?("string"!=typeof i&&(i=o.decode(i)),JSON.parse(i)):(e.isBuffer(i)||(i=e.from(new Uint8Array(i))),n.unpack(i)),t.create=(e,i={},...n)=>{const[r,o]=e.split("?");i.encoding=t.encoding,i=new URLSearchParams(i),o&&new URLSearchParams(o).forEach(((e,t)=>i.set(t,e)));const a=new t.WebSocket(`${r}?${i}`,...n);return s&&(a.binaryType="arraybuffer"),a};for(const e of["CONNECTING","OPEN","CLOSING","CLOSED"])t[e]=t.WebSocket[e]}).call(this,i(14).Buffer)},function(e,t,i){"use strict";const{WSEvents:s}=i(0),n={};for(const e of Object.keys(s))try{n[e]=i(173)(`./${e}.js`)}catch{}e.exports=n},function(e,t,i){"use strict";const s=i(9),n=i(10);class ClientUser extends(n.get("User")){constructor(e,t){super(e,t),this._typing=new Map}_patch(e){super._patch(e),"verified"in e&&(this.verified=e.verified),"mfa_enabled"in e?this.mfaEnabled="boolean"==typeof e.mfa_enabled?e.mfa_enabled:null:void 0===this.mfaEnabled&&(this.mfaEnabled=null),e.token&&(this.client.token=e.token)}get presence(){return this.client.presence}edit(e){return this.client.api.users("@me").patch({data:e}).then((e=>{this.client.token=e.token;const{updated:t}=this.client.actions.UserUpdate.handle(e);return t||this}))}setUsername(e){return this.edit({username:e})}async setAvatar(e){return this.edit({avatar:await s.resolveImage(e)})}setPresence(e){return this.client.presence.set(e)}setStatus(e,t){return this.setPresence({status:e,shardID:t})}setActivity(e,t={}){if(!e)return this.setPresence({activity:null,shardID:t.shardID});const i=Object.assign({},t,"object"==typeof e?e:{name:e});return this.setPresence({activity:i,shardID:i.shardID})}setAFK(e){return this.setPresence({afk:e})}}e.exports=ClientUser},function(e,t,i){"use strict";const s=i(7),n=i(17),{Events:r}=i(0);e.exports=class ChannelManager extends s{constructor(e,t){super(e,t,n)}add(e,t,i=!0){const s=this.cache.get(e.id);if(s)return s._patch&&i&&s._patch(e),t&&t.channels.add(s),s;const o=n.create(this.client,e,t);return o?(i&&this.cache.set(o.id,o),o):(this.client.emit(r.DEBUG,`Failed to find guild, or unknown type for channel ${e.id} ${e.type}`),null)}remove(e){const t=this.cache.get(e);t.guild&&t.guild.channels.cache.delete(e),this.cache.delete(e)}async fetch(e,t=!0,i=!1){if(!i){const t=this.cache.get(e);if(t&&!t.partial)return t}const s=await this.client.api.channels(e).get();return this.add(s,null,t)}}},function(e,t,i){"use strict";const s=i(7),n=i(54),r=i(18),o=i(25),a=i(11),c=i(19),l=i(20),{ChannelTypes:h,Events:u,VerificationLevels:d,DefaultMessageNotifications:f,ExplicitContentFilterLevels:p}=i(0),m=i(9),g=i(8),{resolveColor:E}=i(4);e.exports=class GuildManager extends s{constructor(e,t){super(e,t,n)}resolve(e){return e instanceof r||e instanceof a||e instanceof o||e instanceof l||e instanceof c&&e.guild?super.resolve(e.guild):super.resolve(e)}resolveID(e){return e instanceof r||e instanceof a||e instanceof o||e instanceof l||e instanceof c&&e.guild?super.resolveID(e.guild.id):super.resolveID(e)}async create(e,{afkChannelID:t,afkTimeout:i,channels:s=[],defaultMessageNotifications:n,explicitContentFilter:r,icon:o=null,region:a,roles:c=[],systemChannelID:l,verificationLevel:_}={}){o=await m.resolveImage(o),void 0!==_&&"number"!=typeof _&&(_=d.indexOf(_)),void 0!==n&&"number"!=typeof n&&(n=f.indexOf(n)),void 0!==r&&"number"!=typeof r&&(r=p.indexOf(r));for(const e of s)if(e.type&&(e.type=h[e.type.toUpperCase()]),e.parent_id=e.parentID,delete e.parentID,e.permissionOverwrites){for(const t of e.permissionOverwrites)t.allow&&(t.allow=g.resolve(t.allow)),t.deny&&(t.deny=g.resolve(t.deny));e.permission_overwrites=e.permissionOverwrites,delete e.permissionOverwrites}for(const e of c)e.color&&(e.color=E(e.color)),e.permissions&&(e.permissions=g.resolve(e.permissions));return new Promise(((h,d)=>this.client.api.guilds.post({data:{name:e,region:a,icon:o,verification_level:_,default_message_notifications:n,explicit_content_filter:r,roles:c,channels:s,afk_channel_id:t,afk_timeout:i,system_channel_id:l}}).then((e=>{if(this.client.guilds.cache.has(e.id))return h(this.client.guilds.cache.get(e.id));const handleGuild=i=>{i.id===e.id&&(this.client.clearTimeout(t),this.client.removeListener(u.GUILD_CREATE,handleGuild),this.client.decrementMaxListeners(),h(i))};this.client.incrementMaxListeners(),this.client.on(u.GUILD_CREATE,handleGuild);const t=this.client.setTimeout((()=>{this.client.removeListener(u.GUILD_CREATE,handleGuild),this.client.decrementMaxListeners(),h(this.client.guilds.add(e))}),1e4)}),d)))}async fetch(e,t=!0,i=!1){if(!i){const t=this.cache.get(e);if(t)return t}const s=await this.client.api.guilds(e).get({query:{with_counts:!0}});return this.add(s,t)}}},function(e,t,i){"use strict";const s=i(7),n=i(11),r=i(28),o=i(27);e.exports=class UserManager extends s{constructor(e,t){super(e,t,o)}resolve(e){return e instanceof n?e.user:e instanceof r?e.author:super.resolve(e)}resolveID(e){return e instanceof n?e.user.id:e instanceof r?e.author.id:super.resolveID(e)}async fetch(e,t=!0,i=!1){if(!i){const t=this.cache.get(e);if(t&&!t.partial)return t}const s=await this.client.api.users(e).get();return this.add(s,t)}}},function(e,t,i){"use strict";const s=i(12);class Intents extends s{}Intents.FLAGS={GUILDS:1,GUILD_MEMBERS:2,GUILD_BANS:4,GUILD_EMOJIS:8,GUILD_INTEGRATIONS:16,GUILD_WEBHOOKS:32,GUILD_INVITES:64,GUILD_VOICE_STATES:128,GUILD_PRESENCES:256,GUILD_MESSAGES:512,GUILD_MESSAGE_REACTIONS:1024,GUILD_MESSAGE_TYPING:2048,DIRECT_MESSAGES:4096,DIRECT_MESSAGE_REACTIONS:8192,DIRECT_MESSAGE_TYPING:16384},Intents.PRIVILEGED=Intents.FLAGS.GUILD_MEMBERS|Intents.FLAGS.GUILD_PRESENCES,Intents.ALL=Object.values(Intents.FLAGS).reduce(((e,t)=>e|t),0),Intents.NON_PRIVILEGED=Intents.ALL&~Intents.PRIVILEGED,e.exports=Intents},function(e,t,i){"use strict";const s=i(4);e.exports={BaseClient:i(37),Client:i(115),Shard:i(212),ShardClientUtil:i(213),ShardingManager:i(214),WebhookClient:i(48),ActivityFlags:i(90),BitField:i(12),Collection:i(3),Constants:i(0),DataResolver:i(9),BaseManager:i(7),DiscordAPIError:i(64),HTTPError:i(65),MessageFlags:i(47),Intents:i(101),Permissions:i(8),Speaking:i(215),Snowflake:i(6),SnowflakeUtil:i(6),Structures:i(10),SystemChannelFlags:i(92),UserFlags:i(80),Util:s,version:i(61).version,ChannelManager:i(98),GuildChannelManager:i(87),GuildEmojiManager:i(59),GuildEmojiRoleManager:i(66),GuildMemberManager:i(88),GuildMemberRoleManager:i(73),GuildManager:i(99),ReactionManager:i(78),ReactionUserManager:i(79),MessageManager:i(34),PresenceManager:i(89),RoleManager:i(91),UserManager:i(100),discordSort:s.discordSort,escapeMarkdown:s.escapeMarkdown,fetchRecommendedShards:s.fetchRecommendedShards,resolveColor:s.resolveColor,resolveString:s.resolveString,splitMessage:s.splitMessage,Application:i(51),Base:i(5),Activity:i(24).Activity,APIMessage:i(30),BaseGuildEmoji:i(40),CategoryChannel:i(82),Channel:i(17),ClientApplication:i(50),get ClientUser(){return i(97)},Collector:i(49),DMChannel:i(39),Emoji:i(29),Guild:i(54),GuildAuditLogs:i(86),GuildChannel:i(18),GuildEmoji:i(25),GuildMember:i(11),GuildPreview:i(56),GuildTemplate:i(57),Integration:i(55),Invite:i(19),Message:i(28),MessageAttachment:i(43),MessageCollector:i(72),MessageEmbed:i(44),MessageMentions:i(76),MessageReaction:i(52),NewsChannel:i(83),PermissionOverwrites:i(42),Presence:i(24).Presence,ClientPresence:i(93),ReactionCollector:i(77),ReactionEmoji:i(53),RichPresenceAssets:i(24).RichPresenceAssets,Role:i(20),StoreChannel:i(84),Team:i(74),TeamMember:i(75),TextChannel:i(41),User:i(27),VoiceChannel:i(81),VoiceRegion:i(58),VoiceState:i(94),Webhook:i(13),WebSocket:i(95)}},function(e,t,i){"use strict";t.byteLength=function byteLength(e){var t=getLens(e),i=t[0],s=t[1];return 3*(i+s)/4-s},t.toByteArray=function toByteArray(e){var t,i,s=getLens(e),o=s[0],a=s[1],c=new r(function _byteLength(e,t,i){return 3*(t+i)/4-i}(0,o,a)),l=0,h=a>0?o-4:o;for(i=0;i>16&255,c[l++]=t>>8&255,c[l++]=255&t;2===a&&(t=n[e.charCodeAt(i)]<<2|n[e.charCodeAt(i+1)]>>4,c[l++]=255&t);1===a&&(t=n[e.charCodeAt(i)]<<10|n[e.charCodeAt(i+1)]<<4|n[e.charCodeAt(i+2)]>>2,c[l++]=t>>8&255,c[l++]=255&t);return c},t.fromByteArray=function fromByteArray(e){for(var t,i=e.length,n=i%3,r=[],o=16383,a=0,c=i-n;ac?c:a+o));1===n?(t=e[i-1],r.push(s[t>>2]+s[t<<4&63]+"==")):2===n&&(t=(e[i-2]<<8)+e[i-1],r.push(s[t>>10]+s[t>>4&63]+s[t<<2&63]+"="));return r.join("")};for(var s=[],n=[],r="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,c=o.length;a0)throw new Error("Invalid string. Length must be a multiple of 4");var i=e.indexOf("=");return-1===i&&(i=t),[i,i===t?0:4-i%4]}function encodeChunk(e,t,i){for(var n,r,o=[],a=t;a>18&63]+s[r>>12&63]+s[r>>6&63]+s[63&r]);return o.join("")}n["-".charCodeAt(0)]=62,n["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,i,s,n){var r,o,a=8*n-s-1,c=(1<>1,h=-7,u=i?n-1:0,d=i?-1:1,f=e[t+u];for(u+=d,r=f&(1<<-h)-1,f>>=-h,h+=a;h>0;r=256*r+e[t+u],u+=d,h-=8);for(o=r&(1<<-h)-1,r>>=-h,h+=s;h>0;o=256*o+e[t+u],u+=d,h-=8);if(0===r)r=1-l;else{if(r===c)return o?NaN:1/0*(f?-1:1);o+=Math.pow(2,s),r-=l}return(f?-1:1)*o*Math.pow(2,r-s)},t.write=function(e,t,i,s,n,r){var o,a,c,l=8*r-n-1,h=(1<>1,d=23===n?Math.pow(2,-24)-Math.pow(2,-77):0,f=s?0:r-1,p=s?1:-1,m=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,o=h):(o=Math.floor(Math.log(t)/Math.LN2),t*(c=Math.pow(2,-o))<1&&(o--,c*=2),(t+=o+u>=1?d/c:d*Math.pow(2,1-u))*c>=2&&(o++,c/=2),o+u>=h?(a=0,o=h):o+u>=1?(a=(t*c-1)*Math.pow(2,n),o+=u):(a=t*Math.pow(2,u-1)*Math.pow(2,n),o=0));n>=8;e[i+f]=255&a,f+=p,a/=256,n-=8);for(o=o<0;e[i+f]=255&o,f+=p,o/=256,l-=8);e[i+f-p]|=128*m}},function(e,t,i){"use strict";const{register:s}=i(62),n={CLIENT_INVALID_OPTION:(e,t)=>`The ${e} option must be ${t}`,CLIENT_INVALID_PROVIDED_SHARDS:"None of the provided shards were valid.",TOKEN_INVALID:"An invalid token was provided.",TOKEN_MISSING:"Request to use token, but token was unavailable to the client.",WS_CLOSE_REQUESTED:"WebSocket closed due to user request.",WS_CONNECTION_EXISTS:"There is already an existing WebSocket connection.",WS_NOT_OPEN:(e="data")=>"Websocket not open to send "+e,BITFIELD_INVALID:"Invalid bitfield flag or number.",SHARDING_INVALID:"Invalid shard settings were provided.",SHARDING_REQUIRED:"This session would have handled too many guilds - Sharding is required.",INVALID_INTENTS:"Invalid intent provided for WebSocket intents.",DISALLOWED_INTENTS:"Privileged intent provided is not enabled or whitelisted.",SHARDING_NO_SHARDS:"No shards have been spawned.",SHARDING_IN_PROCESS:"Shards are still being spawned.",SHARDING_SHARD_NOT_FOUND:e=>`Shard ${e} could not be found.`,SHARDING_ALREADY_SPAWNED:e=>`Already spawned ${e} shards.`,SHARDING_PROCESS_EXISTS:e=>`Shard ${e} already has an active process.`,SHARDING_WORKER_EXISTS:e=>`Shard ${e} already has an active worker.`,SHARDING_READY_TIMEOUT:e=>`Shard ${e}'s Client took too long to become ready.`,SHARDING_READY_DISCONNECTED:e=>`Shard ${e}'s Client disconnected before becoming ready.`,SHARDING_READY_DIED:e=>`Shard ${e}'s process exited before its Client became ready.`,SHARDING_NO_CHILD_EXISTS:e=>`Shard ${e} has no active process or worker.`,SHARDING_SHARD_MISCALCULATION:(e,t,i)=>`Calculated invalid shard ${e} for guild ${t} with ${i} shards.`,COLOR_RANGE:"Color must be within the range 0 - 16777215 (0xFFFFFF).",COLOR_CONVERT:"Unable to convert color to a number.",EMBED_FIELD_NAME:"MessageEmbed field names may not be empty.",EMBED_FIELD_VALUE:"MessageEmbed field values may not be empty.",FILE_NOT_FOUND:e=>"File could not be found: "+e,USER_NO_DMCHANNEL:"No DM Channel exists!",VOICE_INVALID_HEARTBEAT:"Tried to set voice heartbeat but no valid interval was specified.",VOICE_USER_MISSING:"Couldn't resolve the user to create stream.",VOICE_JOIN_CHANNEL:(e=!1)=>"You do not have permission to join this voice channel"+(e?"; it is full.":"."),VOICE_CONNECTION_TIMEOUT:"Connection not established within 15 seconds.",VOICE_TOKEN_ABSENT:"Token not provided from voice server packet.",VOICE_SESSION_ABSENT:"Session ID not supplied.",VOICE_INVALID_ENDPOINT:"Invalid endpoint received.",VOICE_NO_BROWSER:"Voice connections are not available in browsers.",VOICE_CONNECTION_ATTEMPTS_EXCEEDED:e=>`Too many connection attempts (${e}).`,VOICE_JOIN_SOCKET_CLOSED:"Tried to send join packet, but the WebSocket is not open.",VOICE_PLAY_INTERFACE_NO_BROADCAST:"A broadcast cannot be played in this context.",VOICE_PLAY_INTERFACE_BAD_TYPE:"Unknown stream type",VOICE_PRISM_DEMUXERS_NEED_STREAM:"To play a webm/ogg stream, you need to pass a ReadableStream.",VOICE_STATE_UNCACHED_MEMBER:"The member of this voice state is uncached.",VOICE_STATE_NOT_OWN:"You cannot self-deafen/mute on VoiceStates that do not belong to the ClientUser.",VOICE_STATE_INVALID_TYPE:e=>e+" must be a boolean.",UDP_SEND_FAIL:"Tried to send a UDP packet, but there is no socket available.",UDP_ADDRESS_MALFORMED:"Malformed UDP address or port.",UDP_CONNECTION_EXISTS:"There is already an existing UDP connection.",REQ_RESOURCE_TYPE:"The resource must be a string, Buffer or a valid file stream.",IMAGE_FORMAT:e=>"Invalid image format: "+e,IMAGE_SIZE:e=>"Invalid image size: "+e,MESSAGE_BULK_DELETE_TYPE:"The messages must be an Array, Collection, or number.",MESSAGE_NONCE_TYPE:"Message nonce must fit in an unsigned 64-bit integer.",TYPING_COUNT:"Count must be at least 1",SPLIT_MAX_LEN:"Chunk exceeds the max length and contains no split characters.",BAN_RESOLVE_ID:(e=!1)=>`Couldn't resolve the user ID to ${e?"ban":"unban"}.`,FETCH_BAN_RESOLVE_ID:"Couldn't resolve the user ID to fetch the ban.",PRUNE_DAYS_TYPE:"Days must be a number",GUILD_CHANNEL_RESOLVE:"Could not resolve channel to a guild channel.",GUILD_VOICE_CHANNEL_RESOLVE:"Could not resolve channel to a guild voice channel.",GUILD_CHANNEL_ORPHAN:"Could not find a parent to this guild channel.",GUILD_OWNED:"Guild is owned by the client.",GUILD_MEMBERS_TIMEOUT:"Members didn't arrive in time.",GUILD_UNCACHED_ME:"The client user as a member of this guild is uncached.",INVALID_TYPE:(e,t,i=!1)=>`Supplied ${e} is not a${i?"n":""} ${t}.`,WEBHOOK_MESSAGE:"The message was not sent by a webhook.",EMOJI_TYPE:"Emoji must be a string or GuildEmoji/ReactionEmoji",EMOJI_MANAGED:"Emoji is managed and has no Author.",MISSING_MANAGE_EMOJIS_PERMISSION:e=>`Client must have Manage Emoji permission in guild ${e} to see emoji authors.`,REACTION_RESOLVE_USER:"Couldn't resolve the user ID to remove from the reaction.",VANITY_URL:"This guild does not have the VANITY_URL feature enabled.",DELETE_GROUP_DM_CHANNEL:"Bots don't have access to Group DM Channels and cannot delete them",FETCH_GROUP_DM_CHANNEL:"Bots don't have access to Group DM Channels and cannot fetch them",MEMBER_FETCH_NONCE_LENGTH:"Nonce length must not exceed 32 characters."};for(const[e,t]of Object.entries(n))s(e,t)},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Collection=void 0;class Collection extends Map{constructor(e){super(e),Object.defineProperty(this,"_array",{value:null,writable:!0,configurable:!0}),Object.defineProperty(this,"_keyArray",{value:null,writable:!0,configurable:!0})}get(e){return super.get(e)}set(e,t){return this._array=null,this._keyArray=null,super.set(e,t)}has(e){return super.has(e)}delete(e){return this._array=null,this._keyArray=null,super.delete(e)}clear(){return super.clear()}array(){return this._array&&this._array.length===this.size||(this._array=[...this.values()]),this._array}keyArray(){return this._keyArray&&this._keyArray.length===this.size||(this._keyArray=[...this.keys()]),this._keyArray}first(e){if(void 0===e)return this.values().next().value;if(e<0)return this.last(-1*e);e=Math.min(this.size,e);const t=this.values();return Array.from({length:e},(()=>t.next().value))}firstKey(e){if(void 0===e)return this.keys().next().value;if(e<0)return this.lastKey(-1*e);e=Math.min(this.size,e);const t=this.keys();return Array.from({length:e},(()=>t.next().value))}last(e){const t=this.array();return void 0===e?t[t.length-1]:e<0?this.first(-1*e):e?t.slice(-e):[]}lastKey(e){const t=this.keyArray();return void 0===e?t[t.length-1]:e<0?this.firstKey(-1*e):e?t.slice(-e):[]}random(e){let t=this.array();return void 0===e?t[Math.floor(Math.random()*t.length)]:0!==t.length&&e?(t=t.slice(),Array.from({length:e},(()=>t.splice(Math.floor(Math.random()*t.length),1)[0]))):[]}randomKey(e){let t=this.keyArray();return void 0===e?t[Math.floor(Math.random()*t.length)]:0!==t.length&&e?(t=t.slice(),Array.from({length:e},(()=>t.splice(Math.floor(Math.random()*t.length),1)[0]))):[]}find(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(e(i,t,this))return i}findKey(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(e(i,t,this))return t}sweep(e,t){void 0!==t&&(e=e.bind(t));const i=this.size;for(const[t,i]of this)e(i,t,this)&&this.delete(t);return i-this.size}filter(e,t){void 0!==t&&(e=e.bind(t));const i=new this.constructor[Symbol.species];for(const[t,s]of this)e(s,t,this)&&i.set(t,s);return i}partition(e,t){void 0!==t&&(e=e.bind(t));const i=[new this.constructor[Symbol.species],new this.constructor[Symbol.species]];for(const[t,s]of this)e(s,t,this)?i[0].set(t,s):i[1].set(t,s);return i}flatMap(e,t){const i=this.map(e,t);return(new this.constructor[Symbol.species]).concat(...i)}map(e,t){void 0!==t&&(e=e.bind(t));const i=this.entries();return Array.from({length:this.size},(()=>{const[t,s]=i.next().value;return e(s,t,this)}))}mapValues(e,t){void 0!==t&&(e=e.bind(t));const i=new this.constructor[Symbol.species];for(const[t,s]of this)i.set(t,e(s,t,this));return i}some(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(e(i,t,this))return!0;return!1}every(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(!e(i,t,this))return!1;return!0}reduce(e,t){let i;if(void 0!==t){i=t;for(const[t,s]of this)i=e(i,s,t,this);return i}let s=!0;for(const[t,n]of this)s?(i=n,s=!1):i=e(i,n,t,this);if(s)throw new TypeError("Reduce of empty collection with no initial value");return i}each(e,t){return this.forEach(e,t),this}tap(e,t){return void 0!==t&&(e=e.bind(t)),e(this),this}clone(){return new this.constructor[Symbol.species](this)}concat(...e){const t=this.clone();for(const i of e)for(const[e,s]of i)t.set(e,s);return t}equals(e){if(!e)return!1;if(this===e)return!0;if(this.size!==e.size)return!1;for(const[t,i]of this)if(!e.has(t)||i!==e.get(t))return!1;return!0}sort(e=((e,t)=>Number(e>t)||Number(e===t)-1)){const t=[...this.entries()];t.sort(((t,i)=>e(t[1],i[1],t[0],i[0]))),super.clear(),this._array=null,this._keyArray=null;for(const[e,i]of t)super.set(e,i);return this}intersect(e){return e.filter(((e,t)=>this.has(t)))}difference(e){return e.filter(((e,t)=>!this.has(t))).concat(this.filter(((t,i)=>!e.has(i))))}sorted(e=((e,t)=>Number(e>t)||Number(e===t)-1)){return new this.constructor[Symbol.species]([...this.entries()]).sort(((t,i,s,n)=>e(t,i,s,n)))}}t.Collection=Collection,Collection.default=Collection,e.exports=Collection,t.default=Collection},function(e,t,i){"use strict";const s=i(108),n=i(112),r=i(113),{Error:o}=i(2),a=i(3),{Endpoints:c}=i(0);e.exports=class RESTManager{constructor(e,t="Bot"){this.client=e,this.handlers=new a,this.tokenPrefix=t,this.versioned=!0,this.globalTimeout=null,e.options.restSweepInterval>0&&e.setInterval((()=>{this.handlers.sweep((e=>e._inactive))}),1e3*e.options.restSweepInterval)}get api(){return n(this)}getAuth(){const e=this.client.token||this.client.accessToken;if(e)return`${this.tokenPrefix} ${e}`;throw new o("TOKEN_MISSING")}get cdn(){return c.CDN(this.client.options.http.cdn)}request(e,t,i={}){const n=new s(this,e,t,i);let o=this.handlers.get(n.route);return o||(o=new r(this),this.handlers.set(n.route,o)),o.push(n)}get endpoint(){return this.client.options.http.api}set endpoint(e){this.client.options.http.api=e}}},function(e,t,i){"use strict";const s=i(109),n=i(110),r=i(111),o=i(36),{browser:a,UserAgent:c}=i(0);if(s.Agent)var l=new s.Agent({keepAlive:!0});e.exports=class APIRequest{constructor(e,t,i,s){this.rest=e,this.client=e.client,this.method=t,this.route=s.route,this.options=s,this.retries=0;let n="";if(s.query){const e=Object.entries(s.query).filter((([,e])=>![null,"null","undefined"].includes(e)&&void 0!==e)).flatMap((([e,t])=>Array.isArray(t)?t.map((t=>[e,t])):[[e,t]]));n=new URLSearchParams(e).toString()}this.path=`${i}${n&&"?"+n}`}make(){const e=(!1===this.options.versioned?this.client.options.http.api:`${this.client.options.http.api}/v${this.client.options.http.version}`)+this.path;let t,i={};if(!1!==this.options.auth&&(i.Authorization=this.rest.getAuth()),this.options.reason&&(i["X-Audit-Log-Reason"]=encodeURIComponent(this.options.reason)),a||(i["User-Agent"]=c),this.options.headers&&(i=Object.assign(i,this.options.headers)),this.options.files&&this.options.files.length){t=new n;for(const e of this.options.files)e&&e.file&&t.append(e.name,e.file,e.name);void 0!==this.options.data&&t.append("payload_json",JSON.stringify(this.options.data)),a||(i=Object.assign(i,t.getHeaders()))}else null!=this.options.data&&(t=JSON.stringify(this.options.data),i["Content-Type"]="application/json");const s=new r,h=this.client.setTimeout((()=>s.abort()),this.client.options.restRequestTimeout);return o(e,{method:this.method,headers:i,agent:l,body:t,signal:s.signal}).finally((()=>this.client.clearTimeout(h)))}}},function(e,t){},function(e,t){e.exports="object"==typeof self?self.FormData:window.FormData},function(e,t,i){"use strict";const{AbortController:s,AbortSignal:n}="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0;e.exports=s,e.exports.AbortSignal=n,e.exports.default=s},function(e,t,i){"use strict";const noop=()=>{},s=["get","post","delete","patch","put"],n=["toString","valueOf","inspect","constructor",Symbol.toPrimitive,Symbol.for("nodejs.util.inspect.custom")];e.exports=function buildRoute(e){const t=[""],i={get(r,o){if(n.includes(o))return()=>t.join("/");if(s.includes(o)){const i=[];for(let e=0;ee.request(o,t.join("/"),Object.assign({versioned:e.versioned,route:i.join("/")},s))}return t.push(o),new Proxy(noop,i)},apply:(e,s,n)=>(t.push(...n.filter((e=>null!=e))),new Proxy(noop,i))};return new Proxy(noop,i)}},function(e,t,i){"use strict";const s=i(114),n=i(64),r=i(65),{Events:{RATE_LIMIT:o},browser:a}=i(0),c=i(4);function parseResponse(e){return e.headers.get("content-type").startsWith("application/json")?e.json():a?e.blob():e.buffer()}function getAPIOffset(e){return new Date(e).getTime()-Date.now()}e.exports=class RequestHandler{constructor(e){this.manager=e,this.queue=new s,this.reset=-1,this.remaining=-1,this.limit=-1,this.retryAfter=-1}async push(e){await this.queue.wait();try{return await this.execute(e)}finally{this.queue.shift()}}get limited(){return Boolean(this.manager.globalTimeout)||this.remaining<=0&&Date.now()=400&&t.status<500){if(429===t.status)return this.manager.client.emit("debug","429 hit on route "+e.route),await c.delayFor(this.retryAfter),this.execute(e);let i;try{i=await parseResponse(t)}catch(t){throw new r(t.message,t.constructor.name,t.status,e.method,e.path)}throw new n(e.path,i,e.method,t.status)}if(t.status>=500&&t.status<600){if(e.retries===this.manager.client.options.retryLimit)throw new r(t.statusText,t.constructor.name,t.status,e.method,e.path);return e.retries++,this.execute(e)}return null}}},function(e,t,i){"use strict";e.exports=class AsyncQueue{constructor(){this.promises=[]}get remaining(){return this.promises.length}wait(){const e=this.promises.length?this.promises[this.promises.length-1].promise:Promise.resolve();let t;const i=new Promise((e=>{t=e}));return this.promises.push({resolve:t,promise:i}),e}shift(){const e=this.promises.shift();void 0!==e&&e.resolve()}}},function(module,exports,__webpack_require__){"use strict";(function(process){const BaseClient=__webpack_require__(37),ActionsManager=__webpack_require__(116),ClientVoiceManager=__webpack_require__(167),WebSocketManager=__webpack_require__(168),{Error:Error,TypeError:TypeError,RangeError:RangeError}=__webpack_require__(2),ChannelManager=__webpack_require__(98),GuildEmojiManager=__webpack_require__(59),GuildManager=__webpack_require__(99),UserManager=__webpack_require__(100),ShardClientUtil=__webpack_require__(210),ClientApplication=__webpack_require__(50),GuildPreview=__webpack_require__(56),GuildTemplate=__webpack_require__(57),Invite=__webpack_require__(19),VoiceRegion=__webpack_require__(58),Webhook=__webpack_require__(13),Collection=__webpack_require__(3),{Events:Events,browser:browser,DefaultOptions:DefaultOptions}=__webpack_require__(0),DataResolver=__webpack_require__(9),Intents=__webpack_require__(101),Permissions=__webpack_require__(8),Structures=__webpack_require__(10);class Client extends BaseClient{constructor(e={}){super(Object.assign({_tokenType:"Bot"},e));let t=process.env;try{t=__webpack_require__(211).workerData||t}catch{}this.options.shards===DefaultOptions.shards&&"SHARDS"in t&&(this.options.shards=JSON.parse(t.SHARDS)),this.options.shardCount===DefaultOptions.shardCount&&("SHARD_COUNT"in t?this.options.shardCount=Number(t.SHARD_COUNT):Array.isArray(this.options.shards)&&(this.options.shardCount=this.options.shards.length));const i=typeof this.options.shards;"undefined"===i&&"number"==typeof this.options.shardCount&&(this.options.shards=Array.from({length:this.options.shardCount},((e,t)=>t))),"number"===i&&(this.options.shards=[this.options.shards]),Array.isArray(this.options.shards)&&(this.options.shards=[...new Set(this.options.shards.filter((e=>!isNaN(e)&&e>=0&&e<1/0&&e===(0|e))))]),this._validateOptions(),this.ws=new WebSocketManager(this),this.actions=new ActionsManager(this),this.voice=browser?null:new ClientVoiceManager(this),this.shard=!browser&&process.env.SHARDING_MANAGER?ShardClientUtil.singleton(this,process.env.SHARDING_MANAGER_MODE):null,this.users=new UserManager(this),this.guilds=new GuildManager(this),this.channels=new ChannelManager(this);const s=Structures.get("ClientPresence");this.presence=new s(this),Object.defineProperty(this,"token",{writable:!0}),browser||this.token||!("DISCORD_TOKEN"in process.env)?this.token=null:this.token=process.env.DISCORD_TOKEN,this.user=null,this.readyAt=null,this.options.messageSweepInterval>0&&this.setInterval(this.sweepMessages.bind(this),1e3*this.options.messageSweepInterval)}get emojis(){const e=new GuildEmojiManager({client:this});for(const t of this.guilds.cache.values())if(t.available)for(const i of t.emojis.cache.values())e.cache.set(i.id,i);return e}get readyTimestamp(){return this.readyAt?this.readyAt.getTime():null}get uptime(){return this.readyAt?Date.now()-this.readyAt:null}async login(e=this.token){if(!e||"string"!=typeof e)throw new Error("TOKEN_INVALID");this.token=e=e.replace(/^(Bot|Bearer)\s*/i,""),this.emit(Events.DEBUG,"Provided token: "+e.split(".").map(((e,t)=>t>1?e.replace(/./g,"*"):e)).join(".")),this.options.presence&&(this.options.ws.presence=await this.presence._parse(this.options.presence)),this.emit(Events.DEBUG,"Preparing to connect to the gateway...");try{return await this.ws.connect(),this.token}catch(e){throw this.destroy(),e}}destroy(){super.destroy(),this.ws.destroy(),this.token=null}fetchInvite(e){const t=DataResolver.resolveInviteCode(e);return this.api.invites(t).get({query:{with_counts:!0}}).then((e=>new Invite(this,e)))}fetchGuildTemplate(e){const t=DataResolver.resolveGuildTemplateCode(e);return this.api.guilds.templates(t).get().then((e=>new GuildTemplate(this,e)))}fetchWebhook(e,t){return this.api.webhooks(e,t).get().then((e=>new Webhook(this,e)))}fetchVoiceRegions(){return this.api.voice.regions.get().then((e=>{const t=new Collection;for(const i of e)t.set(i.id,new VoiceRegion(i));return t}))}sweepMessages(e=this.options.messageCacheLifetime){if("number"!=typeof e||isNaN(e))throw new TypeError("INVALID_TYPE","lifetime","number");if(e<=0)return this.emit(Events.DEBUG,"Didn't sweep messages - lifetime is unlimited"),-1;const t=1e3*e,i=Date.now();let s=0,n=0;for(const e of this.channels.cache.values())e.messages&&(s++,n+=e.messages.cache.sweep((e=>i-(e.editedTimestamp||e.createdTimestamp)>t)));return this.emit(Events.DEBUG,`Swept ${n} messages older than ${e} seconds in ${s} text-based channels`),n}fetchApplication(){return this.api.oauth2.applications("@me").get().then((e=>new ClientApplication(this,e)))}fetchGuildPreview(e){const t=this.guilds.resolveID(e);if(!t)throw new TypeError("INVALID_TYPE","guild","GuildResolvable");return this.api.guilds(t).preview.get().then((e=>new GuildPreview(this,e)))}async generateInvite(e={}){(Array.isArray(e)||["string","number"].includes(typeof e)||e instanceof Permissions)&&(process.emitWarning("Client#generateInvite: Generate invite with an options object instead of a PermissionResolvable","DeprecationWarning"),e={permissions:e});const t=await this.fetchApplication(),i=new URLSearchParams({client_id:t.id,permissions:Permissions.resolve(e.permissions),scope:"bot"});if("boolean"==typeof e.disableGuildSelect&&i.set("disable_guild_select",e.disableGuildSelect.toString()),void 0!==e.guild){const t=this.guilds.resolveID(e.guild);if(!t)throw new TypeError("INVALID_TYPE","options.guild","GuildResolvable");i.set("guild_id",t)}return`${this.options.http.api}${this.api.oauth2.authorize}?${i}`}toJSON(){return super.toJSON({readyAt:!1})}_eval(script){return eval(script)}_validateOptions(e=this.options){if(void 0!==e.ws.intents&&(e.ws.intents=Intents.resolve(e.ws.intents)),"number"!=typeof e.shardCount||isNaN(e.shardCount)||e.shardCount<1)throw new TypeError("CLIENT_INVALID_OPTION","shardCount","a number greater than or equal to 1");if(e.shards&&"auto"!==e.shards&&!Array.isArray(e.shards))throw new TypeError("CLIENT_INVALID_OPTION","shards","'auto', a number or array of numbers");if(e.shards&&!e.shards.length)throw new RangeError("CLIENT_INVALID_PROVIDED_SHARDS");if("number"!=typeof e.messageCacheMaxSize||isNaN(e.messageCacheMaxSize))throw new TypeError("CLIENT_INVALID_OPTION","messageCacheMaxSize","a number");if("number"!=typeof e.messageCacheLifetime||isNaN(e.messageCacheLifetime))throw new TypeError("CLIENT_INVALID_OPTION","The messageCacheLifetime","a number");if("number"!=typeof e.messageSweepInterval||isNaN(e.messageSweepInterval))throw new TypeError("CLIENT_INVALID_OPTION","messageSweepInterval","a number");if("number"!=typeof e.messageEditHistoryMaxSize||isNaN(e.messageEditHistoryMaxSize)||e.messageEditHistoryMaxSize<-1)throw new TypeError("CLIENT_INVALID_OPTION","messageEditHistoryMaxSize","a number greater than or equal to -1");if("boolean"!=typeof e.fetchAllMembers)throw new TypeError("CLIENT_INVALID_OPTION","fetchAllMembers","a boolean");if("string"!=typeof e.disableMentions)throw new TypeError("CLIENT_INVALID_OPTION","disableMentions","a string");if(!Array.isArray(e.partials))throw new TypeError("CLIENT_INVALID_OPTION","partials","an Array");if("number"!=typeof e.restWsBridgeTimeout||isNaN(e.restWsBridgeTimeout))throw new TypeError("CLIENT_INVALID_OPTION","restWsBridgeTimeout","a number");if("number"!=typeof e.restRequestTimeout||isNaN(e.restRequestTimeout))throw new TypeError("CLIENT_INVALID_OPTION","restRequestTimeout","a number");if("number"!=typeof e.restSweepInterval||isNaN(e.restSweepInterval))throw new TypeError("CLIENT_INVALID_OPTION","restSweepInterval","a number");if("number"!=typeof e.retryLimit||isNaN(e.retryLimit))throw new TypeError("CLIENT_INVALID_OPTION","retryLimit","a number")}}module.exports=Client}).call(this,__webpack_require__(15))},function(e,t,i){"use strict";e.exports=class ActionsManager{constructor(e){this.client=e,this.register(i(117)),this.register(i(118)),this.register(i(119)),this.register(i(120)),this.register(i(121)),this.register(i(122)),this.register(i(123)),this.register(i(124)),this.register(i(125)),this.register(i(126)),this.register(i(144)),this.register(i(145)),this.register(i(146)),this.register(i(147)),this.register(i(148)),this.register(i(149)),this.register(i(150)),this.register(i(151)),this.register(i(152)),this.register(i(153)),this.register(i(154)),this.register(i(155)),this.register(i(156)),this.register(i(157)),this.register(i(158)),this.register(i(159)),this.register(i(160)),this.register(i(161)),this.register(i(162)),this.register(i(163)),this.register(i(164)),this.register(i(165)),this.register(i(166))}register(e){this[e.name.replace(/Action$/,"")]=new e(this.client)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageCreateAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id);if(i){const s=i.messages.cache.get(e.id);if(s)return{message:s};const r=i.messages.add(e),o=r.author;let a=r.member;return i.lastMessageID=e.id,o&&(o.lastMessageID=e.id,o.lastMessageChannelID=i.id),a&&(a.lastMessageID=e.id,a.lastMessageChannelID=i.id),t.emit(n.MESSAGE_CREATE,r),{message:r}}return{}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageDeleteAction extends s{handle(e){const t=this.client,i=this.getChannel(e);let s;return i&&(s=this.getMessage(e,i),s&&(i.messages.cache.delete(s.id),s.deleted=!0,t.emit(n.MESSAGE_DELETE,s))),{message:s}}}},function(e,t,i){"use strict";const s=i(1),n=i(3),{Events:r}=i(0);e.exports=class MessageDeleteBulkAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id);if(i){const s=e.ids,o=new n;for(const t of s){const s=this.getMessage({id:t,guild_id:e.guild_id},i,!1);s&&(s.deleted=!0,o.set(s.id,s),i.messages.cache.delete(t))}return o.size>0&&t.emit(r.MESSAGE_BULK_DELETE,o),{messages:o}}return{}}}},function(e,t,i){"use strict";const s=i(1);e.exports=class MessageUpdateAction extends s{handle(e){const t=this.getChannel(e);if(t){const{id:i,channel_id:s,guild_id:n,author:r,timestamp:o,type:a}=e,c=this.getMessage({id:i,channel_id:s,guild_id:n,author:r,timestamp:o,type:a},t);if(c){return{old:c.patch(e),updated:c}}}return{}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0),{PartialTypes:r}=i(0);e.exports=class MessageReactionAdd extends s{handle(e){if(!e.emoji)return!1;const t=this.getUserFromMember(e);if(!t)return!1;const i=this.getChannel(e);if(!i||"voice"===i.type)return!1;const s=this.getMessage(e,i);if(!s)return!1;if(s.partial&&!this.client.options.partials.includes(r.REACTION))return!1;const o=s.reactions.cache.get(e.emoji.id||e.emoji.name);if(o&&o.users.cache.has(t.id))return{message:s,reaction:o,user:t};const a=s.reactions.add({emoji:e.emoji,count:s.partial?null:0,me:t.id===this.client.user.id});return!!a&&(a._add(t),this.client.emit(n.MESSAGE_REACTION_ADD,a,t),{message:s,reaction:a,user:t})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageReactionRemove extends s{handle(e){if(!e.emoji)return!1;const t=this.getUser(e);if(!t)return!1;const i=this.getChannel(e);if(!i||"voice"===i.type)return!1;const s=this.getMessage(e,i);if(!s)return!1;const r=this.getReaction(e,s,t);return!!r&&(r._remove(t),this.client.emit(n.MESSAGE_REACTION_REMOVE,r,t),{message:s,reaction:r,user:t})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageReactionRemoveAll extends s{handle(e){const t=this.getChannel(e);if(!t||"voice"===t.type)return!1;const i=this.getMessage(e,t);return!!i&&(i.reactions.cache.clear(),this.client.emit(n.MESSAGE_REACTION_REMOVE_ALL,i),{message:i})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageReactionRemoveEmoji extends s{handle(e){const t=this.getChannel(e);if(!t||"voice"===t.type)return!1;const i=this.getMessage(e,t);if(!i)return!1;const s=this.getReaction(e,i);return!!s&&(i.partial||i.reactions.cache.delete(s.emoji.id||s.emoji.name),this.client.emit(n.MESSAGE_REACTION_REMOVE_EMOJI,s),{reaction:s})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class ChannelCreateAction extends s{handle(e){const t=this.client,i=t.channels.cache.has(e.id),s=t.channels.add(e);return!i&&s&&t.emit(n.CHANNEL_CREATE,s),{channel:s}}}},function(e,t,i){"use strict";const s=i(1),n=i(39),{Events:r}=i(0);e.exports=class ChannelDeleteAction extends s{constructor(e){super(e),this.deleted=new Map}handle(e){const t=this.client;let i=t.channels.cache.get(e.id);if(i){if(t.channels.remove(i.id),i.deleted=!0,i.messages&&!(i instanceof n))for(const e of i.messages.cache.values())e.deleted=!0;t.emit(r.CHANNEL_DELETE,i)}return{channel:i}}}},function(e,t,i){e.exports=Stream;var s=i(16).EventEmitter;function Stream(){s.call(this)}i(23)(Stream,s),Stream.Readable=i(45),Stream.Writable=i(133),Stream.Duplex=i(134),Stream.Transform=i(135),Stream.PassThrough=i(136),Stream.Stream=Stream,Stream.prototype.pipe=function(e,t){var i=this;function ondata(t){e.writable&&!1===e.write(t)&&i.pause&&i.pause()}function ondrain(){i.readable&&i.resume&&i.resume()}i.on("data",ondata),e.on("drain",ondrain),e._isStdio||t&&!1===t.end||(i.on("end",onend),i.on("close",onclose));var n=!1;function onend(){n||(n=!0,e.end())}function onclose(){n||(n=!0,"function"==typeof e.destroy&&e.destroy())}function onerror(e){if(cleanup(),0===s.listenerCount(this,"error"))throw e}function cleanup(){i.removeListener("data",ondata),e.removeListener("drain",ondrain),i.removeListener("end",onend),i.removeListener("close",onclose),i.removeListener("error",onerror),e.removeListener("error",onerror),i.removeListener("end",cleanup),i.removeListener("close",cleanup),e.removeListener("close",cleanup)}return i.on("error",onerror),e.on("error",onerror),i.on("end",cleanup),i.on("close",cleanup),e.on("close",cleanup),e.emit("pipe",i),e}},function(e,t){},function(e,t,i){"use strict";var s=i(32).Buffer,n=i(130);e.exports=function(){function BufferList(){!function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,BufferList),this.head=null,this.tail=null,this.length=0}return BufferList.prototype.push=function push(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},BufferList.prototype.unshift=function unshift(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},BufferList.prototype.shift=function shift(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},BufferList.prototype.clear=function clear(){this.head=this.tail=null,this.length=0},BufferList.prototype.join=function join(e){if(0===this.length)return"";for(var t=this.head,i=""+t.data;t=t.next;)i+=e+t.data;return i},BufferList.prototype.concat=function concat(e){if(0===this.length)return s.alloc(0);if(1===this.length)return this.head.data;for(var t,i,n,r=s.allocUnsafe(e>>>0),o=this.head,a=0;o;)t=o.data,i=r,n=a,t.copy(i,n),a+=o.data.length,o=o.next;return r},BufferList}(),n&&n.inspect&&n.inspect.custom&&(e.exports.prototype[n.inspect.custom]=function(){var e=n.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,i){(function(t){function config(e){try{if(!t.localStorage)return!1}catch(e){return!1}var i=t.localStorage[e];return null!=i&&"true"===String(i).toLowerCase()}e.exports=function deprecate(e,t){if(config("noDeprecation"))return e;var i=!1;return function deprecated(){if(!i){if(config("throwDeprecation"))throw new Error(t);config("traceDeprecation")?console.trace(t):console.warn(t),i=!0}return e.apply(this,arguments)}}}).call(this,i(22))},function(e,t,i){"use strict";e.exports=PassThrough;var s=i(71),n=Object.create(i(26));function PassThrough(e){if(!(this instanceof PassThrough))return new PassThrough(e);s.call(this,e)}n.inherits=i(23),n.inherits(PassThrough,s),PassThrough.prototype._transform=function(e,t,i){i(null,e)}},function(e,t,i){e.exports=i(46)},function(e,t,i){e.exports=i(21)},function(e,t,i){e.exports=i(45).Transform},function(e,t,i){e.exports=i(45).PassThrough},function(e,t,i){"use strict";const s=i(3);class LimitedCollection extends s{constructor(e=0,t=null){super(t),this.maxSize=e}set(e,t){return 0===this.maxSize?this:(this.size>=this.maxSize&&!this.has(e)&&this.delete(this.firstKey()),super.set(e,t))}static get[Symbol.species](){return s}}e.exports=LimitedCollection},function(e,t){e.exports=function isBuffer(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){"function"==typeof Object.create?e.exports=function inherits(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function inherits(e,t){e.super_=t;var TempCtor=function(){};TempCtor.prototype=t.prototype,e.prototype=new TempCtor,e.prototype.constructor=e}},function(e,t,i){"use strict";const s=i(51);e.exports=class IntegrationApplication extends s{_patch(e){super._patch(e),void 0!==e.bot?this.bot=this.client.users.add(e.bot):this.bot||(this.bot=null)}}},function(e,t,i){"use strict";const s=i(40);e.exports=class GuildPreviewEmoji extends s{get roles(){return new Set(this._roles)}}},function(e,t,i){"use strict";const s=i(7);e.exports=class VoiceStateManager extends s{constructor(e,t){super(e.client,t,{name:"VoiceState"}),this.guild=e}add(e,t=!0){const i=this.cache.get(e.user_id);if(i)return i._patch(e);const s=new this.holds(this.guild,e);return t&&this.cache.set(e.user_id,s),s}}},function(e,t,i){"use strict";const s=i(17),{Error:n}=i(2);e.exports=class PartialGroupDMChannel extends s{constructor(e,t){super(e,t),this.name=t.name,this.icon=t.icon}iconURL({format:e,size:t}={}){return this.icon?this.client.rest.cdn.GDMIcon(this.id,this.icon,e,t):null}delete(){return Promise.reject(new n("DELETE_GROUP_DM_CHANNEL"))}fetch(){return Promise.reject(new n("FETCH_GROUP_DM_CHANNEL"))}}},function(e,t,i){"use strict";const s=i(1),n=i(17),{ChannelTypes:r}=i(0);e.exports=class ChannelUpdateAction extends s{handle(e){let t=this.client.channels.cache.get(e.id);if(t){const i=t._update(e);if(r[t.type.toUpperCase()]!==e.type){const i=n.create(this.client,e,t.guild);for(const[e,s]of t.messages.cache)i.messages.cache.set(e,s);i._typing=new Map(t._typing),t=i,this.client.channels.cache.set(t.id,t)}return{old:i,updated:t}}return{}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildDeleteAction extends s{constructor(e){super(e),this.deleted=new Map}handle(e){const t=this.client;let i=t.guilds.cache.get(e.id);if(i){for(const e of i.channels.cache.values())"text"===e.type&&e.stopTyping(!0);if(e.unavailable)return i.available=!1,t.emit(n.GUILD_UNAVAILABLE,i),{guild:null};for(const e of i.channels.cache.values())this.client.channels.remove(e.id);i.voice&&i.voice.connection&&i.voice.connection.disconnect(),t.guilds.cache.delete(i.id),i.deleted=!0,t.emit(n.GUILD_DELETE,i),this.deleted.set(i.id,i),this.scheduleForDeletion(i.id)}else i=this.deleted.get(e.id)||null;return{guild:i}}scheduleForDeletion(e){this.client.setTimeout((()=>this.deleted.delete(e)),this.client.options.restWsBridgeTimeout)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildUpdateAction extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.id);if(i){const s=i._update(e);return t.emit(n.GUILD_UPDATE,s,i),{old:s,updated:i}}return{old:null,updated:null}}}},function(e,t,i){"use strict";const s=i(1),n=i(19),{Events:r}=i(0);e.exports=class InviteCreateAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id),s=t.guilds.cache.get(e.guild_id);if(!i)return!1;const o=Object.assign(e,{channel:i,guild:s}),a=new n(t,o);return t.emit(r.INVITE_CREATE,a),{invite:a}}}},function(e,t,i){"use strict";const s=i(1),n=i(19),{Events:r}=i(0);e.exports=class InviteDeleteAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id),s=t.guilds.cache.get(e.guild_id);if(!i)return!1;const o=Object.assign(e,{channel:i,guild:s}),a=new n(t,o);return t.emit(r.INVITE_DELETE,a),{invite:a}}}},function(e,t,i){"use strict";const s=i(1),{Events:n,Status:r}=i(0);e.exports=class GuildMemberRemoveAction extends s{handle(e,t){const i=this.client,s=i.guilds.cache.get(e.guild_id);let o=null;return s&&(o=this.getMember({user:e.user},s),s.memberCount--,o&&(o.deleted=!0,s.members.cache.delete(o.id),t.status===r.READY&&i.emit(n.GUILD_MEMBER_REMOVE,o)),s.voiceStates.cache.delete(e.user.id)),{guild:s,member:o}}}},function(e,t,i){"use strict";const s=i(1),{Status:n,Events:r}=i(0);e.exports=class GuildMemberUpdateAction extends s{handle(e,t){const{client:i}=this;if(e.user.username){const t=i.users.cache.get(e.user.id);t?t.equals(e.user)||i.actions.UserUpdate.handle(e.user):i.users.add(e.user)}const s=i.guilds.cache.get(e.guild_id);if(s){const o=this.getMember({user:e.user},s);if(o){const s=o._update(e);t.status===n.READY&&i.emit(r.GUILD_MEMBER_UPDATE,s,o)}else{const t=s.members.add(e);this.client.emit(r.GUILD_MEMBER_AVAILABLE,t)}}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildBanRemove extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id),s=t.users.add(e.user);i&&s&&t.emit(n.GUILD_BAN_REMOVE,i,s)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildRoleCreate extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);let s;if(i){const r=i.roles.cache.has(e.role.id);s=i.roles.add(e.role),r||t.emit(n.GUILD_ROLE_CREATE,s)}return{role:s}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildRoleDeleteAction extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);let s;return i&&(s=i.roles.cache.get(e.role_id),s&&(i.roles.cache.delete(e.role_id),s.deleted=!0,t.emit(n.GUILD_ROLE_DELETE,s))),{role:s}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildRoleUpdateAction extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);if(i){let s=null;const r=i.roles.cache.get(e.role.id);return r&&(s=r._update(e.role),t.emit(n.GUILD_ROLE_UPDATE,s,r)),{old:s,updated:r}}return{old:null,updated:null}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class PresenceUpdateAction extends s{handle(e){let t=this.client.users.cache.get(e.user.id);if(!t&&e.user.username&&(t=this.client.users.add(e.user)),!t)return;e.user&&e.user.username&&(t.equals(e.user)||this.client.actions.UserUpdate.handle(e.user));const i=this.client.guilds.cache.get(e.guild_id);if(!i)return;let s=i.presences.cache.get(t.id);s&&(s=s._clone());let r=i.members.cache.get(t.id);r||"offline"===e.status||(r=i.members.add({user:t,roles:e.roles,deaf:!1,mute:!1}),this.client.emit(n.GUILD_MEMBER_AVAILABLE,r)),i.presences.add(Object.assign(e,{guild:i})),r&&this.client.listenerCount(n.PRESENCE_UPDATE)&&this.client.emit(n.PRESENCE_UPDATE,s,r.presence)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class UserUpdateAction extends s{handle(e){const t=this.client,i=t.users.cache.get(e.id),s=i._update(e);return s.equals(i)?{old:null,updated:null}:(t.emit(n.USER_UPDATE,s,i),{old:s,updated:i})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0),r=i(10);e.exports=class VoiceStateUpdate extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);if(i){const s=r.get("VoiceState"),o=i.voiceStates.cache.has(e.user_id)?i.voiceStates.cache.get(e.user_id)._clone():new s(i,{user_id:e.user_id}),a=i.voiceStates.add(e);let c=i.members.cache.get(e.user_id);c&&e.member?c._patch(e.member):e.member&&e.member.user&&e.member.joined_at&&(c=i.members.add(e.member)),c&&c.user.id===t.user.id&&(t.emit("debug","[VOICE] received voice state update: "+JSON.stringify(e)),t.voice.onVoiceStateUpdate(e)),t.emit(n.VOICE_STATE_UPDATE,o,a)}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildEmojiCreateAction extends s{handle(e,t){const i=e.emojis.cache.has(t.id),s=e.emojis.add(t);return i||this.client.emit(n.GUILD_EMOJI_CREATE,s),{emoji:s}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildEmojiDeleteAction extends s{handle(e){return e.guild.emojis.cache.delete(e.id),e.deleted=!0,this.client.emit(n.GUILD_EMOJI_DELETE,e),{emoji:e}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildEmojiUpdateAction extends s{handle(e,t){const i=e._update(t);return this.client.emit(n.GUILD_EMOJI_UPDATE,i,e),{emoji:e}}}},function(e,t,i){"use strict";const s=i(1);e.exports=class GuildEmojisUpdateAction extends s{handle(e){const t=this.client.guilds.cache.get(e.guild_id);if(!t||!t.emojis)return;const i=new Map(t.emojis.cache);for(const s of e.emojis){const e=t.emojis.cache.get(s.id);e?(i.delete(s.id),e.equals(s)||this.client.actions.GuildEmojiUpdate.handle(e,s)):this.client.actions.GuildEmojiCreate.handle(t,s)}for(const e of i.values())this.client.actions.GuildEmojiDelete.handle(e)}}},function(e,t,i){"use strict";const s=i(1);e.exports=class GuildRolesPositionUpdate extends s{handle(e){const t=this.client.guilds.cache.get(e.guild_id);if(t)for(const i of e.roles){const e=t.roles.cache.get(i.id);e&&(e.rawPosition=i.position)}return{guild:t}}}},function(e,t,i){"use strict";const s=i(1);e.exports=class GuildChannelsPositionUpdate extends s{handle(e){const t=this.client.guilds.cache.get(e.guild_id);if(t)for(const i of e.channels){const e=t.channels.cache.get(i.id);e&&(e.rawPosition=i.position)}return{guild:t}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildIntegrationsUpdate extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);i&&t.emit(n.GUILD_INTEGRATIONS_UPDATE,i)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class WebhooksUpdate extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id);i&&t.emit(n.WEBHOOKS_UPDATE,i)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0),r=["dm","text","news"];e.exports=class TypingStart extends s{handle(e){const t=this.getChannel(e);if(!t)return;if(!r.includes(t.type))return void this.client.emit(n.WARN,`Discord sent a typing packet to a ${t.type} channel ${t.id}`);const i=this.getUserFromMember(e),s=new Date(1e3*e.timestamp);if(t&&i)if(t._typing.has(i.id)){const e=t._typing.get(i.id);e.lastTimestamp=s,e.elapsedTime=Date.now()-e.since,this.client.clearTimeout(e.timeout),e.timeout=this.tooLate(t,i)}else{const e=new Date,s=new Date;t._typing.set(i.id,{user:i,since:e,lastTimestamp:s,elapsedTime:Date.now()-e,timeout:this.tooLate(t,i)}),this.client.emit(n.TYPING_START,t,i)}}tooLate(e,t){return e.client.setTimeout((()=>{e._typing.delete(t.id)}),1e4)}}},function(e,t){},function(e,t,i){"use strict";const s=i(16),n=i(169),r=i(96),{Error:o}=i(2),a=i(3),{Events:c,ShardEvents:l,Status:h,WSCodes:u,WSEvents:d}=i(0),f=i(4),p=[d.READY,d.RESUMED,d.GUILD_CREATE,d.GUILD_DELETE,d.GUILD_MEMBERS_CHUNK,d.GUILD_MEMBER_ADD,d.GUILD_MEMBER_REMOVE],m=Object.keys(u).slice(1).map(Number),g=[1e3,4006,4007];e.exports=class WebSocketManager extends s{constructor(e){super(),Object.defineProperty(this,"client",{value:e}),this.gateway=null,this.totalShards=this.client.options.shards.length,this.shards=new a,Object.defineProperty(this,"shardQueue",{value:new Set,writable:!0}),Object.defineProperty(this,"packetQueue",{value:[]}),this.status=h.IDLE,this.destroyed=!1,this.reconnecting=!1,this.sessionStartLimit=null}get ping(){return this.shards.reduce(((e,t)=>e+t.ping),0)/this.shards.size}debug(e,t){this.client.emit(c.DEBUG,`[WS => ${t?"Shard "+t.id:"Manager"}] ${e}`)}async connect(){const e=new o(u[4004]),{url:t,shards:i,session_start_limit:s}=await this.client.api.gateway.bot.get().catch((t=>{throw 401===t.httpStatus?e:t}));this.sessionStartLimit=s;const{total:r,remaining:a,reset_after:c}=s;this.debug(`Fetched Gateway Information\n URL: ${t}\n Recommended Shards: ${i}`),this.debug(`Session Limit Information\n Total: ${r}\n Remaining: ${a}`),this.gateway=t+"/";let{shards:l}=this.client.options;return"auto"===l&&(this.debug("Using the recommended shard count provided by Discord: "+i),this.totalShards=this.client.options.shardCount=i,l=this.client.options.shards=Array.from({length:i},((e,t)=>t))),this.totalShards=l.length,this.debug("Spawning shards: "+l.join(", ")),this.shardQueue=new Set(l.map((e=>new n(this,e)))),await this._handleSessionLimit(a,c),this.createShards()}async createShards(){if(!this.shardQueue.size)return!1;const[e]=this.shardQueue;this.shardQueue.delete(e),e.eventsAttached||(e.on(l.ALL_READY,(t=>{this.client.emit(c.SHARD_READY,e.id,t),this.shardQueue.size||(this.reconnecting=!1),this.checkShardsReady()})),e.on(l.CLOSE,(t=>{if(1e3===t.code?this.destroyed:m.includes(t.code))return this.client.emit(c.SHARD_DISCONNECT,t,e.id),void this.debug(u[t.code],e);g.includes(t.code)&&(e.sessionID=null),this.client.emit(c.SHARD_RECONNECTING,e.id),this.shardQueue.add(e),e.sessionID?(this.debug("Session ID is present, attempting an immediate reconnect...",e),this.reconnect(!0)):(e.destroy({reset:!0,emit:!1,log:!1}),this.reconnect())})),e.on(l.INVALID_SESSION,(()=>{this.client.emit(c.SHARD_RECONNECTING,e.id)})),e.on(l.DESTROYED,(()=>{this.debug("Shard was destroyed but no WebSocket connection was present! Reconnecting...",e),this.client.emit(c.SHARD_RECONNECTING,e.id),this.shardQueue.add(e),this.reconnect()})),e.eventsAttached=!0),this.shards.set(e.id,e);try{await e.connect()}catch(t){if(t&&t.code&&m.includes(t.code))throw new o(u[t.code]);if(t&&!t.code)throw t;this.debug("Failed to connect to the gateway, requeueing...",e),this.shardQueue.add(e)}return!this.shardQueue.size||(this.debug(`Shard Queue Size: ${this.shardQueue.size}; continuing in 5 seconds...`),await f.delayFor(5e3),await this._handleSessionLimit(),this.createShards())}async reconnect(e=!1){if(this.reconnecting||this.status!==h.READY)return!1;this.reconnecting=!0;try{e||await this._handleSessionLimit(),await this.createShards()}catch(e){if(this.debug("Couldn't reconnect or fetch information about the gateway. "+e),401!==e.httpStatus)return this.debug("Possible network error occurred. Retrying in 5s..."),await f.delayFor(5e3),this.reconnecting=!1,this.reconnect();this.client.listenerCount(c.INVALIDATED)?(this.client.emit(c.INVALIDATED),this.destroy()):this.client.destroy()}finally{this.reconnecting=!1}return!0}broadcast(e){for(const t of this.shards.values())t.send(e)}destroy(){if(!this.destroyed){this.debug("Manager was destroyed. Called by:\n"+new Error("MANAGER_DESTROYED").stack),this.destroyed=!0,this.shardQueue.clear();for(const e of this.shards.values())e.destroy({closeCode:1e3,reset:!0,emit:!1,log:!1})}}async _handleSessionLimit(e,t){if(void 0===e&&void 0===t){const{session_start_limit:i}=await this.client.api.gateway.bot.get();this.sessionStartLimit=i,e=i.remaining,t=i.reset_after,this.debug(`Session Limit Information\n Total: ${i.total}\n Remaining: ${e}`)}e||(this.debug(`Exceeded identify threshold. Will attempt a connection in ${t}ms`),await f.delayFor(t))}handlePacket(e,t){if(e&&this.status!==h.READY&&!p.includes(e.t))return this.packetQueue.push({packet:e,shard:t}),!1;if(this.packetQueue.length){const e=this.packetQueue.shift();this.client.setImmediate((()=>{this.handlePacket(e.packet,e.shard)}))}return e&&r[e.t]&&r[e.t](this.client,e,t),!0}async checkShardsReady(){if(this.status!==h.READY&&this.shards.size===this.totalShards&&!this.shards.some((e=>e.status!==h.READY))){if(this.status=h.NEARLY,this.client.options.fetchAllMembers)try{const e=this.client.guilds.cache.map((e=>e.available?e.members.fetch():Promise.resolve()));await Promise.all(e)}catch(e){this.debug(`Failed to fetch all members before ready! ${e}\n${e.stack}`)}this.triggerClientReady()}}triggerClientReady(){this.status=h.READY,this.client.readyAt=new Date,this.client.emit(c.CLIENT_READY),this.handlePacket()}}},function(e,t,i){"use strict";const s=i(16),n=i(95),{browser:r,Status:o,Events:a,ShardEvents:c,OPCodes:l,WSEvents:h}=i(0),u=Object.keys(o),d=Object.keys(n.WebSocket);let f;if(!r)try{f=i(172)}catch{}e.exports=class WebSocketShard extends s{constructor(e,t){super(),this.manager=e,this.id=t,this.status=o.IDLE,this.sequence=-1,this.closeSequence=0,this.sessionID=null,this.ping=-1,this.lastPingTimestamp=-1,this.lastHeartbeatAcked=!0,Object.defineProperty(this,"ratelimit",{value:{queue:[],total:120,remaining:120,time:6e4,timer:null}}),Object.defineProperty(this,"connection",{value:null,writable:!0}),Object.defineProperty(this,"inflate",{value:null,writable:!0}),Object.defineProperty(this,"helloTimeout",{value:null,writable:!0}),Object.defineProperty(this,"eventsAttached",{value:!1,writable:!0}),Object.defineProperty(this,"expectedGuilds",{value:null,writable:!0}),Object.defineProperty(this,"readyTimeout",{value:null,writable:!0}),Object.defineProperty(this,"connectedAt",{value:0,writable:!0})}debug(e){this.manager.debug(e,this)}connect(){const{gateway:e,client:t}=this.manager;return this.connection&&this.connection.readyState===n.OPEN&&this.status===o.READY?Promise.resolve():new Promise(((i,s)=>{const cleanup=()=>{this.removeListener(c.CLOSE,onClose),this.removeListener(c.READY,onReady),this.removeListener(c.RESUMED,onResumed),this.removeListener(c.INVALID_SESSION,onInvalidOrDestroyed),this.removeListener(c.DESTROYED,onInvalidOrDestroyed)},onReady=()=>{cleanup(),i()},onResumed=()=>{cleanup(),i()},onClose=e=>{cleanup(),s(e)},onInvalidOrDestroyed=()=>{cleanup(),s()};if(this.once(c.READY,onReady),this.once(c.RESUMED,onResumed),this.once(c.CLOSE,onClose),this.once(c.INVALID_SESSION,onInvalidOrDestroyed),this.once(c.DESTROYED,onInvalidOrDestroyed),this.connection&&this.connection.readyState===n.OPEN)return this.debug("An open connection was found, attempting an immediate identify."),void this.identify();this.connection&&(this.debug("A connection object was found. Cleaning up before continuing.\n State: "+d[this.connection.readyState]),this.destroy({emit:!1}));const r={v:t.options.ws.version};f&&(this.inflate=new f.Inflate({chunkSize:65535,flush:f.Z_SYNC_FLUSH,to:"json"===n.encoding?"string":""}),r.compress="zlib-stream"),this.debug(`[CONNECT]\n Gateway : ${e}\n Version : ${t.options.ws.version}\n Encoding : ${n.encoding}\n Compression: ${f?"zlib-stream":"none"}`),this.status=this.status===o.DISCONNECTED?o.RECONNECTING:o.CONNECTING,this.setHelloTimeout(),this.connectedAt=Date.now();const a=this.connection=n.create(e,r);a.onopen=this.onOpen.bind(this),a.onmessage=this.onMessage.bind(this),a.onerror=this.onError.bind(this),a.onclose=this.onClose.bind(this)}))}onOpen(){this.debug(`[CONNECTED] ${this.connection.url} in ${Date.now()-this.connectedAt}ms`),this.status=o.NEARLY}onMessage({data:e}){let t,i;if(e instanceof ArrayBuffer&&(e=new Uint8Array(e)),f){const i=e.length,s=i>=4&&0===e[i-4]&&0===e[i-3]&&255===e[i-2]&&255===e[i-1];if(this.inflate.push(e,s&&f.Z_SYNC_FLUSH),!s)return;t=this.inflate.result}else t=e;try{i=n.unpack(t),this.manager.client.emit(a.RAW,i,this.id),i.op===l.DISPATCH&&this.manager.emit(i.t,i.d,this.id)}catch(e){return void this.manager.client.emit(a.SHARD_ERROR,e,this.id)}this.onPacket(i)}onError(e){const t=e&&e.error?e.error:e;t&&this.manager.client.emit(a.SHARD_ERROR,t,this.id)}onClose(e){-1!==this.sequence&&(this.closeSequence=this.sequence),this.sequence=-1,this.debug(`[CLOSE]\n Event Code: ${e.code}\n Clean : ${e.wasClean}\n Reason : ${e.reason||"No reason received"}`),this.setHeartbeatTimer(-1),this.setHelloTimeout(-1),this.connection&&this._cleanupConnection(),this.status=o.DISCONNECTED,this.emit(c.CLOSE,e)}onPacket(e){if(e){switch(e.t){case h.READY:this.emit(c.READY),this.sessionID=e.d.session_id,this.expectedGuilds=new Set(e.d.guilds.map((e=>e.id))),this.status=o.WAITING_FOR_GUILDS,this.debug(`[READY] Session ${this.sessionID}.`),this.lastHeartbeatAcked=!0,this.sendHeartbeat("ReadyHeartbeat");break;case h.RESUMED:{this.emit(c.RESUMED),this.status=o.READY;const t=e.s-this.closeSequence;this.debug(`[RESUMED] Session ${this.sessionID} | Replayed ${t} events.`),this.lastHeartbeatAcked=!0,this.sendHeartbeat("ResumeHeartbeat");break}}switch(e.s>this.sequence&&(this.sequence=e.s),e.op){case l.HELLO:this.setHelloTimeout(-1),this.setHeartbeatTimer(e.d.heartbeat_interval),this.identify();break;case l.RECONNECT:this.debug("[RECONNECT] Discord asked us to reconnect"),this.destroy({closeCode:4e3});break;case l.INVALID_SESSION:if(this.debug(`[INVALID SESSION] Resumable: ${e.d}.`),e.d)return void this.identifyResume();this.sequence=-1,this.sessionID=null,this.status=o.RECONNECTING,this.emit(c.INVALID_SESSION);break;case l.HEARTBEAT_ACK:this.ackHeartbeat();break;case l.HEARTBEAT:this.sendHeartbeat("HeartbeatRequest",!0);break;default:this.manager.handlePacket(e,this),this.status===o.WAITING_FOR_GUILDS&&e.t===h.GUILD_CREATE&&(this.expectedGuilds.delete(e.d.id),this.checkReady())}}else this.debug(`Received broken packet: '${e}'.`)}checkReady(){if(this.readyTimeout&&(this.manager.client.clearTimeout(this.readyTimeout),this.readyTimeout=null),!this.expectedGuilds.size)return this.debug("Shard received all its guilds. Marking as fully ready."),this.status=o.READY,void this.emit(c.ALL_READY);this.readyTimeout=this.manager.client.setTimeout((()=>{this.debug("Shard did not receive any more guild packets in 15 seconds.\n Unavailable guild count: "+this.expectedGuilds.size),this.readyTimeout=null,this.status=o.READY,this.emit(c.ALL_READY,this.expectedGuilds)}),15e3)}setHelloTimeout(e){-1!==e?(this.debug("Setting a HELLO timeout for 20s."),this.helloTimeout=this.manager.client.setTimeout((()=>{this.debug("Did not receive HELLO in time. Destroying and connecting again."),this.destroy({reset:!0,closeCode:4009})}),2e4)):this.helloTimeout&&(this.debug("Clearing the HELLO timeout."),this.manager.client.clearTimeout(this.helloTimeout),this.helloTimeout=null)}setHeartbeatTimer(e){-1!==e?(this.debug(`Setting a heartbeat interval for ${e}ms.`),this.heartbeatInterval&&this.manager.client.clearInterval(this.heartbeatInterval),this.heartbeatInterval=this.manager.client.setInterval((()=>this.sendHeartbeat()),e)):this.heartbeatInterval&&(this.debug("Clearing the heartbeat interval."),this.manager.client.clearInterval(this.heartbeatInterval),this.heartbeatInterval=null)}sendHeartbeat(e="HeartbeatTimer",t=[o.WAITING_FOR_GUILDS,o.IDENTIFYING,o.RESUMING].includes(this.status)){if(t&&!this.lastHeartbeatAcked)this.debug(`[${e}] Didn't process heartbeat ack yet but we are still connected. Sending one now.`);else if(!this.lastHeartbeatAcked)return this.debug(`[${e}] Didn't receive a heartbeat ack last time, assuming zombie connection. Destroying and reconnecting.\n Status : ${u[this.status]}\n Sequence : ${this.sequence}\n Connection State: ${this.connection?d[this.connection.readyState]:"No Connection??"}`),void this.destroy({closeCode:4009,reset:!0});this.debug(`[${e}] Sending a heartbeat.`),this.lastHeartbeatAcked=!1,this.lastPingTimestamp=Date.now(),this.send({op:l.HEARTBEAT,d:this.sequence},!0)}ackHeartbeat(){this.lastHeartbeatAcked=!0;const e=Date.now()-this.lastPingTimestamp;this.debug(`Heartbeat acknowledged, latency of ${e}ms.`),this.ping=e}identify(){return this.sessionID?this.identifyResume():this.identifyNew()}identifyNew(){const{client:e}=this.manager;if(!e.token)return void this.debug("[IDENTIFY] No token available to identify a new session.");this.status=o.IDENTIFYING;const t={...e.options.ws,token:e.token,shard:[this.id,Number(e.options.shardCount)]};this.debug(`[IDENTIFY] Shard ${this.id}/${e.options.shardCount}`),this.send({op:l.IDENTIFY,d:t},!0)}identifyResume(){if(!this.sessionID)return this.debug("[RESUME] No session ID was present; identifying as a new session."),void this.identifyNew();this.status=o.RESUMING,this.debug(`[RESUME] Session ${this.sessionID}, sequence ${this.closeSequence}`);const e={token:this.manager.client.token,session_id:this.sessionID,seq:this.closeSequence};this.send({op:l.RESUME,d:e},!0)}send(e,t=!1){this.ratelimit.queue[t?"unshift":"push"](e),this.processQueue()}_send(e){if(!this.connection||this.connection.readyState!==n.OPEN)return this.debug(`Tried to send packet '${JSON.stringify(e)}' but no WebSocket is available!`),void this.destroy({close:4e3});this.connection.send(n.pack(e),(e=>{e&&this.manager.client.emit(a.SHARD_ERROR,e,this.id)}))}processQueue(){if(0!==this.ratelimit.remaining&&0!==this.ratelimit.queue.length)for(this.ratelimit.remaining===this.ratelimit.total&&(this.ratelimit.timer=this.manager.client.setTimeout((()=>{this.ratelimit.remaining=this.ratelimit.total,this.processQueue()}),this.ratelimit.time));this.ratelimit.remaining>0;){const e=this.ratelimit.queue.shift();if(!e)return;this._send(e),this.ratelimit.remaining--}}destroy({closeCode:e=1e3,reset:t=!1,emit:i=!0,log:s=!0}={}){if(s&&this.debug(`[DESTROY]\n Close Code : ${e}\n Reset : ${t}\n Emit DESTROYED: ${i}`),this.setHeartbeatTimer(-1),this.setHelloTimeout(-1),this.connection)if(this.connection.readyState===n.OPEN)this.connection.close(e);else{this.debug("WS State: "+d[this.connection.readyState]),this._cleanupConnection();try{this.connection.close(e)}catch{}i&&this._emitDestroyed()}else i&&this._emitDestroyed();this.connection=null,this.status=o.DISCONNECTED,-1!==this.sequence&&(this.closeSequence=this.sequence),t&&(this.sequence=-1,this.sessionID=null),this.ratelimit.remaining=this.ratelimit.total,this.ratelimit.queue.length=0,this.ratelimit.timer&&(this.manager.client.clearTimeout(this.ratelimit.timer),this.ratelimit.timer=null)}_cleanupConnection(){this.connection.onopen=this.connection.onclose=this.connection.onerror=this.connection.onmessage=null}_emitDestroyed(){this.emit(c.DESTROYED)}}},function(e,t){},function(e,t){},function(e,t){},function(e,t,i){var s={"./CHANNEL_CREATE.js":174,"./CHANNEL_DELETE.js":175,"./CHANNEL_PINS_UPDATE.js":176,"./CHANNEL_UPDATE.js":177,"./GUILD_BAN_ADD.js":178,"./GUILD_BAN_REMOVE.js":179,"./GUILD_CREATE.js":180,"./GUILD_DELETE.js":181,"./GUILD_EMOJIS_UPDATE.js":182,"./GUILD_INTEGRATIONS_UPDATE.js":183,"./GUILD_MEMBERS_CHUNK.js":184,"./GUILD_MEMBER_ADD.js":185,"./GUILD_MEMBER_REMOVE.js":186,"./GUILD_MEMBER_UPDATE.js":187,"./GUILD_ROLE_CREATE.js":188,"./GUILD_ROLE_DELETE.js":189,"./GUILD_ROLE_UPDATE.js":190,"./GUILD_UPDATE.js":191,"./INVITE_CREATE.js":192,"./INVITE_DELETE.js":193,"./MESSAGE_CREATE.js":194,"./MESSAGE_DELETE.js":195,"./MESSAGE_DELETE_BULK.js":196,"./MESSAGE_REACTION_ADD.js":197,"./MESSAGE_REACTION_REMOVE.js":198,"./MESSAGE_REACTION_REMOVE_ALL.js":199,"./MESSAGE_REACTION_REMOVE_EMOJI.js":200,"./MESSAGE_UPDATE.js":201,"./PRESENCE_UPDATE.js":202,"./READY.js":203,"./RESUMED.js":204,"./TYPING_START.js":205,"./USER_UPDATE.js":206,"./VOICE_SERVER_UPDATE.js":207,"./VOICE_STATE_UPDATE.js":208,"./WEBHOOKS_UPDATE.js":209,"./index.js":96};function webpackContext(e){var t=webpackContextResolve(e);return i(t)}function webpackContextResolve(e){if(!i.o(s,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return s[e]}webpackContext.keys=function webpackContextKeys(){return Object.keys(s)},webpackContext.resolve=webpackContextResolve,e.exports=webpackContext,webpackContext.id=173},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.ChannelCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.ChannelDelete.handle(t.d)}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,{d:t})=>{const i=e.channels.cache.get(t.channel_id),n=new Date(t.last_pin_timestamp);i&&!Number.isNaN(n.getTime())&&(i.lastPinTimestamp=n.getTime()||null,e.emit(s.CHANNEL_PINS_UPDATE,i,n))}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,t)=>{const{old:i,updated:n}=e.actions.ChannelUpdate.handle(t.d);i&&n&&e.emit(s.CHANNEL_UPDATE,i,n)}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,{d:t})=>{const i=e.guilds.cache.get(t.guild_id),n=e.users.add(t.user);i&&n&&e.emit(s.GUILD_BAN_ADD,i,n)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildBanRemove.handle(t.d)}},function(e,t,i){"use strict";const{Events:s,Status:n}=i(0);e.exports=async(e,{d:t},i)=>{let r=e.guilds.cache.get(t.id);r?r.available||t.unavailable||(r._patch(t),e.ws.status===n.READY&&e.options.fetchAllMembers&&await r.members.fetch().catch((t=>e.emit(s.DEBUG,`Failed to fetch all members: ${t}\n${t.stack}`)))):(t.shardID=i.id,r=e.guilds.add(t),e.ws.status===n.READY&&(e.options.fetchAllMembers&&await r.members.fetch().catch((t=>e.emit(s.DEBUG,`Failed to fetch all members: ${t}\n${t.stack}`))),e.emit(s.GUILD_CREATE,r)))}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildEmojisUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildIntegrationsUpdate.handle(t.d)}},function(e,t,i){"use strict";const s=i(3),{Events:n}=i(0);e.exports=(e,{d:t})=>{const i=e.guilds.cache.get(t.guild_id);if(!i)return;const r=new s;for(const e of t.members)r.set(e.user.id,i.members.add(e));if(t.presences)for(const e of t.presences)i.presences.add(Object.assign(e,{guild:i}));e.emit(n.GUILD_MEMBERS_CHUNK,r,i,{count:t.chunk_count,index:t.chunk_index,nonce:t.nonce})}},function(e,t,i){"use strict";const{Events:s,Status:n}=i(0);e.exports=(e,{d:t},i)=>{const r=e.guilds.cache.get(t.guild_id);if(r){r.memberCount++;const o=r.members.add(t);i.status===n.READY&&e.emit(s.GUILD_MEMBER_ADD,o)}}},function(e,t,i){"use strict";e.exports=(e,t,i)=>{e.actions.GuildMemberRemove.handle(t.d,i)}},function(e,t,i){"use strict";e.exports=(e,t,i)=>{e.actions.GuildMemberUpdate.handle(t.d,i)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildRoleCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildRoleDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildRoleUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.InviteCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.InviteDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageDeleteBulk.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionAdd.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionRemove.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionRemoveAll.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionRemoveEmoji.handle(t.d)}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,t)=>{const{old:i,updated:n}=e.actions.MessageUpdate.handle(t.d);i&&n&&e.emit(s.MESSAGE_UPDATE,i,n)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.PresenceUpdate.handle(t.d)}},function(e,t,i){"use strict";let s;e.exports=(e,{d:t},n)=>{if(e.user)e.user._patch(t.user);else{s||(s=i(97));const n=new s(e,t.user);e.user=n,e.users.cache.set(n.id,n)}for(const i of t.guilds)i.shardID=n.id,e.guilds.add(i);n.checkReady()}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,t,i)=>{const n=i.sequence-i.closeSequence;e.emit(s.SHARD_RESUME,i.id,n)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.TypingStart.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.UserUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.emit("debug","[VOICE] received voice server: "+JSON.stringify(t)),e.voice.onVoiceServer(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.VoiceStateUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.WebhooksUpdate.handle(t.d)}},function(e,t){},function(e,t){},function(e,t){},function(e,t){},function(e,t){},function(e,t,i){"use strict";const s=i(12);class Speaking extends s{}Speaking.FLAGS={SPEAKING:1,SOUNDSHARE:2,PRIORITY_SPEAKING:4},e.exports=Speaking}])})); \ No newline at end of file diff --git a/node_modules/discord.js/webpack/discord.min.js.LICENSE.txt b/node_modules/discord.js/webpack/discord.min.js.LICENSE.txt deleted file mode 100644 index e874b731..00000000 --- a/node_modules/discord.js/webpack/discord.min.js.LICENSE.txt +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ diff --git a/node_modules/secure-random-password/.eslintrc.js b/node_modules/secure-random-password/.eslintrc.js deleted file mode 100644 index d1cfcca7..00000000 --- a/node_modules/secure-random-password/.eslintrc.js +++ /dev/null @@ -1,30 +0,0 @@ -module.exports = { - "env": { - "browser": true, - "commonjs": true, - "jest": true - }, - "extends": "eslint:recommended", - "parserOptions": { - "ecmaVersion": 6 - }, - "rules": { - "indent": [ - "error", - 2 - ], - "linebreak-style": [ - "error", - "unix" - ], - "quotes": [ - "error", - "single" - ], - "semi": [ - "error", - "always", - { "omitLastInOneLineBlock": true } - ] - } -}; diff --git a/node_modules/secure-random-password/.travis.yml b/node_modules/secure-random-password/.travis.yml deleted file mode 100644 index d8847a60..00000000 --- a/node_modules/secure-random-password/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: node_js -install: - - npm install - - npm install -g codecov -node_js: - - "node" -script: - - npm test - - codecov diff --git a/node_modules/secure-random-password/LICENSE.txt b/node_modules/secure-random-password/LICENSE.txt deleted file mode 100644 index acf15b9a..00000000 --- a/node_modules/secure-random-password/LICENSE.txt +++ /dev/null @@ -1,12 +0,0 @@ -Copyright 2018 Rackspace US, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. diff --git a/node_modules/secure-random-password/README.md b/node_modules/secure-random-password/README.md deleted file mode 100644 index dd09937d..00000000 --- a/node_modules/secure-random-password/README.md +++ /dev/null @@ -1,218 +0,0 @@ -# secure-random-password - -[![Build Status](https://travis-ci.org/rackerlabs/secure-random-password.svg?branch=master)](https://travis-ci.org/rackerlabs/secure-random-password) [![codecov](https://codecov.io/gh/rackerlabs/secure-random-password/branch/master/graph/badge.svg)](https://codecov.io/gh/rackerlabs/secure-random-password) [![npm](https://img.shields.io/npm/v/secure-random-password.svg)](https://www.npmjs.com/package/secure-random-password) - -__secure-random-password__ is a password generator that wraps [secure-random](https://www.npmjs.com/package/secure-random) so your passwords will be generated using a cryptographically-secure source of entropy, __whether running in the [browser](#browser-support) or Node.js__. It has support to generate passwords that meet arbitrary __complexity requirements__. - -## Try It - -Curious to see this library in action? Head over to the [demo site](https://www.codetinkerer.com/passwords/) and open up your developer console: - -![console screenshot](https://www.codetinkerer.com/passwords/img/password-site-console.png) - -All functionality can be accessed through the `secureRandomPassword` global variable. Keep reading for example usage. - -## Installation - -``` -npm install secure-random-password -``` - -## Usage - -First import the module. For example, in Node.js: - -```javascript -> const password = require('secure-random-password'); -``` - -(See [Browser Support](#browser-support) if you're running in a browser.) - -If you just want a password: - -```javascript -> password.randomPassword() -'bdnoa(Ejbkby' -``` - -You can specify the length and the characters used: - -```javascript -> password.randomPassword({ length: 4, characters: password.digits }) -'6324' -``` - -#### Character Sets - -You can pass an array of different character sets: - -```javascript -> password.randomPassword({ characters: [password.lower, password.upper, password.digits] }) -'QQScLnAZHTg4' -``` - -The generated password is guaranteed to contain at least one character from each set. - -Contrast that with combining all the sets together: - -```javascript -> password.randomPassword({ characters: password.lower + password.upper + password.digits }) -'ickVmBUwHTDe' -``` - -Notice that the password in this case happens to not have any digits in it. Subsequent calls to `randomPassword(...)` __may__ contain digits (or lower-case/upper-case letters), but it __doesn't have to__. - -#### Obligatory Character Sets - -Sometimes you need at least one character from a given set in order to meet complexity requirements, but you don't really want the password to have a bunch of characters from that set. - -Here's how you can generate a password with 1 upper-case letter, 1 special symbol, and the rest lower-case letters: - -```javascript -> password.randomPassword({ characters: [ -... { characters: password.upper, exactly: 1 }, -... { characters: password.symbols, exactly: 1 }, -... password.lower ] }) -'nerhkn#mZxjp' -``` - -(This is, in fact, the default character set setting if you omit the `characters` option.) - -#### Custom Character Sets - -There is nothing special about `password.lower`, `password.digits`, etc.: - -```javascript -> password.digits -'1234567890' -``` - -It's just a string that contains all the characters in that set. - -You can pass in whatever characters you want: - -```javascript -> password.randomPassword({ characters: 'abc' }) -'cbbaacbbaaba' -``` - -__Security Warning__: there is currently no support for de-duplicating characters. This means you can bias the output if there are duplicate characters passed in: - -```javascript -> password.randomPassword({ characters: 'aaaaaaaaaaaaaaaaaaaaaaaac' }) -'aaaaaaaaacaa' -``` - -#### Avoid Ambiguous Characters - -By default, if there are groups of characters that are easily-confused (such as `O` and `0`) in any of the passed character sets, __all such characters will never be returned__: - -```javascript -> password.randomPassword({ characters: 'O0o' }) -'oooooooooooo' -``` - -You can opt-out of this behavior by setting the `avoidAmbiguous` option: - -```javascript -> password.randomPassword({ avoidAmbiguous: false, characters: 'O0o' }) -'Oo00oo0O0oo0' -``` - -__Note__: ambiguous characters are only removed if there is more than one ambiguous character across all sets. - -```javascript -> password.randomPassword({ characters: password.upper }) -'OVOLRAADPMBA' // happens to contain an 'O' -> password.randomPassword({ characters: [password.upper, password.digits] }) -'WG86SAH22SWB' // output will never contain an 'O' (or a '0' for that matter) -``` - -#### Predicate - -If you need the password to meet some arbitrary complexity requirement, you can pass in a `predicate` function. - -For example, here's how you would generate a password that is guaranteed not to contain the value of a `userName` variable: - -```javascript -> password.randomPassword({ predicate: x => !x.includes(userName) }) -'fvKr#zazokcn' -``` - -Be careful with using `predicate`, because it essentially works like this: - -```javascript -do { - password = tryGeneratePassword(); -} while (!predicate(password)); -``` - -It's easy to pass a `predicate` that will cause `randomPassword(...)` to take a very long time (or never return). In general, only use predicate to test a negative: "this password doesn't contain too many repeating characters", "this password doesn't contain a sequence like '123'". You get the idea. - -__Example__: Say you want to generate a password with 4 letters followed by 4 digits. Don't do this: - -```javascript -> password.randomPassword({ -... characters: [password.lower, password.digits], -... length: 8, -... predicate: x => x.match(/[a-z]{4}[0-9]{4}/) }) -'ivxx4355' -``` - -Instead, do this: - -```javascript -> password.randomPassword({ characters: password.lower, length: 4 }) + -... password.randomPassword({ characters: password.digits, length: 4 }) -'wrix9539' -``` - -### randomString - -Passwords are used for people to prove who they are. Sometimes though we just want a key or random id. In this case, there's no reason to compromise the entropy to make the resulting string more memorable/typeable/whatever since a computer will be remembering it. - -If you want a fully-random string, use the `randomString` function: - -```javascript -> password.randomString() -')g3It%5$x61$qTtgqFL9' -``` - -It supports all the same options as the `randomPassword` function: - -```javascript -> password.randomString({ length: 8 }) -'!t1OP5i#' -``` - -## Browser Support - -__secure-random-password__ is written to the ES5 standard and should run in all major browsers. There are two ways to include it: - -### 1. CommonJS Support - -If you're using a build system, such as Webpack, you can import the module like normal: - -```javascript -const password = require('secure-random-password'); -``` -### 2. Browser Bundle - -Alternatively, you can [download the bundle](/dist/secure-random-password.min.js) and reference it on your page: - -```html - -``` - -The module is accessible via the `secureRandomPassword` global: - -```javascript -> secureRandomPassword.randomPassword() -"zrTpxdktkm*p" -``` - -## Disclaimer - -This library is released as-is. Use it at your own risk. - -There is no guarantee of support. If you do run into issues though, [we'd love to hear about it](/../../issues). diff --git a/node_modules/secure-random-password/dist/secure-random-password.min.js b/node_modules/secure-random-password/dist/secure-random-password.min.js deleted file mode 100644 index ebdb8fba..00000000 --- a/node_modules/secure-random-password/dist/secure-random-password.min.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{var r={10:(r,t,e)=>{"use strict";var n=e(744).Z,o=e(505),a=e(502);Object.keys(o).forEach((function(r){t[r]=o[r]}));var c=["Il1|","O0"];function u(r){var t={avoidAmbiguous:!0,characters:[o.lower,{characters:o.upper,exactly:1},{characters:o.symbols,exactly:1}],length:12,predicate:function(){return!0},random:n},e=function(r){if(!r.characters)return[];var t=Array.isArray(r.characters)?r.characters:[r.characters];return function(r,t){var e=r.map((function(r){return r.characters})).join(""),n=t.filter((function(r){return a.intersection(r,e).length>1})).join("");r.forEach((function(r){r.characters=a.toArray(r.characters).filter((function(r){return n.indexOf(r)<0})).join("")}))}(t=t.map((function(r){return a.isString(r)?{characters:r}:r})),!0===r.avoidAmbiguous?c:r.avoidAmbiguous||[]),t}(r=a.assign({},t,r));if(!a.isInteger(r.length))throw new Error("length must be an integer");if(r.length<1)throw new Error("length must be > 0");if(r.length= # of character sets passed");if(e.some((function(r){return!r.characters})))throw new Error("No character set may be empty");if(0===e.length)throw new Error("Must pass one or more character sets");if("function"!=typeof r.predicate)throw new Error("predicate must be a function");var u,s=e.map((function(r){return r.exactly||1})).reduce((function(r,t){return r+t}),0);if(r.length{t.lower="abcdefghijklmnopqrstuvwxyz",t.upper=t.lower.toUpperCase(),t.consonants="bcdfghjklmnpqrstvwxyz",t.vowels="aeiou",t.digits="1234567890",t.symbols="!@#$%^&*()",t.fullSymbols="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",t.copyableSymbols="_"},744:(r,t,e)=>{"use strict";var n=e(64),o=e(502);function a(r){if("function"!=typeof r)throw new Error("Must pass a randomSource function");this._randomSource=r}function c(r){for(var t=0,e=1,n=(r=r||[]).length-1;n>=0;n--)t+=r[n]*e,e*=256;return t}a.prototype.choose=function(r){if(!r||!r.length)throw new Error("Must pass 1 or more choices");return r[this._getInt(r.length)]},a.prototype.getInt=function(r){if(void 0===r)throw new Error("Must pass an upper bound");if(!o.isInteger(r))throw new Error("Upper bound must be a number");if(r<1)throw new Error("Upper bound must be > 0");return this._getInt(r)},a.prototype._getInt=function(r){if(1===r)return 0;var t,e=Math.ceil(Math.log(r)/Math.log(256)),n=Math.pow(2,8*e)-Math.pow(2,8*e)%r;do{t=c(this._randomSource(e))}while(t>=n);return t%r},a.prototype.shuffle=function(r){r=Array.prototype.slice.call(r||[]);for(var t=[];r.length;)t.push(r.splice(this._getInt(r.length),1)[0]);return t},t.Z=new a(n)},502:(r,t)=>{"use strict";function e(r){return Array.apply(null,Array(r)).map((function(r,t){return t}))}function n(r){return Array.prototype.slice.call(r)}t.assign=function(){var r=n(arguments),t=r[0],e=r.slice(1);return e.filter((function(r){return!!r})).forEach((function(r){Object.keys(r).forEach((function(e){t[e]=r[e]}))})),t},t.intersection=function(r,t){r=n(r),t=n(t);var e={};r.forEach((function(r){e[r]=!0}));var o={};return t.forEach((function(r){o[r]=!0})),Object.keys(e).filter((function(r){return Object.prototype.hasOwnProperty.call(o,r)}))},t.isInteger=function(r){return"number"==typeof r&&isFinite(r)&&Math.floor(r)===r},t.isString=function(r){return"string"==typeof r||r instanceof String},t.range=e,t.repeat=function(r,t){return e(t).map((function(){return r}))},t.toArray=n},64:function(r,t,e){var n;!function(o){"use strict";function a(r,t){if(t=t||{type:"Array"},"undefined"!=typeof process&&"number"==typeof process.pid&&process.versions&&process.versions.node)return function(r,t){var n=e(954).randomBytes(r);switch(t.type){case"Array":return[].slice.call(n);case"Buffer":return n;case"Uint8Array":for(var o=new Uint8Array(r),a=0;a{}},t={};window.secureRandomPassword=function e(n){var o=t[n];if(void 0!==o)return o.exports;var a=t[n]={exports:{}};return r[n].call(a.exports,a,a.exports,e),a.exports}(10)})(); \ No newline at end of file diff --git a/node_modules/secure-random-password/index.html b/node_modules/secure-random-password/index.html deleted file mode 100644 index d994626d..00000000 --- a/node_modules/secure-random-password/index.html +++ /dev/null @@ -1,5 +0,0 @@ - - -

-

hi

-
diff --git a/node_modules/secure-random-password/index.js b/node_modules/secure-random-password/index.js deleted file mode 100644 index 4b57a8e2..00000000 --- a/node_modules/secure-random-password/index.js +++ /dev/null @@ -1,136 +0,0 @@ -'use strict'; - -var random = require('./lib/random').default; -var sets = require('./lib/character-sets'); -var util = require('./lib/util'); - -Object.keys(sets).forEach(function (k) { - exports[k] = sets[k]; -}); - -var defaultAmbiguousSets = [ - 'Il1|', - 'O0' -]; - -function randomPassword(opts) { - var defaults = { - avoidAmbiguous: true, - characters: [ - sets.lower, - { characters: sets.upper, exactly: 1 }, - { characters: sets.symbols, exactly: 1 } - ], - length: 12, - predicate: function () { return true }, - random: random, - }; - opts = util.assign({}, defaults, opts); - - var characterRules = translateRules(opts); - - if (!util.isInteger(opts.length)) { - throw new Error('length must be an integer'); - } - if (opts.length < 1) { - throw new Error('length must be > 0'); - } - if (opts.length < characterRules.length) { - throw new Error('length must be >= # of character sets passed'); - } - if (characterRules.some(function (rule) { return !rule.characters })) { - throw new Error('No character set may be empty'); - } - if (characterRules.length === 0) { - throw new Error('Must pass one or more character sets'); - } - if (typeof opts.predicate !== 'function') { - throw new Error('predicate must be a function'); - } - - var minimumLength = characterRules - .map(function (rule) { return rule.exactly || 1 }) - .reduce(function (l, r) { return l + r }, 0); - if (opts.length < minimumLength) { - throw new Error('length is too short for character set rules'); - } - - var allExactly = characterRules.every(function (rule) { return rule.exactly }); - if (allExactly) { - var exactlyLength = characterRules.reduce(function (acc, r) { return acc + r.exactly }, 0); - if (exactlyLength !== opts.length) { - throw new Error('Must pass a set without exactly rule to generate the specified length'); - } - } - - var result; - do { - result = generatePassword(characterRules, opts.length, opts.random); - } while (!opts.predicate(result)); - return result; -} - -exports.randomPassword = randomPassword; - -function generatePassword(characterRules, length, random) { - var requiredSetsWithRepeats = characterRules - .map(function (rule) { return rule.exactly ? util.repeat(rule.characters, rule.exactly) : [rule.characters] }) - .reduce(function (l, r) { return l.concat(r) }); // flatten back to array of strings - var requiredChoices = requiredSetsWithRepeats - .map(function (characters) { return random.choose(characters) }); - - var fillCharcters = characterRules - .filter(function (rule) { return !rule.exactly }) - .map(function (rule) { return rule.characters }) - .join(''); - var randomChoices = util.range(length - requiredChoices.length) - .map(function () { return random.choose(fillCharcters) }); - - var shuffled = random.shuffle(requiredChoices.concat(randomChoices)); - return shuffled.join(''); -} - -function translateRules(opts) { - if (!opts.characters) { - return []; - } - var result = Array.isArray(opts.characters) - ? opts.characters - : [opts.characters]; - result = result.map(function (x) { return util.isString(x) ? { characters: x } : x }); - - var ambiguousSets = opts.avoidAmbiguous === true - ? defaultAmbiguousSets - : (opts.avoidAmbiguous || []); - - stripAmbiguous(result, ambiguousSets); - - return result; -} - -function stripAmbiguous(characterRules, ambiguousSets) { - var allCharacters = characterRules.map(function (rule) { return rule.characters }).join(''); - - var ambiguousCharacters = ambiguousSets - .filter(function (ambiguousSet) { return util.intersection(ambiguousSet, allCharacters).length > 1 }) - .join(''); - - characterRules.forEach(function (rule) { - rule.characters = util.toArray(rule.characters) - .filter(function(ch) { return ambiguousCharacters.indexOf(ch) < 0 }).join(''); - }); -} - -function randomString(opts) { - var defaults = { - characters: [sets.lower, sets.upper, sets.digits, sets.symbols], - length: 20 - }; - opts = util.assign({}, defaults, opts); - - opts.avoidAmbiguous = false; // hard override - - return randomPassword(opts); -} - -exports.randomString = randomString; diff --git a/node_modules/secure-random-password/index.spec.js b/node_modules/secure-random-password/index.spec.js deleted file mode 100644 index ed1f8ceb..00000000 --- a/node_modules/secure-random-password/index.spec.js +++ /dev/null @@ -1,330 +0,0 @@ -const randomPassword = require('./index').randomPassword; - -describe('passwordGenerator', () => { - let random; - - beforeEach(() => { - random = { - choose: jest.fn(), - shuffle: jest.fn(x => x), - }; - random.choose.mockReturnValue('Q'); - }); - - it('returns a string when called with no options', () => { - var actual = randomPassword(); - - expect(typeof actual).toBe('string'); - }); - - it('throws an error when passed a length that is not an integer', () => { - expect(() => randomPassword({ length: 'not-an-integer' })).toThrow('length must be an integer'); - }); - - it('throws an error when passed a length less than 1', () => { - expect(() => randomPassword({ length: 0 })).toThrow('length must be > 0'); - }); - - it('throws an error when passed characters that is falsy', () => { - const expectedError = 'Must pass one or more character sets'; - expect(() => randomPassword({ characters: null })).toThrow(expectedError); - expect(() => randomPassword({ characters: false })).toThrow(expectedError); - expect(() => randomPassword({ characters: 0 })).toThrow(expectedError); - }); - - it('throws an error when passed a characters set array with no items', () => { - expect(() => randomPassword({ characters: [] })).toThrow('Must pass one or more character sets'); - }); - - it('returns sequence with 1 character of given length when passed only one allowed character', () => { - random.choose.mockImplementation(x => x); - - expect(randomPassword({ - length: 3, - characters: 'a', - random - })).toBe('aaa'); - - expect(randomPassword({ - length: 3, - characters: 'b', - random - })).toBe('bbb'); - }); - - it('returns result of random.choose on characters for length = 1', () => { - let chooseReturnValues = { - 'abc': 'b' - }; - random.choose.mockImplementation(arg => chooseReturnValues[arg] || ''); - - let result = randomPassword({ - length: 1, - characters: 'abc', - random - }); - - expect(result).toBe('b'); - }); - - it('returns combined string of characters returned from random.choose (for `length` many characters)', () => { - let chooseReturnValues = { - 'abc': ['c', 'b', 'a', 'a', 'b', 'c'] - }; - random.choose.mockImplementation(arg => chooseReturnValues[arg].shift() || ''); - - let result = randomPassword({ - length: 6, - characters: 'abc', - random - }); - - expect(result).toBe('cbaabc'); - }); - - describe('when passed multiple character sets', () => { - it('throws an error if the passed length is fewer than the number of sets passed', () => { - expect(() => randomPassword({ - length: 1, - characters: ['abc', '123'], - random - })).toThrow('length must be >= # of character sets passed'); - }); - - it('calls random.choose on each passed set once, then on a combination of all character sets for the remaining length, then shuffles the result', () => { - let chooseReturnValues = { - 'abc': ['b'], - '123': ['2'], - 'abc123': ['3', 'a', '2', 'b'] - }; - random.choose.mockImplementation(arg => chooseReturnValues[arg].shift() || ''); - let shuffleReturnValues = { - 'b23a2b': Array.from('b2a32b') - }; - random.shuffle.mockImplementation(arg => shuffleReturnValues[Array.from(arg).join('')] || []); - - let result = randomPassword({ - length: 6, - characters: ['abc', '123'], - random - }); - - expect(result).toBe('b2a32b'); - }); - }); - - describe('charcters rules', () => { - it('accepts objects with a characters property in place of a string', () => { - random.choose.mockImplementation(x => x); - - expect(randomPassword({ - length: 3, - characters: { characters: 'a' }, - random - })).toBe('aaa'); - }); - - it('accepts an array of objects with a characters property in place of an array of strings', () => { - random.choose.mockImplementation(x => x); - - expect(randomPassword({ - length: 3, - characters: [{ characters: 'a' }], - random - })).toBe('aaa'); - let chooseReturnValues = { - 'abc': ['b'], - '123': ['2'], - 'abc123': ['3', 'a', '2', 'b'] - }; - random.choose.mockImplementation(arg => chooseReturnValues[arg].shift() || ''); - - let result = randomPassword({ - length: 6, - characters: [ - { characters: 'abc' }, - { characters: '123'} - ], - random - }); - - expect(result).toBe('b23a2b'); - }); - - it('accepts an exactly property that causes the associated character set to be chosen from exactly that many times', () => { - let chooseReturnValues = { - 'abc': ['c', 'b', 'a'], - '123': ['3', '2', '1'], - }; - random.choose.mockImplementation(arg => chooseReturnValues[arg].shift() || ''); - let shuffleReturnValues = { - 'c321ba': Array.from('abc123') - }; - random.shuffle.mockImplementation(arg => shuffleReturnValues[Array.from(arg).join('')] || []); - - let result = randomPassword({ - length: 6, - characters: [ - 'abc', - { characters: '123', exactly: 3 } - ], - random - }); - - expect(result).toBe('abc123'); - }); - - it('throws an error when length is less than the totaled number of exactly character sets + required sets', () => { - expect(() => randomPassword({ - length: 42, - characters: [ - 'abc', - { characters: '123', exactly: 42 } - ] - })).toThrow('length is too short for character set rules'); - }); - - it('throws an error when all sets are exactly sets and they are less than length', () => { - expect(() => randomPassword({ - length: 42, - characters: [ - { characters: 'abc', exactly: 20 }, - { characters: '123', exactly: 21 }, - ] - })).toThrow('Must pass a set without exactly rule to generate the specified length'); - }); - - it('accepts a totaled number of exactly character sets + required sets', () => { - expect(() => randomPassword({ - length: 10, - characters: [ - { characters: '123', exactly: 10 } - ] - })).not.toThrow(); - - expect(() => randomPassword({ - length: 30, - characters: [ - { characters: '123', exactly: 10 }, - { characters: '123', exactly: 20 } - ] - })).not.toThrow(); - }); - }); - - describe('avoidAmbiguous option', () => { - it('accepts an avoidAmbiguous array of sets that prevents ambiguous characters from being chosen if multiple characters from any avoidAmbiguous set appear in the passed characters', () => { - let chooseReturnValues = { - 'cd': ['c', 'd', 'c', 'd', 'c', 'd'] - }; - random.choose.mockImplementation(arg => chooseReturnValues[arg].shift() || ''); - - let result = randomPassword({ - length: 6, - characters: 'abcdef', - avoidAmbiguous: ['ab', 'ef'], - random - }); - - expect(result).toBe('cdcdcd'); - }); - - it('does not prevent characters from being chosen if only one charcter in avoidAmbiguous appears in the passed charcters', () => { - let chooseReturnValues = { - 'abc': ['a', 'b', 'c', 'a', 'b', 'c'] - }; - random.choose.mockImplementation(arg => chooseReturnValues[arg].shift() || ''); - - let result = randomPassword({ - length: 6, - characters: 'abc', - avoidAmbiguous: ['cd'], - random - }); - - expect(result).toBe('abcabc'); - }); - - it('matches ambiguous characters across all sets', () => { - let chooseReturnValues = { - 'b': ['b'], - '2': ['2'], - 'b2': ['b', '2', 'b', '2'] - }; - random.choose.mockImplementation(arg => chooseReturnValues[arg].shift() || ''); - - let result = randomPassword({ - length: 6, - characters: ['abc', '123'], - avoidAmbiguous: ['a1', 'c3'], - random - }); - - expect(result).toBe('b2b2b2'); - }); - - it('throws an error if any character set is empty after excluding ambiguous characters', () => { - expect(() => randomPassword({ - length: 42, - characters: [ - 'ab', - 'cd', - 'ef' - ], - avoidAmbiguous: ['cd'] - })).toThrow('No character set may be empty'); - - }); - - it('provides default ambiguous characters sets when true is passed for avoidAmbiguous', () => { - random.choose.mockImplementation(x => x); - - let result = randomPassword({ - length: 6, - characters: 'aIl1|O0', - avoidAmbiguous: true, - random - }); - - expect(result).toBe('aaaaaa'); - }); - - it('provides an empty ambiguous character set when false value is passed for avoidAmbiguous', () => { - let chooseReturnValues = { - 'abc': ['a', 'b', 'c', 'a', 'b', 'c'] - }; - random.choose.mockImplementation(arg => chooseReturnValues[arg].shift() || ''); - - let result = randomPassword({ - length: 6, - characters: 'abc', - avoidAmbiguous: false, - random - }); - - expect(result).toBe('abcabc'); - }); - }); - - describe('predicate option', () => { - it('throws an error if predicate is not a function', () => { - expect(() => randomPassword({ predicate: null })).toThrow('predicate must be a function'); - }); - - it('keeps generating passwords until they pass the predicate', () => { - let chooseReturnValues = { - 'abc': ['a', 'b', 'c', 'a', 'b', 'c', 'c', 'b', 'a'] - }; - random.choose.mockImplementation(arg => chooseReturnValues[arg].shift() || ''); - - let result = randomPassword({ - length: 3, - characters: 'abc', - predicate: (x => x !== 'abc'), - random - }); - - expect(result).toBe('cba'); - }); - }); -}); diff --git a/node_modules/secure-random-password/index.web.js b/node_modules/secure-random-password/index.web.js deleted file mode 100644 index 3ed2b936..00000000 --- a/node_modules/secure-random-password/index.web.js +++ /dev/null @@ -1 +0,0 @@ -window.secureRandomPassword = require('./index'); diff --git a/node_modules/secure-random-password/lib/character-sets.js b/node_modules/secure-random-password/lib/character-sets.js deleted file mode 100644 index 3bac951d..00000000 --- a/node_modules/secure-random-password/lib/character-sets.js +++ /dev/null @@ -1,8 +0,0 @@ -exports.lower = 'abcdefghijklmnopqrstuvwxyz'; -exports.upper = exports.lower.toUpperCase(); -exports.consonants = 'bcdfghjklmnpqrstvwxyz'; -exports.vowels = 'aeiou'; -exports.digits = '1234567890'; -exports.symbols = '!@#$%^&*()'; -exports.fullSymbols = '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'; -exports.copyableSymbols = '_'; diff --git a/node_modules/secure-random-password/lib/random.js b/node_modules/secure-random-password/lib/random.js deleted file mode 100644 index a5ceb948..00000000 --- a/node_modules/secure-random-password/lib/random.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict'; - -var secureRandom = require('secure-random'); - -var util = require('./util'); - -function Random(randomSource) { - if (typeof randomSource !== 'function') { - throw new Error('Must pass a randomSource function'); - } - this._randomSource = randomSource; -} - -Random.prototype.choose = function (choices) { - if (!choices || !choices.length) { - throw new Error('Must pass 1 or more choices'); - } - - return choices[this._getInt(choices.length)]; -}; - -Random.prototype.getInt = function (upperBoundExclusive) { - if (upperBoundExclusive === undefined) { - throw new Error('Must pass an upper bound'); - } - if (!util.isInteger(upperBoundExclusive)) { - throw new Error('Upper bound must be a number'); - } - if (upperBoundExclusive < 1) { - throw new Error('Upper bound must be > 0'); - } - - return this._getInt(upperBoundExclusive); -}; - -Random.prototype._getInt = function (upperBoundExclusive) { - if (upperBoundExclusive === 1) { - return 0; // short-circuit to avoid calling _randomSource with `0` - } - - var numBytes = Math.ceil(Math.log(upperBoundExclusive) / Math.log(256)); - var startOfBias = Math.pow(2, 8*numBytes) - Math.pow(2, 8*numBytes) % upperBoundExclusive; - var randomNumber; - do - { - randomNumber = byteArrayToInt(this._randomSource(numBytes)); - } while (randomNumber >= startOfBias); - return randomNumber % upperBoundExclusive; -}; - -Random.prototype.shuffle = function (items) { - items = Array.prototype.slice.call(items || []); - var result = []; - while (items.length) { - result.push(items.splice(this._getInt(items.length), 1)[0]); - } - return result; -}; - -exports.Random = Random; - -exports.default = new Random(secureRandom); - -function byteArrayToInt(bytes) { - bytes = bytes || []; - - var result = 0; - var power = 1; - for (var i = bytes.length - 1; i >= 0; i--) { - result += bytes[i]*power; - power *= 256; - } - return result; -} diff --git a/node_modules/secure-random-password/lib/random.spec.js b/node_modules/secure-random-password/lib/random.spec.js deleted file mode 100644 index fb055b1c..00000000 --- a/node_modules/secure-random-password/lib/random.spec.js +++ /dev/null @@ -1,137 +0,0 @@ -const Random = require('./random').Random; - -describe('Random', () => { - let randomSource; - let subject; - - beforeEach(() => { - randomSource = jest.fn(); - subject = new Random(randomSource); - }); - - it('throws an error when not passed a function', () => { - expect(() => new Random(123)).toThrow('Must pass a randomSource function'); - }); - - describe('getInt', () => { - it('throws an error when not passed an upper bound', () => { - expect(() => subject.getInt()).toThrow('Must pass an upper bound'); - }); - - it('throws an error when upper bound is not a number', () => { - expect(() => subject.getInt('derp')).toThrow('Upper bound must be a number'); - }); - - it('throws an error when upper bound is less than 1', () => { - expect(() => subject.getInt(0)).toThrow('Upper bound must be > 0'); - }); - - it('does not call randomSource when called with an upper bound of 1', () => { - expect(subject.getInt(1)).toBe(0); - expect(randomSource).not.toHaveBeenCalled(); - }); - - it('returns the result of randomSource(1) when upper bound is 2^8', () => { - let randomValues = [123]; - randomSource.mockImplementation(n => randomValues.splice(0, n)); - - expect(subject.getInt(Math.pow(2, 8))).toBe(123); - }); - - it('returns the integer value of randomSource(4) when upper bound is 2^32', () => { - testCase([123, 45, 67, 89], 123*256*256*256 + 45*256*256 + 67*256 + 89); - testCase([0, 0, 0, 0], 0); - testCase([1, 0, 0, 0], Math.pow(2, 24)); - testCase([255, 255, 255, 255], Math.pow(2, 32) - 1); - - function testCase(randomValues, expected) { - randomSource.mockImplementation(n => randomValues.splice(0, n)); - - expect(subject.getInt(Math.pow(2, 32))).toBe(expected); - } - }); - - it('returns the value of randomSource modulo the upper bound', () => { - let randomValues = [123]; - randomSource.mockImplementation(n => randomValues.splice(0, n)); - - expect(subject.getInt(100)).toBe(23); - }); - - it('keeps calling randomSource until the modulo is unbiased', () => { - testCase(100, [234, 234, 123], 23); - testCase(100, [199], 99); - testCase(100, [200, 123], 23); - testCase(256, [255], 255); - testCase(128, [255], 127); - - function testCase(upperBound, randomValues, expected) { - randomSource.mockImplementation(n => randomValues.splice(0, n)); - - expect(subject.getInt(upperBound)).toBe(expected); - } - }); - - }); - - describe('choose', () => { - - it('throws an error when no choices are passed', () => { - testCase(null); - testCase(''); - testCase([]); - - function testCase(choices) { - expect(() => subject.choose(choices)).toThrow('Must pass 1 or more choices'); - } - }); - - it('returns the choice at the index returned by _getInt(choices.length)', () => { - let randomValues = [1]; - randomSource.mockImplementation(n => randomValues.splice(0, n)); - - let getIntReturnValues = { - ['abc'.length]: 1 - }; - jest.spyOn(subject, '_getInt').mockImplementation(n => getIntReturnValues[n]); - - expect(subject.choose('abc')).toBe('b'); - }); - - }); - - describe('shuffle', () => { - - it('returns an empty array when passed nothing', () => { - expect(subject.shuffle()).toEqual([]); - }); - - it('does not modify the passed items array', () => { - let someItems = [1, 2, 3]; - - subject.shuffle(someItems); - - expect(someItems).toEqual([1, 2, 3]); - }); - - it('returns the single item if there is only 1', () => { - let singleItem = ['a']; - - expect(subject.shuffle(singleItem)).toEqual(['a']); - }); - - it('shuffles items by getting the order from calling _getInt', () => { - let getIntReturnValues = { - 4: 1, // a _b_ cd - 3: 2, // ac _d_ - 2: 0, // _a_ c - 1: 0 // _c_ - }; - jest.spyOn(subject, '_getInt').mockImplementation(n => getIntReturnValues[n]); - - let someItems = ['a', 'b', 'c', 'd']; - expect(subject.shuffle(someItems)).toEqual(['b', 'd', 'a', 'c']); - }); - - }); -}); diff --git a/node_modules/secure-random-password/lib/util.js b/node_modules/secure-random-password/lib/util.js deleted file mode 100644 index 01df81ed..00000000 --- a/node_modules/secure-random-password/lib/util.js +++ /dev/null @@ -1,69 +0,0 @@ -'use strict'; - -function assign() { - var objects = toArray(arguments); - var target = objects[0]; - var sources = objects.slice(1); - - sources - .filter(function (source) { return !!source }) - .forEach(function (source) { - Object.keys(source).forEach(function (key) { - target[key] = source[key]; - }); - }); - - return target; -} - -exports.assign = assign; - -function intersection(left, right) { - left = toArray(left); - right = toArray(right); - - var leftSet = {}; - left.forEach(function (k) { - leftSet[k] = true; - }); - var rightSet = {}; - right.forEach(function (k) { - rightSet[k] = true; - }); - - return Object.keys(leftSet).filter(function(k) { - return Object.prototype.hasOwnProperty.call(rightSet, k); - }); -} - -exports.intersection = intersection; - -function isInteger(n) { - return typeof n === 'number' && isFinite(n) && Math.floor(n) === n; -} - -exports.isInteger = isInteger; - -function isString(s) { - return typeof s === 'string' || s instanceof String; -} - -exports.isString = isString; - -function range(n) { - return Array.apply(null, Array(n)).map(function (x, i) { return i }); -} - -exports.range = range; - -function repeat(val, n) { - return range(n).map(function () { return val }); -} - -exports.repeat = repeat; - -function toArray(x) { - return Array.prototype.slice.call(x); -} - -exports.toArray = toArray; diff --git a/node_modules/secure-random-password/lib/util.spec.js b/node_modules/secure-random-password/lib/util.spec.js deleted file mode 100644 index d92dd641..00000000 --- a/node_modules/secure-random-password/lib/util.spec.js +++ /dev/null @@ -1,136 +0,0 @@ -const util = require('./util'); - -describe('assign', () => { - it('returns first object no matter how many args passed', () => { - let someObj = {}; - expect(util.assign(someObj, {}, {})).toBe(someObj); - }); - - it('copies properties from subsequent object into the first object', () => { - let someObj = { - someOriginalProp: 'herp', - }; - - util.assign(someObj, { newProp1: 'derp', newProp2: 'flerp' }); - - expect(someObj).toHaveProperty('someOriginalProp', 'herp'); - expect(someObj).toHaveProperty('newProp1', 'derp'); - expect(someObj).toHaveProperty('newProp2', 'flerp'); - }); - - it('overrides properties with the same name using the property from the rightmost object', () => { - let someObj = { - someProp: 'herp', - }; - - util.assign(someObj, { someProp: 'derp' }, { someProp: 'flerp' }); - - expect(someObj).toHaveProperty('someProp', 'flerp'); - }); - - it('ignores null/undefined objects passed', () => { - let actual = util.assign({ someProp: 'herp' }, null, undefined, { someProp: 'derp' }); - - expect(actual).toHaveProperty('someProp', 'derp'); - }); -}); - -describe('intersection', () => { - it('returns empty array when passed disjoint sets', () => { - expect(util.intersection('abc', 'def')).toEqual([]); - }); - - it('returns the intersection when passed overlapping sets', () => { - expect(util.intersection('xabcx', '!a@b#c$')).toEqual(['a', 'b', 'c']); - }); - - it('returns a single item when passed sets with repeating items', () => { - expect(util.intersection('aaa', 'aaa')).toEqual(['a']); - }); -}); - -describe('isInteger', () => { - it('returns false for thinigs that are not numbers', () => { - expect(util.isInteger()).toBe(false); - expect(util.isInteger(null)).toBe(false); - expect(util.isInteger(false)).toBe(false); - expect(util.isInteger('not-a-number')).toBe(false); - expect(util.isInteger({})).toBe(false); - }); - - it('returns false for non-finite numbers', () => { - expect(util.isInteger(NaN)).toBe(false); - expect(util.isInteger(Infinity)).toBe(false); - }); - - it('returns false for non-integer numbers', () => { - expect(util.isInteger(1.23)).toBe(false); - }); - - it('returns true for basic integers', () => { - expect(util.isInteger(0)).toBe(true); - expect(util.isInteger(42)).toBe(true); - expect(util.isInteger(-42)).toBe(true); - }); -}); - -describe('isString', () => { - it('returns false for non-string things', () => { - expect(util.isString()).toBe(false); - expect(util.isString(null)).toBe(false); - expect(util.isString(false)).toBe(false); - expect(util.isString(0)).toBe(false); - expect(util.isString({})).toBe(false); - }); - - it('returns true for string primitives', () => { - expect(util.isString('')).toBe(true); - expect(util.isString('derp')).toBe(true); - }); - - it('returns true for string objects', () => { - expect(util.isString(new String('derp'))).toBe(true); - }); -}); - -describe('range', () => { - it('returns empty array when called with 0', () => { - expect(util.range(0)).toEqual([]); - }); - - it('returns [0] when called with 1', () => { - expect(util.range(1)).toEqual([0]); - }); - - it('returns 0, 1, ..., n-1 when called with n', () => { - expect(util.range(12)).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); - }); -}); - -describe('repeat', () => { - it('returns empty array when passed n=0', () => { - expect(util.repeat('derp', 0)).toEqual([]); - }); - - it('returns an array with n repeated items when passed n', () => { - expect(util.repeat('derp', 7)).toEqual([ - 'derp', - 'derp', - 'derp', - 'derp', - 'derp', - 'derp', - 'derp', - ]); - }); -}); - -describe('toArray', () => { - it('returns an array when passed an array', () => { - expect(util.toArray([3, 2, 1])).toEqual([3, 2, 1]); - }); - - it('converts string to an array', () => { - expect(util.toArray('abc')).toEqual(['a', 'b', 'c']); - }); -}); diff --git a/node_modules/secure-random-password/package.json b/node_modules/secure-random-password/package.json deleted file mode 100644 index 1bc1364d..00000000 --- a/node_modules/secure-random-password/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "secure-random-password", - "version": "0.2.3", - "description": "Generate passwords using a cryptographically-strong source of randomness", - "main": "index.js", - "scripts": { - "build": "webpack", - "lint": "eslint --ignore-pattern *.spec.js lib index.js", - "test": "npm run lint && jest" - }, - "keywords": [ - "secure", - "random", - "password", - "generator" - ], - "author": "Michael Kropat", - "license": "Apache-2.0", - "repository": "github:mkropat/secure-random-password", - "jest": { - "collectCoverage": true, - "coverageDirectory": "./coverage/", - "testEnvironment": "node" - }, - "dependencies": { - "secure-random": "^1.1.2" - }, - "devDependencies": { - "eslint": "^7.28.0", - "jest": "^27.0.4", - "webpack": "^5.38.1", - "webpack-cli": "^4.7.2" - } -} diff --git a/node_modules/secure-random-password/webpack.config.js b/node_modules/secure-random-password/webpack.config.js deleted file mode 100644 index a5c4a1ed..00000000 --- a/node_modules/secure-random-password/webpack.config.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - mode: 'production', - entry: './index.web.js', - output: { - filename: 'secure-random-password.min.js', - }, - externals: { - './../../process/browser.js': '{}', - './../../buffer/index.js': '{}', - }, -}; diff --git a/node_modules/secure-random/CHANGELOG.md b/node_modules/secure-random/CHANGELOG.md deleted file mode 100644 index 86cbae2b..00000000 --- a/node_modules/secure-random/CHANGELOG.md +++ /dev/null @@ -1,51 +0,0 @@ -1.1.2 / 2019-05-22 ------------------- -* make compatible for vue-cli - -1.1.1 / 2014-06-30 ------------------- -* bugfix: `1.1.0` only checked for support of `window.msCrypto`, didn't actually add, this bugfix actually adds it - -1.1.0 / 2014-06-30 ------------------- -* added support for `window.msCrypto` for Internet Explorer - -1.0.0 / 2014-06-03 ------------------- -* added Travis-CI support -* added Testling support - -* changed method default return type - -old way: - -```js -var data = secureRandom(10) //return Uint8Array by default -``` - -new way: - -```js -var data = secureRandom(10) //returns Array by default -``` - -* added `Buffer` type -* added `randomArray()` method -* added `randomUint8Array()` -* added `randomBuffer()` - -0.2.1 / 2014-03-20 ------------------- -* removed browserify hack, replaced with `package.json` setting. [weilu / #1](https://github.com/jprichardson/secure-random/pull/1) - -0.2.0 / 2013-12-17 ------------------- -* explicitly force check for `window.crypto` - -0.1.0 / 2013-12-08 ------------------- -* modified code so that Browserify doesn't include the Node.js `crypto` packabe client-side - -0.0.1 / 2013-11-07 ------------------- -* initial release \ No newline at end of file diff --git a/node_modules/secure-random/Makefile b/node_modules/secure-random/Makefile deleted file mode 100644 index cba9fd4a..00000000 --- a/node_modules/secure-random/Makefile +++ /dev/null @@ -1,8 +0,0 @@ - -node-test: - @./node_modules/.bin/mocha - -browser-test: - @./node_modules/.bin/mochify --wd -R spec - -.PHONY: node-test browser-test \ No newline at end of file diff --git a/node_modules/secure-random/README.md b/node_modules/secure-random/README.md deleted file mode 100644 index 103d71e7..00000000 --- a/node_modules/secure-random/README.md +++ /dev/null @@ -1,133 +0,0 @@ -secure-random -============== - -[![build status](https://secure.travis-ci.org/jprichardson/secure-random.png)](http://travis-ci.org/jprichardson/secure-random) - -[![browser support](https://ci.testling.com/jprichardson/secure-random.png)](https://ci.testling.com/jprichardson/secure-random) - -A simple JavaScript component to normalize the creation of cryptographically strong random values. - - -Why? ----- - -Context switching between the browser and Node.js and creating cryptographically secure random numbers is annoying. This normalizes the behavior. Used by [CryptoCoinJS](http://cryptocoinjs.com) and [BitcoinJS](https://github.com/bitcoinjs/bitcoinjs-lib). - - - -Install -------- - -### Node.js/Browserify - - npm install --save secure-random - - -### Component - - component install jprichardson/secure-random - - -### Bower - - bower install secure-random - - -### Script - -```html - -``` - - -Usage ------ - -### secureRandom(byteCount, options) - -- **byteCount**: is the number of bytes to return. -- **options**: options to pass. Only valid value at this time `type`. `type` can be -either `Array`, `Uint8Array`, or `Buffer`. `Buffer` is only valid in Node.js or -[Browserify](https://github.com/substack/node-browserify) environments - it will throw an error otherwise. - - -return an `Array`: - -```js -var bytes = secureRandom(10) //return an Array of 10 bytes -console.log(bytes.length) //10 -``` - -or: - -```js -var bytes = secureRandom(10, {type: 'Array'}) //return an Array of 10 bytes -console.log(bytes.length) //10 -``` - -return a `Buffer`: - -```js -var bytes = secureRandom(10, {type: 'Buffer'}) //return a Buffer of 10 bytes -console.log(bytes.length) //10 -``` - -return a `Uint8Array`: - -```js -var bytes = secureRandom(10, {type: 'Uint8Array'}) //return a Uint8Array of 10 bytes -console.log(bytes.length) //10 -``` - -### randomArray(byteCount) - -Sugar for `secureRandom(byteCount, {type: 'Array'})`. - -```js -var secureRandom = require('secure-random') -var data = secureRandom.randomArray(10) -``` - -### randomUint8Array(byteCount) - -Sugar for `secureRandom(byteCount, {type: 'Uint8Array'})`. - -```js -var secureRandom = require('secure-random') -var data = secureRandom.randomUint8Array(10) -``` - -### randomBuffer(byteCount) - -Sugar for `secureRandom(byteCount, {type: 'Buffer'})`. - -```js -var secureRandom = require('secure-random') -var data = secureRandom.randomBuffer(10) -``` - -Handling Errors ------ - -An error will be thrown if a secure random number generator is not available. - -```javascript -throw new Error("Your browser does not support window.crypto.") -``` - -References ----------- -* [Node.js crypto.randomBytes()](http://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback) -* [Node.js Buffer](http://nodejs.org/api/buffer.html) -* [window.crypto.getRandomValues()](https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues) -* [JavaScript typed arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays) - - -License -------- - -(MIT License) - -Copyright 2013-2014, JP Richardson - - diff --git a/node_modules/secure-random/lib/secure-random.js b/node_modules/secure-random/lib/secure-random.js deleted file mode 100644 index 81b3bd6e..00000000 --- a/node_modules/secure-random/lib/secure-random.js +++ /dev/null @@ -1,83 +0,0 @@ -!function(globals){ -'use strict' - -//*** UMD BEGIN -if (typeof define !== 'undefined' && define.amd) { //require.js / AMD - define([], function() { - return secureRandom - }) -} else if (typeof module !== 'undefined' && module.exports) { //CommonJS - module.exports = secureRandom -} else { //script / browser - globals.secureRandom = secureRandom -} -//*** UMD END - -//options.type is the only valid option -function secureRandom(count, options) { - options = options || {type: 'Array'} - //we check for process.pid to prevent browserify from tricking us - if ( - typeof process != 'undefined' - && typeof process.pid == 'number' - && process.versions - && process.versions.node - ) { - return nodeRandom(count, options) - } else { - var crypto = window.crypto || window.msCrypto - if (!crypto) throw new Error("Your browser does not support window.crypto.") - return browserRandom(count, options) - } -} - -function nodeRandom(count, options) { - var crypto = require('crypto') - var buf = crypto.randomBytes(count) - - switch (options.type) { - case 'Array': - return [].slice.call(buf) - case 'Buffer': - return buf - case 'Uint8Array': - var arr = new Uint8Array(count) - for (var i = 0; i < count; ++i) { arr[i] = buf.readUInt8(i) } - return arr - default: - throw new Error(options.type + " is unsupported.") - } -} - -function browserRandom(count, options) { - var nativeArr = new Uint8Array(count) - var crypto = window.crypto || window.msCrypto - crypto.getRandomValues(nativeArr) - - switch (options.type) { - case 'Array': - return [].slice.call(nativeArr) - case 'Buffer': - try { var b = new Buffer(1) } catch(e) { throw new Error('Buffer not supported in this environment. Use Node.js or Browserify for browser support.')} - return new Buffer(nativeArr) - case 'Uint8Array': - return nativeArr - default: - throw new Error(options.type + " is unsupported.") - } -} - -secureRandom.randomArray = function(byteCount) { - return secureRandom(byteCount, {type: 'Array'}) -} - -secureRandom.randomUint8Array = function(byteCount) { - return secureRandom(byteCount, {type: 'Uint8Array'}) -} - -secureRandom.randomBuffer = function(byteCount) { - return secureRandom(byteCount, {type: 'Buffer'}) -} - - -}(this); diff --git a/node_modules/secure-random/package.json b/node_modules/secure-random/package.json deleted file mode 100644 index 7e0d38e4..00000000 --- a/node_modules/secure-random/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "secure-random", - "version": "1.1.2", - "description": "Normalize the creation of cryptographically strong random values.", - "main": "./lib/secure-random.js", - "repository": { - "type": "git", - "url": "https://github.com/jprichardson/secure-random" - }, - "keywords": [ - "crypto", - "cryptography", - "secure", - "random", - "rand", - "generator", - "number" - ], - "author": "JP Richardson", - "license": "MIT", - "devDependencies": { - "mocha": "^1.20.0", - "terst": "^0.1.0", - "mochify": "^0.9.3" - }, - "dependencies": {}, - "browser": { - "crypto": false - }, - "scripts": { - "test": "mocha --ui bdd", - "unit": "./node_modules/.bin/mocha" - }, - "testling": { - "files": "test/*.js", - "browsers": [ - "firefox/latest", - "chrome/latest", - "safari/6..latest", - "ie/9..latest", - "iphone/6.0..latest", - "android-browser/4.2..latest" - ] - } -} diff --git a/package-lock.json b/package-lock.json index 992b9044..e2a38f84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,16 @@ { "name": "oneforall", - "version": "1.3.0", + "version": "3.5.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "1.3.0", + "version": "3.5.0", "license": "ISC", "dependencies": { "@joefallon/mysql-date": "^0.1.2", "advanced-command-handler": "^2.2.2", "aybabtu": "^1.1.6", - "bcryptjs": "^2.4.3", "canvacord": "^5.2.1", "child_process": "^1.0.2", "colornames": "^1.1.1", @@ -23,7 +22,7 @@ "discord-hybrid-sharding": "^1.1.1", "discord-logs": "^1.9.0", "discord-reply": "^0.1.2", - "discord.js": "^12.5.3", + "discord.js": "^13.0.0-dev.t1627778678.74fc23b", "discord.js-pagination": "^1.0.3", "distube": "^2.8.11", "dotenv": "^8.2.0", @@ -54,7 +53,6 @@ "pretty-ms": "^7.0.1", "random-puppy": "^1.1.0", "request": "^2.88.2", - "secure-random-password": "^0.2.2", "sequelize": "^6.6.2", "serialize-javascript": "^5.0.1", "shelljs": "^0.8.4", @@ -76,10 +74,34 @@ "twemoji-parser": "^13.0.0" } }, + "node_modules/@discordjs/builders": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.3.0.tgz", + "integrity": "sha512-yFBPqohVAtCWoDTQCYk5ubgmkiRbGpbiR4RfYGHCmV5S2YZc7j8WzfKVksjuy2o5IWRfXFsW6G2Lr+KpW41pEA==", + "dependencies": { + "@sindresorhus/is": "^4.0.1", + "discord-api-types": "^0.22.0", + "ow": "^0.26.0", + "ts-mixer": "^5.4.1", + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@discordjs/builders/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + }, "node_modules/@discordjs/collection": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", - "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.1.tgz", + "integrity": "sha512-vhxqzzM8gkomw0TYRF3tgx7SwElzUlXT/Aa41O7mOcyN6wIJfj5JmDWaO5XGKsGSsNx7F3i5oIlrucCCWV1Nog==", + "engines": { + "node": ">=14.0.0" + } }, "node_modules/@discordjs/form-data": { "version": "3.0.1", @@ -173,6 +195,15 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, + "node_modules/@sapphire/async-queue": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.4.tgz", + "integrity": "sha512-fFrlF/uWpGOX5djw5Mu2Hnnrunao75WGey0sP0J3jnhmrJ5TAPzHYOmytD5iN/+pMxS+f+u/gezqHa9tPhRHEA==", + "engines": { + "node": ">=14", + "npm": ">=6" + } + }, "node_modules/@sindresorhus/is": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", @@ -297,6 +328,29 @@ "node": ">=14" } }, + "node_modules/advanced-command-handler/node_modules/@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "node_modules/advanced-command-handler/node_modules/discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "dependencies": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -528,11 +582,6 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, - "node_modules/bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" - }, "node_modules/bignumber.js": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", @@ -714,6 +763,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -1124,6 +1181,14 @@ "node": ">=0.10" } }, + "node_modules/discord-api-types": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz", + "integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg==", + "engines": { + "node": ">=12" + } + }, "node_modules/discord-backup": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/discord-backup/-/discord-backup-2.5.0.tgz", @@ -1132,6 +1197,29 @@ "discord.js": "^12.5.3" } }, + "node_modules/discord-backup/node_modules/@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "node_modules/discord-backup/node_modules/discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "dependencies": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/discord-giveaways": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/discord-giveaways/-/discord-giveaways-4.5.1.tgz", @@ -1149,6 +1237,29 @@ "discord.js": "^12.5.2" } }, + "node_modules/discord-hybrid-sharding/node_modules/@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "node_modules/discord-hybrid-sharding/node_modules/discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "dependencies": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/discord-logs": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/discord-logs/-/discord-logs-1.9.0.tgz", @@ -1166,7 +1277,12 @@ "discord.js": "^12.5.1" } }, - "node_modules/discord.js": { + "node_modules/discord-reply/node_modules/@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "node_modules/discord-reply/node_modules/discord.js": { "version": "12.5.3", "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", @@ -1184,6 +1300,26 @@ "node": ">=12.0.0" } }, + "node_modules/discord.js": { + "version": "13.0.0-dev.t1627778678.74fc23b", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.0.0-dev.t1627778678.74fc23b.tgz", + "integrity": "sha512-djjWBHp3LPK2fYP2SP39fumFixqaoRtaRBdUtqombPltkcp+Cfd8zVwqJe4xr9+tyxva7FQ6k+49cpwxD/Ja2Q==", + "dependencies": { + "@discordjs/builders": "^0.3.0", + "@discordjs/collection": "^0.2.1", + "@discordjs/form-data": "^3.0.1", + "@sapphire/async-queue": "^1.1.4", + "@types/ws": "^7.4.5", + "abort-controller": "^3.0.0", + "discord-api-types": "^0.22.0", + "node-fetch": "^2.6.1", + "ws": "^7.5.1" + }, + "engines": { + "node": ">=14.6.0", + "npm": ">=7.0.0" + } + }, "node_modules/discord.js-better-embed": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/discord.js-better-embed/-/discord.js-better-embed-1.2.1.tgz", @@ -1192,6 +1328,29 @@ "discord.js": "^12.x" } }, + "node_modules/discord.js-better-embed/node_modules/@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "node_modules/discord.js-better-embed/node_modules/discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "dependencies": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/discord.js-pagination": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/discord.js-pagination/-/discord.js-pagination-1.0.3.tgz", @@ -2334,6 +2493,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "node_modules/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", @@ -5521,6 +5685,50 @@ "resolved": "https://registry.npmjs.org/os/-/os-0.1.2.tgz", "integrity": "sha512-ZoXJkvAnljwvc56MbvhtKVWmSkzV712k42Is2mA0+0KTSRakq5XXuXpjZjgAt9ctzl51ojhQWakQQpmOvXWfjQ==" }, + "node_modules/ow": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/ow/-/ow-0.26.0.tgz", + "integrity": "sha512-22YUQW9d6oUSCpIQuBV25djtC1uMtpWqmtUYnuh2UHWeNMpppCFCvq3eSBIWWMDbe2UVq26kWYvBHDzOIu5NYg==", + "dependencies": { + "@sindresorhus/is": "^4.0.1", + "callsites": "^3.1.0", + "dot-prop": "^6.0.1", + "lodash.isequal": "^4.5.0", + "type-fest": "^1.2.1", + "vali-date": "^1.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ow/node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ow/node_modules/type-fest": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.3.0.tgz", + "integrity": "sha512-mYUYkAy6fPatVWtUeCV/qGeGL3IVucmdJOzeAEfwgCJDx8gP0JaW8jn6KQ5xDfPec31e0KXWn5EUOZMhquR1zA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -6198,19 +6406,6 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, - "node_modules/secure-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/secure-random/-/secure-random-1.1.2.tgz", - "integrity": "sha512-H2bdSKERKdBV1SwoqYm6C0y+9EA94v6SUBOWO8kDndc4NoUih7Dv6Tsgma7zO1lv27wIvjlD0ZpMQk7um5dheQ==" - }, - "node_modules/secure-random-password": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/secure-random-password/-/secure-random-password-0.2.3.tgz", - "integrity": "sha512-2zpmr6pK3CZGIS9fgApFw00/tKEBVbJTqe4AZLrLNgahCK6ueIR5uMzvbERNibr8hkWneMcOqDcm4wpHWUxrYw==", - "dependencies": { - "secure-random": "^1.1.2" - } - }, "node_modules/semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -6829,6 +7024,11 @@ "node": ">=0.8" } }, + "node_modules/ts-mixer": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-5.4.1.tgz", + "integrity": "sha512-Zo9HgPCtNouDgJ+LGtrzVOjSg8+7WGQktIKLwAfaNrlOK1mWGlz1ejsAF/YqUEqAGjUTeB5fEg8gH9Aui6w9xA==" + }, "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -7032,6 +7232,14 @@ "uuid": "bin/uuid" } }, + "node_modules/vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/validator": { "version": "13.6.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz", @@ -7248,10 +7456,29 @@ "twemoji-parser": "^13.0.0" } }, + "@discordjs/builders": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.3.0.tgz", + "integrity": "sha512-yFBPqohVAtCWoDTQCYk5ubgmkiRbGpbiR4RfYGHCmV5S2YZc7j8WzfKVksjuy2o5IWRfXFsW6G2Lr+KpW41pEA==", + "requires": { + "@sindresorhus/is": "^4.0.1", + "discord-api-types": "^0.22.0", + "ow": "^0.26.0", + "ts-mixer": "^5.4.1", + "tslib": "^2.3.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + } + } + }, "@discordjs/collection": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", - "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.1.tgz", + "integrity": "sha512-vhxqzzM8gkomw0TYRF3tgx7SwElzUlXT/Aa41O7mOcyN6wIJfj5JmDWaO5XGKsGSsNx7F3i5oIlrucCCWV1Nog==" }, "@discordjs/form-data": { "version": "3.0.1", @@ -7325,6 +7552,11 @@ "tar": "^6.1.0" } }, + "@sapphire/async-queue": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.4.tgz", + "integrity": "sha512-fFrlF/uWpGOX5djw5Mu2Hnnrunao75WGey0sP0J3jnhmrJ5TAPzHYOmytD5iN/+pMxS+f+u/gezqHa9tPhRHEA==" + }, "@sindresorhus/is": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", @@ -7429,6 +7661,28 @@ "dayjs": "^1.10.4", "discord.js": "^12.5.1", "discord.js-better-embed": "^1.1.0" + }, + "dependencies": { + "@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "requires": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + } + } } }, "agent-base": { @@ -7617,11 +7871,6 @@ } } }, - "bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" - }, "bignumber.js": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", @@ -7759,6 +8008,11 @@ } } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -8066,12 +8320,39 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, + "discord-api-types": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz", + "integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg==" + }, "discord-backup": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/discord-backup/-/discord-backup-2.5.0.tgz", "integrity": "sha512-07xCibA41SND74FhUpOoJxN737wTI6sMYbWUUyfxtYfDK2bRFstOf4jwoZFTBlVNkK7PAkCEf6MdSFFgqHcg5w==", "requires": { "discord.js": "^12.5.3" + }, + "dependencies": { + "@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "requires": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + } + } } }, "discord-giveaways": { @@ -8089,6 +8370,28 @@ "integrity": "sha512-eU3unG2e+rX4odyVVUFpyisW1/A3czxqXvLTMITh9h3yAVxQAUgcnsHcfS3G1Z2hyg5dlf4FtJcoOHVmA/vDhA==", "requires": { "discord.js": "^12.5.2" + }, + "dependencies": { + "@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "requires": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + } + } } }, "discord-logs": { @@ -8106,21 +8409,44 @@ "integrity": "sha512-4XAFjJrhrmxsnDSPOQPqtjH534tx92KNFOW1uGZvxlKnPHcdCvbkrd8U/9vm/JQl5xDcbQQFUNoXs2k8kC8BKg==", "requires": { "discord.js": "^12.5.1" + }, + "dependencies": { + "@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "requires": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + } + } } }, "discord.js": { - "version": "12.5.3", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", - "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "version": "13.0.0-dev.t1627778678.74fc23b", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.0.0-dev.t1627778678.74fc23b.tgz", + "integrity": "sha512-djjWBHp3LPK2fYP2SP39fumFixqaoRtaRBdUtqombPltkcp+Cfd8zVwqJe4xr9+tyxva7FQ6k+49cpwxD/Ja2Q==", "requires": { - "@discordjs/collection": "^0.1.6", + "@discordjs/builders": "^0.3.0", + "@discordjs/collection": "^0.2.1", "@discordjs/form-data": "^3.0.1", + "@sapphire/async-queue": "^1.1.4", + "@types/ws": "^7.4.5", "abort-controller": "^3.0.0", + "discord-api-types": "^0.22.0", "node-fetch": "^2.6.1", - "prism-media": "^1.2.9", - "setimmediate": "^1.0.5", - "tweetnacl": "^1.0.3", - "ws": "^7.4.4" + "ws": "^7.5.1" } }, "discord.js-better-embed": { @@ -8129,6 +8455,28 @@ "integrity": "sha512-oildK3yzlgUK++iVlRgsKXxTnC4XkzVE+gP8KTtqn+cYD01Wr5cgfGXpDYNWrL4DBQndw0syNEb1GORiqkx08g==", "requires": { "discord.js": "^12.x" + }, + "dependencies": { + "@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "requires": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + } + } } }, "discord.js-pagination": { @@ -9005,6 +9353,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", @@ -11245,6 +11598,34 @@ "resolved": "https://registry.npmjs.org/os/-/os-0.1.2.tgz", "integrity": "sha512-ZoXJkvAnljwvc56MbvhtKVWmSkzV712k42Is2mA0+0KTSRakq5XXuXpjZjgAt9ctzl51ojhQWakQQpmOvXWfjQ==" }, + "ow": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/ow/-/ow-0.26.0.tgz", + "integrity": "sha512-22YUQW9d6oUSCpIQuBV25djtC1uMtpWqmtUYnuh2UHWeNMpppCFCvq3eSBIWWMDbe2UVq26kWYvBHDzOIu5NYg==", + "requires": { + "@sindresorhus/is": "^4.0.1", + "callsites": "^3.1.0", + "dot-prop": "^6.0.1", + "lodash.isequal": "^4.5.0", + "type-fest": "^1.2.1", + "vali-date": "^1.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "requires": { + "is-obj": "^2.0.0" + } + }, + "type-fest": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.3.0.tgz", + "integrity": "sha512-mYUYkAy6fPatVWtUeCV/qGeGL3IVucmdJOzeAEfwgCJDx8gP0JaW8jn6KQ5xDfPec31e0KXWn5EUOZMhquR1zA==" + } + } + }, "p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -11764,19 +12145,6 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, - "secure-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/secure-random/-/secure-random-1.1.2.tgz", - "integrity": "sha512-H2bdSKERKdBV1SwoqYm6C0y+9EA94v6SUBOWO8kDndc4NoUih7Dv6Tsgma7zO1lv27wIvjlD0ZpMQk7um5dheQ==" - }, - "secure-random-password": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/secure-random-password/-/secure-random-password-0.2.3.tgz", - "integrity": "sha512-2zpmr6pK3CZGIS9fgApFw00/tKEBVbJTqe4AZLrLNgahCK6ueIR5uMzvbERNibr8hkWneMcOqDcm4wpHWUxrYw==", - "requires": { - "secure-random": "^1.1.2" - } - }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -12230,6 +12598,11 @@ "punycode": "^2.1.1" } }, + "ts-mixer": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-5.4.1.tgz", + "integrity": "sha512-Zo9HgPCtNouDgJ+LGtrzVOjSg8+7WGQktIKLwAfaNrlOK1mWGlz1ejsAF/YqUEqAGjUTeB5fEg8gH9Aui6w9xA==" + }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -12389,6 +12762,11 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=" + }, "validator": { "version": "13.6.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz", diff --git a/package.json b/package.json index b39b4a6d..a8422c89 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "@joefallon/mysql-date": "^0.1.2", "advanced-command-handler": "^2.2.2", "aybabtu": "^1.1.6", - "bcryptjs": "^2.4.3", "canvacord": "^5.2.1", "child_process": "^1.0.2", "colornames": "^1.1.1", @@ -24,7 +23,7 @@ "discord-hybrid-sharding": "^1.1.1", "discord-logs": "^1.9.0", "discord-reply": "^0.1.2", - "discord.js": "^12.5.3", + "discord.js": "^13.0.0-dev.t1627778678.74fc23b", "discord.js-pagination": "^1.0.3", "distube": "^2.8.11", "dotenv": "^8.2.0", @@ -55,7 +54,6 @@ "pretty-ms": "^7.0.1", "random-puppy": "^1.1.0", "request": "^2.88.2", - "secure-random-password": "^0.2.2", "sequelize": "^6.6.2", "serialize-javascript": "^5.0.1", "shelljs": "^0.8.4", diff --git a/structures/Client/OneForAll.js b/structures/Client/OneForAll.js index 6995103b..497e80ce 100644 --- a/structures/Client/OneForAll.js +++ b/structures/Client/OneForAll.js @@ -12,6 +12,7 @@ let token = config.token; const io = require('socket.io-client') const Cluster = require("discord-hybrid-sharding"); const {XpSystem} = require('../../utils/Classes/discord-xp') +const Discord = require("discord.js"); let owner = [...config.owners]; if (config.botperso) { const path = './config.json'; @@ -35,8 +36,13 @@ class OneForAll extends Client { constructor(options) { super(options); if (!config.botperso && !config.dev) { - this.cluster = new Cluster.Client(this) + this.shardWebhook = new Discord.WebhookClient({ + id: '801060243785383936', + token: 'foWpfz4X8OEwrZ4SQfOR1khPOH0YdF1AsHzjfIqFW_iRpTSqtPfDwFJYUOx91Y4xv5oq', + url: 'https://discord.com/api/webhooks/801060243785383936/foWpfz4X8OEwrZ4SQfOR1khPOH0YdF1AsHzjfIqFW_iRpTSqtPfDwFJYUOx91Y4xv5oq' + }); + } this.login(token); @@ -55,7 +61,6 @@ class OneForAll extends Client { // "provenance": 'shards' // } // }) - this.finishLoad = false; this.Logger = Logger this.database = new Sequelize(name, user, pass, { dialect: 'mysql', @@ -71,12 +76,6 @@ class OneForAll extends Client { connectTimeout: 60000 }, - // pool: { - // max: 9999999, - // min: 0, - // acquire: 60000, - // idle: 10000 - // }, logging: false }) logs(this)