battlemetrics-wrapper
Version:
a wrapper for the battlemetrics API based on GnomeSlayer's python version
463 lines (414 loc) • 11 kB
text/typescript
import {
GenericAPIResponse,
DataPoint,
Identifier,
} from "../../types/battlemetrics/battlemetricsTypes.js";
import { RelatedIdentifier } from "../../types/battlemetrics/relatedIdentifier.js";
import Helpers from "./helpers.js";
import { URLSearchParams } from "url";
import { randomUUID } from "node:crypto";
import {
Ban,
CoplayRelation,
FlagPlayer,
PlayHistory,
PlayerIdentifier,
PlayerNote,
} from "../../types/battlemetrics/playerTypes.js";
type SearchOptions = {
search?: string;
filterGame?: string;
filterOnline?: boolean;
filterServers?: number;
filterOrganization?: number;
filterPublic?: boolean;
flag?: string;
};
type PlayHistoryParams = {
playerId: number;
serverId: number;
startTime?: string;
endTime?: string;
};
type AddBanParams = {
reason: string;
note: string;
orgId: string;
banlist: string;
serverId: string;
expires?: string;
orgwide?: boolean;
battlemetricsId?: number;
steamId?: number;
};
type addNoteParams = {
note: string;
organizationId: number;
playerId: number;
shared: boolean;
};
type coplayInfoParam = {
playerId: number;
timeStart?: string;
timeEnd?: string;
playerNames?: string;
organizationNames?: string;
serverNames?: string;
};
type sessionHistoryParams = {
playerId: number;
filterServer?: string;
filterOrganization?: string;
};
export default class Player {
public constructor(private helpers: Helpers) {}
public async identifiers(playerID: number) {
const path = `/players/${playerID}/relationships/related-identifiers`;
const params = new URLSearchParams({
include: "player,identifier",
"page[size]": "100",
});
return await this.helpers.makeRequest<
GenericAPIResponse<PlayerIdentifier[]>
>({
method: "GET",
path,
params,
});
}
public async search(options: SearchOptions = {}) {
const {
search,
filterServers,
filterOrganization,
filterPublic,
flag,
filterOnline,
filterGame,
} = options;
const data: any = {
"page[size]": "100",
include: "server,identifier,playerFlag,flagPlayer",
};
if (search) data["filter[search]"] = search;
if (filterServers) data["filter[server]"] = filterServers;
if (filterOrganization) data["filter[organization]"] = filterOrganization;
if (flag) data["filter[playerFlags]"] = flag;
data["filter[online]"] = filterOnline ? "true" : "false";
data["filter[public]"] = filterPublic ? "true" : "false";
if (filterGame) {
// Assuming you need to set game on server object (based on the original code)
// This part may need adjustment depending on the actual structure of the request.
data.server = {
game: filterGame,
};
}
return await this.helpers.makeRequest<RelatedIdentifier[]>({
method: "GET",
path: "/players",
params: new URLSearchParams(data),
});
}
public async info(identifier: number) {
const path: string = `/players/${identifier}`;
const params = new URLSearchParams({
include: "identifier,server,playerCounter,playerFlag,flagPlayer",
});
return await this.helpers.makeRequest<GenericAPIResponse<Player>>({
method: "GET",
path,
params,
});
}
public async playHistory({
playerId,
serverId,
startTime,
endTime,
}: PlayHistoryParams) {
const now: Date = new Date();
if (!startTime) {
const startDate: Date = new Date(now.getTime() - 5 * 24 * 60 * 60 * 1000); // 5 days ago
startTime = startDate.toISOString();
}
if (!endTime) {
const endDate: Date = new Date(now.getTime() + 24 * 60 * 60 * 1000); // 1 day from now
endTime = endDate.toISOString();
}
const path = `/players/${playerId}/time-played-history/${serverId}`;
const params = new URLSearchParams({
start: startTime,
stop: endTime,
});
return await this.helpers.makeRequest<PlayHistory>({
method: "GET",
path,
params,
});
}
public async serverInfo(playerId: number, serverId: number): Promise<any> {
// Change 'any' to a more specific type if you know the structure of the response
return await this.helpers.makeRequest({
method: "GET",
path: `/players/${playerId}/servers/${serverId}`,
params: new URLSearchParams(""),
});
}
public async matchIdentifiers(
identifier: string,
identifierType?: string
): Promise<any> {
// TODO: define type after create html parser
const path = `/players/match?include=player,server,identifier,playerFlag,flagPlayer`;
const data = JSON.stringify({
data: [
{
type: "identifier",
attributes: {
type: identifierType,
identifier: identifier,
},
},
],
});
return await this.helpers.makeRequest({ method: "POST", path, data });
}
public async sessionHistory({
playerId,
filterServer,
filterOrganization,
}: sessionHistoryParams): Promise<GenericAPIResponse<Player>> {
const path = `/players/${playerId}/relationships/sessions`;
const data: any = {
include: "identifier,server",
"page[size]": "100",
};
if (filterServer) {
data["filter[servers]"] = filterServer;
}
if (filterOrganization) {
data["filter[organizations]"] = filterOrganization;
}
const params = new URLSearchParams(data);
return await this.helpers.makeRequest({
method: "GET",
path,
params,
});
}
public async addFlag(playerId: number, flagId?: string) {
const path = `/players/${playerId}/relationships/flags`;
const data: { data: { type: string; id?: string }[] } = {
data: [
{
type: "playerFlag",
},
],
};
if (flagId) {
data.data[0].id = flagId;
}
return await this.helpers.makeRequest<FlagPlayer>({
method: "POST",
path,
data: JSON.stringify(data),
});
}
public async flags(playerId: number) {
const params = new URLSearchParams({
"page[size]": "100",
include: "playerFlag",
});
return await this.helpers.makeRequest<FlagPlayer>({
method: "GET",
path: `/players/${playerId}/relationships/flags`,
params,
});
}
public async deleteFlag(playerId: number, flagId: string) {
const path: string = `/players/${playerId}/relationships/flags/${flagId}`;
return await this.helpers.makeRequest<FlagPlayer>({
method: "DELETE",
path,
data: "",
});
}
public async coplayInfo({
playerId,
timeStart,
timeEnd,
playerNames,
organizationNames,
serverNames,
}: coplayInfoParam) {
if (!timeStart) {
const now = new Date();
now.setDate(now.getDate() - 1);
timeStart = now.toISOString();
}
if (!timeEnd) {
timeEnd = new Date().toISOString();
}
const data: any = {
"filter[period]": `${timeStart}:${timeEnd}`,
"page[size]": "100",
"fields[coplayRelation]": "name,duration",
};
if (playerNames) {
data["filter[players]"] = playerNames;
}
if (organizationNames) {
data["filter[organizations]"] = organizationNames;
}
if (serverNames) {
data["filter[servers]"] = serverNames;
}
const path: string = `/players/${playerId}/relationships/coplay`;
return await this.helpers.makeRequest<CoplayRelation[]>({
method: "GET",
path,
params: new URLSearchParams(data),
});
}
public async quickMatch(identifier: string, identifierType: string) {
const path: string = "/players/quick-match";
const data = JSON.stringify({
data: [
{
type: "identifier",
attributes: {
type: identifierType,
identifier: identifier,
},
},
],
});
return await this.helpers.makeRequest<PlayerIdentifier>({
method: "POST",
path,
data,
});
}
public async addNote({
note,
organizationId,
playerId,
shared = true,
}: addNoteParams) {
const path = `/players/${playerId}/relationships/notes`;
const data = JSON.stringify({
data: {
type: "playerNote",
attributes: {
note: note,
shared: shared,
},
relationships: {
organization: {
data: {
type: "organization",
id: organizationId.toString(),
},
},
},
},
});
return await this.helpers.makeRequest<PlayerNote>({
method: "POST",
path,
data,
});
}
public async addBan({
reason,
note,
orgId,
banlist,
serverId,
expires,
orgwide = true,
battlemetricsId,
steamId,
}: AddBanParams) {
if (expires) {
expires = this.helpers.calculateFutureDate(expires);
}
const data = {
data: {
type: "ban",
attributes: {
uid: randomUUID().slice(0, 14),
reason,
note,
expires,
identifiers: [],
orgWide: orgwide,
autoAddEnabled: true,
nativeEnabled: null,
},
relationships: {
organization: {
data: {
type: "organization",
id: `${orgId}`,
},
},
server: {
data: {
type: "server",
id: `${serverId}`,
},
},
player: {
data: {
type: "player",
id: `${battlemetricsId}`,
},
},
banList: {
data: {
type: "banList",
id: `${banlist}`,
},
},
},
},
};
if (!steamId && !battlemetricsId) {
throw new Error(
"Please submit either a STEAM IDENTIFIER or BATTLEMETRICS IDENTIFIER"
);
}
let bmid: string | undefined;
if (steamId && !battlemetricsId) {
const battlemetricsIdentifiers = await this.matchIdentifiers(
steamId.toString(),
"steamID"
);
bmid = battlemetricsIdentifiers.data[0].relationships.player.data
.id as string;
}
if (bmid) {
const playerInfo = await this.info(Number(battlemetricsId));
if (!playerInfo?.included) {
throw new Error(`Couldn't find ${battlemetricsId}`);
}
for (const included of playerInfo.included) {
if (included.type === "identifier") {
if (
included.attributes.type === "BEGUID" ||
included.attributes.type === "steamID"
) {
const identifiers: number[] = data.data.attributes.identifiers;
identifiers.push(parseInt(included.id));
}
}
}
}
return await this.helpers.makeRequest<Ban>({
method: "POST",
path: `/bans`,
data: JSON.stringify(data),
});
}
}