Tidied select code

This commit is contained in:
Pfych
2021-09-18 13:49:43 +10:00
parent 68d22b1d77
commit bc8a4fa143
6 changed files with 105 additions and 58 deletions
+4 -1
View File
@@ -18,7 +18,10 @@
"rules": {
"indent": [
"error",
"tab"
"tab",
{
"SwitchCase": 1
}
],
"linebreak-style": [
"error",
+2 -2
View File
@@ -1,5 +1,4 @@
/** @TODO Potentially re-work this to only run on PROD env, handy for DEV env! **/
/** @deprecated replace with database call & cache */
export const allowedChannels = ["876321394005254214"];
export enum LoggerLayers {
@@ -10,5 +9,6 @@ export enum LoggerLayers {
botConfigSetup = "botConfigSetup",
tachiFetch = "tachiFetch",
profile = "profile",
selectInteractionHandler = "selectInteractionHandler"
selectInteractionHandler = "selectInteractionHandler",
buildProfileEmbed = "buildProfileEmbed"
}
@@ -1,9 +1,8 @@
import { Interaction } from "discord.js";
import { UserGameStats } from "tachi-common";
import { LoggerLayers } from "../../config";
import { buildProfileIntractable } from "../../profile/buildProfileEmbed";
import { TachiServerV1Get } from "../../utils/fetch-tachi";
import { createLayeredLogger } from "../../utils/logger";
import { stringToSimpleGameType } from "../../utils/utils";
const logger = createLayeredLogger(LoggerLayers.selectInteractionHandler);
@@ -12,12 +11,9 @@ export const handleIsSelectMenu = async (interaction: Interaction): Promise<void
/** Rechecking required to enforce types */
if (interaction.isSelectMenu()) {
const userId = interaction.customId.split(":")[1];
const userData = (await TachiServerV1Get<UserGameStats[]>(`/users/${userId}/game-stats`))?.body;
if (userData) {
await interaction.update(buildProfileIntractable(userData, userId, interaction.values[0]));
} else {
throw new Error("Failed to re-fetch user data! This is a bad sign!");
}
await interaction.update(
await buildProfileIntractable(userId, stringToSimpleGameType(interaction.values[0]))
);
}
return;
} catch (e) {
+58 -40
View File
@@ -1,9 +1,29 @@
import { InteractionReplyOptions, MessageActionRow, MessageEmbed, MessagePayload, MessageSelectMenu } from "discord.js";
import { FormatGame, Game, Playtypes, UserGameStats } from "tachi-common";
import { Game, UserGameStats } from "tachi-common";
import { IDStrings, UGSRatingsLookup } from "tachi-common/js/types";
import { find } from "lodash";
import { LoggerLayers } from "../config";
import { TachiServerV1Get } from "../utils/fetch-tachi";
import { createLayeredLogger } from "../utils/logger";
import { formatGameWrapper, prettyRatingString, SimpleGameType, simpleGameTypeToString } from "../utils/utils";
export const buildProfileEmbed = (data: UserGameStats[], game?: string): MessageEmbed => {
const logger = createLayeredLogger(LoggerLayers.buildProfileEmbed);
const pullRatings = <I extends IDStrings = IDStrings>(
ratings: Partial<Record<UGSRatingsLookup[I], number>>
): string[] => {
const allRatings: string[] = [];
const RatingKeys = <UGSRatingsLookup[I][]>Object.keys(ratings);
RatingKeys.map((rating) => {
const ratingValue: number = ratings[rating] || 0;
allRatings.push(`${prettyRatingString(rating)}: ${Math.round((ratingValue + Number.EPSILON) * 100) / 100}`);
});
return allRatings;
};
export const buildProfileEmbed = (data: UserGameStats[], game?: SimpleGameType<Game>): MessageEmbed => {
const embed = new MessageEmbed().setColor("#cc527a");
/** @TODO FETCH USERS ACTUAL DETAILS */
@@ -13,27 +33,14 @@ export const buildProfileEmbed = (data: UserGameStats[], game?: string): Message
embed.setThumbnail("https://cdn.mos.cms.futurecdn.net/mrArzwHcNuQbRwbEmuiwdJ.jpg");
if (game) {
const specificData: UserGameStats | undefined = find(data, (item) => game === `${item.game}:${item.playtype}`);
if (!specificData) {
throw new Error(`Could not get ratings for requested game: ${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 {
const ratings: string[] = [];
Object.keys(specificData.ratings).map((rating) => {
/** @TODO MAKE THIS ITS OWN FUNCTION THIS IS FILTHY */
ratings.push(
`${rating}: ${
Math.round(
(specificData.ratings[rating as UGSRatingsLookup[IDStrings]] || 0 + Number.EPSILON) * 100
) / 100
}`
);
});
/** @TODO DONT SPLIT THE STRING HERE HOLY SHIT */
embed.addField(
`Stats for: ${FormatGame(game.split(":")[0] as Game, game.split(":")[1] as Playtypes[never])}`,
`${ratings.join("\n")}`
);
throw new Error(`Could not get ratings for requested game: ${game}`);
}
} else {
embed.addField("Select a game to see stats", "\u200B");
@@ -42,24 +49,35 @@ export const buildProfileEmbed = (data: UserGameStats[], game?: string): Message
return embed;
};
export const buildProfileIntractable = (
data: UserGameStats[],
export const buildProfileIntractable = async (
userId: string,
game?: string
): InteractionReplyOptions | MessagePayload => {
const dropdown = new MessageActionRow().addComponents(
new MessageSelectMenu()
.setCustomId(`SelectGameForProfile:${userId}`)
.setPlaceholder("Browse By Game")
.addOptions(
data.map((game) => {
return {
label: `${FormatGame(game.game, game.playtype)}`,
value: `${game.game}:${game.playtype}`
};
})
)
);
game?: SimpleGameType<Game>
): Promise<InteractionReplyOptions | MessagePayload> => {
try {
const data = (await TachiServerV1Get<UserGameStats[]>(`/users/${userId}/game-stats`))?.body;
logger.verbose(data);
return { embeds: [buildProfileEmbed(data, game)], components: [dropdown] };
if (data) {
const dropdown = new MessageActionRow().addComponents(
new MessageSelectMenu()
.setCustomId(`SelectGameForProfile:${userId}`)
.setPlaceholder("Browse By Game")
.addOptions(
data.map((game) => {
return {
label: `${formatGameWrapper(game)}`,
value: `${game.game}:${game.playtype}`
};
})
)
);
return { embeds: [buildProfileEmbed(data, game)], components: [dropdown] };
} else {
throw new Error(`No data found for user ${userId}`);
}
} catch (e) {
logger.error("Unable to build profile interactable");
throw new Error("Unable to build profile interactable");
}
};
+2 -7
View File
@@ -1,9 +1,7 @@
import { CommandInteraction } from "discord.js";
import { LoggerLayers } from "../config";
import { BotConfig } from "../setup";
import { TachiServerV1Get } from "../utils/fetch-tachi";
import { createLayeredLogger } from "../utils/logger";
import { UserGameStats } from "tachi-common";
import { buildProfileIntractable } from "./buildProfileEmbed";
const logger = createLayeredLogger(LoggerLayers.profile);
@@ -13,11 +11,8 @@ export const getProfileByName = async (interaction: CommandInteraction): Promise
const userId = interaction.options.getString("user", false) || "TODO FALLBACK TO SELF";
logger.info(`Fetching user ${userId}`);
const userData = (await TachiServerV1Get<UserGameStats[]>(`/users/${userId}/game-stats`))?.body;
logger.verbose(userData);
if (userData) {
await interaction.reply(buildProfileIntractable(userData, userId));
if (userId) {
await interaction.reply(await buildProfileIntractable(userId));
} else {
await interaction.reply("No user data found for user");
}
+35
View File
@@ -0,0 +1,35 @@
import { FormatGame, Game, Playtypes } from "tachi-common";
import { IDStrings, UGSRatingsLookup } from "tachi-common/js/types";
export interface SimpleGameType<T extends Game> {
game: T;
playtype: Playtypes[T];
}
export const simpleGameTypeToString = <T extends Game>(game: SimpleGameType<T>): IDStrings =>
<IDStrings>`${game.game}:${game.playtype}`;
export const stringToSimpleGameType = (game: string): SimpleGameType<Game> => {
return { game: <Game>game.split(":")[0], playtype: <Playtypes[never]>game.split(":")[1] };
};
export const formatGameWrapper = (game: SimpleGameType<Game>): string => FormatGame(game.game, game.playtype);
export const prettyRatingString = <I extends IDStrings = IDStrings>(rating: UGSRatingsLookup[I]): string => {
switch (rating) {
case "ktRating":
return "Kamai Rating";
case "ktLampRating":
return "Kamai Lamp Rating";
case "sieglinde":
return "???";
case "VF6":
return "Volforce";
case "BPI":
return "BPI";
case "MFCP":
return "???";
default:
return "Skill";
}
};