From 5a721d7545538d4e5824c64bf3e65df299566fcf Mon Sep 17 00:00:00 2001 From: Pfych Date: Sat, 18 Sep 2021 15:21:19 +1000 Subject: [PATCH] Optional game param --- bot/src/profile/buildProfileEmbed.ts | 60 +++++++++++++++++----------- bot/src/profile/fetch.ts | 8 +++- bot/src/slashCommands/register.ts | 8 ++++ bot/src/utils/utils.ts | 23 +++++++++++ 4 files changed, 74 insertions(+), 25 deletions(-) diff --git a/bot/src/profile/buildProfileEmbed.ts b/bot/src/profile/buildProfileEmbed.ts index 1877aeac0..eacc4e7b6 100644 --- a/bot/src/profile/buildProfileEmbed.ts +++ b/bot/src/profile/buildProfileEmbed.ts @@ -45,32 +45,43 @@ export const fetchUserDetails = async (userId: number): Promise): Promise => { - const embed = new MessageEmbed().setColor("#cc527a"); + try { + logger.info(`Building profile embed${game ? `for ${formatGameWrapper(game)}` : ""}`); + const embed = new MessageEmbed().setColor("#cc527a"); - const userId = data[0].userID; - const userDetails = await fetchUserDetails(userId); - const pfp = userDetails.customPfp - ? getPfpUrl(userId) - : "https://cdn.mos.cms.futurecdn.net/mrArzwHcNuQbRwbEmuiwdJ.jpg"; - embed.setTitle(`${userDetails.username}'s Profile`); - embed.setThumbnail(pfp); - embed.setAuthor(`@${userDetails.username}`, pfp); + const userId = data[0].userID; + const userDetails = await fetchUserDetails(userId); + const pfp = userDetails.customPfp + ? getPfpUrl(userId) + : "https://cdn.mos.cms.futurecdn.net/mrArzwHcNuQbRwbEmuiwdJ.jpg"; + embed.setTitle(`${userDetails.username}'s Profile`); + embed.setThumbnail(pfp); + embed.setAuthor(`@${userDetails.username}`, pfp); - if (game) { - const specificData: UserGameStats | undefined = find( - data, - (item) => simpleGameTypeToString(game) === `${item.game}:${item.playtype}` - ); - if (specificData) { - embed.addField(`Stats for: ${formatGameWrapper(game)}`, `${pullRatings(specificData.ratings).join("\n")}`); + logger.info(`Embed is for ${userDetails.username}`); + + if (game) { + const specificData: UserGameStats | undefined = find( + data, + (item) => simpleGameTypeToString(game) === `${item.game}:${item.playtype}` + ); + if (specificData) { + embed.addField( + `Stats for: ${formatGameWrapper(game)}`, + `${pullRatings(specificData.ratings).join("\n")}` + ); + } else { + embed.addField("Select a game to see stats", `No stats for ${formatGameWrapper(game)}`); + } } else { - throw new Error(`Could not get ratings for requested game: ${game}`); + embed.addField("Select a game to see stats", "\u200B"); } - } else { - embed.addField("Select a game to see stats", "\u200B"); - } - return embed; + return embed; + } catch (e) { + logger.error(e); + throw new Error("Unable to build profile embed"); + } }; export const buildProfileIntractable = async ( @@ -81,16 +92,17 @@ export const buildProfileIntractable = async ( const data = (await TachiServerV1Get(`/users/${userId}/game-stats`))?.body; logger.verbose(data); + /** @TODO Verify we got valid data here! */ if (data) { const dropdown = new MessageActionRow().addComponents( new MessageSelectMenu() .setCustomId(`SelectGameForProfile:${userId}`) .setPlaceholder("Browse By Game") .addOptions( - data.map((game) => { + data.map((_game) => { return { - label: `${formatGameWrapper(game)}`, - value: `${game.game}:${game.playtype}` + label: `${formatGameWrapper(_game)}`, + value: `${_game.game}:${_game.playtype}` }; }) ) diff --git a/bot/src/profile/fetch.ts b/bot/src/profile/fetch.ts index 64de84302..42893ac62 100644 --- a/bot/src/profile/fetch.ts +++ b/bot/src/profile/fetch.ts @@ -1,18 +1,24 @@ import { CommandInteraction } from "discord.js"; +import { IDStrings } from "tachi-common/js/types"; import { LoggerLayers } from "../config"; import { BotConfig } from "../setup"; import { createLayeredLogger } from "../utils/logger"; +import { stringToSimpleGameType } from "../utils/utils"; import { buildProfileIntractable } from "./buildProfileEmbed"; const logger = createLayeredLogger(LoggerLayers.profile); export const getProfileByName = async (interaction: CommandInteraction): Promise => { try { + /** @TODO this can be an @User, userId or userName!!! Handle this at some point */ const userId = interaction.options.getString("user", false) || "TODO FALLBACK TO SELF"; logger.info(`Fetching user ${userId}`); + const optionalGameOption = interaction.options.getString("game", false); + const game = optionalGameOption ? stringToSimpleGameType(optionalGameOption) : undefined; + if (userId) { - await interaction.reply(await buildProfileIntractable(userId)); + await interaction.reply(await buildProfileIntractable(userId, game)); } else { await interaction.reply("No user data found for user"); } diff --git a/bot/src/slashCommands/register.ts b/bot/src/slashCommands/register.ts index 073fae8d1..d8122543f 100644 --- a/bot/src/slashCommands/register.ts +++ b/bot/src/slashCommands/register.ts @@ -8,6 +8,7 @@ import { ProcessEnv } from "../setup"; import { LoggerLayers } from "../config"; import { help } from "../help/help"; import { createLayeredLogger } from "../utils/logger"; +import { gamesToChoicesObject } from "../utils/utils"; const logger = createLayeredLogger(LoggerLayers.slashCommands); @@ -30,6 +31,13 @@ export const slashCommands: SlashCommand[] = [ .setName("profile") .setDescription("Displays a Kamaitachi Profile") .addStringOption((option) => option.setName("user").setDescription("The users id").setRequired(false)) + .addStringOption((option) => + option + .setName("game") + .setDescription("The game id") + .setRequired(false) + .addChoices(gamesToChoicesObject()) + ) .toJSON(), exec: async (interaction: CommandInteraction) => await getProfileByName(interaction) } diff --git a/bot/src/utils/utils.ts b/bot/src/utils/utils.ts index db80da880..6a0af67a7 100644 --- a/bot/src/utils/utils.ts +++ b/bot/src/utils/utils.ts @@ -1,3 +1,4 @@ +import { APIApplicationCommandOptionChoice } from "discord-api-types"; import { FormatGame, Game, Playtypes } from "tachi-common"; import { IDStrings, UGSRatingsLookup } from "tachi-common/js/types"; import { ProcessEnv } from "../setup"; @@ -42,3 +43,25 @@ export const getPfpUrl = (userId: number): string => { } return PrependTachiUrl(`/users/${userId}/pfp`); }; + +/** @TODO @zkldi is there somewhere this exists already? */ +export const gameIdentifierStrings = [ + "iidx:SP", + "iidx:DP", + "sdvx:Single", + "usc:Single", + "ddr:SP", + "ddr:DP", + "maimai:Single", + "museca:Single", + "bms:7K", + "bms:14K", + "chunithm:Single", + "gitadora:Gita", + "gitadora:Dora" +]; +export const gamesToChoicesObject = (): [name: string, value: string][] => { + return gameIdentifierStrings.map((identifier) => { + return [formatGameWrapper(stringToSimpleGameType(identifier)), identifier]; + }); +};