mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
032d98e6bd | ||
|
|
f4a90cd531 | ||
|
|
82f03583fe | ||
|
|
81c1a50052 | ||
|
|
c7207799e2 | ||
|
|
e0a719ee93 | ||
|
|
ee6d2e7d82 | ||
|
|
14710b5218 | ||
|
|
4b5e0d1c1c |
No files matched your search
Vendored
+2
@@ -13,9 +13,11 @@
|
||||
"Everytime",
|
||||
"fullstats",
|
||||
"fuzzysort",
|
||||
"immer",
|
||||
"kranvagn",
|
||||
"Leaderboard",
|
||||
"leaderboards",
|
||||
"MURICA",
|
||||
"Oopsy",
|
||||
"outdir",
|
||||
"outfile",
|
||||
|
||||
@@ -13,7 +13,7 @@ export default defineConfig({
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'Home', link: '/' },
|
||||
{ text: 'Guide', link: '/guide/about' },
|
||||
{ text: 'Guide', link: '/guide/introduction' },
|
||||
],
|
||||
|
||||
sidebar: [
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Blitzkrieg 1.15.1
|
||||
|
||||
'MURICA!
|
||||
|
||||
## Changes
|
||||
|
||||
- "Neighbor" is now spelled in the American way
|
||||
- Updated documentation website with the latest information
|
||||
|
||||
## Fixes
|
||||
|
||||
- Fixed the guide link on the documentation website
|
||||
|
||||
## Technical features
|
||||
|
||||
- Added capability to fetch patiently while also parsing the JSON
|
||||
|
||||
## Technical changes
|
||||
|
||||
- Removed neighbor relative position caching
|
||||
|
||||
## Technical fixes
|
||||
|
||||
- `/ratings` now uses the non-caching APIs
|
||||
@@ -1,17 +0,0 @@
|
||||
# Installing Blitzkrieg
|
||||
|
||||
It's easy as 1, 2, 3!
|
||||
|
||||
## Step 1
|
||||
|
||||
Join a server that already has Blitzkrieg or [join our official Discord server](https://discord.gg/nDt7AjGJQH).
|
||||
|
||||
## Step 2
|
||||
|
||||
View the bot's profile and click "Add to Server".
|
||||
|
||||
<video src="https://i.imgur.com/Zq0P3m2.mp4" autoplay loop muted width=320 title="how to install"></video>
|
||||
|
||||
## Step 3
|
||||
|
||||
Review the permissions the bot is asking for and add it to your server!
|
||||
@@ -1,6 +1,10 @@
|
||||
# Introduction
|
||||
|
||||
Blitzkrieg is a multipurpose bot for anything and everything World of Tanks Blitz.
|
||||
🎉 Services for everything and anything World of Tanks Blitz
|
||||
|
||||
## Bot
|
||||
|
||||
Blitzkrieg is available as a Discord bot and can be [installed very easily](/guide/invite).
|
||||
|
||||
- Track statistics
|
||||
- Find inactive players in a clan
|
||||
@@ -8,3 +12,11 @@ Blitzkrieg is a multipurpose bot for anything and everything World of Tanks Blit
|
||||
- Create embeds for streams
|
||||
- Track a player/tanks statistical evolution
|
||||
- ...and a variety of other similar things
|
||||
|
||||
## Website
|
||||
|
||||
Provides a bunch of very helpful tools; https://blitz-krieg.vercel.app/
|
||||
|
||||
- Session tracker
|
||||
- Ratings leaderboard
|
||||
- Way more to come
|
||||
+2
-2
@@ -12,10 +12,10 @@ hero:
|
||||
actions:
|
||||
- theme: brand
|
||||
text: Add to Discord Server
|
||||
link: guide/install
|
||||
link: /guide/invite
|
||||
- theme: alt
|
||||
text: Guide
|
||||
link: /guide/about
|
||||
link: /guide/introduction
|
||||
|
||||
features:
|
||||
- title: Clean and Efficient UI
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "blitzkrieg",
|
||||
"version": "1.15.0",
|
||||
"version": "1.15.1",
|
||||
"description": "🎉 Tools for everything World of Tanks Blitz",
|
||||
"main": "src/server.ts",
|
||||
"type": "module",
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
RatingsNeighbors,
|
||||
RatingsPlayer,
|
||||
} from '../src/commands/ratings';
|
||||
import { patientFetch } from '../src/core/blitzkrieg/patientFetch';
|
||||
import { patientFetchJSON } from '../src/core/blitzkrieg/patientFetchJSON';
|
||||
import commitMultipleFiles from './commitMultipleFiles.js';
|
||||
|
||||
/*
|
||||
@@ -29,11 +29,9 @@ const server = argv.find((arg) => arg.startsWith('--region='))?.split('=')[1];
|
||||
if (!server) throw new Error('Region parameter not specified');
|
||||
|
||||
const NEIGHBORS = 1024;
|
||||
const PLAYERS = await patientFetch(
|
||||
const PLAYERS = await patientFetchJSON<RatingsInfo>(
|
||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/season/`,
|
||||
)
|
||||
.then((response) => response.json() as Promise<RatingsInfo>)
|
||||
.then((data) => (data.detail === undefined ? data.count : undefined));
|
||||
).then((data) => (data.detail === undefined ? data.count : undefined));
|
||||
|
||||
if (PLAYERS === undefined) {
|
||||
throw new Error('No current ratings season running');
|
||||
@@ -44,9 +42,9 @@ const leaderboard: BlitzkriegRatingsLeaderboard = [];
|
||||
let registered = 0;
|
||||
|
||||
async function branchFromPlayer(id: number) {
|
||||
const { neighbors } = await patientFetch(
|
||||
const { neighbors } = await patientFetchJSON<RatingsNeighbors>(
|
||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/user/${id}/?neighbors=${NEIGHBORS}`,
|
||||
).then((response) => response.json() as Promise<RatingsNeighbors>);
|
||||
);
|
||||
|
||||
const firstPlayer = neighbors[0];
|
||||
const lastPlayer = neighbors[neighbors.length - 1];
|
||||
@@ -75,9 +73,9 @@ async function branchFromPlayer(id: number) {
|
||||
}
|
||||
|
||||
async function branchFromLeague(id: number) {
|
||||
const { result } = await patientFetch(
|
||||
const { result } = await patientFetchJSON<{ result: RatingsPlayer[] }>(
|
||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/league/${id}/top/`,
|
||||
).then((response) => response.json() as Promise<{ result: RatingsPlayer[] }>);
|
||||
);
|
||||
|
||||
const firstPlayer = result[0];
|
||||
const lastPlayer = result[result.length - 1];
|
||||
@@ -113,11 +111,8 @@ const leaderboardJSON = JSON.stringify(leaderboard);
|
||||
if (publish) {
|
||||
const octokit = new Octokit({ auth: env.GH_TOKEN });
|
||||
|
||||
const info = await patientFetch(
|
||||
const info = await patientFetchJSON<RatingsInfo & { detail: undefined }>(
|
||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/season/`,
|
||||
).then(
|
||||
(response) =>
|
||||
response.json() as Promise<RatingsInfo & { detail: undefined }>,
|
||||
);
|
||||
const normalizedServer = server === 'na' ? 'com' : server;
|
||||
|
||||
|
||||
@@ -137,15 +137,12 @@ export default function Page() {
|
||||
await Promise.all(
|
||||
range(0, 5).map(async (league: number) => {
|
||||
const data = await getRatingsLeague(region, league);
|
||||
leaguePositionCache.current[region][league] =
|
||||
data.result[0].number - 1;
|
||||
leaguePositionCache.current[region][league] = data[0].number - 1;
|
||||
|
||||
return data;
|
||||
}),
|
||||
)
|
||||
)
|
||||
.map(({ result }) => result)
|
||||
.flat();
|
||||
).flat();
|
||||
|
||||
useLeaderboardCache.setState(
|
||||
produce((draft: LeaderboardCache) => {
|
||||
@@ -308,13 +305,14 @@ export default function Page() {
|
||||
|
||||
if (seedingPlayerNeighborEntry === undefined) return null;
|
||||
|
||||
const seedingPlayerPosition = parseInt(seedingPlayerNeighborEntry[0]);
|
||||
// const seedingPlayerPosition = parseInt(seedingPlayerNeighborEntry[0]);
|
||||
const { neighbors } = await getRatingsNeighbors(region, id, size, true);
|
||||
|
||||
useLeaderboardCache.setState(
|
||||
produce((draft: LeaderboardCache) => {
|
||||
neighbors.forEach((neighbor, neighborIndex) => {
|
||||
const position = neighborIndex - radius + seedingPlayerPosition;
|
||||
// const position = neighborIndex - radius + seedingPlayerPosition;
|
||||
const position = neighbor.number - 1;
|
||||
|
||||
if (!(position in draft[region][season])) {
|
||||
draft[region][season][position] = neighbor.spa_id;
|
||||
|
||||
+25
-31
@@ -15,6 +15,8 @@ import { REGION_NAMES_SHORT, Region } from '../constants/regions';
|
||||
import { getAccountInfo } from '../core/blitz/getAccountInfo';
|
||||
import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo';
|
||||
import getRatingsInfo from '../core/blitz/getRatingsInfo';
|
||||
import { getRatingsLeague } from '../core/blitz/getRatingsLeague';
|
||||
import { getRatingsNeighbors } from '../core/blitz/getRatingsNeighbors';
|
||||
import regionToRegionSubdomain from '../core/blitz/regionToRegionSubdomain';
|
||||
import { getArchivedLatestSeasonNumber } from '../core/blitzkrieg/getArchivedLatestSeasonNumber';
|
||||
import getArchivedRatingsInfo from '../core/blitzkrieg/getArchivedRatingsInfo';
|
||||
@@ -123,14 +125,14 @@ function addSubcommands(
|
||||
.addSubcommand((option) =>
|
||||
addOptions(
|
||||
option
|
||||
.setName('neighbours')
|
||||
.setDescription('Your position and neighbours'),
|
||||
.setName('neighbors')
|
||||
.setDescription('Your position and neighbors'),
|
||||
)
|
||||
.addStringOption(addUsernameChoices)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName('limit')
|
||||
.setDescription('How many neighbours to display (default: 10)')
|
||||
.setDescription('How many neighbors to display (default: 10)')
|
||||
.setRequired(false)
|
||||
.setMinValue(5)
|
||||
.setMaxValue(30),
|
||||
@@ -228,7 +230,7 @@ export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
| 'current';
|
||||
const subcommand = interaction.options.getSubcommand(true) as
|
||||
| 'league'
|
||||
| 'neighbours';
|
||||
| 'neighbors';
|
||||
const limit = interaction.options.getInteger('limit') ?? 10;
|
||||
const seasonOption = interaction.options.getString('season');
|
||||
const season = seasonOption ? parseInt(seasonOption) : undefined;
|
||||
@@ -257,11 +259,8 @@ export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
const regionSubdomain = regionToRegionSubdomain(region);
|
||||
const result =
|
||||
subcommandGroup === 'current'
|
||||
? await fetch(
|
||||
`https://${regionSubdomain}.wotblitz.com/en/api/rating-leaderboards/league/${leagueIndex}/top/`,
|
||||
)
|
||||
.then((response) => response.json() as Promise<LeagueTop>)
|
||||
.then(async ({ result }) =>
|
||||
? await getRatingsLeague(region, leagueIndex).then(
|
||||
async (result) =>
|
||||
result.slice(0, limit).map(
|
||||
(player) =>
|
||||
({
|
||||
@@ -272,7 +271,7 @@ export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
nickname: player.nickname,
|
||||
}) satisfies SimplifiedPlayer,
|
||||
),
|
||||
)
|
||||
)
|
||||
: await getArchivedRatingsLeaderboard(region, season!).then(
|
||||
async (players) => {
|
||||
const firstPlayerIndex =
|
||||
@@ -338,29 +337,24 @@ export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
|
||||
const accountInfo = await getAccountInfo(region, id);
|
||||
const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan;
|
||||
const regionSubdomain = regionToRegionSubdomain(region);
|
||||
const neighbors =
|
||||
subcommandGroup === 'current'
|
||||
? await fetch(
|
||||
`https://${regionSubdomain}.wotblitz.com/en/api/rating-leaderboards/user/${id}/?neighbors=${Math.round(
|
||||
limit / 2,
|
||||
)}`,
|
||||
? await getRatingsNeighbors(
|
||||
region,
|
||||
id,
|
||||
Math.round(limit / 2),
|
||||
).then((players) =>
|
||||
players.neighbors.map(
|
||||
(player) =>
|
||||
({
|
||||
id: player.spa_id,
|
||||
position: player.number,
|
||||
score: player.score,
|
||||
clan: player.clan_tag,
|
||||
nickname: player.nickname,
|
||||
}) satisfies SimplifiedPlayer,
|
||||
),
|
||||
)
|
||||
.then(
|
||||
(response) => response.json() as Promise<RatingsNeighbors>,
|
||||
)
|
||||
.then((players) =>
|
||||
players.neighbors.map(
|
||||
(player) =>
|
||||
({
|
||||
id: player.spa_id,
|
||||
position: player.number,
|
||||
score: player.score,
|
||||
clan: player.clan_tag,
|
||||
nickname: player.nickname,
|
||||
}) satisfies SimplifiedPlayer,
|
||||
),
|
||||
)
|
||||
: await getArchivedRatingsLeaderboard(region, season!).then(
|
||||
async (players) => {
|
||||
const playerIndex = players.findIndex(
|
||||
@@ -414,7 +408,7 @@ export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
titleName = neighbors
|
||||
? accountInfo.nickname
|
||||
: `No Ongoing Season - ${REGION_NAMES_SHORT[region]}`;
|
||||
titleDescription = 'Ratings neighbours';
|
||||
titleDescription = 'Ratings neighbors';
|
||||
playersBefore = neighbors ? neighbors[0].position - 1 : 0;
|
||||
playersAfter =
|
||||
regionRatingsInfo.count - neighbors[neighbors.length - 1].position;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LeagueTop } from '../../commands/ratings';
|
||||
import { LeagueTop, RatingsPlayer } from '../../commands/ratings';
|
||||
import { Region } from '../../constants/regions';
|
||||
import { context } from '../blitzkrieg/context';
|
||||
import { patientFetch } from '../blitzkrieg/patientFetch';
|
||||
@@ -9,7 +9,10 @@ export async function getRatingsLeague(
|
||||
league: number,
|
||||
usePatientFetcher = false,
|
||||
) {
|
||||
const fetcher = usePatientFetcher ? patientFetch : fetch;
|
||||
const fetcher = (url: string) =>
|
||||
usePatientFetcher
|
||||
? patientFetch(url, undefined, { cache: 'no-store' })
|
||||
: fetch(url, { cache: 'no-store' });
|
||||
const response = await fetcher(
|
||||
context === 'website'
|
||||
? `/api/${region}/ratings/current/league/${league}`
|
||||
@@ -17,7 +20,9 @@ export async function getRatingsLeague(
|
||||
region,
|
||||
)}.wotblitz.com/en/api/rating-leaderboards/league/${league}/top/`,
|
||||
);
|
||||
const json = (await response.json()) as LeagueTop;
|
||||
const json = await response.json();
|
||||
|
||||
return json;
|
||||
return context === 'website'
|
||||
? (json as RatingsPlayer[])
|
||||
: (json as LeagueTop).result;
|
||||
}
|
||||
@@ -10,9 +10,10 @@ export async function getRatingsNeighbors(
|
||||
count: number,
|
||||
usePatientFetcher = false,
|
||||
) {
|
||||
const fetcher = usePatientFetcher
|
||||
? patientFetch
|
||||
: (url: string) => fetch(url, { cache: 'no-store' });
|
||||
const fetcher = (url: string) =>
|
||||
usePatientFetcher
|
||||
? patientFetch(url, undefined, { cache: 'no-store' })
|
||||
: fetch(url, { cache: 'no-store' });
|
||||
const response = await fetcher(
|
||||
withCORSProxy(
|
||||
`https://${regionToRegionSubdomain(
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
export async function patientFetchJSON<Type extends object>(
|
||||
url: string,
|
||||
timeout = 1000,
|
||||
options?: Partial<{ cache: 'no-store' }>,
|
||||
) {
|
||||
let patientJSON: Type;
|
||||
|
||||
while (patientJSON! === undefined) {
|
||||
try {
|
||||
patientJSON = (await fetch(url, options).then(({ json }) =>
|
||||
json(),
|
||||
)) as Type;
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
`Failed to fetch ${url} as JSON; retrying in ${timeout}ms...`,
|
||||
error,
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, timeout));
|
||||
}
|
||||
}
|
||||
|
||||
return patientJSON;
|
||||
}
|
||||
Reference in new issue
Block a user