Skip to content

Instantly share code, notes, and snippets.

@pointfeev
Last active April 16, 2025 13:11
Show Gist options
  • Select an option

  • Save pointfeev/31618a04ab2f754158ca7d950e1dd35c to your computer and use it in GitHub Desktop.

Select an option

Save pointfeev/31618a04ab2f754158ca7d950e1dd35c to your computer and use it in GitHub Desktop.
Steam Collection Manager
// ==UserScript==
// @name Steam Collection Manager
// @version 3.1.0
// @description Adds buttons to collections related to the mass removal, addition, and sorting of items.
// @author pointfeev
// @copyright 2021, pointfeev (https://github.com/pointfeev)
// @license MIT
// @match *://*.steamcommunity.com/sharedfiles/filedetails/?id=*
// @match *://*.steamcommunity.com/workshop/filedetails/?id=*
// @match *://*.steamcommunity.com/sharedfiles/managecollection/?id=*
// @match *://*.steamcommunity.com/workshop/managecollection/?id=*
// @icon https://steamcommunity.com/favicon.ico
// @grant none
// @namespace https://github.com/pointfeev
// @homepageURL https://gist.github.com/pointfeev/31618a04ab2f754158ca7d950e1dd35c
// @updateURL https://gist.githubusercontent.com/pointfeev/31618a04ab2f754158ca7d950e1dd35c/raw
// @downloadURL https://gist.githubusercontent.com/pointfeev/31618a04ab2f754158ca7d950e1dd35c/raw
// ==/UserScript==
(function() {
"use strict";
if (document.querySelector("div#mainContentsCollection") == null && document.querySelector("div.manageCollectionItemsBody") == null) return;
let collection_id = new URL(document.location.href).searchParams.get("id");
let sessionID = window.g_sessionID;
let steamID = window.g_steamID;
let author = jQuery("a.friendBlockLinkOverlay").attr("href");
let user = jQuery("a.user_avatar.playerAvatar").attr("href").slice(0, -1);
if (author != null && author != user) return;
let container = document.querySelector("#ig_bottom");
if (container == null)
container = document.querySelector("#BG_bottom");
if (container == null)
return;
let back_color = "#334455";
let back_shadow_color = "#001122";
let text_color = "#FFFFFF";
let remove_color = "#772222";
let add_color = "#226622";
let sort_color = "#226666";
let btn_container_padding = 5;
let btn_offset_x = 1;
let btn_offset_y = 3;
let btn_radius = 3;
let btn_container = document.createElement("div");
btn_container.style.background = back_color;
btn_container.style["border-radius"] = btn_radius * 2 + "px";
btn_container.style.width = btn_container_padding * 2 + "px";
btn_container.style.height = btn_container_padding * 2 + "px";
btn_container.style.position = "fixed";
btn_container.style.top = "33%";
btn_container.style["box-shadow"] = "0 0 10px " + back_shadow_color;
function update_position()
{
btn_container.style.left = jQuery(document).outerWidth(true) / 2 + jQuery(container).width() / 2 + 20 + "px";
}
update_position();
jQuery(window).resize(update_position);
document.body.insert(btn_container);
function create_button(text, background)
{
let btn = document.createElement("a");
jQuery(btn).text(text);
btn.style["font-size"] = "1em";
btn.style["font-family"] = "Arial, Helvetica, Verdana, sans-serif";
btn.style.background = background;
btn.style.color = text_color;
btn.style.padding = "4px";
btn.style["padding-left"] = "6px";
btn.style["padding-right"] = "6px";
btn.style["border-top-left-radius"] = btn_radius + "px";
btn.style["border-bottom-left-radius"] = btn_radius + "px";
btn.style["border-top-right-radius"] = btn_radius + "px";
btn.style["border-bottom-right-radius"] = btn_radius + "px";
btn.style.position = "absolute";
btn.style.top = btn_container_padding + "px";
btn.style.left = btn_container_padding + "px";
btn.style["white-space"] = "nowrap";
btn.style["user-select"] = "none";
//btn.style["box-shadow"] = "3px 3px 3px black";
return btn;
}
function unix()
{
return new Date().getTime() / 1000;
}
let btn_cancel;
function is_cancelled(btn)
{
if (btn_cancel == null)
return true;
if (btn == null)
return false;
let btn_dom = btn[0];
return btn_cancel.style.top != btn_dom.style.top
|| btn_cancel.style.bottom != btn_dom.style.bottom
//|| btn_cancel.style.left != btn_dom.style.left
|| btn_cancel.style.right != btn_dom.style.right;
}
let btn_container_width;
function set_working_text(btn, text)
{
btn.text(text);
let btn_dom = btn[0];
btn_container.style.width = Math.max(parseInt(btn_container_width, 10), parseInt(btn_dom.style.left, 10) + btn.outerWidth(true) + btn_container_padding) + "px";
}
function start_working(btn, btn_text)
{
if (btn_cancel != null)
{
btn_cancel.remove();
btn_cancel = null;
}
let btn_dom = btn[0];
btn_cancel = create_button("Cancel", btn_dom.style.background);
btn_cancel.style.top = btn_dom.style.top;
btn_cancel.style.bottom = btn_dom.style.bottom;
btn_cancel.style.left = btn_dom.style.left;
btn_cancel.style.right = btn_dom.style.right;
btn_cancel.style["border-top-right-radius"] = "0px";
btn_cancel.style["border-bottom-right-radius"] = "0px";
btn_container.insert(btn_cancel);
btn_dom.style["border-top-left-radius"] = "0px";
btn_dom.style["border-bottom-left-radius"] = "0px";
btn_dom.style.left = parseInt(btn_dom.style.left, 10) + jQuery(btn_cancel).outerWidth(true) + btn_offset_x + "px";
set_working_text(btn, btn_text);
jQuery(btn_cancel).click(function() {
stop_working(btn, btn_text);
//location.reload();
});
}
function stop_working(btn, btn_text)
{
btn.text(btn_text);
let btn_dom = btn[0];
btn_dom.style["border-top-left-radius"] = btn_radius + "px";
btn_dom.style["border-bottom-left-radius"] = btn_radius + "px";
btn_dom.style.left = parseInt(btn_dom.style.left, 10) - jQuery(btn_cancel).outerWidth(true) - btn_offset_x + "px";
btn_container.style.width = btn_container_width;
if (btn_cancel != null)
{
btn_cancel.remove();
btn_cancel = null;
}
}
let manage_document;
let manage_document_unix;
function get_manage_document(btn, func)
{
if (manage_document != null && unix() - manage_document_unix < 15) { func(); return; }
manage_document_unix = unix();
set_working_text(btn, "Getting manage document . . .");
if (window.location.pathname == "/sharedfiles/managecollection/")
{
manage_document = jQuery(document.documentElement);
func();
}
else
{
jQuery.ajax({
type: "GET",
url: "https://steamcommunity.com/sharedfiles/managecollection",
data: {
id: collection_id
},
success: function (response) {
if (is_cancelled(btn)) return;
manage_document = jQuery(jQuery.parseHTML(response));
}
}).done(func);
}
}
function update_choice_item(btn, childID, add)
{
let listItems = ["#choice_MyItems_" + childID, "#choice_MyFavoriteItems_" + childID, "#choice_MySubscribedItems_" + childID];
for (let i = 0; i < listItems.length; ++i)
{
if (is_cancelled(btn)) return;
let listElem = manage_document.find(listItems[i]);
if (listElem)
{
if (add) listElem.addClass("inCollection");
else listElem.removeClass("inCollection");
}
}
}
function remove_item(btn, choice_string)
{
if (btn_cancel != null) return;
let btn_text = btn.text();
start_working(btn, btn_text);
set_working_text(btn, "Working . . .");
get_manage_document(btn, function() {
if (is_cancelled(btn)) return;
let sortable_items = manage_document.find("div#sortable_items div.managedCollectionItem");
if (sortable_items.length)
{
let i = 0;
sortable_items.each(function() {
if (is_cancelled(btn)) return;
let item = jQuery(this);
let childID = item.attr("id").replace("sharedfile_", "");
if (choice_string != null && manage_document.find("#choice_" + choice_string + "_" + childID).length) return;
i++;
set_working_text(btn, "Removing " + i + (i == 1 ? " item . . ." : " items . . ."));
jQuery.ajax({
type: "POST",
url: "https://steamcommunity.com/sharedfiles/removechild",
data: {
id: collection_id,
sessionid: sessionID,
childid: childID
},
success: function () {
if (is_cancelled(btn)) return;
item.remove();
update_choice_item(btn, childID, false);
}
}).done(function() {
if (is_cancelled(btn)) return;
i--;
if (i == 0)
{
set_working_text(btn, "Refreshing . . .");
location.reload();
}
else
set_working_text(btn, "Removing " + i + (i == 1 ? " item . . ." : " items . . ."));
});
});
if (is_cancelled(btn)) return;
if (i == 0)
stop_working(btn, btn_text);
}
else
stop_working(btn, btn_text);
});
}
function add_item(btn, choice_string)
{
if (btn_cancel != null) return;
let btn_text = btn.text();
start_working(btn, btn_text);
set_working_text(btn, "Working . . .");
get_manage_document(btn, function() {
if (is_cancelled(btn)) return;
let sortable_items = manage_document.find("div#" + choice_string + " div.itemChoice:not(.inCollection)");
if (sortable_items.length)
{
let i = 0;
sortable_items.each(function() {
if (is_cancelled(btn)) return;
let item = jQuery(this);
if (item.find("div.itemChoiceType").text().trim() != "Item") return;
let childID = item.attr("id").replace("choice_" + choice_string + "_", "");
i++;
set_working_text(btn, "Adding " + i + (i == 1 ? " item . . ." : " items . . ."));
jQuery.ajax({
type: "POST",
url: "https://steamcommunity.com/sharedfiles/addchild",
data: {
id: collection_id,
sessionid: sessionID,
childid: childID
},
success: function () {
if (is_cancelled(btn)) return;
update_choice_item(btn, childID, true);
}
}).done(function() {
if (is_cancelled(btn)) return;
i--;
if (i == 0)
{
set_working_text(btn, "Refreshing . . .");
location.reload();
}
else
set_working_text(btn, "Adding " + i + (i == 1 ? " item . . ." : " items . . ."));
});
});
if (is_cancelled(btn)) return;
if (i == 0)
stop_working(btn, btn_text);
}
else
stop_working(btn, btn_text);
});
}
function sort(btn, sort_selector)
{
if (btn_cancel != null) return;
let btn_text = btn.text();
start_working(btn, btn_text);
set_working_text(btn, "Working . . .");
get_manage_document(btn, function() {
if (is_cancelled(btn)) return;
let items = manage_document.find("#sortable_items").find("div.managedCollectionItem");
let n = 0;
let i = items.length;
items.sort((a, b) => jQuery(a).find(sort_selector).text().localeCompare(jQuery(b).find(sort_selector).text()));
if (is_cancelled(btn)) return;
items.each(function() {
if (is_cancelled(btn)) return;
if (jQuery(this).find(".sortorder_input").val() != items.length - i--) n++;
});
if (is_cancelled(btn)) return;
if (n)
{
set_working_text(btn, "Sorting " + n + (n == 1 ? " item . . ." : " items . . ."));
i = items.length;
items.each(function() {
if (is_cancelled(btn)) return;
jQuery(this).find(".sortorder_input").val(items.length - i--);
});
if (is_cancelled(btn)) return;
jQuery.ajax({
type: "POST",
url: "https://steamcommunity.com/sharedfiles/setcollectionsortorder",
data: manage_document.find("#ChildItemsForm").serialize(),
success: function () {
if (is_cancelled(btn)) return;
set_working_text(btn, "Refreshing . . .");
location.reload();
}
});
}
else
stop_working(btn, btn_text);
});
}
let btns = [];
function add_button(text, background, double_offset, click) {
let btn_dom = create_button(text, background);
let btn = jQuery(btn_dom);
btn.click(click);
let last_btn = btns[btns.length - 1];
if (last_btn != null)
{
btn_container.style.height = parseInt(btn_container.style.height, 10) + btn_offset_y + "px";
btn_dom.style.top = parseInt(last_btn.style.top, 10) + jQuery(last_btn).outerHeight(true) + btn_offset_y + "px";
if (double_offset)
{
btn_container.style.height = parseInt(btn_container.style.height, 10) + btn_offset_y + "px";
btn_dom.style.top = parseInt(btn_dom.style.top, 10) + btn_offset_y + "px";
}
}
btn_container.insert(btn_dom);
btn_container.style.width = Math.max(parseInt(btn_container.style.width, 10), btn.outerWidth(true) + btn_container_padding * 2) + "px";
btn_container.style.height = parseInt(btn_container.style.height, 10) + btn.outerHeight(true) + "px";
btn_container_width = btn_container.style.width;
btns.push(btn_dom);
return btn_dom;
}
add_button("Remove all unowned items", remove_color, false, function() { remove_item(jQuery(this), "MyItems"); });
add_button("Add all unowned items", add_color, false, function() { add_item(jQuery(this), "MyItems"); });
add_button("Remove all unfavorited items", remove_color, true, function() { remove_item(jQuery(this), "MyFavoriteItems"); });
add_button("Add all favorited items", add_color, false, function() { add_item(jQuery(this), "MyFavoriteItems"); });
add_button("Remove all unsubscribed items", remove_color, true, function() { remove_item(jQuery(this), "MySubscribedItems"); });
add_button("Add all subscribed items", add_color, false, function() { add_item(jQuery(this), "MySubscribedItems"); });
add_button("Remove all items", remove_color, true, function() { remove_item(jQuery(this)); });
add_button("Sort items by name", sort_color, true, function() { sort(jQuery(this), ".actual_title"); });
add_button("Sort items by author", sort_color, false, function() { sort(jQuery(this), ".workshopItemAuthorName"); });
})();
@pointfeev
Copy link
Author

pointfeev commented Jul 17, 2021

Copy link

ghost commented Oct 18, 2024

So useful! Would be awesome if you could by subscribed or not subscribed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment