From 2f7f2362bbe46d2fe34a3a13d33c2fff4126b20a Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:58:16 -0600 Subject: [PATCH] feat: auction command --- packages/bot/src/commands/auction.ts | 126 ++++++++++++++++++ .../bot/src/events/interactionCreate/index.ts | 2 + packages/bot/src/main.ts | 4 + packages/bot/src/workers/bot.ts | 4 + packages/bot/src/workers/render.ts | 2 + packages/core/lang/en-US.json | 21 +++ packages/core/src/blitz/classes.ts | 5 + packages/core/src/blitz/index.ts | 1 + .../scripts/src/buildAssets/definitions.ts | 2 +- 9 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 packages/bot/src/commands/auction.ts create mode 100644 packages/core/src/blitz/classes.ts diff --git a/packages/bot/src/commands/auction.ts b/packages/bot/src/commands/auction.ts new file mode 100644 index 000000000..eac778a38 --- /dev/null +++ b/packages/bot/src/commands/auction.ts @@ -0,0 +1,126 @@ +import { + BlitzTankClass, + Region, + regionToRegionSubdomain, +} from '@blitzkit/core'; +import { tankDefinitions } from '../core/blitzkit/nonBlockingPromises'; +import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; +import { translator } from '../core/localization/translator'; +import { CommandRegistry } from '../events/interactionCreate'; + +interface Auction { + 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 | null; + next_price_timestamp?: number | null; + } + | { + 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'; +} + +export const auctionCommand = new Promise((resolve) => { + resolve({ + command: createLocalizedCommand('auction', [ + { subcommand: 'available' }, + { subcommand: 'setup' }, + ]), + + async handler(interaction) { + 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); + const seeableTanks = data.results.filter((result) => result.available); + const { t, translate } = translator(interaction.locale); + + const title = `# ${t`bot.commands.auction.subcommands.available.body.title`}`; + const subtitle = `-# ${translate( + 'bot.commands.auction.subcommands.available.body.available', + [`${seeableTanks.length} / ${data.results.length}`], + )}`; + const body = seeableTanks + .map((data, index) => { + const tank = awaitedTankDefinitions.tanks[data.entity!.id]; + + if (!tank) return ''; + + const name = `[${tank.name}]()`; + const next = translate( + 'bot.commands.auction.subcommands.available.body.next', + [ + `<:gold:1317173197082333244> ${data.next_price!.value.toLocaleString( + interaction.locale, + )}`, + ], + ); + + return `${ + index + 1 + }. ${name} <:gold:1317173197082333244> ${data.price!.value.toLocaleString( + interaction.locale, + )}\n-# ${next}`; + }) + .join('\n\n'); + + return `${title}\n${subtitle}\n\n${body}`; + }, + }); +}); diff --git a/packages/bot/src/events/interactionCreate/index.ts b/packages/bot/src/events/interactionCreate/index.ts index 0af7d04be..5d244c8ed 100644 --- a/packages/bot/src/events/interactionCreate/index.ts +++ b/packages/bot/src/events/interactionCreate/index.ts @@ -15,6 +15,7 @@ import { SlashCommandSubcommandsOnlyBuilder, } from 'discord.js'; import { aboutCommand } from '../../commands/about'; +import { auctionCommand } from '../../commands/auction'; import { breakdownCommand } from '../../commands/breakdown'; import { debugCommand } from '../../commands/debug'; import { evolutionCommand } from '../../commands/evolution'; @@ -76,6 +77,7 @@ interface CommandRegistryExplicit extends CommandRegistryBase { export type CommandRegistry = CommandRegistryImplicit | CommandRegistryExplicit; export const COMMANDS_RAW: Promise[] = [ + auctionCommand, permissionsCommand, debugCommand, aboutCommand, diff --git a/packages/bot/src/main.ts b/packages/bot/src/main.ts index 5a2aeb60d..dcfb6a738 100644 --- a/packages/bot/src/main.ts +++ b/packages/bot/src/main.ts @@ -1,8 +1,12 @@ import { manager } from './core/discord/manager'; +console.log('pre manager event listeners and spawn'); + manager .on('shardCreate', (shard) => { console.log(`🟡 Launching shard ${shard.id}`); shard.on('ready', () => console.log(`🟢 Launched shard ${shard.id}`)); }) .spawn(); + +console.log('post manager event listeners and spawn'); diff --git a/packages/bot/src/workers/bot.ts b/packages/bot/src/workers/bot.ts index 4d19375ef..65f3a4dee 100644 --- a/packages/bot/src/workers/bot.ts +++ b/packages/bot/src/workers/bot.ts @@ -6,4 +6,8 @@ console.log(`🟡 Launching bot ${client.shard?.ids[0]}`); registerProcesses(); +console.log(`post register processes on shard ${client.shard?.ids[0]}`); + client.login(assertSecret(import.meta.env.DISCORD_TOKEN)); + +console.log(`post client login on shard ${client.shard?.ids[0]}`); diff --git a/packages/bot/src/workers/render.ts b/packages/bot/src/workers/render.ts index 0950d7028..1838e44ad 100644 --- a/packages/bot/src/workers/render.ts +++ b/packages/bot/src/workers/render.ts @@ -7,3 +7,5 @@ parentPort?.on('message', async (svg: string) => { const png = svgToPng(svg); parentPort?.postMessage(png); }); + +console.log(`post render thread parent port on thread ${threadId}`); diff --git a/packages/core/lang/en-US.json b/packages/core/lang/en-US.json index 4a0551de5..d23c62126 100644 --- a/packages/core/lang/en-US.json +++ b/packages/core/lang/en-US.json @@ -291,6 +291,27 @@ }, "commands": { + "auction": { + "$": "auction", + "description": "Tanks available in the auction", + + "subcommands": { + "available": { + "$": "available", + "description": "Tanks available right now in the auction", + "body": { + "title": "Blitz Auction", + "available": "%s available", + "next": "Next price: %s" + } + }, + "setup": { + "$": "setup", + "description": "Set up a channel to receive auction updates" + } + } + }, + "replay": { "$": "replay", "description": "Display replay results" diff --git a/packages/core/src/blitz/classes.ts b/packages/core/src/blitz/classes.ts new file mode 100644 index 000000000..61a6bd4a6 --- /dev/null +++ b/packages/core/src/blitz/classes.ts @@ -0,0 +1,5 @@ +export type BlitzTankClass = + | 'lightTank' + | 'mediumTank' + | 'heavyTank' + | 'AT-SPG'; diff --git a/packages/core/src/blitz/index.ts b/packages/core/src/blitz/index.ts index aa2aadf58..5304654f2 100644 --- a/packages/core/src/blitz/index.ts +++ b/packages/core/src/blitz/index.ts @@ -1,5 +1,6 @@ export * from './canSplash'; export * from './clans'; +export * from './classes'; export * from './constants'; export * from './equipmentPrice'; export * from './fetchBlitz'; diff --git a/packages/scripts/src/buildAssets/definitions.ts b/packages/scripts/src/buildAssets/definitions.ts index 070aef7b8..d356268bf 100644 --- a/packages/scripts/src/buildAssets/definitions.ts +++ b/packages/scripts/src/buildAssets/definitions.ts @@ -1,6 +1,7 @@ import { Armor, assertSecret, + BlitzTankClass, CamouflageDefinitions, Consumable, ConsumableDefinitions, @@ -70,7 +71,6 @@ const blitzTankFilterDefinitionCategoryToBlitzkit: Record< function vector3TupleToBlitzkit(tuple: Vector3Tuple) { return { x: tuple[0], y: tuple[1], z: tuple[2] } satisfies Vector3; } -type BlitzTankClass = 'lightTank' | 'mediumTank' | 'heavyTank' | 'AT-SPG'; const blitzTankClassToBlitzkit: Record = { lightTank: TankClass.LIGHT, 'AT-SPG': TankClass.TANK_DESTROYER,