diff --git a/assets/json/trainer-card.json b/assets/json/trainer-card.json new file mode 100644 index 00000000..5f5dd34d --- /dev/null +++ b/assets/json/trainer-card.json @@ -0,0 +1,23 @@ +{ + "styles": { + "default": 3 + }, + "characters": { + "ash": 13, + "red": 922, + "ethan": 900, + "lyra": 901, + "brendan": 241, + "may": 255, + "lucas": 747, + "dawn": 856 + }, + "badges": { + "kanto": [2, 3, 4, 5, 6, 7, 8, 9], + "johto": [10, 11, 12, 13, 14, 15, 16, 17], + "hoenn": [18, 19, 20, 21, 22, 23, 24, 25], + "sinnoh": [26, 27, 28, 29, 30, 31, 32, 33], + "unova": [34, 35, 36, 37, 38, 39, 40, 41], + "kalos": [44, 45, 46, 47, 48, 49, 50, 51] + } +} diff --git a/commands/edit-image/trainer-card.js b/commands/edit-image/trainer-card.js new file mode 100644 index 00000000..2e41bdf7 --- /dev/null +++ b/commands/edit-image/trainer-card.js @@ -0,0 +1,126 @@ +const Command = require('../../structures/Command'); +const request = require('node-superfetch'); +const cheerio = require('cheerio'); +const { stripIndents } = require('common-tags'); +const { list } = require('../../util/Util'); +const { styles, characters, badges } = require('../../assets/json/trainer-card'); + +module.exports = class TrainerCardCommand extends Command { + constructor(client) { + super(client, { + name: 'trainer-card', + aliases: [ + 'pkmn-trainer', + 'pokemon-trainer', + 'pokémon-trainer', + 'pkmn-trainer-card', + 'pokemon-trainer-card', + 'pokémon-trainer-card', + 'pkmn-tc', + 'pokemon-tc', + 'pokémon-tc', + 'ptc' + ], + group: 'edit-image', + memberName: 'trainer-card', + description: 'Creates a trainer card for a Pokémon trainer.', + details: stripIndents` + **Styles:** ${Object.keys(styles).join(', ')} + **Characters:** ${Object.keys(characters).join(', ')} + **Badges:** ${Object.keys(badges).join(', ')} + `, + credit: [ + { + name: 'Pokémon', + url: 'https://www.pokemon.com/us/', + reason: 'Images, Original Game' + }, + { + name: 'PokéAPI', + url: 'https://pokeapi.co/', + reason: 'API' + }, + { + name: 'Pokécharms', + url: 'https://pokecharms.com/', + reason: 'Trainer Card API', + reasonURL: 'https://pokecharms.com/trainer-card-maker/' + } + ], + args: [ + { + key: 'style', + prompt: `What style do you want to use? Either ${list(Object.keys(styles), 'or')}.`, + type: 'string', + oneOf: Object.keys(styles), + parse: style => styles[style.toLowerCase()] + }, + { + key: 'name', + prompt: 'What name do you want to use?', + type: 'string', + max: 12 + }, + { + key: 'character', + prompt: `What character do you want to use? Either ${list(Object.keys(characters, 'or'))}.`, + type: 'string', + oneOf: Object.keys(characters), + parse: character => characters[character.toLowerCase()] + }, + { + key: 'badgeChoice', + label: 'badges', + prompt: `What badges do you want to use? Either ${list(Object.keys(badges), 'or')}.`, + type: 'string', + oneOf: Object.keys(badges), + parse: choice => badges[choice.toLowerCase()] + }, + { + key: 'pokemon', + label: 'Pokémon', + prompt: 'What Pokémon do you want to use? Please enter up to 6 (in seperate messages).', + type: 'pokemon', + infinite: true + } + ] + }); + } + + async run(msg, { style, name, character, badgeChoice, pokemon }) { + try { + const pokemonUsed = []; + for (const pkmn of pokemon) { + const id = await this.fetchPokemonID(pkmn.id); + pokemonUsed.push(id); + } + const card = await this.createCard(style, name, character, badgeChoice, pokemonUsed); + return msg.say({ files: [{ attachment: card, name: 'trainer-card.png' }] }); + } catch (err) { + return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); + } + } + + async createCard(style, name, character, badgeChoice, pokemon) { + const { body } = await request + .post('https://pokecharms.com/index.php?trainer-card-maker/render') + .attach('trainername', name) + .attach('background', style) + .attach('character', character) + .attach('badges', 8) + .attach('badgesUsed', badgeChoice) + .attach('pokemon', pokemon.length) + .attach('pokemonUsed', pokemon) + .attach('_xfResponseType', 'json'); + return Buffer.from(body.trainerCard, 'base64'); + } + + async fetchPokemonID(pokemon) { + const { body } = await request + .post('https://pokecharms.com/trainer-card-maker/pokemon-panels') + .attach('number', pokemon.id) + .attach('_xfResponseType', 'json'); + const $ = cheerio.load(body.templateHtml); + return $('li[class="Panel"]').first().attr('data-id'); + } +}; diff --git a/commands/pokedex/pokedex-cry.js b/commands/pokedex/pokedex-cry.js index 4f7be4ba..3c90edc2 100644 --- a/commands/pokedex/pokedex-cry.js +++ b/commands/pokedex/pokedex-cry.js @@ -49,7 +49,7 @@ module.exports = class PokedexCryCommand extends Command { { key: 'pokemon', prompt: 'What Pokémon would you like to play the cry of?', - type: 'string' + type: 'pokemon' } ] }); @@ -62,9 +62,7 @@ module.exports = class PokedexCryCommand extends Command { return msg.reply(`I am not in a voice channel. Use ${usage} to fix that!`); } try { - const data = await this.client.pokemon.fetch(pokemon); - if (!data) return msg.say('Could not find any results.'); - connection.play(data.cry); + connection.play(pokemon.cry); await reactIfAble(msg, this.client.user, '🔉'); return null; } catch (err) { diff --git a/commands/pokedex/pokedex-image.js b/commands/pokedex/pokedex-image.js index 8b3dabac..6372f0a2 100644 --- a/commands/pokedex/pokedex-image.js +++ b/commands/pokedex/pokedex-image.js @@ -40,7 +40,7 @@ module.exports = class PokedexImageCommand extends Command { { key: 'pokemon', prompt: 'What Pokémon would you like to get the image of?', - type: 'string' + type: 'pokemon' } ] }); @@ -48,9 +48,7 @@ module.exports = class PokedexImageCommand extends Command { async run(msg, { pokemon }) { try { - const data = await this.client.pokemon.fetch(pokemon); - if (!data) return msg.say('Could not find any results.'); - return msg.say(`#${data.displayID} - ${data.name}`, { files: [data.spriteImageURL] }); + return msg.say(`#${pokemon.displayID} - ${pokemon.name}`, { files: [pokemon.spriteImageURL] }); } catch (err) { return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); } diff --git a/commands/pokedex/pokedex-location.js b/commands/pokedex/pokedex-location.js index a7a81623..39b2b286 100644 --- a/commands/pokedex/pokedex-location.js +++ b/commands/pokedex/pokedex-location.js @@ -42,7 +42,7 @@ module.exports = class PokedexLocationCommand extends Command { { key: 'pokemon', prompt: 'What Pokémon would you like to get information on?', - type: 'string' + type: 'pokemon' } ] }); @@ -50,20 +50,18 @@ module.exports = class PokedexLocationCommand extends Command { async run(msg, { pokemon }) { try { - const data = await this.client.pokemon.fetch(pokemon); - if (!data) return msg.say('Could not find any results.'); - if (!data.gameDataCached) await data.fetchGameData(); - if (!data.encounters) await data.fetchEncounters(); - const desc = data.encounters.length - ? data.encounters + if (!pokemon.gameDataCached) await pokemon.fetchGameData(); + if (!pokemon.encounters) await pokemon.fetchEncounters(); + const desc = pokemon.encounters.length + ? pokemon.encounters .map(location => `${location.name} (${location.versions.map(v => versions[v]).join('/')})`) .join('\n') : 'Location Unknown'; const embed = new MessageEmbed() .setColor(0xED1C24) - .setAuthor(`#${data.displayID} - ${data.name}`, data.boxImageURL, data.serebiiURL) + .setAuthor(`#${pokemon.displayID} - ${pokemon.name}`, pokemon.boxImageURL, pokemon.serebiiURL) .setDescription(desc) - .setThumbnail(data.spriteImageURL); + .setThumbnail(pokemon.spriteImageURL); return msg.embed(embed); } catch (err) { return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); diff --git a/commands/pokedex/pokedex-moveset.js b/commands/pokedex/pokedex-moveset.js index f06018e1..5cc1d1fb 100644 --- a/commands/pokedex/pokedex-moveset.js +++ b/commands/pokedex/pokedex-moveset.js @@ -46,7 +46,7 @@ module.exports = class PokedexMovesetCommand extends Command { { key: 'pokemon', prompt: 'What Pokémon would you like to get information on?', - type: 'string' + type: 'pokemon' } ] }); @@ -54,16 +54,14 @@ module.exports = class PokedexMovesetCommand extends Command { async run(msg, { pokemon }) { try { - const data = await this.client.pokemon.fetch(pokemon); - if (!data) return msg.say('Could not find any results.'); - if (!data.gameDataCached) await data.fetchGameData(); - if (!data.moveSet.length) return msg.say('This Pokémon\'s moves are not yet documented.'); + if (!pokemon.gameDataCached) await pokemon.fetchGameData(); + if (!pokemon.moveSet.length) return msg.say('This Pokémon\'s moves are not yet documented.'); const embed = new MessageEmbed() .setColor(0xED1C24) - .setAuthor(`#${data.displayID} - ${data.name}`, data.boxImageURL, data.serebiiURL) - .setDescription(data.moveSet.map(move => `**Level ${move.level}:** ${move.move.name}`).join('\n')) - .setThumbnail(data.spriteImageURL) - .setFooter(`Moveset data taken from ${versions[data.moveSetVersion]}.`); + .setAuthor(`#${pokemon.displayID} - ${pokemon.name}`, pokemon.boxImageURL, pokemon.serebiiURL) + .setDescription(pokemon.moveSet.map(move => `**Level ${move.level}:** ${move.move.name}`).join('\n')) + .setThumbnail(pokemon.spriteImageURL) + .setFooter(`Moveset data taken from ${versions[pokemon.moveSetVersion]}.`); return msg.embed(embed); } catch (err) { return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); diff --git a/commands/pokedex/pokedex-stats.js b/commands/pokedex/pokedex-stats.js index 852adbfa..56a671b4 100644 --- a/commands/pokedex/pokedex-stats.js +++ b/commands/pokedex/pokedex-stats.js @@ -33,7 +33,7 @@ module.exports = class PokedexCommand extends Command { { key: 'pokemon', prompt: 'What Pokémon would you like to get information on?', - type: 'string' + type: 'pokemon' }, { key: 'form', @@ -51,10 +51,8 @@ module.exports = class PokedexCommand extends Command { async run(msg, { pokemon, form }) { try { - const data = await this.client.pokemon.fetch(pokemon); - if (!data) return msg.say('Could not find any results.'); - if (!data.gameDataCached) await data.fetchGameData(); - const displayForms = data.varieties.filter(vrity => vrity.statsDiffer); + if (!pokemon.gameDataCached) await pokemon.fetchGameData(); + const displayForms = pokemon.varieties.filter(vrity => vrity.statsDiffer); const variety = displayForms.find(vrity => { if (!form || form === 'normal') return vrity.default; if (!vrity.name) return false; @@ -64,7 +62,7 @@ module.exports = class PokedexCommand extends Command { const varieties = displayForms.map(vrity => vrity.name || 'Normal'); return msg.say(`Invalid form. The forms available for this Pokémon are: ${list(varieties, 'and')}`); } - const statTotal = data.baseStatTotal(variety.id); + const statTotal = pokemon.baseStatTotal(variety.id); const repeat = { hp: Math.round((variety.stats.hp / 255) * 10) * 2, atk: Math.round((variety.stats.atk / 255) * 10) * 2, @@ -76,8 +74,12 @@ module.exports = class PokedexCommand extends Command { }; const embed = new MessageEmbed() .setColor(0xED1C24) - .setAuthor(`#${data.displayID} - ${data.name}`, data.formBoxImageURL(variety.id), data.serebiiURL) - .setThumbnail(data.formSpriteImageURL(variety.id)) + .setAuthor( + `#${pokemon.displayID} - ${pokemon.name}`, + pokemon.formBoxImageURL(variety.id), + pokemon.serebiiURL + ) + .setThumbnail(pokemon.formSpriteImageURL(variety.id)) .addField(`❯ Base Stats (${variety.name || 'Base'} Form)`, stripIndents` \`HP: [${'█'.repeat(repeat.hp)}${' '.repeat(20 - repeat.hp)}]\` **${variety.stats.hp}** \`Attack: [${'█'.repeat(repeat.atk)}${' '.repeat(20 - repeat.atk)}]\` **${variety.stats.atk}** @@ -90,7 +92,7 @@ module.exports = class PokedexCommand extends Command { `) .addField('❯ Abilities', variety.abilities.map(ability => ability.name).join('/')) .addField('❯ Other Forms', stripIndents` - _Use ${this.usage(`${data.id}