From 0d034710b5db4c9529b822288561ab740baf19fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Wysoki=C5=84ski?= Date: Wed, 3 Apr 2024 07:18:14 +0200 Subject: [PATCH] refactor: extended tribe profile - use /api/v2 --- .eslintignore | 2 +- package.json | 2 +- postbuild.js | 4 +- src/common/dialog-table-v2.ts | 132 ------- src/common/dialog-table.ts | 74 ++-- src/extended-map-popup.user.ts | 8 +- src/extended-player-profile.user.ts | 32 +- src/extended-tribe-profile.user.ts | 143 ++++--- src/extended-village-profile.user.ts | 10 +- src/lib/twhelp.ts | 424 --------------------- src/lib/{twhelpv2 => twhelp}/.gitignore | 0 src/lib/{twhelpv2 => twhelp}/openapi3.json | 0 12 files changed, 156 insertions(+), 675 deletions(-) delete mode 100644 src/common/dialog-table-v2.ts delete mode 100644 src/lib/twhelp.ts rename src/lib/{twhelpv2 => twhelp}/.gitignore (100%) rename src/lib/{twhelpv2 => twhelp}/openapi3.json (100%) diff --git a/.eslintignore b/.eslintignore index dde047a..d0234ea 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,4 +5,4 @@ k8s .prettierrc.js commitlint.config.js postbuild.js -src/lib/twhelpv2 +src/lib/twhelp diff --git a/package.json b/package.json index 46f9d27..b15fc46 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "license": "MIT", "scripts": { "prepare": "husky install", - "generate-client": "openapi --input ./src/lib/twhelpv2/openapi3.json --output ./src/lib/twhelpv2 --name TWHelpV2Client --useOptions --client axios", + "generate-client": "openapi --input src/lib/twhelp/openapi3.json --output src/lib/twhelp --name TWHelpClient --useOptions --client axios", "build": "rm -rf dist && yarn generate-client && parcel build ./src/*.user.ts ./src/*.quickbar.ts", "postbuild": "PUBLIC_URL=https://scripts.twhelp.app node postbuild.js", "lint": "eslint src/**/*.ts" diff --git a/postbuild.js b/postbuild.js index 4cf9f2d..a909e42 100644 --- a/postbuild.js +++ b/postbuild.js @@ -7,7 +7,7 @@ const DIST_DIR = 'dist'; const metadata = { 'extended-player-profile': `// ==UserScript== // @name Extended player profile -// @version 1.1.6 +// @version 1.2.0 // @description Adds additional info and actions on a player overview. // @author Dawid Wysokiński - Kichiyaki - contact@twhelp.app // @match https://*/game.php?*screen=info_player* @@ -43,7 +43,7 @@ const metadata = { // ==/UserScript==`, 'extended-tribe-profile': `// ==UserScript== // @name Extended tribe profile -// @version 1.0.4 +// @version 1.1.0 // @description Adds additional info and actions on a tribe overview. // @author Dawid Wysokiński - Kichiyaki - contact@twhelp.app // @match https://*/game.php?*screen=info_ally* diff --git a/src/common/dialog-table-v2.ts b/src/common/dialog-table-v2.ts deleted file mode 100644 index 2cee4d3..0000000 --- a/src/common/dialog-table-v2.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { createTranslationFunc } from '../utils'; - -const t = createTranslationFunc({ - pl_PL: { - Loading: 'Wczytywanie', - 'Previous page': 'Poprzednia strona', - 'Next page': 'Następna strona', - 'Something went wrong while loading the data': - 'Coś poszło nie tak podczas wczytywania danych', - }, -}); - -export type DialogTableColumn = { - header: string; - accessor: (row: T, index: number, rows: T[]) => string; -}; - -export type Cursor = { - next?: string; - self?: string; -}; - -export type LoadDataResult = { - cursor?: Cursor; - data: T[]; -}; - -export class DialogTableV2 { - private readonly prevPageId: string; - private readonly nextPageId: string; - - private readonly prevCursors: Cursor[] = []; - - constructor( - private readonly id: string, - private readonly columns: DialogTableColumn[], - private readonly limit: number, - private readonly loadData: ( - cursor: string | undefined, - limit: number - ) => Promise> - ) { - this.prevPageId = `${this.id}_page_prev`; - this.nextPageId = `${this.id}_page_next`; - } - - public async render() { - await this.renderPage(); - } - - private async renderPage(pageCursor?: string) { - window.Dialog.show(this.id, `

${t('Loading')}...

`); - - try { - const { data, cursor } = await this.loadData(pageCursor, this.limit); - - window.Dialog.show( - this.id, - ` - ${this.buildPagination(cursor)} - ${this.buildTable(data)} - ` - ); - - this.addEventListeners(cursor); - } catch (err) { - console.error(err); - window.Dialog.close(); - window.UI.ErrorMessage(t('Something went wrong while loading the data')); - } - } - - private buildPagination(cursor?: Cursor): string { - return ` -
- - -
- `; - } - - private buildTable(data: T[]) { - return ` - - - - ${this.columns.map((col) => ``).join('')} - - ${data - .map( - (r, index) => ` - - ${this.columns - .map((col) => ``) - .join('')} - - ` - ) - .join('')} - -
${col.header}
${col.accessor(r, index, data)}
- `; - } - - private addEventListeners(cursor?: Cursor) { - document - .querySelector('#' + this.prevPageId) - ?.addEventListener('click', () => { - const prev = this.prevCursors.pop(); - if (!prev) { - return; - } - this.renderPage(prev.self); - }); - - document - .querySelector('#' + this.nextPageId) - ?.addEventListener('click', () => { - if (!cursor) { - return; - } - this.prevCursors.push(cursor); - this.renderPage(cursor.next); - }); - } -} diff --git a/src/common/dialog-table.ts b/src/common/dialog-table.ts index c962f8a..9be7c62 100644 --- a/src/common/dialog-table.ts +++ b/src/common/dialog-table.ts @@ -15,48 +15,54 @@ export type DialogTableColumn = { accessor: (row: T, index: number, rows: T[]) => string; }; +export type Cursor = { + next?: string; + self?: string; +}; + export type LoadDataResult = { + cursor?: Cursor; data: T[]; - total: number; }; export class DialogTable { - prevPageId: string; - selectId: string; - nextPageId: string; + private readonly prevPageId: string; + private readonly nextPageId: string; + + private readonly prevCursors: Cursor[] = []; + constructor( private readonly id: string, private readonly columns: DialogTableColumn[], private readonly limit: number, private readonly loadData: ( - page: number, + cursor: string | undefined, limit: number ) => Promise> ) { this.prevPageId = `${this.id}_page_prev`; - this.selectId = `${this.id}_page_select`; this.nextPageId = `${this.id}_page_next`; } public async render() { - await this.renderPage(1); + await this.renderPage(); } - private async renderPage(page: number) { - window.Dialog.show(`${this.id}_loading`, `

${t('Loading')}...

`); + private async renderPage(pageCursor?: string) { + window.Dialog.show(this.id, `

${t('Loading')}...

`); try { - const { data, total } = await this.loadData(page, this.limit); + const { data, cursor } = await this.loadData(pageCursor, this.limit); window.Dialog.show( this.id, ` - ${this.buildPagination(page, total)} + ${this.buildPagination(cursor)} ${this.buildTable(data)} ` ); - this.addEventListeners(page); + this.addEventListeners(cursor); } catch (err) { console.error(err); window.Dialog.close(); @@ -64,31 +70,17 @@ export class DialogTable { } } - private buildPagination(page: number, total: number): string { - const maxPage = Math.ceil(total / this.limit); - - const pageOpts = []; - for (let i = 1; i <= (page > maxPage ? page : maxPage); i++) { - pageOpts.push( - `${i}` - ); - } - + private buildPagination(cursor?: Cursor): string { return `
- + this.prevCursors.length === 0 ? ' disabled' : '' + }>< + this.nextPageId + }"${!cursor?.next ? ' disabled' : ''}>>
`; } @@ -116,27 +108,25 @@ export class DialogTable { `; } - private addEventListeners(page: number) { + private addEventListeners(cursor?: Cursor) { document .querySelector('#' + this.prevPageId) ?.addEventListener('click', () => { - this.renderPage(page - 1); - }); - - document - .querySelector('#' + this.selectId) - ?.addEventListener('change', (e: Event) => { - if (!(e.currentTarget instanceof HTMLSelectElement)) { + const prev = this.prevCursors.pop(); + if (!prev) { return; } - - this.renderPage(parseInt(e.currentTarget.value)); + this.renderPage(prev.self); }); document .querySelector('#' + this.nextPageId) ?.addEventListener('click', () => { - this.renderPage(page + 1); + if (!cursor) { + return; + } + this.prevCursors.push(cursor); + this.renderPage(cursor.next); }); } } diff --git a/src/extended-map-popup.user.ts b/src/extended-map-popup.user.ts index c85e8b6..99123ab 100644 --- a/src/extended-map-popup.user.ts +++ b/src/extended-map-popup.user.ts @@ -3,11 +3,11 @@ import { Cache, InMemoryStorage } from './lib/cache'; import { calcDistance, calcLoyalty } from './lib/tw'; import { createTranslationFunc } from './utils'; import { - TWHelpV2Client, + TWHelpClient, Ennoblement, UnitInfo, ServerConfig, -} from './lib/twhelpv2'; +} from './lib/twhelp'; declare global { interface Window { @@ -52,14 +52,14 @@ class TWHelpConnector { private readonly localStorageCache = new Cache(localStorage); private readonly inMemoryCache = new Cache(new InMemoryStorage()); - private readonly client: TWHelpV2Client; + private readonly client: TWHelpClient; constructor( readonly baseUrl: string, private readonly version: string, private readonly server: string ) { - this.client = new TWHelpV2Client({ + this.client = new TWHelpClient({ BASE: baseUrl, }); } diff --git a/src/extended-player-profile.user.ts b/src/extended-player-profile.user.ts index 388f3f6..bfa008d 100644 --- a/src/extended-player-profile.user.ts +++ b/src/extended-player-profile.user.ts @@ -3,8 +3,9 @@ import { InADayClient } from './lib/tw'; import { createTranslationFunc } from './utils'; import { buildURL } from './lib/twstats'; -import { TWHelpV2Client, PlayerSnapshot, Player } from './lib/twhelpv2'; -import { DialogTableV2 } from './common/dialog-table-v2'; +import { TWHelpClient, PlayerSnapshot, Player } from './lib/twhelp'; +import { DialogTable } from './common/dialog-table'; +import { Cache } from './lib/cache'; const t = createTranslationFunc({ pl_PL: { @@ -59,7 +60,7 @@ const t = createTranslationFunc({ }); class TWHelpConnector { - private readonly client: TWHelpV2Client; + private readonly client: TWHelpClient; constructor( readonly baseUrl: string, @@ -67,7 +68,7 @@ class TWHelpConnector { private readonly server: string, private readonly id: number ) { - this.client = new TWHelpV2Client({ + this.client = new TWHelpClient({ BASE: baseUrl, }); } @@ -131,12 +132,23 @@ class TWHelpConnector { } class InADayConnector { + private static readonly CACHE_KEY_PREFIX = + 'extended_player_profile_in_a_day_'; + + private readonly cache = new Cache(localStorage); + private readonly client = new InADayClient(); constructor(private readonly name: string) {} player() { - return this.client.player(this.name); + return this.cache.load( + InADayConnector.CACHE_KEY_PREFIX + this.name, + 600, + () => { + return this.client.player(this.name); + } + ); } } @@ -360,7 +372,7 @@ class UI { private async showOtherServers(e: Event) { e.preventDefault(); - await new DialogTableV2( + await new DialogTable( DialogId.OTHER_SERVERS, [ { @@ -421,7 +433,7 @@ class UI { conquer: 'Villages conquered', }; - await new DialogTableV2( + await new DialogTable( DialogId.IN_A_DAY_RANKS, [ { @@ -469,7 +481,7 @@ class UI { private async showTribeChanges(e: Event) { e.preventDefault(); - await new DialogTableV2( + await new DialogTable( DialogId.TRIBE_CHANGES, [ { @@ -501,7 +513,7 @@ class UI { private async showHistory(e: Event) { e.preventDefault(); - await new DialogTableV2( + await new DialogTable( DialogId.HISTORY, [ { @@ -557,7 +569,7 @@ class UI { private async showEnnoblements(e: Event) { e.preventDefault(); - await new DialogTableV2( + await new DialogTable( DialogId.ENNOBLEMENTS, [ { diff --git a/src/extended-tribe-profile.user.ts b/src/extended-tribe-profile.user.ts index 724e068..15a8deb 100644 --- a/src/extended-tribe-profile.user.ts +++ b/src/extended-tribe-profile.user.ts @@ -1,7 +1,7 @@ import { Player, Tribe, TribeSnapshot, TWHelpClient } from './lib/twhelp'; import { createTranslationFunc } from './utils'; -import { DialogTable } from './common/dialog-table'; import { buildURL } from './lib/twstats'; +import { DialogTable } from './common/dialog-table'; const t = createTranslationFunc({ pl_PL: { @@ -44,47 +44,72 @@ const t = createTranslationFunc({ }); class TWHelpConnector { + private readonly client: TWHelpClient; + constructor( - private readonly client: TWHelpClient, + baseUrl: string, private readonly version: string, private readonly server: string, private readonly id: number - ) {} + ) { + this.client = new TWHelpClient({ + BASE: baseUrl, + }); + } - tribe() { - return this.client.tribe(this.version, this.server, this.id); + async tribe() { + return ( + await this.client.tribes.getTribe({ + versionCode: this.version, + serverKey: this.server, + tribeId: this.id, + }) + ).data; } tribeMembers() { - return this.client.tribeMembers(this.version, this.server, this.id); + return this.client.tribes.listTribeMembers({ + versionCode: this.version, + serverKey: this.server, + tribeId: this.id, + }); } async latestSnapshot() { - const snapshot = await this.tribeSnapshots(1, 1); + const snapshot = await this.tribeSnapshots(undefined, 1); return snapshot.data.length > 0 ? snapshot.data[0] : null; } - tribeSnapshots(page: number, limit: number) { - return this.client.tribeSnapshots(this.version, this.server, this.id, { - offset: (page - 1) * limit, + tribeSnapshots(cursor: string | undefined, limit: number) { + return this.client.snapshots.listTribeTribeSnapshots({ + versionCode: this.version, + serverKey: this.server, + tribeId: this.id, + cursor, limit, - sort: ['date:desc'], + sort: ['date:DESC'], }); } - tribeTribeChanges(page: number, limit: number) { - return this.client.tribeTribeChanges(this.version, this.server, this.id, { - offset: (page - 1) * limit, + memberChanges(cursor: string | undefined, limit: number) { + return this.client.tribeChanges.listTribeMemberChanges({ + versionCode: this.version, + serverKey: this.server, + tribeId: this.id, + cursor, limit, - sort: ['createdAt:desc'], + sort: ['createdAt:DESC'], }); } - tribeEnnoblements(page: number, limit: number) { - return this.client.tribeEnnoblements(this.version, this.server, this.id, { - offset: (page - 1) * limit, + tribeEnnoblements(cursor: string | undefined, limit: number) { + return this.client.ennoblements.listTribeEnnoblements({ + versionCode: this.version, + serverKey: this.server, + tribeId: this.id, + cursor, limit, - sort: ['createdAt:desc'], + sort: ['createdAt:DESC'], }); } } @@ -133,20 +158,20 @@ class UI { ${t('Best rank')}: ${this.tribe.bestRank} (${new Date( - this.tribe.bestRankAt - ).toLocaleString()}) + this.tribe.bestRankAt + ).toLocaleString()}) ${t('Most points')}: ${this.tribe.mostPoints.toLocaleString()} (${new Date( - this.tribe.mostPointsAt - ).toLocaleString()}) + this.tribe.mostPointsAt + ).toLocaleString()}) ${t('Most villages')}: ${this.tribe.mostVillages.toLocaleString()} (${new Date( - this.tribe.mostVillagesAt - ).toLocaleString()}) + this.tribe.mostVillagesAt + ).toLocaleString()}) ` ); @@ -185,29 +210,41 @@ class UI { }, { header: t('ODA'), - value: this.tribe.scoreAtt - (this.latestSnapshot?.scoreAtt ?? 0), + value: + this.tribe.opponentsDefeated.scoreAtt - + (this.latestSnapshot?.opponentsDefeated.scoreAtt ?? 0), }, { header: t('ODA - rank'), - value: this.tribe.rankAtt - (this.latestSnapshot?.rankAtt ?? 0), + value: + this.tribe.opponentsDefeated.rankAtt - + (this.latestSnapshot?.opponentsDefeated.rankAtt ?? 0), rank: true, }, { header: t('ODD'), - value: this.tribe.scoreDef - (this.latestSnapshot?.scoreDef ?? 0), + value: + this.tribe.opponentsDefeated.scoreDef - + (this.latestSnapshot?.opponentsDefeated.scoreDef ?? 0), }, { header: t('ODD - rank'), - value: this.tribe.rankDef - (this.latestSnapshot?.rankDef ?? 0), + value: + this.tribe.opponentsDefeated.rankDef - + (this.latestSnapshot?.opponentsDefeated.rankDef ?? 0), rank: true, }, { header: t('OD'), - value: this.tribe.scoreTotal - (this.latestSnapshot?.scoreTotal ?? 0), + value: + this.tribe.opponentsDefeated.scoreTotal - + (this.latestSnapshot?.opponentsDefeated.scoreTotal ?? 0), }, { header: t('OD - rank'), - value: this.tribe.rankTotal - (this.latestSnapshot?.rankTotal ?? 0), + value: + this.tribe.opponentsDefeated.rankTotal - + (this.latestSnapshot?.opponentsDefeated.rankTotal ?? 0), rank: true, }, ]; @@ -231,10 +268,10 @@ class UI { r.value, r.rank )}">${ - r.customFormat - ? r.customFormat(r.value) - : Math.abs(r.value).toLocaleString() - } + r.customFormat + ? r.customFormat(r.value) + : Math.abs(r.value).toLocaleString() + } ` ) @@ -323,8 +360,8 @@ class UI { }, ], 30, - (page: number, limit: number) => { - return this.twhelpConnector.tribeTribeChanges(page, limit); + (cursor: string | undefined, limit: number) => { + return this.twhelpConnector.memberChanges(cursor, limit); } ).render(); } @@ -359,24 +396,24 @@ class UI { { header: t('OD'), accessor: (s) => - `${s.scoreTotal.toLocaleString()} (${ - s.rankTotal + `${s.opponentsDefeated.scoreTotal.toLocaleString()} (${ + s.opponentsDefeated.rankTotal })`, }, { header: t('ODA'), accessor: (s) => - `${s.scoreAtt.toLocaleString()} (${s.rankAtt})`, + `${s.opponentsDefeated.scoreAtt.toLocaleString()} (${s.opponentsDefeated.rankAtt})`, }, { header: t('ODD'), accessor: (s) => - `${s.scoreDef.toLocaleString()} (${s.rankDef})`, + `${s.opponentsDefeated.scoreDef.toLocaleString()} (${s.opponentsDefeated.rankDef})`, }, ], 30, - (page: number, limit: number) => { - return this.twhelpConnector.tribeSnapshots(page, limit); + (cursor: string | undefined, limit: number) => { + return this.twhelpConnector.tribeSnapshots(cursor, limit); } ).render(); } @@ -428,8 +465,8 @@ class UI { }, ], 30, - (page: number, limit: number) => { - return this.twhelpConnector.tribeEnnoblements(page, limit); + (cursor: string | undefined, limit: number) => { + return this.twhelpConnector.tribeEnnoblements(cursor, limit); } ).render(); } @@ -477,10 +514,10 @@ class UI { const member = this.members.find((m) => m.id === id); [ - (member?.rankAtt ?? 0).toString(), - (member?.rankDef ?? 0).toString(), - (member?.rankSup ?? 0).toString(), - (member?.rankTotal ?? 0).toString(), + (member?.opponentsDefeated.rankAtt ?? 0).toString(), + (member?.opponentsDefeated.rankDef ?? 0).toString(), + (member?.opponentsDefeated.rankSup ?? 0).toString(), + (member?.opponentsDefeated.rankTotal ?? 0).toString(), member?.lastActivityAt ? new Date(member.lastActivityAt).toLocaleString() : '-', @@ -501,9 +538,9 @@ class UI { class ExtendedTribeProfile { private readonly twhelpConnector: TWHelpConnector; - constructor(twhelpClient: TWHelpClient) { + constructor(apiBaseUrl: string) { this.twhelpConnector = new TWHelpConnector( - twhelpClient, + apiBaseUrl, window.game_data.market, window.game_data.world, this.getTribeId() @@ -543,9 +580,7 @@ class ExtendedTribeProfile { return; } - await new ExtendedTribeProfile( - new TWHelpClient(process.env.TWHELP_API_BASE_URL ?? '') - ) + await new ExtendedTribeProfile(process.env.TWHELP_API_BASE_URL ?? '') .run() .catch((err) => { console.log(err); diff --git a/src/extended-village-profile.user.ts b/src/extended-village-profile.user.ts index ada0e4f..f1a365c 100644 --- a/src/extended-village-profile.user.ts +++ b/src/extended-village-profile.user.ts @@ -1,8 +1,8 @@ import { createTranslationFunc } from './utils'; import { calcLoyalty } from './lib/tw'; import { Cache } from './lib/cache'; -import { TWHelpV2Client, Ennoblement, ServerConfig } from './lib/twhelpv2'; -import { DialogTableV2 } from './common/dialog-table-v2'; +import { TWHelpClient, Ennoblement, ServerConfig } from './lib/twhelp'; +import { DialogTable } from './common/dialog-table'; const t = createTranslationFunc({ pl_PL: { @@ -26,7 +26,7 @@ class TWHelpConnector { private cache = new Cache(localStorage); - private client: TWHelpV2Client; + private client: TWHelpClient; constructor( readonly baseUrl: string, @@ -34,7 +34,7 @@ class TWHelpConnector { private readonly server: string, private readonly id: number ) { - this.client = new TWHelpV2Client({ BASE: baseUrl }); + this.client = new TWHelpClient({ BASE: baseUrl }); } serverConfig() { @@ -151,7 +151,7 @@ class UI { private async showEnnoblements(e: Event) { e.preventDefault(); - await new DialogTableV2( + await new DialogTable( DialogId.ENNOBLEMENTS, [ { diff --git a/src/lib/twhelp.ts b/src/lib/twhelp.ts deleted file mode 100644 index 87147d4..0000000 --- a/src/lib/twhelp.ts +++ /dev/null @@ -1,424 +0,0 @@ -import axios, { - AxiosInstance, - AxiosResponseHeaders, - RawAxiosResponseHeaders, -} from 'axios'; - -export type ServerMeta = { - key: string; - open: boolean; -}; - -export type Tribe = { - id: number; - name: string; - tag: string; - numMembers: number; - numVillages: number; - points: number; - allPoints: number; - rank: number; - dominance: number; - rankAtt: number; - scoreAtt: number; - rankDef: number; - scoreDef: number; - rankTotal: number; - scoreTotal: number; - profileUrl: string; - bestRank: number; - bestRankAt: string; - mostPoints: number; - mostPointsAt: string; - mostVillages: number; - mostVillagesAt: string; - createdAt: string; - deletedAt: string | null; -}; - -export type TribeMeta = { - id: number; - name: string; - tag: string; - profileUrl: string; -}; - -export type Player = { - id: number; - points: number; - rank: number; - numVillages: number; - scoreAtt: number; - rankAtt: number; - scoreDef: number; - rankDef: number; - scoreSup: number; - rankSup: number; - scoreTotal: number; - rankTotal: number; - bestRank: number; - bestRankAt: string; - mostPoints: number; - mostPointsAt: string; - mostVillages: number; - mostVillagesAt: string; - lastActivityAt: string; - createdAt: string; - tribe: TribeMeta | null; -}; - -export type PlayerWithServer = Player & { - server: ServerMeta; -}; - -export type PlayerMeta = { - id: number; - name: string; - profileUrl: string; - tribe: TribeMeta | null; -}; - -export type VillageMeta = { - id: number; - fullName: string; - profileUrl: string; - x: number; - y: number; - continent: string; - player: PlayerMeta | null; -}; - -export type TribeChange = { - id: number; - newTribe: TribeMeta | null; - player: PlayerMeta; - createdAt: string; -}; - -export type Ennoblement = { - id: number; - points: number; - newOwner: PlayerMeta | null; - village: VillageMeta; - createdAt: string; -}; - -export type TribeSnapshot = { - id: number; - numMembers: number; - numVillages: number; - points: number; - allPoints: number; - rank: number; - dominance: number; - rankAtt: number; - scoreAtt: number; - rankDef: number; - scoreDef: number; - rankTotal: number; - scoreTotal: number; - date: string; -}; - -export type PlayerSnapshot = { - id: number; - tribe: TribeMeta | null; - points: number; - numVillages: number; - rank: number; - rankAtt: number; - rankDef: number; - rankSup: number; - rankTotal: number; - scoreAtt: number; - scoreDef: number; - scoreSup: number; - scoreTotal: number; - date: string; -}; - -export type ServerConfig = { - speed: number; - unitSpeed: number; - snob: { - maxDist: number; - }; -}; - -export type Unit = { - speed: number; -}; - -export type UnitInfo = { - archer: Unit; - axe: Unit; - catapult: Unit; - heavy: Unit; - knight: Unit; - light: Unit; - marcher: Unit; - militia: Unit; - ram: Unit; - snob: Unit; - spear: Unit; - spy: Unit; - sword: Unit; -}; - -export type ListResult = { - data: T[]; - total: number; -}; - -export type ListTribeChangesQueryParams = { - offset?: number; - limit?: number; - sort?: string[]; -}; - -export type ListEnnoblementsParams = { - offset?: number; - limit?: number; - sort?: string[]; -}; - -export type ListTribeMembers = { - offset?: number; - limit?: number; - sort?: string[]; -}; - -export type ListSnapshotsParams = { - offset?: number; - limit?: number; - sort?: string[]; -}; - -export type ListPlayerOtherServersParams = { - offset?: number; - limit?: number; -}; - -export class TWHelpClient { - client: AxiosInstance; - - constructor(url: string, timeout = 10000) { - this.client = axios.create({ - baseURL: url, - timeout, - }); - } - - public async serverConfig( - version: string, - server: string - ): Promise { - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/config` - ); - return resp.data.data; - } - - public async unitInfo(version: string, server: string): Promise { - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/unit-info` - ); - return resp.data.data; - } - - public async tribe( - version: string, - server: string, - id: number - ): Promise { - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/tribes/${id}` - ); - return resp.data.data; - } - - public async tribeSnapshots( - version: string, - server: string, - id: number, - queryParams?: ListSnapshotsParams - ): Promise> { - const queryString = queryParams ? this.buildQueryString(queryParams) : ''; - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/tribes/${id}/snapshots?${queryString}` - ); - return { - data: resp.data.data, - total: this.parseTotal(resp.headers), - }; - } - - public async tribeTribeChanges( - version: string, - server: string, - id: number, - queryParams?: ListTribeChangesQueryParams - ): Promise> { - const queryString = queryParams ? this.buildQueryString(queryParams) : ''; - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/tribes/${id}/tribe-changes?${queryString}` - ); - return { - data: resp.data.data, - total: this.parseTotal(resp.headers), - }; - } - - public async tribeEnnoblements( - version: string, - server: string, - id: number, - queryParams?: ListEnnoblementsParams - ): Promise> { - const queryString = queryParams ? this.buildQueryString(queryParams) : ''; - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/tribes/${id}/ennoblements?${queryString}` - ); - return { - data: resp.data.data, - total: this.parseTotal(resp.headers), - }; - } - - public async tribeMembers( - version: string, - server: string, - id: number, - queryParams?: ListTribeMembers - ): Promise> { - const queryString = queryParams ? this.buildQueryString(queryParams) : ''; - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/tribes/${id}/members?${queryString}` - ); - return { - data: resp.data.data, - total: this.parseTotal(resp.headers), - }; - } - - public async player( - version: string, - server: string, - id: number - ): Promise { - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/players/${id}` - ); - return resp.data.data; - } - - public async playerTribeChanges( - version: string, - server: string, - id: number, - queryParams?: ListTribeChangesQueryParams - ): Promise> { - const queryString = queryParams ? this.buildQueryString(queryParams) : ''; - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/players/${id}/tribe-changes?${queryString}` - ); - return { - data: resp.data.data, - total: this.parseTotal(resp.headers), - }; - } - - public async playerEnnoblements( - version: string, - server: string, - id: number, - queryParams?: ListEnnoblementsParams - ): Promise> { - const queryString = queryParams ? this.buildQueryString(queryParams) : ''; - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/players/${id}/ennoblements?${queryString}` - ); - return { - data: resp.data.data, - total: this.parseTotal(resp.headers), - }; - } - - public async playerSnapshots( - version: string, - server: string, - id: number, - queryParams?: ListSnapshotsParams - ): Promise> { - const queryString = queryParams ? this.buildQueryString(queryParams) : ''; - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/players/${id}/snapshots?${queryString}` - ); - return { - data: resp.data.data, - total: this.parseTotal(resp.headers), - }; - } - - public async playerOtherServers( - version: string, - server: string, - id: number, - queryParams?: ListPlayerOtherServersParams - ): Promise> { - const queryString = queryParams ? this.buildQueryString(queryParams) : ''; - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/players/${id}/other-servers?${queryString}` - ); - return { - data: resp.data.data, - total: this.parseTotal(resp.headers), - }; - } - - public async villageEnnoblements( - version: string, - server: string, - id: number, - queryParams?: ListEnnoblementsParams - ): Promise> { - const queryString = queryParams ? this.buildQueryString(queryParams) : ''; - const resp = await this.client.get( - `/api/v1/versions/${version}/servers/${server}/villages/${id}/ennoblements?${queryString}` - ); - return { - data: resp.data.data, - total: this.parseTotal(resp.headers), - }; - } - - private buildQueryString( - queryParams: Record - ): string { - const params = new URLSearchParams(); - - for (const [name, val] of Object.entries(queryParams)) { - if (Array.isArray(val)) { - val.forEach((s) => { - params.append(name, s); - }); - continue; - } - - if (val instanceof Date) { - params.set(name, val.toISOString()); - continue; - } - - params.set(name, val.toString()); - } - - return params.toString(); - } - - private parseTotal( - headers: RawAxiosResponseHeaders | AxiosResponseHeaders - ): number { - return parseInt(headers['x-total-count'] ?? '0'); - } -} diff --git a/src/lib/twhelpv2/.gitignore b/src/lib/twhelp/.gitignore similarity index 100% rename from src/lib/twhelpv2/.gitignore rename to src/lib/twhelp/.gitignore diff --git a/src/lib/twhelpv2/openapi3.json b/src/lib/twhelp/openapi3.json similarity index 100% rename from src/lib/twhelpv2/openapi3.json rename to src/lib/twhelp/openapi3.json