steamcommunity 3.48.3 → 3.48.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,466 +1,466 @@
1
- const {chrome} = require('@doctormckay/user-agents');
2
- const Request = require('request');
3
- const SteamID = require('steamid');
4
-
5
- const Helpers = require('./components/helpers.js');
6
-
7
- require('util').inherits(SteamCommunity, require('events').EventEmitter);
8
-
9
- module.exports = SteamCommunity;
10
-
11
- SteamCommunity.SteamID = SteamID;
12
- SteamCommunity.ConfirmationType = require('./resources/EConfirmationType.js');
13
- SteamCommunity.EResult = require('./resources/EResult.js');
14
- SteamCommunity.ESharedFileType = require('./resources/ESharedFileType.js');
15
- SteamCommunity.EFriendRelationship = require('./resources/EFriendRelationship.js');
16
-
17
-
18
- function SteamCommunity(options) {
19
- options = options || {};
20
-
21
- this._jar = Request.jar();
22
- this._captchaGid = -1;
23
- this._httpRequestID = 0;
24
- this.chatState = SteamCommunity.ChatState.Offline;
25
-
26
- var defaults = {
27
- "jar": this._jar,
28
- "timeout": options.timeout || 50000,
29
- "gzip": true,
30
- "headers": {
31
- "User-Agent": options.userAgent || chrome()
32
- }
33
- };
34
-
35
- if (typeof options == "string") {
36
- options = {
37
- localAddress: options
38
- };
39
- }
40
- this._options = options;
41
-
42
- if (options.localAddress) {
43
- defaults.localAddress = options.localAddress;
44
- }
45
-
46
- this.request = options.request || Request.defaults({"forever": true}); // "forever" indicates that we want a keep-alive agent
47
- this.request = this.request.defaults(defaults);
48
-
49
- // English
50
- this._setCookie(Request.cookie('Steam_Language=english'));
51
-
52
- // UTC
53
- this._setCookie(Request.cookie('timezoneOffset=0,0'));
54
- }
55
-
56
- SteamCommunity.prototype.login = function(details, callback) {
57
- if (!details.accountName || !details.password) {
58
- throw new Error("Missing either accountName or password to login; both are needed");
59
- }
60
-
61
- // Delete the cache
62
- delete this._profileURL;
63
-
64
- // default disableMobile to true
65
- let logOnOptions = Object.assign({}, details);
66
- logOnOptions.disableMobile = details.disableMobile !== false;
67
-
68
- this._modernLogin(logOnOptions).then(({sessionID, cookies, steamguard, mobileAccessToken}) => {
69
- this.setCookies(cookies);
70
-
71
- if (mobileAccessToken) {
72
- this.setMobileAppAccessToken(mobileAccessToken);
73
- }
74
-
75
- callback(null, sessionID, cookies, steamguard, null);
76
- }).catch(err => callback(err));
77
- };
78
-
79
- /**
80
- * @deprecated
81
- * @param {string} steamguard
82
- * @param {string} token
83
- * @param {function} callback
84
- */
85
- SteamCommunity.prototype.oAuthLogin = function(steamguard, token, callback) {
86
- steamguard = steamguard.split('||');
87
- var steamID = new SteamID(steamguard[0]);
88
-
89
- var self = this;
90
- this.httpRequestPost({
91
- "uri": "https://api.steampowered.com/IMobileAuthService/GetWGToken/v1/",
92
- "form": {
93
- "access_token": token
94
- },
95
- "json": true
96
- }, function(err, response, body) {
97
- if (err) {
98
- callback(err);
99
- return;
100
- }
101
-
102
- if(!body.response || !body.response.token || !body.response.token_secure) {
103
- callback(new Error("Malformed response"));
104
- return;
105
- }
106
-
107
- var cookies = [
108
- 'steamLogin=' + encodeURIComponent(steamID.getSteamID64() + '||' + body.response.token),
109
- 'steamLoginSecure=' + encodeURIComponent(steamID.getSteamID64() + '||' + body.response.token_secure),
110
- 'steamMachineAuth' + steamID.getSteamID64() + '=' + steamguard[1],
111
- 'sessionid=' + self.getSessionID()
112
- ];
113
-
114
- self.setCookies(cookies);
115
- callback(null, self.getSessionID(), cookies);
116
- }, "steamcommunity");
117
- };
118
-
119
- /**
120
- * Get a token that can be used to log onto Steam using steam-user.
121
- * @param {function} callback
122
- */
123
- SteamCommunity.prototype.getClientLogonToken = function(callback) {
124
- this.httpRequestGet({
125
- "uri": "https://steamcommunity.com/chat/clientjstoken",
126
- "json": true
127
- }, (err, res, body) => {
128
- if (err || res.statusCode != 200) {
129
- callback(err ? err : new Error('HTTP error ' + res.statusCode));
130
- return;
131
- }
132
-
133
- if (!body.logged_in) {
134
- let e = new Error('Not Logged In');
135
- callback(e);
136
- this._notifySessionExpired(e);
137
- return;
138
- }
139
-
140
- if (!body.steamid || !body.account_name || !body.token) {
141
- callback(new Error('Malformed response'));
142
- return;
143
- }
144
-
145
- callback(null, {
146
- "steamID": new SteamID(body.steamid),
147
- "accountName": body.account_name,
148
- "webLogonToken": body.token
149
- });
150
- });
151
- };
152
-
153
- SteamCommunity.prototype._setCookie = function(cookie, secure) {
154
- var protocol = secure ? "https" : "http";
155
- cookie.secure = !!secure;
156
-
157
- if (cookie.domain) {
158
- this._jar.setCookie(cookie.clone(), protocol + '://' + cookie.domain);
159
- } else {
160
- this._jar.setCookie(cookie.clone(), protocol + "://steamcommunity.com");
161
- this._jar.setCookie(cookie.clone(), protocol + "://store.steampowered.com");
162
- this._jar.setCookie(cookie.clone(), protocol + "://help.steampowered.com");
163
- }
164
- };
165
-
166
- SteamCommunity.prototype.setCookies = function(cookies) {
167
- cookies.forEach((cookie) => {
168
- var cookieName = cookie.trim().split('=')[0];
169
- if (cookieName == 'steamLogin' || cookieName == 'steamLoginSecure') {
170
- this.steamID = new SteamID(cookie.match(/steamLogin(Secure)?=(\d+)/)[2]);
171
- }
172
-
173
- this._setCookie(Request.cookie(cookie), !!(cookieName.match(/^steamMachineAuth/) || cookieName.match(/Secure$/)));
174
- });
175
-
176
- // The account we're logged in as might have changed, so verify that our mobile access token (if any) is still valid
177
- // for this account.
178
- this._verifyMobileAccessToken();
179
- };
180
-
181
- SteamCommunity.prototype.getSessionID = function(host = "http://steamcommunity.com") {
182
- var cookies = this._jar.getCookieString(host).split(';');
183
- for(var i = 0; i < cookies.length; i++) {
184
- var match = cookies[i].trim().match(/([^=]+)=(.+)/);
185
- if(match[1] == 'sessionid') {
186
- return decodeURIComponent(match[2]);
187
- }
188
- }
189
-
190
- var sessionID = generateSessionID();
191
- this._setCookie(Request.cookie('sessionid=' + sessionID));
192
- return sessionID;
193
- };
194
-
195
- function generateSessionID() {
196
- return require('crypto').randomBytes(12).toString('hex');
197
- }
198
-
199
- SteamCommunity.prototype.parentalUnlock = function(pin, callback) {
200
- var self = this;
201
- var sessionID = self.getSessionID();
202
-
203
- this.httpRequestPost("https://steamcommunity.com/parental/ajaxunlock", {
204
- "json": true,
205
- "form": {
206
- "pin": pin,
207
- "sessionid": sessionID
208
- }
209
- }, function(err, response, body) {
210
- if(!callback) {
211
- return;
212
- }
213
-
214
- if (err) {
215
- callback(err);
216
- return;
217
- }
218
-
219
- if (!body || typeof body.success !== 'boolean') {
220
- callback("Invalid response");
221
- return;
222
- }
223
-
224
- if (!body.success) {
225
- switch (body.eresult) {
226
- case 15:
227
- callback("Incorrect PIN");
228
- break;
229
-
230
- case 25:
231
- callback("Too many invalid PIN attempts");
232
- break;
233
-
234
- default:
235
- callback("Error " + body.eresult);
236
- }
237
-
238
- return;
239
- }
240
-
241
- callback();
242
- }.bind(this), "steamcommunity");
243
- };
244
-
245
- SteamCommunity.prototype.getNotifications = function(callback) {
246
- var self = this;
247
- this.httpRequestGet({
248
- "uri": "https://steamcommunity.com/actions/GetNotificationCounts",
249
- "json": true
250
- }, function(err, response, body) {
251
- if (err) {
252
- callback(err);
253
- return;
254
- }
255
-
256
- if (!body || !body.notifications) {
257
- callback(new Error("Malformed response"));
258
- return;
259
- }
260
-
261
- var notifications = {
262
- "trades": body.notifications[1] || 0,
263
- "gameTurns": body.notifications[2] || 0,
264
- "moderatorMessages": body.notifications[3] || 0,
265
- "comments": body.notifications[4] || 0,
266
- "items": body.notifications[5] || 0,
267
- "invites": body.notifications[6] || 0,
268
- // dunno about 7
269
- "gifts": body.notifications[8] || 0,
270
- "chat": body.notifications[9] || 0,
271
- "helpRequestReplies": body.notifications[10] || 0,
272
- "accountAlerts": body.notifications[11] || 0
273
- };
274
-
275
- callback(null, notifications);
276
- }, "steamcommunity");
277
- };
278
-
279
- SteamCommunity.prototype.resetItemNotifications = function(callback) {
280
- var self = this;
281
- this.httpRequestGet("https://steamcommunity.com/my/inventory", function(err, response, body) {
282
- if(!callback) {
283
- return;
284
- }
285
-
286
- callback(err || null);
287
- }, "steamcommunity");
288
- };
289
-
290
- SteamCommunity.prototype.loggedIn = function(callback) {
291
- this.httpRequestGet({
292
- "uri": "https://steamcommunity.com/my",
293
- "followRedirect": false,
294
- "checkHttpError": false
295
- }, function(err, response, body) {
296
- if(err || (response.statusCode != 302 && response.statusCode != 403)) {
297
- callback(err || new Error("HTTP error " + response.statusCode));
298
- return;
299
- }
300
-
301
- if(response.statusCode == 403) {
302
- callback(null, true, true);
303
- return;
304
- }
305
-
306
- callback(null, !!response.headers.location.match(/steamcommunity\.com(\/(id|profiles)\/[^\/]+)\/?/), false);
307
- }, "steamcommunity");
308
- };
309
-
310
- SteamCommunity.prototype.getTradeURL = function(callback) {
311
- this._myProfile("tradeoffers/privacy", null, (err, response, body) => {
312
- if (err) {
313
- callback(err);
314
- return;
315
- }
316
-
317
- var match = body.match(/https?:\/\/(www.)?steamcommunity.com\/tradeoffer\/new\/?\?partner=\d+(&|&amp;)token=([a-zA-Z0-9-_]+)/);
318
- if (match) {
319
- var token = match[3];
320
- callback(null, match[0], token);
321
- } else {
322
- callback(new Error("Malformed response"));
323
- }
324
- }, "steamcommunity");
325
- };
326
-
327
- SteamCommunity.prototype.changeTradeURL = function(callback) {
328
- this._myProfile("tradeoffers/newtradeurl", {"sessionid": this.getSessionID()}, (err, response, body) => {
329
- if (!callback) {
330
- return;
331
- }
332
-
333
- if (!body || typeof body !== "string" || body.length < 3 || body.indexOf('"') !== 0) {
334
- callback(new Error("Malformed response"));
335
- return;
336
- }
337
-
338
- var newToken = body.replace(/"/g, ''); //"t1o2k3e4n" => t1o2k3e4n
339
- callback(null, "https://steamcommunity.com/tradeoffer/new/?partner=" + this.steamID.accountid + "&token=" + newToken, newToken);
340
- }, "steamcommunity");
341
- };
342
-
343
- /**
344
- * Clear your profile name (alias) history.
345
- * @param {function} callback
346
- */
347
- SteamCommunity.prototype.clearPersonaNameHistory = function(callback) {
348
- this._myProfile("ajaxclearaliashistory/", {"sessionid": this.getSessionID()}, (err, res, body) => {
349
- if (!callback) {
350
- return;
351
- }
352
-
353
- if (err) {
354
- return callback(err);
355
- }
356
-
357
- if (res.statusCode != 200) {
358
- return callback(new Error("HTTP error " + res.statusCode));
359
- }
360
-
361
- try {
362
- body = JSON.parse(body);
363
- callback(Helpers.eresultError(body.success));
364
- } catch (ex) {
365
- return callback(new Error("Malformed response"));
366
- }
367
- });
368
- };
369
-
370
- SteamCommunity.prototype._myProfile = function(endpoint, form, callback) {
371
- var self = this;
372
-
373
- if (this._profileURL) {
374
- completeRequest(this._profileURL);
375
- } else {
376
- this.httpRequest("https://steamcommunity.com/my", {"followRedirect": false}, function(err, response, body) {
377
- if(err || response.statusCode != 302) {
378
- callback(err || "HTTP error " + response.statusCode);
379
- return;
380
- }
381
-
382
- var match = response.headers.location.match(/steamcommunity\.com(\/(id|profiles)\/[^\/]+)\/?/);
383
- if(!match) {
384
- callback(new Error("Can't get profile URL"));
385
- return;
386
- }
387
-
388
- self._profileURL = match[1];
389
- setTimeout(function () {
390
- delete self._profileURL; // delete the cache
391
- }, 60000).unref();
392
-
393
- completeRequest(match[1]);
394
- }, "steamcommunity");
395
- }
396
-
397
- function completeRequest(url) {
398
- var options = endpoint.endpoint ? endpoint : {};
399
- options.uri = "https://steamcommunity.com" + url + "/" + (endpoint.endpoint || endpoint);
400
-
401
- if (form) {
402
- options.method = "POST";
403
- options.form = form;
404
- options.followAllRedirects = true;
405
- } else if (!options.method) {
406
- options.method = "GET";
407
- }
408
-
409
- self.httpRequest(options, callback, "steamcommunity");
410
- }
411
- };
412
-
413
- /**
414
- * Returns an object whose keys are 64-bit SteamIDs, and whose values are values from the EFriendRelationship enum.
415
- * Therefore, you can deduce your friends or blocked list from this object.
416
- * @param {function} callback
417
- */
418
- SteamCommunity.prototype.getFriendsList = function(callback) {
419
- this.httpRequestGet({
420
- "uri": "https://steamcommunity.com/textfilter/ajaxgetfriendslist",
421
- "json": true
422
- }, (err, res, body) => {
423
- if (err) {
424
- callback(err ? err : new Error('HTTP error ' + res.statusCode));
425
- return;
426
- }
427
-
428
- if (body.success != 1) {
429
- callback(Helpers.eresultError(body.success));
430
- return;
431
- }
432
-
433
- if (!body.friendslist || !body.friendslist.friends) {
434
- callback(new Error('Malformed response'));
435
- return;
436
- }
437
-
438
- const friends = {};
439
- body.friendslist.friends.forEach(friend => (friends[friend.ulfriendid] = friend.efriendrelationship));
440
- callback(null, friends);
441
- });
442
- };
443
-
444
- require('./components/login.js');
445
- require('./components/http.js');
446
- require('./components/chat.js');
447
- require('./components/profile.js');
448
- require('./components/market.js');
449
- require('./components/groups.js');
450
- require('./components/users.js');
451
- require('./components/sharedfiles.js');
452
- require('./components/inventoryhistory.js');
453
- require('./components/webapi.js');
454
- require('./components/twofactor.js');
455
- require('./components/confirmations.js');
456
- require('./components/help.js');
457
- require('./classes/CMarketItem.js');
458
- require('./classes/CMarketSearchResult.js');
459
- require('./classes/CSteamGroup.js');
460
- require('./classes/CSteamSharedFile.js');
461
- require('./classes/CSteamUser.js');
462
-
463
- /**
464
- @callback SteamCommunity~genericErrorCallback
465
- @param {Error|null} err - An Error object on failure, or null on success
466
- */
1
+ const {chrome} = require('@doctormckay/user-agents');
2
+ const Request = require('request');
3
+ const SteamID = require('steamid');
4
+
5
+ const Helpers = require('./components/helpers.js');
6
+
7
+ require('util').inherits(SteamCommunity, require('events').EventEmitter);
8
+
9
+ module.exports = SteamCommunity;
10
+
11
+ SteamCommunity.SteamID = SteamID;
12
+ SteamCommunity.ConfirmationType = require('./resources/EConfirmationType.js');
13
+ SteamCommunity.EResult = require('./resources/EResult.js');
14
+ SteamCommunity.ESharedFileType = require('./resources/ESharedFileType.js');
15
+ SteamCommunity.EFriendRelationship = require('./resources/EFriendRelationship.js');
16
+
17
+
18
+ function SteamCommunity(options) {
19
+ options = options || {};
20
+
21
+ this._jar = Request.jar();
22
+ this._captchaGid = -1;
23
+ this._httpRequestID = 0;
24
+ this.chatState = SteamCommunity.ChatState.Offline;
25
+
26
+ var defaults = {
27
+ "jar": this._jar,
28
+ "timeout": options.timeout || 50000,
29
+ "gzip": true,
30
+ "headers": {
31
+ "User-Agent": options.userAgent || chrome()
32
+ }
33
+ };
34
+
35
+ if (typeof options == "string") {
36
+ options = {
37
+ localAddress: options
38
+ };
39
+ }
40
+ this._options = options;
41
+
42
+ if (options.localAddress) {
43
+ defaults.localAddress = options.localAddress;
44
+ }
45
+
46
+ this.request = options.request || Request.defaults({"forever": true}); // "forever" indicates that we want a keep-alive agent
47
+ this.request = this.request.defaults(defaults);
48
+
49
+ // English
50
+ this._setCookie(Request.cookie('Steam_Language=english'));
51
+
52
+ // UTC
53
+ this._setCookie(Request.cookie('timezoneOffset=0,0'));
54
+ }
55
+
56
+ SteamCommunity.prototype.login = function(details, callback) {
57
+ if (!details.accountName || !details.password) {
58
+ throw new Error("Missing either accountName or password to login; both are needed");
59
+ }
60
+
61
+ // Delete the cache
62
+ delete this._profileURL;
63
+
64
+ // default disableMobile to true
65
+ let logOnOptions = Object.assign({}, details);
66
+ logOnOptions.disableMobile = details.disableMobile !== false;
67
+
68
+ this._modernLogin(logOnOptions).then(({sessionID, cookies, steamguard, mobileAccessToken}) => {
69
+ this.setCookies(cookies);
70
+
71
+ if (mobileAccessToken) {
72
+ this.setMobileAppAccessToken(mobileAccessToken);
73
+ }
74
+
75
+ callback(null, sessionID, cookies, steamguard, null);
76
+ }).catch(err => callback(err));
77
+ };
78
+
79
+ /**
80
+ * @deprecated
81
+ * @param {string} steamguard
82
+ * @param {string} token
83
+ * @param {function} callback
84
+ */
85
+ SteamCommunity.prototype.oAuthLogin = function(steamguard, token, callback) {
86
+ steamguard = steamguard.split('||');
87
+ var steamID = new SteamID(steamguard[0]);
88
+
89
+ var self = this;
90
+ this.httpRequestPost({
91
+ "uri": "https://api.steampowered.com/IMobileAuthService/GetWGToken/v1/",
92
+ "form": {
93
+ "access_token": token
94
+ },
95
+ "json": true
96
+ }, function(err, response, body) {
97
+ if (err) {
98
+ callback(err);
99
+ return;
100
+ }
101
+
102
+ if(!body.response || !body.response.token || !body.response.token_secure) {
103
+ callback(new Error("Malformed response"));
104
+ return;
105
+ }
106
+
107
+ var cookies = [
108
+ 'steamLogin=' + encodeURIComponent(steamID.getSteamID64() + '||' + body.response.token),
109
+ 'steamLoginSecure=' + encodeURIComponent(steamID.getSteamID64() + '||' + body.response.token_secure),
110
+ 'steamMachineAuth' + steamID.getSteamID64() + '=' + steamguard[1],
111
+ 'sessionid=' + self.getSessionID()
112
+ ];
113
+
114
+ self.setCookies(cookies);
115
+ callback(null, self.getSessionID(), cookies);
116
+ }, "steamcommunity");
117
+ };
118
+
119
+ /**
120
+ * Get a token that can be used to log onto Steam using steam-user.
121
+ * @param {function} callback
122
+ */
123
+ SteamCommunity.prototype.getClientLogonToken = function(callback) {
124
+ this.httpRequestGet({
125
+ "uri": "https://steamcommunity.com/chat/clientjstoken",
126
+ "json": true
127
+ }, (err, res, body) => {
128
+ if (err || res.statusCode != 200) {
129
+ callback(err ? err : new Error('HTTP error ' + res.statusCode));
130
+ return;
131
+ }
132
+
133
+ if (!body.logged_in) {
134
+ let e = new Error('Not Logged In');
135
+ callback(e);
136
+ this._notifySessionExpired(e);
137
+ return;
138
+ }
139
+
140
+ if (!body.steamid || !body.account_name || !body.token) {
141
+ callback(new Error('Malformed response'));
142
+ return;
143
+ }
144
+
145
+ callback(null, {
146
+ "steamID": new SteamID(body.steamid),
147
+ "accountName": body.account_name,
148
+ "webLogonToken": body.token
149
+ });
150
+ });
151
+ };
152
+
153
+ SteamCommunity.prototype._setCookie = function(cookie, secure) {
154
+ var protocol = secure ? "https" : "http";
155
+ cookie.secure = !!secure;
156
+
157
+ if (cookie.domain) {
158
+ this._jar.setCookie(cookie.clone(), protocol + '://' + cookie.domain);
159
+ } else {
160
+ this._jar.setCookie(cookie.clone(), protocol + "://steamcommunity.com");
161
+ this._jar.setCookie(cookie.clone(), protocol + "://store.steampowered.com");
162
+ this._jar.setCookie(cookie.clone(), protocol + "://help.steampowered.com");
163
+ }
164
+ };
165
+
166
+ SteamCommunity.prototype.setCookies = function(cookies) {
167
+ cookies.forEach((cookie) => {
168
+ var cookieName = cookie.trim().split('=')[0];
169
+ if (cookieName == 'steamLogin' || cookieName == 'steamLoginSecure') {
170
+ this.steamID = new SteamID(cookie.match(/steamLogin(Secure)?=(\d+)/)[2]);
171
+ }
172
+
173
+ this._setCookie(Request.cookie(cookie), !!(cookieName.match(/^steamMachineAuth/) || cookieName.match(/Secure$/)));
174
+ });
175
+
176
+ // The account we're logged in as might have changed, so verify that our mobile access token (if any) is still valid
177
+ // for this account.
178
+ this._verifyMobileAccessToken();
179
+ };
180
+
181
+ SteamCommunity.prototype.getSessionID = function(host = "http://steamcommunity.com") {
182
+ var cookies = this._jar.getCookieString(host).split(';');
183
+ for(var i = 0; i < cookies.length; i++) {
184
+ var match = cookies[i].trim().match(/([^=]+)=(.+)/);
185
+ if(match[1] == 'sessionid') {
186
+ return decodeURIComponent(match[2]);
187
+ }
188
+ }
189
+
190
+ var sessionID = generateSessionID();
191
+ this._setCookie(Request.cookie('sessionid=' + sessionID));
192
+ return sessionID;
193
+ };
194
+
195
+ function generateSessionID() {
196
+ return require('crypto').randomBytes(12).toString('hex');
197
+ }
198
+
199
+ SteamCommunity.prototype.parentalUnlock = function(pin, callback) {
200
+ var self = this;
201
+ var sessionID = self.getSessionID();
202
+
203
+ this.httpRequestPost("https://steamcommunity.com/parental/ajaxunlock", {
204
+ "json": true,
205
+ "form": {
206
+ "pin": pin,
207
+ "sessionid": sessionID
208
+ }
209
+ }, function(err, response, body) {
210
+ if(!callback) {
211
+ return;
212
+ }
213
+
214
+ if (err) {
215
+ callback(err);
216
+ return;
217
+ }
218
+
219
+ if (!body || typeof body.success !== 'boolean') {
220
+ callback("Invalid response");
221
+ return;
222
+ }
223
+
224
+ if (!body.success) {
225
+ switch (body.eresult) {
226
+ case 15:
227
+ callback("Incorrect PIN");
228
+ break;
229
+
230
+ case 25:
231
+ callback("Too many invalid PIN attempts");
232
+ break;
233
+
234
+ default:
235
+ callback("Error " + body.eresult);
236
+ }
237
+
238
+ return;
239
+ }
240
+
241
+ callback();
242
+ }.bind(this), "steamcommunity");
243
+ };
244
+
245
+ SteamCommunity.prototype.getNotifications = function(callback) {
246
+ var self = this;
247
+ this.httpRequestGet({
248
+ "uri": "https://steamcommunity.com/actions/GetNotificationCounts",
249
+ "json": true
250
+ }, function(err, response, body) {
251
+ if (err) {
252
+ callback(err);
253
+ return;
254
+ }
255
+
256
+ if (!body || !body.notifications) {
257
+ callback(new Error("Malformed response"));
258
+ return;
259
+ }
260
+
261
+ var notifications = {
262
+ "trades": body.notifications[1] || 0,
263
+ "gameTurns": body.notifications[2] || 0,
264
+ "moderatorMessages": body.notifications[3] || 0,
265
+ "comments": body.notifications[4] || 0,
266
+ "items": body.notifications[5] || 0,
267
+ "invites": body.notifications[6] || 0,
268
+ // dunno about 7
269
+ "gifts": body.notifications[8] || 0,
270
+ "chat": body.notifications[9] || 0,
271
+ "helpRequestReplies": body.notifications[10] || 0,
272
+ "accountAlerts": body.notifications[11] || 0
273
+ };
274
+
275
+ callback(null, notifications);
276
+ }, "steamcommunity");
277
+ };
278
+
279
+ SteamCommunity.prototype.resetItemNotifications = function(callback) {
280
+ var self = this;
281
+ this.httpRequestGet("https://steamcommunity.com/my/inventory", function(err, response, body) {
282
+ if(!callback) {
283
+ return;
284
+ }
285
+
286
+ callback(err || null);
287
+ }, "steamcommunity");
288
+ };
289
+
290
+ SteamCommunity.prototype.loggedIn = function(callback) {
291
+ this.httpRequestGet({
292
+ "uri": "https://steamcommunity.com/my",
293
+ "followRedirect": false,
294
+ "checkHttpError": false
295
+ }, function(err, response, body) {
296
+ if(err || (response.statusCode != 302 && response.statusCode != 403)) {
297
+ callback(err || new Error("HTTP error " + response.statusCode));
298
+ return;
299
+ }
300
+
301
+ if(response.statusCode == 403) {
302
+ callback(null, true, true);
303
+ return;
304
+ }
305
+
306
+ callback(null, !!response.headers.location.match(/steamcommunity\.com(\/(id|profiles)\/[^\/]+)\/?/), false);
307
+ }, "steamcommunity");
308
+ };
309
+
310
+ SteamCommunity.prototype.getTradeURL = function(callback) {
311
+ this._myProfile("tradeoffers/privacy", null, (err, response, body) => {
312
+ if (err) {
313
+ callback(err);
314
+ return;
315
+ }
316
+
317
+ var match = body.match(/https?:\/\/(www.)?steamcommunity.com\/tradeoffer\/new\/?\?partner=\d+(&|&amp;)token=([a-zA-Z0-9-_]+)/);
318
+ if (match) {
319
+ var token = match[3];
320
+ callback(null, match[0], token);
321
+ } else {
322
+ callback(new Error("Malformed response"));
323
+ }
324
+ }, "steamcommunity");
325
+ };
326
+
327
+ SteamCommunity.prototype.changeTradeURL = function(callback) {
328
+ this._myProfile("tradeoffers/newtradeurl", {"sessionid": this.getSessionID()}, (err, response, body) => {
329
+ if (!callback) {
330
+ return;
331
+ }
332
+
333
+ if (!body || typeof body !== "string" || body.length < 3 || body.indexOf('"') !== 0) {
334
+ callback(new Error("Malformed response"));
335
+ return;
336
+ }
337
+
338
+ var newToken = body.replace(/"/g, ''); //"t1o2k3e4n" => t1o2k3e4n
339
+ callback(null, "https://steamcommunity.com/tradeoffer/new/?partner=" + this.steamID.accountid + "&token=" + newToken, newToken);
340
+ }, "steamcommunity");
341
+ };
342
+
343
+ /**
344
+ * Clear your profile name (alias) history.
345
+ * @param {function} callback
346
+ */
347
+ SteamCommunity.prototype.clearPersonaNameHistory = function(callback) {
348
+ this._myProfile("ajaxclearaliashistory/", {"sessionid": this.getSessionID()}, (err, res, body) => {
349
+ if (!callback) {
350
+ return;
351
+ }
352
+
353
+ if (err) {
354
+ return callback(err);
355
+ }
356
+
357
+ if (res.statusCode != 200) {
358
+ return callback(new Error("HTTP error " + res.statusCode));
359
+ }
360
+
361
+ try {
362
+ body = JSON.parse(body);
363
+ callback(Helpers.eresultError(body.success));
364
+ } catch (ex) {
365
+ return callback(new Error("Malformed response"));
366
+ }
367
+ });
368
+ };
369
+
370
+ SteamCommunity.prototype._myProfile = function(endpoint, form, callback) {
371
+ var self = this;
372
+
373
+ if (this._profileURL) {
374
+ completeRequest(this._profileURL);
375
+ } else {
376
+ this.httpRequest("https://steamcommunity.com/my", {"followRedirect": false}, function(err, response, body) {
377
+ if(err || response.statusCode != 302) {
378
+ callback(err || "HTTP error " + response.statusCode);
379
+ return;
380
+ }
381
+
382
+ var match = response.headers.location.match(/steamcommunity\.com(\/(id|profiles)\/[^\/]+)\/?/);
383
+ if(!match) {
384
+ callback(new Error("Can't get profile URL"));
385
+ return;
386
+ }
387
+
388
+ self._profileURL = match[1];
389
+ setTimeout(function () {
390
+ delete self._profileURL; // delete the cache
391
+ }, 60000).unref();
392
+
393
+ completeRequest(match[1]);
394
+ }, "steamcommunity");
395
+ }
396
+
397
+ function completeRequest(url) {
398
+ var options = endpoint.endpoint ? endpoint : {};
399
+ options.uri = "https://steamcommunity.com" + url + "/" + (endpoint.endpoint || endpoint);
400
+
401
+ if (form) {
402
+ options.method = "POST";
403
+ options.form = form;
404
+ options.followAllRedirects = true;
405
+ } else if (!options.method) {
406
+ options.method = "GET";
407
+ }
408
+
409
+ self.httpRequest(options, callback, "steamcommunity");
410
+ }
411
+ };
412
+
413
+ /**
414
+ * Returns an object whose keys are 64-bit SteamIDs, and whose values are values from the EFriendRelationship enum.
415
+ * Therefore, you can deduce your friends or blocked list from this object.
416
+ * @param {function} callback
417
+ */
418
+ SteamCommunity.prototype.getFriendsList = function(callback) {
419
+ this.httpRequestGet({
420
+ "uri": "https://steamcommunity.com/textfilter/ajaxgetfriendslist",
421
+ "json": true
422
+ }, (err, res, body) => {
423
+ if (err) {
424
+ callback(err ? err : new Error('HTTP error ' + res.statusCode));
425
+ return;
426
+ }
427
+
428
+ if (body.success != 1) {
429
+ callback(Helpers.eresultError(body.success));
430
+ return;
431
+ }
432
+
433
+ if (!body.friendslist || !body.friendslist.friends) {
434
+ callback(new Error('Malformed response'));
435
+ return;
436
+ }
437
+
438
+ const friends = {};
439
+ body.friendslist.friends.forEach(friend => (friends[friend.ulfriendid] = friend.efriendrelationship));
440
+ callback(null, friends);
441
+ });
442
+ };
443
+
444
+ require('./components/login.js');
445
+ require('./components/http.js');
446
+ require('./components/chat.js');
447
+ require('./components/profile.js');
448
+ require('./components/market.js');
449
+ require('./components/groups.js');
450
+ require('./components/users.js');
451
+ require('./components/sharedfiles.js');
452
+ require('./components/inventoryhistory.js');
453
+ require('./components/webapi.js');
454
+ require('./components/twofactor.js');
455
+ require('./components/confirmations.js');
456
+ require('./components/help.js');
457
+ require('./classes/CMarketItem.js');
458
+ require('./classes/CMarketSearchResult.js');
459
+ require('./classes/CSteamGroup.js');
460
+ require('./classes/CSteamSharedFile.js');
461
+ require('./classes/CSteamUser.js');
462
+
463
+ /**
464
+ @callback SteamCommunity~genericErrorCallback
465
+ @param {Error|null} err - An Error object on failure, or null on success
466
+ */