mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-27 12:39:49 +01:00
feat: some period translations
This commit is contained in:
1 parent
267f23cad8
commit
adad668157
24 files changed
+388
-295
No files matched your search
@@ -35,7 +35,7 @@ import resolvePlayerFromCommand, {
|
|||||||
import calculateWN8 from '../core/statistics/calculateWN8';
|
import calculateWN8 from '../core/statistics/calculateWN8';
|
||||||
import { StatFilters, filterStats } from '../core/statistics/filterStats';
|
import { StatFilters, filterStats } from '../core/statistics/filterStats';
|
||||||
import getWN8Percentile from '../core/statistics/getWN8Percentile';
|
import getWN8Percentile from '../core/statistics/getWN8Percentile';
|
||||||
import { CommandRegistryPromisable } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|
||||||
const ROWS_PER_PAGE = 8;
|
const ROWS_PER_PAGE = 8;
|
||||||
const MAX_PAGES = 9;
|
const MAX_PAGES = 9;
|
||||||
@@ -290,7 +290,7 @@ export async function renderBreakdown(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const breakdownCommand = new Promise<CommandRegistryPromisable>(
|
export const breakdownCommand = new Promise<CommandRegistry>(
|
||||||
async (resolve) => {
|
async (resolve) => {
|
||||||
resolve({
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import { CommandRegistry } from '../events/interactionCreate';
|
|||||||
|
|
||||||
const executionStart = new Date().getTime();
|
const executionStart = new Date().getTime();
|
||||||
|
|
||||||
export const debugCommand: CommandRegistry = {
|
export const debugCommand = new Promise<CommandRegistry>((resolve) => {
|
||||||
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
@@ -35,4 +36,5 @@ export const debugCommand: CommandRegistry = {
|
|||||||
.map(([key, value]) => `- ${key}: ${value}`)
|
.map(([key, value]) => `- ${key}: ${value}`)
|
||||||
.join('\n')}`;
|
.join('\n')}`;
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
});
|
||||||
+185
-178
@@ -1,198 +1,205 @@
|
|||||||
import { SlashCommandBuilder } from 'discord.js';
|
// _____ _____ _ _ _ _ _____ ____ __ __ ______ ____ _____ _ __
|
||||||
import { getAccountInfo } from '../core/blitz/getAccountInfo';
|
// |_ _| / ____| | | | /\ | | | | / ____/ __ \| \/ | ____| | _ \ /\ / ____| |/ /
|
||||||
import getPeriodNow from '../core/blitzkrieg/getPeriodNow';
|
// | | | (___ | |__| | / \ | | | | | | | | | | \ / | |__ | |_) | / \ | | | ' /
|
||||||
import getTimeDaysAgo from '../core/blitzkrieg/getTimeDaysAgo';
|
// | | \___ \| __ | / /\ \ | | | | | | | | | | |\/| | __| | _ < / /\ \| | | <
|
||||||
import { tankDefinitions } from '../core/blitzkrieg/tankDefinitions';
|
// _| |_ ____) | | | |/ ____ \| |____| |____ | |___| |__| | | | | |____ | |_) / ____ \ |____| . \
|
||||||
import getStatsInPeriod from '../core/blitzstars/getStatsInPeriod';
|
// |_____| |_____/|_| |_/_/ \_\______|______| \_____\____/|_| |_|______| |____/_/ \_\_____|_|\_\
|
||||||
import { tankAverages } from '../core/blitzstars/tankAverages';
|
|
||||||
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
|
||||||
import embedNegative from '../core/discord/embedNegative';
|
|
||||||
import embedPositive from '../core/discord/embedPositive';
|
|
||||||
import markdownTable, { TableInput } from '../core/discord/markdownTable';
|
|
||||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
|
||||||
import calculateWN8 from '../core/statistics/calculateWN8';
|
|
||||||
import sumStats from '../core/statistics/sumStats';
|
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
|
||||||
import { PossiblyPromise } from '../types/possiblyPromise';
|
|
||||||
|
|
||||||
export type SkilledClan = 'SKLLD' | 'SMRI';
|
// import { SlashCommandBuilder } from 'discord.js';
|
||||||
|
// import { getAccountInfo } from '../core/blitz/getAccountInfo';
|
||||||
|
// import getPeriodNow from '../core/blitzkrieg/getPeriodNow';
|
||||||
|
// import getTimeDaysAgo from '../core/blitzkrieg/getTimeDaysAgo';
|
||||||
|
// import { tankDefinitions } from '../core/blitzkrieg/tankDefinitions';
|
||||||
|
// import getStatsInPeriod from '../core/blitzstars/getStatsInPeriod';
|
||||||
|
// import { tankAverages } from '../core/blitzstars/tankAverages';
|
||||||
|
// import addUsernameChoices from '../core/discord/addUsernameChoices';
|
||||||
|
// import embedNegative from '../core/discord/embedNegative';
|
||||||
|
// import embedPositive from '../core/discord/embedPositive';
|
||||||
|
// import markdownTable, { TableInput } from '../core/discord/markdownTable';
|
||||||
|
// import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||||
|
// import calculateWN8 from '../core/statistics/calculateWN8';
|
||||||
|
// import sumStats from '../core/statistics/sumStats';
|
||||||
|
// import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
// import { PossiblyPromise } from '../types/possiblyPromise';
|
||||||
|
|
||||||
export const SKILLED_CLANS: Record<SkilledClan, string> = {
|
// export type SkilledClan = 'SKLLD' | 'SMRI';
|
||||||
SKLLD: 'Skilled',
|
|
||||||
SMRI: 'Samurai',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const eligibleCommand: CommandRegistry = {
|
// export const SKILLED_CLANS: Record<SkilledClan, string> = {
|
||||||
inProduction: true,
|
// SKLLD: 'Skilled',
|
||||||
inPublic: false,
|
// SMRI: 'Samurai',
|
||||||
|
// };
|
||||||
|
|
||||||
command: new SlashCommandBuilder()
|
// export const eligibleCommand: CommandRegistry = {
|
||||||
.setName('eligible')
|
// inProduction: true,
|
||||||
.setDescription('Checks eligibility for any Skilled clan')
|
// inPublic: false,
|
||||||
.addStringOption((option) =>
|
|
||||||
option
|
|
||||||
.setName('clan')
|
|
||||||
.setDescription('The clan to check')
|
|
||||||
.setChoices(
|
|
||||||
{
|
|
||||||
name: SKILLED_CLANS.SKLLD,
|
|
||||||
value: 'SKLLD' satisfies SkilledClan,
|
|
||||||
},
|
|
||||||
{ name: SKILLED_CLANS.SMRI, value: 'SMRI' satisfies SkilledClan },
|
|
||||||
)
|
|
||||||
.setRequired(true),
|
|
||||||
)
|
|
||||||
.addStringOption(addUsernameChoices),
|
|
||||||
|
|
||||||
async handler(interaction) {
|
// command: new SlashCommandBuilder()
|
||||||
const clan = interaction.options.getString('clan') as SkilledClan;
|
// .setName('eligible')
|
||||||
const { id, region: region } = await resolvePlayerFromCommand(interaction);
|
// .setDescription('Checks eligibility for any Skilled clan')
|
||||||
const accountInfo = await getAccountInfo(region, id);
|
// .addStringOption((option) =>
|
||||||
const problems: TableInput = [];
|
// option
|
||||||
const title = `${accountInfo.nickname}'s eligibility for ${SKILLED_CLANS[clan]}`;
|
// .setName('clan')
|
||||||
let isEligible = false;
|
// .setDescription('The clan to check')
|
||||||
let body = '';
|
// .setChoices(
|
||||||
|
// {
|
||||||
|
// name: SKILLED_CLANS.SKLLD,
|
||||||
|
// value: 'SKLLD' satisfies SkilledClan,
|
||||||
|
// },
|
||||||
|
// { name: SKILLED_CLANS.SMRI, value: 'SMRI' satisfies SkilledClan },
|
||||||
|
// )
|
||||||
|
// .setRequired(true),
|
||||||
|
// )
|
||||||
|
// .addStringOption(addUsernameChoices),
|
||||||
|
|
||||||
if (clan === 'SKLLD') {
|
// async handler(interaction) {
|
||||||
const { diff: diffed } = await getStatsInPeriod(
|
// const clan = interaction.options.getString('clan') as SkilledClan;
|
||||||
region,
|
// const { id, region: region } = await resolvePlayerFromCommand(interaction);
|
||||||
id,
|
// const accountInfo = await getAccountInfo(region, id);
|
||||||
getTimeDaysAgo(region, 30),
|
// const problems: TableInput = [];
|
||||||
getPeriodNow(),
|
// const title = `${accountInfo.nickname}'s eligibility for ${SKILLED_CLANS[clan]}`;
|
||||||
);
|
// let isEligible = false;
|
||||||
const entries = Object.entries(diffed);
|
// let body = '';
|
||||||
const stats = sumStats(entries.map(([, stats]) => stats));
|
|
||||||
const averageTier =
|
|
||||||
(await entries.reduce<PossiblyPromise<number>>(
|
|
||||||
async (accumulator, [tankIdString, stats]) => {
|
|
||||||
const tankId = parseInt(tankIdString);
|
|
||||||
const tankDefinition = (await tankDefinitions)[tankId];
|
|
||||||
|
|
||||||
if (!tankDefinition) return accumulator;
|
// if (clan === 'SKLLD') {
|
||||||
|
// const { diff: diffed } = await getStatsInPeriod(
|
||||||
|
// region,
|
||||||
|
// id,
|
||||||
|
// getTimeDaysAgo(region, 30),
|
||||||
|
// getPeriodNow(),
|
||||||
|
// );
|
||||||
|
// const entries = Object.entries(diffed);
|
||||||
|
// const stats = sumStats(entries.map(([, stats]) => stats));
|
||||||
|
// const averageTier =
|
||||||
|
// (await entries.reduce<PossiblyPromise<number>>(
|
||||||
|
// async (accumulator, [tankIdString, stats]) => {
|
||||||
|
// const tankId = parseInt(tankIdString);
|
||||||
|
// const tankDefinition = (await tankDefinitions)[tankId];
|
||||||
|
|
||||||
const tankTier = tankDefinition.tier;
|
// if (!tankDefinition) return accumulator;
|
||||||
|
|
||||||
return (await accumulator) + tankTier * stats.battles;
|
// const tankTier = tankDefinition.tier;
|
||||||
},
|
|
||||||
0,
|
|
||||||
)) /
|
|
||||||
(await entries.reduce<PossiblyPromise<number>>(
|
|
||||||
async (accumulator, [tankIdString, stats]) => {
|
|
||||||
const tankId = parseInt(tankIdString);
|
|
||||||
const tankDefinition = (await tankDefinitions)[tankId];
|
|
||||||
|
|
||||||
if (!tankDefinition) return accumulator;
|
// return (await accumulator) + tankTier * stats.battles;
|
||||||
|
// },
|
||||||
|
// 0,
|
||||||
|
// )) /
|
||||||
|
// (await entries.reduce<PossiblyPromise<number>>(
|
||||||
|
// async (accumulator, [tankIdString, stats]) => {
|
||||||
|
// const tankId = parseInt(tankIdString);
|
||||||
|
// const tankDefinition = (await tankDefinitions)[tankId];
|
||||||
|
|
||||||
return stats.battles;
|
// if (!tankDefinition) return accumulator;
|
||||||
},
|
|
||||||
0,
|
|
||||||
));
|
|
||||||
const WN8 =
|
|
||||||
(await entries.reduce<PossiblyPromise<number>>(
|
|
||||||
async (accumulator, [tankIdString, stats]) => {
|
|
||||||
const tankId = parseInt(tankIdString);
|
|
||||||
|
|
||||||
// edge case where new tanks don't have averages
|
// return stats.battles;
|
||||||
if ((await tankAverages)[tankId]) {
|
// },
|
||||||
const tankWN8 = calculateWN8(
|
// 0,
|
||||||
(await tankAverages)[tankId].all,
|
// ));
|
||||||
stats,
|
// const WN8 =
|
||||||
);
|
// (await entries.reduce<PossiblyPromise<number>>(
|
||||||
|
// async (accumulator, [tankIdString, stats]) => {
|
||||||
|
// const tankId = parseInt(tankIdString);
|
||||||
|
|
||||||
if (isNaN(tankWN8)) return accumulator;
|
// // edge case where new tanks don't have averages
|
||||||
return (await accumulator) + tankWN8 * stats.battles;
|
// if ((await tankAverages)[tankId]) {
|
||||||
} else return accumulator;
|
// const tankWN8 = calculateWN8(
|
||||||
},
|
// (await tankAverages)[tankId].all,
|
||||||
0,
|
// stats,
|
||||||
)) / stats.battles;
|
// );
|
||||||
const tier10Damage =
|
|
||||||
(await entries.reduce<PossiblyPromise<number>>(
|
|
||||||
async (accumulator, [tankIdString, stats]) => {
|
|
||||||
const tankId = parseInt(tankIdString);
|
|
||||||
|
|
||||||
if ((await tankDefinitions)[tankId]?.tier === 10) {
|
// if (isNaN(tankWN8)) return accumulator;
|
||||||
const tankStats = diffed[tankId];
|
// return (await accumulator) + tankWN8 * stats.battles;
|
||||||
return (await accumulator) + tankStats.damage_dealt;
|
// } else return accumulator;
|
||||||
} else return accumulator;
|
// },
|
||||||
},
|
// 0,
|
||||||
0,
|
// )) / stats.battles;
|
||||||
)) /
|
// const tier10Damage =
|
||||||
(await entries.reduce<PossiblyPromise<number>>(
|
// (await entries.reduce<PossiblyPromise<number>>(
|
||||||
async (accumulator, [tankIdString, stats]) => {
|
// async (accumulator, [tankIdString, stats]) => {
|
||||||
const tankId = parseInt(tankIdString);
|
// const tankId = parseInt(tankIdString);
|
||||||
|
|
||||||
if ((await tankDefinitions)[tankId]?.tier === 10) {
|
// if ((await tankDefinitions)[tankId]?.tier === 10) {
|
||||||
const tankStats = diffed[tankId];
|
// const tankStats = diffed[tankId];
|
||||||
return (await accumulator) + tankStats.battles;
|
// return (await accumulator) + tankStats.damage_dealt;
|
||||||
} else return accumulator;
|
// } else return accumulator;
|
||||||
},
|
// },
|
||||||
0,
|
// 0,
|
||||||
));
|
// )) /
|
||||||
|
// (await entries.reduce<PossiblyPromise<number>>(
|
||||||
|
// async (accumulator, [tankIdString, stats]) => {
|
||||||
|
// const tankId = parseInt(tankIdString);
|
||||||
|
|
||||||
if (stats.battles < 126) {
|
// if ((await tankDefinitions)[tankId]?.tier === 10) {
|
||||||
problems.push(['Battles', `${stats.battles} (${stats.battles - 126})`]);
|
// const tankStats = diffed[tankId];
|
||||||
}
|
// return (await accumulator) + tankStats.battles;
|
||||||
if (averageTier < 8) {
|
// } else return accumulator;
|
||||||
problems.push([
|
// },
|
||||||
'Average tier',
|
// 0,
|
||||||
`${averageTier.toFixed(2)} (${(averageTier - 8).toFixed(2)})`,
|
// ));
|
||||||
]);
|
|
||||||
}
|
|
||||||
if (stats.wins / stats.battles < 0.6) {
|
|
||||||
problems.push([
|
|
||||||
'Winrate',
|
|
||||||
`${(100 * (stats.wins / stats.battles)).toFixed(2)}% (${(
|
|
||||||
100 *
|
|
||||||
(stats.wins / stats.battles - 0.6)
|
|
||||||
).toFixed(2)}%)`,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
if (WN8 < 2450) {
|
|
||||||
problems.push([
|
|
||||||
'WN8',
|
|
||||||
`${WN8.toFixed(0)} (${(WN8 - 2450).toFixed(0)})`,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
if (tier10Damage < 1250) {
|
|
||||||
problems.push([
|
|
||||||
'Tier 10 damage',
|
|
||||||
`${tier10Damage.toFixed(0)} (${tier10Damage - 1250})`,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
isEligible = problems.length === 0;
|
// if (stats.battles < 126) {
|
||||||
body = isEligible
|
// problems.push(['Battles', `${stats.battles} (${stats.battles - 126})`]);
|
||||||
? 'Player is fully eligible.'
|
// }
|
||||||
: `Player is not eligible. Shortcomings in 30-day statistics:\n\n${markdownTable(
|
// if (averageTier < 8) {
|
||||||
problems,
|
// problems.push([
|
||||||
)}`;
|
// 'Average tier',
|
||||||
} else if (clan === 'SMRI') {
|
// `${averageTier.toFixed(2)} (${(averageTier - 8).toFixed(2)})`,
|
||||||
const stats = accountInfo.statistics.all;
|
// ]);
|
||||||
|
// }
|
||||||
|
// if (stats.wins / stats.battles < 0.6) {
|
||||||
|
// problems.push([
|
||||||
|
// 'Winrate',
|
||||||
|
// `${(100 * (stats.wins / stats.battles)).toFixed(2)}% (${(
|
||||||
|
// 100 *
|
||||||
|
// (stats.wins / stats.battles - 0.6)
|
||||||
|
// ).toFixed(2)}%)`,
|
||||||
|
// ]);
|
||||||
|
// }
|
||||||
|
// if (WN8 < 2450) {
|
||||||
|
// problems.push([
|
||||||
|
// 'WN8',
|
||||||
|
// `${WN8.toFixed(0)} (${(WN8 - 2450).toFixed(0)})`,
|
||||||
|
// ]);
|
||||||
|
// }
|
||||||
|
// if (tier10Damage < 1250) {
|
||||||
|
// problems.push([
|
||||||
|
// 'Tier 10 damage',
|
||||||
|
// `${tier10Damage.toFixed(0)} (${tier10Damage - 1250})`,
|
||||||
|
// ]);
|
||||||
|
// }
|
||||||
|
|
||||||
if (stats.battles < 1500) {
|
// isEligible = problems.length === 0;
|
||||||
problems.push([
|
// body = isEligible
|
||||||
'Battles',
|
// ? 'Player is fully eligible.'
|
||||||
`${stats.battles} (${stats.battles - 1500})`,
|
// : `Player is not eligible. Shortcomings in 30-day statistics:\n\n${markdownTable(
|
||||||
]);
|
// problems,
|
||||||
}
|
// )}`;
|
||||||
if (stats.wins / stats.battles <= 0.53) {
|
// } else if (clan === 'SMRI') {
|
||||||
problems.push([
|
// const stats = accountInfo.statistics.all;
|
||||||
'Winrate',
|
|
||||||
`${(100 * (stats.wins / stats.battles)).toFixed(2)}% (${(
|
|
||||||
100 *
|
|
||||||
(stats.wins / stats.battles - 0.53)
|
|
||||||
).toFixed(2)}%)`,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
isEligible = problems.length === 0;
|
// if (stats.battles < 1500) {
|
||||||
body = isEligible
|
// problems.push([
|
||||||
? 'Player is fully eligible.'
|
// 'Battles',
|
||||||
: `Player is not eligible. Shortcomings in career statistics:\n\n${markdownTable(
|
// `${stats.battles} (${stats.battles - 1500})`,
|
||||||
problems,
|
// ]);
|
||||||
)}`;
|
// }
|
||||||
}
|
// if (stats.wins / stats.battles <= 0.53) {
|
||||||
|
// problems.push([
|
||||||
|
// 'Winrate',
|
||||||
|
// `${(100 * (stats.wins / stats.battles)).toFixed(2)}% (${(
|
||||||
|
// 100 *
|
||||||
|
// (stats.wins / stats.battles - 0.53)
|
||||||
|
// ).toFixed(2)}%)`,
|
||||||
|
// ]);
|
||||||
|
// }
|
||||||
|
|
||||||
return (isEligible ? embedPositive : embedNegative)(title, body);
|
// isEligible = problems.length === 0;
|
||||||
},
|
// body = isEligible
|
||||||
};
|
// ? 'Player is fully eligible.'
|
||||||
|
// : `Player is not eligible. Shortcomings in career statistics:\n\n${markdownTable(
|
||||||
|
// problems,
|
||||||
|
// )}`;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return (isEligible ? embedPositive : embedNegative)(title, body);
|
||||||
|
// },
|
||||||
|
// };
|
||||||
+24
-36
@@ -1,7 +1,4 @@
|
|||||||
import {
|
import { SlashCommandSubcommandGroupBuilder } from 'discord.js';
|
||||||
SlashCommandBuilder,
|
|
||||||
SlashCommandSubcommandGroupBuilder,
|
|
||||||
} from 'discord.js';
|
|
||||||
import CommandWrapper from '../components/CommandWrapper';
|
import CommandWrapper from '../components/CommandWrapper';
|
||||||
import * as Graph from '../components/Graph';
|
import * as Graph from '../components/Graph';
|
||||||
import NoData, { NoDataType } from '../components/NoData';
|
import NoData, { NoDataType } from '../components/NoData';
|
||||||
@@ -20,6 +17,7 @@ import autocompleteTanks from '../core/discord/autocompleteTanks';
|
|||||||
import autocompleteUsername from '../core/discord/autocompleteUsername';
|
import autocompleteUsername from '../core/discord/autocompleteUsername';
|
||||||
import buttonPrimary from '../core/discord/buttonPrimary';
|
import buttonPrimary from '../core/discord/buttonPrimary';
|
||||||
import commandToURL from '../core/discord/commandToURL';
|
import commandToURL from '../core/discord/commandToURL';
|
||||||
|
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
||||||
import { getCustomPeriodParams } from '../core/discord/getCustomPeriodParams';
|
import { getCustomPeriodParams } from '../core/discord/getCustomPeriodParams';
|
||||||
import resolvePeriodFromButton from '../core/discord/resolvePeriodFromButton';
|
import resolvePeriodFromButton from '../core/discord/resolvePeriodFromButton';
|
||||||
import resolvePeriodFromCommand, {
|
import resolvePeriodFromCommand, {
|
||||||
@@ -29,7 +27,7 @@ import resolvePlayerFromButton from '../core/discord/resolvePlayerFromButton';
|
|||||||
import resolvePlayerFromCommand, {
|
import resolvePlayerFromCommand, {
|
||||||
ResolvedPlayer,
|
ResolvedPlayer,
|
||||||
} from '../core/discord/resolvePlayerFromCommand';
|
} from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { CommandRegistryPromisable } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|
||||||
type EvolutionStatType = 'player' | 'tank';
|
type EvolutionStatType = 'player' | 'tank';
|
||||||
|
|
||||||
@@ -107,40 +105,32 @@ async function render(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const evolutionCommand = new Promise<CommandRegistryPromisable>(
|
export const evolutionCommand = new Promise<CommandRegistry>(
|
||||||
async (resolve) => {
|
async (resolve) => {
|
||||||
let playerGroup: SlashCommandSubcommandGroupBuilder;
|
|
||||||
let tankGroup: SlashCommandSubcommandGroupBuilder;
|
|
||||||
const command = new SlashCommandBuilder()
|
|
||||||
.setName('evolution')
|
|
||||||
.setDescription('Evolution of statistics')
|
|
||||||
.addSubcommandGroup((option) => {
|
|
||||||
playerGroup = option
|
|
||||||
.setName('player')
|
|
||||||
.setDescription('Player statistics');
|
|
||||||
|
|
||||||
return playerGroup;
|
|
||||||
})
|
|
||||||
.addSubcommandGroup((option) => {
|
|
||||||
tankGroup = option.setName('tank').setDescription('Tank statistics');
|
|
||||||
|
|
||||||
return tankGroup;
|
|
||||||
});
|
|
||||||
|
|
||||||
addPeriodSubCommands(playerGroup!, (option) =>
|
|
||||||
option.addStringOption(addUsernameChoices),
|
|
||||||
);
|
|
||||||
addPeriodSubCommands(tankGroup!, (option) =>
|
|
||||||
option
|
|
||||||
.addStringOption(addTankChoices)
|
|
||||||
.addStringOption(addUsernameChoices),
|
|
||||||
);
|
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
command,
|
command: createLocalizedCommand('evolution', [
|
||||||
|
{
|
||||||
|
group: 'player',
|
||||||
|
modify(option: SlashCommandSubcommandGroupBuilder) {
|
||||||
|
addPeriodSubCommands(option, (option) =>
|
||||||
|
option.addStringOption(addUsernameChoices),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: 'tank',
|
||||||
|
modify(option: SlashCommandSubcommandGroupBuilder) {
|
||||||
|
addPeriodSubCommands(option, (option) =>
|
||||||
|
option
|
||||||
|
.addStringOption(addTankChoices)
|
||||||
|
.addStringOption(addUsernameChoices),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
|
||||||
async handler(interaction) {
|
async handler(interaction) {
|
||||||
const commandGroup =
|
const commandGroup =
|
||||||
@@ -156,8 +146,6 @@ export const evolutionCommand = new Promise<CommandRegistryPromisable>(
|
|||||||
tankId,
|
tankId,
|
||||||
});
|
});
|
||||||
|
|
||||||
getBlitzStarsLinkButton;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
await render(player, period, commandGroup, tankId),
|
await render(player, period, commandGroup, tankId),
|
||||||
buttonPrimary(path, 'Refresh'),
|
buttonPrimary(path, 'Refresh'),
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import resolvePlayerFromCommand, {
|
|||||||
} from '../core/discord/resolvePlayerFromCommand';
|
} from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { StatFilters, filterStats } from '../core/statistics/filterStats';
|
import { StatFilters, filterStats } from '../core/statistics/filterStats';
|
||||||
import { getTierWeights } from '../core/statistics/getTierWeights';
|
import { getTierWeights } from '../core/statistics/getTierWeights';
|
||||||
import { CommandRegistryPromisable } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|
||||||
async function render(
|
async function render(
|
||||||
{ region, id }: ResolvedPlayer,
|
{ region, id }: ResolvedPlayer,
|
||||||
@@ -64,7 +64,7 @@ async function render(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fullStatsCommand = new Promise<CommandRegistryPromisable>(
|
export const fullStatsCommand = new Promise<CommandRegistry>(
|
||||||
async (resolve) => {
|
async (resolve) => {
|
||||||
const command = await addPeriodicFilterOptions(
|
const command = await addPeriodicFilterOptions(
|
||||||
new SlashCommandBuilder()
|
new SlashCommandBuilder()
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import { CommandRegistry } from '../events/interactionCreate';
|
|||||||
|
|
||||||
const DEFAULT_THRESHOLD = 7;
|
const DEFAULT_THRESHOLD = 7;
|
||||||
|
|
||||||
export const inactiveCommand: CommandRegistry = {
|
export const inactiveCommand = new Promise<CommandRegistry>((resolve) => {
|
||||||
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
@@ -47,7 +48,8 @@ export const inactiveCommand: CommandRegistry = {
|
|||||||
.filter(([, inactiveDays]) => inactiveDays >= threshold)
|
.filter(([, inactiveDays]) => inactiveDays >= threshold)
|
||||||
.sort((a, b) => b[1] - a[1])
|
.sort((a, b) => b[1] - a[1])
|
||||||
.map(
|
.map(
|
||||||
([name, days]) => [name, `${days.toFixed(0)} days`] as [string, string],
|
([name, days]) =>
|
||||||
|
[name, `${days.toFixed(0)} days`] as [string, string],
|
||||||
);
|
);
|
||||||
const hasInactiveMembers = inactive.length > 0;
|
const hasInactiveMembers = inactive.length > 0;
|
||||||
|
|
||||||
@@ -66,4 +68,5 @@ export const inactiveCommand: CommandRegistry = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
autocomplete: autocompleteClan,
|
autocomplete: autocompleteClan,
|
||||||
};
|
});
|
||||||
|
});
|
||||||
@@ -16,14 +16,17 @@ import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
|||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { theme } from '../stitches.config';
|
import { theme } from '../stitches.config';
|
||||||
|
|
||||||
export const verifyCommand: CommandRegistry = {
|
export const verifyCommand = new Promise<CommandRegistry>((resolve) => {
|
||||||
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
command: new SlashCommandBuilder()
|
command: new SlashCommandBuilder()
|
||||||
.setName('link')
|
.setName('link')
|
||||||
.setDescription('Links your Blitz and Discord account')
|
.setDescription('Links your Blitz and Discord account')
|
||||||
.addStringOption((option) => addUsernameChoices(option).setRequired(true)),
|
.addStringOption((option) =>
|
||||||
|
addUsernameChoices(option).setRequired(true),
|
||||||
|
),
|
||||||
|
|
||||||
async handler(interaction) {
|
async handler(interaction) {
|
||||||
const { id, region } = await resolvePlayerFromCommand(interaction);
|
const { id, region } = await resolvePlayerFromCommand(interaction);
|
||||||
@@ -206,4 +209,5 @@ export const verifyCommand: CommandRegistry = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
autocomplete: autocompleteUsername,
|
autocomplete: autocompleteUsername,
|
||||||
};
|
});
|
||||||
|
});
|
||||||
@@ -21,7 +21,8 @@ import autocompleteUsername from '../core/discord/autocompleteUsername';
|
|||||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|
||||||
export const ownedTanksCommand: CommandRegistry = {
|
export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
|
||||||
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
@@ -72,7 +73,9 @@ export const ownedTanksCommand: CommandRegistry = {
|
|||||||
description={`Tier ${TIER_ROMAN_NUMERALS[tier as Tier]} tanks`}
|
description={`Tier ${TIER_ROMAN_NUMERALS[tier as Tier]} tanks`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{filteredTanks.length === 0 && <NoData type={NoDataType.TanksFound} />}
|
{filteredTanks.length === 0 && (
|
||||||
|
<NoData type={NoDataType.TanksFound} />
|
||||||
|
)}
|
||||||
|
|
||||||
{filteredTanks.length > 0 &&
|
{filteredTanks.length > 0 &&
|
||||||
(await Promise.all(
|
(await Promise.all(
|
||||||
@@ -125,4 +128,5 @@ export const ownedTanksCommand: CommandRegistry = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
autocomplete: autocompleteUsername,
|
autocomplete: autocompleteUsername,
|
||||||
};
|
});
|
||||||
|
});
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|
||||||
export const permissionsCommand: CommandRegistry = {
|
export const permissionsCommand = new Promise<CommandRegistry>((resolve) => {
|
||||||
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
@@ -39,4 +40,5 @@ export const permissionsCommand: CommandRegistry = {
|
|||||||
|
|
||||||
return `# Permissions\n${body}`;
|
return `# Permissions\n${body}`;
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
});
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|
||||||
export const pingCommand: CommandRegistry = {
|
export const pingCommand = new Promise<CommandRegistry>((resolve) => {
|
||||||
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
handlesInteraction: true,
|
handlesInteraction: true,
|
||||||
@@ -29,4 +30,5 @@ export const pingCommand: CommandRegistry = {
|
|||||||
const executionTime = Date.now() - executionStart;
|
const executionTime = Date.now() - executionStart;
|
||||||
interaction.editReply(`Pong 🏓 - ${executionTime}ms`);
|
interaction.editReply(`Pong 🏓 - ${executionTime}ms`);
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
});
|
||||||
@@ -12,7 +12,9 @@ import { CommandRegistry } from '../events/interactionCreate';
|
|||||||
|
|
||||||
type SortBy = 'name' | 'count';
|
type SortBy = 'name' | 'count';
|
||||||
|
|
||||||
export const playerAchievementsCommand: CommandRegistry = {
|
export const playerAchievementsCommand = new Promise<CommandRegistry>(
|
||||||
|
(resolve) => {
|
||||||
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
@@ -31,7 +33,8 @@ export const playerAchievementsCommand: CommandRegistry = {
|
|||||||
),
|
),
|
||||||
|
|
||||||
async handler(interaction) {
|
async handler(interaction) {
|
||||||
const sortBy = (interaction.options.getString('sort') ?? 'name') as SortBy;
|
const sortBy = (interaction.options.getString('sort') ??
|
||||||
|
'name') as SortBy;
|
||||||
const account = await resolvePlayerFromCommand(interaction);
|
const account = await resolvePlayerFromCommand(interaction);
|
||||||
const { id, region: region } = account;
|
const { id, region: region } = account;
|
||||||
const accountInfo = await getAccountInfo(region, id);
|
const accountInfo = await getAccountInfo(region, id);
|
||||||
@@ -65,4 +68,6 @@ export const playerAchievementsCommand: CommandRegistry = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
autocomplete: autocompleteUsername,
|
autocomplete: autocompleteUsername,
|
||||||
};
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
@@ -8,7 +8,8 @@ import markdownTable from '../core/discord/markdownTable';
|
|||||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|
||||||
export const playerInfoCommand: CommandRegistry = {
|
export const playerInfoCommand = new Promise<CommandRegistry>((resolve) => {
|
||||||
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
@@ -51,4 +52,5 @@ export const playerInfoCommand: CommandRegistry = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
autocomplete: autocompleteUsername,
|
autocomplete: autocompleteUsername,
|
||||||
};
|
});
|
||||||
|
});
|
||||||
@@ -27,7 +27,7 @@ import addUsernameChoices from '../core/discord/addUsernameChoices';
|
|||||||
import autocompleteUsername from '../core/discord/autocompleteUsername';
|
import autocompleteUsername from '../core/discord/autocompleteUsername';
|
||||||
import embedNegative from '../core/discord/embedNegative';
|
import embedNegative from '../core/discord/embedNegative';
|
||||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { CommandRegistryPromisable } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { UserError } from '../hooks/userError';
|
import { UserError } from '../hooks/userError';
|
||||||
|
|
||||||
export interface RatingsPlayer {
|
export interface RatingsPlayer {
|
||||||
@@ -122,8 +122,7 @@ const noOngoingSeason = embedNegative(
|
|||||||
"Wargaming didn't provide any data for this season.",
|
"Wargaming didn't provide any data for this season.",
|
||||||
);
|
);
|
||||||
|
|
||||||
export const ratingsCommand = new Promise<CommandRegistryPromisable>(
|
export const ratingsCommand = new Promise<CommandRegistry>(async (resolve) => {
|
||||||
async (resolve) => {
|
|
||||||
const latestArchivedSeasonNumber = await getArchivedLatestSeasonNumber();
|
const latestArchivedSeasonNumber = await getArchivedLatestSeasonNumber();
|
||||||
const onGoingSeason = await isOnGoingRatingsSeason();
|
const onGoingSeason = await isOnGoingRatingsSeason();
|
||||||
const seasonNumbers = range(
|
const seasonNumbers = range(
|
||||||
@@ -232,9 +231,7 @@ export const ratingsCommand = new Promise<CommandRegistryPromisable>(
|
|||||||
let regionRatingsInfo: RatingsInfo;
|
let regionRatingsInfo: RatingsInfo;
|
||||||
|
|
||||||
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;
|
||||||
regionRatingsInfo = await (isCurrentSeason
|
regionRatingsInfo = await (isCurrentSeason
|
||||||
? getRatingsInfo(region)
|
? getRatingsInfo(region)
|
||||||
@@ -283,8 +280,7 @@ export const ratingsCommand = new Promise<CommandRegistryPromisable>(
|
|||||||
position: firstPlayerIndex + index + 1,
|
position: firstPlayerIndex + index + 1,
|
||||||
clan: clanData[player.id]?.clan?.tag,
|
clan: clanData[player.id]?.clan?.tag,
|
||||||
nickname:
|
nickname:
|
||||||
clanData[index]?.account_name ??
|
clanData[index]?.account_name ?? `Deleted ${player.id}`,
|
||||||
`Deleted ${player.id}`,
|
|
||||||
}) satisfies SimplifiedPlayer,
|
}) satisfies SimplifiedPlayer,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -451,5 +447,4 @@ export const ratingsCommand = new Promise<CommandRegistryPromisable>(
|
|||||||
|
|
||||||
autocomplete: autocompleteUsername,
|
autocomplete: autocompleteUsername,
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
);
|
|
||||||
@@ -9,7 +9,8 @@ import embedInfo from '../core/discord/embedInfo';
|
|||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { ClanList } from '../types/clanList';
|
import { ClanList } from '../types/clanList';
|
||||||
|
|
||||||
export const searchClansCommand: CommandRegistry = {
|
export const searchClansCommand = new Promise<CommandRegistry>((resolve) => {
|
||||||
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
@@ -17,7 +18,9 @@ export const searchClansCommand: CommandRegistry = {
|
|||||||
.setName('search-clans')
|
.setName('search-clans')
|
||||||
.setDescription('Search clans')
|
.setDescription('Search clans')
|
||||||
.addStringOption(addRegionChoices)
|
.addStringOption(addRegionChoices)
|
||||||
.addStringOption((option) => addClanChoices(option).setAutocomplete(false))
|
.addStringOption((option) =>
|
||||||
|
addClanChoices(option).setAutocomplete(false),
|
||||||
|
)
|
||||||
.addIntegerOption((option) =>
|
.addIntegerOption((option) =>
|
||||||
option
|
option
|
||||||
.setName('limit')
|
.setName('limit')
|
||||||
@@ -43,4 +46,5 @@ export const searchClansCommand: CommandRegistry = {
|
|||||||
.join('\n')}\n\`\`\``,
|
.join('\n')}\n\`\`\``,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
});
|
||||||
@@ -12,7 +12,8 @@ import addUsernameChoices from '../core/discord/addUsernameChoices';
|
|||||||
import embedInfo from '../core/discord/embedInfo';
|
import embedInfo from '../core/discord/embedInfo';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|
||||||
export const searchPlayersCommand: CommandRegistry = {
|
export const searchPlayersCommand = new Promise<CommandRegistry>((resolve) => {
|
||||||
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
@@ -53,4 +54,5 @@ export const searchPlayersCommand: CommandRegistry = {
|
|||||||
}\`\`\``,
|
}\`\`\``,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
});
|
||||||
@@ -6,14 +6,17 @@ import addTankChoices from '../core/discord/addTankChoices';
|
|||||||
import embedInfo from '../core/discord/embedInfo';
|
import embedInfo from '../core/discord/embedInfo';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|
||||||
export const searchTanksCommand: CommandRegistry = {
|
export const searchTanksCommand = new Promise<CommandRegistry>((resolve) => {
|
||||||
|
resolve({
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
command: new SlashCommandBuilder()
|
command: new SlashCommandBuilder()
|
||||||
.setName('search-tanks')
|
.setName('search-tanks')
|
||||||
.setDescription('Search tanks')
|
.setDescription('Search tanks')
|
||||||
.addStringOption((option) => addTankChoices(option).setAutocomplete(false))
|
.addStringOption((option) =>
|
||||||
|
addTankChoices(option).setAutocomplete(false),
|
||||||
|
)
|
||||||
.addIntegerOption((option) =>
|
.addIntegerOption((option) =>
|
||||||
option
|
option
|
||||||
.setName('limit')
|
.setName('limit')
|
||||||
@@ -37,4 +40,5 @@ export const searchTanksCommand: CommandRegistry = {
|
|||||||
: `\`\`\`\n${results.join('\n')}\n\`\`\``,
|
: `\`\`\`\n${results.join('\n')}\n\`\`\``,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
});
|
||||||
@@ -27,7 +27,7 @@ import resolvePlayerFromCommand, {
|
|||||||
ResolvedPlayer,
|
ResolvedPlayer,
|
||||||
} from '../core/discord/resolvePlayerFromCommand';
|
} from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { StatFilters, filterStats } from '../core/statistics/filterStats';
|
import { StatFilters, filterStats } from '../core/statistics/filterStats';
|
||||||
import { CommandRegistryPromisable } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|
||||||
async function render(
|
async function render(
|
||||||
{ region, id }: ResolvedPlayer,
|
{ region, id }: ResolvedPlayer,
|
||||||
@@ -57,8 +57,7 @@ async function render(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const statsCommand = new Promise<CommandRegistryPromisable>(
|
export const statsCommand = new Promise<CommandRegistry>(async (resolve) => {
|
||||||
async (resolve) => {
|
|
||||||
const command = await addPeriodicFilterOptions(
|
const command = await addPeriodicFilterOptions(
|
||||||
new SlashCommandBuilder()
|
new SlashCommandBuilder()
|
||||||
.setName('stats')
|
.setName('stats')
|
||||||
@@ -102,5 +101,4 @@ export const statsCommand = new Promise<CommandRegistryPromisable>(
|
|||||||
return await render(player, period, filters);
|
return await render(player, period, filters);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
);
|
|
||||||
@@ -14,11 +14,10 @@ import resolvePeriodFromButton from '../core/discord/resolvePeriodFromButton';
|
|||||||
import resolvePeriodFromCommand from '../core/discord/resolvePeriodFromCommand';
|
import resolvePeriodFromCommand from '../core/discord/resolvePeriodFromCommand';
|
||||||
import resolvePlayerFromButton from '../core/discord/resolvePlayerFromButton';
|
import resolvePlayerFromButton from '../core/discord/resolvePlayerFromButton';
|
||||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { CommandRegistryPromisable } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { renderBreakdown } from './breakdown';
|
import { renderBreakdown } from './breakdown';
|
||||||
|
|
||||||
export const todayCommand = new Promise<CommandRegistryPromisable>(
|
export const todayCommand = new Promise<CommandRegistry>(async (resolve) => {
|
||||||
async (resolve) => {
|
|
||||||
const awaitedEncyclopediaInfo = await encyclopediaInfo;
|
const awaitedEncyclopediaInfo = await encyclopediaInfo;
|
||||||
const command = addFilterOptions(
|
const command = addFilterOptions(
|
||||||
new SlashCommandBuilder()
|
new SlashCommandBuilder()
|
||||||
@@ -67,5 +66,4 @@ export const todayCommand = new Promise<CommandRegistryPromisable>(
|
|||||||
return await renderBreakdown(player, period, filters);
|
return await renderBreakdown(player, period, filters);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
);
|
|
||||||
@@ -1,14 +1,27 @@
|
|||||||
import { Locale, SlashCommandBuilder } from 'discord.js';
|
import {
|
||||||
|
Locale,
|
||||||
|
SlashCommandBuilder,
|
||||||
|
SlashCommandSubcommandBuilder,
|
||||||
|
SlashCommandSubcommandGroupBuilder,
|
||||||
|
} from 'discord.js';
|
||||||
import { translator } from '../localization/translator';
|
import { translator } from '../localization/translator';
|
||||||
import { localizationObject } from './localizationObject';
|
import { localizationObject } from './localizationObject';
|
||||||
|
|
||||||
interface CreateLocalizedCommandSubcommand {
|
interface CreateLocalizedCommandSubcommand {
|
||||||
subcommand: string;
|
subcommand: string;
|
||||||
|
modify?: (option: SlashCommandSubcommandBuilder) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CreateLocalizedCommandSubcommandGroup {
|
||||||
|
group: string;
|
||||||
|
modify?: (option: SlashCommandSubcommandGroupBuilder) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createLocalizedCommand(
|
export function createLocalizedCommand(
|
||||||
command: string,
|
command: string,
|
||||||
subcommands?: CreateLocalizedCommandSubcommand[],
|
sub?:
|
||||||
|
| CreateLocalizedCommandSubcommand[]
|
||||||
|
| CreateLocalizedCommandSubcommandGroup[],
|
||||||
) {
|
) {
|
||||||
const { translate } = translator(Locale.EnglishUS);
|
const { translate } = translator(Locale.EnglishUS);
|
||||||
const slashCommand = new SlashCommandBuilder()
|
const slashCommand = new SlashCommandBuilder()
|
||||||
@@ -19,26 +32,51 @@ export function createLocalizedCommand(
|
|||||||
localizationObject(`bot.commands.${command}.description`),
|
localizationObject(`bot.commands.${command}.description`),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (subcommands) {
|
if (sub) {
|
||||||
subcommands.map(({ subcommand }) => {
|
sub.map((subItem) => {
|
||||||
|
if ('subcommand' in subItem) {
|
||||||
const subcommandNameLocalizations = localizationObject(
|
const subcommandNameLocalizations = localizationObject(
|
||||||
`bot.commands.${command}.subcommands.${subcommand}`,
|
`bot.commands.${command}.subcommands.${subItem.subcommand}`,
|
||||||
);
|
);
|
||||||
const subcommandDescriptionLocalizations = localizationObject(
|
const subcommandDescriptionLocalizations = localizationObject(
|
||||||
`bot.commands.${command}.subcommands.${subcommand}.description`,
|
`bot.commands.${command}.subcommands.${subItem.subcommand}.description`,
|
||||||
);
|
);
|
||||||
|
|
||||||
slashCommand.addSubcommand((option) =>
|
slashCommand.addSubcommand((option) => {
|
||||||
option
|
if (subItem.modify) subItem.modify(option);
|
||||||
.setName(subcommand)
|
|
||||||
|
return option
|
||||||
|
.setName(subItem.subcommand)
|
||||||
.setNameLocalizations(subcommandNameLocalizations)
|
.setNameLocalizations(subcommandNameLocalizations)
|
||||||
.setDescription(
|
.setDescription(
|
||||||
translate(
|
translate(
|
||||||
`bot.commands.${command}.subcommands.${subcommand}.description`,
|
`bot.commands.${command}.subcommands.${subItem.subcommand}.description`,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.setDescriptionLocalizations(subcommandDescriptionLocalizations),
|
.setDescriptionLocalizations(subcommandDescriptionLocalizations);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const subcommandNameLocalizations = localizationObject(
|
||||||
|
`bot.commands.${command}.groups.${subItem.group}`,
|
||||||
);
|
);
|
||||||
|
const subcommandDescriptionLocalizations = localizationObject(
|
||||||
|
`bot.commands.${command}.groups.${subItem.group}.description`,
|
||||||
|
);
|
||||||
|
|
||||||
|
slashCommand.addSubcommandGroup((option) => {
|
||||||
|
if (subItem.modify) subItem.modify(option);
|
||||||
|
|
||||||
|
return option
|
||||||
|
.setName(subItem.group)
|
||||||
|
.setNameLocalizations(subcommandNameLocalizations)
|
||||||
|
.setDescription(
|
||||||
|
translate(
|
||||||
|
`bot.commands.${command}.groups.${subItem.group}.description`,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.setDescriptionLocalizations(subcommandDescriptionLocalizations);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export default function resolvePeriodFromButton(
|
|||||||
start = getTimeDaysAgo(region, endDaysAgoMax);
|
start = getTimeDaysAgo(region, endDaysAgoMax);
|
||||||
end = getTimeDaysAgo(region, startDaysAgoMin);
|
end = getTimeDaysAgo(region, startDaysAgoMin);
|
||||||
} else {
|
} else {
|
||||||
name = getPeriodOptionName(periodSubcommand);
|
name = getPeriodOptionName(periodSubcommand, interaction.locale);
|
||||||
start = getPeriodStart(region, periodSubcommand);
|
start = getPeriodStart(region, periodSubcommand);
|
||||||
end = getPeriodNow();
|
end = getPeriodNow();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
import { CacheType, ChatInputCommandInteraction } from 'discord.js';
|
import { CacheType, ChatInputCommandInteraction, Locale } from 'discord.js';
|
||||||
import { Region } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import getPeriodNow from '../blitzkrieg/getPeriodNow';
|
import getPeriodNow from '../blitzkrieg/getPeriodNow';
|
||||||
import getPeriodStart from '../blitzkrieg/getPeriodStart';
|
import getPeriodStart from '../blitzkrieg/getPeriodStart';
|
||||||
import getTimeDaysAgo from '../blitzkrieg/getTimeDaysAgo';
|
import getTimeDaysAgo from '../blitzkrieg/getTimeDaysAgo';
|
||||||
|
import { translator } from '../localization/translator';
|
||||||
import { PeriodSize, PeriodType } from './addPeriodSubCommands';
|
import { PeriodSize, PeriodType } from './addPeriodSubCommands';
|
||||||
|
|
||||||
export function getPeriodOptionName(period: PeriodSize) {
|
export function getPeriodOptionName(period: PeriodSize, locale: Locale) {
|
||||||
if (period === 'career') return 'Career';
|
const { translate } = translator(locale);
|
||||||
if (period === 'today') return 'Today';
|
|
||||||
return `${period} days`;
|
if (period === 'career') return translate('bot.common.periods.career');
|
||||||
|
if (period === 'today') return translate('bot.common.periods.today');
|
||||||
|
return translate('bot.common.periods.days', [period]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResolvedPeriod {
|
export interface ResolvedPeriod {
|
||||||
@@ -39,7 +42,7 @@ export default function resolvePeriodFromCommand(
|
|||||||
start = getTimeDaysAgo(region, endDaysAgoMax);
|
start = getTimeDaysAgo(region, endDaysAgoMax);
|
||||||
end = getTimeDaysAgo(region, startDaysAgoMin);
|
end = getTimeDaysAgo(region, startDaysAgoMin);
|
||||||
} else {
|
} else {
|
||||||
name = getPeriodOptionName(periodSubcommand);
|
name = getPeriodOptionName(periodSubcommand, interaction.locale);
|
||||||
start = getPeriodStart(region, periodSubcommand);
|
start = getPeriodStart(region, periodSubcommand);
|
||||||
end = getPeriodNow();
|
end = getPeriodNow();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ export function translator(localeRaw: Locale) {
|
|||||||
const locale = locales.includes(localeRaw) ? localeRaw : Locale.EnglishUS;
|
const locale = locales.includes(localeRaw) ? localeRaw : Locale.EnglishUS;
|
||||||
const strings = translations[locale];
|
const strings = translations[locale];
|
||||||
|
|
||||||
function translate(path: string): string {
|
function translate(path: string, literals?: string[]): string {
|
||||||
const pathArray = path.split('.');
|
const pathArray = path.split('.');
|
||||||
let fragment = strings;
|
let fragment = strings;
|
||||||
|
let resolvedString: string;
|
||||||
|
|
||||||
for (const pathItem of pathArray) {
|
for (const pathItem of pathArray) {
|
||||||
if (typeof fragment === 'string') {
|
if (typeof fragment === 'string') {
|
||||||
@@ -33,14 +34,26 @@ export function translator(localeRaw: Locale) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof fragment === 'string') {
|
if (typeof fragment === 'string') {
|
||||||
return fragment;
|
resolvedString = fragment;
|
||||||
} else if (fragment.$) {
|
} else if (fragment.$) {
|
||||||
return fragment.$!;
|
resolvedString = fragment.$!;
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unresolved tree ending for "${path}" in locale "${locale}"`,
|
`Unresolved tree ending for "${path}" in locale "${locale}"`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (literals) {
|
||||||
|
const chunks = resolvedString.split('%s');
|
||||||
|
let embeddedString = '';
|
||||||
|
|
||||||
|
chunks.forEach((chunk, index) => {
|
||||||
|
if (index !== 0) embeddedString += literals[index - 1];
|
||||||
|
embeddedString += chunk;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolvedString;
|
||||||
}
|
}
|
||||||
|
|
||||||
function t(paths: TemplateStringsArray, ...embeds: string[]) {
|
function t(paths: TemplateStringsArray, ...embeds: string[]) {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import discord from '../../../discord.json' assert { type: 'json' };
|
|||||||
import { aboutCommand } from '../../commands/about';
|
import { aboutCommand } from '../../commands/about';
|
||||||
import { breakdownCommand } from '../../commands/breakdown';
|
import { breakdownCommand } from '../../commands/breakdown';
|
||||||
import { debugCommand } from '../../commands/debug';
|
import { debugCommand } from '../../commands/debug';
|
||||||
import { eligibleCommand } from '../../commands/eligible';
|
|
||||||
import { evolutionCommand } from '../../commands/evolution';
|
import { evolutionCommand } from '../../commands/evolution';
|
||||||
import { fullStatsCommand } from '../../commands/fullStats';
|
import { fullStatsCommand } from '../../commands/fullStats';
|
||||||
import { inactiveCommand } from '../../commands/inactive';
|
import { inactiveCommand } from '../../commands/inactive';
|
||||||
@@ -78,22 +77,18 @@ type CommandRegistryDefinitionDoesHandleInteraction = {
|
|||||||
interaction: ChatInputCommandInteraction<CacheType>,
|
interaction: ChatInputCommandInteraction<CacheType>,
|
||||||
) => InteractionReturnable;
|
) => InteractionReturnable;
|
||||||
};
|
};
|
||||||
export type CommandRegistryPromisable = CommandRegistryBase &
|
export type CommandRegistry = CommandRegistryBase &
|
||||||
(CommandRegistryDefinitionBase &
|
(CommandRegistryDefinitionBase &
|
||||||
(
|
(
|
||||||
| CommandRegistryDefinitionHandlesInteraction
|
| CommandRegistryDefinitionHandlesInteraction
|
||||||
| CommandRegistryDefinitionDoesHandleInteraction
|
| CommandRegistryDefinitionDoesHandleInteraction
|
||||||
));
|
));
|
||||||
export type CommandRegistry =
|
|
||||||
| CommandRegistryPromisable
|
|
||||||
| Promise<CommandRegistryPromisable>;
|
|
||||||
|
|
||||||
const rest = new REST().setToken(secrets.DISCORD_TOKEN);
|
const rest = new REST().setToken(secrets.DISCORD_TOKEN);
|
||||||
|
|
||||||
export const COMMANDS_RAW: CommandRegistry[] = [
|
export const COMMANDS_RAW: Promise<CommandRegistry>[] = [
|
||||||
permissionsCommand,
|
permissionsCommand,
|
||||||
debugCommand,
|
debugCommand,
|
||||||
eligibleCommand,
|
|
||||||
aboutCommand,
|
aboutCommand,
|
||||||
inactiveCommand,
|
inactiveCommand,
|
||||||
ownedTanksCommand,
|
ownedTanksCommand,
|
||||||
@@ -113,7 +108,7 @@ export const COMMANDS_RAW: CommandRegistry[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const commands = Promise.allSettled(COMMANDS_RAW).then((rawCommands) => {
|
export const commands = Promise.allSettled(COMMANDS_RAW).then((rawCommands) => {
|
||||||
return rawCommands.reduce<Record<string, CommandRegistryPromisable>>(
|
return rawCommands.reduce<Record<string, CommandRegistry>>(
|
||||||
(commands, registry) => {
|
(commands, registry) => {
|
||||||
if (registry.status === 'rejected') return commands;
|
if (registry.status === 'rejected') return commands;
|
||||||
if (isDev()) registry.value.command.setDefaultMemberPermissions(0);
|
if (isDev()) registry.value.command.setDefaultMemberPermissions(0);
|
||||||
|
|||||||
@@ -51,6 +51,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"periods": {
|
||||||
|
"career": "Career",
|
||||||
|
"today": "Today",
|
||||||
|
"days": "%s days",
|
||||||
|
"custom": "%s - %s days"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -112,6 +119,23 @@
|
|||||||
},
|
},
|
||||||
"uptime": "Uptime"
|
"uptime": "Uptime"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"evolution": {
|
||||||
|
"$": "evolution",
|
||||||
|
"description": "Evolution of statistics",
|
||||||
|
|
||||||
|
"groups": {
|
||||||
|
"player": {
|
||||||
|
"$": "player",
|
||||||
|
"description": "Player statistics"
|
||||||
|
},
|
||||||
|
|
||||||
|
"tank": {
|
||||||
|
"$": "tank",
|
||||||
|
"description": "Tank statistics"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in new issue
Block a user