import axios, { AxiosInstance } from 'axios'; const DEFAULT_TIMEOUT = 10000; const X_TOTAL_COUNT_HEADER = 'x-total-count'; export type Version = { code: string; host: string; name: string; timezone: 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; }; export type TribeMeta = { id: number; name: string; tag: string; profileUrl: string; }; 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 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 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 ListPlayerSnapshotsParams = { offset?: number; limit?: number; sort?: string[]; }; export class TWHelpClient { client: AxiosInstance; constructor(url: string, timeout?: number) { this.client = axios.create({ baseURL: url, timeout: timeout ?? DEFAULT_TIMEOUT, }); } public async versions(): Promise> { const resp = await this.client.get('/api/v1/versions'); return { data: resp.data.data, total: parseInt(resp.headers[X_TOTAL_COUNT_HEADER] ?? '0'), }; } 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 params = new URLSearchParams(); if (queryParams?.limit) { params.set('limit', queryParams.limit.toString()); } if (queryParams?.offset) { params.set('offset', queryParams.offset.toString()); } if (Array.isArray(queryParams?.sort)) { queryParams?.sort.forEach((s) => { params.append('sort', s); }); } const resp = await this.client.get( `/api/v1/versions/${version}/servers/${server}/players/${id}/tribe-changes?${params.toString()}` ); return { data: resp.data.data, total: parseInt(resp.headers[X_TOTAL_COUNT_HEADER] ?? '0'), }; } public async playerEnnoblements( version: string, server: string, id: number, queryParams?: ListEnnoblementsParams ): Promise> { const params = new URLSearchParams(); if (queryParams?.limit) { params.set('limit', queryParams.limit.toString()); } if (queryParams?.offset) { params.set('offset', queryParams.offset.toString()); } if (Array.isArray(queryParams?.sort)) { queryParams?.sort.forEach((s) => { params.append('sort', s); }); } const resp = await this.client.get( `/api/v1/versions/${version}/servers/${server}/players/${id}/ennoblements?${params.toString()}` ); return { data: resp.data.data, total: parseInt(resp.headers[X_TOTAL_COUNT_HEADER] ?? '0'), }; } public async playerHistory( version: string, server: string, id: number, queryParams?: ListPlayerSnapshotsParams ): Promise> { const params = new URLSearchParams(); if (queryParams?.limit) { params.set('limit', queryParams.limit.toString()); } if (queryParams?.offset) { params.set('offset', queryParams.offset.toString()); } if (Array.isArray(queryParams?.sort)) { queryParams?.sort.forEach((s) => { params.append('sort', s); }); } const resp = await this.client.get( `/api/v1/versions/${version}/servers/${server}/players/${id}/history?${params.toString()}` ); return { data: resp.data.data, total: parseInt(resp.headers[X_TOTAL_COUNT_HEADER] ?? '0'), }; } }