127 lines
4.1 KiB
TypeScript
127 lines
4.1 KiB
TypeScript
/*
|
|
* Copyright (C) 2024 Aleksander <alekswilc> Wilczyński (aleks@alekswilc.dev)
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published
|
|
* by the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* See LICENSE for more.
|
|
*/
|
|
|
|
import { IPlayerPayload, IPlayerStatsPayload } from "../types/player.js";
|
|
import { MProfile } from "../mongo/profile.js";
|
|
import { assert } from "node:console";
|
|
|
|
const STEAM_API_KEY = process.env.STEAM_APIKEY;
|
|
|
|
const steamFetch = (url: string, maxRetries: number = 5) =>
|
|
{
|
|
let retries = 0;
|
|
|
|
return new Promise((res, _rej) =>
|
|
{
|
|
const req = () =>
|
|
{
|
|
if (retries > maxRetries)
|
|
{
|
|
throw new Error("request failed to api steam");
|
|
}
|
|
fetch(url, { signal: AbortSignal.timeout(10000) }).then(x => x.json())
|
|
.then(x => res(x))
|
|
.catch(() =>
|
|
{
|
|
console.log("STEAM request failed! ", url.replace(STEAM_API_KEY!, "[XXX]"), retries);
|
|
|
|
retries++;
|
|
setTimeout(() => req(), 1000);
|
|
});
|
|
};
|
|
req();
|
|
});
|
|
};
|
|
|
|
|
|
export class PlayerUtil
|
|
{
|
|
public static async ensurePlayer(steamId: number | string)
|
|
{
|
|
assert(steamId, "expected steamId to be a string or a number");
|
|
steamId = steamId.toString();
|
|
let player = await MProfile.findOne({ id: steamId });
|
|
|
|
if (!player)
|
|
{
|
|
const data = await steamFetch(`https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=${ STEAM_API_KEY }&format=json&steamids=${ steamId }`, 20) as IPlayerPayload;
|
|
|
|
assert(data.response.players, "Expected data.response.players to be truthy")
|
|
|
|
const stats = await this.getPlayerStats(steamId);
|
|
|
|
player = await MProfile.findOne({ id: steamId });
|
|
if (player) return player;
|
|
|
|
player = await MProfile.create({
|
|
id: steamId,
|
|
username: data.response.players[ 0 ].personaname,
|
|
avatar: data.response.players[ 0 ].avatarfull,
|
|
|
|
steamDispatcherTime: stats?.stats?.find(x => x.name === "DISPATCHER_TIME")?.value ?? 0,
|
|
steamTrainScore: stats?.stats?.find(x => x.name === "SCORE")?.value ?? 0,
|
|
steamTrainDistance: stats?.stats?.find(x => x.name === "DISTANCE_M")?.value ?? 0,
|
|
|
|
trainStats: {},
|
|
dispatcherStats: {},
|
|
|
|
trainPoints: 0,
|
|
trainDistance: 0,
|
|
trainTime: 0,
|
|
|
|
dispatcherTime: 0,
|
|
|
|
flags: !stats ? [ 'private' ] : []
|
|
}).catch(e => e);
|
|
|
|
if (player instanceof Error)
|
|
player = await MProfile.findOne({ id: steamId });
|
|
|
|
}
|
|
|
|
assert(player, "expected player to be truthy");
|
|
|
|
return player;
|
|
}
|
|
|
|
public static async getPlayer(steamId: string) {
|
|
const player = await MProfile.findOne({ id: steamId });
|
|
|
|
if (!player) return undefined;
|
|
|
|
return player;
|
|
}
|
|
|
|
public static async getPlayerSteamData(steamId: string) {
|
|
const data = await steamFetch(`https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=${ STEAM_API_KEY }&format=json&steamids=${ steamId }`, 5) as IPlayerPayload;
|
|
|
|
if (!data?.response?.players?.length)
|
|
return undefined;
|
|
|
|
return data.response.players[0];
|
|
}
|
|
|
|
public static async getPlayerStats(steamId: string)
|
|
{
|
|
const data = await steamFetch(`https://api.steampowered.com/ISteamUserStats/GetUserStatsForGame/v0002/?appid=1422130&key=${ STEAM_API_KEY }&steamid=${ steamId }`) as IPlayerStatsPayload;
|
|
|
|
if (!data.playerstats?.stats)
|
|
{
|
|
return undefined;
|
|
}
|
|
return data.playerstats;
|
|
}
|
|
} |