feat: some progress

This commit is contained in:
TrèsAbhi committed 2025-10-01 22:45:21 -05:00
1 parent 3d69d464f5
commit 5594c0ec3b
7 files changed
+270 -271

No files matched your search

+22 -22
View File
@@ -5,31 +5,31 @@ import {
flags, flags,
getAccountInfo, getAccountInfo,
getTankStats, getTankStats,
} from '@blitzkit/core'; } from "@blitzkit/core";
import { literals } from '@blitzkit/i18n'; import { literals } from "@blitzkit/i18n";
import markdownEscape from 'markdown-escape'; import markdownEscape from "markdown-escape";
import { import {
gameDefinitions, gameDefinitions,
tankDefinitions, tankDefinitions,
} from '../core/blitzkit/nonBlockingPromises'; } from "../core/blitzkit/nonBlockingPromises";
import { addTierChoices } from '../core/discord/addTierChoices'; import { addTierChoices } from "../core/discord/addTierChoices";
import { addUsernameChoices } from '../core/discord/addUsernameChoices'; import { addUsernameChoices } from "../core/discord/addUsernameChoices";
import { autocompleteUsername } from '../core/discord/autocompleteUsername'; import { autocompleteUsername } from "../core/discord/autocompleteUsername";
import { chunkLines } from '../core/discord/chunkLines'; import { chunkLines } from "../core/discord/chunkLines";
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand'; import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand";
import { translator } from '../core/localization/translator'; import { translator } from "../core/localization/translator";
import { CommandRegistry } from '../events/interactionCreate'; import { CommandRegistry } from "../events/interactionCreate";
export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => { export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
resolve({ resolve({
command: createLocalizedCommand('owned-tanks') command: createLocalizedCommand("owned-tanks")
.addStringOption(addTierChoices) .addStringOption(addTierChoices)
.addStringOption(addUsernameChoices), .addStringOption(addUsernameChoices),
async handler(interaction) { async handler(interaction) {
const { strings, unwrap } = translator(interaction.locale); const { strings, unwrap } = translator(interaction.locale);
const tier = Number(interaction.options.getString('tier')); const tier = Number(interaction.options.getString("tier"));
const { id, region } = await resolvePlayerFromCommand(interaction); const { id, region } = await resolvePlayerFromCommand(interaction);
const accountInfo = await getAccountInfo(region, id); const accountInfo = await getAccountInfo(region, id);
const tankStats = await getTankStats(region, id); const tankStats = await getTankStats(region, id);
@@ -43,7 +43,7 @@ export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
tankStats.map(async (tankData) => ({ tankStats.map(async (tankData) => ({
tankDefinitions: (await tankDefinitions).tanks[tankData.tank_id]!, tankDefinitions: (await tankDefinitions).tanks[tankData.tank_id]!,
id: tankData.tank_id, id: tankData.tank_id,
})), }))
) )
).filter((tank) => tank.tankDefinitions?.tier === tier); ).filter((tank) => tank.tankDefinitions?.tier === tier);
const groupedTanks: Record<string, TankDefinition[]> = {}; const groupedTanks: Record<string, TankDefinition[]> = {};
@@ -60,25 +60,25 @@ export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
const awaitedTankDefinitions = await tankDefinitions; const awaitedTankDefinitions = await tankDefinitions;
const awaitedGameDefinitions = await gameDefinitions; const awaitedGameDefinitions = await gameDefinitions;
const title = literals(strings.bot.commands.owned_tanks.body.title, [ const title = literals(strings.bot.commands.owned_tanks.body.title, {
markdownEscape(accountInfo.nickname), name: markdownEscape(accountInfo.nickname),
TIER_ROMAN_NUMERALS[tier], tier: TIER_ROMAN_NUMERALS[tier],
]); });
const tankList = tankStats const tankList = tankStats
.map(({ tank_id }) => awaitedTankDefinitions.tanks[tank_id]) .map(({ tank_id }) => awaitedTankDefinitions.tanks[tank_id])
.filter((tank) => tank.tier === tier) .filter((tank) => tank.tier === tier)
.sort( .sort(
(a, b) => (a, b) =>
TANK_CLASSES.indexOf(a.class) - TANK_CLASSES.indexOf(b.class), TANK_CLASSES.indexOf(a.class) - TANK_CLASSES.indexOf(b.class)
) )
.sort( .sort(
(a, b) => (a, b) =>
awaitedGameDefinitions.nations.indexOf(a.nation) - awaitedGameDefinitions.nations.indexOf(a.nation) -
awaitedGameDefinitions.nations.indexOf(b.nation), awaitedGameDefinitions.nations.indexOf(b.nation)
) )
.map( .map(
(tank) => (tank) =>
`[${flags[tank.nation]} ${markdownEscape(unwrap(tank.name))}](<https://blitzkit.app/tanks/${tank.slug}>)`, `[${flags[tank.nation]} ${markdownEscape(unwrap(tank.name))}](<https://blitzkit.app/tanks/${tank.slug}>)`
); );
const lines = [title, ...tankList]; const lines = [title, ...tankList];
+13 -13
View File
@@ -1,11 +1,11 @@
import { literals } from '@blitzkit/i18n'; import { literals } from "@blitzkit/i18n";
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { translator } from '../core/localization/translator'; import { translator } from "../core/localization/translator";
import { CommandRegistry } from '../events/interactionCreate'; import { CommandRegistry } from "../events/interactionCreate";
export const permissionsCommand = new Promise<CommandRegistry>((resolve) => { export const permissionsCommand = new Promise<CommandRegistry>((resolve) => {
resolve({ resolve({
command: createLocalizedCommand('permissions'), command: createLocalizedCommand("permissions"),
async handler(interaction) { async handler(interaction) {
const { strings } = translator(interaction.locale); const { strings } = translator(interaction.locale);
@@ -14,33 +14,33 @@ export const permissionsCommand = new Promise<CommandRegistry>((resolve) => {
new Date().getDay() === 5 && new Date().getDate() === 13; new Date().getDay() === 5 && new Date().getDate() === 13;
const permissions = [ const permissions = [
[ [
interaction.appPermissions?.has('ViewChannel'), interaction.appPermissions?.has("ViewChannel"),
strings.bot.commands.permissions.body.view_channels, strings.bot.commands.permissions.body.view_channels,
], ],
[ [
interaction.appPermissions?.has('ReadMessageHistory'), interaction.appPermissions?.has("ReadMessageHistory"),
strings.bot.commands.permissions.body.read_message_history, strings.bot.commands.permissions.body.read_message_history,
], ],
[ [
interaction.appPermissions?.has('AttachFiles'), interaction.appPermissions?.has("AttachFiles"),
strings.bot.commands.permissions.body.attach_files, strings.bot.commands.permissions.body.attach_files,
], ],
[ [
interaction.appPermissions?.has('UseExternalEmojis'), interaction.appPermissions?.has("UseExternalEmojis"),
strings.bot.commands.permissions.body.external_emojis, strings.bot.commands.permissions.body.external_emojis,
], ],
]; ];
const body = permissions const body = permissions
.map(([hasPermission, description]) => { .map(([hasPermission, description]) => {
if (hasPermission) { if (hasPermission) {
return `${isFridayThe13th ? '😇' : '✅'} ${description}`; return `${isFridayThe13th ? "😇" : "✅"} ${description}`;
} else { } else {
return `${isFridayThe13th ? '💀' : '❌'} ${description}`; return `${isFridayThe13th ? "💀" : "❌"} ${description}`;
} }
}) })
.join('\n'); .join("\n");
return literals(strings.bot.commands.permissions.body.title, [body]); return literals(strings.bot.commands.permissions.body.title, { body });
}, },
}); });
}); });
+12 -12
View File
@@ -1,15 +1,15 @@
import { literals } from '@blitzkit/i18n'; import { literals } from "@blitzkit/i18n";
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { translator } from '../core/localization/translator'; import { translator } from "../core/localization/translator";
import { CommandRegistry } from '../events/interactionCreate'; import { CommandRegistry } from "../events/interactionCreate";
export const pingCommand = new Promise<CommandRegistry>((resolve) => { export const pingCommand = new Promise<CommandRegistry>((resolve) => {
resolve({ resolve({
handlesInteraction: true, handlesInteraction: true,
command: createLocalizedCommand('ping', [ command: createLocalizedCommand("ping", [
{ subcommand: 'blitzkit' }, { subcommand: "blitzkit" },
{ subcommand: 'wotb' }, { subcommand: "wotb" },
]), ]),
async handler(interaction) { async handler(interaction) {
@@ -17,17 +17,17 @@ export const pingCommand = new Promise<CommandRegistry>((resolve) => {
const subcommand = interaction.options.getSubcommand(); const subcommand = interaction.options.getSubcommand();
const executionStart = Date.now(); const executionStart = Date.now();
if (subcommand === 'blitzkit') { if (subcommand === "blitzkit") {
await interaction.editReply(strings.bot.commands.ping.body.pong); await interaction.editReply(strings.bot.commands.ping.body.pong);
} else { } else {
await fetch('https://api.wotblitz.com/'); await fetch("https://api.wotblitz.com/");
} }
const executionTime = Date.now() - executionStart; const executionTime = Date.now() - executionStart;
interaction.editReply( interaction.editReply(
literals(strings.bot.commands.ping.body.pong_with_time, [ literals(strings.bot.commands.ping.body.pong_with_time, {
`${Math.round(executionTime)}`, time: executionTime.toFixed(0),
]), })
); );
}, },
}); });
+18 -18
View File
@@ -1,19 +1,19 @@
import { getAccountInfo } from '@blitzkit/core'; import { getAccountInfo } from "@blitzkit/core";
import { literals } from '@blitzkit/i18n'; import { literals } from "@blitzkit/i18n";
import markdownEscape from 'markdown-escape'; import markdownEscape from "markdown-escape";
import { addUsernameChoices } from '../core/discord/addUsernameChoices'; import { addUsernameChoices } from "../core/discord/addUsernameChoices";
import { autocompleteUsername } from '../core/discord/autocompleteUsername'; import { autocompleteUsername } from "../core/discord/autocompleteUsername";
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { embedInfo } from '../core/discord/embedInfo'; import { embedInfo } from "../core/discord/embedInfo";
import { markdownTable } from '../core/discord/markdownTable'; import { markdownTable } from "../core/discord/markdownTable";
import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand'; import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand";
import { translator } from '../core/localization/translator'; import { translator } from "../core/localization/translator";
import { CommandRegistry } from '../events/interactionCreate'; import { CommandRegistry } from "../events/interactionCreate";
export const playerInfoCommand = new Promise<CommandRegistry>((resolve) => { export const playerInfoCommand = new Promise<CommandRegistry>((resolve) => {
resolve({ resolve({
command: command:
createLocalizedCommand('player-info').addStringOption(addUsernameChoices), createLocalizedCommand("player-info").addStringOption(addUsernameChoices),
async handler(interaction) { async handler(interaction) {
const { strings } = translator(interaction.locale); const { strings } = translator(interaction.locale);
@@ -22,9 +22,9 @@ export const playerInfoCommand = new Promise<CommandRegistry>((resolve) => {
const accountInfo = await getAccountInfo(region, id); const accountInfo = await getAccountInfo(region, id);
return embedInfo( return embedInfo(
literals(strings.bot.commands.player_info.body.title, [ literals(strings.bot.commands.player_info.body.title, {
markdownEscape(accountInfo.nickname), name: markdownEscape(accountInfo.nickname),
]), }),
markdownTable([ markdownTable([
[ [
@@ -51,16 +51,16 @@ export const playerInfoCommand = new Promise<CommandRegistry>((resolve) => {
[ [
strings.bot.commands.player_info.body.created, strings.bot.commands.player_info.body.created,
new Date(accountInfo.created_at * 1000).toLocaleDateString( new Date(accountInfo.created_at * 1000).toLocaleDateString(
interaction.locale, interaction.locale
), ),
], ],
[ [
strings.bot.commands.player_info.body.last_battle, strings.bot.commands.player_info.body.last_battle,
new Date(accountInfo.last_battle_time * 1000).toLocaleDateString( new Date(accountInfo.last_battle_time * 1000).toLocaleDateString(
interaction.locale, interaction.locale
), ),
], ],
]), ])
); );
}, },
+118 -118
View File
@@ -8,42 +8,42 @@ import {
getRatingInfo, getRatingInfo,
getRatingNeighbors, getRatingNeighbors,
imgur, imgur,
} from '@blitzkit/core'; } from "@blitzkit/core";
import { literals } from '@blitzkit/i18n'; import { literals } from "@blitzkit/i18n";
import { SlashCommandSubcommandBuilder } from 'discord.js'; import { SlashCommandSubcommandBuilder } from "discord.js";
import markdownEscape from 'markdown-escape'; import markdownEscape from "markdown-escape";
import { Glow } from '../components/AllStatsOverview/components/HeroStat/components/Glow'; import { Glow } from "../components/AllStatsOverview/components/HeroStat/components/Glow";
import { CommandWrapper } from '../components/CommandWrapper'; import { CommandWrapper } from "../components/CommandWrapper";
import { DeltaCaret } from '../components/DeltaCaret'; import { DeltaCaret } from "../components/DeltaCaret";
import { TitleBar } from '../components/TitleBar'; import { TitleBar } from "../components/TitleBar";
import { normalizeLeagueIcon } from '../core/blitz/normalizeLeagueIcon'; import { normalizeLeagueIcon } from "../core/blitz/normalizeLeagueIcon";
import { iconPng } from '../core/blitzkit/iconPng'; import { iconPng } from "../core/blitzkit/iconPng";
import { addUsernameChoices } from '../core/discord/addUsernameChoices'; import { addUsernameChoices } from "../core/discord/addUsernameChoices";
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand'; import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand";
import { translator } from '../core/localization/translator'; import { translator } from "../core/localization/translator";
import { CommandRegistry } from '../events/interactionCreate'; import { CommandRegistry } from "../events/interactionCreate";
import { theme } from '../stitches.config'; import { theme } from "../stitches.config";
const LEAGUE_ACCENT = [ const LEAGUE_ACCENT = [
'_purple', "_purple",
'_sand', "_sand",
'_amber', "_amber",
'_mauve', "_mauve",
'_brown', "_brown",
] as const; ] as const;
export const ratingCommand = new Promise<CommandRegistry>((resolve) => { export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
resolve({ resolve({
command: createLocalizedCommand('rating', [ command: createLocalizedCommand("rating", [
{ {
subcommand: 'today', subcommand: "today",
modify(option: SlashCommandSubcommandBuilder) { modify(option: SlashCommandSubcommandBuilder) {
option.addStringOption(addUsernameChoices); option.addStringOption(addUsernameChoices);
}, },
}, },
{ {
subcommand: 'season', subcommand: "season",
modify(option: SlashCommandSubcommandBuilder) { modify(option: SlashCommandSubcommandBuilder) {
option.addStringOption(addUsernameChoices); option.addStringOption(addUsernameChoices);
}, },
@@ -52,11 +52,11 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
async handler(interaction) { async handler(interaction) {
const subcommand = interaction.options.getSubcommand(true) as const subcommand = interaction.options.getSubcommand(true) as
| 'season' | "season"
| 'today'; | "today";
const { strings } = translator(interaction.locale); const { strings } = translator(interaction.locale);
const { id, region } = await resolvePlayerFromCommand(interaction); const { id, region } = await resolvePlayerFromCommand(interaction);
const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan; const clan = (await getClanAccountInfo(region, id, ["clan"]))?.clan;
const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined; const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined;
const ratingInfo = await getRatingInfo(region); const ratingInfo = await getRatingInfo(region);
@@ -67,20 +67,20 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
const leaderboard = await getArchivedRatingLeaderboard( const leaderboard = await getArchivedRatingLeaderboard(
region, region,
ratingInfo.current_season - (subcommand === 'today' ? 0 : 1), ratingInfo.current_season - (subcommand === "today" ? 0 : 1)
); );
if (leaderboard.version!.$case === 'v1') { if (leaderboard.version!.$case === "v1") {
throw new Error( throw new Error(
'Encountered bkrl minimal format in latest season. Wait till next cron?', "Encountered bkrl minimal format in latest season. Wait till next cron?"
); );
} }
const accountInfo = await getAccountInfo(region, id, [ const accountInfo = await getAccountInfo(region, id, [
'statistics.rating', "statistics.rating",
]); ]);
const statsIndex = leaderboard.version!.value.entries.findIndex( const statsIndex = leaderboard.version!.value.entries.findIndex(
(entry) => entry.id === id, (entry) => entry.id === id
); );
const statsA = leaderboard const statsA = leaderboard
? leaderboard.version!.value.entries[statsIndex!] ? leaderboard.version!.value.entries[statsIndex!]
@@ -90,9 +90,9 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
const statsB2Array = (await getRatingNeighbors(region, id, 0)).neighbors; const statsB2Array = (await getRatingNeighbors(region, id, 0)).neighbors;
if (statsB2Array === undefined) { if (statsB2Array === undefined) {
return literals(strings.bot.commands.rating.errors.no_participation, [ return literals(strings.bot.commands.rating.errors.no_participation, {
markdownEscape(accountInfo.nickname), name: markdownEscape(accountInfo.nickname),
]); });
} }
const [statsB2] = statsB2Array; const [statsB2] = statsB2Array;
@@ -102,15 +102,15 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
return strings.bot.commands.rating.errors.unrecorded_stats; return strings.bot.commands.rating.errors.unrecorded_stats;
} }
if (!statsB1) { if (!statsB1) {
return literals(strings.bot.commands.rating.errors.no_participation, [ return literals(strings.bot.commands.rating.errors.no_participation, {
markdownEscape(accountInfo.nickname), name: markdownEscape(accountInfo.nickname),
]); });
} }
const reward = ratingInfo.rewards.find( const reward = ratingInfo.rewards.find(
(reward) => (reward) =>
statsB2.number >= reward.from_position && statsB2.number >= reward.from_position &&
statsB2.number <= reward.to_position, statsB2.number <= reward.to_position
); );
const positionDelta = leaderboard const positionDelta = leaderboard
? statsB2.number - positionA! ? statsB2.number - positionA!
@@ -118,11 +118,11 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
const delta = deltaBkrlBlitzStats( const delta = deltaBkrlBlitzStats(
statsA, statsA,
accountInfo.statistics.rating!, accountInfo.statistics.rating!,
statsB2, statsB2
); );
const leagueTheme = LEAGUE_ACCENT[league.index]; const leagueTheme = LEAGUE_ACCENT[league.index];
let rewardImage = reward let rewardImage = reward
? reward.type === 'vehicle' ? reward.type === "vehicle"
? reward.vehicle.preview_image_url ? reward.vehicle.preview_image_url
: reward.stuff.image_url : reward.stuff.image_url
: undefined; : undefined;
@@ -131,7 +131,7 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
const { ok } = await fetch(rewardImage); const { ok } = await fetch(rewardImage);
if (!ok) { if (!ok) {
rewardImage = imgur('kP88vqr'); rewardImage = imgur("kP88vqr");
} }
} }
@@ -147,24 +147,24 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
<div <div
style={{ style={{
position: 'relative', position: "relative",
display: 'flex', display: "flex",
overflow: 'hidden', overflow: "hidden",
}} }}
> >
<div <div
style={{ style={{
position: 'relative', position: "relative",
padding: 16, padding: 16,
backgroundColor: theme.colors[`appBackground2${leagueTheme}`], backgroundColor: theme.colors[`appBackground2${leagueTheme}`],
borderRadius: 4, borderRadius: 4,
border: `1px solid ${ border: `1px solid ${
theme.colors[`componentInteractive${leagueTheme}`] theme.colors[`componentInteractive${leagueTheme}`]
}`, }`,
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'space-between', justifyContent: "space-between",
width: '100%', width: "100%",
}} }}
> >
{reward === undefined && ( {reward === undefined && (
@@ -172,17 +172,17 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
endOpacity={3 / 4} endOpacity={3 / 4}
color={theme.colors[`solidBackground${leagueTheme}`]} color={theme.colors[`solidBackground${leagueTheme}`]}
style={{ style={{
transform: 'translateX(-16px) rotate(90deg)', transform: "translateX(-16px) rotate(90deg)",
}} }}
/> />
)} )}
<div <div
style={{ style={{
display: 'flex', display: "flex",
gap: 8, gap: 8,
justifyContent: 'center', justifyContent: "center",
alignItems: 'center', alignItems: "center",
}} }}
> >
<img <img
@@ -190,24 +190,24 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
style={{ style={{
width: 64, width: 64,
height: 64, height: 64,
objectFit: 'contain', objectFit: "contain",
}} }}
src={normalizeLeagueIcon( src={normalizeLeagueIcon(
ratingInfo.leagues[league.index].big_icon, ratingInfo.leagues[league.index].big_icon
)} )}
/> />
<div <div
style={{ style={{
display: 'flex', display: "flex",
flexDirection: 'column', flexDirection: "column",
}} }}
> >
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'flex-start', justifyContent: "flex-start",
}} }}
> >
<span <span
@@ -232,7 +232,7 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
}} }}
> >
{Math.abs(delta.score).toLocaleString( {Math.abs(delta.score).toLocaleString(
interaction.locale, interaction.locale
)} )}
</span> </span>
</> </>
@@ -241,9 +241,9 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'flex-start', justifyContent: "flex-start",
}} }}
> >
<span <span
@@ -267,7 +267,7 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
}} }}
> >
{Math.abs(positionDelta).toLocaleString( {Math.abs(positionDelta).toLocaleString(
interaction.locale, interaction.locale
)} )}
</span> </span>
</> </>
@@ -279,23 +279,23 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
{reward && ( {reward && (
<div <div
style={{ style={{
display: 'flex', display: "flex",
gap: 8, gap: 8,
justifyContent: 'center', justifyContent: "center",
alignItems: 'center', alignItems: "center",
}} }}
> >
<div <div
style={{ style={{
display: 'flex', display: "flex",
flexDirection: 'column', flexDirection: "column",
}} }}
> >
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'flex-end', justifyContent: "flex-end",
}} }}
> >
<span <span
@@ -303,13 +303,13 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
color: theme.colors[`textHighContrast${leagueTheme}`], color: theme.colors[`textHighContrast${leagueTheme}`],
fontSize: 16, fontSize: 16,
maxWidth: 136, maxWidth: 136,
textAlign: 'right', textAlign: "right",
whiteSpace: 'nowrap', whiteSpace: "nowrap",
textOverflow: 'ellipsis', textOverflow: "ellipsis",
overflow: 'hidden', overflow: "hidden",
}} }}
> >
{reward.type === 'vehicle' {reward.type === "vehicle"
? reward.vehicle.user_string ? reward.vehicle.user_string
: reward.stuff.title} : reward.stuff.title}
</span> </span>
@@ -317,9 +317,9 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'flex-end', justifyContent: "flex-end",
}} }}
> >
<span <span
@@ -329,7 +329,7 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
}} }}
> >
Reward Reward
{reward.type === 'stuff' ? ` x${reward.count}` : ''} {reward.type === "stuff" ? ` x${reward.count}` : ""}
</span> </span>
</div> </div>
</div> </div>
@@ -338,7 +338,7 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
style={{ style={{
width: 64, width: 64,
height: 64, height: 64,
objectFit: 'cover', objectFit: "cover",
}} }}
src={await iconPng(rewardImage!)} src={await iconPng(rewardImage!)}
/> />
@@ -350,7 +350,7 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
endOpacity={3 / 4} endOpacity={3 / 4}
color={theme.colors[`solidBackground${leagueTheme}`]} color={theme.colors[`solidBackground${leagueTheme}`]}
style={{ style={{
transform: 'translateX(16px) rotate(-90deg)', transform: "translateX(16px) rotate(-90deg)",
}} }}
/> />
)} )}
@@ -362,10 +362,10 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
direction="reverse" direction="reverse"
color={theme.colors[`solidBackground${leagueTheme}`]} color={theme.colors[`solidBackground${leagueTheme}`]}
style={{ style={{
position: 'absolute', position: "absolute",
top: -40, top: -40,
left: '50%', left: "50%",
transform: 'translateX(-50%)', transform: "translateX(-50%)",
}} }}
/> />
)} )}
@@ -373,32 +373,32 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
<Glow <Glow
color={theme.colors[`solidBackground${leagueTheme}`]} color={theme.colors[`solidBackground${leagueTheme}`]}
style={{ style={{
position: 'absolute', position: "absolute",
bottom: -40, bottom: -40,
left: '50%', left: "50%",
transform: 'translateX(-50%)', transform: "translateX(-50%)",
}} }}
/> />
)} )}
</div> </div>
{delta.battles > 0 && ( {delta.battles > 0 && (
<div style={{ padding: '8px 0', display: 'flex' }}> <div style={{ padding: "8px 0", display: "flex" }}>
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
gap: 4, gap: 4,
flex: 1, flex: 1,
flexDirection: 'column', flexDirection: "column",
}} }}
> >
<span <span
style={{ style={{
fontSize: 24, fontSize: 24,
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
fontWeight: 'bold', fontWeight: "bold",
}} }}
> >
{delta.battles.toLocaleString(interaction.locale)} {delta.battles.toLocaleString(interaction.locale)}
@@ -414,19 +414,19 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
</div> </div>
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
gap: 4, gap: 4,
flex: 1, flex: 1,
flexDirection: 'column', flexDirection: "column",
}} }}
> >
<span <span
style={{ style={{
fontSize: 24, fontSize: 24,
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
fontWeight: 'bold', fontWeight: "bold",
}} }}
> >
{(100 * (delta.wins / delta.battles)).toFixed(0)}% {(100 * (delta.wins / delta.battles)).toFixed(0)}%
@@ -442,23 +442,23 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
</div> </div>
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
gap: 4, gap: 4,
flex: 1, flex: 1,
flexDirection: 'column', flexDirection: "column",
}} }}
> >
<span <span
style={{ style={{
fontSize: 24, fontSize: 24,
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
fontWeight: 'bold', fontWeight: "bold",
}} }}
> >
{Math.round(delta.damage / delta.battles).toLocaleString( {Math.round(delta.damage / delta.battles).toLocaleString(
interaction.locale, interaction.locale
)} )}
</span> </span>
<span <span
@@ -472,19 +472,19 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
</div> </div>
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
gap: 4, gap: 4,
flex: 1, flex: 1,
flexDirection: 'column', flexDirection: "column",
}} }}
> >
<span <span
style={{ style={{
fontSize: 24, fontSize: 24,
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
fontWeight: 'bold', fontWeight: "bold",
}} }}
> >
{(100 * (delta.survived / delta.battles)).toFixed(0)}% {(100 * (delta.survived / delta.battles)).toFixed(0)}%
@@ -500,19 +500,19 @@ export const ratingCommand = new Promise<CommandRegistry>((resolve) => {
</div> </div>
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
gap: 4, gap: 4,
flex: 1, flex: 1,
flexDirection: 'column', flexDirection: "column",
}} }}
> >
<span <span
style={{ style={{
fontSize: 24, fontSize: 24,
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
fontWeight: 'bold', fontWeight: "bold",
}} }}
> >
{(delta.kills / delta.battles).toFixed(2)} {(delta.kills / delta.battles).toFixed(2)}
+79 -80
View File
@@ -13,27 +13,27 @@ import {
RatingInfo, RatingInfo,
RatingLeaderboard, RatingLeaderboard,
Region, Region,
} from '@blitzkit/core'; } from "@blitzkit/core";
import { literals } from '@blitzkit/i18n'; import { literals } from "@blitzkit/i18n";
import { import {
APIApplicationCommandOptionChoice, APIApplicationCommandOptionChoice,
Locale, Locale,
SlashCommandSubcommandBuilder, SlashCommandSubcommandBuilder,
} from 'discord.js'; } from "discord.js";
import { range } from 'lodash-es'; import { range } from "lodash-es";
import markdownEscape from 'markdown-escape'; import markdownEscape from "markdown-escape";
import { CommandWrapper } from '../components/CommandWrapper'; import { CommandWrapper } from "../components/CommandWrapper";
import * as Leaderboard from '../components/Leaderboard'; import * as Leaderboard from "../components/Leaderboard";
import { TitleBar } from '../components/TitleBar'; import { TitleBar } from "../components/TitleBar";
import { UserError } from '../core/blitzkit/userError'; import { UserError } from "../core/blitzkit/userError";
import { addRegionChoices } from '../core/discord/addRegionChoices'; import { addRegionChoices } from "../core/discord/addRegionChoices";
import { addUsernameChoices } from '../core/discord/addUsernameChoices'; import { addUsernameChoices } from "../core/discord/addUsernameChoices";
import { autocompleteUsername } from '../core/discord/autocompleteUsername'; import { autocompleteUsername } from "../core/discord/autocompleteUsername";
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { localizationObject } from '../core/discord/localizationObject'; import { localizationObject } from "../core/discord/localizationObject";
import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand'; import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand";
import { translator } from '../core/localization/translator'; import { translator } from "../core/localization/translator";
import { CommandRegistry } from '../events/interactionCreate'; import { CommandRegistry } from "../events/interactionCreate";
interface SimplifiedPlayer { interface SimplifiedPlayer {
id: number; id: number;
@@ -51,7 +51,7 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
const onGoingSeason = await isOnGoingRatingSeason(); const onGoingSeason = await isOnGoingRatingSeason();
const seasonNumbers = range( const seasonNumbers = range(
FIRST_MINIMAL_ARCHIVED_RATING_SEASON, FIRST_MINIMAL_ARCHIVED_RATING_SEASON,
latestArchivedSeasonNumber + (onGoingSeason ? 1 : 0) + 1, latestArchivedSeasonNumber + (onGoingSeason ? 1 : 0) + 1
); );
function addOptions(option: SlashCommandSubcommandBuilder) { function addOptions(option: SlashCommandSubcommandBuilder) {
@@ -66,51 +66,50 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
(strings) => (strings) =>
strings.bot.commands.rating_leaderboard.options.limit.name, strings.bot.commands.rating_leaderboard.options.limit.name,
undefined, undefined,
true, true
), )
) )
.setDescription( .setDescription(
literals( literals(
strings.bot.commands.rating_leaderboard.options.limit strings.bot.commands.rating_leaderboard.options.limit
.description, .description,
[`${DEFAULT_LIMIT}`], { count: DEFAULT_LIMIT }
), )
) )
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
(strings) => (strings) =>
strings.bot.commands.rating_leaderboard.options.limit strings.bot.commands.rating_leaderboard.options.limit
.description, .description,
[`${DEFAULT_LIMIT}`], { count: DEFAULT_LIMIT }
), )
) )
.setRequired(false) .setRequired(false)
.setMinValue(5) .setMinValue(5)
.setMaxValue(30), .setMaxValue(30)
) )
.addStringOption((option) => .addStringOption((option) =>
option option
.setName( .setName(
strings.bot.commands.rating_leaderboard.options.season.name, strings.bot.commands.rating_leaderboard.options.season.name
) )
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
(strings) => (strings) =>
strings.bot.commands.rating_leaderboard.options.season.name, strings.bot.commands.rating_leaderboard.options.season.name,
undefined, undefined,
true, true
), )
) )
.setDescription( .setDescription(
strings.bot.commands.rating_leaderboard.options.season strings.bot.commands.rating_leaderboard.options.season.description
.description,
) )
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
(strings) => (strings) =>
strings.bot.commands.rating_leaderboard.options.season strings.bot.commands.rating_leaderboard.options.season
.description, .description
), )
) )
.setRequired(false) .setRequired(false)
.addChoices( .addChoices(
@@ -124,7 +123,7 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
? literals( ? literals(
strings.bot.commands.rating_leaderboard.options.season strings.bot.commands.rating_leaderboard.options.season
.choices.current, .choices.current,
[`${number}`], { season: number }
) )
: `${number}`, : `${number}`,
value: `${number}`, value: `${number}`,
@@ -133,27 +132,27 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
(strings) => (strings) =>
strings.bot.commands.rating_leaderboard.options strings.bot.commands.rating_leaderboard.options
.season.choices.current, .season.choices.current,
[`${number}`], { season: number }
) )
: undefined, : undefined,
} satisfies APIApplicationCommandOptionChoice<string>; } satisfies APIApplicationCommandOptionChoice<string>;
}) })
.reverse(), .reverse()
), )
); );
} }
resolve({ resolve({
command: createLocalizedCommand('rating-leaderboard', [ command: createLocalizedCommand("rating-leaderboard", [
{ {
subcommand: 'neighbors', subcommand: "neighbors",
modify(option: SlashCommandSubcommandBuilder) { modify(option: SlashCommandSubcommandBuilder) {
option.addStringOption(addUsernameChoices); option.addStringOption(addUsernameChoices);
addOptions(option); addOptions(option);
}, },
}, },
{ {
subcommand: 'league', subcommand: "league",
modify(option: SlashCommandSubcommandBuilder) { modify(option: SlashCommandSubcommandBuilder) {
option option
.addStringOption((option) => { .addStringOption((option) => {
@@ -161,7 +160,7 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
return option return option
.setName( .setName(
strings.bot.commands.rating_leaderboard.options.league.name, strings.bot.commands.rating_leaderboard.options.league.name
) )
.setNameLocalizations( .setNameLocalizations(
localizationObject( localizationObject(
@@ -169,19 +168,19 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
strings.bot.commands.rating_leaderboard.options.league strings.bot.commands.rating_leaderboard.options.league
.name, .name,
undefined, undefined,
true, true
), )
) )
.setDescription( .setDescription(
strings.bot.commands.rating_leaderboard.options.league strings.bot.commands.rating_leaderboard.options.league
.description, .description
) )
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
(strings) => (strings) =>
strings.bot.commands.rating_leaderboard.options.league strings.bot.commands.rating_leaderboard.options.league
.description, .description
), )
) )
.addChoices( .addChoices(
...LEAGUES.map( ...LEAGUES.map(
@@ -195,10 +194,10 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
(strings) => (strings) =>
( (
strings.common.leagues as Record<string, string> strings.common.leagues as Record<string, string>
)[name], )[name]
),
}) satisfies APIApplicationCommandOptionChoice<string>,
), ),
}) satisfies APIApplicationCommandOptionChoice<string>
)
) )
.setRequired(true); .setRequired(true);
}) })
@@ -213,10 +212,10 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
async handler(interaction) { async handler(interaction) {
const { strings } = translator(interaction.locale); const { strings } = translator(interaction.locale);
const subcommand = interaction.options.getSubcommand(true) as const subcommand = interaction.options.getSubcommand(true) as
| 'league' | "league"
| 'neighbors'; | "neighbors";
const limit = interaction.options.getInteger('limit') ?? DEFAULT_LIMIT; const limit = interaction.options.getInteger("limit") ?? DEFAULT_LIMIT;
const seasonOption = interaction.options.getString('season'); const seasonOption = interaction.options.getString("season");
const season = seasonOption const season = seasonOption
? parseInt(seasonOption) ? parseInt(seasonOption)
: onGoingSeason : onGoingSeason
@@ -232,11 +231,11 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
let playerId: number | undefined; let playerId: number | undefined;
let regionRatingInfo: RatingInfo | null; let regionRatingInfo: RatingInfo | null;
if (subcommand === 'league') { if (subcommand === "league") {
const leagueIndex = parseInt( const leagueIndex = parseInt(
interaction.options.getString('league')!, interaction.options.getString("league")!
); );
const region = interaction.options.getString('region') as Region; const region = interaction.options.getString("region") as Region;
regionRatingInfo = await (isCurrentSeason regionRatingInfo = await (isCurrentSeason
? getRatingInfo(region) ? getRatingInfo(region)
: null); : null);
@@ -259,8 +258,8 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
position: player.number, position: player.number,
clan: player.clan_tag, clan: player.clan_tag,
nickname: player.nickname, nickname: player.nickname,
}) satisfies SimplifiedPlayer, }) satisfies SimplifiedPlayer
), )
) )
: await getArchivedRatingLeaderboard(region, season!).then( : await getArchivedRatingLeaderboard(region, season!).then(
async (players) => { async (players) => {
@@ -269,17 +268,17 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
? 0 ? 0
: players.version!.value.entries.findIndex( : players.version!.value.entries.findIndex(
(player) => (player) =>
player.score < LEAGUES[leagueIndex - 1].minScore, player.score < LEAGUES[leagueIndex - 1].minScore
); );
const lastPlayerIndex = firstPlayerIndex + limit - 1; const lastPlayerIndex = firstPlayerIndex + limit - 1;
const trimmed = players.version!.value.entries.slice( const trimmed = players.version!.value.entries.slice(
firstPlayerIndex, firstPlayerIndex,
lastPlayerIndex + 1, lastPlayerIndex + 1
); );
const clanData = await getClanAccountInfo( const clanData = await getClanAccountInfo(
region, region,
trimmed.map(({ id }) => id), trimmed.map(({ id }) => id),
['clan'], ["clan"]
); );
return trimmed.map( return trimmed.map(
@@ -294,16 +293,16 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
literals( literals(
strings.bot.commands.rating_leaderboard.body strings.bot.commands.rating_leaderboard.body
.deleted_player, .deleted_player,
[`${player.id}`], { id: player.id }
), ),
}) satisfies SimplifiedPlayer, }) satisfies SimplifiedPlayer
); );
}, }
); );
const leagueInfo = LEAGUES[leagueIndex]; const leagueInfo = LEAGUES[leagueIndex];
archivedLeaderboard = await getArchivedRatingLeaderboard( archivedLeaderboard = await getArchivedRatingLeaderboard(
region, region,
season, season
); );
players = result; players = result;
@@ -316,12 +315,12 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
? (strings.common.leagues as Record<string, string>)[ ? (strings.common.leagues as Record<string, string>)[
LEAGUES[leagueInfo.index].name LEAGUES[leagueInfo.index].name
] ]
: '' : ""
} - ${strings.common.regions.short[region]}`; } - ${strings.common.regions.short[region]}`;
titleImage = imgur(leagueInfo.icon); titleImage = imgur(leagueInfo.icon);
titleDescription = literals( titleDescription = literals(
strings.bot.commands.rating_leaderboard.body.top_players, strings.bot.commands.rating_leaderboard.body.top_players,
[`${limit}`], { count: limit }
); );
} else { } else {
const { region, id } = await resolvePlayerFromCommand(interaction); const { region, id } = await resolvePlayerFromCommand(interaction);
@@ -338,7 +337,7 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
} }
const accountInfo = await getAccountInfo(region, id); const accountInfo = await getAccountInfo(region, id);
const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan; const clan = (await getClanAccountInfo(region, id, ["clan"]))?.clan;
const neighbors = isCurrentSeason const neighbors = isCurrentSeason
? await getRatingNeighbors(region, id, Math.round(limit / 2)).then( ? await getRatingNeighbors(region, id, Math.round(limit / 2)).then(
(players) => (players) =>
@@ -350,13 +349,13 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
score: player.score, score: player.score,
clan: player.clan_tag, clan: player.clan_tag,
nickname: player.nickname, nickname: player.nickname,
}) satisfies SimplifiedPlayer, }) satisfies SimplifiedPlayer
), )
) )
: await getArchivedRatingLeaderboard(region, season!).then( : await getArchivedRatingLeaderboard(region, season!).then(
async (players) => { async (players) => {
const playerIndex = players.version!.value.entries.findIndex( const playerIndex = players.version!.value.entries.findIndex(
(player) => player.id === id, (player) => player.id === id
); );
if (playerIndex === -1) { if (playerIndex === -1) {
@@ -364,20 +363,20 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
literals( literals(
strings.bot.commands.rating_leaderboard.body strings.bot.commands.rating_leaderboard.body
.no_participation, .no_participation,
[markdownEscape(accountInfo.nickname), `${season}`], { player: markdownEscape(accountInfo.nickname), season }
), )
); );
} }
const halfRange = Math.round(limit / 2); const halfRange = Math.round(limit / 2);
const trimmed = players.version!.value.entries.slice( const trimmed = players.version!.value.entries.slice(
playerIndex - halfRange, playerIndex - halfRange,
playerIndex + halfRange + 1, playerIndex + halfRange + 1
); );
const clanData = await getClanAccountInfo( const clanData = await getClanAccountInfo(
region, region,
trimmed.map((player) => player.id), trimmed.map((player) => player.id),
['clan'], ["clan"]
); );
return trimmed.map((player, index) => ({ return trimmed.map((player, index) => ({
@@ -389,18 +388,18 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
? clanData[index]!.account_name ? clanData[index]!.account_name
: `Deleted ${player.id}`, : `Deleted ${player.id}`,
})); }));
}, }
); );
archivedLeaderboard = await getArchivedRatingLeaderboard( archivedLeaderboard = await getArchivedRatingLeaderboard(
region, region,
season, season
); );
players = neighbors; players = neighbors;
titleImage = clan titleImage = clan
? `https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clan.emblem_set_id}.png` ? `https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clan.emblem_set_id}.png`
: undefined; : undefined;
titleName = neighbors ? accountInfo.nickname : ''; titleName = neighbors ? accountInfo.nickname : "";
titleDescription = titleDescription =
strings.bot.commands.rating_leaderboard.body.neighbors; strings.bot.commands.rating_leaderboard.body.neighbors;
playersAfter = playersAfter =
@@ -414,7 +413,7 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
const items = players.map((player) => { const items = players.map((player) => {
const midnightIndex = const midnightIndex =
archivedLeaderboard?.version!.value.entries.findIndex( archivedLeaderboard?.version!.value.entries.findIndex(
(item) => item.id === player.id, (item) => item.id === player.id
); );
const midnightScore = const midnightScore =
midnightIndex === undefined midnightIndex === undefined
@@ -453,7 +452,7 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
<Leaderboard.Gap <Leaderboard.Gap
message={literals( message={literals(
strings.bot.commands.rating_leaderboard.body.more, strings.bot.commands.rating_leaderboard.body.more,
[`${playersAfter.toLocaleString(interaction.locale)}`], { count: playersAfter.toLocaleString(interaction.locale) }
)} )}
/> />
)} )}
@@ -465,5 +464,5 @@ export const ratingLeaderboardCommand = new Promise<CommandRegistry>(
autocomplete: autocompleteUsername, autocomplete: autocompleteUsername,
}); });
}, }
); );
@@ -1,15 +1,15 @@
import { BlitzKitStrings, literals as literalsFunc } from '@blitzkit/i18n'; import { BlitzKitStrings, literals as literalsFunc } from "@blitzkit/i18n";
import { Locale } from 'discord.js'; import { Locale } from "discord.js";
import { SUPPORTED_LOCALES_DISCORD } from '../localization/strings/constants'; import { SUPPORTED_LOCALES_DISCORD } from "../localization/strings/constants";
import { translator } from '../localization/translator'; import { translator } from "../localization/translator";
const validNameRegex = const validNameRegex =
/^[\p{Ll}\p{Lm}\p{Lo}\p{N}\p{sc=Devanagari}\p{sc=Thai}_-]+$/u; /^[\p{Ll}\p{Lm}\p{Lo}\p{N}\p{sc=Devanagari}\p{sc=Thai}_-]+$/u;
export function localizationObject( export function localizationObject(
path: (strings: BlitzKitStrings) => string, path: (strings: BlitzKitStrings) => string,
literals: string[] = [], literals?: Record<string, string | number>,
strict = false, strict = false
) { ) {
return SUPPORTED_LOCALES_DISCORD.reduce<Partial<Record<Locale, string>>>( return SUPPORTED_LOCALES_DISCORD.reduce<Partial<Record<Locale, string>>>(
(localizations, locale) => { (localizations, locale) => {
@@ -20,7 +20,7 @@ export function localizationObject(
if (!isValid) { if (!isValid) {
console.warn( console.warn(
`Invalid localization for ${locale} (${path}): ${translation}; skipping...`, `Invalid localization for ${locale} (${path}): ${translation}; skipping...`
); );
return localizations; return localizations;
} }
@@ -30,6 +30,6 @@ export function localizationObject(
[locale]: translation, [locale]: translation,
}; };
}, },
{}, {}
); );
} }