mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
feat: made /ratings data-driven
This commit is contained in:
1 parent
d511cfa4cc
commit
f7eadb08a9
1 file changed
+133
-145
+133
-145
@@ -1,4 +1,4 @@
|
||||
import { SlashCommandBuilder, SlashCommandSubcommandBuilder } from 'discord.js';
|
||||
import { SlashCommandBuilder } from 'discord.js';
|
||||
import { BlitzkriegRatingsLeaderboard } from '../../scripts/buildRatingsLeaderboard';
|
||||
import { octokit } from '../bot';
|
||||
import * as Leaderboard from '../components/Leaderboard';
|
||||
@@ -7,7 +7,7 @@ import Wrapper from '../components/Wrapper';
|
||||
import { Region } from '../constants/regions';
|
||||
import regionToRegionSubdomain from '../core/blitz/regionToRegionSubdomain';
|
||||
import addRegionChoices from '../core/discord/addRegionChoices';
|
||||
import { CommandRegistry } from '../events/interactionCreate';
|
||||
import { CommandRegistryRaw } from '../events/interactionCreate';
|
||||
|
||||
export interface RatingsPlayer {
|
||||
spa_id: number;
|
||||
@@ -102,157 +102,145 @@ const ratingsInfo = fetch(
|
||||
return info;
|
||||
});
|
||||
|
||||
function optionalParameters(option: SlashCommandSubcommandBuilder) {
|
||||
return option
|
||||
.addStringOption(addRegionChoices)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName('limit')
|
||||
.setDescription('How many rows to display (default: 10)')
|
||||
.setRequired(false)
|
||||
.setMinValue(5)
|
||||
.setMaxValue(30),
|
||||
);
|
||||
}
|
||||
|
||||
const LEAGUE_INDEXES = ['diamond', 'platinum', 'gold', 'silver', 'bronze'];
|
||||
|
||||
export const DATABASE_REPO = { owner: 'tresabhi', repo: 'blitzkrieg-db' };
|
||||
|
||||
export const ratingsCommand: CommandRegistry = {
|
||||
inProduction: true,
|
||||
inDevelopment: true,
|
||||
inPublic: true,
|
||||
const LEAGUE_SUBCOMMAND_TO_INDEX: Record<string, number> = {};
|
||||
|
||||
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);
|
||||
export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
async (resolve) => {
|
||||
const awaitedRatingsInfo = await ratingsInfo;
|
||||
|
||||
if (subcommandGroup === 'league') {
|
||||
const limit = interaction.options.getInteger('limit') ?? 10;
|
||||
const subcommand = interaction.options.getSubcommand(true);
|
||||
const leagueIndex = LEAGUE_INDEXES.indexOf(subcommand);
|
||||
const region = interaction.options.getString('region') as Region;
|
||||
const regionSubdomain = regionToRegionSubdomain(region);
|
||||
const result = await fetch(
|
||||
`https://${regionSubdomain}.wotblitz.com/en/api/rating-leaderboards/league/${leagueIndex}/top/`,
|
||||
)
|
||||
.then((response) => response.json() as Promise<LeagueTop>)
|
||||
.then(({ result }) => result.slice(0, limit));
|
||||
const awaitedInfo = await ratingsInfo;
|
||||
const leagueInfo = awaitedInfo.leagues[leagueIndex];
|
||||
const midnightLeaderboard = await octokit.repos
|
||||
.getContent({
|
||||
...DATABASE_REPO,
|
||||
path: `${region}/ratings/${awaitedInfo.current_season}/midnight.json`,
|
||||
})
|
||||
.then(({ data }) => {
|
||||
if (!Array.isArray(data) && data.type === 'file') {
|
||||
const content = Buffer.from(data.content, 'base64').toString();
|
||||
const jsonContent = JSON.parse(
|
||||
content,
|
||||
) as BlitzkriegRatingsLeaderboard;
|
||||
const command = new SlashCommandBuilder()
|
||||
.setName('ratings')
|
||||
.setDescription('Ratings battles statistics')
|
||||
.addSubcommandGroup((option) => {
|
||||
const subcommandGroup = option
|
||||
.setName('league')
|
||||
.setDescription('Top league players');
|
||||
|
||||
return jsonContent;
|
||||
}
|
||||
})
|
||||
.catch(() => console.warn('No midnight leaderboard found'));
|
||||
const items = await Promise.all(
|
||||
result.map(async (player) => {
|
||||
const reward = awaitedInfo.rewards.find(
|
||||
(reward) =>
|
||||
player.number >= reward.from_position &&
|
||||
player.number <= reward.to_position,
|
||||
awaitedRatingsInfo.leagues.forEach((league) => {
|
||||
subcommandGroup.addSubcommand((option) => {
|
||||
const subcommandName = league.title.split(' ')[0].toLowerCase();
|
||||
LEAGUE_SUBCOMMAND_TO_INDEX[subcommandName] = league.index;
|
||||
|
||||
return option
|
||||
.setName(subcommandName)
|
||||
.setDescription(`Top ${league.title} players`)
|
||||
.addStringOption(addRegionChoices)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName('limit')
|
||||
.setDescription('How many rows to display (default: 10)')
|
||||
.setRequired(false)
|
||||
.setMinValue(5)
|
||||
.setMaxValue(30),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
return subcommandGroup;
|
||||
});
|
||||
|
||||
resolve({
|
||||
inProduction: true,
|
||||
inDevelopment: true,
|
||||
inPublic: true,
|
||||
|
||||
command,
|
||||
|
||||
async handler(interaction) {
|
||||
const subcommandGroup = interaction.options.getSubcommandGroup(true);
|
||||
|
||||
if (subcommandGroup === 'league') {
|
||||
const limit = interaction.options.getInteger('limit') ?? 10;
|
||||
const subcommand = interaction.options.getSubcommand(true);
|
||||
const leagueIndex = LEAGUE_SUBCOMMAND_TO_INDEX[subcommand];
|
||||
const region = interaction.options.getString('region') as Region;
|
||||
const regionSubdomain = regionToRegionSubdomain(region);
|
||||
const result = await fetch(
|
||||
`https://${regionSubdomain}.wotblitz.com/en/api/rating-leaderboards/league/${leagueIndex}/top/`,
|
||||
)
|
||||
.then((response) => response.json() as Promise<LeagueTop>)
|
||||
.then(({ result }) => result.slice(0, limit));
|
||||
const awaitedInfo = await ratingsInfo;
|
||||
const leagueInfo = awaitedInfo.leagues[leagueIndex];
|
||||
const midnightLeaderboard = await octokit.repos
|
||||
.getContent({
|
||||
...DATABASE_REPO,
|
||||
path: `${region}/ratings/${awaitedInfo.current_season}/midnight.json`,
|
||||
})
|
||||
.then(({ data }) => {
|
||||
if (!Array.isArray(data) && data.type === 'file') {
|
||||
const content = Buffer.from(data.content, 'base64').toString();
|
||||
const jsonContent = JSON.parse(
|
||||
content,
|
||||
) as BlitzkriegRatingsLeaderboard;
|
||||
|
||||
return jsonContent;
|
||||
}
|
||||
})
|
||||
.catch(() => console.warn('No midnight leaderboard found'));
|
||||
const items = await Promise.all(
|
||||
result.map(async (player) => {
|
||||
const reward = awaitedInfo.rewards.find(
|
||||
(reward) =>
|
||||
player.number >= reward.from_position &&
|
||||
player.number <= reward.to_position,
|
||||
);
|
||||
const midnightIndex = midnightLeaderboard?.findIndex(
|
||||
(item) => item.id === player.spa_id,
|
||||
);
|
||||
const midnightScore =
|
||||
midnightIndex === undefined
|
||||
? player.score
|
||||
: midnightLeaderboard![midnightIndex].score;
|
||||
const midnightPosition =
|
||||
midnightIndex === undefined ? player.number : midnightIndex + 1;
|
||||
|
||||
return (
|
||||
<Leaderboard.Item
|
||||
nickname={player.nickname}
|
||||
score={player.score}
|
||||
position={player.number}
|
||||
clan={player.clan_tag}
|
||||
reward={reward}
|
||||
deltaScore={player.score - midnightScore}
|
||||
deltaPosition={midnightPosition - player.number}
|
||||
key={player.spa_id}
|
||||
/>
|
||||
);
|
||||
}),
|
||||
);
|
||||
const midnightIndex = midnightLeaderboard?.findIndex(
|
||||
(item) => item.id === player.spa_id,
|
||||
);
|
||||
const midnightScore =
|
||||
midnightIndex === undefined
|
||||
? player.score
|
||||
: midnightLeaderboard![midnightIndex].score;
|
||||
const midnightPosition =
|
||||
midnightIndex === undefined ? player.number : midnightIndex + 1;
|
||||
|
||||
const playersBefore = result[0].number - 1;
|
||||
const playersAfter =
|
||||
awaitedInfo.count - result[result.length - 1].number;
|
||||
|
||||
return (
|
||||
<Leaderboard.Item
|
||||
nickname={player.nickname}
|
||||
score={player.score}
|
||||
position={player.number}
|
||||
clan={player.clan_tag}
|
||||
reward={reward}
|
||||
deltaScore={player.score - midnightScore}
|
||||
deltaPosition={midnightPosition - player.number}
|
||||
key={player.spa_id}
|
||||
/>
|
||||
<Wrapper>
|
||||
<TitleBar
|
||||
name={leagueInfo.title}
|
||||
image={
|
||||
leagueInfo.big_icon.startsWith('http')
|
||||
? leagueInfo.big_icon
|
||||
: `https:${leagueInfo.big_icon}`
|
||||
}
|
||||
description={`Top ${limit} players • ${new Date().toDateString()}`}
|
||||
/>
|
||||
|
||||
<Leaderboard.Root>
|
||||
{playersBefore > 0 && (
|
||||
<Leaderboard.Gap number={playersBefore} />
|
||||
)}
|
||||
{items}
|
||||
{playersAfter > 0 && <Leaderboard.Gap number={playersAfter} />}
|
||||
</Leaderboard.Root>
|
||||
</Wrapper>
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const playersBefore = result[0].number - 1;
|
||||
const playersAfter = awaitedInfo.count - result[result.length - 1].number;
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<TitleBar
|
||||
name={leagueInfo.title}
|
||||
image={
|
||||
leagueInfo.big_icon.startsWith('http')
|
||||
? leagueInfo.big_icon
|
||||
: `https:${leagueInfo.big_icon}`
|
||||
}
|
||||
description={`Top ${limit} players • ${new Date().toDateString()}`}
|
||||
/>
|
||||
|
||||
<Leaderboard.Root>
|
||||
{playersBefore > 0 && <Leaderboard.Gap number={playersBefore} />}
|
||||
{items}
|
||||
{playersAfter > 0 && <Leaderboard.Gap number={playersAfter} />}
|
||||
</Leaderboard.Root>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return [];
|
||||
return [];
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
);
|
||||
Reference in new issue
Block a user