diff --git a/package.json b/package.json index 88b6e7c33..7731d05e9 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,12 @@ "dependencies": { "@types/node": "^18.15.11", "discord.js": "^14.9.0", + "markdown-escape": "^2.0.0", "node-fetch": "^3.3.1", "typescript": "^5.0.4", "vite-node": "^0.30.1" + }, + "devDependencies": { + "@types/markdown-escape": "^1.1.0" } } diff --git a/src/commands/eligible.ts b/src/commands/eligible.ts index c970de214..b83c4456e 100644 --- a/src/commands/eligible.ts +++ b/src/commands/eligible.ts @@ -1,4 +1,5 @@ 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'; @@ -108,7 +109,7 @@ export default { poweredByBlitzStars( new EmbedBuilder() .setTitle( - `${data.nickname} is ${ + `${markdownEscape(data.nickname)} is ${ eligible ? '' : 'not ' }eligible for ${CLANS[clan].name}`, ) @@ -116,10 +117,14 @@ export default { .setDescription( `${ eligible - ? `${data.nickname} meets all the requirements set for ${CLANS[clan].name}.` - : `${data.nickname}'s shortcomings for ${ + ? `${markdownEscape( + data.nickname, + )} meets all the requirements set for ${ CLANS[clan].name - } (${ + }.` + : `${markdownEscape( + data.nickname, + )}'s shortcomings for ${CLANS[clan].name} (${ clan === 'sklld' ? '30 days stats' : 'career stats' }):\n\n${issues.join('\n')}` }\n\n${blitzLinks(data)}`, diff --git a/src/commands/inactive.ts b/src/commands/inactive.ts index 4787a3787..d05cd83f6 100644 --- a/src/commands/inactive.ts +++ b/src/commands/inactive.ts @@ -1,4 +1,5 @@ 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'; @@ -68,7 +69,9 @@ export default { .sort((a, b) => b[1] - a[1]) .map(([nickname, inactiveDays]) => { const days = Math.floor(inactiveDays); - return `**${nickname}**: ${days} day${days === 1 ? '' : 's'}`; + return `**${markdownEscape(nickname)}**: ${days} day${ + days === 1 ? '' : 's' + }`; }); const hasInactiveMembers = inactiveInfo.length > 0; @@ -80,8 +83,8 @@ export default { ) .setTitle( hasInactiveMembers - ? `${clan.name}'s inactive members` - : `No inactive members in ${clan.name}`, + ? `${markdownEscape(clan.name)}'s inactive members` + : `No inactive members in ${markdownEscape(clan.name)}`, ) .setDescription( hasInactiveMembers diff --git a/src/commands/searchplayers.ts b/src/commands/searchplayers.ts index 901e54504..89d857008 100644 --- a/src/commands/searchplayers.ts +++ b/src/commands/searchplayers.ts @@ -1,4 +1,5 @@ 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 { Players } from '../types/players.js'; @@ -38,12 +39,14 @@ export default { embeds: [ new EmbedBuilder() .setColor(SKILLED_COLOR) - .setTitle(`Player search results for "${name}"`) + .setTitle(`Player search results for "${markdownEscape(name)}"`) .setDescription( `\`\`\`${ players.length === 0 ? 'No players found.' - : players.map((player) => player.nickname).join('\n') + : players + .map((player) => markdownEscape(player.nickname)) + .join('\n') }\`\`\``, ), ], diff --git a/src/commands/stats.ts b/src/commands/stats.ts index 4120fff80..82f285416 100644 --- a/src/commands/stats.ts +++ b/src/commands/stats.ts @@ -1,4 +1,5 @@ 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'; @@ -55,7 +56,7 @@ export default { new EmbedBuilder() .setColor(SKILLED_COLOR) .setTitle( - `${data.nickname}'s ${ + `${markdownEscape(data.nickname)}'s ${ period === 'career' ? period : `${period} day` } stats`, ) diff --git a/src/commands/tanks.ts b/src/commands/tanks.ts index e44ac3498..faceaf31b 100644 --- a/src/commands/tanks.ts +++ b/src/commands/tanks.ts @@ -1,4 +1,5 @@ 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'; @@ -68,20 +69,20 @@ export default { embeds: [ new EmbedBuilder() .setTitle( - `${account.nickname}'s owned ${ + `${markdownEscape(account.nickname)}'s owned ${ tier === null ? '' : `tier ${tier} ` }tanks`, ) .setDescription( `${ tanks.length === 0 - ? `No tanks found for player in tier ${tier}` + ? `No tanks found in tier ${tier}` : tanks .map( (tank) => - `${TANK_TYPE_EMOJIS[tank.type]} ${tank.name} ${ - tank.is_premium ? '⭐' : '' - }${ + `${TANK_TYPE_EMOJIS[tank.type]} ${markdownEscape( + tank.name, + )} ${tank.is_premium ? '⭐' : ''}${ COMP_TANKS.includes(tank.tank_id) ? '🏆' : '' }`, ) diff --git a/src/commands/verify.ts b/src/commands/verify.ts index 4fad9688c..5e6702b38 100644 --- a/src/commands/verify.ts +++ b/src/commands/verify.ts @@ -1,4 +1,5 @@ import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; +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'; @@ -52,7 +53,9 @@ export default { .setColor(POSITIVE_COLOR) .setTitle(`${interaction.user.username} is verified`) .setDescription( - `The user is now verified as ${name}${clanTag}`, + `The user is now verified as ${markdownEscape( + name, + )}${markdownEscape(clanTag)}`, ), ], }); @@ -66,7 +69,11 @@ export default { embeds: [ new EmbedBuilder() .setColor(NEGATIVE_COLOR) - .setTitle(`${interaction.user.username} failed to verify`) + .setTitle( + `${markdownEscape( + interaction.user.username, + )} failed to verify`, + ) .setDescription( 'I may not have the permission to change your nickname.', ), diff --git a/src/utilities/getBlitzAccount.ts b/src/utilities/getBlitzAccount.ts index aff068bff..77c0264f2 100644 --- a/src/utilities/getBlitzAccount.ts +++ b/src/utilities/getBlitzAccount.ts @@ -3,6 +3,7 @@ import { ChatInputCommandInteraction, EmbedBuilder, } from 'discord.js'; +import markdownEscape from 'markdown-escape'; import { NEGATIVE_COLOR } from '../constants/colors.js'; import { BLITZ_SERVERS, BlitzServer } from '../constants/servers.js'; import { Player, Players } from '../types/players.js'; @@ -21,7 +22,10 @@ export default async function getBlitzAccount( `https://api.wotblitz.${server}/wotb/account/list/?application_id=${args['wargaming-application-id']}&search=${name}`, interaction, async (players) => { - if (players.length > 0 && players[0].nickname === name) { + if ( + players.length > 0 && + players[0].nickname.toLowerCase() === name.toLowerCase() + ) { callback(players[0]); } else { // no exact match @@ -31,7 +35,9 @@ export default async function getBlitzAccount( .setColor(NEGATIVE_COLOR) .setTitle(`Account not found`) .setDescription( - `I couldn't find "${name}" in the ${serverName} server. I found ${ + `I couldn't find "${markdownEscape( + name, + )}" in the ${serverName} server. I found ${ players ? players.length < 100 ? players.length @@ -41,9 +47,9 @@ export default async function getBlitzAccount( players?.length !== 1 ? 's' : '' }. ${ players && players.length > 0 - ? `Did you mean "${players[0].nickname}"? ` + ? `Did you mean "${markdownEscape(players[0].nickname)}"? ` : '' - }Re-run the command, don't make typos, and capitalize correctly.`, + }Re-run the command and don't make typos.`, ), ], }); diff --git a/src/utilities/getBlitzStarsAccount.ts b/src/utilities/getBlitzStarsAccount.ts index 57ad2e56e..cb82601d1 100644 --- a/src/utilities/getBlitzStarsAccount.ts +++ b/src/utilities/getBlitzStarsAccount.ts @@ -3,6 +3,7 @@ import { ChatInputCommandInteraction, EmbedBuilder, } from 'discord.js'; +import markdownEscape from 'markdown-escape'; import fetch from 'node-fetch'; import { NEGATIVE_COLOR } from '../constants/colors.js'; import { PlayerStatistics } from '../types/statistics.js'; @@ -20,7 +21,9 @@ export default async function getBlitzStarsAccount( embeds: [ new EmbedBuilder() .setTitle('No data to display') - .setDescription(`${name} is not tracked by BlitzStars.`) + .setDescription( + `${markdownEscape(name)} is not tracked by BlitzStars.`, + ) .setColor(NEGATIVE_COLOR), ], }); diff --git a/src/utilities/getClan.ts b/src/utilities/getClan.ts index a6209de61..4a194703b 100644 --- a/src/utilities/getClan.ts +++ b/src/utilities/getClan.ts @@ -3,6 +3,7 @@ import { ChatInputCommandInteraction, EmbedBuilder, } from 'discord.js'; +import markdownEscape from 'markdown-escape'; import { NEGATIVE_COLOR } from '../constants/colors.js'; import { BLITZ_SERVERS, BlitzServer } from '../constants/servers.js'; import { Clan, ClanList } from '../types/clanList.js'; @@ -23,7 +24,8 @@ export default async function getClan( async (clans) => { if ( clans.length > 0 && - (clans[0].name === name || clans[0].tag === name.toUpperCase()) + (clans[0].name.toLowerCase() === name.toLowerCase() || + clans[0].tag.toLowerCase() === name.toLowerCase()) ) { callback(clans[0]); } else { @@ -34,13 +36,17 @@ export default async function getClan( .setColor(NEGATIVE_COLOR) .setTitle(`Clan not found`) .setDescription( - `I couldn't find "${name}" in the ${serverName} server. I found ${ + `I couldn't find "${markdownEscape( + name, + )}" in the ${serverName} server. I found ${ clans ? (clans.length < 100 ? clans.length : 'over 100') : 0 } similarly spelled clan${clans?.length !== 1 ? 's' : ''}. ${ clans && clans.length > 0 - ? `Did you mean "${clans[0].name}" or "${clans[0].tag}"? ` + ? `Did you mean "${markdownEscape( + clans[0].name, + )}" or "${markdownEscape(clans[0].tag)}"? ` : '' - }Re-run the command, don't make typos, and capitalize correctly.`, + }Re-run the command, don't make typos.`, ), ], }); diff --git a/yarn.lock b/yarn.lock index 53f371bb5..104cb6901 100644 --- a/yarn.lock +++ b/yarn.lock @@ -179,6 +179,11 @@ resolved "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz" integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A== +"@types/markdown-escape@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/markdown-escape/-/markdown-escape-1.1.0.tgz#8bd940d6701880eb7229467542c029bc05a7b22f" + integrity sha512-bJZh73L6fSt8MmTON/btR8hiKRipoIoPfLO41lxr6l65QXdG1rwUjR8Hu5xU7XYHBwKHiJZ+sTQ8L2TKkQrBpw== + "@types/node@*", "@types/node@^18.15.11": version "18.15.11" resolved "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz" @@ -331,6 +336,11 @@ lodash@^4.17.21: resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +markdown-escape@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/markdown-escape/-/markdown-escape-2.0.0.tgz#44484d30d7845b91575c77fd8898f23a0a6f890c" + integrity sha512-Trz4v0+XWlwy68LJIyw3bLbsJiC8XAbRCKF9DbEtZjyndKOGVx6n+wNB0VfoRmY2LKboQLeniap3xrb6LGSJ8A== + mlly@^1.1.1, mlly@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.2.0.tgz#f0f6c2fc8d2d12ea6907cd869066689b5031b613"