krzysztof-s
9/8/2017 - 6:42 PM

Subscribe and Unsubscribe Items from Steam Workshop without going into item and clicking button. Just do it from list!

Subscribe and Unsubscribe Items from Steam Workshop without going into item and clicking button. Just do it from list!

// ==UserScript==
// @name         Steam Workshop Fast Subscribe
// @homepage     https://zakku.tk
// @version      2.0
// @description  Subscribe and Unsubscribe Items from Steam Workshop without going into item and clicking button. Just do it from list!
// @author       ZaKKu
// @match        http://steamcommunity.com/workshop/browse/*
// @match        http://steamcommunity.com/id/*/myworkshopfiles/*
// @match        https://steamcommunity.com/workshop/browse/*
// @match        https://steamcommunity.com/id/*/myworkshopfiles/*
// @require      https://code.jquery.com/jquery-2.0.3.min.js
// @downloadURL  https://gist.github.com/zaker102/562cceea6b5e6f8ba2755e0b0c35deea/raw/01fd4f8a4753e030391d01e4fd9c9d7917931def/Steam%2520Workshop%2520Fast%2520Subscribe.user.js
// @updateURL  https://gist.github.com/zaker102/562cceea6b5e6f8ba2755e0b0c35deea/raw/01fd4f8a4753e030391d01e4fd9c9d7917931def/Steam%2520Workshop%2520Fast%2520Subscribe.user.js
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';
    let idList = [];
    let compere = [];
    let defaultList = document.querySelector('.workshopBrowsePagingInfo').innerHTML;
    let subscribedList = [];

    function getIds() {

        let url = window.location.href;
        let testURL = /^(http|https):\/\/steamcommunity.com\/id.*[a-z]\/myworkshopfiles\/\?appid=.*[0-9]/g.exec(url);

        let items = document.querySelectorAll('.workshopItem a[href*="//steamcommunity.com/sharedfiles/filedetails/?id="]:first-child');
        for(var i = 0; i < items.length; i++) {
            let id = items[i].href.split("id=")[1].split("&")[0];
            let url = items[i].href.split('&searchtext=')[0];
            let title = document.querySelectorAll('.workshopItem .workshopItemTitle')[i].innerHTML;
            let author = (testURL === null ? document.querySelectorAll('.workshopItemAuthorName a')[i].innerHTML : document.querySelector('#HeaderUserInfoName a').innerHTML);
            let img = document.querySelectorAll('.workshopItemPreviewImage')[i].src.split("?")[0];
            let rating = document.querySelectorAll('.fileRating')[i].src.split('/').pop().split("-")[0];
            let incompatible = document.querySelectorAll('.workshop_checkmark')[i].style.display === 'block';
            let favorited = false;

            let nodes = document.querySelectorAll('.workshopItem')[i].childNodes;

            for(var j = 0; j < nodes.length; j++) {
                if(nodes[j].className === "user_action_history_icon favorited") {
                    favorited = true;
                }
            }
            idList.push({id: id, name: title, author: author, rating: rating, favorited: favorited, incompatible: incompatible, url: url, image: img});
        }

        if (unsafeWindow.items === undefined) {
            unsafeWindow.items = idList;
        }
    }

    function getSubscribeData() {
        var url = window.location.href;
        var appid = /appid=([^&]+)/.exec(url)[1];
        let a = document.querySelector('.user_avatar.playerAvatar').href.split('/');
        let username = a[a.length - 2];
        return { session: g_sessionID, appid: appid, username: username };
    }

    function createFilter() {
        let pattern = '<div class="filterOption"><input type="checkbox" id="%id%" value="%id%" class="inputTagsFilter" %checked%><label for="%id%">%name%</label></div>';
        let panel = document.querySelector('.rightDetailsBlock');
        panel.innerHTML = '<div class="rightSectionTitle"><div class="tagSearch">Loading ' + idList.length + ' items..</div></div>';
        getSubscribedItems(function(list) {
            for(var i = 0; i < idList.length; i++) {
                compere.push(idList[i].id);
                let pc = pattern;
                let index = list.indexOf(idList[i].id);

                if(index > -1) {
                    pc = replaceAll(pc, "%checked%", "checked");
                } else {
                    pc = replaceAll(pc, "%checked%", "");
                }

                pc = replaceAll(pc, "%id%", idList[i].id);
                pc = replaceAll(pc, "%name%", idList[i].name);
                panel.innerHTML += pc;
            }
            updateStatus();
            listenToFilter();
        });
    }

    function listenToFilter() {
        $('.filterOption').click(function(e) {
            let target = $(e.target);
            if(target.is(":checked")) {
                subscribeMod(target.val(), function(result) { if(result !== 1) target.prop('checked', false); });
            } else {
                unsubscribeMod(target.val(), function(result) { if(result !== 1) target.prop('checked', true); });
            }
        });
    }


    function getSubscribedItems(callback) {
        let data = getSubscribeData();
        let url = '//steamcommunity.com/id/'+ data.username +'/myworkshopfiles/?appid='+ data.appid +'&browsefilter=mysubscriptions';
        let result = [];
        let outstandingRequests = 0;
        $.ajax({
            type: 'GET',
            url: url,
            success: function(response) {
                let button = $(response).find('a.pagelink[href^="?appid='+ data.appid +'&browsefilter=mysubscriptions&p="]');
                let count = ($(button).length > 0 ? Number($(button[button.length -1]).html()) : 0);

				for(var i = 0; i <= count; i++) {
					outstandingRequests++;
					$.ajax({
                        type: 'GET',
                        url: url + '&p=' + i,
                        success: function(response) {
                            let items = $(response).find('.workshopItemSubscriptionDetails a[href*="//steamcommunity.com/sharedfiles/filedetails/?id="]');
                            for(var j = 0; j < items.length; j++) {
                                result.push(items[j].href.split("id=")[1].split("&")[0]);
                                subscribedList.push(items[j].href.split("id=")[1].split("&")[0]);
                            }
                            if (!(--outstandingRequests)) {
                                callback(result);
                            }
                        }
                    });
                }
            }
        });
    }

    function subscribeMod(id, callback) {
        let data = getSubscribeData();
        var index = findWithAttr(idList, 'id', id);
        if(index == -1) return;
        $.ajax({
            type: "POST",
            url: "//steamcommunity.com/sharedfiles/subscribe",
            headers: {
                "Content-Type": "application/x-www-form-urlencoded",
            },
            data: {
                id: idList[index].id,
                appid: data.appid,
                sessionid: data.session
            },
            success: function (response) {
                console.log(response);
                if(response.success == 1) {
                    subscribedList.push(id);
                    updateStatus();
                }
                return callback(response.success);
            }
        });
    }
    function unsubscribeMod(id, callback) {
        let data = getSubscribeData();
        var index = subscribedList.indexOf(id);
        if(index == -1) return;
        $.ajax({
            type: "POST",
            url: "//steamcommunity.com/sharedfiles/unsubscribe",
            headers: {
                "Content-Type": "application/x-www-form-urlencoded",
            },
            data: {
                id: subscribedList[index],
                appid: data.appid,
                sessionid: data.session
            },
            success: function (response) {
                console.log(response);
                if(response.success == 1) {
                    let i = subscribedList.indexOf(id);
                    if(i > -1) {
                        subscribedList.splice(i, 1);
                        updateStatus();
                    }
                }
                return callback(response.success);
            }
        });
    }

    function updateStatus() {
        for(var i = 0; i < idList.length; i++) {
            let item = document.querySelectorAll('.workshopItem')[i];
            let pattern = document.createElement('div');
            pattern.setAttribute("id", "user_action_history_icon_subscribed" + idList[i].id);
            pattern.setAttribute("data-tooltip-content", "You are subscribed to this item.");
            pattern.className = "user_action_history_icon subscribed tooltip";
            $('#user_action_history_icon_subscribed' + idList[i].id).remove();
            if(subscribedList.indexOf(idList[i].id) > -1) {
                $('.fileRating')[i].before(pattern);
            } else {
                $('#user_action_history_icon_subscribed' + idList[i].id).remove();
            }
        }
        let notDisplayedCount = subscribedList.filter(function(i) {return compere.indexOf(i) < 0;}).length;
        document.querySelector('.workshopBrowsePagingInfo').innerHTML = defaultList + ', ' + notDisplayedCount + ' subscribed ' + (notDisplayedCount > 1 || notDisplayedCount === 0 ? 'items are' : 'item is') + ' not displayed';
        document.querySelector('.rightSectionTitle .tagSearch').innerHTML = "Subscribed to " + subscribedList.length + " " + (subscribedList.length > 1 ? "mods" : "mod");
    }

    function replaceAll(str, search, replace) {
        return str.split(search).join(replace);
    }

    function findWithAttr(array, attr, value) {
        for(var i = 0; i < array.length; i += 1) {
            if(array[i][attr] === value) {
                return i;
            }
        }
        return -1;
    }

    getIds();
    createFilter();

    if (unsafeWindow.data === undefined) {
        unsafeWindow.data = getSubscribeData();
    }

    if (unsafeWindow.list === undefined) {
        unsafeWindow.list = subscribedList;
    }
})();