mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
feat: start on amending slugs
This commit is contained in:
1 parent
dd0b2bade7
commit
3d69d464f5
5 files changed
+38
-177
No files matched your search
Vendored
+1
@@ -86,6 +86,7 @@
|
|||||||
"Fullscreen",
|
"Fullscreen",
|
||||||
"fullstats",
|
"fullstats",
|
||||||
"fuzzysort",
|
"fuzzysort",
|
||||||
|
"gamemode",
|
||||||
"gameplay",
|
"gameplay",
|
||||||
"glsl",
|
"glsl",
|
||||||
"GLTF",
|
"GLTF",
|
||||||
|
|||||||
@@ -1,144 +0,0 @@
|
|||||||
import {
|
|
||||||
BlitzTankClass,
|
|
||||||
Region,
|
|
||||||
regionToRegionSubdomain,
|
|
||||||
} from '@blitzkit/core';
|
|
||||||
import { literals } from '@blitzkit/i18n';
|
|
||||||
import { tankDefinitions } from '../core/blitzkit/nonBlockingPromises';
|
|
||||||
import { chunkLines } from '../core/discord/chunkLines';
|
|
||||||
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
|
||||||
import { translator } from '../core/localization/translator';
|
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
|
||||||
|
|
||||||
type Auction = null | {
|
|
||||||
count: number;
|
|
||||||
has_next: boolean;
|
|
||||||
results: Result[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type Result =
|
|
||||||
| {
|
|
||||||
id?: number;
|
|
||||||
type: 'vehicle';
|
|
||||||
countable?: boolean;
|
|
||||||
entity?: Entity;
|
|
||||||
initial_count: number;
|
|
||||||
current_count: number;
|
|
||||||
saleable?: boolean;
|
|
||||||
available_from?: Date;
|
|
||||||
available_before?: Date;
|
|
||||||
price?: Price;
|
|
||||||
next_price: Price | null;
|
|
||||||
available: true;
|
|
||||||
display?: boolean;
|
|
||||||
next_price_datetime: Date;
|
|
||||||
next_price_timestamp: number;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
available: false;
|
|
||||||
type: 'vehicle';
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Entity {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
nation: string;
|
|
||||||
subnation: string;
|
|
||||||
use_subnation_flag: boolean;
|
|
||||||
type_slug: BlitzTankClass;
|
|
||||||
level: number;
|
|
||||||
roman_level: string;
|
|
||||||
user_string: string;
|
|
||||||
image_url: string;
|
|
||||||
preview_image_url: string;
|
|
||||||
is_premium: boolean;
|
|
||||||
is_collectible: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Price {
|
|
||||||
currency: Currency;
|
|
||||||
value: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Currency {
|
|
||||||
name: 'gold';
|
|
||||||
count: number;
|
|
||||||
title: 'Gold';
|
|
||||||
image_url: string;
|
|
||||||
sizes: unknown;
|
|
||||||
type: 'currency';
|
|
||||||
}
|
|
||||||
|
|
||||||
const WARNING_COUNT = 500;
|
|
||||||
|
|
||||||
export const auctionCommand = new Promise<CommandRegistry>((resolve) => {
|
|
||||||
resolve({
|
|
||||||
command: createLocalizedCommand('auction'),
|
|
||||||
|
|
||||||
async handler(interaction) {
|
|
||||||
const { strings } = translator(interaction.locale);
|
|
||||||
const awaitedTankDefinitions = await tankDefinitions;
|
|
||||||
const region: Region = 'com';
|
|
||||||
const pageSize = 80;
|
|
||||||
const saleable = true;
|
|
||||||
const data = await fetch(
|
|
||||||
`https://${regionToRegionSubdomain(
|
|
||||||
region,
|
|
||||||
)}.wotblitz.com/en/api/events/items/auction/?page_size=${
|
|
||||||
pageSize
|
|
||||||
}&type[]=vehicle&saleable=${saleable}`,
|
|
||||||
).then((response) => response.json() as Promise<Auction>);
|
|
||||||
|
|
||||||
if (data === null) {
|
|
||||||
return strings.bot.commands.auction.errors.no_auction;
|
|
||||||
}
|
|
||||||
|
|
||||||
const saleableTanks = data.results.filter((result) => result.available);
|
|
||||||
const nextPricesTimestamp = saleableTanks[0].next_price_timestamp;
|
|
||||||
|
|
||||||
const title = `# ${strings.bot.commands.auction.body.title}`;
|
|
||||||
const subtitle = `${literals(strings.bot.commands.auction.body.subtitle, [
|
|
||||||
`${saleableTanks.length} / ${data.results.length}`,
|
|
||||||
`<t:${nextPricesTimestamp}:R>`,
|
|
||||||
'<https://wotblitz.com/auction/>',
|
|
||||||
])}`;
|
|
||||||
const body = saleableTanks.map((data, index) => {
|
|
||||||
const tank = awaitedTankDefinitions.tanks[data.entity!.id];
|
|
||||||
|
|
||||||
if (!tank) return '';
|
|
||||||
|
|
||||||
const name = `[${tank.name}](<https://blitzkit.app/tanks/${
|
|
||||||
tank.slug
|
|
||||||
}>)`;
|
|
||||||
const next =
|
|
||||||
data.next_price === null
|
|
||||||
? ''
|
|
||||||
: `\n-# ${literals(strings.bot.commands.auction.body.next, [
|
|
||||||
`<:gold:1317173197082333244> ${data.next_price.value.toLocaleString(
|
|
||||||
interaction.locale,
|
|
||||||
)}`,
|
|
||||||
])}`;
|
|
||||||
const available = literals(
|
|
||||||
strings.bot.commands.auction.body.available,
|
|
||||||
[
|
|
||||||
data.current_count.toLocaleString(interaction.locale),
|
|
||||||
data.initial_count.toLocaleString(interaction.locale),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
const isOut = data.current_count === 0;
|
|
||||||
const outString = isOut ? '~~' : '';
|
|
||||||
const isLow = data.current_count <= WARNING_COUNT;
|
|
||||||
|
|
||||||
return `${index + 1}. ${
|
|
||||||
outString
|
|
||||||
}${name} <:gold:1317173197082333244> ${data.price!.value.toLocaleString(
|
|
||||||
interaction.locale,
|
|
||||||
)}${outString}\n-#${isLow ? ' ‼️ ' : ' '}${available}${isOut ? '' : next}`;
|
|
||||||
});
|
|
||||||
const header = `${title}\n${subtitle}`;
|
|
||||||
const lines = [header, ...body];
|
|
||||||
|
|
||||||
return chunkLines(lines, '\n\n');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,44 +1,44 @@
|
|||||||
import { getAccountInfo, getClanInfo } from '@blitzkit/core';
|
import { getAccountInfo, getClanInfo } from "@blitzkit/core";
|
||||||
import { literals } from '@blitzkit/i18n';
|
import { literals } from "@blitzkit/i18n";
|
||||||
import { Locale } from 'discord.js';
|
import { Locale } from "discord.js";
|
||||||
import { CommandWrapper } from '../components/CommandWrapper';
|
import { CommandWrapper } from "../components/CommandWrapper";
|
||||||
import { GenericStats } from '../components/GenericStats';
|
import { GenericStats } from "../components/GenericStats";
|
||||||
import { NoData } from '../components/NoData';
|
import { NoData } from "../components/NoData";
|
||||||
import { TitleBar } from '../components/TitleBar';
|
import { TitleBar } from "../components/TitleBar";
|
||||||
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 { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
|
||||||
import { localizationObject } from '../core/discord/localizationObject';
|
import { localizationObject } from "../core/discord/localizationObject";
|
||||||
import { resolveClanFromCommand } from '../core/discord/resolveClanFromCommand';
|
import { resolveClanFromCommand } from "../core/discord/resolveClanFromCommand";
|
||||||
import { translator } from '../core/localization/translator';
|
import { translator } from "../core/localization/translator";
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from "../events/interactionCreate";
|
||||||
|
|
||||||
const DEFAULT_THRESHOLD = 7;
|
const DEFAULT_THRESHOLD = 7;
|
||||||
|
|
||||||
export const inactiveCommand = new Promise<CommandRegistry>((resolve) => {
|
export const inactiveCommand = new Promise<CommandRegistry>((resolve) => {
|
||||||
resolve({
|
resolve({
|
||||||
command: createLocalizedCommand('inactive')
|
command: createLocalizedCommand("inactive")
|
||||||
.addStringOption(addClanChoices)
|
.addStringOption(addClanChoices)
|
||||||
.addNumberOption((option) => {
|
.addNumberOption((option) => {
|
||||||
const { strings } = translator(Locale.EnglishUS);
|
const { strings } = translator(Locale.EnglishUS);
|
||||||
|
|
||||||
return option
|
return option
|
||||||
.setName('threshold')
|
.setName("threshold")
|
||||||
.setNameLocalizations(
|
.setNameLocalizations(
|
||||||
localizationObject(
|
localizationObject(
|
||||||
(strings) => strings.bot.commands.inactive.options.threshold.name,
|
(strings) => strings.bot.commands.inactive.options.threshold.name,
|
||||||
undefined,
|
undefined,
|
||||||
true,
|
true
|
||||||
),
|
)
|
||||||
)
|
)
|
||||||
.setDescription(
|
.setDescription(
|
||||||
strings.bot.commands.inactive.options.threshold.description,
|
strings.bot.commands.inactive.options.threshold.description
|
||||||
)
|
)
|
||||||
.setDescriptionLocalizations(
|
.setDescriptionLocalizations(
|
||||||
localizationObject(
|
localizationObject(
|
||||||
(strings) =>
|
(strings) =>
|
||||||
strings.bot.commands.inactive.options.threshold.description,
|
strings.bot.commands.inactive.options.threshold.description
|
||||||
),
|
)
|
||||||
)
|
)
|
||||||
.setMinValue(0);
|
.setMinValue(0);
|
||||||
}),
|
}),
|
||||||
@@ -47,7 +47,7 @@ export const inactiveCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
const { strings } = translator(interaction.locale);
|
const { strings } = translator(interaction.locale);
|
||||||
const { region, id } = await resolveClanFromCommand(interaction);
|
const { region, id } = await resolveClanFromCommand(interaction);
|
||||||
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 clanInfo = await getClanInfo(region, id);
|
const clanInfo = await getClanInfo(region, id);
|
||||||
const accountInfo = await getAccountInfo(region, clanInfo.members_ids);
|
const accountInfo = await getAccountInfo(region, clanInfo.members_ids);
|
||||||
@@ -57,7 +57,7 @@ export const inactiveCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
[
|
[
|
||||||
account.nickname,
|
account.nickname,
|
||||||
(time - account.last_battle_time) / 60 / 60 / 24,
|
(time - account.last_battle_time) / 60 / 60 / 24,
|
||||||
] as [string, number],
|
] as [string, number]
|
||||||
)
|
)
|
||||||
.filter(([, inactiveDays]) => inactiveDays >= threshold)
|
.filter(([, inactiveDays]) => inactiveDays >= threshold)
|
||||||
.sort((a, b) => b[1] - a[1])
|
.sort((a, b) => b[1] - a[1])
|
||||||
@@ -65,10 +65,10 @@ export const inactiveCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
([name, days]) =>
|
([name, days]) =>
|
||||||
[
|
[
|
||||||
name,
|
name,
|
||||||
literals(strings.bot.commands.inactive.body.listing, [
|
literals(strings.bot.commands.inactive.body.listing, {
|
||||||
days.toFixed(0),
|
days: days.toFixed(0),
|
||||||
]),
|
}),
|
||||||
] as [string, string],
|
] as [string, string]
|
||||||
);
|
);
|
||||||
const hasInactiveMembers = inactive.length > 0;
|
const hasInactiveMembers = inactive.length > 0;
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ export const inactiveCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
image={`https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clanInfo.emblem_set_id}.png`}
|
image={`https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clanInfo.emblem_set_id}.png`}
|
||||||
description={`${literals(
|
description={`${literals(
|
||||||
strings.bot.commands.inactive.body.subtitle,
|
strings.bot.commands.inactive.body.subtitle,
|
||||||
[`${threshold}`],
|
{ days: threshold }
|
||||||
)} • ${new Date().toLocaleDateString(interaction.locale)}`}
|
)} • ${new Date().toLocaleDateString(interaction.locale)}`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
export function literals(string: string, literals: string[]) {
|
export function literals(
|
||||||
return literals.reduce((accumulator, literal, index) => {
|
string: string,
|
||||||
return accumulator.replace(`%s${index + 1}`, literal);
|
literals?: Record<string, string | number>
|
||||||
}, string);
|
) {
|
||||||
|
for (const key in literals) {
|
||||||
|
string = string.replaceAll(`{${key}}`, `${literals[key]}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return string;
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,6 @@ const title = literals(strings.website.tools.tankopedia.tank_seo_title, [
|
|||||||
],
|
],
|
||||||
strings.common.tank_class_short[tank.class],
|
strings.common.tank_class_short[tank.class],
|
||||||
"BlitzKit",
|
"BlitzKit",
|
||||||
strings.common.nations[tank.nation as keyof typeof strings.common.nations],
|
|
||||||
]);
|
]);
|
||||||
const url = import.meta.env.SITE + Astro.url.pathname;
|
const url = import.meta.env.SITE + Astro.url.pathname;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user