mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-22 03:07:04 +02:00
feat: more command locales
This commit is contained in:
1 parent
38ca1499e2
commit
b3a50f2b27
11 files changed
+185
-78
No files matched your search
@@ -1,4 +1,3 @@
|
||||
import { SlashCommandBuilder } from 'discord.js';
|
||||
import CommandWrapper from '../components/CommandWrapper';
|
||||
import NoData from '../components/NoData';
|
||||
import * as Tanks from '../components/Tanks';
|
||||
@@ -18,7 +17,9 @@ import { tankIcon } from '../core/blitzkrieg/tankIcon';
|
||||
import addTierChoices from '../core/discord/addTierChoices';
|
||||
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
||||
import autocompleteUsername from '../core/discord/autocompleteUsername';
|
||||
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||
import { translator } from '../core/localization/translator';
|
||||
import { CommandRegistry } from '../events/interactionCreate';
|
||||
|
||||
export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
@@ -26,13 +27,12 @@ export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
inProduction: true,
|
||||
inPublic: true,
|
||||
|
||||
command: new SlashCommandBuilder()
|
||||
.setName('owned-tanks')
|
||||
.setDescription("Shows a player's owned tanks")
|
||||
command: createLocalizedCommand('owned-tanks')
|
||||
.addStringOption(addTierChoices)
|
||||
.addStringOption(addUsernameChoices),
|
||||
|
||||
async handler(interaction) {
|
||||
const { translate } = translator(interaction.locale);
|
||||
const tier = Number(interaction.options.getString('tier'));
|
||||
const account = await resolvePlayerFromCommand(interaction);
|
||||
const { id, region: server } = account;
|
||||
@@ -70,7 +70,9 @@ export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
? emblemIdToURL(clanAccountInfo.clan.emblem_set_id)
|
||||
: undefined
|
||||
}
|
||||
description={`Tier ${TIER_ROMAN_NUMERALS[tier as Tier]} tanks`}
|
||||
description={translate('bot.commands.owned_tanks.body.subtitle', [
|
||||
TIER_ROMAN_NUMERALS[tier as Tier],
|
||||
])}
|
||||
/>
|
||||
|
||||
{filteredTanks.length === 0 && (
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { SlashCommandBuilder } from 'discord.js';
|
||||
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
||||
import { translator } from '../core/localization/translator';
|
||||
import { CommandRegistry } from '../events/interactionCreate';
|
||||
|
||||
export const permissionsCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
@@ -6,26 +7,25 @@ export const permissionsCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
inProduction: true,
|
||||
inPublic: true,
|
||||
|
||||
command: new SlashCommandBuilder()
|
||||
.setName('permissions')
|
||||
.setDescription('Checks wether the bot has the required permissions'),
|
||||
command: createLocalizedCommand('permissions'),
|
||||
|
||||
async handler(interaction) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
// friday the 13th permissions easter egg
|
||||
const isFridayThe13th =
|
||||
new Date().getDay() === 5 && new Date().getDate() === 13;
|
||||
const permissions = [
|
||||
[
|
||||
interaction.appPermissions?.has('ViewChannel'),
|
||||
'View channels: needed for the refresh button to work',
|
||||
t`bot.commands.permissions.body.view_channel`,
|
||||
],
|
||||
[
|
||||
interaction.appPermissions?.has('ReadMessageHistory'),
|
||||
'Read message history: also needed for the refresh button to work',
|
||||
t`bot.commands.permissions.body.read_message_history`,
|
||||
],
|
||||
[
|
||||
interaction.appPermissions?.has('AttachFiles'),
|
||||
'Attach files: needed for image-based commands to work',
|
||||
t`bot.commands.permissions.body.attach_files`,
|
||||
],
|
||||
];
|
||||
const body = permissions
|
||||
@@ -38,7 +38,7 @@ export const permissionsCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
return `# Permissions\n${body}`;
|
||||
return translate('bot.commands.permissions.body.title', [body]);
|
||||
},
|
||||
});
|
||||
});
|
||||
+13
-12
@@ -1,4 +1,5 @@
|
||||
import { SlashCommandBuilder } from 'discord.js';
|
||||
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
||||
import { translator } from '../core/localization/translator';
|
||||
import { CommandRegistry } from '../events/interactionCreate';
|
||||
|
||||
export const pingCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
@@ -7,28 +8,28 @@ export const pingCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
inPublic: true,
|
||||
handlesInteraction: true,
|
||||
|
||||
command: new SlashCommandBuilder()
|
||||
.setName('ping')
|
||||
.setDescription('Check if the bot is alive')
|
||||
.addSubcommand((option) =>
|
||||
option.setName('blitzkrieg').setDescription('Ping Blitzkrieg'),
|
||||
)
|
||||
.addSubcommand((option) =>
|
||||
option.setName('blitz').setDescription('Ping Blitz'),
|
||||
),
|
||||
command: createLocalizedCommand('ping', [
|
||||
{ subcommand: 'blitzkrieg' },
|
||||
{ subcommand: 'wotb' },
|
||||
]),
|
||||
|
||||
async handler(interaction) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const subcommand = interaction.options.getSubcommand();
|
||||
const executionStart = Date.now();
|
||||
|
||||
if (subcommand === 'blitzkrieg') {
|
||||
await interaction.editReply('Pong 🏓');
|
||||
await interaction.editReply(t`bot.commands.ping.body.pong`);
|
||||
} else {
|
||||
await fetch('https://api.wotblitz.com/');
|
||||
}
|
||||
|
||||
const executionTime = Date.now() - executionStart;
|
||||
interaction.editReply(`Pong 🏓 - ${executionTime}ms`);
|
||||
interaction.editReply(
|
||||
translate('bot.commands.ping.body.pong_with_time', [
|
||||
`${Math.round(executionTime)}`,
|
||||
]),
|
||||
);
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -256,6 +256,8 @@ export const ratingsCommand = new Promise<CommandRegistry>(async (resolve) => {
|
||||
},
|
||||
]),
|
||||
|
||||
// BIG TODO: title seems to be in english
|
||||
|
||||
async handler(interaction) {
|
||||
const { t, translate } = translator(interaction.locale);
|
||||
const subcommand = interaction.options.getSubcommand(true) as
|
||||
|
||||
@@ -51,6 +51,7 @@ export const searchPlayersCommand = new Promise<CommandRegistry>((resolve) => {
|
||||
),
|
||||
|
||||
async handler(interaction) {
|
||||
const { translate } = translator(interaction.locale);
|
||||
const server = interaction.options.getString('region') as Region;
|
||||
const name = interaction.options.getString('username')!;
|
||||
const limit = interaction.options.getInteger('limit') ?? 25;
|
||||
|
||||
+11
-10
@@ -1,4 +1,4 @@
|
||||
import { Locale, SlashCommandBuilder } from 'discord.js';
|
||||
import { Locale } from 'discord.js';
|
||||
import AllStatsOverview from '../components/AllStatsOverview';
|
||||
import CommandWrapper from '../components/CommandWrapper';
|
||||
import NoData from '../components/NoData';
|
||||
@@ -15,6 +15,7 @@ import autocompleteTanks from '../core/discord/autocompleteTanks';
|
||||
import autocompleteUsername from '../core/discord/autocompleteUsername';
|
||||
import { buttonRefresh } from '../core/discord/buttonRefresh';
|
||||
import commandToURL from '../core/discord/commandToURL';
|
||||
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
||||
import { getCustomPeriodParams } from '../core/discord/getCustomPeriodParams';
|
||||
import { getFiltersFromButton } from '../core/discord/getFiltersFromButton';
|
||||
import { getFiltersFromCommand } from '../core/discord/getFiltersFromCommand';
|
||||
@@ -52,25 +53,25 @@ async function render(
|
||||
|
||||
{!stats.battles && <NoData type="battles_in_period" locale={locale} />}
|
||||
{stats.battles > 0 && (
|
||||
<AllStatsOverview stats={stats} supplementaryStats={supplementary} />
|
||||
<AllStatsOverview
|
||||
locale={locale}
|
||||
stats={stats}
|
||||
supplementaryStats={supplementary}
|
||||
/>
|
||||
)}
|
||||
</CommandWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export const statsCommand = new Promise<CommandRegistry>(async (resolve) => {
|
||||
const command = await addPeriodicFilterOptions(
|
||||
new SlashCommandBuilder()
|
||||
.setName('stats')
|
||||
.setDescription('Regular battles statistics'),
|
||||
(option) => option.addStringOption(addUsernameChoices),
|
||||
);
|
||||
|
||||
resolve({
|
||||
inProduction: true,
|
||||
inPublic: true,
|
||||
|
||||
command,
|
||||
command: await addPeriodicFilterOptions(
|
||||
createLocalizedCommand('stats'),
|
||||
(option) => option.addStringOption(addUsernameChoices),
|
||||
),
|
||||
|
||||
async handler(interaction) {
|
||||
const player = await resolvePlayerFromCommand(interaction);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { SlashCommandBuilder } from 'discord.js';
|
||||
import { NATIONS } from '../core/blitzkrieg/tankDefinitions';
|
||||
import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton';
|
||||
import { addFilterOptions } from '../core/discord/addFilterOptions';
|
||||
@@ -7,6 +6,7 @@ import autocompleteTanks from '../core/discord/autocompleteTanks';
|
||||
import autocompleteUsername from '../core/discord/autocompleteUsername';
|
||||
import { buttonRefresh } from '../core/discord/buttonRefresh';
|
||||
import commandToURL from '../core/discord/commandToURL';
|
||||
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
||||
import { getCustomPeriodParams } from '../core/discord/getCustomPeriodParams';
|
||||
import { getFiltersFromButton } from '../core/discord/getFiltersFromButton';
|
||||
import { getFiltersFromCommand } from '../core/discord/getFiltersFromCommand';
|
||||
@@ -19,18 +19,14 @@ import { renderBreakdown } from './breakdown';
|
||||
|
||||
export const todayCommand = new Promise<CommandRegistry>(async (resolve) => {
|
||||
const nations = await NATIONS;
|
||||
const command = addFilterOptions(
|
||||
new SlashCommandBuilder()
|
||||
.setName('today')
|
||||
.setDescription("Today's played tanks and statistics"),
|
||||
nations,
|
||||
).addStringOption(addUsernameChoices);
|
||||
|
||||
resolve({
|
||||
inProduction: true,
|
||||
inPublic: true,
|
||||
|
||||
command,
|
||||
command: addFilterOptions(
|
||||
createLocalizedCommand('today'),
|
||||
nations,
|
||||
).addStringOption(addUsernameChoices),
|
||||
|
||||
async handler(interaction) {
|
||||
const player = await resolvePlayerFromCommand(interaction);
|
||||
|
||||
@@ -1,30 +1,21 @@
|
||||
import { Locale } from 'discord.js';
|
||||
import { Percentile } from '../../../../constants/percentiles';
|
||||
import { translator } from '../../../../core/localization/translator';
|
||||
import getWN8Percentile from '../../../../core/statistics/getWN8Percentile';
|
||||
import { theme } from '../../../../stitches.config';
|
||||
import { PERCENTILE_COLORS } from '../../../PercentileIndicator';
|
||||
import { Glow } from './components/Glow';
|
||||
|
||||
export interface WN8DisplayProps {
|
||||
WN8?: number;
|
||||
wn8?: number;
|
||||
locale: Locale;
|
||||
}
|
||||
|
||||
export const PERCENTILE_NAMES = {
|
||||
[Percentile.VeryBad]: 'Very Bad',
|
||||
[Percentile.Bad]: 'Bad',
|
||||
[Percentile.BelowAverage]: 'Below Average',
|
||||
[Percentile.Average]: 'Average',
|
||||
[Percentile.AboveAverage]: 'Above Average',
|
||||
[Percentile.Good]: 'Good',
|
||||
[Percentile.VeryGood]: 'Very Good',
|
||||
[Percentile.Great]: 'Great',
|
||||
[Percentile.Unicum]: 'Unicum',
|
||||
[Percentile.SuperUnicum]: 'Super Unicum',
|
||||
};
|
||||
|
||||
export function WN8Display({ WN8 }: WN8DisplayProps) {
|
||||
export function WN8Display({ wn8, locale }: WN8DisplayProps) {
|
||||
const percentile =
|
||||
WN8 === undefined ? Percentile.VeryBad : getWN8Percentile(WN8);
|
||||
wn8 === undefined ? Percentile.VeryBad : getWN8Percentile(wn8);
|
||||
const color = PERCENTILE_COLORS[percentile];
|
||||
const { translate } = translator(locale);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -59,7 +50,7 @@ export function WN8Display({ WN8 }: WN8DisplayProps) {
|
||||
color: theme.colors.textHighContrast,
|
||||
}}
|
||||
>
|
||||
{WN8 === undefined ? '--' : WN8.toFixed(0)}
|
||||
{wn8 === undefined ? '--' : wn8.toFixed(0)}
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
@@ -67,7 +58,7 @@ export function WN8Display({ WN8 }: WN8DisplayProps) {
|
||||
color: theme.colors.textHighContrast,
|
||||
}}
|
||||
>
|
||||
{PERCENTILE_NAMES[percentile]}
|
||||
{translate(`common.wn8_percentile.${percentile}`)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { Locale } from 'discord.js';
|
||||
import { AllStats, SupplementaryStats } from '../../core/blitz/getAccountInfo';
|
||||
import { translator } from '../../core/localization/translator';
|
||||
import { WN8Display } from './components/WN8Display';
|
||||
import {
|
||||
WN8SurroundingStat,
|
||||
@@ -8,12 +10,16 @@ import {
|
||||
export interface AllStatsOverviewProps {
|
||||
stats: AllStats;
|
||||
supplementaryStats: SupplementaryStats;
|
||||
locale: Locale;
|
||||
}
|
||||
|
||||
export default function AllStatsOverview({
|
||||
stats,
|
||||
locale,
|
||||
supplementaryStats,
|
||||
}: AllStatsOverviewProps) {
|
||||
const { t } = translator(locale);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -32,18 +38,18 @@ export default function AllStatsOverview({
|
||||
}}
|
||||
>
|
||||
<WN8SurroundingStat
|
||||
label="Battles"
|
||||
label={t`bot.commands.stats.body.battles`}
|
||||
value={stats.battles.toLocaleString()}
|
||||
align={WN8SurroundingStatAlign.Right}
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label="Winrate"
|
||||
label={t`bot.commands.stats.body.winrate`}
|
||||
value={`${(100 * (stats.wins / stats.battles)).toFixed(2)}%`}
|
||||
align={WN8SurroundingStatAlign.Right}
|
||||
padded
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label="Damage"
|
||||
label={t`bot.commands.stats.body.damage`}
|
||||
value={Math.round(
|
||||
stats.damage_dealt / stats.battles,
|
||||
).toLocaleString()}
|
||||
@@ -51,13 +57,13 @@ export default function AllStatsOverview({
|
||||
padded
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label="Dmg. ratio"
|
||||
label={t`bot.commands.stats.body.damage_ratio`}
|
||||
value={(stats.damage_dealt / stats.damage_received).toFixed(2)}
|
||||
align={WN8SurroundingStatAlign.Right}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<WN8Display WN8={supplementaryStats.WN8} />
|
||||
<WN8Display locale={locale} wn8={supplementaryStats.WN8} />
|
||||
|
||||
<div
|
||||
style={{
|
||||
@@ -68,25 +74,25 @@ export default function AllStatsOverview({
|
||||
}}
|
||||
>
|
||||
<WN8SurroundingStat
|
||||
label="Tier"
|
||||
label={t`bot.commands.stats.body.tier`}
|
||||
value={
|
||||
supplementaryStats.tier ? supplementaryStats.tier.toFixed(2) : '--'
|
||||
}
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label="Survival"
|
||||
label={t`bot.commands.stats.body.survival`}
|
||||
value={`${(100 * (stats.survived_battles / stats.battles)).toFixed(
|
||||
2,
|
||||
)}%`}
|
||||
padded
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label="Accuracy"
|
||||
label={t`bot.commands.stats.body.accuracy`}
|
||||
value={`${(100 * (stats.hits / stats.shots)).toFixed(2)}%`}
|
||||
padded
|
||||
/>
|
||||
<WN8SurroundingStat
|
||||
label="Kill ratio"
|
||||
label={t`bot.commands.stats.body.kill_ratio`}
|
||||
value={(
|
||||
stats.frags /
|
||||
(stats.battles - stats.survived_battles)
|
||||
|
||||
@@ -1,16 +1,38 @@
|
||||
import { SlashCommandStringOption } from 'discord.js';
|
||||
import {
|
||||
APIApplicationCommandOptionChoice,
|
||||
Locale,
|
||||
SlashCommandStringOption,
|
||||
} from 'discord.js';
|
||||
import { range } from 'lodash';
|
||||
import { translator } from '../localization/translator';
|
||||
import numberToRomanNumeral from '../math/numberToRomanNumeral';
|
||||
import { localizationObject } from './localizationObject';
|
||||
|
||||
export default function addTierChoices(option: SlashCommandStringOption) {
|
||||
const { t, translate } = translator(Locale.EnglishUS);
|
||||
|
||||
return option
|
||||
.setName('tier')
|
||||
.setDescription('The tier you want to see')
|
||||
.setName(t`bot.common.options.tier`)
|
||||
.setNameLocalizations(localizationObject('bot.common.options.tier'))
|
||||
.setDescription(t`bot.common.options.tier.description`)
|
||||
.setDescriptionLocalizations(
|
||||
localizationObject('bot.common.options.tier.description'),
|
||||
)
|
||||
.setChoices(
|
||||
...range(10, 0).map((tier) => ({
|
||||
name: `Tier ${tier} - ${numberToRomanNumeral(tier)}`,
|
||||
value: `${tier}`,
|
||||
})),
|
||||
...range(10, 0).map(
|
||||
(tier) =>
|
||||
({
|
||||
name: translate('bot.common.options.tier.choices.tier', [
|
||||
`${tier}`,
|
||||
numberToRomanNumeral(tier),
|
||||
]),
|
||||
value: `${tier}`,
|
||||
name_localizations: localizationObject(
|
||||
'bot.common.options.tier.choices.tier',
|
||||
[`${tier}`, numberToRomanNumeral(tier)],
|
||||
),
|
||||
}) satisfies APIApplicationCommandOptionChoice,
|
||||
),
|
||||
)
|
||||
.setRequired(true);
|
||||
}
|
||||
@@ -1,5 +1,18 @@
|
||||
{
|
||||
"common": {
|
||||
"wn8_percentile": {
|
||||
"0": "Very bad",
|
||||
"1": "Bad",
|
||||
"2": "Below average",
|
||||
"3": "Average",
|
||||
"4": "Above average",
|
||||
"5": "Good",
|
||||
"6": "Very good",
|
||||
"7": "Great",
|
||||
"8": "Unicum",
|
||||
"9": "Super unicum"
|
||||
},
|
||||
|
||||
"nations": {
|
||||
"ussr": "U.S.S.R.",
|
||||
"germany": "Germany",
|
||||
@@ -135,6 +148,15 @@
|
||||
"region": {
|
||||
"$": "region",
|
||||
"description": "Region"
|
||||
},
|
||||
|
||||
"tier": {
|
||||
"$": "tier",
|
||||
"description": "Tier",
|
||||
|
||||
"choices": {
|
||||
"tier": "Tier %s - %s"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -386,6 +408,69 @@
|
||||
"neighbors": "Ratings neighbors",
|
||||
"more": "+%s more"
|
||||
}
|
||||
},
|
||||
|
||||
"today": {
|
||||
"$": "today",
|
||||
"description": "Today's played tanks and statistics"
|
||||
},
|
||||
|
||||
"stats": {
|
||||
"$": "stats",
|
||||
"description": "Quick statistics for a period",
|
||||
|
||||
"body": {
|
||||
"battles": "Battles",
|
||||
"winrate": "Winrate",
|
||||
"damage": "Damage",
|
||||
"damage_ratio": "Damage ratio",
|
||||
"tier": "Tier",
|
||||
"survival": "Survival",
|
||||
"accuracy": "Accuracy",
|
||||
"kill_ratio": "Kill ratio"
|
||||
}
|
||||
},
|
||||
|
||||
"owned_tanks": {
|
||||
"$": "owned-tanks",
|
||||
"description": "Shows all own tanks in a tier",
|
||||
|
||||
"body": {
|
||||
"subtitle": "Tier %s tanks"
|
||||
}
|
||||
},
|
||||
|
||||
"permissions": {
|
||||
"$": "permissions",
|
||||
"description": "Checks wether the bot has the required permissions to function",
|
||||
|
||||
"body": {
|
||||
"title": "# Permissions\n\n%s",
|
||||
"view_channels": "View channels: needed for the refresh button to work",
|
||||
"read_message_history": "Read message history: needed for the refresh button to find the message to refresh",
|
||||
"attach_files": "Attach files: needed for image-based commands to work"
|
||||
}
|
||||
},
|
||||
|
||||
"ping": {
|
||||
"$": "ping",
|
||||
"description": "Check wether the bot is alive.",
|
||||
|
||||
"body": {
|
||||
"pong": "Pong 🏓",
|
||||
"pong_with_time": "Pong 🏓 - %sms"
|
||||
},
|
||||
|
||||
"subcommands": {
|
||||
"blitzkrieg": {
|
||||
"$": "blitzkrieg",
|
||||
"description": "Ping Blitzkrieg"
|
||||
},
|
||||
"wotb": {
|
||||
"$": "wotb",
|
||||
"description": "Ping World of Tanks Blitz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user