From d88784d2fcb1f009fcc851e5f7c4d50deab3a0c6 Mon Sep 17 00:00:00 2001 From: tresabhi Date: Mon, 8 May 2023 01:03:05 +0000 Subject: [PATCH] feat: nickname based commands --- src/commands/eligible.ts | 11 ++++-- src/commands/stats.ts | 11 ++++-- src/commands/tanks.ts | 29 ++++++++------ src/commands/verify.ts | 18 +++++---- src/constants/servers.ts | 12 ++++++ src/embeds/badNicknameFormat.ts | 6 +++ src/embeds/noMember.ts | 6 +++ src/utilities/addIGNOption.ts | 2 +- src/utilities/addServerChoices.ts | 2 +- src/utilities/errorEmbed.ts | 9 +++++ src/utilities/extractUser.ts | 66 +++++++++++++++++++++++++++++++ 11 files changed, 143 insertions(+), 29 deletions(-) create mode 100644 src/embeds/badNicknameFormat.ts create mode 100644 src/embeds/noMember.ts create mode 100644 src/utilities/errorEmbed.ts create mode 100644 src/utilities/extractUser.ts diff --git a/src/commands/eligible.ts b/src/commands/eligible.ts index a8c1e6d83..75f031b72 100644 --- a/src/commands/eligible.ts +++ b/src/commands/eligible.ts @@ -2,10 +2,10 @@ import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; import markdownEscape from 'markdown-escape'; import { CommandRegistry } from '../behaviors/interactionCreate.js'; import { NEGATIVE_COLOR, POSITIVE_COLOR } from '../constants/colors.js'; -import { BlitzServer } from '../constants/servers.js'; import addIGNOption from '../utilities/addIGNOption.js'; import addServerChoices from '../utilities/addServerChoices.js'; import blitzLinks from '../utilities/blitzLinks.js'; +import extractUser from '../utilities/extractUser.js'; import getBlitzAccount from '../utilities/getBlitzAccount.js'; import getBlitzStarsAccount from '../utilities/getBlitzStarsAccount.js'; import poweredByBlitzStars from '../utilities/poweredByBlitzStars.js'; @@ -36,10 +36,13 @@ export default { .addStringOption(addServerChoices) .addStringOption(addIGNOption), - execute(interaction) { - const name = interaction.options.getString('name')!; - const server = interaction.options.getString('server') as BlitzServer; + async execute(interaction) { const clan = interaction.options.getString('clan') as keyof typeof CLANS; + + const extractedUser = await extractUser(interaction); + if (!extractedUser) return; + + const { name, server } = extractedUser; const command = `eligible ${server} ${name} ${clan}`; getBlitzAccount(interaction, command, name, server, async (account) => { diff --git a/src/commands/stats.ts b/src/commands/stats.ts index 5c429576b..ad5257458 100644 --- a/src/commands/stats.ts +++ b/src/commands/stats.ts @@ -2,13 +2,13 @@ import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; import markdownEscape from 'markdown-escape'; import { CommandRegistry } from '../behaviors/interactionCreate.js'; import { SKILLED_COLOR } from '../constants/colors.js'; -import { BlitzServer } from '../constants/servers.js'; import { AccountInfo, AllStats } from '../types/accountInfo.js'; import { PeriodStatistics } from '../types/statistics.js'; import addIGNOption from '../utilities/addIGNOption.js'; import addServerChoices from '../utilities/addServerChoices.js'; import { args } from '../utilities/args.js'; import blitzLinks from '../utilities/blitzLinks.js'; +import extractUser from '../utilities/extractUser.js'; import getBlitzAccount from '../utilities/getBlitzAccount.js'; import getBlitzStarsAccount from '../utilities/getBlitzStarsAccount.js'; import getWargamingResponse from '../utilities/getWargamingResponse.js'; @@ -39,10 +39,13 @@ export default { .addStringOption(addServerChoices) .addStringOption(addIGNOption), - execute(interaction) { - const name = interaction.options.getString('name')!; - const server = interaction.options.getString('server') as BlitzServer; + async execute(interaction) { const period = interaction.options.getString('period') as Period; + + const extractedUser = await extractUser(interaction); + if (!extractedUser) return; + + const { name, server } = extractedUser; const command = `stats ${server} ${name} ${period}`; getBlitzAccount( diff --git a/src/commands/tanks.ts b/src/commands/tanks.ts index ee90b0c32..c01a6a5e2 100644 --- a/src/commands/tanks.ts +++ b/src/commands/tanks.ts @@ -2,11 +2,11 @@ import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; import markdownEscape from 'markdown-escape'; import { CommandRegistry } from '../behaviors/interactionCreate.js'; import { SKILLED_COLOR } from '../constants/colors.js'; -import { BlitzServer } from '../constants/servers.js'; import { TanksStats } from '../types/tanksStats.js'; import addIGNOption from '../utilities/addIGNOption.js'; import addServerChoices from '../utilities/addServerChoices.js'; import { args } from '../utilities/args.js'; +import extractUser from '../utilities/extractUser.js'; import getBlitzAccount from '../utilities/getBlitzAccount.js'; import getWargamingResponse from '../utilities/getWargamingResponse.js'; import { TANK_TYPE_EMOJIS, tankopedia } from '../utilities/tankopedia.js'; @@ -38,23 +38,28 @@ export default { inPublic: true, command: new SlashCommandBuilder() - .setName('tanks') + .setName('tanksdev') .setDescription("Shows a player's owned tanks") - .addStringOption(addServerChoices) - .addStringOption(addIGNOption) .addIntegerOption((option) => option .setName('tier') - .setDescription('The tier you want to see (default: all tiers)') + .setDescription('The tier you want to see') .setMinValue(1) .setMaxValue(10) .setRequired(true), - ), + ) + .addStringOption(addServerChoices) + .addStringOption(addIGNOption), - execute(interaction) { - const server = interaction.options.getString('server') as BlitzServer; - const name = interaction.options.getString('name')!; + async execute(interaction) { const tier = interaction.options.getInteger('tier')!; + + await interaction.deferReply(); + + const extractedUser = await extractUser(interaction); + if (!extractedUser) return; + + const { name, server } = extractedUser; const command = `tanks ${server} ${name} ${tier}`; getBlitzAccount(interaction, command, name, server, async (account) => { @@ -63,9 +68,9 @@ export default { interaction, command, async (tankStats) => { - const tanks = tankStats[account.account_id]!.map( - (tankData) => tankopedia.data[tankData.tank_id], - ).filter((tank) => tank.tier === tier); + const tanks = tankStats[account.account_id] + .map((tankData) => tankopedia.data[tankData.tank_id]) + .filter((tank) => tank.tier === tier); await interaction.editReply({ embeds: [ diff --git a/src/commands/verify.ts b/src/commands/verify.ts index 509eccf1b..fefca291c 100644 --- a/src/commands/verify.ts +++ b/src/commands/verify.ts @@ -3,7 +3,7 @@ import markdownEscape from 'markdown-escape'; import discord from '../../discord.json' assert { type: 'json' }; import { CommandRegistry } from '../behaviors/interactionCreate.js'; import { NEGATIVE_COLOR, POSITIVE_COLOR } from '../constants/colors.js'; -import { BlitzServer } from '../constants/servers.js'; +import { BLITZ_SERVERS_SHORT, BlitzServer } from '../constants/servers.js'; import { PlayerClanData } from '../types/playerClanData.js'; import addIGNOption from '../utilities/addIGNOption.js'; import addServerChoices from '../utilities/addServerChoices.js'; @@ -17,10 +17,10 @@ export default { inPublic: true, command: new SlashCommandBuilder() - .setName('verify') + .setName('verifydev') .setDescription("Set's the user's username to their in-game name") - .addStringOption(addServerChoices) - .addStringOption(addIGNOption), + .addStringOption((option) => addServerChoices(option).setRequired(true)) + .addStringOption((Option) => addIGNOption(Option).setRequired(true)), execute(interaction) { let name = interaction.options.getString('name')!; @@ -70,7 +70,9 @@ export default { if (member) { await member - ?.setNickname(`${name}${clanTag}`) + ?.setNickname( + `${name} (${BLITZ_SERVERS_SHORT[server]})${clanTag}`, + ) .then(async () => { if (interaction.guildId === discord.guild_id) { if ( @@ -112,13 +114,15 @@ export default { .setDescription( `The user is now verified as ${markdownEscape( name, - )}${markdownEscape(clanTag)}`, + )} (${BLITZ_SERVERS_SHORT[server]})${markdownEscape( + clanTag, + )}`, ), ], }); console.log( - `${interaction.user.username} verified as ${name}${clanTag}`, + `${interaction.user.username} verified as ${name} (${BLITZ_SERVERS_SHORT[server]})${clanTag}`, ); }) .catch(async () => { diff --git a/src/constants/servers.ts b/src/constants/servers.ts index 804640b19..d8ce0cd67 100644 --- a/src/constants/servers.ts +++ b/src/constants/servers.ts @@ -4,4 +4,16 @@ export const BLITZ_SERVERS = { asia: 'Asia', }; +export const BLITZ_SERVERS_SHORT = { + com: 'NA', + eu: 'EU', + asia: 'ASIA', +}; + +export const BLITZ_SERVERS_SHORT_INVERSE = { + NA: 'com', + EU: 'eu', + ASIA: 'asia', +}; + export type BlitzServer = keyof typeof BLITZ_SERVERS; diff --git a/src/embeds/badNicknameFormat.ts b/src/embeds/badNicknameFormat.ts new file mode 100644 index 000000000..f5950c710 --- /dev/null +++ b/src/embeds/badNicknameFormat.ts @@ -0,0 +1,6 @@ +import errorEmbed from '../utilities/errorEmbed.js'; + +export const badNicknameFormat = errorEmbed( + 'Bad nickname format', + 'I expected your nickname to be... \n\n```\nIN_GAME_NAME (SERVER) [CLAN_TAG]\n```\nUse the `/verify` command to setup your nickname correctly or manually provide me with your in-game name and server in the command.', +); diff --git a/src/embeds/noMember.ts b/src/embeds/noMember.ts new file mode 100644 index 000000000..15167af5a --- /dev/null +++ b/src/embeds/noMember.ts @@ -0,0 +1,6 @@ +import errorEmbed from '../utilities/errorEmbed.js'; + +export const noMember = errorEmbed( + 'User of command is not a member', + 'Discord claims that the user of this command does not have an account... strange!', +); diff --git a/src/utilities/addIGNOption.ts b/src/utilities/addIGNOption.ts index 99937265f..17cf4bdc1 100644 --- a/src/utilities/addIGNOption.ts +++ b/src/utilities/addIGNOption.ts @@ -4,5 +4,5 @@ export default function addIGNOption(option: SlashCommandStringOption) { return option .setName('name') .setDescription('The username you use in Blitz') - .setRequired(true); + .setRequired(false); } diff --git a/src/utilities/addServerChoices.ts b/src/utilities/addServerChoices.ts index ee94f20ac..3f0125b8c 100644 --- a/src/utilities/addServerChoices.ts +++ b/src/utilities/addServerChoices.ts @@ -10,5 +10,5 @@ export default function addServerChoices(option: SlashCommandStringOption) { { name: BLITZ_SERVERS.eu, value: 'eu' }, { name: BLITZ_SERVERS.asia, value: 'asia' }, ) - .setRequired(true); + .setRequired(false); } diff --git a/src/utilities/errorEmbed.ts b/src/utilities/errorEmbed.ts new file mode 100644 index 000000000..08b35ab18 --- /dev/null +++ b/src/utilities/errorEmbed.ts @@ -0,0 +1,9 @@ +import { EmbedBuilder } from 'discord.js'; +import { NEGATIVE_COLOR } from '../constants/colors.js'; + +export default function errorEmbed(title: string, description: string) { + return new EmbedBuilder() + .setColor(NEGATIVE_COLOR) + .setTitle(title) + .setDescription(description); +} diff --git a/src/utilities/extractUser.ts b/src/utilities/extractUser.ts new file mode 100644 index 000000000..b278178a6 --- /dev/null +++ b/src/utilities/extractUser.ts @@ -0,0 +1,66 @@ +import { CacheType, ChatInputCommandInteraction } from 'discord.js'; +import { + BLITZ_SERVERS_SHORT, + BLITZ_SERVERS_SHORT_INVERSE, + BlitzServer, +} from '../constants/servers.js'; +import { badNicknameFormat } from '../embeds/badNicknameFormat.js'; +import { noMember } from '../embeds/noMember.js'; +import errorEmbed from './errorEmbed.js'; + +const nicknamePattern = /(.+) \((.+)\)/; + +const VALID_BLITZ_SERVERS_SHORT = Object.keys(BLITZ_SERVERS_SHORT_INVERSE); + +export default async function extractUser( + interaction: ChatInputCommandInteraction, +) { + if (!interaction.member) { + await interaction.editReply({ embeds: [noMember] }); + return; + } + + const member = interaction.guild?.members.cache.get( + interaction.member.user.id, + ); + const nickname = member?.nickname ?? member?.user.username; + if (!nickname) { + await interaction.editReply({ embeds: [noMember] }); + return; + } + + const matches = nickname.match(nicknamePattern); + if (!matches) { + await interaction.editReply({ embeds: [badNicknameFormat] }); + return; + } + + const [, nameMatch, serverMatch] = matches; + const nameArg = interaction.options.getString('name'); + const serverArg = interaction.options.getString( + 'server', + ) as BlitzServer | null; + const name = nameArg ?? nameMatch; + const server = + BLITZ_SERVERS_SHORT[serverArg as keyof typeof BLITZ_SERVERS_SHORT] ?? + serverMatch; + + if (!VALID_BLITZ_SERVERS_SHORT.includes(server)) { + await interaction.editReply({ + embeds: [ + errorEmbed( + 'Invalid server', + `"${server}" is not a valid server. Use the \`/verify\` command to setup your nickname correctly or manually provide me with the server in the command.`, + ), + ], + }); + return; + } + + return { + name, + server: BLITZ_SERVERS_SHORT_INVERSE[ + server as keyof typeof BLITZ_SERVERS_SHORT_INVERSE + ] as BlitzServer, + }; +}