Skip to content

Commit

Permalink
feat: Add steamcommunity sharedfile workshop subscribing library patch
Browse files Browse the repository at this point in the history
  • Loading branch information
3urobeat committed Jan 6, 2025
1 parent ee79d32 commit 624dd0d
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 32 deletions.
11 changes: 8 additions & 3 deletions src/data/fileStructure.json
Original file line number Diff line number Diff line change
Expand Up @@ -448,13 +448,18 @@
{
"path": "src/libraryPatches/CSteamSharedFile.js",
"url": "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/beta-testing/src/libraryPatches/CSteamSharedFile.js",
"checksum": "9f155bb4bded0f93b388399f17e859a8"
"checksum": "445874b13cdd04a885790508055202be"
},
{
"path": "src/libraryPatches/EDiscussionType.js",
"url": "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/beta-testing/src/libraryPatches/EDiscussionType.js",
"checksum": "4a801c29078172b6b35e86843670ae6e"
},
{
"path": "src/libraryPatches/ESharedFileType.js",
"url": "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/beta-testing/src/libraryPatches/ESharedFileType.js",
"checksum": "86de7b8864dd78fcfc542e88bc4c5a68"
},
{
"path": "src/libraryPatches/README.md",
"url": "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/beta-testing/src/libraryPatches/README.md",
Expand All @@ -478,7 +483,7 @@
{
"path": "src/libraryPatches/sharedfiles.js",
"url": "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/beta-testing/src/libraryPatches/sharedfiles.js",
"checksum": "a33395c4ab436fa534e404487d8e7925"
"checksum": "778ee43931a32422004d50168679127b"
},
{
"path": "src/pluginSystem/handlePluginData.js",
Expand Down Expand Up @@ -628,7 +633,7 @@
{
"path": "types/types.d.ts",
"url": "https://raw.githubusercontent.com/3urobeat/steam-comment-service-bot/beta-testing/types/types.d.ts",
"checksum": "c42ffd93755b217a59a82852946a87e5"
"checksum": "1570c999b124f71794ed294650f133d1"
}
]
}
94 changes: 68 additions & 26 deletions src/libraryPatches/CSteamSharedFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const SteamID = require('steamid');
const SteamCommunity = require('steamcommunity');
const Helpers = require('../../node_modules/steamcommunity/components/helpers.js');

const ESharedFileType = require('../../node_modules/steamcommunity/resources/ESharedFileType.js');
const ESharedFileType = require("./ESharedFileType.js");


/**
Expand All @@ -22,6 +22,8 @@ SteamCommunity.prototype.getSteamSharedFile = function(sharedFileId, callback) {
fileSize: null,
postDate: null,
resolution: null,
categories: [],
tags: [],
uniqueVisitorsCount: null,
favoritesCount: null,
upvoteCount: null,
Expand All @@ -44,6 +46,27 @@ SteamCommunity.prototype.getSteamSharedFile = function(sharedFileId, callback) {
// Load output into cheerio to make parsing easier
let $ = Cheerio.load(body);


// Determine type by looking at the second breadcrumb. Find the first separator as it has a unique name and go to the next element which holds our value of interest
let breadcrumb = $(".breadcrumbs > .breadcrumb_separator").next().get(0).children[0].data || "";

if (breadcrumb.includes("Screenshot")) {
sharedfile.type = ESharedFileType.Screenshot;
}

if (breadcrumb.includes("Artwork")) {
sharedfile.type = ESharedFileType.Artwork;
}

if (breadcrumb.includes("Guide")) {
sharedfile.type = ESharedFileType.Guide;
}

if (breadcrumb.includes("Workshop")) {
sharedfile.type = ESharedFileType.Workshop;
}


// Dynamically map detailsStatsContainerLeft to detailsStatsContainerRight in an object to make readout easier. It holds size, post date and resolution.
let detailsStatsObj = {};
let detailsLeft = $(".detailsStatsContainerLeft").children();
Expand All @@ -57,6 +80,7 @@ SteamCommunity.prototype.getSteamSharedFile = function(sharedFileId, callback) {
detailsStatsObj[detailsLeft[e].children[0].data.trim()] = detailsRight[e].children[0].data;
});


// Dynamically map stats_table descriptions to values. This holds Unique Visitors and Current Favorites
let statsTableObj = {};
let statsTable = $(".stats_table").children();
Expand Down Expand Up @@ -89,8 +113,28 @@ SteamCommunity.prototype.getSteamSharedFile = function(sharedFileId, callback) {
}


// Find resolution if artwork or screenshot
sharedfile.resolution = detailsStatsObj["Size"] || null;
// Find resolution if artwork or screenshot. Guides don't have a resolution and workshop items display it somewhere else
if (sharedfile.type != ESharedFileType.Workshop) {
sharedfile.resolution = detailsStatsObj["Size"] || null;
} else {
let resolutionTag = $(".workshopTagsTitle:contains(\"Resolution:\")").next();

sharedfile.resolution = resolutionTag.text() || null; // Keep prop null if this workshop item does not have a resolution
}


// Find categories if guide or workshop item
if (sharedfile.type == ESharedFileType.Guide || sharedfile.type == ESharedFileType.Workshop) {
let categoryTag = $(".workshopTagsTitle:contains(\"Category:\")").parent().contents().slice(1).text(); // Find div containing 'Category:' workshopTagsTitle, remove first element 'Category:' and get everything else as text

sharedfile.categories = categoryTag ? categoryTag.split(", ") : []; // Convert to array if string is not empty (aka no categories have been found)
}


// Find tags (there can be multiple)
let tagsTag = $(".workshopTagsTitle:contains(\"Tags:\")").next().contents();

sharedfile.tags = tagsTag.map((i, e) => e.type === 'text' ? $(e).text() : '').get() || []; // Map text to an array - https://stackoverflow.com/a/31543727


// Find uniqueVisitorsCount. We can't use ' || null' here as Number("0") casts to false
Expand Down Expand Up @@ -124,24 +168,6 @@ SteamCommunity.prototype.getSteamSharedFile = function(sharedFileId, callback) {
sharedfile.isDownvoted = String($(".workshopItemControlCtn > #VoteDownBtn")[0].attribs["class"]).includes("toggled"); // Check if downvote btn class contains "toggled"


// Determine type by looking at the second breadcrumb. Find the first separator as it has a unique name and go to the next element which holds our value of interest
let breadcrumb = $(".breadcrumbs > .breadcrumb_separator").next().get(0) || $(".breadcrumbs").get(0).children[1]; // Some artworks only have one breadcrumb like "username's Artwork" so let's check that as a backup

if (breadcrumb) { // If neither could be found then leave type at null
if (breadcrumb.children[0].data.includes("Screenshot")) {
sharedfile.type = ESharedFileType.Screenshot;
}

if (breadcrumb.children[0].data.includes("Artwork")) {
sharedfile.type = ESharedFileType.Artwork;
}

if (breadcrumb.children[0].data.includes("Guide")) {
sharedfile.type = ESharedFileType.Guide;
}
}


// Find owner profile link, convert to steamID64 using SteamIdResolver lib and create a SteamID object
let ownerHref = $(".friendBlockLinkOverlay").attr()["href"];

Expand All @@ -167,7 +193,7 @@ SteamCommunity.prototype.getSteamSharedFile = function(sharedFileId, callback) {
* Constructor - Creates a new SharedFile object
* @class
* @param {SteamCommunity} community
* @param {{ id: string, type: ESharedFileType, appID: number, owner: SteamID|null, fileSize: string|null, postDate: number, resolution: string|null, uniqueVisitorsCount: number, favoritesCount: number, upvoteCount: number|null, guideNumRatings: Number|null, isUpvoted: boolean, isDownvoted: boolean }} data
* @param {{ id: string, type: ESharedFileType, appID: number, owner: SteamID|null, fileSize: string|null, postDate: number, resolution: string|null, category: string[], tags: string[], uniqueVisitorsCount: number, favoritesCount: number, upvoteCount: number|null, guideNumRatings: Number|null, isUpvoted: boolean, isDownvoted: boolean }} data
*/
function CSteamSharedFile(community, data) {
/**
Expand All @@ -181,7 +207,7 @@ function CSteamSharedFile(community, data) {

/**
* Deletes a comment from this sharedfile's comment section
* @param {string} cid - ID of the comment to delete
* @param {String} cid - ID of the comment to delete
* @param {function} callback - Takes only an Error object/null as the first argument
*/
CSteamSharedFile.prototype.deleteComment = function(cid, callback) {
Expand All @@ -198,7 +224,7 @@ CSteamSharedFile.prototype.favorite = function(callback) {

/**
* Posts a comment to this sharedfile
* @param {string} message - Content of the comment to post
* @param {String} message - Content of the comment to post
* @param {function} callback - Takes only an Error object/null as the first argument
*/
CSteamSharedFile.prototype.comment = function(message, callback) {
Expand All @@ -209,7 +235,7 @@ CSteamSharedFile.prototype.comment = function(message, callback) {
* Subscribes to this sharedfile's comment section. Note: Checkbox on webpage does not update
* @param {function} callback - Takes only an Error object/null as the first argument
*/
CSteamSharedFile.prototype.subscribe = function(callback) {
CSteamSharedFile.prototype.subscribeComments = function(callback) {
this._community.subscribeSharedFileComments(this.owner, this.id, callback);
};

Expand All @@ -225,6 +251,22 @@ CSteamSharedFile.prototype.unfavorite = function(callback) {
* Unsubscribes from this sharedfile's comment section. Note: Checkbox on webpage does not update
* @param {function} callback - Takes only an Error object/null as the first argument
*/
CSteamSharedFile.prototype.unsubscribe = function(callback) {
CSteamSharedFile.prototype.unsubscribeComments = function(callback) {
this._community.unsubscribeSharedFileComments(this.owner, this.id, callback);
};

/**
* Subscribes to this workshop item
* @param {function} callback - Takes only an Error object/null as the first argument
*/
CSteamSharedFile.prototype.subscribeWorkshop = function(callback) {
this._community.subscribeWorkshopSharedFile(this.id, this.appID, callback);
};

/**
* Unsubscribes from this workshop item
* @param {function} callback - Takes only an Error object/null as the first argument
*/
CSteamSharedFile.prototype.unsubscribeWorkshop = function(callback) {
this._community.unsubscribeWorkshopSharedFile(this.id, this.appID, callback);
};
15 changes: 15 additions & 0 deletions src/libraryPatches/ESharedFileType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @enum ESharedFileType
*/
module.exports = {
"Screenshot": 0,
"Artwork": 1,
"Guide": 2,
"Workshop": 3,

// Value-to-name mapping for convenience
"0": "Screenshot",
"1": "Artwork",
"2": "Guide",
"3": "Workshop"
};
48 changes: 47 additions & 1 deletion src/libraryPatches/sharedfiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,50 @@ SteamCommunity.prototype.postSharedFileComment = function(userID, sharedFileId,
callback(new Error(body.error));
}
}, "steamcommunity");
};
};

/**
* Subscribes to a workshop item sharedfile.
* @param {String} sharedFileId - ID of the sharedfile
* @param {String} appid - ID of the app associated to this sharedfile
* @param {function} callback - Takes only an Error object/null as the first argument
*/
SteamCommunity.prototype.subscribeWorkshopSharedFile = function(sharedFileId, appid, callback) {
this.httpRequestPost({
"uri": "https://steamcommunity.com/sharedfiles/subscribe",
"form": {
"id": sharedFileId,
"appid": appid,
"sessionid": this.getSessionID()
}
}, function(err, response, body) {
if (!callback) {
return;
}

callback(err);
}, "steamcommunity");
};

/**
* Unsubscribes from a workshop item sharedfile.
* @param {String} sharedFileId - ID of the sharedfile
* @param {String} appid - ID of the app associated to this sharedfile
* @param {function} callback - Takes only an Error object/null as the first argument
*/
SteamCommunity.prototype.unsubscribeWorkshopSharedFile = function(sharedFileId, appid, callback) {
this.httpRequestPost({
"uri": "https://steamcommunity.com/sharedfiles/unsubscribe",
"form": {
"id": sharedFileId,
"appid": appid,
"sessionid": this.getSessionID()
}
}, function(err, response, body) {
if (!callback) {
return;
}

callback(err);
}, "steamcommunity");
};
14 changes: 12 additions & 2 deletions types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1758,7 +1758,7 @@ declare class CSteamSharedFile {
* Subscribes to this sharedfile's comment section. Note: Checkbox on webpage does not update
* @param callback - Takes only an Error object/null as the first argument
*/
subscribe(callback: (...params: any[]) => any): void;
subscribeComments(callback: (...params: any[]) => any): void;
/**
* Unfavorites this sharedfile
* @param callback - Takes only an Error object/null as the first argument
Expand All @@ -1768,7 +1768,17 @@ declare class CSteamSharedFile {
* Unsubscribes from this sharedfile's comment section. Note: Checkbox on webpage does not update
* @param callback - Takes only an Error object/null as the first argument
*/
unsubscribe(callback: (...params: any[]) => any): void;
unsubscribeComments(callback: (...params: any[]) => any): void;
/**
* Subscribes to this workshop item
* @param callback - Takes only an Error object/null as the first argument
*/
subscribeWorkshop(callback: (...params: any[]) => any): void;
/**
* Unsubscribes from this workshop item
* @param callback - Takes only an Error object/null as the first argument
*/
unsubscribeWorkshop(callback: (...params: any[]) => any): void;
}

/**
Expand Down

0 comments on commit 624dd0d

Please sign in to comment.