-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathSteamRPC.js
159 lines (136 loc) · 6.97 KB
/
SteamRPC.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import { readdir } from "node:fs/promises";
import DiscordRPC from "@xhayper/discord-rpc";
import SteamID from "steamid";
import fetch from "node-fetch";
import LogUpdate from "log-update";
// ==================== Configuration Settings =====================
// Steam user identification
// You'll need to find your own SteamID64 URL using https://steamrep.com
// Note: This also allows custom URLs like https://steamcommunity.com/id/crementif but they require providing a valid web key.
const steamProfileURL = "https://steamcommunity.com/profiles/76561198259089872";
// ONLY needs to be replaced if you use a custom URL in the steamProfileURL variable above. There's no real benefit!
// You can get one from https://steamcommunity.com/dev/apikey. Use localhost as the domain name.
const steamWebKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
// Advanced Configuration Settings
const pollRate = 20*1000; // Poll Steam Rich Presence every n seconds. You should keep this at or above 20 seconds.
const discordClientId = "433731243516100629"; // Keep this id unless you want to supply your own application id.
// =================================================================
// Initialize Status Variables
let gameStatus = "";
let discordStatus = "logging in";
let steamStatus = "obtaining user id";
let debugLine = "";
// Initialize Discord Objects
const discordRPCClient = new DiscordRPC.Client({
clientId: discordClientId,
transport: "ipc"
});
// Setup discord RPC
discordRPCClient.on("ready", () => {
discordStatus = "connected (IPC)";
renderWindow();
});
discordRPCClient.on("error", (err, message) => {
discordStatus = `error ${err}: ${message}`;
renderWindow();
});
// =================================================================
// Logging
let currSpinFrame = 0;
function renderWindow() {
const spinFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
currSpinFrame++;
if (currSpinFrame == 10) currSpinFrame = 0;
LogUpdate(
`Steam: ${!steamStatus.startsWith("connected") ? steamStatus+spinFrames[currSpinFrame] : steamStatus}\n` +
`Discord: ${discordStatus+(discordStatus!=="connected (IPC)" ? " "+spinFrames[currSpinFrame] : "")}\n` +
`Game: ${gameStatus}\n` +
`\n` +
`> ${debugLine}\n`
);
};
// =================================================================
// SteamRPC Logic
async function getSteamUserId() {
if (steamProfileURL.startsWith("https://steamcommunity.com/id/")) {
let res = await fetch(`https://api.steampowered.com/ISteamUser/ResolveVanityURL/v1/?key=${steamWebKey}&vanityurl=${steamProfileURL.split("id/")[1].split("/")[0]}`);
if (res.ok) {
let resJson = await res.json();
if (resJson.response.success == 1) return new SteamID(resJson.response.steamid);
}
}
else if (steamProfileURL.startsWith("https://steamcommunity.com/profiles/")) {
return new SteamID(steamProfileURL.split("profiles/")[1].split("/")[0]);
}
}
async function loadProfiles() {
let profiles = {};
let profileFolders = (await readdir("profiles")).filter((folder) => folder != "ExampleProfile");
for (const folder of profileFolders) {
try {
let profile = await import(`./profiles/${folder}/index.js`);
if (typeof profile.title != "string") throw "Exported 'title' couldn't be found or isn't a valid string type!";
if (typeof profile.appID != "number") throw "Exported 'appID' couldn't be found or isn't a valid number type!";
if (typeof profile.translateSteamPresence != "function") throw "Exported 'translateSteamPresence' function couldn't be found or isn't a valid function type!";
if (profiles.hasOwnProperty(profile.appID)) throw `Found two profiles that export the same appID ${profile.appID}! Make sure to change the appID variable in each profile!`;
profiles[profile.appID] = profile;
}
catch (err) {
throw new Error(`An error occured while trying to load the profile from "profiles/${folder}"!`, {cause: err});
}
debugLine = `[${Object.keys(profiles).length}/${profileFolders.length}] Loading '${folder}'...`;
renderWindow();
}
debugLine = `Finished loading ${Object.keys(profiles).length} profile(s), waiting for Steam Rich Presence events...`;
return profiles;
}
async function pollSteamPresence(steamUserId, profiles) {
// todo: Is there a way to find/create the Join Game button on the user's profile page, eg steam://joinlobby/1938090/109775241047500448/76561198259089872
let res = await fetch(`https://steamcommunity.com/miniprofile/${steamUserId.getSteam3RenderedID().substring(5, 5+9)}/json?appid=undefined`, {headers: {"X-Requested-With": "XMLHttpRequest"}});
if (res.ok) {
steamStatus = "connected";
gameStatus = "";
let resJson = await res.json();
if (resJson.in_game) {
gameStatus = `${resJson.in_game.name} (not supported)`;
if (resJson.in_game?.logo && resJson.in_game?.rich_presence) {
let curr_appid = resJson.in_game.logo.split("/apps/")[1].split("/")[0];
let curr_rpc = resJson.in_game.rich_presence;
debugLine = "Current Steam RPC Status: " + resJson.in_game.rich_presence;
if (profiles.hasOwnProperty(curr_appid)) {
let profile = profiles[curr_appid];
try {
gameStatus = profile.title;
let translatedDiscordRPC = profile.translateSteamPresence(curr_rpc);
if (typeof translatedDiscordRPC !== "object") throw `Profile returned '${typeof translatedDiscordRPC}' instead of an object.`;
discordRPCClient.user?.setActivity(translatedDiscordRPC);
}
catch (codeErr) {
throw new Error(`A code error has occured in the game profile for '${profile.title}'!`, {cause: codeErr});
}
}
}
}
}
else {
gameStatus = "";
steamStatus = `Error ${res.status} while fetching status: ${res.statusText}`;
}
renderWindow();
}
// =================================================================
// Start each component
let loadingPrint = setInterval(renderWindow, 0.5*1000);
let [steamUserId, profiles] = await Promise.all([getSteamUserId(), loadProfiles()]);
clearInterval(loadingPrint);
if (Object.keys(profiles).length <= 0) {
throw "No profiles were found inside the /profiles directory!";
}
if (steamUserId == undefined) {
throw "Failed to obtain user id from steamProfileURL variable. It should be set to either https://steamcommunity.com/id/crementif or https://steamcommunity.com/profiles/76561198259089872.";
}
steamStatus = `Using Steam User ID ${steamUserId.getSteamID64()}`;
renderWindow();
pollSteamPresence(steamUserId, profiles);
setInterval(pollSteamPresence, pollRate, steamUserId, profiles);
discordRPCClient.login();