Compare commits

...
2 Commits
Author SHA1 Message Date
TresAbhi 04086f31b9 fix: spelling 2023-09-07 03:25:07 +00:00
TresAbhi 7037aa9c3b feat: 1.12.5 2023-09-07 03:24:07 +00:00
7 changed files with 113 additions and 110 deletions

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
# Blitzkrieg 1.12.4
Some patch up work
## Changes
- `/clan-event` now is more legible and comes with an approximation warning
## Fixed
- `/clan-event` now uses a more optimized way of fetching large data
- This should fix the issue where too many people using the command broke it
+63 -76
View File
@@ -1,9 +1,16 @@
import { SlashCommandBuilder } from 'discord.js'; import { SlashCommandBuilder } from 'discord.js';
import markdownEscape from 'markdown-escape'; import markdownEscape from 'markdown-escape';
import getWargamingResponse from '../core/blitz/getWargamingResponse';
import { PlayerHistoriesRaw } from '../core/blitzstars/getPlayerHistories';
import addClanChoices from '../core/discord/addClanChoices';
import autocompleteClan from '../core/discord/autocompleteClan'; import autocompleteClan from '../core/discord/autocompleteClan';
import embedInfo from '../core/discord/embedInfo'; import embedWarning from '../core/discord/embedWarning';
import resolveClanFromCommand from '../core/discord/resolveClanFromCommand';
import { secrets } from '../core/node/secrets'; import { secrets } from '../core/node/secrets';
import { CommandRegistry } from '../events/interactionCreate'; import { CommandRegistry } from '../events/interactionCreate';
import { AccountAchievements } from '../types/accountAchievements';
import { AccountInfo } from '../types/accountInfo';
import { ClanInfo } from '../types/clanInfo';
const DEFAULT_THRESHOLD = 7; const DEFAULT_THRESHOLD = 7;
@@ -15,92 +22,72 @@ export const clanEventCommand: CommandRegistry = {
command: new SlashCommandBuilder() command: new SlashCommandBuilder()
.setName('clan-event') .setName('clan-event')
.setDescription('Lists all inactive players') .setDescription('Lists all inactive players')
.addStringOption((option) => .addStringOption(addClanChoices),
option
.setName('clan')
.setDescription('The clan name or tag you are checking')
.setRequired(true),
),
async handler(interaction) { async handler(interaction) {
const REGION = 'com'; const { region, id } = await resolveClanFromCommand(interaction);
const CLAN_SEARCH = interaction.options.getString('clan', true); const clan = (
await getWargamingResponse<ClanInfo>(
const { `https://api.wotblitz.${region}/wotb/clans/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&clan_id=${id}`,
clan_id,
name: clan_name,
tag: clan_tag,
} = await fetch(
`https://api.wotblitz.${REGION}/wotb/clans/list/?application_id=${secrets.WARGAMING_APPLICATION_ID}&search=${CLAN_SEARCH}`,
) )
.then((response) => response.json()) )[id];
.then(({ data }) => data[0]); const memberIds = clan.members_ids.join(',');
const memebers = await fetch( const [players, achievements, previousJointVictories] = await Promise.all([
`https://api.wotblitz.${REGION}/wotb/clans/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&clan_id=${clan_id}`, getWargamingResponse<AccountInfo>(
) `https://api.wotblitz.${region}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${memberIds}`,
.then((response) => response.json()) ),
.then(({ data }) => data[clan_id].members_ids); getWargamingResponse<AccountAchievements>(
const stats = await Promise.all( `https://api.wotblitz.${region}/wotb/account/achievements/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${memberIds}`,
memebers.map(async (id, index) => { ),
await new Promise((resolve) => setTimeout(resolve, index * 200)); Promise.all(
clan.members_ids.map((id) =>
const [yesterdayPlatoonWins, name, todayPlatoonWins] =
await Promise.all([
fetch(`https://www.blitzstars.com/api/playerstats/${id}`) fetch(`https://www.blitzstars.com/api/playerstats/${id}`)
.then((response) => response.json()) .then((response) => response.json() as Promise<PlayerHistoriesRaw>)
.then((data) => data[0]?.achievements.jointVictoryCount), .then((data) => ({
fetch(
`https://api.wotblitz.${REGION}/wotb/account/info/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
)
.then((response) => response.json())
.then(({ data }) => data[id].nickname),
fetch(
`https://api.wotblitz.${REGION}/wotb/account/achievements/?application_id=${secrets.WARGAMING_APPLICATION_ID}&account_id=${id}`,
)
.then((response) => response.json())
.then(({ data }) => data[id].max_series.jointVictory),
]);
return {
id, id,
name, jointVictory: data[0]?.achievements.jointVictoryCount as
yesterdayPlatoonWins, | number
todayPlatoonWins, | undefined,
}; })),
),
).then((data) =>
data.reduce<Record<number, number | undefined>>(
(accumulator, value) => ({
...accumulator,
[value.id]: value.jointVictory,
}), }),
); {},
),
return embedInfo( ),
`Estimation of ${clan_name} [${clan_tag}]'s total platoon wins today: ${( ]);
stats.reduce( const jointVictories = clan.members_ids.map((id) => ({
(accumulator, player) => id,
accumulator + joinVictory:
(player.yesterdayPlatoonWins === undefined previousJointVictories[id] === undefined
? 0 ? 0
: player.todayPlatoonWins - player.yesterdayPlatoonWins), : achievements[id].max_series.jointVictory -
previousJointVictories[id]!,
}));
return [
`# ${clan.name} [${clan.tag}]'s platoon wins today: ${(
jointVictories.reduce(
(accumulator, { joinVictory }) => accumulator + joinVictory,
0, 0,
) / 2 ) / 2
).toFixed(0)}`, ).toFixed(0)}\n${jointVictories
stats .sort((a, b) => b.joinVictory - a.joinVictory)
.sort(
(playerA, playerB) =>
(playerB.yesterdayPlatoonWins === undefined
? 0
: playerB.todayPlatoonWins - playerB.yesterdayPlatoonWins) -
(playerA.yesterdayPlatoonWins === undefined
? 0
: playerA.todayPlatoonWins - playerA.yesterdayPlatoonWins),
)
.map( .map(
(player) => ({ id, joinVictory }) =>
`${markdownEscape(player.name)}: ${ `- ${markdownEscape(players[id].nickname)}: ${joinVictory}`,
player.yesterdayPlatoonWins === undefined
? 0
: player.todayPlatoonWins - player.yesterdayPlatoonWins
}`,
) )
.join('\n'), .join('\n')}`,
);
embedWarning(
'This is an approximation!',
'Wargaming provides use with little to no information about platoons. Platooning with mixed clans may inflate the number and platooning in non-regular battles may deflate.',
),
];
}, },
autocomplete: autocompleteClan, autocomplete: autocompleteClan,
+4 -5
View File
@@ -3,10 +3,10 @@ import GenericStats from '../components/GenericStats';
import NoData, { NoDataType } from '../components/NoData'; import NoData, { NoDataType } from '../components/NoData';
import TitleBar from '../components/TitleBar'; import TitleBar from '../components/TitleBar';
import Wrapper from '../components/Wrapper'; import Wrapper from '../components/Wrapper';
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 resolveClanFromCommand from '../core/discord/resolveClanFromCommand';
import { secrets } from '../core/node/secrets'; 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';
@@ -33,19 +33,18 @@ export const inactiveCommand: CommandRegistry = {
), ),
async handler(interaction) { async handler(interaction) {
const clanName = interaction.options.getString('clan')!; const { region, id } = await resolveClanFromCommand(interaction);
const { server, id } = await getBlitzClan(clanName);
const threshold = const threshold =
interaction.options.getNumber('threshold')! ?? DEFAULT_THRESHOLD; interaction.options.getNumber('threshold')! ?? DEFAULT_THRESHOLD;
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=${secrets.WARGAMING_APPLICATION_ID}&clan_id=${id}`, `https://api.wotblitz.${region}/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=${ `https://api.wotblitz.${region}/wotb/account/info/?application_id=${
secrets.WARGAMING_APPLICATION_ID secrets.WARGAMING_APPLICATION_ID
}&account_id=${memberIds.join(',')}`, }&account_id=${memberIds.join(',')}`,
); );
-22
View File
@@ -1,22 +0,0 @@
import { Region } from '../../constants/regions';
import { serverAndIdPattern } from '../discord/resolvePlayerFromCommand';
import throwError from '../node/throwError';
import listClans from './listClans';
export default async function getBlitzClan(clan: string) {
if (serverAndIdPattern.test(clan)) {
const [server, accountId] = clan.split('/');
return { server: server as Region, id: Number(accountId) };
} else {
const accounts = await listClans(clan);
if (accounts[0]) {
return { server: accounts[0].server, id: accounts[0].clan_id };
} else {
throw throwError(
'Could not find clan',
`I couldn't find clan \`${clan}\`. Try selecting a username from the search result.`,
);
}
}
}
+5 -5
View File
@@ -3,8 +3,8 @@ import { Clan, ClanList } from '../../types/clanList';
import { secrets } from '../node/secrets'; import { secrets } from '../node/secrets';
import getWargamingResponse from './getWargamingResponse'; import getWargamingResponse from './getWargamingResponse';
export type ClanListWithServer = (Clan & { export type ClanListWithRegion = (Clan & {
server: 'com' | 'eu' | 'asia'; region: 'com' | 'eu' | 'asia';
})[]; })[];
export default async function listClans(search: string, limit = 9) { export default async function listClans(search: string, limit = 9) {
@@ -21,7 +21,7 @@ export default async function listClans(search: string, limit = 9) {
value && value &&
value.map((account) => ({ value.map((account) => ({
...account, ...account,
server: 'com' as Region, region: 'com' as Region,
})), })),
), ),
getWargamingResponse<ClanList>( getWargamingResponse<ClanList>(
@@ -31,7 +31,7 @@ export default async function listClans(search: string, limit = 9) {
value && value &&
value.map((account) => ({ value.map((account) => ({
...account, ...account,
server: 'eu' as Region, region: 'eu' as Region,
})), })),
), ),
getWargamingResponse<ClanList>( getWargamingResponse<ClanList>(
@@ -41,7 +41,7 @@ export default async function listClans(search: string, limit = 9) {
value && value &&
value.map((account) => ({ value.map((account) => ({
...account, ...account,
server: 'asia' as Region, region: 'asia' as Region,
})), })),
), ),
]) ])
+2 -2
View File
@@ -19,8 +19,8 @@ export default async function autocompleteClan(
? players.map( ? players.map(
(player) => (player) =>
({ ({
name: `${player.name} (${REGION_NAMES[player.server]})`, name: `${player.name} (${REGION_NAMES[player.region]})`,
value: `${player.server}/${player.clan_id}`, value: `${player.region}/${player.clan_id}`,
}) satisfies ApplicationCommandOptionChoiceData<string>, }) satisfies ApplicationCommandOptionChoiceData<string>,
) )
: [], : [],
@@ -0,0 +1,27 @@
import { ChatInputCommandInteraction } from 'discord.js';
import { Region } from '../../constants/regions';
import listClans from '../blitz/listClans';
import throwError from '../node/throwError';
import { serverAndIdPattern } from './resolvePlayerFromCommand';
export default async function resolveClanFromCommand(
interaction: ChatInputCommandInteraction,
) {
const clan = interaction.options.getString('clan', true);
if (serverAndIdPattern.test(clan)) {
const [server, accountId] = clan.split('/');
return { region: server as Region, id: Number(accountId) };
} else {
const accounts = await listClans(clan);
if (accounts[0]) {
return { region: accounts[0].region, id: accounts[0].clan_id };
} else {
throw throwError(
'Could not find clan',
`I couldn't find clan \`${clan}\`. Try selecting a username from the search result.`,
);
}
}
}