Compare commits

...

17 Commits

Author SHA1 Message Date
Alexander Corn
193d77c3d1 1.0.0 2014-12-17 04:10:42 -05:00
Alexander Corn
6014ce1567 Updated readme 2014-12-17 04:09:47 -05:00
Alexander Corn
8e8ce2aa89 Added CSteamGroup.leave method 2014-12-17 03:07:59 -05:00
Alexander Corn
0cb5eef1f8 Added _myProfile helper to make calls to the user's profile URL 2014-12-17 03:07:49 -05:00
Alexander Corn
7f2a287c56 Added CSteamGroup.join method 2014-12-17 02:49:51 -05:00
Alexander Corn
7643d2efad Added CSteamGroup.kick method 2014-12-17 02:42:15 -05:00
Alexander Corn
d257108500 Added CSteamGroup.setPlayerOfTheWeek method 2014-12-17 02:39:53 -05:00
Alexander Corn
b0b8dbbabf Added scheduleEvent method 2014-12-17 02:29:58 -05:00
Alexander Corn
b1e31b32fe Moved checking for Steam Community errors to main SteamCommunity 2014-12-17 02:04:24 -05:00
Alexander Corn
0f16f11668 Added postAnnouncement method to CSteamGroup 2014-12-17 01:59:21 -05:00
Alexander Corn
e6789b1021 Added CSteamGroup 2014-12-17 01:48:17 -05:00
Alexander Corn
218d0dc7da Added xml2js dependency 2014-12-17 01:48:07 -05:00
Alexander Corn
5ca5bc30ac Use SteamID class for SteamIDs 2014-12-17 00:55:43 -05:00
Alexander Corn
7d1c641967 Added steamid dependency 2014-12-17 00:50:15 -05:00
Alexander Corn
90593b2dc0 Ignore test.js 2014-12-17 00:48:52 -05:00
Alexander Corn
3d3c899f9d Started shift to more versatile module 2014-12-17 00:48:19 -05:00
Alexander Corn
037ac1a9d7 Bumped required request version 2014-12-17 00:47:54 -05:00
5 changed files with 390 additions and 105 deletions

3
.gitignore vendored
View File

@@ -1 +1,2 @@
node_modules/*
node_modules/*
test.js

View File

@@ -1,6 +1,6 @@
# Steam Community for Node.js
simply # 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).

288
classes/CSteamGroup.js Normal file
View File

@@ -0,0 +1,288 @@
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(err || response.statusCode != 200) {
callback(err || "HTTP error " + response.statusCode);
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(err || response.statusCode != 200) {
callback(err || "HTTP error " + response.statusCode);
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 || "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 || "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 || "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 || "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 || "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(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 || "HTTP error " + response.statusCode);
return;
}
if(self._community._checkCommunityError(body, callback)) {
return;
}
callback(null);
});
};

139
index.js
View File

@@ -1,33 +1,24 @@
var Request = require('request');
var RSA = require('node-bignumber').Key;
var hex2b64 = require('node-bignumber').hex2b64;
var SteamID = require('steamid');
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._request = Request.defaults({"jar": this._jar});
}
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.steamID && details.sentry) {
this._jar.setCookie(Request.cookie('steamMachineAuth' + details.steamID.getSteamID64() + '=' + encodeURIComponent(details.sentry)), '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;
@@ -47,17 +38,18 @@ SteamCommunity.prototype.login = function(authCode, callback) {
var form = {
"captcha_text": "",
"captchagid": -1,
"emailauth": authCode || "",
"emailauth": details.authCode || "",
"emailsteamid": "",
"loginfriendlyname": "",
"password": hex2b64(key.encrypt(self._password)),
"password": hex2b64(key.encrypt(details.password)),
"remember_login": false,
"rsatimestamp": json.timestamp,
"twofactorcode": "",
"username": self._username
"username": details.accountName
};
request.post("https://steamcommunity.com/login/dologin/", {"form": form}, function(err, response, body) {
console.log(self._jar.getCookieString("https://steamcommunity.com"));
self._request.post("https://steamcommunity.com/login/dologin/", {"form": form}, function(err, response, body) {
if(err) {
callback(err);
return;
@@ -74,35 +66,86 @@ SteamCommunity.prototype.login = function(authCode, callback) {
if(!json.success) {
callback(json.message);
} 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(json.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 = {"steamID": self.steamID, "sentry": 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._checkCommunityError = function(html, callback) {
if(html.match(/<h1>Sorry!<\/h1>/)) {
var match = html.match(/<h3>(.+)<\/h3>/);
callback(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);
});
};
require('./classes/CSteamGroup.js');

View File

@@ -1,6 +1,6 @@
{
"name": "steamcommunity",
"version": "0.1.0",
"version": "1.0.0",
"description": "Facilitates logins to the Steam Communtiy website",
"keywords": ["steam", "steam community"],
"homepage": "https://github.com/DoctorMcKay/node-steamcommunity",
@@ -13,7 +13,9 @@
"url": "https://github.com/Doctor_McKay/node-steamcommunity.git"
},
"dependencies": {
"request": "2.44.x",
"node-bignumber": "1.2.x"
"request": "2.51.x",
"node-bignumber": "1.2.x",
"steamid": "0.1.x",
"xml2js": "0.4.x"
}
}