mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
feat: added basic infrastructure for ratings command
This commit is contained in:
1 parent
9419aec116
commit
aa6011b18d
40 files changed
+227
-96
No files matched your search
@@ -49,7 +49,7 @@ export const eligibleCommand: CommandRegistry = {
|
||||
|
||||
async handler(interaction) {
|
||||
const clan = interaction.options.getString('clan') as SkilledClan;
|
||||
const { id, server } = await resolvePlayerFromCommand(interaction);
|
||||
const { id, region: server } = await resolvePlayerFromCommand(interaction);
|
||||
const accountInfo = await getWargamingResponse<AccountInfo>(
|
||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||
);
|
||||
|
||||
@@ -34,7 +34,7 @@ export const evolutionCommand: CommandRegistry = {
|
||||
true,
|
||||
) as StatType;
|
||||
const player = await resolvePlayerFromCommand(interaction);
|
||||
const period = resolvePeriodFromCommand(player.server, interaction);
|
||||
const period = resolvePeriodFromCommand(player.region, interaction);
|
||||
const tankIdRaw = interaction.options.getString('tank')!;
|
||||
const tankId =
|
||||
commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null;
|
||||
@@ -42,7 +42,7 @@ export const evolutionCommand: CommandRegistry = {
|
||||
const end = interaction.options.getInteger('end');
|
||||
const { nickname } = (
|
||||
await getWargamingResponse<AccountInfo>(
|
||||
`https://api.wotblitz.${player.server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||
`https://api.wotblitz.${player.region}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||
)
|
||||
)[player.id];
|
||||
const path = interactionToURL(interaction, {
|
||||
@@ -57,7 +57,7 @@ export const evolutionCommand: CommandRegistry = {
|
||||
primaryButton(path, 'Refresh'),
|
||||
// linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
||||
linkButton(
|
||||
`https://www.blitzstars.com/player/${player.server}/${nickname}${
|
||||
`https://www.blitzstars.com/player/${player.region}/${nickname}${
|
||||
commandGroup === 'tank' ? `/tank/${tankId!}` : ''
|
||||
}`,
|
||||
'BlitzStars',
|
||||
|
||||
@@ -33,7 +33,7 @@ export const fullStatsCommand: CommandRegistry = {
|
||||
true,
|
||||
) as StatType;
|
||||
const player = await resolvePlayerFromCommand(interaction);
|
||||
const period = resolvePeriodFromCommand(player.server, interaction);
|
||||
const period = resolvePeriodFromCommand(player.region, interaction);
|
||||
const tankIdRaw = interaction.options.getString('tank')!;
|
||||
const tankId =
|
||||
commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null;
|
||||
@@ -47,7 +47,7 @@ export const fullStatsCommand: CommandRegistry = {
|
||||
});
|
||||
const { nickname } = (
|
||||
await getWargamingResponse<AccountInfo>(
|
||||
`https://api.wotblitz.${player.server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||
`https://api.wotblitz.${player.region}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||
)
|
||||
)[player.id];
|
||||
|
||||
@@ -56,7 +56,7 @@ export const fullStatsCommand: CommandRegistry = {
|
||||
primaryButton(path, 'Refresh'),
|
||||
// linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
||||
linkButton(
|
||||
`https://www.blitzstars.com/player/${player.server}/${nickname}`,
|
||||
`https://www.blitzstars.com/player/${player.region}/${nickname}`,
|
||||
'BlitzStars',
|
||||
),
|
||||
];
|
||||
|
||||
@@ -4,7 +4,7 @@ import NoData, { NoDataType } from '../components/NoData';
|
||||
import PoweredBy, { PoweredByType } from '../components/PoweredBy';
|
||||
import TitleBar from '../components/TitleBar';
|
||||
import Wrapper from '../components/Wrapper';
|
||||
import { REGION_DOMAIN_NAMES } from '../constants/regions';
|
||||
import { REGION_NAMES } from '../constants/regions';
|
||||
import getBlitzClan from '../core/blitz/getBlitzClan';
|
||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||
import addClanChoices from '../core/discord/addClanChoices';
|
||||
@@ -72,7 +72,7 @@ export const inactiveCommand: CommandRegistry = {
|
||||
nameDiscriminator="(Inactivity)"
|
||||
image={`https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clanData.emblem_set_id}.png`}
|
||||
description={`${threshold}+ Days • ${new Date().toDateString()} • ${
|
||||
REGION_DOMAIN_NAMES[server]
|
||||
REGION_NAMES[server]
|
||||
}`}
|
||||
/>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import PoweredBy, { PoweredByType } from '../components/PoweredBy';
|
||||
import * as Tanks from '../components/Tanks';
|
||||
import TitleBar from '../components/TitleBar';
|
||||
import Wrapper from '../components/Wrapper';
|
||||
import { REGION_DOMAIN_NAMES } from '../constants/regions';
|
||||
import { REGION_NAMES } from '../constants/regions';
|
||||
import getTankStats from '../core/blitz/getTankStats';
|
||||
import getTreeType from '../core/blitz/getTreeType';
|
||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||
@@ -74,7 +74,7 @@ export const ownedTanksCommand: CommandRegistry = {
|
||||
async handler(interaction) {
|
||||
const tier = Number(interaction.options.getString('tier'));
|
||||
const account = await resolvePlayerFromCommand(interaction);
|
||||
const { id, server } = account;
|
||||
const { id, region: server } = account;
|
||||
const accountInfo = await getWargamingResponse<AccountInfo>(
|
||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||
);
|
||||
@@ -105,7 +105,7 @@ export const ownedTanksCommand: CommandRegistry = {
|
||||
: undefined
|
||||
}
|
||||
description={`Owned tanks • ${new Date().toDateString()} • ${
|
||||
REGION_DOMAIN_NAMES[server]
|
||||
REGION_NAMES[server]
|
||||
}`}
|
||||
/>
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ export const playerAchievementsCommand: CommandRegistry = {
|
||||
async handler(interaction) {
|
||||
const sortBy = (interaction.options.getString('sort') ?? 'name') as SortBy;
|
||||
const account = await resolvePlayerFromCommand(interaction);
|
||||
const { id, server } = account;
|
||||
const { id, region: server } = account;
|
||||
const accounts = await getWargamingResponse<AccountInfo>(
|
||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||
);
|
||||
|
||||
@@ -22,7 +22,7 @@ export const playerInfoCommand: CommandRegistry = {
|
||||
|
||||
async handler(interaction) {
|
||||
const account = await resolvePlayerFromCommand(interaction);
|
||||
const { id, server } = account;
|
||||
const { id, region: server } = account;
|
||||
const accounts = await getWargamingResponse<AccountInfo>(
|
||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||
);
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
import { SlashCommandBuilder, SlashCommandSubcommandBuilder } from 'discord.js';
|
||||
import regionToRegionSubdomain from '../core/blitz/regionToRegionSubdomain';
|
||||
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
||||
import autocompleteUsername from '../core/discord/autocompleteUsername';
|
||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||
import { CommandRegistry } from '../events/interactionCreate';
|
||||
|
||||
export interface LeaguePlayer {
|
||||
spa_id: number;
|
||||
mmr: number;
|
||||
season_number: number;
|
||||
calibrationBattlesLeft: number;
|
||||
number: number;
|
||||
percentile: number;
|
||||
skip: boolean;
|
||||
updated_at: string;
|
||||
score: number;
|
||||
nickname: string;
|
||||
clan_tag: string;
|
||||
}
|
||||
|
||||
export interface LeagueTop {
|
||||
result: LeaguePlayer[];
|
||||
}
|
||||
|
||||
const LEAGUE_INDEXES = ['diamond', 'platinum', 'gold', 'silver', 'bronze'];
|
||||
|
||||
function optionalParameters(option: SlashCommandSubcommandBuilder) {
|
||||
return option
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName('limit')
|
||||
.setDescription('How many rows to display (default: 16)')
|
||||
.setRequired(true)
|
||||
.setMinValue(5)
|
||||
.setMaxValue(30),
|
||||
)
|
||||
.addStringOption(addUsernameChoices);
|
||||
}
|
||||
|
||||
export const ratingsCommand: CommandRegistry = {
|
||||
inProduction: true,
|
||||
inDevelopment: true,
|
||||
inPublic: true,
|
||||
inPreview: true,
|
||||
|
||||
command: new SlashCommandBuilder()
|
||||
.setName('ratings')
|
||||
.setDescription('Ratings battles statistics')
|
||||
.addSubcommandGroup((option) =>
|
||||
option
|
||||
.setName('league')
|
||||
.setDescription('Top league players')
|
||||
.addSubcommand((option) =>
|
||||
optionalParameters(
|
||||
option
|
||||
.setName('diamond')
|
||||
.setDescription('Top Diamond League players'),
|
||||
),
|
||||
)
|
||||
.addSubcommand((option) =>
|
||||
optionalParameters(
|
||||
option
|
||||
.setName('platinum')
|
||||
.setDescription('Top Platinum League players'),
|
||||
),
|
||||
)
|
||||
.addSubcommand((option) =>
|
||||
optionalParameters(
|
||||
option.setName('gold').setDescription('Top Gold League players'),
|
||||
),
|
||||
)
|
||||
.addSubcommand((option) =>
|
||||
optionalParameters(
|
||||
option
|
||||
.setName('silver')
|
||||
.setDescription('Top Silver League players'),
|
||||
),
|
||||
)
|
||||
.addSubcommand((option) =>
|
||||
optionalParameters(
|
||||
option
|
||||
.setName('bronze')
|
||||
.setDescription('Top Bronze League players'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
async handler(interaction) {
|
||||
const subcommandGroup = interaction.options.getSubcommandGroup(true);
|
||||
|
||||
if (subcommandGroup === 'league') {
|
||||
const limit = interaction.options.getInteger('limit') ?? 16;
|
||||
const subcommand = interaction.options.getSubcommand(true);
|
||||
const leagueIndex = LEAGUE_INDEXES.indexOf(subcommand);
|
||||
const player = await resolvePlayerFromCommand(interaction);
|
||||
const regionSubdomain = regionToRegionSubdomain(player.region);
|
||||
const { result } = await fetch(
|
||||
`https://${regionSubdomain}.wotblitz.com/en/api/rating-leaderboards/league/${leagueIndex}/top/`,
|
||||
).then((response) => response.json() as Promise<LeagueTop>);
|
||||
|
||||
return `\`\`\`${result
|
||||
.slice(0, limit)
|
||||
.map(
|
||||
(player) =>
|
||||
`${player.number}: ${player.nickname} [${player.clan_tag}]`,
|
||||
)
|
||||
.join('\n')}\`\`\``;
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
|
||||
autocomplete: autocompleteUsername,
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SlashCommandBuilder } from 'discord.js';
|
||||
import markdownEscape from 'markdown-escape';
|
||||
import { REGION_DOMAIN_NAMES, RegionDomain } from '../constants/regions';
|
||||
import { REGION_NAMES, Region } from '../constants/regions';
|
||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||
import addClanChoices from '../core/discord/addClanChoices';
|
||||
import addServerChoices from '../core/discord/addServerChoices';
|
||||
@@ -28,7 +28,7 @@ export const searchClansCommand: CommandRegistry = {
|
||||
),
|
||||
|
||||
async handler(interaction) {
|
||||
const server = interaction.options.getString('server') as RegionDomain;
|
||||
const server = interaction.options.getString('server') as Region;
|
||||
const clan = interaction.options.getString('clan')!;
|
||||
const limit = interaction.options.getInteger('limit') ?? 25;
|
||||
const clanList = await getWargamingResponse<ClanList>(
|
||||
@@ -36,9 +36,7 @@ export const searchClansCommand: CommandRegistry = {
|
||||
);
|
||||
|
||||
return embedInfo(
|
||||
`Clan search for "${markdownEscape(clan)}" in ${
|
||||
REGION_DOMAIN_NAMES[server]
|
||||
}`,
|
||||
`Clan search for "${markdownEscape(clan)}" in ${REGION_NAMES[server]}`,
|
||||
clanList.length === 0
|
||||
? 'No clans found.'
|
||||
: `\`\`\`\n${clanList
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SlashCommandBuilder } from 'discord.js';
|
||||
import markdownEscape from 'markdown-escape';
|
||||
import { REGION_DOMAIN_NAMES, RegionDomain } from '../constants/regions';
|
||||
import { REGION_NAMES, Region } from '../constants/regions';
|
||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||
import { usernamePattern } from '../core/blitz/listPlayers';
|
||||
import addServerChoices from '../core/discord/addServerChoices';
|
||||
@@ -31,7 +31,7 @@ export const searchPlayersCommand: CommandRegistry = {
|
||||
),
|
||||
|
||||
async handler(interaction) {
|
||||
const server = interaction.options.getString('server') as RegionDomain;
|
||||
const server = interaction.options.getString('server') as Region;
|
||||
const name = interaction.options.getString('username')!;
|
||||
const limit = interaction.options.getInteger('limit') ?? 25;
|
||||
const trimmedSearch = name.trim();
|
||||
@@ -44,9 +44,7 @@ export const searchPlayersCommand: CommandRegistry = {
|
||||
: [];
|
||||
|
||||
return embedInfo(
|
||||
`Player search for "${markdownEscape(name)}" in ${
|
||||
REGION_DOMAIN_NAMES[server]
|
||||
}`,
|
||||
`Player search for "${markdownEscape(name)}" in ${REGION_NAMES[server]}`,
|
||||
`\`\`\`${
|
||||
players.length === 0
|
||||
? 'No players found.'
|
||||
|
||||
@@ -26,7 +26,7 @@ export const statsCommand: CommandRegistry = {
|
||||
command: addStatTypeSubCommandGroups(
|
||||
new SlashCommandBuilder()
|
||||
.setName('stats')
|
||||
.setDescription('In-game statistics'),
|
||||
.setDescription('Regular battles statistics'),
|
||||
),
|
||||
|
||||
async handler(interaction) {
|
||||
@@ -34,7 +34,7 @@ export const statsCommand: CommandRegistry = {
|
||||
true,
|
||||
) as StatType;
|
||||
const player = await resolvePlayerFromCommand(interaction);
|
||||
const period = resolvePeriodFromCommand(player.server, interaction);
|
||||
const period = resolvePeriodFromCommand(player.region, interaction);
|
||||
const tankIdRaw = interaction.options.getString('tank')!;
|
||||
const tankId =
|
||||
commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null;
|
||||
@@ -48,7 +48,7 @@ export const statsCommand: CommandRegistry = {
|
||||
});
|
||||
const { nickname } = (
|
||||
await getWargamingResponse<AccountInfo>(
|
||||
`https://api.wotblitz.${player.server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||
`https://api.wotblitz.${player.region}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||
)
|
||||
)[player.id];
|
||||
|
||||
@@ -57,7 +57,7 @@ export const statsCommand: CommandRegistry = {
|
||||
primaryButton(path, 'Refresh'),
|
||||
linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
||||
linkButton(
|
||||
`https://www.blitzstars.com/player/${player.server}/${nickname}`,
|
||||
`https://www.blitzstars.com/player/${player.region}/${nickname}`,
|
||||
'BlitzStars',
|
||||
),
|
||||
];
|
||||
|
||||
@@ -37,7 +37,7 @@ export const todayCommand: CommandRegistry = {
|
||||
const limit = interaction.options.getInteger('limit') ?? Infinity;
|
||||
const { nickname } = (
|
||||
await getWargamingResponse<AccountInfo>(
|
||||
`https://api.wotblitz.${player.server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||
`https://api.wotblitz.${player.region}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||
)
|
||||
)[player.id];
|
||||
const path = interactionToURL(interaction, player);
|
||||
@@ -47,7 +47,7 @@ export const todayCommand: CommandRegistry = {
|
||||
primaryButton(path, 'Refresh'),
|
||||
linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
||||
linkButton(
|
||||
`https://www.blitzstars.com/player/${player.server}/${nickname}`,
|
||||
`https://www.blitzstars.com/player/${player.region}/${nickname}`,
|
||||
'BlitzStars',
|
||||
),
|
||||
];
|
||||
|
||||
@@ -24,7 +24,7 @@ export const verifyCommand: CommandRegistry = {
|
||||
|
||||
async handler(interaction) {
|
||||
const blitzAccount = await resolvePlayerFromCommand(interaction);
|
||||
const { id, server } = blitzAccount;
|
||||
const { id, region: server } = blitzAccount;
|
||||
const accountInfo = await getWargamingResponse<AccountInfo>(
|
||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export type RegionDomain = 'com' | 'eu' | 'asia';
|
||||
export type Region = 'com' | 'eu' | 'asia';
|
||||
export type RegionSubdomain = 'na' | 'eu' | 'asia';
|
||||
|
||||
export const REGION_DOMAIN_NAMES: Record<RegionDomain, string> = {
|
||||
export const REGION_NAMES: Record<Region, string> = {
|
||||
com: 'North America',
|
||||
eu: 'Europe',
|
||||
asia: 'Asia',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import { serverAndIdPattern } from '../discord/resolvePlayerFromCommand';
|
||||
import throwError from '../node/throwError';
|
||||
import listClans from './listClans';
|
||||
@@ -6,7 +6,7 @@ import listClans from './listClans';
|
||||
export default async function getBlitzClan(clan: string) {
|
||||
if (serverAndIdPattern.test(clan)) {
|
||||
const [server, accountId] = clan.split('/');
|
||||
return { server: server as RegionDomain, id: Number(accountId) };
|
||||
return { server: server as Region, id: Number(accountId) };
|
||||
} else {
|
||||
const accounts = await listClans(clan);
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { REGION_DOMAIN_NAMES, RegionDomain } from '../../constants/regions';
|
||||
import { REGION_NAMES, Region } from '../../constants/regions';
|
||||
import { TanksStats } from '../../types/tanksStats';
|
||||
import { WARGAMING_APPLICATION_ID } from '../node/arguments';
|
||||
import throwError from '../node/throwError';
|
||||
import getWargamingResponse from './getWargamingResponse';
|
||||
|
||||
export default async function getTankStats(server: RegionDomain, id: number) {
|
||||
export default async function getTankStats(server: Region, id: number) {
|
||||
const tankStats = await getWargamingResponse<TanksStats>(
|
||||
`https://api.wotblitz.${server}/wotb/tanks/stats/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||
);
|
||||
@@ -12,7 +12,7 @@ export default async function getTankStats(server: RegionDomain, id: number) {
|
||||
if (tankStats[id] === null) {
|
||||
throw throwError(
|
||||
'No tank stats available',
|
||||
`Wargaming says there is no tank stats for this account. This account may not have any battles/tanks or exist in the ${REGION_DOMAIN_NAMES[server]} server.`,
|
||||
`Wargaming says there is no tank stats for this account. This account may not have any battles/tanks or exist in the ${REGION_NAMES[server]} server.`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import { Clan, ClanList } from '../../types/clanList';
|
||||
import { WARGAMING_APPLICATION_ID } from '../node/arguments';
|
||||
import getWargamingResponse from './getWargamingResponse';
|
||||
@@ -21,7 +21,7 @@ export default async function listClans(search: string, limit = 9) {
|
||||
value &&
|
||||
value.map((account) => ({
|
||||
...account,
|
||||
server: 'com' as RegionDomain,
|
||||
server: 'com' as Region,
|
||||
})),
|
||||
),
|
||||
getWargamingResponse<ClanList>(
|
||||
@@ -31,7 +31,7 @@ export default async function listClans(search: string, limit = 9) {
|
||||
value &&
|
||||
value.map((account) => ({
|
||||
...account,
|
||||
server: 'eu' as RegionDomain,
|
||||
server: 'eu' as Region,
|
||||
})),
|
||||
),
|
||||
getWargamingResponse<ClanList>(
|
||||
@@ -41,7 +41,7 @@ export default async function listClans(search: string, limit = 9) {
|
||||
value &&
|
||||
value.map((account) => ({
|
||||
...account,
|
||||
server: 'asia' as RegionDomain,
|
||||
server: 'asia' as Region,
|
||||
})),
|
||||
),
|
||||
])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import { Account, AccountList } from '../../types/accountList';
|
||||
import { WARGAMING_APPLICATION_ID } from '../node/arguments';
|
||||
import getWargamingResponse from './getWargamingResponse';
|
||||
@@ -25,7 +25,7 @@ export default async function listPlayers(search: string, limit = 9) {
|
||||
value &&
|
||||
value.map((account) => ({
|
||||
...account,
|
||||
server: 'com' as RegionDomain,
|
||||
server: 'com' as Region,
|
||||
})),
|
||||
),
|
||||
getWargamingResponse<AccountList>(
|
||||
@@ -35,7 +35,7 @@ export default async function listPlayers(search: string, limit = 9) {
|
||||
value &&
|
||||
value.map((account) => ({
|
||||
...account,
|
||||
server: 'eu' as RegionDomain,
|
||||
server: 'eu' as Region,
|
||||
})),
|
||||
),
|
||||
getWargamingResponse<AccountList>(
|
||||
@@ -45,7 +45,7 @@ export default async function listPlayers(search: string, limit = 9) {
|
||||
value &&
|
||||
value.map((account) => ({
|
||||
...account,
|
||||
server: 'asia' as RegionDomain,
|
||||
server: 'asia' as Region,
|
||||
})),
|
||||
),
|
||||
])
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { Region, RegionSubdomain } from '../../constants/regions';
|
||||
|
||||
export default function regionToRegionSubdomain(
|
||||
regionDomain: Region,
|
||||
): RegionSubdomain {
|
||||
return regionDomain === 'com' ? 'na' : regionDomain;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import { AllStats } from '../../types/accountInfo';
|
||||
import getTankHistories, {
|
||||
TankHistories,
|
||||
@@ -35,7 +35,7 @@ export const emptyTankHistoryNode: TankHistoryRaw = {
|
||||
};
|
||||
|
||||
export default async function getDiffedTankStats(
|
||||
server: RegionDomain,
|
||||
server: Region,
|
||||
id: number,
|
||||
start: number,
|
||||
end: number,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import { Period } from '../discord/addPeriodSubCommands';
|
||||
import getTimeDaysAgo from './getTimeDaysAgo';
|
||||
|
||||
export default function getPeriodStart(
|
||||
server: RegionDomain,
|
||||
server: Region,
|
||||
period: Exclude<Period, 'custom'>,
|
||||
) {
|
||||
if (period === 'career') {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import { AccountInfo, AllStats } from '../../types/accountInfo';
|
||||
import {
|
||||
GetHistoriesOptions,
|
||||
@@ -25,13 +25,13 @@ export interface PlayerHistoryRaw {
|
||||
account_id: number;
|
||||
[key: string]: number;
|
||||
};
|
||||
region: RegionDomain;
|
||||
region: Region;
|
||||
}
|
||||
|
||||
export type PlayerHistoriesRaw = PlayerHistoryRaw[];
|
||||
|
||||
export default async function getPlayerHistories(
|
||||
server: RegionDomain,
|
||||
server: Region,
|
||||
id: number,
|
||||
options?: Partial<GetHistoriesOptions>,
|
||||
) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import {
|
||||
GetHistoriesOptions,
|
||||
Histories,
|
||||
@@ -32,7 +32,7 @@ export const getTankHistoriesDefaultOptions: GetTankHistoriesOptions = {
|
||||
};
|
||||
|
||||
export default async function getTankHistories(
|
||||
server: RegionDomain,
|
||||
server: Region,
|
||||
id: number,
|
||||
options?: Partial<GetTankHistoriesOptions>,
|
||||
) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
|
||||
export const TIME_ZONE_MAPPINGS: Record<RegionDomain, number> = {
|
||||
export const TIME_ZONE_MAPPINGS: Record<Region, number> = {
|
||||
com: -5, // Central North American Time
|
||||
eu: +1, // Central European Time
|
||||
asia: +7, // Central Asia Standard Time
|
||||
};
|
||||
|
||||
export default function getTimeDaysAgo(server: RegionDomain, daysAgo: number) {
|
||||
export default function getTimeDaysAgo(server: Region, daysAgo: number) {
|
||||
const now = new Date();
|
||||
if (daysAgo === 0) now.getTime() / 1000;
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { SlashCommandStringOption } from 'discord.js';
|
||||
import { REGION_DOMAIN_NAMES } from '../../constants/regions';
|
||||
import { REGION_NAMES } from '../../constants/regions';
|
||||
|
||||
export default function addServerChoices(option: SlashCommandStringOption) {
|
||||
return option
|
||||
.setName('server')
|
||||
.setDescription('The Blitz server you are in')
|
||||
.addChoices(
|
||||
{ name: REGION_DOMAIN_NAMES.com, value: 'com' },
|
||||
{ name: REGION_DOMAIN_NAMES.eu, value: 'eu' },
|
||||
{ name: REGION_DOMAIN_NAMES.asia, value: 'asia' },
|
||||
{ name: REGION_NAMES.com, value: 'com' },
|
||||
{ name: REGION_NAMES.eu, value: 'eu' },
|
||||
{ name: REGION_NAMES.asia, value: 'asia' },
|
||||
)
|
||||
.setRequired(true);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
AutocompleteInteraction,
|
||||
CacheType,
|
||||
} from 'discord.js';
|
||||
import { REGION_DOMAIN_NAMES } from '../../constants/regions';
|
||||
import { REGION_NAMES } from '../../constants/regions';
|
||||
import listClans from '../blitz/listClans';
|
||||
|
||||
export default async function autocompleteClan(
|
||||
@@ -18,7 +18,7 @@ export default async function autocompleteClan(
|
||||
? players.map(
|
||||
(player) =>
|
||||
({
|
||||
name: `${player.name} (${REGION_DOMAIN_NAMES[player.server]})`,
|
||||
name: `${player.name} (${REGION_NAMES[player.server]})`,
|
||||
value: `${player.server}/${player.clan_id}`,
|
||||
}) satisfies ApplicationCommandOptionChoiceData<string>,
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
AutocompleteInteraction,
|
||||
CacheType,
|
||||
} from 'discord.js';
|
||||
import { REGION_DOMAIN_NAMES } from '../../constants/regions';
|
||||
import { REGION_NAMES } from '../../constants/regions';
|
||||
import listPlayers from '../blitz/listPlayers';
|
||||
|
||||
export default async function autocompleteUsername(
|
||||
@@ -19,9 +19,7 @@ export default async function autocompleteUsername(
|
||||
? players.map(
|
||||
(player) =>
|
||||
({
|
||||
name: `${player.nickname} (${
|
||||
REGION_DOMAIN_NAMES[player.server]
|
||||
})`,
|
||||
name: `${player.nickname} (${REGION_NAMES[player.server]})`,
|
||||
value: `${player.server}/${player.account_id}`,
|
||||
}) satisfies ApplicationCommandOptionChoiceData<string>,
|
||||
)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ButtonInteraction, CacheType } from 'discord.js';
|
||||
import { CYCLIC_API } from '../../constants/cyclic';
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import resolvePeriodFromURL from '../express/resolvePeriodFromURL';
|
||||
|
||||
export default function resolvePeriodFromButton(
|
||||
server: RegionDomain,
|
||||
server: Region,
|
||||
interaction: ButtonInteraction<CacheType>,
|
||||
) {
|
||||
return resolvePeriodFromURL(server, `${CYCLIC_API}/${interaction.customId}`);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CacheType, ChatInputCommandInteraction } from 'discord.js';
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import getPeriodNow from '../blitzstars/getPeriodNow';
|
||||
import getPeriodStart from '../blitzstars/getPeriodStart';
|
||||
import getTimeDaysAgo from '../blitzstars/getTimeDaysAgo';
|
||||
@@ -31,7 +31,7 @@ export interface ResolvedPeriod {
|
||||
}
|
||||
|
||||
export default function resolvePeriodFromCommand(
|
||||
server: RegionDomain,
|
||||
server: Region,
|
||||
interaction: ChatInputCommandInteraction<CacheType>,
|
||||
) {
|
||||
let statsName: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CacheType, ChatInputCommandInteraction } from 'discord.js';
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import listPlayers, {
|
||||
usernamePatternWithoutPosition,
|
||||
} from '../blitz/listPlayers';
|
||||
@@ -8,7 +8,7 @@ import throwError from '../node/throwError';
|
||||
export const serverAndIdPattern = /(com|eu|asia)\/[0-9]+/;
|
||||
|
||||
export interface ResolvedPlayer {
|
||||
server: RegionDomain;
|
||||
region: Region;
|
||||
id: number;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ export default async function resolvePlayerFromCommand(
|
||||
if (serverAndIdPattern.test(username)) {
|
||||
const [server, accountId] = username.split('/');
|
||||
return {
|
||||
server: server as RegionDomain,
|
||||
region: server as Region,
|
||||
id: Number(accountId),
|
||||
} satisfies ResolvedPlayer;
|
||||
} else {
|
||||
@@ -39,7 +39,7 @@ export default async function resolvePlayerFromCommand(
|
||||
|
||||
if (accounts[0]) {
|
||||
return {
|
||||
server: accounts[0].server,
|
||||
region: accounts[0].server,
|
||||
id: accounts[0].account_id,
|
||||
} satisfies ResolvedPlayer;
|
||||
} else {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Request } from 'express';
|
||||
import { CYCLIC_API } from '../../constants/cyclic';
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import resolvePeriodFromURL from './resolvePeriodFromURL';
|
||||
|
||||
export default function resolvePeriodFromRequest(
|
||||
server: RegionDomain,
|
||||
server: Region,
|
||||
request: Request,
|
||||
) {
|
||||
return resolvePeriodFromURL(server, `${CYCLIC_API}${request.path}`);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import getPeriodNow from '../blitzstars/getPeriodNow';
|
||||
import getPeriodStart from '../blitzstars/getPeriodStart';
|
||||
import getTimeDaysAgo from '../blitzstars/getTimeDaysAgo';
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from '../discord/resolvePeriodFromCommand';
|
||||
|
||||
export default function resolvePeriodFromURL(
|
||||
server: RegionDomain,
|
||||
server: Region,
|
||||
urlString: string,
|
||||
) {
|
||||
let statsName: string;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RegionDomain } from '../../constants/regions';
|
||||
import { Region } from '../../constants/regions';
|
||||
import { ResolvedPlayer } from '../discord/resolvePlayerFromCommand';
|
||||
|
||||
export default function resolvePlayerFromURL(urlString: string) {
|
||||
@@ -6,6 +6,6 @@ export default function resolvePlayerFromURL(urlString: string) {
|
||||
|
||||
return {
|
||||
id: parseInt(url.searchParams.get('id')!),
|
||||
server: url.searchParams.get('server') as RegionDomain,
|
||||
region: url.searchParams.get('server') as Region,
|
||||
} satisfies ResolvedPlayer;
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
ChatInputCommandInteraction,
|
||||
} from 'discord.js';
|
||||
import { commands } from '..';
|
||||
import discord from '../../../../discord.json' assert { type: 'json' };
|
||||
import embedNegative from '../../../core/discord/embedNegative';
|
||||
import embedWarning from '../../../core/discord/embedWarning';
|
||||
import normalizeInteractionReturnable from '../../../core/discord/normalizeInteractionReturnable';
|
||||
@@ -21,6 +22,19 @@ export default async function handleChatInputCommand(
|
||||
await interaction.deferReply();
|
||||
|
||||
try {
|
||||
if (registry.inPreview && interaction.guildId !== discord.tres_guild_id) {
|
||||
interaction.editReply({
|
||||
embeds: [
|
||||
embedWarning(
|
||||
`\`/${registry.command.name}\` is in Public Preview`,
|
||||
'[Join the official Discord server](https://discord.gg/nDt7AjGJQH) to gain early access to this command before it is released to the public.',
|
||||
),
|
||||
],
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const returnable = await registry.handler(interaction);
|
||||
|
||||
if (registry.handlesInteraction) return;
|
||||
|
||||
@@ -23,6 +23,7 @@ import { ownedTanksCommand } from '../../commands/ownedTanks';
|
||||
import { pingCommand } from '../../commands/ping';
|
||||
import { playerAchievementsCommand } from '../../commands/playerAchievements';
|
||||
import { playerInfoCommand } from '../../commands/playerInfo';
|
||||
import { ratingsCommand } from '../../commands/ratings';
|
||||
import { searchClansCommand } from '../../commands/searchClans';
|
||||
import { searchPlayersCommand } from '../../commands/searchPlayers';
|
||||
import { searchTanksCommand } from '../../commands/searchTanks';
|
||||
@@ -56,6 +57,7 @@ export interface Registry {
|
||||
export interface CommandRegistry<HandlesInteraction extends boolean = boolean>
|
||||
extends Registry {
|
||||
inPublic: boolean;
|
||||
inPreview?: boolean;
|
||||
handlesInteraction?: HandlesInteraction;
|
||||
command:
|
||||
| SlashCommandBuilder
|
||||
@@ -88,6 +90,7 @@ export const COMMANDS_RAW: CommandRegistry[] = [
|
||||
pingCommand,
|
||||
evolutionCommand,
|
||||
statsCommand,
|
||||
ratingsCommand,
|
||||
];
|
||||
export const commands: Record<string, CommandRegistry> = COMMANDS_RAW.reduce(
|
||||
(accumulator, registry) => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import NoData, { NoDataType } from '../components/NoData';
|
||||
import PoweredBy, { PoweredByType } from '../components/PoweredBy';
|
||||
import TitleBar from '../components/TitleBar';
|
||||
import Wrapper from '../components/Wrapper';
|
||||
import { REGION_DOMAIN_NAMES } from '../constants/regions';
|
||||
import { REGION_NAMES } from '../constants/regions';
|
||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||
import resolveTankName from '../core/blitz/resolveTankName';
|
||||
import { tankopedia } from '../core/blitz/tankopedia';
|
||||
@@ -20,7 +20,7 @@ import { StatType } from './fullStats';
|
||||
export default async function evolution<Type extends StatType>(
|
||||
type: Type,
|
||||
{ start, end, evolutionName }: ResolvedPeriod,
|
||||
{ server, id }: ResolvedPlayer,
|
||||
{ region: server, id }: ResolvedPlayer,
|
||||
tankId: Type extends 'tank' ? number : null,
|
||||
) {
|
||||
let nameDiscriminator: string | undefined;
|
||||
@@ -89,7 +89,7 @@ export default async function evolution<Type extends StatType>(
|
||||
nameDiscriminator={nameDiscriminator}
|
||||
image={image}
|
||||
description={`${evolutionName} • ${new Date().toDateString()} • ${
|
||||
REGION_DOMAIN_NAMES[server]
|
||||
REGION_NAMES[server]
|
||||
}`}
|
||||
/>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import PoweredBy, { PoweredByType } from '../components/PoweredBy';
|
||||
import TierWeights, { TierWeightsRecord } from '../components/TierWeights';
|
||||
import TitleBar from '../components/TitleBar';
|
||||
import Wrapper from '../components/Wrapper';
|
||||
import { REGION_DOMAIN_NAMES } from '../constants/regions';
|
||||
import { REGION_NAMES } from '../constants/regions';
|
||||
import calculateWN8 from '../core/blitz/calculateWN8';
|
||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||
import resolveTankName from '../core/blitz/resolveTankName';
|
||||
@@ -28,7 +28,7 @@ export type StatType = 'player' | 'tank';
|
||||
export default async function fullStats<Type extends StatType>(
|
||||
type: Type,
|
||||
{ start, end, statsName }: ResolvedPeriod,
|
||||
{ server, id }: ResolvedPlayer,
|
||||
{ region: server, id }: ResolvedPlayer,
|
||||
tankId: Type extends 'tank' ? number : null,
|
||||
) {
|
||||
let nameDiscriminator: string | undefined;
|
||||
@@ -143,7 +143,7 @@ export default async function fullStats<Type extends StatType>(
|
||||
nameDiscriminator={nameDiscriminator}
|
||||
image={image}
|
||||
description={`${statsName} • ${new Date().toDateString()} • ${
|
||||
REGION_DOMAIN_NAMES[server]
|
||||
REGION_NAMES[server]
|
||||
}`}
|
||||
/>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import PoweredBy, { PoweredByType } from '../components/PoweredBy';
|
||||
import { TierWeightsRecord } from '../components/TierWeights';
|
||||
import TitleBar from '../components/TitleBar';
|
||||
import Wrapper from '../components/Wrapper';
|
||||
import { REGION_DOMAIN_NAMES } from '../constants/regions';
|
||||
import { REGION_NAMES } from '../constants/regions';
|
||||
import calculateWN8 from '../core/blitz/calculateWN8';
|
||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||
import resolveTankName from '../core/blitz/resolveTankName';
|
||||
@@ -29,7 +29,7 @@ export type StatType = 'player' | 'tank';
|
||||
export default async function stats<Type extends StatType>(
|
||||
type: Type,
|
||||
{ start, end, statsName }: ResolvedPeriod,
|
||||
{ server, id }: ResolvedPlayer,
|
||||
{ region: server, id }: ResolvedPlayer,
|
||||
tankId: Type extends 'tank' ? number : null,
|
||||
naked = false,
|
||||
) {
|
||||
@@ -164,7 +164,7 @@ export default async function stats<Type extends StatType>(
|
||||
nameDiscriminator={nameDiscriminator}
|
||||
image={image}
|
||||
description={`${statsName} • ${new Date().toDateString()} • ${
|
||||
REGION_DOMAIN_NAMES[server]
|
||||
REGION_NAMES[server]
|
||||
}`}
|
||||
/>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import NoData, { NoDataType } from '../components/NoData';
|
||||
import PoweredBy, { PoweredByType } from '../components/PoweredBy';
|
||||
import TitleBar from '../components/TitleBar';
|
||||
import Wrapper from '../components/Wrapper';
|
||||
import { REGION_DOMAIN_NAMES } from '../constants/regions';
|
||||
import { REGION_NAMES } from '../constants/regions';
|
||||
import calculateWN8 from '../core/blitz/calculateWN8';
|
||||
import getTankStats from '../core/blitz/getTankStats';
|
||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||
@@ -21,7 +21,7 @@ import { PlayerClanData } from '../types/playerClanData';
|
||||
import { PossiblyPromise } from '../types/possiblyPromise';
|
||||
|
||||
export default async function today(
|
||||
{ server, id }: ResolvedPlayer,
|
||||
{ region: server, id }: ResolvedPlayer,
|
||||
limit = Infinity,
|
||||
naked?: boolean,
|
||||
) {
|
||||
@@ -162,7 +162,7 @@ export default async function today(
|
||||
: undefined
|
||||
}
|
||||
description={`Today's breakdown • ${new Date().toDateString()} • ${
|
||||
REGION_DOMAIN_NAMES[server]
|
||||
REGION_NAMES[server]
|
||||
}`}
|
||||
/>
|
||||
|
||||
|
||||
Reference in new issue
Block a user