Compare commits

...

12 Commits

Author SHA1 Message Date
Alexander Corn
cff35ba863 3.9.0 2015-09-09 12:04:52 -04:00
Alexander Corn
d975fdfba8 Added getInventoryHistory method 2015-09-09 12:04:28 -04:00
Alexander Corn
4e3c319ee1 Added async dependency 2015-09-09 11:52:31 -04:00
Alexander Corn
e5cbd23110 3.8.0 2015-09-07 00:10:38 -04:00
Alexander Corn
82f1d490f9 Added contextid property to CEconItem objects 2015-09-07 00:10:32 -04:00
Alexander Corn
c3f5b492b3 Added inventory methods to CSteamUser 2015-09-07 00:01:35 -04:00
Alexander Corn
09cd81b607 Added CEconItem and getUserInventory 2015-09-07 00:00:19 -04:00
Alexander Corn
8a6d912374 Added getUserInventoryContexts 2015-09-06 23:22:10 -04:00
Alexander Corn
c392f2ac74 3.7.2 2015-09-02 17:28:27 -04:00
Alexander Corn
8e6f859269 Properly handle all instances of access being denied because not logged in 2015-09-02 17:28:13 -04:00
Alexander Corn
84dce9872a 3.7.1 2015-09-02 17:22:17 -04:00
Alexander Corn
c2ad457e87 Fixed getWebApiKey not failing if not logged in 2015-09-02 17:19:12 -04:00
6 changed files with 326 additions and 9 deletions

59
classes/CEconItem.js Normal file
View File

@@ -0,0 +1,59 @@
module.exports = CEconItem;
function CEconItem(item, descriptions, contextID) {
var thing;
for(thing in item) {
if(item.hasOwnProperty(thing)) {
this[thing] = item[thing];
}
}
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];
}
}
}
}
this.tradable = !!this.tradable;
this.marketable = !!this.marketable;
this.commodity = !!this.commodity;
this.market_tradable_restriction = (this.market_tradable_restriction ? parseInt(this.market_tradable_restriction, 10) : 0);
this.market_marketable_restriction = (this.market_marketable_restriction ? parseInt(this.market_marketable_restriction, 10) : 0);
}
CEconItem.prototype.getImageURL = function() {
return "https://steamcommunity-a.akamaihd.net/economy/image/" + this.icon_url + "/";
};
CEconItem.prototype.getLargeImageURL = function() {
if(!this.icon_url_large) {
return this.getImageURL();
}
return "https://steamcommunity-a.akamaihd.net/economy/image/" + this.icon_url_large + "/";
};
CEconItem.prototype.getTag = function(category) {
if(!this.tags) {
return null;
}
for(var i = 0; i < this.tags.length; i++) {
if(this.tags[i].category == category) {
return this.tags[i];
}
}
return null;
};

View File

@@ -134,3 +134,11 @@ CSteamUser.prototype.comment = function(message, callback) {
CSteamUser.prototype.inviteToGroup = function(groupID, callback) {
this._community.inviteUserToGroup(this.steamID, groupID, callback);
};
CSteamUser.prototype.getInventoryContexts = function(callback) {
this._community.getUserInventoryContexts(this.steamID, callback);
};
CSteamUser.prototype.getInventory = function(appID, contextID, tradableOnly, callback) {
this._community.getInventory(appID, contextID, tradableOnly, callback);
};

View File

@@ -0,0 +1,141 @@
var SteamCommunity = require('../index.js');
var CEconItem = require('../classes/CEconItem.js');
var SteamID = require('steamid');
var request = require('request');
var Cheerio = require('cheerio');
var Async = require('async');
SteamCommunity.prototype.getInventoryHistory = function(options, callback) {
if(typeof options === 'function') {
callback = options;
options = {};
}
options.page = options.page || 1;
this.request("https://steamcommunity.com/my/inventoryhistory?l=english&p=" + options.page, function(err, response, body) {
if(err) {
callback(err);
return;
}
var output = {};
var vanityURLs = [];
var $ = Cheerio.load(body);
var html = $('.inventory_history_pagingrow').html();
if(!html) {
callback("Malformed page: no paging row found");
return;
}
var match = html.match(/(\d+) - (\d+) of (\d+) History Items/);
output.first = parseInt(match[1], 10);
output.last = parseInt(match[2], 10);
output.totalTrades = parseInt(match[3], 10);
// Load the inventory item data
var match2 = body.match(/var g_rgHistoryInventory = (.*);/);
if(!match2) {
callback("Malformed page: no trade found");
return;
}
var historyInventory = JSON.parse(match2[1]);
output.trades = [];
var trades = $('.tradehistoryrow');
var item, trade, profileLink, items, j, econItem, timeMatch, time;
for(var i = 0; i < trades.length; i++) {
item = $(trades[i]);
trade = {};
timeMatch = item.find('.tradehistory_timestamp').html().match(/(\d+):(\d+)(am|pm)/);
if(timeMatch[1] == 12 && timeMatch[3] == 'am') {
timeMatch[1] = 0;
}
if(timeMatch[1] < 12 && timeMatch[3] == 'pm') {
timeMatch[1] = parseInt(timeMatch[1], 10) + 12;
}
time = (timeMatch[1] < 10 ? '0' : '') + timeMatch[1] + ':' + timeMatch[2] + ':00';
trade.date = new Date(item.find('.tradehistory_date').html() + ' ' + time);
trade.partnerName = item.find('.tradehistory_event_description a').html();
trade.partnerSteamID = null;
trade.partnerVanityURL = null;
trade.itemsReceived = [];
trade.itemsGiven = [];
profileLink = item.find('.tradehistory_event_description a').attr('href');
if(profileLink.indexOf('/profiles/') != -1) {
trade.partnerSteamID = new SteamID(profileLink.match(/(\d+)$/)[1]);
} else {
trade.partnerVanityURL = profileLink.match(/\/([^\/]+)$/)[1];
if(options.resolveVanityURLs && vanityURLs.indexOf(trade.partnerVanityURL) == -1) {
vanityURLs.push(trade.partnerVanityURL);
}
}
items = item.find('.history_item');
for(j = 0; j < items.length; j++) {
match = body.match(new RegExp("HistoryPageCreateItemHover\\( '" + $(items[j]).attr('id') + "', (\\d+), '(\\d+)', '(\\d+)', '(\\d+)' \\);"));
econItem = historyInventory[match[1]][match[2]][match[3]];
if($(items[j]).attr('id').indexOf('received') != -1) {
trade.itemsReceived.push(new CEconItem(econItem));
} else {
trade.itemsGiven.push(new CEconItem(econItem));
}
}
output.trades.push(trade);
}
if(options.resolveVanityURLs) {
Async.map(vanityURLs, resolveVanityURL, function(err, results) {
if(err) {
callback(err);
return;
}
for(i = 0; i < output.trades.length; i++) {
if(output.trades[i].partnerSteamID || !output.trades[i].partnerVanityURL) {
continue;
}
// Find the vanity URL
for(j = 0; j < results.length; j++) {
if(results[j].vanityURL == output.trades[i].partnerVanityURL) {
output.trades[i].partnerSteamID = new SteamID(results[j].steamID);
break;
}
}
}
callback(null, output);
});
} else {
callback(null, output);
}
});
};
function resolveVanityURL(vanityURL, callback) {
request("https://steamcommunity.com/id/" + vanityURL + "/?xml=1", function(err, response, body) {
if(err) {
callback(err);
return;
}
var match = body.match(/<steamID64>(\d+)<\/steamID64>/);
if(!match || !match[1]) {
callback("Couldn't find Steam ID");
return;
}
callback(null, {"vanityURL": vanityURL, "steamID": match[1]});
});
}

View File

@@ -1,5 +1,6 @@
var SteamCommunity = require('../index.js');
var SteamID = require('steamid');
var CEconItem = require('../classes/CEconItem.js');
SteamCommunity.prototype.addFriend = function(userID, callback) {
if(typeof userID === 'string') {
@@ -197,3 +198,101 @@ SteamCommunity.prototype.inviteUserToGroup = function(userID, groupID, callback)
}
});
};
SteamCommunity.prototype.getUserInventoryContexts = function(userID, callback) {
if(typeof userID === 'string') {
userID = new SteamID(userID);
}
if(typeof userID === 'function') {
callback = userID;
userID = this.steamID;
}
if(!userID) {
callback(new Error("No SteamID specified and not logged in"));
return;
}
var self = this;
this.request("https://steamcommunity.com/profiles/" + userID.getSteamID64() + "/inventory/", function(err, response, body) {
if(self._checkHttpError(err, response, callback)) {
return;
}
var match = body.match(/var g_rgAppContextData = ([^\n]+);\r?\n/);
if(!match) {
callback(new Error("Malformed response"));
return;
}
var data;
try {
data = JSON.parse(match[1]);
} catch(e) {
callback(new Error("Malformed response"));
return;
}
callback(null, data);
});
};
SteamCommunity.prototype.getUserInventory = function(userID, appID, contextID, tradableOnly, callback) {
var self = this;
if(typeof userID === 'string') {
userID = new SteamID(userID);
}
var endpoint = "/profiles/" + userID.getSteamID64();
get([], []);
function get(inventory, currency, start) {
self.request({
"uri": "https://steamcommunity.com" + endpoint + "/inventory/json/" + appID + "/" + contextID,
"qs": {
"start": start,
"trading": tradableOnly ? 1 : undefined
},
"json": true
}, function(err, response, body) {
if(self._checkHttpError(err, response, callback)) {
return;
}
if(!body || !body.success || !body.rgInventory || !body.rgDescriptions || !body.rgCurrency) {
callback(new Error(body.Error || "Malformed response"));
return;
}
var i;
for(i in body.rgInventory) {
if(!body.rgInventory.hasOwnProperty(i)) {
continue;
}
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);
} else {
callback(null, inventory, currency);
}
});
}
};

View File

@@ -149,7 +149,10 @@ function generateSessionID() {
SteamCommunity.prototype.getWebApiKey = function(domain, callback) {
var self = this;
this.request("https://steamcommunity.com/dev/apikey", function(err, response, body) {
this.request({
"uri": "https://steamcommunity.com/dev/apikey",
"followRedirect": false
}, function(err, response, body) {
if(self._checkHttpError(err, response, callback)) {
return;
}
@@ -172,8 +175,8 @@ SteamCommunity.prototype.getWebApiKey = function(domain, callback) {
"Submit": "Register"
}
}, function(err, response, body) {
if(err || response.statusCode >= 400) {
return callback(err.message || "HTTP error " + response.statusCode);
if(self._checkHttpError(err, response, callback)) {
return;
}
self.getWebApiKey(domain, callback);
@@ -308,7 +311,12 @@ SteamCommunity.prototype._checkHttpError = function(err, response, callback) {
return true;
}
if(response.statusCode != 200) {
if(response.statusCode >= 300 && response.statusCode <= 399 && response.headers.location.indexOf('/login') != -1) {
callback(new Error("Not Logged In"));
return true;
}
if(response.statusCode >= 400) {
var error = new Error("HTTP error " + response.statusCode);
error.code = response.statusCode;
callback(error);
@@ -323,6 +331,7 @@ require('./components/profile.js');
require('./components/market.js');
require('./components/groups.js');
require('./components/users.js');
require('./components/inventoryhistory.js');
require('./classes/CMarketItem.js');
require('./classes/CMarketSearchResult.js');
require('./classes/CSteamGroup.js');

View File

@@ -1,6 +1,6 @@
{
"name": "steamcommunity",
"version": "3.7.0",
"version": "3.9.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",
@@ -13,10 +13,11 @@
"url": "https://github.com/DoctorMcKay/node-steamcommunity.git"
},
"dependencies": {
"request": "^2.58.0",
"request": "^2.61.0",
"node-bignumber": "^1.2.1",
"steamid": "^0.3.0",
"xml2js": "^0.4.9",
"cheerio": "^0.19.0"
"steamid": "^0.3.1",
"xml2js": "^0.4.11",
"cheerio": "^0.19.0",
"async": "^1.4.2"
}
}