scripts/src/lib/twhelp.ts

425 lines
9.4 KiB
TypeScript

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<T> = {
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<ServerConfig> {
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<UnitInfo> {
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<Tribe> {
const resp = await this.client.get(
`/api/v1/versions/${version}/servers/${server}/tribes/${id}`
);
return resp.data.data;
}
public async tribeHistory(
version: string,
server: string,
id: number,
queryParams?: ListSnapshotsParams
): Promise<ListResult<TribeSnapshot>> {
const queryString = queryParams ? this.buildQueryString(queryParams) : '';
const resp = await this.client.get(
`/api/v1/versions/${version}/servers/${server}/tribes/${id}/history?${queryString}`
);
return {
data: resp.data.data,
total: this.parseTotal(resp.headers),
};
}
public async tribeTribeChanges(
version: string,
server: string,
id: number,
queryParams?: ListTribeChangesQueryParams
): Promise<ListResult<TribeChange>> {
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<ListResult<Ennoblement>> {
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<ListResult<Player>> {
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<Player> {
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<ListResult<TribeChange>> {
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<ListResult<Ennoblement>> {
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 playerHistory(
version: string,
server: string,
id: number,
queryParams?: ListSnapshotsParams
): Promise<ListResult<PlayerSnapshot>> {
const queryString = queryParams ? this.buildQueryString(queryParams) : '';
const resp = await this.client.get(
`/api/v1/versions/${version}/servers/${server}/players/${id}/history?${queryString}`
);
return {
data: resp.data.data,
total: this.parseTotal(resp.headers),
};
}
public async playerOtherServers(
version: string,
server: string,
id: number,
queryParams?: ListPlayerOtherServersParams
): Promise<ListResult<PlayerWithServer>> {
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<ListResult<Ennoblement>> {
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, string | boolean | number | Date | string[]>
): 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');
}
}