fix: more imports

This commit is contained in:
TrèsAbhi committed 2024-09-08 10:11:24 -05:00
1 parent 25cfb7db74
commit 4f24db0956
182 files changed
+456 -452

No files matched your search

+88
View File
@@ -0,0 +1,88 @@
import { assertSecret, EventManager, Region } from '@blitzkit/core';
import { patientFetch } from '../../../website/src/core/blitzkit/patientFetch';
const RETRY_ERRORS = ['REQUEST_LIMIT_EXCEEDED', 'SOURCE_NOT_AVAILABLE'];
export const retryAbleBlitzFetchEvent = new EventManager();
export const blitzFetchQueueAvailableEvent = new EventManager();
type BlitzResponse<Data extends object> =
| {
status: 'error';
error: { field: string; message: string; code: 402; value: null };
}
| {
status: 'ok';
data: Data;
};
const MAX_CALLS_PER_SECOND = 10;
const queue: { url: string; resolve: (data: object) => void }[] = [];
let inProgress = 0;
function decrement() {
inProgress--;
blitzFetchQueueAvailableEvent.emit(undefined);
manageQueue();
}
async function manageQueue() {
if (queue.length > 0 && inProgress < MAX_CALLS_PER_SECOND) {
inProgress++;
const timeout = setTimeout(decrement, 1000);
const request = queue.shift()!;
const data = (await patientFetch(request.url)
.then((response) => response.json())
.catch((error) => ({ status: 'error', error }))) as BlitzResponse<
typeof request.resolve
>;
if (data.status === 'ok') {
request.resolve(data.data);
} else {
if (RETRY_ERRORS.includes(data.error.message)) {
retryAbleBlitzFetchEvent.emit(undefined);
clearTimeout(timeout);
setTimeout(() => {
queue.push(request);
decrement();
}, 1000 / MAX_CALLS_PER_SECOND);
} else {
clearTimeout(timeout);
decrement();
throw new Error(`Wargaming response error status: "${data.status}"`, {
cause: `Message: "${data.error.message}"\nURL: "${request.url}"`,
});
}
}
}
}
export type FetchBlitzParams = Record<string, string | number | undefined>;
export function fetchBlitz<Data extends object>(
region: Region,
path: string,
params: FetchBlitzParams = {},
) {
return new Promise<Data>((resolve) => {
queue.push({
url: `https://api.wotblitz.${region}/wotb/${path}/?${Object.entries({
application_id: assertSecret(
process.env.NEXT_PUBLIC_WARGAMING_APPLICATION_ID,
),
...params,
})
.filter(([_, value]) => value !== undefined)
.map(([key, value]) => `${key}=${encodeURIComponent(value!)}`)
.join('&')}`,
resolve(data) {
resolve(data as Data);
},
});
manageQueue();
});
}
@@ -0,0 +1,5 @@
import { LEAGUES } from '@blitzkit/core';
export function getLeagueFromScore(score: number) {
return LEAGUES.find(({ minScore }) => score >= minScore)!;
}
+24
View File
@@ -0,0 +1,24 @@
import { RatingInfo, Region } from '@blitzkit/core';
import { regionToRegionSubdomain } from '../../../website/src/core/blitz/regionToRegionSubdomain';
import { context } from '../../../website/src/core/blitzkit/context';
import { patientFetch } from '../../../website/src/core/blitzkit/patientFetch';
const cache: Partial<Record<Region, RatingInfo>> = {};
export async function getRatingInfo(region: Region) {
if (cache[region]) return cache[region]!;
const response = await patientFetch(
context === 'website'
? `/api/${region}/rating/current/info`
: `https://${regionToRegionSubdomain(
region,
)}.wotblitz.com/en/api/rating-leaderboards/season/`,
undefined,
);
const data = (await response.json()) as RatingInfo;
cache[region] = data;
return data;
}
+5
View File
@@ -1,10 +1,15 @@
export * from './clans';
export * from './constants';
export * from './equipmentPrice';
export * from './fetchBlitz';
export * from './getLeagueFromScore';
export * from './getRatingInfo';
export * from './idToRegion';
export * from './nations';
export * from './permanentSkills';
export * from './rating';
export * from './regions';
export * from './regionSubdomainToRegion';
export * from './resolveNearPenetration';
export * from './searchClansAcrossRegions';
export * from './searchPlayersAcrossRegions';
@@ -0,0 +1,5 @@
import { Region, RegionSubdomain } from '@blitzkit/core';
export function regionSubdomainToRegion(regionDomain: RegionSubdomain): Region {
return regionDomain === 'na' ? 'com' : regionDomain;
}
@@ -1,11 +1,7 @@
import { Region } from '@blitzkit/core';
import fetchBlitz from '../../../website/src/core/blitz/fetchBlitz';
import { fetchBlitz, Region } from '@blitzkit/core';
import { ClanList } from './clans';
export default async function searchClansAcrossRegions(
search: string,
limit = 25,
) {
export async function searchClansAcrossRegions(search: string, limit = 25) {
const trimmed = search.trim();
if (trimmed.length < 3 && trimmed.length > 100) return [];
const normalizedLimit = Math.floor(limit / 3);
@@ -0,0 +1,2 @@
export const usernamePattern = /^[a-zA-Z0-9_]{3,24}$/;
export const usernamePatternWithoutPosition = /[a-zA-Z0-9_]{3,24}/;
@@ -0,0 +1,61 @@
import { Region } from '@blitzkit/core';
import { fetchBlitz } from '@blitzkit/core/src/blitz/fetchBlitz';
import { usernamePattern } from './constants';
export interface AccountListItem {
nickname: string;
account_id: number;
}
export type AccountList = AccountListItem[];
export type AccountListWithServer = (AccountListItem & {
region: Region;
})[];
export async function searchPlayersAcrossRegions(search: string, limit = 25) {
const trimmedSearch = search.trim();
const normalizedLimit = Math.floor(limit / 3);
if (usernamePattern.test(trimmedSearch)) {
return (
await Promise.all([
fetchBlitz<AccountList>('com', 'account/list', {
search,
limit: normalizedLimit,
}).then(
(value) =>
value &&
value.map((account) => ({
...account,
region: 'com' as Region,
})),
),
fetchBlitz<AccountList>('eu', 'account/list', {
search,
limit: normalizedLimit,
}).then(
(value) =>
value &&
value.map((account) => ({
...account,
region: 'eu' as Region,
})),
),
fetchBlitz<AccountList>('asia', 'account/list', {
search,
limit: normalizedLimit,
}).then(
(value) =>
value &&
value.map((account) => ({
...account,
region: 'asia' as Region,
})),
),
])
)
.filter(Boolean)
.flat() as AccountListWithServer;
} else {
return [] as AccountListWithServer;
}
}