-
Notifications
You must be signed in to change notification settings - Fork 0
/
getallapps.js
229 lines (198 loc) · 7.85 KB
/
getallapps.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/**
* This downloads the whole library of apps, games, etc belonging to the user on Steam.
* Sections can be uncommented to allow for saving various steps for troubleshooting and debugging.
* This script was copied and repurposed from the betamanifestdownloader.js example file
* found within the steam-user node module.
*/
/***
* Create a file in this folder called .env
* In this file, set 2 variables:
* STEAM_ACCOUNT_NAME='<your steam username>'
* STEAM_ACCOUNT_PASSWORD='<your steam password>'
* These 2 variables are used to log in for the first time
* if you haven't signed in yet and created a refresh token.
*/
require('dotenv').config()
const STEAM_ACCOUNT_NAME = process.env.STEAM_ACCOUNT_NAME ?? 'user'; // Username for your Steam account
const STEAM_ACCOUNT_PASSWORD = process.env.STEAM_ACCOUNT_PASSWORD ?? 'password'; // Password for your Steam account
const STEAM_ACCOUNT_2FA_SECRET = ''; // Your shared_secret if you have mobile authentication enabled, or blank to prompt for a code from stdin
// DO NOT SHARE THIS TOKEN!!!
const STEAM_REFRESH_TOKEN = './refreshToken.config';
const SteamUser = require('steam-user'); // change to `require('steam-user')` if running outside of the examples directory
const SteamTotp = require('steam-totp');
const fs = require('fs');
const path = require('path');
const { exit } = require('process');
let dataSet = [];
const debugged = true;
const debugDir = './debug';
if (debugged) {
try {
fs.mkdirSync(debugDir, {recursive: true});
console.log('Directory ${debugDir} created or already exists');
} catch (error) {
console.error(`Error creating directory ${path}:`, error);
}
}
let user = new SteamUser();
user.setOptions({
//renewRefreshTokens: true,
enablePicsCache: true
});
fs.access(STEAM_REFRESH_TOKEN, fs.constants.F_OK, (err) => {
if (err) {
console.log('Username and Password');
user.logOn({
accountName: STEAM_ACCOUNT_NAME,
password: STEAM_ACCOUNT_PASSWORD,
twoFactorCode: STEAM_ACCOUNT_2FA_SECRET ? SteamTotp.generateAuthCode(STEAM_ACCOUNT_2FA_SECRET) : undefined,
});
return;
}
let refresh = fs.readFileSync(STEAM_REFRESH_TOKEN, { encoding: 'utf8' });
console.log('Using Refresh Token');
//console.log(refresh);
user.logOn({
refreshToken: refresh,
});
});
user.on('loggedOn', async () => {
console.log(`Logged on to Steam as ${user.steamID.steam3()}`);
});
user.on('licenses', async function(licenses) {
console.log('Got licenses.');
if (debugged) {
const licenseOut = path.join(debugDir, 'licenses.json');
fs.writeFile(licenseOut, JSON.stringify(licenses, null, 4), 'utf8', function(error) {
console.log(error || 'Successfully dumped our steam licenses to licenses.json');
});
}
});
user.on('ownershipCached', async () => {
console.log('Ownership Cached');
// Get all owned Apps.
let output = user.getOwnedApps();
fs.writeFileSync('apps.json', JSON.stringify(output, undefined, '\t'));
// If you want to have every appID you own exported to a single JSON file,
// then set debugged to true.
// This file is a JSON list of every app ID in your library.
// It contains only the App IDs, nothing else.
if (debugged) {
const appsOut = path.join(debugDir, 'apps.json');
fs.writeFileSync(appsOut, JSON.stringify(output, null, 4), 'utf8', function(error) {
console.log(error || 'Successfully dumped our steam licenses to licenses.json');
});
}
/* Uses the appIDs to get the product info. Product Info includes
AppID
Change Number
Token
AppInfo
AppID again
Common
App Name
App Type {DLC,Config,Tool,Game,Music,Application}
Depots
DepotID
Config {oslist: windows,macos,linux}
Manifest {public,etc}/ Encrypted Manifest for beta branches
Some "depots" are not Objects. Exclude those.
Branches
*/
// What we want is the 2nd AppID, since it's within the All Important AppInfo, the App Name, App Type, and Depots
let result = await user.getProductInfo(output, [], true); // Passing true as the third argument automatically requests access tokens, which are required for some apps
//console.log(result);
//console.log('Got app info, writing to files');
for (let appid in result.apps) {
// Enables writing the appinfo object contents to separate files.
// See above to understand what is in AppInfo
// This writes the depot data for each app before filtering.
if (debugged) {
fs.mkdirSync(`${debugDir}/Apps_before`, {recursive: true});
const fileName = `${appid}.json`;
const AppsDirOut = path.join(debugDir, 'Apps_before', fileName);
fs.writeFileSync(AppsDirOut, JSON.stringify(result.apps[appid].appinfo, null, '\t'));
}
/* Removal of any apps that are just configs or do not have any config type, such as
* AppId = 5: Engine.GoldSource, no type
* AppId = 7: Steam Client, config type
* We are only wanting DLC, Tools, Games, Music, Betas, Demos and Applications
*/
if (!result.apps[appid].appinfo.common?.type || result.apps[appid].appinfo.common?.type == 'Config' || result.apps[appid].appinfo.common?.type == 'config') {
delete result.apps[appid];
continue;
}
// Now we only want those that have depots, since those are what we need to get manifests
// and subsequently the chunks.
if (!result.apps[appid].appinfo?.depots) {
delete result.apps[appid];
continue;
}
// This removes any depot item that isn't an object. These are things that do not include a manifest
// which are their own object.
for (let depots in result.apps[appid].appinfo?.depots) {
if (typeof result.apps[appid].appinfo.depots[depots] !== 'object') {
delete result.apps[appid].appinfo.depots[depots];
continue
}
if (typeof result.apps[appid].appinfo.depots[depots].depotfromapp === 'string') {
let numericPart = result.apps[appid].appinfo.depots[depots].depotfromapp.match(/\d+/);
if (numericPart && output.includes(parseInt(numericPart[0]))) {
delete result.apps[appid].appinfo.depots[depots];
continue
}
}
}
// Tolld you we wanted these. :D
const entry = {
appid: appid,
name: result.apps[appid].appinfo.common.name,
type: result.apps[appid].appinfo.common.type,
depots: result.apps[appid].appinfo.depots
};
dataSet.push(entry);
if (debugged) {
// Forbidden Names must be Purged!!!!
// Windows hates certain characters in file and folder names.
let appName = result.apps[appid].appinfo.common.name;
let forbiddenCharsRegex = /[<>:"\/\\|?*\x00-\x1F]/g;
appName = appName.replace(forbiddenCharsRegex, '');
fs.mkdirSync(`${debugDir}/Apps_After`, {recursive: true});
const fileName = `${appName}_${appid}.json`;
const AppsDirOut = path.join(debugDir, 'Apps_After', fileName);
fs.writeFileSync(AppsDirOut, JSON.stringify(result.apps[appid].appinfo, null, '\t'));
}
}
// This will save every app and their respective depot information after records are deduplicated.
fs.writeFileSync('./data.json', JSON.stringify(dataSet, undefined, '\t'));
user.logOff();
exit(0);
});
// user.on('debug-traffic-outgoing', function(outputBuffer, header) {
// console.log('Header: ', header);
// console.log('Buffer: ', outputBuffer);
// });
// user.on('debug-traffic-incoming', function(buffer, eMsg) {
// console.log('Buffer: ', buffer);
// console.log('eMsg: ', eMsg);
// });
// user.on('debug', function(msg) {
// console.log(msg);
// });user.on('debug-traffic-incoming', function(buffer, eMsg) {
// console.log('Buffer: ', buffer);
// console.log('eMsg: ', eMsg);
// });
// user.on('debug', function(msg) {
// console.log(msg);
// });
/** The Refresh token is generated upon first login.
* This detects when it is created and saves the file
* for reuse. A real godsend for logging in, since you
* don't have to type your password or SteamGuard token
* every time, causing rate limits.
**** DO NOT SHARE YOUR TOKEN!! ******
*/
user.on('refreshToken', async (refreshToken) => {
let filename = STEAM_REFRESH_TOKEN;
fs.writeFileSync(filename, refreshToken);
});