Skip to content

Commit

Permalink
Merge pull request #846 from Glazelf/whos-that-pokemon
Browse files Browse the repository at this point in the history
Who's That Pokémon?
  • Loading branch information
Glazelf authored May 14, 2024
2 parents 4b1e535 + 482153b commit ef897e0
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 56 deletions.
41 changes: 35 additions & 6 deletions commands/api/pokemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ exports.run = async (client, interaction, logger, ephemeral = true) => {
const sendMessage = require('../../util/sendMessage');
const { Dex } = require('pokemon-showdown');
const getPokemon = require('../../util/pokemon/getPokemon');
const getWhosThatPokemon = require('../../util/pokemon/getWhosThatPokemon');
const getTypeEmotes = require('../../util/pokemon/getTypeEmotes');
const capitalizeString = require('../../util/capitalizeString');
const leadingZeros = require('../../util/leadingZeros');
const getRandomObjectItem = require('../../util/getRandomObjectItem');
const learnsets = require('../../node_modules/pokemon-showdown/dist/data/learnsets.js').Learnsets;
const checkBaseSpeciesMoves = require('../../util/pokemon/checkBaseSpeciesMoves');
const isAdmin = require('../../util/isAdmin');
Expand All @@ -31,6 +33,8 @@ exports.run = async (client, interaction, logger, ephemeral = true) => {
.setColor(client.globalVars.embedColor);
let pokemonName = interaction.options.getString("pokemon");
let pokemonButtons = new Discord.ActionRowBuilder();
let returnString = "";
let pokemonFiles = null;
let nameBulbapedia = null;
let linkBulbapedia = null;
// Set generation
Expand All @@ -41,10 +45,7 @@ exports.run = async (client, interaction, logger, ephemeral = true) => {
// Used for pokemon and learn
let noPokemonString = `Sorry, I could not find a Pokémon by that name in generation ${generationInput}.`;
let pokemon = dexModified.species.get(pokemonName);
if (pokemonName && pokemonName.toLowerCase() == "random") {
let allKeys = Object.keys(allPokemon);
pokemon = allPokemon[allKeys[allKeys.length * Math.random() << 0]];
};
if (pokemonName && pokemonName.toLowerCase() == "random") pokemon = getRandomObjectItem(allPokemon);
// Used for move and learn
let moveSearch = interaction.options.getString("move");
let move = dexModified.moves.get(moveSearch);
Expand Down Expand Up @@ -224,7 +225,8 @@ exports.run = async (client, interaction, logger, ephemeral = true) => {
case "pokemon":
if (!pokemon || !pokemon.exists || pokemon.num <= 0) return sendMessage({ client: client, interaction: interaction, content: noPokemonString });
let messageObject = await getPokemon({ client: client, interaction: interaction, pokemon: pokemon, learnsetBool: learnsetBool, shinyBool: shinyBool, generation: generationInput, ephemeral: ephemeral });
return sendMessage({ client: client, interaction: interaction, embeds: messageObject.embeds, components: messageObject.components, ephemeral: ephemeral });
pokemonEmbed = messageObject.embeds;
pokemonButtons = messageObject.components;
break;
case "learn":
if (!pokemon || !pokemon.exists || pokemon.num <= 0) return sendMessage({ client: client, interaction: interaction, content: noPokemonString });
Expand Down Expand Up @@ -364,10 +366,28 @@ exports.run = async (client, interaction, logger, ephemeral = true) => {
]);
};
break;
case "whosthat":
pokemonEmbed = null;
await interaction.deferReply({ ephemeral: ephemeral });
allPokemon = allPokemon.filter(pokemon =>
pokemon.num > 0 &&
!["CAP"].includes(pokemon.isNonstandard) &&
!pokemon.name.endsWith("-Totem") &&
!pokemon.name.startsWith("Arceus-") &&
!pokemon.name.startsWith("Silvally-") &&
!pokemon.name.startsWith("Gourgeist-") &&
!pokemon.name.startsWith("Pumpkaboo-") &&
!["Flapple-Gmax", "Appletun-Gmax", "Toxtricity-Gmax", "Toxtricity-Low-Key-Gmax"].includes(pokemon.name)
);
let whosThatPokemonMessageObject = await getWhosThatPokemon({ client: client, pokemonList: allPokemon });
returnString = whosThatPokemonMessageObject.content;
pokemonFiles = whosThatPokemonMessageObject.files;
pokemonButtons = whosThatPokemonMessageObject.components;
break;
};
// Bulbapedia button
if (linkBulbapedia) pokemonButtons.addComponents(new Discord.ButtonBuilder({ label: 'More info', style: Discord.ButtonStyle.Link, url: linkBulbapedia }));
return sendMessage({ client: client, interaction: interaction, embeds: pokemonEmbed, components: pokemonButtons, ephemeral: ephemeral });
return sendMessage({ client: client, interaction: interaction, content: returnString, embeds: pokemonEmbed, components: pokemonButtons, files: pokemonFiles, ephemeral: ephemeral });

function getLearnData(learnData) {
let learnInfo = "";
Expand Down Expand Up @@ -590,5 +610,14 @@ module.exports.config = {
type: Discord.ApplicationCommandOptionType.Boolean,
description: "Whether the reply will be private."
}]
}, {
name: "whosthat",
type: Discord.ApplicationCommandOptionType.Subcommand,
description: "Who's that Pokémon?",
options: [{
name: "ephemeral",
type: Discord.ApplicationCommandOptionType.Boolean,
description: "Whether the reply will be private."
}]
}]
};
68 changes: 56 additions & 12 deletions events/interactionCreate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,25 @@ module.exports = async (client, interaction) => {
const getMonster = require('../util/mh/getMonster');
const randomNumber = require('../util/randomNumber');
const capitalizeString = require('../util/capitalizeString');
const getWhosThatPokemon = require('../util/pokemon/getWhosThatPokemon');
const { Dex } = require('pokemon-showdown');
const axios = require("axios");
const fs = require("fs");
const monstersJSON = require("../submodules/monster-hunter-DB/monsters.json");
const questsJSON = require("../submodules/monster-hunter-DB/quests.json");

const { EligibleRoles } = require('../database/dbServices/server.api');
const api_trophy = require('../database/dbServices/trophy.api');
const api_user = require('../database/dbServices/user.api');

if (!interaction) return;
if (interaction.user.bot) return;
// ID split
let customIdSplit = null;
if (interaction.customId) customIdSplit = interaction.customId.split("|");
// Shinx battle state
let inCommandInteractions = ["battleYes", "battleNo"]; // Interactions that are handled in the command file
if (inCommandInteractions.includes(interaction.customId)) return;
// Common variables
let pkmQuizModalId = 'pkmQuizModal';
switch (interaction.type) {
case Discord.InteractionType.ApplicationCommand:
if (!interaction.member) return sendMessage({ client: client, interaction: interaction, content: `Sorry, you're not allowed to use commands in private messages!\nThis is because a lot of the responses require a server to be present.\nDon't worry, similar to this message, most of my replies will be invisible to other server members!` });
Expand Down Expand Up @@ -54,16 +59,40 @@ module.exports = async (client, interaction) => {
case Discord.ComponentType.Button:
let messageObject = null;
if (!interaction.customId) return;
if (interaction.user.id !== interaction.message.interaction.user.id) return sendMessage({ client: client, interaction: interaction, content: `Only ${interaction.message.interaction.user} can use this button as the original interaction was used by them!`, ephemeral: true });
if (interaction.customId.startsWith("pkm")) {
let pkmQuizGuessButtonIdStart = "pkmQuizGuess";
if (interaction.user.id !== interaction.message.interaction.user.id &&
!interaction.customId.startsWith(pkmQuizGuessButtonIdStart)
) return sendMessage({ client: client, interaction: interaction, content: `Only ${interaction.message.interaction.user} can use this button as the original interaction was used by them!`, ephemeral: true });
let pkmQuizModalGuessId = `pkmQuizModalGuess|${customIdSplit[1]}`;
if (interaction.customId.startsWith("pkmQuizReveal")) {
// Response in case of forfeit/reveal
let pkmQuizRevealCorrectAnswer = interaction.message.components[0].components[0].customId.split("|")[1];
let pkmQuizRevealMessageObject = await getWhosThatPokemon({ client: client, pokemon: pkmQuizRevealCorrectAnswer, winner: interaction.user, reveal: true });
return interaction.update({ content: pkmQuizRevealMessageObject.content, files: pkmQuizRevealMessageObject.files, embeds: pkmQuizRevealMessageObject.embeds, components: [] });
} else if (interaction.customId.startsWith(pkmQuizGuessButtonIdStart)) {
// Who's That Pokémon? modal
const pkmQuizModal = new Discord.ModalBuilder()
.setCustomId(pkmQuizModalId)
.setTitle("Who's That Pokémon?");
const pkmQuizModalGuessInput = new Discord.TextInputBuilder()
.setCustomId(pkmQuizModalGuessId)
.setLabel("Put in your guess!")
.setPlaceholder("Pikachu")
.setStyle(Discord.TextInputStyle.Short)
.setMaxLength(64)
.setRequired(true);
const pkmQuizActionRow = new Discord.ActionRowBuilder().addComponents(pkmQuizModalGuessInput);
pkmQuizModal.addComponents(pkmQuizActionRow);
return interaction.showModal(pkmQuizModal);
} else if (interaction.customId.startsWith("pkm")) {
// Pokémon command
let newPokemonName = null;
for (let componentRow of interaction.message.components) {
if (newPokemonName) break;
newPokemonName = componentRow.components.find(component => component.customId == interaction.customId);
};
if (!newPokemonName) return;
let customIdSplit = interaction.customId.split("|")

let learnsetBool = (customIdSplit[1] == "true");
let shinyBool = (customIdSplit[2] == "true");
let generationButton = customIdSplit[3];
Expand Down Expand Up @@ -93,10 +122,10 @@ module.exports = async (client, interaction) => {
} else if (interaction.customId.startsWith("mhquests")) {
// Monster Hunter quests
const getQuests = require('../util/mh/getQuests');
let mhQuestsDirection = interaction.customId.split("|")[1];
let mhQuestsGameName = interaction.customId.split("|")[2];
let mhQuestsPage = interaction.customId.split("|")[3];
let mhQuestsPagesTotal = interaction.customId.split("|")[4];
let mhQuestsDirection = customIdSplit[1];
let mhQuestsGameName = interaction.customId.split("|");[2];
let mhQuestsPage = interaction.customId.split("|");[3];
let mhQuestsPagesTotal = interaction.customId.split("|");[4];
switch (mhQuestsDirection) {
case "left":
mhQuestsPage = parseInt(mhQuestsPage) - 1;
Expand All @@ -118,9 +147,9 @@ module.exports = async (client, interaction) => {
} else if (interaction.customId.startsWith("splatfest")) {
// Splatfest
const getSplatfests = require('../util/splat/getSplatfests');
let splatfestDirection = interaction.customId.split("|")[1];
let splatfestPage = interaction.customId.split("|")[2];
let splatfestRegion = interaction.customId.split("|")[3];
let splatfestDirection = interaction.customId.split("|");[1];
let splatfestPage = interaction.customId.split("|");[2];
let splatfestRegion = interaction.customId.split("|");[3];
switch (splatfestDirection) {
case "left":
splatfestPage = parseInt(splatfestPage) + 1;
Expand Down Expand Up @@ -618,6 +647,21 @@ module.exports = async (client, interaction) => {
await interaction.guild.publicUpdatesChannel.send({ embeds: [modMailEmbed], components: [profileButtons] });
return sendMessage({ client: client, interaction: interaction, content: `Your message has been sent to the mods!\nModerators should get back to you as soon as soon as possible.` });
break;
case pkmQuizModalId:
let pkmQuizGuessResultEphemeral = false;
if (interaction.message.flags.has("Ephemeral")) pkmQuizGuessResultEphemeral = true;
// Who's That Pokémon? modal response
let pkmQuizButtonID = Array.from(interaction.fields.fields.keys())[0];
let pkmQuizCorrectAnswer = pkmQuizButtonID.split("|")[1];
const pkmQuizModalGuess = interaction.fields.getTextInputValue(pkmQuizButtonID);

if (pkmQuizModalGuess.toLowerCase() == pkmQuizCorrectAnswer.toLowerCase()) {
let pkmQuizMessageObject = await getWhosThatPokemon({ client: client, pokemon: pkmQuizCorrectAnswer, winner: interaction.user });
interaction.update({ content: pkmQuizMessageObject.content, files: pkmQuizMessageObject.files, components: [] });
} else {
return sendMessage({ client: client, interaction: interaction, content: `${interaction.user} guessed incorrectly: \`${pkmQuizModalGuess}\`.`, ephemeral: pkmQuizGuessResultEphemeral });
};
break;
};
return;
default:
Expand Down
4 changes: 4 additions & 0 deletions util/getRandomObjectItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = (objectList) => {
let listKeys = Object.keys(objectList);
return objectList[listKeys[listKeys.length * Math.random() << 0]];
};
41 changes: 41 additions & 0 deletions util/pokemon/getCleanPokemonID.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module.exports = (pokemon) => {
let pokemonID = pokemon.num.toString();
let pokemonName = pokemon.name;
let pokemonTypes = pokemon.types;
const leadingZeros = require('../leadingZeros');
const correctionID = require('../../objects/pokemon/correctionID.json');
// Turn this number into 4 when Showdown and Serebii switch to 4 digit IDs consistently. This approach doesn't change 4-digit IDs.
pokemonID = leadingZeros(pokemonID, 3);
// Forms
const primalString = "-Primal";
const totemString = "-Totem";
const gmaxString = "-Gmax";
const eternamaxString = "-Eternamax";
const primalBool = pokemonName.endsWith(primalString);
const totemBool = pokemonName.endsWith(totemString);
const gmaxBool = pokemonName.endsWith(gmaxString);
const eternamaxBool = pokemonName.endsWith(eternamaxString);
const dynamaxBool = Boolean(gmaxBool || eternamaxBool);
const totemAlolaBool = totemBool && pokemonName.split("-")[1] == "Alola";
let formChar;

if (primalBool || gmaxBool) {
if (primalBool) formChar = "-m";
if (gmaxBool) formChar = "-gi";
pokemonID = `${pokemonID}${formChar}`;
} else if (!totemBool || totemAlolaBool) {
// Catches all forms where the form extension on Serebii is just the first letter of the form name
if (pokemonName.split("-")[1]) pokemonID = `${pokemonID}-${pokemonName.split("-")[1].split("", 1)[0].toLowerCase()}`;
};
// Edgecase ID corrections
// TODO: add a bunch of meaningless forms like Unown and Vivillon
pokemonID = correctValue(correctionID, pokemonName, pokemonID);
if (pokemonName.startsWith("Arceus-") || pokemonName.startsWith("Silvally-")) pokemonID = `${pokemonID.split("-")[0]}-${pokemonTypes[0].toLowerCase()}`;
return pokemonID;

function correctValue(object, key, input) {
key = key.toLowerCase();
if (object[key]) return object[key];
return input;
};
};
Loading

0 comments on commit ef897e0

Please sign in to comment.