mirror of
https://github.com/DoctorMcKay/node-steamcommunity.git
synced 2026-09-03 22:02:46 +08:00
Compare commits
124 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26effb27fe | ||
|
|
5880e922ab | ||
|
|
fe007811a5 | ||
|
|
7b882c8439 | ||
|
|
6c4cb9e62f | ||
|
|
2300081d43 | ||
|
|
0f20f918be | ||
|
|
b761b8108b | ||
|
|
46e16cc0b6 | ||
|
|
237d3786a2 | ||
|
|
1884ceb7d9 | ||
|
|
893c4df06b | ||
|
|
593ed6b9ef | ||
|
|
840e9548ed | ||
|
|
dee6b7964b | ||
|
|
2fc434d475 | ||
|
|
42ebbda00d | ||
|
|
eed791acbd | ||
|
|
54b83016af | ||
|
|
1032b1f832 | ||
|
|
fce2560abe | ||
|
|
0069bb36ef | ||
|
|
1028c4193f | ||
|
|
991b11e0f4 | ||
|
|
72c01468da | ||
|
|
eecd682033 | ||
|
|
574a3127cb | ||
|
|
55027f7b1f | ||
|
|
70ffc5559d | ||
|
|
f4be134f71 | ||
|
|
7792969cae | ||
|
|
57a3532860 | ||
|
|
facf335f0e | ||
|
|
1c3817b797 | ||
|
|
74efd50f72 | ||
|
|
87e3665b01 | ||
|
|
0b94419de4 | ||
|
|
defbd347cc | ||
|
|
7efc1f2fd0 | ||
|
|
05c2da89da | ||
|
|
b83c40419c | ||
|
|
fb0097499d | ||
|
|
c2983e3bcd | ||
|
|
80b3cc52d2 | ||
|
|
fa59b188a5 | ||
|
|
e446cc3cd8 | ||
|
|
722ca6689b | ||
|
|
1276c71e4e | ||
|
|
a51bd21153 | ||
|
|
f1bbfc4901 | ||
|
|
eb8d094bf1 | ||
|
|
b1cca95ec0 | ||
|
|
27ef78cc4b | ||
|
|
4223d88fd1 | ||
|
|
ac02f6cb49 | ||
|
|
d84601e256 | ||
|
|
4152865f5e | ||
|
|
7627e6a3a0 | ||
|
|
bbcf0eb72f | ||
|
|
d51b6582e2 | ||
|
|
bbd339b88b | ||
|
|
fcaaa38085 | ||
|
|
26f27e2698 | ||
|
|
6d8d0c5fbb | ||
|
|
08c9ab6809 | ||
|
|
c150425ee5 | ||
|
|
eae78aab93 | ||
|
|
5c2666e0f4 | ||
|
|
c64b6c7e99 | ||
|
|
318f9ab2b4 | ||
|
|
5c2894a7d4 | ||
|
|
3167034b97 | ||
|
|
3bfe8c3713 | ||
|
|
0c4e026701 | ||
|
|
c246011fe2 | ||
|
|
c290e16dc5 | ||
|
|
f8852ba6c4 | ||
|
|
52ee65d9da | ||
|
|
42e04b123a | ||
|
|
1f69d1fc04 | ||
|
|
e4b5e763eb | ||
|
|
6feb607366 | ||
|
|
cc64d9883a | ||
|
|
d4a92b4dea | ||
|
|
e2849719c1 | ||
|
|
c9541d093c | ||
|
|
339d5dc1e4 | ||
|
|
2a7a03d35e | ||
|
|
ff1c3279c8 | ||
|
|
9175a44828 | ||
|
|
deeeb633cf | ||
|
|
a50bd35a54 | ||
|
|
5bf51a2e3e | ||
|
|
448b32b9c6 | ||
|
|
01428e6007 | ||
|
|
43d1147fd7 | ||
|
|
479cc47bf5 | ||
|
|
01217a3659 | ||
|
|
0e34bceb1f | ||
|
|
c4ea8eeb41 | ||
|
|
0f83fe8c64 | ||
|
|
5624611421 | ||
|
|
49d2bb4252 | ||
|
|
b54ccff7c8 | ||
|
|
b82f7ca045 | ||
|
|
2526539266 | ||
|
|
fc75036974 | ||
|
|
ee1e819812 | ||
|
|
fceea0737d | ||
|
|
f3ac556922 | ||
|
|
2e02c14455 | ||
|
|
8f580fc231 | ||
|
|
6f596b5b16 | ||
|
|
1249e28d83 | ||
|
|
85bcaa70be | ||
|
|
2a5419513c | ||
|
|
deec5c52a4 | ||
|
|
2399a5b783 | ||
|
|
efea8c6265 | ||
|
|
2be414b20c | ||
|
|
25ebb4c5a3 | ||
|
|
ac87fd3a40 | ||
|
|
c67e2e04f1 | ||
|
|
83eeb0f190 |
15
README.md
15
README.md
@@ -9,12 +9,15 @@ This module provides an easy interface for the Steam Community website. This mod
|
|||||||
|
|
||||||
It supports Steam Guard and CAPTCHAs.
|
It supports Steam Guard and CAPTCHAs.
|
||||||
|
|
||||||
# Installation
|
**Have a question about the module or coding in general? *Do not create a GitHub issue.* GitHub issues are for feature
|
||||||
|
requests and bug reports. Instead, post in the [dedicated forum](https://dev.doctormckay.com/forum/8-node-steamcommunity/).
|
||||||
Install it from npm:
|
Such issues may be ignored!**
|
||||||
|
|
||||||
$ npm install steamcommunity
|
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
|
|
||||||
As of version 1.0.0, documentation is on the [GitHub wiki](https://github.com/DoctorMcKay/node-steamcommunity/wiki).
|
Documentation is available on the [GitHub wiki](https://github.com/DoctorMcKay/node-steamcommunity/wiki).
|
||||||
|
|
||||||
|
# Support
|
||||||
|
|
||||||
|
Report bugs on the [issue tracker](https://github.com/DoctorMcKay/node-steamcommunity/issues) or ask questions
|
||||||
|
on the [dedicated forum](https://dev.doctormckay.com/forum/8-node-steamcommunity/).
|
||||||
|
|||||||
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);
|
||||||
|
};
|
||||||
@@ -25,11 +25,18 @@ function CEconItem(item, descriptions, contextID) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.is_currency = !!this.is_currency;
|
||||||
this.tradable = !!this.tradable;
|
this.tradable = !!this.tradable;
|
||||||
this.marketable = !!this.marketable;
|
this.marketable = !!this.marketable;
|
||||||
this.commodity = !!this.commodity;
|
this.commodity = !!this.commodity;
|
||||||
this.market_tradable_restriction = (this.market_tradable_restriction ? parseInt(this.market_tradable_restriction, 10) : 0);
|
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);
|
this.market_marketable_restriction = (this.market_marketable_restriction ? parseInt(this.market_marketable_restriction, 10) : 0);
|
||||||
|
this.fraudwarnings = this.fraudwarnings || [];
|
||||||
|
this.descriptions = this.descriptions || [];
|
||||||
|
|
||||||
|
if(this.owner && JSON.stringify(this.owner) == '{}') {
|
||||||
|
this.owner = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CEconItem.prototype.getImageURL = function() {
|
CEconItem.prototype.getImageURL = function() {
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
var SteamCommunity = require('../index.js');
|
var SteamCommunity = require('../index.js');
|
||||||
var Cheerio = require('cheerio');
|
var Cheerio = require('cheerio');
|
||||||
|
|
||||||
SteamCommunity.prototype.getMarketItem = function(appid, hashName, callback) {
|
SteamCommunity.prototype.getMarketItem = function(appid, hashName, currency, callback) {
|
||||||
|
if (typeof currency == "function") {
|
||||||
|
callback = currency;
|
||||||
|
currency = 1;
|
||||||
|
}
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request("https://steamcommunity.com/market/listings/" + appid + "/" + encodeURIComponent(hashName), function(err, response, body) {
|
this.httpRequest("https://steamcommunity.com/market/listings/" + appid + "/" + encodeURIComponent(hashName), function(err, response, body) {
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,23 +18,21 @@ SteamCommunity.prototype.getMarketItem = function(appid, hashName, callback) {
|
|||||||
callback(new Error("There are no listings for this item."));
|
callback(new Error("There are no listings for this item."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var item = new CMarketItem(self, body, $);
|
var item = new CMarketItem(appid, hashName, self, body, $);
|
||||||
if(item.commodity) {
|
item.updatePrice(currency, function(err) {
|
||||||
item.updatePrice(function(err) {
|
if(err) {
|
||||||
if(err) {
|
callback(err);
|
||||||
callback(err);
|
} else {
|
||||||
} else {
|
callback(null, item);
|
||||||
callback(null, item);
|
}
|
||||||
}
|
});
|
||||||
});
|
}, "steamcommunity");
|
||||||
} else {
|
|
||||||
callback(null, item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function CMarketItem(community, body, $) {
|
function CMarketItem(appid, hashName, community, body, $) {
|
||||||
|
this._appid = appid;
|
||||||
|
this._hashName = hashName;
|
||||||
this._community = community;
|
this._community = community;
|
||||||
this._$ = $;
|
this._$ = $;
|
||||||
|
|
||||||
@@ -38,6 +41,12 @@ function CMarketItem(community, body, $) {
|
|||||||
if(match) {
|
if(match) {
|
||||||
this._country = match[1];
|
this._country = match[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._language = "english";
|
||||||
|
match = body.match(/var g_strLanguage = "([^"]+)";/);
|
||||||
|
if(match) {
|
||||||
|
this._language = match[1];
|
||||||
|
}
|
||||||
|
|
||||||
this.commodity = false;
|
this.commodity = false;
|
||||||
var match = body.match(/Market_LoadOrderSpread\(\s*(\d+)\s*\);/);
|
var match = body.match(/Market_LoadOrderSpread\(\s*(\d+)\s*\);/);
|
||||||
@@ -62,37 +71,45 @@ function CMarketItem(community, body, $) {
|
|||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.quantity = 0;
|
this.firstAsset = null;
|
||||||
this.lowestPrice = 0;
|
this.assets = null;
|
||||||
|
match = body.match(/var g_rgAssets = (.*);/);
|
||||||
if(!this.commodity) {
|
if (match) {
|
||||||
var total = $('#searchResults_total');
|
try {
|
||||||
if(total) {
|
this.assets = JSON.parse(match[1]);
|
||||||
this.quantity = parseInt(total.text().replace(/[^\d]/g, '').trim(), 10);
|
this.assets = this.assets['730']['2'];
|
||||||
}
|
this.firstAsset = this.assets[Object.keys(this.assets)[0]];
|
||||||
|
} catch (e) {
|
||||||
var lowest = $('.market_listing_price.market_listing_price_with_fee');
|
// ignore
|
||||||
if(lowest[0]) {
|
|
||||||
this.lowestPrice = parseInt($(lowest[0]).text().replace(/[^\d]/g, '').trim(), 10);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.quantity = 0;
|
||||||
|
this.lowestPrice = 0;
|
||||||
// TODO: Buying listings and placing buy orders
|
// TODO: Buying listings and placing buy orders
|
||||||
}
|
}
|
||||||
|
|
||||||
CMarketItem.prototype.updatePrice = function(callback) {
|
CMarketItem.prototype.updatePrice = function (currency, callback) {
|
||||||
|
if (this.commodity) {
|
||||||
|
this.updatePriceForCommodity(currency, callback);
|
||||||
|
} else {
|
||||||
|
this.updatePriceForNonCommodity(currency, callback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CMarketItem.prototype.updatePriceForCommodity = function(currency, callback) {
|
||||||
if(!this.commodity) {
|
if(!this.commodity) {
|
||||||
throw new Error("Cannot update price for non-commodity item");
|
throw new Error("Cannot update price for non-commodity item");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Currency option maybe?
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this._community.request({
|
this._community.httpRequest({
|
||||||
"uri": "https://steamcommunity.com/market/itemordershistogram?country=US&language=english¤cy=1&item_nameid=" + this.commodityID,
|
"uri": "https://steamcommunity.com/market/itemordershistogram?country=US&language=english¤cy=" + currency + "&item_nameid=" + this.commodityID,
|
||||||
"json": true,
|
"json": true
|
||||||
}, function(err, response, body) {
|
}, function(err, response, body) {
|
||||||
if(self._community._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,5 +139,50 @@ CMarketItem.prototype.updatePrice = function(callback) {
|
|||||||
if(callback) {
|
if(callback) {
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
|
};
|
||||||
|
|
||||||
|
CMarketItem.prototype.updatePriceForNonCommodity = function (currency, callback) {
|
||||||
|
if(this.commodity) {
|
||||||
|
throw new Error("Cannot update price for commodity item");
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
this._community.httpRequest({
|
||||||
|
"uri": "https://steamcommunity.com/market/listings/" +
|
||||||
|
this._appid + "/" +
|
||||||
|
encodeURIComponent(this._hashName) +
|
||||||
|
"/render/?query=&start=0&count=10&country=US&language=english¤cy=" + currency,
|
||||||
|
"json": true
|
||||||
|
}, function(err, response, body) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body.success != 1) {
|
||||||
|
callback && callback(new Error("Error " + body.success));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var match = body.total_count;
|
||||||
|
if (match) {
|
||||||
|
self.quantity = parseInt(match, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
var lowestPrice;
|
||||||
|
var $ = Cheerio.load(body.results_html);
|
||||||
|
match = $(".market_listing_price.market_listing_price_with_fee");
|
||||||
|
if (match) {
|
||||||
|
for (var i = 0; i < match.length; i++) {
|
||||||
|
lowestPrice = parseFloat($(match[i]).text().replace(",", ".").replace(/[^\d.]/g, ''));
|
||||||
|
if (!isNaN(lowestPrice)) {
|
||||||
|
self.lowestPrice = lowestPrice;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback && callback(null);
|
||||||
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ SteamCommunity.prototype.marketSearch = function(options, callback) {
|
|||||||
qs.count = 100;
|
qs.count = 100;
|
||||||
qs.sort_column = 'price';
|
qs.sort_column = 'price';
|
||||||
qs.sort_dir = 'asc';
|
qs.sort_dir = 'asc';
|
||||||
performSearch.call(this, this.request, qs, [], callback);
|
performSearch.call(this, this.httpRequest, qs, [], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
function performSearch(request, qs, results, callback) {
|
function performSearch(request, qs, results, callback) {
|
||||||
@@ -40,7 +40,8 @@ function performSearch(request, qs, results, callback) {
|
|||||||
},
|
},
|
||||||
"json": true
|
"json": true
|
||||||
}, function(err, response, body) {
|
}, function(err, response, body) {
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,9 +70,9 @@ function performSearch(request, qs, results, callback) {
|
|||||||
callback(null, results);
|
callback(null, results);
|
||||||
} else {
|
} else {
|
||||||
qs.start += body.pagesize;
|
qs.start += body.pagesize;
|
||||||
performSearch(request, qs, results, callback);
|
performSearch.call(self, request, qs, results, callback);
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
}
|
}
|
||||||
|
|
||||||
function CMarketSearchResult(row) {
|
function CMarketSearchResult(row) {
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
var SteamCommunity = require('../index.js');
|
var SteamCommunity = require('../index.js');
|
||||||
|
var Helpers = require('../components/helpers.js');
|
||||||
var SteamID = require('steamid');
|
var SteamID = require('steamid');
|
||||||
var xml2js = require('xml2js');
|
var xml2js = require('xml2js');
|
||||||
|
|
||||||
SteamCommunity.prototype.getSteamGroup = function(id, callback) {
|
SteamCommunity.prototype.getSteamGroup = function(id, callback) {
|
||||||
if(typeof id !== 'string' && !(typeof id === 'object' && id.__proto__ === SteamID.prototype)) {
|
if(typeof id !== 'string' && !Helpers.isSteamID(id)) {
|
||||||
throw new Error("id parameter should be a group URL string or a SteamID object");
|
throw new Error("id parameter should be a group URL string or a SteamID object");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,12 +13,9 @@ SteamCommunity.prototype.getSteamGroup = function(id, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request("https://steamcommunity.com/" + (typeof id === 'string' ? "groups/" + id : "gid/" + id.toString()) + "/memberslistxml/?xml=1", function(err, response, body) {
|
this.httpRequest("https://steamcommunity.com/" + (typeof id === 'string' ? "groups/" + id : "gid/" + id.toString()) + "/memberslistxml/?xml=1", function(err, response, body) {
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
return;
|
callback(err);
|
||||||
}
|
|
||||||
|
|
||||||
if(self._checkCommunityError(body, callback)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,7 +27,7 @@ SteamCommunity.prototype.getSteamGroup = function(id, callback) {
|
|||||||
|
|
||||||
callback(null, new CSteamGroup(self, result.memberList));
|
callback(null, new CSteamGroup(self, result.memberList));
|
||||||
});
|
});
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
function CSteamGroup(community, groupData) {
|
function CSteamGroup(community, groupData) {
|
||||||
@@ -64,7 +62,7 @@ CSteamGroup.prototype.getMembers = function(addresses, callback) {
|
|||||||
callback = addresses;
|
callback = addresses;
|
||||||
addresses = null;
|
addresses = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._community.getGroupMembers(this.steamID, callback, null, null, addresses, 0);
|
this._community.getGroupMembers(this.steamID, callback, null, null, addresses, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -76,10 +74,22 @@ CSteamGroup.prototype.leave = function(callback) {
|
|||||||
this._community.leaveGroup(this.steamID, callback);
|
this._community.leaveGroup(this.steamID, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CSteamGroup.prototype.getAllAnnouncements = function(time, callback) {
|
||||||
|
this._community.getAllGroupAnnouncements(this.steamID, time, callback);
|
||||||
|
};
|
||||||
|
|
||||||
CSteamGroup.prototype.postAnnouncement = function(headline, content, callback) {
|
CSteamGroup.prototype.postAnnouncement = function(headline, content, callback) {
|
||||||
this._community.postGroupAnnouncement(this.steamID, headline, content, callback);
|
this._community.postGroupAnnouncement(this.steamID, headline, content, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CSteamGroup.prototype.editAnnouncement = function(annoucementID, headline, content, callback) {
|
||||||
|
this._community.editGroupAnnouncement(this.steamID, annoucementID, headline, content, callback)
|
||||||
|
};
|
||||||
|
|
||||||
|
CSteamGroup.prototype.deleteAnnouncement = function(annoucementID, callback) {
|
||||||
|
this._community.deleteGroupAnnouncement(this.steamID, annoucementID, callback)
|
||||||
|
};
|
||||||
|
|
||||||
CSteamGroup.prototype.scheduleEvent = function(name, type, description, time, server, callback) {
|
CSteamGroup.prototype.scheduleEvent = function(name, type, description, time, server, callback) {
|
||||||
this._community.scheduleGroupEvent(this.steamID, name, type, description, time, server, callback);
|
this._community.scheduleGroupEvent(this.steamID, name, type, description, time, server, callback);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
var SteamCommunity = require('../index.js');
|
var SteamCommunity = require('../index.js');
|
||||||
|
var Helpers = require('../components/helpers.js');
|
||||||
var SteamID = require('steamid');
|
var SteamID = require('steamid');
|
||||||
var xml2js = require('xml2js');
|
var xml2js = require('xml2js');
|
||||||
|
|
||||||
SteamCommunity.prototype.getSteamUser = function(id, callback) {
|
SteamCommunity.prototype.getSteamUser = function(id, callback) {
|
||||||
if(typeof id !== 'string' && !(typeof id === 'object' && id.__proto__ === SteamID.prototype)) {
|
if(typeof id !== 'string' && !Helpers.isSteamID(id)) {
|
||||||
throw new Error("id parameter should be a user URL string or a SteamID object");
|
throw new Error("id parameter should be a user URL string or a SteamID object");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,12 +13,9 @@ SteamCommunity.prototype.getSteamUser = function(id, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request("http://steamcommunity.com/" + (typeof id === 'string' ? "id/" + id : "profiles/" + id.toString()) + "/?xml=1", function(err, response, body) {
|
this.httpRequest("http://steamcommunity.com/" + (typeof id === 'string' ? "id/" + id : "profiles/" + id.toString()) + "/?xml=1", function(err, response, body) {
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
return;
|
callback(err);
|
||||||
}
|
|
||||||
|
|
||||||
if(self._checkCommunityError(body, callback)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +46,7 @@ SteamCommunity.prototype.getSteamUser = function(id, callback) {
|
|||||||
|
|
||||||
callback(null, new CSteamUser(self, result.profile, customurl));
|
callback(null, new CSteamUser(self, result.profile, customurl));
|
||||||
});
|
});
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
function CSteamUser(community, userData, customurl) {
|
function CSteamUser(community, userData, customurl) {
|
||||||
@@ -65,9 +63,9 @@ function CSteamUser(community, userData, customurl) {
|
|||||||
this.avatarHash = this.avatarHash[1];
|
this.avatarHash = this.avatarHash[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.vacBanned = !!processItem('vacBanned', false);
|
this.vacBanned = processItem('vacBanned', false) == 1;
|
||||||
this.tradeBanState = processItem('tradeBanState', 'None');
|
this.tradeBanState = processItem('tradeBanState', 'None');
|
||||||
this.isLimitedAccount = !!processItem('isLimitedAccount');
|
this.isLimitedAccount = processItem('isLimitedAccount') == 1;
|
||||||
this.customURL = processItem('customURL', customurl);
|
this.customURL = processItem('customURL', customurl);
|
||||||
|
|
||||||
if(this.visibilityState == 3) {
|
if(this.visibilityState == 3) {
|
||||||
@@ -90,7 +88,7 @@ function CSteamUser(community, userData, customurl) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
if(userData.groups && userData.groups[0] && userData.groups[0].group) {
|
if(userData.groups && userData.groups[0] && userData.groups[0].group) {
|
||||||
this.groups = userData.groups[0].group.map(function(group) {
|
this.groups = userData.groups[0].group.map(function(group) {
|
||||||
if(group['$'] && group['$'].isPrimary) {
|
if(group['$'] && group['$'].isPrimary === "1") {
|
||||||
self.primaryGroup = new SteamID(group.groupID64[0]);
|
self.primaryGroup = new SteamID(group.groupID64[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,27 +40,19 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
|
|||||||
this.chatState = SteamCommunity.ChatState.LoggingOn;
|
this.chatState = SteamCommunity.ChatState.LoggingOn;
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request("https://steamcommunity.com/chat", function(err, response, body) {
|
this.getWebApiOauthToken(function(err, token) {
|
||||||
if(err || response.statusCode != 200) {
|
if(err) {
|
||||||
self.emit('debug', 'Error requesting chat WebAPI token: ' + (err ? err.message : "HTTP error " + response.statusCode));
|
self.emit('debug', "Cannot get oauth token: " + err.message);
|
||||||
self.chatState = SteamCommunity.ChatState.LogOnFailed;
|
self.chatState = SteamCommunity.ChatState.LogOnFailed;
|
||||||
setTimeout(self.chatLogon.bind(self), 5000);
|
setTimeout(self.chatLogon.bind(self), 5000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var match = body.match(/[0-9a-f]{32}/);
|
self.httpRequestPost({
|
||||||
if(!match) {
|
|
||||||
self.emit('debug', 'Couldn\'t find a WebAPI chat token in the response.');
|
|
||||||
self.chatState = SteamCommunity.ChatState.LogOnFailed;
|
|
||||||
setTimeout(self.chatLogon.bind(self), 5000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.request.post({
|
|
||||||
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Logon/v1",
|
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Logon/v1",
|
||||||
"form": {
|
"form": {
|
||||||
"ui_mode": uiMode,
|
"ui_mode": uiMode,
|
||||||
"access_token": match[0]
|
"access_token": token
|
||||||
},
|
},
|
||||||
"json": true
|
"json": true
|
||||||
}, function(err, response, body) {
|
}, function(err, response, body) {
|
||||||
@@ -81,7 +73,7 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
|
|||||||
self._chat = {
|
self._chat = {
|
||||||
"umqid": body.umqid,
|
"umqid": body.umqid,
|
||||||
"message": body.message,
|
"message": body.message,
|
||||||
"accessToken": match[0],
|
"accessToken": token,
|
||||||
"interval": interval
|
"interval": interval
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -90,7 +82,7 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
|
|||||||
self.chatState = SteamCommunity.ChatState.LoggedOn;
|
self.chatState = SteamCommunity.ChatState.LoggedOn;
|
||||||
self.emit('chatLoggedOn');
|
self.emit('chatLoggedOn');
|
||||||
self._chatPoll();
|
self._chatPoll();
|
||||||
});
|
}, "steamcommunity");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -109,8 +101,9 @@ SteamCommunity.prototype.chatMessage = function(recipient, text, type, callback)
|
|||||||
}
|
}
|
||||||
|
|
||||||
type = type || 'saytext';
|
type = type || 'saytext';
|
||||||
|
|
||||||
this.request.post({
|
var self = this;
|
||||||
|
this.httpRequestPost({
|
||||||
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Message/v1",
|
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Message/v1",
|
||||||
"form": {
|
"form": {
|
||||||
"access_token": this._chat.accessToken,
|
"access_token": this._chat.accessToken,
|
||||||
@@ -125,7 +118,8 @@ SteamCommunity.prototype.chatMessage = function(recipient, text, type, callback)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,12 +128,12 @@ SteamCommunity.prototype.chatMessage = function(recipient, text, type, callback)
|
|||||||
} else {
|
} else {
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.chatLogoff = function() {
|
SteamCommunity.prototype.chatLogoff = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Logoff/v1",
|
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Logoff/v1",
|
||||||
"form": {
|
"form": {
|
||||||
"access_token": this._chat.accessToken,
|
"access_token": this._chat.accessToken,
|
||||||
@@ -156,14 +150,14 @@ SteamCommunity.prototype.chatLogoff = function() {
|
|||||||
delete self.chatFriends;
|
delete self.chatFriends;
|
||||||
self.chatState = SteamCommunity.ChatState.Offline;
|
self.chatState = SteamCommunity.ChatState.Offline;
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype._chatPoll = function() {
|
SteamCommunity.prototype._chatPoll = function() {
|
||||||
this.emit('debug', 'Doing chat poll');
|
this.emit('debug', 'Doing chat poll');
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Poll/v1",
|
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Poll/v1",
|
||||||
"form": {
|
"form": {
|
||||||
"umqid": self._chat.umqid,
|
"umqid": self._chat.umqid,
|
||||||
@@ -218,13 +212,13 @@ SteamCommunity.prototype._chatPoll = function() {
|
|||||||
self.emit('debug', 'Unhandled chat message type: ' + message.type);
|
self.emit('debug', 'Unhandled chat message type: ' + message.type);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype._chatUpdatePersona = function(steamID) {
|
SteamCommunity.prototype._chatUpdatePersona = function(steamID) {
|
||||||
this.emit('debug', 'Updating persona data for ' + steamID);
|
this.emit('debug', 'Updating persona data for ' + steamID);
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request({
|
this.httpRequest({
|
||||||
"uri": "https://steamcommunity.com/chat/friendstate/" + steamID.accountid,
|
"uri": "https://steamcommunity.com/chat/friendstate/" + steamID.accountid,
|
||||||
"json": true
|
"json": true
|
||||||
}, function(err, response, body) {
|
}, function(err, response, body) {
|
||||||
@@ -249,5 +243,5 @@ SteamCommunity.prototype._chatUpdatePersona = function(steamID) {
|
|||||||
|
|
||||||
self.emit('chatPersonaState', steamID, persona);
|
self.emit('chatPersonaState', steamID, persona);
|
||||||
self.chatFriends[steamID.getSteamID64()] = persona;
|
self.chatFriends[steamID.getSteamID64()] = persona;
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
347
components/confirmations.js
Normal file
347
components/confirmations.js
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
var SteamCommunity = require('../index.js');
|
||||||
|
var Cheerio = require('cheerio');
|
||||||
|
var SteamTotp = require('steam-totp');
|
||||||
|
var Async = require('async');
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if (err.message == "Invalid protocol: steammobile:") {
|
||||||
|
err.message = "Not Logged In";
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(err);
|
||||||
|
self._notifySessionExpired(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = SteamTotp.getDeviceID(community.steamID);
|
||||||
|
params.a = community.steamID.getSteamID64();
|
||||||
|
params.k = key;
|
||||||
|
params.t = time;
|
||||||
|
params.m = "android";
|
||||||
|
params.tag = tag;
|
||||||
|
|
||||||
|
community.httpRequestGet({
|
||||||
|
"uri": "https://steamcommunity.com/mobileconf/" + url,
|
||||||
|
"qs": params,
|
||||||
|
"json": !!json
|
||||||
|
}, function(err, response, body) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, body);
|
||||||
|
}, "steamcommunity");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 should probably be at least 10,000 to avoid rate-limits.
|
||||||
|
* @param {Buffer|string|null} [identitySecret=null] - Your identity_secret. If passed, all confirmations will be automatically accepted and nothing will be emitted.
|
||||||
|
*/
|
||||||
|
SteamCommunity.prototype.startConfirmationChecker = function(pollInterval, identitySecret) {
|
||||||
|
this._confirmationPollInterval = pollInterval;
|
||||||
|
this._knownConfirmations = this._knownConfirmations || {};
|
||||||
|
this._confirmationKeys = this._confirmationKeys || {};
|
||||||
|
this._identitySecret = identitySecret;
|
||||||
|
|
||||||
|
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._identitySecret) {
|
||||||
|
delete this._identitySecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
if(!this._confirmationQueue) {
|
||||||
|
this._confirmationQueue = Async.queue(function(conf, callback) {
|
||||||
|
// Worker to process new confirmations
|
||||||
|
if(self._identitySecret) {
|
||||||
|
// 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() {
|
||||||
|
// If there was an error and it wasn't actually accepted, we'll pick it up again
|
||||||
|
delete self._knownConfirmations[conf.id];
|
||||||
|
setTimeout(callback, 1000); // Call the callback in 1 second, to make sure the time changes
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.emit('newConfirmation', conf);
|
||||||
|
setTimeout(callback, 1000); // Call the callback in 1 second, to make sure the time changes
|
||||||
|
}
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emit('debug', 'Checking confirmations');
|
||||||
|
|
||||||
|
this._confirmationCheckerGetKey('conf', function(err, key) {
|
||||||
|
if(err) {
|
||||||
|
resetTimer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getConfirmations(key.time, key.key, function(err, confirmations) {
|
||||||
|
if(err) {
|
||||||
|
self.emit('debug', "Can't check confirmations: " + err.message);
|
||||||
|
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) {
|
||||||
|
newOnes.forEach(function(conf) {
|
||||||
|
self._knownConfirmations[conf.id] = conf; // Add it to our list of known confirmations
|
||||||
|
|
||||||
|
if(err) {
|
||||||
|
self._confirmationQueue.push(conf);
|
||||||
|
} else {
|
||||||
|
// Get its offer ID, if we can
|
||||||
|
conf.getOfferID(key.time, key.key, function(err, offerID) {
|
||||||
|
conf.offerID = offerID ? offerID : null;
|
||||||
|
self._confirmationQueue.push(conf);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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() {
|
||||||
|
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) {
|
||||||
|
if(this._identitySecret) {
|
||||||
|
if(tag == 'details') {
|
||||||
|
// We don't care about details
|
||||||
|
callback(new Error("Disabled"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var time = Math.floor(Date.now() / 1000);
|
||||||
|
callback(null, {"time": time, "key": SteamTotp.getConfirmationKey(this._identitySecret, time, tag)});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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});
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -38,8 +38,9 @@ SteamCommunity.prototype.getGroupMembers = function(gid, callback, members, link
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request(options, function(err, response, body) {
|
this.httpRequest(options, function(err, response, body) {
|
||||||
if (self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ SteamCommunity.prototype.getGroupMembers = function(gid, callback, members, link
|
|||||||
callback(null, members);
|
callback(null, members);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.getGroupMembersEx = function(gid, addresses, callback) {
|
SteamCommunity.prototype.getGroupMembersEx = function(gid, addresses, callback) {
|
||||||
@@ -73,7 +74,7 @@ SteamCommunity.prototype.joinGroup = function(gid, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/gid/" + gid.getSteamID64(),
|
"uri": "https://steamcommunity.com/gid/" + gid.getSteamID64(),
|
||||||
"form": {
|
"form": {
|
||||||
"action": "join",
|
"action": "join",
|
||||||
@@ -84,17 +85,8 @@ SteamCommunity.prototype.joinGroup = function(gid, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(err || response.statusCode >= 400) {
|
callback(err || null);
|
||||||
callback(err || new Error("HTTP error " + response.statusCode));
|
}, "steamcommunity");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(self._checkCommunityError(body, callback)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.leaveGroup = function(gid, callback) {
|
SteamCommunity.prototype.leaveGroup = function(gid, callback) {
|
||||||
@@ -112,49 +104,129 @@ SteamCommunity.prototype.leaveGroup = function(gid, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(err || response.statusCode >= 400) {
|
callback(err || null);
|
||||||
callback(err || new Error("HTTP error " + response.statusCode));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(self._checkCommunityError(body, callback)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SteamCommunity.prototype.getAllGroupAnnouncements = function(gid, time, callback) {
|
||||||
|
if(typeof gid === 'string') {
|
||||||
|
gid = new SteamID(gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof time === 'function') {
|
||||||
|
callback = time;
|
||||||
|
time = new Date(0); // The beginnig of time...
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
this.httpRequest({
|
||||||
|
"uri": "https://steamcommunity.com/gid/" + gid.getSteamID64() + "/rss/"
|
||||||
|
}, function(err, response, body) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xml2js.parseString(body, function(err, results) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!results.rss.channel[0].item) {
|
||||||
|
return callback(null, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
var announcements = results.rss.channel[0].item.map(function(announcement) {
|
||||||
|
var splitLink = announcement.link[0].split('/');
|
||||||
|
return {
|
||||||
|
headline: announcement.title[0],
|
||||||
|
content: announcement.description[0],
|
||||||
|
date: new Date(announcement.pubDate[0]),
|
||||||
|
author: announcement.author[0],
|
||||||
|
aid: splitLink[splitLink.length - 1]
|
||||||
|
}
|
||||||
|
}).filter(function(announcement) {
|
||||||
|
return (announcement.date > time);
|
||||||
|
});
|
||||||
|
|
||||||
|
return callback(null, announcements);
|
||||||
|
});
|
||||||
|
}, "steamcommunity");
|
||||||
|
}
|
||||||
|
|
||||||
SteamCommunity.prototype.postGroupAnnouncement = function(gid, headline, content, callback) {
|
SteamCommunity.prototype.postGroupAnnouncement = function(gid, headline, content, callback) {
|
||||||
if(typeof gid === 'string') {
|
if(typeof gid === 'string') {
|
||||||
gid = new SteamID(gid);
|
gid = new SteamID(gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/gid/" + gid.getSteamID64() + "/announcements",
|
"uri": "https://steamcommunity.com/gid/" + gid.getSteamID64() + "/announcements",
|
||||||
"form": {
|
"form": {
|
||||||
"sessionID": this.getSessionID(),
|
"sessionID": this.getSessionID(),
|
||||||
"action": "post",
|
"action": "post",
|
||||||
"headline": headline,
|
"headline": headline,
|
||||||
"body": content
|
"body": content,
|
||||||
|
"languages[0][headline]": headline,
|
||||||
|
"languages[0][body]": content
|
||||||
}
|
}
|
||||||
}, function(err, response, body) {
|
}, function(err, response, body) {
|
||||||
if(!callback) {
|
if(!callback) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(err || response.statusCode >= 400) {
|
callback(err || null);
|
||||||
callback(err || new Error("HTTP error " + response.statusCode));
|
}, "steamcommunity");
|
||||||
|
};
|
||||||
|
|
||||||
|
SteamCommunity.prototype.editGroupAnnouncement = function(gid, aid, headline, content, callback) {
|
||||||
|
if(typeof gid === 'string') {
|
||||||
|
gid = new SteamID(gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var submitData = {
|
||||||
|
"uri": "https://steamcommunity.com/gid/" + gid.getSteamID64() + "/announcements",
|
||||||
|
"form": {
|
||||||
|
"sessionID": this.getSessionID(),
|
||||||
|
"gid": aid,
|
||||||
|
"action": "update",
|
||||||
|
"headline": headline,
|
||||||
|
"body": content,
|
||||||
|
"languages[0][headline]": headline,
|
||||||
|
"languages[0][body]": content,
|
||||||
|
"languages[0][updated]": 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.httpRequestPost(submitData, function(err, response, body) {
|
||||||
|
if(!callback) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self._checkCommunityError(body, callback)) {
|
callback(err || null);
|
||||||
|
}, "steamcommunity");
|
||||||
|
};
|
||||||
|
|
||||||
|
SteamCommunity.prototype.deleteGroupAnnouncement = function(gid, aid, callback) {
|
||||||
|
if(typeof gid === 'string') {
|
||||||
|
gid = new SteamID(gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var submitData = {
|
||||||
|
"uri": "https://steamcommunity.com/gid/" + gid.getSteamID64() + "/announcements/delete/" + aid + "?sessionID=" + this.getSessionID()
|
||||||
|
};
|
||||||
|
|
||||||
|
this.httpRequestGet(submitData, function(err, response, body) {
|
||||||
|
if(!callback) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null);
|
callback(err || null);
|
||||||
})
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.scheduleGroupEvent = function(gid, name, type, description, time, server, callback) {
|
SteamCommunity.prototype.scheduleGroupEvent = function(gid, name, type, description, time, server, callback) {
|
||||||
@@ -202,7 +274,7 @@ SteamCommunity.prototype.scheduleGroupEvent = function(gid, name, type, descript
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/gid/" + gid.toString() + "/eventEdit",
|
"uri": "https://steamcommunity.com/gid/" + gid.toString() + "/eventEdit",
|
||||||
"form": form
|
"form": form
|
||||||
}, function(err, response, body) {
|
}, function(err, response, body) {
|
||||||
@@ -210,17 +282,8 @@ SteamCommunity.prototype.scheduleGroupEvent = function(gid, name, type, descript
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(err || response.statusCode >= 400) {
|
callback(err || null);
|
||||||
callback(err || new Error("HTTP error " + response.statusCode));
|
}, "steamcommunity");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(self._checkCommunityError(body, callback)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.setGroupPlayerOfTheWeek = function(gid, steamID, callback) {
|
SteamCommunity.prototype.setGroupPlayerOfTheWeek = function(gid, steamID, callback) {
|
||||||
@@ -233,7 +296,7 @@ SteamCommunity.prototype.setGroupPlayerOfTheWeek = function(gid, steamID, callba
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/gid/" + gid.getSteamID64() + "/potwEdit",
|
"uri": "https://steamcommunity.com/gid/" + gid.getSteamID64() + "/potwEdit",
|
||||||
"form": {
|
"form": {
|
||||||
"xml": 1,
|
"xml": 1,
|
||||||
@@ -263,7 +326,7 @@ SteamCommunity.prototype.setGroupPlayerOfTheWeek = function(gid, steamID, callba
|
|||||||
callback(new Error(results.response.results[0]));
|
callback(new Error(results.response.results[0]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.kickGroupMember = function(gid, steamID, callback) {
|
SteamCommunity.prototype.kickGroupMember = function(gid, steamID, callback) {
|
||||||
@@ -276,7 +339,7 @@ SteamCommunity.prototype.kickGroupMember = function(gid, steamID, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/gid/" + gid.getSteamID64() + "/membersManage",
|
"uri": "https://steamcommunity.com/gid/" + gid.getSteamID64() + "/membersManage",
|
||||||
"form": {
|
"form": {
|
||||||
"sessionID": this.getSessionID(),
|
"sessionID": this.getSessionID(),
|
||||||
@@ -289,17 +352,8 @@ SteamCommunity.prototype.kickGroupMember = function(gid, steamID, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(err || response.statusCode >= 400) {
|
callback(err || null);
|
||||||
callback(err || new Error("HTTP error " + response.statusCode));
|
}, "steamcommunity");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(self._checkCommunityError(body, callback)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.getGroupHistory = function(gid, page, callback) {
|
SteamCommunity.prototype.getGroupHistory = function(gid, page, callback) {
|
||||||
@@ -313,12 +367,9 @@ SteamCommunity.prototype.getGroupHistory = function(gid, page, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request("https://steamcommunity.com/gid/" + gid.getSteamID64() + "/history?p=" + page, function(err, response, body) {
|
this.httpRequest("https://steamcommunity.com/gid/" + gid.getSteamID64() + "/history?p=" + page, function(err, response, body) {
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
return;
|
callback(err);
|
||||||
}
|
|
||||||
|
|
||||||
if(self._checkCommunityError(body, callback)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,5 +433,5 @@ SteamCommunity.prototype.getGroupHistory = function(gid, page, callback) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
callback(null, output);
|
callback(null, output);
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|||||||
13
components/helpers.js
Normal file
13
components/helpers.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
exports.isSteamID = function(input) {
|
||||||
|
var keys = Object.keys(input);
|
||||||
|
if (keys.length != 4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure it has the keys we expect
|
||||||
|
keys = keys.filter(function(item) {
|
||||||
|
return ['universe', 'type', 'instance', 'accountid'].indexOf(item) != -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
return keys.length == 4;
|
||||||
|
};
|
||||||
138
components/http.js
Normal file
138
components/http.js
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
var SteamCommunity = require('../index.js');
|
||||||
|
|
||||||
|
SteamCommunity.prototype.httpRequest = function(uri, options, callback, source) {
|
||||||
|
if (typeof uri === 'object') {
|
||||||
|
source = callback;
|
||||||
|
callback = options;
|
||||||
|
options = uri;
|
||||||
|
uri = options.url || options.uri;
|
||||||
|
} else if (typeof options === 'function') {
|
||||||
|
source = callback;
|
||||||
|
callback = options;
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
options.url = options.uri = uri;
|
||||||
|
|
||||||
|
if (this._httpRequestConvenienceMethod) {
|
||||||
|
options.method = this._httpRequestConvenienceMethod;
|
||||||
|
delete this._httpRequestConvenienceMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
var requestID = ++this._httpRequestID;
|
||||||
|
source = source || "";
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
var continued = false;
|
||||||
|
|
||||||
|
if (!this.onPreHttpRequest || !this.onPreHttpRequest(requestID, source, options, continueRequest)) {
|
||||||
|
// No pre-hook, or the pre-hook doesn't want to delay the request.
|
||||||
|
continueRequest(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function continueRequest(err) {
|
||||||
|
if (continued) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
continued = true;
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
if (callback) {
|
||||||
|
callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.request(options, function (err, response, body) {
|
||||||
|
var hasCallback = !!callback;
|
||||||
|
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
|
||||||
|
|
||||||
|
self.emit('postHttpRequest', requestID, source, options, httpError || communityError || tradeError || null, response, body, {
|
||||||
|
"hasCallback": hasCallback,
|
||||||
|
"httpError": httpError,
|
||||||
|
"communityError": communityError,
|
||||||
|
"tradeError": tradeError
|
||||||
|
});
|
||||||
|
|
||||||
|
if(hasCallback && !(httpError || communityError || tradeError)) {
|
||||||
|
callback.apply(self, arguments);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SteamCommunity.prototype.httpRequestGet = function() {
|
||||||
|
this._httpRequestConvenienceMethod = "GET";
|
||||||
|
return this.httpRequest.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
SteamCommunity.prototype.httpRequestPost = function() {
|
||||||
|
this._httpRequestConvenienceMethod = "POST";
|
||||||
|
return this.httpRequest.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
SteamCommunity.prototype._notifySessionExpired = function(err) {
|
||||||
|
this.emit('sessionExpired', err);
|
||||||
|
};
|
||||||
|
|
||||||
|
SteamCommunity.prototype._checkHttpError = function(err, response, callback) {
|
||||||
|
if(err) {
|
||||||
|
callback(err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
err = new Error("HTTP error " + response.statusCode);
|
||||||
|
err.code = response.statusCode;
|
||||||
|
callback(err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
SteamCommunity.prototype._checkCommunityError = function(html, callback) {
|
||||||
|
var err;
|
||||||
|
|
||||||
|
if(typeof html === 'string' && html.match(/<h1>Sorry!<\/h1>/)) {
|
||||||
|
var match = html.match(/<h3>(.+)<\/h3>/);
|
||||||
|
err = new Error(match ? match[1] : "Unknown error occurred");
|
||||||
|
callback(err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof html === 'string' && html.match(/g_steamID = false;/) && html.match(/<h1>Sign In<\/h1>/)) {
|
||||||
|
err = new Error("Not Logged In");
|
||||||
|
callback(err);
|
||||||
|
this._notifySessionExpired(err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
SteamCommunity.prototype._checkTradeError = function(html, callback) {
|
||||||
|
if (typeof html !== 'string') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var match = html.match(/<div id="error_msg">\s*([^<]+)\s*<\/div>/);
|
||||||
|
if (match) {
|
||||||
|
var err = new Error(match[1].trim());
|
||||||
|
callback(new Error(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
@@ -13,7 +13,7 @@ SteamCommunity.prototype.getInventoryHistory = function(options, callback) {
|
|||||||
|
|
||||||
options.page = options.page || 1;
|
options.page = options.page || 1;
|
||||||
|
|
||||||
this.request("https://steamcommunity.com/my/inventoryhistory?l=english&p=" + options.page, function(err, response, body) {
|
this.httpRequest("https://steamcommunity.com/my/inventoryhistory?l=english&p=" + options.page, function(err, response, body) {
|
||||||
if(err) {
|
if(err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
return;
|
return;
|
||||||
@@ -50,6 +50,8 @@ SteamCommunity.prototype.getInventoryHistory = function(options, callback) {
|
|||||||
for(var i = 0; i < trades.length; i++) {
|
for(var i = 0; i < trades.length; i++) {
|
||||||
item = $(trades[i]);
|
item = $(trades[i]);
|
||||||
trade = {};
|
trade = {};
|
||||||
|
|
||||||
|
trade.onHold = !!item.find('span:nth-of-type(2)').text().match(/Trade on Hold/i);
|
||||||
|
|
||||||
timeMatch = item.find('.tradehistory_timestamp').html().match(/(\d+):(\d+)(am|pm)/);
|
timeMatch = item.find('.tradehistory_timestamp').html().match(/(\d+):(\d+)(am|pm)/);
|
||||||
if(timeMatch[1] == 12 && timeMatch[3] == 'am') {
|
if(timeMatch[1] == 12 && timeMatch[3] == 'am') {
|
||||||
@@ -81,7 +83,7 @@ SteamCommunity.prototype.getInventoryHistory = function(options, callback) {
|
|||||||
|
|
||||||
items = item.find('.history_item');
|
items = item.find('.history_item');
|
||||||
for(j = 0; j < items.length; j++) {
|
for(j = 0; j < items.length; j++) {
|
||||||
match = body.match(new RegExp("HistoryPageCreateItemHover\\( '" + $(items[j]).attr('id') + "', (\\d+), '(\\d+)', '(\\d+)', '(\\d+)' \\);"));
|
match = body.match(new RegExp("HistoryPageCreateItemHover\\( '" + $(items[j]).attr('id') + "', (\\d+), '(\\d+)', '(\\d+|class_\\d+_instance_\\d+|class_\\d+)', '(\\d+)' \\);"));
|
||||||
econItem = historyInventory[match[1]][match[2]][match[3]];
|
econItem = historyInventory[match[1]][match[2]][match[3]];
|
||||||
|
|
||||||
if($(items[j]).attr('id').indexOf('received') != -1) {
|
if($(items[j]).attr('id').indexOf('received') != -1) {
|
||||||
@@ -120,7 +122,7 @@ SteamCommunity.prototype.getInventoryHistory = function(options, callback) {
|
|||||||
} else {
|
} else {
|
||||||
callback(null, output);
|
callback(null, output);
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
function resolveVanityURL(vanityURL, callback) {
|
function resolveVanityURL(vanityURL, callback) {
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ var Cheerio = require('cheerio');
|
|||||||
|
|
||||||
SteamCommunity.prototype.getMarketApps = function(callback) {
|
SteamCommunity.prototype.getMarketApps = function(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request('https://steamcommunity.com/market/', function (err, response, body) {
|
this.httpRequest('https://steamcommunity.com/market/', function (err, response, body) {
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var $ = Cheerio.load(body);
|
var $ = Cheerio.load(body);
|
||||||
if ($('.market_search_game_button_group')) {
|
if ($('.market_search_game_button_group')) {
|
||||||
apps = {};
|
apps = {};
|
||||||
@@ -21,5 +23,5 @@ SteamCommunity.prototype.getMarketApps = function(callback) {
|
|||||||
} else {
|
} else {
|
||||||
callback(new Error("Malformed response"));
|
callback(new Error("Malformed response"));
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -190,10 +190,6 @@ SteamCommunity.prototype.profileSettings = function(settings, callback) {
|
|||||||
case 'inventoryGifts':
|
case 'inventoryGifts':
|
||||||
values.inventoryGiftPrivacy = settings[i] ? 1 : 0;
|
values.inventoryGiftPrivacy = settings[i] ? 1 : 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'emailConfirmation':
|
|
||||||
values.tradeConfirmationSetting = settings[i] ? 1 : 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +220,7 @@ SteamCommunity.prototype.uploadAvatar = function(image, format, callback) {
|
|||||||
if(image instanceof Buffer) {
|
if(image instanceof Buffer) {
|
||||||
doUpload(image);
|
doUpload(image);
|
||||||
} else if(image.match(/^https?:\/\//)) {
|
} else if(image.match(/^https?:\/\//)) {
|
||||||
this.request.get({
|
this.httpRequestGet({
|
||||||
"uri": image,
|
"uri": image,
|
||||||
"encoding": null
|
"encoding": null
|
||||||
}, function(err, response, body) {
|
}, function(err, response, body) {
|
||||||
@@ -241,7 +237,7 @@ SteamCommunity.prototype.uploadAvatar = function(image, format, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
doUpload(body);
|
doUpload(body);
|
||||||
})
|
}, "steamcommunity");
|
||||||
} else {
|
} else {
|
||||||
if(!format) {
|
if(!format) {
|
||||||
format = image.match(/\.([^\.]+)$/);
|
format = image.match(/\.([^\.]+)$/);
|
||||||
@@ -304,7 +300,7 @@ SteamCommunity.prototype.uploadAvatar = function(image, format, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.request.post({
|
self.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/actions/FileUploader",
|
"uri": "https://steamcommunity.com/actions/FileUploader",
|
||||||
"formData": {
|
"formData": {
|
||||||
"MAX_FILE_SIZE": buffer.length,
|
"MAX_FILE_SIZE": buffer.length,
|
||||||
@@ -358,6 +354,6 @@ SteamCommunity.prototype.uploadAvatar = function(image, format, callback) {
|
|||||||
if(callback) {
|
if(callback) {
|
||||||
callback(null, body.images.full);
|
callback(null, body.images.full);
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
157
components/twofactor.js
Normal file
157
components/twofactor.js
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.httpRequestPost({
|
||||||
|
"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": SteamTotp.getDeviceID(self.steamID),
|
||||||
|
"sms_phone_id": "1"
|
||||||
|
},
|
||||||
|
"json": true
|
||||||
|
}, function(err, response, body) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
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");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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.httpRequestPost({
|
||||||
|
"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 (err) {
|
||||||
|
callback(err);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SteamCommunity.prototype.disableTwoFactor = function(revocationCode, callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.getWebApiOauthToken(function(err, token) {
|
||||||
|
if(err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.httpRequestPost({
|
||||||
|
"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 (err) {
|
||||||
|
callback(err);
|
||||||
|
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);
|
||||||
|
}, "steamcommunity");
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -8,7 +8,7 @@ SteamCommunity.prototype.addFriend = function(userID, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/actions/AddFriendAjax",
|
"uri": "https://steamcommunity.com/actions/AddFriendAjax",
|
||||||
"form": {
|
"form": {
|
||||||
"accept_invite": 0,
|
"accept_invite": 0,
|
||||||
@@ -21,7 +21,8 @@ SteamCommunity.prototype.addFriend = function(userID, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ SteamCommunity.prototype.addFriend = function(userID, callback) {
|
|||||||
} else {
|
} else {
|
||||||
callback(new Error("Unknown error"));
|
callback(new Error("Unknown error"));
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.acceptFriendRequest = function(userID, callback) {
|
SteamCommunity.prototype.acceptFriendRequest = function(userID, callback) {
|
||||||
@@ -39,7 +40,7 @@ SteamCommunity.prototype.acceptFriendRequest = function(userID, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/actions/AddFriendAjax",
|
"uri": "https://steamcommunity.com/actions/AddFriendAjax",
|
||||||
"form": {
|
"form": {
|
||||||
"accept_invite": 1,
|
"accept_invite": 1,
|
||||||
@@ -51,12 +52,8 @@ SteamCommunity.prototype.acceptFriendRequest = function(userID, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
callback(err || null);
|
||||||
return;
|
}, "steamcommunity");
|
||||||
}
|
|
||||||
|
|
||||||
callback(null);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.removeFriend = function(userID, callback) {
|
SteamCommunity.prototype.removeFriend = function(userID, callback) {
|
||||||
@@ -65,7 +62,7 @@ SteamCommunity.prototype.removeFriend = function(userID, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/actions/RemoveFriendAjax",
|
"uri": "https://steamcommunity.com/actions/RemoveFriendAjax",
|
||||||
"form": {
|
"form": {
|
||||||
"sessionID": this.getSessionID(),
|
"sessionID": this.getSessionID(),
|
||||||
@@ -76,12 +73,8 @@ SteamCommunity.prototype.removeFriend = function(userID, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
callback(err || null);
|
||||||
return;
|
}, "steamcommunity");
|
||||||
}
|
|
||||||
|
|
||||||
callback(null);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.blockCommunication = function(userID, callback) {
|
SteamCommunity.prototype.blockCommunication = function(userID, callback) {
|
||||||
@@ -90,7 +83,7 @@ SteamCommunity.prototype.blockCommunication = function(userID, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/actions/BlockUserAjax",
|
"uri": "https://steamcommunity.com/actions/BlockUserAjax",
|
||||||
"form": {
|
"form": {
|
||||||
"sessionID": this.getSessionID(),
|
"sessionID": this.getSessionID(),
|
||||||
@@ -101,12 +94,8 @@ SteamCommunity.prototype.blockCommunication = function(userID, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
callback(err || null);
|
||||||
return;
|
}, "steamcommunity");
|
||||||
}
|
|
||||||
|
|
||||||
callback(null);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.unblockCommunication = function(userID, callback) {
|
SteamCommunity.prototype.unblockCommunication = function(userID, callback) {
|
||||||
@@ -137,7 +126,7 @@ SteamCommunity.prototype.postUserComment = function(userID, message, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/comment/Profile/post/" + userID.toString() + "/-1",
|
"uri": "https://steamcommunity.com/comment/Profile/post/" + userID.toString() + "/-1",
|
||||||
"form": {
|
"form": {
|
||||||
"comment": message,
|
"comment": message,
|
||||||
@@ -150,18 +139,19 @@ SteamCommunity.prototype.postUserComment = function(userID, message, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(body.success) {
|
if(body.success) {
|
||||||
callback(null);
|
callback(null);
|
||||||
} else if(bpdy.error) {
|
} else if(body.error) {
|
||||||
callback(new Error(body.error));
|
callback(new Error(body.error));
|
||||||
} else {
|
} else {
|
||||||
callback(new Error("Unknown error"));
|
callback(new Error("Unknown error"));
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.inviteUserToGroup = function(userID, groupID, callback) {
|
SteamCommunity.prototype.inviteUserToGroup = function(userID, groupID, callback) {
|
||||||
@@ -170,7 +160,7 @@ SteamCommunity.prototype.inviteUserToGroup = function(userID, groupID, callback)
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post({
|
this.httpRequestPost({
|
||||||
"uri": "https://steamcommunity.com/actions/GroupInvite",
|
"uri": "https://steamcommunity.com/actions/GroupInvite",
|
||||||
"form": {
|
"form": {
|
||||||
"group": groupID.toString(),
|
"group": groupID.toString(),
|
||||||
@@ -185,7 +175,8 @@ SteamCommunity.prototype.inviteUserToGroup = function(userID, groupID, callback)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +187,7 @@ SteamCommunity.prototype.inviteUserToGroup = function(userID, groupID, callback)
|
|||||||
} else {
|
} else {
|
||||||
callback(new Error("Unknown error"));
|
callback(new Error("Unknown error"));
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.getUserInventoryContexts = function(userID, callback) {
|
SteamCommunity.prototype.getUserInventoryContexts = function(userID, callback) {
|
||||||
@@ -215,8 +206,9 @@ SteamCommunity.prototype.getUserInventoryContexts = function(userID, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request("https://steamcommunity.com/profiles/" + userID.getSteamID64() + "/inventory/", function(err, response, body) {
|
this.httpRequest("https://steamcommunity.com/profiles/" + userID.getSteamID64() + "/inventory/", function(err, response, body) {
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +227,7 @@ SteamCommunity.prototype.getUserInventoryContexts = function(userID, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
callback(null, data);
|
callback(null, data);
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.getUserInventory = function(userID, appID, contextID, tradableOnly, callback) {
|
SteamCommunity.prototype.getUserInventory = function(userID, appID, contextID, tradableOnly, callback) {
|
||||||
@@ -249,7 +241,7 @@ SteamCommunity.prototype.getUserInventory = function(userID, appID, contextID, t
|
|||||||
get([], []);
|
get([], []);
|
||||||
|
|
||||||
function get(inventory, currency, start) {
|
function get(inventory, currency, start) {
|
||||||
self.request({
|
self.httpRequest({
|
||||||
"uri": "https://steamcommunity.com" + endpoint + "/inventory/json/" + appID + "/" + contextID,
|
"uri": "https://steamcommunity.com" + endpoint + "/inventory/json/" + appID + "/" + contextID,
|
||||||
"qs": {
|
"qs": {
|
||||||
"start": start,
|
"start": start,
|
||||||
@@ -257,12 +249,18 @@ SteamCommunity.prototype.getUserInventory = function(userID, appID, contextID, t
|
|||||||
},
|
},
|
||||||
"json": true
|
"json": true
|
||||||
}, function(err, response, body) {
|
}, function(err, response, body) {
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!body || !body.success || !body.rgInventory || !body.rgDescriptions || !body.rgCurrency) {
|
if(!body || !body.success || !body.rgInventory || !body.rgDescriptions || !body.rgCurrency) {
|
||||||
callback(new Error(body.Error || "Malformed response"));
|
if(body) {
|
||||||
|
callback(new Error(body.Error || "Malformed response"));
|
||||||
|
} else {
|
||||||
|
callback(new Error("Malformed response"));
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,6 +291,6 @@ SteamCommunity.prototype.getUserInventory = function(userID, appID, contextID, t
|
|||||||
} else {
|
} else {
|
||||||
callback(null, inventory, currency);
|
callback(null, inventory, currency);
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
65
components/webapi.js
Normal file
65
components/webapi.js
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
var SteamCommunity = require('../index.js');
|
||||||
|
|
||||||
|
SteamCommunity.prototype.getWebApiKey = function(domain, callback) {
|
||||||
|
var self = this;
|
||||||
|
this.httpRequest({
|
||||||
|
"uri": "https://steamcommunity.com/dev/apikey",
|
||||||
|
"followRedirect": false
|
||||||
|
}, function(err, response, body) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
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.httpRequestPost('https://steamcommunity.com/dev/registerkey', {
|
||||||
|
"form": {
|
||||||
|
"domain": domain,
|
||||||
|
"agreeToTerms": "agreed",
|
||||||
|
"sessionid": self.getSessionID(),
|
||||||
|
"Submit": "Register"
|
||||||
|
}
|
||||||
|
}, function(err, response, body) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getWebApiKey(domain, callback);
|
||||||
|
}, "steamcommunity");
|
||||||
|
}
|
||||||
|
}, "steamcommunity");
|
||||||
|
};
|
||||||
|
|
||||||
|
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.httpRequest("https://steamcommunity.com/chat", function(err, response, body) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var match = body.match(/"([0-9a-f]{32})"/);
|
||||||
|
if (!match) {
|
||||||
|
callback(new Error("Malformed response"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, match[1]);
|
||||||
|
}, "steamcommunity");
|
||||||
|
};
|
||||||
109
examples/edit-group-announcement.js
Normal file
109
examples/edit-group-announcement.js
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
var SteamCommunity = require('../index.js');
|
||||||
|
var ReadLine = require('readline');
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var community = new SteamCommunity();
|
||||||
|
var rl = ReadLine.createInterface({
|
||||||
|
"input": process.stdin,
|
||||||
|
"output": process.stdout
|
||||||
|
});
|
||||||
|
|
||||||
|
rl.question("Username: ", function(accountName) {
|
||||||
|
rl.question("Password: ", function(password) {
|
||||||
|
doLogin(accountName, password);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function doLogin(accountName, password, authCode, twoFactorCode) {
|
||||||
|
community.login({
|
||||||
|
"accountName": accountName,
|
||||||
|
"password": password,
|
||||||
|
"authCode": authCode,
|
||||||
|
"twoFactorCode": twoFactorCode
|
||||||
|
}, function(err, sessionID, cookies, steamguard) {
|
||||||
|
if(err) {
|
||||||
|
if(err.message == 'SteamGuardMobile') {
|
||||||
|
rl.question("Steam Authenticator Code: ", function(code) {
|
||||||
|
doLogin(accountName, password, null, code);
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(err.message == 'SteamGuard') {
|
||||||
|
console.log("An email has been sent to your address at " + err.emaildomain);
|
||||||
|
rl.question("Steam Guard Code: ", function(code) {
|
||||||
|
doLogin(accountName, password, code);
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(err);
|
||||||
|
process.exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Logged on!");
|
||||||
|
|
||||||
|
rl.question("Group ID: ", function(gid) {
|
||||||
|
community.getSteamGroup(gid, function(err, group) {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
group.getAllAnnouncements(function(err, announcements) {
|
||||||
|
|
||||||
|
if(announcements.length === 0) {
|
||||||
|
return console.log("This group has no announcements");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = announcements.length - 1; i >= 0; i--) {
|
||||||
|
console.log("[%s] %s %s: %s", announcements[i].date, announcements[i].aid, announcements[i].author, announcements[i].content);
|
||||||
|
};
|
||||||
|
|
||||||
|
rl.question("Would you like to delete delete or edit an annoucement? (Type edit/delete): ", function(choice) {
|
||||||
|
rl.question("Annoucement ID: ", function(aid) {
|
||||||
|
if(choice === 'edit') {
|
||||||
|
rl.question("New title: ", function(header) {
|
||||||
|
rl.question("New body: ", function(content) {
|
||||||
|
// EW THE PYRAMID!
|
||||||
|
// Try replace this with delete!
|
||||||
|
editAnnouncement(group, aid, header, content);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
deleteAnnouncement(group, aid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function editAnnouncement(group, aid, header, content) {
|
||||||
|
// Actual community method.
|
||||||
|
group.editAnnouncement(aid, header, content, function(error) {
|
||||||
|
if(!error) {
|
||||||
|
console.log("Annoucement edited!");
|
||||||
|
} else {
|
||||||
|
console.log("Unable to edit annoucement! %j", error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteAnnouncement(group, aid) {
|
||||||
|
// group.deleteAnnouncement(aid);
|
||||||
|
// Or
|
||||||
|
group.deleteAnnouncement(aid, function(err) {
|
||||||
|
if(!err) {
|
||||||
|
console.log("Deleted");
|
||||||
|
} else {
|
||||||
|
console.log("Error deleting announcement.");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
97
examples/enable_twofactor.js
Normal file
97
examples/enable_twofactor.js
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
var SteamCommunity = require('../index.js');
|
||||||
|
var ReadLine = require('readline');
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var community = new SteamCommunity();
|
||||||
|
var rl = ReadLine.createInterface({
|
||||||
|
"input": process.stdin,
|
||||||
|
"output": process.stdout
|
||||||
|
});
|
||||||
|
|
||||||
|
rl.question("Username: ", function(accountName) {
|
||||||
|
rl.question("Password: ", function(password) {
|
||||||
|
doLogin(accountName, password);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function doLogin(accountName, password, authCode) {
|
||||||
|
community.login({
|
||||||
|
"accountName": accountName,
|
||||||
|
"password": password,
|
||||||
|
"authCode": authCode
|
||||||
|
}, function(err, sessionID, cookies, steamguard) {
|
||||||
|
if(err) {
|
||||||
|
if(err.message == 'SteamGuardMobile') {
|
||||||
|
console.log("This account already has two-factor authentication enabled.");
|
||||||
|
process.exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(err.message == 'SteamGuard') {
|
||||||
|
console.log("An email has been sent to your address at " + err.emaildomain);
|
||||||
|
rl.question("Steam Guard Code: ", function(code) {
|
||||||
|
doLogin(accountName, password, code);
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(err);
|
||||||
|
process.exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Logged on!");
|
||||||
|
community.enableTwoFactor(function(err, response) {
|
||||||
|
if(err) {
|
||||||
|
if(err.eresult == 2) {
|
||||||
|
console.log("Error: Failed to enable two-factor authentication. Do you have a phone number attached to your account?");
|
||||||
|
process.exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(err.eresult == 84) {
|
||||||
|
console.log("Error: RateLimitExceeded. Try again later.");
|
||||||
|
process.exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(err);
|
||||||
|
process.exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(response.status != 1) {
|
||||||
|
console.log("Error: Status " + response.status);
|
||||||
|
process.exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Writing secrets to twofactor_" + community.steamID.getSteamID64() + ".json");
|
||||||
|
console.log("Revocation code: " + response.revocation_code);
|
||||||
|
fs.writeFile("twofactor_" + community.steamID.getSteamID64() + ".json", JSON.stringify(response, null, "\t"));
|
||||||
|
|
||||||
|
promptActivationCode(response);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function promptActivationCode(response) {
|
||||||
|
rl.question("SMS Code: ", function(smsCode) {
|
||||||
|
community.finalizeTwoFactor(response.shared_secret, smsCode, function(err) {
|
||||||
|
if(err) {
|
||||||
|
if(err.message == "Invalid activation code") {
|
||||||
|
console.log(err);
|
||||||
|
promptActivationCode(response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(err);
|
||||||
|
} else {
|
||||||
|
console.log("Two-factor authentication enabled!");
|
||||||
|
}
|
||||||
|
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
315
index.js
315
index.js
@@ -3,24 +3,45 @@ var RSA = require('node-bignumber').Key;
|
|||||||
var hex2b64 = require('node-bignumber').hex2b64;
|
var hex2b64 = require('node-bignumber').hex2b64;
|
||||||
var SteamID = require('steamid');
|
var SteamID = require('steamid');
|
||||||
|
|
||||||
|
const USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36";
|
||||||
|
|
||||||
require('util').inherits(SteamCommunity, require('events').EventEmitter);
|
require('util').inherits(SteamCommunity, require('events').EventEmitter);
|
||||||
|
|
||||||
module.exports = SteamCommunity;
|
module.exports = SteamCommunity;
|
||||||
|
|
||||||
SteamCommunity.SteamID = SteamID;
|
SteamCommunity.SteamID = SteamID;
|
||||||
|
|
||||||
function SteamCommunity(localAddress) {
|
function SteamCommunity(options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
this._jar = Request.jar();
|
this._jar = Request.jar();
|
||||||
this._captchaGid = -1;
|
this._captchaGid = -1;
|
||||||
|
this._httpRequestID = 0;
|
||||||
this.chatState = SteamCommunity.ChatState.Offline;
|
this.chatState = SteamCommunity.ChatState.Offline;
|
||||||
|
|
||||||
var defaults = {"jar": this._jar, "timeout": 50000};
|
var defaults = {
|
||||||
if(localAddress) {
|
"jar": this._jar,
|
||||||
defaults.localAddress = localAddress;
|
"timeout": options.timeout || 50000,
|
||||||
|
"gzip": true,
|
||||||
|
"headers": {
|
||||||
|
"User-Agent": options.userAgent || USER_AGENT
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof options == "string") {
|
||||||
|
options = {
|
||||||
|
localAddress: options
|
||||||
|
};
|
||||||
|
}
|
||||||
|
this._options = options;
|
||||||
|
|
||||||
|
if (options.localAddress) {
|
||||||
|
defaults.localAddress = options.localAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.request = Request.defaults(defaults);
|
this.request = options.request || Request.defaults();
|
||||||
|
this.request = this.request.defaults(defaults);
|
||||||
|
|
||||||
// English
|
// English
|
||||||
this._jar.setCookie(Request.cookie('Steam_Language=english'), 'https://steamcommunity.com');
|
this._jar.setCookie(Request.cookie('Steam_Language=english'), 'https://steamcommunity.com');
|
||||||
|
|
||||||
@@ -35,57 +56,79 @@ SteamCommunity.prototype.login = function(details, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request.post("https://steamcommunity.com/login/getrsakey/", {"form": {"username": details.accountName}}, function(err, response, body) {
|
|
||||||
if(err) {
|
// 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._jar.setCookie(Request.cookie("mobileClientVersion=0 (2.1.3)"), "https://steamcommunity.com");
|
||||||
|
this._jar.setCookie(Request.cookie("mobileClient=android"), "https://steamcommunity.com");
|
||||||
|
|
||||||
|
this.httpRequestPost("https://steamcommunity.com/login/getrsakey/", {
|
||||||
|
"form": {"username": details.accountName},
|
||||||
|
"headers": mobileHeaders,
|
||||||
|
"json": true
|
||||||
|
}, function(err, response, body) {
|
||||||
|
// Remove the mobile cookies
|
||||||
|
if (err) {
|
||||||
|
deleteMobileCookies();
|
||||||
callback(err);
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var json;
|
if(!body.publickey_mod || !body.publickey_exp) {
|
||||||
try {
|
deleteMobileCookies();
|
||||||
json = JSON.parse(body);
|
callback(new Error("Invalid RSA key received"));
|
||||||
} catch(e) {
|
|
||||||
callback(e);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = new RSA();
|
var key = new RSA();
|
||||||
key.setPublic(json.publickey_mod, json.publickey_exp);
|
key.setPublic(body.publickey_mod, body.publickey_exp);
|
||||||
|
|
||||||
var form = {
|
self.httpRequestPost({
|
||||||
"captcha_text": details.captcha || "",
|
|
||||||
"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
|
|
||||||
};
|
|
||||||
|
|
||||||
self.request.post({
|
|
||||||
"uri": "https://steamcommunity.com/login/dologin/",
|
"uri": "https://steamcommunity.com/login/dologin/",
|
||||||
"json": true,
|
"json": true,
|
||||||
"form": form
|
"form": {
|
||||||
|
"captcha_text": details.captcha || "",
|
||||||
|
"captchagid": self._captchaGid,
|
||||||
|
"emailauth": details.authCode || "",
|
||||||
|
"emailsteamid": "",
|
||||||
|
"password": hex2b64(key.encrypt(details.password)),
|
||||||
|
"remember_login": "true",
|
||||||
|
"rsatimestamp": body.timestamp,
|
||||||
|
"twofactorcode": details.twoFactorCode || "",
|
||||||
|
"username": details.accountName,
|
||||||
|
"oauth_client_id": "DE45CD61",
|
||||||
|
"oauth_scope": "read_profile write_profile read_client write_client",
|
||||||
|
"loginfriendlyname": "#login_emailauth_friendlyname_mobile",
|
||||||
|
"donotcache": Date.now()
|
||||||
|
},
|
||||||
|
"headers": mobileHeaders
|
||||||
}, function(err, response, body) {
|
}, function(err, response, body) {
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
deleteMobileCookies();
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var error;
|
||||||
if(!body.success && body.emailauth_needed) {
|
if(!body.success && body.emailauth_needed) {
|
||||||
// Steam Guard (email)
|
// Steam Guard (email)
|
||||||
var error = new Error("SteamGuard");
|
error = new Error("SteamGuard");
|
||||||
error.emaildomain = body.emaildomain;
|
error.emaildomain = body.emaildomain;
|
||||||
|
|
||||||
callback(error);
|
callback(error);
|
||||||
} else if(!body.success && body.requires_twofactor) {
|
} else if(!body.success && body.requires_twofactor) {
|
||||||
// Steam Guard (app)
|
// Steam Guard (app)
|
||||||
callback(new Error("SteamGuardMobile"));
|
callback(new Error("SteamGuardMobile"));
|
||||||
} else if(!body.success && body.captcha_needed) {
|
} else if(!body.success && body.captcha_needed && body.message.match(/Please verify your humanity/)) {
|
||||||
var error = new Error("CAPTCHA");
|
error = new Error("CAPTCHA");
|
||||||
error.captchaurl = "https://steamcommunity.com/public/captcha.php?gid=" + body.captcha_gid;
|
error.captchaurl = "https://steamcommunity.com/login/rendercaptcha/?gid=" + body.captcha_gid;
|
||||||
|
|
||||||
self._captchaGid = body.captcha_gid;
|
self._captchaGid = body.captcha_gid;
|
||||||
|
|
||||||
@@ -94,9 +137,12 @@ SteamCommunity.prototype.login = function(details, callback) {
|
|||||||
callback(new Error(body.message || "Unknown error"));
|
callback(new Error(body.message || "Unknown error"));
|
||||||
} else {
|
} else {
|
||||||
var sessionID = generateSessionID();
|
var sessionID = generateSessionID();
|
||||||
|
var oAuth = JSON.parse( body.oauth );
|
||||||
self._jar.setCookie(Request.cookie('sessionid=' + sessionID), 'http://steamcommunity.com');
|
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) {
|
var cookies = self._jar.getCookieString("https://steamcommunity.com").split(';').map(function(cookie) {
|
||||||
return cookie.trim();
|
return cookie.trim();
|
||||||
});
|
});
|
||||||
@@ -111,10 +157,54 @@ SteamCommunity.prototype.login = function(details, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null, sessionID, cookies, steamguard);
|
callback(null, sessionID, cookies, steamguard, oAuth.oauth_token);
|
||||||
}
|
}
|
||||||
});
|
}, "steamcommunity");
|
||||||
});
|
}, "steamcommunity");
|
||||||
|
|
||||||
|
function deleteMobileCookies() {
|
||||||
|
var cookie = Request.cookie('mobileClientVersion=');
|
||||||
|
cookie.expires = new Date(0);
|
||||||
|
self._jar.setCookie(cookie, "https://steamcommunity.com");
|
||||||
|
|
||||||
|
cookie = Request.cookie('mobileClient=');
|
||||||
|
cookie.expires = new Date(0);
|
||||||
|
self._jar.setCookie(cookie, "https://steamcommunity.com");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SteamCommunity.prototype.oAuthLogin = function(steamguard, token, callback) {
|
||||||
|
steamguard = steamguard.split('||');
|
||||||
|
var steamID = new SteamID(steamguard[0]);
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
this.httpRequestPost({
|
||||||
|
"uri": "https://api.steampowered.com/IMobileAuthService/GetWGToken/v1/",
|
||||||
|
"form": {
|
||||||
|
"access_token": token
|
||||||
|
},
|
||||||
|
"json": true
|
||||||
|
}, function(err, response, body) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!body.response || !body.response.token || !body.response.token_secure) {
|
||||||
|
callback(new Error("Malformed response"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cookies = [
|
||||||
|
'steamLogin=' + encodeURIComponent(steamID.getSteamID64() + '||' + body.response.token),
|
||||||
|
'steamLoginSecure=' + encodeURIComponent(steamID.getSteamID64() + '||' + body.response.token_secure),
|
||||||
|
'steamMachineAuth' + steamID.getSteamID64() + '=' + steamguard[1],
|
||||||
|
'sessionid=' + self.getSessionID()
|
||||||
|
];
|
||||||
|
|
||||||
|
self.setCookies(cookies);
|
||||||
|
callback(null, self.getSessionID(), cookies);
|
||||||
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.setCookies = function(cookies) {
|
SteamCommunity.prototype.setCookies = function(cookies) {
|
||||||
@@ -144,49 +234,13 @@ SteamCommunity.prototype.getSessionID = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function generateSessionID() {
|
function generateSessionID() {
|
||||||
return Math.floor(Math.random() * 1000000000);
|
return require('crypto').randomBytes(12).toString('hex');
|
||||||
};
|
}
|
||||||
|
|
||||||
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) {
|
SteamCommunity.prototype.parentalUnlock = function(pin, callback) {
|
||||||
this.request.post("https://steamcommunity.com/parental/ajaxunlock", {
|
var self = this;
|
||||||
|
|
||||||
|
this.httpRequestPost("https://steamcommunity.com/parental/ajaxunlock", {
|
||||||
"json": true,
|
"json": true,
|
||||||
"form": {
|
"form": {
|
||||||
"pin": pin
|
"pin": pin
|
||||||
@@ -196,25 +250,30 @@ SteamCommunity.prototype.parentalUnlock = function(pin, callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!body || typeof body.success !== 'boolean') {
|
if(!body || typeof body.success !== 'boolean') {
|
||||||
return callback("Invalid response");
|
callback("Invalid response");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!body.success) {
|
if(!body.success) {
|
||||||
return callback("Incorrect PIN");
|
callback("Incorrect PIN");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}.bind(this));
|
}.bind(this), "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.getNotifications = function(callback) {
|
SteamCommunity.prototype.getNotifications = function(callback) {
|
||||||
this.request.get("https://steamcommunity.com/actions/RefreshNotificationArea", function(err, response, body) {
|
var self = this;
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
this.httpRequestGet("https://steamcommunity.com/actions/RefreshNotificationArea", function(err, response, body) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,25 +303,26 @@ SteamCommunity.prototype.getNotifications = function(callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
callback(null, notifications);
|
callback(null, notifications);
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.resetItemNotifications = function(callback) {
|
SteamCommunity.prototype.resetItemNotifications = function(callback) {
|
||||||
this.request.get("https://steamcommunity.com/my/inventory", function(err, response, body) {
|
var self = this;
|
||||||
|
this.httpRequestGet("https://steamcommunity.com/my/inventory", function(err, response, body) {
|
||||||
if(!callback) {
|
if(!callback) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self._checkHttpError(err, response, callback)) {
|
callback(err || null);
|
||||||
return;
|
}, "steamcommunity");
|
||||||
}
|
|
||||||
|
|
||||||
callback(null);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype.loggedIn = function(callback) {
|
SteamCommunity.prototype.loggedIn = function(callback) {
|
||||||
this.request("https://steamcommunity.com/my", {"followRedirect": false}, function(err, response, body) {
|
this.httpRequestGet({
|
||||||
|
"uri": "https://steamcommunity.com/my",
|
||||||
|
"followRedirect": false,
|
||||||
|
"checkHttpError": false
|
||||||
|
}, function(err, response, body) {
|
||||||
if(err || (response.statusCode != 302 && response.statusCode != 403)) {
|
if(err || (response.statusCode != 302 && response.statusCode != 403)) {
|
||||||
callback(err || new Error("HTTP error " + response.statusCode));
|
callback(err || new Error("HTTP error " + response.statusCode));
|
||||||
return;
|
return;
|
||||||
@@ -274,22 +334,12 @@ SteamCommunity.prototype.loggedIn = function(callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
callback(null, !!response.headers.location.match(/steamcommunity\.com(\/(id|profiles)\/[^\/]+)\/?/), false);
|
callback(null, !!response.headers.location.match(/steamcommunity\.com(\/(id|profiles)\/[^\/]+)\/?/), false);
|
||||||
});
|
}, "steamcommunity");
|
||||||
};
|
|
||||||
|
|
||||||
SteamCommunity.prototype._checkCommunityError = function(html, callback) {
|
|
||||||
if(html.match(/<h1>Sorry!<\/h1>/)) {
|
|
||||||
var match = html.match(/<h3>(.+)<\/h3>/);
|
|
||||||
callback(new Error(match ? match[1] : "Unknown error occurred"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype._myProfile = function(endpoint, form, callback) {
|
SteamCommunity.prototype._myProfile = function(endpoint, form, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.request("https://steamcommunity.com/my", {"followRedirect": false}, function(err, response, body) {
|
this.httpRequest("https://steamcommunity.com/my", {"followRedirect": false}, function(err, response, body) {
|
||||||
if(err || response.statusCode != 302) {
|
if(err || response.statusCode != 302) {
|
||||||
callback(err || "HTTP error " + response.statusCode);
|
callback(err || "HTTP error " + response.statusCode);
|
||||||
return;
|
return;
|
||||||
@@ -297,42 +347,41 @@ SteamCommunity.prototype._myProfile = function(endpoint, form, callback) {
|
|||||||
|
|
||||||
var match = response.headers.location.match(/steamcommunity\.com(\/(id|profiles)\/[^\/]+)\/?/);
|
var match = response.headers.location.match(/steamcommunity\.com(\/(id|profiles)\/[^\/]+)\/?/);
|
||||||
if(!match) {
|
if(!match) {
|
||||||
callback("Can't get profile URL");
|
callback(new Error("Can't get profile URL"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(form ? self.request.post : self.request)("https://steamcommunity.com" + match[1] + "/" + endpoint, form ? {"form": form} : {}, callback);
|
var options = {
|
||||||
});
|
"uri": "https://steamcommunity.com" + match[1] + "/" + endpoint,
|
||||||
|
"method": "GET"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (form) {
|
||||||
|
options.method = "POST";
|
||||||
|
options.form = form;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.httpRequest(options, callback, "steamcommunity");
|
||||||
|
}, "steamcommunity");
|
||||||
};
|
};
|
||||||
|
|
||||||
SteamCommunity.prototype._checkHttpError = function(err, response, callback) {
|
|
||||||
if(err) {
|
|
||||||
callback(err);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
require('./components/http.js');
|
||||||
require('./components/chat.js');
|
require('./components/chat.js');
|
||||||
require('./components/profile.js');
|
require('./components/profile.js');
|
||||||
require('./components/market.js');
|
require('./components/market.js');
|
||||||
require('./components/groups.js');
|
require('./components/groups.js');
|
||||||
require('./components/users.js');
|
require('./components/users.js');
|
||||||
require('./components/inventoryhistory.js');
|
require('./components/inventoryhistory.js');
|
||||||
|
require('./components/webapi.js');
|
||||||
|
require('./components/twofactor.js');
|
||||||
|
require('./components/confirmations.js');
|
||||||
require('./classes/CMarketItem.js');
|
require('./classes/CMarketItem.js');
|
||||||
require('./classes/CMarketSearchResult.js');
|
require('./classes/CMarketSearchResult.js');
|
||||||
require('./classes/CSteamGroup.js');
|
require('./classes/CSteamGroup.js');
|
||||||
require('./classes/CSteamUser.js');
|
require('./classes/CSteamUser.js');
|
||||||
|
|
||||||
|
/**
|
||||||
|
@callback SteamCommunity~genericErrorCallback
|
||||||
|
@param {Error|null} err - An Error object on failure, or null on success
|
||||||
|
*/
|
||||||
20
package.json
20
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "steamcommunity",
|
"name": "steamcommunity",
|
||||||
"version": "3.9.8",
|
"version": "3.19.2",
|
||||||
"description": "Provides an interface for logging into and interacting with the Steam Community website",
|
"description": "Provides an interface for logging into and interacting with the Steam Community website",
|
||||||
"keywords": ["steam", "steam community"],
|
"keywords": ["steam", "steam community"],
|
||||||
"homepage": "https://github.com/DoctorMcKay/node-steamcommunity",
|
"homepage": "https://github.com/DoctorMcKay/node-steamcommunity",
|
||||||
@@ -13,11 +13,15 @@
|
|||||||
"url": "https://github.com/DoctorMcKay/node-steamcommunity.git"
|
"url": "https://github.com/DoctorMcKay/node-steamcommunity.git"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"request": "^2.61.0",
|
"request": "^2.61.0",
|
||||||
"node-bignumber": "^1.2.1",
|
"node-bignumber": "^1.2.1",
|
||||||
"steamid": "^0.3.1",
|
"steamid": "^0.3.1",
|
||||||
"xml2js": "^0.4.11",
|
"xml2js": "^0.4.11",
|
||||||
"cheerio": "^0.19.0",
|
"cheerio": "^0.20.0",
|
||||||
"async": "^1.4.2"
|
"async": "^1.4.2",
|
||||||
|
"steam-totp": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user