Last active 1741880405

Revision bf984d5adeea454e9881fbad1c733465d603d96a

export_subscriptions.js Raw
1// ==UserScript==
2// @name Export Steam Workshop Subscriptions
3// @version 1.0
4// @description Adds a button to subscribed items page to easily export ALL workshop subscriptions to a simple JSON file.
5// @author Jackz
6// @match http*://steamcommunity.com/id/*/myworkshopfiles*
7// @grant GM_setClipboard
8// @grant GM_getValue
9// @grant GM_setValue
10// @grant GM_listValues
11// ==/UserScript==
12const ID_REGEX = new RegExp(/\?id=(\d+)/m);
13(async function() {
14 'use strict';
15 if(getParameterByName('reset')) {
16 await GM_setValue('page', null)
17 await GM_setValue('items', null)
18 window.location.href = UpdateQueryString("reset", null, window.location.path)
19 return;
20 }
21 let page = await GM_getValue('page');
22 let items = await GM_getValue('items');
23 if(items) {
24 items = JSON.parse(items)
25 }else{
26 items = []
27 }
28 const isFirstTime = page == null
29 if(isFirstTime) {
30 page = parseInt(getParameterByName('p')) || 1
31 const forceEndPage = getParameterByName('end')
32 if(forceEndPage && !isNaN(forceEndPage)) {
33 await GM_setValue('lastpage', parseInt(forceEndPage))
34 }else{
35 const links = document.getElementsByClassName("pagelink")
36 const lastPage = links.length > 0 ? parseInt(links[links.length - 1].text) : 1
37 await GM_setValue('lastpage', lastPage)
38 }
39 await GM_setValue('items', null)
40 }
41 document.getElementsByClassName("rightDetailsBlock")[1].insert("<span class=\"btn_grey_steamui btn_medium\" id=\"subscribe-item\"><span>Export</span></span>")
42 document.getElementById('subscribe-item').addEventListener('click', () => grabItems(page, items))
43 if(!isFirstTime) {
44 await grabItems(page, items)
45 }
46})();
47
48function UpdateQueryString(key, value, url) {
49 if (!url) url = window.location.href;
50 var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
51 hash;
52
53 if (re.test(url)) {
54 if (typeof value !== 'undefined' && value !== null) {
55 return url.replace(re, '$1' + key + "=" + value + '$2$3');
56 }
57 else {
58 hash = url.split('#');
59 url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
60 if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
61 url += '#' + hash[1];
62 }
63 return url;
64 }
65 }
66 else {
67 if (typeof value !== 'undefined' && value !== null) {
68 var separator = url.indexOf('?') !== -1 ? '&' : '?';
69 hash = url.split('#');
70 url = hash[0] + separator + key + '=' + value;
71 if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
72 url += '#' + hash[1];
73 }
74 return url;
75 }
76 else {
77 return url;
78 }
79 }
80}
81
82async function grabItems(page, items) {
83 for(const item of document.getElementsByClassName("workshopItemSubscriptionDetails")) {
84 const match = item.outerHTML.match(ID_REGEX)
85 const name = item.childNodes[1].innerText
86 items.push({
87 fileid: match[1],
88 name: name.replace(/\s/g, '%20')
89 })
90 }
91 let lastPage = GM_getValue('lastpage')
92 if(page >= lastPage) {
93 await GM_setClipboard(items, "text");
94 await GM_setValue('page', null)
95 await GM_setValue('items', null)
96 const appid = getParameterByName("appid")
97 var a = document.createElement("a");
98 a.href = "data:application/json," + JSON.stringify({
99 items,
100 meta: {
101 timestamp: Date.now(),
102 appid
103 }
104 }); //content
105 a.download = "workshop_subscriptions_" + appid + ".json"; //file name
106 a.click();
107 return;
108 }else{
109 await GM_setValue('page', page + 1)
110 await GM_setValue('items', JSON.stringify(items))
111 const url = UpdateQueryString("p", page+1, window.location.path)
112 window.location.href = url
113 }
114}
115
116function getParameterByName(name, url = window.location.href) {
117 name = name.replace(/[\[\]]/g, '\\$&');
118 var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
119 results = regex.exec(url);
120 if (!results) return null;
121 if (!results[2]) return '';
122 return decodeURIComponent(results[2].replace(/\+/g, ' '));
123}