mirror of
https://github.com/DoctorMcKay/node-steamcommunity.git
synced 2026-08-19 13:13:28 +08:00
Compare commits
86 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bb2cb6137 | ||
|
|
c9538137d5 | ||
|
|
df05fd04c4 | ||
|
|
dee52bf7e2 | ||
|
|
6d455e8797 | ||
|
|
a0b776ca8b | ||
|
|
3f0db21e02 | ||
|
|
6798b73a17 | ||
|
|
b98451a4b6 | ||
|
|
af2ba3f56b | ||
|
|
9c2662ae16 | ||
|
|
9ee49d4f15 | ||
|
|
911ae86379 | ||
|
|
a12e8cb67c | ||
|
|
edd95cc93f | ||
|
|
4f1f265c4d | ||
|
|
80c0c3ebbc | ||
|
|
a1ef4b5646 | ||
|
|
06f7f10dfe | ||
|
|
484c049940 | ||
|
|
36038daa1b | ||
|
|
12cffdd62c | ||
|
|
eaacef66bb | ||
|
|
0ef652cbac | ||
|
|
608377277c | ||
|
|
bcaa740b54 | ||
|
|
2674287b43 | ||
|
|
8b6bed5527 | ||
|
|
6def665b64 | ||
|
|
4f618c0a27 | ||
|
|
19fe951d96 | ||
|
|
a348112ccb | ||
|
|
dff2727f85 | ||
|
|
1fd12dd4d0 | ||
|
|
31093da1a8 | ||
|
|
1e609524e8 | ||
|
|
2a758fc180 | ||
|
|
eb2081c325 | ||
|
|
c60d4942e0 | ||
|
|
1aa42b89f7 | ||
|
|
e01d05c140 | ||
|
|
8ec0ef84c2 | ||
|
|
0e5929df24 | ||
|
|
74bf2dcfca | ||
|
|
e8634e17ca | ||
|
|
2a2947344f | ||
|
|
e789d07833 | ||
|
|
88059596b3 | ||
|
|
399cc5ee84 | ||
|
|
a24bb9d4ad | ||
|
|
81eb26b30d | ||
|
|
0c95e75e39 | ||
|
|
2eaa5b057d | ||
|
|
d5592246cf | ||
|
|
22ab86434a | ||
|
|
d367ceb2a6 | ||
|
|
5ab5a6d401 | ||
|
|
a88a39c62c | ||
|
|
5f4f4a03a4 | ||
|
|
079db4b7bf | ||
|
|
22ba30f5da | ||
|
|
8ca763d9b9 | ||
|
|
eb88ace3d7 | ||
|
|
4138d1c14a | ||
|
|
4c0cd4dc8b | ||
|
|
8bad7dd09f | ||
|
|
3402acb33a | ||
|
|
00426a6aea | ||
|
|
116c57e6ff | ||
|
|
193d77c3d1 | ||
|
|
6014ce1567 | ||
|
|
8e8ce2aa89 | ||
|
|
0cb5eef1f8 | ||
|
|
7f2a287c56 | ||
|
|
7643d2efad | ||
|
|
d257108500 | ||
|
|
b0b8dbbabf | ||
|
|
b1e31b32fe | ||
|
|
0f16f11668 | ||
|
|
e6789b1021 | ||
|
|
218d0dc7da | ||
|
|
5ca5bc30ac | ||
|
|
7d1c641967 | ||
|
|
90593b2dc0 | ||
|
|
3d3c899f9d | ||
|
|
037ac1a9d7 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
node_modules/*
|
||||
node_modules/*
|
||||
test.js
|
||||
|
||||
55
README.md
55
README.md
@@ -1,6 +1,6 @@
|
||||
# Steam Community for Node.js
|
||||
|
||||
This lightweight module provides an easy interface to login to the Steam Community website. You can also login to the Steam Community website via [node-steam](https://github.com/seishun/node-steam)'s `webLogOn` method, but this module may be useful if you don't want to run an entire Steam instance.
|
||||
This lightweight module provides an easy interface for the Steam Community website. This module can be used to simply login to steamcommunity.com for use with other libraries, or to interact with steamcommunity.com.
|
||||
|
||||
It supports Steam Guard but doesn't support CAPTCHAs, so make sure you don't provide Steam with an incorrect password.
|
||||
|
||||
@@ -10,55 +10,6 @@ Install it from npm:
|
||||
|
||||
$ npm install steamcommunity
|
||||
|
||||
# Usage
|
||||
# Documentation
|
||||
|
||||
First, instantiate the `SteamCommunity` object:
|
||||
|
||||
```js
|
||||
var SteamCommunity = require('steamcommunity');
|
||||
var community = new SteamCommunity("username", "password");
|
||||
```
|
||||
|
||||
Then, simply call the `login` method:
|
||||
|
||||
```js
|
||||
community.login(function(err, sessionID, cookies, steamguard) {
|
||||
// Do something with the sessionID and cookies.
|
||||
// The steamguard parameter is only meaningful if you've entered a Steam Guard auth code, as shown below.
|
||||
});
|
||||
```
|
||||
|
||||
# Steam Guard
|
||||
|
||||
In order to authenticate with a Steam Guard authorization, you need to provide your 64-bit Steam ID and machineAuth value to the constructor:
|
||||
|
||||
```js
|
||||
var SteamCommunity = require('steamcommunity');
|
||||
var community = new SteamCommunity("username", "password", "steamid64", "machineAuth");
|
||||
```
|
||||
|
||||
If you don't have a prior authorization, you can get one by logging in as normal (without the steamID and machineAuth parameters). The callback to the `login` method will get `SteamGuard` as `err`. This means that an email has been sent to the email address tied to your account. Once you get the code, just call `login` again with the code as the first parameter:
|
||||
|
||||
```js
|
||||
community.login('ABCDE', function(err, sessionID, cookies, steamguard) {
|
||||
// steamguard is now an object with two properties: steamID and machineAuth. You'll want to save these and provide them to subsequent constructors.
|
||||
// If you call login again on this instance of SteamCommunity, the Steam Guard machineAuth will be sent automatically so you don't need to reconstruct a new instance.
|
||||
});
|
||||
```
|
||||
|
||||
# Methods
|
||||
|
||||
## Constructor: SteamCommunity(username, password[, steamID, machineAuth])
|
||||
|
||||
Instantiate a new instance of `SteamCommunity`. `steamID` and `machineAuth` are optional, but if you have them and your account is protectd by Steam Guard, you should provide them. Otherwise, you'll get a `SteamGuard` error when you try to login.
|
||||
|
||||
## login([code, ]callback)
|
||||
|
||||
Attempts to login to Steam Community using the credentials supplied in the constructor. If you have previously received a `SteamGuard` error and you have an email auth code, supply it here as the first parameter.
|
||||
|
||||
The `callback` has 4 parameters:
|
||||
|
||||
- `err` - An error that occurred, or `null` on success. The value will be `SteamGuard` if you need to supply an email auth code.
|
||||
- `sessionID` - This session's sessionID. Whatever module you're using with this will know what to do with it.
|
||||
- `cookies` - An array of session cookies. The format is the same as that returned by [node-steam](https://github.com/seishun/node-steam)'s `webLogOn` method, so anything designed to work with node-steam will also work with this.
|
||||
- `steamguard` - If you supplied an email auth code, this will contain your `steamID` and `machineAuth` code, which you should save and provide for subsequent logins.
|
||||
As of version 1.0.0, documentation is on the [GitHub wiki](https://github.com/DoctorMcKay/node-steamcommunity/wiki).
|
||||
126
classes/CMarketItem.js
Normal file
126
classes/CMarketItem.js
Normal file
@@ -0,0 +1,126 @@
|
||||
var SteamCommunity = require('../index.js');
|
||||
var Cheerio = require('cheerio');
|
||||
|
||||
SteamCommunity.prototype.getMarketItem = function(appid, hashName, callback) {
|
||||
var self = this;
|
||||
this.request("https://steamcommunity.com/market/listings/" + appid + "/" + encodeURIComponent(hashName), function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $ = Cheerio.load(body);
|
||||
if($('.market_listing_table_message') && $('.market_listing_table_message').text().trim() == 'There are no listings for this item.') {
|
||||
callback(new Error("There are no listings for this item."));
|
||||
return;
|
||||
}
|
||||
|
||||
var item = new CMarketItem(self, body, $);
|
||||
if(item.commodity) {
|
||||
item.updatePrice(function(err) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
} else {
|
||||
callback(null, item);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback(null, item);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function CMarketItem(community, body, $) {
|
||||
this._community = community;
|
||||
this._$ = $;
|
||||
|
||||
this._country = "US";
|
||||
var match = body.match(/var g_strCountryCode = "([^"]+)";/);
|
||||
if(match) {
|
||||
this._country = match[1];
|
||||
}
|
||||
|
||||
this.commodity = false;
|
||||
var match = body.match(/Market_LoadOrderSpread\(\s*(\d+)\s*\);/);
|
||||
if(match) {
|
||||
this.commodity = true;
|
||||
this.commodityID = parseInt(match[1], 10);
|
||||
}
|
||||
|
||||
this.medianSalePrices = null;
|
||||
match = body.match(/var line1=([^;]+);/);
|
||||
if(match) {
|
||||
try {
|
||||
this.medianSalePrices = JSON.parse(match[1]);
|
||||
this.medianSalePrices = this.medianSalePrices.map(function(item) {
|
||||
return {
|
||||
"hour": new Date(item[0]),
|
||||
"price": item[1],
|
||||
"quantity": parseInt(item[2], 10)
|
||||
};
|
||||
});
|
||||
} catch(e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
this.quantity = 0;
|
||||
this.lowestPrice = 0;
|
||||
|
||||
if(!this.commodity) {
|
||||
var total = $('#searchResults_total');
|
||||
if(total) {
|
||||
this.quantity = parseInt(total.text().replace(/[^\d]/g, '').trim(), 10);
|
||||
}
|
||||
|
||||
var lowest = $('.market_listing_price.market_listing_price_with_fee');
|
||||
if(lowest[0]) {
|
||||
this.lowestPrice = parseInt($(lowest[0]).text().replace(/[^\d]/g, '').trim(), 10);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Buying listings and placing buy orders
|
||||
}
|
||||
|
||||
CMarketItem.prototype.updatePrice = function(callback) {
|
||||
if(!this.commodity) {
|
||||
throw new Error("Cannot update price for non-commodity item");
|
||||
}
|
||||
|
||||
// TODO: Currency option maybe?
|
||||
var self = this;
|
||||
this._community.request({
|
||||
"uri": "https://steamcommunity.com/market/itemordershistogram?country=US&language=english¤cy=1&item_nameid=" + this.commodityID,
|
||||
"json": true,
|
||||
}, function(err, response, body) {
|
||||
if(self._community._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(body.success != 1) {
|
||||
if(callback) {
|
||||
callback(new Error("Error " + body.success));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var match = (body.sell_order_summary || '').match(/<span class="market_commodity_orders_header_promote">(\d+)<\/span>/);
|
||||
if(match) {
|
||||
self.quantity = parseInt(match[1], 10);
|
||||
}
|
||||
|
||||
self.buyQuantity = 0;
|
||||
match = (body.buy_order_summary || '').match(/<span class="market_commodity_orders_header_promote">(\d+)<\/span>/);
|
||||
if(match) {
|
||||
self.buyQuantity = parseInt(match[1], 10);
|
||||
}
|
||||
|
||||
self.lowestPrice = parseInt(body.lowest_sell_order, 10);
|
||||
self.highestBuyOrder = parseInt(body.highest_buy_order, 10);
|
||||
|
||||
// TODO: The tables?
|
||||
if(callback) {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
};
|
||||
85
classes/CMarketSearchResult.js
Normal file
85
classes/CMarketSearchResult.js
Normal file
@@ -0,0 +1,85 @@
|
||||
var SteamCommunity = require('../index.js');
|
||||
var Cheerio = require('cheerio');
|
||||
|
||||
SteamCommunity.prototype.marketSearch = function(options, callback) {
|
||||
var qs = {};
|
||||
|
||||
if(typeof options === 'string') {
|
||||
qs.query = options;
|
||||
} else {
|
||||
qs.query = options.query || '';
|
||||
qs.appid = options.appid;
|
||||
qs.search_descriptions = options.searchDescriptions ? 1 : 0;
|
||||
|
||||
if(qs.appid) {
|
||||
for(var i in options) {
|
||||
if(['query', 'appid', 'searchDescriptions'].indexOf(i) != -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is a tag
|
||||
qs['category_' + qs.appid + '_' + i + '[]'] = 'tag_' + options[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qs.start = 0;
|
||||
qs.count = 100;
|
||||
qs.sort_column = 'price';
|
||||
qs.sort_dir = 'asc';
|
||||
performSearch.call(this, this.request, qs, [], callback);
|
||||
};
|
||||
|
||||
function performSearch(request, qs, results, callback) {
|
||||
var self = this;
|
||||
request({
|
||||
"uri": "https://steamcommunity.com/market/search/render/",
|
||||
"qs": qs,
|
||||
"headers": {
|
||||
"referer": "https://steamcommunity.com/market/search"
|
||||
},
|
||||
"json": true
|
||||
}, function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!body.success) {
|
||||
callback(new Error("Success is not true"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!body.results_html) {
|
||||
callback(new Error("No results_html in response"));
|
||||
return;
|
||||
}
|
||||
|
||||
var $ = Cheerio.load(body.results_html);
|
||||
if($('.market_listing_table_message').length > 0) {
|
||||
callback(new Error($('.market_listing_table_message').text()));
|
||||
return;
|
||||
}
|
||||
|
||||
var rows = $('.market_listing_row_link');
|
||||
for(var i = 0; i < rows.length; i++) {
|
||||
results.push(new CMarketSearchResult($(rows[i])));
|
||||
}
|
||||
|
||||
if(body.start + body.pagesize >= body.total_count) {
|
||||
callback(null, results);
|
||||
} else {
|
||||
qs.start += body.pagesize;
|
||||
performSearch(request, qs, results, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function CMarketSearchResult(row) {
|
||||
var match = row.attr('href').match(/\/market\/listings\/(\d+)\/(.+)/);
|
||||
|
||||
this.appid = parseInt(match[1], 10);
|
||||
this.market_hash_name = decodeURIComponent(match[2]);
|
||||
this.image = row.find('.market_listing_item_img').attr('src').match(/^https?:\/\/[^\/]+\/economy\/image\/[^\/]+\//)[0];
|
||||
this.price = parseInt(row.find('.market_listing_their_price .market_table_value span').text().replace(/[^\d]+/g, ''), 10);
|
||||
this.quantity = parseInt(row.find('.market_listing_num_listings_qty').text().replace(/[^\d]+/g, ''), 10);
|
||||
}
|
||||
286
classes/CSteamGroup.js
Normal file
286
classes/CSteamGroup.js
Normal file
@@ -0,0 +1,286 @@
|
||||
var SteamCommunity = require('../index.js');
|
||||
var SteamID = require('steamid');
|
||||
var xml2js = require('xml2js');
|
||||
|
||||
SteamCommunity.prototype.getSteamGroup = function(id, callback) {
|
||||
if(typeof id !== 'string' && !(typeof id === 'object' && id.__proto__ === SteamID.prototype)) {
|
||||
throw new Error("id parameter should be a group URL string or a SteamID object");
|
||||
}
|
||||
|
||||
if(typeof id === 'object' && (id.universe != SteamID.Universe.PUBLIC || id.type != SteamID.Type.CLAN)) {
|
||||
throw new Error("SteamID must stand for a clan account in the public universe");
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.request("https://steamcommunity.com/" + (typeof id === 'string' ? "groups/" + id : "gid/" + id.toString()) + "/memberslistxml/?xml=1", function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._checkCommunityError(body, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
xml2js.parseString(body, function(err, result) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, new CSteamGroup(self, result.memberList));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function CSteamGroup(community, groupData) {
|
||||
this._community = community;
|
||||
|
||||
this.steamID = new SteamID(groupData.groupID64[0]);
|
||||
this.name = groupData.groupDetails[0].groupName[0];
|
||||
this.url = groupData.groupDetails[0].groupURL[0];
|
||||
this.headline = groupData.groupDetails[0].headline[0];
|
||||
this.summary = groupData.groupDetails[0].summary[0];
|
||||
this.avatarHash = groupData.groupDetails[0].avatarIcon[0].match(/([0-9a-f]+)\.jpg$/)[1];
|
||||
this.members = parseInt(groupData.groupDetails[0].memberCount[0], 10);
|
||||
this.membersInChat = parseInt(groupData.groupDetails[0].membersInChat[0], 10);
|
||||
this.membersInGame = parseInt(groupData.groupDetails[0].membersInGame[0], 10);
|
||||
this.membersOnline = parseInt(groupData.groupDetails[0].membersOnline[0], 10);
|
||||
}
|
||||
|
||||
CSteamGroup.prototype.getAvatarURL = function(size, protocol) {
|
||||
size = size || '';
|
||||
protocol = protocol || 'http://';
|
||||
|
||||
var url = protocol + "steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/" + this.avatarHash.substring(0, 2) + "/" + this.avatarHash;
|
||||
if(size == 'full' || size == 'medium') {
|
||||
return url + "_" + size + ".jpg";
|
||||
} else {
|
||||
return url + ".jpg";
|
||||
}
|
||||
};
|
||||
|
||||
CSteamGroup.prototype.getMembers = function(callback, members, link) {
|
||||
members = members || [];
|
||||
link = link || "http://steamcommunity.com/gid/" + this.steamID.toString() + "/memberslistxml/?xml=1";
|
||||
|
||||
var self = this;
|
||||
this._community.request(link, function(err, response, body) {
|
||||
if(self._community._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
xml2js.parseString(body, function(err, result) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
members = members.concat(result.memberList.members[0].steamID64.map(function(steamID) {
|
||||
return new SteamID(steamID);
|
||||
}));
|
||||
|
||||
if(result.memberList.nextPageLink) {
|
||||
self.getMembers(callback, members, result.memberList.nextPageLink[0]);
|
||||
} else {
|
||||
callback(null, members);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
CSteamGroup.prototype.join = function(callback) {
|
||||
var form = {
|
||||
"action": "join",
|
||||
"sessionID": this._community.getSessionID()
|
||||
};
|
||||
|
||||
var self = this;
|
||||
this._community.request.post("https://steamcommunity.com/gid/" + this.steamID.toString(), {"form": form}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(err || response.statusCode >= 400) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._community._checkCommunityError(body, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
CSteamGroup.prototype.leave = function(callback) {
|
||||
var form = {
|
||||
"sessionID": this._community.getSessionID(),
|
||||
"action": "leaveGroup",
|
||||
"groupId": this.steamID.toString()
|
||||
};
|
||||
|
||||
var self = this;
|
||||
this._community._myProfile("home_process", form, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(err || response.statusCode >= 400) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._community._checkCommunityError(body, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
CSteamGroup.prototype.postAnnouncement = function(headline, content, callback) {
|
||||
var form = {
|
||||
"sessionID": this._community.getSessionID(),
|
||||
"action": "post",
|
||||
"headline": headline,
|
||||
"body": content
|
||||
};
|
||||
|
||||
this._community.request.post("https://steamcommunity.com/gid/" + this.steamID.toString() + "/announcements", {"form": form}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(err || response.statusCode >= 400) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._community._checkCommunityError(body, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
CSteamGroup.prototype.scheduleEvent = function(name, type, description, time, server, callback) {
|
||||
// Event types: ChatEvent - Chat, OtherEvent - A lil somethin somethin, PartyEvent - Party!, MeetingEvent - Important meeting, SpecialCauseEvent - Special cause (charity ball?), MusicAndArtsEvent - Music or Art type thing, SportsEvent - Sporting endeavor, TripEvent - Out of town excursion
|
||||
// Passing a number for type will make it a game event for that appid
|
||||
|
||||
if(typeof server === 'function') {
|
||||
callback = server;
|
||||
server = {"ip": "", "password": ""};
|
||||
} else if(typeof server === 'string') {
|
||||
server = {"ip": server, "password": ""};
|
||||
} else {
|
||||
server = {"ip": "", "password": ""};
|
||||
}
|
||||
|
||||
var form = {
|
||||
"sessionid": this._community.getSessionID(),
|
||||
"action": "newEvent",
|
||||
"tzOffset": new Date().getTimezoneOffset() * -60,
|
||||
"name": name,
|
||||
"type": (typeof type === 'number' || !isNaN(parseInt(type, 10)) ? "GameEvent" : type),
|
||||
"appID": (typeof type === 'number' || !isNaN(parseInt(type, 10)) ? type : ''),
|
||||
"serverIP": server.ip,
|
||||
"serverPassword": server.password,
|
||||
"notes": description,
|
||||
"eventQuickTime": "now"
|
||||
};
|
||||
|
||||
if(time === null) {
|
||||
form.startDate = 'MM/DD/YY';
|
||||
form.startHour = '12';
|
||||
form.startMinute = '00';
|
||||
form.startAMPM = 'PM';
|
||||
form.timeChoice = 'quick';
|
||||
} else {
|
||||
form.startDate = (time.getMonth() + 1 < 10 ? '0' : '') + (time.getMonth() + 1) + '/' + (time.getDate() < 10 ? '0' : '') + time.getDate() + '/' + time.getFullYear().toString().substring(2);
|
||||
form.startHour = (time.getHours() === 0 ? '12' : (time.getHours() > 12 ? time.getHours() - 12 : time.getHours()));
|
||||
form.startMinute = (time.getMinutes() < 10 ? '0' : '') + time.getMinutes();
|
||||
form.startAMPM = (time.getHours() <= 12 ? 'AM' : 'PM');
|
||||
form.timeChoice = 'specific';
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this._community.request.post("https://steamcommunity.com/gid/" + this.steamID.toString() + "/eventEdit", {"form": form}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(err || response.statusCode >= 400) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._community._checkCommunityError(body, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
CSteamGroup.prototype.setPlayerOfTheWeek = function(steamID, callback) {
|
||||
var form = {
|
||||
"xml": 1,
|
||||
"action": "potw",
|
||||
"memberId": steamID.getSteam3RenderedID(),
|
||||
"sessionid": this._community.getSessionID()
|
||||
};
|
||||
|
||||
var self = this;
|
||||
this._community.request.post("https://steamcommunity.com/gid/" + this.steamID.toString() + "/potwEdit", {"form": form}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(err || response.statusCode != 200) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
return;
|
||||
}
|
||||
|
||||
xml2js.parseString(body, function(err, results) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if(results.response.results[0] == 'OK') {
|
||||
callback(null, new SteamID(results.response.oldPOTW[0]), new SteamID(results.response.newPOTW[0]));
|
||||
} else {
|
||||
callback(new Error(results.response.results[0]));
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
CSteamGroup.prototype.kick = function(steamID, callback) {
|
||||
var form = {
|
||||
"sessionID": this._community.getSessionID(),
|
||||
"action": "kick",
|
||||
"memberId": steamID.toString(),
|
||||
"queryString": ""
|
||||
};
|
||||
|
||||
var self = this;
|
||||
this._community.request.post("https://steamcommunity.com/gid/" + this.steamID.toString() + "/membersManage", {"form": form}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(err || response.statusCode >= 400) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._community._checkCommunityError(body, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
230
classes/CSteamUser.js
Normal file
230
classes/CSteamUser.js
Normal file
@@ -0,0 +1,230 @@
|
||||
var SteamCommunity = require('../index.js');
|
||||
var SteamID = require('steamid');
|
||||
var xml2js = require('xml2js');
|
||||
|
||||
SteamCommunity.prototype.getSteamUser = function(id, callback) {
|
||||
if(typeof id !== 'string' && !(typeof id === 'object' && id.__proto__ === SteamID.prototype)) {
|
||||
throw new Error("id parameter should be a user URL string or a SteamID object");
|
||||
}
|
||||
|
||||
if(typeof id === 'object' && (id.universe != SteamID.Universe.PUBLIC || id.type != SteamID.Type.INDIVIDUAL)) {
|
||||
throw new Error("SteamID must stand for an individual account in the public universe");
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.request("http://steamcommunity.com/" + (typeof id === 'string' ? "id/" + id : "profiles/" + id.toString()) + "/?xml=1", function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._checkCommunityError(body, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
xml2js.parseString(body, function(err, result) {
|
||||
if(err || (!result.response && !result.profile)) {
|
||||
callback(err || new Error("No valid response"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(result.response && result.response.error && result.response.error.length) {
|
||||
callback(new Error(result.response.error[0]));
|
||||
return;
|
||||
}
|
||||
|
||||
// Try and find custom URL from redirect
|
||||
var customurl = null;
|
||||
if(response.request.redirects && response.request.redirects.length) {
|
||||
var match = response.request.redirects[0].redirectUri.match(/https?:\/\/steamcommunity\.com\/id\/([^/])+\/\?xml=1/);
|
||||
if(match) {
|
||||
customurl = match[1];
|
||||
}
|
||||
}
|
||||
|
||||
callback(null, new CSteamUser(self, result.profile, customurl));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function CSteamUser(community, userData, customurl) {
|
||||
this._community = community;
|
||||
|
||||
this.steamID = new SteamID(userData.steamID64[0]);
|
||||
this.name = userData.steamID[0];
|
||||
this.onlineState = userData.onlineState[0];
|
||||
this.stateMessage = userData.stateMessage[0];
|
||||
this.privacyState = userData.privacyState[0];
|
||||
this.visibilityState = userData.visibilityState[0];
|
||||
this.avatarHash = userData.avatarIcon[0].match(/([0-9a-f]+)\.[a-z]+$/)[1];
|
||||
this.vacBanned = !!userData.vacBanned[0];
|
||||
this.tradeBanState = userData.tradeBanState[0];
|
||||
this.isLimitedAccount = !!userData.isLimitedAccount[0];
|
||||
this.customURL = userData.customURL ? userData.customURL[0] : customurl;
|
||||
|
||||
if(this.visibilityState == 3) {
|
||||
this.memberSince = new Date(userData.memberSince[0].replace(/(\d{1,2})(st|nd|th)/, "$1"));
|
||||
this.location = userData.location[0] || null;
|
||||
this.realName = userData.realname[0] || null;
|
||||
this.summary = userData.summary[0] || null;
|
||||
} else {
|
||||
this.memberSince = null;
|
||||
this.location = null;
|
||||
this.realName = null;
|
||||
this.summary = null;
|
||||
}
|
||||
|
||||
// Maybe handle mostPlayedGames?
|
||||
|
||||
this.groups = null;
|
||||
this.primaryGroup = null;
|
||||
|
||||
var self = this;
|
||||
if(userData.groups && userData.groups[0] && userData.groups[0].group) {
|
||||
this.groups = userData.groups[0].group.map(function(group) {
|
||||
if(group['$'] && group['$'].isPrimary) {
|
||||
self.primaryGroup = new SteamID(group.groupID64[0]);
|
||||
}
|
||||
|
||||
return new SteamID(group.groupID64[0]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
CSteamUser.getAvatarURL = function(hash, size, protocol) {
|
||||
size = size || '';
|
||||
protocol = protocol || 'http://';
|
||||
|
||||
var url = protocol + "steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/" + hash.substring(0, 2) + "/" + hash;
|
||||
if(size == 'full' || size == 'medium') {
|
||||
return url + "_" + size + ".jpg";
|
||||
} else {
|
||||
return url + ".jpg";
|
||||
}
|
||||
};
|
||||
|
||||
CSteamUser.prototype.getAvatarURL = function(size, protocol) {
|
||||
return CSteamUser.getAvatarURL(this.avatarHash, size, protocol);
|
||||
};
|
||||
|
||||
CSteamUser.prototype.addFriend = function(callback) {
|
||||
var self = this;
|
||||
this._community.request.post('https://steamcommunity.com/actions/AddFriendAjax', {"form": {"accept_invite": 0, "sessionID": this._community.getSessionID(), "steamid": this.steamID.toString()}}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._community._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var json;
|
||||
try {
|
||||
json = JSON.parse(body);
|
||||
} catch(e) {
|
||||
callback(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if(json.success) {
|
||||
callback(null);
|
||||
} else {
|
||||
callback(new Error("Unknown error"));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
CSteamUser.prototype.acceptFriendRequest = function(callback) {
|
||||
var self = this;
|
||||
this._community.request.post('https://steamcommunity.com/actions/AddFriendAjax', {"form": {"accept_invite": 1, "sessionID": this._community.getSessionID(), "steamid": this.steamID.toString()}}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._community._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
CSteamUser.prototype.removeFriend = function(callback) {
|
||||
var self = this;
|
||||
this._community.request.post('https://steamcommunity.com/actions/RemoveFriendAjax', {"form": {"sessionID": this._community.getSessionID(), "steamid": this.steamID.toString()}}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._community._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
CSteamUser.prototype.blockCommunication = function(callback) {
|
||||
var self = this;
|
||||
this._community.request.post('https://steamcommunity.com/actions/BlockUserAjax', {"form": {"sessionID": this._community.getSessionID(), "steamid": this.steamID.toString()}}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._community._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
CSteamUser.prototype.unblockCommunication = function(callback) {
|
||||
var form = {"action": "unignore"};
|
||||
form['friends[' + this.steamID.toString() + ']'] = 1;
|
||||
|
||||
this._community._myProfile('friends/blocked/', form, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(err || response.statusCode >= 400) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
CSteamUser.prototype.comment = function(message, callback) {
|
||||
this._community.request.post('https://steamcommunity.com/comment/Profile/post/' + this.steamID.toString() + '/-1/', {"form": {
|
||||
"comment": message,
|
||||
"count": 6,
|
||||
"sessionid": this._community.getSessionID()
|
||||
}}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(err || response.statusCode != 200) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
return;
|
||||
}
|
||||
|
||||
var json;
|
||||
try {
|
||||
json = JSON.parse(body);
|
||||
} catch(e) {
|
||||
callback(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if(json.success) {
|
||||
callback(null);
|
||||
} else if(json.error) {
|
||||
callback(new Error(json.error));
|
||||
} else {
|
||||
callback(new Error("Unknown error"));
|
||||
}
|
||||
});
|
||||
};
|
||||
253
components/chat.js
Normal file
253
components/chat.js
Normal file
@@ -0,0 +1,253 @@
|
||||
var SteamCommunity = require('../index.js');
|
||||
var SteamID = require('steamid');
|
||||
|
||||
SteamCommunity.ChatState = {
|
||||
"Offline": 0,
|
||||
"LoggingOn": 1,
|
||||
"LogOnFailed": 2,
|
||||
"LoggedOn": 3
|
||||
};
|
||||
|
||||
SteamCommunity.PersonaState = {
|
||||
"Offline": 0,
|
||||
"Online": 1,
|
||||
"Busy": 2,
|
||||
"Away": 3,
|
||||
"Snooze": 4,
|
||||
"LookingToTrade": 5,
|
||||
"LookingToPlay": 6,
|
||||
"Max": 7
|
||||
};
|
||||
|
||||
SteamCommunity.PersonaStateFlag = {
|
||||
"HasRichPresence": 1,
|
||||
"InJoinableGame": 2,
|
||||
|
||||
"OnlineUsingWeb": 256,
|
||||
"OnlineUsingMobile": 512,
|
||||
"OnlineUsingBigPicture": 1024
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
|
||||
if(this.chatState == SteamCommunity.ChatState.LoggingOn || this.chatState == SteamCommunity.ChatState.LoggedOn) {
|
||||
return;
|
||||
}
|
||||
|
||||
interval = interval || 500;
|
||||
uiMode = uiMode || "web";
|
||||
|
||||
this.emit('debug', 'Requesting chat WebAPI token');
|
||||
this.chatState = SteamCommunity.ChatState.LoggingOn;
|
||||
|
||||
var self = this;
|
||||
this.request("https://steamcommunity.com/chat", function(err, response, body) {
|
||||
if(err || response.statusCode != 200) {
|
||||
self.emit('debug', 'Error requesting chat WebAPI token: ' + (err ? err.message : "HTTP error " + response.statusCode));
|
||||
self.chatState = SteamCommunity.ChatState.LogOnFailed;
|
||||
setTimeout(self.chatLogon.bind(self), 5000);
|
||||
return;
|
||||
}
|
||||
|
||||
var match = body.match(/[0-9a-f]{32}/);
|
||||
if(!match) {
|
||||
self.emit('debug', 'Couldn\'t find a WebAPI chat token in the response.');
|
||||
self.chatState = SteamCommunity.ChatState.LogOnFailed;
|
||||
setTimeout(self.chatLogon.bind(self), 5000);
|
||||
return;
|
||||
}
|
||||
|
||||
self.request.post({
|
||||
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Logon/v1",
|
||||
"form": {
|
||||
"ui_mode": uiMode,
|
||||
"access_token": match[0]
|
||||
},
|
||||
"json": true
|
||||
}, function(err, response, body) {
|
||||
if(err || response.statusCode != 200) {
|
||||
self.emit('debug', 'Error logging into webchat: ' + (err ? err.message : "HTTP error " + response.statusCode));
|
||||
self.chatState = SteamCommunity.ChatState.LogOnFailed;
|
||||
setTimeout(self.chatLogon.bind(self), 5000);
|
||||
return;
|
||||
}
|
||||
|
||||
if(body.error != 'OK') {
|
||||
self.emit('debug', 'Error logging into webchat: ' + body.error);
|
||||
self.chatState = SteamCommunity.ChatState.LogOnFailed;
|
||||
setTimeout(self.chatLogon.bind(self), 5000);
|
||||
return;
|
||||
}
|
||||
|
||||
self._chat = {
|
||||
"umqid": body.umqid,
|
||||
"message": body.message,
|
||||
"accessToken": match[0],
|
||||
"interval": interval
|
||||
};
|
||||
|
||||
self.chatFriends = {};
|
||||
|
||||
self.chatState = SteamCommunity.ChatState.LoggedOn;
|
||||
self.emit('chatLoggedOn');
|
||||
self._chatPoll();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.chatMessage = function(recipient, text, type, callback) {
|
||||
if(this.chatState != SteamCommunity.ChatState.LoggedOn) {
|
||||
throw new Error("Chat must be logged on before messages can be sent");
|
||||
}
|
||||
|
||||
if(typeof recipient === 'string') {
|
||||
recipient = new SteamID(recipient);
|
||||
}
|
||||
|
||||
if(typeof type === 'function') {
|
||||
callback = type;
|
||||
type = 'saytext';
|
||||
}
|
||||
|
||||
type = type || 'saytext';
|
||||
|
||||
this.request.post({
|
||||
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Message/v1",
|
||||
"form": {
|
||||
"access_token": this._chat.accessToken,
|
||||
"steamid_dst": recipient.toString(),
|
||||
"text": text,
|
||||
"type": type,
|
||||
"umqid": this._chat.umqid
|
||||
},
|
||||
"json": true
|
||||
}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(body.error != 'OK') {
|
||||
callback(new Error(body.error));
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.chatLogoff = function() {
|
||||
var self = this;
|
||||
this.request.post({
|
||||
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Logoff/v1",
|
||||
"form": {
|
||||
"access_token": this._chat.accessToken,
|
||||
"umqid": this._chat.umqid
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
if(err || response.statusCode != 200) {
|
||||
self.emit('debug', 'Error logging off of chat: ' + (err ? err.message : "HTTP error " + response.statusCode));
|
||||
setTimeout(self.chatLogoff.bind(self), 1000);
|
||||
} else {
|
||||
self.emit('chatLoggedOff');
|
||||
clearTimeout(self._chat.timer);
|
||||
delete self._chat;
|
||||
delete self.chatFriends;
|
||||
self.chatState = SteamCommunity.ChatState.Offline;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype._chatPoll = function() {
|
||||
this.emit('debug', 'Doing chat poll');
|
||||
|
||||
var self = this;
|
||||
this.request.post({
|
||||
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Poll/v1",
|
||||
"form": {
|
||||
"umqid": self._chat.umqid,
|
||||
"message": self._chat.message,
|
||||
"pollid": 1,
|
||||
"sectimeout": 20,
|
||||
"secidletime": 0,
|
||||
"use_accountids": 1,
|
||||
"access_token": self._chat.accessToken
|
||||
},
|
||||
"json": true
|
||||
}, function(err, response, body) {
|
||||
if(self.chatState == SteamCommunity.ChatState.Offline) {
|
||||
return;
|
||||
}
|
||||
|
||||
self._chat.timer = setTimeout(self._chatPoll.bind(self), self._chat.interval);
|
||||
|
||||
if(err || response.statusCode != 200) {
|
||||
self.emit('debug', 'Error in chat poll: ' + (err ? err.message : "HTTP error " + response.statusCode));
|
||||
return;
|
||||
}
|
||||
|
||||
if(body.error != 'OK') {
|
||||
self.emit('debug', 'Error in chat poll: ' + body.error);
|
||||
return;
|
||||
}
|
||||
|
||||
self._chat.message = body.messagelast;
|
||||
|
||||
(body.messages || []).forEach(function(message) {
|
||||
var sender = new SteamID();
|
||||
sender.universe = SteamID.Universe.PUBLIC;
|
||||
sender.type = SteamID.Type.INDIVIDUAL;
|
||||
sender.instance = SteamID.Instance.DESKTOP;
|
||||
sender.accountid = message.accountid_from;
|
||||
|
||||
switch(message.type) {
|
||||
case 'personastate':
|
||||
self._chatUpdatePersona(sender);
|
||||
break;
|
||||
|
||||
case 'saytext':
|
||||
self.emit('chatMessage', sender, message.text);
|
||||
break;
|
||||
|
||||
case 'typing':
|
||||
self.emit('chatTyping', sender);
|
||||
break;
|
||||
|
||||
default:
|
||||
self.emit('debug', 'Unhandled chat message type: ' + message.type);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype._chatUpdatePersona = function(steamID) {
|
||||
this.emit('debug', 'Updating persona data for ' + steamID);
|
||||
var self = this;
|
||||
this.request({
|
||||
"uri": "https://steamcommunity.com/chat/friendstate/" + steamID.accountid,
|
||||
"json": true
|
||||
}, function(err, response, body) {
|
||||
if(err || response.statusCode != 200) {
|
||||
self.emit('debug', 'Chat update persona error: ' + (err ? err.message : "HTTP error " + response.statusCode));
|
||||
setTimeout(function() {
|
||||
self._chatUpdatePersona(steamID);
|
||||
}, 2000);
|
||||
return;
|
||||
}
|
||||
|
||||
var persona = {
|
||||
"steamID": steamID,
|
||||
"personaName": body.m_strName,
|
||||
"personaState": body.m_ePersonaState,
|
||||
"personaStateFlags": body.m_nPersonaStateFlags || 0,
|
||||
"avatarHash": body.m_strAvatarHash,
|
||||
"inGame": !!body.m_bInGame,
|
||||
"inGameAppID": body.m_nInGameAppID ? parseInt(body.m_nInGameAppID, 10) : null,
|
||||
"inGameName": body.m_strInGameName || null
|
||||
};
|
||||
|
||||
self.emit('chatPersonaState', steamID, persona);
|
||||
self.chatFriends[steamID.getSteamID64()] = persona;
|
||||
});
|
||||
};
|
||||
213
components/profile.js
Normal file
213
components/profile.js
Normal file
@@ -0,0 +1,213 @@
|
||||
var SteamCommunity = require('../index.js');
|
||||
var SteamID = require('steamid');
|
||||
var Cheerio = require('cheerio');
|
||||
|
||||
SteamCommunity.PrivacyState = {
|
||||
"Private": 1,
|
||||
"FriendsOnly": 2,
|
||||
"Public": 3
|
||||
};
|
||||
|
||||
var CommentPrivacyState = {
|
||||
"1": "commentselfonly",
|
||||
"2": "commentfriendsonly",
|
||||
"3": "commentanyone"
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.setupProfile = function(callback) {
|
||||
var self = this;
|
||||
this._myProfile("edit?welcomed=1", null, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(err || response.statusCode != 200) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.editProfile = function(settings, callback) {
|
||||
var self = this;
|
||||
this._myProfile("edit", null, function(err, response, body) {
|
||||
if(err || response.statusCode != 200) {
|
||||
if(callback) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var $ = Cheerio.load(body);
|
||||
var form = $('#editForm');
|
||||
if(!form) {
|
||||
if(callback) {
|
||||
callback(new Error("Malformed response"));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var values = {};
|
||||
form.serializeArray().forEach(function(item) {
|
||||
values[item.name] = item.value;
|
||||
});
|
||||
|
||||
for(var i in settings) {
|
||||
if(!settings.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(i) {
|
||||
case 'name':
|
||||
values.personaName = settings[i];
|
||||
break;
|
||||
|
||||
case 'realName':
|
||||
values.real_name = settings[i];
|
||||
break;
|
||||
|
||||
case 'summary':
|
||||
values.summary = settings[i];
|
||||
break;
|
||||
|
||||
case 'country':
|
||||
values.country = settings[i];
|
||||
break;
|
||||
|
||||
case 'state':
|
||||
values.state = settings[i];
|
||||
break;
|
||||
|
||||
case 'city':
|
||||
values.city = settings[i];
|
||||
break;
|
||||
|
||||
case 'customURL':
|
||||
values.customURL = settings[i];
|
||||
break;
|
||||
|
||||
case 'background':
|
||||
// The assetid of our desired profile background
|
||||
values.profile_background = settings[i];
|
||||
break;
|
||||
|
||||
case 'featuredBadge':
|
||||
// Currently, game badges aren't supported
|
||||
values.favorite_badge_badgeid = settings[i];
|
||||
break;
|
||||
|
||||
case 'primaryGroup':
|
||||
if(typeof settings[i] === 'object' && settings[i].accountid) {
|
||||
values.primary_group_steamid = settings[i].accountid;
|
||||
} else {
|
||||
values.primary_group_steamid = new SteamID(settings[i]).accountid;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// TODO: profile showcases
|
||||
}
|
||||
}
|
||||
|
||||
self._myProfile("edit", values, function(err, response, body) {
|
||||
if(err || response.statusCode != 200) {
|
||||
if(callback) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for an error
|
||||
var $ = Cheerio.load(body);
|
||||
var error = $('#errorText .formRowFields');
|
||||
if(error) {
|
||||
error = error.text().trim();
|
||||
if(error) {
|
||||
if(callback) {
|
||||
callback(new Error(error));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(callback) {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.profileSettings = function(settings, callback) {
|
||||
var self = this;
|
||||
this._myProfile("edit/settings", null, function(err, response, body) {
|
||||
if(err || response.statusCode != 200) {
|
||||
if(callback) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var $ = Cheerio.load(body);
|
||||
var form = $('#editForm');
|
||||
if(!form) {
|
||||
if(callback) {
|
||||
callback(new Error("Malformed response"));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var values = {};
|
||||
form.serializeArray().forEach(function(item) {
|
||||
values[item.name] = item.value;
|
||||
});
|
||||
|
||||
for(var i in settings) {
|
||||
if(!settings.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(i) {
|
||||
case 'profile':
|
||||
values.privacySetting = settings[i];
|
||||
break;
|
||||
|
||||
case 'comments':
|
||||
values.commentSetting = CommentPrivacyState[settings[i]];
|
||||
break;
|
||||
|
||||
case 'inventory':
|
||||
values.inventoryPrivacySetting = settings[i];
|
||||
break;
|
||||
|
||||
case 'inventoryGifts':
|
||||
values.inventoryGiftPrivacy = settings[i] ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 'emailConfirmation':
|
||||
values.tradeConfirmationSetting = settings[i] ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self._myProfile("edit/settings", values, function(err, response, body) {
|
||||
if(err || response.statusCode != 200) {
|
||||
if(callback) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(callback) {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
337
index.js
337
index.js
@@ -1,33 +1,32 @@
|
||||
var Request = require('request');
|
||||
var RSA = require('node-bignumber').Key;
|
||||
var hex2b64 = require('node-bignumber').hex2b64;
|
||||
var SteamID = require('steamid');
|
||||
|
||||
require('util').inherits(SteamCommunity, require('events').EventEmitter);
|
||||
|
||||
module.exports = SteamCommunity;
|
||||
|
||||
function SteamCommunity(username, password, steamID, machineAuth) {
|
||||
this._username = username;
|
||||
this._password = password;
|
||||
this._steamID = steamID;
|
||||
this._sentry = machineAuth;
|
||||
SteamCommunity.SteamID = SteamID;
|
||||
|
||||
function SteamCommunity() {
|
||||
this._jar = Request.jar();
|
||||
this._captchaGid = -1;
|
||||
this.request = Request.defaults({"jar": this._jar, "timeout": 50000});
|
||||
this.chatState = SteamCommunity.ChatState.Offline;
|
||||
|
||||
// English
|
||||
this._jar.setCookie(Request.cookie('Steam_Language=english'), 'https://steamcommunity.com');
|
||||
}
|
||||
|
||||
SteamCommunity.prototype.login = function(authCode, callback) {
|
||||
if(typeof authCode === 'function') {
|
||||
callback = authCode;
|
||||
authCode = "";
|
||||
}
|
||||
|
||||
var request;
|
||||
if(this._steamID && this._sentry) {
|
||||
var jar = Request.jar();
|
||||
request = Request.defaults({"jar": jar});
|
||||
jar.setCookieSync(Request.cookie('steamMachineAuth' + this._steamID + '=' + this._sentry), 'https://steamcommunity.com');
|
||||
} else {
|
||||
request = Request;
|
||||
SteamCommunity.prototype.login = function(details, callback) {
|
||||
if(details.steamguard) {
|
||||
var parts = details.steamguard.split('||');
|
||||
this._jar.setCookie(Request.cookie('steamMachineAuth' + parts[0] + '=' + encodeURIComponent(parts[1])), 'https://steamcommunity.com');
|
||||
}
|
||||
|
||||
var self = this;
|
||||
request.post("https://steamcommunity.com/login/getrsakey/", {"form": {"username": this._username}}, function(err, response, body) {
|
||||
this.request.post("https://steamcommunity.com/login/getrsakey/", {"form": {"username": details.accountName}}, function(err, response, body) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
@@ -45,64 +44,274 @@ SteamCommunity.prototype.login = function(authCode, callback) {
|
||||
key.setPublic(json.publickey_mod, json.publickey_exp);
|
||||
|
||||
var form = {
|
||||
"captcha_text": "",
|
||||
"captchagid": -1,
|
||||
"emailauth": authCode || "",
|
||||
"captcha_text": details.captcha || "",
|
||||
"captchagid": self._captchaGid,
|
||||
"emailauth": details.authCode || "",
|
||||
"emailsteamid": "",
|
||||
"loginfriendlyname": "",
|
||||
"password": hex2b64(key.encrypt(self._password)),
|
||||
"remember_login": false,
|
||||
"password": hex2b64(key.encrypt(details.password)),
|
||||
"remember_login": "true",
|
||||
"rsatimestamp": json.timestamp,
|
||||
"twofactorcode": "",
|
||||
"username": self._username
|
||||
"twofactorcode": details.twoFactorCode || "",
|
||||
"username": details.accountName
|
||||
};
|
||||
|
||||
request.post("https://steamcommunity.com/login/dologin/", {"form": form}, function(err, response, body) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
self.request.post({
|
||||
"uri": "https://steamcommunity.com/login/dologin/",
|
||||
"json": true,
|
||||
"form": form
|
||||
}, function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var json;
|
||||
try {
|
||||
json = JSON.parse(body);
|
||||
} catch(e) {
|
||||
callback(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!json.success) {
|
||||
callback(json.message);
|
||||
if(!body.success && body.emailauth_needed) {
|
||||
// Steam Guard (email)
|
||||
var error = new Error("SteamGuard");
|
||||
error.emaildomain = body.emaildomain;
|
||||
|
||||
callback(error);
|
||||
} else if(!body.success && body.requires_twofactor) {
|
||||
// Steam Guard (app)
|
||||
callback(new Error("SteamGuardMobile"));
|
||||
} else if(!body.success && body.captcha_needed) {
|
||||
var error = new Error("CAPTCHA");
|
||||
error.captchaurl = "https://steamcommunity.com/public/captcha.php?gid=" + body.captcha_gid;
|
||||
|
||||
self._captchaGid = body.captcha_gid;
|
||||
|
||||
callback(error);
|
||||
} else if(!body.success) {
|
||||
callback(new Error(body.message || "Unknown error"));
|
||||
} else {
|
||||
var cookies = [];
|
||||
for(var i = 0; i < response.headers['set-cookie'].length; i++) {
|
||||
var header = response.headers['set-cookie'][i];
|
||||
var pos = header.indexOf(';');
|
||||
if(pos != -1) {
|
||||
header = header.substring(0, pos);
|
||||
var sessionID = generateSessionID();
|
||||
self._jar.setCookie(Request.cookie('sessionid=' + sessionID), 'http://steamcommunity.com');
|
||||
|
||||
self.steamID = new SteamID(body.transfer_parameters.steamid);
|
||||
var cookies = self._jar.getCookieString("https://steamcommunity.com").split(';').map(function(cookie) {
|
||||
return cookie.trim();
|
||||
});
|
||||
|
||||
// Find the Steam Guard cookie
|
||||
var steamguard = null;
|
||||
for(var i = 0; i < cookies.length; i++) {
|
||||
var parts = cookies[i].split('=');
|
||||
if(parts[0] == 'steamMachineAuth' + self.steamID) {
|
||||
steamguard = self.steamID.toString() + '||' + decodeURIComponent(parts[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
cookies.push(header);
|
||||
}
|
||||
|
||||
var sessionID = Math.floor(Math.random() * 1000000000);
|
||||
cookies.push('sessionid=' + sessionID);
|
||||
|
||||
if(self._steamID && self._sentry) {
|
||||
cookies.push('steamMachineAuth' + self._steamID + '=' + self._sentry);
|
||||
}
|
||||
|
||||
var steamguard = {};
|
||||
if(json.transfer_parameters.steamid && json.transfer_parameters.webcookie) {
|
||||
steamguard.steamID = json.transfer_parameters.steamid;
|
||||
steamguard.machineAuth = json.transfer_parameters.webcookie;
|
||||
|
||||
self._steamID = steamguard.steamID;
|
||||
self._sentry = steamguard.machineAuth;
|
||||
}
|
||||
|
||||
callback(null, sessionID, cookies, steamguard);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.setCookies = function(cookies) {
|
||||
var self = this;
|
||||
cookies.forEach(function(cookie) {
|
||||
var cookieName = cookie.match(/(.+)=/)[1];
|
||||
if(cookieName == 'steamLogin') {
|
||||
self.steamID = new SteamID(cookie.match(/=(\d+)/)[1]);
|
||||
}
|
||||
|
||||
self._jar.setCookie(Request.cookie(cookie), (cookieName.match(/^steamMachineAuth/) || cookieName.match(/Secure$/) ? "https://" : "http://") + "steamcommunity.com");
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.getSessionID = function() {
|
||||
var cookies = this._jar.getCookieString("http://steamcommunity.com").split(';');
|
||||
for(var i = 0; i < cookies.length; i++) {
|
||||
var match = cookies[i].trim().match(/([^=]+)=(.+)/);
|
||||
if(match[1] == 'sessionid') {
|
||||
return decodeURIComponent(match[2]);
|
||||
}
|
||||
}
|
||||
|
||||
var sessionID = generateSessionID();
|
||||
this._jar.setCookie(Request.cookie('sessionid=' + sessionID), "http://steamcommunity.com");
|
||||
return sessionID;
|
||||
};
|
||||
|
||||
function generateSessionID() {
|
||||
return Math.floor(Math.random() * 1000000000);
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.getWebApiKey = function(domain, callback) {
|
||||
var self = this;
|
||||
this.request("https://steamcommunity.com/dev/apikey", function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(body.match(/<h2>Access Denied<\/h2>/)) {
|
||||
return callback("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(err || response.statusCode >= 400) {
|
||||
return callback(err.message || "HTTP error " + response.statusCode);
|
||||
}
|
||||
|
||||
self.getWebApiKey(domain, callback);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.parentalUnlock = function(pin, callback) {
|
||||
this.request.post("https://steamcommunity.com/parental/ajaxunlock", {
|
||||
"json": true,
|
||||
"form": {
|
||||
"pin": pin
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!body || typeof body.success !== 'boolean') {
|
||||
return callback("Invalid response");
|
||||
}
|
||||
|
||||
if(!body.success) {
|
||||
return callback("Incorrect PIN");
|
||||
}
|
||||
|
||||
callback();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.getNotifications = function(callback) {
|
||||
this.request.get("https://steamcommunity.com/actions/RefreshNotificationArea", function(err, response, body) {
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var notifications = {
|
||||
"comments": 0,
|
||||
"items": 0,
|
||||
"invites": 0,
|
||||
"gifts": 0,
|
||||
"chat": 0,
|
||||
"trades": 0
|
||||
};
|
||||
|
||||
var items = {
|
||||
"comments": /(\d+) new comments?/,
|
||||
"items": /(\d+) new items? in your inventory/,
|
||||
"invites": /(\d+) new invites?/,
|
||||
"gifts": /(\d+) new gifts?/,
|
||||
"chat": /(\d+) unread chat messages?/,
|
||||
"trades": /(\d+) new trade notifications?/
|
||||
};
|
||||
|
||||
var match;
|
||||
for(var i in items) {
|
||||
if(match = body.match(items[i])) {
|
||||
notifications[i] = parseInt(match[1], 10);
|
||||
}
|
||||
}
|
||||
|
||||
callback(null, notifications);
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.resetItemNotifications = function(callback) {
|
||||
this.request.get("https://steamcommunity.com/my/inventory", function(err, response, body) {
|
||||
if(!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(self._checkHttpError(err, response, callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype.loggedIn = function(callback) {
|
||||
this.request("https://steamcommunity.com/my", {"followRedirect": false}, function(err, response, body) {
|
||||
if(err || (response.statusCode != 302 && response.statusCode != 403)) {
|
||||
callback(err || new Error("HTTP error " + response.statusCode));
|
||||
return;
|
||||
}
|
||||
|
||||
if(response.statusCode == 403) {
|
||||
callback(null, true, true);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, !!response.headers.location.match(/steamcommunity\.com(\/(id|profiles)\/[^\/]+)\/?/), false);
|
||||
});
|
||||
};
|
||||
|
||||
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) {
|
||||
var self = this;
|
||||
this.request("https://steamcommunity.com/my", {"followRedirect": false}, function(err, response, body) {
|
||||
if(err || response.statusCode != 302) {
|
||||
callback(err || "HTTP error " + response.statusCode);
|
||||
return;
|
||||
}
|
||||
|
||||
var match = response.headers.location.match(/steamcommunity\.com(\/(id|profiles)\/[^\/]+)\/?/);
|
||||
if(!match) {
|
||||
callback("Can't get profile URL");
|
||||
return;
|
||||
}
|
||||
|
||||
(form ? self.request.post : self.request)("https://steamcommunity.com" + match[1] + "/" + endpoint, form ? {"form": form} : {}, callback);
|
||||
});
|
||||
};
|
||||
|
||||
SteamCommunity.prototype._checkHttpError = function(err, response, callback) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(response.statusCode != 200) {
|
||||
var error = new Error("HTTP error " + response.statusCode);
|
||||
error.code = response.statusCode;
|
||||
callback(error);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
require('./classes/CMarketItem.js');
|
||||
require('./classes/CMarketSearchResult.js');
|
||||
require('./classes/CSteamGroup.js');
|
||||
require('./classes/CSteamUser.js');
|
||||
require('./components/chat.js');
|
||||
require('./components/profile.js');
|
||||
|
||||
13
package.json
13
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "steamcommunity",
|
||||
"version": "0.1.0",
|
||||
"description": "Facilitates logins to the Steam Communtiy website",
|
||||
"version": "3.3.2",
|
||||
"description": "Provides an interface for logging into and interacting with the Steam Community website",
|
||||
"keywords": ["steam", "steam community"],
|
||||
"homepage": "https://github.com/DoctorMcKay/node-steamcommunity",
|
||||
"bugs": {
|
||||
@@ -10,10 +10,13 @@
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Doctor_McKay/node-steamcommunity.git"
|
||||
"url": "https://github.com/DoctorMcKay/node-steamcommunity.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"request": "2.44.x",
|
||||
"node-bignumber": "1.2.x"
|
||||
"request": "^2.58.0",
|
||||
"node-bignumber": "^1.2.1",
|
||||
"steamid": "^0.3.0",
|
||||
"xml2js": "^0.4.9",
|
||||
"cheerio": "^0.19.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user