mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c2861f956 | ||
|
|
894b841769 | ||
|
|
62627c96a3 | ||
|
|
c173ece882 | ||
|
|
eca7cbbbeb | ||
|
|
c72bfa9f71 | ||
|
|
b4ae39a509 | ||
|
|
631c051895 | ||
|
|
9a2e11a2a4 | ||
|
|
aa6011b18d | ||
|
|
9419aec116 | ||
|
|
638402589f | ||
|
|
6d6a6bf738 |
No files matched your search
@@ -1,8 +1,8 @@
|
|||||||
name: CD North America Ratings Latest
|
name: CD Asia Ratings Latest
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * *'
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
host:
|
host:
|
||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'npm'
|
cache: "npm"
|
||||||
|
|
||||||
- name: Install Yarn
|
- name: Install Yarn
|
||||||
run: npm install --location=global yarn
|
run: npm install --location=global yarn
|
||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
- name: Use node_modules cache
|
- name: Use node_modules cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: '**/node_modules'
|
path: "**/node_modules"
|
||||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
name: CD North America Ratings Leaderboards
|
name: CD Asia Ratings Leaderboards
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 17 * * *'
|
- cron: "0 17 * * *"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
host:
|
host:
|
||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'npm'
|
cache: "npm"
|
||||||
|
|
||||||
- name: Install Yarn
|
- name: Install Yarn
|
||||||
run: npm install --location=global yarn
|
run: npm install --location=global yarn
|
||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
- name: Use node_modules cache
|
- name: Use node_modules cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: '**/node_modules'
|
path: "**/node_modules"
|
||||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
name: CD North America Ratings Latest
|
name: CD Europe Ratings Latest
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * *'
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
host:
|
host:
|
||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'npm'
|
cache: "npm"
|
||||||
|
|
||||||
- name: Install Yarn
|
- name: Install Yarn
|
||||||
run: npm install --location=global yarn
|
run: npm install --location=global yarn
|
||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
- name: Use node_modules cache
|
- name: Use node_modules cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: '**/node_modules'
|
path: "**/node_modules"
|
||||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
name: CD North America Ratings Leaderboards
|
name: CD Europe Ratings Leaderboards
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 23 * * *'
|
- cron: "0 23 * * *"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
host:
|
host:
|
||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'npm'
|
cache: "npm"
|
||||||
|
|
||||||
- name: Install Yarn
|
- name: Install Yarn
|
||||||
run: npm install --location=global yarn
|
run: npm install --location=global yarn
|
||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
- name: Use node_modules cache
|
- name: Use node_modules cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: '**/node_modules'
|
path: "**/node_modules"
|
||||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
|||||||
Vendored
+2
@@ -28,6 +28,7 @@
|
|||||||
"statsfull",
|
"statsfull",
|
||||||
"Stringifying",
|
"Stringifying",
|
||||||
"strvk",
|
"strvk",
|
||||||
|
"subnation",
|
||||||
"tankaverages",
|
"tankaverages",
|
||||||
"tankopedia",
|
"tankopedia",
|
||||||
"tankstats",
|
"tankstats",
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
"vickers",
|
"vickers",
|
||||||
"vitepress",
|
"vitepress",
|
||||||
"wargaming",
|
"wargaming",
|
||||||
|
"webp",
|
||||||
"winrate"
|
"winrate"
|
||||||
],
|
],
|
||||||
"deno.enable": false,
|
"deno.enable": false,
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Blitzkrieg 1.11.0
|
||||||
|
|
||||||
|
I am going on vacation so I thought I'd publish this a bit prematurely without all the planned features.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- Added `/ratings`
|
||||||
|
- This command currently only has the `leagues` subcommand group
|
||||||
|
- Displays the top players in a league
|
||||||
|
- Also shows the changes in their positions and scores since last region midnight
|
||||||
|
- Use `/help timezones` to know when Blitzkrieg records the leaderboard
|
||||||
|
- Blitzkrieg now internally generates and keeps a permanent record of all leaderboards updated every `UTC+0` midnight
|
||||||
|
- This approach will allow us to capture the absolute latest state of the leaderboard before it is wiped for the next season
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- Removed region "Europe" in `/verify` example
|
||||||
|
|
||||||
|
## Technical Changes
|
||||||
|
|
||||||
|
- Add scripts were upgraded to TypeScript
|
||||||
|
- Secrets now only throw errors if they're used when not provided
|
||||||
+8
-6
@@ -5,24 +5,25 @@
|
|||||||
"main": "src/server.ts",
|
"main": "src/server.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:bot": "node scripts/build --build=bot",
|
"build:bot": "vite-node --script scripts/build --build=bot",
|
||||||
"build:server": "node scripts/build --build=server",
|
"build:server": "vite-node --script scripts/build --build=server",
|
||||||
"build:docs": "vitepress build docs",
|
"build:docs": "vitepress build docs",
|
||||||
"build:ratingsleaderboard": "node scripts/generateRatingsLeaderboard",
|
"build:ratingsleaderboard": "vite-node --script scripts/buildRatingsLeaderboard",
|
||||||
"build": "node scripts/build --build=all",
|
"build": "vite-node --script scripts/build --build=all",
|
||||||
"dev:bot": "yarn build:bot --dev && yarn start:bot",
|
"dev:bot": "yarn build:bot --dev && yarn start:bot",
|
||||||
"dev:server": "yarn build:server --dev && yarn start:server",
|
"dev:server": "yarn build:server --dev && yarn start:server",
|
||||||
"dev:docs": "vitepress dev docs",
|
"dev:docs": "vitepress dev docs",
|
||||||
"start:bot": "node --enable-source-maps --trace-warnings dist/bot.cjs",
|
"start:bot": "node --enable-source-maps --trace-warnings dist/bot.cjs",
|
||||||
"start:server": "node --enable-source-maps --trace-warnings dist/server.cjs",
|
"start:server": "node --enable-source-maps --trace-warnings dist/server.cjs",
|
||||||
"host:docs": "vitepress preview docs",
|
"host:docs": "vitepress preview docs",
|
||||||
"publish:ratingsleaderboard": "node scripts/generateRatingsLeaderboard --publish",
|
"publish:ratingsleaderboard": "vite-node --script scripts/buildRatingsLeaderboard --publish",
|
||||||
"zip": "zip -r dist.zip dist",
|
"zip": "zip -r dist.zip dist",
|
||||||
"lint": "npx tsc",
|
"lint": "npx tsc",
|
||||||
"format": "prettier --write \"**/*.@(json|js|jsx|css|md|ts|tsx|html|xml|yml|gltf)\""
|
"format": "prettier --write \"**/*.@(json|js|jsx|css|md|ts|tsx|html|xml|yml|gltf)\""
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@octokit/rest": "^20.0.1",
|
||||||
"@radix-ui/colors": "^0.1.8",
|
"@radix-ui/colors": "^0.1.8",
|
||||||
"@resvg/resvg-js": "^2.4.1",
|
"@resvg/resvg-js": "^2.4.1",
|
||||||
"bepaint": "^0.1.0-beta.3",
|
"bepaint": "^0.1.0-beta.3",
|
||||||
@@ -30,15 +31,16 @@
|
|||||||
"esbuild": "^0.18.10",
|
"esbuild": "^0.18.10",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"false": "^0.0.4",
|
||||||
"fuzzysort": "^2.0.4",
|
"fuzzysort": "^2.0.4",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"markdown-escape": "^2.0.0",
|
"markdown-escape": "^2.0.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"satori": "^0.9.1",
|
"satori": "^0.9.1",
|
||||||
|
"vite-node": "^0.33.0",
|
||||||
"vitepress-plugin-auto-sidebar": "^1.1.0"
|
"vitepress-plugin-auto-sidebar": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@octokit/rest": "^20.0.1",
|
|
||||||
"@total-typescript/ts-reset": "^0.4.2",
|
"@total-typescript/ts-reset": "^0.4.2",
|
||||||
"@types/escape-html": "^1.0.2",
|
"@types/escape-html": "^1.0.2",
|
||||||
"@types/express": "^4.17.17",
|
"@types/express": "^4.17.17",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { build } from 'esbuild';
|
import { BuildOptions, build } from 'esbuild';
|
||||||
import { copyFile, mkdir, rm } from 'fs/promises';
|
import { copyFile, mkdir, rm } from 'fs/promises';
|
||||||
import { argv } from 'process';
|
import { argv } from 'process';
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ if (isProd) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const commonOptions = {
|
const commonOptions: BuildOptions = {
|
||||||
platform: 'node',
|
platform: 'node',
|
||||||
loader: {
|
loader: {
|
||||||
'.node': 'copy',
|
'.node': 'copy',
|
||||||
@@ -46,9 +46,7 @@ if (buildBot) {
|
|||||||
|
|
||||||
entryPoints: ['src/bot.ts'],
|
entryPoints: ['src/bot.ts'],
|
||||||
outfile: 'dist/bot.cjs',
|
outfile: 'dist/bot.cjs',
|
||||||
}).then(() => {
|
}).then(() => console.log('Bot built'));
|
||||||
console.log('Bot built');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buildServer) {
|
if (buildServer) {
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
import { Octokit } from '@octokit/rest';
|
import { Octokit } from '@octokit/rest';
|
||||||
import { rm, writeFile } from 'fs/promises';
|
import { rm, writeFile } from 'fs/promises';
|
||||||
import { argv, env } from 'process';
|
import { argv, env } from 'process';
|
||||||
|
import {
|
||||||
|
RatingsInfo,
|
||||||
|
RatingsNeighbors,
|
||||||
|
RatingsPlayer,
|
||||||
|
} from '../src/commands/ratings';
|
||||||
import commitMultipleFiles from './commitMultipleFiles.js';
|
import commitMultipleFiles from './commitMultipleFiles.js';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -8,11 +13,13 @@ import commitMultipleFiles from './commitMultipleFiles.js';
|
|||||||
* Central European Time (UTC+1): use 0 23 * * *.
|
* Central European Time (UTC+1): use 0 23 * * *.
|
||||||
* Central Asia Standard Time (UTC+7): use 0 17 * * *.
|
* Central Asia Standard Time (UTC+7): use 0 17 * * *.
|
||||||
*
|
*
|
||||||
* :region/ratings/:season/info.json: season info like rewards, start & end time, etc.
|
* na/ratings/49/info.json: season info like rewards, start & end time, etc.
|
||||||
* :region/ratings/:season/latest.json: the absolute latest leaderboard recorded at UTC+0 midnight
|
* na/ratings/49/latest.json: the absolute latest leaderboard recorded at UTC+0 midnight
|
||||||
* :region/ratings/:season/leaderboards/:time.json: collection of all recorded leaderboards at local midnights
|
* na/ratings/49/midnight.json: last midnight's leaderboard relative to the region
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export type BlitzkriegRatingsLeaderboard = { id: number; score: number }[];
|
||||||
|
|
||||||
const publish = argv.includes('--publish');
|
const publish = argv.includes('--publish');
|
||||||
const latest = argv.includes('--latest');
|
const latest = argv.includes('--latest');
|
||||||
const server = argv.find((arg) => arg.startsWith('--region='))?.split('=')[1];
|
const server = argv.find((arg) => arg.startsWith('--region='))?.split('=')[1];
|
||||||
@@ -23,22 +30,22 @@ const NEIGHBORS = 1000;
|
|||||||
const PLAYERS = await fetch(
|
const PLAYERS = await fetch(
|
||||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/season/`,
|
`https://${server}.wotblitz.com/en/api/rating-leaderboards/season/`,
|
||||||
)
|
)
|
||||||
.then((response) => response.json())
|
.then((response) => response.json() as Promise<RatingsInfo>)
|
||||||
.then((data) => data.count);
|
.then((data) => data.count);
|
||||||
|
|
||||||
const players = {};
|
const players: Record<number, RatingsPlayer> = {};
|
||||||
const leaderboard = [];
|
const leaderboard: BlitzkriegRatingsLeaderboard = [];
|
||||||
let registered = 0;
|
let registered = 0;
|
||||||
|
|
||||||
async function branchFromPlayer(id) {
|
async function branchFromPlayer(id: number) {
|
||||||
const { neighbors } = await fetch(
|
const { neighbors } = await fetch(
|
||||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/user/${id}/?neighbors=${NEIGHBORS}`,
|
`https://${server}.wotblitz.com/en/api/rating-leaderboards/user/${id}/?neighbors=${NEIGHBORS}`,
|
||||||
).then((response) => response.json());
|
).then((response) => response.json() as Promise<RatingsNeighbors>);
|
||||||
|
|
||||||
const firstPlayer = neighbors[0];
|
const firstPlayer = neighbors[0];
|
||||||
const lastPlayer = neighbors[neighbors.length - 1];
|
const lastPlayer = neighbors[neighbors.length - 1];
|
||||||
|
|
||||||
const branches = [];
|
const branches: Promise<void>[] = [];
|
||||||
if (!players[firstPlayer.number])
|
if (!players[firstPlayer.number])
|
||||||
branches.push(branchFromPlayer(firstPlayer.spa_id));
|
branches.push(branchFromPlayer(firstPlayer.spa_id));
|
||||||
if (!players[lastPlayer.number])
|
if (!players[lastPlayer.number])
|
||||||
@@ -61,10 +68,10 @@ async function branchFromPlayer(id) {
|
|||||||
await Promise.all(branches);
|
await Promise.all(branches);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function branchFromLeague(id) {
|
async function branchFromLeague(id: number) {
|
||||||
const { result } = await fetch(
|
const { result } = await fetch(
|
||||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/league/${id}/top/`,
|
`https://${server}.wotblitz.com/en/api/rating-leaderboards/league/${id}/top/`,
|
||||||
).then((response) => response.json());
|
).then((response) => response.json() as Promise<{ result: RatingsPlayer[] }>);
|
||||||
|
|
||||||
const firstPlayer = result[0];
|
const firstPlayer = result[0];
|
||||||
const lastPlayer = result[result.length - 1];
|
const lastPlayer = result[result.length - 1];
|
||||||
@@ -75,7 +82,7 @@ async function branchFromLeague(id) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Branching form leagues...');
|
console.log('Branching from leagues...');
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
branchFromLeague(0),
|
branchFromLeague(0),
|
||||||
branchFromLeague(1),
|
branchFromLeague(1),
|
||||||
@@ -86,8 +93,13 @@ await Promise.all([
|
|||||||
|
|
||||||
console.log('Converting to an array...');
|
console.log('Converting to an array...');
|
||||||
for (let index = 0; index < PLAYERS; index++) {
|
for (let index = 0; index < PLAYERS; index++) {
|
||||||
leaderboard[index] = players[index + 1];
|
const listing = players[index + 1];
|
||||||
if (!leaderboard[index]) console.warn(`${index} had no player`);
|
if (!listing) console.warn(`Position ${index + 1} had no player`);
|
||||||
|
|
||||||
|
leaderboard[index] = {
|
||||||
|
id: listing.spa_id,
|
||||||
|
score: listing.score,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const leaderboardJSON = JSON.stringify(leaderboard);
|
const leaderboardJSON = JSON.stringify(leaderboard);
|
||||||
@@ -97,14 +109,13 @@ if (publish) {
|
|||||||
|
|
||||||
const info = await fetch(
|
const info = await fetch(
|
||||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/season/`,
|
`https://${server}.wotblitz.com/en/api/rating-leaderboards/season/`,
|
||||||
).then((response) => response.json());
|
).then((response) => response.json() as Promise<RatingsInfo>);
|
||||||
const time = Math.round(Date.now() / 1000);
|
|
||||||
const normalizedServer = server === 'na' ? 'com' : server;
|
const normalizedServer = server === 'na' ? 'com' : server;
|
||||||
|
|
||||||
const infoPath = `${normalizedServer}/ratings/${info.current_season}/info.json`;
|
const infoPath = `${normalizedServer}/ratings/${info.current_season}/info.json`;
|
||||||
const leaderboardPath = `${normalizedServer}/ratings/${info.current_season}/${
|
const leaderboardPath = `${normalizedServer}/ratings/${info.current_season}/${
|
||||||
latest ? 'latest.json' : `leaderboards/${time}.json`
|
latest ? 'latest' : 'midnight'
|
||||||
}`;
|
}.json`;
|
||||||
const infoJSON = JSON.stringify(info);
|
const infoJSON = JSON.stringify(info);
|
||||||
|
|
||||||
console.log(`Publishing to season ${info.current_season}...`);
|
console.log(`Publishing to season ${info.current_season}...`);
|
||||||
@@ -113,7 +124,7 @@ if (publish) {
|
|||||||
'tresabhi',
|
'tresabhi',
|
||||||
'blitzkrieg-db',
|
'blitzkrieg-db',
|
||||||
'main',
|
'main',
|
||||||
`${info.current_season}/${time}`,
|
new Date().toString(),
|
||||||
[
|
[
|
||||||
{ path: infoPath, content: infoJSON },
|
{ path: infoPath, content: infoJSON },
|
||||||
{ path: leaderboardPath, content: leaderboardJSON },
|
{ path: leaderboardPath, content: leaderboardJSON },
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
|
import { Octokit } from '@octokit/rest';
|
||||||
|
|
||||||
export default async function commitMultipleFiles(
|
export default async function commitMultipleFiles(
|
||||||
octokit,
|
octokit: Octokit,
|
||||||
owner,
|
owner: string,
|
||||||
repo,
|
repo: string,
|
||||||
branch,
|
branch: string,
|
||||||
message,
|
message: string,
|
||||||
changes,
|
changes: { path: string; content: string }[],
|
||||||
) {
|
) {
|
||||||
// Get the latest commit SHA on the specified branch
|
// Get the latest commit SHA on the specified branch
|
||||||
const { data: refData } = await octokit.git.getRef({
|
const { data: refData } = await octokit.git.getRef({
|
||||||
@@ -31,12 +33,13 @@ export default async function commitMultipleFiles(
|
|||||||
content: change.content,
|
content: change.content,
|
||||||
encoding: 'utf-8',
|
encoding: 'utf-8',
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sha: blobData.sha,
|
sha: blobData.sha,
|
||||||
path: change.path,
|
path: change.path,
|
||||||
mode: '100644',
|
mode: '100644',
|
||||||
type: 'blob',
|
type: 'blob',
|
||||||
};
|
} as const;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
+5
-2
@@ -1,5 +1,6 @@
|
|||||||
|
import { Octokit } from '@octokit/rest';
|
||||||
import { Client, GatewayIntentBits } from 'discord.js';
|
import { Client, GatewayIntentBits } from 'discord.js';
|
||||||
import { DISCORD_TOKEN } from './core/node/arguments';
|
import { secrets } from './core/node/secrets';
|
||||||
import { registerErrorHandlers } from './events/error';
|
import { registerErrorHandlers } from './events/error';
|
||||||
import guildMemberAdd from './events/guildMemberAdd';
|
import guildMemberAdd from './events/guildMemberAdd';
|
||||||
import interactionCreate from './events/interactionCreate';
|
import interactionCreate from './events/interactionCreate';
|
||||||
@@ -12,5 +13,7 @@ export const client = new Client({
|
|||||||
.on('guildMemberAdd', guildMemberAdd)
|
.on('guildMemberAdd', guildMemberAdd)
|
||||||
.on('interactionCreate', interactionCreate);
|
.on('interactionCreate', interactionCreate);
|
||||||
|
|
||||||
|
export const octokit = new Octokit({ auth: secrets.GH_TOKEN });
|
||||||
|
|
||||||
registerErrorHandlers();
|
registerErrorHandlers();
|
||||||
client.login(DISCORD_TOKEN);
|
client.login(secrets.DISCORD_TOKEN);
|
||||||
@@ -12,7 +12,7 @@ import embedNegative from '../core/discord/embedNegative';
|
|||||||
import embedPositive from '../core/discord/embedPositive';
|
import embedPositive from '../core/discord/embedPositive';
|
||||||
import markdownTable, { TableInput } from '../core/discord/markdownTable';
|
import markdownTable, { TableInput } from '../core/discord/markdownTable';
|
||||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { AccountInfo } from '../types/accountInfo';
|
import { AccountInfo } from '../types/accountInfo';
|
||||||
import { PossiblyPromise } from '../types/possiblyPromise';
|
import { PossiblyPromise } from '../types/possiblyPromise';
|
||||||
@@ -49,9 +49,9 @@ export const eligibleCommand: CommandRegistry = {
|
|||||||
|
|
||||||
async handler(interaction) {
|
async handler(interaction) {
|
||||||
const clan = interaction.options.getString('clan') as SkilledClan;
|
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>(
|
const accountInfo = await getWargamingResponse<AccountInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
const problems: TableInput = [];
|
const problems: TableInput = [];
|
||||||
const title = `${accountInfo[id].nickname}'s eligibility for ${SKILLED_CLANS[clan]}`;
|
const title = `${accountInfo[id].nickname}'s eligibility for ${SKILLED_CLANS[clan]}`;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ 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 { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import evolution from '../renderers/evolution';
|
import evolution from '../renderers/evolution';
|
||||||
import { StatType } from '../renderers/fullStats';
|
import { StatType } from '../renderers/fullStats';
|
||||||
@@ -34,7 +34,7 @@ export const evolutionCommand: CommandRegistry = {
|
|||||||
true,
|
true,
|
||||||
) as StatType;
|
) as StatType;
|
||||||
const player = await resolvePlayerFromCommand(interaction);
|
const player = await resolvePlayerFromCommand(interaction);
|
||||||
const period = resolvePeriodFromCommand(player.server, interaction);
|
const period = resolvePeriodFromCommand(player.region, interaction);
|
||||||
const tankIdRaw = interaction.options.getString('tank')!;
|
const tankIdRaw = interaction.options.getString('tank')!;
|
||||||
const tankId =
|
const tankId =
|
||||||
commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null;
|
commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null;
|
||||||
@@ -42,7 +42,7 @@ export const evolutionCommand: CommandRegistry = {
|
|||||||
const end = interaction.options.getInteger('end');
|
const end = interaction.options.getInteger('end');
|
||||||
const { nickname } = (
|
const { nickname } = (
|
||||||
await getWargamingResponse<AccountInfo>(
|
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=${secrets.WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||||
)
|
)
|
||||||
)[player.id];
|
)[player.id];
|
||||||
const path = interactionToURL(interaction, {
|
const path = interactionToURL(interaction, {
|
||||||
@@ -57,7 +57,7 @@ export const evolutionCommand: CommandRegistry = {
|
|||||||
primaryButton(path, 'Refresh'),
|
primaryButton(path, 'Refresh'),
|
||||||
// linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
// linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
||||||
linkButton(
|
linkButton(
|
||||||
`https://www.blitzstars.com/player/${player.server}/${nickname}${
|
`https://www.blitzstars.com/player/${player.region}/${nickname}${
|
||||||
commandGroup === 'tank' ? `/tank/${tankId!}` : ''
|
commandGroup === 'tank' ? `/tank/${tankId!}` : ''
|
||||||
}`,
|
}`,
|
||||||
'BlitzStars',
|
'BlitzStars',
|
||||||
@@ -75,7 +75,7 @@ export const evolutionCommand: CommandRegistry = {
|
|||||||
const path = url.pathname.split('/').filter(Boolean);
|
const path = url.pathname.split('/').filter(Boolean);
|
||||||
const commandGroup = path[1] as StatType;
|
const commandGroup = path[1] as StatType;
|
||||||
const player = await resolvePlayerFromButton(interaction);
|
const player = await resolvePlayerFromButton(interaction);
|
||||||
const period = resolvePeriodFromButton(player.server, interaction);
|
const period = resolvePeriodFromButton(player.region, interaction);
|
||||||
|
|
||||||
return await evolution(
|
return await evolution(
|
||||||
commandGroup,
|
commandGroup,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ 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 { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import fullStats, { StatType } from '../renderers/fullStats';
|
import fullStats, { StatType } from '../renderers/fullStats';
|
||||||
import { AccountInfo } from '../types/accountInfo';
|
import { AccountInfo } from '../types/accountInfo';
|
||||||
@@ -33,7 +33,7 @@ export const fullStatsCommand: CommandRegistry = {
|
|||||||
true,
|
true,
|
||||||
) as StatType;
|
) as StatType;
|
||||||
const player = await resolvePlayerFromCommand(interaction);
|
const player = await resolvePlayerFromCommand(interaction);
|
||||||
const period = resolvePeriodFromCommand(player.server, interaction);
|
const period = resolvePeriodFromCommand(player.region, interaction);
|
||||||
const tankIdRaw = interaction.options.getString('tank')!;
|
const tankIdRaw = interaction.options.getString('tank')!;
|
||||||
const tankId =
|
const tankId =
|
||||||
commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null;
|
commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null;
|
||||||
@@ -47,7 +47,7 @@ export const fullStatsCommand: CommandRegistry = {
|
|||||||
});
|
});
|
||||||
const { nickname } = (
|
const { nickname } = (
|
||||||
await getWargamingResponse<AccountInfo>(
|
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=${secrets.WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||||
)
|
)
|
||||||
)[player.id];
|
)[player.id];
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ export const fullStatsCommand: CommandRegistry = {
|
|||||||
primaryButton(path, 'Refresh'),
|
primaryButton(path, 'Refresh'),
|
||||||
// linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
// linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
||||||
linkButton(
|
linkButton(
|
||||||
`https://www.blitzstars.com/player/${player.server}/${nickname}`,
|
`https://www.blitzstars.com/player/${player.region}/${nickname}`,
|
||||||
'BlitzStars',
|
'BlitzStars',
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@@ -72,7 +72,7 @@ export const fullStatsCommand: CommandRegistry = {
|
|||||||
const path = url.pathname.split('/').filter(Boolean);
|
const path = url.pathname.split('/').filter(Boolean);
|
||||||
const commandGroup = path[1] as StatType;
|
const commandGroup = path[1] as StatType;
|
||||||
const player = await resolvePlayerFromButton(interaction);
|
const player = await resolvePlayerFromButton(interaction);
|
||||||
const period = resolvePeriodFromButton(player.server, interaction);
|
const period = resolvePeriodFromButton(player.region, interaction);
|
||||||
|
|
||||||
return await fullStats(
|
return await fullStats(
|
||||||
commandGroup,
|
commandGroup,
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import NoData, { NoDataType } from '../components/NoData';
|
|||||||
import PoweredBy, { PoweredByType } from '../components/PoweredBy';
|
import PoweredBy, { PoweredByType } from '../components/PoweredBy';
|
||||||
import TitleBar from '../components/TitleBar';
|
import TitleBar from '../components/TitleBar';
|
||||||
import Wrapper from '../components/Wrapper';
|
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 getBlitzClan from '../core/blitz/getBlitzClan';
|
||||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||||
import addClanChoices from '../core/discord/addClanChoices';
|
import addClanChoices from '../core/discord/addClanChoices';
|
||||||
import autocompleteClan from '../core/discord/autocompleteClan';
|
import autocompleteClan from '../core/discord/autocompleteClan';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { AccountInfo } from '../types/accountInfo';
|
import { AccountInfo } from '../types/accountInfo';
|
||||||
import { ClanInfo } from '../types/clanInfo';
|
import { ClanInfo } from '../types/clanInfo';
|
||||||
@@ -42,14 +42,14 @@ export const inactiveCommand: CommandRegistry = {
|
|||||||
const time = new Date().getTime() / 1000;
|
const time = new Date().getTime() / 1000;
|
||||||
const clanData = (
|
const clanData = (
|
||||||
await getWargamingResponse<ClanInfo>(
|
await getWargamingResponse<ClanInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/clans/info/?application_id=${WARGAMING_APPLICATION_ID}&clan_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/clans/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&clan_id=${id}`,
|
||||||
)
|
)
|
||||||
)[id];
|
)[id];
|
||||||
const memberIds = clanData.members_ids;
|
const memberIds = clanData.members_ids;
|
||||||
const accounts = await getWargamingResponse<AccountInfo>(
|
const accounts = await getWargamingResponse<AccountInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${memberIds.join(
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${
|
||||||
',',
|
secrets.WARGAMING_APPLICATION_ID
|
||||||
)}`,
|
}&account_id=${memberIds.join(',')}`,
|
||||||
);
|
);
|
||||||
const inactive = memberIds
|
const inactive = memberIds
|
||||||
.map((memberId) => {
|
.map((memberId) => {
|
||||||
@@ -72,7 +72,7 @@ export const inactiveCommand: CommandRegistry = {
|
|||||||
nameDiscriminator="(Inactivity)"
|
nameDiscriminator="(Inactivity)"
|
||||||
image={`https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clanData.emblem_set_id}.png`}
|
image={`https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clanData.emblem_set_id}.png`}
|
||||||
description={`${threshold}+ Days • ${new Date().toDateString()} • ${
|
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 * as Tanks from '../components/Tanks';
|
||||||
import TitleBar from '../components/TitleBar';
|
import TitleBar from '../components/TitleBar';
|
||||||
import Wrapper from '../components/Wrapper';
|
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 getTankStats from '../core/blitz/getTankStats';
|
||||||
import getTreeType from '../core/blitz/getTreeType';
|
import getTreeType from '../core/blitz/getTreeType';
|
||||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
||||||
import autocompleteUsername from '../core/discord/autocompleteUsername';
|
import autocompleteUsername from '../core/discord/autocompleteUsername';
|
||||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { AccountInfo } from '../types/accountInfo';
|
import { AccountInfo } from '../types/accountInfo';
|
||||||
import { PlayerClanData } from '../types/playerClanData';
|
import { PlayerClanData } from '../types/playerClanData';
|
||||||
@@ -74,9 +74,9 @@ export const ownedTanksCommand: CommandRegistry = {
|
|||||||
async handler(interaction) {
|
async handler(interaction) {
|
||||||
const tier = Number(interaction.options.getString('tier'));
|
const tier = Number(interaction.options.getString('tier'));
|
||||||
const account = await resolvePlayerFromCommand(interaction);
|
const account = await resolvePlayerFromCommand(interaction);
|
||||||
const { id, server } = account;
|
const { id, region: server } = account;
|
||||||
const accountInfo = await getWargamingResponse<AccountInfo>(
|
const accountInfo = await getWargamingResponse<AccountInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
const tankStats = await getTankStats(server, id);
|
const tankStats = await getTankStats(server, id);
|
||||||
const tanks = (
|
const tanks = (
|
||||||
@@ -88,7 +88,7 @@ export const ownedTanksCommand: CommandRegistry = {
|
|||||||
)
|
)
|
||||||
).filter((tank) => tank?.tier === tier);
|
).filter((tank) => tank?.tier === tier);
|
||||||
const clanData = await getWargamingResponse<PlayerClanData>(
|
const clanData = await getWargamingResponse<PlayerClanData>(
|
||||||
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
||||||
);
|
);
|
||||||
const leftColumnSize = Math.ceil(tanks.length / 2);
|
const leftColumnSize = Math.ceil(tanks.length / 2);
|
||||||
const leftColumn = tanks.slice(0, leftColumnSize);
|
const leftColumn = tanks.slice(0, leftColumnSize);
|
||||||
@@ -105,7 +105,7 @@ export const ownedTanksCommand: CommandRegistry = {
|
|||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
description={`Owned tanks • ${new Date().toDateString()} • ${
|
description={`Owned tanks • ${new Date().toDateString()} • ${
|
||||||
REGION_DOMAIN_NAMES[server]
|
REGION_NAMES[server]
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import autocompleteUsername from '../core/discord/autocompleteUsername';
|
|||||||
import embedInfo from '../core/discord/embedInfo';
|
import embedInfo from '../core/discord/embedInfo';
|
||||||
import markdownTable, { TableInputEntry } from '../core/discord/markdownTable';
|
import markdownTable, { TableInputEntry } from '../core/discord/markdownTable';
|
||||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { AccountAchievements } from '../types/accountAchievements';
|
import { AccountAchievements } from '../types/accountAchievements';
|
||||||
import { AccountInfo } from '../types/accountInfo';
|
import { AccountInfo } from '../types/accountInfo';
|
||||||
@@ -36,13 +36,13 @@ 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, server } = account;
|
const { id, region: server } = account;
|
||||||
const accounts = await getWargamingResponse<AccountInfo>(
|
const accounts = await getWargamingResponse<AccountInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
const accountsAchievements =
|
const accountsAchievements =
|
||||||
await getWargamingResponse<AccountAchievements>(
|
await getWargamingResponse<AccountAchievements>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/achievements/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/account/achievements/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
const accountAchievements = accountsAchievements[id];
|
const accountAchievements = accountsAchievements[id];
|
||||||
const compound = {
|
const compound = {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import autocompleteUsername from '../core/discord/autocompleteUsername';
|
|||||||
import embedInfo from '../core/discord/embedInfo';
|
import embedInfo from '../core/discord/embedInfo';
|
||||||
import markdownTable from '../core/discord/markdownTable';
|
import markdownTable from '../core/discord/markdownTable';
|
||||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { AccountInfo } from '../types/accountInfo';
|
import { AccountInfo } from '../types/accountInfo';
|
||||||
|
|
||||||
@@ -22,9 +22,9 @@ export const playerInfoCommand: CommandRegistry = {
|
|||||||
|
|
||||||
async handler(interaction) {
|
async handler(interaction) {
|
||||||
const account = await resolvePlayerFromCommand(interaction);
|
const account = await resolvePlayerFromCommand(interaction);
|
||||||
const { id, server } = account;
|
const { id, region: server } = account;
|
||||||
const accounts = await getWargamingResponse<AccountInfo>(
|
const accounts = await getWargamingResponse<AccountInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
const accountInfo = accounts[id];
|
const accountInfo = accounts[id];
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,262 @@
|
|||||||
|
import { SlashCommandBuilder, SlashCommandSubcommandBuilder } from 'discord.js';
|
||||||
|
import { BlitzkriegRatingsLeaderboard } from '../../scripts/buildRatingsLeaderboard';
|
||||||
|
import { octokit } from '../bot';
|
||||||
|
import * as Leaderboard from '../components/Leaderboard';
|
||||||
|
import TitleBar from '../components/TitleBar';
|
||||||
|
import Wrapper from '../components/Wrapper';
|
||||||
|
import { REGION_NAMES, Region } from '../constants/regions';
|
||||||
|
import regionToRegionSubdomain from '../core/blitz/regionToRegionSubdomain';
|
||||||
|
import addRegionChoices from '../core/discord/addRegionChoices';
|
||||||
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|
||||||
|
export interface RatingsPlayer {
|
||||||
|
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: RatingsPlayer[];
|
||||||
|
}
|
||||||
|
|
||||||
|
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[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RatingsNeighbors {
|
||||||
|
neighbors: RatingsPlayer[];
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Caching ratings info...');
|
||||||
|
const ratingsInfo = fetch(
|
||||||
|
'https://na.wotblitz.com/en/api/rating-leaderboards/season/',
|
||||||
|
)
|
||||||
|
.then((response) => response.json() as Promise<RatingsInfo>)
|
||||||
|
.then((info) => {
|
||||||
|
console.log('Cached ratings info');
|
||||||
|
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,
|
||||||
|
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') ?? 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;
|
||||||
|
|
||||||
|
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 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()} • ${
|
||||||
|
REGION_NAMES[region]
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Leaderboard.Root>
|
||||||
|
{playersBefore > 0 && <Leaderboard.Gap number={playersBefore} />}
|
||||||
|
{items}
|
||||||
|
{playersAfter > 0 && <Leaderboard.Gap number={playersAfter} />}
|
||||||
|
</Leaderboard.Root>
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
import markdownEscape from 'markdown-escape';
|
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 getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||||
import addClanChoices from '../core/discord/addClanChoices';
|
import addClanChoices from '../core/discord/addClanChoices';
|
||||||
import addServerChoices from '../core/discord/addServerChoices';
|
import addRegionChoices from '../core/discord/addRegionChoices';
|
||||||
import embedInfo from '../core/discord/embedInfo';
|
import embedInfo from '../core/discord/embedInfo';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { ClanList } from '../types/clanList';
|
import { ClanList } from '../types/clanList';
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ export const searchClansCommand: CommandRegistry = {
|
|||||||
command: new SlashCommandBuilder()
|
command: new SlashCommandBuilder()
|
||||||
.setName('searchclans')
|
.setName('searchclans')
|
||||||
.setDescription('Search clans')
|
.setDescription('Search clans')
|
||||||
.addStringOption(addServerChoices)
|
.addStringOption(addRegionChoices)
|
||||||
.addStringOption((option) => addClanChoices(option).setAutocomplete(false))
|
.addStringOption((option) => addClanChoices(option).setAutocomplete(false))
|
||||||
.addIntegerOption((option) =>
|
.addIntegerOption((option) =>
|
||||||
option
|
option
|
||||||
@@ -28,17 +28,15 @@ export const searchClansCommand: CommandRegistry = {
|
|||||||
),
|
),
|
||||||
|
|
||||||
async handler(interaction) {
|
async handler(interaction) {
|
||||||
const server = interaction.options.getString('server') as RegionDomain;
|
const server = interaction.options.getString('region') as Region;
|
||||||
const clan = interaction.options.getString('clan')!;
|
const clan = interaction.options.getString('clan')!;
|
||||||
const limit = interaction.options.getInteger('limit') ?? 25;
|
const limit = interaction.options.getInteger('limit') ?? 25;
|
||||||
const clanList = await getWargamingResponse<ClanList>(
|
const clanList = await getWargamingResponse<ClanList>(
|
||||||
`https://api.wotblitz.${server}/wotb/clans/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${clan}&limit=${limit}`,
|
`https://api.wotblitz.${server}/wotb/clans/list/?application_id=${secrets.WARGAMING_APPLICATION_ID}&search=${clan}&limit=${limit}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
return embedInfo(
|
return embedInfo(
|
||||||
`Clan search for "${markdownEscape(clan)}" in ${
|
`Clan search for "${markdownEscape(clan)}" in ${REGION_NAMES[server]}`,
|
||||||
REGION_DOMAIN_NAMES[server]
|
|
||||||
}`,
|
|
||||||
clanList.length === 0
|
clanList.length === 0
|
||||||
? 'No clans found.'
|
? 'No clans found.'
|
||||||
: `\`\`\`\n${clanList
|
: `\`\`\`\n${clanList
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
import markdownEscape from 'markdown-escape';
|
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 getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||||
import { usernamePattern } from '../core/blitz/listPlayers';
|
import { usernamePattern } from '../core/blitz/listPlayers';
|
||||||
import addServerChoices from '../core/discord/addServerChoices';
|
import addRegionChoices from '../core/discord/addRegionChoices';
|
||||||
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
||||||
import embedInfo from '../core/discord/embedInfo';
|
import embedInfo from '../core/discord/embedInfo';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { AccountList } from '../types/accountList';
|
import { AccountList } from '../types/accountList';
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ export const searchPlayersCommand: CommandRegistry = {
|
|||||||
command: new SlashCommandBuilder()
|
command: new SlashCommandBuilder()
|
||||||
.setName('searchplayers')
|
.setName('searchplayers')
|
||||||
.setDescription('Search players in a Blitz server')
|
.setDescription('Search players in a Blitz server')
|
||||||
.addStringOption(addServerChoices)
|
.addStringOption(addRegionChoices)
|
||||||
.addStringOption((option) =>
|
.addStringOption((option) =>
|
||||||
addUsernameChoices(option).setAutocomplete(false).setRequired(true),
|
addUsernameChoices(option).setAutocomplete(false).setRequired(true),
|
||||||
)
|
)
|
||||||
@@ -31,22 +31,20 @@ export const searchPlayersCommand: CommandRegistry = {
|
|||||||
),
|
),
|
||||||
|
|
||||||
async handler(interaction) {
|
async handler(interaction) {
|
||||||
const server = interaction.options.getString('server') as RegionDomain;
|
const server = interaction.options.getString('region') as Region;
|
||||||
const name = interaction.options.getString('username')!;
|
const name = interaction.options.getString('username')!;
|
||||||
const limit = interaction.options.getInteger('limit') ?? 25;
|
const limit = interaction.options.getInteger('limit') ?? 25;
|
||||||
const trimmedSearch = name.trim();
|
const trimmedSearch = name.trim();
|
||||||
const players = usernamePattern.test(trimmedSearch)
|
const players = usernamePattern.test(trimmedSearch)
|
||||||
? await getWargamingResponse<AccountList>(
|
? await getWargamingResponse<AccountList>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${encodeURIComponent(
|
`https://api.wotblitz.${server}/wotb/account/list/?application_id=${
|
||||||
trimmedSearch,
|
secrets.WARGAMING_APPLICATION_ID
|
||||||
)}&limit=${limit}`,
|
}&search=${encodeURIComponent(trimmedSearch)}&limit=${limit}`,
|
||||||
)
|
)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
return embedInfo(
|
return embedInfo(
|
||||||
`Player search for "${markdownEscape(name)}" in ${
|
`Player search for "${markdownEscape(name)}" in ${REGION_NAMES[server]}`,
|
||||||
REGION_DOMAIN_NAMES[server]
|
|
||||||
}`,
|
|
||||||
`\`\`\`${
|
`\`\`\`${
|
||||||
players.length === 0
|
players.length === 0
|
||||||
? 'No players found.'
|
? 'No players found.'
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ 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 { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { StatType } from '../renderers/fullStats';
|
import { StatType } from '../renderers/fullStats';
|
||||||
import stats from '../renderers/stats';
|
import stats from '../renderers/stats';
|
||||||
@@ -26,7 +26,7 @@ export const statsCommand: CommandRegistry = {
|
|||||||
command: addStatTypeSubCommandGroups(
|
command: addStatTypeSubCommandGroups(
|
||||||
new SlashCommandBuilder()
|
new SlashCommandBuilder()
|
||||||
.setName('stats')
|
.setName('stats')
|
||||||
.setDescription('In-game statistics'),
|
.setDescription('Regular battles statistics'),
|
||||||
),
|
),
|
||||||
|
|
||||||
async handler(interaction) {
|
async handler(interaction) {
|
||||||
@@ -34,7 +34,7 @@ export const statsCommand: CommandRegistry = {
|
|||||||
true,
|
true,
|
||||||
) as StatType;
|
) as StatType;
|
||||||
const player = await resolvePlayerFromCommand(interaction);
|
const player = await resolvePlayerFromCommand(interaction);
|
||||||
const period = resolvePeriodFromCommand(player.server, interaction);
|
const period = resolvePeriodFromCommand(player.region, interaction);
|
||||||
const tankIdRaw = interaction.options.getString('tank')!;
|
const tankIdRaw = interaction.options.getString('tank')!;
|
||||||
const tankId =
|
const tankId =
|
||||||
commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null;
|
commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null;
|
||||||
@@ -48,7 +48,7 @@ export const statsCommand: CommandRegistry = {
|
|||||||
});
|
});
|
||||||
const { nickname } = (
|
const { nickname } = (
|
||||||
await getWargamingResponse<AccountInfo>(
|
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=${secrets.WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||||
)
|
)
|
||||||
)[player.id];
|
)[player.id];
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ export const statsCommand: CommandRegistry = {
|
|||||||
primaryButton(path, 'Refresh'),
|
primaryButton(path, 'Refresh'),
|
||||||
linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
||||||
linkButton(
|
linkButton(
|
||||||
`https://www.blitzstars.com/player/${player.server}/${nickname}`,
|
`https://www.blitzstars.com/player/${player.region}/${nickname}`,
|
||||||
'BlitzStars',
|
'BlitzStars',
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@@ -73,7 +73,7 @@ export const statsCommand: CommandRegistry = {
|
|||||||
const path = url.pathname.split('/').filter(Boolean);
|
const path = url.pathname.split('/').filter(Boolean);
|
||||||
const commandGroup = path[1] as StatType;
|
const commandGroup = path[1] as StatType;
|
||||||
const player = await resolvePlayerFromButton(interaction);
|
const player = await resolvePlayerFromButton(interaction);
|
||||||
const period = resolvePeriodFromButton(player.server, interaction);
|
const period = resolvePeriodFromButton(player.region, interaction);
|
||||||
|
|
||||||
return await stats(
|
return await stats(
|
||||||
commandGroup,
|
commandGroup,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import linkButton from '../core/discord/linkButton';
|
|||||||
import primaryButton from '../core/discord/primaryButton';
|
import primaryButton from '../core/discord/primaryButton';
|
||||||
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 { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import today from '../renderers/today';
|
import today from '../renderers/today';
|
||||||
import { AccountInfo } from '../types/accountInfo';
|
import { AccountInfo } from '../types/accountInfo';
|
||||||
@@ -37,7 +37,7 @@ export const todayCommand: CommandRegistry = {
|
|||||||
const limit = interaction.options.getInteger('limit') ?? Infinity;
|
const limit = interaction.options.getInteger('limit') ?? Infinity;
|
||||||
const { nickname } = (
|
const { nickname } = (
|
||||||
await getWargamingResponse<AccountInfo>(
|
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=${secrets.WARGAMING_APPLICATION_ID}&account_id=${player.id}`,
|
||||||
)
|
)
|
||||||
)[player.id];
|
)[player.id];
|
||||||
const path = interactionToURL(interaction, player);
|
const path = interactionToURL(interaction, player);
|
||||||
@@ -47,7 +47,7 @@ export const todayCommand: CommandRegistry = {
|
|||||||
primaryButton(path, 'Refresh'),
|
primaryButton(path, 'Refresh'),
|
||||||
linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
linkButton(`${CYCLIC_API}/${path}`, 'Embed'),
|
||||||
linkButton(
|
linkButton(
|
||||||
`https://www.blitzstars.com/player/${player.server}/${nickname}`,
|
`https://www.blitzstars.com/player/${player.region}/${nickname}`,
|
||||||
'BlitzStars',
|
'BlitzStars',
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import autocompleteUsername from '../core/discord/autocompleteUsername';
|
|||||||
import embedNegative from '../core/discord/embedNegative';
|
import embedNegative from '../core/discord/embedNegative';
|
||||||
import embedPositive from '../core/discord/embedPositive';
|
import embedPositive from '../core/discord/embedPositive';
|
||||||
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
import { AccountInfo } from '../types/accountInfo';
|
import { AccountInfo } from '../types/accountInfo';
|
||||||
import { PlayerClanData } from '../types/playerClanData';
|
import { PlayerClanData } from '../types/playerClanData';
|
||||||
@@ -24,12 +24,12 @@ export const verifyCommand: CommandRegistry = {
|
|||||||
|
|
||||||
async handler(interaction) {
|
async handler(interaction) {
|
||||||
const blitzAccount = await resolvePlayerFromCommand(interaction);
|
const blitzAccount = await resolvePlayerFromCommand(interaction);
|
||||||
const { id, server } = blitzAccount;
|
const { id, region: server } = blitzAccount;
|
||||||
const accountInfo = await getWargamingResponse<AccountInfo>(
|
const accountInfo = await getWargamingResponse<AccountInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
const clanData = await getWargamingResponse<PlayerClanData>(
|
const clanData = await getWargamingResponse<PlayerClanData>(
|
||||||
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
||||||
);
|
);
|
||||||
const clan = clanData[id]?.clan;
|
const clan = clanData[id]?.clan;
|
||||||
const clanTag = clan ? ` [${clan!.tag}]` : '';
|
const clanTag = clan ? ` [${clan!.tag}]` : '';
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { theme } from '../../../stitches.config';
|
||||||
|
|
||||||
|
export interface GapProps {
|
||||||
|
number: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Gap({ number }: GapProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
padding: 8,
|
||||||
|
backgroundColor: theme.colors.componentNonInteractive,
|
||||||
|
borderRadius: 4,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: theme.colors.textLowContrast,
|
||||||
|
fontSize: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
+ {number.toLocaleString()} more
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
import { RatingsReward } from '../../../commands/ratings';
|
||||||
|
import { theme } from '../../../stitches.config';
|
||||||
|
|
||||||
|
export interface ItemProps {
|
||||||
|
position: number;
|
||||||
|
deltaPosition?: number;
|
||||||
|
score: number;
|
||||||
|
deltaScore?: number;
|
||||||
|
reward?: RatingsReward;
|
||||||
|
nickname: string;
|
||||||
|
clan?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeImage(url: string) {
|
||||||
|
return url.endsWith('.webp') ? 'https://i.imgur.com/ZniCzbO.png' : url;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Item({
|
||||||
|
position,
|
||||||
|
deltaPosition,
|
||||||
|
score,
|
||||||
|
deltaScore,
|
||||||
|
reward,
|
||||||
|
nickname,
|
||||||
|
clan,
|
||||||
|
}: ItemProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
padding: 8,
|
||||||
|
backgroundColor: theme.colors.componentInteractive,
|
||||||
|
borderRadius: 4,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
gap: 8,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: theme.colors.textLowContrast,
|
||||||
|
fontSize: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{position.toLocaleString()}.
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
gap: 4,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: theme.colors.textHighContrast,
|
||||||
|
fontSize: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{nickname}
|
||||||
|
</span>
|
||||||
|
{clan && (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: theme.colors.textLowContrast,
|
||||||
|
fontSize: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
[{clan}]
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{deltaPosition !== undefined && deltaPosition !== 0 && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
gap: 4,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
}}
|
||||||
|
src={
|
||||||
|
deltaPosition > 0
|
||||||
|
? 'https://i.imgur.com/qbjiXa1.png'
|
||||||
|
: 'https://i.imgur.com/3uyNhun.png'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: theme.colors.textLowContrast,
|
||||||
|
fontSize: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Math.abs(deltaPosition).toLocaleString()}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
gap: 4,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{reward && (
|
||||||
|
<img
|
||||||
|
style={{ width: 16, height: 16, objectFit: 'cover' }}
|
||||||
|
src={normalizeImage(
|
||||||
|
reward.type === 'vehicle'
|
||||||
|
? reward.vehicle.image_url
|
||||||
|
: reward.stuff.image_url,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{reward && reward.count > 1 && (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: theme.colors.textLowContrast,
|
||||||
|
fontSize: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
x {reward.count.toLocaleString()}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
gap: 4,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{deltaScore !== 0 && deltaScore !== undefined && (
|
||||||
|
<span style={{ color: theme.colors.textLowContrast, fontSize: 16 }}>
|
||||||
|
{Math.abs(deltaScore).toLocaleString()}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{deltaScore !== 0 && deltaScore !== undefined && (
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
}}
|
||||||
|
src={
|
||||||
|
deltaScore > 0
|
||||||
|
? 'https://i.imgur.com/qbjiXa1.png'
|
||||||
|
: 'https://i.imgur.com/3uyNhun.png'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<span style={{ color: theme.colors.textHighContrast, fontSize: 16 }}>
|
||||||
|
{score.toLocaleString()}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
export interface RootProps {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Root({ children }: RootProps) {
|
||||||
|
return (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export * from './components/Gap';
|
||||||
|
export * from './components/Item';
|
||||||
|
export * from './components/Root';
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
export type RegionDomain = 'com' | 'eu' | 'asia';
|
export type Region = 'com' | 'eu' | 'asia';
|
||||||
export type RegionSubdomain = 'na' | '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',
|
com: 'North America',
|
||||||
eu: 'Europe',
|
eu: 'Europe',
|
||||||
asia: 'Asia',
|
asia: 'Asia',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { RegionDomain } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import { serverAndIdPattern } from '../discord/resolvePlayerFromCommand';
|
import { serverAndIdPattern } from '../discord/resolvePlayerFromCommand';
|
||||||
import throwError from '../node/throwError';
|
import throwError from '../node/throwError';
|
||||||
import listClans from './listClans';
|
import listClans from './listClans';
|
||||||
@@ -6,7 +6,7 @@ import listClans from './listClans';
|
|||||||
export default async function getBlitzClan(clan: string) {
|
export default async function getBlitzClan(clan: string) {
|
||||||
if (serverAndIdPattern.test(clan)) {
|
if (serverAndIdPattern.test(clan)) {
|
||||||
const [server, accountId] = clan.split('/');
|
const [server, accountId] = clan.split('/');
|
||||||
return { server: server as RegionDomain, id: Number(accountId) };
|
return { server: server as Region, id: Number(accountId) };
|
||||||
} else {
|
} else {
|
||||||
const accounts = await listClans(clan);
|
const accounts = await listClans(clan);
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { REGION_DOMAIN_NAMES, RegionDomain } from '../../constants/regions';
|
import { REGION_NAMES, Region } from '../../constants/regions';
|
||||||
import { TanksStats } from '../../types/tanksStats';
|
import { TanksStats } from '../../types/tanksStats';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../node/arguments';
|
import { secrets } from '../node/secrets';
|
||||||
import throwError from '../node/throwError';
|
import throwError from '../node/throwError';
|
||||||
import getWargamingResponse from './getWargamingResponse';
|
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>(
|
const tankStats = await getWargamingResponse<TanksStats>(
|
||||||
`https://api.wotblitz.${server}/wotb/tanks/stats/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/tanks/stats/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (tankStats[id] === null) {
|
if (tankStats[id] === null) {
|
||||||
throw throwError(
|
throw throwError(
|
||||||
'No tank stats available',
|
'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,6 +1,6 @@
|
|||||||
import { RegionDomain } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import { Clan, ClanList } from '../../types/clanList';
|
import { Clan, ClanList } from '../../types/clanList';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../node/arguments';
|
import { secrets } from '../node/secrets';
|
||||||
import getWargamingResponse from './getWargamingResponse';
|
import getWargamingResponse from './getWargamingResponse';
|
||||||
|
|
||||||
export type ClanListWithServer = (Clan & {
|
export type ClanListWithServer = (Clan & {
|
||||||
@@ -15,33 +15,33 @@ export default async function listClans(search: string, limit = 9) {
|
|||||||
return (
|
return (
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
getWargamingResponse<ClanList>(
|
getWargamingResponse<ClanList>(
|
||||||
`https://api.wotblitz.com/wotb/clans/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${search}&limit=${normalizedLimit}`,
|
`https://api.wotblitz.com/wotb/clans/list/?application_id=${secrets.WARGAMING_APPLICATION_ID}&search=${search}&limit=${normalizedLimit}`,
|
||||||
).then(
|
).then(
|
||||||
(value) =>
|
(value) =>
|
||||||
value &&
|
value &&
|
||||||
value.map((account) => ({
|
value.map((account) => ({
|
||||||
...account,
|
...account,
|
||||||
server: 'com' as RegionDomain,
|
server: 'com' as Region,
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
getWargamingResponse<ClanList>(
|
getWargamingResponse<ClanList>(
|
||||||
`https://api.wotblitz.eu/wotb/clans/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${search}&limit=${normalizedLimit}`,
|
`https://api.wotblitz.eu/wotb/clans/list/?application_id=${secrets.WARGAMING_APPLICATION_ID}&search=${search}&limit=${normalizedLimit}`,
|
||||||
).then(
|
).then(
|
||||||
(value) =>
|
(value) =>
|
||||||
value &&
|
value &&
|
||||||
value.map((account) => ({
|
value.map((account) => ({
|
||||||
...account,
|
...account,
|
||||||
server: 'eu' as RegionDomain,
|
server: 'eu' as Region,
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
getWargamingResponse<ClanList>(
|
getWargamingResponse<ClanList>(
|
||||||
`https://api.wotblitz.asia/wotb/clans/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${search}&limit=${normalizedLimit}`,
|
`https://api.wotblitz.asia/wotb/clans/list/?application_id=${secrets.WARGAMING_APPLICATION_ID}&search=${search}&limit=${normalizedLimit}`,
|
||||||
).then(
|
).then(
|
||||||
(value) =>
|
(value) =>
|
||||||
value &&
|
value &&
|
||||||
value.map((account) => ({
|
value.map((account) => ({
|
||||||
...account,
|
...account,
|
||||||
server: 'asia' as RegionDomain,
|
server: 'asia' as Region,
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { RegionDomain } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import { Account, AccountList } from '../../types/accountList';
|
import { Account, AccountList } from '../../types/accountList';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../node/arguments';
|
import { secrets } from '../node/secrets';
|
||||||
import getWargamingResponse from './getWargamingResponse';
|
import getWargamingResponse from './getWargamingResponse';
|
||||||
|
|
||||||
export type AccountListWithServer = (Account & {
|
export type AccountListWithServer = (Account & {
|
||||||
@@ -19,33 +19,33 @@ export default async function listPlayers(search: string, limit = 9) {
|
|||||||
return (
|
return (
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
getWargamingResponse<AccountList>(
|
getWargamingResponse<AccountList>(
|
||||||
`https://api.wotblitz.com/wotb/account/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=${normalizedLimit}`,
|
`https://api.wotblitz.com/wotb/account/list/?application_id=${secrets.WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=${normalizedLimit}`,
|
||||||
).then(
|
).then(
|
||||||
(value) =>
|
(value) =>
|
||||||
value &&
|
value &&
|
||||||
value.map((account) => ({
|
value.map((account) => ({
|
||||||
...account,
|
...account,
|
||||||
server: 'com' as RegionDomain,
|
server: 'com' as Region,
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
getWargamingResponse<AccountList>(
|
getWargamingResponse<AccountList>(
|
||||||
`https://api.wotblitz.eu/wotb/account/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=${normalizedLimit}`,
|
`https://api.wotblitz.eu/wotb/account/list/?application_id=${secrets.WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=${normalizedLimit}`,
|
||||||
).then(
|
).then(
|
||||||
(value) =>
|
(value) =>
|
||||||
value &&
|
value &&
|
||||||
value.map((account) => ({
|
value.map((account) => ({
|
||||||
...account,
|
...account,
|
||||||
server: 'eu' as RegionDomain,
|
server: 'eu' as Region,
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
getWargamingResponse<AccountList>(
|
getWargamingResponse<AccountList>(
|
||||||
`https://api.wotblitz.asia/wotb/account/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=${normalizedLimit}`,
|
`https://api.wotblitz.asia/wotb/account/list/?application_id=${secrets.WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=${normalizedLimit}`,
|
||||||
).then(
|
).then(
|
||||||
(value) =>
|
(value) =>
|
||||||
value &&
|
value &&
|
||||||
value.map((account) => ({
|
value.map((account) => ({
|
||||||
...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 { AllStats } from '../../types/accountInfo';
|
||||||
import getTankHistories, {
|
import getTankHistories, {
|
||||||
TankHistories,
|
TankHistories,
|
||||||
@@ -35,7 +35,7 @@ export const emptyTankHistoryNode: TankHistoryRaw = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function getDiffedTankStats(
|
export default async function getDiffedTankStats(
|
||||||
server: RegionDomain,
|
server: Region,
|
||||||
id: number,
|
id: number,
|
||||||
start: number,
|
start: number,
|
||||||
end: number,
|
end: number,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { RegionDomain } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import { Period } from '../discord/addPeriodSubCommands';
|
import { Period } from '../discord/addPeriodSubCommands';
|
||||||
import getTimeDaysAgo from './getTimeDaysAgo';
|
import getTimeDaysAgo from './getTimeDaysAgo';
|
||||||
|
|
||||||
export default function getPeriodStart(
|
export default function getPeriodStart(
|
||||||
server: RegionDomain,
|
server: Region,
|
||||||
period: Exclude<Period, 'custom'>,
|
period: Exclude<Period, 'custom'>,
|
||||||
) {
|
) {
|
||||||
if (period === 'career') {
|
if (period === 'career') {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { RegionDomain } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import { AccountInfo, AllStats } from '../../types/accountInfo';
|
import { AccountInfo, AllStats } from '../../types/accountInfo';
|
||||||
import {
|
import {
|
||||||
GetHistoriesOptions,
|
GetHistoriesOptions,
|
||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
getHistoriesDefaultOptions,
|
getHistoriesDefaultOptions,
|
||||||
} from '../../types/histories';
|
} from '../../types/histories';
|
||||||
import getWargamingResponse from '../blitz/getWargamingResponse';
|
import getWargamingResponse from '../blitz/getWargamingResponse';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../node/arguments';
|
import { secrets } from '../node/secrets';
|
||||||
import { emptyAllStats } from './getDiffedTankStats';
|
import { emptyAllStats } from './getDiffedTankStats';
|
||||||
|
|
||||||
export interface PlayerHistoryRaw {
|
export interface PlayerHistoryRaw {
|
||||||
@@ -25,13 +25,13 @@ export interface PlayerHistoryRaw {
|
|||||||
account_id: number;
|
account_id: number;
|
||||||
[key: string]: number;
|
[key: string]: number;
|
||||||
};
|
};
|
||||||
region: RegionDomain;
|
region: Region;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PlayerHistoriesRaw = PlayerHistoryRaw[];
|
export type PlayerHistoriesRaw = PlayerHistoryRaw[];
|
||||||
|
|
||||||
export default async function getPlayerHistories(
|
export default async function getPlayerHistories(
|
||||||
server: RegionDomain,
|
server: Region,
|
||||||
id: number,
|
id: number,
|
||||||
options?: Partial<GetHistoriesOptions>,
|
options?: Partial<GetHistoriesOptions>,
|
||||||
) {
|
) {
|
||||||
@@ -67,7 +67,7 @@ export default async function getPlayerHistories(
|
|||||||
statistics: { all },
|
statistics: { all },
|
||||||
} = (
|
} = (
|
||||||
await getWargamingResponse<AccountInfo>(
|
await getWargamingResponse<AccountInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
)
|
)
|
||||||
)[id];
|
)[id];
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { RegionDomain } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import {
|
import {
|
||||||
GetHistoriesOptions,
|
GetHistoriesOptions,
|
||||||
Histories,
|
Histories,
|
||||||
@@ -32,7 +32,7 @@ export const getTankHistoriesDefaultOptions: GetTankHistoriesOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function getTankHistories(
|
export default async function getTankHistories(
|
||||||
server: RegionDomain,
|
server: Region,
|
||||||
id: number,
|
id: number,
|
||||||
options?: Partial<GetTankHistoriesOptions>,
|
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
|
com: -5, // Central North American Time
|
||||||
eu: +1, // Central European Time
|
eu: +1, // Central European Time
|
||||||
asia: +7, // Central Asia Standard 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();
|
const now = new Date();
|
||||||
if (daysAgo === 0) now.getTime() / 1000;
|
if (daysAgo === 0) now.getTime() / 1000;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { SlashCommandStringOption } from 'discord.js';
|
||||||
|
import { REGION_NAMES } from '../../constants/regions';
|
||||||
|
|
||||||
|
export default function addRegionChoices(option: SlashCommandStringOption) {
|
||||||
|
return option
|
||||||
|
.setName('region')
|
||||||
|
.setDescription('The Blitz region you are in')
|
||||||
|
.addChoices(
|
||||||
|
{ name: REGION_NAMES.com, value: 'com' },
|
||||||
|
{ name: REGION_NAMES.eu, value: 'eu' },
|
||||||
|
{ name: REGION_NAMES.asia, value: 'asia' },
|
||||||
|
)
|
||||||
|
.setRequired(true);
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import { SlashCommandStringOption } from 'discord.js';
|
|
||||||
import { REGION_DOMAIN_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' },
|
|
||||||
)
|
|
||||||
.setRequired(true);
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
AutocompleteInteraction,
|
AutocompleteInteraction,
|
||||||
CacheType,
|
CacheType,
|
||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
import { REGION_DOMAIN_NAMES } from '../../constants/regions';
|
import { REGION_NAMES } from '../../constants/regions';
|
||||||
import listClans from '../blitz/listClans';
|
import listClans from '../blitz/listClans';
|
||||||
|
|
||||||
export default async function autocompleteClan(
|
export default async function autocompleteClan(
|
||||||
@@ -18,7 +18,7 @@ export default async function autocompleteClan(
|
|||||||
? players.map(
|
? players.map(
|
||||||
(player) =>
|
(player) =>
|
||||||
({
|
({
|
||||||
name: `${player.name} (${REGION_DOMAIN_NAMES[player.server]})`,
|
name: `${player.name} (${REGION_NAMES[player.server]})`,
|
||||||
value: `${player.server}/${player.clan_id}`,
|
value: `${player.server}/${player.clan_id}`,
|
||||||
}) satisfies ApplicationCommandOptionChoiceData<string>,
|
}) satisfies ApplicationCommandOptionChoiceData<string>,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
AutocompleteInteraction,
|
AutocompleteInteraction,
|
||||||
CacheType,
|
CacheType,
|
||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
import { REGION_DOMAIN_NAMES } from '../../constants/regions';
|
import { REGION_NAMES } from '../../constants/regions';
|
||||||
import listPlayers from '../blitz/listPlayers';
|
import listPlayers from '../blitz/listPlayers';
|
||||||
|
|
||||||
export default async function autocompleteUsername(
|
export default async function autocompleteUsername(
|
||||||
@@ -19,9 +19,7 @@ export default async function autocompleteUsername(
|
|||||||
? players.map(
|
? players.map(
|
||||||
(player) =>
|
(player) =>
|
||||||
({
|
({
|
||||||
name: `${player.nickname} (${
|
name: `${player.nickname} (${REGION_NAMES[player.server]})`,
|
||||||
REGION_DOMAIN_NAMES[player.server]
|
|
||||||
})`,
|
|
||||||
value: `${player.server}/${player.account_id}`,
|
value: `${player.server}/${player.account_id}`,
|
||||||
}) satisfies ApplicationCommandOptionChoiceData<string>,
|
}) satisfies ApplicationCommandOptionChoiceData<string>,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { ButtonInteraction, CacheType } from 'discord.js';
|
import { ButtonInteraction, CacheType } from 'discord.js';
|
||||||
import { CYCLIC_API } from '../../constants/cyclic';
|
import { CYCLIC_API } from '../../constants/cyclic';
|
||||||
import { RegionDomain } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import resolvePeriodFromURL from '../express/resolvePeriodFromURL';
|
import resolvePeriodFromURL from '../express/resolvePeriodFromURL';
|
||||||
|
|
||||||
export default function resolvePeriodFromButton(
|
export default function resolvePeriodFromButton(
|
||||||
server: RegionDomain,
|
server: Region,
|
||||||
interaction: ButtonInteraction<CacheType>,
|
interaction: ButtonInteraction<CacheType>,
|
||||||
) {
|
) {
|
||||||
return resolvePeriodFromURL(server, `${CYCLIC_API}/${interaction.customId}`);
|
return resolvePeriodFromURL(server, `${CYCLIC_API}/${interaction.customId}`);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { CacheType, ChatInputCommandInteraction } from 'discord.js';
|
import { CacheType, ChatInputCommandInteraction } from 'discord.js';
|
||||||
import { RegionDomain } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import getPeriodNow from '../blitzstars/getPeriodNow';
|
import getPeriodNow from '../blitzstars/getPeriodNow';
|
||||||
import getPeriodStart from '../blitzstars/getPeriodStart';
|
import getPeriodStart from '../blitzstars/getPeriodStart';
|
||||||
import getTimeDaysAgo from '../blitzstars/getTimeDaysAgo';
|
import getTimeDaysAgo from '../blitzstars/getTimeDaysAgo';
|
||||||
@@ -31,7 +31,7 @@ export interface ResolvedPeriod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function resolvePeriodFromCommand(
|
export default function resolvePeriodFromCommand(
|
||||||
server: RegionDomain,
|
server: Region,
|
||||||
interaction: ChatInputCommandInteraction<CacheType>,
|
interaction: ChatInputCommandInteraction<CacheType>,
|
||||||
) {
|
) {
|
||||||
let statsName: string;
|
let statsName: string;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { CacheType, ChatInputCommandInteraction } from 'discord.js';
|
import { CacheType, ChatInputCommandInteraction } from 'discord.js';
|
||||||
import { RegionDomain } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import listPlayers, {
|
import listPlayers, {
|
||||||
usernamePatternWithoutPosition,
|
usernamePatternWithoutPosition,
|
||||||
} from '../blitz/listPlayers';
|
} from '../blitz/listPlayers';
|
||||||
@@ -8,7 +8,7 @@ import throwError from '../node/throwError';
|
|||||||
export const serverAndIdPattern = /(com|eu|asia)\/[0-9]+/;
|
export const serverAndIdPattern = /(com|eu|asia)\/[0-9]+/;
|
||||||
|
|
||||||
export interface ResolvedPlayer {
|
export interface ResolvedPlayer {
|
||||||
server: RegionDomain;
|
region: Region;
|
||||||
id: number;
|
id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ export default async function resolvePlayerFromCommand(
|
|||||||
if (serverAndIdPattern.test(username)) {
|
if (serverAndIdPattern.test(username)) {
|
||||||
const [server, accountId] = username.split('/');
|
const [server, accountId] = username.split('/');
|
||||||
return {
|
return {
|
||||||
server: server as RegionDomain,
|
region: server as Region,
|
||||||
id: Number(accountId),
|
id: Number(accountId),
|
||||||
} satisfies ResolvedPlayer;
|
} satisfies ResolvedPlayer;
|
||||||
} else {
|
} else {
|
||||||
@@ -39,7 +39,7 @@ export default async function resolvePlayerFromCommand(
|
|||||||
|
|
||||||
if (accounts[0]) {
|
if (accounts[0]) {
|
||||||
return {
|
return {
|
||||||
server: accounts[0].server,
|
region: accounts[0].server,
|
||||||
id: accounts[0].account_id,
|
id: accounts[0].account_id,
|
||||||
} satisfies ResolvedPlayer;
|
} satisfies ResolvedPlayer;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
import { CYCLIC_API } from '../../constants/cyclic';
|
import { CYCLIC_API } from '../../constants/cyclic';
|
||||||
import { RegionDomain } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import resolvePeriodFromURL from './resolvePeriodFromURL';
|
import resolvePeriodFromURL from './resolvePeriodFromURL';
|
||||||
|
|
||||||
export default function resolvePeriodFromRequest(
|
export default function resolvePeriodFromRequest(
|
||||||
server: RegionDomain,
|
server: Region,
|
||||||
request: Request,
|
request: Request,
|
||||||
) {
|
) {
|
||||||
return resolvePeriodFromURL(server, `${CYCLIC_API}${request.path}`);
|
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 getPeriodNow from '../blitzstars/getPeriodNow';
|
||||||
import getPeriodStart from '../blitzstars/getPeriodStart';
|
import getPeriodStart from '../blitzstars/getPeriodStart';
|
||||||
import getTimeDaysAgo from '../blitzstars/getTimeDaysAgo';
|
import getTimeDaysAgo from '../blitzstars/getTimeDaysAgo';
|
||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
} from '../discord/resolvePeriodFromCommand';
|
} from '../discord/resolvePeriodFromCommand';
|
||||||
|
|
||||||
export default function resolvePeriodFromURL(
|
export default function resolvePeriodFromURL(
|
||||||
server: RegionDomain,
|
server: Region,
|
||||||
urlString: string,
|
urlString: string,
|
||||||
) {
|
) {
|
||||||
let statsName: string;
|
let statsName: string;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { RegionDomain } from '../../constants/regions';
|
import { Region } from '../../constants/regions';
|
||||||
import { ResolvedPlayer } from '../discord/resolvePlayerFromCommand';
|
import { ResolvedPlayer } from '../discord/resolvePlayerFromCommand';
|
||||||
|
|
||||||
export default function resolvePlayerFromURL(urlString: string) {
|
export default function resolvePlayerFromURL(urlString: string) {
|
||||||
@@ -6,6 +6,6 @@ export default function resolvePlayerFromURL(urlString: string) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
id: parseInt(url.searchParams.get('id')!),
|
id: parseInt(url.searchParams.get('id')!),
|
||||||
server: url.searchParams.get('server') as RegionDomain,
|
region: url.searchParams.get('region') as Region,
|
||||||
} satisfies ResolvedPlayer;
|
} satisfies ResolvedPlayer;
|
||||||
}
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
export const DISCORD_TOKEN = process.env.DISCORD_TOKEN!;
|
|
||||||
export const WARGAMING_APPLICATION_ID = process.env.WARGAMING_APPLICATION_ID!;
|
|
||||||
|
|
||||||
if (!DISCORD_TOKEN) {
|
|
||||||
throw new Error('No Discord token provided');
|
|
||||||
}
|
|
||||||
if (!WARGAMING_APPLICATION_ID) {
|
|
||||||
throw new Error('No Wargaming application id provided}');
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
export const SECRET_KEYS = [
|
||||||
|
'DISCORD_TOKEN',
|
||||||
|
'WARGAMING_APPLICATION_ID',
|
||||||
|
'GH_TOKEN',
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export type SECRET = typeof SECRET_KEYS extends readonly (infer T)[]
|
||||||
|
? T
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export const secrets = SECRET_KEYS.reduce<Partial<Record<SECRET, string>>>(
|
||||||
|
(accumulator, key) => ({
|
||||||
|
...accumulator,
|
||||||
|
|
||||||
|
get [key](): string {
|
||||||
|
if (!(key in process.env)) throw new Error(`Key ${key} not provided`);
|
||||||
|
return process.env[key]!;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{},
|
||||||
|
) as Record<SECRET, string>;
|
||||||
@@ -15,7 +15,7 @@ export default async function (member: GuildMember) {
|
|||||||
.setColor(ACCENT_COLOR)
|
.setColor(ACCENT_COLOR)
|
||||||
.setTitle(`Welcome ${member.user.username}`)
|
.setTitle(`Welcome ${member.user.username}`)
|
||||||
.setDescription(
|
.setDescription(
|
||||||
`Welcome to the Skilled server, **${member.user.username}**! To continue, please use the \`/verify\` command.\n\nExample: \`/verify Europe Sabina244\``,
|
`Welcome to the Skilled server, **${member.user.username}**! To continue, please use the \`/verify\` command.\n\nExample: \`/verify Sabina244\``,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
ChatInputCommandInteraction,
|
ChatInputCommandInteraction,
|
||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
import { commands } from '..';
|
import { commands } from '..';
|
||||||
|
import discord from '../../../../discord.json' assert { type: 'json' };
|
||||||
import embedNegative from '../../../core/discord/embedNegative';
|
import embedNegative from '../../../core/discord/embedNegative';
|
||||||
import embedWarning from '../../../core/discord/embedWarning';
|
import embedWarning from '../../../core/discord/embedWarning';
|
||||||
import normalizeInteractionReturnable from '../../../core/discord/normalizeInteractionReturnable';
|
import normalizeInteractionReturnable from '../../../core/discord/normalizeInteractionReturnable';
|
||||||
@@ -21,6 +22,19 @@ export default async function handleChatInputCommand(
|
|||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
|
||||||
try {
|
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);
|
const returnable = await registry.handler(interaction);
|
||||||
|
|
||||||
if (registry.handlesInteraction) return;
|
if (registry.handlesInteraction) return;
|
||||||
|
|||||||
@@ -23,15 +23,16 @@ import { ownedTanksCommand } from '../../commands/ownedTanks';
|
|||||||
import { pingCommand } from '../../commands/ping';
|
import { pingCommand } from '../../commands/ping';
|
||||||
import { playerAchievementsCommand } from '../../commands/playerAchievements';
|
import { playerAchievementsCommand } from '../../commands/playerAchievements';
|
||||||
import { playerInfoCommand } from '../../commands/playerInfo';
|
import { playerInfoCommand } from '../../commands/playerInfo';
|
||||||
|
import { ratingsCommand } from '../../commands/ratings';
|
||||||
import { searchClansCommand } from '../../commands/searchClans';
|
import { searchClansCommand } from '../../commands/searchClans';
|
||||||
import { searchPlayersCommand } from '../../commands/searchPlayers';
|
import { searchPlayersCommand } from '../../commands/searchPlayers';
|
||||||
import { searchTanksCommand } from '../../commands/searchTanks';
|
import { searchTanksCommand } from '../../commands/searchTanks';
|
||||||
import { statsCommand } from '../../commands/stats';
|
import { statsCommand } from '../../commands/stats';
|
||||||
import { todayCommand } from '../../commands/today';
|
import { todayCommand } from '../../commands/today';
|
||||||
import { verifyCommand } from '../../commands/verify';
|
import { verifyCommand } from '../../commands/verify';
|
||||||
import { DISCORD_TOKEN } from '../../core/node/arguments';
|
|
||||||
import getClientId from '../../core/node/getClientId';
|
import getClientId from '../../core/node/getClientId';
|
||||||
import isDev from '../../core/node/isDev';
|
import isDev from '../../core/node/isDev';
|
||||||
|
import { secrets } from '../../core/node/secrets';
|
||||||
import handleAutocomplete from './handlers/autocomplete';
|
import handleAutocomplete from './handlers/autocomplete';
|
||||||
import handleButton from './handlers/button';
|
import handleButton from './handlers/button';
|
||||||
import handleChatInputCommand from './handlers/chatInputCommand';
|
import handleChatInputCommand from './handlers/chatInputCommand';
|
||||||
@@ -56,6 +57,7 @@ export interface Registry {
|
|||||||
export interface CommandRegistry<HandlesInteraction extends boolean = boolean>
|
export interface CommandRegistry<HandlesInteraction extends boolean = boolean>
|
||||||
extends Registry {
|
extends Registry {
|
||||||
inPublic: boolean;
|
inPublic: boolean;
|
||||||
|
inPreview?: boolean;
|
||||||
handlesInteraction?: HandlesInteraction;
|
handlesInteraction?: HandlesInteraction;
|
||||||
command:
|
command:
|
||||||
| SlashCommandBuilder
|
| SlashCommandBuilder
|
||||||
@@ -69,7 +71,7 @@ export interface CommandRegistry<HandlesInteraction extends boolean = boolean>
|
|||||||
button?: (interaction: ButtonInteraction<CacheType>) => InteractionReturnable;
|
button?: (interaction: ButtonInteraction<CacheType>) => InteractionReturnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rest = new REST().setToken(DISCORD_TOKEN);
|
const rest = new REST().setToken(secrets.DISCORD_TOKEN);
|
||||||
|
|
||||||
export const COMMANDS_RAW: CommandRegistry[] = [
|
export const COMMANDS_RAW: CommandRegistry[] = [
|
||||||
debugCommand,
|
debugCommand,
|
||||||
@@ -88,6 +90,7 @@ export const COMMANDS_RAW: CommandRegistry[] = [
|
|||||||
pingCommand,
|
pingCommand,
|
||||||
evolutionCommand,
|
evolutionCommand,
|
||||||
statsCommand,
|
statsCommand,
|
||||||
|
ratingsCommand,
|
||||||
];
|
];
|
||||||
export const commands: Record<string, CommandRegistry> = COMMANDS_RAW.reduce(
|
export const commands: Record<string, CommandRegistry> = COMMANDS_RAW.reduce(
|
||||||
(accumulator, registry) => {
|
(accumulator, registry) => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import NoData, { NoDataType } from '../components/NoData';
|
|||||||
import PoweredBy, { PoweredByType } from '../components/PoweredBy';
|
import PoweredBy, { PoweredByType } from '../components/PoweredBy';
|
||||||
import TitleBar from '../components/TitleBar';
|
import TitleBar from '../components/TitleBar';
|
||||||
import Wrapper from '../components/Wrapper';
|
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 getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||||
import resolveTankName from '../core/blitz/resolveTankName';
|
import resolveTankName from '../core/blitz/resolveTankName';
|
||||||
import { tankopedia } from '../core/blitz/tankopedia';
|
import { tankopedia } from '../core/blitz/tankopedia';
|
||||||
@@ -11,7 +11,7 @@ import getPlayerHistories from '../core/blitzstars/getPlayerHistories';
|
|||||||
import getTankHistories from '../core/blitzstars/getTankHistories';
|
import getTankHistories from '../core/blitzstars/getTankHistories';
|
||||||
import { ResolvedPeriod } from '../core/discord/resolvePeriodFromCommand';
|
import { ResolvedPeriod } from '../core/discord/resolvePeriodFromCommand';
|
||||||
import { ResolvedPlayer } from '../core/discord/resolvePlayerFromCommand';
|
import { ResolvedPlayer } from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { AccountInfo } from '../types/accountInfo';
|
import { AccountInfo } from '../types/accountInfo';
|
||||||
import { Histories } from '../types/histories';
|
import { Histories } from '../types/histories';
|
||||||
import { PlayerClanData } from '../types/playerClanData';
|
import { PlayerClanData } from '../types/playerClanData';
|
||||||
@@ -20,7 +20,7 @@ import { StatType } from './fullStats';
|
|||||||
export default async function evolution<Type extends StatType>(
|
export default async function evolution<Type extends StatType>(
|
||||||
type: Type,
|
type: Type,
|
||||||
{ start, end, evolutionName }: ResolvedPeriod,
|
{ start, end, evolutionName }: ResolvedPeriod,
|
||||||
{ server, id }: ResolvedPlayer,
|
{ region: server, id }: ResolvedPlayer,
|
||||||
tankId: Type extends 'tank' ? number : null,
|
tankId: Type extends 'tank' ? number : null,
|
||||||
) {
|
) {
|
||||||
let nameDiscriminator: string | undefined;
|
let nameDiscriminator: string | undefined;
|
||||||
@@ -29,7 +29,7 @@ export default async function evolution<Type extends StatType>(
|
|||||||
if (type === 'player') {
|
if (type === 'player') {
|
||||||
const clan = (
|
const clan = (
|
||||||
await getWargamingResponse<PlayerClanData>(
|
await getWargamingResponse<PlayerClanData>(
|
||||||
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
||||||
)
|
)
|
||||||
)[id]?.clan;
|
)[id]?.clan;
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ export default async function evolution<Type extends StatType>(
|
|||||||
const minX = Math.min(...xs);
|
const minX = Math.min(...xs);
|
||||||
|
|
||||||
const accountInfo = await getWargamingResponse<AccountInfo>(
|
const accountInfo = await getWargamingResponse<AccountInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -89,7 +89,7 @@ export default async function evolution<Type extends StatType>(
|
|||||||
nameDiscriminator={nameDiscriminator}
|
nameDiscriminator={nameDiscriminator}
|
||||||
image={image}
|
image={image}
|
||||||
description={`${evolutionName} • ${new Date().toDateString()} • ${
|
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 TierWeights, { TierWeightsRecord } from '../components/TierWeights';
|
||||||
import TitleBar from '../components/TitleBar';
|
import TitleBar from '../components/TitleBar';
|
||||||
import Wrapper from '../components/Wrapper';
|
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 calculateWN8 from '../core/blitz/calculateWN8';
|
||||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||||
import resolveTankName from '../core/blitz/resolveTankName';
|
import resolveTankName from '../core/blitz/resolveTankName';
|
||||||
@@ -14,7 +14,7 @@ import getDiffedTankStats from '../core/blitzstars/getDiffedTankStats';
|
|||||||
import { tankAverages } from '../core/blitzstars/tankAverages';
|
import { tankAverages } from '../core/blitzstars/tankAverages';
|
||||||
import { ResolvedPeriod } from '../core/discord/resolvePeriodFromCommand';
|
import { ResolvedPeriod } from '../core/discord/resolvePeriodFromCommand';
|
||||||
import { ResolvedPlayer } from '../core/discord/resolvePlayerFromCommand';
|
import { ResolvedPlayer } from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import {
|
import {
|
||||||
AccountInfo,
|
AccountInfo,
|
||||||
AllStats,
|
AllStats,
|
||||||
@@ -28,7 +28,7 @@ export type StatType = 'player' | 'tank';
|
|||||||
export default async function fullStats<Type extends StatType>(
|
export default async function fullStats<Type extends StatType>(
|
||||||
type: Type,
|
type: Type,
|
||||||
{ start, end, statsName }: ResolvedPeriod,
|
{ start, end, statsName }: ResolvedPeriod,
|
||||||
{ server, id }: ResolvedPlayer,
|
{ region: server, id }: ResolvedPlayer,
|
||||||
tankId: Type extends 'tank' ? number : null,
|
tankId: Type extends 'tank' ? number : null,
|
||||||
) {
|
) {
|
||||||
let nameDiscriminator: string | undefined;
|
let nameDiscriminator: string | undefined;
|
||||||
@@ -37,7 +37,7 @@ export default async function fullStats<Type extends StatType>(
|
|||||||
if (type === 'player') {
|
if (type === 'player') {
|
||||||
const clan = (
|
const clan = (
|
||||||
await getWargamingResponse<PlayerClanData>(
|
await getWargamingResponse<PlayerClanData>(
|
||||||
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
||||||
)
|
)
|
||||||
)[id]?.clan;
|
)[id]?.clan;
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ export default async function fullStats<Type extends StatType>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const accountInfo = await getWargamingResponse<AccountInfo>(
|
const accountInfo = await getWargamingResponse<AccountInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -143,7 +143,7 @@ export default async function fullStats<Type extends StatType>(
|
|||||||
nameDiscriminator={nameDiscriminator}
|
nameDiscriminator={nameDiscriminator}
|
||||||
image={image}
|
image={image}
|
||||||
description={`${statsName} • ${new Date().toDateString()} • ${
|
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 { TierWeightsRecord } from '../components/TierWeights';
|
||||||
import TitleBar from '../components/TitleBar';
|
import TitleBar from '../components/TitleBar';
|
||||||
import Wrapper from '../components/Wrapper';
|
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 calculateWN8 from '../core/blitz/calculateWN8';
|
||||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||||
import resolveTankName from '../core/blitz/resolveTankName';
|
import resolveTankName from '../core/blitz/resolveTankName';
|
||||||
@@ -14,7 +14,7 @@ import getDiffedTankStats from '../core/blitzstars/getDiffedTankStats';
|
|||||||
import { tankAverages } from '../core/blitzstars/tankAverages';
|
import { tankAverages } from '../core/blitzstars/tankAverages';
|
||||||
import { ResolvedPeriod } from '../core/discord/resolvePeriodFromCommand';
|
import { ResolvedPeriod } from '../core/discord/resolvePeriodFromCommand';
|
||||||
import { ResolvedPlayer } from '../core/discord/resolvePlayerFromCommand';
|
import { ResolvedPlayer } from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { theme } from '../stitches.config';
|
import { theme } from '../stitches.config';
|
||||||
import {
|
import {
|
||||||
AccountInfo,
|
AccountInfo,
|
||||||
@@ -29,7 +29,7 @@ export type StatType = 'player' | 'tank';
|
|||||||
export default async function stats<Type extends StatType>(
|
export default async function stats<Type extends StatType>(
|
||||||
type: Type,
|
type: Type,
|
||||||
{ start, end, statsName }: ResolvedPeriod,
|
{ start, end, statsName }: ResolvedPeriod,
|
||||||
{ server, id }: ResolvedPlayer,
|
{ region: server, id }: ResolvedPlayer,
|
||||||
tankId: Type extends 'tank' ? number : null,
|
tankId: Type extends 'tank' ? number : null,
|
||||||
naked = false,
|
naked = false,
|
||||||
) {
|
) {
|
||||||
@@ -39,7 +39,7 @@ export default async function stats<Type extends StatType>(
|
|||||||
if (type === 'player') {
|
if (type === 'player') {
|
||||||
const clan = (
|
const clan = (
|
||||||
await getWargamingResponse<PlayerClanData>(
|
await getWargamingResponse<PlayerClanData>(
|
||||||
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
||||||
)
|
)
|
||||||
)[id]?.clan;
|
)[id]?.clan;
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ export default async function stats<Type extends StatType>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const accountInfo = await getWargamingResponse<AccountInfo>(
|
const accountInfo = await getWargamingResponse<AccountInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
const overview = (
|
const overview = (
|
||||||
<AllStatsOverview stats={stats} supplementaryStats={supplementaryStats} />
|
<AllStatsOverview stats={stats} supplementaryStats={supplementaryStats} />
|
||||||
@@ -164,7 +164,7 @@ export default async function stats<Type extends StatType>(
|
|||||||
nameDiscriminator={nameDiscriminator}
|
nameDiscriminator={nameDiscriminator}
|
||||||
image={image}
|
image={image}
|
||||||
description={`${statsName} • ${new Date().toDateString()} • ${
|
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 PoweredBy, { PoweredByType } from '../components/PoweredBy';
|
||||||
import TitleBar from '../components/TitleBar';
|
import TitleBar from '../components/TitleBar';
|
||||||
import Wrapper from '../components/Wrapper';
|
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 calculateWN8 from '../core/blitz/calculateWN8';
|
||||||
import getTankStats from '../core/blitz/getTankStats';
|
import getTankStats from '../core/blitz/getTankStats';
|
||||||
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
import getWargamingResponse from '../core/blitz/getWargamingResponse';
|
||||||
@@ -15,13 +15,13 @@ import getPeriodNow from '../core/blitzstars/getPeriodNow';
|
|||||||
import getTimeDaysAgo from '../core/blitzstars/getTimeDaysAgo';
|
import getTimeDaysAgo from '../core/blitzstars/getTimeDaysAgo';
|
||||||
import { tankAverages } from '../core/blitzstars/tankAverages';
|
import { tankAverages } from '../core/blitzstars/tankAverages';
|
||||||
import { ResolvedPlayer } from '../core/discord/resolvePlayerFromCommand';
|
import { ResolvedPlayer } from '../core/discord/resolvePlayerFromCommand';
|
||||||
import { WARGAMING_APPLICATION_ID } from '../core/node/arguments';
|
import { secrets } from '../core/node/secrets';
|
||||||
import { AccountInfo, AllStats } from '../types/accountInfo';
|
import { AccountInfo, AllStats } from '../types/accountInfo';
|
||||||
import { PlayerClanData } from '../types/playerClanData';
|
import { PlayerClanData } from '../types/playerClanData';
|
||||||
import { PossiblyPromise } from '../types/possiblyPromise';
|
import { PossiblyPromise } from '../types/possiblyPromise';
|
||||||
|
|
||||||
export default async function today(
|
export default async function today(
|
||||||
{ server, id }: ResolvedPlayer,
|
{ region: server, id }: ResolvedPlayer,
|
||||||
limit = Infinity,
|
limit = Infinity,
|
||||||
naked?: boolean,
|
naked?: boolean,
|
||||||
) {
|
) {
|
||||||
@@ -32,10 +32,10 @@ export default async function today(
|
|||||||
getPeriodNow(),
|
getPeriodNow(),
|
||||||
);
|
);
|
||||||
const accountInfo = await getWargamingResponse<AccountInfo>(
|
const accountInfo = await getWargamingResponse<AccountInfo>(
|
||||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
const clanData = await getWargamingResponse<PlayerClanData>(
|
const clanData = await getWargamingResponse<PlayerClanData>(
|
||||||
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
|
||||||
);
|
);
|
||||||
const careerTankStatsRaw = await getTankStats(server, id);
|
const careerTankStatsRaw = await getTankStats(server, id);
|
||||||
const careerStats: Record<number, AllStats> = {
|
const careerStats: Record<number, AllStats> = {
|
||||||
@@ -162,7 +162,7 @@ export default async function today(
|
|||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
description={`Today's breakdown • ${new Date().toDateString()} • ${
|
description={`Today's breakdown • ${new Date().toDateString()} • ${
|
||||||
REGION_DOMAIN_NAMES[server]
|
REGION_NAMES[server]
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const statsRoute: RouteRegistry = {
|
|||||||
async handler(req) {
|
async handler(req) {
|
||||||
const type = req.params.type as StatType;
|
const type = req.params.type as StatType;
|
||||||
const player = resolvePlayerFromRequest(req);
|
const player = resolvePlayerFromRequest(req);
|
||||||
const period = resolvePeriodFromRequest(player.server, req);
|
const period = resolvePeriodFromRequest(player.region, req);
|
||||||
|
|
||||||
return await stats(
|
return await stats(
|
||||||
type,
|
type,
|
||||||
|
|||||||
+1
-4
@@ -11,8 +11,5 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"jsx": "react-jsx"
|
"jsx": "react-jsx"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src/**/*.ts"]
|
||||||
"src/**/*.ts",
|
|
||||||
"src/components/AllStatsOverview/components/WN8SurroundingStat.tsx"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
@@ -933,6 +933,11 @@ accepts@~1.3.8:
|
|||||||
mime-types "~2.1.34"
|
mime-types "~2.1.34"
|
||||||
negotiator "0.6.3"
|
negotiator "0.6.3"
|
||||||
|
|
||||||
|
acorn@^8.9.0:
|
||||||
|
version "8.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
|
||||||
|
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
|
||||||
|
|
||||||
algoliasearch@^4.0.0:
|
algoliasearch@^4.0.0:
|
||||||
version "4.18.0"
|
version "4.18.0"
|
||||||
resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.18.0.tgz#1183ad0384a5b2c14f381c3a361da611acc8edb3"
|
resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.18.0.tgz#1183ad0384a5b2c14f381c3a361da611acc8edb3"
|
||||||
@@ -1013,6 +1018,11 @@ [email protected]:
|
|||||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
|
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
|
||||||
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
|
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
|
||||||
|
|
||||||
|
cac@^6.7.14:
|
||||||
|
version "6.7.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959"
|
||||||
|
integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==
|
||||||
|
|
||||||
call-bind@^1.0.0:
|
call-bind@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||||
@@ -1089,6 +1099,13 @@ [email protected]:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms "2.0.0"
|
ms "2.0.0"
|
||||||
|
|
||||||
|
debug@^4.3.4:
|
||||||
|
version "4.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||||
|
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||||
|
dependencies:
|
||||||
|
ms "2.1.2"
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||||
@@ -1252,6 +1269,11 @@ express@^4.18.2:
|
|||||||
utils-merge "1.0.1"
|
utils-merge "1.0.1"
|
||||||
vary "~1.1.2"
|
vary "~1.1.2"
|
||||||
|
|
||||||
|
"false@^0.0.4":
|
||||||
|
version "0.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/false/-/false-0.0.4.tgz#8f55de5af5c03f50bf68aed57ed80e3d2176a517"
|
||||||
|
integrity sha512-CPAG3ud9Cz8NvLKlsTLr/F1aoJL6tPyhNTzaDFzS5CX6id21hVuS5sBK8wlTLuvFklpvH1idvPbW8Lbri3G7qA==
|
||||||
|
|
||||||
fast-deep-equal@^3.1.3:
|
fast-deep-equal@^3.1.3:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||||
@@ -1475,11 +1497,26 @@ minisearch@^6.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/minisearch/-/minisearch-6.1.0.tgz#6e74e743dbd0e88fa5ca52fef2391e0aa7055252"
|
resolved "https://registry.yarnpkg.com/minisearch/-/minisearch-6.1.0.tgz#6e74e743dbd0e88fa5ca52fef2391e0aa7055252"
|
||||||
integrity sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==
|
integrity sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==
|
||||||
|
|
||||||
|
mlly@^1.2.0, mlly@^1.4.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.4.0.tgz#830c10d63f1f97bd8785377b24dc2a15d972832b"
|
||||||
|
integrity sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==
|
||||||
|
dependencies:
|
||||||
|
acorn "^8.9.0"
|
||||||
|
pathe "^1.1.1"
|
||||||
|
pkg-types "^1.0.3"
|
||||||
|
ufo "^1.1.2"
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
|
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||||
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
version "2.1.3"
|
version "2.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||||
@@ -1537,6 +1574,11 @@ [email protected]:
|
|||||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||||
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
|
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
|
||||||
|
|
||||||
|
pathe@^1.1.0, pathe@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.1.tgz#1dd31d382b974ba69809adc9a7a347e65d84829a"
|
||||||
|
integrity sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==
|
||||||
|
|
||||||
peek-readable@^5.0.0:
|
peek-readable@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-5.0.0.tgz#7ead2aff25dc40458c60347ea76cfdfd63efdfec"
|
resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-5.0.0.tgz#7ead2aff25dc40458c60347ea76cfdfd63efdfec"
|
||||||
@@ -1547,6 +1589,15 @@ picocolors@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||||
|
|
||||||
|
pkg-types@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.0.3.tgz#988b42ab19254c01614d13f4f65a2cfc7880f868"
|
||||||
|
integrity sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==
|
||||||
|
dependencies:
|
||||||
|
jsonc-parser "^3.2.0"
|
||||||
|
mlly "^1.2.0"
|
||||||
|
pathe "^1.1.0"
|
||||||
|
|
||||||
postcss-value-parser@^4.0.2, postcss-value-parser@^4.2.0:
|
postcss-value-parser@^4.0.2, postcss-value-parser@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||||
@@ -1561,6 +1612,15 @@ postcss@^8.1.10, postcss@^8.4.23:
|
|||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
source-map-js "^1.0.2"
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
|
postcss@^8.4.25:
|
||||||
|
version "8.4.26"
|
||||||
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.26.tgz#1bc62ab19f8e1e5463d98cf74af39702a00a9e94"
|
||||||
|
integrity sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==
|
||||||
|
dependencies:
|
||||||
|
nanoid "^3.3.6"
|
||||||
|
picocolors "^1.0.0"
|
||||||
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
preact@^10.0.0:
|
preact@^10.0.0:
|
||||||
version "10.15.1"
|
version "10.15.1"
|
||||||
resolved "https://registry.yarnpkg.com/preact/-/preact-10.15.1.tgz#a1de60c9fc0c79a522d969c65dcaddc5d994eede"
|
resolved "https://registry.yarnpkg.com/preact/-/preact-10.15.1.tgz#a1de60c9fc0c79a522d969c65dcaddc5d994eede"
|
||||||
@@ -1631,6 +1691,13 @@ rollup@^3.21.0:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.2"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
|
rollup@^3.25.2:
|
||||||
|
version "3.26.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.26.2.tgz#2e76a37606cb523fc9fef43e6f59c93f86d95e7c"
|
||||||
|
integrity sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
[email protected], safe-buffer@~5.2.0:
|
[email protected], safe-buffer@~5.2.0:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
@@ -1790,6 +1857,11 @@ typescript@^5.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274"
|
||||||
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
|
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
|
||||||
|
|
||||||
|
ufo@^1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.1.2.tgz#d0d9e0fa09dece0c31ffd57bd363f030a35cfe76"
|
||||||
|
integrity sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==
|
||||||
|
|
||||||
undici@^5.22.0:
|
undici@^5.22.0:
|
||||||
version "5.22.1"
|
version "5.22.1"
|
||||||
resolved "https://registry.yarnpkg.com/undici/-/undici-5.22.1.tgz#877d512effef2ac8be65e695f3586922e1a57d7b"
|
resolved "https://registry.yarnpkg.com/undici/-/undici-5.22.1.tgz#877d512effef2ac8be65e695f3586922e1a57d7b"
|
||||||
@@ -1830,6 +1902,29 @@ vary@~1.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||||
|
|
||||||
|
vite-node@^0.33.0:
|
||||||
|
version "0.33.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.33.0.tgz#c6a3a527e0b8090da7436241bc875760ae0eef28"
|
||||||
|
integrity sha512-19FpHYbwWWxDr73ruNahC+vtEdza52kA90Qb3La98yZ0xULqV8A5JLNPUff0f5zID4984tW7l3DH2przTJUZSw==
|
||||||
|
dependencies:
|
||||||
|
cac "^6.7.14"
|
||||||
|
debug "^4.3.4"
|
||||||
|
mlly "^1.4.0"
|
||||||
|
pathe "^1.1.1"
|
||||||
|
picocolors "^1.0.0"
|
||||||
|
vite "^3.0.0 || ^4.0.0"
|
||||||
|
|
||||||
|
"vite@^3.0.0 || ^4.0.0":
|
||||||
|
version "4.4.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/vite/-/vite-4.4.4.tgz#b76e6049c0e080cb54e735ad2d18287753752118"
|
||||||
|
integrity sha512-4mvsTxjkveWrKDJI70QmelfVqTm+ihFAb6+xf4sjEU2TmUCTlVX87tmg/QooPEMQb/lM9qGHT99ebqPziEd3wg==
|
||||||
|
dependencies:
|
||||||
|
esbuild "^0.18.10"
|
||||||
|
postcss "^8.4.25"
|
||||||
|
rollup "^3.25.2"
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
vite@^4.3.9:
|
vite@^4.3.9:
|
||||||
version "4.3.9"
|
version "4.3.9"
|
||||||
resolved "https://registry.yarnpkg.com/vite/-/vite-4.3.9.tgz#db896200c0b1aa13b37cdc35c9e99ee2fdd5f96d"
|
resolved "https://registry.yarnpkg.com/vite/-/vite-4.3.9.tgz#db896200c0b1aa13b37cdc35c9e99ee2fdd5f96d"
|
||||||
|
|||||||
Reference in new issue
Block a user