diff --git a/Xiao.js b/Xiao.js index 50003c74..0263fbad 100644 --- a/Xiao.js +++ b/Xiao.js @@ -1,8 +1,8 @@ require('dotenv').config(); const { XIAO_TOKEN, OWNERS, XIAO_PREFIX, INVITE } = process.env; const path = require('path'); -const { CommandoClient } = require('discord.js-commando'); -const client = new CommandoClient({ +const Client = require('./structures/Client'); +const client = new Client({ commandPrefix: XIAO_PREFIX, owner: OWNERS.split(','), invite: INVITE, diff --git a/commands/games/whos-that-pokemon.js b/commands/games/whos-that-pokemon.js index 2253726f..5c4f9d88 100644 --- a/commands/games/whos-that-pokemon.js +++ b/commands/games/whos-that-pokemon.js @@ -25,49 +25,36 @@ module.exports = class WhosThatPokemonCommand extends Command { } ] }); - - this.cache = new Map(); } async run(msg, { hide }) { const pokemon = Math.floor(Math.random() * 802) + 1; try { - const data = await this.fetchPokemon(pokemon); + const data = await this.client.pokemon.fetch(pokemon.toString()); const names = data.names.map(name => name.name.toLowerCase()); - const displayName = data.names.filter(name => name.language.name === 'en')[0].name; - const id = data.id.toString().padStart(3, '0'); - const attachment = await this.fetchImage(id, hide); - await msg.reply('**You have 15 seconds, who\'s that Pokémon?**', { files: [{ attachment, name: `${id}.png` }] }); + const attachment = await this.fetchImage(data, hide); + await msg.reply('**You have 15 seconds, who\'s that Pokémon?**', { files: [attachment] }); const msgs = await msg.channel.awaitMessages(res => res.author.id === msg.author.id, { max: 1, time: 15000 }); - if (!msgs.size) return msg.reply(`Sorry, time is up! It was ${displayName}.`); - if (!names.includes(msgs.first().content.toLowerCase())) return msg.reply(`Nope, sorry, it's ${displayName}.`); + if (!msgs.size) return msg.reply(`Sorry, time is up! It was ${data.name}.`); + if (!names.includes(msgs.first().content.toLowerCase())) return msg.reply(`Nope, sorry, it's ${data.name}.`); return msg.reply('Nice job! 10/10! You deserve some cake!'); } catch (err) { return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); } } - async fetchPokemon(pokemon) { - if (this.cache.has(pokemon)) return this.cache.get(pokemon); - const { body } = await request.get(`https://pokeapi.co/api/v2/pokemon-species/${pokemon}/`); - this.cache.set(body.id, { - id: body.id, - names: body.names - }); - return body; - } - - async fetchImage(id, hide = false) { - const image = await request.get(`https://www.serebii.net/sunmoon/pokemon/${id}.png`); - if (!hide) return image.body; + async fetchImage(pokemon, hide = false) { + const name = `${pokemon.id}.png`; + const image = await request.get(pokemon.spriteImageURL); + if (!hide) return { attachment: image.body, name }; const base = await loadImage(image.body); const canvas = createCanvas(base.width, base.height); const ctx = canvas.getContext('2d'); ctx.drawImage(base, 0, 0); silhouette(ctx, 0, 0, base.width, base.height); - return canvas.toBuffer(); + return { attachment: canvas.toBuffer(), name }; } }; diff --git a/commands/search/pokedex.js b/commands/search/pokedex.js index 7bec37d5..ce1896df 100644 --- a/commands/search/pokedex.js +++ b/commands/search/pokedex.js @@ -1,6 +1,5 @@ const Command = require('../../structures/Command'); -const { Collection, MessageEmbed } = require('discord.js'); -const request = require('node-superfetch'); +const { MessageEmbed } = require('discord.js'); const { stripIndents } = require('common-tags'); module.exports = class PokedexCommand extends Command { @@ -16,64 +15,27 @@ module.exports = class PokedexCommand extends Command { { key: 'pokemon', prompt: 'What Pokémon would you like to get information on?', - type: 'string', - parse: pokemon => this.makeSlug(pokemon) + type: 'string' } ] }); - - this.cache = new Collection(); } async run(msg, { pokemon }) { try { - const data = await this.fetchPokemon(pokemon); + const data = await this.client.pokemon.fetch(pokemon); const embed = new MessageEmbed() .setColor(0xED1C24) - .setAuthor( - `#${data.displayID} - ${data.name}`, - `https://www.serebii.net/pokedex-sm/icon/${data.displayID}.png`, - `https://www.serebii.net/pokedex-sm/${data.displayID}.shtml` - ) + .setAuthor(`#${data.displayID} - ${data.name}`, data.boxImageURL, data.serebiiURL) .setDescription(stripIndents` - **The ${data.genus}** + **${data.genus}** ${data.entries[Math.floor(Math.random() * data.entries.length)]} `) - .setThumbnail(`https://www.serebii.net/sunmoon/pokemon/${data.displayID}.png`); + .setThumbnail(data.spriteImageURL); return msg.embed(embed); } catch (err) { if (err.status === 404) return msg.say('Could not find any results.'); return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); } } - - async fetchPokemon(query) { - const num = Number.parseInt(query, 10); - if (this.cache.has(num)) return this.cache.get(num); - const found = this.cache.find(pokemon => pokemon.slug === query); - if (found) return found; - const { body } = await request.get(`https://pokeapi.co/api/v2/pokemon-species/${query}/`); - const entries = body.flavor_text_entries - .filter(entry => entry.language.name === 'en') - .map(entry => entry.flavor_text.replace(/\n|\f|\r/g, ' ')); - const { name } = this.filterPokemonData(body.names); - this.cache.set(body.id, { - id: body.id, - displayID: body.id.toString().padStart(3, '0'), - name, - slug: this.makeSlug(name), - genus: this.filterPokemonData(body.genera).genus, - entries - }); - return this.cache.get(body.id); - } - - filterPokemonData(arr) { - const filtered = arr.filter(entry => entry.language.name === 'en'); - return filtered[0]; - } - - makeSlug(name) { - return encodeURIComponent(name.toLowerCase().replace(/ /g, '-').replace(/[^a-zA-Z0-9-]/g, '')); - } }; diff --git a/structures/Client.js b/structures/Client.js new file mode 100644 index 00000000..a2839509 --- /dev/null +++ b/structures/Client.js @@ -0,0 +1,10 @@ +const { CommandoClient } = require('discord.js-commando'); +const PokemonStore = require('./PokemonStore'); + +module.exports = class XiaoClient extends CommandoClient { + constructor(options) { + super(options); + + this.pokemon = new PokemonStore(); + } +}; diff --git a/structures/Pokemon.js b/structures/Pokemon.js new file mode 100644 index 00000000..2ccf9865 --- /dev/null +++ b/structures/Pokemon.js @@ -0,0 +1,31 @@ +module.exports = class Pokemon { + constructor(data) { + this.id = data.id; + this.name = data.names.filter(entry => entry.language.name === 'en')[0].name; + this.entries = data.flavor_text_entries + .filter(entry => entry.language.name === 'en') + .map(entry => entry.flavor_text.replace(/\n|\f|\r/g, ' ')); + this.names = data.names; + this.genus = `The ${data.genera.filter(entry => entry.language.name === 'en')[0].genus}`; + } + + get displayID() { + return this.id.toString().padStart(3, '0'); + } + + get slug() { + return encodeURIComponent(this.name.toLowerCase().replace(/ /g, '-').replace(/[^a-zA-Z0-9-]/g, '')); + } + + get spriteImageURL() { + return `https://www.serebii.net/sunmoon/pokemon/${this.displayID}.png`; + } + + get boxImageURL() { + return `https://www.serebii.net/pokedex-sm/icon/${this.displayID}.png`; + } + + get serebiiURL() { + return `https://www.serebii.net/pokedex-sm/${this.displayID}.shtml`; + } +}; diff --git a/structures/PokemonStore.js b/structures/PokemonStore.js new file mode 100644 index 00000000..a613e56c --- /dev/null +++ b/structures/PokemonStore.js @@ -0,0 +1,21 @@ +const { Collection } = require('discord.js'); +const request = require('node-superfetch'); +const Pokemon = require('./Pokemon'); + +module.exports = class PokemonStore extends Collection { + constructor(iterable) { + super(iterable); + } + + async fetch(query) { + query = encodeURIComponent(query.toLowerCase().replace(/ /g, '-').replace(/[^a-zA-Z0-9-]/g, '')); + const num = Number.parseInt(query, 10); + if (this.has(num)) return this.get(num); + const found = this.find(pokemon => pokemon.slug === query); + if (found) return found; + const { body } = await request.get(`https://pokeapi.co/api/v2/pokemon-species/${query}/`); + const pokemon = new Pokemon(body); + this.set(pokemon.id, pokemon); + return pokemon; + } +};