Compare commits

...

20 Commits

Author SHA1 Message Date
Alexander Corn
dd638df118 3.23.2 2016-08-09 15:45:32 -04:00
Alexander Corn
b937a05442 Make sure we actually get json back when we want it (fixes #122) 2016-08-09 15:45:21 -04:00
Alexander Corn
9c34d18cd9 3.23.1 2016-08-07 00:04:56 -04:00
Alexander Corn
02e3798124 Handle some cases where the session expires while we're using webchat 2016-08-07 00:04:30 -04:00
Alexander Corn
5d9922cc33 3.23.0 2016-07-13 13:12:39 -04:00
Alexander Corn
153011e1c9 Make _community non-enumerable on CConfirmation 2016-07-13 13:11:56 -04:00
Alexander Corn
575c196cb7 Added acceptAllConfirmations method 2016-07-13 13:11:44 -04:00
Alexander Corn
47a24d19cf Added ability to act on multiple confirmations 2016-07-13 13:11:36 -04:00
Alexander Corn
0eac19b71c 3.22.0 2016-07-10 01:02:48 -04:00
Alexander Corn
ca73ecc786 Parse times in getUserAliases into Date objects 2016-07-10 01:02:36 -04:00
Alexander Corn
e8733613d7 Merge pull request #117 from andrewda/master
Add ability to get user aliases
2016-07-10 00:52:13 -04:00
Andrew Dassonville
89a1df67ec Add ability to get user aliases 2016-07-06 16:20:42 -07:00
Alexander Corn
3ba0a8592e 3.21.2 2016-07-01 18:30:32 -04:00
Alexander Corn
57fa7a679f Fixed market search results including query string (fixes #113) 2016-07-01 18:29:56 -04:00
Alexander Corn
446e315183 Fixed market search result prices being horribly wrong 2016-07-01 18:27:39 -04:00
Alexander Corn
c6a9b74471 3.21.1 2016-06-29 23:08:54 -04:00
Alexander Corn
018e18cb5d Give "Family View Restricted" error if access denied due to Family View 2016-06-29 23:08:40 -04:00
Alexander Corn
303ce10e73 3.21.0 2016-06-27 16:57:12 -04:00
Alexander Corn
60e0e63a92 Fixed marketSearch (fixes #112) 2016-06-27 16:56:16 -04:00
Luke
17e5b94782 Added deleting events in CSteamGroup (#109)
* Added deleteEvent()

* Added deleteGroupEvent()
2016-06-21 22:39:23 -04:00
11 changed files with 197 additions and 64 deletions

View File

@@ -1,7 +1,7 @@
module.exports = CConfirmation;
function CConfirmation(community, data) {
this._community = community;
Object.defineProperty(this, "_community", {"value": community});
this.id = data.id;
this.key = data.key;

View File

@@ -27,60 +27,63 @@ SteamCommunity.prototype.marketSearch = function(options, callback) {
qs.count = 100;
qs.sort_column = 'price';
qs.sort_dir = 'asc';
performSearch.call(this, this.httpRequest, qs, [], callback);
var self = this;
var results = [];
performSearch();
function performSearch() {
self.httpRequest({
"uri": "https://steamcommunity.com/market/search/render/",
"qs": qs,
"headers": {
"referer": "https://steamcommunity.com/market/search"
},
"json": true
}, function(err, response, body) {
if (err) {
callback(err);
return;
}
if(!body.success) {
callback(new Error("Success is not true"));
return;
}
if(!body.results_html) {
callback(new Error("No results_html in response"));
return;
}
var $ = Cheerio.load(body.results_html);
var $errorMsg = $('.market_listing_table_message');
if($errorMsg.length > 0) {
callback(new Error($errorMsg.text()));
return;
}
var rows = $('.market_listing_row_link');
for(var i = 0; i < rows.length; i++) {
results.push(new CMarketSearchResult($(rows[i])));
}
if(body.start + body.pagesize >= body.total_count) {
callback(null, results);
} else {
qs.start += body.pagesize;
performSearch();
}
}, "steamcommunity");
}
};
function performSearch(request, qs, results, callback) {
var self = this;
request({
"uri": "https://steamcommunity.com/market/search/render/",
"qs": qs,
"headers": {
"referer": "https://steamcommunity.com/market/search"
},
"json": true
}, function(err, response, body) {
if (err) {
callback(err);
return;
}
if(!body.success) {
callback(new Error("Success is not true"));
return;
}
if(!body.results_html) {
callback(new Error("No results_html in response"));
return;
}
var $ = Cheerio.load(body.results_html);
if($('.market_listing_table_message').length > 0) {
callback(new Error($('.market_listing_table_message').text()));
return;
}
var rows = $('.market_listing_row_link');
for(var i = 0; i < rows.length; i++) {
results.push(new CMarketSearchResult($(rows[i])));
}
if(body.start + body.pagesize >= body.total_count) {
callback(null, results);
} else {
qs.start += body.pagesize;
performSearch.call(self, request, qs, results, callback);
}
}, "steamcommunity");
}
function CMarketSearchResult(row) {
var match = row.attr('href').match(/\/market\/listings\/(\d+)\/(.+)/);
var match = row.attr('href').match(/\/market\/listings\/(\d+)\/([^\?\/]+)/);
this.appid = parseInt(match[1], 10);
this.market_hash_name = decodeURIComponent(match[2]);
this.image = row.find('.market_listing_item_img').attr('src').match(/^https?:\/\/[^\/]+\/economy\/image\/[^\/]+\//)[0];
this.price = parseInt(row.find('.market_listing_their_price .market_table_value span').text().replace(/[^\d]+/g, ''), 10);
this.price = parseInt(row.find('.market_listing_their_price .market_table_value span.normal_price').text().replace(/[^\d]+/g, ''), 10);
this.quantity = parseInt(row.find('.market_listing_num_listings_qty').text().replace(/[^\d]+/g, ''), 10);
}

View File

@@ -98,6 +98,10 @@ CSteamGroup.prototype.editEvent = function(id, name, type, description, time, se
this._community.editGroupEvent(this.steamID, id, name, type, description, time, server, callback);
};
CSteamGroup.prototype.deleteEvent = function (id, callback) {
this._community.deleteGroupEvent(this.steamID, id, callback);
};
CSteamGroup.prototype.setPlayerOfTheWeek = function(steamID, callback) {
this._community.setGroupPlayerOfTheWeek(this.steamID, steamID, callback);
};

View File

@@ -150,6 +150,10 @@ CSteamUser.prototype.inviteToGroup = function(groupID, callback) {
this._community.inviteUserToGroup(this.steamID, groupID, callback);
};
CSteamUser.prototype.getAliases = function(callback) {
this._community.getUserAliases(this.steamID, callback);
};
CSteamUser.prototype.getInventoryContexts = function(callback) {
this._community.getUserInventoryContexts(this.steamID, callback);
};

View File

@@ -84,7 +84,8 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
"umqid": body.umqid,
"message": body.message,
"accessToken": token,
"interval": interval
"interval": interval,
"uiMode": uiMode
};
self.chatFriends = {};
@@ -188,11 +189,19 @@ SteamCommunity.prototype._chatPoll = function() {
if(err || response.statusCode != 200) {
self.emit('debug', 'Error in chat poll: ' + (err ? err.message : "HTTP error " + response.statusCode));
if (err.message == "Not Logged On") {
self._relogWebChat();
}
return;
}
if(!body || body.error != 'OK') {
self.emit('debug', 'Error in chat poll: ' + (body && body.error ? body.error : "Malformed response"));
if (body && body.error && body.error == "Not Logged On") {
self._relogWebChat();
}
return;
}
@@ -225,6 +234,13 @@ SteamCommunity.prototype._chatPoll = function() {
}, "steamcommunity");
};
SteamCommunity.prototype._relogWebChat = function() {
this.emit('debug', "Relogging web chat");
clearTimeout(this._chat.timer);
this.chatState = SteamCommunity.ChatState.Offline;
this.chatLogon(this._chat.interval, this._chat.uiMode);
};
SteamCommunity.prototype._chatUpdatePersona = function(steamID) {
this.emit('debug', 'Updating persona data for ' + steamID);
var self = this;

View File

@@ -108,15 +108,15 @@ SteamCommunity.prototype.getConfirmationOfferID = function(confID, time, key, ca
/**
* 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|int[]} confID - The ID of the confirmation in question, or an array of confirmation IDs
* @param {string|string[]} confKey - The confirmation key associated with the confirmation in question (or an array of them) (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", {
request(this, (confID instanceof Array) ? "multiajaxop" : "ajaxop", key, time, accept ? "allow" : "cancel", {
"op": accept ? "allow" : "cancel",
"cid": confID,
"ck": confKey
@@ -144,6 +144,31 @@ SteamCommunity.prototype.respondToConfirmation = function(confID, confKey, time,
});
};
SteamCommunity.prototype.acceptAllConfirmations = function(time, confKey, allowKey, callback) {
var self = this;
this.getConfirmations(time, confKey, function(err, confs) {
if (err) {
callback(err);
return;
}
if (confs.length == 0) {
callback(null, []);
return;
}
self.respondToConfirmation(confs.map(function(conf) { return conf.id; }), confs.map(function(conf) { return conf.key; }), time, allowKey, true, function(err) {
if (err) {
callback(err);
return;
}
callback(err, confs);
});
});
};
function request(community, url, key, time, tag, params, json, callback) {
params = params || {};
params.p = SteamTotp.getDeviceID(community.steamID);
@@ -153,11 +178,19 @@ function request(community, url, key, time, tag, params, json, callback) {
params.m = "android";
params.tag = tag;
community.httpRequestGet({
var req = {
"method": url == 'multiajaxop' ? 'POST' : 'GET',
"uri": "https://steamcommunity.com/mobileconf/" + url,
"qs": params,
"json": !!json
}, function(err, response, body) {
};
if (req.method == "GET") {
req.qs = params;
} else {
req.form = params;
}
community.httpRequest(req, function(err, response, body) {
if (err) {
callback(err);
return;

View File

@@ -344,6 +344,30 @@ SteamCommunity.prototype.editGroupEvent = function (gid, id, name, type, descrip
}, "steamcommunity");
};
SteamCommunity.prototype.deleteGroupEvent = function(gid, id, callback) {
if (typeof gid === 'string') {
gid = new SteamID(gid);
}
var form = {
"sessionid": this.getSessionID(),
"action": "deleteEvent",
"eventID": id
};
var self = this;
this.httpRequestPost({
"uri": "https://steamcommunity.com/gid/" + gid.toString() + "/eventEdit",
"form": form
}, function(err, response, body) {
if(!callback) {
return;
}
callback(err || null);
}, "steamcommunity");
};
SteamCommunity.prototype.setGroupPlayerOfTheWeek = function(gid, steamID, callback) {
if(typeof gid === 'string') {
gid = new SteamID(gid);

View File

@@ -11,3 +11,13 @@ exports.isSteamID = function(input) {
return keys.length == 4;
};
exports.decodeSteamTime = function(time) {
var parts = time.split('@');
if (!parts[0].match(/,/)) {
// no year, assume current year
parts[0] += ", " + (new Date()).getFullYear();
}
return new Date(parts.join('@').replace(/(am|pm)/, ' $1') + " UTC"); // add a space so JS can decode it
};

View File

@@ -50,16 +50,22 @@ SteamCommunity.prototype.httpRequest = function(uri, options, callback, source)
var httpError = options.checkHttpError !== false && self._checkHttpError(err, response, callback);
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;
self.emit('postHttpRequest', requestID, source, options, httpError || communityError || tradeError || null, response, body, {
self.emit('postHttpRequest', requestID, source, options, httpError || communityError || tradeError || jsonError || null, response, body, {
"hasCallback": hasCallback,
"httpError": httpError,
"communityError": communityError,
"tradeError": tradeError
"tradeError": tradeError,
"jsonError": jsonError
});
if(hasCallback && !(httpError || communityError || tradeError)) {
callback.apply(self, arguments);
if (hasCallback) {
if (jsonError) {
callback.call(self, jsonError, response);
} else if (!(httpError || communityError || tradeError)) {
callback.apply(self, arguments);
}
}
});
}
@@ -80,19 +86,25 @@ SteamCommunity.prototype._notifySessionExpired = function(err) {
};
SteamCommunity.prototype._checkHttpError = function(err, response, callback) {
if(err) {
if (err) {
callback(err);
return err;
}
if(response.statusCode >= 300 && response.statusCode <= 399 && response.headers.location.indexOf('/login') != -1) {
if (response.statusCode >= 300 && response.statusCode <= 399 && response.headers.location.indexOf('/login') != -1) {
err = new Error("Not Logged In");
callback(err);
this._notifySessionExpired(err);
return err;
}
if(response.statusCode >= 400) {
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);
return err;
}
if (response.statusCode >= 400) {
err = new Error("HTTP error " + response.statusCode);
err.code = response.statusCode;
callback(err);

View File

@@ -1,6 +1,7 @@
var SteamCommunity = require('../index.js');
var SteamID = require('steamid');
var CEconItem = require('../classes/CEconItem.js');
var Helpers = require('./helpers.js');
SteamCommunity.prototype.addFriend = function(userID, callback) {
if(typeof userID === 'string') {
@@ -190,6 +191,32 @@ SteamCommunity.prototype.inviteUserToGroup = function(userID, groupID, callback)
}, "steamcommunity");
};
SteamCommunity.prototype.getUserAliases = function(userID, callback) {
if (typeof userID === 'string') {
userID = new SteamID(userID);
}
this.httpRequestGet({
"uri": "https://steamcommunity.com/profiles/" + userID.getSteamID64() + "/ajaxaliases",
"json": true
}, function(err, response, body) {
if (err) {
callback(err);
return;
}
if (typeof body !== 'object') {
callback(new Error("Malformed response"));
return;
}
callback(null, body.map(function(entry) {
entry.timechanged = Helpers.decodeSteamTime(entry.timechanged);
return entry;
}));
}, "steamcommunity");
};
SteamCommunity.prototype.getUserInventoryContexts = function(userID, callback) {
if(typeof userID === 'string') {
userID = new SteamID(userID);

View File

@@ -1,6 +1,6 @@
{
"name": "steamcommunity",
"version": "3.20.0",
"version": "3.23.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",