diff --git a/.vscode/settings.json b/.vscode/settings.json index dee1574f6..4cc04f9af 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -28,6 +28,7 @@ "statsfull", "Stringifying", "strvk", + "subnation", "tankaverages", "tankopedia", "tankstats", diff --git a/src/commands/ratings.ts b/src/commands/ratings.tsx similarity index 52% rename from src/commands/ratings.ts rename to src/commands/ratings.tsx index de0702faa..51e8cc1e1 100644 --- a/src/commands/ratings.ts +++ b/src/commands/ratings.tsx @@ -1,9 +1,16 @@ import { SlashCommandBuilder, SlashCommandSubcommandBuilder } from 'discord.js'; +import * as Leaderboard from '../components/Leaderboard'; +import TitleBar from '../components/TitleBar'; +import Wrapper from '../components/Wrapper'; +import { REGION_NAMES } from '../constants/regions'; +import getWargamingResponse from '../core/blitz/getWargamingResponse'; 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 { WARGAMING_APPLICATION_ID } from '../core/node/arguments'; import { CommandRegistry } from '../events/interactionCreate'; +import { AccountInfo } from '../types/accountInfo'; export interface LeaguePlayer { spa_id: number; @@ -23,7 +30,76 @@ export interface LeagueTop { result: LeaguePlayer[]; } -const LEAGUE_INDEXES = ['diamond', 'platinum', 'gold', 'silver', 'bronze']; +export type RatingsReward = { + from_position: number; + to_position: number; + count: number; +} & ( + | { + type: 'vehicle'; + + vehicle: { + id: number; + name: string; + nation: string; + subnation: string; + use_subnation_flag: boolean; + type_slug: string; + level: number; + roman_level: string; + user_string: string; + image_url: string; + preview_url: string; + is_premium: boolean; + is_collectible: boolean; + }; + } + | { + type: 'stuff'; + + stuff: { + name: string; + count: number; + title: string; + image_url: string; + type: string; + + sizes: {}; + }; + } +); + +export interface RatingsLeague { + title: string; + small_icon: string; + big_icon: string; + background: string; + index: number; + percentile: number; +} + +export interface RatingsInfo { + title: string; + icon: string | null; + start_at: string; + finish_at: string; + current_season: number; + updated_at: string; + count: number; + + rewards: RatingsReward[]; + leagues: RatingsLeague[]; +} + +console.log('Caching ratings info...'); +const ratingsLeagueInfo = fetch( + 'https://na.wotblitz.com/en/api/rating-leaderboards/season/', +) + .then((response) => response.json() as Promise) + .then((info) => { + console.log('Cached ratings info'); + return info; + }); function optionalParameters(option: SlashCommandSubcommandBuilder) { return option @@ -31,13 +107,15 @@ function optionalParameters(option: SlashCommandSubcommandBuilder) { option .setName('limit') .setDescription('How many rows to display (default: 16)') - .setRequired(true) + .setRequired(false) .setMinValue(5) .setMaxValue(30), ) .addStringOption(addUsernameChoices); } +const LEAGUE_INDEXES = ['diamond', 'platinum', 'gold', 'silver', 'bronze']; + export const ratingsCommand: CommandRegistry = { inProduction: true, inDevelopment: true, @@ -98,14 +176,38 @@ export const ratingsCommand: CommandRegistry = { const { result } = await fetch( `https://${regionSubdomain}.wotblitz.com/en/api/rating-leaderboards/league/${leagueIndex}/top/`, ).then((response) => response.json() as Promise); - - return `\`\`\`${result + const { nickname } = await getWargamingResponse( + `https://api.wotblitz.${player.region}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${player.id}`, + ).then((accounts) => accounts[player.id]); + const leagueInfo = (await ratingsLeagueInfo).leagues[leagueIndex]; + const items = result .slice(0, limit) - .map( - (player) => - `${player.number}: ${player.nickname} [${player.clan_tag}]`, - ) - .join('\n')}\`\`\``; + .map((player) => ( + + )); + + return ( + + + + {items} + + ); } return []; diff --git a/src/components/Leaderboard/components/Gap.tsx b/src/components/Leaderboard/components/Gap.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/src/components/Leaderboard/components/Item.tsx b/src/components/Leaderboard/components/Item.tsx new file mode 100644 index 000000000..dbc3ac48e --- /dev/null +++ b/src/components/Leaderboard/components/Item.tsx @@ -0,0 +1,104 @@ +import { RatingsReward } from '../../../commands/ratings'; +import { theme } from '../../../stitches.config'; + +export interface ItemProps { + position: number; + deltaPosition?: number; + points: number; + deltaPoints?: number; + reward: RatingsReward; + nickname: string; + clan?: string; +} + +export function Item({ + position, + deltaPosition, + points, + deltaPoints, + reward, + nickname, + clan, +}: ItemProps) { + return ( +
+ + {position}. + + +
+ + {nickname} + + {clan && ( + + [{clan}] + + )} +
+ + {deltaPosition !== undefined && deltaPosition !== 0 && ( +
+ 0 + ? 'https://i.imgur.com/qbjiXa1.png' + : 'https://i.imgur.com/3uyNhun.png' + } + /> + + {deltaPosition} + +
+ )} +
+ ); +} diff --git a/src/components/Leaderboard/components/Root.tsx b/src/components/Leaderboard/components/Root.tsx new file mode 100644 index 000000000..9f40d82f9 --- /dev/null +++ b/src/components/Leaderboard/components/Root.tsx @@ -0,0 +1,13 @@ +import { ReactNode } from 'react'; + +export interface RootProps { + children: ReactNode; +} + +export function Root({ children }: RootProps) { + return ( +
+ {children} +
+ ); +} diff --git a/src/components/Leaderboard/index.ts b/src/components/Leaderboard/index.ts new file mode 100644 index 000000000..4334194b1 --- /dev/null +++ b/src/components/Leaderboard/index.ts @@ -0,0 +1,3 @@ +export * from './components/Gap'; +export * from './components/Item'; +export * from './components/Root'; diff --git a/tsconfig.json b/tsconfig.json index 5f2ace03b..e6d1941ec 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,8 +11,5 @@ "resolveJsonModule": true, "jsx": "react-jsx" }, - "include": [ - "src/**/*.ts", - "src/components/AllStatsOverview/components/WN8SurroundingStat.tsx" - ] + "include": ["src/**/*.ts"] }