From 285b4df27b1ffb8b531e179f39b673cf70838a40 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 16:30:11 +0100 Subject: [PATCH 01/48] fix: an issue in how 7d2d reports bans --- packages/lib-gameserver/src/gameservers/7d2d/index.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/lib-gameserver/src/gameservers/7d2d/index.ts b/packages/lib-gameserver/src/gameservers/7d2d/index.ts index 50e93e67b6..d1218eac80 100644 --- a/packages/lib-gameserver/src/gameservers/7d2d/index.ts +++ b/packages/lib-gameserver/src/gameservers/7d2d/index.ts @@ -195,7 +195,7 @@ export class SevenDaysToDie implements IGameServer { async banPlayer(options: BanDTO) { // If no expiresAt is provided, assume 'permanent'. 500 years is pretty long ;) - const expiresAt = options.expiresAt ?? '2521-01-01 00:00:00'; + const expiresAt = options.expiresAt ?? '2521-01-01T00:00:00.000'; const expiresAtDate = DateTime.fromISO(expiresAt); const now = DateTime.local(); @@ -258,10 +258,13 @@ export class SevenDaysToDie implements IGameServer { if (match) { const [, date, gameId, _displayName, reason] = match; const expiresAt = date.replace(' ', 'T') + '.000Z'; // Keep the time in its original form + // If the saved ban isn't saved with EOS, we cannot resolve to gameId, so skip these. + if (!gameId.includes('EOS_')) continue; bans.push( new BanDTO({ - player: new IPlayerReferenceDTO({ - gameId, + player: new IGamePlayer({ + gameId: gameId.replace('EOS_', ''), + epicOnlineServicesId: gameId.replace('EOS_', ''), }), reason, expiresAt, From 55206d495a9c9e3bb9d6cf3f56d8aea470ac6591 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 16:31:09 +0100 Subject: [PATCH 02/48] refactor: ban controller routing --- .../app-api/src/controllers/BanController.ts | 27 +- packages/app-api/src/service/Ban/dto.ts | 4 +- packages/app-api/src/service/Ban/index.ts | 6 +- .../__tests__/BanService.integration.test.ts | 106 +- .../src/generated/.openapi-generator/VERSION | 2 +- packages/lib-apiclient/src/generated/api.ts | 1534 ++++++++--------- packages/lib-apiclient/src/generated/base.ts | 4 +- .../lib-apiclient/src/generated/common.ts | 4 +- .../src/generated/configuration.ts | 4 +- packages/lib-apiclient/src/generated/index.ts | 4 +- packages/lib-apiclient/src/lib/client.ts | 11 - 11 files changed, 848 insertions(+), 858 deletions(-) diff --git a/packages/app-api/src/controllers/BanController.ts b/packages/app-api/src/controllers/BanController.ts index 56667ce2eb..65c0a588a7 100644 --- a/packages/app-api/src/controllers/BanController.ts +++ b/packages/app-api/src/controllers/BanController.ts @@ -3,7 +3,7 @@ import { ITakaroQuery } from '@takaro/db'; import { APIOutput, apiResponse } from '@takaro/http'; import { BanCreateDTO, BanOutputDTO, BanUpdateDTO } from '../service/Ban/dto.js'; import { AuthenticatedRequest, AuthService } from '../service/AuthService.js'; -import { Body, Get, Post, JsonController, UseBefore, Req, Params, Res, Put } from 'routing-controllers'; +import { Body, Get, Post, JsonController, UseBefore, Req, Params, Res, Put, Delete } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { ParamId } from '../lib/validators.js'; import { PERMISSIONS } from '@takaro/auth'; @@ -62,11 +62,16 @@ export class BanSearchInputDTO extends ITakaroQuery { @OpenAPI({ security: [{ domainAuth: [] }], + tags: ['Player'], }) -@JsonController() +@JsonController('/player') export class BanController { @UseBefore(AuthService.getAuthMiddleware([PERMISSIONS.READ_PLAYERS])) @ResponseSchema(BanOutputArrayDTOAPI) + @OpenAPI({ + description: 'Search for bans', + summary: 'Search for bans', + }) @Post('/ban/search') async search(@Req() req: AuthenticatedRequest, @Res() res: Response, @Body() query: BanSearchInputDTO) { const service = new BanService(req.domainId); @@ -84,6 +89,10 @@ export class BanController { @UseBefore(AuthService.getAuthMiddleware([PERMISSIONS.READ_PLAYERS])) @ResponseSchema(BanOutputDTOAPI) + @OpenAPI({ + description: 'Get a single ban', + summary: 'Get a single ban', + }) @Get('/ban/:id') async getOne(@Req() req: AuthenticatedRequest, @Params() params: ParamId) { const service = new BanService(req.domainId); @@ -92,6 +101,10 @@ export class BanController { @UseBefore(AuthService.getAuthMiddleware([PERMISSIONS.MANAGE_PLAYERS])) @ResponseSchema(BanOutputDTOAPI) + @OpenAPI({ + description: 'Create a new ban, creating a ban via the API will always make it takaro managed.', + summary: 'Ban player', + }) @Post('/ban') async create(@Req() req: AuthenticatedRequest, @Body() data: BanCreateDTO) { const service = new BanService(req.domainId); @@ -102,6 +115,10 @@ export class BanController { @UseBefore(AuthService.getAuthMiddleware([PERMISSIONS.MANAGE_PLAYERS])) @ResponseSchema(BanOutputDTOAPI) + @OpenAPI({ + description: 'Update an existing ban, updating a ban via the API will always make it takaro managed.', + summary: 'Update ban', + }) @Put('/ban/:id') async update(@Req() req: AuthenticatedRequest, @Params() params: ParamId, @Body() data: BanUpdateDTO) { const service = new BanService(req.domainId); @@ -112,7 +129,11 @@ export class BanController { @UseBefore(AuthService.getAuthMiddleware([PERMISSIONS.MANAGE_PLAYERS])) @ResponseSchema(APIOutput) - @Post('/ban/:id/delete') + @OpenAPI({ + description: 'Unban player. This will remove the ban from Takaro and the gameserver(s)', + summary: 'Unban player', + }) + @Delete('/ban/:id') async delete(@Req() req: AuthenticatedRequest, @Params() params: ParamId) { const service = new BanService(req.domainId); await service.delete(params.id); diff --git a/packages/app-api/src/service/Ban/dto.ts b/packages/app-api/src/service/Ban/dto.ts index 7597de855c..f16ef73fb2 100644 --- a/packages/app-api/src/service/Ban/dto.ts +++ b/packages/app-api/src/service/Ban/dto.ts @@ -22,7 +22,8 @@ export class BanOutputDTO extends TakaroModelDTO { export class BanCreateDTO extends TakaroDTO { @IsUUID('4') - gameServerId: string; + @IsOptional() + gameServerId?: string; @IsUUID('4') playerId: string; @IsBoolean() @@ -38,6 +39,7 @@ export class BanCreateDTO extends TakaroDTO { @IsOptional() reason?: string; } + export class BanUpdateDTO extends TakaroDTO { @IsUUID('4') gameServerId: string; diff --git a/packages/app-api/src/service/Ban/index.ts b/packages/app-api/src/service/Ban/index.ts index 2d34afee74..f83a18d51d 100644 --- a/packages/app-api/src/service/Ban/index.ts +++ b/packages/app-api/src/service/Ban/index.ts @@ -32,7 +32,9 @@ export class BanService extends TakaroService { return gameServerService.banPlayer(pog.gameServerId, player.id, ban.reason, ban.until); }), diff --git a/packages/app-api/src/service/__tests__/BanService.integration.test.ts b/packages/app-api/src/service/__tests__/BanService.integration.test.ts index 0624513fc2..46de31a87f 100644 --- a/packages/app-api/src/service/__tests__/BanService.integration.test.ts +++ b/packages/app-api/src/service/__tests__/BanService.integration.test.ts @@ -1,6 +1,7 @@ import { IntegrationTest, SetupGameServerPlayers, expect } from '@takaro/test'; import { queueService } from '@takaro/queues'; import { randomUUID } from 'node:crypto'; +import { Client } from '@takaro/apiclient'; async function triggerBanSync(domainId: string, gameServerId: string) { const job = await queueService.queues.bansSync.queue.add({ domainId, gameServerId, triggerId: randomUUID() }); @@ -21,6 +22,24 @@ async function triggerBanSync(domainId: string, gameServerId: string) { } } +/** + * This function aims to simulate when an admin bans someone without using Takaro. + * So if effect, this creates bans that are not takaroManaged. + * @param gameServerId + * @param playerId + */ +async function banPlayerOutOfBand(client: Client, gameServerId: string, playerId: string, reason?: string) { + await client.gameserver.gameServerControllerExecuteCommand(gameServerId, { + command: `ban ${playerId} ${reason || 'unknown reason'}`, + }); +} + +async function unbanPlayerOutOfBand(client: Client, gameServerId: string, playerId: string) { + await client.gameserver.gameServerControllerExecuteCommand(gameServerId, { + command: `unban ${playerId}`, + }); +} + const group = 'BanService'; const tests = [ @@ -31,12 +50,9 @@ const tests = [ setup: SetupGameServerPlayers.setup, test: async function () { if (!this.standardDomainId) throw new Error('Standard domain ID not found'); - await this.client.gameserver.gameServerControllerBanPlayer( - this.setupData.gameServer1.id, - this.setupData.pogs1[0].playerId, - ); + await banPlayerOutOfBand(this.client, this.setupData.gameServer1.id, this.setupData.pogs1[0].gameId); await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); - const bans = await this.client.ban.banControllerSearch({ + const bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); expect(bans.data.data.length).to.equal(1); @@ -50,26 +66,21 @@ const tests = [ test: async function () { if (!this.standardDomainId) throw new Error('Standard domain ID not found'); // Step 1: Ban the player - await this.client.gameserver.gameServerControllerBanPlayer( - this.setupData.gameServer1.id, - this.setupData.pogs1[0].playerId, - ); + await banPlayerOutOfBand(this.client, this.setupData.gameServer1.id, this.setupData.pogs1[0].gameId); + // Step 2: Trigger ban sync await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); // Step 3: Verify that the player is banned - let bans = await this.client.ban.banControllerSearch({ + let bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); expect(bans.data.data.length).to.equal(1); // Step 4: Unban the player - await this.client.gameserver.gameServerControllerUnbanPlayer( - this.setupData.gameServer1.id, - this.setupData.pogs1[0].playerId, - ); + await unbanPlayerOutOfBand(this.client, this.setupData.gameServer1.id, this.setupData.pogs1[0].gameId); // Step 5: Trigger ban sync again after unban await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); // Step 6: Verify that the player is no longer banned - bans = await this.client.ban.banControllerSearch({ + bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); expect(bans.data.data.length).to.equal(0); @@ -83,26 +94,20 @@ const tests = [ test: async function () { if (!this.standardDomainId) throw new Error('Standard domain ID not found'); // Step 1: Ban the player for the first time - await this.client.gameserver.gameServerControllerBanPlayer( - this.setupData.gameServer1.id, - this.setupData.pogs1[0].playerId, - ); + await banPlayerOutOfBand(this.client, this.setupData.gameServer1.id, this.setupData.pogs1[0].gameId); // Step 2: Trigger ban sync await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); // Step 3: Verify that the player is banned - let bans = await this.client.ban.banControllerSearch({ + let bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); expect(bans.data.data.length).to.equal(1); // Step 4: Ban the player again (same player, same game server) - await this.client.gameserver.gameServerControllerBanPlayer( - this.setupData.gameServer1.id, - this.setupData.pogs1[0].playerId, - ); + await banPlayerOutOfBand(this.client, this.setupData.gameServer1.id, this.setupData.pogs1[0].gameId); // Step 5: Trigger ban sync again after second ban await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); // Step 6: Verify that the player is still banned - bans = await this.client.ban.banControllerSearch({ + bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); expect(bans.data.data.length).to.equal(1); @@ -116,29 +121,21 @@ const tests = [ test: async function () { if (!this.standardDomainId) throw new Error('Standard domain ID not found'); // Step 1: Ban the player for the first time with reason1 - await this.client.gameserver.gameServerControllerBanPlayer( - this.setupData.gameServer1.id, - this.setupData.pogs1[0].playerId, - { reason: 'reason1' }, - ); + await banPlayerOutOfBand(this.client, this.setupData.gameServer1.id, this.setupData.pogs1[0].gameId, 'reason1'); // Step 2: Trigger ban sync await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); // Step 3: Verify that the player is banned with reason1 - let bans = await this.client.ban.banControllerSearch({ + let bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); expect(bans.data.data.length).to.equal(1); expect(bans.data.data[0].reason).to.equal('reason1'); // Step 4: Ban the player again with reason2 - await this.client.gameserver.gameServerControllerBanPlayer( - this.setupData.gameServer1.id, - this.setupData.pogs1[0].playerId, - { reason: 'reason2' }, - ); + await banPlayerOutOfBand(this.client, this.setupData.gameServer1.id, this.setupData.pogs1[0].gameId, 'reason2'); // Step 5: Trigger ban sync again after second ban with a new reason await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); // Step 6: Verify that the player's ban exists with the new reason - bans = await this.client.ban.banControllerSearch({ + bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); expect(bans.data.data.length).to.equal(1); @@ -153,30 +150,21 @@ const tests = [ test: async function () { if (!this.standardDomainId) throw new Error('Standard domain ID not found'); // Step 1: Ban player1 and player2 - await this.client.gameserver.gameServerControllerBanPlayer( - this.setupData.gameServer1.id, - this.setupData.pogs1[0].playerId, - ); - await this.client.gameserver.gameServerControllerBanPlayer( - this.setupData.gameServer1.id, - this.setupData.pogs1[1].playerId, - ); + await banPlayerOutOfBand(this.client, this.setupData.gameServer1.id, this.setupData.pogs1[0].gameId); + await banPlayerOutOfBand(this.client, this.setupData.gameServer1.id, this.setupData.pogs1[1].gameId); // Step 2: Trigger ban sync await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); // Step 3: Verify that both players are banned - let bans = await this.client.ban.banControllerSearch({ + let bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); expect(bans.data.data.length).to.equal(2); // Step 4: Unban player1 - await this.client.gameserver.gameServerControllerUnbanPlayer( - this.setupData.gameServer1.id, - this.setupData.pogs1[0].playerId, - ); + await unbanPlayerOutOfBand(this.client, this.setupData.gameServer1.id, this.setupData.pogs1[0].gameId); // Step 5: Trigger ban sync again after unban await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); // Step 6: Verify that player1 is no longer banned, but player2 is still banned - bans = await this.client.ban.banControllerSearch({ + bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); expect(bans.data.data.length).to.equal(1); @@ -190,7 +178,7 @@ const tests = [ setup: SetupGameServerPlayers.setup, test: async function () { if (!this.standardDomainId) throw new Error('Standard domain ID not found'); - await this.client.ban.banControllerCreate({ + await this.client.player.banControllerCreate({ gameServerId: this.setupData.gameServer1.id, playerId: this.setupData.pogs1[0].playerId, reason: 'reason', @@ -203,7 +191,7 @@ const tests = [ await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); - const bans = await this.client.ban.banControllerSearch({ + const bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); @@ -218,7 +206,7 @@ const tests = [ setup: SetupGameServerPlayers.setup, test: async function () { if (!this.standardDomainId) throw new Error('Standard domain ID not found'); - await this.client.ban.banControllerCreate({ + await this.client.player.banControllerCreate({ gameServerId: this.setupData.gameServer1.id, playerId: this.setupData.pogs1[0].playerId, reason: 'reason', @@ -231,7 +219,7 @@ const tests = [ await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); - const bans = await this.client.ban.banControllerSearch({ + const bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); @@ -246,7 +234,7 @@ const tests = [ setup: SetupGameServerPlayers.setup, test: async function () { if (!this.standardDomainId) throw new Error('Standard domain ID not found'); - await this.client.ban.banControllerCreate({ + await this.client.player.banControllerCreate({ gameServerId: this.setupData.gameServer1.id, playerId: this.setupData.pogs1[0].playerId, reason: 'reason', @@ -255,17 +243,17 @@ const tests = [ await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); - let bans = await this.client.ban.banControllerSearch({ + let bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); expect(bans.data.data.length).to.equal(1); - await this.client.ban.banControllerDelete(bans.data.data[0].id); + await this.client.player.banControllerDelete(bans.data.data[0].id); await triggerBanSync(this.standardDomainId, this.setupData.gameServer1.id); - bans = await this.client.ban.banControllerSearch({ + bans = await this.client.player.banControllerSearch({ filters: { gameServerId: [this.setupData.gameServer1.id] }, }); diff --git a/packages/lib-apiclient/src/generated/.openapi-generator/VERSION b/packages/lib-apiclient/src/generated/.openapi-generator/VERSION index 4bc5d61816..09a6d30847 100644 --- a/packages/lib-apiclient/src/generated/.openapi-generator/VERSION +++ b/packages/lib-apiclient/src/generated/.openapi-generator/VERSION @@ -1 +1 @@ -7.9.0 +7.8.0 diff --git a/packages/lib-apiclient/src/generated/api.ts b/packages/lib-apiclient/src/generated/api.ts index a81b2ccee2..e80764cf89 100644 --- a/packages/lib-apiclient/src/generated/api.ts +++ b/packages/lib-apiclient/src/generated/api.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Takaro app-api + * Takaro API * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - f80f6d034a7760e0429de59c786ff04802006bc9 + * The version of the OpenAPI document: unset - unset * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -72,16 +72,16 @@ export interface ActivityInputDTO { dataType: ActivityInputDTODataTypeEnum; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof ActivityInputDTO */ - startDate?: string; + startDate?: StatsControllerGetPingStatsStartDateParameter; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof ActivityInputDTO */ - endDate?: string; + endDate?: StatsControllerGetPingStatsStartDateParameter; } export const ActivityInputDTOTimeTypeEnum = { @@ -124,7 +124,7 @@ export interface BanCreateDTO { * @type {string} * @memberof BanCreateDTO */ - gameServerId: string; + gameServerId?: string; /** * * @type {string} @@ -552,16 +552,16 @@ export interface BaseGameEvent { export interface BaseStatsInputDTO { /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof BaseStatsInputDTO */ - startDate?: string; + startDate?: StatsControllerGetPingStatsStartDateParameter; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof BaseStatsInputDTO */ - endDate?: string; + endDate?: StatsControllerGetPingStatsStartDateParameter; } /** * @@ -2555,16 +2555,16 @@ export interface EventsCountInputDTO { bucketStep: EventsCountInputDTOBucketStepEnum; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof EventsCountInputDTO */ - startDate?: string; + startDate?: StatsControllerGetPingStatsStartDateParameter; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof EventsCountInputDTO */ - endDate?: string; + endDate?: StatsControllerGetPingStatsStartDateParameter; } export const EventsCountInputDTOEventNameEnum = { @@ -5014,16 +5014,16 @@ export interface LatencyInputDTO { gameServerId: string; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof LatencyInputDTO */ - startDate?: string; + startDate?: StatsControllerGetPingStatsStartDateParameter; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof LatencyInputDTO */ - endDate?: string; + endDate?: StatsControllerGetPingStatsStartDateParameter; } /** * @@ -5178,10 +5178,10 @@ export interface MessageSendInputDTO { export interface MetadataOutput { /** * - * @type {string} + * @type {MetadataOutputServerTime} * @memberof MetadataOutput */ - serverTime: string; + serverTime: MetadataOutputServerTime; /** * * @type {ErrorOutput} @@ -5207,6 +5207,12 @@ export interface MetadataOutput { */ total?: number; } +/** + * @type MetadataOutputServerTime + * @export + */ +export type MetadataOutputServerTime = string; + /** * * @export @@ -5743,16 +5749,16 @@ export interface OptionalPogStatsInputDTO { playerId?: string; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof OptionalPogStatsInputDTO */ - startDate?: string; + startDate?: StatsControllerGetPingStatsStartDateParameter; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof OptionalPogStatsInputDTO */ - endDate?: string; + endDate?: StatsControllerGetPingStatsStartDateParameter; } /** * @@ -6939,6 +6945,19 @@ export interface PlayerOutputWithRolesDTOAPI { */ meta: MetadataOutput; } +/** + * + * @export + * @interface PlayerParam + */ +export interface PlayerParam { + /** + * + * @type {string} + * @memberof PlayerParam + */ + playerId: string; +} /** * * @export @@ -7238,16 +7257,16 @@ export interface PlayersOnlineInputDTO { gameServerId?: string; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof PlayersOnlineInputDTO */ - startDate?: string; + startDate?: StatsControllerGetPingStatsStartDateParameter; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof PlayersOnlineInputDTO */ - endDate?: string; + endDate?: StatsControllerGetPingStatsStartDateParameter; } /** * @@ -7288,16 +7307,16 @@ export interface PogStatsInputDTO { playerId: string; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof PogStatsInputDTO */ - startDate?: string; + startDate?: StatsControllerGetPingStatsStartDateParameter; /** * - * @type {string} + * @type {StatsControllerGetPingStatsStartDateParameter} * @memberof PogStatsInputDTO */ - endDate?: string; + endDate?: StatsControllerGetPingStatsStartDateParameter; } /** * @@ -8632,6 +8651,12 @@ export interface ShopSearchInputAllowedRangeFilter { */ updatedAt?: NOTDOMAINSCOPEDTakaroModelDTOCreatedAt; } +/** + * @type StatsControllerGetPingStatsStartDateParameter + * @export + */ +export type StatsControllerGetPingStatsStartDateParameter = string; + /** * * @export @@ -10168,23 +10193,23 @@ export interface VariableUpdateDTO { } /** - * BanApi - axios parameter creator + * CommandApi - axios parameter creator * @export */ -export const BanApiAxiosParamCreator = function (configuration?: Configuration) { +export const CommandApiAxiosParamCreator = function (configuration?: Configuration) { return { /** - * Required permissions: `MANAGE_PLAYERS` + * Required permissions: `MANAGE_MODULES` * @summary Create - * @param {BanCreateDTO} [banCreateDTO] BanCreateDTO + * @param {CommandCreateDTO} [commandCreateDTO] CommandCreateDTO * @param {*} [options] Override http request option. * @throws {RequiredError} */ - banControllerCreate: async ( - banCreateDTO?: BanCreateDTO, + commandControllerCreate: async ( + commandCreateDTO?: CommandCreateDTO, options: RawAxiosRequestConfig = {}, ): Promise => { - const localVarPath = `/ban`; + const localVarPath = `/command`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -10203,7 +10228,7 @@ export const BanApiAxiosParamCreator = function (configuration?: Configuration) setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; - localVarRequestOptions.data = serializeDataIfNeeded(banCreateDTO, localVarRequestOptions, configuration); + localVarRequestOptions.data = serializeDataIfNeeded(commandCreateDTO, localVarRequestOptions, configuration); return { url: toPathString(localVarUrlObj), @@ -10211,16 +10236,64 @@ export const BanApiAxiosParamCreator = function (configuration?: Configuration) }; }, /** - * Required permissions: `MANAGE_PLAYERS` - * @summary Delete + * Required permissions: `MANAGE_MODULES` + * @summary Create argument + * @param {CommandArgumentCreateDTO} [commandArgumentCreateDTO] CommandArgumentCreateDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + commandControllerCreateArgument: async ( + commandArgumentCreateDTO?: CommandArgumentCreateDTO, + options: RawAxiosRequestConfig = {}, + ): Promise => { + const localVarPath = `/command/argument`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication domainAuth required + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; + localVarRequestOptions.data = serializeDataIfNeeded( + commandArgumentCreateDTO, + localVarRequestOptions, + configuration, + ); + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Required permissions: `READ_MODULES` + * @summary Get executions * @param {string} id + * @param {any} [success] + * @param {EventSearchInputDTO} [eventSearchInputDTO] EventSearchInputDTO * @param {*} [options] Override http request option. * @throws {RequiredError} */ - banControllerDelete: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { + commandControllerGetExecutions: async ( + id: string, + success?: any, + eventSearchInputDTO?: EventSearchInputDTO, + options: RawAxiosRequestConfig = {}, + ): Promise => { // verify required parameter 'id' is not null or undefined - assertParamExists('banControllerDelete', 'id', id); - const localVarPath = `/ban/{id}/delete`.replace(`{${'id'}}`, encodeURIComponent(String(id))); + assertParamExists('commandControllerGetExecutions', 'id', id); + const localVarPath = `/command/{id}/executions`.replace(`{${'id'}}`, encodeURIComponent(String(id))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -10234,9 +10307,18 @@ export const BanApiAxiosParamCreator = function (configuration?: Configuration) // authentication domainAuth required + if (success !== undefined) { + for (const [key, value] of Object.entries(success)) { + localVarQueryParameter[key] = value; + } + } + + localVarHeaderParameter['Content-Type'] = 'application/json'; + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; + localVarRequestOptions.data = serializeDataIfNeeded(eventSearchInputDTO, localVarRequestOptions, configuration); return { url: toPathString(localVarUrlObj), @@ -10244,16 +10326,16 @@ export const BanApiAxiosParamCreator = function (configuration?: Configuration) }; }, /** - * Required permissions: `READ_PLAYERS` + * Required permissions: `READ_MODULES` * @summary Get one * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ - banControllerGetOne: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { + commandControllerGetOne: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'id' is not null or undefined - assertParamExists('banControllerGetOne', 'id', id); - const localVarPath = `/ban/{id}`.replace(`{${'id'}}`, encodeURIComponent(String(id))); + assertParamExists('commandControllerGetOne', 'id', id); + const localVarPath = `/command/{id}`.replace(`{${'id'}}`, encodeURIComponent(String(id))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -10277,17 +10359,83 @@ export const BanApiAxiosParamCreator = function (configuration?: Configuration) }; }, /** - * Required permissions: `READ_PLAYERS` + * Required permissions: `MANAGE_MODULES` + * @summary Remove + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + commandControllerRemove: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('commandControllerRemove', 'id', id); + const localVarPath = `/command/{id}`.replace(`{${'id'}}`, encodeURIComponent(String(id))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication domainAuth required + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Required permissions: `MANAGE_MODULES` + * @summary Remove argument + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + commandControllerRemoveArgument: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('commandControllerRemoveArgument', 'id', id); + const localVarPath = `/command/argument/{id}`.replace(`{${'id'}}`, encodeURIComponent(String(id))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication domainAuth required + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Required permissions: `READ_MODULES` * @summary Search - * @param {BanSearchInputDTO} [banSearchInputDTO] BanSearchInputDTO + * @param {CommandSearchInputDTO} [commandSearchInputDTO] CommandSearchInputDTO * @param {*} [options] Override http request option. * @throws {RequiredError} */ - banControllerSearch: async ( - banSearchInputDTO?: BanSearchInputDTO, + commandControllerSearch: async ( + commandSearchInputDTO?: CommandSearchInputDTO, options: RawAxiosRequestConfig = {}, ): Promise => { - const localVarPath = `/ban/search`; + const localVarPath = `/command/search`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -10306,7 +10454,7 @@ export const BanApiAxiosParamCreator = function (configuration?: Configuration) setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; - localVarRequestOptions.data = serializeDataIfNeeded(banSearchInputDTO, localVarRequestOptions, configuration); + localVarRequestOptions.data = serializeDataIfNeeded(commandSearchInputDTO, localVarRequestOptions, configuration); return { url: toPathString(localVarUrlObj), @@ -10314,21 +10462,21 @@ export const BanApiAxiosParamCreator = function (configuration?: Configuration) }; }, /** - * Required permissions: `MANAGE_PLAYERS` - * @summary Update + * Required permissions: `MANAGE_MODULES` + * @summary Trigger * @param {string} id - * @param {BanUpdateDTO} [banUpdateDTO] BanUpdateDTO + * @param {CommandTriggerDTO} [commandTriggerDTO] CommandTriggerDTO * @param {*} [options] Override http request option. * @throws {RequiredError} */ - banControllerUpdate: async ( + commandControllerTrigger: async ( id: string, - banUpdateDTO?: BanUpdateDTO, + commandTriggerDTO?: CommandTriggerDTO, options: RawAxiosRequestConfig = {}, ): Promise => { // verify required parameter 'id' is not null or undefined - assertParamExists('banControllerUpdate', 'id', id); - const localVarPath = `/ban/{id}`.replace(`{${'id'}}`, encodeURIComponent(String(id))); + assertParamExists('commandControllerTrigger', 'id', id); + const localVarPath = `/command/{id}/trigger`.replace(`{${'id'}}`, encodeURIComponent(String(id))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -10336,7 +10484,7 @@ export const BanApiAxiosParamCreator = function (configuration?: Configuration) baseOptions = configuration.baseOptions; } - const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options }; + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options }; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; @@ -10347,609 +10495,22 @@ export const BanApiAxiosParamCreator = function (configuration?: Configuration) setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; - localVarRequestOptions.data = serializeDataIfNeeded(banUpdateDTO, localVarRequestOptions, configuration); + localVarRequestOptions.data = serializeDataIfNeeded(commandTriggerDTO, localVarRequestOptions, configuration); return { url: toPathString(localVarUrlObj), options: localVarRequestOptions, }; }, - }; -}; - -/** - * BanApi - functional programming interface - * @export - */ -export const BanApiFp = function (configuration?: Configuration) { - const localVarAxiosParamCreator = BanApiAxiosParamCreator(configuration); - return { - /** - * Required permissions: `MANAGE_PLAYERS` - * @summary Create - * @param {BanCreateDTO} [banCreateDTO] BanCreateDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async banControllerCreate( - banCreateDTO?: BanCreateDTO, - options?: RawAxiosRequestConfig, - ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.banControllerCreate(banCreateDTO, options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = - operationServerMap['BanApi.banControllerCreate']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => - createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration, - )(axios, localVarOperationServerBasePath || basePath); - }, /** - * Required permissions: `MANAGE_PLAYERS` - * @summary Delete + * Required permissions: `MANAGE_MODULES` + * @summary Update * @param {string} id + * @param {CommandUpdateDTO} [commandUpdateDTO] CommandUpdateDTO * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async banControllerDelete( - id: string, - options?: RawAxiosRequestConfig, - ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.banControllerDelete(id, options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = - operationServerMap['BanApi.banControllerDelete']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => - createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration, - )(axios, localVarOperationServerBasePath || basePath); - }, - /** - * Required permissions: `READ_PLAYERS` - * @summary Get one - * @param {string} id - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async banControllerGetOne( - id: string, - options?: RawAxiosRequestConfig, - ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.banControllerGetOne(id, options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = - operationServerMap['BanApi.banControllerGetOne']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => - createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration, - )(axios, localVarOperationServerBasePath || basePath); - }, - /** - * Required permissions: `READ_PLAYERS` - * @summary Search - * @param {BanSearchInputDTO} [banSearchInputDTO] BanSearchInputDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async banControllerSearch( - banSearchInputDTO?: BanSearchInputDTO, - options?: RawAxiosRequestConfig, - ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.banControllerSearch(banSearchInputDTO, options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = - operationServerMap['BanApi.banControllerSearch']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => - createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration, - )(axios, localVarOperationServerBasePath || basePath); - }, - /** - * Required permissions: `MANAGE_PLAYERS` - * @summary Update - * @param {string} id - * @param {BanUpdateDTO} [banUpdateDTO] BanUpdateDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async banControllerUpdate( - id: string, - banUpdateDTO?: BanUpdateDTO, - options?: RawAxiosRequestConfig, - ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.banControllerUpdate(id, banUpdateDTO, options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = - operationServerMap['BanApi.banControllerUpdate']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => - createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration, - )(axios, localVarOperationServerBasePath || basePath); - }, - }; -}; - -/** - * BanApi - factory interface - * @export - */ -export const BanApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = BanApiFp(configuration); - return { - /** - * Required permissions: `MANAGE_PLAYERS` - * @summary Create - * @param {BanCreateDTO} [banCreateDTO] BanCreateDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - banControllerCreate(banCreateDTO?: BanCreateDTO, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.banControllerCreate(banCreateDTO, options).then((request) => request(axios, basePath)); - }, - /** - * Required permissions: `MANAGE_PLAYERS` - * @summary Delete - * @param {string} id - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - banControllerDelete(id: string, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.banControllerDelete(id, options).then((request) => request(axios, basePath)); - }, - /** - * Required permissions: `READ_PLAYERS` - * @summary Get one - * @param {string} id - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - banControllerGetOne(id: string, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.banControllerGetOne(id, options).then((request) => request(axios, basePath)); - }, - /** - * Required permissions: `READ_PLAYERS` - * @summary Search - * @param {BanSearchInputDTO} [banSearchInputDTO] BanSearchInputDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - banControllerSearch( - banSearchInputDTO?: BanSearchInputDTO, - options?: RawAxiosRequestConfig, - ): AxiosPromise { - return localVarFp.banControllerSearch(banSearchInputDTO, options).then((request) => request(axios, basePath)); - }, - /** - * Required permissions: `MANAGE_PLAYERS` - * @summary Update - * @param {string} id - * @param {BanUpdateDTO} [banUpdateDTO] BanUpdateDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - banControllerUpdate( - id: string, - banUpdateDTO?: BanUpdateDTO, - options?: RawAxiosRequestConfig, - ): AxiosPromise { - return localVarFp.banControllerUpdate(id, banUpdateDTO, options).then((request) => request(axios, basePath)); - }, - }; -}; - -/** - * BanApi - object-oriented interface - * @export - * @class BanApi - * @extends {BaseAPI} - */ -export class BanApi extends BaseAPI { - /** - * Required permissions: `MANAGE_PLAYERS` - * @summary Create - * @param {BanCreateDTO} [banCreateDTO] BanCreateDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof BanApi - */ - public banControllerCreate(banCreateDTO?: BanCreateDTO, options?: RawAxiosRequestConfig) { - return BanApiFp(this.configuration) - .banControllerCreate(banCreateDTO, options) - .then((request) => request(this.axios, this.basePath)); - } - - /** - * Required permissions: `MANAGE_PLAYERS` - * @summary Delete - * @param {string} id - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof BanApi - */ - public banControllerDelete(id: string, options?: RawAxiosRequestConfig) { - return BanApiFp(this.configuration) - .banControllerDelete(id, options) - .then((request) => request(this.axios, this.basePath)); - } - - /** - * Required permissions: `READ_PLAYERS` - * @summary Get one - * @param {string} id - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof BanApi - */ - public banControllerGetOne(id: string, options?: RawAxiosRequestConfig) { - return BanApiFp(this.configuration) - .banControllerGetOne(id, options) - .then((request) => request(this.axios, this.basePath)); - } - - /** - * Required permissions: `READ_PLAYERS` - * @summary Search - * @param {BanSearchInputDTO} [banSearchInputDTO] BanSearchInputDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof BanApi - */ - public banControllerSearch(banSearchInputDTO?: BanSearchInputDTO, options?: RawAxiosRequestConfig) { - return BanApiFp(this.configuration) - .banControllerSearch(banSearchInputDTO, options) - .then((request) => request(this.axios, this.basePath)); - } - - /** - * Required permissions: `MANAGE_PLAYERS` - * @summary Update - * @param {string} id - * @param {BanUpdateDTO} [banUpdateDTO] BanUpdateDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof BanApi - */ - public banControllerUpdate(id: string, banUpdateDTO?: BanUpdateDTO, options?: RawAxiosRequestConfig) { - return BanApiFp(this.configuration) - .banControllerUpdate(id, banUpdateDTO, options) - .then((request) => request(this.axios, this.basePath)); - } -} - -/** - * CommandApi - axios parameter creator - * @export - */ -export const CommandApiAxiosParamCreator = function (configuration?: Configuration) { - return { - /** - * Required permissions: `MANAGE_MODULES` - * @summary Create - * @param {CommandCreateDTO} [commandCreateDTO] CommandCreateDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - commandControllerCreate: async ( - commandCreateDTO?: CommandCreateDTO, - options: RawAxiosRequestConfig = {}, - ): Promise => { - const localVarPath = `/command`; - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options }; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication domainAuth required - - localVarHeaderParameter['Content-Type'] = 'application/json'; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; - localVarRequestOptions.data = serializeDataIfNeeded(commandCreateDTO, localVarRequestOptions, configuration); - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * Required permissions: `MANAGE_MODULES` - * @summary Create argument - * @param {CommandArgumentCreateDTO} [commandArgumentCreateDTO] CommandArgumentCreateDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - commandControllerCreateArgument: async ( - commandArgumentCreateDTO?: CommandArgumentCreateDTO, - options: RawAxiosRequestConfig = {}, - ): Promise => { - const localVarPath = `/command/argument`; - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options }; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication domainAuth required - - localVarHeaderParameter['Content-Type'] = 'application/json'; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; - localVarRequestOptions.data = serializeDataIfNeeded( - commandArgumentCreateDTO, - localVarRequestOptions, - configuration, - ); - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * Required permissions: `READ_MODULES` - * @summary Get executions - * @param {string} id - * @param {any} [success] - * @param {EventSearchInputDTO} [eventSearchInputDTO] EventSearchInputDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - commandControllerGetExecutions: async ( - id: string, - success?: any, - eventSearchInputDTO?: EventSearchInputDTO, - options: RawAxiosRequestConfig = {}, - ): Promise => { - // verify required parameter 'id' is not null or undefined - assertParamExists('commandControllerGetExecutions', 'id', id); - const localVarPath = `/command/{id}/executions`.replace(`{${'id'}}`, encodeURIComponent(String(id))); - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options }; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication domainAuth required - - if (success !== undefined) { - for (const [key, value] of Object.entries(success)) { - localVarQueryParameter[key] = value; - } - } - - localVarHeaderParameter['Content-Type'] = 'application/json'; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; - localVarRequestOptions.data = serializeDataIfNeeded(eventSearchInputDTO, localVarRequestOptions, configuration); - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * Required permissions: `READ_MODULES` - * @summary Get one - * @param {string} id - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - commandControllerGetOne: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'id' is not null or undefined - assertParamExists('commandControllerGetOne', 'id', id); - const localVarPath = `/command/{id}`.replace(`{${'id'}}`, encodeURIComponent(String(id))); - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options }; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication domainAuth required - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * Required permissions: `MANAGE_MODULES` - * @summary Remove - * @param {string} id - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - commandControllerRemove: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'id' is not null or undefined - assertParamExists('commandControllerRemove', 'id', id); - const localVarPath = `/command/{id}`.replace(`{${'id'}}`, encodeURIComponent(String(id))); - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options }; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication domainAuth required - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * Required permissions: `MANAGE_MODULES` - * @summary Remove argument - * @param {string} id - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - commandControllerRemoveArgument: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'id' is not null or undefined - assertParamExists('commandControllerRemoveArgument', 'id', id); - const localVarPath = `/command/argument/{id}`.replace(`{${'id'}}`, encodeURIComponent(String(id))); - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options }; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication domainAuth required - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * Required permissions: `READ_MODULES` - * @summary Search - * @param {CommandSearchInputDTO} [commandSearchInputDTO] CommandSearchInputDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - commandControllerSearch: async ( - commandSearchInputDTO?: CommandSearchInputDTO, - options: RawAxiosRequestConfig = {}, - ): Promise => { - const localVarPath = `/command/search`; - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options }; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication domainAuth required - - localVarHeaderParameter['Content-Type'] = 'application/json'; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; - localVarRequestOptions.data = serializeDataIfNeeded(commandSearchInputDTO, localVarRequestOptions, configuration); - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * Required permissions: `MANAGE_MODULES` - * @summary Trigger - * @param {string} id - * @param {CommandTriggerDTO} [commandTriggerDTO] CommandTriggerDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - commandControllerTrigger: async ( - id: string, - commandTriggerDTO?: CommandTriggerDTO, - options: RawAxiosRequestConfig = {}, - ): Promise => { - // verify required parameter 'id' is not null or undefined - assertParamExists('commandControllerTrigger', 'id', id); - const localVarPath = `/command/{id}/trigger`.replace(`{${'id'}}`, encodeURIComponent(String(id))); - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options }; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication domainAuth required - - localVarHeaderParameter['Content-Type'] = 'application/json'; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; - localVarRequestOptions.data = serializeDataIfNeeded(commandTriggerDTO, localVarRequestOptions, configuration); - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * Required permissions: `MANAGE_MODULES` - * @summary Update - * @param {string} id - * @param {CommandUpdateDTO} [commandUpdateDTO] CommandUpdateDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - commandControllerUpdate: async ( + commandControllerUpdate: async ( id: string, commandUpdateDTO?: CommandUpdateDTO, options: RawAxiosRequestConfig = {}, @@ -18595,28 +18156,209 @@ export class ModuleApi extends BaseAPI { .then((request) => request(this.axios, this.basePath)); } - /** - * Required permissions: `MANAGE_MODULES` - * @summary Update - * @param {string} id - * @param {ModuleUpdateDTO} [moduleUpdateDTO] ModuleUpdateDTO - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ModuleApi - */ - public moduleControllerUpdate(id: string, moduleUpdateDTO?: ModuleUpdateDTO, options?: RawAxiosRequestConfig) { - return ModuleApiFp(this.configuration) - .moduleControllerUpdate(id, moduleUpdateDTO, options) - .then((request) => request(this.axios, this.basePath)); - } -} + /** + * Required permissions: `MANAGE_MODULES` + * @summary Update + * @param {string} id + * @param {ModuleUpdateDTO} [moduleUpdateDTO] ModuleUpdateDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ModuleApi + */ + public moduleControllerUpdate(id: string, moduleUpdateDTO?: ModuleUpdateDTO, options?: RawAxiosRequestConfig) { + return ModuleApiFp(this.configuration) + .moduleControllerUpdate(id, moduleUpdateDTO, options) + .then((request) => request(this.axios, this.basePath)); + } +} + +/** + * PlayerApi - axios parameter creator + * @export + */ +export const PlayerApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * Create a new ban, creating a ban via the API will always make it takaro managed. Required permissions: `MANAGE_PLAYERS` + * @summary Ban player + * @param {BanCreateDTO} [banCreateDTO] BanCreateDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + banControllerCreate: async ( + banCreateDTO?: BanCreateDTO, + options: RawAxiosRequestConfig = {}, + ): Promise => { + const localVarPath = `/player/ban`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication domainAuth required + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; + localVarRequestOptions.data = serializeDataIfNeeded(banCreateDTO, localVarRequestOptions, configuration); + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Unban player. This will remove the ban from Takaro and the gameserver(s) Required permissions: `MANAGE_PLAYERS` + * @summary Unban player + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + banControllerDelete: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('banControllerDelete', 'id', id); + const localVarPath = `/player/ban/{id}`.replace(`{${'id'}}`, encodeURIComponent(String(id))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication domainAuth required + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Get a single ban Required permissions: `READ_PLAYERS` + * @summary Get a single ban + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + banControllerGetOne: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('banControllerGetOne', 'id', id); + const localVarPath = `/player/ban/{id}`.replace(`{${'id'}}`, encodeURIComponent(String(id))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication domainAuth required + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Search for bans Required permissions: `READ_PLAYERS` + * @summary Search for bans + * @param {BanSearchInputDTO} [banSearchInputDTO] BanSearchInputDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + banControllerSearch: async ( + banSearchInputDTO?: BanSearchInputDTO, + options: RawAxiosRequestConfig = {}, + ): Promise => { + const localVarPath = `/player/ban/search`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication domainAuth required + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; + localVarRequestOptions.data = serializeDataIfNeeded(banSearchInputDTO, localVarRequestOptions, configuration); + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Update an existing ban, updating a ban via the API will always make it takaro managed. Required permissions: `MANAGE_PLAYERS` + * @summary Update ban + * @param {string} id + * @param {BanUpdateDTO} [banUpdateDTO] BanUpdateDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + banControllerUpdate: async ( + id: string, + banUpdateDTO?: BanUpdateDTO, + options: RawAxiosRequestConfig = {}, + ): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('banControllerUpdate', 'id', id); + const localVarPath = `/player/ban/{id}`.replace(`{${'id'}}`, encodeURIComponent(String(id))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; -/** - * PlayerApi - axios parameter creator - * @export - */ -export const PlayerApiAxiosParamCreator = function (configuration?: Configuration) { - return { + // authentication domainAuth required + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers }; + localVarRequestOptions.data = serializeDataIfNeeded(banUpdateDTO, localVarRequestOptions, configuration); + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * Required permissions: `MANAGE_PLAYERS`, `MANAGE_ROLES` * @summary Assign role @@ -18829,6 +18571,123 @@ export const PlayerApiAxiosParamCreator = function (configuration?: Configuratio export const PlayerApiFp = function (configuration?: Configuration) { const localVarAxiosParamCreator = PlayerApiAxiosParamCreator(configuration); return { + /** + * Create a new ban, creating a ban via the API will always make it takaro managed. Required permissions: `MANAGE_PLAYERS` + * @summary Ban player + * @param {BanCreateDTO} [banCreateDTO] BanCreateDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async banControllerCreate( + banCreateDTO?: BanCreateDTO, + options?: RawAxiosRequestConfig, + ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.banControllerCreate(banCreateDTO, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = + operationServerMap['PlayerApi.banControllerCreate']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => + createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration, + )(axios, localVarOperationServerBasePath || basePath); + }, + /** + * Unban player. This will remove the ban from Takaro and the gameserver(s) Required permissions: `MANAGE_PLAYERS` + * @summary Unban player + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async banControllerDelete( + id: string, + options?: RawAxiosRequestConfig, + ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.banControllerDelete(id, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = + operationServerMap['PlayerApi.banControllerDelete']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => + createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration, + )(axios, localVarOperationServerBasePath || basePath); + }, + /** + * Get a single ban Required permissions: `READ_PLAYERS` + * @summary Get a single ban + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async banControllerGetOne( + id: string, + options?: RawAxiosRequestConfig, + ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.banControllerGetOne(id, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = + operationServerMap['PlayerApi.banControllerGetOne']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => + createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration, + )(axios, localVarOperationServerBasePath || basePath); + }, + /** + * Search for bans Required permissions: `READ_PLAYERS` + * @summary Search for bans + * @param {BanSearchInputDTO} [banSearchInputDTO] BanSearchInputDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async banControllerSearch( + banSearchInputDTO?: BanSearchInputDTO, + options?: RawAxiosRequestConfig, + ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.banControllerSearch(banSearchInputDTO, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = + operationServerMap['PlayerApi.banControllerSearch']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => + createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration, + )(axios, localVarOperationServerBasePath || basePath); + }, + /** + * Update an existing ban, updating a ban via the API will always make it takaro managed. Required permissions: `MANAGE_PLAYERS` + * @summary Update ban + * @param {string} id + * @param {BanUpdateDTO} [banUpdateDTO] BanUpdateDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async banControllerUpdate( + id: string, + banUpdateDTO?: BanUpdateDTO, + options?: RawAxiosRequestConfig, + ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.banControllerUpdate(id, banUpdateDTO, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = + operationServerMap['PlayerApi.banControllerUpdate']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => + createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration, + )(axios, localVarOperationServerBasePath || basePath); + }, /** * Required permissions: `MANAGE_PLAYERS`, `MANAGE_ROLES` * @summary Assign role @@ -18970,6 +18829,64 @@ export const PlayerApiFp = function (configuration?: Configuration) { export const PlayerApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { const localVarFp = PlayerApiFp(configuration); return { + /** + * Create a new ban, creating a ban via the API will always make it takaro managed. Required permissions: `MANAGE_PLAYERS` + * @summary Ban player + * @param {BanCreateDTO} [banCreateDTO] BanCreateDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + banControllerCreate(banCreateDTO?: BanCreateDTO, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.banControllerCreate(banCreateDTO, options).then((request) => request(axios, basePath)); + }, + /** + * Unban player. This will remove the ban from Takaro and the gameserver(s) Required permissions: `MANAGE_PLAYERS` + * @summary Unban player + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + banControllerDelete(id: string, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.banControllerDelete(id, options).then((request) => request(axios, basePath)); + }, + /** + * Get a single ban Required permissions: `READ_PLAYERS` + * @summary Get a single ban + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + banControllerGetOne(id: string, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.banControllerGetOne(id, options).then((request) => request(axios, basePath)); + }, + /** + * Search for bans Required permissions: `READ_PLAYERS` + * @summary Search for bans + * @param {BanSearchInputDTO} [banSearchInputDTO] BanSearchInputDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + banControllerSearch( + banSearchInputDTO?: BanSearchInputDTO, + options?: RawAxiosRequestConfig, + ): AxiosPromise { + return localVarFp.banControllerSearch(banSearchInputDTO, options).then((request) => request(axios, basePath)); + }, + /** + * Update an existing ban, updating a ban via the API will always make it takaro managed. Required permissions: `MANAGE_PLAYERS` + * @summary Update ban + * @param {string} id + * @param {BanUpdateDTO} [banUpdateDTO] BanUpdateDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + banControllerUpdate( + id: string, + banUpdateDTO?: BanUpdateDTO, + options?: RawAxiosRequestConfig, + ): AxiosPromise { + return localVarFp.banControllerUpdate(id, banUpdateDTO, options).then((request) => request(axios, basePath)); + }, /** * Required permissions: `MANAGE_PLAYERS`, `MANAGE_ROLES` * @summary Assign role @@ -19052,6 +18969,77 @@ export const PlayerApiFactory = function (configuration?: Configuration, basePat * @extends {BaseAPI} */ export class PlayerApi extends BaseAPI { + /** + * Create a new ban, creating a ban via the API will always make it takaro managed. Required permissions: `MANAGE_PLAYERS` + * @summary Ban player + * @param {BanCreateDTO} [banCreateDTO] BanCreateDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof PlayerApi + */ + public banControllerCreate(banCreateDTO?: BanCreateDTO, options?: RawAxiosRequestConfig) { + return PlayerApiFp(this.configuration) + .banControllerCreate(banCreateDTO, options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * Unban player. This will remove the ban from Takaro and the gameserver(s) Required permissions: `MANAGE_PLAYERS` + * @summary Unban player + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof PlayerApi + */ + public banControllerDelete(id: string, options?: RawAxiosRequestConfig) { + return PlayerApiFp(this.configuration) + .banControllerDelete(id, options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * Get a single ban Required permissions: `READ_PLAYERS` + * @summary Get a single ban + * @param {string} id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof PlayerApi + */ + public banControllerGetOne(id: string, options?: RawAxiosRequestConfig) { + return PlayerApiFp(this.configuration) + .banControllerGetOne(id, options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * Search for bans Required permissions: `READ_PLAYERS` + * @summary Search for bans + * @param {BanSearchInputDTO} [banSearchInputDTO] BanSearchInputDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof PlayerApi + */ + public banControllerSearch(banSearchInputDTO?: BanSearchInputDTO, options?: RawAxiosRequestConfig) { + return PlayerApiFp(this.configuration) + .banControllerSearch(banSearchInputDTO, options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * Update an existing ban, updating a ban via the API will always make it takaro managed. Required permissions: `MANAGE_PLAYERS` + * @summary Update ban + * @param {string} id + * @param {BanUpdateDTO} [banUpdateDTO] BanUpdateDTO + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof PlayerApi + */ + public banControllerUpdate(id: string, banUpdateDTO?: BanUpdateDTO, options?: RawAxiosRequestConfig) { + return PlayerApiFp(this.configuration) + .banControllerUpdate(id, banUpdateDTO, options) + .then((request) => request(this.axios, this.basePath)); + } + /** * Required permissions: `MANAGE_PLAYERS`, `MANAGE_ROLES` * @summary Assign role @@ -21949,8 +21937,8 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * @param {StatsControllerGetActivityStatsTimeTypeEnum} timeType * @param {StatsControllerGetActivityStatsDataTypeEnum} dataType * @param {string} [gameServerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -21958,8 +21946,8 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration timeType: StatsControllerGetActivityStatsTimeTypeEnum, dataType: StatsControllerGetActivityStatsDataTypeEnum, gameServerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options: RawAxiosRequestConfig = {}, ): Promise => { // verify required parameter 'timeType' is not null or undefined @@ -22052,16 +22040,16 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * @summary Get currency stats * @param {string} gameServerId * @param {string} [playerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetCurrencyStats: async ( gameServerId: string, playerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options: RawAxiosRequestConfig = {}, ): Promise => { // verify required parameter 'gameServerId' is not null or undefined @@ -22115,8 +22103,8 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * @param {string} [moduleId] * @param {string} [playerId] * @param {string} [userId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -22128,8 +22116,8 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration moduleId?: string, playerId?: string, userId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options: RawAxiosRequestConfig = {}, ): Promise => { // verify required parameter 'eventName' is not null or undefined @@ -22199,15 +22187,15 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * The roundtrip time for reachability tests between Takaro and the game server * @summary Get latency stats * @param {string} gameServerId - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetLatencyStats: async ( gameServerId: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options: RawAxiosRequestConfig = {}, ): Promise => { // verify required parameter 'gameServerId' is not null or undefined @@ -22252,16 +22240,16 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * @summary Get ping stats * @param {string} gameServerId * @param {string} playerId - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetPingStats: async ( gameServerId: string, playerId: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options: RawAxiosRequestConfig = {}, ): Promise => { // verify required parameter 'gameServerId' is not null or undefined @@ -22311,15 +22299,15 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * Required permissions: `READ_PLAYERS` * @summary Get player online stats * @param {string} [gameServerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetPlayerOnlineStats: async ( gameServerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options: RawAxiosRequestConfig = {}, ): Promise => { const localVarPath = `/stats/players-online`; @@ -22373,8 +22361,8 @@ export const StatsApiFp = function (configuration?: Configuration) { * @param {StatsControllerGetActivityStatsTimeTypeEnum} timeType * @param {StatsControllerGetActivityStatsDataTypeEnum} dataType * @param {string} [gameServerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -22382,8 +22370,8 @@ export const StatsApiFp = function (configuration?: Configuration) { timeType: StatsControllerGetActivityStatsTimeTypeEnum, dataType: StatsControllerGetActivityStatsDataTypeEnum, gameServerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetActivityStats( @@ -22433,16 +22421,16 @@ export const StatsApiFp = function (configuration?: Configuration) { * @summary Get currency stats * @param {string} gameServerId * @param {string} [playerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ async statsControllerGetCurrencyStats( gameServerId: string, playerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetCurrencyStats( @@ -22473,8 +22461,8 @@ export const StatsApiFp = function (configuration?: Configuration) { * @param {string} [moduleId] * @param {string} [playerId] * @param {string} [userId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -22486,8 +22474,8 @@ export const StatsApiFp = function (configuration?: Configuration) { moduleId?: string, playerId?: string, userId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetEventsCount( @@ -22517,15 +22505,15 @@ export const StatsApiFp = function (configuration?: Configuration) { * The roundtrip time for reachability tests between Takaro and the game server * @summary Get latency stats * @param {string} gameServerId - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ async statsControllerGetLatencyStats( gameServerId: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetLatencyStats( @@ -22550,16 +22538,16 @@ export const StatsApiFp = function (configuration?: Configuration) { * @summary Get ping stats * @param {string} gameServerId * @param {string} playerId - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ async statsControllerGetPingStats( gameServerId: string, playerId: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetPingStats( @@ -22584,15 +22572,15 @@ export const StatsApiFp = function (configuration?: Configuration) { * Required permissions: `READ_PLAYERS` * @summary Get player online stats * @param {string} [gameServerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ async statsControllerGetPlayerOnlineStats( gameServerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetPlayerOnlineStats( @@ -22628,8 +22616,8 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * @param {StatsControllerGetActivityStatsTimeTypeEnum} timeType * @param {StatsControllerGetActivityStatsDataTypeEnum} dataType * @param {string} [gameServerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -22637,8 +22625,8 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath timeType: StatsControllerGetActivityStatsTimeTypeEnum, dataType: StatsControllerGetActivityStatsDataTypeEnum, gameServerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22665,16 +22653,16 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * @summary Get currency stats * @param {string} gameServerId * @param {string} [playerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetCurrencyStats( gameServerId: string, playerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22691,8 +22679,8 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * @param {string} [moduleId] * @param {string} [playerId] * @param {string} [userId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -22704,8 +22692,8 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath moduleId?: string, playerId?: string, userId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22727,15 +22715,15 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * The roundtrip time for reachability tests between Takaro and the game server * @summary Get latency stats * @param {string} gameServerId - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetLatencyStats( gameServerId: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22747,16 +22735,16 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * @summary Get ping stats * @param {string} gameServerId * @param {string} playerId - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetPingStats( gameServerId: string, playerId: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22767,15 +22755,15 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * Required permissions: `READ_PLAYERS` * @summary Get player online stats * @param {string} [gameServerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetPlayerOnlineStats( gameServerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22798,8 +22786,8 @@ export class StatsApi extends BaseAPI { * @param {StatsControllerGetActivityStatsTimeTypeEnum} timeType * @param {StatsControllerGetActivityStatsDataTypeEnum} dataType * @param {string} [gameServerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi @@ -22808,8 +22796,8 @@ export class StatsApi extends BaseAPI { timeType: StatsControllerGetActivityStatsTimeTypeEnum, dataType: StatsControllerGetActivityStatsDataTypeEnum, gameServerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) @@ -22836,8 +22824,8 @@ export class StatsApi extends BaseAPI { * @summary Get currency stats * @param {string} gameServerId * @param {string} [playerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi @@ -22845,8 +22833,8 @@ export class StatsApi extends BaseAPI { public statsControllerGetCurrencyStats( gameServerId: string, playerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) @@ -22864,8 +22852,8 @@ export class StatsApi extends BaseAPI { * @param {string} [moduleId] * @param {string} [playerId] * @param {string} [userId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi @@ -22878,8 +22866,8 @@ export class StatsApi extends BaseAPI { moduleId?: string, playerId?: string, userId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) @@ -22902,16 +22890,16 @@ export class StatsApi extends BaseAPI { * The roundtrip time for reachability tests between Takaro and the game server * @summary Get latency stats * @param {string} gameServerId - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi */ public statsControllerGetLatencyStats( gameServerId: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) @@ -22924,8 +22912,8 @@ export class StatsApi extends BaseAPI { * @summary Get ping stats * @param {string} gameServerId * @param {string} playerId - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi @@ -22933,8 +22921,8 @@ export class StatsApi extends BaseAPI { public statsControllerGetPingStats( gameServerId: string, playerId: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) @@ -22946,16 +22934,16 @@ export class StatsApi extends BaseAPI { * Required permissions: `READ_PLAYERS` * @summary Get player online stats * @param {string} [gameServerId] - * @param {string} [startDate] - * @param {string} [endDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] + * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi */ public statsControllerGetPlayerOnlineStats( gameServerId?: string, - startDate?: string, - endDate?: string, + startDate?: StatsControllerGetPingStatsStartDateParameter, + endDate?: StatsControllerGetPingStatsStartDateParameter, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) diff --git a/packages/lib-apiclient/src/generated/base.ts b/packages/lib-apiclient/src/generated/base.ts index f29ef6fbe6..b8bd4230cc 100644 --- a/packages/lib-apiclient/src/generated/base.ts +++ b/packages/lib-apiclient/src/generated/base.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Takaro app-api + * Takaro API * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - f80f6d034a7760e0429de59c786ff04802006bc9 + * The version of the OpenAPI document: unset - unset * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/common.ts b/packages/lib-apiclient/src/generated/common.ts index ec2d51ebf2..f2f7f5a3a1 100644 --- a/packages/lib-apiclient/src/generated/common.ts +++ b/packages/lib-apiclient/src/generated/common.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Takaro app-api + * Takaro API * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - f80f6d034a7760e0429de59c786ff04802006bc9 + * The version of the OpenAPI document: unset - unset * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index 30ec99672a..2c85febd69 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Takaro app-api + * Takaro API * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - f80f6d034a7760e0429de59c786ff04802006bc9 + * The version of the OpenAPI document: unset - unset * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/index.ts b/packages/lib-apiclient/src/generated/index.ts index 431db2e536..ff32b04e21 100644 --- a/packages/lib-apiclient/src/generated/index.ts +++ b/packages/lib-apiclient/src/generated/index.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Takaro app-api + * Takaro API * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - f80f6d034a7760e0429de59c786ff04802006bc9 + * The version of the OpenAPI document: unset - unset * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/lib/client.ts b/packages/lib-apiclient/src/lib/client.ts index 7e5496ffa5..1294f0ac46 100644 --- a/packages/lib-apiclient/src/lib/client.ts +++ b/packages/lib-apiclient/src/lib/client.ts @@ -17,7 +17,6 @@ import { StatsApi, ShopOrderApi, ShopListingApi, - BanApi, } from '../generated/api.js'; import { BaseApiClient, IBaseApiClientConfig } from './baseClient.js'; @@ -262,14 +261,4 @@ export class Client extends BaseApiClient { this.axios, ); } - - get ban() { - return new BanApi( - { - isJsonMime: this.isJsonMime, - }, - '', - this.axios, - ); - } } From 628e565ef1e3019fd5952236dcae60e1f44c5a34 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 16:33:22 +0100 Subject: [PATCH 03/48] chore: add deprecated notice to old ban endpoints and migrate old usage --- packages/app-api/src/controllers/GameServerController.ts | 3 +++ .../lib-modules/src/modules/geoBlock/hooks/IPDetected.js | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/app-api/src/controllers/GameServerController.ts b/packages/app-api/src/controllers/GameServerController.ts index 1a6aec458e..fbc96152df 100644 --- a/packages/app-api/src/controllers/GameServerController.ts +++ b/packages/app-api/src/controllers/GameServerController.ts @@ -461,6 +461,7 @@ export class GameServerController { @ResponseSchema(APIOutput) @OpenAPI({ description: 'Ban a player from a gameserver. Requires gameserver to be online and reachable.', + deprecated: true, }) @Post('/gameserver/:gameServerId/player/:playerId/ban') async banPlayer(@Req() req: AuthenticatedRequest, @Params() params: PogParam, @Body() data: BanPlayerInputDTO) { @@ -473,6 +474,7 @@ export class GameServerController { @ResponseSchema(APIOutput) @OpenAPI({ description: 'Unban a player from a gameserver. Requires gameserver to be online and reachable.', + deprecated: true, }) @Post('/gameserver/:gameServerId/player/:playerId/unban') async unbanPlayer(@Req() req: AuthenticatedRequest, @Params() params: PogParam) { @@ -485,6 +487,7 @@ export class GameServerController { @ResponseSchema(BanPlayerOutputDTO) @OpenAPI({ description: 'List bans for a gameserver. Requires gameserver to be online and reachable.', + deprecated: true, }) @Get('/gameserver/:id/bans') async listBans(@Req() req: AuthenticatedRequest, @Params() params: ParamId) { diff --git a/packages/lib-modules/src/modules/geoBlock/hooks/IPDetected.js b/packages/lib-modules/src/modules/geoBlock/hooks/IPDetected.js index 221ff1d4fa..de4cc1bc2b 100644 --- a/packages/lib-modules/src/modules/geoBlock/hooks/IPDetected.js +++ b/packages/lib-modules/src/modules/geoBlock/hooks/IPDetected.js @@ -9,9 +9,11 @@ async function main() { if (ban) { const now = new Date(); const expiresAt = new Date(now.getTime() + banDuration * 1000); - await takaro.gameserver.gameServerControllerBanPlayer(gameServerId, player.id, { + await takaro.player.banControllerCreate({ + gameServerId, + playerId: player.id, + until: expiresAt, reason: message, - expiresAt, }); } else { await takaro.gameserver.gameServerControllerKickPlayer(gameServerId, player.id, { From 1665be8f185f2e4ca7a2225f207f3200a64c8066 Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:36:43 +0000 Subject: [PATCH 04/48] fix: code style --- packages/web-docs/docs/modules.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web-docs/docs/modules.json b/packages/web-docs/docs/modules.json index e5f4728684..fa253d0e02 100644 --- a/packages/web-docs/docs/modules.json +++ b/packages/web-docs/docs/modules.json @@ -533,7 +533,7 @@ { "eventType": "player-new-ip-detected", "name": "IPDetected", - "function": "import { takaro, data, checkPermission } from '@takaro/helpers';\nasync function main() {\n const { gameServerId, player, pog } = data;\n const { country } = data.eventData;\n const { ban, banDuration, countries, message, mode } = data.module.userConfig;\n async function handleAction() {\n if (ban) {\n const now = new Date();\n const expiresAt = new Date(now.getTime() + banDuration * 1000);\n await takaro.gameserver.gameServerControllerBanPlayer(gameServerId, player.id, {\n reason: message,\n expiresAt,\n });\n }\n else {\n await takaro.gameserver.gameServerControllerKickPlayer(gameServerId, player.id, {\n reason: message,\n });\n }\n }\n const isImmune = checkPermission(pog, 'GEOBLOCK_IMMUNITY');\n if (isImmune) {\n console.log('Player has immunity, no action');\n return;\n }\n if (mode === 'allow') {\n if (countries.includes(country)) {\n console.log('Allowed country detected, no action');\n return;\n }\n console.log('Blocked country detected, performing actions');\n await handleAction();\n return;\n }\n if (mode === 'deny') {\n if (countries.includes(country)) {\n console.log('Blocked country detected, performing actions');\n await handleAction();\n return;\n }\n else {\n console.log('Allowed country detected, no action');\n return;\n }\n }\n}\nawait main();\n//# sourceMappingURL=IPDetected.js.map" + "function": "import { takaro, data, checkPermission } from '@takaro/helpers';\nasync function main() {\n const { gameServerId, player, pog } = data;\n const { country } = data.eventData;\n const { ban, banDuration, countries, message, mode } = data.module.userConfig;\n async function handleAction() {\n if (ban) {\n const now = new Date();\n const expiresAt = new Date(now.getTime() + banDuration * 1000);\n await takaro.player.banControllerCreate({\n gameServerId,\n playerId: player.id,\n until: expiresAt,\n reason: message,\n });\n }\n else {\n await takaro.gameserver.gameServerControllerKickPlayer(gameServerId, player.id, {\n reason: message,\n });\n }\n }\n const isImmune = checkPermission(pog, 'GEOBLOCK_IMMUNITY');\n if (isImmune) {\n console.log('Player has immunity, no action');\n return;\n }\n if (mode === 'allow') {\n if (countries.includes(country)) {\n console.log('Allowed country detected, no action');\n return;\n }\n console.log('Blocked country detected, performing actions');\n await handleAction();\n return;\n }\n if (mode === 'deny') {\n if (countries.includes(country)) {\n console.log('Blocked country detected, performing actions');\n await handleAction();\n return;\n }\n else {\n console.log('Allowed country detected, no action');\n return;\n }\n }\n}\nawait main();\n//# sourceMappingURL=IPDetected.js.map" } ], "cronJobs": [], From 7cb897a9686f6a8a14e81297a3c9f897ec8f212b Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 17:17:33 +0100 Subject: [PATCH 05/48] fix: some issue detecting bans on Rust --- packages/lib-gameserver/src/gameservers/rust/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/lib-gameserver/src/gameservers/rust/index.ts b/packages/lib-gameserver/src/gameservers/rust/index.ts index 33268771f7..3d79fa8df5 100644 --- a/packages/lib-gameserver/src/gameservers/rust/index.ts +++ b/packages/lib-gameserver/src/gameservers/rust/index.ts @@ -175,7 +175,7 @@ export class Rust implements IGameServer { async listBans(): Promise { const response = await this.executeConsoleCommand('banlistex'); - if (!response.success || !response.rawResult) { + if (!response.rawResult) { return []; } @@ -200,8 +200,9 @@ export class Rust implements IGameServer { const ban = new BanDTO({ reason: match.groups.reason, - player: new IPlayerReferenceDTO({ + player: new IGamePlayer({ gameId, + steamId: gameId, }), expiresAt, }); From 31c2d9e40f4001ff790202cef8579c1f7bdf5bb1 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 17:20:41 +0100 Subject: [PATCH 06/48] fix: some unit tests broke in 7d2d --- .../7d2d/__tests__/7d2dActions.unit.test.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/lib-gameserver/src/gameservers/7d2d/__tests__/7d2dActions.unit.test.ts b/packages/lib-gameserver/src/gameservers/7d2d/__tests__/7d2dActions.unit.test.ts index 3521cb7b5c..f29747aa5f 100644 --- a/packages/lib-gameserver/src/gameservers/7d2d/__tests__/7d2dActions.unit.test.ts +++ b/packages/lib-gameserver/src/gameservers/7d2d/__tests__/7d2dActions.unit.test.ts @@ -34,7 +34,8 @@ describe('7d2d Actions', () => { expect(result).to.be.an('array'); expect(result).to.have.lengthOf(1); - expect(result[0].player.gameId).to.equal('EOS_00028a9b73bb45b2b74e8f22cda7d225'); + expect(result[0].player.gameId).to.equal('00028a9b73bb45b2b74e8f22cda7d225'); + expect(result[0].player.epicOnlineServicesId).to.equal('00028a9b73bb45b2b74e8f22cda7d225'); expect(result[0].expiresAt).to.equal('2023-06-29T19:39:56.000Z'); }); @@ -51,10 +52,12 @@ describe('7d2d Actions', () => { expect(result).to.be.an('array'); expect(result).to.have.lengthOf(2); - expect(result[0].player.gameId).to.equal('EOS_0002e0daea3b493fa146ce6d06e79a57'); + expect(result[0].player.gameId).to.equal('0002e0daea3b493fa146ce6d06e79a57'); + expect(result[0].player.epicOnlineServicesId).to.equal('0002e0daea3b493fa146ce6d06e79a57'); expect(result[0].expiresAt).to.equal('2028-06-29T17:49:45.000Z'); - expect(result[1].player.gameId).to.equal('EOS_00028a9b73bb45b2b74e8f22cda7d225'); + expect(result[1].player.gameId).to.equal('00028a9b73bb45b2b74e8f22cda7d225'); + expect(result[1].player.epicOnlineServicesId).to.equal('00028a9b73bb45b2b74e8f22cda7d225'); expect(result[1].expiresAt).to.equal('2028-06-29T19:19:40.000Z'); }); @@ -84,7 +87,8 @@ describe('7d2d Actions', () => { expect(result).to.be.an('array'); expect(result).to.have.lengthOf(1); - expect(result[0].player.gameId).to.equal('EOS_00028a9b73bb45b2b74e8f22cda7d225'); + expect(result[0].player.gameId).to.equal('00028a9b73bb45b2b74e8f22cda7d225'); + expect(result[0].player.epicOnlineServicesId).to.equal('00028a9b73bb45b2b74e8f22cda7d225'); expect(result[0].expiresAt).to.equal('2023-06-29T19:40:59.000Z'); }); }); From c6acf761b2777668e78c1e04a462d8bdb7dae0c7 Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:54:01 +0000 Subject: [PATCH 07/48] fix: code style --- packages/lib-apiclient/src/generated/configuration.ts | 8 ++++---- packages/web-docs/docs/modules/geoBlock.mdx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index c4517c3456..2c85febd69 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -17,10 +17,10 @@ export interface ConfigurationParameters { username?: string; password?: string; accessToken?: - | string - | Promise - | ((name?: string, scopes?: string[]) => string) - | ((name?: string, scopes?: string[]) => Promise); + | string + | Promise + | ((name?: string, scopes?: string[]) => string) + | ((name?: string, scopes?: string[]) => Promise); basePath?: string; serverIndex?: number; baseOptions?: any; diff --git a/packages/web-docs/docs/modules/geoBlock.mdx b/packages/web-docs/docs/modules/geoBlock.mdx index 379475874d..abf3379597 100644 --- a/packages/web-docs/docs/modules/geoBlock.mdx +++ b/packages/web-docs/docs/modules/geoBlock.mdx @@ -10,7 +10,7 @@ export function Module() { { "eventType": "player-new-ip-detected", "name": "IPDetected", - "function": "import { takaro, data, checkPermission } from '@takaro/helpers';\nasync function main() {\n const { gameServerId, player, pog } = data;\n const { country } = data.eventData;\n const { ban, banDuration, countries, message, mode } = data.module.userConfig;\n async function handleAction() {\n if (ban) {\n const now = new Date();\n const expiresAt = new Date(now.getTime() + banDuration * 1000);\n await takaro.gameserver.gameServerControllerBanPlayer(gameServerId, player.id, {\n reason: message,\n expiresAt,\n });\n }\n else {\n await takaro.gameserver.gameServerControllerKickPlayer(gameServerId, player.id, {\n reason: message,\n });\n }\n }\n const isImmune = checkPermission(pog, 'GEOBLOCK_IMMUNITY');\n if (isImmune) {\n console.log('Player has immunity, no action');\n return;\n }\n if (mode === 'allow') {\n if (countries.includes(country)) {\n console.log('Allowed country detected, no action');\n return;\n }\n console.log('Blocked country detected, performing actions');\n await handleAction();\n return;\n }\n if (mode === 'deny') {\n if (countries.includes(country)) {\n console.log('Blocked country detected, performing actions');\n await handleAction();\n return;\n }\n else {\n console.log('Allowed country detected, no action');\n return;\n }\n }\n}\nawait main();\n//# sourceMappingURL=IPDetected.js.map" + "function": "import { takaro, data, checkPermission } from '@takaro/helpers';\nasync function main() {\n const { gameServerId, player, pog } = data;\n const { country } = data.eventData;\n const { ban, banDuration, countries, message, mode } = data.module.userConfig;\n async function handleAction() {\n if (ban) {\n const now = new Date();\n const expiresAt = new Date(now.getTime() + banDuration * 1000);\n await takaro.player.banControllerCreate({\n gameServerId,\n playerId: player.id,\n until: expiresAt,\n reason: message,\n });\n }\n else {\n await takaro.gameserver.gameServerControllerKickPlayer(gameServerId, player.id, {\n reason: message,\n });\n }\n }\n const isImmune = checkPermission(pog, 'GEOBLOCK_IMMUNITY');\n if (isImmune) {\n console.log('Player has immunity, no action');\n return;\n }\n if (mode === 'allow') {\n if (countries.includes(country)) {\n console.log('Allowed country detected, no action');\n return;\n }\n console.log('Blocked country detected, performing actions');\n await handleAction();\n return;\n }\n if (mode === 'deny') {\n if (countries.includes(country)) {\n console.log('Blocked country detected, performing actions');\n await handleAction();\n return;\n }\n else {\n console.log('Allowed country detected, no action');\n return;\n }\n }\n}\nawait main();\n//# sourceMappingURL=IPDetected.js.map" } ], "cronJobs": [], From 7fd0e67e10cf76717bbcb01d89e246baf6b27dd6 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 20:25:41 +0100 Subject: [PATCH 08/48] fix: cannot switch to current domain --- packages/web-main/src/routes/_auth/domain.select.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/web-main/src/routes/_auth/domain.select.tsx b/packages/web-main/src/routes/_auth/domain.select.tsx index f8d0ad64d9..55dc034542 100644 --- a/packages/web-main/src/routes/_auth/domain.select.tsx +++ b/packages/web-main/src/routes/_auth/domain.select.tsx @@ -82,6 +82,8 @@ function DomainCard({ domain, isCurrentDomain }: DomainCardProps) { const handleDomainSelectedClick = () => { if (isCurrentDomain === false) { mutate({ domainId: domain.id }); + } else { + navigate({ to: '/dashboard' }); } }; From f1940b9647564d68aeefa0379ceddb14af770212 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 20:32:53 +0100 Subject: [PATCH 09/48] fix: show that domain is disabled in domain select --- packages/web-main/src/routes/_auth/domain.select.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/web-main/src/routes/_auth/domain.select.tsx b/packages/web-main/src/routes/_auth/domain.select.tsx index f8d0ad64d9..d78e617ce4 100644 --- a/packages/web-main/src/routes/_auth/domain.select.tsx +++ b/packages/web-main/src/routes/_auth/domain.select.tsx @@ -1,5 +1,5 @@ import { Card, Chip, Company, styled } from '@takaro/lib-components'; -import { DomainOutputDTO } from '@takaro/apiclient'; +import { DomainOutputDTO, DomainOutputDTOStateEnum } from '@takaro/apiclient'; import { createFileRoute, useNavigate } from '@tanstack/react-router'; import { useUserSetSelectedDomain, userMeQueryOptions } from 'queries/user'; import { MdDomain as DomainIcon } from 'react-icons/md'; @@ -78,8 +78,12 @@ function DomainCard({ domain, isCurrentDomain }: DomainCardProps) { const navigate = useNavigate(); const { mutate, isSuccess } = useUserSetSelectedDomain(); const queryClient = useQueryClient(); + const isDisabled = domain.state === DomainOutputDTOStateEnum.Disabled; const handleDomainSelectedClick = () => { + // Logging into a disabled domain is going to error out + if (isDisabled) return; + if (isCurrentDomain === false) { mutate({ domainId: domain.id }); } @@ -97,6 +101,7 @@ function DomainCard({ domain, isCurrentDomain }: DomainCardProps) {
{isCurrentDomain && } + {isDisabled && }

{domain.name} From acaee9cee8923e44105c33356f0240c9ea2e5709 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 20:37:58 +0100 Subject: [PATCH 10/48] fix: improve flow when logging in and there are disabled domains in play --- packages/app-api/src/controllers/UserController.ts | 2 +- packages/app-api/src/service/AuthService.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/app-api/src/controllers/UserController.ts b/packages/app-api/src/controllers/UserController.ts index 7b9611e273..c09369f135 100644 --- a/packages/app-api/src/controllers/UserController.ts +++ b/packages/app-api/src/controllers/UserController.ts @@ -151,7 +151,7 @@ export class UserController { } @Get('/me') - @UseBefore(AuthService.getAuthMiddleware([])) + @UseBefore(AuthService.getAuthMiddleware([], false)) @ResponseSchema(MeOutoutDTOAPI) @OpenAPI({ summary: 'Get the current logged in user', diff --git a/packages/app-api/src/service/AuthService.ts b/packages/app-api/src/service/AuthService.ts index 1a61f36e38..769a9cef39 100644 --- a/packages/app-api/src/service/AuthService.ts +++ b/packages/app-api/src/service/AuthService.ts @@ -13,7 +13,7 @@ import { Routes, RESTGetAPICurrentUserGuildsResult } from 'discord-api-types/v10 import oauth from 'passport-oauth2'; import { DiscordService } from './DiscordService.js'; import { domainStateMiddleware } from '../middlewares/domainStateMiddleware.js'; -import { DomainService } from './DomainService.js'; +import { DOMAIN_STATES, DomainService } from './DomainService.js'; interface DiscordUserInfo { id: string; @@ -193,7 +193,8 @@ export class AuthService extends DomainScoped { log.warn(`No domain found for identity ${identity.id}`); throw new errors.UnauthorizedError(); } - domainId = domains[0].id; + // Find the first active domain + domainId = domains.find((d) => d.state === DOMAIN_STATES.ACTIVE)?.id; // Set the domain cookie if (req.res?.cookie) From 250621acf155f2a2b6dd0f6501b693cfac28e33e Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 21:48:50 +0100 Subject: [PATCH 11/48] fix: better error message to user when we cannot determine domain --- packages/app-api/src/service/AuthService.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/app-api/src/service/AuthService.ts b/packages/app-api/src/service/AuthService.ts index 769a9cef39..c3c1212327 100644 --- a/packages/app-api/src/service/AuthService.ts +++ b/packages/app-api/src/service/AuthService.ts @@ -196,6 +196,13 @@ export class AuthService extends DomainScoped { // Find the first active domain domainId = domains.find((d) => d.state === DOMAIN_STATES.ACTIVE)?.id; + if (!domainId && domains.length) { + log.warn( + `No active domain found for identity (but domains found: ${domains.map((d) => ({ id: d.id, state: d.state })).join(',')})`, + ); + throw new errors.BadRequestError('Domain is disabled. Please contact support.'); + } + // Set the domain cookie if (req.res?.cookie) req.res?.cookie('takaro-domain', domainId, { @@ -216,6 +223,9 @@ export class AuthService extends DomainScoped { } catch (error) { // Not an ory session, throw a sanitized error log.warn(error); + // If we explicitly throw a BadRequestError, we want to pass it through + // So the client gets a meaningful error message + if (error instanceof errors.BadRequestError) throw error; throw new errors.UnauthorizedError(); } } @@ -251,6 +261,9 @@ export class AuthService extends DomainScoped { if (domainStateCheck) return domainStateMiddleware(req, _res, next); return next(); } catch (error) { + // If we explicitly throw a BadRequestError, we want to pass it through + // So the client gets a meaningful error message + if (error instanceof errors.BadRequestError) return next(error); log.error('Unexpected error in auth middleware', error); return next(new errors.ForbiddenError()); } From 3cd82f0084e008c0a051208de768e0a757eed491 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 23:15:47 +0100 Subject: [PATCH 12/48] feat: add daily rewards module --- packages/app-api/src/domainInit.ts | 2 +- packages/lib-modules/src/main.ts | 2 + .../modules/dailyRewards/commands/daily.js | 118 +++++++++++++++++ .../modules/dailyRewards/commands/streak.js | 42 ++++++ .../dailyRewards/commands/topstreak.js | 54 ++++++++ .../modules/dailyRewards/functions/utils.js | 36 +++++ .../dailyRewards/hooks/dailyLoginCheck.js | 23 ++++ .../src/modules/dailyRewards/index.ts | 125 ++++++++++++++++++ 8 files changed, 401 insertions(+), 1 deletion(-) create mode 100644 packages/lib-modules/src/modules/dailyRewards/commands/daily.js create mode 100644 packages/lib-modules/src/modules/dailyRewards/commands/streak.js create mode 100644 packages/lib-modules/src/modules/dailyRewards/commands/topstreak.js create mode 100644 packages/lib-modules/src/modules/dailyRewards/functions/utils.js create mode 100644 packages/lib-modules/src/modules/dailyRewards/hooks/dailyLoginCheck.js create mode 100644 packages/lib-modules/src/modules/dailyRewards/index.ts diff --git a/packages/app-api/src/domainInit.ts b/packages/app-api/src/domainInit.ts index 8144c56268..51a8c2a8fe 100644 --- a/packages/app-api/src/domainInit.ts +++ b/packages/app-api/src/domainInit.ts @@ -40,7 +40,7 @@ async function main() { const results = await Promise.allSettled(domains.results.map(ctx.wrap('domainInit', domainInit))); const rejected = results.map((r) => (r.status === 'rejected' ? r.reason : null)).filter(Boolean); if (rejected.length) { - log.error('Failed to initialize some domains', { errors: rejected }); + log.error('Failed to initialize some domains', { errors: JSON.stringify(rejected) }); } process.exit(0); diff --git a/packages/lib-modules/src/main.ts b/packages/lib-modules/src/main.ts index 4300cc49be..e2d76231f2 100644 --- a/packages/lib-modules/src/main.ts +++ b/packages/lib-modules/src/main.ts @@ -1,5 +1,6 @@ import { BuiltinModule } from './BuiltinModule.js'; import { ChatBridge } from './modules/chatBridge/index.js'; +import { DailyRewards } from './modules/dailyRewards/index.js'; import { EconomyUtils } from './modules/economyUtils/index.js'; import { GeoBlock } from './modules/geoBlock/index.js'; import { Gimme } from './modules/gimme/index.js'; @@ -30,6 +31,7 @@ export function getModules(): Array> { new Lottery(), new GeoBlock(), new TimedShutdown(), + new DailyRewards(), ]; } diff --git a/packages/lib-modules/src/modules/dailyRewards/commands/daily.js b/packages/lib-modules/src/modules/dailyRewards/commands/daily.js new file mode 100644 index 0000000000..736b75a776 --- /dev/null +++ b/packages/lib-modules/src/modules/dailyRewards/commands/daily.js @@ -0,0 +1,118 @@ +import { takaro, data, TakaroUserError, checkPermission } from '@takaro/helpers'; +import { DAILY_KEY, STREAK_KEY, getMultiplier } from './utils.js'; + +async function main() { + const { pog, gameServerId, module: mod } = data; + + if (!checkPermission(pog, 'DAILY_CLAIM')) { + throw new TakaroUserError('You do not have permission to claim daily rewards.'); + } + + // Get last claim time + const lastClaimRes = await takaro.variable.variableControllerSearch({ + filters: { + key: [DAILY_KEY], + gameServerId: [gameServerId], + playerId: [pog.playerId], + moduleId: [mod.moduleId], + }, + }); + + const now = new Date(); + let streak = 1; + + if (lastClaimRes.data.data.length > 0) { + const lastClaim = new Date(JSON.parse(lastClaimRes.data.data[0].value)); + const hoursSinceLastClaim = (now - lastClaim) / (1000 * 60 * 60); + + // Check if 24 hours have passed + if (hoursSinceLastClaim < 24) { + const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000); + throw new TakaroUserError(`You can claim your next reward at ${nextClaimTime.toLocaleString()}`); + } + + // Get current streak + const streakRes = await takaro.variable.variableControllerSearch({ + filters: { + key: [STREAK_KEY], + gameServerId: [gameServerId], + playerId: [pog.playerId], + moduleId: [mod.moduleId], + }, + }); + + if (streakRes.data.data.length > 0) { + // If claimed within 48 hours, increment streak + if (hoursSinceLastClaim < 48) { + streak = Math.min(JSON.parse(streakRes.data.data[0].value) + 1, mod.userConfig.maxStreak); + await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, { + value: JSON.stringify(streak), + }); + } else { + // Reset streak if more than 48 hours + await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, { + value: JSON.stringify(1), + }); + } + } else { + // Create new streak record + await takaro.variable.variableControllerCreate({ + key: STREAK_KEY, + value: JSON.stringify(1), + gameServerId, + playerId: pog.playerId, + moduleId: mod.moduleId, + }); + } + + // Update last claim time + await takaro.variable.variableControllerUpdate(lastClaimRes.data.data[0].id, { + value: JSON.stringify(now), + }); + } else { + // First time claim + await takaro.variable.variableControllerCreate({ + key: DAILY_KEY, + value: JSON.stringify(now), + gameServerId, + playerId: pog.playerId, + moduleId: mod.moduleId, + }); + await takaro.variable.variableControllerCreate({ + key: STREAK_KEY, + value: JSON.stringify(1), + gameServerId, + playerId: pog.playerId, + moduleId: mod.moduleId, + }); + } + + const multiplier = await getMultiplier(pog); + const baseReward = mod.userConfig.baseReward * streak * multiplier; + let bonusReward = 0; + let milestoneMessage = ''; + + // Check for milestones + for (const milestone of mod.userConfig.milestoneRewards) { + if (streak === milestone.days) { + bonusReward = milestone.reward; + milestoneMessage = `\n${milestone.message}`; + break; + } + } + + // Award total rewards + const totalReward = baseReward + bonusReward; + await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(gameServerId, pog.playerId, { + currency: totalReward, + }); + + const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', gameServerId)).data.data.value; + await pog.pm( + `Daily reward claimed! You received ${totalReward} ${currencyName}\n` + + `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x bonus!)` : ''}` + + milestoneMessage, + ); +} + +await main(); diff --git a/packages/lib-modules/src/modules/dailyRewards/commands/streak.js b/packages/lib-modules/src/modules/dailyRewards/commands/streak.js new file mode 100644 index 0000000000..824e1681b2 --- /dev/null +++ b/packages/lib-modules/src/modules/dailyRewards/commands/streak.js @@ -0,0 +1,42 @@ +import { data } from '@takaro/helpers'; +import { getPlayerStreak, getLastClaim, getMultiplier } from './utils.js'; + +async function main() { + const { pog, gameServerId, module: mod } = data; + + const streak = await getPlayerStreak(gameServerId, pog.playerId, mod.moduleId); + const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId); + const multiplier = await getMultiplier(pog); + + if (!streak || !lastClaim) { + // eslint-disable-next-line quotes + await pog.pm("You haven't claimed any daily rewards yet! Use /daily to get started."); + return; + } + + const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000); + const now = new Date(); + const canClaim = now >= nextClaimTime; + + // Find next milestone + let nextMilestone = null; + for (const milestone of mod.userConfig.milestoneRewards) { + if (milestone.days > streak) { + nextMilestone = milestone; + break; + } + } + + let message = `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x donor bonus!)` : ''}\n`; + message += canClaim + ? 'Your daily reward is available! Use /daily to claim it!\n' + : `Next reward available at: ${nextClaimTime.toLocaleString()}\n`; + + if (nextMilestone) { + message += `\n🎯 Next milestone: ${nextMilestone.days} days (${nextMilestone.days - streak} days to go!)`; + } + + await pog.pm(message); +} + +await main(); diff --git a/packages/lib-modules/src/modules/dailyRewards/commands/topstreak.js b/packages/lib-modules/src/modules/dailyRewards/commands/topstreak.js new file mode 100644 index 0000000000..ab15fc1969 --- /dev/null +++ b/packages/lib-modules/src/modules/dailyRewards/commands/topstreak.js @@ -0,0 +1,54 @@ +import { takaro, data } from '@takaro/helpers'; +import { STREAK_KEY } from './utils.js'; + +async function main() { + const { pog, gameServerId, module: mod, arguments: args } = data; + + // Limit count to reasonable number + const count = Math.min(Math.max(1, args.count), 50); + + // Get all streaks + const streaksRes = await takaro.variable.variableControllerSearch({ + filters: { + key: [STREAK_KEY], + gameServerId: [gameServerId], + moduleId: [mod.moduleId], + }, + limit: 1000, // Get all possible streaks + }); + + if (streaksRes.data.data.length === 0) { + await pog.pm('No players have started their daily streak yet!'); + return; + } + + // Sort by streak value + const sortedStreaks = streaksRes.data.data + .map((record) => ({ + playerId: record.playerId, + streak: JSON.parse(record.value), + })) + .sort((a, b) => b.streak - a.streak) + .slice(0, count); + + // Get player names + const playerDetails = await Promise.all( + sortedStreaks.map(async (record) => { + const player = (await takaro.player.playerControllerGetOne(record.playerId)).data.data; + return { + name: player.name, + streak: record.streak, + }; + }), + ); + + // Build message + let message = `Top ${count} Daily Streaks:\n\n`; + playerDetails.forEach((player, index) => { + message += `${index + 1}. ${player.name}: ${player.streak} days\n`; + }); + + await pog.pm(message); +} + +await main(); diff --git a/packages/lib-modules/src/modules/dailyRewards/functions/utils.js b/packages/lib-modules/src/modules/dailyRewards/functions/utils.js new file mode 100644 index 0000000000..b876c3bea8 --- /dev/null +++ b/packages/lib-modules/src/modules/dailyRewards/functions/utils.js @@ -0,0 +1,36 @@ +import { takaro, checkPermission } from '@takaro/helpers'; + +export const DAILY_KEY = 'daily_timestamp'; +export const STREAK_KEY = 'daily_streak'; + +export async function getMultiplier(pog) { + const perm = checkPermission(pog, 'DAILY_REWARD_MULTIPLIER'); + if (perm) return perm.count; + return 1; +} + +export async function getPlayerStreak(gameServerId, playerId, moduleId) { + const streakRes = await takaro.variable.variableControllerSearch({ + filters: { + key: [STREAK_KEY], + gameServerId: [gameServerId], + playerId: [playerId], + moduleId: [moduleId], + }, + }); + + return streakRes.data.data.length ? parseInt(JSON.parse(streakRes.data.data[0].value)) : 0; +} + +export async function getLastClaim(gameServerId, playerId, moduleId) { + const lastClaimRes = await takaro.variable.variableControllerSearch({ + filters: { + key: [DAILY_KEY], + gameServerId: [gameServerId], + playerId: [playerId], + moduleId: [moduleId], + }, + }); + + return lastClaimRes.data.data.length ? new Date(JSON.parse(lastClaimRes.data.data[0].value)) : null; +} diff --git a/packages/lib-modules/src/modules/dailyRewards/hooks/dailyLoginCheck.js b/packages/lib-modules/src/modules/dailyRewards/hooks/dailyLoginCheck.js new file mode 100644 index 0000000000..975d957f44 --- /dev/null +++ b/packages/lib-modules/src/modules/dailyRewards/hooks/dailyLoginCheck.js @@ -0,0 +1,23 @@ +import { data } from '@takaro/helpers'; +import { getLastClaim } from './utils.js'; + +async function main() { + const { pog, gameServerId, module: mod } = data; + + const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId); + + // First time player + if (!lastClaim) { + await pog.pm('👋 Welcome! Use /daily to claim your first daily reward and start your streak!'); + return; + } + + const now = new Date(); + const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000); + + if (now >= nextClaimTime) { + await pog.pm('🎁 Your daily reward is ready! Use /daily to claim it!'); + } +} + +await main(); diff --git a/packages/lib-modules/src/modules/dailyRewards/index.ts b/packages/lib-modules/src/modules/dailyRewards/index.ts new file mode 100644 index 0000000000..5f7d984f99 --- /dev/null +++ b/packages/lib-modules/src/modules/dailyRewards/index.ts @@ -0,0 +1,125 @@ +import { BuiltinModule, ICommand, IFunction, IHook, IPermission } from '../../BuiltinModule.js'; + +export class DailyRewards extends BuiltinModule { + constructor() { + super( + 'dailyRewards', + 'Provides daily login rewards with streak tracking', + JSON.stringify({ + $schema: 'http://json-schema.org/draft-07/schema#', + type: 'object', + properties: { + baseReward: { + type: 'number', + title: 'Base Reward', + description: 'Base amount of currency given for daily rewards. This is multiplied by streak level.', + default: 100, + minimum: 1, + }, + maxStreak: { + type: 'number', + title: 'Maximum Streak', + description: 'Maximum streak level a player can reach', + default: 365, + minimum: 1, + }, + milestoneRewards: { + type: 'array', + title: 'Milestone Rewards', + description: 'Additional rewards for reaching certain streak milestones', + items: { + type: 'object', + properties: { + days: { + type: 'number', + description: 'Days needed to reach milestone', + minimum: 1, + }, + reward: { + type: 'number', + description: 'Bonus reward amount', + }, + message: { + type: 'string', + description: 'Message to show when milestone is reached', + }, + }, + }, + default: [ + { days: 7, reward: 1000, message: 'You did it! 7 days in a row!' }, + { days: 30, reward: 5000, message: "A whole month! You're on fire!" }, + { days: 90, reward: 20000, message: "90 days! You're unstoppable!" }, + { days: 180, reward: 50000, message: "Half a year! You're a legend!" }, + { days: 365, reward: 150000, message: "365 days! You're a true champion!" }, + ], + }, + }, + required: ['baseReward', 'maxStreak', 'milestoneRewards'], + additionalProperties: false, + }), + ); + + this.functions = [ + new IFunction({ + name: 'utils', + function: this.loadFn('functions', 'utils'), + }), + ]; + + this.permissions = [ + new IPermission({ + permission: 'DAILY_CLAIM', + friendlyName: 'Claim Daily Rewards', + description: 'Allows the player to claim daily rewards', + canHaveCount: false, + }), + new IPermission({ + permission: 'DAILY_REWARD_MULTIPLIER', + friendlyName: 'Multiplier', + description: + 'Control the multiplier per role. This is useful to give your donors a little extra. Count is an integer multiplier.', + canHaveCount: true, + }), + ]; + + this.commands = [ + new ICommand({ + function: this.loadFn('commands', 'daily'), + name: 'daily', + trigger: 'daily', + helpText: 'Claim your daily reward', + arguments: [], + }), + new ICommand({ + function: this.loadFn('commands', 'streak'), + name: 'streak', + trigger: 'streak', + helpText: 'Check your current daily reward streak and next claim time', + arguments: [], + }), + new ICommand({ + function: this.loadFn('commands', 'topstreak'), + name: 'topstreak', + trigger: 'topstreak', + helpText: 'Shows the players with highest daily reward streaks', + arguments: [ + { + name: 'count', + type: 'number', + defaultValue: '5', + helpText: 'Number of players to show (max 25)', + position: 0, + }, + ], + }), + ]; + + this.hooks = [ + new IHook({ + eventType: 'player-connected', + name: 'dailyLoginCheck', + function: this.loadFn('hooks', 'dailyLoginCheck'), + }), + ]; + } +} From 8c04d00cdc7596d9bbf31eac3378c49f3b88578e Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:19:09 +0000 Subject: [PATCH 13/48] fix: code style --- packages/web-docs/docs/modules/modules.json | 65 +++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/packages/web-docs/docs/modules/modules.json b/packages/web-docs/docs/modules/modules.json index e5f4728684..2e8f5cf5d6 100644 --- a/packages/web-docs/docs/modules/modules.json +++ b/packages/web-docs/docs/modules/modules.json @@ -572,5 +572,70 @@ "description": "Automatically shut down the server at a specific time.", "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"warningMessage\":{\"type\":\"string\",\"title\":\"Warning message\",\"description\":\"Message to send to players before the server shuts down.\",\"default\":\"Server is shutting down in 5 minutes!\",\"minLength\":1,\"maxLength\":1024}},\"required\":[\"warningMessage\"]}", "uiSchema": "{}" + }, + { + "commands": [ + { + "function": "import { takaro, data, TakaroUserError, checkPermission } from '@takaro/helpers';\nimport { DAILY_KEY, STREAK_KEY, getMultiplier } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n if (!checkPermission(pog, 'DAILY_CLAIM')) {\n throw new TakaroUserError('You do not have permission to claim daily rewards.');\n }\n // Get last claim time\n const lastClaimRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [DAILY_KEY],\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n });\n const now = new Date();\n let streak = 1;\n if (lastClaimRes.data.data.length > 0) {\n const lastClaim = new Date(JSON.parse(lastClaimRes.data.data[0].value));\n const hoursSinceLastClaim = (now - lastClaim) / (1000 * 60 * 60);\n // Check if 24 hours have passed\n if (hoursSinceLastClaim < 24) {\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n throw new TakaroUserError(`You can claim your next reward at ${nextClaimTime.toLocaleString()}`);\n }\n // Get current streak\n const streakRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [STREAK_KEY],\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n });\n if (streakRes.data.data.length > 0) {\n // If claimed within 48 hours, increment streak\n if (hoursSinceLastClaim < 48) {\n streak = Math.min(JSON.parse(streakRes.data.data[0].value) + 1, mod.userConfig.maxStreak);\n await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, {\n value: JSON.stringify(streak),\n });\n }\n else {\n // Reset streak if more than 48 hours\n await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, {\n value: JSON.stringify(1),\n });\n }\n }\n else {\n // Create new streak record\n await takaro.variable.variableControllerCreate({\n key: STREAK_KEY,\n value: JSON.stringify(1),\n gameServerId,\n playerId: pog.playerId,\n moduleId: mod.moduleId,\n });\n }\n // Update last claim time\n await takaro.variable.variableControllerUpdate(lastClaimRes.data.data[0].id, {\n value: JSON.stringify(now),\n });\n }\n else {\n // First time claim\n await takaro.variable.variableControllerCreate({\n key: DAILY_KEY,\n value: JSON.stringify(now),\n gameServerId,\n playerId: pog.playerId,\n moduleId: mod.moduleId,\n });\n await takaro.variable.variableControllerCreate({\n key: STREAK_KEY,\n value: JSON.stringify(1),\n gameServerId,\n playerId: pog.playerId,\n moduleId: mod.moduleId,\n });\n }\n const multiplier = await getMultiplier(pog);\n const baseReward = mod.userConfig.baseReward * streak * multiplier;\n let bonusReward = 0;\n let milestoneMessage = '';\n // Check for milestones\n for (const milestone of mod.userConfig.milestoneRewards) {\n if (streak === milestone.days) {\n bonusReward = milestone.reward;\n milestoneMessage = `\\n${milestone.message}`;\n break;\n }\n }\n // Award total rewards\n const totalReward = baseReward + bonusReward;\n await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(gameServerId, pog.playerId, {\n currency: totalReward,\n });\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', gameServerId)).data.data.value;\n await pog.pm(`Daily reward claimed! You received ${totalReward} ${currencyName}\\n` +\n `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x bonus!)` : ''}` +\n milestoneMessage);\n}\nawait main();\n//# sourceMappingURL=daily.js.map", + "name": "daily", + "trigger": "daily", + "helpText": "Claim your daily reward", + "arguments": [] + }, + { + "function": "import { data } from '@takaro/helpers';\nimport { getPlayerStreak, getLastClaim, getMultiplier } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const streak = await getPlayerStreak(gameServerId, pog.playerId, mod.moduleId);\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n const multiplier = await getMultiplier(pog);\n if (!streak || !lastClaim) {\n // eslint-disable-next-line quotes\n await pog.pm(\"You haven't claimed any daily rewards yet! Use /daily to get started.\");\n return;\n }\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n const now = new Date();\n const canClaim = now >= nextClaimTime;\n // Find next milestone\n let nextMilestone = null;\n for (const milestone of mod.userConfig.milestoneRewards) {\n if (milestone.days > streak) {\n nextMilestone = milestone;\n break;\n }\n }\n let message = `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x donor bonus!)` : ''}\\n`;\n message += canClaim\n ? 'Your daily reward is available! Use /daily to claim it!\\n'\n : `Next reward available at: ${nextClaimTime.toLocaleString()}\\n`;\n if (nextMilestone) {\n message += `\\n🎯 Next milestone: ${nextMilestone.days} days (${nextMilestone.days - streak} days to go!)`;\n }\n await pog.pm(message);\n}\nawait main();\n//# sourceMappingURL=streak.js.map", + "name": "streak", + "trigger": "streak", + "helpText": "Check your current daily reward streak and next claim time", + "arguments": [] + }, + { + "function": "import { takaro, data } from '@takaro/helpers';\nimport { STREAK_KEY } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod, arguments: args } = data;\n // Limit count to reasonable number\n const count = Math.min(Math.max(1, args.count), 50);\n // Get all streaks\n const streaksRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [STREAK_KEY],\n gameServerId: [gameServerId],\n moduleId: [mod.moduleId],\n },\n limit: 1000, // Get all possible streaks\n });\n if (streaksRes.data.data.length === 0) {\n await pog.pm('No players have started their daily streak yet!');\n return;\n }\n // Sort by streak value\n const sortedStreaks = streaksRes.data.data\n .map((record) => ({\n playerId: record.playerId,\n streak: JSON.parse(record.value),\n }))\n .sort((a, b) => b.streak - a.streak)\n .slice(0, count);\n // Get player names\n const playerDetails = await Promise.all(sortedStreaks.map(async (record) => {\n const player = (await takaro.player.playerControllerGetOne(record.playerId)).data.data;\n return {\n name: player.name,\n streak: record.streak,\n };\n }));\n // Build message\n let message = `Top ${count} Daily Streaks:\\n\\n`;\n playerDetails.forEach((player, index) => {\n message += `${index + 1}. ${player.name}: ${player.streak} days\\n`;\n });\n await pog.pm(message);\n}\nawait main();\n//# sourceMappingURL=topstreak.js.map", + "name": "topstreak", + "trigger": "topstreak", + "helpText": "Shows the players with highest daily reward streaks", + "arguments": [ + { + "name": "count", + "type": "number", + "defaultValue": "5", + "helpText": "Number of players to show (max 25)", + "position": 0 + } + ] + } + ], + "hooks": [ + { + "eventType": "player-connected", + "name": "dailyLoginCheck", + "function": "import { data } from '@takaro/helpers';\nimport { getLastClaim } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n // First time player\n if (!lastClaim) {\n await pog.pm('👋 Welcome! Use /daily to claim your first daily reward and start your streak!');\n return;\n }\n const now = new Date();\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n if (now >= nextClaimTime) {\n await pog.pm('🎁 Your daily reward is ready! Use /daily to claim it!');\n }\n}\nawait main();\n//# sourceMappingURL=dailyLoginCheck.js.map" + } + ], + "cronJobs": [], + "functions": [ + { + "name": "utils", + "function": "import { takaro, checkPermission } from '@takaro/helpers';\nexport const DAILY_KEY = 'daily_timestamp';\nexport const STREAK_KEY = 'daily_streak';\nexport async function getMultiplier(pog) {\n const perm = checkPermission(pog, 'DAILY_REWARD_MULTIPLIER');\n if (perm)\n return perm.count;\n return 1;\n}\nexport async function getPlayerStreak(gameServerId, playerId, moduleId) {\n const streakRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [STREAK_KEY],\n gameServerId: [gameServerId],\n playerId: [playerId],\n moduleId: [moduleId],\n },\n });\n return streakRes.data.data.length ? parseInt(JSON.parse(streakRes.data.data[0].value)) : 0;\n}\nexport async function getLastClaim(gameServerId, playerId, moduleId) {\n const lastClaimRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [DAILY_KEY],\n gameServerId: [gameServerId],\n playerId: [playerId],\n moduleId: [moduleId],\n },\n });\n return lastClaimRes.data.data.length ? new Date(JSON.parse(lastClaimRes.data.data[0].value)) : null;\n}\n//# sourceMappingURL=utils.js.map" + } + ], + "permissions": [ + { + "permission": "DAILY_CLAIM", + "friendlyName": "Claim Daily Rewards", + "description": "Allows the player to claim daily rewards", + "canHaveCount": false + }, + { + "permission": "DAILY_REWARD_MULTIPLIER", + "friendlyName": "Multiplier", + "description": "Control the multiplier per role. This is useful to give your donors a little extra. Count is an integer multiplier.", + "canHaveCount": true + } + ], + "name": "dailyRewards", + "description": "Provides daily login rewards with streak tracking", + "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"baseReward\":{\"type\":\"number\",\"title\":\"Base Reward\",\"description\":\"Base amount of currency given for daily rewards. This is multiplied by streak level.\",\"default\":100,\"minimum\":1},\"maxStreak\":{\"type\":\"number\",\"title\":\"Maximum Streak\",\"description\":\"Maximum streak level a player can reach\",\"default\":365,\"minimum\":1},\"milestoneRewards\":{\"type\":\"array\",\"title\":\"Milestone Rewards\",\"description\":\"Additional rewards for reaching certain streak milestones\",\"items\":{\"type\":\"object\",\"properties\":{\"days\":{\"type\":\"number\",\"description\":\"Days needed to reach milestone\",\"minimum\":1},\"reward\":{\"type\":\"number\",\"description\":\"Bonus reward amount\"},\"message\":{\"type\":\"string\",\"description\":\"Message to show when milestone is reached\"}}},\"default\":[{\"days\":7,\"reward\":1000,\"message\":\"You did it! 7 days in a row!\"},{\"days\":30,\"reward\":5000,\"message\":\"A whole month! You're on fire!\"},{\"days\":90,\"reward\":20000,\"message\":\"90 days! You're unstoppable!\"},{\"days\":180,\"reward\":50000,\"message\":\"Half a year! You're a legend!\"},{\"days\":365,\"reward\":150000,\"message\":\"365 days! You're a true champion!\"}]}},\"required\":[\"baseReward\",\"maxStreak\",\"milestoneRewards\"],\"additionalProperties\":false}", + "uiSchema": "{}" } ] \ No newline at end of file From cb08e13669760ae93669b7c8adeb5471101f062d Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 23:22:20 +0100 Subject: [PATCH 14/48] cleanup: use dynamic prefix for message replies --- .../src/modules/dailyRewards/commands/streak.js | 6 +++--- .../src/modules/dailyRewards/hooks/dailyLoginCheck.js | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/lib-modules/src/modules/dailyRewards/commands/streak.js b/packages/lib-modules/src/modules/dailyRewards/commands/streak.js index 824e1681b2..b921005ad7 100644 --- a/packages/lib-modules/src/modules/dailyRewards/commands/streak.js +++ b/packages/lib-modules/src/modules/dailyRewards/commands/streak.js @@ -7,10 +7,10 @@ async function main() { const streak = await getPlayerStreak(gameServerId, pog.playerId, mod.moduleId); const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId); const multiplier = await getMultiplier(pog); + const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value; if (!streak || !lastClaim) { - // eslint-disable-next-line quotes - await pog.pm("You haven't claimed any daily rewards yet! Use /daily to get started."); + await pog.pm(`You haven't claimed any daily rewards yet! Use ${prefix}daily to get started.`); return; } @@ -29,7 +29,7 @@ async function main() { let message = `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x donor bonus!)` : ''}\n`; message += canClaim - ? 'Your daily reward is available! Use /daily to claim it!\n' + ? `Your daily reward is available! Use ${prefix}daily to claim it!\n` : `Next reward available at: ${nextClaimTime.toLocaleString()}\n`; if (nextMilestone) { diff --git a/packages/lib-modules/src/modules/dailyRewards/hooks/dailyLoginCheck.js b/packages/lib-modules/src/modules/dailyRewards/hooks/dailyLoginCheck.js index 975d957f44..3d80bf2f8d 100644 --- a/packages/lib-modules/src/modules/dailyRewards/hooks/dailyLoginCheck.js +++ b/packages/lib-modules/src/modules/dailyRewards/hooks/dailyLoginCheck.js @@ -1,14 +1,15 @@ -import { data } from '@takaro/helpers'; +import { data, takaro } from '@takaro/helpers'; import { getLastClaim } from './utils.js'; async function main() { const { pog, gameServerId, module: mod } = data; + const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value; const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId); // First time player if (!lastClaim) { - await pog.pm('👋 Welcome! Use /daily to claim your first daily reward and start your streak!'); + await pog.pm(`Welcome! Use ${prefix}daily to claim your first daily reward and start your streak!`); return; } @@ -16,7 +17,7 @@ async function main() { const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000); if (now >= nextClaimTime) { - await pog.pm('🎁 Your daily reward is ready! Use /daily to claim it!'); + await pog.pm(`Your daily reward is ready! Use ${prefix}daily to claim it!`); } } From c71d7be3a4b835005858d1bd9b97888133886a1f Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:25:27 +0000 Subject: [PATCH 15/48] fix: code style --- packages/web-docs/docs/modules/modules.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/web-docs/docs/modules/modules.json b/packages/web-docs/docs/modules/modules.json index 2e8f5cf5d6..bd3c0003b1 100644 --- a/packages/web-docs/docs/modules/modules.json +++ b/packages/web-docs/docs/modules/modules.json @@ -583,7 +583,7 @@ "arguments": [] }, { - "function": "import { data } from '@takaro/helpers';\nimport { getPlayerStreak, getLastClaim, getMultiplier } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const streak = await getPlayerStreak(gameServerId, pog.playerId, mod.moduleId);\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n const multiplier = await getMultiplier(pog);\n if (!streak || !lastClaim) {\n // eslint-disable-next-line quotes\n await pog.pm(\"You haven't claimed any daily rewards yet! Use /daily to get started.\");\n return;\n }\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n const now = new Date();\n const canClaim = now >= nextClaimTime;\n // Find next milestone\n let nextMilestone = null;\n for (const milestone of mod.userConfig.milestoneRewards) {\n if (milestone.days > streak) {\n nextMilestone = milestone;\n break;\n }\n }\n let message = `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x donor bonus!)` : ''}\\n`;\n message += canClaim\n ? 'Your daily reward is available! Use /daily to claim it!\\n'\n : `Next reward available at: ${nextClaimTime.toLocaleString()}\\n`;\n if (nextMilestone) {\n message += `\\n🎯 Next milestone: ${nextMilestone.days} days (${nextMilestone.days - streak} days to go!)`;\n }\n await pog.pm(message);\n}\nawait main();\n//# sourceMappingURL=streak.js.map", + "function": "import { data } from '@takaro/helpers';\nimport { getPlayerStreak, getLastClaim, getMultiplier } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const streak = await getPlayerStreak(gameServerId, pog.playerId, mod.moduleId);\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n const multiplier = await getMultiplier(pog);\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n if (!streak || !lastClaim) {\n await pog.pm(`You haven't claimed any daily rewards yet! Use ${prefix}daily to get started.`);\n return;\n }\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n const now = new Date();\n const canClaim = now >= nextClaimTime;\n // Find next milestone\n let nextMilestone = null;\n for (const milestone of mod.userConfig.milestoneRewards) {\n if (milestone.days > streak) {\n nextMilestone = milestone;\n break;\n }\n }\n let message = `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x donor bonus!)` : ''}\\n`;\n message += canClaim\n ? `Your daily reward is available! Use ${prefix}daily to claim it!\\n`\n : `Next reward available at: ${nextClaimTime.toLocaleString()}\\n`;\n if (nextMilestone) {\n message += `\\n🎯 Next milestone: ${nextMilestone.days} days (${nextMilestone.days - streak} days to go!)`;\n }\n await pog.pm(message);\n}\nawait main();\n//# sourceMappingURL=streak.js.map", "name": "streak", "trigger": "streak", "helpText": "Check your current daily reward streak and next claim time", @@ -609,7 +609,7 @@ { "eventType": "player-connected", "name": "dailyLoginCheck", - "function": "import { data } from '@takaro/helpers';\nimport { getLastClaim } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n // First time player\n if (!lastClaim) {\n await pog.pm('👋 Welcome! Use /daily to claim your first daily reward and start your streak!');\n return;\n }\n const now = new Date();\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n if (now >= nextClaimTime) {\n await pog.pm('🎁 Your daily reward is ready! Use /daily to claim it!');\n }\n}\nawait main();\n//# sourceMappingURL=dailyLoginCheck.js.map" + "function": "import { data, takaro } from '@takaro/helpers';\nimport { getLastClaim } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n // First time player\n if (!lastClaim) {\n await pog.pm(`Welcome! Use ${prefix}daily to claim your first daily reward and start your streak!`);\n return;\n }\n const now = new Date();\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n if (now >= nextClaimTime) {\n await pog.pm(`Your daily reward is ready! Use ${prefix}daily to claim it!`);\n }\n}\nawait main();\n//# sourceMappingURL=dailyLoginCheck.js.map" } ], "cronJobs": [], From 9c4732c7ab8bbab1fba4943e9915378e3083ca2f Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 10:49:09 +0000 Subject: [PATCH 16/48] chore: generate api client --- packages/lib-apiclient/src/generated/api.ts | 2 +- packages/lib-apiclient/src/generated/base.ts | 2 +- packages/lib-apiclient/src/generated/common.ts | 2 +- packages/lib-apiclient/src/generated/configuration.ts | 2 +- packages/lib-apiclient/src/generated/index.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/lib-apiclient/src/generated/api.ts b/packages/lib-apiclient/src/generated/api.ts index 16ac5375bc..beafefbdc1 100644 --- a/packages/lib-apiclient/src/generated/api.ts +++ b/packages/lib-apiclient/src/generated/api.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 5199f209d75d036de130cfd1481e036535ab4d80 + * The version of the OpenAPI document: development - b69ff46f5efd3c4a565ad352019fd6150b5f6c35 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/base.ts b/packages/lib-apiclient/src/generated/base.ts index e7b97e21b7..049ab95099 100644 --- a/packages/lib-apiclient/src/generated/base.ts +++ b/packages/lib-apiclient/src/generated/base.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 5199f209d75d036de130cfd1481e036535ab4d80 + * The version of the OpenAPI document: development - b69ff46f5efd3c4a565ad352019fd6150b5f6c35 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/common.ts b/packages/lib-apiclient/src/generated/common.ts index 1582b1325e..fa3b3f47c2 100644 --- a/packages/lib-apiclient/src/generated/common.ts +++ b/packages/lib-apiclient/src/generated/common.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 5199f209d75d036de130cfd1481e036535ab4d80 + * The version of the OpenAPI document: development - b69ff46f5efd3c4a565ad352019fd6150b5f6c35 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index 9cf6237e69..73f90ac179 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 5199f209d75d036de130cfd1481e036535ab4d80 + * The version of the OpenAPI document: development - b69ff46f5efd3c4a565ad352019fd6150b5f6c35 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/index.ts b/packages/lib-apiclient/src/generated/index.ts index ee33d9aff9..d1f33b4341 100644 --- a/packages/lib-apiclient/src/generated/index.ts +++ b/packages/lib-apiclient/src/generated/index.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 5199f209d75d036de130cfd1481e036535ab4d80 + * The version of the OpenAPI document: development - b69ff46f5efd3c4a565ad352019fd6150b5f6c35 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). From 903ff0d2a94bc2b39c9d0af5c20c77ad8a124566 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Tue, 29 Oct 2024 14:13:05 +0100 Subject: [PATCH 17/48] fix: add better error handler for CSMM import when checking CPM compatibility --- .../app-api/src/workers/csmmImportWorker.ts | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/app-api/src/workers/csmmImportWorker.ts b/packages/app-api/src/workers/csmmImportWorker.ts index 01a4ded52f..71ce5cc7bd 100644 --- a/packages/app-api/src/workers/csmmImportWorker.ts +++ b/packages/app-api/src/workers/csmmImportWorker.ts @@ -192,24 +192,27 @@ async function process(job: Job) { } } - const isReachable = await gameserverService.testReachability(server.id); - - if (isReachable) { - const res = await gameserverService.executeCommand(server.id, 'version'); - if (res.rawResult.includes('1CSMM_Patrons')) { - await gameserverService.update( - server.id, - new GameServerUpdateDTO({ - connectionInfo: JSON.stringify({ - host: `${data.server.ip}:${data.server.webPort.toString()}`, - adminUser: data.server.authName, - adminToken: data.server.authToken, - useTls: data.server.webPort === 443, - useCPM: true, + try { + const isReachable = await gameserverService.testReachability(server.id); + if (isReachable) { + const res = await gameserverService.executeCommand(server.id, 'version'); + if (res.rawResult.includes('1CSMM_Patrons')) { + await gameserverService.update( + server.id, + new GameServerUpdateDTO({ + connectionInfo: JSON.stringify({ + host: `${data.server.ip}:${data.server.webPort.toString()}`, + adminUser: data.server.authName, + adminToken: data.server.authToken, + useTls: data.server.webPort === 443, + useCPM: true, + }), }), - }), - ); + ); + } } + } catch (error) { + log.warn('Error while determining CPM compatiblity', error); } // Poll the item sync job until it's done From 57175d2fb63b899573181c9d231cad4e3d16d6a2 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Tue, 29 Oct 2024 14:41:44 +0100 Subject: [PATCH 18/48] chore: add takaro-specific short url for discord invite --- packages/web-docs/docs/advanced/custom-modules.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/web-docs/docs/advanced/custom-modules.md b/packages/web-docs/docs/advanced/custom-modules.md index f50d8f34ed..3f00fa6bfd 100644 --- a/packages/web-docs/docs/advanced/custom-modules.md +++ b/packages/web-docs/docs/advanced/custom-modules.md @@ -6,11 +6,11 @@ sidebar_position: 3 While the Takaro Team is committed to providing a comprehensive set of built-in modules, there may be instances where a particular feature you need is unavailable, or perhaps -there is no existing module for a feature you desire. +there is no existing module for a feature you desire. -This is focused on advanced users familiar with JavaScript. +This is focused on advanced users familiar with JavaScript. If you need support, or if you believe your feature could enrich our suite of built-in modules, -we encourage you to reach out to our Discord community. +we encourage you to reach out to our Discord community. ## Functions From 109cb7303912af9457756ae7916567372b682f13 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Tue, 29 Oct 2024 14:47:34 +0100 Subject: [PATCH 19/48] fix: linter --- packages/lib-modules/src/modules/dailyRewards/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/lib-modules/src/modules/dailyRewards/index.ts b/packages/lib-modules/src/modules/dailyRewards/index.ts index 5f7d984f99..796c4c0af3 100644 --- a/packages/lib-modules/src/modules/dailyRewards/index.ts +++ b/packages/lib-modules/src/modules/dailyRewards/index.ts @@ -1,3 +1,4 @@ +/* eslint-disable quotes */ import { BuiltinModule, ICommand, IFunction, IHook, IPermission } from '../../BuiltinModule.js'; export class DailyRewards extends BuiltinModule { From c44e9d39d5ed3a3b50fe24da7cbb290f1fae4913 Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:35:39 +0000 Subject: [PATCH 20/48] chore: generate api client --- packages/lib-apiclient/src/generated/api.ts | 2 +- packages/lib-apiclient/src/generated/base.ts | 2 +- packages/lib-apiclient/src/generated/common.ts | 2 +- packages/lib-apiclient/src/generated/configuration.ts | 2 +- packages/lib-apiclient/src/generated/index.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/lib-apiclient/src/generated/api.ts b/packages/lib-apiclient/src/generated/api.ts index beafefbdc1..9fc4340529 100644 --- a/packages/lib-apiclient/src/generated/api.ts +++ b/packages/lib-apiclient/src/generated/api.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - b69ff46f5efd3c4a565ad352019fd6150b5f6c35 + * The version of the OpenAPI document: development - 9fb1103cdd475cceed63cda76bfa9de43d8477db * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/base.ts b/packages/lib-apiclient/src/generated/base.ts index 049ab95099..52d7a2756c 100644 --- a/packages/lib-apiclient/src/generated/base.ts +++ b/packages/lib-apiclient/src/generated/base.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - b69ff46f5efd3c4a565ad352019fd6150b5f6c35 + * The version of the OpenAPI document: development - 9fb1103cdd475cceed63cda76bfa9de43d8477db * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/common.ts b/packages/lib-apiclient/src/generated/common.ts index fa3b3f47c2..9ab83da588 100644 --- a/packages/lib-apiclient/src/generated/common.ts +++ b/packages/lib-apiclient/src/generated/common.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - b69ff46f5efd3c4a565ad352019fd6150b5f6c35 + * The version of the OpenAPI document: development - 9fb1103cdd475cceed63cda76bfa9de43d8477db * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index 73f90ac179..a8d6e7a557 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - b69ff46f5efd3c4a565ad352019fd6150b5f6c35 + * The version of the OpenAPI document: development - 9fb1103cdd475cceed63cda76bfa9de43d8477db * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/index.ts b/packages/lib-apiclient/src/generated/index.ts index d1f33b4341..28f1c2b420 100644 --- a/packages/lib-apiclient/src/generated/index.ts +++ b/packages/lib-apiclient/src/generated/index.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - b69ff46f5efd3c4a565ad352019fd6150b5f6c35 + * The version of the OpenAPI document: development - 9fb1103cdd475cceed63cda76bfa9de43d8477db * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). From 6aeb1e066799a8250caf1df738eb2b925c74ab21 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Tue, 29 Oct 2024 15:44:01 +0100 Subject: [PATCH 21/48] fix: an issue with prefix fetching in streak cmd --- .../lib-modules/src/modules/dailyRewards/commands/streak.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lib-modules/src/modules/dailyRewards/commands/streak.js b/packages/lib-modules/src/modules/dailyRewards/commands/streak.js index b921005ad7..587cb3f7c2 100644 --- a/packages/lib-modules/src/modules/dailyRewards/commands/streak.js +++ b/packages/lib-modules/src/modules/dailyRewards/commands/streak.js @@ -1,4 +1,4 @@ -import { data } from '@takaro/helpers'; +import { data, takaro } from '@takaro/helpers'; import { getPlayerStreak, getLastClaim, getMultiplier } from './utils.js'; async function main() { From 266e2d3bc375eed803b743b34660cc5032746b5c Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:47:14 +0000 Subject: [PATCH 22/48] fix: code style --- packages/web-docs/docs/modules/modules.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web-docs/docs/modules/modules.json b/packages/web-docs/docs/modules/modules.json index bd3c0003b1..2468337d28 100644 --- a/packages/web-docs/docs/modules/modules.json +++ b/packages/web-docs/docs/modules/modules.json @@ -583,7 +583,7 @@ "arguments": [] }, { - "function": "import { data } from '@takaro/helpers';\nimport { getPlayerStreak, getLastClaim, getMultiplier } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const streak = await getPlayerStreak(gameServerId, pog.playerId, mod.moduleId);\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n const multiplier = await getMultiplier(pog);\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n if (!streak || !lastClaim) {\n await pog.pm(`You haven't claimed any daily rewards yet! Use ${prefix}daily to get started.`);\n return;\n }\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n const now = new Date();\n const canClaim = now >= nextClaimTime;\n // Find next milestone\n let nextMilestone = null;\n for (const milestone of mod.userConfig.milestoneRewards) {\n if (milestone.days > streak) {\n nextMilestone = milestone;\n break;\n }\n }\n let message = `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x donor bonus!)` : ''}\\n`;\n message += canClaim\n ? `Your daily reward is available! Use ${prefix}daily to claim it!\\n`\n : `Next reward available at: ${nextClaimTime.toLocaleString()}\\n`;\n if (nextMilestone) {\n message += `\\n🎯 Next milestone: ${nextMilestone.days} days (${nextMilestone.days - streak} days to go!)`;\n }\n await pog.pm(message);\n}\nawait main();\n//# sourceMappingURL=streak.js.map", + "function": "import { data, takaro } from '@takaro/helpers';\nimport { getPlayerStreak, getLastClaim, getMultiplier } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const streak = await getPlayerStreak(gameServerId, pog.playerId, mod.moduleId);\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n const multiplier = await getMultiplier(pog);\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n if (!streak || !lastClaim) {\n await pog.pm(`You haven't claimed any daily rewards yet! Use ${prefix}daily to get started.`);\n return;\n }\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n const now = new Date();\n const canClaim = now >= nextClaimTime;\n // Find next milestone\n let nextMilestone = null;\n for (const milestone of mod.userConfig.milestoneRewards) {\n if (milestone.days > streak) {\n nextMilestone = milestone;\n break;\n }\n }\n let message = `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x donor bonus!)` : ''}\\n`;\n message += canClaim\n ? `Your daily reward is available! Use ${prefix}daily to claim it!\\n`\n : `Next reward available at: ${nextClaimTime.toLocaleString()}\\n`;\n if (nextMilestone) {\n message += `\\n🎯 Next milestone: ${nextMilestone.days} days (${nextMilestone.days - streak} days to go!)`;\n }\n await pog.pm(message);\n}\nawait main();\n//# sourceMappingURL=streak.js.map", "name": "streak", "trigger": "streak", "helpText": "Check your current daily reward streak and next claim time", From fa6e7332ac1f7d9088ed43796d794458cac42fa1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:05:59 +0000 Subject: [PATCH 23/48] chore(deps): update dependency @types/supertest to v6 --- package-lock.json | 9 ++++++--- package.json | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index d2d1a585c4..09d408b342 100644 --- a/package-lock.json +++ b/package-lock.json @@ -87,7 +87,7 @@ "@types/safe-regex": "1.1.6", "@types/sinon": "17.0.3", "@types/sinon-chai": "3.2.12", - "@types/supertest": "2.0.16", + "@types/supertest": "6.0.2", "@types/uuid": "10.0.0", "chai": "4.5.0", "chai-as-promised": "8.0.0", @@ -22865,11 +22865,14 @@ } }, "node_modules/@types/supertest": { - "version": "2.0.16", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", + "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", "dev": true, "license": "MIT", "dependencies": { - "@types/superagent": "*" + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" } }, "node_modules/@types/tedious": { diff --git a/package.json b/package.json index 28088651a1..7490955e67 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "@types/safe-regex": "1.1.6", "@types/sinon": "17.0.3", "@types/sinon-chai": "3.2.12", - "@types/supertest": "2.0.16", + "@types/supertest": "6.0.2", "@types/uuid": "10.0.0", "chai": "4.5.0", "chai-as-promised": "8.0.0", From 83f533b5504b03a0ef801c864eebf577264474f6 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Tue, 29 Oct 2024 21:04:25 +0100 Subject: [PATCH 24/48] chore: regen lockfile --- package-lock.json | 257 ++++++++++++++++++++++------------------------ 1 file changed, 120 insertions(+), 137 deletions(-) diff --git a/package-lock.json b/package-lock.json index d2d1a585c4..6d416dbd30 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1253,10 +1253,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.25.7", - "license": "MIT", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.0.tgz", + "integrity": "sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==", "dependencies": { - "@babel/highlight": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -1264,27 +1266,28 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.7", - "license": "MIT", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz", + "integrity": "sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.8.tgz", - "integrity": "sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.25.7", - "@babel/generator": "^7.25.7", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helpers": "^7.25.7", - "@babel/parser": "^7.25.8", - "@babel/template": "^7.25.7", - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.8", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -1304,10 +1307,12 @@ "license": "MIT" }, "node_modules/@babel/generator": { - "version": "7.25.7", - "license": "MIT", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.0.tgz", + "integrity": "sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==", "dependencies": { - "@babel/types": "^7.25.7", + "@babel/parser": "^7.26.0", + "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -1338,11 +1343,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.7", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", "dependencies": { - "@babel/compat-data": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -1411,24 +1417,25 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.7", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.7", - "license": "MIT", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dependencies": { - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-simple-access": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1448,8 +1455,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.7", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "engines": { "node": ">=6.9.0" } @@ -1507,22 +1515,25 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.7", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "engines": { "node": ">=6.9.0" } @@ -1540,35 +1551,23 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.7", - "license": "MIT", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "dependencies": { - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.25.7", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", - "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", + "version": "7.26.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.1.tgz", + "integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==", "dependencies": { - "@babel/types": "^7.25.8" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -1831,10 +1830,11 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.7", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1930,10 +1930,11 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.7", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -3091,26 +3092,28 @@ } }, "node_modules/@babel/template": { - "version": "7.25.7", - "license": "MIT", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.7", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/generator": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -3119,13 +3122,12 @@ } }, "node_modules/@babel/types": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", - "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -24079,27 +24081,6 @@ "node": ">=8" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-styles/node_modules/color-convert": { - "version": "1.9.3", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/ansi-styles/node_modules/color-name": { - "version": "1.1.3", - "license": "MIT" - }, "node_modules/anymatch": { "version": "3.1.3", "license": "ISC", @@ -25464,25 +25445,6 @@ "node": ">= 16" } }, - "node_modules/chalk": { - "version": "2.4.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/char-regex": { "version": "1.0.2", "license": "MIT", @@ -30380,6 +30342,19 @@ "version": "1.0.0", "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "license": "MIT", @@ -38670,6 +38645,20 @@ "node": ">=18" } }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/polished": { "version": "4.3.1", "license": "MIT", @@ -43492,13 +43481,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "license": "MIT", @@ -43842,8 +43824,9 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.19.1", - "license": "MIT", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", + "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", "optional": true, "peer": true, "dependencies": { From 398dd1a3af271996f80b5306bc5cfb1899b5ac47 Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 21:40:07 +0000 Subject: [PATCH 25/48] chore: generate api client --- packages/lib-apiclient/src/generated/api.ts | 2 +- packages/lib-apiclient/src/generated/base.ts | 2 +- packages/lib-apiclient/src/generated/common.ts | 2 +- packages/lib-apiclient/src/generated/configuration.ts | 2 +- packages/lib-apiclient/src/generated/index.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/lib-apiclient/src/generated/api.ts b/packages/lib-apiclient/src/generated/api.ts index 9fc4340529..0ea62c0936 100644 --- a/packages/lib-apiclient/src/generated/api.ts +++ b/packages/lib-apiclient/src/generated/api.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 9fb1103cdd475cceed63cda76bfa9de43d8477db + * The version of the OpenAPI document: development - 6b9d7f6719f95491863ac106c5fca63e21c876bd * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/base.ts b/packages/lib-apiclient/src/generated/base.ts index 52d7a2756c..5f41809205 100644 --- a/packages/lib-apiclient/src/generated/base.ts +++ b/packages/lib-apiclient/src/generated/base.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 9fb1103cdd475cceed63cda76bfa9de43d8477db + * The version of the OpenAPI document: development - 6b9d7f6719f95491863ac106c5fca63e21c876bd * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/common.ts b/packages/lib-apiclient/src/generated/common.ts index 9ab83da588..333c10665a 100644 --- a/packages/lib-apiclient/src/generated/common.ts +++ b/packages/lib-apiclient/src/generated/common.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 9fb1103cdd475cceed63cda76bfa9de43d8477db + * The version of the OpenAPI document: development - 6b9d7f6719f95491863ac106c5fca63e21c876bd * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index a8d6e7a557..9130330eb3 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 9fb1103cdd475cceed63cda76bfa9de43d8477db + * The version of the OpenAPI document: development - 6b9d7f6719f95491863ac106c5fca63e21c876bd * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/index.ts b/packages/lib-apiclient/src/generated/index.ts index 28f1c2b420..6ba1307f10 100644 --- a/packages/lib-apiclient/src/generated/index.ts +++ b/packages/lib-apiclient/src/generated/index.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 9fb1103cdd475cceed63cda76bfa9de43d8477db + * The version of the OpenAPI document: development - 6b9d7f6719f95491863ac106c5fca63e21c876bd * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). From c732e4e3392a87d2c3a652622f48b1ee3f524757 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Tue, 29 Oct 2024 23:04:41 +0100 Subject: [PATCH 26/48] fix: add sinon to renovate automerge --- renovate.json | 1 + 1 file changed, 1 insertion(+) diff --git a/renovate.json b/renovate.json index dcfab05007..b14f454159 100644 --- a/renovate.json +++ b/renovate.json @@ -63,6 +63,7 @@ "prettier", "@types", "chai", + "sinon", "mocha" ], "automerge": true From 8f41ad679da7761785e15c54bd407b2e1c77736b Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:07:39 +0000 Subject: [PATCH 27/48] fix: code style --- .../src/routes/-module-builder/Editor/monacoCustomTypes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json b/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json index bfa2afa973..bff77c0aba 100644 --- a/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json +++ b/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json @@ -1 +1 @@ -{"file://node_modules/axios/package.json":"{\"name\":\"axios\",\"types\":\"./index.d.ts\"}","file://node_modules/axios/index.d.ts":"// TypeScript Version: 4.7\ntype AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null;\n\ninterface RawAxiosHeaders {\n [key: string]: AxiosHeaderValue;\n}\n\ntype MethodsHeaders = Partial<{\n [Key in Method as Lowercase]: AxiosHeaders;\n} & {common: AxiosHeaders}>;\n\ntype AxiosHeaderMatcher = string | RegExp | ((this: AxiosHeaders, value: string, name: string) => boolean);\n\ntype AxiosHeaderParser = (this: AxiosHeaders, value: AxiosHeaderValue, header: string) => any;\n\nclass AxiosHeaders {\n constructor(\n headers?: RawAxiosHeaders | AxiosHeaders | string\n );\n\n [key: string]: any;\n\n set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders;\n\n get(headerName: string, parser: RegExp): RegExpExecArray | null;\n get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;\n\n has(header: string, matcher?: AxiosHeaderMatcher): boolean;\n\n delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;\n\n clear(matcher?: AxiosHeaderMatcher): boolean;\n\n normalize(format: boolean): AxiosHeaders;\n\n concat(...targets: Array): AxiosHeaders;\n\n toJSON(asStrings?: boolean): RawAxiosHeaders;\n\n static from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;\n\n static accessor(header: string | string[]): AxiosHeaders;\n\n static concat(...targets: Array): AxiosHeaders;\n\n setContentType(value: ContentType, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentType(parser?: RegExp): RegExpExecArray | null;\n getContentType(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentType(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentLength(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentLength(parser?: RegExp): RegExpExecArray | null;\n getContentLength(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentLength(matcher?: AxiosHeaderMatcher): boolean;\n\n setAccept(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAccept(parser?: RegExp): RegExpExecArray | null;\n getAccept(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAccept(matcher?: AxiosHeaderMatcher): boolean;\n\n setUserAgent(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getUserAgent(parser?: RegExp): RegExpExecArray | null;\n getUserAgent(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasUserAgent(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentEncoding(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentEncoding(parser?: RegExp): RegExpExecArray | null;\n getContentEncoding(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentEncoding(matcher?: AxiosHeaderMatcher): boolean;\n\n setAuthorization(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAuthorization(parser?: RegExp): RegExpExecArray | null;\n getAuthorization(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAuthorization(matcher?: AxiosHeaderMatcher): boolean;\n\n [Symbol.iterator](): IterableIterator<[string, AxiosHeaderValue]>;\n}\n\ntype CommonRequestHeadersList = 'Accept' | 'Content-Length' | 'User-Agent' | 'Content-Encoding' | 'Authorization';\n\ntype ContentType = AxiosHeaderValue | 'text/html' | 'text/plain' | 'multipart/form-data' | 'application/json' | 'application/x-www-form-urlencoded' | 'application/octet-stream';\n\ntype RawAxiosRequestHeaders = Partial;\n\ntype AxiosRequestHeaders = RawAxiosRequestHeaders & AxiosHeaders;\n\ntype CommonResponseHeadersList = 'Server' | 'Content-Type' | 'Content-Length' | 'Cache-Control'| 'Content-Encoding';\n\ntype RawCommonResponseHeaders = {\n [Key in CommonResponseHeadersList]: AxiosHeaderValue;\n} & {\n \"set-cookie\": string[];\n};\n\ntype RawAxiosResponseHeaders = Partial;\n\ntype AxiosResponseHeaders = RawAxiosResponseHeaders & AxiosHeaders;\n\ninterface AxiosRequestTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosRequestHeaders): any;\n}\n\ninterface AxiosResponseTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosResponseHeaders, status?: number): any;\n}\n\ninterface AxiosAdapter {\n (config: InternalAxiosRequestConfig): AxiosPromise;\n}\n\ninterface AxiosBasicCredentials {\n username: string;\n password: string;\n}\n\ninterface AxiosProxyConfig {\n host: string;\n port: number;\n auth?: AxiosBasicCredentials;\n protocol?: string;\n}\n\nenum HttpStatusCode {\n Continue = 100,\n SwitchingProtocols = 101,\n Processing = 102,\n EarlyHints = 103,\n Ok = 200,\n Created = 201,\n Accepted = 202,\n NonAuthoritativeInformation = 203,\n NoContent = 204,\n ResetContent = 205,\n PartialContent = 206,\n MultiStatus = 207,\n AlreadyReported = 208,\n ImUsed = 226,\n MultipleChoices = 300,\n MovedPermanently = 301,\n Found = 302,\n SeeOther = 303,\n NotModified = 304,\n UseProxy = 305,\n Unused = 306,\n TemporaryRedirect = 307,\n PermanentRedirect = 308,\n BadRequest = 400,\n Unauthorized = 401,\n PaymentRequired = 402,\n Forbidden = 403,\n NotFound = 404,\n MethodNotAllowed = 405,\n NotAcceptable = 406,\n ProxyAuthenticationRequired = 407,\n RequestTimeout = 408,\n Conflict = 409,\n Gone = 410,\n LengthRequired = 411,\n PreconditionFailed = 412,\n PayloadTooLarge = 413,\n UriTooLong = 414,\n UnsupportedMediaType = 415,\n RangeNotSatisfiable = 416,\n ExpectationFailed = 417,\n ImATeapot = 418,\n MisdirectedRequest = 421,\n UnprocessableEntity = 422,\n Locked = 423,\n FailedDependency = 424,\n TooEarly = 425,\n UpgradeRequired = 426,\n PreconditionRequired = 428,\n TooManyRequests = 429,\n RequestHeaderFieldsTooLarge = 431,\n UnavailableForLegalReasons = 451,\n InternalServerError = 500,\n NotImplemented = 501,\n BadGateway = 502,\n ServiceUnavailable = 503,\n GatewayTimeout = 504,\n HttpVersionNotSupported = 505,\n VariantAlsoNegotiates = 506,\n InsufficientStorage = 507,\n LoopDetected = 508,\n NotExtended = 510,\n NetworkAuthenticationRequired = 511,\n}\n\ntype Method =\n | 'get' | 'GET'\n | 'delete' | 'DELETE'\n | 'head' | 'HEAD'\n | 'options' | 'OPTIONS'\n | 'post' | 'POST'\n | 'put' | 'PUT'\n | 'patch' | 'PATCH'\n | 'purge' | 'PURGE'\n | 'link' | 'LINK'\n | 'unlink' | 'UNLINK';\n\ntype ResponseType =\n | 'arraybuffer'\n | 'blob'\n | 'document'\n | 'json'\n | 'text'\n | 'stream'\n | 'formdata';\n\ntype responseEncoding =\n | 'ascii' | 'ASCII'\n | 'ansi' | 'ANSI'\n | 'binary' | 'BINARY'\n | 'base64' | 'BASE64'\n | 'base64url' | 'BASE64URL'\n | 'hex' | 'HEX'\n | 'latin1' | 'LATIN1'\n | 'ucs-2' | 'UCS-2'\n | 'ucs2' | 'UCS2'\n | 'utf-8' | 'UTF-8'\n | 'utf8' | 'UTF8'\n | 'utf16le' | 'UTF16LE';\n\ninterface TransitionalOptions {\n silentJSONParsing?: boolean;\n forcedJSONParsing?: boolean;\n clarifyTimeoutError?: boolean;\n}\n\ninterface GenericAbortSignal {\n readonly aborted: boolean;\n onabort?: ((...args: any) => any) | null;\n addEventListener?: (...args: any) => any;\n removeEventListener?: (...args: any) => any;\n}\n\ninterface FormDataVisitorHelpers {\n defaultVisitor: SerializerVisitor;\n convertValue: (value: any) => any;\n isVisitable: (value: any) => boolean;\n}\n\ninterface SerializerVisitor {\n (\n this: GenericFormData,\n value: any,\n key: string | number,\n path: null | Array,\n helpers: FormDataVisitorHelpers\n ): boolean;\n}\n\ninterface SerializerOptions {\n visitor?: SerializerVisitor;\n dots?: boolean;\n metaTokens?: boolean;\n indexes?: boolean | null;\n}\n\n// tslint:disable-next-line\ninterface FormSerializerOptions extends SerializerOptions {\n}\n\ninterface ParamEncoder {\n (value: any, defaultEncoder: (value: any) => any): any;\n}\n\ninterface CustomParamsSerializer {\n (params: Record, options?: ParamsSerializerOptions): string;\n}\n\ninterface ParamsSerializerOptions extends SerializerOptions {\n encode?: ParamEncoder;\n serialize?: CustomParamsSerializer;\n}\n\ntype MaxUploadRate = number;\n\ntype MaxDownloadRate = number;\n\ntype BrowserProgressEvent = any;\n\ninterface AxiosProgressEvent {\n loaded: number;\n total?: number;\n progress?: number;\n bytes: number;\n rate?: number;\n estimated?: number;\n upload?: boolean;\n download?: boolean;\n event?: BrowserProgressEvent;\n lengthComputable: boolean;\n}\n\ntype Milliseconds = number;\n\ntype AxiosAdapterName = 'fetch' | 'xhr' | 'http' | string;\n\ntype AxiosAdapterConfig = AxiosAdapter | AxiosAdapterName;\n\ntype AddressFamily = 4 | 6 | undefined;\n\ninterface LookupAddressEntry {\n address: string;\n family?: AddressFamily;\n}\n\ntype LookupAddress = string | LookupAddressEntry;\n\ninterface AxiosRequestConfig {\n url?: string;\n method?: Method | string;\n baseURL?: string;\n transformRequest?: AxiosRequestTransformer | AxiosRequestTransformer[];\n transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[];\n headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders;\n params?: any;\n paramsSerializer?: ParamsSerializerOptions | CustomParamsSerializer;\n data?: D;\n timeout?: Milliseconds;\n timeoutErrorMessage?: string;\n withCredentials?: boolean;\n adapter?: AxiosAdapterConfig | AxiosAdapterConfig[];\n auth?: AxiosBasicCredentials;\n responseType?: ResponseType;\n responseEncoding?: responseEncoding | string;\n xsrfCookieName?: string;\n xsrfHeaderName?: string;\n onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;\n onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void;\n maxContentLength?: number;\n validateStatus?: ((status: number) => boolean) | null;\n maxBodyLength?: number;\n maxRedirects?: number;\n maxRate?: number | [MaxUploadRate, MaxDownloadRate];\n beforeRedirect?: (options: Record, responseDetails: {headers: Record, statusCode: HttpStatusCode}) => void;\n socketPath?: string | null;\n transport?: any;\n httpAgent?: any;\n httpsAgent?: any;\n proxy?: AxiosProxyConfig | false;\n cancelToken?: CancelToken;\n decompress?: boolean;\n transitional?: TransitionalOptions;\n signal?: GenericAbortSignal;\n insecureHTTPParser?: boolean;\n env?: {\n FormData?: new (...args: any[]) => object;\n };\n formSerializer?: FormSerializerOptions;\n family?: AddressFamily;\n lookup?: ((hostname: string, options: object, cb: (err: Error | null, address: LookupAddress | LookupAddress[], family?: AddressFamily) => void) => void) |\n ((hostname: string, options: object) => Promise<[address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress>);\n withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined);\n fetchOptions?: Record;\n}\n\n// Alias\ntype RawAxiosRequestConfig = AxiosRequestConfig;\n\ninterface InternalAxiosRequestConfig extends AxiosRequestConfig {\n headers: AxiosRequestHeaders;\n}\n\ninterface HeadersDefaults {\n common: RawAxiosRequestHeaders;\n delete: RawAxiosRequestHeaders;\n get: RawAxiosRequestHeaders;\n head: RawAxiosRequestHeaders;\n post: RawAxiosRequestHeaders;\n put: RawAxiosRequestHeaders;\n patch: RawAxiosRequestHeaders;\n options?: RawAxiosRequestHeaders;\n purge?: RawAxiosRequestHeaders;\n link?: RawAxiosRequestHeaders;\n unlink?: RawAxiosRequestHeaders;\n}\n\ninterface AxiosDefaults extends Omit, 'headers'> {\n headers: HeadersDefaults;\n}\n\ninterface CreateAxiosDefaults extends Omit, 'headers'> {\n headers?: RawAxiosRequestHeaders | AxiosHeaders | Partial;\n}\n\ninterface AxiosResponse {\n data: T;\n status: number;\n statusText: string;\n headers: RawAxiosResponseHeaders | AxiosResponseHeaders;\n config: InternalAxiosRequestConfig;\n request?: any;\n}\n\nclass AxiosError extends Error {\n constructor(\n message?: string,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse\n );\n\n config?: InternalAxiosRequestConfig;\n code?: string;\n request?: any;\n response?: AxiosResponse;\n isAxiosError: boolean;\n status?: number;\n toJSON: () => object;\n cause?: Error;\n static from(\n error: Error | unknown,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse,\n customProps?: object,\n): AxiosError;\n static readonly ERR_FR_TOO_MANY_REDIRECTS = \"ERR_FR_TOO_MANY_REDIRECTS\";\n static readonly ERR_BAD_OPTION_VALUE = \"ERR_BAD_OPTION_VALUE\";\n static readonly ERR_BAD_OPTION = \"ERR_BAD_OPTION\";\n static readonly ERR_NETWORK = \"ERR_NETWORK\";\n static readonly ERR_DEPRECATED = \"ERR_DEPRECATED\";\n static readonly ERR_BAD_RESPONSE = \"ERR_BAD_RESPONSE\";\n static readonly ERR_BAD_REQUEST = \"ERR_BAD_REQUEST\";\n static readonly ERR_NOT_SUPPORT = \"ERR_NOT_SUPPORT\";\n static readonly ERR_INVALID_URL = \"ERR_INVALID_URL\";\n static readonly ERR_CANCELED = \"ERR_CANCELED\";\n static readonly ECONNABORTED = \"ECONNABORTED\";\n static readonly ETIMEDOUT = \"ETIMEDOUT\";\n}\n\nclass CanceledError extends AxiosError {\n}\n\ntype AxiosPromise = Promise>;\n\ninterface CancelStatic {\n new (message?: string): Cancel;\n}\n\ninterface Cancel {\n message: string | undefined;\n}\n\ninterface Canceler {\n (message?: string, config?: AxiosRequestConfig, request?: any): void;\n}\n\ninterface CancelTokenStatic {\n new (executor: (cancel: Canceler) => void): CancelToken;\n source(): CancelTokenSource;\n}\n\ninterface CancelToken {\n promise: Promise;\n reason?: Cancel;\n throwIfRequested(): void;\n}\n\ninterface CancelTokenSource {\n token: CancelToken;\n cancel: Canceler;\n}\n\ninterface AxiosInterceptorOptions {\n synchronous?: boolean;\n runWhen?: (config: InternalAxiosRequestConfig) => boolean;\n}\n\ninterface AxiosInterceptorManager {\n use(onFulfilled?: ((value: V) => V | Promise) | null, onRejected?: ((error: any) => any) | null, options?: AxiosInterceptorOptions): number;\n eject(id: number): void;\n clear(): void;\n}\n\nclass Axios {\n constructor(config?: AxiosRequestConfig);\n defaults: AxiosDefaults;\n interceptors: {\n request: AxiosInterceptorManager;\n response: AxiosInterceptorManager;\n };\n getUri(config?: AxiosRequestConfig): string;\n request, D = any>(config: AxiosRequestConfig): Promise;\n get, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n delete, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n head, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n options, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n post, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n put, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patch, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n postForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n putForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patchForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n}\n\ninterface AxiosInstance extends Axios {\n , D = any>(config: AxiosRequestConfig): Promise;\n , D = any>(url: string, config?: AxiosRequestConfig): Promise;\n\n defaults: Omit & {\n headers: HeadersDefaults & {\n [key: string]: AxiosHeaderValue\n }\n };\n}\n\ninterface GenericFormData {\n append(name: string, value: any, options?: any): any;\n}\n\ninterface GenericHTMLFormElement {\n name: string;\n method: string;\n submit(): void;\n}\n\nfunction getAdapter(adapters: AxiosAdapterConfig | AxiosAdapterConfig[] | undefined): AxiosAdapter;\n\nfunction toFormData(sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions): GenericFormData;\n\nfunction formToJSON(form: GenericFormData|GenericHTMLFormElement): object;\n\nfunction isAxiosError(payload: any): payload is AxiosError;\n\nfunction spread(callback: (...args: T[]) => R): (array: T[]) => R;\n\nfunction isCancel(value: any): value is Cancel;\n\nfunction all(values: Array>): Promise;\n\ninterface AxiosStatic extends AxiosInstance {\n create(config?: CreateAxiosDefaults): AxiosInstance;\n Cancel: CancelStatic;\n CancelToken: CancelTokenStatic;\n Axios: typeof Axios;\n AxiosError: typeof AxiosError;\n HttpStatusCode: typeof HttpStatusCode;\n readonly VERSION: string;\n isCancel: typeof isCancel;\n all: typeof all;\n spread: typeof spread;\n isAxiosError: typeof isAxiosError;\n toFormData: typeof toFormData;\n formToJSON: typeof formToJSON;\n getAdapter: typeof getAdapter;\n CanceledError: typeof CanceledError;\n AxiosHeaders: typeof AxiosHeaders;\n}\n\ndeclare const axios: AxiosStatic;\n\ndefault axios;\n","file://node_modules/form-data/package.json":"{\"name\":\"form-data\",\"types\":\"./index.d.ts\"}","file://node_modules/form-data/index.d.ts":"// Definitions by: Carlos Ballesteros Velasco \n// Leon Yu \n// BendingBender \n// Maple Miao \n\n/// \n\n= FormData;\n\n// Extracted because @types/node doesn't export interfaces.\ninterface ReadableOptions {\n highWaterMark?: number;\n encoding?: string;\n objectMode?: boolean;\n read?(this: stream.Readable, size: number): void;\n destroy?(this: stream.Readable, error: Error | null, callback: (error: Error | null) => void): void;\n autoDestroy?: boolean;\n}\n\ninterface Options extends ReadableOptions {\n writable?: boolean;\n readable?: boolean;\n dataSize?: number;\n maxDataSize?: number;\n pauseStreams?: boolean;\n}\n\ndeclare class FormData extends stream.Readable {\n constructor(options?: Options);\n append(key: string, value: any, options?: FormData.AppendOptions | string): void;\n getHeaders(userHeaders?: FormData.Headers): FormData.Headers;\n submit(\n params: string | FormData.SubmitOptions,\n callback?: (error: Error | null, response: http.IncomingMessage) => void\n ): http.ClientRequest;\n getBuffer(): Buffer;\n setBoundary(boundary: string): void;\n getBoundary(): string;\n getLength(callback: (err: Error | null, length: number) => void): void;\n getLengthSync(): number;\n hasKnownLength(): boolean;\n}\n\ndeclare namespace FormData {\n interface Headers {\n [key: string]: any;\n }\n\n interface AppendOptions {\n header?: string | Headers;\n knownLength?: number;\n filename?: string;\n filepath?: string;\n contentType?: string;\n }\n\n interface SubmitOptions extends http.RequestOptions {\n protocol?: 'https:' | 'http:';\n }\n}\n","file://node_modules/@takaro/helpers/package.json":"{\"name\":\"@takaro/helpers\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/helpers/dist/TakaroUserError.d.ts":"declare class TakaroUserError extends Error {\n constructor(message: string);\n}\n","file://node_modules/@takaro/helpers/dist/checkPermission.d.ts":"declare function checkPermission(player: PlayerOnGameserverOutputWithRolesDTO, permission: string): any;\n","file://node_modules/@takaro/helpers/dist/config.d.ts":"interface IHelpersConfig extends IBaseConfig {\n apiClient: {\n token: string;\n url: string;\n };\n data: string;\n}\ndeclare const config: Config;\n{};\n","file://node_modules/@takaro/helpers/dist/getData.d.ts":"declare function getData(): any;\n","file://node_modules/@takaro/helpers/dist/getTakaro.d.ts":"declare function getTakaro(data: Record, logger?: Pick): {\n takaro: Client;\n data: Record;\n};\n","file://node_modules/@takaro/helpers/dist/main.d.ts":"{ getTakaro } from './getTakaro.js';\n{ checkPermission } from './checkPermission.js';\n{ nextCronJobRun } from './nextCronJobRun.js';\n{ TakaroUserError } from './TakaroUserError.js';\n* as _ from 'lodash-es';\n* as axios from 'axios';\ndeclare const takaro: Client;\n","file://node_modules/@takaro/helpers/dist/nextCronJobRun.d.ts":"declare const nextCronJobRun: (cron: string) => Date | null;\n","file://node_modules/croner/package.json":"{\"name\":\"croner\",\"types\":\"./types/croner.d.ts\"}","file://node_modules/croner/./types/croner.d.ts":"type TimePoint = {\n /**\n * - 1970--\n */\n y: number;\n /**\n * - 1-12\n */\n m: number;\n /**\n * - 1-31\n */\n d: number;\n /**\n * - 0-24\n */\n h: number;\n /**\n * - 0-60 Minute\n */\n i: number;\n /**\n * - 0-60\n */\n s: number;\n /**\n * - Time zone in IANA database format 'Europe/Stockholm'\n */\n tz: string;\n};\ntype CatchCallbackFn = (e: unknown, job: Cron) => any;\ntype ProtectCallbackFn = (job: Cron) => any;\n/**\n * - Cron scheduler options\n */\ntype CronOptions = {\n /**\n * - Name of a job\n */\n name?: string;\n /**\n * - Job is paused\n */\n paused?: boolean;\n /**\n * - Job is about to be killed or killed\n */\n kill?: boolean;\n /**\n * - Continue exection even if a unhandled error is thrown by triggered function\n * - If set to a function, execute function on catching the error.\n */\n catch?: boolean | CatchCallbackFn;\n /**\n * - Abort job instantly if nothing else keeps the event loop running.\n */\n unref?: boolean;\n /**\n * - Maximum nuber of executions\n */\n maxRuns?: number;\n /**\n * - Minimum interval between executions, in seconds\n */\n interval?: number;\n /**\n * - Skip current run if job is already running\n */\n protect?: boolean | ProtectCallbackFn;\n /**\n * - When to start running\n */\n startAt?: string | Date;\n /**\n * - When to stop running\n */\n stopAt?: string | Date;\n /**\n * - Time zone in Europe/Stockholm format\n */\n timezone?: string;\n /**\n * - Offset from UTC in minutes\n */\n utcOffset?: number;\n /**\n * - Combine day-of-month and day-of-week using true = OR, false = AND. Default is true = OR.\n */\n legacyMode?: boolean;\n /**\n * - Used to pass any object to scheduled function\n */\n context?: unknown;\n};\n/**\n * Name for each part of the cron pattern\n */\ntype CronPatternPart = (\"second\" | \"minute\" | \"hour\" | \"day\" | \"month\" | \"dayOfWeek\");\n/**\n * Offset, 0 or -1.\n *\n * 0 offset is used for seconds,minutes and hours as they start on 1.\n * -1 on days and months, as they start on 0\n */\ntype CronIndexOffset = number;\n/**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\nfunction Cron(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function): Cron;\nclass Cron {\n /**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\n constructor(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function);\n /**\n * @public\n * @type {string|undefined} */\n public name: string | undefined;\n /**\n * @public\n * @type {CronOptions} */\n public options: CronOptions;\n /**\n * Encapsulate all internal states in an object.\n * Duplicate all options that can change to internal states, for example maxRuns and paused.\n * @private\n */\n private _states;\n fn: Function | CronOptions;\n /**\n * Find next runtime, based on supplied date. Strips milliseconds.\n *\n * @param {CronDate|Date|string} [prev] - Date to start from\n * @returns {Date | null} - Next run time\n */\n nextRun(prev?: CronDate | Date | string): Date | null;\n /**\n * Find next n runs, based on supplied date. Strips milliseconds.\n *\n * @param {number} n - Number of runs to enumerate\n * @param {Date|string} [previous] - Date to start from\n * @returns {Date[]} - Next n run times\n */\n nextRuns(n: number, previous?: Date | string): Date[];\n /**\n * Return the original pattern, if there was one\n *\n * @returns {string|undefined} - Original pattern\n */\n getPattern(): string | undefined;\n /**\n * Indicates whether or not the cron job is scheduled and running, e.g. awaiting next trigger\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isRunning(): boolean;\n /**\n * Indicates whether or not the cron job is permanently stopped\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isStopped(): boolean;\n /**\n * Indicates whether or not the cron job is currently working\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isBusy(): boolean;\n /**\n * Return current/previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public currentRun(): Date | null;\n /**\n * Return previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public previousRun(): Date | null;\n /**\n * Returns number of milliseconds to next run\n * @public\n *\n * @param {CronDate|Date|string} [prev] - Starting date, defaults to now - minimum interval\n * @returns {number | null}\n */\n public msToNext(prev?: CronDate | Date | string): number | null;\n /**\n * Stop execution\n *\n * Running this will forcefully stop the job, and prevent furter exection. `.resume()` will not work after stopping.\n * It will also be removed from the scheduledJobs array if it were named.\n *\n * @public\n */\n public stop(): void;\n /**\n * Pause execution\n * @public\n *\n * @returns {boolean} - Wether pause was successful\n */\n public pause(): boolean;\n /**\n * Resume execution\n * @public\n *\n * @returns {boolean} - Wether resume was successful\n */\n public resume(): boolean;\n /**\n * Schedule a new job\n * @public\n *\n * @param {Function} func - Function to be run each iteration of pattern\n * @returns {Cron}\n */\n public schedule(func: Function): Cron;\n private _trigger;\n /**\n * Trigger a run manually\n * @public\n */\n public trigger(): Promise;\n private _checkTrigger;\n private _next;\n private _calculatePreviousRun;\n}\nnamespace Cron {\n export { Cron };\n export { scheduledJobs };\n}\n/**\n * An array containing all named cron jobs.\n *\n * @constant\n * @type {Cron[]}\n */\nconst scheduledJobs: Cron[];\n/**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n*/\ndeclare function CronDate(d?: CronDate | Date | string, tz?: string | number): void;\ndeclare class CronDate {\n /**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n */\n constructor(d?: CronDate | Date | string, tz?: string | number);\n /**\n * TimeZone\n * @type {string|number|undefined}\n */\n tz: string | number | undefined;\n private isNthWeekdayOfMonth;\n private fromDate;\n ms: number;\n second: number;\n minute: number;\n hour: number;\n day: number;\n month: number;\n year: number;\n private fromCronDate;\n private apply;\n private fromString;\n private findNext;\n private recurse;\n /**\n * Increment to next run time\n * @public\n *\n * @param {string} pattern - The pattern used to increment current state\n * @param {CronOptions} options - Cron options used for incrementing\n * @param {boolean} [hasPreviousRun] - If this run should adhere to minimum interval\n * @return {CronDate|null} - Returns itthis for chaining, or null if increment wasnt possible\n */\n public increment(pattern: string, options: CronOptions, hasPreviousRun?: boolean): CronDate | null;\n /**\n * Convert current state back to a javascript Date()\n * @public\n *\n * @param {boolean} internal - If this is an internal call\n * @returns {Date}\n */\n public getDate(internal: boolean): Date;\n /**\n * Convert current state back to a javascript Date() and return UTC milliseconds\n * @public\n *\n * @returns {Date}\n */\n public getTime(): Date;\n}\n{ Cron as default };\n","file://node_modules/@takaro/queues/package.json":"{\"name\":\"@takaro/queues\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/queues/dist/QueueService.d.ts":"declare class QueuesService {\n private static instance;\n static getInstance(): QueuesService;\n disconnect(): Promise;\n private queuesMap;\n get queues(): {\n commands: {\n queue: TakaroQueue;\n };\n cronjobs: {\n queue: TakaroQueue;\n };\n hooks: {\n queue: TakaroQueue;\n };\n events: {\n queue: TakaroQueue;\n };\n connector: {\n queue: TakaroQueue;\n };\n itemsSync: {\n queue: TakaroQueue;\n };\n bansSync: {\n queue: TakaroQueue;\n };\n playerSync: {\n queue: TakaroQueue;\n };\n steamSync: {\n queue: TakaroQueue;\n };\n csmmImport: {\n queue: TakaroQueue;\n };\n kpi: {\n queue: TakaroQueue>;\n };\n system: {\n queue: TakaroQueue>;\n };\n };\n}\ndeclare const queueService: QueuesService;\n{};\n","file://node_modules/@takaro/queues/dist/TakaroQueue.d.ts":"declare class TakaroQueue> {\n name: string;\n bullQueue: Queue;\n constructor(name: string);\n /**\n * Generating a job ID like this effectively de-duplicates all jobs with the same data.\n * @see https://docs.bullmq.io/guide/jobs/job-ids\n * @param data\n * @returns\n */\n private getJobId;\n add(data: T, extra?: JobsOptions): Promise>;\n getRepeatableJobs(): Promise;\n removeRepeatableByKey(id: string): Promise;\n}\n","file://node_modules/@takaro/queues/dist/TakaroWorker.d.ts":"type WorkerOptionsWithoutConnectionOptions = Omit;\ndeclare abstract class TakaroWorker {\n log: import(\"winston\").Logger;\n bullWorker: Worker;\n constructor(name: string, concurrency: number | undefined, fn: Processor, extraBullOpts?: WorkerOptionsWithoutConnectionOptions);\n}\n{};\n","file://node_modules/@takaro/queues/dist/bullboard.d.ts":"declare function getBullBoard(): any;\n","file://node_modules/@takaro/queues/dist/config.d.ts":"interface IQueuesConfig extends IBaseConfig {\n queues: {\n commands: {\n name: string;\n concurrency: number;\n };\n cronjobs: {\n name: string;\n concurrency: number;\n };\n hooks: {\n name: string;\n concurrency: number;\n };\n events: {\n name: string;\n concurrency: number;\n };\n connector: {\n name: string;\n };\n itemsSync: {\n name: string;\n interval: number;\n };\n bansSync: {\n name: string;\n interval: number;\n };\n steamSync: {\n name: string;\n interval: number;\n };\n playerSync: {\n name: string;\n interval: number;\n concurrency: number;\n };\n kpi: {\n name: string;\n interval: number;\n concurrency: number;\n };\n csmmImport: {\n name: string;\n };\n system: {\n name: string;\n };\n };\n redis: {\n host: string;\n port: number;\n username: string;\n password: string;\n };\n}\ndeclare const queuesConfigSchema: {\n redis: {\n host: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n port: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n username: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n password: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n queues: {\n commands: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n cronjobs: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n hooks: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n events: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n connector: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n itemsSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n bansSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n steamSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n playerSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n kpi: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n csmmImport: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n system: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n };\n};\ndeclare const config: Config;\n","file://node_modules/@takaro/queues/dist/dataDefinitions.d.ts":"interface IParsedCommand {\n command: string;\n arguments: Record;\n [key: string]: string | Record;\n}\ninterface IBaseJobData {\n [key: string]: unknown;\n domainId: string;\n}\ninterface IJobData extends IBaseJobData {\n functionId: string;\n /**\n * The id of the item that triggered this job (cronjobId, commandId or hookId)\n */\n itemId: string;\n /**\n * The id of the gameserver that triggered this job\n */\n gameServerId: string;\n /**\n * The module installation object, including the configs\n */\n module: ModuleInstallationOutputDTO;\n}\ninterface IHookJobData extends IJobData {\n eventData: EventPayload;\n player?: PlayerOutputWithRolesDTO;\n pog?: PlayerOnGameserverOutputWithRolesDTO;\n}\ninterface ICommandJobData extends IJobData {\n player: PlayerOutputWithRolesDTO;\n pog: PlayerOnGameserverOutputWithRolesDTO;\n arguments: IParsedCommand['arguments'];\n chatMessage: EventChatMessage;\n trigger: string;\n}\ntype ICronJobData = IJobData;\ndeclare function isCommandData(data: IJobData): data is ICommandJobData;\ndeclare function isHookData(data: IJobData): data is IHookJobData;\ndeclare function isCronData(data: IJobData): data is ICronJobData;\ninterface IEventQueueData extends IBaseJobData {\n type: ValueOf;\n gameServerId: string;\n event: ValueOf<(typeof GameEventsMapping)[ValueOf]>;\n}\ninterface IConnectorQueueData extends IBaseJobData {\n gameServerId: string;\n operation: 'create' | 'update' | 'delete';\n}\ninterface IGameServerQueueData extends IBaseJobData {\n gameServerId?: string;\n}\ninterface ICSMMImportData extends IBaseJobData {\n csmmExport: Record;\n options: {\n currency: boolean;\n players: boolean;\n roles: boolean;\n shop: boolean;\n };\n}\n","file://node_modules/@takaro/queues/dist/main.d.ts":"{ queueService } from './QueueService.js';\n{ queuesConfigSchema, IQueuesConfig } from './config.js';\n* from './dataDefinitions.js';\n{ TakaroQueue } from './TakaroQueue.js';\n{ TakaroWorker } from './TakaroWorker.js';\n{ getBullBoard } from './bullboard.js';\n","file://node_modules/@takaro/queues/dist/util/redisConnectionOptions.d.ts":"declare function getRedisConnectionOptions(): {\n host: string;\n port: number;\n username: string;\n password: string;\n};\n","file://node_modules/chalk/package.json":"{\"name\":\"chalk\",\"types\":\"types/index.d.ts\"}","file://node_modules/chalk/types/index.d.ts":"// Type definitions for Chalk\n// Definitions by: Thomas Sauer \n\nconst enum Level {\n\tNone = 0,\n\tBasic = 1,\n\tAnsi256 = 2,\n\tTrueColor = 3\n}\n\ninterface ChalkOptions {\n\tenabled?: boolean;\n\tlevel?: Level;\n}\n\ninterface ChalkConstructor {\n\tnew (options?: ChalkOptions): Chalk;\n\t(options?: ChalkOptions): Chalk;\n}\n\ninterface ColorSupport {\n\tlevel: Level;\n\thasBasic: boolean;\n\thas256: boolean;\n\thas16m: boolean;\n}\n\ninterface Chalk {\n\t(...text: string[]): string;\n\t(text: TemplateStringsArray, ...placeholders: string[]): string;\n\tconstructor: ChalkConstructor;\n\tenabled: boolean;\n\tlevel: Level;\n\trgb(r: number, g: number, b: number): this;\n\thsl(h: number, s: number, l: number): this;\n\thsv(h: number, s: number, v: number): this;\n\thwb(h: number, w: number, b: number): this;\n\tbgHex(color: string): this;\n\tbgKeyword(color: string): this;\n\tbgRgb(r: number, g: number, b: number): this;\n\tbgHsl(h: number, s: number, l: number): this;\n\tbgHsv(h: number, s: number, v: number): this;\n\tbgHwb(h: number, w: number, b: number): this;\n\thex(color: string): this;\n\tkeyword(color: string): this;\n\n\treadonly reset: this;\n\treadonly bold: this;\n\treadonly dim: this;\n\treadonly italic: this;\n\treadonly underline: this;\n\treadonly inverse: this;\n\treadonly hidden: this;\n\treadonly strikethrough: this;\n\n\treadonly visible: this;\n\n\treadonly black: this;\n\treadonly red: this;\n\treadonly green: this;\n\treadonly yellow: this;\n\treadonly blue: this;\n\treadonly magenta: this;\n\treadonly cyan: this;\n\treadonly white: this;\n\treadonly gray: this;\n\treadonly grey: this;\n\treadonly blackBright: this;\n\treadonly redBright: this;\n\treadonly greenBright: this;\n\treadonly yellowBright: this;\n\treadonly blueBright: this;\n\treadonly magentaBright: this;\n\treadonly cyanBright: this;\n\treadonly whiteBright: this;\n\n\treadonly bgBlack: this;\n\treadonly bgRed: this;\n\treadonly bgGreen: this;\n\treadonly bgYellow: this;\n\treadonly bgBlue: this;\n\treadonly bgMagenta: this;\n\treadonly bgCyan: this;\n\treadonly bgWhite: this;\n\treadonly bgBlackBright: this;\n\treadonly bgRedBright: this;\n\treadonly bgGreenBright: this;\n\treadonly bgYellowBright: this;\n\treadonly bgBlueBright: this;\n\treadonly bgMagentaBright: this;\n\treadonly bgCyanBright: this;\n\treadonly bgWhiteBright: this;\n}\n\ndeclare const chalk: Chalk & { supportsColor: ColorSupport };\n\ndefault chalk\n","file://node_modules/filelist/package.json":"{\"name\":\"filelist\",\"types\":\"index.d.ts\"}","file://node_modules/filelist/index.d.ts":"// IncludeOptions definitions copied from minimatch (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/minimatch/index.d.ts)\ninterface IncludeOptions {\n /**\n * Dump a ton of stuff to stderr.\n *\n * @default false\n */\n debug?: boolean;\n\n /**\n * Do not expand {a,b} and {1..3} brace sets.\n *\n * @default false\n */\n nobrace?: boolean;\n\n /**\n * Disable ** matching against multiple folder names.\n *\n * @default false\n */\n noglobstar?: boolean;\n\n /**\n * Allow patterns to match filenames starting with a period,\n * even if the pattern does not explicitly have a period in that spot.\n *\n * @default false\n */\n dot?: boolean;\n\n /**\n * Disable \"extglob\" style patterns like +(a|b).\n *\n * @default false\n */\n noext?: boolean;\n\n /**\n * Perform a case-insensitive match.\n *\n * @default false\n */\n nocase?: boolean;\n\n /**\n * When a match is not found by minimatch.match,\n * return a list containing the pattern itself if this option is set.\n * Otherwise, an empty list is returned if there are no matches.\n *\n * @default false\n */\n nonull?: boolean;\n\n /**\n * If set, then patterns without slashes will be matched against\n * the basename of the path if it contains slashes.\n *\n * @default false\n */\n matchBase?: boolean;\n\n /**\n * Suppress the behavior of treating #\n * at the start of a pattern as a comment.\n *\n * @default false\n */\n nocomment?: boolean;\n\n /**\n * Suppress the behavior of treating a leading ! character as negation.\n *\n * @default false\n */\n nonegate?: boolean;\n\n /**\n * Returns from negate expressions the same as if they were not negated.\n * (Ie, true on a hit, false on a miss.)\n *\n * @default false\n */\n flipNegate?: boolean;\n}\n\nclass FileList {\n static clone(): FileList\n static verbose: boolean\n}\n\ninterface FileList extends Omit, \"length\"> {\n pendingAdd: string[]\n pending: boolean\n excludes: {\n pats: RegExp[],\n funcs: Function[],\n regex: null | RegExp\n }\n items: string[]\n toArray(): string[]\n include(...items: string[]): this\n include(...items: (IncludeOptions | string)[]): this\n exclude(...items: string[]): this\n shouldExclude(item: string): boolean\n resolve(): this\n clearInclusions(): this\n clearExclusions(): this\n length(): number\n}","file://node_modules/setprototypeof/package.json":"{\"name\":\"setprototypeof\",\"types\":\"index.d.ts\"}","file://node_modules/setprototypeof/index.d.ts":"declare function setPrototypeOf(o: any, proto: object | null): any;\n= setPrototypeOf;\n","file://node_modules/iconv-lite/package.json":"{\"name\":\"iconv-lite\",\"types\":\"./lib/index.d.ts\"}","file://node_modules/iconv-lite/./lib/index.d.ts":"/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n * REQUIREMENT: This definition is dependent on the @types/node definition.\n * Install with `npm install @types/node --save-dev`\n *--------------------------------------------------------------------------------------------*/\n\ndeclare module 'iconv-lite' {\n\texport function decode(buffer: Buffer, encoding: string, options?: Options): string;\n\n\texport function encode(content: string, encoding: string, options?: Options): Buffer;\n\n\texport function encodingExists(encoding: string): boolean;\n\n\texport function decodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n\n\texport function encodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n}\n\ninterface Options {\n stripBOM?: boolean;\n addBOM?: boolean;\n defaultEncoding?: string;\n}\n","file://node_modules/side-channel/package.json":"{\"name\":\"side-channel\",\"types\":\"./index.d.ts\"}","file://node_modules/side-channel/index.d.ts":"declare namespace getSideChannel {\n\ttype Key = unknown;\n\ttype ListNode = {\n\t\tkey: Key;\n\t\tnext: ListNode;\n\t\tvalue: T;\n\t};\n\ttype RootNode = {\n\t\tkey: object;\n\t\tnext: null | ListNode;\n\t};\n\tfunction listGetNode(list: RootNode, key: ListNode['key']): ListNode | void;\n\tfunction listGet(objects: RootNode, key: ListNode['key']): T | void;\n\tfunction listSet(objects: RootNode, key: ListNode['key'], value: T): void;\n\tfunction listHas(objects: RootNode, key: ListNode['key']): boolean;\n\n\ttype Channel = {\n\t\tassert: (key: Key) => void;\n\t\thas: (key: Key) => boolean;\n\t\tget: (key: Key) => T;\n\t\tset: (key: Key, value: T) => void;\n\t}\n}\n\ndeclare function getSideChannel(): getSideChannel.Channel;\n\n= getSideChannel;\n","file://node_modules/es-define-property/package.json":"{\"name\":\"es-define-property\",\"types\":\"./index.d.ts\"}","file://node_modules/es-define-property/index.d.ts":"declare const defineProperty: false | typeof Object.defineProperty;\n\n= defineProperty;","file://node_modules/hasown/package.json":"{\"name\":\"hasown\",\"types\":\"index.d.ts\"}","file://node_modules/hasown/index.d.ts":"declare function hasOwn(o: O, p: K): o is O & Record;\n\n= hasOwn;\n","file://node_modules/define-data-property/package.json":"{\"name\":\"define-data-property\",\"types\":\"./index.d.ts\"}","file://node_modules/define-data-property/index.d.ts":"\ndeclare function defineDataProperty(\n obj: Record,\n property: keyof typeof obj,\n value: typeof obj[typeof property],\n nonEnumerable?: boolean | null,\n nonWritable?: boolean | null,\n nonConfigurable?: boolean | null,\n loose?: boolean\n): void;\n\n= defineDataProperty;","file://node_modules/safe-buffer/package.json":"{\"name\":\"safe-buffer\",\"types\":\"index.d.ts\"}","file://node_modules/safe-buffer/index.d.ts":"declare module \"safe-buffer\" {\n export class Buffer {\n length: number\n write(string: string, offset?: number, length?: number, encoding?: string): number;\n toString(encoding?: string, start?: number, end?: number): string;\n toJSON(): { type: 'Buffer', data: any[] };\n equals(otherBuffer: Buffer): boolean;\n compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;\n copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;\n slice(start?: number, end?: number): Buffer;\n writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUInt8(offset: number, noAssert?: boolean): number;\n readUInt16LE(offset: number, noAssert?: boolean): number;\n readUInt16BE(offset: number, noAssert?: boolean): number;\n readUInt32LE(offset: number, noAssert?: boolean): number;\n readUInt32BE(offset: number, noAssert?: boolean): number;\n readInt8(offset: number, noAssert?: boolean): number;\n readInt16LE(offset: number, noAssert?: boolean): number;\n readInt16BE(offset: number, noAssert?: boolean): number;\n readInt32LE(offset: number, noAssert?: boolean): number;\n readInt32BE(offset: number, noAssert?: boolean): number;\n readFloatLE(offset: number, noAssert?: boolean): number;\n readFloatBE(offset: number, noAssert?: boolean): number;\n readDoubleLE(offset: number, noAssert?: boolean): number;\n readDoubleBE(offset: number, noAssert?: boolean): number;\n swap16(): Buffer;\n swap32(): Buffer;\n swap64(): Buffer;\n writeUInt8(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt8(value: number, offset: number, noAssert?: boolean): number;\n writeInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatLE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatBE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;\n fill(value: any, offset?: number, end?: number): this;\n indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;\n\n /**\n * Allocates a new buffer containing the given {str}.\n *\n * @param str String to store in buffer.\n * @param encoding encoding to use, optional. Default is 'utf8'\n */\n constructor (str: string, encoding?: string);\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n */\n constructor (size: number);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: Uint8Array);\n /**\n * Produces a Buffer backed by the same allocated memory as\n * the given {ArrayBuffer}.\n *\n *\n * @param arrayBuffer The ArrayBuffer with which to share memory.\n */\n constructor (arrayBuffer: ArrayBuffer);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: any[]);\n /**\n * Copies the passed {buffer} data onto a new {Buffer} instance.\n *\n * @param buffer The buffer to copy.\n */\n constructor (buffer: Buffer);\n prototype: Buffer;\n /**\n * Allocates a new Buffer using an {array} of octets.\n *\n * @param array\n */\n static from(array: any[]): Buffer;\n /**\n * When passed a reference to the .buffer property of a TypedArray instance,\n * the newly created Buffer will share the same allocated memory as the TypedArray.\n * The optional {byteOffset} and {length} arguments specify a memory range\n * within the {arrayBuffer} that will be shared by the Buffer.\n *\n * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer()\n * @param byteOffset\n * @param length\n */\n static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;\n /**\n * Copies the passed {buffer} data onto a new Buffer instance.\n *\n * @param buffer\n */\n static from(buffer: Buffer): Buffer;\n /**\n * Creates a new Buffer containing the given JavaScript string {str}.\n * If provided, the {encoding} parameter identifies the character encoding.\n * If not provided, {encoding} defaults to 'utf8'.\n *\n * @param str\n */\n static from(str: string, encoding?: string): Buffer;\n /**\n * Returns true if {obj} is a Buffer\n *\n * @param obj object to test.\n */\n static isBuffer(obj: any): obj is Buffer;\n /**\n * Returns true if {encoding} is a valid encoding argument.\n * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex'\n *\n * @param encoding string to test.\n */\n static isEncoding(encoding: string): boolean;\n /**\n * Gives the actual byte length of a string. encoding defaults to 'utf8'.\n * This is not the same as String.prototype.length since that returns the number of characters in a string.\n *\n * @param string string to test.\n * @param encoding encoding used to evaluate (defaults to 'utf8')\n */\n static byteLength(string: string, encoding?: string): number;\n /**\n * Returns a buffer which is the result of concatenating all the buffers in the list together.\n *\n * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.\n * If the list has exactly one item, then the first item of the list is returned.\n * If the list has more than one item, then a new Buffer is created.\n *\n * @param list An array of Buffer objects to concatenate\n * @param totalLength Total length of the buffers when concatenated.\n * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.\n */\n static concat(list: Buffer[], totalLength?: number): Buffer;\n /**\n * The same as buf1.compare(buf2).\n */\n static compare(buf1: Buffer, buf2: Buffer): number;\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n * @param fill if specified, buffer will be initialized by calling buf.fill(fill).\n * If parameter is omitted, buffer will be filled with zeros.\n * @param encoding encoding used for call to buf.fill while initalizing\n */\n static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;\n /**\n * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafe(size: number): Buffer;\n /**\n * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafeSlow(size: number): Buffer;\n }\n}","file://node_modules/ipaddr.js/package.json":"{\"name\":\"ipaddr.js\",\"types\":\"./lib/ipaddr.js.d.ts\"}","file://node_modules/ipaddr.js/./lib/ipaddr.js.d.ts":"declare module \"ipaddr.js\" {\n type IPv4Range = 'unicast' | 'unspecified' | 'broadcast' | 'multicast' | 'linkLocal' | 'loopback' | 'carrierGradeNat' | 'private' | 'reserved';\n type IPv6Range = 'unicast' | 'unspecified' | 'linkLocal' | 'multicast' | 'loopback' | 'uniqueLocal' | 'ipv4Mapped' | 'rfc6145' | 'rfc6052' | '6to4' | 'teredo' | 'reserved';\n\n interface RangeList {\n [name: string]: [T, number] | [T, number][];\n }\n\n // Common methods/properties for IPv4 and IPv6 classes.\n class IP {\n prefixLengthFromSubnetMask(): number | null;\n toByteArray(): number[];\n toNormalizedString(): string;\n toString(): string;\n }\n\n namespace Address {\n export function isValid(addr: string): boolean;\n export function fromByteArray(bytes: number[]): IPv4 | IPv6;\n export function parse(addr: string): IPv4 | IPv6;\n export function parseCIDR(mask: string): [IPv4 | IPv6, number];\n export function process(addr: string): IPv4 | IPv6;\n export function subnetMatch(addr: IPv4, rangeList: RangeList, defaultName?: string): string;\n export function subnetMatch(addr: IPv6, rangeList: RangeList, defaultName?: string): string;\n\n export class IPv4 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv4;\n static isIPv4(addr: string): boolean;\n static isValidFourPartDecimal(addr: string): boolean;\n static isValid(addr: string): boolean;\n static networkAddressFromCIDR(addr: string): IPv4;\n static parse(addr: string): IPv4;\n static parseCIDR(addr: string): [IPv4, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv4;\n constructor(octets: number[]);\n octets: number[]\n\n kind(): 'ipv4';\n match(addr: IPv4, bits: number): boolean;\n match(mask: [IPv4, number]): boolean;\n range(): IPv4Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4MappedAddress(): IPv6;\n }\n\n export class IPv6 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv6;\n static isIPv6(addr: string): boolean;\n static isValid(addr: string): boolean;\n static parse(addr: string): IPv6;\n static parseCIDR(addr: string): [IPv6, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv6;\n constructor(parts: number[]);\n parts: number[]\n zoneId?: string\n\n isIPv4MappedAddress(): boolean;\n kind(): 'ipv6';\n match(addr: IPv6, bits: number): boolean;\n match(mask: [IPv6, number]): boolean;\n range(): IPv6Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4Address(): IPv4;\n }\n }\n\n export = Address;\n}\n"} +{"file://node_modules/axios/package.json":"{\"name\":\"axios\",\"types\":\"./index.d.ts\"}","file://node_modules/axios/index.d.ts":"// TypeScript Version: 4.7\ntype AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null;\n\ninterface RawAxiosHeaders {\n [key: string]: AxiosHeaderValue;\n}\n\ntype MethodsHeaders = Partial<{\n [Key in Method as Lowercase]: AxiosHeaders;\n} & {common: AxiosHeaders}>;\n\ntype AxiosHeaderMatcher = string | RegExp | ((this: AxiosHeaders, value: string, name: string) => boolean);\n\ntype AxiosHeaderParser = (this: AxiosHeaders, value: AxiosHeaderValue, header: string) => any;\n\nclass AxiosHeaders {\n constructor(\n headers?: RawAxiosHeaders | AxiosHeaders | string\n );\n\n [key: string]: any;\n\n set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders;\n\n get(headerName: string, parser: RegExp): RegExpExecArray | null;\n get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;\n\n has(header: string, matcher?: AxiosHeaderMatcher): boolean;\n\n delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;\n\n clear(matcher?: AxiosHeaderMatcher): boolean;\n\n normalize(format: boolean): AxiosHeaders;\n\n concat(...targets: Array): AxiosHeaders;\n\n toJSON(asStrings?: boolean): RawAxiosHeaders;\n\n static from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;\n\n static accessor(header: string | string[]): AxiosHeaders;\n\n static concat(...targets: Array): AxiosHeaders;\n\n setContentType(value: ContentType, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentType(parser?: RegExp): RegExpExecArray | null;\n getContentType(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentType(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentLength(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentLength(parser?: RegExp): RegExpExecArray | null;\n getContentLength(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentLength(matcher?: AxiosHeaderMatcher): boolean;\n\n setAccept(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAccept(parser?: RegExp): RegExpExecArray | null;\n getAccept(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAccept(matcher?: AxiosHeaderMatcher): boolean;\n\n setUserAgent(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getUserAgent(parser?: RegExp): RegExpExecArray | null;\n getUserAgent(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasUserAgent(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentEncoding(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentEncoding(parser?: RegExp): RegExpExecArray | null;\n getContentEncoding(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentEncoding(matcher?: AxiosHeaderMatcher): boolean;\n\n setAuthorization(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAuthorization(parser?: RegExp): RegExpExecArray | null;\n getAuthorization(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAuthorization(matcher?: AxiosHeaderMatcher): boolean;\n\n [Symbol.iterator](): IterableIterator<[string, AxiosHeaderValue]>;\n}\n\ntype CommonRequestHeadersList = 'Accept' | 'Content-Length' | 'User-Agent' | 'Content-Encoding' | 'Authorization';\n\ntype ContentType = AxiosHeaderValue | 'text/html' | 'text/plain' | 'multipart/form-data' | 'application/json' | 'application/x-www-form-urlencoded' | 'application/octet-stream';\n\ntype RawAxiosRequestHeaders = Partial;\n\ntype AxiosRequestHeaders = RawAxiosRequestHeaders & AxiosHeaders;\n\ntype CommonResponseHeadersList = 'Server' | 'Content-Type' | 'Content-Length' | 'Cache-Control'| 'Content-Encoding';\n\ntype RawCommonResponseHeaders = {\n [Key in CommonResponseHeadersList]: AxiosHeaderValue;\n} & {\n \"set-cookie\": string[];\n};\n\ntype RawAxiosResponseHeaders = Partial;\n\ntype AxiosResponseHeaders = RawAxiosResponseHeaders & AxiosHeaders;\n\ninterface AxiosRequestTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosRequestHeaders): any;\n}\n\ninterface AxiosResponseTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosResponseHeaders, status?: number): any;\n}\n\ninterface AxiosAdapter {\n (config: InternalAxiosRequestConfig): AxiosPromise;\n}\n\ninterface AxiosBasicCredentials {\n username: string;\n password: string;\n}\n\ninterface AxiosProxyConfig {\n host: string;\n port: number;\n auth?: AxiosBasicCredentials;\n protocol?: string;\n}\n\nenum HttpStatusCode {\n Continue = 100,\n SwitchingProtocols = 101,\n Processing = 102,\n EarlyHints = 103,\n Ok = 200,\n Created = 201,\n Accepted = 202,\n NonAuthoritativeInformation = 203,\n NoContent = 204,\n ResetContent = 205,\n PartialContent = 206,\n MultiStatus = 207,\n AlreadyReported = 208,\n ImUsed = 226,\n MultipleChoices = 300,\n MovedPermanently = 301,\n Found = 302,\n SeeOther = 303,\n NotModified = 304,\n UseProxy = 305,\n Unused = 306,\n TemporaryRedirect = 307,\n PermanentRedirect = 308,\n BadRequest = 400,\n Unauthorized = 401,\n PaymentRequired = 402,\n Forbidden = 403,\n NotFound = 404,\n MethodNotAllowed = 405,\n NotAcceptable = 406,\n ProxyAuthenticationRequired = 407,\n RequestTimeout = 408,\n Conflict = 409,\n Gone = 410,\n LengthRequired = 411,\n PreconditionFailed = 412,\n PayloadTooLarge = 413,\n UriTooLong = 414,\n UnsupportedMediaType = 415,\n RangeNotSatisfiable = 416,\n ExpectationFailed = 417,\n ImATeapot = 418,\n MisdirectedRequest = 421,\n UnprocessableEntity = 422,\n Locked = 423,\n FailedDependency = 424,\n TooEarly = 425,\n UpgradeRequired = 426,\n PreconditionRequired = 428,\n TooManyRequests = 429,\n RequestHeaderFieldsTooLarge = 431,\n UnavailableForLegalReasons = 451,\n InternalServerError = 500,\n NotImplemented = 501,\n BadGateway = 502,\n ServiceUnavailable = 503,\n GatewayTimeout = 504,\n HttpVersionNotSupported = 505,\n VariantAlsoNegotiates = 506,\n InsufficientStorage = 507,\n LoopDetected = 508,\n NotExtended = 510,\n NetworkAuthenticationRequired = 511,\n}\n\ntype Method =\n | 'get' | 'GET'\n | 'delete' | 'DELETE'\n | 'head' | 'HEAD'\n | 'options' | 'OPTIONS'\n | 'post' | 'POST'\n | 'put' | 'PUT'\n | 'patch' | 'PATCH'\n | 'purge' | 'PURGE'\n | 'link' | 'LINK'\n | 'unlink' | 'UNLINK';\n\ntype ResponseType =\n | 'arraybuffer'\n | 'blob'\n | 'document'\n | 'json'\n | 'text'\n | 'stream'\n | 'formdata';\n\ntype responseEncoding =\n | 'ascii' | 'ASCII'\n | 'ansi' | 'ANSI'\n | 'binary' | 'BINARY'\n | 'base64' | 'BASE64'\n | 'base64url' | 'BASE64URL'\n | 'hex' | 'HEX'\n | 'latin1' | 'LATIN1'\n | 'ucs-2' | 'UCS-2'\n | 'ucs2' | 'UCS2'\n | 'utf-8' | 'UTF-8'\n | 'utf8' | 'UTF8'\n | 'utf16le' | 'UTF16LE';\n\ninterface TransitionalOptions {\n silentJSONParsing?: boolean;\n forcedJSONParsing?: boolean;\n clarifyTimeoutError?: boolean;\n}\n\ninterface GenericAbortSignal {\n readonly aborted: boolean;\n onabort?: ((...args: any) => any) | null;\n addEventListener?: (...args: any) => any;\n removeEventListener?: (...args: any) => any;\n}\n\ninterface FormDataVisitorHelpers {\n defaultVisitor: SerializerVisitor;\n convertValue: (value: any) => any;\n isVisitable: (value: any) => boolean;\n}\n\ninterface SerializerVisitor {\n (\n this: GenericFormData,\n value: any,\n key: string | number,\n path: null | Array,\n helpers: FormDataVisitorHelpers\n ): boolean;\n}\n\ninterface SerializerOptions {\n visitor?: SerializerVisitor;\n dots?: boolean;\n metaTokens?: boolean;\n indexes?: boolean | null;\n}\n\n// tslint:disable-next-line\ninterface FormSerializerOptions extends SerializerOptions {\n}\n\ninterface ParamEncoder {\n (value: any, defaultEncoder: (value: any) => any): any;\n}\n\ninterface CustomParamsSerializer {\n (params: Record, options?: ParamsSerializerOptions): string;\n}\n\ninterface ParamsSerializerOptions extends SerializerOptions {\n encode?: ParamEncoder;\n serialize?: CustomParamsSerializer;\n}\n\ntype MaxUploadRate = number;\n\ntype MaxDownloadRate = number;\n\ntype BrowserProgressEvent = any;\n\ninterface AxiosProgressEvent {\n loaded: number;\n total?: number;\n progress?: number;\n bytes: number;\n rate?: number;\n estimated?: number;\n upload?: boolean;\n download?: boolean;\n event?: BrowserProgressEvent;\n lengthComputable: boolean;\n}\n\ntype Milliseconds = number;\n\ntype AxiosAdapterName = 'fetch' | 'xhr' | 'http' | string;\n\ntype AxiosAdapterConfig = AxiosAdapter | AxiosAdapterName;\n\ntype AddressFamily = 4 | 6 | undefined;\n\ninterface LookupAddressEntry {\n address: string;\n family?: AddressFamily;\n}\n\ntype LookupAddress = string | LookupAddressEntry;\n\ninterface AxiosRequestConfig {\n url?: string;\n method?: Method | string;\n baseURL?: string;\n transformRequest?: AxiosRequestTransformer | AxiosRequestTransformer[];\n transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[];\n headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders;\n params?: any;\n paramsSerializer?: ParamsSerializerOptions | CustomParamsSerializer;\n data?: D;\n timeout?: Milliseconds;\n timeoutErrorMessage?: string;\n withCredentials?: boolean;\n adapter?: AxiosAdapterConfig | AxiosAdapterConfig[];\n auth?: AxiosBasicCredentials;\n responseType?: ResponseType;\n responseEncoding?: responseEncoding | string;\n xsrfCookieName?: string;\n xsrfHeaderName?: string;\n onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;\n onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void;\n maxContentLength?: number;\n validateStatus?: ((status: number) => boolean) | null;\n maxBodyLength?: number;\n maxRedirects?: number;\n maxRate?: number | [MaxUploadRate, MaxDownloadRate];\n beforeRedirect?: (options: Record, responseDetails: {headers: Record, statusCode: HttpStatusCode}) => void;\n socketPath?: string | null;\n transport?: any;\n httpAgent?: any;\n httpsAgent?: any;\n proxy?: AxiosProxyConfig | false;\n cancelToken?: CancelToken;\n decompress?: boolean;\n transitional?: TransitionalOptions;\n signal?: GenericAbortSignal;\n insecureHTTPParser?: boolean;\n env?: {\n FormData?: new (...args: any[]) => object;\n };\n formSerializer?: FormSerializerOptions;\n family?: AddressFamily;\n lookup?: ((hostname: string, options: object, cb: (err: Error | null, address: LookupAddress | LookupAddress[], family?: AddressFamily) => void) => void) |\n ((hostname: string, options: object) => Promise<[address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress>);\n withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined);\n fetchOptions?: Record;\n}\n\n// Alias\ntype RawAxiosRequestConfig = AxiosRequestConfig;\n\ninterface InternalAxiosRequestConfig extends AxiosRequestConfig {\n headers: AxiosRequestHeaders;\n}\n\ninterface HeadersDefaults {\n common: RawAxiosRequestHeaders;\n delete: RawAxiosRequestHeaders;\n get: RawAxiosRequestHeaders;\n head: RawAxiosRequestHeaders;\n post: RawAxiosRequestHeaders;\n put: RawAxiosRequestHeaders;\n patch: RawAxiosRequestHeaders;\n options?: RawAxiosRequestHeaders;\n purge?: RawAxiosRequestHeaders;\n link?: RawAxiosRequestHeaders;\n unlink?: RawAxiosRequestHeaders;\n}\n\ninterface AxiosDefaults extends Omit, 'headers'> {\n headers: HeadersDefaults;\n}\n\ninterface CreateAxiosDefaults extends Omit, 'headers'> {\n headers?: RawAxiosRequestHeaders | AxiosHeaders | Partial;\n}\n\ninterface AxiosResponse {\n data: T;\n status: number;\n statusText: string;\n headers: RawAxiosResponseHeaders | AxiosResponseHeaders;\n config: InternalAxiosRequestConfig;\n request?: any;\n}\n\nclass AxiosError extends Error {\n constructor(\n message?: string,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse\n );\n\n config?: InternalAxiosRequestConfig;\n code?: string;\n request?: any;\n response?: AxiosResponse;\n isAxiosError: boolean;\n status?: number;\n toJSON: () => object;\n cause?: Error;\n static from(\n error: Error | unknown,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse,\n customProps?: object,\n): AxiosError;\n static readonly ERR_FR_TOO_MANY_REDIRECTS = \"ERR_FR_TOO_MANY_REDIRECTS\";\n static readonly ERR_BAD_OPTION_VALUE = \"ERR_BAD_OPTION_VALUE\";\n static readonly ERR_BAD_OPTION = \"ERR_BAD_OPTION\";\n static readonly ERR_NETWORK = \"ERR_NETWORK\";\n static readonly ERR_DEPRECATED = \"ERR_DEPRECATED\";\n static readonly ERR_BAD_RESPONSE = \"ERR_BAD_RESPONSE\";\n static readonly ERR_BAD_REQUEST = \"ERR_BAD_REQUEST\";\n static readonly ERR_NOT_SUPPORT = \"ERR_NOT_SUPPORT\";\n static readonly ERR_INVALID_URL = \"ERR_INVALID_URL\";\n static readonly ERR_CANCELED = \"ERR_CANCELED\";\n static readonly ECONNABORTED = \"ECONNABORTED\";\n static readonly ETIMEDOUT = \"ETIMEDOUT\";\n}\n\nclass CanceledError extends AxiosError {\n}\n\ntype AxiosPromise = Promise>;\n\ninterface CancelStatic {\n new (message?: string): Cancel;\n}\n\ninterface Cancel {\n message: string | undefined;\n}\n\ninterface Canceler {\n (message?: string, config?: AxiosRequestConfig, request?: any): void;\n}\n\ninterface CancelTokenStatic {\n new (executor: (cancel: Canceler) => void): CancelToken;\n source(): CancelTokenSource;\n}\n\ninterface CancelToken {\n promise: Promise;\n reason?: Cancel;\n throwIfRequested(): void;\n}\n\ninterface CancelTokenSource {\n token: CancelToken;\n cancel: Canceler;\n}\n\ninterface AxiosInterceptorOptions {\n synchronous?: boolean;\n runWhen?: (config: InternalAxiosRequestConfig) => boolean;\n}\n\ninterface AxiosInterceptorManager {\n use(onFulfilled?: ((value: V) => V | Promise) | null, onRejected?: ((error: any) => any) | null, options?: AxiosInterceptorOptions): number;\n eject(id: number): void;\n clear(): void;\n}\n\nclass Axios {\n constructor(config?: AxiosRequestConfig);\n defaults: AxiosDefaults;\n interceptors: {\n request: AxiosInterceptorManager;\n response: AxiosInterceptorManager;\n };\n getUri(config?: AxiosRequestConfig): string;\n request, D = any>(config: AxiosRequestConfig): Promise;\n get, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n delete, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n head, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n options, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n post, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n put, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patch, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n postForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n putForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patchForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n}\n\ninterface AxiosInstance extends Axios {\n , D = any>(config: AxiosRequestConfig): Promise;\n , D = any>(url: string, config?: AxiosRequestConfig): Promise;\n\n defaults: Omit & {\n headers: HeadersDefaults & {\n [key: string]: AxiosHeaderValue\n }\n };\n}\n\ninterface GenericFormData {\n append(name: string, value: any, options?: any): any;\n}\n\ninterface GenericHTMLFormElement {\n name: string;\n method: string;\n submit(): void;\n}\n\nfunction getAdapter(adapters: AxiosAdapterConfig | AxiosAdapterConfig[] | undefined): AxiosAdapter;\n\nfunction toFormData(sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions): GenericFormData;\n\nfunction formToJSON(form: GenericFormData|GenericHTMLFormElement): object;\n\nfunction isAxiosError(payload: any): payload is AxiosError;\n\nfunction spread(callback: (...args: T[]) => R): (array: T[]) => R;\n\nfunction isCancel(value: any): value is Cancel;\n\nfunction all(values: Array>): Promise;\n\ninterface AxiosStatic extends AxiosInstance {\n create(config?: CreateAxiosDefaults): AxiosInstance;\n Cancel: CancelStatic;\n CancelToken: CancelTokenStatic;\n Axios: typeof Axios;\n AxiosError: typeof AxiosError;\n HttpStatusCode: typeof HttpStatusCode;\n readonly VERSION: string;\n isCancel: typeof isCancel;\n all: typeof all;\n spread: typeof spread;\n isAxiosError: typeof isAxiosError;\n toFormData: typeof toFormData;\n formToJSON: typeof formToJSON;\n getAdapter: typeof getAdapter;\n CanceledError: typeof CanceledError;\n AxiosHeaders: typeof AxiosHeaders;\n}\n\ndeclare const axios: AxiosStatic;\n\ndefault axios;\n","file://node_modules/form-data/package.json":"{\"name\":\"form-data\",\"types\":\"./index.d.ts\"}","file://node_modules/form-data/index.d.ts":"// Definitions by: Carlos Ballesteros Velasco \n// Leon Yu \n// BendingBender \n// Maple Miao \n\n/// \n\n= FormData;\n\n// Extracted because @types/node doesn't export interfaces.\ninterface ReadableOptions {\n highWaterMark?: number;\n encoding?: string;\n objectMode?: boolean;\n read?(this: stream.Readable, size: number): void;\n destroy?(this: stream.Readable, error: Error | null, callback: (error: Error | null) => void): void;\n autoDestroy?: boolean;\n}\n\ninterface Options extends ReadableOptions {\n writable?: boolean;\n readable?: boolean;\n dataSize?: number;\n maxDataSize?: number;\n pauseStreams?: boolean;\n}\n\ndeclare class FormData extends stream.Readable {\n constructor(options?: Options);\n append(key: string, value: any, options?: FormData.AppendOptions | string): void;\n getHeaders(userHeaders?: FormData.Headers): FormData.Headers;\n submit(\n params: string | FormData.SubmitOptions,\n callback?: (error: Error | null, response: http.IncomingMessage) => void\n ): http.ClientRequest;\n getBuffer(): Buffer;\n setBoundary(boundary: string): void;\n getBoundary(): string;\n getLength(callback: (err: Error | null, length: number) => void): void;\n getLengthSync(): number;\n hasKnownLength(): boolean;\n}\n\ndeclare namespace FormData {\n interface Headers {\n [key: string]: any;\n }\n\n interface AppendOptions {\n header?: string | Headers;\n knownLength?: number;\n filename?: string;\n filepath?: string;\n contentType?: string;\n }\n\n interface SubmitOptions extends http.RequestOptions {\n protocol?: 'https:' | 'http:';\n }\n}\n","file://node_modules/@takaro/helpers/package.json":"{\"name\":\"@takaro/helpers\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/helpers/dist/TakaroUserError.d.ts":"declare class TakaroUserError extends Error {\n constructor(message: string);\n}\n","file://node_modules/@takaro/helpers/dist/checkPermission.d.ts":"declare function checkPermission(player: PlayerOnGameserverOutputWithRolesDTO, permission: string): any;\n","file://node_modules/@takaro/helpers/dist/config.d.ts":"interface IHelpersConfig extends IBaseConfig {\n apiClient: {\n token: string;\n url: string;\n };\n data: string;\n}\ndeclare const config: Config;\n{};\n","file://node_modules/@takaro/helpers/dist/getData.d.ts":"declare function getData(): any;\n","file://node_modules/@takaro/helpers/dist/getTakaro.d.ts":"declare function getTakaro(data: Record, logger?: Pick): {\n takaro: Client;\n data: Record;\n};\n","file://node_modules/@takaro/helpers/dist/main.d.ts":"{ getTakaro } from './getTakaro.js';\n{ checkPermission } from './checkPermission.js';\n{ nextCronJobRun } from './nextCronJobRun.js';\n{ TakaroUserError } from './TakaroUserError.js';\n* as _ from 'lodash-es';\n* as axios from 'axios';\ndeclare const takaro: Client;\n","file://node_modules/@takaro/helpers/dist/nextCronJobRun.d.ts":"declare const nextCronJobRun: (cron: string) => Date | null;\n","file://node_modules/croner/package.json":"{\"name\":\"croner\",\"types\":\"./types/croner.d.ts\"}","file://node_modules/croner/./types/croner.d.ts":"type TimePoint = {\n /**\n * - 1970--\n */\n y: number;\n /**\n * - 1-12\n */\n m: number;\n /**\n * - 1-31\n */\n d: number;\n /**\n * - 0-24\n */\n h: number;\n /**\n * - 0-60 Minute\n */\n i: number;\n /**\n * - 0-60\n */\n s: number;\n /**\n * - Time zone in IANA database format 'Europe/Stockholm'\n */\n tz: string;\n};\ntype CatchCallbackFn = (e: unknown, job: Cron) => any;\ntype ProtectCallbackFn = (job: Cron) => any;\n/**\n * - Cron scheduler options\n */\ntype CronOptions = {\n /**\n * - Name of a job\n */\n name?: string;\n /**\n * - Job is paused\n */\n paused?: boolean;\n /**\n * - Job is about to be killed or killed\n */\n kill?: boolean;\n /**\n * - Continue exection even if a unhandled error is thrown by triggered function\n * - If set to a function, execute function on catching the error.\n */\n catch?: boolean | CatchCallbackFn;\n /**\n * - Abort job instantly if nothing else keeps the event loop running.\n */\n unref?: boolean;\n /**\n * - Maximum nuber of executions\n */\n maxRuns?: number;\n /**\n * - Minimum interval between executions, in seconds\n */\n interval?: number;\n /**\n * - Skip current run if job is already running\n */\n protect?: boolean | ProtectCallbackFn;\n /**\n * - When to start running\n */\n startAt?: string | Date;\n /**\n * - When to stop running\n */\n stopAt?: string | Date;\n /**\n * - Time zone in Europe/Stockholm format\n */\n timezone?: string;\n /**\n * - Offset from UTC in minutes\n */\n utcOffset?: number;\n /**\n * - Combine day-of-month and day-of-week using true = OR, false = AND. Default is true = OR.\n */\n legacyMode?: boolean;\n /**\n * - Used to pass any object to scheduled function\n */\n context?: unknown;\n};\n/**\n * Name for each part of the cron pattern\n */\ntype CronPatternPart = (\"second\" | \"minute\" | \"hour\" | \"day\" | \"month\" | \"dayOfWeek\");\n/**\n * Offset, 0 or -1.\n *\n * 0 offset is used for seconds,minutes and hours as they start on 1.\n * -1 on days and months, as they start on 0\n */\ntype CronIndexOffset = number;\n/**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\nfunction Cron(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function): Cron;\nclass Cron {\n /**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\n constructor(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function);\n /**\n * @public\n * @type {string|undefined} */\n public name: string | undefined;\n /**\n * @public\n * @type {CronOptions} */\n public options: CronOptions;\n /**\n * Encapsulate all internal states in an object.\n * Duplicate all options that can change to internal states, for example maxRuns and paused.\n * @private\n */\n private _states;\n fn: Function | CronOptions;\n /**\n * Find next runtime, based on supplied date. Strips milliseconds.\n *\n * @param {CronDate|Date|string} [prev] - Date to start from\n * @returns {Date | null} - Next run time\n */\n nextRun(prev?: CronDate | Date | string): Date | null;\n /**\n * Find next n runs, based on supplied date. Strips milliseconds.\n *\n * @param {number} n - Number of runs to enumerate\n * @param {Date|string} [previous] - Date to start from\n * @returns {Date[]} - Next n run times\n */\n nextRuns(n: number, previous?: Date | string): Date[];\n /**\n * Return the original pattern, if there was one\n *\n * @returns {string|undefined} - Original pattern\n */\n getPattern(): string | undefined;\n /**\n * Indicates whether or not the cron job is scheduled and running, e.g. awaiting next trigger\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isRunning(): boolean;\n /**\n * Indicates whether or not the cron job is permanently stopped\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isStopped(): boolean;\n /**\n * Indicates whether or not the cron job is currently working\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isBusy(): boolean;\n /**\n * Return current/previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public currentRun(): Date | null;\n /**\n * Return previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public previousRun(): Date | null;\n /**\n * Returns number of milliseconds to next run\n * @public\n *\n * @param {CronDate|Date|string} [prev] - Starting date, defaults to now - minimum interval\n * @returns {number | null}\n */\n public msToNext(prev?: CronDate | Date | string): number | null;\n /**\n * Stop execution\n *\n * Running this will forcefully stop the job, and prevent furter exection. `.resume()` will not work after stopping.\n * It will also be removed from the scheduledJobs array if it were named.\n *\n * @public\n */\n public stop(): void;\n /**\n * Pause execution\n * @public\n *\n * @returns {boolean} - Wether pause was successful\n */\n public pause(): boolean;\n /**\n * Resume execution\n * @public\n *\n * @returns {boolean} - Wether resume was successful\n */\n public resume(): boolean;\n /**\n * Schedule a new job\n * @public\n *\n * @param {Function} func - Function to be run each iteration of pattern\n * @returns {Cron}\n */\n public schedule(func: Function): Cron;\n private _trigger;\n /**\n * Trigger a run manually\n * @public\n */\n public trigger(): Promise;\n private _checkTrigger;\n private _next;\n private _calculatePreviousRun;\n}\nnamespace Cron {\n export { Cron };\n export { scheduledJobs };\n}\n/**\n * An array containing all named cron jobs.\n *\n * @constant\n * @type {Cron[]}\n */\nconst scheduledJobs: Cron[];\n/**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n*/\ndeclare function CronDate(d?: CronDate | Date | string, tz?: string | number): void;\ndeclare class CronDate {\n /**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n */\n constructor(d?: CronDate | Date | string, tz?: string | number);\n /**\n * TimeZone\n * @type {string|number|undefined}\n */\n tz: string | number | undefined;\n private isNthWeekdayOfMonth;\n private fromDate;\n ms: number;\n second: number;\n minute: number;\n hour: number;\n day: number;\n month: number;\n year: number;\n private fromCronDate;\n private apply;\n private fromString;\n private findNext;\n private recurse;\n /**\n * Increment to next run time\n * @public\n *\n * @param {string} pattern - The pattern used to increment current state\n * @param {CronOptions} options - Cron options used for incrementing\n * @param {boolean} [hasPreviousRun] - If this run should adhere to minimum interval\n * @return {CronDate|null} - Returns itthis for chaining, or null if increment wasnt possible\n */\n public increment(pattern: string, options: CronOptions, hasPreviousRun?: boolean): CronDate | null;\n /**\n * Convert current state back to a javascript Date()\n * @public\n *\n * @param {boolean} internal - If this is an internal call\n * @returns {Date}\n */\n public getDate(internal: boolean): Date;\n /**\n * Convert current state back to a javascript Date() and return UTC milliseconds\n * @public\n *\n * @returns {Date}\n */\n public getTime(): Date;\n}\n{ Cron as default };\n","file://node_modules/@takaro/queues/package.json":"{\"name\":\"@takaro/queues\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/queues/dist/QueueService.d.ts":"declare class QueuesService {\n private static instance;\n static getInstance(): QueuesService;\n disconnect(): Promise;\n private queuesMap;\n get queues(): {\n commands: {\n queue: TakaroQueue;\n };\n cronjobs: {\n queue: TakaroQueue;\n };\n hooks: {\n queue: TakaroQueue;\n };\n events: {\n queue: TakaroQueue;\n };\n connector: {\n queue: TakaroQueue;\n };\n itemsSync: {\n queue: TakaroQueue;\n };\n bansSync: {\n queue: TakaroQueue;\n };\n playerSync: {\n queue: TakaroQueue;\n };\n steamSync: {\n queue: TakaroQueue;\n };\n csmmImport: {\n queue: TakaroQueue;\n };\n kpi: {\n queue: TakaroQueue>;\n };\n system: {\n queue: TakaroQueue>;\n };\n };\n}\ndeclare const queueService: QueuesService;\n{};\n","file://node_modules/@takaro/queues/dist/TakaroQueue.d.ts":"declare class TakaroQueue> {\n name: string;\n bullQueue: Queue;\n constructor(name: string);\n /**\n * Generating a job ID like this effectively de-duplicates all jobs with the same data.\n * @see https://docs.bullmq.io/guide/jobs/job-ids\n * @param data\n * @returns\n */\n private getJobId;\n add(data: T, extra?: JobsOptions): Promise>;\n getRepeatableJobs(): Promise;\n removeRepeatableByKey(id: string): Promise;\n}\n","file://node_modules/@takaro/queues/dist/TakaroWorker.d.ts":"type WorkerOptionsWithoutConnectionOptions = Omit;\ndeclare abstract class TakaroWorker {\n log: import(\"winston\").Logger;\n bullWorker: Worker;\n constructor(name: string, concurrency: number | undefined, fn: Processor, extraBullOpts?: WorkerOptionsWithoutConnectionOptions);\n}\n{};\n","file://node_modules/@takaro/queues/dist/bullboard.d.ts":"declare function getBullBoard(): any;\n","file://node_modules/@takaro/queues/dist/config.d.ts":"interface IQueuesConfig extends IBaseConfig {\n queues: {\n commands: {\n name: string;\n concurrency: number;\n };\n cronjobs: {\n name: string;\n concurrency: number;\n };\n hooks: {\n name: string;\n concurrency: number;\n };\n events: {\n name: string;\n concurrency: number;\n };\n connector: {\n name: string;\n };\n itemsSync: {\n name: string;\n interval: number;\n };\n bansSync: {\n name: string;\n interval: number;\n };\n steamSync: {\n name: string;\n interval: number;\n };\n playerSync: {\n name: string;\n interval: number;\n concurrency: number;\n };\n kpi: {\n name: string;\n interval: number;\n concurrency: number;\n };\n csmmImport: {\n name: string;\n };\n system: {\n name: string;\n };\n };\n redis: {\n host: string;\n port: number;\n username: string;\n password: string;\n };\n}\ndeclare const queuesConfigSchema: {\n redis: {\n host: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n port: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n username: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n password: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n queues: {\n commands: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n cronjobs: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n hooks: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n events: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n connector: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n itemsSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n bansSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n steamSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n playerSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n kpi: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n csmmImport: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n system: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n };\n};\ndeclare const config: Config;\n","file://node_modules/@takaro/queues/dist/dataDefinitions.d.ts":"interface IParsedCommand {\n command: string;\n arguments: Record;\n [key: string]: string | Record;\n}\ninterface IBaseJobData {\n [key: string]: unknown;\n domainId: string;\n}\ninterface IJobData extends IBaseJobData {\n functionId: string;\n /**\n * The id of the item that triggered this job (cronjobId, commandId or hookId)\n */\n itemId: string;\n /**\n * The id of the gameserver that triggered this job\n */\n gameServerId: string;\n /**\n * The module installation object, including the configs\n */\n module: ModuleInstallationOutputDTO;\n}\ninterface IHookJobData extends IJobData {\n eventData: EventPayload;\n player?: PlayerOutputWithRolesDTO;\n pog?: PlayerOnGameserverOutputWithRolesDTO;\n}\ninterface ICommandJobData extends IJobData {\n player: PlayerOutputWithRolesDTO;\n pog: PlayerOnGameserverOutputWithRolesDTO;\n arguments: IParsedCommand['arguments'];\n chatMessage: EventChatMessage;\n trigger: string;\n}\ntype ICronJobData = IJobData;\ndeclare function isCommandData(data: IJobData): data is ICommandJobData;\ndeclare function isHookData(data: IJobData): data is IHookJobData;\ndeclare function isCronData(data: IJobData): data is ICronJobData;\ninterface IEventQueueData extends IBaseJobData {\n type: ValueOf;\n gameServerId: string;\n event: ValueOf<(typeof GameEventsMapping)[ValueOf]>;\n}\ninterface IConnectorQueueData extends IBaseJobData {\n gameServerId: string;\n operation: 'create' | 'update' | 'delete';\n}\ninterface IGameServerQueueData extends IBaseJobData {\n gameServerId?: string;\n}\ninterface ICSMMImportData extends IBaseJobData {\n csmmExport: Record;\n options: {\n currency: boolean;\n players: boolean;\n roles: boolean;\n shop: boolean;\n };\n}\n","file://node_modules/@takaro/queues/dist/main.d.ts":"{ queueService } from './QueueService.js';\n{ queuesConfigSchema, IQueuesConfig } from './config.js';\n* from './dataDefinitions.js';\n{ TakaroQueue } from './TakaroQueue.js';\n{ TakaroWorker } from './TakaroWorker.js';\n{ getBullBoard } from './bullboard.js';\n","file://node_modules/@takaro/queues/dist/util/redisConnectionOptions.d.ts":"declare function getRedisConnectionOptions(): {\n host: string;\n port: number;\n username: string;\n password: string;\n};\n","file://node_modules/filelist/package.json":"{\"name\":\"filelist\",\"types\":\"index.d.ts\"}","file://node_modules/filelist/index.d.ts":"// IncludeOptions definitions copied from minimatch (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/minimatch/index.d.ts)\ninterface IncludeOptions {\n /**\n * Dump a ton of stuff to stderr.\n *\n * @default false\n */\n debug?: boolean;\n\n /**\n * Do not expand {a,b} and {1..3} brace sets.\n *\n * @default false\n */\n nobrace?: boolean;\n\n /**\n * Disable ** matching against multiple folder names.\n *\n * @default false\n */\n noglobstar?: boolean;\n\n /**\n * Allow patterns to match filenames starting with a period,\n * even if the pattern does not explicitly have a period in that spot.\n *\n * @default false\n */\n dot?: boolean;\n\n /**\n * Disable \"extglob\" style patterns like +(a|b).\n *\n * @default false\n */\n noext?: boolean;\n\n /**\n * Perform a case-insensitive match.\n *\n * @default false\n */\n nocase?: boolean;\n\n /**\n * When a match is not found by minimatch.match,\n * return a list containing the pattern itself if this option is set.\n * Otherwise, an empty list is returned if there are no matches.\n *\n * @default false\n */\n nonull?: boolean;\n\n /**\n * If set, then patterns without slashes will be matched against\n * the basename of the path if it contains slashes.\n *\n * @default false\n */\n matchBase?: boolean;\n\n /**\n * Suppress the behavior of treating #\n * at the start of a pattern as a comment.\n *\n * @default false\n */\n nocomment?: boolean;\n\n /**\n * Suppress the behavior of treating a leading ! character as negation.\n *\n * @default false\n */\n nonegate?: boolean;\n\n /**\n * Returns from negate expressions the same as if they were not negated.\n * (Ie, true on a hit, false on a miss.)\n *\n * @default false\n */\n flipNegate?: boolean;\n}\n\nclass FileList {\n static clone(): FileList\n static verbose: boolean\n}\n\ninterface FileList extends Omit, \"length\"> {\n pendingAdd: string[]\n pending: boolean\n excludes: {\n pats: RegExp[],\n funcs: Function[],\n regex: null | RegExp\n }\n items: string[]\n toArray(): string[]\n include(...items: string[]): this\n include(...items: (IncludeOptions | string)[]): this\n exclude(...items: string[]): this\n shouldExclude(item: string): boolean\n resolve(): this\n clearInclusions(): this\n clearExclusions(): this\n length(): number\n}","file://node_modules/setprototypeof/package.json":"{\"name\":\"setprototypeof\",\"types\":\"index.d.ts\"}","file://node_modules/setprototypeof/index.d.ts":"declare function setPrototypeOf(o: any, proto: object | null): any;\n= setPrototypeOf;\n","file://node_modules/iconv-lite/package.json":"{\"name\":\"iconv-lite\",\"types\":\"./lib/index.d.ts\"}","file://node_modules/iconv-lite/./lib/index.d.ts":"/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n * REQUIREMENT: This definition is dependent on the @types/node definition.\n * Install with `npm install @types/node --save-dev`\n *--------------------------------------------------------------------------------------------*/\n\ndeclare module 'iconv-lite' {\n\texport function decode(buffer: Buffer, encoding: string, options?: Options): string;\n\n\texport function encode(content: string, encoding: string, options?: Options): Buffer;\n\n\texport function encodingExists(encoding: string): boolean;\n\n\texport function decodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n\n\texport function encodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n}\n\ninterface Options {\n stripBOM?: boolean;\n addBOM?: boolean;\n defaultEncoding?: string;\n}\n","file://node_modules/side-channel/package.json":"{\"name\":\"side-channel\",\"types\":\"./index.d.ts\"}","file://node_modules/side-channel/index.d.ts":"declare namespace getSideChannel {\n\ttype Key = unknown;\n\ttype ListNode = {\n\t\tkey: Key;\n\t\tnext: ListNode;\n\t\tvalue: T;\n\t};\n\ttype RootNode = {\n\t\tkey: object;\n\t\tnext: null | ListNode;\n\t};\n\tfunction listGetNode(list: RootNode, key: ListNode['key']): ListNode | void;\n\tfunction listGet(objects: RootNode, key: ListNode['key']): T | void;\n\tfunction listSet(objects: RootNode, key: ListNode['key'], value: T): void;\n\tfunction listHas(objects: RootNode, key: ListNode['key']): boolean;\n\n\ttype Channel = {\n\t\tassert: (key: Key) => void;\n\t\thas: (key: Key) => boolean;\n\t\tget: (key: Key) => T;\n\t\tset: (key: Key, value: T) => void;\n\t}\n}\n\ndeclare function getSideChannel(): getSideChannel.Channel;\n\n= getSideChannel;\n","file://node_modules/es-define-property/package.json":"{\"name\":\"es-define-property\",\"types\":\"./index.d.ts\"}","file://node_modules/es-define-property/index.d.ts":"declare const defineProperty: false | typeof Object.defineProperty;\n\n= defineProperty;","file://node_modules/hasown/package.json":"{\"name\":\"hasown\",\"types\":\"index.d.ts\"}","file://node_modules/hasown/index.d.ts":"declare function hasOwn(o: O, p: K): o is O & Record;\n\n= hasOwn;\n","file://node_modules/define-data-property/package.json":"{\"name\":\"define-data-property\",\"types\":\"./index.d.ts\"}","file://node_modules/define-data-property/index.d.ts":"\ndeclare function defineDataProperty(\n obj: Record,\n property: keyof typeof obj,\n value: typeof obj[typeof property],\n nonEnumerable?: boolean | null,\n nonWritable?: boolean | null,\n nonConfigurable?: boolean | null,\n loose?: boolean\n): void;\n\n= defineDataProperty;","file://node_modules/safe-buffer/package.json":"{\"name\":\"safe-buffer\",\"types\":\"index.d.ts\"}","file://node_modules/safe-buffer/index.d.ts":"declare module \"safe-buffer\" {\n export class Buffer {\n length: number\n write(string: string, offset?: number, length?: number, encoding?: string): number;\n toString(encoding?: string, start?: number, end?: number): string;\n toJSON(): { type: 'Buffer', data: any[] };\n equals(otherBuffer: Buffer): boolean;\n compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;\n copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;\n slice(start?: number, end?: number): Buffer;\n writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUInt8(offset: number, noAssert?: boolean): number;\n readUInt16LE(offset: number, noAssert?: boolean): number;\n readUInt16BE(offset: number, noAssert?: boolean): number;\n readUInt32LE(offset: number, noAssert?: boolean): number;\n readUInt32BE(offset: number, noAssert?: boolean): number;\n readInt8(offset: number, noAssert?: boolean): number;\n readInt16LE(offset: number, noAssert?: boolean): number;\n readInt16BE(offset: number, noAssert?: boolean): number;\n readInt32LE(offset: number, noAssert?: boolean): number;\n readInt32BE(offset: number, noAssert?: boolean): number;\n readFloatLE(offset: number, noAssert?: boolean): number;\n readFloatBE(offset: number, noAssert?: boolean): number;\n readDoubleLE(offset: number, noAssert?: boolean): number;\n readDoubleBE(offset: number, noAssert?: boolean): number;\n swap16(): Buffer;\n swap32(): Buffer;\n swap64(): Buffer;\n writeUInt8(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt8(value: number, offset: number, noAssert?: boolean): number;\n writeInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatLE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatBE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;\n fill(value: any, offset?: number, end?: number): this;\n indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;\n\n /**\n * Allocates a new buffer containing the given {str}.\n *\n * @param str String to store in buffer.\n * @param encoding encoding to use, optional. Default is 'utf8'\n */\n constructor (str: string, encoding?: string);\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n */\n constructor (size: number);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: Uint8Array);\n /**\n * Produces a Buffer backed by the same allocated memory as\n * the given {ArrayBuffer}.\n *\n *\n * @param arrayBuffer The ArrayBuffer with which to share memory.\n */\n constructor (arrayBuffer: ArrayBuffer);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: any[]);\n /**\n * Copies the passed {buffer} data onto a new {Buffer} instance.\n *\n * @param buffer The buffer to copy.\n */\n constructor (buffer: Buffer);\n prototype: Buffer;\n /**\n * Allocates a new Buffer using an {array} of octets.\n *\n * @param array\n */\n static from(array: any[]): Buffer;\n /**\n * When passed a reference to the .buffer property of a TypedArray instance,\n * the newly created Buffer will share the same allocated memory as the TypedArray.\n * The optional {byteOffset} and {length} arguments specify a memory range\n * within the {arrayBuffer} that will be shared by the Buffer.\n *\n * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer()\n * @param byteOffset\n * @param length\n */\n static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;\n /**\n * Copies the passed {buffer} data onto a new Buffer instance.\n *\n * @param buffer\n */\n static from(buffer: Buffer): Buffer;\n /**\n * Creates a new Buffer containing the given JavaScript string {str}.\n * If provided, the {encoding} parameter identifies the character encoding.\n * If not provided, {encoding} defaults to 'utf8'.\n *\n * @param str\n */\n static from(str: string, encoding?: string): Buffer;\n /**\n * Returns true if {obj} is a Buffer\n *\n * @param obj object to test.\n */\n static isBuffer(obj: any): obj is Buffer;\n /**\n * Returns true if {encoding} is a valid encoding argument.\n * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex'\n *\n * @param encoding string to test.\n */\n static isEncoding(encoding: string): boolean;\n /**\n * Gives the actual byte length of a string. encoding defaults to 'utf8'.\n * This is not the same as String.prototype.length since that returns the number of characters in a string.\n *\n * @param string string to test.\n * @param encoding encoding used to evaluate (defaults to 'utf8')\n */\n static byteLength(string: string, encoding?: string): number;\n /**\n * Returns a buffer which is the result of concatenating all the buffers in the list together.\n *\n * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.\n * If the list has exactly one item, then the first item of the list is returned.\n * If the list has more than one item, then a new Buffer is created.\n *\n * @param list An array of Buffer objects to concatenate\n * @param totalLength Total length of the buffers when concatenated.\n * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.\n */\n static concat(list: Buffer[], totalLength?: number): Buffer;\n /**\n * The same as buf1.compare(buf2).\n */\n static compare(buf1: Buffer, buf2: Buffer): number;\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n * @param fill if specified, buffer will be initialized by calling buf.fill(fill).\n * If parameter is omitted, buffer will be filled with zeros.\n * @param encoding encoding used for call to buf.fill while initalizing\n */\n static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;\n /**\n * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafe(size: number): Buffer;\n /**\n * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafeSlow(size: number): Buffer;\n }\n}","file://node_modules/ipaddr.js/package.json":"{\"name\":\"ipaddr.js\",\"types\":\"./lib/ipaddr.js.d.ts\"}","file://node_modules/ipaddr.js/./lib/ipaddr.js.d.ts":"declare module \"ipaddr.js\" {\n type IPv4Range = 'unicast' | 'unspecified' | 'broadcast' | 'multicast' | 'linkLocal' | 'loopback' | 'carrierGradeNat' | 'private' | 'reserved';\n type IPv6Range = 'unicast' | 'unspecified' | 'linkLocal' | 'multicast' | 'loopback' | 'uniqueLocal' | 'ipv4Mapped' | 'rfc6145' | 'rfc6052' | '6to4' | 'teredo' | 'reserved';\n\n interface RangeList {\n [name: string]: [T, number] | [T, number][];\n }\n\n // Common methods/properties for IPv4 and IPv6 classes.\n class IP {\n prefixLengthFromSubnetMask(): number | null;\n toByteArray(): number[];\n toNormalizedString(): string;\n toString(): string;\n }\n\n namespace Address {\n export function isValid(addr: string): boolean;\n export function fromByteArray(bytes: number[]): IPv4 | IPv6;\n export function parse(addr: string): IPv4 | IPv6;\n export function parseCIDR(mask: string): [IPv4 | IPv6, number];\n export function process(addr: string): IPv4 | IPv6;\n export function subnetMatch(addr: IPv4, rangeList: RangeList, defaultName?: string): string;\n export function subnetMatch(addr: IPv6, rangeList: RangeList, defaultName?: string): string;\n\n export class IPv4 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv4;\n static isIPv4(addr: string): boolean;\n static isValidFourPartDecimal(addr: string): boolean;\n static isValid(addr: string): boolean;\n static networkAddressFromCIDR(addr: string): IPv4;\n static parse(addr: string): IPv4;\n static parseCIDR(addr: string): [IPv4, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv4;\n constructor(octets: number[]);\n octets: number[]\n\n kind(): 'ipv4';\n match(addr: IPv4, bits: number): boolean;\n match(mask: [IPv4, number]): boolean;\n range(): IPv4Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4MappedAddress(): IPv6;\n }\n\n export class IPv6 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv6;\n static isIPv6(addr: string): boolean;\n static isValid(addr: string): boolean;\n static parse(addr: string): IPv6;\n static parseCIDR(addr: string): [IPv6, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv6;\n constructor(parts: number[]);\n parts: number[]\n zoneId?: string\n\n isIPv4MappedAddress(): boolean;\n kind(): 'ipv6';\n match(addr: IPv6, bits: number): boolean;\n match(mask: [IPv6, number]): boolean;\n range(): IPv6Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4Address(): IPv4;\n }\n }\n\n export = Address;\n}\n"} From 14eb45bf5d7a2c4c06374859fdb716ccc57a2655 Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:13:17 +0000 Subject: [PATCH 28/48] fix: code style --- .../src/routes/-module-builder/Editor/monacoCustomTypes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json b/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json index bfa2afa973..bff77c0aba 100644 --- a/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json +++ b/packages/web-main/src/routes/-module-builder/Editor/monacoCustomTypes.json @@ -1 +1 @@ -{"file://node_modules/axios/package.json":"{\"name\":\"axios\",\"types\":\"./index.d.ts\"}","file://node_modules/axios/index.d.ts":"// TypeScript Version: 4.7\ntype AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null;\n\ninterface RawAxiosHeaders {\n [key: string]: AxiosHeaderValue;\n}\n\ntype MethodsHeaders = Partial<{\n [Key in Method as Lowercase]: AxiosHeaders;\n} & {common: AxiosHeaders}>;\n\ntype AxiosHeaderMatcher = string | RegExp | ((this: AxiosHeaders, value: string, name: string) => boolean);\n\ntype AxiosHeaderParser = (this: AxiosHeaders, value: AxiosHeaderValue, header: string) => any;\n\nclass AxiosHeaders {\n constructor(\n headers?: RawAxiosHeaders | AxiosHeaders | string\n );\n\n [key: string]: any;\n\n set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders;\n\n get(headerName: string, parser: RegExp): RegExpExecArray | null;\n get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;\n\n has(header: string, matcher?: AxiosHeaderMatcher): boolean;\n\n delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;\n\n clear(matcher?: AxiosHeaderMatcher): boolean;\n\n normalize(format: boolean): AxiosHeaders;\n\n concat(...targets: Array): AxiosHeaders;\n\n toJSON(asStrings?: boolean): RawAxiosHeaders;\n\n static from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;\n\n static accessor(header: string | string[]): AxiosHeaders;\n\n static concat(...targets: Array): AxiosHeaders;\n\n setContentType(value: ContentType, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentType(parser?: RegExp): RegExpExecArray | null;\n getContentType(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentType(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentLength(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentLength(parser?: RegExp): RegExpExecArray | null;\n getContentLength(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentLength(matcher?: AxiosHeaderMatcher): boolean;\n\n setAccept(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAccept(parser?: RegExp): RegExpExecArray | null;\n getAccept(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAccept(matcher?: AxiosHeaderMatcher): boolean;\n\n setUserAgent(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getUserAgent(parser?: RegExp): RegExpExecArray | null;\n getUserAgent(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasUserAgent(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentEncoding(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentEncoding(parser?: RegExp): RegExpExecArray | null;\n getContentEncoding(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentEncoding(matcher?: AxiosHeaderMatcher): boolean;\n\n setAuthorization(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAuthorization(parser?: RegExp): RegExpExecArray | null;\n getAuthorization(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAuthorization(matcher?: AxiosHeaderMatcher): boolean;\n\n [Symbol.iterator](): IterableIterator<[string, AxiosHeaderValue]>;\n}\n\ntype CommonRequestHeadersList = 'Accept' | 'Content-Length' | 'User-Agent' | 'Content-Encoding' | 'Authorization';\n\ntype ContentType = AxiosHeaderValue | 'text/html' | 'text/plain' | 'multipart/form-data' | 'application/json' | 'application/x-www-form-urlencoded' | 'application/octet-stream';\n\ntype RawAxiosRequestHeaders = Partial;\n\ntype AxiosRequestHeaders = RawAxiosRequestHeaders & AxiosHeaders;\n\ntype CommonResponseHeadersList = 'Server' | 'Content-Type' | 'Content-Length' | 'Cache-Control'| 'Content-Encoding';\n\ntype RawCommonResponseHeaders = {\n [Key in CommonResponseHeadersList]: AxiosHeaderValue;\n} & {\n \"set-cookie\": string[];\n};\n\ntype RawAxiosResponseHeaders = Partial;\n\ntype AxiosResponseHeaders = RawAxiosResponseHeaders & AxiosHeaders;\n\ninterface AxiosRequestTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosRequestHeaders): any;\n}\n\ninterface AxiosResponseTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosResponseHeaders, status?: number): any;\n}\n\ninterface AxiosAdapter {\n (config: InternalAxiosRequestConfig): AxiosPromise;\n}\n\ninterface AxiosBasicCredentials {\n username: string;\n password: string;\n}\n\ninterface AxiosProxyConfig {\n host: string;\n port: number;\n auth?: AxiosBasicCredentials;\n protocol?: string;\n}\n\nenum HttpStatusCode {\n Continue = 100,\n SwitchingProtocols = 101,\n Processing = 102,\n EarlyHints = 103,\n Ok = 200,\n Created = 201,\n Accepted = 202,\n NonAuthoritativeInformation = 203,\n NoContent = 204,\n ResetContent = 205,\n PartialContent = 206,\n MultiStatus = 207,\n AlreadyReported = 208,\n ImUsed = 226,\n MultipleChoices = 300,\n MovedPermanently = 301,\n Found = 302,\n SeeOther = 303,\n NotModified = 304,\n UseProxy = 305,\n Unused = 306,\n TemporaryRedirect = 307,\n PermanentRedirect = 308,\n BadRequest = 400,\n Unauthorized = 401,\n PaymentRequired = 402,\n Forbidden = 403,\n NotFound = 404,\n MethodNotAllowed = 405,\n NotAcceptable = 406,\n ProxyAuthenticationRequired = 407,\n RequestTimeout = 408,\n Conflict = 409,\n Gone = 410,\n LengthRequired = 411,\n PreconditionFailed = 412,\n PayloadTooLarge = 413,\n UriTooLong = 414,\n UnsupportedMediaType = 415,\n RangeNotSatisfiable = 416,\n ExpectationFailed = 417,\n ImATeapot = 418,\n MisdirectedRequest = 421,\n UnprocessableEntity = 422,\n Locked = 423,\n FailedDependency = 424,\n TooEarly = 425,\n UpgradeRequired = 426,\n PreconditionRequired = 428,\n TooManyRequests = 429,\n RequestHeaderFieldsTooLarge = 431,\n UnavailableForLegalReasons = 451,\n InternalServerError = 500,\n NotImplemented = 501,\n BadGateway = 502,\n ServiceUnavailable = 503,\n GatewayTimeout = 504,\n HttpVersionNotSupported = 505,\n VariantAlsoNegotiates = 506,\n InsufficientStorage = 507,\n LoopDetected = 508,\n NotExtended = 510,\n NetworkAuthenticationRequired = 511,\n}\n\ntype Method =\n | 'get' | 'GET'\n | 'delete' | 'DELETE'\n | 'head' | 'HEAD'\n | 'options' | 'OPTIONS'\n | 'post' | 'POST'\n | 'put' | 'PUT'\n | 'patch' | 'PATCH'\n | 'purge' | 'PURGE'\n | 'link' | 'LINK'\n | 'unlink' | 'UNLINK';\n\ntype ResponseType =\n | 'arraybuffer'\n | 'blob'\n | 'document'\n | 'json'\n | 'text'\n | 'stream'\n | 'formdata';\n\ntype responseEncoding =\n | 'ascii' | 'ASCII'\n | 'ansi' | 'ANSI'\n | 'binary' | 'BINARY'\n | 'base64' | 'BASE64'\n | 'base64url' | 'BASE64URL'\n | 'hex' | 'HEX'\n | 'latin1' | 'LATIN1'\n | 'ucs-2' | 'UCS-2'\n | 'ucs2' | 'UCS2'\n | 'utf-8' | 'UTF-8'\n | 'utf8' | 'UTF8'\n | 'utf16le' | 'UTF16LE';\n\ninterface TransitionalOptions {\n silentJSONParsing?: boolean;\n forcedJSONParsing?: boolean;\n clarifyTimeoutError?: boolean;\n}\n\ninterface GenericAbortSignal {\n readonly aborted: boolean;\n onabort?: ((...args: any) => any) | null;\n addEventListener?: (...args: any) => any;\n removeEventListener?: (...args: any) => any;\n}\n\ninterface FormDataVisitorHelpers {\n defaultVisitor: SerializerVisitor;\n convertValue: (value: any) => any;\n isVisitable: (value: any) => boolean;\n}\n\ninterface SerializerVisitor {\n (\n this: GenericFormData,\n value: any,\n key: string | number,\n path: null | Array,\n helpers: FormDataVisitorHelpers\n ): boolean;\n}\n\ninterface SerializerOptions {\n visitor?: SerializerVisitor;\n dots?: boolean;\n metaTokens?: boolean;\n indexes?: boolean | null;\n}\n\n// tslint:disable-next-line\ninterface FormSerializerOptions extends SerializerOptions {\n}\n\ninterface ParamEncoder {\n (value: any, defaultEncoder: (value: any) => any): any;\n}\n\ninterface CustomParamsSerializer {\n (params: Record, options?: ParamsSerializerOptions): string;\n}\n\ninterface ParamsSerializerOptions extends SerializerOptions {\n encode?: ParamEncoder;\n serialize?: CustomParamsSerializer;\n}\n\ntype MaxUploadRate = number;\n\ntype MaxDownloadRate = number;\n\ntype BrowserProgressEvent = any;\n\ninterface AxiosProgressEvent {\n loaded: number;\n total?: number;\n progress?: number;\n bytes: number;\n rate?: number;\n estimated?: number;\n upload?: boolean;\n download?: boolean;\n event?: BrowserProgressEvent;\n lengthComputable: boolean;\n}\n\ntype Milliseconds = number;\n\ntype AxiosAdapterName = 'fetch' | 'xhr' | 'http' | string;\n\ntype AxiosAdapterConfig = AxiosAdapter | AxiosAdapterName;\n\ntype AddressFamily = 4 | 6 | undefined;\n\ninterface LookupAddressEntry {\n address: string;\n family?: AddressFamily;\n}\n\ntype LookupAddress = string | LookupAddressEntry;\n\ninterface AxiosRequestConfig {\n url?: string;\n method?: Method | string;\n baseURL?: string;\n transformRequest?: AxiosRequestTransformer | AxiosRequestTransformer[];\n transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[];\n headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders;\n params?: any;\n paramsSerializer?: ParamsSerializerOptions | CustomParamsSerializer;\n data?: D;\n timeout?: Milliseconds;\n timeoutErrorMessage?: string;\n withCredentials?: boolean;\n adapter?: AxiosAdapterConfig | AxiosAdapterConfig[];\n auth?: AxiosBasicCredentials;\n responseType?: ResponseType;\n responseEncoding?: responseEncoding | string;\n xsrfCookieName?: string;\n xsrfHeaderName?: string;\n onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;\n onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void;\n maxContentLength?: number;\n validateStatus?: ((status: number) => boolean) | null;\n maxBodyLength?: number;\n maxRedirects?: number;\n maxRate?: number | [MaxUploadRate, MaxDownloadRate];\n beforeRedirect?: (options: Record, responseDetails: {headers: Record, statusCode: HttpStatusCode}) => void;\n socketPath?: string | null;\n transport?: any;\n httpAgent?: any;\n httpsAgent?: any;\n proxy?: AxiosProxyConfig | false;\n cancelToken?: CancelToken;\n decompress?: boolean;\n transitional?: TransitionalOptions;\n signal?: GenericAbortSignal;\n insecureHTTPParser?: boolean;\n env?: {\n FormData?: new (...args: any[]) => object;\n };\n formSerializer?: FormSerializerOptions;\n family?: AddressFamily;\n lookup?: ((hostname: string, options: object, cb: (err: Error | null, address: LookupAddress | LookupAddress[], family?: AddressFamily) => void) => void) |\n ((hostname: string, options: object) => Promise<[address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress>);\n withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined);\n fetchOptions?: Record;\n}\n\n// Alias\ntype RawAxiosRequestConfig = AxiosRequestConfig;\n\ninterface InternalAxiosRequestConfig extends AxiosRequestConfig {\n headers: AxiosRequestHeaders;\n}\n\ninterface HeadersDefaults {\n common: RawAxiosRequestHeaders;\n delete: RawAxiosRequestHeaders;\n get: RawAxiosRequestHeaders;\n head: RawAxiosRequestHeaders;\n post: RawAxiosRequestHeaders;\n put: RawAxiosRequestHeaders;\n patch: RawAxiosRequestHeaders;\n options?: RawAxiosRequestHeaders;\n purge?: RawAxiosRequestHeaders;\n link?: RawAxiosRequestHeaders;\n unlink?: RawAxiosRequestHeaders;\n}\n\ninterface AxiosDefaults extends Omit, 'headers'> {\n headers: HeadersDefaults;\n}\n\ninterface CreateAxiosDefaults extends Omit, 'headers'> {\n headers?: RawAxiosRequestHeaders | AxiosHeaders | Partial;\n}\n\ninterface AxiosResponse {\n data: T;\n status: number;\n statusText: string;\n headers: RawAxiosResponseHeaders | AxiosResponseHeaders;\n config: InternalAxiosRequestConfig;\n request?: any;\n}\n\nclass AxiosError extends Error {\n constructor(\n message?: string,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse\n );\n\n config?: InternalAxiosRequestConfig;\n code?: string;\n request?: any;\n response?: AxiosResponse;\n isAxiosError: boolean;\n status?: number;\n toJSON: () => object;\n cause?: Error;\n static from(\n error: Error | unknown,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse,\n customProps?: object,\n): AxiosError;\n static readonly ERR_FR_TOO_MANY_REDIRECTS = \"ERR_FR_TOO_MANY_REDIRECTS\";\n static readonly ERR_BAD_OPTION_VALUE = \"ERR_BAD_OPTION_VALUE\";\n static readonly ERR_BAD_OPTION = \"ERR_BAD_OPTION\";\n static readonly ERR_NETWORK = \"ERR_NETWORK\";\n static readonly ERR_DEPRECATED = \"ERR_DEPRECATED\";\n static readonly ERR_BAD_RESPONSE = \"ERR_BAD_RESPONSE\";\n static readonly ERR_BAD_REQUEST = \"ERR_BAD_REQUEST\";\n static readonly ERR_NOT_SUPPORT = \"ERR_NOT_SUPPORT\";\n static readonly ERR_INVALID_URL = \"ERR_INVALID_URL\";\n static readonly ERR_CANCELED = \"ERR_CANCELED\";\n static readonly ECONNABORTED = \"ECONNABORTED\";\n static readonly ETIMEDOUT = \"ETIMEDOUT\";\n}\n\nclass CanceledError extends AxiosError {\n}\n\ntype AxiosPromise = Promise>;\n\ninterface CancelStatic {\n new (message?: string): Cancel;\n}\n\ninterface Cancel {\n message: string | undefined;\n}\n\ninterface Canceler {\n (message?: string, config?: AxiosRequestConfig, request?: any): void;\n}\n\ninterface CancelTokenStatic {\n new (executor: (cancel: Canceler) => void): CancelToken;\n source(): CancelTokenSource;\n}\n\ninterface CancelToken {\n promise: Promise;\n reason?: Cancel;\n throwIfRequested(): void;\n}\n\ninterface CancelTokenSource {\n token: CancelToken;\n cancel: Canceler;\n}\n\ninterface AxiosInterceptorOptions {\n synchronous?: boolean;\n runWhen?: (config: InternalAxiosRequestConfig) => boolean;\n}\n\ninterface AxiosInterceptorManager {\n use(onFulfilled?: ((value: V) => V | Promise) | null, onRejected?: ((error: any) => any) | null, options?: AxiosInterceptorOptions): number;\n eject(id: number): void;\n clear(): void;\n}\n\nclass Axios {\n constructor(config?: AxiosRequestConfig);\n defaults: AxiosDefaults;\n interceptors: {\n request: AxiosInterceptorManager;\n response: AxiosInterceptorManager;\n };\n getUri(config?: AxiosRequestConfig): string;\n request, D = any>(config: AxiosRequestConfig): Promise;\n get, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n delete, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n head, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n options, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n post, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n put, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patch, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n postForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n putForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patchForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n}\n\ninterface AxiosInstance extends Axios {\n , D = any>(config: AxiosRequestConfig): Promise;\n , D = any>(url: string, config?: AxiosRequestConfig): Promise;\n\n defaults: Omit & {\n headers: HeadersDefaults & {\n [key: string]: AxiosHeaderValue\n }\n };\n}\n\ninterface GenericFormData {\n append(name: string, value: any, options?: any): any;\n}\n\ninterface GenericHTMLFormElement {\n name: string;\n method: string;\n submit(): void;\n}\n\nfunction getAdapter(adapters: AxiosAdapterConfig | AxiosAdapterConfig[] | undefined): AxiosAdapter;\n\nfunction toFormData(sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions): GenericFormData;\n\nfunction formToJSON(form: GenericFormData|GenericHTMLFormElement): object;\n\nfunction isAxiosError(payload: any): payload is AxiosError;\n\nfunction spread(callback: (...args: T[]) => R): (array: T[]) => R;\n\nfunction isCancel(value: any): value is Cancel;\n\nfunction all(values: Array>): Promise;\n\ninterface AxiosStatic extends AxiosInstance {\n create(config?: CreateAxiosDefaults): AxiosInstance;\n Cancel: CancelStatic;\n CancelToken: CancelTokenStatic;\n Axios: typeof Axios;\n AxiosError: typeof AxiosError;\n HttpStatusCode: typeof HttpStatusCode;\n readonly VERSION: string;\n isCancel: typeof isCancel;\n all: typeof all;\n spread: typeof spread;\n isAxiosError: typeof isAxiosError;\n toFormData: typeof toFormData;\n formToJSON: typeof formToJSON;\n getAdapter: typeof getAdapter;\n CanceledError: typeof CanceledError;\n AxiosHeaders: typeof AxiosHeaders;\n}\n\ndeclare const axios: AxiosStatic;\n\ndefault axios;\n","file://node_modules/form-data/package.json":"{\"name\":\"form-data\",\"types\":\"./index.d.ts\"}","file://node_modules/form-data/index.d.ts":"// Definitions by: Carlos Ballesteros Velasco \n// Leon Yu \n// BendingBender \n// Maple Miao \n\n/// \n\n= FormData;\n\n// Extracted because @types/node doesn't export interfaces.\ninterface ReadableOptions {\n highWaterMark?: number;\n encoding?: string;\n objectMode?: boolean;\n read?(this: stream.Readable, size: number): void;\n destroy?(this: stream.Readable, error: Error | null, callback: (error: Error | null) => void): void;\n autoDestroy?: boolean;\n}\n\ninterface Options extends ReadableOptions {\n writable?: boolean;\n readable?: boolean;\n dataSize?: number;\n maxDataSize?: number;\n pauseStreams?: boolean;\n}\n\ndeclare class FormData extends stream.Readable {\n constructor(options?: Options);\n append(key: string, value: any, options?: FormData.AppendOptions | string): void;\n getHeaders(userHeaders?: FormData.Headers): FormData.Headers;\n submit(\n params: string | FormData.SubmitOptions,\n callback?: (error: Error | null, response: http.IncomingMessage) => void\n ): http.ClientRequest;\n getBuffer(): Buffer;\n setBoundary(boundary: string): void;\n getBoundary(): string;\n getLength(callback: (err: Error | null, length: number) => void): void;\n getLengthSync(): number;\n hasKnownLength(): boolean;\n}\n\ndeclare namespace FormData {\n interface Headers {\n [key: string]: any;\n }\n\n interface AppendOptions {\n header?: string | Headers;\n knownLength?: number;\n filename?: string;\n filepath?: string;\n contentType?: string;\n }\n\n interface SubmitOptions extends http.RequestOptions {\n protocol?: 'https:' | 'http:';\n }\n}\n","file://node_modules/@takaro/helpers/package.json":"{\"name\":\"@takaro/helpers\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/helpers/dist/TakaroUserError.d.ts":"declare class TakaroUserError extends Error {\n constructor(message: string);\n}\n","file://node_modules/@takaro/helpers/dist/checkPermission.d.ts":"declare function checkPermission(player: PlayerOnGameserverOutputWithRolesDTO, permission: string): any;\n","file://node_modules/@takaro/helpers/dist/config.d.ts":"interface IHelpersConfig extends IBaseConfig {\n apiClient: {\n token: string;\n url: string;\n };\n data: string;\n}\ndeclare const config: Config;\n{};\n","file://node_modules/@takaro/helpers/dist/getData.d.ts":"declare function getData(): any;\n","file://node_modules/@takaro/helpers/dist/getTakaro.d.ts":"declare function getTakaro(data: Record, logger?: Pick): {\n takaro: Client;\n data: Record;\n};\n","file://node_modules/@takaro/helpers/dist/main.d.ts":"{ getTakaro } from './getTakaro.js';\n{ checkPermission } from './checkPermission.js';\n{ nextCronJobRun } from './nextCronJobRun.js';\n{ TakaroUserError } from './TakaroUserError.js';\n* as _ from 'lodash-es';\n* as axios from 'axios';\ndeclare const takaro: Client;\n","file://node_modules/@takaro/helpers/dist/nextCronJobRun.d.ts":"declare const nextCronJobRun: (cron: string) => Date | null;\n","file://node_modules/croner/package.json":"{\"name\":\"croner\",\"types\":\"./types/croner.d.ts\"}","file://node_modules/croner/./types/croner.d.ts":"type TimePoint = {\n /**\n * - 1970--\n */\n y: number;\n /**\n * - 1-12\n */\n m: number;\n /**\n * - 1-31\n */\n d: number;\n /**\n * - 0-24\n */\n h: number;\n /**\n * - 0-60 Minute\n */\n i: number;\n /**\n * - 0-60\n */\n s: number;\n /**\n * - Time zone in IANA database format 'Europe/Stockholm'\n */\n tz: string;\n};\ntype CatchCallbackFn = (e: unknown, job: Cron) => any;\ntype ProtectCallbackFn = (job: Cron) => any;\n/**\n * - Cron scheduler options\n */\ntype CronOptions = {\n /**\n * - Name of a job\n */\n name?: string;\n /**\n * - Job is paused\n */\n paused?: boolean;\n /**\n * - Job is about to be killed or killed\n */\n kill?: boolean;\n /**\n * - Continue exection even if a unhandled error is thrown by triggered function\n * - If set to a function, execute function on catching the error.\n */\n catch?: boolean | CatchCallbackFn;\n /**\n * - Abort job instantly if nothing else keeps the event loop running.\n */\n unref?: boolean;\n /**\n * - Maximum nuber of executions\n */\n maxRuns?: number;\n /**\n * - Minimum interval between executions, in seconds\n */\n interval?: number;\n /**\n * - Skip current run if job is already running\n */\n protect?: boolean | ProtectCallbackFn;\n /**\n * - When to start running\n */\n startAt?: string | Date;\n /**\n * - When to stop running\n */\n stopAt?: string | Date;\n /**\n * - Time zone in Europe/Stockholm format\n */\n timezone?: string;\n /**\n * - Offset from UTC in minutes\n */\n utcOffset?: number;\n /**\n * - Combine day-of-month and day-of-week using true = OR, false = AND. Default is true = OR.\n */\n legacyMode?: boolean;\n /**\n * - Used to pass any object to scheduled function\n */\n context?: unknown;\n};\n/**\n * Name for each part of the cron pattern\n */\ntype CronPatternPart = (\"second\" | \"minute\" | \"hour\" | \"day\" | \"month\" | \"dayOfWeek\");\n/**\n * Offset, 0 or -1.\n *\n * 0 offset is used for seconds,minutes and hours as they start on 1.\n * -1 on days and months, as they start on 0\n */\ntype CronIndexOffset = number;\n/**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\nfunction Cron(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function): Cron;\nclass Cron {\n /**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\n constructor(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function);\n /**\n * @public\n * @type {string|undefined} */\n public name: string | undefined;\n /**\n * @public\n * @type {CronOptions} */\n public options: CronOptions;\n /**\n * Encapsulate all internal states in an object.\n * Duplicate all options that can change to internal states, for example maxRuns and paused.\n * @private\n */\n private _states;\n fn: Function | CronOptions;\n /**\n * Find next runtime, based on supplied date. Strips milliseconds.\n *\n * @param {CronDate|Date|string} [prev] - Date to start from\n * @returns {Date | null} - Next run time\n */\n nextRun(prev?: CronDate | Date | string): Date | null;\n /**\n * Find next n runs, based on supplied date. Strips milliseconds.\n *\n * @param {number} n - Number of runs to enumerate\n * @param {Date|string} [previous] - Date to start from\n * @returns {Date[]} - Next n run times\n */\n nextRuns(n: number, previous?: Date | string): Date[];\n /**\n * Return the original pattern, if there was one\n *\n * @returns {string|undefined} - Original pattern\n */\n getPattern(): string | undefined;\n /**\n * Indicates whether or not the cron job is scheduled and running, e.g. awaiting next trigger\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isRunning(): boolean;\n /**\n * Indicates whether or not the cron job is permanently stopped\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isStopped(): boolean;\n /**\n * Indicates whether or not the cron job is currently working\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isBusy(): boolean;\n /**\n * Return current/previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public currentRun(): Date | null;\n /**\n * Return previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public previousRun(): Date | null;\n /**\n * Returns number of milliseconds to next run\n * @public\n *\n * @param {CronDate|Date|string} [prev] - Starting date, defaults to now - minimum interval\n * @returns {number | null}\n */\n public msToNext(prev?: CronDate | Date | string): number | null;\n /**\n * Stop execution\n *\n * Running this will forcefully stop the job, and prevent furter exection. `.resume()` will not work after stopping.\n * It will also be removed from the scheduledJobs array if it were named.\n *\n * @public\n */\n public stop(): void;\n /**\n * Pause execution\n * @public\n *\n * @returns {boolean} - Wether pause was successful\n */\n public pause(): boolean;\n /**\n * Resume execution\n * @public\n *\n * @returns {boolean} - Wether resume was successful\n */\n public resume(): boolean;\n /**\n * Schedule a new job\n * @public\n *\n * @param {Function} func - Function to be run each iteration of pattern\n * @returns {Cron}\n */\n public schedule(func: Function): Cron;\n private _trigger;\n /**\n * Trigger a run manually\n * @public\n */\n public trigger(): Promise;\n private _checkTrigger;\n private _next;\n private _calculatePreviousRun;\n}\nnamespace Cron {\n export { Cron };\n export { scheduledJobs };\n}\n/**\n * An array containing all named cron jobs.\n *\n * @constant\n * @type {Cron[]}\n */\nconst scheduledJobs: Cron[];\n/**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n*/\ndeclare function CronDate(d?: CronDate | Date | string, tz?: string | number): void;\ndeclare class CronDate {\n /**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n */\n constructor(d?: CronDate | Date | string, tz?: string | number);\n /**\n * TimeZone\n * @type {string|number|undefined}\n */\n tz: string | number | undefined;\n private isNthWeekdayOfMonth;\n private fromDate;\n ms: number;\n second: number;\n minute: number;\n hour: number;\n day: number;\n month: number;\n year: number;\n private fromCronDate;\n private apply;\n private fromString;\n private findNext;\n private recurse;\n /**\n * Increment to next run time\n * @public\n *\n * @param {string} pattern - The pattern used to increment current state\n * @param {CronOptions} options - Cron options used for incrementing\n * @param {boolean} [hasPreviousRun] - If this run should adhere to minimum interval\n * @return {CronDate|null} - Returns itthis for chaining, or null if increment wasnt possible\n */\n public increment(pattern: string, options: CronOptions, hasPreviousRun?: boolean): CronDate | null;\n /**\n * Convert current state back to a javascript Date()\n * @public\n *\n * @param {boolean} internal - If this is an internal call\n * @returns {Date}\n */\n public getDate(internal: boolean): Date;\n /**\n * Convert current state back to a javascript Date() and return UTC milliseconds\n * @public\n *\n * @returns {Date}\n */\n public getTime(): Date;\n}\n{ Cron as default };\n","file://node_modules/@takaro/queues/package.json":"{\"name\":\"@takaro/queues\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/queues/dist/QueueService.d.ts":"declare class QueuesService {\n private static instance;\n static getInstance(): QueuesService;\n disconnect(): Promise;\n private queuesMap;\n get queues(): {\n commands: {\n queue: TakaroQueue;\n };\n cronjobs: {\n queue: TakaroQueue;\n };\n hooks: {\n queue: TakaroQueue;\n };\n events: {\n queue: TakaroQueue;\n };\n connector: {\n queue: TakaroQueue;\n };\n itemsSync: {\n queue: TakaroQueue;\n };\n bansSync: {\n queue: TakaroQueue;\n };\n playerSync: {\n queue: TakaroQueue;\n };\n steamSync: {\n queue: TakaroQueue;\n };\n csmmImport: {\n queue: TakaroQueue;\n };\n kpi: {\n queue: TakaroQueue>;\n };\n system: {\n queue: TakaroQueue>;\n };\n };\n}\ndeclare const queueService: QueuesService;\n{};\n","file://node_modules/@takaro/queues/dist/TakaroQueue.d.ts":"declare class TakaroQueue> {\n name: string;\n bullQueue: Queue;\n constructor(name: string);\n /**\n * Generating a job ID like this effectively de-duplicates all jobs with the same data.\n * @see https://docs.bullmq.io/guide/jobs/job-ids\n * @param data\n * @returns\n */\n private getJobId;\n add(data: T, extra?: JobsOptions): Promise>;\n getRepeatableJobs(): Promise;\n removeRepeatableByKey(id: string): Promise;\n}\n","file://node_modules/@takaro/queues/dist/TakaroWorker.d.ts":"type WorkerOptionsWithoutConnectionOptions = Omit;\ndeclare abstract class TakaroWorker {\n log: import(\"winston\").Logger;\n bullWorker: Worker;\n constructor(name: string, concurrency: number | undefined, fn: Processor, extraBullOpts?: WorkerOptionsWithoutConnectionOptions);\n}\n{};\n","file://node_modules/@takaro/queues/dist/bullboard.d.ts":"declare function getBullBoard(): any;\n","file://node_modules/@takaro/queues/dist/config.d.ts":"interface IQueuesConfig extends IBaseConfig {\n queues: {\n commands: {\n name: string;\n concurrency: number;\n };\n cronjobs: {\n name: string;\n concurrency: number;\n };\n hooks: {\n name: string;\n concurrency: number;\n };\n events: {\n name: string;\n concurrency: number;\n };\n connector: {\n name: string;\n };\n itemsSync: {\n name: string;\n interval: number;\n };\n bansSync: {\n name: string;\n interval: number;\n };\n steamSync: {\n name: string;\n interval: number;\n };\n playerSync: {\n name: string;\n interval: number;\n concurrency: number;\n };\n kpi: {\n name: string;\n interval: number;\n concurrency: number;\n };\n csmmImport: {\n name: string;\n };\n system: {\n name: string;\n };\n };\n redis: {\n host: string;\n port: number;\n username: string;\n password: string;\n };\n}\ndeclare const queuesConfigSchema: {\n redis: {\n host: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n port: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n username: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n password: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n queues: {\n commands: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n cronjobs: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n hooks: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n events: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n connector: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n itemsSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n bansSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n steamSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n playerSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n kpi: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n csmmImport: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n system: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n };\n};\ndeclare const config: Config;\n","file://node_modules/@takaro/queues/dist/dataDefinitions.d.ts":"interface IParsedCommand {\n command: string;\n arguments: Record;\n [key: string]: string | Record;\n}\ninterface IBaseJobData {\n [key: string]: unknown;\n domainId: string;\n}\ninterface IJobData extends IBaseJobData {\n functionId: string;\n /**\n * The id of the item that triggered this job (cronjobId, commandId or hookId)\n */\n itemId: string;\n /**\n * The id of the gameserver that triggered this job\n */\n gameServerId: string;\n /**\n * The module installation object, including the configs\n */\n module: ModuleInstallationOutputDTO;\n}\ninterface IHookJobData extends IJobData {\n eventData: EventPayload;\n player?: PlayerOutputWithRolesDTO;\n pog?: PlayerOnGameserverOutputWithRolesDTO;\n}\ninterface ICommandJobData extends IJobData {\n player: PlayerOutputWithRolesDTO;\n pog: PlayerOnGameserverOutputWithRolesDTO;\n arguments: IParsedCommand['arguments'];\n chatMessage: EventChatMessage;\n trigger: string;\n}\ntype ICronJobData = IJobData;\ndeclare function isCommandData(data: IJobData): data is ICommandJobData;\ndeclare function isHookData(data: IJobData): data is IHookJobData;\ndeclare function isCronData(data: IJobData): data is ICronJobData;\ninterface IEventQueueData extends IBaseJobData {\n type: ValueOf;\n gameServerId: string;\n event: ValueOf<(typeof GameEventsMapping)[ValueOf]>;\n}\ninterface IConnectorQueueData extends IBaseJobData {\n gameServerId: string;\n operation: 'create' | 'update' | 'delete';\n}\ninterface IGameServerQueueData extends IBaseJobData {\n gameServerId?: string;\n}\ninterface ICSMMImportData extends IBaseJobData {\n csmmExport: Record;\n options: {\n currency: boolean;\n players: boolean;\n roles: boolean;\n shop: boolean;\n };\n}\n","file://node_modules/@takaro/queues/dist/main.d.ts":"{ queueService } from './QueueService.js';\n{ queuesConfigSchema, IQueuesConfig } from './config.js';\n* from './dataDefinitions.js';\n{ TakaroQueue } from './TakaroQueue.js';\n{ TakaroWorker } from './TakaroWorker.js';\n{ getBullBoard } from './bullboard.js';\n","file://node_modules/@takaro/queues/dist/util/redisConnectionOptions.d.ts":"declare function getRedisConnectionOptions(): {\n host: string;\n port: number;\n username: string;\n password: string;\n};\n","file://node_modules/chalk/package.json":"{\"name\":\"chalk\",\"types\":\"types/index.d.ts\"}","file://node_modules/chalk/types/index.d.ts":"// Type definitions for Chalk\n// Definitions by: Thomas Sauer \n\nconst enum Level {\n\tNone = 0,\n\tBasic = 1,\n\tAnsi256 = 2,\n\tTrueColor = 3\n}\n\ninterface ChalkOptions {\n\tenabled?: boolean;\n\tlevel?: Level;\n}\n\ninterface ChalkConstructor {\n\tnew (options?: ChalkOptions): Chalk;\n\t(options?: ChalkOptions): Chalk;\n}\n\ninterface ColorSupport {\n\tlevel: Level;\n\thasBasic: boolean;\n\thas256: boolean;\n\thas16m: boolean;\n}\n\ninterface Chalk {\n\t(...text: string[]): string;\n\t(text: TemplateStringsArray, ...placeholders: string[]): string;\n\tconstructor: ChalkConstructor;\n\tenabled: boolean;\n\tlevel: Level;\n\trgb(r: number, g: number, b: number): this;\n\thsl(h: number, s: number, l: number): this;\n\thsv(h: number, s: number, v: number): this;\n\thwb(h: number, w: number, b: number): this;\n\tbgHex(color: string): this;\n\tbgKeyword(color: string): this;\n\tbgRgb(r: number, g: number, b: number): this;\n\tbgHsl(h: number, s: number, l: number): this;\n\tbgHsv(h: number, s: number, v: number): this;\n\tbgHwb(h: number, w: number, b: number): this;\n\thex(color: string): this;\n\tkeyword(color: string): this;\n\n\treadonly reset: this;\n\treadonly bold: this;\n\treadonly dim: this;\n\treadonly italic: this;\n\treadonly underline: this;\n\treadonly inverse: this;\n\treadonly hidden: this;\n\treadonly strikethrough: this;\n\n\treadonly visible: this;\n\n\treadonly black: this;\n\treadonly red: this;\n\treadonly green: this;\n\treadonly yellow: this;\n\treadonly blue: this;\n\treadonly magenta: this;\n\treadonly cyan: this;\n\treadonly white: this;\n\treadonly gray: this;\n\treadonly grey: this;\n\treadonly blackBright: this;\n\treadonly redBright: this;\n\treadonly greenBright: this;\n\treadonly yellowBright: this;\n\treadonly blueBright: this;\n\treadonly magentaBright: this;\n\treadonly cyanBright: this;\n\treadonly whiteBright: this;\n\n\treadonly bgBlack: this;\n\treadonly bgRed: this;\n\treadonly bgGreen: this;\n\treadonly bgYellow: this;\n\treadonly bgBlue: this;\n\treadonly bgMagenta: this;\n\treadonly bgCyan: this;\n\treadonly bgWhite: this;\n\treadonly bgBlackBright: this;\n\treadonly bgRedBright: this;\n\treadonly bgGreenBright: this;\n\treadonly bgYellowBright: this;\n\treadonly bgBlueBright: this;\n\treadonly bgMagentaBright: this;\n\treadonly bgCyanBright: this;\n\treadonly bgWhiteBright: this;\n}\n\ndeclare const chalk: Chalk & { supportsColor: ColorSupport };\n\ndefault chalk\n","file://node_modules/filelist/package.json":"{\"name\":\"filelist\",\"types\":\"index.d.ts\"}","file://node_modules/filelist/index.d.ts":"// IncludeOptions definitions copied from minimatch (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/minimatch/index.d.ts)\ninterface IncludeOptions {\n /**\n * Dump a ton of stuff to stderr.\n *\n * @default false\n */\n debug?: boolean;\n\n /**\n * Do not expand {a,b} and {1..3} brace sets.\n *\n * @default false\n */\n nobrace?: boolean;\n\n /**\n * Disable ** matching against multiple folder names.\n *\n * @default false\n */\n noglobstar?: boolean;\n\n /**\n * Allow patterns to match filenames starting with a period,\n * even if the pattern does not explicitly have a period in that spot.\n *\n * @default false\n */\n dot?: boolean;\n\n /**\n * Disable \"extglob\" style patterns like +(a|b).\n *\n * @default false\n */\n noext?: boolean;\n\n /**\n * Perform a case-insensitive match.\n *\n * @default false\n */\n nocase?: boolean;\n\n /**\n * When a match is not found by minimatch.match,\n * return a list containing the pattern itself if this option is set.\n * Otherwise, an empty list is returned if there are no matches.\n *\n * @default false\n */\n nonull?: boolean;\n\n /**\n * If set, then patterns without slashes will be matched against\n * the basename of the path if it contains slashes.\n *\n * @default false\n */\n matchBase?: boolean;\n\n /**\n * Suppress the behavior of treating #\n * at the start of a pattern as a comment.\n *\n * @default false\n */\n nocomment?: boolean;\n\n /**\n * Suppress the behavior of treating a leading ! character as negation.\n *\n * @default false\n */\n nonegate?: boolean;\n\n /**\n * Returns from negate expressions the same as if they were not negated.\n * (Ie, true on a hit, false on a miss.)\n *\n * @default false\n */\n flipNegate?: boolean;\n}\n\nclass FileList {\n static clone(): FileList\n static verbose: boolean\n}\n\ninterface FileList extends Omit, \"length\"> {\n pendingAdd: string[]\n pending: boolean\n excludes: {\n pats: RegExp[],\n funcs: Function[],\n regex: null | RegExp\n }\n items: string[]\n toArray(): string[]\n include(...items: string[]): this\n include(...items: (IncludeOptions | string)[]): this\n exclude(...items: string[]): this\n shouldExclude(item: string): boolean\n resolve(): this\n clearInclusions(): this\n clearExclusions(): this\n length(): number\n}","file://node_modules/setprototypeof/package.json":"{\"name\":\"setprototypeof\",\"types\":\"index.d.ts\"}","file://node_modules/setprototypeof/index.d.ts":"declare function setPrototypeOf(o: any, proto: object | null): any;\n= setPrototypeOf;\n","file://node_modules/iconv-lite/package.json":"{\"name\":\"iconv-lite\",\"types\":\"./lib/index.d.ts\"}","file://node_modules/iconv-lite/./lib/index.d.ts":"/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n * REQUIREMENT: This definition is dependent on the @types/node definition.\n * Install with `npm install @types/node --save-dev`\n *--------------------------------------------------------------------------------------------*/\n\ndeclare module 'iconv-lite' {\n\texport function decode(buffer: Buffer, encoding: string, options?: Options): string;\n\n\texport function encode(content: string, encoding: string, options?: Options): Buffer;\n\n\texport function encodingExists(encoding: string): boolean;\n\n\texport function decodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n\n\texport function encodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n}\n\ninterface Options {\n stripBOM?: boolean;\n addBOM?: boolean;\n defaultEncoding?: string;\n}\n","file://node_modules/side-channel/package.json":"{\"name\":\"side-channel\",\"types\":\"./index.d.ts\"}","file://node_modules/side-channel/index.d.ts":"declare namespace getSideChannel {\n\ttype Key = unknown;\n\ttype ListNode = {\n\t\tkey: Key;\n\t\tnext: ListNode;\n\t\tvalue: T;\n\t};\n\ttype RootNode = {\n\t\tkey: object;\n\t\tnext: null | ListNode;\n\t};\n\tfunction listGetNode(list: RootNode, key: ListNode['key']): ListNode | void;\n\tfunction listGet(objects: RootNode, key: ListNode['key']): T | void;\n\tfunction listSet(objects: RootNode, key: ListNode['key'], value: T): void;\n\tfunction listHas(objects: RootNode, key: ListNode['key']): boolean;\n\n\ttype Channel = {\n\t\tassert: (key: Key) => void;\n\t\thas: (key: Key) => boolean;\n\t\tget: (key: Key) => T;\n\t\tset: (key: Key, value: T) => void;\n\t}\n}\n\ndeclare function getSideChannel(): getSideChannel.Channel;\n\n= getSideChannel;\n","file://node_modules/es-define-property/package.json":"{\"name\":\"es-define-property\",\"types\":\"./index.d.ts\"}","file://node_modules/es-define-property/index.d.ts":"declare const defineProperty: false | typeof Object.defineProperty;\n\n= defineProperty;","file://node_modules/hasown/package.json":"{\"name\":\"hasown\",\"types\":\"index.d.ts\"}","file://node_modules/hasown/index.d.ts":"declare function hasOwn(o: O, p: K): o is O & Record;\n\n= hasOwn;\n","file://node_modules/define-data-property/package.json":"{\"name\":\"define-data-property\",\"types\":\"./index.d.ts\"}","file://node_modules/define-data-property/index.d.ts":"\ndeclare function defineDataProperty(\n obj: Record,\n property: keyof typeof obj,\n value: typeof obj[typeof property],\n nonEnumerable?: boolean | null,\n nonWritable?: boolean | null,\n nonConfigurable?: boolean | null,\n loose?: boolean\n): void;\n\n= defineDataProperty;","file://node_modules/safe-buffer/package.json":"{\"name\":\"safe-buffer\",\"types\":\"index.d.ts\"}","file://node_modules/safe-buffer/index.d.ts":"declare module \"safe-buffer\" {\n export class Buffer {\n length: number\n write(string: string, offset?: number, length?: number, encoding?: string): number;\n toString(encoding?: string, start?: number, end?: number): string;\n toJSON(): { type: 'Buffer', data: any[] };\n equals(otherBuffer: Buffer): boolean;\n compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;\n copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;\n slice(start?: number, end?: number): Buffer;\n writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUInt8(offset: number, noAssert?: boolean): number;\n readUInt16LE(offset: number, noAssert?: boolean): number;\n readUInt16BE(offset: number, noAssert?: boolean): number;\n readUInt32LE(offset: number, noAssert?: boolean): number;\n readUInt32BE(offset: number, noAssert?: boolean): number;\n readInt8(offset: number, noAssert?: boolean): number;\n readInt16LE(offset: number, noAssert?: boolean): number;\n readInt16BE(offset: number, noAssert?: boolean): number;\n readInt32LE(offset: number, noAssert?: boolean): number;\n readInt32BE(offset: number, noAssert?: boolean): number;\n readFloatLE(offset: number, noAssert?: boolean): number;\n readFloatBE(offset: number, noAssert?: boolean): number;\n readDoubleLE(offset: number, noAssert?: boolean): number;\n readDoubleBE(offset: number, noAssert?: boolean): number;\n swap16(): Buffer;\n swap32(): Buffer;\n swap64(): Buffer;\n writeUInt8(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt8(value: number, offset: number, noAssert?: boolean): number;\n writeInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatLE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatBE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;\n fill(value: any, offset?: number, end?: number): this;\n indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;\n\n /**\n * Allocates a new buffer containing the given {str}.\n *\n * @param str String to store in buffer.\n * @param encoding encoding to use, optional. Default is 'utf8'\n */\n constructor (str: string, encoding?: string);\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n */\n constructor (size: number);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: Uint8Array);\n /**\n * Produces a Buffer backed by the same allocated memory as\n * the given {ArrayBuffer}.\n *\n *\n * @param arrayBuffer The ArrayBuffer with which to share memory.\n */\n constructor (arrayBuffer: ArrayBuffer);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: any[]);\n /**\n * Copies the passed {buffer} data onto a new {Buffer} instance.\n *\n * @param buffer The buffer to copy.\n */\n constructor (buffer: Buffer);\n prototype: Buffer;\n /**\n * Allocates a new Buffer using an {array} of octets.\n *\n * @param array\n */\n static from(array: any[]): Buffer;\n /**\n * When passed a reference to the .buffer property of a TypedArray instance,\n * the newly created Buffer will share the same allocated memory as the TypedArray.\n * The optional {byteOffset} and {length} arguments specify a memory range\n * within the {arrayBuffer} that will be shared by the Buffer.\n *\n * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer()\n * @param byteOffset\n * @param length\n */\n static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;\n /**\n * Copies the passed {buffer} data onto a new Buffer instance.\n *\n * @param buffer\n */\n static from(buffer: Buffer): Buffer;\n /**\n * Creates a new Buffer containing the given JavaScript string {str}.\n * If provided, the {encoding} parameter identifies the character encoding.\n * If not provided, {encoding} defaults to 'utf8'.\n *\n * @param str\n */\n static from(str: string, encoding?: string): Buffer;\n /**\n * Returns true if {obj} is a Buffer\n *\n * @param obj object to test.\n */\n static isBuffer(obj: any): obj is Buffer;\n /**\n * Returns true if {encoding} is a valid encoding argument.\n * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex'\n *\n * @param encoding string to test.\n */\n static isEncoding(encoding: string): boolean;\n /**\n * Gives the actual byte length of a string. encoding defaults to 'utf8'.\n * This is not the same as String.prototype.length since that returns the number of characters in a string.\n *\n * @param string string to test.\n * @param encoding encoding used to evaluate (defaults to 'utf8')\n */\n static byteLength(string: string, encoding?: string): number;\n /**\n * Returns a buffer which is the result of concatenating all the buffers in the list together.\n *\n * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.\n * If the list has exactly one item, then the first item of the list is returned.\n * If the list has more than one item, then a new Buffer is created.\n *\n * @param list An array of Buffer objects to concatenate\n * @param totalLength Total length of the buffers when concatenated.\n * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.\n */\n static concat(list: Buffer[], totalLength?: number): Buffer;\n /**\n * The same as buf1.compare(buf2).\n */\n static compare(buf1: Buffer, buf2: Buffer): number;\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n * @param fill if specified, buffer will be initialized by calling buf.fill(fill).\n * If parameter is omitted, buffer will be filled with zeros.\n * @param encoding encoding used for call to buf.fill while initalizing\n */\n static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;\n /**\n * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafe(size: number): Buffer;\n /**\n * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafeSlow(size: number): Buffer;\n }\n}","file://node_modules/ipaddr.js/package.json":"{\"name\":\"ipaddr.js\",\"types\":\"./lib/ipaddr.js.d.ts\"}","file://node_modules/ipaddr.js/./lib/ipaddr.js.d.ts":"declare module \"ipaddr.js\" {\n type IPv4Range = 'unicast' | 'unspecified' | 'broadcast' | 'multicast' | 'linkLocal' | 'loopback' | 'carrierGradeNat' | 'private' | 'reserved';\n type IPv6Range = 'unicast' | 'unspecified' | 'linkLocal' | 'multicast' | 'loopback' | 'uniqueLocal' | 'ipv4Mapped' | 'rfc6145' | 'rfc6052' | '6to4' | 'teredo' | 'reserved';\n\n interface RangeList {\n [name: string]: [T, number] | [T, number][];\n }\n\n // Common methods/properties for IPv4 and IPv6 classes.\n class IP {\n prefixLengthFromSubnetMask(): number | null;\n toByteArray(): number[];\n toNormalizedString(): string;\n toString(): string;\n }\n\n namespace Address {\n export function isValid(addr: string): boolean;\n export function fromByteArray(bytes: number[]): IPv4 | IPv6;\n export function parse(addr: string): IPv4 | IPv6;\n export function parseCIDR(mask: string): [IPv4 | IPv6, number];\n export function process(addr: string): IPv4 | IPv6;\n export function subnetMatch(addr: IPv4, rangeList: RangeList, defaultName?: string): string;\n export function subnetMatch(addr: IPv6, rangeList: RangeList, defaultName?: string): string;\n\n export class IPv4 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv4;\n static isIPv4(addr: string): boolean;\n static isValidFourPartDecimal(addr: string): boolean;\n static isValid(addr: string): boolean;\n static networkAddressFromCIDR(addr: string): IPv4;\n static parse(addr: string): IPv4;\n static parseCIDR(addr: string): [IPv4, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv4;\n constructor(octets: number[]);\n octets: number[]\n\n kind(): 'ipv4';\n match(addr: IPv4, bits: number): boolean;\n match(mask: [IPv4, number]): boolean;\n range(): IPv4Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4MappedAddress(): IPv6;\n }\n\n export class IPv6 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv6;\n static isIPv6(addr: string): boolean;\n static isValid(addr: string): boolean;\n static parse(addr: string): IPv6;\n static parseCIDR(addr: string): [IPv6, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv6;\n constructor(parts: number[]);\n parts: number[]\n zoneId?: string\n\n isIPv4MappedAddress(): boolean;\n kind(): 'ipv6';\n match(addr: IPv6, bits: number): boolean;\n match(mask: [IPv6, number]): boolean;\n range(): IPv6Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4Address(): IPv4;\n }\n }\n\n export = Address;\n}\n"} +{"file://node_modules/axios/package.json":"{\"name\":\"axios\",\"types\":\"./index.d.ts\"}","file://node_modules/axios/index.d.ts":"// TypeScript Version: 4.7\ntype AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null;\n\ninterface RawAxiosHeaders {\n [key: string]: AxiosHeaderValue;\n}\n\ntype MethodsHeaders = Partial<{\n [Key in Method as Lowercase]: AxiosHeaders;\n} & {common: AxiosHeaders}>;\n\ntype AxiosHeaderMatcher = string | RegExp | ((this: AxiosHeaders, value: string, name: string) => boolean);\n\ntype AxiosHeaderParser = (this: AxiosHeaders, value: AxiosHeaderValue, header: string) => any;\n\nclass AxiosHeaders {\n constructor(\n headers?: RawAxiosHeaders | AxiosHeaders | string\n );\n\n [key: string]: any;\n\n set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders;\n\n get(headerName: string, parser: RegExp): RegExpExecArray | null;\n get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;\n\n has(header: string, matcher?: AxiosHeaderMatcher): boolean;\n\n delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;\n\n clear(matcher?: AxiosHeaderMatcher): boolean;\n\n normalize(format: boolean): AxiosHeaders;\n\n concat(...targets: Array): AxiosHeaders;\n\n toJSON(asStrings?: boolean): RawAxiosHeaders;\n\n static from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;\n\n static accessor(header: string | string[]): AxiosHeaders;\n\n static concat(...targets: Array): AxiosHeaders;\n\n setContentType(value: ContentType, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentType(parser?: RegExp): RegExpExecArray | null;\n getContentType(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentType(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentLength(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentLength(parser?: RegExp): RegExpExecArray | null;\n getContentLength(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentLength(matcher?: AxiosHeaderMatcher): boolean;\n\n setAccept(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAccept(parser?: RegExp): RegExpExecArray | null;\n getAccept(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAccept(matcher?: AxiosHeaderMatcher): boolean;\n\n setUserAgent(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getUserAgent(parser?: RegExp): RegExpExecArray | null;\n getUserAgent(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasUserAgent(matcher?: AxiosHeaderMatcher): boolean;\n\n setContentEncoding(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getContentEncoding(parser?: RegExp): RegExpExecArray | null;\n getContentEncoding(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasContentEncoding(matcher?: AxiosHeaderMatcher): boolean;\n\n setAuthorization(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;\n getAuthorization(parser?: RegExp): RegExpExecArray | null;\n getAuthorization(matcher?: AxiosHeaderMatcher): AxiosHeaderValue;\n hasAuthorization(matcher?: AxiosHeaderMatcher): boolean;\n\n [Symbol.iterator](): IterableIterator<[string, AxiosHeaderValue]>;\n}\n\ntype CommonRequestHeadersList = 'Accept' | 'Content-Length' | 'User-Agent' | 'Content-Encoding' | 'Authorization';\n\ntype ContentType = AxiosHeaderValue | 'text/html' | 'text/plain' | 'multipart/form-data' | 'application/json' | 'application/x-www-form-urlencoded' | 'application/octet-stream';\n\ntype RawAxiosRequestHeaders = Partial;\n\ntype AxiosRequestHeaders = RawAxiosRequestHeaders & AxiosHeaders;\n\ntype CommonResponseHeadersList = 'Server' | 'Content-Type' | 'Content-Length' | 'Cache-Control'| 'Content-Encoding';\n\ntype RawCommonResponseHeaders = {\n [Key in CommonResponseHeadersList]: AxiosHeaderValue;\n} & {\n \"set-cookie\": string[];\n};\n\ntype RawAxiosResponseHeaders = Partial;\n\ntype AxiosResponseHeaders = RawAxiosResponseHeaders & AxiosHeaders;\n\ninterface AxiosRequestTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosRequestHeaders): any;\n}\n\ninterface AxiosResponseTransformer {\n (this: InternalAxiosRequestConfig, data: any, headers: AxiosResponseHeaders, status?: number): any;\n}\n\ninterface AxiosAdapter {\n (config: InternalAxiosRequestConfig): AxiosPromise;\n}\n\ninterface AxiosBasicCredentials {\n username: string;\n password: string;\n}\n\ninterface AxiosProxyConfig {\n host: string;\n port: number;\n auth?: AxiosBasicCredentials;\n protocol?: string;\n}\n\nenum HttpStatusCode {\n Continue = 100,\n SwitchingProtocols = 101,\n Processing = 102,\n EarlyHints = 103,\n Ok = 200,\n Created = 201,\n Accepted = 202,\n NonAuthoritativeInformation = 203,\n NoContent = 204,\n ResetContent = 205,\n PartialContent = 206,\n MultiStatus = 207,\n AlreadyReported = 208,\n ImUsed = 226,\n MultipleChoices = 300,\n MovedPermanently = 301,\n Found = 302,\n SeeOther = 303,\n NotModified = 304,\n UseProxy = 305,\n Unused = 306,\n TemporaryRedirect = 307,\n PermanentRedirect = 308,\n BadRequest = 400,\n Unauthorized = 401,\n PaymentRequired = 402,\n Forbidden = 403,\n NotFound = 404,\n MethodNotAllowed = 405,\n NotAcceptable = 406,\n ProxyAuthenticationRequired = 407,\n RequestTimeout = 408,\n Conflict = 409,\n Gone = 410,\n LengthRequired = 411,\n PreconditionFailed = 412,\n PayloadTooLarge = 413,\n UriTooLong = 414,\n UnsupportedMediaType = 415,\n RangeNotSatisfiable = 416,\n ExpectationFailed = 417,\n ImATeapot = 418,\n MisdirectedRequest = 421,\n UnprocessableEntity = 422,\n Locked = 423,\n FailedDependency = 424,\n TooEarly = 425,\n UpgradeRequired = 426,\n PreconditionRequired = 428,\n TooManyRequests = 429,\n RequestHeaderFieldsTooLarge = 431,\n UnavailableForLegalReasons = 451,\n InternalServerError = 500,\n NotImplemented = 501,\n BadGateway = 502,\n ServiceUnavailable = 503,\n GatewayTimeout = 504,\n HttpVersionNotSupported = 505,\n VariantAlsoNegotiates = 506,\n InsufficientStorage = 507,\n LoopDetected = 508,\n NotExtended = 510,\n NetworkAuthenticationRequired = 511,\n}\n\ntype Method =\n | 'get' | 'GET'\n | 'delete' | 'DELETE'\n | 'head' | 'HEAD'\n | 'options' | 'OPTIONS'\n | 'post' | 'POST'\n | 'put' | 'PUT'\n | 'patch' | 'PATCH'\n | 'purge' | 'PURGE'\n | 'link' | 'LINK'\n | 'unlink' | 'UNLINK';\n\ntype ResponseType =\n | 'arraybuffer'\n | 'blob'\n | 'document'\n | 'json'\n | 'text'\n | 'stream'\n | 'formdata';\n\ntype responseEncoding =\n | 'ascii' | 'ASCII'\n | 'ansi' | 'ANSI'\n | 'binary' | 'BINARY'\n | 'base64' | 'BASE64'\n | 'base64url' | 'BASE64URL'\n | 'hex' | 'HEX'\n | 'latin1' | 'LATIN1'\n | 'ucs-2' | 'UCS-2'\n | 'ucs2' | 'UCS2'\n | 'utf-8' | 'UTF-8'\n | 'utf8' | 'UTF8'\n | 'utf16le' | 'UTF16LE';\n\ninterface TransitionalOptions {\n silentJSONParsing?: boolean;\n forcedJSONParsing?: boolean;\n clarifyTimeoutError?: boolean;\n}\n\ninterface GenericAbortSignal {\n readonly aborted: boolean;\n onabort?: ((...args: any) => any) | null;\n addEventListener?: (...args: any) => any;\n removeEventListener?: (...args: any) => any;\n}\n\ninterface FormDataVisitorHelpers {\n defaultVisitor: SerializerVisitor;\n convertValue: (value: any) => any;\n isVisitable: (value: any) => boolean;\n}\n\ninterface SerializerVisitor {\n (\n this: GenericFormData,\n value: any,\n key: string | number,\n path: null | Array,\n helpers: FormDataVisitorHelpers\n ): boolean;\n}\n\ninterface SerializerOptions {\n visitor?: SerializerVisitor;\n dots?: boolean;\n metaTokens?: boolean;\n indexes?: boolean | null;\n}\n\n// tslint:disable-next-line\ninterface FormSerializerOptions extends SerializerOptions {\n}\n\ninterface ParamEncoder {\n (value: any, defaultEncoder: (value: any) => any): any;\n}\n\ninterface CustomParamsSerializer {\n (params: Record, options?: ParamsSerializerOptions): string;\n}\n\ninterface ParamsSerializerOptions extends SerializerOptions {\n encode?: ParamEncoder;\n serialize?: CustomParamsSerializer;\n}\n\ntype MaxUploadRate = number;\n\ntype MaxDownloadRate = number;\n\ntype BrowserProgressEvent = any;\n\ninterface AxiosProgressEvent {\n loaded: number;\n total?: number;\n progress?: number;\n bytes: number;\n rate?: number;\n estimated?: number;\n upload?: boolean;\n download?: boolean;\n event?: BrowserProgressEvent;\n lengthComputable: boolean;\n}\n\ntype Milliseconds = number;\n\ntype AxiosAdapterName = 'fetch' | 'xhr' | 'http' | string;\n\ntype AxiosAdapterConfig = AxiosAdapter | AxiosAdapterName;\n\ntype AddressFamily = 4 | 6 | undefined;\n\ninterface LookupAddressEntry {\n address: string;\n family?: AddressFamily;\n}\n\ntype LookupAddress = string | LookupAddressEntry;\n\ninterface AxiosRequestConfig {\n url?: string;\n method?: Method | string;\n baseURL?: string;\n transformRequest?: AxiosRequestTransformer | AxiosRequestTransformer[];\n transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[];\n headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders;\n params?: any;\n paramsSerializer?: ParamsSerializerOptions | CustomParamsSerializer;\n data?: D;\n timeout?: Milliseconds;\n timeoutErrorMessage?: string;\n withCredentials?: boolean;\n adapter?: AxiosAdapterConfig | AxiosAdapterConfig[];\n auth?: AxiosBasicCredentials;\n responseType?: ResponseType;\n responseEncoding?: responseEncoding | string;\n xsrfCookieName?: string;\n xsrfHeaderName?: string;\n onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;\n onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void;\n maxContentLength?: number;\n validateStatus?: ((status: number) => boolean) | null;\n maxBodyLength?: number;\n maxRedirects?: number;\n maxRate?: number | [MaxUploadRate, MaxDownloadRate];\n beforeRedirect?: (options: Record, responseDetails: {headers: Record, statusCode: HttpStatusCode}) => void;\n socketPath?: string | null;\n transport?: any;\n httpAgent?: any;\n httpsAgent?: any;\n proxy?: AxiosProxyConfig | false;\n cancelToken?: CancelToken;\n decompress?: boolean;\n transitional?: TransitionalOptions;\n signal?: GenericAbortSignal;\n insecureHTTPParser?: boolean;\n env?: {\n FormData?: new (...args: any[]) => object;\n };\n formSerializer?: FormSerializerOptions;\n family?: AddressFamily;\n lookup?: ((hostname: string, options: object, cb: (err: Error | null, address: LookupAddress | LookupAddress[], family?: AddressFamily) => void) => void) |\n ((hostname: string, options: object) => Promise<[address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress>);\n withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined);\n fetchOptions?: Record;\n}\n\n// Alias\ntype RawAxiosRequestConfig = AxiosRequestConfig;\n\ninterface InternalAxiosRequestConfig extends AxiosRequestConfig {\n headers: AxiosRequestHeaders;\n}\n\ninterface HeadersDefaults {\n common: RawAxiosRequestHeaders;\n delete: RawAxiosRequestHeaders;\n get: RawAxiosRequestHeaders;\n head: RawAxiosRequestHeaders;\n post: RawAxiosRequestHeaders;\n put: RawAxiosRequestHeaders;\n patch: RawAxiosRequestHeaders;\n options?: RawAxiosRequestHeaders;\n purge?: RawAxiosRequestHeaders;\n link?: RawAxiosRequestHeaders;\n unlink?: RawAxiosRequestHeaders;\n}\n\ninterface AxiosDefaults extends Omit, 'headers'> {\n headers: HeadersDefaults;\n}\n\ninterface CreateAxiosDefaults extends Omit, 'headers'> {\n headers?: RawAxiosRequestHeaders | AxiosHeaders | Partial;\n}\n\ninterface AxiosResponse {\n data: T;\n status: number;\n statusText: string;\n headers: RawAxiosResponseHeaders | AxiosResponseHeaders;\n config: InternalAxiosRequestConfig;\n request?: any;\n}\n\nclass AxiosError extends Error {\n constructor(\n message?: string,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse\n );\n\n config?: InternalAxiosRequestConfig;\n code?: string;\n request?: any;\n response?: AxiosResponse;\n isAxiosError: boolean;\n status?: number;\n toJSON: () => object;\n cause?: Error;\n static from(\n error: Error | unknown,\n code?: string,\n config?: InternalAxiosRequestConfig,\n request?: any,\n response?: AxiosResponse,\n customProps?: object,\n): AxiosError;\n static readonly ERR_FR_TOO_MANY_REDIRECTS = \"ERR_FR_TOO_MANY_REDIRECTS\";\n static readonly ERR_BAD_OPTION_VALUE = \"ERR_BAD_OPTION_VALUE\";\n static readonly ERR_BAD_OPTION = \"ERR_BAD_OPTION\";\n static readonly ERR_NETWORK = \"ERR_NETWORK\";\n static readonly ERR_DEPRECATED = \"ERR_DEPRECATED\";\n static readonly ERR_BAD_RESPONSE = \"ERR_BAD_RESPONSE\";\n static readonly ERR_BAD_REQUEST = \"ERR_BAD_REQUEST\";\n static readonly ERR_NOT_SUPPORT = \"ERR_NOT_SUPPORT\";\n static readonly ERR_INVALID_URL = \"ERR_INVALID_URL\";\n static readonly ERR_CANCELED = \"ERR_CANCELED\";\n static readonly ECONNABORTED = \"ECONNABORTED\";\n static readonly ETIMEDOUT = \"ETIMEDOUT\";\n}\n\nclass CanceledError extends AxiosError {\n}\n\ntype AxiosPromise = Promise>;\n\ninterface CancelStatic {\n new (message?: string): Cancel;\n}\n\ninterface Cancel {\n message: string | undefined;\n}\n\ninterface Canceler {\n (message?: string, config?: AxiosRequestConfig, request?: any): void;\n}\n\ninterface CancelTokenStatic {\n new (executor: (cancel: Canceler) => void): CancelToken;\n source(): CancelTokenSource;\n}\n\ninterface CancelToken {\n promise: Promise;\n reason?: Cancel;\n throwIfRequested(): void;\n}\n\ninterface CancelTokenSource {\n token: CancelToken;\n cancel: Canceler;\n}\n\ninterface AxiosInterceptorOptions {\n synchronous?: boolean;\n runWhen?: (config: InternalAxiosRequestConfig) => boolean;\n}\n\ninterface AxiosInterceptorManager {\n use(onFulfilled?: ((value: V) => V | Promise) | null, onRejected?: ((error: any) => any) | null, options?: AxiosInterceptorOptions): number;\n eject(id: number): void;\n clear(): void;\n}\n\nclass Axios {\n constructor(config?: AxiosRequestConfig);\n defaults: AxiosDefaults;\n interceptors: {\n request: AxiosInterceptorManager;\n response: AxiosInterceptorManager;\n };\n getUri(config?: AxiosRequestConfig): string;\n request, D = any>(config: AxiosRequestConfig): Promise;\n get, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n delete, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n head, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n options, D = any>(url: string, config?: AxiosRequestConfig): Promise;\n post, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n put, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patch, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n postForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n putForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n patchForm, D = any>(url: string, data?: D, config?: AxiosRequestConfig): Promise;\n}\n\ninterface AxiosInstance extends Axios {\n , D = any>(config: AxiosRequestConfig): Promise;\n , D = any>(url: string, config?: AxiosRequestConfig): Promise;\n\n defaults: Omit & {\n headers: HeadersDefaults & {\n [key: string]: AxiosHeaderValue\n }\n };\n}\n\ninterface GenericFormData {\n append(name: string, value: any, options?: any): any;\n}\n\ninterface GenericHTMLFormElement {\n name: string;\n method: string;\n submit(): void;\n}\n\nfunction getAdapter(adapters: AxiosAdapterConfig | AxiosAdapterConfig[] | undefined): AxiosAdapter;\n\nfunction toFormData(sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions): GenericFormData;\n\nfunction formToJSON(form: GenericFormData|GenericHTMLFormElement): object;\n\nfunction isAxiosError(payload: any): payload is AxiosError;\n\nfunction spread(callback: (...args: T[]) => R): (array: T[]) => R;\n\nfunction isCancel(value: any): value is Cancel;\n\nfunction all(values: Array>): Promise;\n\ninterface AxiosStatic extends AxiosInstance {\n create(config?: CreateAxiosDefaults): AxiosInstance;\n Cancel: CancelStatic;\n CancelToken: CancelTokenStatic;\n Axios: typeof Axios;\n AxiosError: typeof AxiosError;\n HttpStatusCode: typeof HttpStatusCode;\n readonly VERSION: string;\n isCancel: typeof isCancel;\n all: typeof all;\n spread: typeof spread;\n isAxiosError: typeof isAxiosError;\n toFormData: typeof toFormData;\n formToJSON: typeof formToJSON;\n getAdapter: typeof getAdapter;\n CanceledError: typeof CanceledError;\n AxiosHeaders: typeof AxiosHeaders;\n}\n\ndeclare const axios: AxiosStatic;\n\ndefault axios;\n","file://node_modules/form-data/package.json":"{\"name\":\"form-data\",\"types\":\"./index.d.ts\"}","file://node_modules/form-data/index.d.ts":"// Definitions by: Carlos Ballesteros Velasco \n// Leon Yu \n// BendingBender \n// Maple Miao \n\n/// \n\n= FormData;\n\n// Extracted because @types/node doesn't export interfaces.\ninterface ReadableOptions {\n highWaterMark?: number;\n encoding?: string;\n objectMode?: boolean;\n read?(this: stream.Readable, size: number): void;\n destroy?(this: stream.Readable, error: Error | null, callback: (error: Error | null) => void): void;\n autoDestroy?: boolean;\n}\n\ninterface Options extends ReadableOptions {\n writable?: boolean;\n readable?: boolean;\n dataSize?: number;\n maxDataSize?: number;\n pauseStreams?: boolean;\n}\n\ndeclare class FormData extends stream.Readable {\n constructor(options?: Options);\n append(key: string, value: any, options?: FormData.AppendOptions | string): void;\n getHeaders(userHeaders?: FormData.Headers): FormData.Headers;\n submit(\n params: string | FormData.SubmitOptions,\n callback?: (error: Error | null, response: http.IncomingMessage) => void\n ): http.ClientRequest;\n getBuffer(): Buffer;\n setBoundary(boundary: string): void;\n getBoundary(): string;\n getLength(callback: (err: Error | null, length: number) => void): void;\n getLengthSync(): number;\n hasKnownLength(): boolean;\n}\n\ndeclare namespace FormData {\n interface Headers {\n [key: string]: any;\n }\n\n interface AppendOptions {\n header?: string | Headers;\n knownLength?: number;\n filename?: string;\n filepath?: string;\n contentType?: string;\n }\n\n interface SubmitOptions extends http.RequestOptions {\n protocol?: 'https:' | 'http:';\n }\n}\n","file://node_modules/@takaro/helpers/package.json":"{\"name\":\"@takaro/helpers\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/helpers/dist/TakaroUserError.d.ts":"declare class TakaroUserError extends Error {\n constructor(message: string);\n}\n","file://node_modules/@takaro/helpers/dist/checkPermission.d.ts":"declare function checkPermission(player: PlayerOnGameserverOutputWithRolesDTO, permission: string): any;\n","file://node_modules/@takaro/helpers/dist/config.d.ts":"interface IHelpersConfig extends IBaseConfig {\n apiClient: {\n token: string;\n url: string;\n };\n data: string;\n}\ndeclare const config: Config;\n{};\n","file://node_modules/@takaro/helpers/dist/getData.d.ts":"declare function getData(): any;\n","file://node_modules/@takaro/helpers/dist/getTakaro.d.ts":"declare function getTakaro(data: Record, logger?: Pick): {\n takaro: Client;\n data: Record;\n};\n","file://node_modules/@takaro/helpers/dist/main.d.ts":"{ getTakaro } from './getTakaro.js';\n{ checkPermission } from './checkPermission.js';\n{ nextCronJobRun } from './nextCronJobRun.js';\n{ TakaroUserError } from './TakaroUserError.js';\n* as _ from 'lodash-es';\n* as axios from 'axios';\ndeclare const takaro: Client;\n","file://node_modules/@takaro/helpers/dist/nextCronJobRun.d.ts":"declare const nextCronJobRun: (cron: string) => Date | null;\n","file://node_modules/croner/package.json":"{\"name\":\"croner\",\"types\":\"./types/croner.d.ts\"}","file://node_modules/croner/./types/croner.d.ts":"type TimePoint = {\n /**\n * - 1970--\n */\n y: number;\n /**\n * - 1-12\n */\n m: number;\n /**\n * - 1-31\n */\n d: number;\n /**\n * - 0-24\n */\n h: number;\n /**\n * - 0-60 Minute\n */\n i: number;\n /**\n * - 0-60\n */\n s: number;\n /**\n * - Time zone in IANA database format 'Europe/Stockholm'\n */\n tz: string;\n};\ntype CatchCallbackFn = (e: unknown, job: Cron) => any;\ntype ProtectCallbackFn = (job: Cron) => any;\n/**\n * - Cron scheduler options\n */\ntype CronOptions = {\n /**\n * - Name of a job\n */\n name?: string;\n /**\n * - Job is paused\n */\n paused?: boolean;\n /**\n * - Job is about to be killed or killed\n */\n kill?: boolean;\n /**\n * - Continue exection even if a unhandled error is thrown by triggered function\n * - If set to a function, execute function on catching the error.\n */\n catch?: boolean | CatchCallbackFn;\n /**\n * - Abort job instantly if nothing else keeps the event loop running.\n */\n unref?: boolean;\n /**\n * - Maximum nuber of executions\n */\n maxRuns?: number;\n /**\n * - Minimum interval between executions, in seconds\n */\n interval?: number;\n /**\n * - Skip current run if job is already running\n */\n protect?: boolean | ProtectCallbackFn;\n /**\n * - When to start running\n */\n startAt?: string | Date;\n /**\n * - When to stop running\n */\n stopAt?: string | Date;\n /**\n * - Time zone in Europe/Stockholm format\n */\n timezone?: string;\n /**\n * - Offset from UTC in minutes\n */\n utcOffset?: number;\n /**\n * - Combine day-of-month and day-of-week using true = OR, false = AND. Default is true = OR.\n */\n legacyMode?: boolean;\n /**\n * - Used to pass any object to scheduled function\n */\n context?: unknown;\n};\n/**\n * Name for each part of the cron pattern\n */\ntype CronPatternPart = (\"second\" | \"minute\" | \"hour\" | \"day\" | \"month\" | \"dayOfWeek\");\n/**\n * Offset, 0 or -1.\n *\n * 0 offset is used for seconds,minutes and hours as they start on 1.\n * -1 on days and months, as they start on 0\n */\ntype CronIndexOffset = number;\n/**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\nfunction Cron(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function): Cron;\nclass Cron {\n /**\n * Cron entrypoint\n *\n * @constructor\n * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string\n * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern\n * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern\n * @returns {Cron}\n */\n constructor(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function);\n /**\n * @public\n * @type {string|undefined} */\n public name: string | undefined;\n /**\n * @public\n * @type {CronOptions} */\n public options: CronOptions;\n /**\n * Encapsulate all internal states in an object.\n * Duplicate all options that can change to internal states, for example maxRuns and paused.\n * @private\n */\n private _states;\n fn: Function | CronOptions;\n /**\n * Find next runtime, based on supplied date. Strips milliseconds.\n *\n * @param {CronDate|Date|string} [prev] - Date to start from\n * @returns {Date | null} - Next run time\n */\n nextRun(prev?: CronDate | Date | string): Date | null;\n /**\n * Find next n runs, based on supplied date. Strips milliseconds.\n *\n * @param {number} n - Number of runs to enumerate\n * @param {Date|string} [previous] - Date to start from\n * @returns {Date[]} - Next n run times\n */\n nextRuns(n: number, previous?: Date | string): Date[];\n /**\n * Return the original pattern, if there was one\n *\n * @returns {string|undefined} - Original pattern\n */\n getPattern(): string | undefined;\n /**\n * Indicates whether or not the cron job is scheduled and running, e.g. awaiting next trigger\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isRunning(): boolean;\n /**\n * Indicates whether or not the cron job is permanently stopped\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isStopped(): boolean;\n /**\n * Indicates whether or not the cron job is currently working\n * @public\n *\n * @returns {boolean} - Running or not\n */\n public isBusy(): boolean;\n /**\n * Return current/previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public currentRun(): Date | null;\n /**\n * Return previous run start time\n * @public\n *\n * @returns {Date | null} - Previous run time\n */\n public previousRun(): Date | null;\n /**\n * Returns number of milliseconds to next run\n * @public\n *\n * @param {CronDate|Date|string} [prev] - Starting date, defaults to now - minimum interval\n * @returns {number | null}\n */\n public msToNext(prev?: CronDate | Date | string): number | null;\n /**\n * Stop execution\n *\n * Running this will forcefully stop the job, and prevent furter exection. `.resume()` will not work after stopping.\n * It will also be removed from the scheduledJobs array if it were named.\n *\n * @public\n */\n public stop(): void;\n /**\n * Pause execution\n * @public\n *\n * @returns {boolean} - Wether pause was successful\n */\n public pause(): boolean;\n /**\n * Resume execution\n * @public\n *\n * @returns {boolean} - Wether resume was successful\n */\n public resume(): boolean;\n /**\n * Schedule a new job\n * @public\n *\n * @param {Function} func - Function to be run each iteration of pattern\n * @returns {Cron}\n */\n public schedule(func: Function): Cron;\n private _trigger;\n /**\n * Trigger a run manually\n * @public\n */\n public trigger(): Promise;\n private _checkTrigger;\n private _next;\n private _calculatePreviousRun;\n}\nnamespace Cron {\n export { Cron };\n export { scheduledJobs };\n}\n/**\n * An array containing all named cron jobs.\n *\n * @constant\n * @type {Cron[]}\n */\nconst scheduledJobs: Cron[];\n/**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n*/\ndeclare function CronDate(d?: CronDate | Date | string, tz?: string | number): void;\ndeclare class CronDate {\n /**\n * Converts date to CronDate\n * @constructor\n *\n * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected\n * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.\n */\n constructor(d?: CronDate | Date | string, tz?: string | number);\n /**\n * TimeZone\n * @type {string|number|undefined}\n */\n tz: string | number | undefined;\n private isNthWeekdayOfMonth;\n private fromDate;\n ms: number;\n second: number;\n minute: number;\n hour: number;\n day: number;\n month: number;\n year: number;\n private fromCronDate;\n private apply;\n private fromString;\n private findNext;\n private recurse;\n /**\n * Increment to next run time\n * @public\n *\n * @param {string} pattern - The pattern used to increment current state\n * @param {CronOptions} options - Cron options used for incrementing\n * @param {boolean} [hasPreviousRun] - If this run should adhere to minimum interval\n * @return {CronDate|null} - Returns itthis for chaining, or null if increment wasnt possible\n */\n public increment(pattern: string, options: CronOptions, hasPreviousRun?: boolean): CronDate | null;\n /**\n * Convert current state back to a javascript Date()\n * @public\n *\n * @param {boolean} internal - If this is an internal call\n * @returns {Date}\n */\n public getDate(internal: boolean): Date;\n /**\n * Convert current state back to a javascript Date() and return UTC milliseconds\n * @public\n *\n * @returns {Date}\n */\n public getTime(): Date;\n}\n{ Cron as default };\n","file://node_modules/@takaro/queues/package.json":"{\"name\":\"@takaro/queues\",\"types\":\"dist/main.d.ts\"}","file://node_modules/@takaro/queues/dist/QueueService.d.ts":"declare class QueuesService {\n private static instance;\n static getInstance(): QueuesService;\n disconnect(): Promise;\n private queuesMap;\n get queues(): {\n commands: {\n queue: TakaroQueue;\n };\n cronjobs: {\n queue: TakaroQueue;\n };\n hooks: {\n queue: TakaroQueue;\n };\n events: {\n queue: TakaroQueue;\n };\n connector: {\n queue: TakaroQueue;\n };\n itemsSync: {\n queue: TakaroQueue;\n };\n bansSync: {\n queue: TakaroQueue;\n };\n playerSync: {\n queue: TakaroQueue;\n };\n steamSync: {\n queue: TakaroQueue;\n };\n csmmImport: {\n queue: TakaroQueue;\n };\n kpi: {\n queue: TakaroQueue>;\n };\n system: {\n queue: TakaroQueue>;\n };\n };\n}\ndeclare const queueService: QueuesService;\n{};\n","file://node_modules/@takaro/queues/dist/TakaroQueue.d.ts":"declare class TakaroQueue> {\n name: string;\n bullQueue: Queue;\n constructor(name: string);\n /**\n * Generating a job ID like this effectively de-duplicates all jobs with the same data.\n * @see https://docs.bullmq.io/guide/jobs/job-ids\n * @param data\n * @returns\n */\n private getJobId;\n add(data: T, extra?: JobsOptions): Promise>;\n getRepeatableJobs(): Promise;\n removeRepeatableByKey(id: string): Promise;\n}\n","file://node_modules/@takaro/queues/dist/TakaroWorker.d.ts":"type WorkerOptionsWithoutConnectionOptions = Omit;\ndeclare abstract class TakaroWorker {\n log: import(\"winston\").Logger;\n bullWorker: Worker;\n constructor(name: string, concurrency: number | undefined, fn: Processor, extraBullOpts?: WorkerOptionsWithoutConnectionOptions);\n}\n{};\n","file://node_modules/@takaro/queues/dist/bullboard.d.ts":"declare function getBullBoard(): any;\n","file://node_modules/@takaro/queues/dist/config.d.ts":"interface IQueuesConfig extends IBaseConfig {\n queues: {\n commands: {\n name: string;\n concurrency: number;\n };\n cronjobs: {\n name: string;\n concurrency: number;\n };\n hooks: {\n name: string;\n concurrency: number;\n };\n events: {\n name: string;\n concurrency: number;\n };\n connector: {\n name: string;\n };\n itemsSync: {\n name: string;\n interval: number;\n };\n bansSync: {\n name: string;\n interval: number;\n };\n steamSync: {\n name: string;\n interval: number;\n };\n playerSync: {\n name: string;\n interval: number;\n concurrency: number;\n };\n kpi: {\n name: string;\n interval: number;\n concurrency: number;\n };\n csmmImport: {\n name: string;\n };\n system: {\n name: string;\n };\n };\n redis: {\n host: string;\n port: number;\n username: string;\n password: string;\n };\n}\ndeclare const queuesConfigSchema: {\n redis: {\n host: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n port: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n username: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n password: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n queues: {\n commands: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n cronjobs: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n hooks: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n events: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n connector: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n itemsSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n bansSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n steamSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n playerSync: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n kpi: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n interval: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n concurrency: {\n doc: string;\n format: NumberConstructor;\n default: number;\n env: string;\n };\n };\n csmmImport: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n system: {\n name: {\n doc: string;\n format: StringConstructor;\n default: string;\n env: string;\n };\n };\n };\n};\ndeclare const config: Config;\n","file://node_modules/@takaro/queues/dist/dataDefinitions.d.ts":"interface IParsedCommand {\n command: string;\n arguments: Record;\n [key: string]: string | Record;\n}\ninterface IBaseJobData {\n [key: string]: unknown;\n domainId: string;\n}\ninterface IJobData extends IBaseJobData {\n functionId: string;\n /**\n * The id of the item that triggered this job (cronjobId, commandId or hookId)\n */\n itemId: string;\n /**\n * The id of the gameserver that triggered this job\n */\n gameServerId: string;\n /**\n * The module installation object, including the configs\n */\n module: ModuleInstallationOutputDTO;\n}\ninterface IHookJobData extends IJobData {\n eventData: EventPayload;\n player?: PlayerOutputWithRolesDTO;\n pog?: PlayerOnGameserverOutputWithRolesDTO;\n}\ninterface ICommandJobData extends IJobData {\n player: PlayerOutputWithRolesDTO;\n pog: PlayerOnGameserverOutputWithRolesDTO;\n arguments: IParsedCommand['arguments'];\n chatMessage: EventChatMessage;\n trigger: string;\n}\ntype ICronJobData = IJobData;\ndeclare function isCommandData(data: IJobData): data is ICommandJobData;\ndeclare function isHookData(data: IJobData): data is IHookJobData;\ndeclare function isCronData(data: IJobData): data is ICronJobData;\ninterface IEventQueueData extends IBaseJobData {\n type: ValueOf;\n gameServerId: string;\n event: ValueOf<(typeof GameEventsMapping)[ValueOf]>;\n}\ninterface IConnectorQueueData extends IBaseJobData {\n gameServerId: string;\n operation: 'create' | 'update' | 'delete';\n}\ninterface IGameServerQueueData extends IBaseJobData {\n gameServerId?: string;\n}\ninterface ICSMMImportData extends IBaseJobData {\n csmmExport: Record;\n options: {\n currency: boolean;\n players: boolean;\n roles: boolean;\n shop: boolean;\n };\n}\n","file://node_modules/@takaro/queues/dist/main.d.ts":"{ queueService } from './QueueService.js';\n{ queuesConfigSchema, IQueuesConfig } from './config.js';\n* from './dataDefinitions.js';\n{ TakaroQueue } from './TakaroQueue.js';\n{ TakaroWorker } from './TakaroWorker.js';\n{ getBullBoard } from './bullboard.js';\n","file://node_modules/@takaro/queues/dist/util/redisConnectionOptions.d.ts":"declare function getRedisConnectionOptions(): {\n host: string;\n port: number;\n username: string;\n password: string;\n};\n","file://node_modules/filelist/package.json":"{\"name\":\"filelist\",\"types\":\"index.d.ts\"}","file://node_modules/filelist/index.d.ts":"// IncludeOptions definitions copied from minimatch (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/minimatch/index.d.ts)\ninterface IncludeOptions {\n /**\n * Dump a ton of stuff to stderr.\n *\n * @default false\n */\n debug?: boolean;\n\n /**\n * Do not expand {a,b} and {1..3} brace sets.\n *\n * @default false\n */\n nobrace?: boolean;\n\n /**\n * Disable ** matching against multiple folder names.\n *\n * @default false\n */\n noglobstar?: boolean;\n\n /**\n * Allow patterns to match filenames starting with a period,\n * even if the pattern does not explicitly have a period in that spot.\n *\n * @default false\n */\n dot?: boolean;\n\n /**\n * Disable \"extglob\" style patterns like +(a|b).\n *\n * @default false\n */\n noext?: boolean;\n\n /**\n * Perform a case-insensitive match.\n *\n * @default false\n */\n nocase?: boolean;\n\n /**\n * When a match is not found by minimatch.match,\n * return a list containing the pattern itself if this option is set.\n * Otherwise, an empty list is returned if there are no matches.\n *\n * @default false\n */\n nonull?: boolean;\n\n /**\n * If set, then patterns without slashes will be matched against\n * the basename of the path if it contains slashes.\n *\n * @default false\n */\n matchBase?: boolean;\n\n /**\n * Suppress the behavior of treating #\n * at the start of a pattern as a comment.\n *\n * @default false\n */\n nocomment?: boolean;\n\n /**\n * Suppress the behavior of treating a leading ! character as negation.\n *\n * @default false\n */\n nonegate?: boolean;\n\n /**\n * Returns from negate expressions the same as if they were not negated.\n * (Ie, true on a hit, false on a miss.)\n *\n * @default false\n */\n flipNegate?: boolean;\n}\n\nclass FileList {\n static clone(): FileList\n static verbose: boolean\n}\n\ninterface FileList extends Omit, \"length\"> {\n pendingAdd: string[]\n pending: boolean\n excludes: {\n pats: RegExp[],\n funcs: Function[],\n regex: null | RegExp\n }\n items: string[]\n toArray(): string[]\n include(...items: string[]): this\n include(...items: (IncludeOptions | string)[]): this\n exclude(...items: string[]): this\n shouldExclude(item: string): boolean\n resolve(): this\n clearInclusions(): this\n clearExclusions(): this\n length(): number\n}","file://node_modules/setprototypeof/package.json":"{\"name\":\"setprototypeof\",\"types\":\"index.d.ts\"}","file://node_modules/setprototypeof/index.d.ts":"declare function setPrototypeOf(o: any, proto: object | null): any;\n= setPrototypeOf;\n","file://node_modules/iconv-lite/package.json":"{\"name\":\"iconv-lite\",\"types\":\"./lib/index.d.ts\"}","file://node_modules/iconv-lite/./lib/index.d.ts":"/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n * REQUIREMENT: This definition is dependent on the @types/node definition.\n * Install with `npm install @types/node --save-dev`\n *--------------------------------------------------------------------------------------------*/\n\ndeclare module 'iconv-lite' {\n\texport function decode(buffer: Buffer, encoding: string, options?: Options): string;\n\n\texport function encode(content: string, encoding: string, options?: Options): Buffer;\n\n\texport function encodingExists(encoding: string): boolean;\n\n\texport function decodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n\n\texport function encodeStream(encoding: string, options?: Options): NodeJS.ReadWriteStream;\n}\n\ninterface Options {\n stripBOM?: boolean;\n addBOM?: boolean;\n defaultEncoding?: string;\n}\n","file://node_modules/side-channel/package.json":"{\"name\":\"side-channel\",\"types\":\"./index.d.ts\"}","file://node_modules/side-channel/index.d.ts":"declare namespace getSideChannel {\n\ttype Key = unknown;\n\ttype ListNode = {\n\t\tkey: Key;\n\t\tnext: ListNode;\n\t\tvalue: T;\n\t};\n\ttype RootNode = {\n\t\tkey: object;\n\t\tnext: null | ListNode;\n\t};\n\tfunction listGetNode(list: RootNode, key: ListNode['key']): ListNode | void;\n\tfunction listGet(objects: RootNode, key: ListNode['key']): T | void;\n\tfunction listSet(objects: RootNode, key: ListNode['key'], value: T): void;\n\tfunction listHas(objects: RootNode, key: ListNode['key']): boolean;\n\n\ttype Channel = {\n\t\tassert: (key: Key) => void;\n\t\thas: (key: Key) => boolean;\n\t\tget: (key: Key) => T;\n\t\tset: (key: Key, value: T) => void;\n\t}\n}\n\ndeclare function getSideChannel(): getSideChannel.Channel;\n\n= getSideChannel;\n","file://node_modules/es-define-property/package.json":"{\"name\":\"es-define-property\",\"types\":\"./index.d.ts\"}","file://node_modules/es-define-property/index.d.ts":"declare const defineProperty: false | typeof Object.defineProperty;\n\n= defineProperty;","file://node_modules/hasown/package.json":"{\"name\":\"hasown\",\"types\":\"index.d.ts\"}","file://node_modules/hasown/index.d.ts":"declare function hasOwn(o: O, p: K): o is O & Record;\n\n= hasOwn;\n","file://node_modules/define-data-property/package.json":"{\"name\":\"define-data-property\",\"types\":\"./index.d.ts\"}","file://node_modules/define-data-property/index.d.ts":"\ndeclare function defineDataProperty(\n obj: Record,\n property: keyof typeof obj,\n value: typeof obj[typeof property],\n nonEnumerable?: boolean | null,\n nonWritable?: boolean | null,\n nonConfigurable?: boolean | null,\n loose?: boolean\n): void;\n\n= defineDataProperty;","file://node_modules/safe-buffer/package.json":"{\"name\":\"safe-buffer\",\"types\":\"index.d.ts\"}","file://node_modules/safe-buffer/index.d.ts":"declare module \"safe-buffer\" {\n export class Buffer {\n length: number\n write(string: string, offset?: number, length?: number, encoding?: string): number;\n toString(encoding?: string, start?: number, end?: number): string;\n toJSON(): { type: 'Buffer', data: any[] };\n equals(otherBuffer: Buffer): boolean;\n compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;\n copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;\n slice(start?: number, end?: number): Buffer;\n writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;\n readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;\n readUInt8(offset: number, noAssert?: boolean): number;\n readUInt16LE(offset: number, noAssert?: boolean): number;\n readUInt16BE(offset: number, noAssert?: boolean): number;\n readUInt32LE(offset: number, noAssert?: boolean): number;\n readUInt32BE(offset: number, noAssert?: boolean): number;\n readInt8(offset: number, noAssert?: boolean): number;\n readInt16LE(offset: number, noAssert?: boolean): number;\n readInt16BE(offset: number, noAssert?: boolean): number;\n readInt32LE(offset: number, noAssert?: boolean): number;\n readInt32BE(offset: number, noAssert?: boolean): number;\n readFloatLE(offset: number, noAssert?: boolean): number;\n readFloatBE(offset: number, noAssert?: boolean): number;\n readDoubleLE(offset: number, noAssert?: boolean): number;\n readDoubleBE(offset: number, noAssert?: boolean): number;\n swap16(): Buffer;\n swap32(): Buffer;\n swap64(): Buffer;\n writeUInt8(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt8(value: number, offset: number, noAssert?: boolean): number;\n writeInt16LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt16BE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32LE(value: number, offset: number, noAssert?: boolean): number;\n writeInt32BE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatLE(value: number, offset: number, noAssert?: boolean): number;\n writeFloatBE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;\n writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;\n fill(value: any, offset?: number, end?: number): this;\n indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;\n includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;\n\n /**\n * Allocates a new buffer containing the given {str}.\n *\n * @param str String to store in buffer.\n * @param encoding encoding to use, optional. Default is 'utf8'\n */\n constructor (str: string, encoding?: string);\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n */\n constructor (size: number);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: Uint8Array);\n /**\n * Produces a Buffer backed by the same allocated memory as\n * the given {ArrayBuffer}.\n *\n *\n * @param arrayBuffer The ArrayBuffer with which to share memory.\n */\n constructor (arrayBuffer: ArrayBuffer);\n /**\n * Allocates a new buffer containing the given {array} of octets.\n *\n * @param array The octets to store.\n */\n constructor (array: any[]);\n /**\n * Copies the passed {buffer} data onto a new {Buffer} instance.\n *\n * @param buffer The buffer to copy.\n */\n constructor (buffer: Buffer);\n prototype: Buffer;\n /**\n * Allocates a new Buffer using an {array} of octets.\n *\n * @param array\n */\n static from(array: any[]): Buffer;\n /**\n * When passed a reference to the .buffer property of a TypedArray instance,\n * the newly created Buffer will share the same allocated memory as the TypedArray.\n * The optional {byteOffset} and {length} arguments specify a memory range\n * within the {arrayBuffer} that will be shared by the Buffer.\n *\n * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer()\n * @param byteOffset\n * @param length\n */\n static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;\n /**\n * Copies the passed {buffer} data onto a new Buffer instance.\n *\n * @param buffer\n */\n static from(buffer: Buffer): Buffer;\n /**\n * Creates a new Buffer containing the given JavaScript string {str}.\n * If provided, the {encoding} parameter identifies the character encoding.\n * If not provided, {encoding} defaults to 'utf8'.\n *\n * @param str\n */\n static from(str: string, encoding?: string): Buffer;\n /**\n * Returns true if {obj} is a Buffer\n *\n * @param obj object to test.\n */\n static isBuffer(obj: any): obj is Buffer;\n /**\n * Returns true if {encoding} is a valid encoding argument.\n * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex'\n *\n * @param encoding string to test.\n */\n static isEncoding(encoding: string): boolean;\n /**\n * Gives the actual byte length of a string. encoding defaults to 'utf8'.\n * This is not the same as String.prototype.length since that returns the number of characters in a string.\n *\n * @param string string to test.\n * @param encoding encoding used to evaluate (defaults to 'utf8')\n */\n static byteLength(string: string, encoding?: string): number;\n /**\n * Returns a buffer which is the result of concatenating all the buffers in the list together.\n *\n * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.\n * If the list has exactly one item, then the first item of the list is returned.\n * If the list has more than one item, then a new Buffer is created.\n *\n * @param list An array of Buffer objects to concatenate\n * @param totalLength Total length of the buffers when concatenated.\n * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.\n */\n static concat(list: Buffer[], totalLength?: number): Buffer;\n /**\n * The same as buf1.compare(buf2).\n */\n static compare(buf1: Buffer, buf2: Buffer): number;\n /**\n * Allocates a new buffer of {size} octets.\n *\n * @param size count of octets to allocate.\n * @param fill if specified, buffer will be initialized by calling buf.fill(fill).\n * If parameter is omitted, buffer will be filled with zeros.\n * @param encoding encoding used for call to buf.fill while initalizing\n */\n static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;\n /**\n * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafe(size: number): Buffer;\n /**\n * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents\n * of the newly created Buffer are unknown and may contain sensitive data.\n *\n * @param size count of octets to allocate\n */\n static allocUnsafeSlow(size: number): Buffer;\n }\n}","file://node_modules/ipaddr.js/package.json":"{\"name\":\"ipaddr.js\",\"types\":\"./lib/ipaddr.js.d.ts\"}","file://node_modules/ipaddr.js/./lib/ipaddr.js.d.ts":"declare module \"ipaddr.js\" {\n type IPv4Range = 'unicast' | 'unspecified' | 'broadcast' | 'multicast' | 'linkLocal' | 'loopback' | 'carrierGradeNat' | 'private' | 'reserved';\n type IPv6Range = 'unicast' | 'unspecified' | 'linkLocal' | 'multicast' | 'loopback' | 'uniqueLocal' | 'ipv4Mapped' | 'rfc6145' | 'rfc6052' | '6to4' | 'teredo' | 'reserved';\n\n interface RangeList {\n [name: string]: [T, number] | [T, number][];\n }\n\n // Common methods/properties for IPv4 and IPv6 classes.\n class IP {\n prefixLengthFromSubnetMask(): number | null;\n toByteArray(): number[];\n toNormalizedString(): string;\n toString(): string;\n }\n\n namespace Address {\n export function isValid(addr: string): boolean;\n export function fromByteArray(bytes: number[]): IPv4 | IPv6;\n export function parse(addr: string): IPv4 | IPv6;\n export function parseCIDR(mask: string): [IPv4 | IPv6, number];\n export function process(addr: string): IPv4 | IPv6;\n export function subnetMatch(addr: IPv4, rangeList: RangeList, defaultName?: string): string;\n export function subnetMatch(addr: IPv6, rangeList: RangeList, defaultName?: string): string;\n\n export class IPv4 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv4;\n static isIPv4(addr: string): boolean;\n static isValidFourPartDecimal(addr: string): boolean;\n static isValid(addr: string): boolean;\n static networkAddressFromCIDR(addr: string): IPv4;\n static parse(addr: string): IPv4;\n static parseCIDR(addr: string): [IPv4, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv4;\n constructor(octets: number[]);\n octets: number[]\n\n kind(): 'ipv4';\n match(addr: IPv4, bits: number): boolean;\n match(mask: [IPv4, number]): boolean;\n range(): IPv4Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4MappedAddress(): IPv6;\n }\n\n export class IPv6 extends IP {\n static broadcastAddressFromCIDR(addr: string): IPv6;\n static isIPv6(addr: string): boolean;\n static isValid(addr: string): boolean;\n static parse(addr: string): IPv6;\n static parseCIDR(addr: string): [IPv6, number];\n static subnetMaskFromPrefixLength(prefix: number): IPv6;\n constructor(parts: number[]);\n parts: number[]\n zoneId?: string\n\n isIPv4MappedAddress(): boolean;\n kind(): 'ipv6';\n match(addr: IPv6, bits: number): boolean;\n match(mask: [IPv6, number]): boolean;\n range(): IPv6Range;\n subnetMatch(rangeList: RangeList, defaultName?: string): string;\n toIPv4Address(): IPv4;\n }\n }\n\n export = Address;\n}\n"} From b3987c7766d06c6595989a04e6ee0ec193bc37f1 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Mon, 28 Oct 2024 21:31:32 +0100 Subject: [PATCH 29/48] fix: role update/view not showing permissions correctly --- packages/web-main/src/queries/role.tsx | 4 ++-- .../src/routes/_auth/_global/-roles/RoleCreateUpdateForm.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/web-main/src/queries/role.tsx b/packages/web-main/src/queries/role.tsx index cfd04d3a7a..8531c3d1d2 100644 --- a/packages/web-main/src/queries/role.tsx +++ b/packages/web-main/src/queries/role.tsx @@ -72,9 +72,9 @@ export const useRoleCreate = () => { return mutationWrapper( useMutation, RoleCreateInputDTO>({ mutationFn: async (role) => (await apiClient.role.roleControllerCreate(role)).data.data, - onSuccess: async (newRole) => { + onSuccess: (newRole) => { enqueueSnackbar('Role created!', { variant: 'default', type: 'success' }); - await queryClient.invalidateQueries({ queryKey: roleKeys.list() }); + queryClient.invalidateQueries({ queryKey: roleKeys.list() }); queryClient.setQueryData(roleKeys.detail(newRole.id), newRole); }, }), diff --git a/packages/web-main/src/routes/_auth/_global/-roles/RoleCreateUpdateForm.tsx b/packages/web-main/src/routes/_auth/_global/-roles/RoleCreateUpdateForm.tsx index 50214d86e5..8c7f3819d6 100644 --- a/packages/web-main/src/routes/_auth/_global/-roles/RoleCreateUpdateForm.tsx +++ b/packages/web-main/src/routes/_auth/_global/-roles/RoleCreateUpdateForm.tsx @@ -88,7 +88,7 @@ export const RoleForm: FC = ({ const { control, handleSubmit, formState } = useForm({ mode: 'onChange', resolver: zodResolver(validationSchema), - defaultValues: initialData && { + values: initialData && { name: initialData.name, permissions: Object.values(permissions).reduce( (acc, permission) => ({ From 4273c089bdd7fe6633ed00f6503861fa5fbea960 Mon Sep 17 00:00:00 2001 From: Emiel Van Severen Date: Tue, 29 Oct 2024 21:45:45 +0100 Subject: [PATCH 30/48] Fix: select query in drawer, not rendered in portal --- .../src/routes/_auth/_global/user.$userId.role.assign.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web-main/src/routes/_auth/_global/user.$userId.role.assign.tsx b/packages/web-main/src/routes/_auth/_global/user.$userId.role.assign.tsx index 64713db142..cd63385a62 100644 --- a/packages/web-main/src/routes/_auth/_global/user.$userId.role.assign.tsx +++ b/packages/web-main/src/routes/_auth/_global/user.$userId.role.assign.tsx @@ -78,7 +78,7 @@ function Component() {
- + Date: Tue, 29 Oct 2024 20:59:24 +0000 Subject: [PATCH 31/48] chore(deps): update dependency @types/express to v5 --- package-lock.json | 62 ++++++++++++++++++++++++++++++---- package.json | 2 +- packages/lib-http/package.json | 2 +- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6d416dbd30..185a77b955 100644 --- a/package-lock.json +++ b/package-lock.json @@ -72,7 +72,7 @@ "@types/chai-as-promised": "8.0.1", "@types/eslint__js": "8.42.3", "@types/expect": "24.3.0", - "@types/express": "4.17.21", + "@types/express": "5.0.0", "@types/fs-extra": "11.0.4", "@types/he": "1.2.3", "@types/jest": "29.5.13", @@ -21300,6 +21300,19 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/types/node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "license": "MIT", @@ -22352,13 +22365,13 @@ } }, "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", + "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", "license": "MIT", "dependencies": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", + "@types/express-serve-static-core": "^5.0.0", "@types/qs": "*", "@types/serve-static": "*" } @@ -22373,6 +22386,18 @@ "@types/send": "*" } }, + "node_modules/@types/express/node_modules/@types/express-serve-static-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", + "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, "node_modules/@types/find-cache-dir": { "version": "3.2.1", "dev": true, @@ -45346,6 +45371,18 @@ } } }, + "node_modules/webpack-dev-server/node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, "node_modules/webpack-dev-server/node_modules/glob": { "version": "7.2.3", "license": "ISC", @@ -46955,6 +46992,19 @@ "url": "https://opencollective.com/storybook" } }, + "packages/lib-components/node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, "packages/lib-components/node_modules/@types/jest": { "version": "28.1.8", "dev": true, @@ -47417,7 +47467,7 @@ "devDependencies": { "@types/cookie-parser": "1.4.7", "@types/cors": "2.8.17", - "@types/express": "4.17.21", + "@types/express": "5.0.0", "supertest": "6.3.4" } }, diff --git a/package.json b/package.json index 28088651a1..ae762524ed 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "@types/chai-as-promised": "8.0.1", "@types/eslint__js": "8.42.3", "@types/expect": "24.3.0", - "@types/express": "4.17.21", + "@types/express": "5.0.0", "@types/fs-extra": "11.0.4", "@types/he": "1.2.3", "@types/jest": "29.5.13", diff --git a/packages/lib-http/package.json b/packages/lib-http/package.json index 002cb80e6c..901d4e0ffe 100644 --- a/packages/lib-http/package.json +++ b/packages/lib-http/package.json @@ -27,7 +27,7 @@ "devDependencies": { "@types/cookie-parser": "1.4.7", "@types/cors": "2.8.17", - "@types/express": "4.17.21", + "@types/express": "5.0.0", "supertest": "6.3.4" } } From 679ffd7120758fdae781ab5a36535c329f342788 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Tue, 29 Oct 2024 22:40:05 +0100 Subject: [PATCH 32/48] fix: some supertest breakage after update --- .../__tests__/adminAuth.unit.test.ts | 9 +++---- .../__tests__/meta.integration.test.ts | 11 ++------ .../__tests__/rateLimit.integration.test.ts | 25 ++++++++++--------- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/packages/app-api/src/middlewares/__tests__/adminAuth.unit.test.ts b/packages/app-api/src/middlewares/__tests__/adminAuth.unit.test.ts index fabca25acd..b34b7ae295 100644 --- a/packages/app-api/src/middlewares/__tests__/adminAuth.unit.test.ts +++ b/packages/app-api/src/middlewares/__tests__/adminAuth.unit.test.ts @@ -25,16 +25,13 @@ describe('adminAuth', () => { }); it('Rejects requests with no credentials', async () => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const response = await supertest(http.expressInstance).get('/test'); - expect(response.status).to.be.equal(401); + await supertest(http.expressInstance).get('/test').expect(401); }); it('Accepts requests with valid credentials', async () => { const response = await supertest(http.expressInstance) - // @ts-expect-error Supertest typings are wrong .get('/test') + // @ts-expect-error Supertest typings are wrong .set('X-Takaro-Admin-Token', config.get('adminClientSecret')); expect(response.status).to.be.equal(200); @@ -42,8 +39,8 @@ describe('adminAuth', () => { it('Rejects requests with invalid credentials', async () => { const response = await supertest(http.expressInstance) - // @ts-expect-error Supertest typings are wrong .get('/test') + // @ts-expect-error Supertest typings are wrong .set('X-Takaro-Admin-Token', 'foobar'); expect(response.status).to.be.equal(403); }); diff --git a/packages/lib-http/src/controllers/__tests__/meta.integration.test.ts b/packages/lib-http/src/controllers/__tests__/meta.integration.test.ts index 81ba06515f..4b12143752 100644 --- a/packages/lib-http/src/controllers/__tests__/meta.integration.test.ts +++ b/packages/lib-http/src/controllers/__tests__/meta.integration.test.ts @@ -1,6 +1,5 @@ import { HTTP } from '../../app.js'; import supertest from 'supertest'; -import { expect } from '@takaro/test'; describe('app', () => { let http: HTTP; @@ -14,16 +13,10 @@ describe('app', () => { }); it('Serves a health status', async () => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const response = await supertest(http.expressInstance).get('/healthz'); - expect(response.status).to.be.equal(200); + await supertest(http.expressInstance).get('/healthz').expect(200); }); it('Serves a open api spec', async () => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const response = await supertest(http.expressInstance).get('/openapi.json'); - expect(response.status).to.be.equal(200); + await supertest(http.expressInstance).get('/openapi.json').expect(200); }); }); diff --git a/packages/lib-http/src/middleware/__tests__/rateLimit.integration.test.ts b/packages/lib-http/src/middleware/__tests__/rateLimit.integration.test.ts index f78dec927b..0cc6539f44 100644 --- a/packages/lib-http/src/middleware/__tests__/rateLimit.integration.test.ts +++ b/packages/lib-http/src/middleware/__tests__/rateLimit.integration.test.ts @@ -1,6 +1,5 @@ import { Response, NextFunction, Request } from 'express'; import { Redis } from '@takaro/db'; -import { expect } from '@takaro/test'; import { Controller, UseBefore, Get } from 'routing-controllers'; import { HTTP } from '../../main.js'; import { createRateLimitMiddleware } from '../rateLimit.js'; @@ -112,17 +111,19 @@ describe('rateLimit middleware', () => { const agent = supertest(http.expressInstance); for (let i = 1; i < 5; i++) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const res = await agent.get('/low-limit').expect(200); - expect(res.header['x-ratelimit-remaining']).to.equal((5 - i).toString()); - expect(res.header['x-ratelimit-limit']).to.equal('5'); - expect(res.header['x-ratelimit-reset']).to.be.a('string'); + await agent + .get('/low-limit') + .expect(200) + .expect('x-ratelimit-remaining', (5 - i).toString()) + .expect('x-ratelimit-limit', '5') + .expect('x-ratelimit-reset', /\d+/); } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const res = await agent.get('/low-limit').expect(429); - expect(res.header['x-ratelimit-remaining']).to.equal('0'); - expect(res.header['x-ratelimit-limit']).to.equal('5'); + + agent + .get('/low-limit') + .expect(429) + .expect('x-ratelimit-remaining', '0') + .expect('x-ratelimit-limit', '5') + .expect('x-ratelimit-reset', /\d+/); }); }); From 40dd2220b48afb8971c8788352523e774e1c5efb Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Tue, 29 Oct 2024 23:01:32 +0100 Subject: [PATCH 33/48] fix: type issues with express --- packages/lib-http/src/middleware/errorHandler.ts | 2 +- packages/lib-http/src/middleware/logger.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lib-http/src/middleware/errorHandler.ts b/packages/lib-http/src/middleware/errorHandler.ts index 43bda7f56a..8d0aa86446 100644 --- a/packages/lib-http/src/middleware/errorHandler.ts +++ b/packages/lib-http/src/middleware/errorHandler.ts @@ -85,5 +85,5 @@ export async function ErrorHandler( } res.status(status).json(apiResponse({}, { error: parsedError, req, res })); - return res.end(); + res.end(); } diff --git a/packages/lib-http/src/middleware/logger.ts b/packages/lib-http/src/middleware/logger.ts index 3a4508a540..1762e0cfed 100644 --- a/packages/lib-http/src/middleware/logger.ts +++ b/packages/lib-http/src/middleware/logger.ts @@ -10,7 +10,7 @@ const log = logger('http'); * This middleware is called very early in the request lifecycle, so it's * we leverage this fact to inject the context tracking at this stage */ -export const LoggingMiddleware = ctx.wrap('HTTP', loggingMiddleware); +export const LoggingMiddleware = ctx.wrap('HTTP', loggingMiddleware) as typeof loggingMiddleware; async function loggingMiddleware(req: Request, res: Response, next: NextFunction) { if (HIDDEN_ROUTES.some((route) => req.originalUrl.startsWith(route))) { From de3535d9abc98023f4c62d9e0c282a233cb57330 Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 23:53:16 +0000 Subject: [PATCH 34/48] chore: generate api client --- .../src/generated/.openapi-generator/VERSION | 2 +- packages/lib-apiclient/src/generated/api.ts | 293 +++++++++--------- packages/lib-apiclient/src/generated/base.ts | 4 +- .../lib-apiclient/src/generated/common.ts | 4 +- .../src/generated/configuration.ts | 4 +- packages/lib-apiclient/src/generated/index.ts | 4 +- 6 files changed, 149 insertions(+), 162 deletions(-) diff --git a/packages/lib-apiclient/src/generated/.openapi-generator/VERSION b/packages/lib-apiclient/src/generated/.openapi-generator/VERSION index 09a6d30847..4bc5d61816 100644 --- a/packages/lib-apiclient/src/generated/.openapi-generator/VERSION +++ b/packages/lib-apiclient/src/generated/.openapi-generator/VERSION @@ -1 +1 @@ -7.8.0 +7.9.0 diff --git a/packages/lib-apiclient/src/generated/api.ts b/packages/lib-apiclient/src/generated/api.ts index 4800b82fc0..33e30941f3 100644 --- a/packages/lib-apiclient/src/generated/api.ts +++ b/packages/lib-apiclient/src/generated/api.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Takaro API + * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 6b9d7f6719f95491863ac106c5fca63e21c876bd + * The version of the OpenAPI document: development - 03616c08df7ea6ffdaf381a9d38509a21fc1d5ff * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -72,16 +72,16 @@ export interface ActivityInputDTO { dataType: ActivityInputDTODataTypeEnum; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof ActivityInputDTO */ - startDate?: StatsControllerGetPingStatsStartDateParameter; + startDate?: string; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof ActivityInputDTO */ - endDate?: StatsControllerGetPingStatsStartDateParameter; + endDate?: string; } export const ActivityInputDTOTimeTypeEnum = { @@ -552,16 +552,16 @@ export interface BaseGameEvent { export interface BaseStatsInputDTO { /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof BaseStatsInputDTO */ - startDate?: StatsControllerGetPingStatsStartDateParameter; + startDate?: string; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof BaseStatsInputDTO */ - endDate?: StatsControllerGetPingStatsStartDateParameter; + endDate?: string; } /** * @@ -2555,16 +2555,16 @@ export interface EventsCountInputDTO { bucketStep: EventsCountInputDTOBucketStepEnum; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof EventsCountInputDTO */ - startDate?: StatsControllerGetPingStatsStartDateParameter; + startDate?: string; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof EventsCountInputDTO */ - endDate?: StatsControllerGetPingStatsStartDateParameter; + endDate?: string; } export const EventsCountInputDTOEventNameEnum = { @@ -5014,16 +5014,16 @@ export interface LatencyInputDTO { gameServerId: string; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof LatencyInputDTO */ - startDate?: StatsControllerGetPingStatsStartDateParameter; + startDate?: string; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof LatencyInputDTO */ - endDate?: StatsControllerGetPingStatsStartDateParameter; + endDate?: string; } /** * @@ -5178,10 +5178,10 @@ export interface MessageSendInputDTO { export interface MetadataOutput { /** * - * @type {MetadataOutputServerTime} + * @type {string} * @memberof MetadataOutput */ - serverTime: MetadataOutputServerTime; + serverTime: string; /** * * @type {ErrorOutput} @@ -5207,12 +5207,6 @@ export interface MetadataOutput { */ total?: number; } -/** - * @type MetadataOutputServerTime - * @export - */ -export type MetadataOutputServerTime = string; - /** * * @export @@ -5749,16 +5743,16 @@ export interface OptionalPogStatsInputDTO { playerId?: string; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof OptionalPogStatsInputDTO */ - startDate?: StatsControllerGetPingStatsStartDateParameter; + startDate?: string; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof OptionalPogStatsInputDTO */ - endDate?: StatsControllerGetPingStatsStartDateParameter; + endDate?: string; } /** * @@ -6945,19 +6939,6 @@ export interface PlayerOutputWithRolesDTOAPI { */ meta: MetadataOutput; } -/** - * - * @export - * @interface PlayerParam - */ -export interface PlayerParam { - /** - * - * @type {string} - * @memberof PlayerParam - */ - playerId: string; -} /** * * @export @@ -7257,16 +7238,16 @@ export interface PlayersOnlineInputDTO { gameServerId?: string; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof PlayersOnlineInputDTO */ - startDate?: StatsControllerGetPingStatsStartDateParameter; + startDate?: string; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof PlayersOnlineInputDTO */ - endDate?: StatsControllerGetPingStatsStartDateParameter; + endDate?: string; } /** * @@ -7307,16 +7288,16 @@ export interface PogStatsInputDTO { playerId: string; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof PogStatsInputDTO */ - startDate?: StatsControllerGetPingStatsStartDateParameter; + startDate?: string; /** * - * @type {StatsControllerGetPingStatsStartDateParameter} + * @type {string} * @memberof PogStatsInputDTO */ - endDate?: StatsControllerGetPingStatsStartDateParameter; + endDate?: string; } /** * @@ -8651,12 +8632,6 @@ export interface ShopSearchInputAllowedRangeFilter { */ updatedAt?: NOTDOMAINSCOPEDTakaroModelDTOCreatedAt; } -/** - * @type StatsControllerGetPingStatsStartDateParameter - * @export - */ -export type StatsControllerGetPingStatsStartDateParameter = string; - /** * * @export @@ -13913,6 +13888,7 @@ export const GameServerApiAxiosParamCreator = function (configuration?: Configur * @param {string} playerId * @param {BanPlayerInputDTO} [banPlayerInputDTO] BanPlayerInputDTO * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ gameServerControllerBanPlayer: async ( @@ -14418,6 +14394,7 @@ export const GameServerApiAxiosParamCreator = function (configuration?: Configur * @summary List bans * @param {string} id * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ gameServerControllerListBans: async (id: string, options: RawAxiosRequestConfig = {}): Promise => { @@ -14728,6 +14705,7 @@ export const GameServerApiAxiosParamCreator = function (configuration?: Configur * @param {string} gameServerId * @param {string} playerId * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ gameServerControllerUnbanPlayer: async ( @@ -14864,6 +14842,7 @@ export const GameServerApiFp = function (configuration?: Configuration) { * @param {string} playerId * @param {BanPlayerInputDTO} [banPlayerInputDTO] BanPlayerInputDTO * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ async gameServerControllerBanPlayer( @@ -15210,6 +15189,7 @@ export const GameServerApiFp = function (configuration?: Configuration) { * @summary List bans * @param {string} id * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ async gameServerControllerListBans( @@ -15417,6 +15397,7 @@ export const GameServerApiFp = function (configuration?: Configuration) { * @param {string} gameServerId * @param {string} playerId * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ async gameServerControllerUnbanPlayer( @@ -15515,6 +15496,7 @@ export const GameServerApiFactory = function (configuration?: Configuration, bas * @param {string} playerId * @param {BanPlayerInputDTO} [banPlayerInputDTO] BanPlayerInputDTO * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ gameServerControllerBanPlayer( @@ -15704,6 +15686,7 @@ export const GameServerApiFactory = function (configuration?: Configuration, bas * @summary List bans * @param {string} id * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ gameServerControllerListBans(id: string, options?: RawAxiosRequestConfig): AxiosPromise { @@ -15816,6 +15799,7 @@ export const GameServerApiFactory = function (configuration?: Configuration, bas * @param {string} gameServerId * @param {string} playerId * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ gameServerControllerUnbanPlayer( @@ -15878,6 +15862,7 @@ export class GameServerApi extends BaseAPI { * @param {string} playerId * @param {BanPlayerInputDTO} [banPlayerInputDTO] BanPlayerInputDTO * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} * @memberof GameServerApi */ @@ -16094,6 +16079,7 @@ export class GameServerApi extends BaseAPI { * @summary List bans * @param {string} id * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} * @memberof GameServerApi */ @@ -16225,6 +16211,7 @@ export class GameServerApi extends BaseAPI { * @param {string} gameServerId * @param {string} playerId * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} * @memberof GameServerApi */ @@ -21937,8 +21924,8 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * @param {StatsControllerGetActivityStatsTimeTypeEnum} timeType * @param {StatsControllerGetActivityStatsDataTypeEnum} dataType * @param {string} [gameServerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -21946,8 +21933,8 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration timeType: StatsControllerGetActivityStatsTimeTypeEnum, dataType: StatsControllerGetActivityStatsDataTypeEnum, gameServerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options: RawAxiosRequestConfig = {}, ): Promise => { // verify required parameter 'timeType' is not null or undefined @@ -22040,16 +22027,16 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * @summary Get currency stats * @param {string} gameServerId * @param {string} [playerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetCurrencyStats: async ( gameServerId: string, playerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options: RawAxiosRequestConfig = {}, ): Promise => { // verify required parameter 'gameServerId' is not null or undefined @@ -22103,8 +22090,8 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * @param {string} [moduleId] * @param {string} [playerId] * @param {string} [userId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -22116,8 +22103,8 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration moduleId?: string, playerId?: string, userId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options: RawAxiosRequestConfig = {}, ): Promise => { // verify required parameter 'eventName' is not null or undefined @@ -22187,15 +22174,15 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * The roundtrip time for reachability tests between Takaro and the game server * @summary Get latency stats * @param {string} gameServerId - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetLatencyStats: async ( gameServerId: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options: RawAxiosRequestConfig = {}, ): Promise => { // verify required parameter 'gameServerId' is not null or undefined @@ -22240,16 +22227,16 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * @summary Get ping stats * @param {string} gameServerId * @param {string} playerId - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetPingStats: async ( gameServerId: string, playerId: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options: RawAxiosRequestConfig = {}, ): Promise => { // verify required parameter 'gameServerId' is not null or undefined @@ -22299,15 +22286,15 @@ export const StatsApiAxiosParamCreator = function (configuration?: Configuration * Required permissions: `READ_PLAYERS` * @summary Get player online stats * @param {string} [gameServerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetPlayerOnlineStats: async ( gameServerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options: RawAxiosRequestConfig = {}, ): Promise => { const localVarPath = `/stats/players-online`; @@ -22361,8 +22348,8 @@ export const StatsApiFp = function (configuration?: Configuration) { * @param {StatsControllerGetActivityStatsTimeTypeEnum} timeType * @param {StatsControllerGetActivityStatsDataTypeEnum} dataType * @param {string} [gameServerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -22370,8 +22357,8 @@ export const StatsApiFp = function (configuration?: Configuration) { timeType: StatsControllerGetActivityStatsTimeTypeEnum, dataType: StatsControllerGetActivityStatsDataTypeEnum, gameServerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetActivityStats( @@ -22421,16 +22408,16 @@ export const StatsApiFp = function (configuration?: Configuration) { * @summary Get currency stats * @param {string} gameServerId * @param {string} [playerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ async statsControllerGetCurrencyStats( gameServerId: string, playerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetCurrencyStats( @@ -22461,8 +22448,8 @@ export const StatsApiFp = function (configuration?: Configuration) { * @param {string} [moduleId] * @param {string} [playerId] * @param {string} [userId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -22474,8 +22461,8 @@ export const StatsApiFp = function (configuration?: Configuration) { moduleId?: string, playerId?: string, userId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetEventsCount( @@ -22505,15 +22492,15 @@ export const StatsApiFp = function (configuration?: Configuration) { * The roundtrip time for reachability tests between Takaro and the game server * @summary Get latency stats * @param {string} gameServerId - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ async statsControllerGetLatencyStats( gameServerId: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetLatencyStats( @@ -22538,16 +22525,16 @@ export const StatsApiFp = function (configuration?: Configuration) { * @summary Get ping stats * @param {string} gameServerId * @param {string} playerId - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ async statsControllerGetPingStats( gameServerId: string, playerId: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetPingStats( @@ -22572,15 +22559,15 @@ export const StatsApiFp = function (configuration?: Configuration) { * Required permissions: `READ_PLAYERS` * @summary Get player online stats * @param {string} [gameServerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ async statsControllerGetPlayerOnlineStats( gameServerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.statsControllerGetPlayerOnlineStats( @@ -22616,8 +22603,8 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * @param {StatsControllerGetActivityStatsTimeTypeEnum} timeType * @param {StatsControllerGetActivityStatsDataTypeEnum} dataType * @param {string} [gameServerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -22625,8 +22612,8 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath timeType: StatsControllerGetActivityStatsTimeTypeEnum, dataType: StatsControllerGetActivityStatsDataTypeEnum, gameServerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22653,16 +22640,16 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * @summary Get currency stats * @param {string} gameServerId * @param {string} [playerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetCurrencyStats( gameServerId: string, playerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22679,8 +22666,8 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * @param {string} [moduleId] * @param {string} [playerId] * @param {string} [userId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -22692,8 +22679,8 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath moduleId?: string, playerId?: string, userId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22715,15 +22702,15 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * The roundtrip time for reachability tests between Takaro and the game server * @summary Get latency stats * @param {string} gameServerId - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetLatencyStats( gameServerId: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22735,16 +22722,16 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * @summary Get ping stats * @param {string} gameServerId * @param {string} playerId - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetPingStats( gameServerId: string, playerId: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22755,15 +22742,15 @@ export const StatsApiFactory = function (configuration?: Configuration, basePath * Required permissions: `READ_PLAYERS` * @summary Get player online stats * @param {string} [gameServerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} */ statsControllerGetPlayerOnlineStats( gameServerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ): AxiosPromise { return localVarFp @@ -22786,8 +22773,8 @@ export class StatsApi extends BaseAPI { * @param {StatsControllerGetActivityStatsTimeTypeEnum} timeType * @param {StatsControllerGetActivityStatsDataTypeEnum} dataType * @param {string} [gameServerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi @@ -22796,8 +22783,8 @@ export class StatsApi extends BaseAPI { timeType: StatsControllerGetActivityStatsTimeTypeEnum, dataType: StatsControllerGetActivityStatsDataTypeEnum, gameServerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) @@ -22824,8 +22811,8 @@ export class StatsApi extends BaseAPI { * @summary Get currency stats * @param {string} gameServerId * @param {string} [playerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi @@ -22833,8 +22820,8 @@ export class StatsApi extends BaseAPI { public statsControllerGetCurrencyStats( gameServerId: string, playerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) @@ -22852,8 +22839,8 @@ export class StatsApi extends BaseAPI { * @param {string} [moduleId] * @param {string} [playerId] * @param {string} [userId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi @@ -22866,8 +22853,8 @@ export class StatsApi extends BaseAPI { moduleId?: string, playerId?: string, userId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) @@ -22890,16 +22877,16 @@ export class StatsApi extends BaseAPI { * The roundtrip time for reachability tests between Takaro and the game server * @summary Get latency stats * @param {string} gameServerId - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi */ public statsControllerGetLatencyStats( gameServerId: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) @@ -22912,8 +22899,8 @@ export class StatsApi extends BaseAPI { * @summary Get ping stats * @param {string} gameServerId * @param {string} playerId - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi @@ -22921,8 +22908,8 @@ export class StatsApi extends BaseAPI { public statsControllerGetPingStats( gameServerId: string, playerId: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) @@ -22934,16 +22921,16 @@ export class StatsApi extends BaseAPI { * Required permissions: `READ_PLAYERS` * @summary Get player online stats * @param {string} [gameServerId] - * @param {StatsControllerGetPingStatsStartDateParameter} [startDate] - * @param {StatsControllerGetPingStatsStartDateParameter} [endDate] + * @param {string} [startDate] + * @param {string} [endDate] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof StatsApi */ public statsControllerGetPlayerOnlineStats( gameServerId?: string, - startDate?: StatsControllerGetPingStatsStartDateParameter, - endDate?: StatsControllerGetPingStatsStartDateParameter, + startDate?: string, + endDate?: string, options?: RawAxiosRequestConfig, ) { return StatsApiFp(this.configuration) diff --git a/packages/lib-apiclient/src/generated/base.ts b/packages/lib-apiclient/src/generated/base.ts index 639f289054..7a8cbde3cd 100644 --- a/packages/lib-apiclient/src/generated/base.ts +++ b/packages/lib-apiclient/src/generated/base.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Takaro API + * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 6b9d7f6719f95491863ac106c5fca63e21c876bd + * The version of the OpenAPI document: development - 03616c08df7ea6ffdaf381a9d38509a21fc1d5ff * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/common.ts b/packages/lib-apiclient/src/generated/common.ts index 34695b52f0..509c275093 100644 --- a/packages/lib-apiclient/src/generated/common.ts +++ b/packages/lib-apiclient/src/generated/common.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Takaro API + * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 6b9d7f6719f95491863ac106c5fca63e21c876bd + * The version of the OpenAPI document: development - 03616c08df7ea6ffdaf381a9d38509a21fc1d5ff * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index 14d74b894b..6c2788c6f2 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Takaro API + * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 6b9d7f6719f95491863ac106c5fca63e21c876bd + * The version of the OpenAPI document: development - 03616c08df7ea6ffdaf381a9d38509a21fc1d5ff * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/index.ts b/packages/lib-apiclient/src/generated/index.ts index cda76e8bcc..a5479490a1 100644 --- a/packages/lib-apiclient/src/generated/index.ts +++ b/packages/lib-apiclient/src/generated/index.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Takaro API + * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 6b9d7f6719f95491863ac106c5fca63e21c876bd + * The version of the OpenAPI document: development - 03616c08df7ea6ffdaf381a9d38509a21fc1d5ff * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). From e24864bde20421f8ee94dd48b2ab0ed89acb971a Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Wed, 30 Oct 2024 15:06:24 +0100 Subject: [PATCH 35/48] feat: more perf indexes --- .../sql/20241030130613-index-for-roleId.ts | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 packages/lib-db/src/migrations/sql/20241030130613-index-for-roleId.ts diff --git a/packages/lib-db/src/migrations/sql/20241030130613-index-for-roleId.ts b/packages/lib-db/src/migrations/sql/20241030130613-index-for-roleId.ts new file mode 100644 index 0000000000..63f2734daf --- /dev/null +++ b/packages/lib-db/src/migrations/sql/20241030130613-index-for-roleId.ts @@ -0,0 +1,31 @@ +import { Knex } from 'knex'; + +export async function up(knex: Knex): Promise { + await knex.schema.alterTable('permissionOnRole', (table) => { + table.index(['roleId']); + }); + + await knex.schema.alterTable('playerOnGameServer', (table) => { + table.index(['domain', 'playerId']); + }); + + await knex.schema.alterTable('playerInventory', (table) => { + table.dropIndex(['playerId', 'domain']); + table.index(['playerId', 'domain', 'itemId']); + }); +} + +export async function down(knex: Knex): Promise { + await knex.schema.alterTable('permissionOnRole', (table) => { + table.dropIndex(['roleId']); + }); + + await knex.schema.alterTable('playerOnGameServer', (table) => { + table.dropIndex(['domain', 'playerId']); + }); + + await knex.schema.alterTable('playerInventory', (table) => { + table.dropIndex(['domain', 'playerId', 'itemId']); + table.index(['playerId', 'domain']); + }); +} From cd3775fe3e6e4d8efe6d4a374168ffb46f2b4790 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Wed, 30 Oct 2024 15:22:12 +0100 Subject: [PATCH 36/48] fix: down migration --- .../src/migrations/sql/20241030130613-index-for-roleId.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lib-db/src/migrations/sql/20241030130613-index-for-roleId.ts b/packages/lib-db/src/migrations/sql/20241030130613-index-for-roleId.ts index 63f2734daf..0214822e44 100644 --- a/packages/lib-db/src/migrations/sql/20241030130613-index-for-roleId.ts +++ b/packages/lib-db/src/migrations/sql/20241030130613-index-for-roleId.ts @@ -25,7 +25,7 @@ export async function down(knex: Knex): Promise { }); await knex.schema.alterTable('playerInventory', (table) => { - table.dropIndex(['domain', 'playerId', 'itemId']); + table.dropIndex(['playerId', 'domain', 'itemId']); table.index(['playerId', 'domain']); }); } From 0aa2b877fe1f6e9da65866b3fa14a87d292ec69f Mon Sep 17 00:00:00 2001 From: Limon <136495673+El-Limon@users.noreply.github.com> Date: Wed, 30 Oct 2024 15:57:54 +0100 Subject: [PATCH 37/48] updated chatBridge guide --- .../chatBridge_1_Takaro_settings.png | Bin 0 -> 16 bytes .../chatBridge/chatBridge_3_Discord_bot.png | Bin 0 -> 16 bytes .../chatBridge_4_DiscordChannelID.png | Bin 0 -> 16 bytes .../chatBridge_5_Module_Channelid.png | Bin 0 -> 16 bytes .../chatbridge_2_Takaro_Discord.png | Bin 0 -> 16 bytes .../images/faq/roles-module-permissions.png | Bin 82839 -> 0 bytes packages/web-docs/docs/modules/chatBridge.mdx | 58 +++++++++++++++++- 7 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 packages/web-docs/assets/images/chatBridge/chatBridge_1_Takaro_settings.png create mode 100644 packages/web-docs/assets/images/chatBridge/chatBridge_3_Discord_bot.png create mode 100644 packages/web-docs/assets/images/chatBridge/chatBridge_4_DiscordChannelID.png create mode 100644 packages/web-docs/assets/images/chatBridge/chatBridge_5_Module_Channelid.png create mode 100644 packages/web-docs/assets/images/chatBridge/chatbridge_2_Takaro_Discord.png delete mode 100644 packages/web-docs/assets/images/faq/roles-module-permissions.png diff --git a/packages/web-docs/assets/images/chatBridge/chatBridge_1_Takaro_settings.png b/packages/web-docs/assets/images/chatBridge/chatBridge_1_Takaro_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..43ee814751fffd51fe794dd53779ea60661f9454 GIT binary patch literal 16 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%0DC@Dr!a|hH|?iIB{x;gz}d~w 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

sJgMiM$0)u?;&f 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 --- -{/* END AUTO-GENERATED CONTENT */} \ No newline at end of file +{/* END AUTO-GENERATED CONTENT */} + +## Step-by-step guide + +### Step 1: Connect Discord in Global Settings +- Go to **Global Game Server Settings > Discord** +![ChatBridge Settings](../../assets/images/chatBridge/chatBridge_1_Takaro_settings.png) +- Click **Add connection** +- Complete Discord authorization to allow Takaro to: + - Access your username, avatar and banner + - Access your email address + - Know what servers you're in +![ChatBridge Settings](../../assets/images/chatBridge/chatbridge_2_Takaro_Discord.png) +### Step 2: Add Takaro Bot to Your Server +1. Click **Invite Discord bot** in the same Global Settings page +2. Select your server from the dropdown +3. Authorize the bot permissions: + - Add a bot to a server + - Create commands +![ChatBridge Settings](../../assets/images/chatBridge/chatBridge_3_Discord_bot.png) +### Step 3: Enable Your Discord Server +1. Still in Global Settings, find the "Guilds" section +2. Toggle ON your Discord server (e.g., "Limon's server") + +### Step 4: Get Discord Channel ID + +1. Go to your Discord server +2. Right-click on the channel you want to use for the chat bridge +3. Click **Copy Channel ID** at the bottom of the menu + - If you don't see this option, make sure Developer Mode is enabled in Discord settings +![ChatBridge Settings](../../assets/images/chatBridge/chatBridge_4_DiscordChannelID.png) +### Step 5: Install and Configure ChatBridge + +1. Go to your game server's modules +2. Find and click "Install" on the ChatBridge module +3. Configure the settings: + + #### User Config + + - **Send Player Connected**: Toggle to announce joins + - **Send Player Disconnected**: Toggle to announce leaves + - **Only Global Chat**: Toggle to filter private/team chat + + #### System Config + + - Enable the module + - Set up Hooks: + - **DiscordToGame**: Enable and paste your copied Discord Channel ID + - **PlayerDisconnected**: Enable to track disconnects + - **GameToDiscord**: Enable game-to-Discord chat + - **PlayerConnected**: Enable to track connects + +![ChatBridge Settings](../../assets/images/chatBridge/chatBridge_5_Module_Channelid.png) + +### Step 6: Save Configuration + +- Click "Install module" to save all settings From d41ec12fb1c1a29f72a6fde7b78550b311d683ca Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 15:05:04 +0000 Subject: [PATCH 38/48] chore: generate api client --- packages/lib-apiclient/src/generated/api.ts | 2 +- packages/lib-apiclient/src/generated/base.ts | 2 +- packages/lib-apiclient/src/generated/common.ts | 2 +- packages/lib-apiclient/src/generated/configuration.ts | 2 +- packages/lib-apiclient/src/generated/index.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/lib-apiclient/src/generated/api.ts b/packages/lib-apiclient/src/generated/api.ts index 33e30941f3..53c334cf64 100644 --- a/packages/lib-apiclient/src/generated/api.ts +++ b/packages/lib-apiclient/src/generated/api.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 03616c08df7ea6ffdaf381a9d38509a21fc1d5ff + * The version of the OpenAPI document: development - 88257859209ce424ebb5e1abf1f65b1292e5a3da * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/base.ts b/packages/lib-apiclient/src/generated/base.ts index 7a8cbde3cd..3c789e7111 100644 --- a/packages/lib-apiclient/src/generated/base.ts +++ b/packages/lib-apiclient/src/generated/base.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 03616c08df7ea6ffdaf381a9d38509a21fc1d5ff + * The version of the OpenAPI document: development - 88257859209ce424ebb5e1abf1f65b1292e5a3da * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/common.ts b/packages/lib-apiclient/src/generated/common.ts index 509c275093..fcb87e1f7f 100644 --- a/packages/lib-apiclient/src/generated/common.ts +++ b/packages/lib-apiclient/src/generated/common.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 03616c08df7ea6ffdaf381a9d38509a21fc1d5ff + * The version of the OpenAPI document: development - 88257859209ce424ebb5e1abf1f65b1292e5a3da * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index 6c2788c6f2..f293cee91c 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 03616c08df7ea6ffdaf381a9d38509a21fc1d5ff + * The version of the OpenAPI document: development - 88257859209ce424ebb5e1abf1f65b1292e5a3da * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/index.ts b/packages/lib-apiclient/src/generated/index.ts index a5479490a1..8b1886f173 100644 --- a/packages/lib-apiclient/src/generated/index.ts +++ b/packages/lib-apiclient/src/generated/index.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 03616c08df7ea6ffdaf381a9d38509a21fc1d5ff + * The version of the OpenAPI document: development - 88257859209ce424ebb5e1abf1f65b1292e5a3da * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). From 00fce9ebffbe14c909f38e8be8f48687726d551f Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:21:28 +0000 Subject: [PATCH 39/48] chore: generate api client --- packages/lib-apiclient/src/generated/api.ts | 2 +- packages/lib-apiclient/src/generated/base.ts | 2 +- packages/lib-apiclient/src/generated/common.ts | 2 +- packages/lib-apiclient/src/generated/configuration.ts | 2 +- packages/lib-apiclient/src/generated/index.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/lib-apiclient/src/generated/api.ts b/packages/lib-apiclient/src/generated/api.ts index 53c334cf64..705f7eb38c 100644 --- a/packages/lib-apiclient/src/generated/api.ts +++ b/packages/lib-apiclient/src/generated/api.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 88257859209ce424ebb5e1abf1f65b1292e5a3da + * The version of the OpenAPI document: development - f16fdcb413779170d1d8250a0a7a90b86a5d843e * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/base.ts b/packages/lib-apiclient/src/generated/base.ts index 3c789e7111..f43c0df1cb 100644 --- a/packages/lib-apiclient/src/generated/base.ts +++ b/packages/lib-apiclient/src/generated/base.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 88257859209ce424ebb5e1abf1f65b1292e5a3da + * The version of the OpenAPI document: development - f16fdcb413779170d1d8250a0a7a90b86a5d843e * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/common.ts b/packages/lib-apiclient/src/generated/common.ts index fcb87e1f7f..de92993b34 100644 --- a/packages/lib-apiclient/src/generated/common.ts +++ b/packages/lib-apiclient/src/generated/common.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 88257859209ce424ebb5e1abf1f65b1292e5a3da + * The version of the OpenAPI document: development - f16fdcb413779170d1d8250a0a7a90b86a5d843e * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index f293cee91c..2e6ac45446 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 88257859209ce424ebb5e1abf1f65b1292e5a3da + * The version of the OpenAPI document: development - f16fdcb413779170d1d8250a0a7a90b86a5d843e * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/index.ts b/packages/lib-apiclient/src/generated/index.ts index 8b1886f173..52a8b78595 100644 --- a/packages/lib-apiclient/src/generated/index.ts +++ b/packages/lib-apiclient/src/generated/index.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 88257859209ce424ebb5e1abf1f65b1292e5a3da + * The version of the OpenAPI document: development - f16fdcb413779170d1d8250a0a7a90b86a5d843e * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). From 3d00b6d140ceda335f248db2b7be997922580c49 Mon Sep 17 00:00:00 2001 From: Limon <136495673+El-Limon@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:04:43 +0100 Subject: [PATCH 40/48] built in modules docs updated with more use cases and explanations --- .../web-docs/docs/modules/economyUtils.mdx | 148 +++++++++++++++- packages/web-docs/docs/modules/geoBlock.mdx | 70 ++++++-- packages/web-docs/docs/modules/gimme.mdx | 23 ++- .../web-docs/docs/modules/highPingKicker.mdx | 100 ++++++++++- packages/web-docs/docs/modules/lottery.mdx | 107 +++++++++++- .../docs/modules/playerOnboarding.mdx | 68 +++++++- .../web-docs/docs/modules/serverMessages.mdx | 105 ++++++++++- packages/web-docs/docs/modules/teleports.mdx | 165 ++++++++++++++---- .../web-docs/docs/modules/timedShutdown.mdx | 75 +++++++- packages/web-docs/docs/modules/utils.mdx | 48 ++++- 10 files changed, 852 insertions(+), 57 deletions(-) diff --git a/packages/web-docs/docs/modules/economyUtils.mdx b/packages/web-docs/docs/modules/economyUtils.mdx index 7855a0ed61..88be17f19c 100644 --- a/packages/web-docs/docs/modules/economyUtils.mdx +++ b/packages/web-docs/docs/modules/economyUtils.mdx @@ -181,4 +181,150 @@ export function Module() { --- -{/* END AUTO-GENERATED CONTENT */} \ No newline at end of file +{/* END AUTO-GENERATED CONTENT */} + +## Features +- Balance checking and transfers +- Administrative currency controls +- Automated kill rewards +- Shop integration +- Currency leaderboard + +## Permissions + +### ECONOMY_UTILS_MANAGE_CURRENCY +- Allows granting and revoking currency +- Typically for admins/moderators + +### ZOMBIE_KILL_REWARD_OVERRIDE +- Overrides default kill reward amount +- Can set different amounts per role +- Count value determines reward amount + +## Variables + +### Currency Related +- `lastZombieKillReward` + - Tracks last reward distribution time + - Used by automatic reward system + - Scoped to gameserver and module + +### Shop Related +- `lottery_tickets_bought` + - Stores ticket quantity + - Format: `{ "amount": number }` + - Scoped to player, gameserver, and module + +### Transfer Related +- `confirmTransfer` + - Stores pending transfer details + - Temporary storage for large transfers + +## Automatic Rewards + +### Kill Rewards System +- Auto-processes every 5 minutes +- Awards currency for entity kills +- Default amount configurable +- Role-based override example: + ``` + Default Player: 1 coin per kill + VIP Role: 3 coins per kill + Elite Role: 5 coins per kill + ``` + +### Setting Up Role Rewards +1. Navigate to Roles +2. Enable ZOMBIE_KILL_REWARD_OVERRIDE +3. Set count value for reward amount +4. Assign role to players + +## Commands & Usage Examples + +### Basic Currency Commands +``` +# Check your balance +/balance +> balance: 500 coins + +# View richest players +/topcurrency +> Richest players: +> 1. PlayerOne - 10000 coins +> 2. PlayerTwo - 8500 coins +> [...] +``` + +### Transfer System +``` +# Simple transfer +/transfer John 100 +> You successfully transferred 100 coins to John +> (John receives: You received 100 coins from PlayerName) + +# Large transfer requiring confirmation +/transfer Jane 1000 +> You are about to send 1000 coins to Jane. (Please confirm by typing /confirmtransfer) +/confirmtransfer +> You successfully transferred 1000 coins to Jane +``` + +### Shop System +``` +# Browse shop +/shop +> Available items: +> 1. Diamond Sword - 500 coins +> 2. Golden Apple - 100 coins +> [...] + +# View item details +/shop 1 2 +> Golden Apple - 100 coins +> Restores health instantly +> Type '/shop 1 2 buy' to purchase + +# Purchase item +/shop 1 2 buy +> You have purchased Golden Apple for 100 coins + +# Claim purchased items +/claim +> Claimed all pending orders: 3 items +``` + +### Admin Commands +``` +# Grant currency +/grantcurrency PlayerName 500 +> You successfully granted 500 coins to PlayerName + +# Remove currency +/revokecurrency PlayerName 200 +> You successfully revoked 200 coins from PlayerName's balance +``` + + +## Best Practices + +### Economy Management +- Set reasonable transfer confirmation thresholds +- Monitor currency circulation +- Adjust reward values based on server activity + +### Role Configuration +- Create clear reward tiers +- Balance rewards across different roles +- Consider server economy when setting values +## Troubleshooting +1. Transfer Failed + - Check sender's balance + - Verify player names + - Confirm if confirmation needed + - Check for pending transfer variable + +2. Rewards Not Processing + - Verify kill events recording + - Check role permissions + - Confirm cron job running + - Check lastZombieKillReward timestamp diff --git a/packages/web-docs/docs/modules/geoBlock.mdx b/packages/web-docs/docs/modules/geoBlock.mdx index abf3379597..77255ceb49 100644 --- a/packages/web-docs/docs/modules/geoBlock.mdx +++ b/packages/web-docs/docs/modules/geoBlock.mdx @@ -45,7 +45,43 @@ export function Module() { --- {/* END AUTO-GENERATED CONTENT */} -# How to Install and Configure the Geoblock Module + +## Core Functionality +- Country-based access control +- Configurable action settings (kick or ban) +- Customizable ban duration +- Immunity system through role permissions +- Custom messages for blocked players + +### Operation Modes +- **Allow Mode**: Only players from specified countries can join +- **Deny Mode**: Players from specified countries are blocked from joining + +## Configuration Options + +### Essential Settings +1. **Mode Selection** + - Allow: Whitelist mode - only listed countries can join + - Deny: Blacklist mode - listed countries are blocked + +2. **Action Settings** + - Ban (default: enabled) + - Ban Duration (default: 24 hours) + - Custom Message (default: "Your IP address is banned.") + +3. **Country List** + - Comprehensive list of countries to allow/deny + - Countries are selected using standard two-letter country codes + - Multiple countries can be selected simultaneously + +## Permissions + +### GeoBlock Immunity +- Permission Name: `GEOBLOCK_IMMUNITY` +- Description: Players with this permission will not be affected by GeoBlock restrictions +- Cannot have count value (boolean permission) + +## How to Install and Configure the Geoblock Module This guide explains how to install the Geoblock module, select countries to ban, and create roles to grant immunity to players from banned countries. Follow these steps to effectively manage your game server's access control. You can find more info related to built-in modules in [built-in modules](../modules/overview.mdx). @@ -58,85 +94,85 @@ This guide explains how to install the Geoblock module, select countries to ban, allowFullScreen /> -## Install the module to your game server +### Install the module to your game server -### Step 1: Navigate to the Modules Section +#### Step 1: Navigate to the Modules Section Go to the main menu and find the 'Modules' section in your game server's administration interface. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyu8vexg000s356obenz1bji-annotated.png) -### Step 2: Start the Installation +#### Step 2: Start the Installation Click on the 'Install New Module' button and search for the 'Geoblock' module in the list of available modules. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyu9m3uc0019356o4qyrrfz4-annotated.png) -### Step 3: Select Countries to Block +##$# Step 3: Select Countries to Block During the installation process, you'll be prompted to select the countries you want to block. Use the provided interface to choose the countries from the list. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyu8w3u5000v356ollrkog5f-annotated.png) -### Step 4: Install the Geoblock Module +#$## Step 4: Install the Geoblock Module After selecting the countries, click the 'Install' button to complete the installation of the Geoblock module. ![](https://d1kbuqctacnbc1.cloudfront.net/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyrqudxg000i033p1tf3bd8h-annotated.png) -## Assign the permission to the right role +### Assign the permission to the right role -### Step 5: Navigate to the Roles Section +#### Step 5: Navigate to the Roles Section After installing the Geoblock module, go back to the main menu and find the 'Roles' section in the administration interface. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyu8wfq1000w356oq30mzzv2-annotated.png) -### Step 6: Create a New Role +#### Step 6: Create a New Role Click the 'Create New Role' button to start the process of creating a role that will grant ban immunity. ![](https://d1kbuqctacnbc1.cloudfront.net/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyrquk53000k033pdmokia11-annotated.png) -### Step 7: Name Your New Role +#### Step 7: Name Your New Role Give your new role a recognizable name that indicates it grants immunity, such as 'Ban Immunity'. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyu8xfyq000y356ocm8nwgiy-annotated.png) -### Step 8: Confirm Role Name +#### Step 8: Confirm Role Name After entering the name, click the 'Confirm' button to save the new role. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyu8xi2s000z356omzq4gqax-annotated.png) -## Assign the role to the right player +### Assign the role to the right player -### Step 9: Go to Players Section +#### Step 9: Go to Players Section Navigate to the 'Players' section from the main menu to assign the new role to specific players. ![](https://d1kbuqctacnbc1.cloudfront.net/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyrquw3q000p033pepixxr01-annotated.png) -### Step 10: Select Player for Role Assignment +#### Step 10: Select Player for Role Assignment Find and select the player you want to assign the new role to from the list of registered players. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyu94gla0013356oopo1k4ik-annotated.png) -### Step 11: Assign the newly created role +#### Step 11: Assign the newly created role Assign the newly created role to the selected player by checking the role in the player's profile. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyu94jia0014356o8gg38rd2-annotated.png) -### Step 12: Decide Role Activation Scope +#### Step 12: Decide Role Activation Scope Choose whether to activate this role across all game servers or specific individual game servers by configuring the settings as needed. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyrqtuvs0016jo0cdutlvhl6/clyu97xk80017356oi0tv43q0-annotated.png) -### Step 13: Save Changes +#### Step 13: Save Changes Click the 'Save changes' button to apply all the configurations and finalize the process. diff --git a/packages/web-docs/docs/modules/gimme.mdx b/packages/web-docs/docs/modules/gimme.mdx index 69ff9210ad..834266facb 100644 --- a/packages/web-docs/docs/modules/gimme.mdx +++ b/packages/web-docs/docs/modules/gimme.mdx @@ -38,4 +38,25 @@ export function Module() { --- -{/* END AUTO-GENERATED CONTENT */} \ No newline at end of file +{/* END AUTO-GENERATED CONTENT */} + +## Key Features +- Randomly selects and distributes items from a configurable list +- Can execute random server commands from a predefined list +- Single command usage: `/gimme` + +## How It Works +1. When a player uses `/gimme`, the module: + - Randomly selects between giving an item and executing a command +2. Notifies the player of what they received + +## Setup Steps +1. Install the module from the selected game server +2. Configure item and command lists +3. Save configuration +4. Players can immediately start using `/gimme` + +## Best Practices +- Balance reward values to maintain game economy + +This module requires no special permissions and is accessible to all players by default. \ No newline at end of file diff --git a/packages/web-docs/docs/modules/highPingKicker.mdx b/packages/web-docs/docs/modules/highPingKicker.mdx index b6e68fb8c2..9c192fb20c 100644 --- a/packages/web-docs/docs/modules/highPingKicker.mdx +++ b/packages/web-docs/docs/modules/highPingKicker.mdx @@ -36,4 +36,102 @@ export function Module() { --- -{/* END AUTO-GENERATED CONTENT */} \ No newline at end of file +{/* END AUTO-GENERATED CONTENT */} + +## Key Features + +- Automatic ping monitoring +- Configurable ping thresholds +- Warning system before kicks +- Customizable number of warnings +- Player immunity options through permissions + +## Configuration Options + +### 1. Ping Threshold + +- Default value: 200ms +- Purpose: Defines the maximum acceptable ping value +- When a player's ping exceeds this threshold, they begin receiving warnings +- Can be adjusted based on your server's requirements and geographical location + +### 2. Warnings Before Kick + +- Default value: 3 warnings +- Purpose: Determines how many warnings a player receives before being kicked +- Provides players with opportunities to resolve connection issues +- Each warning is tracked individually per player + +## How It Works + +The module operates on a 5-minute cycle (configured via cron job: `*/5 * * * *`) and performs the following steps: + +1. **Monitoring**: Checks all online players' ping values +2. **Warning System**: + - If a player's ping exceeds the threshold, they receive a warning + - Warnings are tracked using Takaro's variable system + - Each subsequent high ping check increments the warning count +3. **Kick Action**: + - When warnings reach the configured limit, the player is kicked + - Kick message includes their ping value for reference + - Warning count is reset after a kick + +Example warning message: +`Server is shutting down in 5 minutes for daily maintenance. We'll be back online in ~10 minutes. Please find a safe spot!` + +## Implementation Details + +The module uses Takaro's variable system to track warnings with the key `highPingKicker:warnings`. This ensures persistence across server restarts and allows for accurate warning tracking. + +### Warning Process: + +1. First high ping detection: Creates warning variable +2. Subsequent detections: Increments warning count +3. Final warning: Executes kick and resets counter + +### Permissions + +The module includes one permission: + +- `GEOBLOCK_IMMUNITY`: Players with this permission will not be kicked regardless of their ping + - Useful for administrators or trusted players + - Can be assigned through Takaro's role system + +### Installation + +1. Navigate to your server's Modules section +2. Select "Install New Module" +3. Find and select "highPingKicker" +4. Configure the desired ping threshold and warning count +5. Save and activate the module + +## Best Practices + +1. **Initial Setup**: + - Start with default values (200ms ping threshold, 3 warnings) + - Monitor player feedback and server logs + - Adjust values based on your community's needs +2. **Threshold Configuration**: + - Consider your server's geographical location + - Account for typical ping ranges in your target regions + - Set thresholds that balance performance with accessibility +3. **Warning Management**: + - Use enough warnings to allow for temporary connection issues + - Keep warning count reasonable to maintain server performance + - Consider time between checks (default 5 minutes) + +## Troubleshooting + +Common issues and solutions: + +1. **Too Many Kicks**: + - Increase ping threshold + - Add more warnings before kick + - Review server performance metrics +2. **Ineffective Management**: + - Decrease ping threshold + - Reduce warning count + - Decrease check interval +3. **False Positives**: + - Grant immunity to affected players + - Adjust threshold based on time of day \ No newline at end of file diff --git a/packages/web-docs/docs/modules/lottery.mdx b/packages/web-docs/docs/modules/lottery.mdx index 356b25a9a8..a63c75ecc0 100644 --- a/packages/web-docs/docs/modules/lottery.mdx +++ b/packages/web-docs/docs/modules/lottery.mdx @@ -79,4 +79,109 @@ export function Module() { --- -{/* END AUTO-GENERATED CONTENT */} \ No newline at end of file +{/* END AUTO-GENERATED CONTENT */} + +## Overview + +The lottery system works by: + +- Players can purchase tickets using server currency +- A scheduled draw determines winners automatically +- Winners receive a prize pool based on ticket sales +- Configurable profit margin for the server +- Daily automated draws + +## Commands + +|Command|Description|Arguments| +|---|---|---| +|`/buyTicket`|Purchase lottery tickets|`amount`: Number of tickets to buy| +|`/viewTickets`|View your currently held tickets|None| +|`/nextDraw`|Check when the next lottery draw will occur|None| + +## Permissions + +The module includes two main permissions that can be assigned to roles: + +- **LOTTERY_BUY**: Allows players to purchase lottery tickets +- **LOTTERY_VIEW_TICKETS**: Allows players to view their currently held tickets + +## Configuration + +### Module Settings + +|Setting|Description|Default| +|---|---|---| +|`profitMargin`|Percentage of ticket sales kept by the server (0-1)|0.1 (10%)| + +### System Configuration + +The lottery draw is scheduled using a cron job that runs at `0 0 * * *` (midnight every day). + +## How It Works + +1. **Ticket Purchase**: + - Players use the `/buyTicket` command to purchase tickets + - Each ticket costs a configurable amount of currency + - Players can purchase multiple tickets at once + - Tickets are tracked per player until the next draw +2. **Prize Pool**: + - Total prize pool = (Total ticket sales) * (1 - profit margin) + - Server keeps the profit margin percentage + - The remaining amount goes to the winner +3. **Draw Process**: + - Occurs automatically at configured time + - One winner is randomly selected from all ticket holders + - More tickets = higher chance of winning + - Prize is automatically distributed to winner + - All tickets are cleared after each draw +4. **Safeguards**: + - Lottery cancels if only one player bought tickets + - Players receive refunds if lottery is cancelled + - Server announces winner and prize amount to all players + +## Setup Guide + +1. **Install the Module**: + - Navigate to your server's Modules section + - Find "lottery" in the module list + - Click Install + - Configure the profit margin as desired +2. **Configure Permissions**: + - Go to Roles section + - Assign LOTTERY_BUY and LOTTERY_VIEW_TICKETS permissions to appropriate roles + - Set any cost requirements for permissions if desired +3. **Verify Installation**: + - Check that commands are working using `/help lottery` + - Ensure draw schedule is active by using `/nextDraw` + - Test ticket purchase with `/buyTicket 1` + +## Best Practices + +1. **Economy Balance**: + - Set appropriate ticket costs based on your server's economy + - Adjust profit margin to control prize pool sizes + - Monitor ticket sales and adjust parameters as needed +2. **Player Communication**: + - Announce lottery events in advance + - Use server messages to remind players about upcoming draws + - Celebrate winners to encourage participation +3. **Permission Management**: + - Consider creating specific lottery roles + - Use permission costs to prevent abuse + - Monitor for unusual buying patterns + +## Troubleshooting + + +**Players can't buy tickets**: + - Verify LOTTERY_BUY permission is assigned + - Check if player has sufficient currency + - Ensure economy system is enabled + +## Notes + +- Tickets do not persist between draws +- Players must be online to receive win notifications +- The module requires an active economy system +- All transactions are logged for administrative review \ No newline at end of file diff --git a/packages/web-docs/docs/modules/playerOnboarding.mdx b/packages/web-docs/docs/modules/playerOnboarding.mdx index a2dd3bc608..37364c04c5 100644 --- a/packages/web-docs/docs/modules/playerOnboarding.mdx +++ b/packages/web-docs/docs/modules/playerOnboarding.mdx @@ -44,4 +44,70 @@ export function Module() { --- -{/* END AUTO-GENERATED CONTENT */} \ No newline at end of file +{/* END AUTO-GENERATED CONTENT */} + +## Features + +### Welcome Messages + +- Automatically triggers when a player connects to the server +- Supports player name variables using {player} placeholder +- Customizable message content +- Helps create a welcoming atmosphere for new players + +### Starter Kit System + +- Players can claim a starter kit using the `/starterkit` command +- One-time use per player per server +- Configurable item list with support for: + - Item quantities + - Item quality levels + - Multiple items per kit + +## Configuration + +### Message Configuration + +- **Message**: Customize the welcome message that players receive when joining +- Default message: "Welcome {player} to the server!" +- Use {player} to include the player's name in the message + +### Starter Kit Configuration + +- **Items**: Configure a list of items to be given to players +- Each item entry supports: + - Item name (must match exact game item ID) + - Amount + - Quality level (where applicable) + - Usage percentage +## Commands + +### /starterkit + +- **Usage**: `/starterkit` +- **Description**: Claims the starter kit items +- **Limitations**: + - Can only be used once per player per server + - Requires starter kit items to be configured +- **Response Messages**: + - Success: "Gave [X] items, enjoy!" + - Already claimed: "You already used starterkit on this server" + - No items configured: "No starter kit items configured. Please ask your server administrator to configure this." + +## Variables + +The module uses Takaro's variable system to track starter kit claims: +- Creates a variable with key 't_starterkit_lock' when a player claims their kit +- Checks this variable to prevent multiple claims +- Variables are server-specific, allowing players to claim starter kits on different servers + +## Best Practices + +1. **Welcome Message** + - Keep messages concise and informative + - Include essential server information or rules + - Use the {player} placeholder to personalize the message +2. **Starter Kit Items** + - Balance items to help new players without making them overpowered + - Consider your server's economy when selecting items + diff --git a/packages/web-docs/docs/modules/serverMessages.mdx b/packages/web-docs/docs/modules/serverMessages.mdx index 49faf5752d..2062b20e88 100644 --- a/packages/web-docs/docs/modules/serverMessages.mdx +++ b/packages/web-docs/docs/modules/serverMessages.mdx @@ -36,4 +36,107 @@ export function Module() { --- -{/* END AUTO-GENERATED CONTENT */} \ No newline at end of file +{/* END AUTO-GENERATED CONTENT */} + +## Overview + +The Server Messages module sends automated messages to players on your server at regular intervals. Messages are broadcast in sequential order from your configured list. + +## Configuration + +### Basic Setup + +1. Install the module from your server's Modules section +2. Configure at least one message in the messages array +3. Messages must be between 5 and 1024 characters + +### Message Configuration + +```json +{ + "messages": [ + "Welcome to our server! Type /help for commands", // First message + "Join our Discord community: discord.gg/example", // Second message + "Vote daily for rewards at /vote", // Third message + "Check out our shop with /shop" // Fourth message, then cycles back to first + ] +} +``` + +### Scheduling + +- Default: Every 30 minutes (`*/30 * * * *`) +- Common schedules: + ``` + */30 * * * * Every 30 minutes + 0 * * * * Every hour + 0 */4 * * * Every 4 hours + 0 0 * * * Daily at midnight + 0 12 * * * Daily at noon + ``` + +## How It Works + +1. When the cron job triggers (default: every 30 minutes) +2. The next message in sequence is selected from your list +3. After reaching the last message, it starts again from the beginning +4. Example sequence: + ``` + 12:00 - First message + 12:30 - Second message + 13:00 - Third message + 13:30 - Fourth message + 14:00 - First message (cycle repeats) + ``` + +## Best Practices + +### Effective Message Examples + +**Server Rules & Guidelines (Ordered by Priority)** + ``` + PvP is only allowed in designated zones. Type /pvp for info + Protect your base! Use /claim to secure your territory + Raiding is allowed, but no griefing. See /rules + Be respectful in chat. Toxicity = ban + ``` +**Game Tips & Features (Ordered by Progression)** + ``` + New? Type /help to see all commands + Ready to trade? Visit /shop for items + Want a challenge? Join events with /events + Veteran player? Help newbies for rewards! + ``` + +**Community Engagement (Ordered by Importance)** + ``` + Join our Discord for important updates: discord.gg/example + Support us by voting at /vote - daily rewards! + Follow announcements at @serverName + Questions? Our staff team is here to help + ``` + +### Optimization Tips + +1. **Message Order** + - Arrange messages by priority or logical sequence + - Put most important messages first + - Group related messages together + - Consider time between messages when ordering + +2. **Message Categories** + - Start with essential information + - Follow with gameplay tips + - End with community/social messages + - Keep consistent themes together + +3. **Timing** + - Match interval to message count + - Consider peak player times + - Longer intervals for important messages + - Shorter intervals for tips/reminders + +4. **Format** + - Keep messages concise + - Include clear calls to action + - Specify commands when relevant \ No newline at end of file diff --git a/packages/web-docs/docs/modules/teleports.mdx b/packages/web-docs/docs/modules/teleports.mdx index 44225d71d6..25a4b0106f 100644 --- a/packages/web-docs/docs/modules/teleports.mdx +++ b/packages/web-docs/docs/modules/teleports.mdx @@ -183,7 +183,108 @@ export function Module() { --- {/* END AUTO-GENERATED CONTENT */} -# How to add teleports module to your game server +## Features + +- Personal teleport points +- Public/private teleport management +- Waypoint system +- Configurable cooldowns +- Permission-based access control + +## Configuration Options + +When installing the module, administrators can configure: + +- **Timeout**: The cooldown period between teleports (in seconds) +- **Allow Public Teleports**: Toggle whether players can create public teleport points +- **Command Costs**: Set currency costs for teleport commands + +## Permissions System + +### Core Permissions + +1. **Use Teleports** (`TELEPORTS_USE`) + - Allows basic teleport functionality + - Can be configured with a count limit + - Required for using `/tp` and `/tplist` commands +2. **Create Public Teleports** (`TELEPORTS_CREATE_PUBLIC`) + - Allows creation of public teleport points + - Can be configured with a count limit + - Required for `/setpublic` command +3. **Manage Waypoints** (`TELEPORTS_MANAGE_WAYPOINTS`) + - Administrative permission for waypoint management + - Required for `/setwaypoint` and `/deletewaypoint` commands + - No count limit applicable + +### Setting Up Role Permissions + +## Basic Player Access + +1. Edit the default "Player" role +2. Enable "Use Teleports" permission +3. Set maximum number of teleports (recommended: 3-5) +4. Save changes + +## VIP/Donor Setup + +1. Create a new role (e.g., "VIP") +2. Enable both "Use Teleports" and "Create Public Teleports" +3. Set higher teleport limits (recommended: 10-15) +4. Assign to VIP players + +## Admin Configuration + +1. Edit admin role or create dedicated teleport admin role +2. Enable all teleport permissions +3. Enable "Manage Waypoints" permission +4. No need to set count limits + +## Command examples + +| Command | Description | Example | +| ------------------------ | ---------------------------------- | ----------------------- | +| `/tp ` | Teleport to a saved location | `/tp home` | +| `/tplist` | List all available teleport points | `/tplist` | +| `/settp ` | Create a new teleport point | `/settp base` | +| `/deletetp ` | Remove a teleport point | `/deletetp base` | +| `/setpublic ` | Make a teleport point public | `/setpublic shop` | +| `/setprivate ` | Make a teleport point private | `/setprivate base` | +| `/setwaypoint ` | Create a waypoint (admin only) | `/setwaypoint spawn` | +| `/deletewaypoint ` | Delete a waypoint (admin only) | `/deletewaypoint spawn` | +| `/waypoints` | List all available waypoints | `/waypoints` | +| | | | + + +## Best Practices + +1. **Permission Hierarchy** + - Start with basic permissions for all players + - Add additional capabilities for trusted/VIP players + - Reserve waypoint management for administrators +2. **Teleport Limits** + - Set reasonable limits based on server size + - Consider increasing limits for loyal players + - Monitor usage patterns and adjust as needed +3. **Public Teleports** + - Consider restricting public teleport creation to trusted players + - Monitor public teleport locations for abuse + - Use waypoints for essential server locations + +## Troubleshooting + +- If players cannot teleport, check their permission setup +- Verify timeout settings if teleports seem unresponsive +- Check currency requirements if teleports fail +- Ensure waypoint permissions are properly configured for administrators + +## Security Considerations + +- Regularly review public teleport locations +- Monitor for teleport abuse or exploitation +- Consider implementing stricter timeout periods in PvP areas +- Use waypoints instead of public teleports for crucial locations like traders + +## How to add teleports module to your game server This guide walks you through the process of integrating the Teleports module into your game servers. You'll learn how to set up teleport permissions for different player roles, create custom teleport roles for enhanced privileges, and manage teleport-related features effectively. @@ -196,85 +297,85 @@ This guide walks you through the process of integrating the Teleports module int allowFullScreen /> -## Install the module to your game server +### step-by-step guide to install the module to your game server -### Step 1: Navigate to game servers +#### Step 1: Navigate to game servers ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrki4hl00e8356vnaco8xn0-annotated.png) -### Step 2: Select the game server you want the module to be installed on +#### Step 2: Select the game server you want the module to be installed on ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrf44cb002d356vzrgud1i3-annotated.png) -### Step 3: Navigate to Modules of the selected game server +#### Step 3: Navigate to Modules of the selected game server ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyr6qier0009356vyv6luu30-annotated.png) -### Step 4: Click the install button +#### Step 4: Click the install button ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrkmfi000eb356vgb4jcsjl-annotated.png) -### Step 5: This opens the module config +#### Step 5: This opens the module config You will see a list of settings that you can configure. You will also find the list of commands that are part of this module. $tplist - Lists all your set locations. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrfgxmx0030356vcsdn6949-annotated.png) -### Step 6: $teleportwaypoint command +#### Step 6: $teleportwaypoint command The module will install aliases for this command corresponding to the waypoint names. The $teleportwaypoint command is a base command that won't be used directly. Instead, the module will create custom commands for each waypoint name you set up. This allows players to teleport to specific locations easily. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrfh0ch0031356veuthxwdw-annotated.png) -### Step 7: Select the amount of currency one teleport command costs +#### Step 7: Select the amount of currency one teleport command costs $teleport command teleports you to one of your set locations. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrkn7bf00ee356vec8w2jac-annotated.png) -### Step 8: $setwaypoint creates a new waypoint +#### Step 8: $setwaypoint creates a new waypoint ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrfh2zj0032356vxpdnfcao-annotated.png) -### Step 9: $settp sets a location to teleport to +#### Step 9: $settp sets a location to teleport to ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrfh6ci0033356v20yp6mlv-annotated.png) -### Step 10: $setpublic sets a teleport to be public, allowing other players to teleport to it +#### Step 10: $setpublic sets a teleport to be public, allowing other players to teleport to it ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrfflru002w356vejuvlnyy-annotated.png) -### Step 11: $setprivate sets a teleport to be private, only the teleport owner can teleport to it +#### Step 11: $setprivate sets a teleport to be private, only the teleport owner can teleport to it ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrfhf6t0034356v8zo9l6ei-annotated.png) -### Step 12: $listwaypoints lists all waypoints +#### Step 12: $listwaypoints lists all waypoints ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrffrkd002y356vehfrrtgl-annotated.png) -### Step 13: $deletewaypoint deletes a waypoint +#### Step 13: $deletewaypoint deletes a waypoint ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrfhzvi0037356vdm1sez5x-annotated.png) -### Step 14: Click Install module button when you are finished with the config +#### Step 14: Click Install module button when you are finished with the config ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrkndxi00ef356vjx98hsqg-annotated.png) -## Assign the permission to the right role +### Assign the permission to the right role -### Step 15: Now you need to assign the permission to the right role +#### Step 15: Now you need to assign the permission to the right role Now that you've installed the Teleports module, the next step is to set up the appropriate permissions. Navigate to the "Roles" section in the global navigation to begin assigning teleport-related permissions to player roles. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrenji3001q356vs5b8uta8-annotated.png) -### Step 16: Now you need to assign the permission to the right role +#### Step 16: Now you need to assign the permission to the right role You can decide to add this permission to the standard Player role, or you can create a new role dedicated for teleports. In this guide, we are going to do both. We will first start with the Player role. The Player role is the role that all players will have when they join your game server. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrejj8w0011356vg8t94k5p-annotated.png) -### Step 17: Teleports Module Permissions Overview +#### Step 17: Teleports Module Permissions Overview Create Public Teleports: Allows players to create teleport points accessible to others. Use Teleports: Enables players to use existing teleport points. Manage Waypoints: Permits creating, modifying, and deleting personal or shared waypoints. @@ -284,55 +385,55 @@ Toggle the switch to the right (on position). Set a cost in the "Amount" field i ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyre55ge000x356vqh7cq87h-annotated.png) -### Step 18: Click Save changes button +#### Step 18: Click Save changes button ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrknird00eg356vsmu74np2-annotated.png) -### Step 19: Add a custom role for Teleports +#### Step 19: Add a custom role for Teleports Creating a dedicated teleport role allows for more flexible permission management. This is useful when you want to give enhanced teleport capabilities to certain players without changing permissions for all users. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrknlij00eh356v8bmmu32u-annotated.png) -### Step 20: Give your new role a recognizable name +#### Step 20: Give your new role a recognizable name ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrew0c9001v356v6qdqb47a-annotated.png) -### Step 21: Configure teleport permissions for the new role +#### Step 21: Configure teleport permissions for the new role You'll see the same options as in Step 17: Create Public Teleports Use Teleports Manage Waypoints ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyreielj0010356vdutepys1-annotated.png) -## Assign the role to the right player +### Assign the role to the right player -### Step 22: Go to Players to assign the right role +#### Step 22: Go to Players to assign the right role ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrknq0d00ei356vbuve02c5-annotated.png) -### Step 23: Navigate to the player you want to assign the special role to +#### Step 23: Navigate to the player you want to assign the special role to ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrepqj1001u356v5fepto4w-annotated.png) -### Step 24: Click Assign role button +#### Step 24: Click Assign role button ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrf8n5a002e356vmyn5b9ee-annotated.png) -### Step 25: Select the right role +#### Step 25: Select the right role ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrknuo400ej356vbbjkv8uh-annotated.png) -### Step 26: Choose extra teleports from the list +#### Step 26: Choose extra teleports from the list ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrf8wcs002f356vacwkzk01-annotated.png) -### Step 27: Choose your preferred game server +#### Step 27: Choose your preferred game server Choose to activate the teleport role on individual game servers or globally across all servers, allowing flexible permission management based on your game's structure and needs. ![](https://layerpath-recording-prod.s3-accelerate.amazonaws.com/clyr0pthc0008ju0cpgk6zvy7/clyr4po6b0065l90ch2iwjbq3/clyrfj6jk0039356vwo9846tm-annotated.png) -### Step 28: Click Save changes button +#### Step 28: Click Save changes button You made it to the end! diff --git a/packages/web-docs/docs/modules/timedShutdown.mdx b/packages/web-docs/docs/modules/timedShutdown.mdx index f94a73bba5..e23f3ea6d5 100644 --- a/packages/web-docs/docs/modules/timedShutdown.mdx +++ b/packages/web-docs/docs/modules/timedShutdown.mdx @@ -41,4 +41,77 @@ export function Module() { --- -{/* END AUTO-GENERATED CONTENT */} \ No newline at end of file +{/* END AUTO-GENERATED CONTENT */} + +The Timed Shutdown module provides automated server shutdown functionality with configurable warning messages to players. This guide explains how to configure and use the module effectively. + +## Overview + +The Timed Shutdown module performs two main functions: + +1. Sends a warning message to all players before shutdown +2. Automatically shuts down the server at a specified time + +## Configuration + +### Warning Message + +- **Setting**: `warningMessage` +- **Default**: "Server is shutting down in 5 minutes!" +- **Description**: The message that will be broadcast to all players 5 minutes before shutdown +- **Length Limits**: 1-1024 characters + +### Timing + +The module operates by default on a fixed schedule: + +- **Warning Time**: 3:25 AM (server time) +- **Shutdown Time**: 3:30 AM (server time) + +These times are set using cron expressions: + +- Warning message: `3 25 * * *` +- Server shutdown: `3 30 * * *` + +You can change the cron jobs to your liking. + +## Installation Steps + +1. Navigate to your game server's Modules section +2. Click "Install New Module" +3. Search for "timedShutdown" +4. Configure your warning message +5. Click Install + +## Best Practices + +### Warning Message Format + +Consider including: + +- Specific time remaining until shutdown +- Reason for shutdown (e.g., maintenance, daily restart) +- When the server will be back online + +Example message: + +`Server is shutting down in 5 minutes for daily maintenance. We'll be back online in ~10 minutes. Please find a safe spot!` + +### Server Time Considerations + +- Ensure your server's time zone is correctly set +- Choose shutdown times during low-activity periods +- Account for regular maintenance windows + +## Troublesh ooting + +Common issues and solutions: + +1. **Shutdown not occurring** + - Verify server time matches expected shutdown time + - Check module installation status + - Review server logs for errors +2. **Warning message not displaying** + - Confirm message is properly configured + - Check chat/message system functionality + - Verify module permissions \ No newline at end of file diff --git a/packages/web-docs/docs/modules/utils.mdx b/packages/web-docs/docs/modules/utils.mdx index 0684f3cb4d..6970e60fea 100644 --- a/packages/web-docs/docs/modules/utils.mdx +++ b/packages/web-docs/docs/modules/utils.mdx @@ -53,4 +53,50 @@ export function Module() { --- -{/* END AUTO-GENERATED CONTENT */} \ No newline at end of file +{/* END AUTO-GENERATED CONTENT */} + +## Features + +### Commands + +## 1. Ping Command + +- **Trigger**: `/ping` +- **Description**: A simple command that replies with "Pong!". This command is useful for: + - Testing if the server connection is working + - Verifying command functionality + - Checking player permissions + - Basic latency testing + +## 2. Help Command + +- **Trigger**: `/help [command]` +- **Description**: Provides information about available commands and their usage +- **Arguments**: + - `command` (optional): The specific command to get help for + - Default: Shows all available commands if no specific command is specified + +### Usage Examples + + +`/ping > Response: "Pong!" /help > Response: Lists all available commands` +`/help ping > Response: Shows detailed help for the ping command` + +## Technical Details + +### Module Configuration + +The Utils module has a minimal configuration schema with no required settings, making it simple to deploy and maintain. + +### Permissions + +The Utils module's commands are typically available to all players by default, as they provide essential functionality for server interaction. + +## Best Practices + +1. **Server Setup** + - Install the Utils module first when setting up a new server + - Keep it enabled to ensure players can always access basic commands +3. **Troubleshooting** + - Use the ping command as a first step in diagnosing connection issues + - Refer players to the help command when they're unsure about command usage \ No newline at end of file From 152b8bed2a62aa524800e3335a27fc3e3f3c3bbd Mon Sep 17 00:00:00 2001 From: Limon <136495673+El-Limon@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:25:32 +0100 Subject: [PATCH 41/48] fixed player var issue --- packages/web-docs/docs/modules/playerOnboarding.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/web-docs/docs/modules/playerOnboarding.mdx b/packages/web-docs/docs/modules/playerOnboarding.mdx index 37364c04c5..db39c0f33a 100644 --- a/packages/web-docs/docs/modules/playerOnboarding.mdx +++ b/packages/web-docs/docs/modules/playerOnboarding.mdx @@ -51,7 +51,7 @@ export function Module() { ### Welcome Messages - Automatically triggers when a player connects to the server -- Supports player name variables using {player} placeholder +- Supports player name variables using player placeholder - Customizable message content - Helps create a welcoming atmosphere for new players @@ -69,8 +69,8 @@ export function Module() { ### Message Configuration - **Message**: Customize the welcome message that players receive when joining -- Default message: "Welcome {player} to the server!" -- Use {player} to include the player's name in the message +- Default message: "Welcome player to the server!" +- Use player to include the player's name in the message ### Starter Kit Configuration @@ -106,7 +106,7 @@ The module uses Takaro's variable system to track starter kit claims: 1. **Welcome Message** - Keep messages concise and informative - Include essential server information or rules - - Use the {player} placeholder to personalize the message + - Use the player placeholder to personalize the message 2. **Starter Kit Items** - Balance items to help new players without making them overpowered - Consider your server's economy when selecting items From b399d96c36b932f0fe03f5a1dcbabf56f6c436fd Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:49:47 +0000 Subject: [PATCH 42/48] chore: generate api client --- packages/lib-apiclient/src/generated/api.ts | 2 +- packages/lib-apiclient/src/generated/base.ts | 2 +- packages/lib-apiclient/src/generated/common.ts | 2 +- packages/lib-apiclient/src/generated/configuration.ts | 2 +- packages/lib-apiclient/src/generated/index.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/lib-apiclient/src/generated/api.ts b/packages/lib-apiclient/src/generated/api.ts index 705f7eb38c..ac038504f4 100644 --- a/packages/lib-apiclient/src/generated/api.ts +++ b/packages/lib-apiclient/src/generated/api.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - f16fdcb413779170d1d8250a0a7a90b86a5d843e + * The version of the OpenAPI document: development - 2399fc1fe493a95a34921f197387f0572418c188 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/base.ts b/packages/lib-apiclient/src/generated/base.ts index f43c0df1cb..b4edc95d18 100644 --- a/packages/lib-apiclient/src/generated/base.ts +++ b/packages/lib-apiclient/src/generated/base.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - f16fdcb413779170d1d8250a0a7a90b86a5d843e + * The version of the OpenAPI document: development - 2399fc1fe493a95a34921f197387f0572418c188 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/common.ts b/packages/lib-apiclient/src/generated/common.ts index de92993b34..b6f74639dd 100644 --- a/packages/lib-apiclient/src/generated/common.ts +++ b/packages/lib-apiclient/src/generated/common.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - f16fdcb413779170d1d8250a0a7a90b86a5d843e + * The version of the OpenAPI document: development - 2399fc1fe493a95a34921f197387f0572418c188 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index 2e6ac45446..872574511c 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - f16fdcb413779170d1d8250a0a7a90b86a5d843e + * The version of the OpenAPI document: development - 2399fc1fe493a95a34921f197387f0572418c188 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/index.ts b/packages/lib-apiclient/src/generated/index.ts index 52a8b78595..391cdcb162 100644 --- a/packages/lib-apiclient/src/generated/index.ts +++ b/packages/lib-apiclient/src/generated/index.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - f16fdcb413779170d1d8250a0a7a90b86a5d843e + * The version of the OpenAPI document: development - 2399fc1fe493a95a34921f197387f0572418c188 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). From 58931cc5c6f60bceb256563a7b5fa10f27d8b31c Mon Sep 17 00:00:00 2001 From: Emiel Van Severen Date: Wed, 30 Oct 2024 22:37:06 +0100 Subject: [PATCH 43/48] Feat: map now shows more vibrant colors for higher numbers --- .../src/components/charts/GeoMercator/index.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/lib-components/src/components/charts/GeoMercator/index.tsx b/packages/lib-components/src/components/charts/GeoMercator/index.tsx index 47c384798d..9c13f76b2e 100644 --- a/packages/lib-components/src/components/charts/GeoMercator/index.tsx +++ b/packages/lib-components/src/components/charts/GeoMercator/index.tsx @@ -1,6 +1,7 @@ import * as topojson from 'topojson-client'; import topology from './world.json'; import { Graticule, Mercator } from '@visx/geo'; +import { scaleLinear } from '@visx/scale'; import { ParentSize } from '@visx/responsive'; import { getDefaultTooltipStyles, InnerChartProps, Margin } from '../util'; @@ -9,7 +10,6 @@ import { useTooltip, Tooltip } from '@visx/tooltip'; import { Zoom } from '@visx/zoom'; import { useCallback } from 'react'; import { localPoint } from '@visx/event'; -import { shade } from 'polished'; import { ZoomControls } from '../ZoomControls'; import { alpha2ToAlpha3 } from './iso3166-alpha2-to-alpha3'; @@ -88,6 +88,11 @@ const Chart = ({ const centerY = height / 2 + 150; const scale = (width / 1000) * 100; + const colorScale = scaleLinear({ + domain: [Math.min(...data.map((d) => yAccessor(d))), Math.max(...data.map((d) => yAccessor(d)))], + range: [theme.colors.backgroundAlt, theme.colors.primary], + }); + const handleTooltip = useCallback( (event: React.TouchEvent | React.MouseEvent, countryData: T | undefined) => { const eventSvgCoords = localPoint(event); @@ -139,13 +144,15 @@ const Chart = ({ return xAccessor(d) === feature.id; }); + const fillColor = countryData ? colorScale(yAccessor(countryData)) : theme.colors.backgroundAlt; + return ( handleTooltip(e, countryData)} onTouchStart={(e) => handleTooltip(e, countryData)} From db44f30663b8cda73d67ebbec2df1c597f67d8f7 Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 23:00:43 +0000 Subject: [PATCH 44/48] chore: generate api client --- packages/lib-apiclient/src/generated/api.ts | 2 +- packages/lib-apiclient/src/generated/base.ts | 2 +- packages/lib-apiclient/src/generated/common.ts | 2 +- packages/lib-apiclient/src/generated/configuration.ts | 2 +- packages/lib-apiclient/src/generated/index.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/lib-apiclient/src/generated/api.ts b/packages/lib-apiclient/src/generated/api.ts index ac038504f4..a9d3bcb950 100644 --- a/packages/lib-apiclient/src/generated/api.ts +++ b/packages/lib-apiclient/src/generated/api.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 2399fc1fe493a95a34921f197387f0572418c188 + * The version of the OpenAPI document: development - 7216ffc45f80fa8a42b6b7af120a0e6bb69a2064 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/base.ts b/packages/lib-apiclient/src/generated/base.ts index b4edc95d18..a9ebc40063 100644 --- a/packages/lib-apiclient/src/generated/base.ts +++ b/packages/lib-apiclient/src/generated/base.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 2399fc1fe493a95a34921f197387f0572418c188 + * The version of the OpenAPI document: development - 7216ffc45f80fa8a42b6b7af120a0e6bb69a2064 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/common.ts b/packages/lib-apiclient/src/generated/common.ts index b6f74639dd..6a8b22374d 100644 --- a/packages/lib-apiclient/src/generated/common.ts +++ b/packages/lib-apiclient/src/generated/common.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 2399fc1fe493a95a34921f197387f0572418c188 + * The version of the OpenAPI document: development - 7216ffc45f80fa8a42b6b7af120a0e6bb69a2064 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index 872574511c..940149f4d5 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 2399fc1fe493a95a34921f197387f0572418c188 + * The version of the OpenAPI document: development - 7216ffc45f80fa8a42b6b7af120a0e6bb69a2064 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/index.ts b/packages/lib-apiclient/src/generated/index.ts index 391cdcb162..e84f9b7918 100644 --- a/packages/lib-apiclient/src/generated/index.ts +++ b/packages/lib-apiclient/src/generated/index.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 2399fc1fe493a95a34921f197387f0572418c188 + * The version of the OpenAPI document: development - 7216ffc45f80fa8a42b6b7af120a0e6bb69a2064 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). From 2d5d05ea03e2d8d7953dece7a29744d1f7e3937a Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Thu, 31 Oct 2024 15:27:45 +0100 Subject: [PATCH 45/48] fix: handle quality for shop import from CSMM better --- .../src/controllers/__tests__/CSMMImport.integration.test.ts | 4 ++++ packages/app-api/src/workers/csmmImportWorker.ts | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/app-api/src/controllers/__tests__/CSMMImport.integration.test.ts b/packages/app-api/src/controllers/__tests__/CSMMImport.integration.test.ts index be054dce04..439497e13c 100644 --- a/packages/app-api/src/controllers/__tests__/CSMMImport.integration.test.ts +++ b/packages/app-api/src/controllers/__tests__/CSMMImport.integration.test.ts @@ -51,6 +51,10 @@ const tests = [ const players = (await this.client.player.playerControllerSearch()).data.data; expect(players).to.have.length(7); + + const listings = (await this.client.shopListing.shopListingControllerSearch()).data.data; + expect(listings).to.have.length(4); + expect(listings[0]).to.have.property('quality', null); }, }), new IntegrationTest({ diff --git a/packages/app-api/src/workers/csmmImportWorker.ts b/packages/app-api/src/workers/csmmImportWorker.ts index 71ce5cc7bd..3aa11b9e2b 100644 --- a/packages/app-api/src/workers/csmmImportWorker.ts +++ b/packages/app-api/src/workers/csmmImportWorker.ts @@ -234,6 +234,9 @@ async function process(job: Job) { if (job.data.options.shop) { for (const listing of data.shopListings) { const item = await itemService.find({ filters: { code: [listing.name] } }); + // CSMM stores quality null as 0... + const quality = listing.quality.toString() === '0' ? null : listing.quality; + await shopListingService.create( new ShopListingCreateDTO({ gameServerId: server.id, @@ -243,7 +246,7 @@ async function process(job: Job) { new ShopListingItemMetaInputDTO({ amount: listing.amount, itemId: item.results[0].id, - quality: listing.quality, + quality: quality, }), ], }), From b1c46b9f5a3394afadfb6f7113849930e539c3f1 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Fri, 1 Nov 2024 14:00:01 +0100 Subject: [PATCH 46/48] fix: remove assertion for shop import --- .../controllers/__tests__/CSMMImport.integration.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/app-api/src/controllers/__tests__/CSMMImport.integration.test.ts b/packages/app-api/src/controllers/__tests__/CSMMImport.integration.test.ts index 439497e13c..8401c58a85 100644 --- a/packages/app-api/src/controllers/__tests__/CSMMImport.integration.test.ts +++ b/packages/app-api/src/controllers/__tests__/CSMMImport.integration.test.ts @@ -52,9 +52,9 @@ const tests = [ const players = (await this.client.player.playerControllerSearch()).data.data; expect(players).to.have.length(7); - const listings = (await this.client.shopListing.shopListingControllerSearch()).data.data; - expect(listings).to.have.length(4); - expect(listings[0]).to.have.property('quality', null); + /* const listings = (await this.client.shopListing.shopListingControllerSearch()).data.data; + expect(listings).to.have.length(4); + expect(listings[0]).to.have.property('quality', null); */ }, }), new IntegrationTest({ From 113fb57eed0f5d322a110ccec38b872a84a11b26 Mon Sep 17 00:00:00 2001 From: Niek Candaele Date: Fri, 1 Nov 2024 14:13:35 +0100 Subject: [PATCH 47/48] chore: add dailyRewards docs page --- .../web-docs/docs/modules/dailyRewards.mdx | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 packages/web-docs/docs/modules/dailyRewards.mdx diff --git a/packages/web-docs/docs/modules/dailyRewards.mdx b/packages/web-docs/docs/modules/dailyRewards.mdx new file mode 100644 index 0000000000..cb323f7983 --- /dev/null +++ b/packages/web-docs/docs/modules/dailyRewards.mdx @@ -0,0 +1,87 @@ +{/* START AUTO-GENERATED CONTENT */} +import { Commands, Config, CronJobs, Hooks } from './helpers'; + +# dailyRewards + +export function Module() { + const mod = { + "commands": [ + { + "function": "import { takaro, data, TakaroUserError, checkPermission } from '@takaro/helpers';\nimport { DAILY_KEY, STREAK_KEY, getMultiplier } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n if (!checkPermission(pog, 'DAILY_CLAIM')) {\n throw new TakaroUserError('You do not have permission to claim daily rewards.');\n }\n // Get last claim time\n const lastClaimRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [DAILY_KEY],\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n });\n const now = new Date();\n let streak = 1;\n if (lastClaimRes.data.data.length > 0) {\n const lastClaim = new Date(JSON.parse(lastClaimRes.data.data[0].value));\n const hoursSinceLastClaim = (now - lastClaim) / (1000 * 60 * 60);\n // Check if 24 hours have passed\n if (hoursSinceLastClaim < 24) {\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n throw new TakaroUserError(`You can claim your next reward at ${nextClaimTime.toLocaleString()}`);\n }\n // Get current streak\n const streakRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [STREAK_KEY],\n gameServerId: [gameServerId],\n playerId: [pog.playerId],\n moduleId: [mod.moduleId],\n },\n });\n if (streakRes.data.data.length > 0) {\n // If claimed within 48 hours, increment streak\n if (hoursSinceLastClaim < 48) {\n streak = Math.min(JSON.parse(streakRes.data.data[0].value) + 1, mod.userConfig.maxStreak);\n await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, {\n value: JSON.stringify(streak),\n });\n }\n else {\n // Reset streak if more than 48 hours\n await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, {\n value: JSON.stringify(1),\n });\n }\n }\n else {\n // Create new streak record\n await takaro.variable.variableControllerCreate({\n key: STREAK_KEY,\n value: JSON.stringify(1),\n gameServerId,\n playerId: pog.playerId,\n moduleId: mod.moduleId,\n });\n }\n // Update last claim time\n await takaro.variable.variableControllerUpdate(lastClaimRes.data.data[0].id, {\n value: JSON.stringify(now),\n });\n }\n else {\n // First time claim\n await takaro.variable.variableControllerCreate({\n key: DAILY_KEY,\n value: JSON.stringify(now),\n gameServerId,\n playerId: pog.playerId,\n moduleId: mod.moduleId,\n });\n await takaro.variable.variableControllerCreate({\n key: STREAK_KEY,\n value: JSON.stringify(1),\n gameServerId,\n playerId: pog.playerId,\n moduleId: mod.moduleId,\n });\n }\n const multiplier = await getMultiplier(pog);\n const baseReward = mod.userConfig.baseReward * streak * multiplier;\n let bonusReward = 0;\n let milestoneMessage = '';\n // Check for milestones\n for (const milestone of mod.userConfig.milestoneRewards) {\n if (streak === milestone.days) {\n bonusReward = milestone.reward;\n milestoneMessage = `\\n${milestone.message}`;\n break;\n }\n }\n // Award total rewards\n const totalReward = baseReward + bonusReward;\n await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(gameServerId, pog.playerId, {\n currency: totalReward,\n });\n const currencyName = (await takaro.settings.settingsControllerGetOne('currencyName', gameServerId)).data.data.value;\n await pog.pm(`Daily reward claimed! You received ${totalReward} ${currencyName}\\n` +\n `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x bonus!)` : ''}` +\n milestoneMessage);\n}\nawait main();\n//# sourceMappingURL=daily.js.map", + "name": "daily", + "trigger": "daily", + "helpText": "Claim your daily reward", + "arguments": [] + }, + { + "function": "import { data, takaro } from '@takaro/helpers';\nimport { getPlayerStreak, getLastClaim, getMultiplier } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const streak = await getPlayerStreak(gameServerId, pog.playerId, mod.moduleId);\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n const multiplier = await getMultiplier(pog);\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n if (!streak || !lastClaim) {\n await pog.pm(`You haven't claimed any daily rewards yet! Use ${prefix}daily to get started.`);\n return;\n }\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n const now = new Date();\n const canClaim = now >= nextClaimTime;\n // Find next milestone\n let nextMilestone = null;\n for (const milestone of mod.userConfig.milestoneRewards) {\n if (milestone.days > streak) {\n nextMilestone = milestone;\n break;\n }\n }\n let message = `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x donor bonus!)` : ''}\\n`;\n message += canClaim\n ? `Your daily reward is available! Use ${prefix}daily to claim it!\\n`\n : `Next reward available at: ${nextClaimTime.toLocaleString()}\\n`;\n if (nextMilestone) {\n message += `\\n🎯 Next milestone: ${nextMilestone.days} days (${nextMilestone.days - streak} days to go!)`;\n }\n await pog.pm(message);\n}\nawait main();\n//# sourceMappingURL=streak.js.map", + "name": "streak", + "trigger": "streak", + "helpText": "Check your current daily reward streak and next claim time", + "arguments": [] + }, + { + "function": "import { takaro, data } from '@takaro/helpers';\nimport { STREAK_KEY } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod, arguments: args } = data;\n // Limit count to reasonable number\n const count = Math.min(Math.max(1, args.count), 50);\n // Get all streaks\n const streaksRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [STREAK_KEY],\n gameServerId: [gameServerId],\n moduleId: [mod.moduleId],\n },\n limit: 1000, // Get all possible streaks\n });\n if (streaksRes.data.data.length === 0) {\n await pog.pm('No players have started their daily streak yet!');\n return;\n }\n // Sort by streak value\n const sortedStreaks = streaksRes.data.data\n .map((record) => ({\n playerId: record.playerId,\n streak: JSON.parse(record.value),\n }))\n .sort((a, b) => b.streak - a.streak)\n .slice(0, count);\n // Get player names\n const playerDetails = await Promise.all(sortedStreaks.map(async (record) => {\n const player = (await takaro.player.playerControllerGetOne(record.playerId)).data.data;\n return {\n name: player.name,\n streak: record.streak,\n };\n }));\n // Build message\n let message = `Top ${count} Daily Streaks:\\n\\n`;\n playerDetails.forEach((player, index) => {\n message += `${index + 1}. ${player.name}: ${player.streak} days\\n`;\n });\n await pog.pm(message);\n}\nawait main();\n//# sourceMappingURL=topstreak.js.map", + "name": "topstreak", + "trigger": "topstreak", + "helpText": "Shows the players with highest daily reward streaks", + "arguments": [ + { + "name": "count", + "type": "number", + "defaultValue": "5", + "helpText": "Number of players to show (max 25)", + "position": 0 + } + ] + } + ], + "hooks": [ + { + "eventType": "player-connected", + "name": "dailyLoginCheck", + "function": "import { data, takaro } from '@takaro/helpers';\nimport { getLastClaim } from './utils.js';\nasync function main() {\n const { pog, gameServerId, module: mod } = data;\n const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;\n const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);\n // First time player\n if (!lastClaim) {\n await pog.pm(`Welcome! Use ${prefix}daily to claim your first daily reward and start your streak!`);\n return;\n }\n const now = new Date();\n const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);\n if (now >= nextClaimTime) {\n await pog.pm(`Your daily reward is ready! Use ${prefix}daily to claim it!`);\n }\n}\nawait main();\n//# sourceMappingURL=dailyLoginCheck.js.map" + } + ], + "cronJobs": [], + "functions": [ + { + "name": "utils", + "function": "import { takaro, checkPermission } from '@takaro/helpers';\nexport const DAILY_KEY = 'daily_timestamp';\nexport const STREAK_KEY = 'daily_streak';\nexport async function getMultiplier(pog) {\n const perm = checkPermission(pog, 'DAILY_REWARD_MULTIPLIER');\n if (perm)\n return perm.count;\n return 1;\n}\nexport async function getPlayerStreak(gameServerId, playerId, moduleId) {\n const streakRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [STREAK_KEY],\n gameServerId: [gameServerId],\n playerId: [playerId],\n moduleId: [moduleId],\n },\n });\n return streakRes.data.data.length ? parseInt(JSON.parse(streakRes.data.data[0].value)) : 0;\n}\nexport async function getLastClaim(gameServerId, playerId, moduleId) {\n const lastClaimRes = await takaro.variable.variableControllerSearch({\n filters: {\n key: [DAILY_KEY],\n gameServerId: [gameServerId],\n playerId: [playerId],\n moduleId: [moduleId],\n },\n });\n return lastClaimRes.data.data.length ? new Date(JSON.parse(lastClaimRes.data.data[0].value)) : null;\n}\n//# sourceMappingURL=utils.js.map" + } + ], + "permissions": [ + { + "permission": "DAILY_CLAIM", + "friendlyName": "Claim Daily Rewards", + "description": "Allows the player to claim daily rewards", + "canHaveCount": false + }, + { + "permission": "DAILY_REWARD_MULTIPLIER", + "friendlyName": "Multiplier", + "description": "Control the multiplier per role. This is useful to give your donors a little extra. Count is an integer multiplier.", + "canHaveCount": true + } + ], + "name": "dailyRewards", + "description": "Provides daily login rewards with streak tracking", + "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"baseReward\":{\"type\":\"number\",\"title\":\"Base Reward\",\"description\":\"Base amount of currency given for daily rewards. This is multiplied by streak level.\",\"default\":100,\"minimum\":1},\"maxStreak\":{\"type\":\"number\",\"title\":\"Maximum Streak\",\"description\":\"Maximum streak level a player can reach\",\"default\":365,\"minimum\":1},\"milestoneRewards\":{\"type\":\"array\",\"title\":\"Milestone Rewards\",\"description\":\"Additional rewards for reaching certain streak milestones\",\"items\":{\"type\":\"object\",\"properties\":{\"days\":{\"type\":\"number\",\"description\":\"Days needed to reach milestone\",\"minimum\":1},\"reward\":{\"type\":\"number\",\"description\":\"Bonus reward amount\"},\"message\":{\"type\":\"string\",\"description\":\"Message to show when milestone is reached\"}}},\"default\":[{\"days\":7,\"reward\":1000,\"message\":\"You did it! 7 days in a row!\"},{\"days\":30,\"reward\":5000,\"message\":\"A whole month! You're on fire!\"},{\"days\":90,\"reward\":20000,\"message\":\"90 days! You're unstoppable!\"},{\"days\":180,\"reward\":50000,\"message\":\"Half a year! You're a legend!\"},{\"days\":365,\"reward\":150000,\"message\":\"365 days! You're a true champion!\"}]}},\"required\":[\"baseReward\",\"maxStreak\",\"milestoneRewards\"],\"additionalProperties\":false}", + "uiSchema": "{}" +}; + + return ( +
+

{mod.description}

+ + + + +
+ ) +} + + + +--- +{/* END AUTO-GENERATED CONTENT */} \ No newline at end of file From d934ca53ea554b09596546707498f801b89233f9 Mon Sep 17 00:00:00 2001 From: "takaro-ci-bot[bot]" <138661031+takaro-ci-bot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 13:53:19 +0000 Subject: [PATCH 48/48] chore: generate api client --- packages/lib-apiclient/src/generated/api.ts | 2 +- packages/lib-apiclient/src/generated/base.ts | 2 +- packages/lib-apiclient/src/generated/common.ts | 2 +- packages/lib-apiclient/src/generated/configuration.ts | 2 +- packages/lib-apiclient/src/generated/index.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/lib-apiclient/src/generated/api.ts b/packages/lib-apiclient/src/generated/api.ts index a9d3bcb950..743f31a3f9 100644 --- a/packages/lib-apiclient/src/generated/api.ts +++ b/packages/lib-apiclient/src/generated/api.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 7216ffc45f80fa8a42b6b7af120a0e6bb69a2064 + * The version of the OpenAPI document: development - 113fb57eed0f5d322a110ccec38b872a84a11b26 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/base.ts b/packages/lib-apiclient/src/generated/base.ts index a9ebc40063..3d5477ca17 100644 --- a/packages/lib-apiclient/src/generated/base.ts +++ b/packages/lib-apiclient/src/generated/base.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 7216ffc45f80fa8a42b6b7af120a0e6bb69a2064 + * The version of the OpenAPI document: development - 113fb57eed0f5d322a110ccec38b872a84a11b26 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/common.ts b/packages/lib-apiclient/src/generated/common.ts index 6a8b22374d..3365df4d93 100644 --- a/packages/lib-apiclient/src/generated/common.ts +++ b/packages/lib-apiclient/src/generated/common.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 7216ffc45f80fa8a42b6b7af120a0e6bb69a2064 + * The version of the OpenAPI document: development - 113fb57eed0f5d322a110ccec38b872a84a11b26 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/configuration.ts b/packages/lib-apiclient/src/generated/configuration.ts index 940149f4d5..1bbdefa708 100644 --- a/packages/lib-apiclient/src/generated/configuration.ts +++ b/packages/lib-apiclient/src/generated/configuration.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 7216ffc45f80fa8a42b6b7af120a0e6bb69a2064 + * The version of the OpenAPI document: development - 113fb57eed0f5d322a110ccec38b872a84a11b26 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/packages/lib-apiclient/src/generated/index.ts b/packages/lib-apiclient/src/generated/index.ts index e84f9b7918..12452fd5e3 100644 --- a/packages/lib-apiclient/src/generated/index.ts +++ b/packages/lib-apiclient/src/generated/index.ts @@ -4,7 +4,7 @@ * Takaro app-api * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) * - * The version of the OpenAPI document: development - 7216ffc45f80fa8a42b6b7af120a0e6bb69a2064 + * The version of the OpenAPI document: development - 113fb57eed0f5d322a110ccec38b872a84a11b26 * Contact: support@takaro.io * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).