From 19cb5b445b1d2f1f1070855e4e91df365a24e30a Mon Sep 17 00:00:00 2001 From: Pihkaal Date: Fri, 5 Dec 2025 17:11:06 +0100 Subject: [PATCH] refactor(discord-bot): improve 'gemmes' command --- apps/discord-bot/.env.example | 1 + apps/discord-bot/src/commands/gemmes.ts | 99 ++++++++++++------------- apps/discord-bot/src/env.ts | 3 + apps/discord-bot/src/utils/discord.ts | 11 ++- 4 files changed, 62 insertions(+), 52 deletions(-) diff --git a/apps/discord-bot/.env.example b/apps/discord-bot/.env.example index 640e068..7a7d2f1 100644 --- a/apps/discord-bot/.env.example +++ b/apps/discord-bot/.env.example @@ -9,6 +9,7 @@ QUEST_EXCLUDE= DISCORD_WEBHOOK_URL= DISCORD_MENTION= DISCORD_REWARDS_GIVER= +DISCORD_STAFF_ROLE_ID="" # Postgres database url DATABASE_URL="" diff --git a/apps/discord-bot/src/commands/gemmes.ts b/apps/discord-bot/src/commands/gemmes.ts index 64347fd..33e7534 100644 --- a/apps/discord-bot/src/commands/gemmes.ts +++ b/apps/discord-bot/src/commands/gemmes.ts @@ -1,65 +1,62 @@ +import { EmbedBuilder } from "discord.js"; +import { env } from "~/env"; import type { Command } from "~/commands"; import { getAccountBalance, setAccountBalance } from "~/services/account"; import { getClanMembers } from "~/services/wov"; -import { createErrorEmbed } from "~/utils/discord"; - -const STAFF_ROLE_ID = "1147963065640439900"; +import { replyError } from "~/utils/discord"; export const gemmesCommand: Command = async (message, args) => { + // retrieve player name + // NOTE: discord members have display name formatted like "🕸 | InGamePseudo" const displayName = message.member?.displayName || message.author.username; - let playerName = displayName.replace("🕸 |", "").trim(); - if (args.length >= 1) { - playerName = args[0]; + const playerName = args[0] || displayName.replace("🕸 |", "").trim(); + + // get clan member + const clanMembers = await getClanMembers(); + const clanMember = clanMembers.find((x) => x.username === playerName); + if (!clanMember) { + await replyError( + message, + `\`${playerName}\` n'est pas dans le clan (la honte).\n**Attention les majuscules sont importantes**`, + ); + return; } - const clanMembers = await getClanMembers(); - - let clanMember = clanMembers.find((x) => x.username === playerName); - if (!clanMember) { - await message.reply( - createErrorEmbed( - `\`${playerName}\` n'est pas dans le clan (la honte).\n**Attention les majuscules sont importantes**`, - ), - ); - } else { - if (args.length === 2 && message.member) { - if (!message.member.roles.cache.has(STAFF_ROLE_ID)) { - await message.reply( - createErrorEmbed("Tu t'es cru chez mémé ou quoi faut être staff"), - ); - return; - } - - if ( - (args[1][0] !== "+" && args[1][0] !== "-") || - !args[1] || - isNaN(Number(args[1].substring(1))) - ) { - await message.reply( - createErrorEmbed( - "Format: `@LBF gemmes <+GEMMES | -GEMMES>`\nExemple:`@LBF gemmes Yuno -10000`\n**Attention les majuscules sont importantes**", - ), - ); - return; - } - - const mult = args[1][0] === "+" ? 1 : -1; - const delta = Number(args[1].substring(1)) * mult; - const balance = await getAccountBalance(clanMember.playerId); - await setAccountBalance( - clanMember.playerId, - Math.max(0, balance + delta), + // handle balance modification (staff only) + if (args.length === 2) { + if (!message.member?.roles.cache.has(env.DISCORD_STAFF_ROLE_ID)) { + await replyError( + message, + "Tu t'es cru chez mémé ou quoi faut être staff", ); + return; + } + + const op = args[1][0]; + const amount = Number(args[1].substring(1)); + if ((op !== "+" && op !== "-") || args[1].length === 1 || isNaN(amount)) { + await replyError( + message, + "Format: `@LBF gemmes <+GEMMES | -GEMMES>`\nExemple: `@LBF gemmes Yuno -10000`\n**Attention les majuscules sont importantes**", + ); + return; } const balance = await getAccountBalance(clanMember.playerId); - await message.reply({ - embeds: [ - { - description: `### 💎 Compte de ${playerName}\n\n\nGemmes disponibles: **${balance}**\n\n-# Voir avec <@294871767820795904> pour échanger contre skin/carte etc`, - color: 4360641, - }, - ], - }); + const delta = amount * (op === "+" ? 1 : -1); + await setAccountBalance(clanMember.playerId, Math.max(0, balance + delta)); } + + // display balance + const balance = await getAccountBalance(clanMember.playerId); + await message.reply({ + embeds: [ + new EmbedBuilder() + .setDescription( + // TODO: mention here instead of in the env + `### 💎 Compte de ${playerName}\n\n\nGemmes disponibles: **${balance}**\n\n-# Voir avec ${env.DISCORD_REWARDS_GIVER} pour échanger contre skin/carte etc`, + ) + .setColor(0x4289c1), + ], + }); }; diff --git a/apps/discord-bot/src/env.ts b/apps/discord-bot/src/env.ts index 7092b73..9dc65b7 100644 --- a/apps/discord-bot/src/env.ts +++ b/apps/discord-bot/src/env.ts @@ -6,9 +6,12 @@ const schema = z.object({ DISCORD_MENTION: z.string(), DISCORD_REWARDS_GIVER: z.string(), DISCORD_REWARDS_CHANNEL: z.string(), + // TODO: remove and compose from staff role id DISCORD_ADMIN_MENTION: z.string(), + // TODO: rename to reward ask channel or smth DISCORD_ADMIN_CHANNEL: z.string(), DISCORD_TRACKING_CHANNEL: z.string(), + DISCORD_STAFF_ROLE_ID: z.string(), WOV_API_KEY: z.string(), WOV_CLAN_ID: z.string(), WOV_FETCH_INTERVAL: z.coerce.number(), diff --git a/apps/discord-bot/src/utils/discord.ts b/apps/discord-bot/src/utils/discord.ts index 4c4ab99..befd711 100644 --- a/apps/discord-bot/src/utils/discord.ts +++ b/apps/discord-bot/src/utils/discord.ts @@ -1,7 +1,7 @@ import { getAccountBalance, setAccountBalance } from "~/services/account"; import { env } from "~/env"; import type { QuestResult } from "~/services/wov"; -import type { MessageCreateOptions, APIEmbed } from "discord.js"; +import type { MessageCreateOptions, APIEmbed, Message } from "discord.js"; export const makeResultEmbed = async ( result: QuestResult, @@ -105,3 +105,12 @@ export const createInfoEmbed = ( }, ], }); + +export const replyError = (message: Message, text: string, color?: number) => + message.reply(createErrorEmbed(text, color)); + +export const replySuccess = (message: Message, text: string, color?: number) => + message.reply(createSuccessEmbed(text, color)); + +export const replyInfo = (message: Message, text: string, color?: number) => + message.reply(createInfoEmbed(text, color));