mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-10 08:18:12 +03:00
Tidied select code
This commit is contained in:
+4
-1
@@ -18,7 +18,10 @@
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
"tab"
|
||||
"tab",
|
||||
{
|
||||
"SwitchCase": 1
|
||||
}
|
||||
],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
|
||||
+2
-2
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user