Compare commits

...

46 Commits

Author SHA1 Message Date
Alex Corn
e299623452 Use different filenames for different images, similar to how Steam does it 2019-09-25 05:33:14 -04:00
Alex Corn
29b31009ce Merge remote-tracking branch 'origin/master' 2019-09-25 05:30:14 -04:00
Alex Corn
d4d0d7da26 3.41.0 2019-09-24 04:07:34 -04:00
Alex Corn
3c8488d441 Added method sendImageToUser 2019-09-24 04:06:37 -04:00
Alex Corn
3ea0995415 3.40.2 2019-09-21 04:27:55 -04:00
Alex Corn
21c4ba3e27 Restore cache_expiration from game-specific data for backwards compatibility
(Fixes #229)
2019-09-21 04:27:39 -04:00
Alex Corn
4d4df7c2a5 3.40.1 2019-09-07 05:06:06 -04:00
Alex Corn
aa0d4d32b7 Removed stats-reporter 2019-09-07 05:05:46 -04:00
Alex Corn
444a6d238d Merge pull request #225 from Revadike/patch-1
Added userID guard
2019-06-17 03:18:06 -04:00
Revadike
98373708e5 Added userID guard
Because I got this:
```
 2019-06-12 | 01:22:30.151 | ERROR | crashBot                       | Fatal error: TypeError: Cannot read property 'getSteamID64' of null
    at get (node_modules\steamcommunity\components\users.js:416:60)
    at SteamCommunity.getUserInventoryContents (node_modules\steamcommunity\components\users.js:412:2)
    at unpackSteamBoosterPacks (index.js:3588:21)
    at cleanupSteamInventory (index.js:3583:5)
    at SteamUser.refreshSteamWebSession (index.js:857:38)
    at Object.onceWrapper (events.js:273:13)
    at SteamUser.emit (events.js:182:13)
    at SteamUser.gotSteamWebSession (index.js:1754:16)
    at SteamUser.emit (events.js:182:13)
    at _apiRequest (node_modules\steam-user\components\web.js:61:9)
    at IncomingMessage.<anonymous> (node_modules\steam-user\components\webapi.js:82:4)
    at IncomingMessage.emit (events.js:187:15)
    at endReadableNT (_stream_readable.js:1094:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
```
2019-06-17 02:43:07 +02:00
Alex Corn
0df2662053 3.40.0 2019-04-19 01:28:43 -04:00
Alex Corn
a46ed17415 Added clearPersonaNameHistory 2019-04-19 01:20:01 -04:00
Alex Corn
fbfff1398b Merge remote-tracking branch 'origin/master'
# Conflicts:
#	.idea/encodings.xml
2019-02-14 00:29:44 -05:00
Alex Corn
224b7b85e0 3.39.0 2019-02-13 17:59:41 -05:00
Alex Corn
22d34b1faf Added Steam ID to output of getClientLogonToken 2019-02-13 17:59:33 -05:00
Alex Corn
cfd932dc72 Changed output format of getClientLogonToken 2019-02-13 17:42:28 -05:00
Alex Corn
4710afa28b Added getClientLogonToken 2019-02-13 17:40:45 -05:00
Alex Corn
1180eb9d3f Deprecated webchat methods 2019-02-13 17:35:39 -05:00
Alex Corn
3ca85bedc2 Merge branch 'master' of ssh://github.com/DoctorMcKay/node-steamcommunity 2019-02-13 17:28:57 -05:00
Alex Corn
e05efabcb9 Merge pull request #211 from Hongarc/master
Add comment group
2019-02-12 21:35:58 -05:00
Alex Corn
6cd06c3adf Updated module type 2019-02-06 19:54:04 -05:00
Alex Corn
d35e3c107c Make sure CConfirmation.{id, creator} are always strings 2019-02-06 19:36:01 -05:00
Alex Corn
4e90811008 Merge pull request #213 from Royalgamer06/patch-2
Package 'fs' never used
2018-11-19 14:54:33 -05:00
Royalgamer06
018d3de5a2 Package 'fs' never used 2018-11-19 20:48:57 +01:00
Alex Corn
3949abe09f 3.38.0 2018-11-01 01:20:31 -04:00
Alex Corn
62394b9ffe Added ability to change friends list privacy 2018-11-01 01:20:19 -04:00
Alex Corn
ebac6c97ad Added IDE config to repo 2018-10-31 03:47:55 -04:00
Hongarc
a0ad33d5eb Add comment group 2018-10-20 13:29:52 +07:00
Alex Corn
b7a3e51bfc Merge pull request #205 from waylaidwanderer/master
Add the ability to set custom mobile user-agent
2018-07-11 02:31:04 -04:00
Joel
bf13224cbf Add the ability to set custom mobile user-agent 2018-07-10 23:30:12 -07:00
Alex Corn
117374a4c5 Updated Chrome user-agent 2018-07-11 02:22:39 -04:00
Alex Corn
aa84505132 3.37.1 2018-07-11 02:12:45 -04:00
Alex Corn
bb97565f2a Fixed steamID not being properly set 2018-07-11 02:12:37 -04:00
Alex Corn
7462e4b767 3.37.0 2018-07-11 00:00:16 -04:00
Alex Corn
adbf1d47a7 Added postProfileStatus and deleteProfileStatus (closes #200) 2018-07-10 23:59:57 -04:00
Alex Corn
8c4fde720a Updated EResult 2018-07-10 23:53:05 -04:00
Alex Corn
458d7b6db1 Renamed getProfileBackground to getUserProfileBackground and added it to CSteamUser 2018-07-10 23:28:26 -04:00
Alex Corn
411d74036f Updated getProfileBackground output a bit 2018-07-10 23:24:41 -04:00
Mert
1b3117b8dc Add getProfileBackground method
Adds ability to get URL of Steamcommunity profile background.
2018-07-10 23:18:03 -04:00
Alex Corn
6eec88d196 3.36.2 2018-05-18 17:32:48 -04:00
Alex Corn
3921ce17d0 Follow redirects when posting to own profile (fixes #178) 2018-05-18 17:32:33 -04:00
Alex Corn
4441d6f6e0 Bumped required request version 2018-05-18 17:29:14 -04:00
Alex Corn
870de6817e 3.36.1 2018-04-15 10:43:14 -04:00
Alex Corn
d5dbb230df Removed extra import 2018-04-15 10:43:05 -04:00
Alex Corn
5e9c06bdc4 3.36.0 2018-04-11 00:27:57 -04:00
Alex Corn
8d163d0d85 Added privacy controls for gameDetails and playtime 2018-04-11 00:27:10 -04:00
30 changed files with 741 additions and 112 deletions

52
.gitignore vendored
View File

@@ -1,3 +1,53 @@
node_modules/* node_modules/*
test.js test.js
.idea/
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
.idea/httpRequests/
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
cmake-build-release/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

1
.idea/.name generated Normal file
View File

@@ -0,0 +1 @@
node-steamcommunity

13
.idea/codeStyleSettings.xml generated Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
</value>
</option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
</component>
</project>

18
.idea/codeStyles/Project.xml generated Normal file
View File

@@ -0,0 +1,18 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
<codeStyleSettings language="JSON">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JavaScript">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
<option name="SMART_TABS" value="true" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
</state>
</component>

3
.idea/copyright/profiles_settings.xml generated Normal file
View File

@@ -0,0 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
</component>

6
.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

View File

@@ -0,0 +1,11 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="ES6ConvertRequireIntoImport" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="ES6ConvertToForOf" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="ES6ConvertVarToLetConst" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSEqualityComparisonWithCoercion" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSFunctionExpressionToArrowFunction" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="JSStringConcatenationToES6Template" enabled="false" level="INFORMATION" enabled_by_default="false" />
</profile>
</component>

6
.idea/jsLibraryMappings.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>

6
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/steamcommunity.iml" filepath="$PROJECT_DIR$/.idea/steamcommunity.iml" />
</modules>
</component>
</project>

8
.idea/node-steamcommunity.iml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

9
.idea/steamcommunity.iml generated Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

4
.idea/watcherTasks.xml generated Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions" suppressed-tasks="Babel" />
</project>

View File

@@ -9,8 +9,6 @@ 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.
This reports anonymous usage statistics to the author. [See here](https://github.com/DoctorMcKay/node-stats-reporter) for more information.
**Have a question about the module or coding in general? *Do not create a GitHub issue.* GitHub issues are for feature **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/). requests and bug reports. Instead, post in the [dedicated forum](https://dev.doctormckay.com/forum/8-node-steamcommunity/).
Such issues may be ignored!** Such issues may be ignored!**

View File

@@ -5,9 +5,9 @@ module.exports = CConfirmation;
function CConfirmation(community, data) { function CConfirmation(community, data) {
Object.defineProperty(this, "_community", {"value": community}); Object.defineProperty(this, "_community", {"value": community});
this.id = data.id; this.id = data.id.toString();
this.type = data.type; this.type = data.type;
this.creator = data.creator; this.creator = data.creator.toString();
this.key = data.key; this.key = data.key;
this.title = data.title; this.title = data.title;
this.receiving = data.receiving; this.receiving = data.receiving;

View File

@@ -66,6 +66,22 @@ function CEconItem(item, description, contextID) {
this.market_fee_app = parseInt(match[1], 10); this.market_fee_app = parseInt(match[1], 10);
} }
// Restore cache_expiration, if we can (for CS:GO items)
if (this.appid == 730 && this.contextid == 2 && this.owner_descriptions) {
let description = this.owner_descriptions.find(d => d.value && d.value.indexOf('Tradable After ') == 0);
if (description) {
let date = new Date(description.value.substring(15).replace(/[,()]/g, ''));
if (date) {
this.cache_expiration = date.toISOString();
}
}
}
// If we have item_expiration, also set cache_expiration to the same value
if (this.item_expiration) {
this.cache_expiration = this.item_expiration;
}
if (this.actions === "") { if (this.actions === "") {
this.actions = []; this.actions = [];
} }

View File

@@ -123,6 +123,10 @@ CSteamGroup.prototype.deleteComment = function(cid, callback) {
this._community.deleteGroupComment(this.steamID, cid, callback); this._community.deleteGroupComment(this.steamID, cid, callback);
}; };
CSteamGroup.prototype.comment = function(message, callback) {
this._community.postGroupComment(this.steamID, message, callback);
};
/** /**
* Get requests to join this restricted group. * Get requests to join this restricted group.
* @param {function} callback - First argument is null/Error, second is array of SteamID objects * @param {function} callback - First argument is null/Error, second is array of SteamID objects

View File

@@ -7,29 +7,29 @@ SteamCommunity.prototype.getSteamUser = function(id, callback) {
if(typeof id !== 'string' && !Helpers.isSteamID(id)) { 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");
} }
if(typeof id === 'object' && (id.universe != SteamID.Universe.PUBLIC || id.type != SteamID.Type.INDIVIDUAL)) { 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"); throw new Error("SteamID must stand for an individual account in the public universe");
} }
var self = this; var self = this;
this.httpRequest("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 (err) { if (err) {
callback(err); callback(err);
return; return;
} }
xml2js.parseString(body, function(err, result) { xml2js.parseString(body, function(err, result) {
if(err || (!result.response && !result.profile)) { if(err || (!result.response && !result.profile)) {
callback(err || new Error("No valid response")); callback(err || new Error("No valid response"));
return; return;
} }
if(result.response && result.response.error && result.response.error.length) { if(result.response && result.response.error && result.response.error.length) {
callback(new Error(result.response.error[0])); callback(new Error(result.response.error[0]));
return; return;
} }
// Try and find custom URL from redirect // Try and find custom URL from redirect
var customurl = null; var customurl = null;
if(response.request.redirects && response.request.redirects.length) { if(response.request.redirects && response.request.redirects.length) {
@@ -43,7 +43,7 @@ SteamCommunity.prototype.getSteamUser = function(id, callback) {
callback(new Error("No valid response")); callback(new Error("No valid response"));
return; return;
} }
callback(null, new CSteamUser(self, result.profile, customurl)); callback(null, new CSteamUser(self, result.profile, customurl));
}); });
}, "steamcommunity"); }, "steamcommunity");
@@ -51,7 +51,7 @@ SteamCommunity.prototype.getSteamUser = function(id, callback) {
function CSteamUser(community, userData, customurl) { function CSteamUser(community, userData, customurl) {
this._community = community; this._community = community;
this.steamID = new SteamID(userData.steamID64[0]); this.steamID = new SteamID(userData.steamID64[0]);
this.name = processItem('steamID'); this.name = processItem('steamID');
this.onlineState = processItem('onlineState'); this.onlineState = processItem('onlineState');
@@ -67,7 +67,7 @@ function CSteamUser(community, userData, customurl) {
this.tradeBanState = processItem('tradeBanState', 'None'); this.tradeBanState = processItem('tradeBanState', 'None');
this.isLimitedAccount = processItem('isLimitedAccount') == 1; this.isLimitedAccount = processItem('isLimitedAccount') == 1;
this.customURL = processItem('customURL', customurl); this.customURL = processItem('customURL', customurl);
if(this.visibilityState == 3) { if(this.visibilityState == 3) {
this.memberSince = new Date(processItem('memberSince', '0').replace(/(\d{1,2})(st|nd|th)/, "$1")); this.memberSince = new Date(processItem('memberSince', '0').replace(/(\d{1,2})(st|nd|th)/, "$1"));
this.location = processItem('location'); this.location = processItem('location');
@@ -79,19 +79,19 @@ function CSteamUser(community, userData, customurl) {
this.realName = null; this.realName = null;
this.summary = null; this.summary = null;
} }
// Maybe handle mostPlayedGames? // Maybe handle mostPlayedGames?
this.groups = null; this.groups = null;
this.primaryGroup = null; this.primaryGroup = null;
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 === "1") { if(group['$'] && group['$'].isPrimary === "1") {
self.primaryGroup = new SteamID(group.groupID64[0]); self.primaryGroup = new SteamID(group.groupID64[0]);
} }
return new SteamID(group.groupID64[0]); return new SteamID(group.groupID64[0]);
}); });
} }
@@ -110,7 +110,7 @@ CSteamUser.getAvatarURL = function(hash, size, protocol) {
protocol = protocol || 'http://'; protocol = protocol || 'http://';
hash = hash || "72f78b4c8cc1f62323f8a33f6d53e27db57c2252"; // The default "?" avatar hash = hash || "72f78b4c8cc1f62323f8a33f6d53e27db57c2252"; // The default "?" avatar
var url = protocol + "steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/" + hash.substring(0, 2) + "/" + hash; var url = protocol + "steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/" + hash.substring(0, 2) + "/" + hash;
if(size == 'full' || size == 'medium') { if(size == 'full' || size == 'medium') {
return url + "_" + size + ".jpg"; return url + "_" + size + ".jpg";
@@ -182,3 +182,21 @@ CSteamUser.prototype.getInventory = function(appID, contextID, tradableOnly, cal
CSteamUser.prototype.getInventoryContents = function(appID, contextID, tradableOnly, callback) { CSteamUser.prototype.getInventoryContents = function(appID, contextID, tradableOnly, callback) {
this._community.getUserInventoryContents(this.steamID, appID, contextID, tradableOnly, callback); this._community.getUserInventoryContents(this.steamID, appID, contextID, tradableOnly, callback);
}; };
/**
* Get the background URL of user's profile.
* @param {function} callback
*/
CSteamUser.prototype.getProfileBackground = function(callback) {
this._community.getUserProfileBackground(this.steamID, callback);
};
/**
* Upload an image to Steam and send it to the target user over chat.
* @param {Buffer} imageContentsBuffer - The image contents, as a Buffer
* @param {{spoiler?: boolean}} [options]
* @param {function} callback
*/
CSteamUser.prototype.sendImage = function(imageContentsBuffer, options, callback) {
this._community.sendImageToUser(this.steamID, imageContentsBuffer, options, callback);
};

View File

@@ -5,17 +5,22 @@ SteamCommunity.ChatState = require('../resources/EChatState.js');
SteamCommunity.PersonaState = require('../resources/EPersonaState.js'); SteamCommunity.PersonaState = require('../resources/EPersonaState.js');
SteamCommunity.PersonaStateFlag = require('../resources/EPersonaStateFlag.js'); SteamCommunity.PersonaStateFlag = require('../resources/EPersonaStateFlag.js');
/**
* @deprecated No support for new Steam chat. Use steam-user instead.
* @param {int} interval
* @param {string} uiMode
*/
SteamCommunity.prototype.chatLogon = function(interval, uiMode) { SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
if(this.chatState == SteamCommunity.ChatState.LoggingOn || this.chatState == SteamCommunity.ChatState.LoggedOn) { if(this.chatState == SteamCommunity.ChatState.LoggingOn || this.chatState == SteamCommunity.ChatState.LoggedOn) {
return; return;
} }
interval = interval || 500; interval = interval || 500;
uiMode = uiMode || "web"; uiMode = uiMode || "web";
this.emit('debug', 'Requesting chat WebAPI token'); this.emit('debug', 'Requesting chat WebAPI token');
this.chatState = SteamCommunity.ChatState.LoggingOn; this.chatState = SteamCommunity.ChatState.LoggingOn;
var self = this; var self = this;
this.getWebApiOauthToken(function(err, token) { this.getWebApiOauthToken(function(err, token) {
if(err) { if(err) {
@@ -32,7 +37,7 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
self.emit('debug', "Cannot get oauth token: " + err.message); self.emit('debug', "Cannot get oauth token: " + err.message);
return; return;
} }
self.httpRequestPost({ self.httpRequestPost({
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Logon/v1", "uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Logon/v1",
"form": { "form": {
@@ -48,7 +53,7 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
setTimeout(self.chatLogon.bind(self), 5000); setTimeout(self.chatLogon.bind(self), 5000);
return; return;
} }
if(body.error != 'OK') { if(body.error != 'OK') {
self.chatState = SteamCommunity.ChatState.LogOnFailed; self.chatState = SteamCommunity.ChatState.LogOnFailed;
self.emit('chatLogOnFailed', new Error(body.error), false); self.emit('chatLogOnFailed', new Error(body.error), false);
@@ -56,7 +61,7 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
setTimeout(self.chatLogon.bind(self), 5000); setTimeout(self.chatLogon.bind(self), 5000);
return; return;
} }
self._chat = { self._chat = {
"umqid": body.umqid, "umqid": body.umqid,
"message": body.message, "message": body.message,
@@ -64,9 +69,9 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
"interval": interval, "interval": interval,
"uiMode": uiMode "uiMode": uiMode
}; };
self.chatFriends = {}; self.chatFriends = {};
self.chatState = SteamCommunity.ChatState.LoggedOn; self.chatState = SteamCommunity.ChatState.LoggedOn;
self.emit('chatLoggedOn'); self.emit('chatLoggedOn');
self._chatPoll(); self._chatPoll();
@@ -74,20 +79,27 @@ SteamCommunity.prototype.chatLogon = function(interval, uiMode) {
}); });
}; };
/**
* @deprecated No support for new Steam chat. Use steam-user instead.
* @param {string|SteamID} recipient
* @param {string} text
* @param {string} [type]
* @param {function} [callback]
*/
SteamCommunity.prototype.chatMessage = function(recipient, text, type, callback) { SteamCommunity.prototype.chatMessage = function(recipient, text, type, callback) {
if(this.chatState != SteamCommunity.ChatState.LoggedOn) { if(this.chatState != SteamCommunity.ChatState.LoggedOn) {
throw new Error("Chat must be logged on before messages can be sent"); throw new Error("Chat must be logged on before messages can be sent");
} }
if(typeof recipient === 'string') { if(typeof recipient === 'string') {
recipient = new SteamID(recipient); recipient = new SteamID(recipient);
} }
if(typeof type === 'function') { if(typeof type === 'function') {
callback = type; callback = type;
type = 'saytext'; type = 'saytext';
} }
type = type || 'saytext'; type = type || 'saytext';
var self = this; var self = this;
@@ -105,12 +117,12 @@ SteamCommunity.prototype.chatMessage = function(recipient, text, type, callback)
if(!callback) { if(!callback) {
return; return;
} }
if (err) { if (err) {
callback(err); callback(err);
return; return;
} }
if(body.error != 'OK') { if(body.error != 'OK') {
callback(new Error(body.error)); callback(new Error(body.error));
} else { } else {
@@ -119,6 +131,9 @@ SteamCommunity.prototype.chatMessage = function(recipient, text, type, callback)
}, "steamcommunity"); }, "steamcommunity");
}; };
/**
* @deprecated No support for new Steam chat. Use steam-user instead.
*/
SteamCommunity.prototype.chatLogoff = function() { SteamCommunity.prototype.chatLogoff = function() {
var self = this; var self = this;
this.httpRequestPost({ this.httpRequestPost({
@@ -141,9 +156,12 @@ SteamCommunity.prototype.chatLogoff = function() {
}, "steamcommunity"); }, "steamcommunity");
}; };
/**
* @private
*/
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.httpRequestPost({ this.httpRequestPost({
"uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Poll/v1", "uri": "https://api.steampowered.com/ISteamWebUserPresenceOAuth/Poll/v1",
@@ -161,9 +179,9 @@ SteamCommunity.prototype._chatPoll = function() {
if (self.chatState == SteamCommunity.ChatState.Offline) { if (self.chatState == SteamCommunity.ChatState.Offline) {
return; return;
} }
self._chat.timer = setTimeout(self._chatPoll.bind(self), self._chat.interval); self._chat.timer = setTimeout(self._chatPoll.bind(self), self._chat.interval);
if(err || response.statusCode != 200) { if(err || response.statusCode != 200) {
self.emit('debug', 'Error in chat poll: ' + (err ? err.message : "HTTP error " + response.statusCode)); self.emit('debug', 'Error in chat poll: ' + (err ? err.message : "HTTP error " + response.statusCode));
if (err.message == "Not Logged On") { if (err.message == "Not Logged On") {
@@ -172,7 +190,7 @@ SteamCommunity.prototype._chatPoll = function() {
return; return;
} }
if(!body || body.error != 'OK') { if(!body || body.error != 'OK') {
self.emit('debug', 'Error in chat poll: ' + (body && body.error ? body.error : "Malformed response")); self.emit('debug', 'Error in chat poll: ' + (body && body.error ? body.error : "Malformed response"));
if (body && body.error && body.error == "Not Logged On") { if (body && body.error && body.error == "Not Logged On") {
@@ -181,29 +199,29 @@ SteamCommunity.prototype._chatPoll = function() {
return; return;
} }
self._chat.message = body.messagelast; self._chat.message = body.messagelast;
(body.messages || []).forEach(function(message) { (body.messages || []).forEach(function(message) {
var sender = new SteamID(); var sender = new SteamID();
sender.universe = SteamID.Universe.PUBLIC; sender.universe = SteamID.Universe.PUBLIC;
sender.type = SteamID.Type.INDIVIDUAL; sender.type = SteamID.Type.INDIVIDUAL;
sender.instance = SteamID.Instance.DESKTOP; sender.instance = SteamID.Instance.DESKTOP;
sender.accountid = message.accountid_from; sender.accountid = message.accountid_from;
switch(message.type) { switch(message.type) {
case 'personastate': case 'personastate':
self._chatUpdatePersona(sender); self._chatUpdatePersona(sender);
break; break;
case 'saytext': case 'saytext':
self.emit('chatMessage', sender, message.text); self.emit('chatMessage', sender, message.text);
break; break;
case 'typing': case 'typing':
self.emit('chatTyping', sender); self.emit('chatTyping', sender);
break; break;
default: default:
self.emit('debug', 'Unhandled chat message type: ' + message.type); self.emit('debug', 'Unhandled chat message type: ' + message.type);
} }
@@ -211,6 +229,9 @@ SteamCommunity.prototype._chatPoll = function() {
}, "steamcommunity"); }, "steamcommunity");
}; };
/**
* @private
*/
SteamCommunity.prototype._relogWebChat = function() { SteamCommunity.prototype._relogWebChat = function() {
this.emit('debug', "Relogging web chat"); this.emit('debug', "Relogging web chat");
clearTimeout(this._chat.timer); clearTimeout(this._chat.timer);
@@ -218,6 +239,10 @@ SteamCommunity.prototype._relogWebChat = function() {
this.chatLogon(this._chat.interval, this._chat.uiMode); this.chatLogon(this._chat.interval, this._chat.uiMode);
}; };
/**
* @param {SteamID} steamID
* @private
*/
SteamCommunity.prototype._chatUpdatePersona = function(steamID) { SteamCommunity.prototype._chatUpdatePersona = function(steamID) {
if (!this.chatFriends || this.chatState == SteamCommunity.ChatState.Offline) { if (!this.chatFriends || this.chatState == SteamCommunity.ChatState.Offline) {
return; // we no longer care return; // we no longer care
@@ -240,7 +265,7 @@ SteamCommunity.prototype._chatUpdatePersona = function(steamID) {
}, 2000); }, 2000);
return; return;
} }
var persona = { var persona = {
"steamID": steamID, "steamID": steamID,
"personaName": body.m_strName, "personaName": body.m_strName,
@@ -255,4 +280,4 @@ 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"); }, "steamcommunity");
}; };

View File

@@ -591,6 +591,30 @@ SteamCommunity.prototype.deleteGroupComment = function(gid, cid, callback) {
}, "steamcommunity"); }, "steamcommunity");
}; };
SteamCommunity.prototype.postGroupComment = function(gid, message, callback) {
if (typeof gid === 'string') {
gid = new SteamID(gid);
}
var options = {
"uri": "https://steamcommunity.com/comment/Clan/post/" + gid.getSteamID64() + "/-1/",
"form": {
"comment": message,
"count": 6,
"sessionid": this.getSessionID()
}
};
var self = this;
this.httpRequestPost(options, function(err, response, body) {
if(!callback) {
return;
}
callback(err || null);
}, "steamcommunity");
};
/** /**
* Get requests to join a restricted group. * Get requests to join a restricted group.
* @param {SteamID|string} gid - The SteamID of the group you want to manage * @param {SteamID|string} gid - The SteamID of the group you want to manage

View File

@@ -1,3 +1,5 @@
const EResult = require('../resources/EResult.js');
exports.isSteamID = function(input) { exports.isSteamID = function(input) {
var keys = Object.keys(input); var keys = Object.keys(input);
if (keys.length != 4) { if (keys.length != 4) {
@@ -36,3 +38,19 @@ exports.decodeSteamTime = function(time) {
return date; return date;
}; };
/**
* Get an Error object for a particular EResult
* @param {int} eresult
* @returns {null|Error}
*/
exports.eresultError = function(eresult) {
if (eresult == EResult.OK) {
// no error
return null;
}
var err = new Error(EResult[eresult] || ("Error " + eresult));
err.eresult = eresult;
return err;
};

View File

@@ -1,7 +1,9 @@
var SteamCommunity = require('../index.js'); const Cheerio = require('cheerio');
var SteamID = require('steamid'); const FS = require('fs');
var Cheerio = require('cheerio'); const SteamID = require('steamid');
var fs = require('fs');
const Helpers = require('./helpers.js');
const SteamCommunity = require('../index.js');
SteamCommunity.PrivacyState = { SteamCommunity.PrivacyState = {
"Private": 1, "Private": 1,
@@ -10,9 +12,9 @@ SteamCommunity.PrivacyState = {
}; };
var CommentPrivacyState = { var CommentPrivacyState = {
"1": "commentselfonly", "1": 2, // private
"2": "commentfriendsonly", "2": 0, // friends only
"3": "commentanyone" "3": 1 // anyone
}; };
SteamCommunity.prototype.setupProfile = function(callback) { SteamCommunity.prototype.setupProfile = function(callback) {
@@ -148,10 +150,9 @@ SteamCommunity.prototype.editProfile = function(settings, callback) {
}; };
SteamCommunity.prototype.profileSettings = function(settings, callback) { SteamCommunity.prototype.profileSettings = function(settings, callback) {
var self = this; this._myProfile("edit/settings", null, (err, response, body) => {
this._myProfile("edit/settings", null, function(err, response, body) { if (err || response.statusCode != 200) {
if(err || response.statusCode != 200) { if (callback) {
if(callback) {
callback(err || new Error("HTTP error " + response.statusCode)); callback(err || new Error("HTTP error " + response.statusCode));
} }
@@ -159,8 +160,8 @@ SteamCommunity.prototype.profileSettings = function(settings, callback) {
} }
var $ = Cheerio.load(body); var $ = Cheerio.load(body);
var form = $('#editForm'); var existingSettings = $('.ProfileReactRoot[data-privacysettings]').data('privacysettings');
if(!form) { if (!existingSettings) {
if(callback) { if(callback) {
callback(new Error("Malformed response")); callback(new Error("Malformed response"));
} }
@@ -168,46 +169,75 @@ SteamCommunity.prototype.profileSettings = function(settings, callback) {
return; return;
} }
var values = {}; // PrivacySettings => {PrivacyProfile, PrivacyInventory, PrivacyInventoryGifts, PrivacyOwnedGames, PrivacyPlaytime}
form.serializeArray().forEach(function(item) { // eCommentPermission
values[item.name] = item.value; var privacy = existingSettings.PrivacySettings;
}); var commentPermission = existingSettings.eCommentPermission;
for(var i in settings) { for (var i in settings) {
if(!settings.hasOwnProperty(i)) { if (!settings.hasOwnProperty(i)) {
continue; continue;
} }
switch(i) { switch (i) {
case 'profile': case 'profile':
values.privacySetting = settings[i]; privacy.PrivacyProfile = settings[i];
break; break;
case 'comments': case 'comments':
values.commentSetting = CommentPrivacyState[settings[i]]; commentPermission = CommentPrivacyState[settings[i]];
break; break;
case 'inventory': case 'inventory':
values.inventoryPrivacySetting = settings[i]; privacy.PrivacyInventory = settings[i];
break; break;
case 'inventoryGifts': case 'inventoryGifts':
values.inventoryGiftPrivacy = settings[i] ? 1 : 0; privacy.PrivacyInventoryGifts = settings[i] ? SteamCommunity.PrivacyState.Private : SteamCommunity.PrivacyState.Public;
break;
case 'gameDetails':
privacy.PrivacyOwnedGames = settings[i];
break;
case 'playtime':
privacy.PrivacyPlaytime = settings[i] ? SteamCommunity.PrivacyState.Private : SteamCommunity.PrivacyState.Public;
break;
case 'friendsList':
privacy.PrivacyFriendsList = settings[i];
break; break;
} }
} }
self._myProfile("edit/settings", values, function(err, response, body) { this._myProfile({
if(err || response.statusCode != 200) { "method": "POST",
if(callback) { "endpoint": "ajaxsetprivacy/",
"json": true,
"formData": { // it's multipart because lolvalve
"sessionid": this.getSessionID(),
"Privacy": JSON.stringify(privacy),
"eCommentPermission": commentPermission
}
}, null, function(err, response, body) {
if (err || response.statusCode != 200) {
if (callback) {
callback(err || new Error("HTTP error " + response.statusCode)); callback(err || new Error("HTTP error " + response.statusCode));
} }
return; return;
} }
if(callback) { if (body.success != 1) {
callback(null); if (callback) {
callback(new Error(body.success ? "Error " + body.success : "Request was not successful"));
}
return;
}
if (callback) {
callback(null, body.Privacy);
} }
}); });
}); });
@@ -256,7 +286,7 @@ SteamCommunity.prototype.uploadAvatar = function(image, format, callback) {
} }
} }
fs.readFile(image, function(err, file) { FS.readFile(image, function(err, file) {
if(err) { if(err) {
if(callback) { if(callback) {
callback(err); callback(err);
@@ -367,3 +397,68 @@ SteamCommunity.prototype.uploadAvatar = function(image, format, callback) {
}, "steamcommunity"); }, "steamcommunity");
} }
}; };
/**
* Post a new status to your profile activity feed.
* @param {string} statusText - The text of this status update
* @param {{appID: int}} [options] - Options for this status update. All are optional. If you don't pass any options, this can be omitted.
* @param {function} callback - err, postID
*/
SteamCommunity.prototype.postProfileStatus = function(statusText, options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
this._myProfile("ajaxpostuserstatus/", {
"appid": options.appID || 0,
"sessionid": this.getSessionID(),
"status_text": statusText
}, (err, res, body) => {
try {
body = JSON.parse(body);
if (body.message) {
callback(new Error(body.message));
return;
}
var match = body.blotter_html.match(/id="userstatus_(\d+)_/);
if (!match) {
callback(new Error("Malformed response"));
return;
}
callback(null, parseInt(match[1], 10));
} catch (ex) {
callback(ex);
}
});
};
/**
* Delete a previously-posted profile status update.
* @param {int} postID
* @param {function} [callback]
*/
SteamCommunity.prototype.deleteProfileStatus = function(postID, callback) {
this._myProfile("ajaxdeleteuserstatus/", {
"sessionid": this.getSessionID(),
"postid": postID
}, (err, res, body) => {
if (!callback) {
return;
}
try {
body = JSON.parse(body);
if (!body.success) {
callback(new Error("Malformed response"));
return;
}
callback(Helpers.eresultError(body.success));
} catch (ex) {
callback(ex);
}
});
};

View File

@@ -1,7 +1,12 @@
var SteamCommunity = require('../index.js'); const Cheerio = require('cheerio');
var SteamID = require('steamid'); const Crypto = require('crypto');
var CEconItem = require('../classes/CEconItem.js'); const imageSize = require('image-size');
var Helpers = require('./helpers.js'); const SteamID = require('steamid');
const SteamCommunity = require('../index.js');
const CEconItem = require('../classes/CEconItem.js');
const Helpers = require('./helpers.js');
SteamCommunity.prototype.addFriend = function(userID, callback) { SteamCommunity.prototype.addFriend = function(userID, callback) {
if(typeof userID === 'string') { if(typeof userID === 'string') {
@@ -217,6 +222,45 @@ SteamCommunity.prototype.getUserAliases = function(userID, callback) {
}, "steamcommunity"); }, "steamcommunity");
}; };
/**
* Get the background URL of user's profile.
* @param {SteamID|string} userID - The user's SteamID as a SteamID object or a string which can parse into one
* @param {function} callback
*/
SteamCommunity.prototype.getUserProfileBackground = function(userID, callback) {
if (typeof userID === 'string') {
userID = new SteamID(userID);
}
this.httpRequest("https://steamcommunity.com/profiles/" + userID.getSteamID64(), (err, response, body) => {
if (err) {
callback(err);
return;
}
var $ = Cheerio.load(body);
var $privateProfileInfo = $('.profile_private_info');
if ($privateProfileInfo.length > 0) {
callback(new Error($privateProfileInfo.text().trim()));
return;
}
if ($('body').hasClass('has_profile_background')) {
var backgroundUrl = $('div.profile_background_image_content').css('background-image');
var matcher = backgroundUrl.match(/\(([^)]+)\)/);
if (matcher.length != 2 || !matcher[1].length) {
callback(new Error("Malformed response"));
} else {
callback(null, matcher[1]);
}
} else {
callback(null, null);
}
}, "steamcommunity");
};
SteamCommunity.prototype.getUserInventoryContexts = function(userID, callback) { SteamCommunity.prototype.getUserInventoryContexts = function(userID, callback) {
if (typeof userID === 'string') { if (typeof userID === 'string') {
userID = new SteamID(userID); userID = new SteamID(userID);
@@ -355,17 +399,22 @@ SteamCommunity.prototype.getUserInventory = function(userID, appID, contextID, t
* @param {function} callback * @param {function} callback
*/ */
SteamCommunity.prototype.getUserInventoryContents = function(userID, appID, contextID, tradableOnly, language, callback) { SteamCommunity.prototype.getUserInventoryContents = function(userID, appID, contextID, tradableOnly, language, callback) {
if (typeof language === 'function') {
callback = language;
language = "english";
}
if (!userID) {
callback(new Error("The user's SteamID is invalid or missing."));
return;
}
var self = this; var self = this;
if (typeof userID === 'string') { if (typeof userID === 'string') {
userID = new SteamID(userID); userID = new SteamID(userID);
} }
if (typeof language === 'function') {
callback = language;
language = "english";
}
var pos = 1; var pos = 1;
get([], []); get([], []);
@@ -389,7 +438,7 @@ SteamCommunity.prototype.getUserInventoryContents = function(userID, appID, cont
// We can never get private profile error for our own inventory! // We can never get private profile error for our own inventory!
self._notifySessionExpired(err); self._notifySessionExpired(err);
} }
callback(new Error("This profile is private.")); callback(new Error("This profile is private."));
return; return;
} }
@@ -423,13 +472,13 @@ SteamCommunity.prototype.getUserInventoryContents = function(userID, appID, cont
} else { } else {
callback(new Error("Malformed response")); callback(new Error("Malformed response"));
} }
return; return;
} }
for (var i = 0; i < body.assets.length; i++) { for (var i = 0; i < body.assets.length; i++) {
var description = getDescription(body.descriptions, body.assets[i].classid, body.assets[i].instanceid); var description = getDescription(body.descriptions, body.assets[i].classid, body.assets[i].instanceid);
if (!tradableOnly || (description && description.tradable)) { if (!tradableOnly || (description && description.tradable)) {
body.assets[i].pos = pos++; body.assets[i].pos = pos++;
(body.assets[i].currencyid ? currency : inventory).push(new CEconItem(body.assets[i], description, contextID)); (body.assets[i].currencyid ? currency : inventory).push(new CEconItem(body.assets[i], description, contextID));
@@ -457,7 +506,162 @@ SteamCommunity.prototype.getUserInventoryContents = function(userID, appID, cont
for (var i = 0; i < descriptions.length; i++) { for (var i = 0; i < descriptions.length; i++) {
quickDescriptionLookup[descriptions[i].classid + '_' + (descriptions[i].instanceid || '0')] = descriptions[i]; quickDescriptionLookup[descriptions[i].classid + '_' + (descriptions[i].instanceid || '0')] = descriptions[i];
} }
return quickDescriptionLookup[key]; return quickDescriptionLookup[key];
} }
}; };
/**
* Upload an image to Steam and send it to another user over Steam chat.
* @param {SteamID|string} userID - Either a SteamID object or a string that can parse into one
* @param {Buffer} imageContentsBuffer - The image contents, as a Buffer
* @param {{spoiler?: boolean}} [options]
* @param {function} callback
*/
SteamCommunity.prototype.sendImageToUser = function(userID, imageContentsBuffer, options, callback) {
if (typeof options == 'function') {
callback = options;
options = {};
}
options = options || {};
if (!userID) {
callback(new Error('The user\'s SteamID is invalid or missing'));
return;
}
if (typeof userID == 'string') {
userID = new SteamID(userID);
}
if (!Buffer.isBuffer(imageContentsBuffer)) {
callback(new Error('The image contents must be a Buffer containing an image'));
return;
}
var imageDetails = null;
try {
imageDetails = imageSize(imageContentsBuffer);
} catch (ex) {
callback(ex);
return;
}
var imageHash = Crypto.createHash('sha1');
imageHash.update(imageContentsBuffer);
imageHash = imageHash.digest('hex');
var filename = Date.now() + '_image.' + imageDetails.type;
this.httpRequestPost({
uri: 'https://steamcommunity.com/chat/beginfileupload/?l=english',
headers: {
referer: 'https://steamcommunity.com/chat/'
},
formData: { // it's multipart
sessionid: this.getSessionID(),
l: 'english',
file_size: imageContentsBuffer.length,
file_name: filename,
file_sha: imageHash,
file_image_width: imageDetails.width,
file_image_height: imageDetails.height,
file_type: 'image/' + (imageDetails.type == 'jpg' ? 'jpeg' : imageDetails.type)
},
json: true
}, (err, res, body) => {
if (err) {
if (body && body.success) {
var err2 = Helpers.eresultError(body.success);
if (body.message) {
err2.message = body.message;
}
callback(err2);
} else {
callback(err);
}
return;
}
if (body.success != 1) {
callback(Helpers.eresultError(body.success));
return;
}
var hmac = body.hmac;
var timestamp = body.timestamp;
var startResult = body.result;
if (!startResult || !startResult.ugcid || !startResult.url_host || !startResult.request_headers) {
callback(new Error('Malformed response'));
return;
}
// Okay, now we need to PUT the file to the provided URL
var uploadUrl = (startResult.use_https ? 'https' : 'http') + '://' + startResult.url_host + startResult.url_path;
var headers = {};
startResult.request_headers.forEach((header) => {
headers[header.name.toLowerCase()] = header.value;
});
this.httpRequest({
uri: uploadUrl,
method: 'PUT',
headers,
body: imageContentsBuffer
}, (err, res, body) => {
if (err) {
callback(err);
return;
}
// Now we need to commit the upload
this.httpRequestPost({
uri: 'https://steamcommunity.com/chat/commitfileupload/',
headers: {
referer: 'https://steamcommunity.com/chat/'
},
formData: { // it's multipart again
sessionid: this.getSessionID(),
l: 'english',
file_name: filename,
file_sha: imageHash,
success: '1',
ugcid: startResult.ugcid,
file_type: 'image/' + (imageDetails.type == 'jpg' ? 'jpeg' : imageDetails.type),
file_image_width: imageDetails.width,
file_image_height: imageDetails.height,
timestamp,
hmac,
friend_steamid: userID.getSteamID64(),
spoiler: options.spoiler ? '1' : '0'
},
json: true
}, (err, res, body) => {
if (err) {
callback(err);
return;
}
if (body.success != 1) {
callback(Helpers.eresultError(body.success));
return;
}
if (body.result.success != 1) {
// lol valve
callback(Helpers.eresultError(body.result.success));
return;
}
if (!body.result.details || !body.result.details.url) {
callback(new Error('Malformed response'));
return;
}
callback(null, body.result.details.url);
}, 'steamcommunity');
}, 'steamcommunity');
}, 'steamcommunity');
};

View File

@@ -14,7 +14,7 @@ SteamCommunity.prototype.getWebApiKey = function(domain, callback) {
if(body.match(/<h2>Access Denied<\/h2>/)) { if(body.match(/<h2>Access Denied<\/h2>/)) {
return callback(new Error("Access Denied")); return callback(new Error("Access Denied"));
} }
if(body.match(/You must have a validated email address to create a Steam Web API key./)) { if(body.match(/You must have a validated email address to create a Steam Web API key./)) {
return callback(new Error("You must have a validated email address to create a Steam Web API key.")); return callback(new Error("You must have a validated email address to create a Steam Web API key."));
} }
@@ -44,6 +44,10 @@ SteamCommunity.prototype.getWebApiKey = function(domain, callback) {
}, "steamcommunity"); }, "steamcommunity");
}; };
/**
* @deprecated No longer works if not logged in via mobile login. Will be removed in a future release.
* @param {function} callback
*/
SteamCommunity.prototype.getWebApiOauthToken = function(callback) { SteamCommunity.prototype.getWebApiOauthToken = function(callback) {
var self = this; var self = this;

View File

@@ -1,6 +1,5 @@
var SteamCommunity = require('../index.js'); var SteamCommunity = require('../index.js');
var ReadLine = require('readline'); var ReadLine = require('readline');
var fs = require('fs');
var community = new SteamCommunity(); var community = new SteamCommunity();
var rl = ReadLine.createInterface({ var rl = ReadLine.createInterface({

View File

@@ -1,11 +1,11 @@
require('@doctormckay/stats-reporter').setup(require('./package.json')); const hex2b64 = require('node-bignumber').hex2b64;
const Request = require('request');
const RSA = require('node-bignumber').Key;
const SteamID = require('steamid');
var Request = require('request'); const Helpers = require('./components/helpers.js');
var RSA = require('node-bignumber').Key;
var hex2b64 = require('node-bignumber').hex2b64;
var SteamID = require('steamid');
const USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"; const USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36";
require('util').inherits(SteamCommunity, require('events').EventEmitter); require('util').inherits(SteamCommunity, require('events').EventEmitter);
@@ -13,7 +13,7 @@ module.exports = SteamCommunity;
SteamCommunity.SteamID = SteamID; SteamCommunity.SteamID = SteamID;
SteamCommunity.ConfirmationType = require('./resources/EConfirmationType.js'); SteamCommunity.ConfirmationType = require('./resources/EConfirmationType.js');
SteamCommunity.EResult = require('./resources/EResult.js') SteamCommunity.EResult = require('./resources/EResult.js');
function SteamCommunity(options) { function SteamCommunity(options) {
@@ -77,7 +77,7 @@ SteamCommunity.prototype.login = function(details, callback) {
mobileHeaders = { mobileHeaders = {
"X-Requested-With": "com.valvesoftware.android.steam.community", "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", "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", "User-Agent": this._options.mobileUserAgent || details.mobileUserAgent || "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, */*" "Accept": "text/javascript, text/html, application/xml, text/xml, */*"
}; };
@@ -249,6 +249,40 @@ SteamCommunity.prototype.oAuthLogin = function(steamguard, token, callback) {
}, "steamcommunity"); }, "steamcommunity");
}; };
/**
* Get a token that can be used to log onto Steam using steam-user.
* @param {function} callback
*/
SteamCommunity.prototype.getClientLogonToken = function(callback) {
this.httpRequestGet({
"uri": "https://steamcommunity.com/chat/clientjstoken",
"json": true
}, (err, res, body) => {
if (err || res.statusCode != 200) {
callback(err ? err : new Error('HTTP error ' + res.statusCode));
return;
}
if (!body.logged_in) {
let e = new Error('Not Logged In');
callback(e);
this._notifySessionExpired(e);
return;
}
if (!body.steamid || !body.account_name || !body.token) {
callback(new Error('Malformed response'));
return;
}
callback(null, {
"steamID": new SteamID(body.steamid),
"accountName": body.account_name,
"webLogonToken": body.token
});
});
};
SteamCommunity.prototype._setCookie = function(cookie, secure) { SteamCommunity.prototype._setCookie = function(cookie, secure) {
var protocol = secure ? "https" : "http"; var protocol = secure ? "https" : "http";
cookie.secure = !!secure; cookie.secure = !!secure;
@@ -259,14 +293,13 @@ SteamCommunity.prototype._setCookie = function(cookie, secure) {
}; };
SteamCommunity.prototype.setCookies = function(cookies) { SteamCommunity.prototype.setCookies = function(cookies) {
var self = this; cookies.forEach((cookie) => {
cookies.forEach(function(cookie) {
var cookieName = cookie.match(/(.+)=/)[1]; var cookieName = cookie.match(/(.+)=/)[1];
if(cookieName == 'steamLogin') { if (cookieName == 'steamLogin' || cookieName == 'steamLoginSecure') {
self.steamID = new SteamID(cookie.match(/=(\d+)/)[1]); this.steamID = new SteamID(cookie.match(/=(\d+)/)[1]);
} }
self._setCookie(Request.cookie(cookie), !!(cookieName.match(/^steamMachineAuth/) || cookieName.match(/Secure$/))); this._setCookie(Request.cookie(cookie), !!(cookieName.match(/^steamMachineAuth/) || cookieName.match(/Secure$/)));
}); });
}; };
@@ -398,7 +431,7 @@ SteamCommunity.prototype.loggedIn = function(callback) {
}; };
SteamCommunity.prototype.getTradeURL = function(callback) { SteamCommunity.prototype.getTradeURL = function(callback) {
this._myProfile("/tradeoffers/privacy", null, (err, response, body) => { this._myProfile("tradeoffers/privacy", null, (err, response, body) => {
if (err) { if (err) {
callback(err); callback(err);
return; return;
@@ -415,7 +448,7 @@ SteamCommunity.prototype.getTradeURL = function(callback) {
}; };
SteamCommunity.prototype.changeTradeURL = function(callback) { SteamCommunity.prototype.changeTradeURL = function(callback) {
this._myProfile("/tradeoffers/newtradeurl", {"sessionid": this.getSessionID()}, (err, response, body) => { this._myProfile("tradeoffers/newtradeurl", {"sessionid": this.getSessionID()}, (err, response, body) => {
if (!callback) { if (!callback) {
return; return;
} }
@@ -430,6 +463,33 @@ SteamCommunity.prototype.changeTradeURL = function(callback) {
}, "steamcommunity"); }, "steamcommunity");
}; };
/**
* Clear your profile name (alias) history.
* @param {function} callback
*/
SteamCommunity.prototype.clearPersonaNameHistory = function(callback) {
this._myProfile("ajaxclearaliashistory/", {"sessionid": this.getSessionID()}, (err, res, body) => {
if (!callback) {
return;
}
if (err) {
return callback(err);
}
if (res.statusCode != 200) {
return callback(new Error("HTTP error " + res.statusCode));
}
try {
body = JSON.parse(body);
callback(Helpers.eresultError(body.success));
} catch (ex) {
return callback(new Error("Malformed response"));
}
});
};
SteamCommunity.prototype._myProfile = function(endpoint, form, callback) { SteamCommunity.prototype._myProfile = function(endpoint, form, callback) {
var self = this; var self = this;
@@ -460,11 +520,13 @@ SteamCommunity.prototype._myProfile = function(endpoint, form, callback) {
function completeRequest(url) { function completeRequest(url) {
var options = endpoint.endpoint ? endpoint : {}; var options = endpoint.endpoint ? endpoint : {};
options.uri = "https://steamcommunity.com" + url + "/" + (endpoint.endpoint || endpoint); options.uri = "https://steamcommunity.com" + url + "/" + (endpoint.endpoint || endpoint);
options.method = "GET";
if (form) { if (form) {
options.method = "POST"; options.method = "POST";
options.form = form; options.form = form;
options.followAllRedirects = true;
} else if (!options.method) {
options.method = "GET";
} }
self.httpRequest(options, callback, "steamcommunity"); self.httpRequest(options, callback, "steamcommunity");

View File

@@ -1,6 +1,6 @@
{ {
"name": "steamcommunity", "name": "steamcommunity",
"version": "3.35.2", "version": "3.41.0",
"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": [ "keywords": [
"steam", "steam",
@@ -21,14 +21,14 @@
"url": "https://github.com/DoctorMcKay/node-steamcommunity.git" "url": "https://github.com/DoctorMcKay/node-steamcommunity.git"
}, },
"dependencies": { "dependencies": {
"@doctormckay/stats-reporter": "^1.0.2", "async": "^2.6.3",
"request": "^2.81.0",
"node-bignumber": "^1.2.1",
"steamid": "^1.0.0",
"xml2js": "^0.4.11",
"cheerio": "0.22.0", "cheerio": "0.22.0",
"async": "^2.1.4", "image-size": "^0.8.2",
"steam-totp": "^1.3.0" "node-bignumber": "^1.2.1",
"request": "^2.88.0",
"steam-totp": "^1.5.0",
"steamid": "^1.1.3",
"xml2js": "^0.4.22"
}, },
"engines": { "engines": {
"node": ">=4.0.0" "node": ">=4.0.0"

View File

@@ -119,6 +119,10 @@ module.exports = {
"GSLTExpired": 106, "GSLTExpired": 106,
"InsufficientFunds": 107, "InsufficientFunds": 107,
"TooManyPending": 108, "TooManyPending": 108,
"NoSiteLicensesFound": 109,
"WGNetworkSendExceeded": 110,
"AccountNotFriends": 111,
"LimitedUserAccount": 112,
// Value-to-name mapping for convenience // Value-to-name mapping for convenience
"0": "Invalid", "0": "Invalid",
@@ -229,4 +233,8 @@ module.exports = {
"106": "GSLTExpired", "106": "GSLTExpired",
"107": "InsufficientFunds", "107": "InsufficientFunds",
"108": "TooManyPending", "108": "TooManyPending",
"109": "NoSiteLicensesFound",
"110": "WGNetworkSendExceeded",
"111": "AccountNotFriends",
"112": "LimitedUserAccount",
}; };