mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
feat: some progress
This commit is contained in:
1 parent
3d69d464f5
commit
5594c0ec3b
7 files changed
+270
-271
No files matched your search
@@ -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];
|
||||||
|
|
||||||
|
|||||||
@@ -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 });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -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),
|
||||||
]),
|
})
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
]),
|
])
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -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)}
|
||||||
|
|||||||
@@ -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,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{},
|
{}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user