Files
galvanic-corrosion-rewrite/src/util/steam/steam.ts
zombieb f19552929e galvanic corrosion rewrite
commit this before something goes horribly wrong
2025-08-12 21:04:52 -04:00

110 lines
4.2 KiB
TypeScript

/* Galvanic Corrosion - Rec Room custom server for communities.
<https://gitea.proxnet.dev/zombieb/galvanic-corrosion>
Copyright (C) 2025 @zombieb (Discord / proxnet Gitea)
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.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
import Logging from "@proxnet/undead-logging";
import { SteamAuth, SteamAuthResult, SteamAuthRes } from "./SteamAuthTypes.ts";
import { SteamPlayer } from "./SteamCommonTypes.ts";
const log = new Logging("Steam");
const steamkey = Deno.env.get("STEAMKEY");
function buildSteamUrl(steaminterface: string, endpoint: string) {
return `https://api.steampowered.com/${steaminterface}/${endpoint}`;
}
export enum PersonaState {
Offline,
Online,
Busy,
Away,
Snooze,
LookingToTrade,
LookingToPlay
}
export enum CommunityVisibilityState {
NotVisible,
PubliclyVisible = 3
}
class SteamBase {
async GetPlayerSummaries(steamids: string[]) {
if (!steamkey) return [];
const params = new URLSearchParams();
params.append('key', steamkey);
params.append('steamids', steamids.join(','))
try {
const res = await fetch(`${buildSteamUrl('ISteamUser', 'GetPlayerSummaries/v2')}?${params}`);
if (res.status !== 200) return [];
const resjson = await res.json() as { response: { players: SteamPlayer[] } };
return resjson.response.players;
} catch (err) {
log.e(`Could not fetch Steam player summaries: ${(err as Error).stack}`);
return [];
}
}
async AuthenticateUserTicket(ticket: string, userid: string): Promise<SteamAuth> {
if (!steamkey) return { valid: SteamAuthResult.NotConfigured }; // always authenticate if no steam API key was found
const params = new URLSearchParams();
params.append('key', steamkey);
params.append('appid', "471710");
params.append('ticket', ticket);
try {
const res = await fetch(`${buildSteamUrl('ISteamUserAuth', 'AuthenticateUserTicket/v1')}?${params}`);
const resjson = (await res.json()) as SteamAuthRes;
if (resjson.response.error) {
log.w(`Steam Authentication failed: (${resjson.response.error.errorcode}) ${resjson.response.error.errordesc}`);
// add more error codes later if needed
const conditions = [
resjson.response.error.errorcode == 100
].includes(true);
if (conditions) log.w('This error indicates a client problem.');
return { valid: SteamAuthResult.Failure, res: resjson.response.error };
}
//log.d(JSON.stringify(resjson.response));
if (resjson.response.params) {
// since rec room is not eligible for family sharing on Steam
const valid = resjson.response.params.steamid === userid && resjson.response.params.ownersteamid === userid;
if (valid) return { valid: SteamAuthResult.Success, res: resjson.response.params }
else throw new Error('`ownersteamid` is not equal to `steamid`, report me to GC devs!');
}
else {
log.w("Steam Authentication failed: Steam response did not contain params or error! This should never be logged!");
return { valid: SteamAuthResult.Failure, res: { errorcode: -1, errordesc: 'Steam response error' } };
}
} catch (err) {
log.w(`Steam Authentication failed: ${(err as Error).message}`);
return { valid: SteamAuthResult.Failure, res: { errorcode: -1, errordesc: 'Steam response error' } };
}
}
}
const Steam = new SteamBase();
export default Steam;