2025-04-11 16:48:47 +02:00

173 lines
5.5 KiB
TypeScript

/*
* Copyright (C) 2025 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 steamKeys: string[] = JSON.parse(process.env.STEAM_APIKEY!);
const steamFetch = (url: string) =>
{
let retries = 0;
return new Promise((res, _rej) =>
{
const req = () =>
{
const steamKey = steamKeys[ Math.floor(Math.random() * steamKeys.length) ];
fetch(url.replace("[STEAMKEY]", steamKey), { signal: AbortSignal.timeout(10000) }).then(x => x.json())
.then(x => res(x))
.catch(() =>
{
console.log("STEAM request failed! ", url.replace("[STEAMKEY]", steamKey), retries);
retries++;
setTimeout(() => req(), retries * 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=[STEAMKEY]&format=json&steamids=${ steamId }`) 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;
}
const trainStats: {
[ trainName: string ]: {
score: number,
distance: number
time: number,
}
} = {};
const dispatcherStats: {
[ name: string ]: {
time: number
}
} = {};
let trainPoints = 0;
let trainDistance = 0;
let dispatcherTime = 0;
if (stats)
{
trainStats[ "N/A" ] = {
score: stats?.stats?.find(x => x.name === "SCORE")?.value ?? 0,
distance: stats?.stats?.find(x => x.name === "DISTANCE_M")?.value ?? 0,
time: 0,
};
dispatcherStats[ "N/A" ] = {
time: (stats?.stats?.find(x => x.name === "DISPATCHER_TIME")?.value ?? 0) * 1000 * 60,
};
trainPoints = stats?.stats?.find(x => x.name === "SCORE")?.value ?? 0;
trainDistance = stats?.stats?.find(x => x.name === "DISTANCE_M")?.value ?? 0;
dispatcherTime = (stats?.stats?.find(x => x.name === "DISPATCHER_TIME")?.value ?? 0) * 1000 * 60;
}
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,
trainDistance,
trainTime: 0,
dispatcherTime,
flags: !stats ? [ "private" ] : [],
createdAt: Date.now(),
}).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=[STEAMKEY]&format=json&steamids=${ steamId }`) 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=[STEAMKEY]&steamid=${ steamId }`) as IPlayerStatsPayload;
if (!data.playerstats?.stats)
{
return undefined;
}
return data.playerstats;
}
}