diff --git a/package-lock.json b/package-lock.json index 944e417..32c4852 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@discordjs/opus": "^0.5.3", "@discordjs/voice": "^0.6.0", + "@distube/ytdl-core": "^4.9.4", "@giphy/js-fetch-api": "^4.1.2", "ascii-table": "^0.0.9", "canvas": "^2.8.0", @@ -177,11 +178,11 @@ } }, "node_modules/@distube/ytdl-core": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/@distube/ytdl-core/-/ytdl-core-4.9.3.tgz", - "integrity": "sha512-oj/XoIvY2Vc7eySHvbschqPNU4gFNkF9s5er1eljGzcBC5TP+ygt/TAo59yOJEZJe5gTsaIvbv/4W6IKCuBUPg==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/@distube/ytdl-core/-/ytdl-core-4.9.4.tgz", + "integrity": "sha512-9ca8fh5jGhLnMRgpyS68YFhtJ891Y41R1hqxG1IEuUrUYmTVA+hVbTHKRgSqNYsGis2fRNFaHeYd9hchPWrbnQ==", "dependencies": { - "m3u8stream": "^0.8.3", + "m3u8stream": "^0.8.4", "miniget": "^4.0.0", "sax": "^1.1.3" }, @@ -5081,11 +5082,11 @@ } }, "@distube/ytdl-core": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/@distube/ytdl-core/-/ytdl-core-4.9.3.tgz", - "integrity": "sha512-oj/XoIvY2Vc7eySHvbschqPNU4gFNkF9s5er1eljGzcBC5TP+ygt/TAo59yOJEZJe5gTsaIvbv/4W6IKCuBUPg==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/@distube/ytdl-core/-/ytdl-core-4.9.4.tgz", + "integrity": "sha512-9ca8fh5jGhLnMRgpyS68YFhtJ891Y41R1hqxG1IEuUrUYmTVA+hVbTHKRgSqNYsGis2fRNFaHeYd9hchPWrbnQ==", "requires": { - "m3u8stream": "^0.8.3", + "m3u8stream": "^0.8.4", "miniget": "^4.0.0", "sax": "^1.1.3" } diff --git a/package.json b/package.json index f9f06cf..b1422e0 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "dependencies": { "@discordjs/opus": "^0.5.3", "@discordjs/voice": "^0.6.0", + "@distube/ytdl-core": "^4.9.4", "@giphy/js-fetch-api": "^4.1.2", "ascii-table": "^0.0.9", "canvas": "^2.8.0", diff --git a/src/Commands/Developper/command.js b/src/Commands/Developper/command.js index 7b1281d..39d8b74 100644 --- a/src/Commands/Developper/command.js +++ b/src/Commands/Developper/command.js @@ -42,6 +42,7 @@ module.exports = { const { options, guild } = message const Sub = options.getSubcommand(["enable", "disable", "reload"]); + if(!message.member.permissions.has("ADMINISTRATOR")) return message.reply({embeds :[errorEmbed().setDescription("You need to be an administrator to use this command.")], ephemeral: true}) let Commandfiles = []; diff --git a/src/Commands/Fun/cat.js b/src/Commands/Fun/cat.js new file mode 100644 index 0000000..5a25a3c --- /dev/null +++ b/src/Commands/Fun/cat.js @@ -0,0 +1,51 @@ +const { MessageEmbed, CommandInteraction } = require("discord.js"); +const { errorEmbed } = require("../../util/Embeds") +const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); // eslint-disable-line + + +module.exports = { + + name: "cat", + description: "Random Cat Pictures", + permission: "ADMINISTRATOR", + active: true, + + /** + * + * @param {CommandInteraction} message + */ + async execute(message) { + + try { + + await message.deferReply().catch(() => { }); + + const fetchAPI = async () => { + const response = await fetch("https://some-random-api.ml/animal/cat", { + method: "GET", + }); + return await response.json(); + } + + const data = await fetchAPI(); + + + const embed = new MessageEmbed() + .setTitle("Cat Picture") + .setColor("#00D7FF") + .setDescription(data.fact) + .setImage(data.image) + .setFooter(`Requested by ${message.member.user.tag}`, message.member.displayAvatarURL()) + .setTimestamp(); + + await message.editReply({ embeds: [embed] }); + + + + } catch (err) { + console.log(err) + return message.editReply({ embeds: [errorEmbed().setDescription(`Une erreur est survenue`)], ephemeral: true }) + } + + }, +}; diff --git a/src/Commands/Fun/dog.js b/src/Commands/Fun/dog.js new file mode 100644 index 0000000..c835020 --- /dev/null +++ b/src/Commands/Fun/dog.js @@ -0,0 +1,50 @@ +const { MessageEmbed, CommandInteraction } = require("discord.js"); +const { errorEmbed } = require("../../util/Embeds") +const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); // eslint-disable-line + + +module.exports = { + + name: "dog", + description: "Random Dog Pictures", + permission: "ADMINISTRATOR", + active: true, + + /** + * + * @param {CommandInteraction} message + */ + async execute(message) { + + try { + + await message.deferReply().catch(() => { }); + + const fetchAPI = async () => { + const response = await fetch("https://some-random-api.ml/animal/dog", { + method: "GET", + }); + return await response.json(); + } + + const data = await fetchAPI(); + + const embed = new MessageEmbed() + .setTitle("Dog Picture") + .setColor("#00D7FF") + .setDescription(data.fact) + .setImage(data.image) + .setFooter(`Requested by ${message.member.user.tag}`, message.member.displayAvatarURL()) + .setTimestamp(); + + await message.editReply({ embeds: [embed] }); + + + + } catch (err) { + console.log(err) + return message.reply({ embeds: [errorEmbed().setDescription(`Une erreur est survenue`)], ephemeral: true }) + } + + }, +}; diff --git a/src/Commands/Fun/fakeYTcomment.js b/src/Commands/Fun/fakeYTcomment.js new file mode 100644 index 0000000..0e0e235 --- /dev/null +++ b/src/Commands/Fun/fakeYTcomment.js @@ -0,0 +1,77 @@ +const { errorEmbed } = require("../../util/Embeds") +const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); // eslint-disable-line +const { MessageEmbed, CommandInteraction, Client, MessageAttachment } = require('discord.js'); + + +module.exports = { + + name: "fakecomment", + description: "Fakes a Youtube comment", + permission: "ADMINISTRATOR", + active : true, + + options: [ + { + name: "comment", + description: "what do you want to comment", + type: "STRING", + required: true, + + }, + { + name: "user", + description: "the user writing the comment", + type: "USER", + required: false + } + ], + + /** + * + * @param {CommandInteraction} message + * @param {Client} client + */ + + async execute(message,client) { + + try { + + await message.deferReply().catch(() => { }); + + let comment = message.options.getString("comment") + let Target = message.options.getMember("user") + + if(!Target) Target = message.member + + const fetchAPI = async () => { + const response = await fetch(`https://some-random-api.ml/canvas/youtube-comment?avatar=${Target.displayAvatarURL({format:"png"})}&username=${Target.user.username}&comment=${comment}`, { + method: "GET", + }); + return await response; + } + + + const data = await fetchAPI(); + + + const attach = new MessageAttachment(data.body, 'img.png'); + + const embed = new MessageEmbed() + .setDescription(`**${Target}'s Youtube comment**`) + .setColor("RED") + .setImage(`attachment://img.png`) + .setFooter(`Requested by ${message.member.user.tag}`, message.member.displayAvatarURL()) + .setTimestamp(); + + await message.editReply({ embeds: [embed], files: [attach] }); + + + + } catch (err) { + console.log(err) + return message.editReply({ embeds: [errorEmbed().setDescription(`Une erreur est survenue`)], ephemeral: true }) + } + + + } +} \ No newline at end of file diff --git a/src/Commands/Fun/faketweet.js b/src/Commands/Fun/faketweet.js new file mode 100644 index 0000000..ddcd952 --- /dev/null +++ b/src/Commands/Fun/faketweet.js @@ -0,0 +1,78 @@ +const { errorEmbed } = require("../../util/Embeds") +const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); // eslint-disable-line +const { MessageEmbed, CommandInteraction, Client, MessageAttachment } = require('discord.js'); + + +module.exports = { + + name: "faketweet", + description: "Fakes a tweet", + permission: "ADMINISTRATOR", + active : true, + + options: [ + { + name: "tweet", + description: "what do you want to tweet", + type: "STRING", + required: true, + + }, + { + name: "user", + description: "the user writing the comment", + type: "USER", + required: false + } + ], + + /** + * + * @param {CommandInteraction} message + * @param {Client} client + */ + + async execute(message,client) { + + try { + + await message.deferReply().catch(() => { }); + + let tweet = message.options.getString("tweet") + let Target = message.options.getMember("user") + + if(!Target) Target = message.member + + const fetchAPI = async () => { + const response = await fetch(`https://some-random-api.ml/canvas/tweet?avatar=${Target.displayAvatarURL({format:"png"})}&username=${Target.user.username}&displayname=${ Target.nickname ? Target.nickname : Target.user.username }&comment=${tweet}`, { + method: "GET", + }); + + return await response; + } + + + const data = await fetchAPI(); + + + const attach = new MessageAttachment(data.body, 'img.png'); + + const embed = new MessageEmbed() + .setDescription(`**${Target}'s Tweet**`) + .setColor("#00C5FF") + .setImage(`attachment://img.png`) + .setFooter(`Requested by ${message.member.user.tag}`, message.member.displayAvatarURL()) + .setTimestamp(); + + await message.editReply({ embeds: [embed], files: [attach] }); + + + + } catch (err) { + console.log(err) + return message.editReply({ embeds: [errorEmbed().setDescription(`Une erreur est survenue`)], ephemeral: true }) + } + + + } +} \ No newline at end of file diff --git a/src/Commands/Fun/overlay.js b/src/Commands/Fun/overlay.js new file mode 100644 index 0000000..bf1c8e6 --- /dev/null +++ b/src/Commands/Fun/overlay.js @@ -0,0 +1,125 @@ +const { errorEmbed } = require("../../util/Embeds") +const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); // eslint-disable-line +const { MessageEmbed, CommandInteraction, Client, MessageAttachment } = require('discord.js'); + + +module.exports = { + + name: "overlay", + description: "add an overlay on your avatar", + permission: "ADMINISTRATOR", + active : true, + + options: [ + { + name: "overlay", + description: "the overlay you want to add", + type: "STRING", + required: true, + + // choose "gay", "glass", "Wasted", "mission passed", "jail", "comrade", "triggered" + + choices: [ + { + name: "Gay", + value: "gay", + }, + { + name: "Glass", + value : "glass" + }, + { + name: "Wasted", + value : "wasted" + }, + { + name: "Mission Passed", + value : "passed" + }, + { + name: "Jail", + value : "jail" + }, + { + name: "Comrade", + value : "comrade" + }, + { + name: "Triggered", + value : "triggered" + }, + { + name: "Simp Card", + value : "simpcard" + }, + { + name: "Horny", + value : "horny" + }, + { + name: "Blur", + value : "blur" + }, + { + name: "Pixelate", + value : "pixelate" + }, + ] + }, + { + name: "user", + description: "the user you want to add the overlay to", + type: "USER", + required: false + } + ], + + /** + * + * @param {CommandInteraction} message + * @param {Client} client + */ + + async execute(message,client) { + + try { + + await message.deferReply().catch(() => { }); + + let overlay = message.options.getString("overlay") + let Target = message.options.getMember("user") + + if(!Target) Target = message.member + + const fetchAPI = async () => { + const response = await fetch(`https://some-random-api.ml/canvas/${overlay}?avatar=${Target.displayAvatarURL({format:"png"})}`, { + method: "GET", + }); + return await response; + } + + + const data = await fetchAPI(); + + + const attach = new MessageAttachment(data.body, 'img.png'); + + const embed = new MessageEmbed() + .setDescription(`**${Target}'s avatar with ${overlay} overlay**`) + .setColor("WHITE") + .setImage(`attachment://img.png`) + .setFooter(`Requested by ${message.member.user.tag}`, message.member.displayAvatarURL()) + .setTimestamp(); + + await message.editReply({ embeds: [embed], files: [attach] }); + + + + } catch (err) { + console.log(err) + return message.editReply({ embeds: [errorEmbed().setDescription(`Une erreur est survenue`)], ephemeral: true }) + } + + + } +} \ No newline at end of file diff --git a/src/Commands/Fun/pileouface.js b/src/Commands/Fun/pileouface.js index 5ae619e..594b6eb 100644 --- a/src/Commands/Fun/pileouface.js +++ b/src/Commands/Fun/pileouface.js @@ -1,4 +1,3 @@ -const { joinVoiceChannel } = require('@discordjs/voice'); const { MessageEmbed } = require('discord.js'); module.exports = { diff --git a/src/Commands/Fun/roll.js b/src/Commands/Fun/roll.js index ea6c5bd..34f4378 100644 --- a/src/Commands/Fun/roll.js +++ b/src/Commands/Fun/roll.js @@ -1,4 +1,3 @@ -const { joinVoiceChannel } = require('@discordjs/voice'); const { MessageEmbed } = require('discord.js'); module.exports = { diff --git a/src/Commands/Games/blackjack.js b/src/Commands/Games/blackjack.js new file mode 100644 index 0000000..c4ab7c1 --- /dev/null +++ b/src/Commands/Games/blackjack.js @@ -0,0 +1,312 @@ +const { CommandInteraction, MessageEmbed, MessageActionRow, MessageButton, Client } = require("discord.js"); +const { errorEmbed } = require("../../util/Embeds"); + +module.exports = { + name: "blackjack", + description: "Play blackjack", + permission: "ADMINISTRATOR", + active: true, + + options: [], + + /** + * + * + * @param {CommandInteraction} message + * @param {Client} client + * + */ + async execute(message, client) { + + let blackjackEmbed = new MessageEmbed() + .setTitle("🎲 -- Blackjack -- 🎲") + .setDescription("Vous voulez faire une partie de blackjack ?") + .setColor("#0099ff") + .setFooter("Blackjack") + .setTimestamp() + + let inviteRow = new MessageActionRow() + .addComponents( + new MessageButton() + .setLabel('Oui') + .setCustomId(`BJ-accept`) + .setStyle('SUCCESS'), + new MessageButton() + .setLabel('Non') + .setCustomId(`BJ-decline`) + .setStyle('DANGER') + ) + + let blackjackRow = new MessageActionRow() + .addComponents( + + new MessageButton() + .setLabel('Piocher') + .setCustomId(`BJ-draw`) + .setStyle('SUCCESS') + .setEmoji('🎴'), + + new MessageButton() + .setLabel('Rester') + .setCustomId(`BJ-stay`) + .setStyle('SECONDARY') + .setEmoji('💤'), + new MessageButton() + .setLabel('Abandonner') + .setCustomId(`BJ-abandon`) + .setStyle('DANGER') + .setEmoji('🏳️'), + ) + + await message.deferReply() + + let blackjack = await message.editReply( + { + embeds: [blackjackEmbed], + components: [inviteRow] + } + ); + + const acceptCollector = blackjack.createMessageComponentCollector({ + type: 'BUTTON', + time: 30000 + }) + + acceptCollector.on('collect', async (btn) => { + + if (btn.user.id !== message.member.id) { + return await btn.reply({ + embeds: [errorEmbed().setDescription('Vous ne pouvez pas intéragir car ce n\'est pas votre partie')], + ephemeral: true + }) + } + + if (btn.customId === 'BJ-decline') { + return await blackjack.delete() + } + + + acceptCollector.stop() + await btn.deferUpdate() + + + let playerHand = [DrawCard(), DrawCard()]; + let botHand = []; + + /** + * @param {Array} deck + * @returns {Number} + */ + + + + + blackjackEmbed.description = "\n**[Voir les Règles](https://fr.wikipedia.org/wiki/Blackjack_(jeu))**" + blackjackEmbed.addFields( + { name: "- Votre Main -", value: "-", inline: true }, + { name: `- ( ${Score(playerHand)} ) - SCORE - ( ${Score(botHand)} ) -`, value: "--------------------------", inline: true }, + { name: "- Main du bot -", value: "-", inline: true }, + ) + + blackjackEmbed.fields[0].value = `\`${playerHand[0].number} ${playerHand[0].icon}\` | \`${playerHand[1].number} ${playerHand[1].icon}\`` + + await message.editReply({ + embeds: [blackjackEmbed], + components: [blackjackRow] + }) + + const blackjackCollector = blackjack.createMessageComponentCollector({ + type: 'BUTTON', + time: 300000 + }) + + blackjackCollector.on('collect', async (btn) => { + + + + + if (btn.user.id !== message.member.id) { + return await btn.reply({ + embeds: [errorEmbed().setDescription('Vous ne pouvez pas intéragir car ce n\'est pas votre partie')], + ephemeral: true + }) + } + + await btn.deferUpdate() + + if (btn.customId === 'BJ-abandon') { + + blackjackCollector.stop("abandon") + return await blackjack.delete() + + } + + + + if (btn.customId === 'BJ-draw') { + + playerHand.push(DrawCard()); + + blackjackEmbed.fields[0].value = "" + playerHand.forEach(card => { + blackjackEmbed.fields[0].value += `\`${card.number} ${card.icon}\` | ` + }); + blackjackEmbed.fields[0].value = "" + blackjackEmbed.fields[0].value.slice(0, -2) + + + blackjackEmbed.fields[1].name = `- ( ${Score(playerHand)} ) - SCORE - ( ${Score(botHand)} ) -` + + } + + if (btn.customId === 'BJ-stay') { + return blackjackCollector.stop("stay") + } + + + /*if (Score(playerHand) = 21 && playerHand.length === 2) { + + blackjackRow.components[0].setDisabled(true) + blackjackRow.components[1].setDisabled(true) + blackjackRow.components[2].setDisabled(true) + + + blackjackCollector.stop("blackjack") + }*/ + + + if (Score(playerHand) > 21) { + + blackjackRow.components[0].setDisabled(true) + blackjackRow.components[1].setDisabled(true) + blackjackRow.components[2].setDisabled(true) + blackjackEmbed.fields[1].value = "Vous avez perdu !" + + blackjackCollector.stop("lose") + } + + return blackjack.edit({ + embeds: [blackjackEmbed], + components: [blackjackRow] + }) + + + + + }) + + + blackjackCollector.on('end', async (collected, reason) => { + + switch (reason) { + + case "stay": + + while (Score(botHand) < 17) { + botHand.push(DrawCard()); + + blackjackEmbed.fields[2].value = "" + + botHand.forEach(card => { + blackjackEmbed.fields[2].value += `\`${card.number} ${card.icon}\` | ` + }); + + blackjackEmbed.fields[2].value = "" + blackjackEmbed.fields[2].value.slice(0, -2) + + + blackjackEmbed.fields[1].name = `- ( ${Score(playerHand)} ) - SCORE - ( ${Score(botHand)} ) -` + } + + if (Score(botHand) > 21) { + blackjackEmbed.fields[1].value = "Vous avez gagné !" + } else if (Score(botHand) > Score(playerHand)) { + blackjackEmbed.fields[1].value = "Vous avez perdu !" + } else if (Score(botHand) === Score(playerHand)) { + blackjackEmbed.fields[1].value = "Egalité !" + } else { + blackjackEmbed.fields[1].value = "Vous avez gagné !" + } + + blackjack.edit({ + embeds: [blackjackEmbed], + components: [], + }) + + break; + + case "blackjack": + + break; + case "lose": + + blackjack.edit({ + embeds: [blackjackEmbed], + components: [], + }) + + break; + + case "time": + await blackjack.edit( + { + embeds: [errorEmbed().setDescription("Vous n'avez pas répondu dans le temps imparti")], + components: [], + } + ) + break; + + } + + }) + + + }) + + acceptCollector.on('end', async (collected, reason) => { + if(reason === 'time') { + await blackjack.edit( + { + embeds: [errorEmbed().setDescription("Vous n'avez pas répondu dans le temps imparti")], + components: [], + } + ) + } + + }) + + + + + + + } +} + + +function DrawCard() { + let icon = ["♦️", "♠️", "♣️", "♥️"]; + let number = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]; + let card = Math.floor(Math.random() * 13); + let suit = Math.floor(Math.random() * 4) ; + + return { + icon: icon[suit], + number: number[card], + index : card, + } +} + +function Score(deck) { + + let score = 0; + + deck.forEach(card => { + if (card.number === "A") { + score + 11 > 21 ? score += 1 : score += 11; + } + + score += card.index > 9 ? 10 : card.index + 1; + + }); + + return score; +} \ No newline at end of file diff --git a/src/Commands/Fun/curvytron.js b/src/Commands/Games/curvytron.js similarity index 100% rename from src/Commands/Fun/curvytron.js rename to src/Commands/Games/curvytron.js diff --git a/src/Commands/Fun/hot.js b/src/Commands/Games/hot.js similarity index 100% rename from src/Commands/Fun/hot.js rename to src/Commands/Games/hot.js diff --git a/src/Commands/Fun/rps.js b/src/Commands/Games/rps.js similarity index 100% rename from src/Commands/Fun/rps.js rename to src/Commands/Games/rps.js diff --git a/src/Commands/Miscellaneous/emoji-steal.js b/src/Commands/Miscellaneous/emoji-steal.js index c9b0add..ae9ea92 100644 --- a/src/Commands/Miscellaneous/emoji-steal.js +++ b/src/Commands/Miscellaneous/emoji-steal.js @@ -1,4 +1,4 @@ -const { MessageEmbed, Util } = require('discord.js') +const { MessageEmbed, Util, CommandInteraction, Client } = require('discord.js') const delay = require("delay") const { errorEmbed } = require("../../util/Embeds") @@ -20,11 +20,17 @@ module.exports = { }, ], + + /** + * + * @param {CommandInteraction} message + * @param {Client} client + */ async execute(message, client) { - + if(!message.member.permissions.has("ADMINISTRATOR")) return message.reply({embeds : [errorEmbed().setDescription("You can't steal an emoji from another server!")]}) let argsEmoji = message.options.getString('emoji') let emoji = [] diff --git a/src/Commands/Moderation/kick.js b/src/Commands/Moderation/kick.js index 1c71956..409ff08 100644 --- a/src/Commands/Moderation/kick.js +++ b/src/Commands/Moderation/kick.js @@ -46,7 +46,7 @@ module.exports = { if (Target.id === guild.ownerID) return interaction.reply({embeds : [errorEmbed().setDescription("You can't kick the server owner.")]}) if (Target.roles.highest.position > member.roles.highest.position) return interaction.reply({embeds : [errorEmbed().setDescription("You can't kick a user with a higher role than you.")]}) - if (Target.permissions.has(this.perms)) return interaction.reply({embeds : [errorEmbed().setDescription("You can't kick a user who had " + this.permission + " permission")]}) + if (Target.permissions.has("ADMINISTRATOR")) return interaction.reply({embeds : [errorEmbed().setDescription("You can't kick a user who had " + "`ADMINISTRATOR`" + " permission")]}) Target.send({ embeds: [kickEmbed().setDescription("You have been kicked from **" + guild.name + "** for **" + Reason + "**")] }) .catch(() => { diff --git a/src/Commands/Pokemon/my-pokedex.js b/src/Commands/Pokemon/my-pokedex.js new file mode 100644 index 0000000..872c755 --- /dev/null +++ b/src/Commands/Pokemon/my-pokedex.js @@ -0,0 +1,726 @@ +const { CommandInteraction, Client, MessageEmbed, MessageActionRow, MessageButton, MessageSelectMenu } = require("discord.js") +const db = require("../../Models/my-pokedex") +const { errorEmbed, successEmbed } = require("../../util/Embeds") +const Pokedex = require("pokedex-promise-v2"); +const P = new Pokedex(); +const {pokemonNames} = require("../../util/pokemonNames") + +module.exports = { + + name: "mypokedex", + description: "My Pokedex", + permission: "ADMINISTRATOR", + active: true, + options: [ + { + name: "init", + description: "initialize your pokedex", + type: "SUB_COMMAND", + + }, + + { + name: "delete", + description: "delete your pokedex", + type: "SUB_COMMAND", + + }, + + { + name: "add", + description: "add a pokemon to your pokedex", + type: "SUB_COMMAND_GROUP", + options: [ + { + name: "by-names", + description: "add one or several pokemons by name", + type: "SUB_COMMAND", + options: [ + { + name: "pokemon", + description: "the pokemon name", + type: "STRING", + required: true, + } + ], + }, + { + name: "by-index-numbers", + description: "add one or several pokemons by index number", + type: "SUB_COMMAND", + options: [ + { + name: "index", + description: "the pokemon index", + type: "NUMBER", + required: true, + } + ], + }, + { + name: "by-index-group", + description: "add group of pokemon by index number", + type: "SUB_COMMAND", + options: [ + { + name: "min", + description: "the minimum index", + type: "NUMBER", + required: true, + }, + { + name: "max", + description: "the maximum index", + type: "NUMBER", + required: true, + } + ], + }, + ] + }, + + + { + name: "remove", + description: "remove a pokemon from your pokedex", + type: "SUB_COMMAND_GROUP", + options: [ + { + name: "by-names", + description: "add one or several pokemons by name", + type: "SUB_COMMAND", + options: [ + { + name: "pokemon", + description: "the pokemon name", + type: "STRING", + required: true, + } + ], + }, + { + name: "by-index-numbers", + description: "add one or several pokemons by index number", + type: "SUB_COMMAND", + options: [ + { + name: "index", + description: "the pokemon index", + type: "NUMBER", + required: true, + } + ], + }, + { + name: "by-index-group", + description: "add group of pokemon by index number", + type: "SUB_COMMAND", + options: [ + { + name: "min", + description: "the minimum index", + type: "NUMBER", + required: true, + }, + { + name: "max", + description: "the maximum index", + type: "NUMBER", + required: true, + } + ], + }, + ] + }, + + { + name: "view", + description: "view your pokedex", + type: "SUB_COMMAND", + + }, + + ], + + /** + * + * @param {CommandInteraction} message + * @param {Client} client + */ + + async execute(message, client) { + + const { options, guild, member } = message + + let Sub = options.getSubcommand(["view", "init","delete"]) + + await message.deferReply() + + //! INITIALISATION DE LA BDD POKEDEX DU USER + + if (Sub === "init") { + //if (message.member.permissions.has("ADMINISTRATOR")) { return message.editReply({ embed: [errorEmbed().setDescription("You need to be an administrator to use this command.")], ephemeral: true }) } + + let initEmbed = new MessageEmbed() + .setTitle("Initialisation de votre Pokédex...") + .setColor("#000000") + .setDescription("Veuillez indiquer la version de votre jeu") + .setTimestamp() + + + let isInDB = false + + + await db.findOne({ UserID: member.id }, async (err, doc) => { + if (err) { return await message.editReply({ embed: [errorEmbed().setDescription("Une erreur a été rencontrée lors de la recherche de votre Pokédex")], ephemeral: true }) } + if (doc) { + isInDB = true + return await message.editReply({ embeds: [errorEmbed().setDescription(`Tu as déjà un Pokédex`)], ephemeral: true }) + } + }).clone() + + console.log(isInDB) + if (isInDB) return; + + let tempDB = {} + let versions = [] + let pokedexs = [] + + await P.getVersionGroupsList().then(res => { + + res.results.forEach(version => { + let versionsBlacklist = ["colosseum", "xd"] + + if (!versionsBlacklist.includes(version.name)) { + versions.push({ label: "Pokemon " + version.name, value: version.name }) + } + }) + + }) + + let row = new MessageActionRow().addComponents( + new MessageSelectMenu() + .setOptions(versions) + .setCustomId("pokedex-version") + .setPlaceholder("Choisissez une version") + ) + + m = await message.editReply({ + embeds: [initEmbed], + components: [row] + }) + const versionCollector = m.createMessageComponentCollector({ + type: "SELECT_MENU", + time: 60000 + }) + + versionCollector.on("collect", async (menu) => { + + if (menu.user.id !== member.id) { + return menu.reply({ + embeds: [errorEmbed().setDescription("Ce n'est pas ton Pokédex")], + ephemeral: true + }) + } + + if (menu.customId === "pokedex-version") { + + console.log(); + tempDB.version = menu.values[0] + + await P.getVersionGroupByName(menu.values[0]).then(res => { + + let tempRegions = [] + + if (res.regions.length > 1) { + res.regions.forEach(region => { + tempRegions.push(region.name) + }) + } else { + tempRegions.push(res.regions[0].name) + } + + (tempRegions.length > 1) ? tempDB.regions = tempRegions.join(",") : tempDB.regions = tempRegions[0] + + + let pokedexregions = "" + + if (tempDB.regions.includes(",")) { + tempDB.regions.split(",").forEach(region => { + pokedexregions += "`" + region + "` " + }) + } else { + pokedexregions = "`" + tempDB.regions + "`" + } + + tempDB.generations = res.generation.name + initEmbed.addFields( + { name: "Version", value: `\`${menu.values[0]}\``, inline: true }, + { name: "Région(s)", value: `${tempDB.regions}`, inline: true }, + { name: "Génération", value: `\`${res.generation.name}\``, inline: true } + ) + + let nationalBlacklist = ["lets-go", "firered-leafgreen", "red-blue", "yellow", "gold-silver", "crystal"] + + if (!nationalBlacklist.includes(menu.values[0])) { + pokedexs.push({ label: "National", value: "national" }) + } + + if (res.pokedexes.length > 1) { + + let pokedexlist = "" + + res.pokedexes.forEach(pokedex => { + if (res.pokedexes.indexOf(pokedex) !== res.pokedexes.length - 1) { + pokedexlist += pokedex.name + "," + } else { + pokedexlist += pokedex.name + } + }) + + pokedexs.push({ label: "Tous les Pokédex de la région", value: `${pokedexlist}` }) + } + + res.pokedexes.forEach(pokedex => { + pokedexs.push({ label: pokedex.name, value: pokedex.name }) + }) + + + + + }).catch(err => { + console.log(err); + return message.editReply({ embeds: [errorEmbed().setDescription(`${err}`)], components: [], ephemeral: true }) + + }) + + + await menu.deferUpdate() + versionCollector.stop() + + let row = new MessageActionRow().addComponents( + new MessageSelectMenu() + .setOptions(pokedexs) + .setCustomId("pokedex-type") + .setPlaceholder("Choisissez un Pokédex") + ) + + await m.edit({ + embeds: [initEmbed.setDescription("Veuillez choisir un Pokédex")], + components: [row] + }) + + const pokedexCollector = m.createMessageComponentCollector({ + type: "SELECT_MENU", + time: 60000 + }) + + pokedexCollector.on("collect", async (menu) => { + + if (menu.user.id !== member.id) { + return menu.reply({ + embeds: [errorEmbed().setDescription("Ce n'est pas ton Pokédex")], + ephemeral: true + }) + } + + if (menu.customId === "pokedex-type") { + + tempDB.pokedex = menu.values[0] + + let pokedexnames = "" + + if (tempDB.pokedex.includes(",")) { + tempDB.pokedex.split(",").forEach(pokedex => { + pokedexnames += "`" + pokedex + "` " + }) + } else { + pokedexnames = "`" + tempDB.pokedex + "`" + } + + initEmbed.addFields( + { name: "Pokédex", value: `${pokedexnames}`, inline: true } + ) + + await menu.deferUpdate() + pokedexCollector.stop() + + let row = new MessageActionRow().addComponents( + new MessageSelectMenu() + .setOptions([{ label: "Oui", value: "yes", emoji: "✔️" }, { label: "Non", value: "no", emoji: "❌" }]) + .setCustomId("pokedex-init-confirm") + .setPlaceholder("Confirmer l'initialisation") + ) + + await m.edit({ + embeds: [initEmbed.setDescription("\`\`\`Voulez-vous initialiser votre pokedex ?\`\`\`")], + components: [row] + }) + + const confirmCollector = m.createMessageComponentCollector({ + type: "SELECT_MENU", + time: 60000 + }) + + confirmCollector.on("collect", async (menu) => { + + if (menu.user.id !== member.id) { + return menu.reply({ + embeds: [errorEmbed().setDescription("Ce n'est pas ton Pokédex")], + ephemeral: true + }) + } + if (menu.customId === "pokedex-init-confirm") { + if (menu.values[0] === "yes") { + + tempDB.pokemonNotCatch = [] + + await menu.deferUpdate() + confirmCollector.stop() + await m.edit({ + embeds: [initEmbed.setDescription("Initialisation en cours...")], + components: [] + }) + + + if (tempDB.pokedex === "national") { + console.log("national"); + + let index_max + + //set max index with all generations + + if (tempDB.generations === "generation-i") { + index_max = 151 + } else if (tempDB.generations === "generation-ii") { + index_max = 251 + } + else if (tempDB.generations === "generation-iii") { + index_max = 386 + } + else if (tempDB.generations === "generation-iv") { + index_max = 493 + } + else if (tempDB.generations === "generation-v") { + index_max = 649 + } + else if (tempDB.generations === "generation-vi") { + index_max = 721 + } + else if (tempDB.generations === "generation-vii") { + index_max = 809 + } + else if (tempDB.generations === "generation-viii") { + index_max = 898 + } + + await P.getPokedexByName("national").then(res => { + res.pokemon_entries.forEach(pokemon => { + if (pokemon.entry_number <= index_max) { + pokemonFR = Object.keys(pokemonNames).find(key => pokemonNames[key] === pokemon.pokemon_species.name) + + tempDB.pokemonNotCatch.push( + { + name: pokemonFR, + index: pokemon.entry_number, + pokedex: "national" + } + ); + } + }) + }) + + + + } + else if (tempDB.pokedex.includes(",")) { + console.log("multiple"); + let pokedexes = tempDB.pokedex.split(",") + console.log(pokedexes); + + for (let i = 0; i < pokedexes.length; i++) { + let pokemonFR + await P.getPokedexByName(pokedexes[i]).then(res => { + + res.pokemon_entries.forEach(pokemon => { + + pokemonFR = Object.keys(pokemonNames).find(key => pokemonNames[key] === pokemon.pokemon_species.name) + + tempDB.pokemonNotCatch.push( + { + name: pokemonFR, + index: pokemon.entry_number, + pokedex: pokedexes[i] + } + ); + + }) + + }) + } + + } + else { + console.log("single"); + await P.getPokedexByName(tempDB.pokedex).then(res => { + res.pokemon_entries.forEach(pokemon => { + pokemonFR = Object.keys(pokemonNames).find(key => pokemonNames[key] === pokemon.pokemon_species.name) + + tempDB.pokemonNotCatch.push( + { + name: pokemonFR, + index: pokemon.entry_number, + pokedex: tempDB.pokedex + } + ); + }) + }) + + } + + console.log(tempDB.pokemonNotCatch); + + + //create line in DB + + await db.findOne({ UserID: member.id }, (err, data) => { + if (err) throw err; + if (!data) { + data = new db({ + + UserID: member.id, + UserTag: member.user.tag, + + PokedexName: tempDB.pokedex, // ex: national + PokedexRegion: tempDB.regions, // ex: galar + PokedexGameVersion: tempDB.version, // ex: sword-shield + PokedexGeneration: tempDB.generations, // ex: gen-7 + + PokemonNotYetCaught: tempDB.pokemonNotCatch, + }) + data.save() + } + }).clone() + + + await m.edit({ + embeds: [initEmbed.setTitle("✅ Pokedex initialisé ✅").setDescription("Votre Pokédex a été initialisé avec succès. ").setColor("#00ff00")], + components: [] + }) + + + } else { + await menu.deferUpdate() + confirmCollector.stop() + await m.edit({ + embeds: [new MessageEmbed().setDescription("Votre Pokédex n'a pas été initialisé.").setColor("RED")], + components: [] + }) + } + } + }) + + confirmCollector.on("end", async (collected, reason) => { + if (reason === "time") { + return m.edit({ embeds: [errorEmbed().setDescription("Vous n'avez pas comfirmé dans le temps imparti")], components: [], ephemeral: true }) + } + }) + } + + + }) + + pokedexCollector.on("end", async (collected, reason) => { + if (reason === "time") { + return m.edit({ embeds: [errorEmbed().setDescription("Vous n'avez pas choisis de Pokédex dans le temps imparti")], components: [], ephemeral: true }) + } + }) + + + } + }) + versionCollector.on("end", async (collected, reason) => { + if (reason === "time") { + return m.edit({ embeds: [errorEmbed().setDescription("Vous n'avez pas choisis de version dans le temps imparti")], components: [], ephemeral: true }) + } + }) + + + } + + //! SUPPRESION DE LA BDD POKEDEX DU USER + + else if (Sub === "delete") { + + let deleteEmbed = new MessageEmbed() + .setTitle("Supression de votre Pokédex...") + .setColor("RED") + .setDescription("\`\`\`Êtes-vous sûr de vouloir supprimés votre Pokédex ?\`\`\`") + .setTimestamp() + + await db.findOne({ UserID: member.id }, async (err, data) => { + if (err) { return await message.editReply({ embed: [errorEmbed().setDescription("Une erreur a été rencontrée lors de la recherche de votre Pokédex")], ephemeral: true }) } + if (!data) { + return await message.editReply({ embeds: [errorEmbed().setDescription(`Vous n'avez pas de Pokédex.\nPour créer un Pokédex, utilisez la commande : \`/${this.name} init\`.`)], ephemeral: true }) + } else { + + let pokedexnames = "" + let pokedexregions = "" + + if (data.PokedexName.includes(",")) { + data.PokedexName.split(",").forEach(pokedex => { + pokedexnames += "`" + pokedex + "` " + }) + } else { + pokedexnames = "`" + data.PokedexName + "`" + } + + if (data.PokedexRegion.includes(",")) { + data.PokedexRegion.split(",").forEach(region => { + pokedexregions += "`" + region + "` " + }) + } else { + pokedexregions = "`" + data.PokedexRegion + "`" + } + + deleteEmbed.addFields( + { name: "Pokedex", value: `${pokedexnames}`, inline: true }, + { name: "Région(s)", value: `${pokedexregions}`, inline: true }, + { name: "Version", value: `\`${data.PokedexGameVersion}\``, inline: true }, + { name: "Génération", value: `\`${data.PokedexGeneration}\``, inline: true }, + { name: "Pokémon attrapé/vu", value: `\`${data.PokemonCaught.length}\``, inline: true }, + { name: "Pokémon non attrapé/vu", value: `\`${data.PokemonNotYetCaught.length}\``, inline: true }, + ) + + + + + + + let row = new MessageActionRow().addComponents( + new MessageSelectMenu() + .setOptions([{ label: "Oui", value: "yes", emoji: "✔️" }, { label: "Non", value: "no", emoji: "❌" }]) + .setCustomId("pokedex-delete-confirm") + .setPlaceholder("Confirmer la suppression") + ) + + let m = await message.editReply({ + embeds: [deleteEmbed], + components: [row], + ephemeral: true + }) + + const confirmCollector = m.createMessageComponentCollector({ + type: "SELECT_MENU", + time: 60000 + }) + + confirmCollector.on("collect", async (menu) => { + + if (menu.user.id !== member.id) { + return menu.reply({ + embeds: [errorEmbed().setDescription("Ce n'est pas ton pokédex")], + ephemeral: true + }) + } + if (menu.customId === "pokedex-delete-confirm") { + + + if (menu.values[0] === "yes") { + + confirmCollector.stop() + await menu.deferUpdate() + await data.delete() + + + await message.edit({ + embeds: [deleteEmbed.setTitle("🗑️ Pokédex supprimé 🗑️").setDescription("Votre Pokédex a été supprimé avec succès.")], + components: [], + ephemeral: true + }) + + + } else { + await menu.deferUpdate() + confirmCollector.stop() + await message.edit({ + embeds: [new MessageEmbed().setDescription("Votre Pokédex n'a pas été supprimé.").setColor("RED")], + components: [], + ephemeral: true + }) + } + } + }) + + confirmCollector.on("end", async (collected, reason) => { + if (reason === "time") { + return m.edit({ + embeds: [errorEmbed().setDescription("Vous n'avez pas confirmé dans le temps imparti")], + components: [], + ephemeral: true + }) + } + }) + } + }).clone() + + + } + + //! AFFICHAGE DES INFORMATIONS DU POKÉDEX + + else if (Sub === "view") { + + let viewEmbed = new MessageEmbed() + .setColor("GOLD") + + + await db.findOne({ UserID: member.id }, async (err, data) => { + if (err) { return await message.editReply({ embed: [errorEmbed().setDescription("Une erreur a été rencontrée lors de la recherche de votre Pokédex")], ephemeral: true }) } + if (!data) { + return await message.editReply({ embeds: [errorEmbed().setDescription(`Vous n'avez pas de Pokédex.\nPour créer un Pokédex, utilisez la commande : \`/${this.name} init\`.`)], ephemeral: true }) + } else { + let pokedexnames = "" + let pokedexregions = "" + + if (data.PokedexName.includes(",")) { + data.PokedexName.split(",").forEach(pokedex => { + pokedexnames += "`" + pokedex + "` " + }) + } else { + pokedexnames = "`" + data.PokedexName + "`" + } + + if (data.PokedexRegion.includes(",")) { + data.PokedexRegion.split(",").forEach(region => { + pokedexregions += "`" + region + "` " + }) + } else { + pokedexregions = "`" + data.PokedexRegion + "`" + } + + + viewEmbed.setAuthor(`Pokédex de ${member.user.username}`, member.displayAvatarURL()) + .setDescription(`**Complété à ${Math.round((data.PokemonCaught.length/data.PokemonNotYetCaught.length)*100)} %**\n`) + .addFields( + { name: "Pokedex", value: `${pokedexnames}`, inline: true }, + { name: "Région(s)", value: `${pokedexregions}`, inline: true }, + { name: "Version", value: `\`${data.PokedexGameVersion}\``, inline: true }, + { name: "Génération", value: `\`${data.PokedexGeneration}\``, inline: true }, + { name: "Pokémon attrapé/vu", value: `\`${data.PokemonCaught.length}\``, inline: true }, + { name: "Pokémon non attrapé/vu", value: `\`${data.PokemonNotYetCaught.length}\``, inline: true }, + ) + + message.editReply({embeds: [viewEmbed]}) + } + }).clone() + + + + + + + } + + } +} \ No newline at end of file diff --git a/src/Commands/Fun/pokedex.js b/src/Commands/Pokemon/pokemon-info.js similarity index 96% rename from src/Commands/Fun/pokedex.js rename to src/Commands/Pokemon/pokemon-info.js index 03ff6aa..b333ef6 100644 --- a/src/Commands/Fun/pokedex.js +++ b/src/Commands/Pokemon/pokemon-info.js @@ -10,8 +10,8 @@ const P = new Pokedex(); module.exports = { - name: "pokedex", - description: "Choisis ton Pokemon", + name: "pokemon-info", + description: "Affiche les informations d'un pokemon", permission: "ADMINISTRATOR", active: true, @@ -29,7 +29,7 @@ module.exports = { let pokemonArgs = message.options.getString("pokemon"); let pokemonEN = pokemonNames[pokemonArgs.toLowerCase().normalize("NFD").replace(/\p{Diacritic}/gu, "")]; - console.log() + if (isNaN(pokemonArgs)) { @@ -102,9 +102,6 @@ module.exports = { return str } - - console.log(pokemonData); - try { message.editReply({ embeds: [ @@ -159,8 +156,7 @@ module.exports = { // } // }) - // .catch(function (error) { //catch error - // console.log("There was an ERROR: ", error); + // .catch(function (error) { ERROR: ", error); // message.reply({ embeds: [errorEmbed().setDescription(`${error}`)] }); // }); // }; diff --git a/src/Commands/Fun/pokemonlist.js b/src/Commands/Pokemon/pokemon-list.js similarity index 99% rename from src/Commands/Fun/pokemonlist.js rename to src/Commands/Pokemon/pokemon-list.js index b266ce6..e849b7d 100644 --- a/src/Commands/Fun/pokemonlist.js +++ b/src/Commands/Pokemon/pokemon-list.js @@ -7,7 +7,7 @@ const { errorEmbed } = require("../../util/Embeds") module.exports = { - name: "pokemonlist", + name: "pokemon-list", description: "Affiche 1 à 10 pokemon random", permission: "ADMINISTRATOR", active: true, diff --git a/src/Commands/Setup/set-channel.js b/src/Commands/Setup/set-channel.js index b71d8e1..143b1d3 100644 --- a/src/Commands/Setup/set-channel.js +++ b/src/Commands/Setup/set-channel.js @@ -30,6 +30,10 @@ module.exports = { { name: "goodbye", value : "goodbye" + }, + { + name: "music", + value : "music" } ], required: true, @@ -122,6 +126,25 @@ module.exports = { }) break; + case "music": + + db.findOne({ + GuildID: message.guild.id + }, async (err, data) => { + if (err) throw err + if (!data) { + data = new db({ + GuildID: message.guild.id, + MusicChannelID: message.channel.id + + }) + } else { + data.MusicChannelID = message.channel.id + } + data.save() + }) + + break; } diff --git a/src/Commands/Setup/setnick.js b/src/Commands/Setup/setnick.js new file mode 100644 index 0000000..9a7cfeb --- /dev/null +++ b/src/Commands/Setup/setnick.js @@ -0,0 +1,64 @@ +const { MessageEmbed, CommandInteraction } = require("discord.js"); +const { errorEmbed } = require("../../util/Embeds") +const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); // eslint-disable-line + + +module.exports = { + + name: "setnick", + description: "Change your nickname", + permission: "ADMINISTRATOR", + active: true, + + options: [ + { + name: "nickname", + description: "The nickname you want to change to", + type: "STRING", + required: true, + }, + { + name: "member", + description: "The user you want to change the nickname of", + type: "USER", + required: false, + }, + ], + + /** + * + * @param {CommandInteraction} message + */ + + async execute(message) { + + let Target = message.options.getMember("member"); + let newNickname = message.options.getString("nickname"); + + if (!Target) Target = message.member; + + oldNickname = Target.nickname ? Target.nickname : Target.user.username; + + //Permission checking + + if (!message.member.permissions.has("CHANGE_NICKNAME")) return message.reply({ embeds: [errorEmbed().setDescription(`Vous n'avez pas la permission de changer de pseudo`)], ephemeral: true }); + if (!message.guild.me.permissions.has("MANAGE_NICKNAMES")) return message.reply({ embeds: [errorEmbed().setDescription(`Je n'ai pas la permission de changer de pseudo`)], ephemeral: true }); + if (Target.roles.highest.position > message.member.roles.highest.position && Target != message.member) return message.reply({ embeds: [errorEmbed().setDescription(`Vous ne pouvez pas changer le pseudo d'un membre de rang supérieur à vous`)], ephemeral: true }); + + + //Nickname checking + + if (newNickname.length > 32) return message.reply({ embeds: [errorEmbed().setDescription(`Le pseudo que vous avez entré est trop long || \`Max : 32 caractères\``)], ephemeral: true }); + if (newNickname.length < 2) return message.reply({ embeds: [errorEmbed().setDescription(`Le pseudo que vous avez entré est trop court|| \`Min : 2 caractères\``)], ephemeral: true }); + + //Nickname changing + + await Target.setNickname(newNickname).then(() => { + message.reply({ embeds: [new MessageEmbed().setDescription(`**Le pseudo de ${Target} a été changé** \n\n\`${oldNickname}\` ---> \`${newNickname}\``).setColor("GREEN")], ephemeral: true }); + }).catch((err) => { + message.reply({ embeds: [errorEmbed().setDescription(`Je ne peux pas changer le surnom de ${Target} dù à une erreur survenue lors de l'exécution`)], ephemeral: true }); + console.log(err); + }); + + }, +}; diff --git a/src/Commands/music/lyrics.js b/src/Commands/music/lyrics.js index 2ba3976..232949f 100644 --- a/src/Commands/music/lyrics.js +++ b/src/Commands/music/lyrics.js @@ -19,12 +19,7 @@ module.exports = { const queue = client.distube.getQueue(message) if (!queue) return message.reply({ embeds: [errorEmbed().setDescription(`There is nothing in the queue right now !`)], ephemeral: true }) - message.reply({ - embeds: [ - musicEmbed() - .setDescription("⏳ Searching ...") - ] - }) + message.deferReply({ ephemeral: false }) //open Browser const browser = await puppeteer.launch({headless: true}) @@ -52,18 +47,31 @@ module.exports = { //scrap the lyrics lyrics = await page.evaluate(() => { - let elements = document.querySelector('body > routable-page > ng-outlet > song-page > div > div > div.song_body.column_layout > div.column_layout-column_span.column_layout-column_span--primary > div > defer-compile:nth-child(2) > lyrics > div > div > section > p') + + let elements = document.querySelector('#lyrics-root') return elements.innerText }) - - //close browser + //if lyrics is longer than 2000 characters, send lyrics in multiple embed + if (lyrics.length > 4000) { + let lyricsArray = [] + for (let i = 0; i < lyrics.length; i += 4000) { + lyricsArray.push(lyrics.substring(i, i + 4000)) + } + + for (let i = 0; i < lyricsArray.length; i++) { + message.followUp({ embeds: [musicEmbed() + .setDescription(lyricsArray[i]) + ]}) + await sleep(1000) + } + } else { + message.followUp({ embeds: [musicEmbed() + .setDescription(lyrics) + ]}) + } + browser.close() - message.editReply({ - embeds: [ - musicEmbed() - .setDescription(`${lyrics}`) - ]}) } catch (e) { message.editReply({ embeds: [errorEmbed().setDescription(`Lyrics not found`)], ephemeral: true }) console.log(e); diff --git a/src/Commands/music/nowplaying.js b/src/Commands/music/nowplaying.js index 56ee19d..2af608d 100644 --- a/src/Commands/music/nowplaying.js +++ b/src/Commands/music/nowplaying.js @@ -26,8 +26,6 @@ function generateProgressBar(currentTime, duration) { } - - module.exports = { name: "nowplaying", @@ -38,31 +36,36 @@ module.exports = { async execute(message, client) { - channel = message.member.voice.channel - + const channel = message.member.voice.channel if (!channel) return message.reply({ embeds: [errorEmbed().setDescription(`Please join a voice channel !`)], ephemeral: true }) const queue = client.distube.getQueue(message) if (!queue) return message.reply({ embeds: [errorEmbed().setDescription(`Nothing is playing right now !`)], ephemeral: true }) try { - let playingSong = queue.songs[0] - - - - - await message.reply({ embeds: [musicEmbed() + message.deferReply({ ephemeral: false }) + var refreshTimout = queue.songs[0].duration - queue.songs[0].currentTime + var count = 0 + var refreshMessage = setInterval(() => { + count ++ + if(count > refreshTimout) clearInterval(refreshMessage) + let playingSong = queue.songs[0] + //console.log(`${queue.formattedCurrentTime} **${generateProgressBar(queue.currentTime, playingSong.duration )}** ${playingSong.formattedDuration}`) + message.editReply({ embeds: [musicEmbed() .setTitle(`Playing ${playingSong.name}`) .setURL(`${playingSong.url}`) .setThumbnail(`${playingSong.thumbnail}`) - .setDescription(`${queue.formattedCurrentTime} **${generateProgressBar(queue.currentTime, playingSong.duration )}** ${playingSong.formattedDuration}`) - .addField(`Requester`, `${playingSong.member}`, true) + .setDescription(`**${queue.formattedCurrentTime} ${generateProgressBar(queue.currentTime, playingSong.duration )} ${playingSong.formattedDuration}**`) + .addField(`Requester`, `${playingSong.user}`, true) .addField(`Author`, `[${playingSong.uploader.name}](${playingSong.uploader.url})`, true) .addField(`Volume`, `${queue.volume}%`, true) - ], - components: [musicButtonRow()], - ephemeral: true }) + ], + components: [musicButtonRow()], + ephemeral: false }) + }, 1000) + + } catch (e) { - message.reply({ embeds: [errorEmbed().setDescription(`${e}`)], ephemeral: true }) + message.editReply({ embeds: [errorEmbed().setDescription(`${e}`)], ephemeral: true }) } diff --git a/src/Commands/music/play.js b/src/Commands/music/play.js index 01b7b06..ce0aac8 100644 --- a/src/Commands/music/play.js +++ b/src/Commands/music/play.js @@ -27,12 +27,7 @@ module.exports = { if (music=="") return - message.reply({ - embeds: [ - musicEmbed() - .setDescription("⏳ Searching ...") - ] - }) + message.deferReply({ ephemeral: false }) var channel = message.member.voice.channel; await joinVoiceChannel({ diff --git a/src/Commands/music/previous.js b/src/Commands/music/previous.js index 1f30155..49a1046 100644 --- a/src/Commands/music/previous.js +++ b/src/Commands/music/previous.js @@ -10,7 +10,7 @@ module.exports = { async execute(message, client) { const queue = client.distube.getQueue(message) - const previousSong = queue.previousSongs[0] + const previousSong = queue.previousSongs[queue.previousSongs.length-1] if (!queue) return message.reply({ embeds: [errorEmbed().setDescription(`There is nothing in the queue right now !`)], ephemeral: true }) if (previousSong === undefined) return message.reply({ embeds: [errorEmbed().setDescription(`Nothing has been played previously in queue right now !`)], ephemeral: true }) try { diff --git a/src/Commands/music/queue.js b/src/Commands/music/queue.js index 9aafd75..4a1b168 100644 --- a/src/Commands/music/queue.js +++ b/src/Commands/music/queue.js @@ -16,15 +16,18 @@ module.exports = { const queue = client.distube.getQueue(message) if (!queue) return message.reply({ embeds: [errorEmbed().setDescription(`There is nothing in the queue right now !`)], ephemeral: true }) - const tracks = queue.songs.map((song, i) => `**${i}** - [${song.name}](${song.url}) - ${song.formattedDuration}`); const numberSongs = queue.songs.length; - const nextSongs = numberSongs > 6 ? `And **${numberSongs - 6}** other song(s)...` : `**${numberSongs}** song(s) in the playlist`; + const previousNumberSongs = queue.previousSongs.length; + const tracks = queue.songs.map((song, i) => `**${i+previousNumberSongs}** - [${song.name}](${song.url}) - ${song.formattedDuration}`); + const previousTracks = queue.previousSongs.map((song, i) => `**${i}** - [${song.name}](${song.url}) - ${song.formattedDuration}`); + + const nextSongs = `**${previousNumberSongs}** out of **${numberSongs}** song(s) in the playlist`; let playingEmbed = musicEmbed() - .setDescription(`Current [${queue.songs[0].name}](${queue.songs[0].url})\n\n${tracks.slice(1, 6).join('\n')}\n\n${nextSongs}`) + .setDescription(`${previousTracks.slice(-6).join('\n')}\n⤵️ ⤵️ ⤵️ \n**${previousNumberSongs} Current [${queue.songs[0].name}](${queue.songs[0].url})**\n⤴️ ⤴️ ⤴️ \n${tracks.slice(1, 6).join('\n')}\n\n${nextSongs}`) .setThumbnail(queue.songs[0].thumbnail) - message.reply({ embeds: [playingEmbed],components: [musicButtonRow()] , ephemeral: true }) + message.reply({ embeds: [playingEmbed], ephemeral: true }) } catch (e) { message.reply({ embeds: [errorEmbed().setDescription(`${e}`)], ephemeral: true }) } diff --git a/src/Commands/template.js b/src/Commands/template.js new file mode 100644 index 0000000..7daea02 --- /dev/null +++ b/src/Commands/template.js @@ -0,0 +1,23 @@ +const { CommandInteraction, MessageEmbed, Client } = require("discord.js"); +const { errorEmbed } = require("../../util/Embeds"); + +module.exports = { + name: "", + description: "", + permission: "ADMINISTRATOR", + active: true, + + options: [], + + /** + * + * + * @param {CommandInteraction} message + * @param {Client} client + * + */ + async execute(message, client) { + + + } +} diff --git a/src/Events/Interaction/interactionCreate.js b/src/Events/Interaction/interactionCreate.js index eeb7b64..ef77f6e 100644 --- a/src/Events/Interaction/interactionCreate.js +++ b/src/Events/Interaction/interactionCreate.js @@ -29,7 +29,7 @@ module.exports = { try { if (interaction.customId !== 'remove') return - await interaction.deferReply({ ephemeral: false}) + await interaction.deferReply() const queue = client.distube.getQueue(interaction) const songId = interaction.values[0] queue.songs.splice(songId, 1) diff --git a/src/Events/Interaction/musicButtons.js b/src/Events/Interaction/musicButtons.js index 6692b35..d672dd8 100644 --- a/src/Events/Interaction/musicButtons.js +++ b/src/Events/Interaction/musicButtons.js @@ -2,6 +2,28 @@ const { ButtonInteraction, Client } = require("discord.js"); const { errorEmbed, musicEmbed } = require("../../util/Embeds"); const {musicButtonRow } = require("../../util/buttonLayout") +function generateProgressBar(currentTime, duration) { + + //make a ASCII progress bar |------🔴--------| + let progressBar = "|" + let progressBarLength = 25 + let progressBarMax = duration + let progressBarCurrent = currentTime + let progressBarPercent = (progressBarCurrent / progressBarMax) * 100 + let progressBarPercentRounded = Math.round(progressBarPercent/(100/progressBarLength)) + for (let i = 0; i < progressBarLength; i++) { + if (i < progressBarPercentRounded) { + progressBar = progressBar.concat("─") + } else if (i == progressBarPercentRounded) { + progressBar = progressBar.concat("⏸️") + } else { + progressBar = progressBar.concat("─") + } + } + progressBar = progressBar.concat("|") + return progressBar + +} module.exports = { @@ -25,31 +47,44 @@ module.exports = { const queue = client.distube.getQueue(interaction) if (!queue) return interaction.reply({ embeds: [errorEmbed().setDescription(`There is nothing in the queue right now !`)], ephemeral: true }) - + switch (customId) { //! Pause Button - + case "pause": { try{ + let playingSong = queue.songs[0] + if (queue.paused) { queue.resume() - return interaction.reply({ - embeds: [ - musicEmbed() - .setDescription(`${interaction.user} Resumed the song...`) - ], components: [musicButtonRow()] - }) + await interaction.message.edit({ embeds: [musicEmbed() + .setTitle(`Playing ${playingSong.name}`) + .setURL(`${playingSong.url}`) + .setThumbnail(`${playingSong.thumbnail}`) + .addField(`Requester`, `${playingSong.member}`, true) + .addField(`Author`, `[${playingSong.uploader.name}](${playingSong.uploader.url})`, true) + .addField(`Volume`, `${queue.volume}%`, true) + ], + components: [musicButtonRow()], + ephemeral: true }) + return interaction.deferUpdate() } - queue.pause() - interaction.reply({ - embeds: [ - musicEmbed() - .setDescription(`${interaction.user} Paused the song...`) - ], components: [musicButtonRow()] - }) + queue.pause() + await interaction.message.edit({ embeds: [musicEmbed() + .setTitle(`${interaction.user.username} paused ${playingSong.name}`) + .setURL(`${playingSong.url}`) + .setThumbnail(`${playingSong.thumbnail}`) + .setDescription(`${queue.formattedCurrentTime} **${generateProgressBar(queue.currentTime, playingSong.duration )}** ${playingSong.formattedDuration}`) + .addField(`Requester`, `${playingSong.member}`, true) + .addField(`Author`, `[${playingSong.uploader.name}](${playingSong.uploader.url})`, true) + .addField(`Volume`, `${queue.volume}%`, true) + ], + components: [musicButtonRow()], + ephemeral: true }) + interaction.deferUpdate() } catch (e) { interaction.reply({ embeds: [errorEmbed().setDescription(`${e}`)], ephemeral: true }) @@ -63,19 +98,20 @@ module.exports = { { let previousSong; - try {previousSong = queue.previousSongs[0]} catch (e) {console.log(e)} + try {previousSong = queue.previousSongs[queue.previousSongs.length-1]} catch (e) {console.log(e)} if (previousSong === undefined) return interaction.reply({ embeds: [errorEmbed().setDescription(`Nothing has been played previously in queue right now !`)], ephemeral: true }) try { queue.previous() - interaction.reply({ + interaction.message.edit({ embeds: [ musicEmbed() .setThumbnail(`${previousSong.thumbnail}`) .setDescription(` Song skipped by ${interaction.user}! Now playing:\n [${previousSong.name}](${previousSong.url})`) ],components: [musicButtonRow()]}) + interaction.deferUpdate() } catch (e) { interaction.reply({ embeds: [errorEmbed().setDescription(`${e}`)], ephemeral: true }) } @@ -91,11 +127,12 @@ module.exports = { mode = queue.setRepeatMode() mode = mode ? mode === 2 ? "Repeat queue" : "Repeat song" : "Off" - interaction.reply({ + interaction.message.edit({ embeds: [ musicEmbed() .setDescription(`🔁 | ${interaction.user} has set repeat mode to ${mode}`) ]}) + interaction.deferUpdate() } catch (e) { interaction.reply({ embeds: [errorEmbed().setDescription(`${e}`)], ephemeral: true }) } @@ -106,15 +143,14 @@ module.exports = { case "shuffle": { try { - - queue.shuffle() - interaction.reply({ + interaction.message.edit({ embeds: [ musicEmbed() .setDescription(`🔀 | ${interaction.user} Shuffled the queue !`) ],components: [musicButtonRow()]}) + interaction.deferUpdate() } catch (e) { interaction.reply({ embeds: [errorEmbed().setDescription(`${e}`)], ephemeral: true }) } @@ -130,13 +166,13 @@ module.exports = { if (nextSong === undefined) return interaction.reply({ embeds: [errorEmbed().setDescription(`There is nothing next in queue right now !`)], ephemeral: true }) - interaction.reply({ + interaction.message.edit({ embeds: [ musicEmbed() .setThumbnail(`${nextSong.thumbnail}`) .setDescription(` Song skipped by ${interaction.user}! Now playing:\n [${nextSong.name}](${nextSong.url})`) ],components: [musicButtonRow()]}) - + interaction.deferUpdate() queue.skip() diff --git a/src/Events/distube/distube.error.js b/src/Events/distube/distube.error.js new file mode 100644 index 0000000..fffaa4b --- /dev/null +++ b/src/Events/distube/distube.error.js @@ -0,0 +1,29 @@ +const { DisTube } = require("distube") +const { errorEmbed} = require("../../util/Embeds") + +module.exports = { + + name: 'error', + once: false, + + +/** + * @param {DisTube.Queue} queue + * @param {DisTube.Song} song + */ + async execute(channel, error) { + + try{ + console.log(`Error: ${error}, in channel: ${channel}`) + } catch (e) { + console.log(e) + } + + try{ + channel.guild.channels.cache.get((await config(newChannel.guild.id)).channel.logID).send({ embeds : [errorEmbed().setDescription(`${e}`)] }); + } catch (e) { + console.log(e); + } + + } +} diff --git a/src/Events/distube/distube.finishSong.js b/src/Events/distube/distube.finishSong.js new file mode 100644 index 0000000..e728f39 --- /dev/null +++ b/src/Events/distube/distube.finishSong.js @@ -0,0 +1,20 @@ +const { DisTube } = require("distube") + + +module.exports = { + + name: 'finishSong', + once: false, + + +/** + * @param {DisTube.Queue} queue + * @param {DisTube.Song} song + */ + async execute(queue,song) { + if (!queue) return console.log("Queue is not defined") + + console.log(`Finished \`${song.name}\` - \`${song.formattedDuration}\`\nRequested by: ${song.user}`) + + } +} diff --git a/src/Events/distube/distube.playSong.js b/src/Events/distube/distube.playSong.js new file mode 100644 index 0000000..7ab2685 --- /dev/null +++ b/src/Events/distube/distube.playSong.js @@ -0,0 +1,89 @@ +const { DisTube } = require("distube") +const { errorEmbed, musicEmbed} = require("../../util/Embeds") +const { musicButtonRow } = require("../../util/buttonLayout") +const config = require('../../config') + +function generateProgressBar(currentTime, duration) { + + //make a ASCII progress bar |------🔴--------| + let progressBar = "|" + let progressBarLength = 25 + let progressBarMax = duration + let progressBarCurrent = currentTime + let progressBarPercent = (progressBarCurrent / progressBarMax) * 100 + let progressBarPercentRounded = Math.round(progressBarPercent/(100/progressBarLength)) + for (let i = 0; i < progressBarLength; i++) { + if (i < progressBarPercentRounded) { + progressBar = progressBar.concat("─") + } else if (i == progressBarPercentRounded) { + progressBar = progressBar.concat("🔹") + } else { + progressBar = progressBar.concat("─") + } + } + progressBar = progressBar.concat("|") + return progressBar + +} + +module.exports = { + + name: 'playSong', + once: false, + + +/** + * @param {DisTube.Queue} queue + * @param {DisTube.Song} song + */ + async execute(queue,song) { + if (!queue) return console.log("Queue is not defined") + console.log(`Playing \`${song.name}\` - \`${song.formattedDuration}\`\nRequested by: ${song.user}`) + + const embed = musicEmbed() + .setTitle(`Playing ${song.name}`) + .setURL(`${song.url}`) + .setThumbnail(`${song.thumbnail}`) + .setDescription(`**${queue.formattedCurrentTime} ${generateProgressBar(queue.currentTime, song.duration )} ${song.formattedDuration}**`) + .addField(`Requester`, `${song.member}`, true) + .addField(`Author`, `[${song.uploader.name}](${song.uploader.url})`, true) + .addField(`Volume`, `${queue.volume}%`, true) + + try{ + musicChannel = await queue.voiceChannel.guild.channels.cache.get((await config(queue.voiceChannel.guild.id)).channel.MusicChannelID).send({ embeds : [embed], components: [musicButtonRow()], + ephemeral: false }) + } + catch(err){ + //console.log(err) + return console.log("Music channel is not defined") + } + + try{ + const ckeckPlayingSong = queue.songs[0] + var refreshMessage = setInterval(() => { + if (!queue) return console.log("nothing in the queue") + let playingSong = queue.songs[0] + if (!playingSong) { + console.log("wrong duration"); + return clearInterval(refreshMessage) + } + if (ckeckPlayingSong.name != playingSong.name) return clearInterval(refreshMessage) + //console.log(`${queue.formattedCurrentTime} **${generateProgressBar(queue.currentTime, playingSong.duration )}** ${playingSong.formattedDuration}`) + musicChannel.edit({ embeds: [musicEmbed() + .setTitle(`Playing ${playingSong.name}`) + .setURL(`${playingSong.url}`) + .setThumbnail(`${playingSong.thumbnail}`) + .setDescription(`**${queue.formattedCurrentTime} ${generateProgressBar(queue.currentTime, playingSong.duration )} ${playingSong.formattedDuration}**`) + .addField(`Requester`, `${playingSong.user}`, true) + .addField(`Author`, `[${playingSong.uploader.name}](${playingSong.uploader.url})`, true) + .addField(`Volume`, `${queue.volume}%`, true) + ], + components: [musicButtonRow()], + ephemeral: false }) + }, 3000) + } catch (err) { + console.log(err) + } + + } +} diff --git a/src/Events/log/MessageDelete.js b/src/Events/log/MessageDelete.js index 1abee7a..f61f156 100644 --- a/src/Events/log/MessageDelete.js +++ b/src/Events/log/MessageDelete.js @@ -10,7 +10,7 @@ module.exports = { async execute(message, client) { - if (message.author.bot || message.user.id === client.user.id) return; + if (message.author.bot || message.member.id === client.user.id) return; const { channel } = await config(message.guild.id) diff --git a/src/Events/log/MessageUpdate.js b/src/Events/log/MessageUpdate.js index ec67cae..d9554d2 100644 --- a/src/Events/log/MessageUpdate.js +++ b/src/Events/log/MessageUpdate.js @@ -13,7 +13,7 @@ module.exports = { - if (newMessage.author.bot || message.user.id === client.user.id) return; + if (newMessage.author.bot || newMessage.user.id === client.user.id) return; if (newMessage.channel.id === channel.logID) return; if (oldMessage.content === newMessage.content) return; diff --git a/src/Models/channels.js b/src/Models/channels.js index bcd46dd..afcea21 100644 --- a/src/Models/channels.js +++ b/src/Models/channels.js @@ -7,6 +7,7 @@ module.exports = model('Channels', new Schema({ ReportChannelID: String, WelcomeChannelID: String, ByeChannelID: String, + MusicChannelID: String, })) diff --git a/src/Models/my-pokedex.js b/src/Models/my-pokedex.js new file mode 100644 index 0000000..92fc0f6 --- /dev/null +++ b/src/Models/my-pokedex.js @@ -0,0 +1,17 @@ +const { Schema, model } = require('mongoose'); + +module.exports = model('MyPokedex', new Schema({ + + UserID: String, + UserTag: String, + + PokedexName: String, // ex: national + PokedexRegion: String, // ex: galar + PokedexGameVersion: String, // ex: sword-shield + PokedexGeneration: String, // ex: gen-7 + + PokemonCaught: Array, + PokemonNotYetCaught: Array, + + +})); \ No newline at end of file diff --git a/src/Structures/Events.js b/src/Structures/Events.js index 8257c14..5ac7c6b 100644 --- a/src/Structures/Events.js +++ b/src/Structures/Events.js @@ -23,9 +23,12 @@ module.exports = async (client) => { } try { - if (event.once) { + + if (file.includes("distube.")) { + client.distube.on(event.name, (...args) => event.execute(...args, client)); + } else if (event.once) { client.once(event.name, (...args) => event.execute(...args, client)); - } else { + } else { client.on(event.name, (...args) => event.execute(...args, client)); } } catch (e) { diff --git a/src/config.js b/src/config.js index 749a67c..bf418d4 100644 --- a/src/config.js +++ b/src/config.js @@ -6,7 +6,7 @@ const db = require('./Models/channels') module.exports = async (guildID) => { //fetch channel from database and store in global variable - let bienvenue, auRevoir, log, report + let bienvenue, auRevoir, log, report, music await db.findOne({ GuildID: guildID }, async (err, data) => { @@ -19,6 +19,7 @@ module.exports = async (guildID) => { auRevoir = (data.ByeChannelID) ? data.ByeChannelID : null log = (data.LogChannelID) ? data.LogChannelID : null report = (data.ReportChannelID) ? data.ReportChannelID : null + music = (data.MusicChannelID) ? data.MusicChannelID : null } @@ -28,20 +29,16 @@ module.exports = async (guildID) => { - console.log(bienvenue, auRevoir, log, report); + console.log(bienvenue, auRevoir, log, report, music); return { channel: { bienvenueID: bienvenue, - au_revoirID: auRevoir, - logID: log, - - reportID: report + reportID: report, + MusicChannelID: music }, } - } - diff --git a/src/util/EventNames.js b/src/util/EventNames.js index ad8555f..07d5b46 100644 --- a/src/util/EventNames.js +++ b/src/util/EventNames.js @@ -14,6 +14,7 @@ module.exports = { "error", "guildBanAdd", "guildBanRemove", + "playSong", "guildCreate", "guildDelete", "guildIntegrationsUpdate", diff --git a/src/util/pokemonNames.json b/src/util/pokemonNames.json index 92dafd3..e793207 100644 --- a/src/util/pokemonNames.json +++ b/src/util/pokemonNames.json @@ -101,7 +101,7 @@ "krabboss" : "kingler", "voltorbe" : "voltorb", "electrode" : "electrode", - "nœunœuf" : "exeggcute", + "noeunoeuf" : "exeggcute", "noadkoko" : "exeggutor", "osselait" : "cubone", "ossatueur" : "marowak", @@ -473,7 +473,7 @@ "givrali" : "glaceon", "scorvol" : "gliscor", "mammochon" : "mamoswine", - "z" : "porygon-z", + "porygon-z" : "porygon-z", "gallame" : "gallade", "tarinorme" : "probopass", "noctunoir" : "dusknoir",