forked from simrail/simrail.pro
Merge pull request 'fix some issues' (#22) from v2 into main
Reviewed-on: alekswilc/simrail-logs#22
This commit is contained in:
commit
42d46e32b3
@ -2,15 +2,38 @@ import { IPlayerPayload, IPlayerStatsPayload } from '../types/player.js';
|
||||
|
||||
const STEAM_API_KEY = process.env.STEAM_APIKEY;
|
||||
|
||||
const fetchFuckingSteamApi = (url: string) => {
|
||||
let retries = 0;
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
const req = () => {
|
||||
if (retries > 5) 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(), 500);
|
||||
})
|
||||
}
|
||||
req();
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export class PlayerUtil {
|
||||
public static async getPlayer(steamId: number | string) {
|
||||
const data = (await fetch(`https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=${STEAM_API_KEY}&format=json&steamids=${steamId}`).then(x => x.json())) as IPlayerPayload;
|
||||
const data = await fetchFuckingSteamApi(`https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=${STEAM_API_KEY}&format=json&steamids=${steamId}`) as IPlayerPayload;
|
||||
|
||||
if (!data.response.players) return;
|
||||
return data.response.players[0];
|
||||
}
|
||||
|
||||
public static async getPlayerStats(steamId: string) {
|
||||
const data = (await fetch(`http://api.steampowered.com/ISteamUserStats/GetUserStatsForGame/v0002/?appid=1422130&key=${STEAM_API_KEY}&steamid=${steamId}`).then(x => x.json())) as IPlayerStatsPayload;
|
||||
const data = await fetchFuckingSteamApi(`http://api.steampowered.com/ISteamUserStats/GetUserStatsForGame/v0002/?appid=1422130&key=${STEAM_API_KEY}&steamid=${steamId}`) as IPlayerStatsPayload;
|
||||
|
||||
|
||||
if (!data.playerstats?.stats) return;
|
||||
return data.playerstats;
|
||||
}
|
||||
|
@ -78,122 +78,140 @@ export class SimrailClient extends EventEmitter {
|
||||
this.trainsOccupied = (await redis.json.get('trains_occupied') as unknown as SimrailClient['trainsOccupied']);
|
||||
}
|
||||
|
||||
private async processStation(server: Server, stations: ApiResponse<Station>) {
|
||||
if (stations.result) {
|
||||
if (!this.stations[server.ServerCode]) this.stations[server.ServerCode] = [];
|
||||
if (!this.stationsOccupied[server.ServerCode]) this.stationsOccupied[server.ServerCode] = {};
|
||||
|
||||
if (!this.stations[server.ServerCode].length) {
|
||||
this.stations[server.ServerCode] = stations.data;
|
||||
redis.json.set('stations', '$', this.stations);
|
||||
|
||||
}
|
||||
|
||||
stations.data.forEach(async (x) => {
|
||||
const data = this.stations[server.ServerCode].find(y => y.Name === x.Name);
|
||||
if (!data) return;
|
||||
|
||||
if (data.DispatchedBy[0]?.SteamId !== x.DispatchedBy[0]?.SteamId) {
|
||||
if (!data.DispatchedBy[0]?.SteamId) {
|
||||
// join
|
||||
const date = new Date();
|
||||
const player = await PlayerUtil.getPlayer(x.DispatchedBy[0]?.SteamId);
|
||||
|
||||
this.emit(SimrailClientEvents.StationJoined, server, x, player);
|
||||
this.stationsOccupied[server.ServerCode][data.Prefix] = {
|
||||
SteamId: x.DispatchedBy[0]?.SteamId,
|
||||
JoinedAt: date.getTime()
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
// leave
|
||||
const player = await PlayerUtil.getPlayer(data.DispatchedBy[0]?.SteamId)
|
||||
|
||||
this.emit(SimrailClientEvents.StationLeft, server, x, player, this.stationsOccupied[server.ServerCode][data.Prefix]?.JoinedAt);
|
||||
delete this.stationsOccupied[server.ServerCode][data.Prefix];
|
||||
|
||||
}
|
||||
})
|
||||
redis.json.set('stations_occupied', '$', this.stationsOccupied);
|
||||
|
||||
this.stations[server.ServerCode] = stations.data;
|
||||
redis.json.set('stations', '$', this.stations);
|
||||
}
|
||||
}
|
||||
|
||||
private async processTrain(server: Server, trains: ApiResponse<Train>) {
|
||||
if (trains.result) {
|
||||
if (!this.trains[server.ServerCode]) this.trains[server.ServerCode] = [];
|
||||
if (!this.trainsOccupied[server.ServerCode]) this.trainsOccupied[server.ServerCode] = {};
|
||||
|
||||
if (!this.trains[server.ServerCode].length) {
|
||||
this.trains[server.ServerCode] = trains.data;
|
||||
|
||||
redis.json.set('trains', '$', this.trains);
|
||||
return;
|
||||
}
|
||||
|
||||
trains.data.forEach(async (x) => {
|
||||
const data = this.trains[server.ServerCode].find(y => y.id === x.id);
|
||||
if (!data) return;
|
||||
|
||||
if (data.TrainData.ControlledBySteamID !== x.TrainData.ControlledBySteamID) {
|
||||
|
||||
if (!data.TrainData.ControlledBySteamID) {
|
||||
if (!x.TrainData.ControlledBySteamID) return;
|
||||
// join
|
||||
const date = new Date();
|
||||
|
||||
const player = await PlayerUtil.getPlayer(x.TrainData.ControlledBySteamID!);
|
||||
|
||||
const playerStats = await PlayerUtil.getPlayerStats(x.TrainData.ControlledBySteamID!);
|
||||
|
||||
|
||||
this.emit(SimrailClientEvents.TrainJoined, server, x, player, playerStats?.stats.find(x => x.name === 'DISTANCE_M')?.value);
|
||||
|
||||
this.trainsOccupied[server.ServerCode][x.TrainNoLocal] = {
|
||||
SteamId: x.TrainData.ControlledBySteamID!,
|
||||
JoinedAt: date.getTime(),
|
||||
StartPlayerDistance: playerStats?.stats.find(x => x.name === 'DISTANCE_M')?.value!,
|
||||
StartPlayerPoints: playerStats?.stats.find(x => x.name === "SCORE")?.value!,
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.TrainData.ControlledBySteamID) return;
|
||||
const date = new Date();
|
||||
|
||||
const player = await PlayerUtil.getPlayer(data.TrainData.ControlledBySteamID!);
|
||||
|
||||
const playerId = data.TrainData.ControlledBySteamID!;
|
||||
const trainOccupied = this.trainsOccupied[server.ServerCode][data.TrainNoLocal] && JSON.parse(JSON.stringify(this.trainsOccupied[server.ServerCode][data.TrainNoLocal])) || null;
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
|
||||
PlayerUtil.getPlayerStats(playerId).then(playerStats => {
|
||||
const oldKm = trainOccupied?.StartPlayerDistance ?? 0;
|
||||
|
||||
const distance = oldKm ? (playerStats?.stats.find(x => x.name === 'DISTANCE_M')?.value ?? 0) - oldKm : 0;
|
||||
|
||||
const oldPoints = trainOccupied?.StartPlayerPoints ?? 0;
|
||||
|
||||
const points = oldPoints ? (playerStats?.stats.find(x => x.name === 'SCORE')?.value ?? 0) - oldPoints : 0;
|
||||
|
||||
|
||||
this.emit(SimrailClientEvents.TrainLeft, server, data, player, trainOccupied?.JoinedAt, date.getTime(), points, distance, x.Vehicles[0]);
|
||||
})
|
||||
}, 80_000)
|
||||
delete this.trainsOccupied[server.ServerCode][data.TrainNoLocal];
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
this.trains[server.ServerCode] = trains.data;
|
||||
redis.json.set('trains', '$', this.trains);
|
||||
redis.json.set('trains_occupied', '$', this.trainsOccupied);
|
||||
}
|
||||
}
|
||||
|
||||
private async update() {
|
||||
const servers = (await fetch('https://panel.simrail.eu:8084/servers-open').then(x => x.json()).catch(x => ({data: [], result: false})) as ApiResponse<Server>)
|
||||
const servers = (await fetch('https://panel.simrail.eu:8084/servers-open').then(x => x.json()).catch(x => ({ data: [], result: false })) as ApiResponse<Server>)
|
||||
.data?.filter(x => x.ServerName.includes('Polski')) ?? []; // no plans to support other servers
|
||||
|
||||
|
||||
if (!servers.length) console.log('SimrailAPI is down')
|
||||
|
||||
// TODO: maybe node:worker_threads?
|
||||
// TODO: check performance
|
||||
servers.forEach(async (server) => {
|
||||
const stations = (await fetch('https://panel.simrail.eu:8084/stations-open?serverCode=' + server.ServerCode).then(x => x.json()).catch(() => ({ result: false }))) as ApiResponse<Station>;
|
||||
const trains = (await fetch('https://panel.simrail.eu:8084/trains-open?serverCode=' + server.ServerCode).then(x => x.json()).catch(() => ({ result: false }))) as ApiResponse<Train>;
|
||||
if (stations.result) {
|
||||
if (!this.stations[server.ServerCode]) this.stations[server.ServerCode] = [];
|
||||
if (!this.stationsOccupied[server.ServerCode]) this.stationsOccupied[server.ServerCode] = {};
|
||||
const stations = (await fetch('https://panel.simrail.eu:8084/stations-open?serverCode=' + server.ServerCode).then(x => x.json()).catch(() => ({ result: false }))) as ApiResponse<Station>;
|
||||
const trains = (await fetch('https://panel.simrail.eu:8084/trains-open?serverCode=' + server.ServerCode).then(x => x.json()).catch(() => ({ result: false }))) as ApiResponse<Train>;
|
||||
|
||||
if (!this.stations[server.ServerCode].length) {
|
||||
this.stations[server.ServerCode] = stations.data;
|
||||
redis.json.set('stations', '$', this.stations);
|
||||
return;
|
||||
}
|
||||
this.processStation(server, stations);
|
||||
this.processTrain(server, trains);
|
||||
|
||||
stations.data.forEach(async (x) => {
|
||||
const data = this.stations[server.ServerCode].find(y => y.Name === x.Name);
|
||||
if (!data) return;
|
||||
|
||||
if (data.DispatchedBy[0]?.SteamId !== x.DispatchedBy[0]?.SteamId) {
|
||||
if (!data.DispatchedBy[0]?.SteamId) {
|
||||
// join
|
||||
const date = new Date();
|
||||
const player = await PlayerUtil.getPlayer(x.DispatchedBy[0]?.SteamId);
|
||||
|
||||
this.emit(SimrailClientEvents.StationJoined, server, x, player);
|
||||
this.stationsOccupied[server.ServerCode][data.Prefix] = {
|
||||
SteamId: x.DispatchedBy[0]?.SteamId,
|
||||
JoinedAt: date.getTime()
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
// leave
|
||||
const player = await PlayerUtil.getPlayer(data.DispatchedBy[0]?.SteamId)
|
||||
|
||||
this.emit(SimrailClientEvents.StationLeft, server, x, player, this.stationsOccupied[server.ServerCode][data.Prefix]?.JoinedAt);
|
||||
delete this.stationsOccupied[server.ServerCode][data.Prefix];
|
||||
|
||||
}
|
||||
})
|
||||
redis.json.set('stations_occupied', '$', this.stationsOccupied);
|
||||
|
||||
this.stations[server.ServerCode] = stations.data;
|
||||
redis.json.set('stations', '$', this.stations);
|
||||
}
|
||||
|
||||
if (trains.result) {
|
||||
if (!this.trains[server.ServerCode]) this.trains[server.ServerCode] = [];
|
||||
if (!this.trainsOccupied[server.ServerCode]) this.trainsOccupied[server.ServerCode] = {};
|
||||
|
||||
if (!this.trains[server.ServerCode].length) {
|
||||
this.trains[server.ServerCode] = trains.data;
|
||||
redis.json.set('trains', '$', this.trains);
|
||||
return;
|
||||
}
|
||||
|
||||
trains.data.forEach(async (x) => {
|
||||
const data = this.trains[server.ServerCode].find(y => y.id === x.id);
|
||||
if (!data) return;
|
||||
|
||||
if (data.TrainData.ControlledBySteamID !== x.TrainData.ControlledBySteamID) {
|
||||
if (!data.TrainData.ControlledBySteamID) {
|
||||
if (!x.TrainData.ControlledBySteamID) return;
|
||||
// join
|
||||
const date = new Date();
|
||||
const player = await PlayerUtil.getPlayer(x.TrainData.ControlledBySteamID!);
|
||||
const playerStats = await PlayerUtil.getPlayerStats(x.TrainData.ControlledBySteamID!);
|
||||
|
||||
this.emit(SimrailClientEvents.TrainJoined, server, x, player, playerStats?.stats.find(x => x.name === 'DISTANCE_M')?.value);
|
||||
|
||||
this.trainsOccupied[server.ServerCode][x.TrainNoLocal] = {
|
||||
SteamId: x.TrainData.ControlledBySteamID!,
|
||||
JoinedAt: date.getTime(),
|
||||
StartPlayerDistance: playerStats?.stats.find(x => x.name === 'DISTANCE_M')?.value!,
|
||||
StartPlayerPoints: playerStats?.stats.find(x => x.name === "SCORE")?.value!,
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.TrainData.ControlledBySteamID) return;
|
||||
const date = new Date();
|
||||
|
||||
const player = await PlayerUtil.getPlayer(data.TrainData.ControlledBySteamID!);
|
||||
const playerId = data.TrainData.ControlledBySteamID!;
|
||||
const trainOccupied = this.trainsOccupied[server.ServerCode][data.TrainNoLocal];
|
||||
|
||||
setTimeout(async () => {
|
||||
const playerStats = await PlayerUtil.getPlayerStats(playerId);
|
||||
const oldKm = trainOccupied?.StartPlayerDistance ?? 0;
|
||||
|
||||
const distance = oldKm ? (playerStats?.stats.find(x => x.name === 'DISTANCE_M')?.value ?? 0) - oldKm : 0;
|
||||
|
||||
const oldPoints = trainOccupied?.StartPlayerPoints ?? 0;
|
||||
const points = oldPoints ? (playerStats?.stats.find(x => x.name === 'SCORE')?.value ?? 0) - oldPoints : 0;
|
||||
|
||||
|
||||
this.emit(SimrailClientEvents.TrainLeft, server, data, player, trainOccupied?.JoinedAt, date.getTime(), points, distance, x.Vehicles[0]);
|
||||
}, 60000)
|
||||
delete this.trainsOccupied[server.ServerCode][data.TrainNoLocal];
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
this.trains[server.ServerCode] = trains.data;
|
||||
redis.json.set('trains', '$', this.trains);
|
||||
redis.json.set('trains_occupied', '$', this.trainsOccupied);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user