From 4d9dc067afe62de8a7579506c74444c4a920db03 Mon Sep 17 00:00:00 2001 From: tresabhi Date: Fri, 16 Jun 2023 02:01:06 +0000 Subject: [PATCH] feat: return-based interaction reply edits --- .vscode/settings.json | 5 ++ package.json | 2 +- scripts/build.js | 13 ++-- src/commands/debug.ts | 44 +++++------ src/commands/eligible.ts | 8 +- src/commands/help.ts | 40 +++++----- src/commands/inactive.tsx | 9 +-- src/commands/ownedtanks.tsx | 7 +- src/commands/playerachievements.ts | 42 +++++------ src/commands/playerinfo.ts | 56 +++++++------- src/commands/searchclans.ts | 24 +++--- src/commands/searchplayers.ts | 24 +++--- src/commands/searchtanks.ts | 18 ++--- src/commands/stats.tsx | 21 +----- src/commands/tankstats.tsx | 19 +---- src/commands/today.tsx | 21 +----- src/commands/verify.ts | 114 ++++++++++------------------- src/core/process/psa.ts | 20 +++++ src/events/interactionCreate.ts | 68 ++++++++++++----- 19 files changed, 249 insertions(+), 306 deletions(-) create mode 100644 src/core/process/psa.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index e44870599..57e6e0dab 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,13 +8,18 @@ "kranvagn", "outfile", "ownedtanks", + "playerachievements", + "playerinfo", "Resvg", + "searchclans", "searchplayers", + "searchtanks", "SKLLD", "Smri", "startcase", "strvk", "tankopedia", + "tankstats", "Unicum", "Unregistering", "vickers", diff --git a/package.json b/package.json index b7e103244..6a3c36767 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "src/index.ts", "type": "module", "scripts": { - "dev": "yarn build && yarn start", + "dev": "yarn build --dev && yarn start", "start": "node --enable-source-maps dist/index.cjs", "zip": "zip -r dist.zip dist", "build": "node scripts/build", diff --git a/scripts/build.js b/scripts/build.js index 975ff801b..b4bd2b4e2 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -1,10 +1,13 @@ import { build } from 'esbuild'; import { rmSync } from 'fs'; +import { argv } from 'process'; + +const isDev = argv.includes('--dev'); console.log('Removing dist...'); rmSync('dist', { recursive: true, force: true }); -console.log('Creating context...'); +console.log('Building...'); build({ entryPoints: ['src/index.ts'], outfile: 'dist/index.cjs', @@ -15,9 +18,9 @@ build({ '.ttf': 'file', }, - bundle: true, - sourcemap: true, + bundle: isDev, + sourcemap: isDev, minifyIdentifiers: false, // causes errors - minifySyntax: true, - minifyWhitespace: true, + minifySyntax: isDev, + minifyWhitespace: isDev, }); diff --git a/src/commands/debug.ts b/src/commands/debug.ts index 278060b45..4e2816c69 100644 --- a/src/commands/debug.ts +++ b/src/commands/debug.ts @@ -13,38 +13,34 @@ const executionStart = new Date().getTime(); export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() .setName(cmdName('debug')) .setDescription('Debug information about the bot'), - async execute(interaction) { + execute(interaction) { const currentTime = new Date().getTime(); const uptime = currentTime - executionStart; - await interaction.editReply({ - embeds: [ - infoEmbed( - `${client.user?.username} debug information`, - cleanTable([ - ['Version', packageJSON.version], - ['Client ID', getClientId()], - ['Tag', interaction.client.user.tag], - [ - 'Uptime', - `${Math.floor(uptime / 1000 / 60 / 60 / 24)}d ${Math.floor( - (uptime / 1000 / 60 / 60) % 24, - )}h ${Math.floor((uptime / 1000 / 60) % 60)}m ${Math.floor( - (uptime / 1000) % 60, - )}s ${Math.floor(uptime % 1000)}ms`, - ], - ['Tankopedia cached', `${tankopedia !== undefined}`], - ['Tank averages cached', `${tankAverages !== undefined}`], - ]), - ), - ], - }); + return infoEmbed( + `${client.user?.username} debug information`, + cleanTable([ + ['Version', packageJSON.version], + ['Client ID', getClientId()], + ['Tag', interaction.client.user.tag], + [ + 'Uptime', + `${Math.floor(uptime / 1000 / 60 / 60 / 24)}d ${Math.floor( + (uptime / 1000 / 60 / 60) % 24, + )}h ${Math.floor((uptime / 1000 / 60) % 60)}m ${Math.floor( + (uptime / 1000) % 60, + )}s ${Math.floor(uptime % 1000)}ms`, + ], + ['Tankopedia cached', `${tankopedia !== undefined}`], + ['Tank averages cached', `${tankAverages !== undefined}`], + ]), + ); }, } satisfies CommandRegistry; diff --git a/src/commands/eligible.ts b/src/commands/eligible.ts index f6a65bd33..1e1fbb615 100644 --- a/src/commands/eligible.ts +++ b/src/commands/eligible.ts @@ -26,7 +26,7 @@ export const SKILLED_CLANS: Record = { export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: false, command: new SlashCommandBuilder() @@ -166,10 +166,6 @@ export default { )}`; } - await interaction.editReply({ - embeds: isEligible - ? [positiveEmbed(title, body)] - : [negativeEmbed(title, body)], - }); + return (isEligible ? positiveEmbed : negativeEmbed)(title, body); }, } satisfies CommandRegistry; diff --git a/src/commands/help.ts b/src/commands/help.ts index 327e465bc..f8d466831 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -1,7 +1,7 @@ -import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; +import { SlashCommandBuilder } from 'discord.js'; import discord from '../../discord.json' assert { type: 'json' }; -import { ACCENT_COLOR } from '../constants/colors.js'; import cmdName from '../core/interaction/cmdName.js'; +import infoEmbed from '../core/interaction/infoEmbed.js'; import { CommandRegistry, guildCommands, @@ -18,26 +18,20 @@ export default { .setName(cmdName('help')) .setDescription('All the help you need about the bot'), - async execute(interaction) { - await interaction.editReply({ - embeds: [ - new EmbedBuilder() - .setTitle(`${client.user?.username} help`) - .setColor(ACCENT_COLOR) - .setDescription( - `**About**\n${ - client.user?.username - } automates many mundane tasks and provide statistics in numerous flexible ways.\n\nMade by TresAbhi from the Skilled [SKLLD] clan.\nGitHub: https://github.com/tresabhi/blitzkrieg\nDiscord server: https://discord.gg/nDt7AjGJQH\nSkilled server: https://discord.gg/ZPvcEG7DS8\n\n**Commands**\n${(interaction.guildId === - discord.sklld_guild_id - ? [...guildCommands, ...publicCommands] - : publicCommands - ) - .map((command) => `**/${command.name}**: ${command.description}`) - .join( - '\n', - )}\n\n*I am a new bot; I may make mistakes and go offline unexpectedly from time to time.*`, - ), - ], - }); + execute(interaction) { + return infoEmbed( + `${client.user?.username} help`, + `**About**\n${ + client.user?.username + } automates many mundane tasks and provide statistics in numerous flexible ways.\n\nMade by TresAbhi from the Skilled [SKLLD] clan.\nGitHub: https://github.com/tresabhi/blitzkrieg\nDiscord server: https://discord.gg/nDt7AjGJQH\nSkilled server: https://discord.gg/ZPvcEG7DS8\n\n**Commands**\n${(interaction.guildId === + discord.sklld_guild_id + ? [...guildCommands, ...publicCommands] + : publicCommands + ) + .map((command) => `**/${command.name}**: ${command.description}`) + .join( + '\n', + )}\n\n*I am a new bot; I may make mistakes and go offline unexpectedly from time to time.*`, + ); }, } satisfies CommandRegistry; diff --git a/src/commands/inactive.tsx b/src/commands/inactive.tsx index 9b91fa8eb..6b55d094d 100644 --- a/src/commands/inactive.tsx +++ b/src/commands/inactive.tsx @@ -11,7 +11,6 @@ import getWargamingResponse from '../core/blitz/getWargamingResponse.js'; import cmdName from '../core/interaction/cmdName.js'; import addClanChoices from '../core/options/addClanChoices.js'; import { WARGAMING_APPLICATION_ID } from '../core/process/args.js'; -import render from '../core/ui/render.js'; import { CommandRegistry } from '../events/interactionCreate.js'; import { AccountInfo } from '../types/accountInfo.js'; import { ClanInfo } from '../types/clanInfo.js'; @@ -20,7 +19,7 @@ const DEFAULT_THRESHOLD = 7; export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() @@ -67,7 +66,7 @@ export default { ); const hasInactiveMembers = inactive.length > 0; - const image = await render( + return ( } - , + ); - - await interaction.editReply({ files: [image] }); }, autocomplete: clanAutocomplete, diff --git a/src/commands/ownedtanks.tsx b/src/commands/ownedtanks.tsx index 98df0be0f..1150bbee6 100644 --- a/src/commands/ownedtanks.tsx +++ b/src/commands/ownedtanks.tsx @@ -13,7 +13,6 @@ import { TIER_ROMAN_NUMERALS, tankopedia } from '../core/blitz/tankopedia.js'; import cmdName from '../core/interaction/cmdName.js'; import addUsernameOption from '../core/options/addUsernameOption.js'; import { WARGAMING_APPLICATION_ID } from '../core/process/args.js'; -import render from '../core/ui/render.js'; import { CommandRegistry } from '../events/interactionCreate.js'; import { AccountInfo } from '../types/accountInfo.js'; import { PlayerClanData } from '../types/playerClanData.js'; @@ -72,7 +71,7 @@ export default { `https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`, ); - const image = await render( + return ( {/* TODO: integrate some of these into title bar */} - , + ); - - await interaction.editReply({ files: [image] }); }, autocomplete: usernameAutocomplete, diff --git a/src/commands/playerachievements.ts b/src/commands/playerachievements.ts index cbe3626fd..ec4346aa8 100644 --- a/src/commands/playerachievements.ts +++ b/src/commands/playerachievements.ts @@ -17,7 +17,7 @@ type SortBy = 'name' | 'count'; export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() @@ -51,30 +51,26 @@ export default { ...accountAchievements.max_series, }; - interaction.editReply({ - embeds: [ - infoEmbed( - `${markdownEscape(accounts[id].nickname)}'s information`, + return infoEmbed( + `${markdownEscape(accounts[id].nickname)}'s information`, - cleanTable( - Object.keys(compound) - .filter((achievement) => compound[achievement] > 0) - .sort( - sortBy === 'count' - ? (a, b) => compound[b] - compound[a] - : undefined, - ) - .map( - (achievement) => - [ - startCase(achievement), - compound[achievement], - ] as TableInputEntry, - ), + cleanTable( + Object.keys(compound) + .filter((achievement) => compound[achievement] > 0) + .sort( + sortBy === 'count' + ? (a, b) => compound[b] - compound[a] + : undefined, + ) + .map( + (achievement) => + [ + startCase(achievement), + compound[achievement], + ] as TableInputEntry, ), - ), - ], - }); + ), + ); }, autocomplete: usernameAutocomplete, diff --git a/src/commands/playerinfo.ts b/src/commands/playerinfo.ts index 46a3eefb8..f4967ab9a 100644 --- a/src/commands/playerinfo.ts +++ b/src/commands/playerinfo.ts @@ -13,7 +13,7 @@ import { AccountInfo } from '../types/accountInfo.js'; export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() @@ -29,36 +29,32 @@ export default { ); const accountInfo = accounts[id]; - interaction.editReply({ - embeds: [ - infoEmbed( - `${markdownEscape(accountInfo.nickname)}'s information`, + return infoEmbed( + `${markdownEscape(accountInfo.nickname)}'s information`, - cleanTable([ - ['Nickname', `${accountInfo.nickname}`], - ['Battles', `${accountInfo.statistics.all.battles}`], - [ - 'Winrate', - `${( - 100 * - (accountInfo.statistics.all.wins / - accountInfo.statistics.all.battles) - ).toFixed(2)}%`, - ], - [], - ['Account ID', `${accountInfo.account_id}`], - [ - 'Created', - `${new Date(accountInfo.created_at * 1000).toDateString()}`, - ], - [ - 'Last battle', - `${new Date(accountInfo.last_battle_time * 1000).toDateString()}`, - ], - ]), - ), - ], - }); + cleanTable([ + ['Nickname', `${accountInfo.nickname}`], + ['Battles', `${accountInfo.statistics.all.battles}`], + [ + 'Winrate', + `${( + 100 * + (accountInfo.statistics.all.wins / + accountInfo.statistics.all.battles) + ).toFixed(2)}%`, + ], + [], + ['Account ID', `${accountInfo.account_id}`], + [ + 'Created', + `${new Date(accountInfo.created_at * 1000).toDateString()}`, + ], + [ + 'Last battle', + `${new Date(accountInfo.last_battle_time * 1000).toDateString()}`, + ], + ]), + ); }, autocomplete: usernameAutocomplete, diff --git a/src/commands/searchclans.ts b/src/commands/searchclans.ts index 28216932d..b230382a4 100644 --- a/src/commands/searchclans.ts +++ b/src/commands/searchclans.ts @@ -12,7 +12,7 @@ import { ClanList } from '../types/clanList.js'; export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() @@ -36,19 +36,13 @@ export default { `https://api.wotblitz.${server}/wotb/clans/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${clan}&limit=${limit}`, ); - await interaction.editReply({ - embeds: [ - infoEmbed( - `Clan search for "${markdownEscape(clan)}" in ${ - BLITZ_SERVERS[server] - }`, - clanList.length === 0 - ? 'No clans found.' - : `\`\`\`\n${clanList - .map((clan) => `${clan.name} [${clan.tag}]`) - .join('\n')}\n\`\`\``, - ), - ], - }); + return infoEmbed( + `Clan search for "${markdownEscape(clan)}" in ${BLITZ_SERVERS[server]}`, + clanList.length === 0 + ? 'No clans found.' + : `\`\`\`\n${clanList + .map((clan) => `${clan.name} [${clan.tag}]`) + .join('\n')}\n\`\`\``, + ); }, } satisfies CommandRegistry; diff --git a/src/commands/searchplayers.ts b/src/commands/searchplayers.ts index 1f29125e5..4c70a0f42 100644 --- a/src/commands/searchplayers.ts +++ b/src/commands/searchplayers.ts @@ -13,7 +13,7 @@ import { AccountList } from '../types/accountList.js'; export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() @@ -44,19 +44,13 @@ export default { ) : []; - await interaction.editReply({ - embeds: [ - infoEmbed( - `Player search for "${markdownEscape(name)}" in ${ - BLITZ_SERVERS[server] - }`, - `\`\`\`${ - players.length === 0 - ? 'No players found.' - : players.map((player) => player.nickname).join('\n') - }\`\`\``, - ), - ], - }); + return infoEmbed( + `Player search for "${markdownEscape(name)}" in ${BLITZ_SERVERS[server]}`, + `\`\`\`${ + players.length === 0 + ? 'No players found.' + : players.map((player) => player.nickname).join('\n') + }\`\`\``, + ); }, } satisfies CommandRegistry; diff --git a/src/commands/searchtanks.ts b/src/commands/searchtanks.ts index 2d525cdc0..77d716e08 100644 --- a/src/commands/searchtanks.ts +++ b/src/commands/searchtanks.ts @@ -9,7 +9,7 @@ import { CommandRegistry } from '../events/interactionCreate.js'; export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() @@ -31,15 +31,11 @@ export default { (result) => result.target, ); - await interaction.editReply({ - embeds: [ - infoEmbed( - `Tank search for "${markdownEscape(tank)}"`, - results.length === 0 - ? 'No tanks found.' - : `\`\`\`\n${results.join('\n')}\n\`\`\``, - ), - ], - }); + return infoEmbed( + `Tank search for "${markdownEscape(tank)}"`, + results.length === 0 + ? 'No tanks found.' + : `\`\`\`\n${results.join('\n')}\n\`\`\``, + ); }, } satisfies CommandRegistry; diff --git a/src/commands/stats.tsx b/src/commands/stats.tsx index 9939e2c20..e28b77218 100644 --- a/src/commands/stats.tsx +++ b/src/commands/stats.tsx @@ -1,8 +1,4 @@ -import { - ActionRowBuilder, - ButtonBuilder, - SlashCommandBuilder, -} from 'discord.js'; +import { SlashCommandBuilder } from 'discord.js'; import GenericAllStats from '../components/GenericAllStats.js'; import NoData, { NoDataType } from '../components/NoData.js'; import PoweredByBlitzStars from '../components/PoweredByBlitzStars.js'; @@ -29,7 +25,6 @@ import addStatPeriodChoices, { } from '../core/options/addStatPeriodChoices.js'; import addUsernameOption from '../core/options/addUsernameOption.js'; import { WARGAMING_APPLICATION_ID } from '../core/process/args.js'; -import render from '../core/ui/render.js'; import { CommandRegistry } from '../events/interactionCreate.js'; import { AccountInfo, @@ -40,7 +35,7 @@ import { PlayerClanData } from '../types/playerClanData.js'; export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() @@ -134,7 +129,7 @@ export default { if (!hasWN8AccumulatedAtAll) supplementaryStats.WN8 = undefined; - const image = await render( + return [ , - ); - - const actionRow = new ActionRowBuilder().addComponents( fullBlitzStarsStats(server, accountInfo[id].nickname), supportBlitzStars, - ); - - await interaction.editReply({ - files: [image], - components: [actionRow], - }); + ]; }, autocomplete: usernameAutocomplete, diff --git a/src/commands/tankstats.tsx b/src/commands/tankstats.tsx index baae75a9c..37c86f763 100644 --- a/src/commands/tankstats.tsx +++ b/src/commands/tankstats.tsx @@ -1,8 +1,4 @@ -import { - ActionRowBuilder, - ButtonBuilder, - SlashCommandBuilder, -} from 'discord.js'; +import { SlashCommandBuilder } from 'discord.js'; import GenericAllStats from '../components/GenericAllStats.js'; import NoData, { NoDataType } from '../components/NoData.js'; import PoweredByBlitzStars from '../components/PoweredByBlitzStars.js'; @@ -34,7 +30,6 @@ import addStatPeriodChoices, { import addTankChoices from '../core/options/addTankChoices.js'; import addUsernameOption from '../core/options/addUsernameOption.js'; import { WARGAMING_APPLICATION_ID } from '../core/process/args.js'; -import render from '../core/ui/render.js'; import { CommandRegistry } from '../events/interactionCreate.js'; import { AccountInfo, AllStats } from '../types/accountInfo.js'; @@ -81,7 +76,7 @@ export default { stats = tankStatsOverTime[tankId] ?? emptyAllStats; } - const image = await render( + return [ , - ); - - const actionRow = new ActionRowBuilder().addComponents( fullBlitzStarsStats(server, accountInfo[id].nickname), supportBlitzStars, - ); - - await interaction.editReply({ - files: [image], - components: [actionRow], - }); + ]; }, autocomplete: (interaction) => { diff --git a/src/commands/today.tsx b/src/commands/today.tsx index 887e3f27a..681b4ee1d 100644 --- a/src/commands/today.tsx +++ b/src/commands/today.tsx @@ -1,8 +1,4 @@ -import { - ActionRowBuilder, - ButtonBuilder, - SlashCommandBuilder, -} from 'discord.js'; +import { SlashCommandBuilder } from 'discord.js'; import * as Breakdown from '../components/Breakdown/index.js'; import NoData, { NoDataType } from '../components/NoData.js'; import PoweredByBlitzStars from '../components/PoweredByBlitzStars.js'; @@ -25,14 +21,13 @@ import fullBlitzStarsStats from '../core/interaction/fullBlitzStarsStats.js'; import { supportBlitzStars } from '../core/interaction/supportBlitzStars.js'; import addUsernameOption from '../core/options/addUsernameOption.js'; import { WARGAMING_APPLICATION_ID } from '../core/process/args.js'; -import render from '../core/ui/render.js'; import { CommandRegistry } from '../events/interactionCreate.js'; import { AccountInfo, AllStats } from '../types/accountInfo.js'; import { PlayerClanData } from '../types/playerClanData.js'; export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() @@ -159,7 +154,7 @@ export default { ); }); - const image = await render( + return [ , - ); - - const actionRow = new ActionRowBuilder().addComponents( fullBlitzStarsStats(server, accountInfo[id].nickname), supportBlitzStars, - ); - - await interaction.editReply({ - files: [image], - components: [actionRow], - }); + ]; }, autocomplete: usernameAutocomplete, diff --git a/src/commands/verify.ts b/src/commands/verify.ts index 7fbfdeabc..0f66939f3 100644 --- a/src/commands/verify.ts +++ b/src/commands/verify.ts @@ -1,11 +1,12 @@ -import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; +import { SlashCommandBuilder } from 'discord.js'; import markdownEscape from 'markdown-escape'; import discord from '../../discord.json' assert { type: 'json' }; -import { NEGATIVE_COLOR, POSITIVE_COLOR } from '../constants/colors.js'; import usernameAutocomplete from '../core/autocomplete/username.js'; import getBlitzAccount from '../core/blitz/getBlitzAccount.js'; import getWargamingResponse from '../core/blitz/getWargamingResponse.js'; import cmdName from '../core/interaction/cmdName.js'; +import negativeEmbed from '../core/interaction/negativeEmbed.js'; +import positiveEmbed from '../core/interaction/positiveEmbed.js'; import addUsernameOption from '../core/options/addUsernameOption.js'; import { WARGAMING_APPLICATION_ID } from '../core/process/args.js'; import { CommandRegistry } from '../events/interactionCreate.js'; @@ -14,7 +15,7 @@ import { PlayerClanData } from '../types/playerClanData.js'; export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() @@ -33,84 +34,49 @@ export default { ); const clan = clanData[id]?.clan; const clanTag = clan ? ` [${clan!.tag}]` : ''; + const member = + interaction.member && + interaction.guild?.members.cache.get(interaction.member?.user.id); if (!interaction.guild?.members.me?.permissions.has('ManageNicknames')) { - interaction.editReply({ - embeds: [ - new EmbedBuilder() - .setColor(NEGATIVE_COLOR) - .setTitle( - `${markdownEscape(interaction.user.username)} failed to verify`, - ) - .setDescription( - "I don't have the permission to change your nickname.", - ), - ], - }); - - return; + return negativeEmbed( + `${markdownEscape(interaction.user.username)} failed to verify`, + "I don't have the permission to change your nickname.", + ); + } + if (!interaction.member || !member) { + return negativeEmbed( + `${interaction.user.username} is not in this server`, + "I couldn't find this person in this server. Did they leave?", + ); } - if (interaction.member) { - const member = interaction.guild?.members.cache.get( - interaction.member?.user.id, - ); + try { + await member.setNickname(`${accountInfo[id].nickname}${clanTag}`); - if (member) { - try { - await member.setNickname(`${accountInfo[id].nickname}${clanTag}`); - - if (interaction.guildId === discord.sklld_guild_id) { - if ( - !interaction.guild?.members.me?.permissions.has('ManageRoles') - ) { - await interaction.editReply({ - embeds: [ - new EmbedBuilder() - .setColor(NEGATIVE_COLOR) - .setTitle( - `${markdownEscape( - interaction.user.username, - )} failed to verify`, - ) - .setDescription( - "I don't have the permission to change your manage roles.", - ), - ], - }); - - return; - } - - await member.roles.remove(discord.sklld_verify_role); - await member.roles.add(discord.sklld_peasant_role); - } - - await interaction.editReply({ - embeds: [ - new EmbedBuilder() - .setColor(POSITIVE_COLOR) - .setTitle(`${interaction.user.username} is verified`) - .setDescription( - `The user is now verified as ${markdownEscape( - accountInfo[id].nickname, - )}${markdownEscape(clanTag)}`, - ), - ], - }); - } catch (error) { - await interaction.editReply({ - embeds: [ - new EmbedBuilder() - .setColor(NEGATIVE_COLOR) - .setTitle(`${interaction.user.username} failed to verify`) - .setDescription( - "I can't change your nickname because you have higher permissions than me. Try setting your nickname to your Blitz username manually.", - ), - ], - }); + if (interaction.guildId === discord.sklld_guild_id) { + if (!interaction.guild?.members.me?.permissions.has('ManageRoles')) { + return negativeEmbed( + `${markdownEscape(interaction.user.username)} failed to verify`, + "I don't have the permission to change your manage roles.", + ); } + + await member.roles.remove(discord.sklld_verify_role); + await member.roles.add(discord.sklld_peasant_role); } + + return positiveEmbed( + `${interaction.user.username} is verified`, + `The user is now verified as ${markdownEscape( + accountInfo[id].nickname, + )}${markdownEscape(clanTag)}`, + ); + } catch (error) { + return negativeEmbed( + `${interaction.user.username} failed to verify`, + "I can't change your nickname because you have higher permissions than me. Try setting your nickname to your Blitz username manually.", + ); } }, diff --git a/src/core/process/psa.ts b/src/core/process/psa.ts new file mode 100644 index 000000000..f4ee1df95 --- /dev/null +++ b/src/core/process/psa.ts @@ -0,0 +1,20 @@ +export interface PSAData { + title: string; + description: string; +} + +export interface PSA { + data?: PSAData; +} + +export const psa: PSA = {}; + +console.log('Caching PSA...'); +fetch( + 'https://gist.githubusercontent.com/tresabhi/ed4b136f08856e615212e573aabe1968/raw', +).then((response) => { + response.json().then((data) => { + psa.data = data as PSAData; + }); + console.log('PSA cached'); +}); diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts index 37ec47d85..80d0d5ba6 100644 --- a/src/events/interactionCreate.ts +++ b/src/events/interactionCreate.ts @@ -5,7 +5,9 @@ import { ButtonStyle, CacheType, ChatInputCommandInteraction, + EmbedBuilder, Interaction, + InteractionEditReplyOptions, REST, RESTPostAPIChatInputApplicationCommandsJSONBody, Routes, @@ -30,36 +32,44 @@ import negativeEmbed from '../core/interaction/negativeEmbed.js'; import { DISCORD_TOKEN } from '../core/process/args.js'; import getClientId from '../core/process/getClientId.js'; import isDev from '../core/process/isDev.js'; +import render from '../core/ui/render.js'; import { handleError } from './error.js'; +export type CommandReturnable = EmbedBuilder | ButtonBuilder | JSX.Element; +export type RichCommandReturnable = CommandReturnable | CommandReturnable[]; + export interface CommandRegistry { inDevelopment: boolean; inProduction: boolean; inPublic: boolean; command: Omit; - execute: (interaction: ChatInputCommandInteraction) => void; + execute: ( + interaction: ChatInputCommandInteraction, + ) => RichCommandReturnable | Promise; autocomplete?: (interaction: AutocompleteInteraction) => void; } const rest = new REST().setToken(DISCORD_TOKEN); -const commands = [ - debug, - eligible, - help, - inactive, - ownedtanks, - playerachievements, - playerinfo, - searchclans, - searchplayers, - searchtanks, - stats, - tankstats, - today, - verify, -].reduce>((accumulator, registry) => { +const commands = ( + [ + debug, + eligible, + help, + inactive, + ownedtanks, + playerachievements, + playerinfo, + searchclans, + searchplayers, + searchtanks, + stats, + tankstats, + today, + verify, + ] as CommandRegistry[] +).reduce>((accumulator, registry) => { return { ...accumulator, [registry.command.name]: registry }; }, {}); @@ -138,7 +148,29 @@ export default async function interactionCreate( await interaction.deferReply(); try { - await command.execute(interaction); + const result = await command.execute(interaction); + const reply: InteractionEditReplyOptions = {}; + + await Promise.all( + (Array.isArray(result) ? result : [result]).map(async (item) => { + if (item instanceof EmbedBuilder) { + if (!reply.embeds) reply.embeds = []; + reply.embeds.push(item); + } else if (item instanceof ButtonBuilder) { + if (!reply.components) + reply.components = [new ActionRowBuilder()]; + ( + reply.components[0] as ActionRowBuilder + ).addComponents(item); + } else { + const image = await render(item); + if (!reply.files) reply.files = []; + reply.files.push(image); + } + }), + ); + + await interaction.editReply(reply); } catch (error) { const actionRow = new ActionRowBuilder().addComponents( new ButtonBuilder()