mirror of
https://github.com/DoctorMcKay/node-steamcommunity.git
synced 2026-08-19 21:23:28 +08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1afcd1962 | ||
|
|
513b0bff1c | ||
|
|
ab037b1931 | ||
|
|
06df0ecd42 | ||
|
|
b789e13a70 | ||
|
|
95a36b00c1 | ||
|
|
41c87501c4 | ||
|
|
4f3ddcc787 | ||
|
|
d10fa9983d | ||
|
|
666226731e | ||
|
|
d096f47cac | ||
|
|
a8eedb3067 |
@@ -2,30 +2,34 @@ module.exports = CEconItem;
|
||||
|
||||
function CEconItem(item, descriptions, contextID) {
|
||||
var thing;
|
||||
for(thing in item) {
|
||||
if(item.hasOwnProperty(thing)) {
|
||||
for (thing in item) {
|
||||
if (item.hasOwnProperty(thing)) {
|
||||
this[thing] = item[thing];
|
||||
}
|
||||
}
|
||||
|
||||
this.assetid = this.id = (this.id || this.assetid);
|
||||
var isCurrency = (typeof this.is_currency !== 'undefined') ? (!!this.is_currency) : (typeof this.currencyid !== 'undefined'); // I don't want to put this on the object yet; it's nice to have the ids at the top of printed output
|
||||
|
||||
if (isCurrency) {
|
||||
this.currencyid = this.id = (this.id || this.currencyid);
|
||||
} else {
|
||||
this.assetid = this.id = (this.id || this.assetid);
|
||||
}
|
||||
|
||||
this.instanceid = this.instanceid || '0';
|
||||
this.amount = parseInt(this.amount, 10);
|
||||
this.contextid = this.contextid || contextID.toString();
|
||||
|
||||
// Merge the description
|
||||
if(descriptions) {
|
||||
var description = descriptions[this.classid + '_' + this.instanceid];
|
||||
if(description) {
|
||||
for(thing in description) {
|
||||
if(description.hasOwnProperty(thing)) {
|
||||
this[thing] = description[thing];
|
||||
}
|
||||
if (descriptions) {
|
||||
for (thing in descriptions) {
|
||||
if (descriptions.hasOwnProperty(thing)) {
|
||||
this[thing] = descriptions[thing];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.is_currency = !!this.is_currency;
|
||||
this.is_currency = isCurrency;
|
||||
this.tradable = !!this.tradable;
|
||||
this.marketable = !!this.marketable;
|
||||
this.commodity = !!this.commodity;
|
||||
@@ -34,7 +38,7 @@ function CEconItem(item, descriptions, contextID) {
|
||||
this.fraudwarnings = this.fraudwarnings || [];
|
||||
this.descriptions = this.descriptions || [];
|
||||
|
||||
if(this.owner && JSON.stringify(this.owner) == '{}') {
|
||||
if (this.owner && JSON.stringify(this.owner) == '{}') {
|
||||
this.owner = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,12 +156,28 @@ SteamCommunity.prototype.acceptConfirmationForObject = function(identitySecret,
|
||||
var self = this;
|
||||
this._usedConfTimes = this._usedConfTimes || [];
|
||||
|
||||
SteamTotp.getTimeOffset(function(err, offset) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if (typeof this._timeOffset !== 'undefined') {
|
||||
// time offset is already known and saved
|
||||
doConfirmation();
|
||||
} else {
|
||||
SteamTotp.getTimeOffset(function(err, offset) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
self._timeOffset = offset;
|
||||
doConfirmation();
|
||||
|
||||
setTimeout(function() {
|
||||
// Delete the saved time offset after 12 hours because why not
|
||||
delete self._timeOffset;
|
||||
}, 1000 * 60 * 60 * 12);
|
||||
});
|
||||
}
|
||||
|
||||
function doConfirmation() {
|
||||
var offset = self._timeOffset;
|
||||
var time = SteamTotp.time(offset);
|
||||
self.getConfirmations(time, SteamTotp.getConfirmationKey(identitySecret, time, "conf"), function(err, confs) {
|
||||
if (err) {
|
||||
@@ -190,7 +206,7 @@ SteamCommunity.prototype.acceptConfirmationForObject = function(identitySecret,
|
||||
|
||||
conf.respond(time, SteamTotp.getConfirmationKey(identitySecret, time, "allow"), true, callback);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -313,8 +329,9 @@ SteamCommunity.prototype.checkConfirmations = function() {
|
||||
// We should accept this
|
||||
self.emit('debug', "Accepting confirmation #" + conf.id);
|
||||
var time = Math.floor(Date.now() / 1000);
|
||||
conf.respond(time, SteamTotp.getConfirmationKey(self._identitySecret, time, "allow"), true, function() {
|
||||
conf.respond(time, SteamTotp.getConfirmationKey(self._identitySecret, time, "allow"), true, function(err) {
|
||||
// If there was an error and it wasn't actually accepted, we'll pick it up again
|
||||
if (!err) self.emit('confirmationAccepted', conf);
|
||||
delete self._knownConfirmations[conf.id];
|
||||
setTimeout(callback, 1000); // Call the callback in 1 second, to make sure the time changes
|
||||
});
|
||||
@@ -366,28 +383,6 @@ SteamCommunity.prototype.checkConfirmations = function() {
|
||||
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() {
|
||||
if(self._identitySecret) {
|
||||
self.emit('debug', 'Accepting confirmation #' + conf.id);
|
||||
var time = Math.floor(Date.now() / 1000);
|
||||
conf.respond(time, SteamTotp.getConfirmationKey(self._identitySecret, time, "allow"), true, function(err) {
|
||||
if (err) {
|
||||
self.emit('debug', "Can't accept confirmation #" + conf.id + ": " + err.message);
|
||||
}
|
||||
|
||||
// We'll just retry next time we poll
|
||||
delete self._knownConfirmations[conf.id];
|
||||
});
|
||||
} else {
|
||||
self.emit('newConfirmation', conf);
|
||||
}
|
||||
}, handleNumber * 1000);
|
||||
}
|
||||
};
|
||||
|
||||
SteamCommunity.prototype._confirmationCheckerGetKey = function(tag, callback) {
|
||||
|
||||
@@ -47,10 +47,10 @@ SteamCommunity.prototype.httpRequest = function(uri, options, callback, source)
|
||||
|
||||
self.request(options, function (err, response, body) {
|
||||
var hasCallback = !!callback;
|
||||
var httpError = options.checkHttpError !== false && self._checkHttpError(err, response, callback);
|
||||
var httpError = options.checkHttpError !== false && self._checkHttpError(err, response, callback, body);
|
||||
var communityError = !options.json && options.checkCommunityError !== false && self._checkCommunityError(body, httpError ? function () {} : callback); // don't fire the callback if hasHttpError did it already
|
||||
var tradeError = !options.json && options.checkTradeError !== false && self._checkTradeError(body, httpError || communityError ? function () {} : callback); // don't fire the callback if either of the previous already did
|
||||
var jsonError = options.json && !body ? new Error("Malformed JSON response") : null;
|
||||
var jsonError = options.json && options.checkJsonError !== false && !body ? new Error("Malformed JSON response") : null;
|
||||
|
||||
self.emit('postHttpRequest', requestID, source, options, httpError || communityError || tradeError || jsonError || null, response, body, {
|
||||
"hasCallback": hasCallback,
|
||||
@@ -85,29 +85,29 @@ SteamCommunity.prototype._notifySessionExpired = function(err) {
|
||||
this.emit('sessionExpired', err);
|
||||
};
|
||||
|
||||
SteamCommunity.prototype._checkHttpError = function(err, response, callback) {
|
||||
SteamCommunity.prototype._checkHttpError = function(err, response, callback, body) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
callback(err, response, body);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (response.statusCode >= 300 && response.statusCode <= 399 && response.headers.location.indexOf('/login') != -1) {
|
||||
err = new Error("Not Logged In");
|
||||
callback(err);
|
||||
callback(err, response, body);
|
||||
this._notifySessionExpired(err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (response.statusCode == 403 && response.body && response.body.match(/<div id="parental_notice_instructions">Enter your PIN below to exit Family View.<\/div>/)) {
|
||||
err = new Error("Family View Restricted");
|
||||
callback(err);
|
||||
callback(err, response, body);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (response.statusCode >= 400) {
|
||||
err = new Error("HTTP error " + response.statusCode);
|
||||
err.code = response.statusCode;
|
||||
callback(err);
|
||||
callback(err, response, body);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -263,27 +263,34 @@ SteamCommunity.prototype.getUserInventory = function(userID, appID, contextID, t
|
||||
if(typeof userID === 'string') {
|
||||
userID = new SteamID(userID);
|
||||
}
|
||||
|
||||
get([], [], 1);
|
||||
|
||||
var endpoint = "/profiles/" + userID.getSteamID64();
|
||||
get([], []);
|
||||
|
||||
function get(inventory, currency, start) {
|
||||
function get(inventory, currency, step, start) {
|
||||
self.httpRequest({
|
||||
"uri": "https://steamcommunity.com" + endpoint + "/inventory/json/" + appID + "/" + contextID,
|
||||
"uri": "https://steamcommunity.com/inventory/" + userID.getSteamID64() + "/" + appID + "/" + contextID,
|
||||
"qs": {
|
||||
"start": start,
|
||||
"trading": tradableOnly ? 1 : undefined
|
||||
"l": "english", // Default language
|
||||
"count": 5000, // Max items per 'page'
|
||||
"start_assetid": start
|
||||
},
|
||||
"json": true
|
||||
}, function(err, response, body) {
|
||||
if (err) {
|
||||
if (err.message == "HTTP error 403" && body === null) {
|
||||
// 403 with a body of "null" means the inventory/profile is private.
|
||||
callback(new Error("This profile is private."));
|
||||
return;
|
||||
}
|
||||
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!body || !body.success || !body.rgInventory || !body.rgDescriptions || !body.rgCurrency) {
|
||||
if(body) {
|
||||
callback(new Error(body.Error || "Malformed response"));
|
||||
if (!body || !body.success || !body.assets || !body.descriptions) {
|
||||
if (body) {
|
||||
// Dunno if the error/Error property even exists on this new endpoint
|
||||
callback(new Error(body.error || body.Error || "Malformed response"));
|
||||
} else {
|
||||
callback(new Error("Malformed response"));
|
||||
}
|
||||
@@ -291,33 +298,40 @@ SteamCommunity.prototype.getUserInventory = function(userID, appID, contextID, t
|
||||
return;
|
||||
}
|
||||
|
||||
var i;
|
||||
for(i in body.rgInventory) {
|
||||
if(!body.rgInventory.hasOwnProperty(i)) {
|
||||
continue;
|
||||
for (var i = 0; i < body.assets.length; i++) {
|
||||
var description = getDescription(body.descriptions, body.assets[i].classid, body.assets[i].instanceid);
|
||||
|
||||
if (!tradableOnly || (description && description.tradable)) {
|
||||
(body.assets[i].currencyid ? currency : inventory).push(new CEconItem(body.assets[i], description, contextID));
|
||||
}
|
||||
|
||||
inventory.push(new CEconItem(body.rgInventory[i], body.rgDescriptions, contextID));
|
||||
}
|
||||
|
||||
for(i in body.rgCurrency) {
|
||||
if(!body.rgCurrency.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
currency.push(new CEconItem(body.rgInventory[i], body.rgDescriptions, contextID));
|
||||
}
|
||||
|
||||
if(body.more) {
|
||||
var match = response.request.uri.href.match(/\/(profiles|id)\/([^\/]+)\//);
|
||||
if(match) {
|
||||
endpoint = "/" + match[1] + "/" + match[2];
|
||||
}
|
||||
|
||||
get(inventory, currency, body.more_start);
|
||||
if(body.total_inventory_count > 5000 * step) {
|
||||
get(inventory, currency, step + 1, body.assets[body.assets.length - 1].assetid);
|
||||
} else {
|
||||
callback(null, inventory, currency);
|
||||
callback(null, inventory, currency, body.total_inventory_count);
|
||||
}
|
||||
}, "steamcommunity");
|
||||
}
|
||||
|
||||
// A bit of optimization; objects are hash tables so it's more efficient to look up by key than to iterate an array
|
||||
var quickDescriptionLookup = {};
|
||||
|
||||
function getDescription(descriptions, classID, instanceID) {
|
||||
instanceID = instanceID || '0'; // instanceID can be undefined, in which case it's 0.
|
||||
|
||||
var key = classID + '_' + instanceID;
|
||||
|
||||
if (quickDescriptionLookup[key]) {
|
||||
return quickDescriptionLookup[key];
|
||||
}
|
||||
|
||||
for (var i = 0; i < descriptions.length; i++) {
|
||||
quickDescriptionLookup[key] = descriptions[i];
|
||||
|
||||
if (descriptions[i].classid == classID && descriptions[i].instanceid == instanceID) {
|
||||
return descriptions[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "steamcommunity",
|
||||
"version": "3.27.1",
|
||||
"version": "3.29.0",
|
||||
"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",
|
||||
|
||||
Reference in New Issue
Block a user