mirror of
https://github.com/DoctorMcKay/node-steamcommunity.git
synced 2026-08-19 13:13:28 +08:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01217a3659 | ||
|
|
0e34bceb1f | ||
|
|
c4ea8eeb41 | ||
|
|
0f83fe8c64 | ||
|
|
5624611421 | ||
|
|
49d2bb4252 | ||
|
|
b54ccff7c8 | ||
|
|
b82f7ca045 | ||
|
|
2526539266 | ||
|
|
fc75036974 | ||
|
|
ee1e819812 | ||
|
|
fceea0737d | ||
|
|
f3ac556922 | ||
|
|
2e02c14455 | ||
|
|
8f580fc231 | ||
|
|
6f596b5b16 | ||
|
|
1249e28d83 | ||
|
|
85bcaa70be | ||
|
|
2a5419513c | ||
|
|
deec5c52a4 | ||
|
|
2399a5b783 | ||
|
|
efea8c6265 | ||
|
|
2be414b20c | ||
|
|
25ebb4c5a3 |
20
classes/CConfirmation.js
Normal file
20
classes/CConfirmation.js
Normal file
@@ -0,0 +1,20 @@
|
||||
module.exports = CConfirmation;
|
||||
|
||||
function CConfirmation(community, data) {
|
||||
this._community = community;
|
||||
|
||||
this.id = data.id;
|
||||
this.key = data.key;
|
||||
this.title = data.title;
|
||||
this.receiving = data.receiving;
|
||||
this.time = data.time;
|
||||
this.icon = data.icon;
|
||||
}
|
||||
|
||||
CConfirmation.prototype.getOfferID = function(time, key, callback) {
|
||||
this._community.getConfirmationOfferID(this.id, time, key, callback);
|
||||
};
|
||||
|
||||
CConfirmation.prototype.respond = function(time, key, accept, callback) {
|
||||
this._community.respondToConfirmation(this.id, this.key, time, key, accept, callback);
|
||||
};
|
||||
@@ -65,9 +65,9 @@ function CSteamUser(community, userData, customurl) {
|
||||
this.avatarHash = this.avatarHash[1];
|
||||
}
|
||||
|
||||
this.vacBanned = !!processItem('vacBanned', false);
|
||||
this.vacBanned = processItem('vacBanned', false) == 1;
|
||||
this.tradeBanState = processItem('tradeBanState', 'None');
|
||||
this.isLimitedAccount = !!processItem('isLimitedAccount');
|
||||
this.isLimitedAccount = processItem('isLimitedAccount') == 1;
|
||||
this.customURL = processItem('customURL', customurl);
|
||||
|
||||
if(this.visibilityState == 3) {
|
||||
|
||||
@@ -40,17 +40,9 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
|
||||
this.chatState = SteamCommunity.ChatState.LoggingOn;
|
||||
|
||||
var self = this;
|
||||
this.request("https://steamcommunity.com/chat", function(err, response, body) {
|
||||
if(err || response.statusCode != 200) {
|
||||
self.emit('debug', 'Error requesting chat WebAPI token: ' + (err ? err.message : "HTTP error " + response.statusCode));
|
||||
self.chatState = SteamCommunity.ChatState.LogOnFailed;
|
||||
setTimeout(self.chatLogon.bind(self), 5000);
|
||||
return;
|
||||
}
|
||||
|
||||
var match = body.match(/[0-9a-f]{32}/);
|
||||
if(!match) {
|
||||
self.emit('debug', 'Couldn\'t find a WebAPI chat token in the response.');
|
||||
this.getWebApiOauthToken(function(err, token) {
|
||||
if(err) {
|
||||
self.emit('debug', "Cannot get oauth token: " + err.message);
|
||||
self.chatState = SteamCommunity.ChatState.LogOnFailed;
|
||||
setTimeout(self.chatLogon.bind(self), 5000);
|
||||
return;
|
||||
@@ -60,7 +52,7 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
|
||||
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Logon/v1",
|
||||
"form": {
|
||||
"ui_mode": uiMode,
|
||||
"access_token": match[0]
|
||||
"access_token": token
|
||||
},
|
||||
"json": true
|
||||
}, function(err, response, body) {
|
||||
@@ -81,7 +73,7 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
|
||||
self._chat = {
|
||||
"umqid": body.umqid,
|
||||
"message": body.message,
|
||||
"accessToken": match[0],
|
||||
"accessToken": token,
|
||||
"interval": interval
|
||||
};
|
||||
|
||||
|
||||
284
components/confirmations.js
Normal file
284
components/confirmations.js
Normal file
@@ -0,0 +1,284 @@
|
||||
var SteamCommunity = require('../index.js');
|
||||
var Cheerio = require('cheerio');
|
||||
|
||||
var CConfirmation = require('../classes/CConfirmation.js');
|
||||
|
||||
/**
|
||||
* Get a list of your account's currently outstanding confirmations.
|
||||
* @param {int} time - The unix timestamp with which the following key was generated
|
||||
* @param {string} key - The confirmation key that was generated using the preceeding time and the tag "conf" (this key can be reused)
|
||||
* @param {SteamCommunity~getConfirmations} callback - Called when the list of confirmations is received
|
||||
*/
|
||||
SteamCommunity.prototype.getConfirmations = function(time, key, callback) {
|
||||
var self = this;
|
||||
|
||||
request(this, "conf", key, time, "conf", null, false, function(err, body) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
}
|
||||
|
||||
var $ = Cheerio.load(body);
|
||||
var empty = $('#mobileconf_empty');
|
||||
if(empty.length > 0) {
|
||||
if(!$(empty).hasClass('mobileconf_done')) {
|
||||
// An error occurred
|
||||
callback(new Error(empty.find('div:nth-of-type(2)').text()));
|
||||
} else {
|
||||
callback(null, []);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We have something to confirm
|
||||
var confirmations = $('#mobileconf_list');
|
||||
if(!confirmations) {
|
||||
callback(new Error("Malformed response"));
|
||||
return;
|
||||
}
|
||||
|
||||
var confs = [];
|
||||
Array.prototype.forEach.call(confirmations.find('.mobileconf_list_entry'), function(conf) {
|
||||
conf = $(conf);
|
||||
|
||||
var img = conf.find('.mobileconf_list_entry_icon img');
|
||||
confs.push(new CConfirmation(self, {
|
||||
"id": conf.data('confid'),
|
||||
"key": conf.data('key'),
|
||||
"title": conf.find('.mobileconf_list_entry_description>div:nth-of-type(1)').text().trim(),
|
||||
"receiving": conf.find('.mobileconf_list_entry_description>div:nth-of-type(2)').text().trim(),
|
||||
"time": conf.find('.mobileconf_list_entry_description>div:nth-of-type(3)').text().trim(),
|
||||
"icon": img.length < 1 ? '' : $(img).attr('src')
|
||||
}));
|
||||
});
|
||||
|
||||
callback(null, confs);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @callback SteamCommunity~getConfirmations
|
||||
* @param {Error|null} err - An Error object on failure, or null on success
|
||||
* @param {CConfirmation[]} confirmations - An array of CConfirmation objects
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the trade offer ID associated with a particular confirmation
|
||||
* @param {int} confID - The ID of the confirmation in question
|
||||
* @param {int} time - The unix timestamp with which the following key was generated
|
||||
* @param {string} key - The confirmation key that was generated using the preceeding time and the tag "details" (this key can be reused)
|
||||
* @param {SteamCommunity~getConfirmationOfferID} callback
|
||||
*/
|
||||
SteamCommunity.prototype.getConfirmationOfferID = function(confID, time, key, callback) {
|
||||
request(this, "details/" + confID, key, time, "details", null, true, function(err, body) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
}
|
||||
|
||||
if(!body.success) {
|
||||
callback(new Error("Cannot load confirmation details"));
|
||||
return;
|
||||
}
|
||||
|
||||
var $ = Cheerio.load(body.html);
|
||||
var offer = $('.tradeoffer');
|
||||
if(offer.length < 1) {
|
||||
callback(null, null);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, offer.attr('id').split('_')[1]);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @callback SteamCommunity~getConfirmationOfferID
|
||||
* @param {Error|null} err - An Error object on failure, or null on success
|
||||
* @param {string} offerID - The trade offer ID associated with the specified confirmation, or null if not for an offer
|
||||
*/
|
||||
|
||||
/**
|
||||
* Confirm or cancel a given confirmation.
|
||||
* @param {int} confID - The ID of the confirmation in question
|
||||
* @param {string} confKey - The confirmation key associated with the confirmation in question (not a TOTP key, the `key` property of CConfirmation)
|
||||
* @param {int} time - The unix timestamp with which the following key was generated
|
||||
* @param {string} key - The confirmation key that was generated using the preceeding time and the tag "allow" (if accepting) or "cancel" (if not accepting)
|
||||
* @param {boolean} accept - true if you want to accept the confirmation, false if you want to cancel it
|
||||
* @param {SteamCommunity~genericErrorCallback} callback - Called when the request is complete
|
||||
*/
|
||||
SteamCommunity.prototype.respondToConfirmation = function(confID, confKey, time, key, accept, callback) {
|
||||
request(this, "ajaxop", key, time, accept ? "allow" : "cancel", {
|
||||
"op": accept ? "allow" : "cancel",
|
||||
"cid": confID,
|
||||
"ck": confKey
|
||||
}, true, function(err, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if(body.success) {
|
||||
callback(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if(body.message) {
|
||||
callback(new Error(body.message));
|
||||
return;
|
||||
}
|
||||
|
||||
callback(new Error("Could not act on confirmation"));
|
||||
});
|
||||
};
|
||||
|
||||
function request(community, url, key, time, tag, params, json, callback) {
|
||||
params = params || {};
|
||||
params.p = "android:" + Date.now();
|
||||
params.a = community.steamID.getSteamID64();
|
||||
params.k = key;
|
||||
params.t = time;
|
||||
params.m = "android";
|
||||
params.tag = tag;
|
||||
|
||||
community.request.get({
|
||||
"uri": "https://steamcommunity.com/mobileconf/" + url,
|
||||
"qs": params,
|
||||
"json": !!json
|
||||
}, function(err, response, body) {
|
||||
if(community._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, body);
|
||||
});
|
||||
}
|
||||
|
||||
// Confirmation checker
|
||||
|
||||
/**
|
||||
* Start automatically polling our confirmations for new ones. The `confKeyNeeded` event will be emitted when we need a confirmation key, or `newConfirmation` when we get a new confirmation
|
||||
* @param {int} pollInterval - The interval, in milliseconds, at which we will poll for confirmations. This shouldn't be any less than 10,000 probably.
|
||||
*/
|
||||
SteamCommunity.prototype.startConfirmationChecker = function(pollInterval) {
|
||||
this._confirmationPollInterval = pollInterval;
|
||||
this._knownConfirmations = this._knownConfirmations || {};
|
||||
this._confirmationKeys = this._confirmationKeys || {};
|
||||
|
||||
if(this._confirmationTimer) {
|
||||
clearTimeout(this._confirmationTimer);
|
||||
}
|
||||
|
||||
setTimeout(this.checkConfirmations.bind(this), 500);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop automatically polling our confirmations.
|
||||
*/
|
||||
SteamCommunity.prototype.stopConfirmationChecker = function() {
|
||||
if(this._confirmationPollInterval) {
|
||||
delete this._confirmationPollInterval;
|
||||
}
|
||||
|
||||
if(this._confirmationTimer) {
|
||||
clearTimeout(this._confirmationTimer);
|
||||
delete this._confirmationTimer;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the confirmation checker right now instead of waiting for the next poll.
|
||||
* Useful to call right after you send/accept an offer that needs confirmation.
|
||||
*/
|
||||
SteamCommunity.prototype.checkConfirmations = function() {
|
||||
if(this._confirmationTimer) {
|
||||
clearTimeout(this._confirmationTimer);
|
||||
delete this._confirmationTimer;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this._confirmationCheckerGetKey('conf', function(err, key) {
|
||||
if(err) {
|
||||
resetTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
self.getConfirmations(key.time, key.key, function(err, confirmations) {
|
||||
if(err) {
|
||||
resetTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
var known = self._knownConfirmations;
|
||||
|
||||
var newOnes = confirmations.filter(function(conf) {
|
||||
return !known[conf.id];
|
||||
});
|
||||
|
||||
if(newOnes.length < 1) {
|
||||
resetTimer();
|
||||
return; // No new ones
|
||||
}
|
||||
|
||||
// We have new confirmations! Grab a key to get details.
|
||||
self._confirmationCheckerGetKey('details', function(err, key) {
|
||||
var handled = 0;
|
||||
|
||||
newOnes.forEach(function(conf) {
|
||||
if(err) {
|
||||
handleNewConfirmation(conf, handled++);
|
||||
} else {
|
||||
// Get its offer ID, if we can
|
||||
conf.getOfferID(key.time, key.key, function(err, offerID) {
|
||||
conf.offerID = offerID ? offerID : null;
|
||||
handleNewConfirmation(conf, handled++);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
resetTimer();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function resetTimer() {
|
||||
if(self._confirmationPollInterval) {
|
||||
self._confirmationTimer = setTimeout(self.checkConfirmations.bind(self), self._confirmationPollInterval);
|
||||
}
|
||||
}
|
||||
|
||||
function handleNewConfirmation(conf, handleNumber) {
|
||||
self._knownConfirmations[conf.id] = conf;
|
||||
|
||||
// Delay them by 1 second per new confirmation that we see, so that keys won't be the same.
|
||||
setTimeout(function() {
|
||||
self.emit('newConfirmation', conf);
|
||||
}, handleNumber * 1000);
|
||||
}
|
||||
};
|
||||
|
||||
SteamCommunity.prototype._confirmationCheckerGetKey = function(tag, callback) {
|
||||
var existing = this._confirmationKeys[tag];
|
||||
var reusable = ['conf', 'details'];
|
||||
|
||||
// See if we already have a key that we can reuse.
|
||||
if(reusable.indexOf(tag) != -1 && existing && (Date.now() - (existing.time * 1000) < (1000 * 60 * 5))) {
|
||||
callback(null, existing);
|
||||
return;
|
||||
}
|
||||
|
||||
// We need a fresh one
|
||||
var self = this;
|
||||
this.emit('confKeyNeeded', tag, function(err, time, key) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
self._confirmationKeys[tag] = {"time": time, "key": key};
|
||||
callback(null, {"time": time, "key": key});
|
||||
});
|
||||
};
|
||||
159
components/twofactor.js
Normal file
159
components/twofactor.js
Normal file
@@ -0,0 +1,159 @@
|
||||
var SteamTotp = require('steam-totp');
|
||||
var SteamCommunity = require('../index.js');
|
||||
|
||||
var ETwoFactorTokenType = {
|
||||
"None": 0, // No token-based two-factor authentication
|
||||
"ValveMobileApp": 1, // Tokens generated using Valve's special charset (5 digits, alphanumeric)
|
||||
"ThirdParty": 2 // Tokens generated using literally everyone else's standard charset (6 digits, numeric). This is disabled.
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.enableTwoFactor = function(callback) {
|
||||
var self = this;
|
||||
|
||||
this.getWebApiOauthToken(function(err, token) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a random device ID hash
|
||||
var hash = require('crypto').createHash('sha1');
|
||||
hash.update(Math.random().toString());
|
||||
hash = hash.digest('hex');
|
||||
|
||||
self.request.post({
|
||||
"uri": "https://api.steampowered.com/ITwoFactorService/AddAuthenticator/v1/",
|
||||
"form": {
|
||||
"steamid": self.steamID.getSteamID64(),
|
||||
"access_token": token,
|
||||
"authenticator_time": Math.floor(Date.now() / 1000),
|
||||
"authenticator_type": ETwoFactorTokenType.ValveMobileApp,
|
||||
"device_identifier": 'android:' + hash,
|
||||
"sms_phone_id": "1"
|
||||
},
|
||||
"json": true
|
||||
}, function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!body.response) {
|
||||
callback(new Error("Malformed response"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(body.response.status != 1) {
|
||||
var error = new Error("Error " + body.response.status);
|
||||
error.eresult = body.response.status;
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, body.response);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.finalizeTwoFactor = function(secret, activationCode, callback) {
|
||||
var attemptsLeft = 30;
|
||||
var diff = 0;
|
||||
|
||||
var self = this;
|
||||
this.getWebApiOauthToken(function(err, token) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
finalize(token);
|
||||
});
|
||||
|
||||
function finalize(token) {
|
||||
var code = SteamTotp.generateAuthCode(secret, diff);
|
||||
|
||||
self.request.post({
|
||||
"uri": "https://api.steampowered.com/ITwoFactorService/FinalizeAddAuthenticator/v1/",
|
||||
"form": {
|
||||
"steamid": self.steamID.getSteamID64(),
|
||||
"access_token": token,
|
||||
"authenticator_code": code,
|
||||
"authenticator_time": Math.floor(Date.now() / 1000),
|
||||
"activation_code": activationCode
|
||||
},
|
||||
"json": true
|
||||
}, function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!body.response) {
|
||||
callback(new Error("Malformed response"));
|
||||
return;
|
||||
}
|
||||
|
||||
body = body.response;
|
||||
|
||||
if(body.server_time) {
|
||||
diff = body.server_time - Math.floor(Date.now() / 1000);
|
||||
}
|
||||
|
||||
if(body.status == 89) {
|
||||
callback(new Error("Invalid activation code"));
|
||||
} else if(body.want_more) {
|
||||
attemptsLeft--;
|
||||
diff += 30;
|
||||
|
||||
finalize(token);
|
||||
} else if(!body.success) {
|
||||
callback(new Error("Error " + body.status));
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.disableTwoFactor = function(revocationCode, callback) {
|
||||
var self = this;
|
||||
|
||||
this.getWebApiOauthToken(function(err, token) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
self.request.post({
|
||||
"uri": "https://api.steampowered.com/ITwoFactorService/RemoveAuthenticator/v1/",
|
||||
"form": {
|
||||
"steamid": self.steamID.getSteamID64(),
|
||||
"access_token": token,
|
||||
"revocation_code": revocationCode,
|
||||
"steamguard_scheme": 1
|
||||
},
|
||||
"json": true
|
||||
}, function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!body.response) {
|
||||
callback(new Error("Malformed response"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!body.response.success) {
|
||||
callback(new Error("Request failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(body.response.status == 1) {
|
||||
callback(null);
|
||||
return;
|
||||
}
|
||||
|
||||
var error = new Error("Cannot remove authenticator (" + body.response.status + ")");
|
||||
error.eresult = body.response.status;
|
||||
callback(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
66
components/webapi.js
Normal file
66
components/webapi.js
Normal file
@@ -0,0 +1,66 @@
|
||||
var SteamCommunity = require('../index.js');
|
||||
|
||||
SteamCommunity.prototype.getWebApiKey = function(domain, callback) {
|
||||
var self = this;
|
||||
this.request({
|
||||
"uri": "https://steamcommunity.com/dev/apikey",
|
||||
"followRedirect": false
|
||||
}, function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(body.match(/<h2>Access Denied<\/h2>/)) {
|
||||
return callback(new Error("Access Denied"));
|
||||
}
|
||||
|
||||
var match = body.match(/<p>Key: ([0-9A-F]+)<\/p>/);
|
||||
if(match) {
|
||||
// We already have an API key registered
|
||||
callback(null, match[1]);
|
||||
} else {
|
||||
// We need to register a new API key
|
||||
self.request.post('https://steamcommunity.com/dev/registerkey', {
|
||||
"form": {
|
||||
"domain": domain,
|
||||
"agreeToTerms": "agreed",
|
||||
"sessionid": self.getSessionID(),
|
||||
"Submit": "Register"
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.getWebApiKey(domain, callback);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.getWebApiOauthToken = function(callback) {
|
||||
var self = this;
|
||||
|
||||
if( this.oAuthToken ) {
|
||||
return callback( null, this.oAuthToken );
|
||||
}
|
||||
|
||||
// Pull an oauth token from the webchat UI
|
||||
this.request("https://steamcommunity.com/chat", function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._checkCommunityError(body, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var match = body.match(/"([0-9a-f]{32})"/);
|
||||
if (!match) {
|
||||
callback(new Error("Malformed response"));
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, match[1]);
|
||||
});
|
||||
};
|
||||
89
index.js
89
index.js
@@ -14,7 +14,11 @@ function SteamCommunity(localAddress) {
|
||||
this._captchaGid = -1;
|
||||
this.chatState = SteamCommunity.ChatState.Offline;
|
||||
|
||||
var defaults = {"jar": this._jar, "timeout": 50000};
|
||||
var defaults = {
|
||||
"jar": this._jar,
|
||||
"timeout": 50000
|
||||
};
|
||||
|
||||
if(localAddress) {
|
||||
defaults.localAddress = localAddress;
|
||||
}
|
||||
@@ -26,6 +30,9 @@ function SteamCommunity(localAddress) {
|
||||
|
||||
// UTC
|
||||
this._jar.setCookie(Request.cookie('timezoneOffset=0,0'), 'https://steamcommunity.com');
|
||||
|
||||
this._jar.setCookie(Request.cookie("mobileClientVersion=0 (2.1.3)"), "https://steamcommunity.com");
|
||||
this._jar.setCookie(Request.cookie("mobileClient=android"), "https://steamcommunity.com");
|
||||
}
|
||||
|
||||
SteamCommunity.prototype.login = function(details, callback) {
|
||||
@@ -35,7 +42,21 @@ SteamCommunity.prototype.login = function(details, callback) {
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.request.post("https://steamcommunity.com/login/getrsakey/", {"form": {"username": details.accountName}}, function(err, response, body) {
|
||||
|
||||
// headers required to convince steam that we're logging in from a mobile device so that we can get the oAuth data
|
||||
var mobileHeaders = {
|
||||
"X-Requested-With": "com.valvesoftware.android.steam.community",
|
||||
"referer": "https://steamcommunity.com/mobilelogin?oauth_client_id=DE45CD61&oauth_scope=read_profile%20write_profile%20read_client%20write_client",
|
||||
"user-agent": "Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; Google Nexus 4 - 4.1.1 - API 16 - 768x1280 Build/JRO03S) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
||||
"accept": "text/javascript, text/html, application/xml, text/xml, */*"
|
||||
};
|
||||
|
||||
this.request.post("https://steamcommunity.com/login/getrsakey/", {
|
||||
"form": {
|
||||
"username": details.accountName
|
||||
},
|
||||
"headers": mobileHeaders
|
||||
}, function(err, response, body) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
@@ -57,18 +78,21 @@ SteamCommunity.prototype.login = function(details, callback) {
|
||||
"captchagid": self._captchaGid,
|
||||
"emailauth": details.authCode || "",
|
||||
"emailsteamid": "",
|
||||
"loginfriendlyname": "",
|
||||
"password": hex2b64(key.encrypt(details.password)),
|
||||
"remember_login": "true",
|
||||
"rsatimestamp": json.timestamp,
|
||||
"twofactorcode": details.twoFactorCode || "",
|
||||
"username": details.accountName
|
||||
"username": details.accountName,
|
||||
"oauth_client_id": "DE45CD61",
|
||||
"oauth_scope": "read_profile write_profile read_client write_client",
|
||||
"loginfriendlyname": "#login_emailauth_friendlyname_mobile"
|
||||
};
|
||||
|
||||
self.request.post({
|
||||
"uri": "https://steamcommunity.com/login/dologin/",
|
||||
"json": true,
|
||||
"form": form
|
||||
"form": form,
|
||||
"headers": mobileHeaders
|
||||
}, function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
@@ -94,9 +118,12 @@ SteamCommunity.prototype.login = function(details, callback) {
|
||||
callback(new Error(body.message || "Unknown error"));
|
||||
} else {
|
||||
var sessionID = generateSessionID();
|
||||
var oAuth = JSON.parse( body.oauth );
|
||||
self._jar.setCookie(Request.cookie('sessionid=' + sessionID), 'http://steamcommunity.com');
|
||||
|
||||
self.steamID = new SteamID(body.transfer_parameters.steamid);
|
||||
self.steamID = new SteamID(oAuth.steamid);
|
||||
self.oAuthToken = oAuth.oauth_token;
|
||||
|
||||
var cookies = self._jar.getCookieString("https://steamcommunity.com").split(';').map(function(cookie) {
|
||||
return cookie.trim();
|
||||
});
|
||||
@@ -145,45 +172,7 @@ SteamCommunity.prototype.getSessionID = function() {
|
||||
|
||||
function generateSessionID() {
|
||||
return Math.floor(Math.random() * 1000000000);
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.getWebApiKey = function(domain, callback) {
|
||||
var self = this;
|
||||
this.request({
|
||||
"uri": "https://steamcommunity.com/dev/apikey",
|
||||
"followRedirect": false
|
||||
}, function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(body.match(/<h2>Access Denied<\/h2>/)) {
|
||||
return callback(new Error("Access Denied"));
|
||||
}
|
||||
|
||||
var match = body.match(/<p>Key: ([0-9A-F]+)<\/p>/);
|
||||
if(match) {
|
||||
// We already have an API key registered
|
||||
callback(null, match[1]);
|
||||
} else {
|
||||
// We need to register a new API key
|
||||
self.request.post('https://steamcommunity.com/dev/registerkey', {
|
||||
"form": {
|
||||
"domain": domain,
|
||||
"agreeToTerms": "agreed",
|
||||
"sessionid": self.getSessionID(),
|
||||
"Submit": "Register"
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.getWebApiKey(domain, callback);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
SteamCommunity.prototype.parentalUnlock = function(pin, callback) {
|
||||
this.request.post("https://steamcommunity.com/parental/ajaxunlock", {
|
||||
@@ -213,6 +202,7 @@ SteamCommunity.prototype.parentalUnlock = function(pin, callback) {
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.getNotifications = function(callback) {
|
||||
var self = this;
|
||||
this.request.get("https://steamcommunity.com/actions/RefreshNotificationArea", function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
@@ -248,6 +238,7 @@ SteamCommunity.prototype.getNotifications = function(callback) {
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.resetItemNotifications = function(callback) {
|
||||
var self = this;
|
||||
this.request.get("https://steamcommunity.com/my/inventory", function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
@@ -332,7 +323,15 @@ require('./components/market.js');
|
||||
require('./components/groups.js');
|
||||
require('./components/users.js');
|
||||
require('./components/inventoryhistory.js');
|
||||
require('./components/webapi.js');
|
||||
require('./components/twofactor.js');
|
||||
require('./components/confirmations.js');
|
||||
require('./classes/CMarketItem.js');
|
||||
require('./classes/CMarketSearchResult.js');
|
||||
require('./classes/CSteamGroup.js');
|
||||
require('./classes/CSteamUser.js');
|
||||
|
||||
/**
|
||||
@callback SteamCommunity~genericErrorCallback
|
||||
@param {Error|null} err - An Error object on failure, or null on success
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "steamcommunity",
|
||||
"version": "3.9.9",
|
||||
"version": "3.12.2",
|
||||
"description": "Provides an interface for logging into and interacting with the Steam Community website",
|
||||
"keywords": ["steam", "steam community"],
|
||||
"homepage": "https://github.com/DoctorMcKay/node-steamcommunity",
|
||||
@@ -18,6 +18,7 @@
|
||||
"steamid": "^0.3.1",
|
||||
"xml2js": "^0.4.11",
|
||||
"cheerio": "^0.19.0",
|
||||
"async": "^1.4.2"
|
||||
"async": "^1.4.2",
|
||||
"steam-totp": "^1.0.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user