From a46ed1741505a2ffe02ca212bc0bdc8ac8136e36 Mon Sep 17 00:00:00 2001 From: Alex Corn Date: Fri, 19 Apr 2019 01:20:01 -0400 Subject: [PATCH 1/9] Added clearPersonaNameHistory --- index.js | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index df80436..ea7a441 100644 --- a/index.js +++ b/index.js @@ -5,6 +5,8 @@ const Request = require('request'); const RSA = require('node-bignumber').Key; const SteamID = require('steamid'); +const Helpers = require('./components/helpers.js'); + 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); @@ -431,7 +433,7 @@ SteamCommunity.prototype.loggedIn = 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) { callback(err); return; @@ -448,7 +450,7 @@ SteamCommunity.prototype.getTradeURL = 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) { return; } @@ -463,6 +465,33 @@ SteamCommunity.prototype.changeTradeURL = function(callback) { }, "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) { var self = this; From 0df26620531b7d6981d3612260ea4f04dd721da9 Mon Sep 17 00:00:00 2001 From: Alex Corn Date: Fri, 19 Apr 2019 01:28:43 -0400 Subject: [PATCH 2/9] 3.40.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8c12c1b..7dfb401 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "steamcommunity", - "version": "3.39.0", + "version": "3.40.0", "description": "Provides an interface for logging into and interacting with the Steam Community website", "keywords": [ "steam", From 98373708e52629b172b1ad540f89e705d5c72f66 Mon Sep 17 00:00:00 2001 From: Revadike Date: Mon, 17 Jun 2019 02:43:07 +0200 Subject: [PATCH 3/9] 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. (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) ``` --- components/users.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/users.js b/components/users.js index 946ecd7..68cf70d 100644 --- a/components/users.js +++ b/components/users.js @@ -397,6 +397,11 @@ SteamCommunity.prototype.getUserInventory = function(userID, appID, contextID, t * @param {function} callback */ SteamCommunity.prototype.getUserInventoryContents = function(userID, appID, contextID, tradableOnly, language, callback) { + if (!userID) { + callback(new Error("The user's SteamID is invalid or missing.")); + return; + } + var self = this; if (typeof userID === 'string') { From aa0d4d32b7c87244d8416323feb7ac12c774718f Mon Sep 17 00:00:00 2001 From: Alex Corn Date: Sat, 7 Sep 2019 05:05:46 -0400 Subject: [PATCH 4/9] Removed stats-reporter --- README.md | 2 -- index.js | 2 -- package.json | 1 - 3 files changed, 5 deletions(-) diff --git a/README.md b/README.md index 175a289..a569dc6 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,6 @@ This module provides an easy interface for the Steam Community website. This mod 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 requests and bug reports. Instead, post in the [dedicated forum](https://dev.doctormckay.com/forum/8-node-steamcommunity/). Such issues may be ignored!** diff --git a/index.js b/index.js index ea7a441..2f8a24a 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,3 @@ -require('@doctormckay/stats-reporter').setup(require('./package.json')); - const hex2b64 = require('node-bignumber').hex2b64; const Request = require('request'); const RSA = require('node-bignumber').Key; diff --git a/package.json b/package.json index 7dfb401..cbe601c 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ "url": "https://github.com/DoctorMcKay/node-steamcommunity.git" }, "dependencies": { - "@doctormckay/stats-reporter": "^1.0.2", "request": "^2.86.0", "node-bignumber": "^1.2.1", "steamid": "^1.0.0", From 4d4df7c2a5ebbb94afce4558404f4e22b9ecc67f Mon Sep 17 00:00:00 2001 From: Alex Corn Date: Sat, 7 Sep 2019 05:06:06 -0400 Subject: [PATCH 5/9] 3.40.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cbe601c..42eb97e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "steamcommunity", - "version": "3.40.0", + "version": "3.40.1", "description": "Provides an interface for logging into and interacting with the Steam Community website", "keywords": [ "steam", From 21c4ba3e27361a9f08a7421755c5ddf947e72e4d Mon Sep 17 00:00:00 2001 From: Alex Corn Date: Sat, 21 Sep 2019 04:27:39 -0400 Subject: [PATCH 6/9] Restore cache_expiration from game-specific data for backwards compatibility (Fixes #229) --- classes/CEconItem.js | 16 ++++++++++++++++ components/users.js | 10 +++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/classes/CEconItem.js b/classes/CEconItem.js index 4667d72..c011b63 100644 --- a/classes/CEconItem.js +++ b/classes/CEconItem.js @@ -66,6 +66,22 @@ function CEconItem(item, description, contextID) { 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 === "") { this.actions = []; } diff --git a/components/users.js b/components/users.js index 68cf70d..3b9619f 100644 --- a/components/users.js +++ b/components/users.js @@ -397,6 +397,11 @@ SteamCommunity.prototype.getUserInventory = function(userID, appID, contextID, t * @param {function} 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; @@ -408,11 +413,6 @@ SteamCommunity.prototype.getUserInventoryContents = function(userID, appID, cont userID = new SteamID(userID); } - if (typeof language === 'function') { - callback = language; - language = "english"; - } - var pos = 1; get([], []); From 3ea0995415c7a444c3362135b20a62cfdd5a1508 Mon Sep 17 00:00:00 2001 From: Alex Corn Date: Sat, 21 Sep 2019 04:27:55 -0400 Subject: [PATCH 7/9] 3.40.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 42eb97e..bf0c25c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "steamcommunity", - "version": "3.40.1", + "version": "3.40.2", "description": "Provides an interface for logging into and interacting with the Steam Community website", "keywords": [ "steam", From 3c8488d4419646756d911459177d324ae8b5b7ce Mon Sep 17 00:00:00 2001 From: Alex Corn Date: Tue, 24 Sep 2019 04:06:37 -0400 Subject: [PATCH 8/9] Added method sendImageToUser --- classes/CSteamUser.js | 10 +++ components/users.js | 155 ++++++++++++++++++++++++++++++++++++++++++ package.json | 13 ++-- 3 files changed, 172 insertions(+), 6 deletions(-) diff --git a/classes/CSteamUser.js b/classes/CSteamUser.js index 9ca4564..a412eb0 100644 --- a/classes/CSteamUser.js +++ b/classes/CSteamUser.js @@ -190,3 +190,13 @@ CSteamUser.prototype.getInventoryContents = function(appID, contextID, tradableO 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); +}; diff --git a/components/users.js b/components/users.js index 3b9619f..b1b1291 100644 --- a/components/users.js +++ b/components/users.js @@ -1,4 +1,6 @@ const Cheerio = require('cheerio'); +const Crypto = require('crypto'); +const imageSize = require('image-size'); const SteamID = require('steamid'); const SteamCommunity = require('../index.js'); @@ -508,3 +510,156 @@ SteamCommunity.prototype.getUserInventoryContents = function(userID, appID, cont 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'); + + 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: 'image.' + imageDetails.type, + 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: 'image.' + imageDetails.type, + 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'); +}; diff --git a/package.json b/package.json index bf0c25c..9dfbd69 100644 --- a/package.json +++ b/package.json @@ -21,13 +21,14 @@ "url": "https://github.com/DoctorMcKay/node-steamcommunity.git" }, "dependencies": { - "request": "^2.86.0", - "node-bignumber": "^1.2.1", - "steamid": "^1.0.0", - "xml2js": "^0.4.11", + "async": "^2.6.3", "cheerio": "0.22.0", - "async": "^2.1.4", - "steam-totp": "^1.3.0" + "image-size": "^0.8.2", + "node-bignumber": "^1.2.1", + "request": "^2.88.0", + "steam-totp": "^1.5.0", + "steamid": "^1.1.3", + "xml2js": "^0.4.22" }, "engines": { "node": ">=4.0.0" From d4d0d7da260e5b64a2dd98d65e9d397fffc37c4e Mon Sep 17 00:00:00 2001 From: Alex Corn Date: Tue, 24 Sep 2019 04:07:34 -0400 Subject: [PATCH 9/9] 3.41.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9dfbd69..42146c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "steamcommunity", - "version": "3.40.2", + "version": "3.41.0", "description": "Provides an interface for logging into and interacting with the Steam Community website", "keywords": [ "steam",