Merge branch 'main' into dev

This commit is contained in:
TrèsAbhi committed 2024-02-23 16:05:29 -06:00
commit 23a33c7722
45 files changed
+743 -504

No files matched your search

+8 -1
View File
@@ -4,7 +4,11 @@ import { context } from '../blitzkrieg/context';
import { patientFetch } from '../blitzkrieg/patientFetch';
import regionToRegionSubdomain from './regionToRegionSubdomain';
const ratingsInfoCache: Partial<Record<Region, RatingsInfo>> = {};
export default async function getRatingsInfo(region: Region) {
if (ratingsInfoCache[region]) return ratingsInfoCache[region]!;
const response = await patientFetch(
context === 'website'
? `/api/${region}/ratings/current/info`
@@ -14,6 +18,9 @@ export default async function getRatingsInfo(region: Region) {
undefined,
{ cache: 'no-store' },
);
const data = (await response.json()) as RatingsInfo;
return (await response.json()) as Promise<RatingsInfo>;
ratingsInfoCache[region] = data;
return data;
}
+3 -4
View File
@@ -10,10 +10,9 @@ export default async function getTankStats(region: Region, id: number) {
);
if (tankStats[id] === null) {
throw new UserError('No tank stats available', {
cause:
"This player doesn't have any stats for tanks available. This may not be the player you are looking for.",
});
throw new UserError(
"# No tank stats available\nThis player doesn't have any stats available. This may not be the player you are looking for.",
);
}
return tankStats[id];
+6
View File
@@ -0,0 +1,6 @@
import getRatingsInfo from './getRatingsInfo';
export async function isOnGoingRatingsSeason() {
const ratingsInfo = await getRatingsInfo('com');
return ratingsInfo.detail === undefined;
}
+7 -6
View File
@@ -1,5 +1,6 @@
import { go } from 'fuzzysort';
import { UserError } from '../../hooks/userError';
import markdownEscape from 'markdown-escape';
import {
tankDefinitions,
tanksDefinitionsArray,
@@ -15,9 +16,9 @@ export default async function resolveTankId(tank: string | number) {
});
if (searchResult.length === 0) {
throw new UserError('Tank not found', {
cause: `Could not find tank by the name "${tank}".`,
});
throw new UserError(
`# Tank not found\nCould not find tank by the name "${markdownEscape(`${tank}`)}".`,
);
} else {
return searchResult[0].obj.id;
}
@@ -25,9 +26,9 @@ export default async function resolveTankId(tank: string | number) {
if ((await tankDefinitions)[number]) {
return number;
} else {
throw new UserError('Tank not found', {
cause: `Could not find tank by the ID "${number}".`,
});
throw new UserError(
`# Tank not found\nCould not find tank by the ID "${number}". Try typing the name of the tank instead of a number.`,
);
}
}
}
@@ -1,17 +1,28 @@
import getRatingsInfo from '../blitz/getRatingsInfo';
interface GitHubTrees {
tree: { path: string; url: string }[];
}
let cachedLatestArchivedSeasonNumber: number | null = null;
export async function getArchivedLatestSeasonNumber() {
if (cachedLatestArchivedSeasonNumber !== null) {
return cachedLatestArchivedSeasonNumber;
}
const ratingsInfo = await getRatingsInfo('com');
if (ratingsInfo.detail) {
const comURL = (
const regionsURL = (
(await fetch(
'https://api.github.com/repos/tresabhi/blitzkrieg-assets/git/trees/main/regions',
).then((response) => response.json())) as {
tree: { path: string; url: string }[];
}
'https://api.github.com/repos/tresabhi/blitzkrieg-assets/git/trees/main',
).then((response) => response.json())) as GitHubTrees
).tree.find(({ path }) => path === 'regions')!.url;
const comURL = (
(await fetch(regionsURL).then((response) =>
response.json(),
)) as GitHubTrees
).tree.find(({ path }) => path === 'com')!.url;
const ratingsURL = (
(await fetch(comURL).then((response) => response.json())) as {
@@ -20,14 +31,16 @@ export async function getArchivedLatestSeasonNumber() {
).tree[0].url;
const latestSeason = Math.max(
...(
(await fetch(ratingsURL).then((response) => {
response.json();
})) as { tree: { path: string }[] }
).tree.map(({ path }) => parseInt(path)),
(await fetch(ratingsURL).then((response) => response.json())) as {
tree: { path: string }[];
}
).tree.map(({ path }) => Number(path)),
);
return latestSeason;
cachedLatestArchivedSeasonNumber = latestSeason;
} else {
return ratingsInfo.current_season - 1;
cachedLatestArchivedSeasonNumber = ratingsInfo.current_season - 1;
}
return cachedLatestArchivedSeasonNumber;
}
@@ -0,0 +1,25 @@
import {
SlashCommandBuilder,
SlashCommandSubcommandBuilder,
SlashCommandSubcommandGroupBuilder,
} from 'discord.js';
import { encyclopediaInfo } from '../blitz/encyclopediaInfo';
import { addFilterOptions } from './addFilterOptions';
import addPeriodSubCommands from './addPeriodSubCommands';
export default async function addPeriodicFilterOptions<
OptionType extends SlashCommandBuilder | SlashCommandSubcommandGroupBuilder,
>(
option: OptionType,
extra: (
option: SlashCommandSubcommandBuilder,
) => SlashCommandSubcommandBuilder = (option) => option,
): Promise<OptionType> {
const awaitedEncyclopediaInfo = await encyclopediaInfo;
addPeriodSubCommands(option, (option) => {
return addFilterOptions(extra(option), awaitedEncyclopediaInfo);
});
return option;
}
+6 -1
View File
@@ -3,12 +3,17 @@ import { PeriodType } from './addPeriodSubCommands';
export function getCustomPeriodParams(
interaction: ChatInputCommandInteraction,
forcedNonCustomPeriod = false,
) {
if ((interaction.options.getSubcommand() as PeriodType) === 'custom')
if (
!forcedNonCustomPeriod &&
(interaction.options.getSubcommand() as PeriodType) === 'custom'
) {
return {
start: interaction.options.getInteger('start', true),
end: interaction.options.getInteger('end', true),
};
}
return undefined;
}
+4 -3
View File
@@ -1,4 +1,5 @@
import { ChatInputCommandInteraction } from 'discord.js';
import markdownEscape from 'markdown-escape';
import { Region } from '../../constants/regions';
import { UserError } from '../../hooks/userError';
import searchClansAcrossRegions from '../blitz/searchClansAcrossRegions';
@@ -18,9 +19,9 @@ export default async function resolveClanFromCommand(
if (accounts[0]) {
return { region: accounts[0].region, id: accounts[0].clan_id };
} else {
throw new UserError('Could not find clan', {
cause: `I couldn't find clan \`${clan}\`. Try selecting a username from the search result.`,
});
throw new UserError(
`# Could not find clan\nCouldn't find "${markdownEscape(clan)}". Try selecting a clan from the search result.`,
);
}
}
}
+4 -1
View File
@@ -20,11 +20,14 @@ export interface ResolvedPeriod {
export default function resolvePeriodFromCommand(
region: Region,
interaction: ChatInputCommandInteraction<CacheType>,
forcedPeriod?: PeriodType,
) {
let name: string;
let start: number;
let end: number;
const periodSubcommand = interaction.options.getSubcommand() as PeriodType;
const periodSubcommand = forcedPeriod
? forcedPeriod
: (interaction.options.getSubcommand() as PeriodType);
if (periodSubcommand === 'custom') {
const startOption = interaction.options.getInteger('start', true);
+6 -6
View File
@@ -34,11 +34,11 @@ export default async function resolvePlayerFromCommand(
id: accounts[0].account_id,
} satisfies ResolvedPlayer;
} else {
throw new UserError('Could not find user', {
cause: `I couldn't find user "${markdownEscape(
throw new UserError(
`# Could not find user\nI couldn't find user "${markdownEscape(
commandUsername,
)}". Try picking an user from the search result, typing in a valid username, or using the \`/link\` command.`,
});
);
}
}
} else {
@@ -47,9 +47,9 @@ export default async function resolvePlayerFromCommand(
if (account) {
return { region: account.region, id: account.blitz };
} else {
throw new UserError('Use the `/link` command', {
cause: 'Link your Blitz and Discord accounts to get started.',
});
throw new UserError(
"# I don't know who you are\nUse the `/link` command to get started.",
);
}
}
}
+13 -3
View File
@@ -4,12 +4,19 @@ import {
emptyIndividualTankStats,
} from '../../types/tanksStats';
export function deltaTankStats(a: NormalizedTankStats, b: NormalizedTankStats) {
export function deltaTankStats(
a: NormalizedTankStats,
b: NormalizedTankStats,
time?: number,
) {
const bTanks = Object.keys(b);
const changedTanks = bTanks.filter((id) => {
return (
a[id as unknown as number]?.all.battles !==
b[id as unknown as number].all.battles
b[id as unknown as number].all.battles &&
(time === undefined
? true
: b[id as unknown as number].last_battle_time > time)
);
});
const diff = changedTanks.map((id) => {
@@ -24,7 +31,10 @@ export function deltaTankStats(a: NormalizedTankStats, b: NormalizedTankStats) {
in_garage: bTank.in_garage,
max_xp: Math.max(aTank.max_xp, bTank.max_xp),
in_garage_updated: bTank.in_garage_updated,
last_battle_time: bTank.last_battle_time - aTank.last_battle_time,
last_battle_time: Math.max(
bTank.last_battle_time,
aTank.last_battle_time,
),
mark_of_mastery: bTank.mark_of_mastery,
tank_id: bTank.tank_id,