Greasy Fork is available in English.
在创意工坊中注入一个MOD下载按钮,用于下载MOD
- // ==UserScript==// @name Steam创意工坊饥荒mod下载工具// @namespace https://gfork.dahi.icu/users/3128// @version 1.9.4// @description 在创意工坊中注入一个MOD下载按钮,用于下载MOD// @author 极品小猫// @include https://steamcommunity.com/sharedfiles/filedetails/*// @include https://steamcommunity.com/id/*/myworkshopfiles/*// @include https://steamcommunity.com/id/*/myworkshopfiles?*// @match https://t.vvwall.com/*// @connect 5.5w.pw// @connect steamworkshopdownloader.io// @grant GM_setClipboard// @grant GM_addStyle// @grant GM_download// @grant GM_xmlhttpRequest// ==/UserScript==(function() {'use strict';let webHost=location.host, webPath=location.pathname;if(webHost=='steamcommunity.com') {let modDownloadStart, HostID=[3,2,1]; //mod 下载开始标记,防止重复请求下载if(webPath.search('myworkshopfiles')>-1) {GM_addStyle(`.download_Mod, .general_btn {text-align:center;}`)document.querySelectorAll('[id^="Subscription"]').forEach(function(e, i){console.log(i, e, e.id);let mid=e.id.replace(/^[^\d]+/i,''),actionsCtn=e.querySelector('.actionsCtn');let down_A=document.createElement('a');down_A.className="download_Mod";down_A.target='_blank';down_A.textContent='下载 MOD';let down_span=document.createElement('span');down_span.className='general_btn';down_span.style.width='70px';down_span.appendChild(down_A);actionsCtn.appendChild(down_span);down_A.addEventListener('click', function(){ModDownloadAjax(mid);jQuery(this).html('<img src="https://community.cloudflare.steamstatic.com/public/images/login/throbber.gif" style="height:20px;vertical-align:middle;">');});});} else { //workshop详细页let down_A=document.createElement('a');//down_A.href="https://t.vvwall.com/#"+publishedfileid;down_A.id="download_Mod";down_A.target='_blank';down_A.textContent='下载 MOD';let down_span=document.createElement('span');down_span.className='general_btn share tooltip';down_span.id="download_ModBtn"down_span.appendChild(down_A);GM_addStyle('#download_Mod {line-height:30px;}')document.querySelector('#ItemControls').appendChild(down_span);let modTags=document.querySelector('span.workshopTagsTitle~a[href*="version"]');let modVersion=modTags?modTags.textContent.trim().replace('version:','v'):'';document.querySelector('#download_ModBtn').addEventListener('click', function(e){if(modDownloadStart) return false;ModDownloadAjax(publishedfileid, modVersion);jQuery(this).html('<img src="https://community.cloudflare.steamstatic.com/public/images/login/throbber.gif" style="height:20px;vertical-align:middle;">');//jQuery('<img src="https://community.cloudflare.steamstatic.com/public/images/login/throbber.gif" style="height:20px;vertical-align:middle;">').appendTo(this);//jQuery(this).replaceWith('<img src="https://community.cloudflare.steamstatic.com/public/images/login/throbber.gif" style="height:20px;vertical-align:middle;">');});}/*let down_A=$('<a>').text('下载MOD'),downBtn=$('<span class="general_btn report tooltip" data-tooltip-text="下载MOD">').append(down_A);*/function ModDownloadAjax(mid, target){modDownloadStart=true; //标记 mod 下载线程已开始mid=Number(mid);let _HostID = HostID.shift();console.log(mid, [mid], JSON.stringify(mid), _HostID);GM_xmlhttpRequest({url:'https://backend-0'+_HostID + '-prd.steamworkshopdownloader.io/api/details/file',method: 'post',timeout : 5000,data: JSON.stringify([mid]),responseType : 'json',headers : {'content-type' : 'application/x-www-form-urlencoded',},onTimeout : function(e){console.log(e);modDownloadStart=false;jQuery('#download_ModBtn').html('请求超时,请重试');},abort : function(e){console.log('请求已取消')},onload: function(e){console.log(e, e.response);let modData, downloadTitle;switch(e.status) {case 200:modData=e.response[0];modData.tags.forEach(function(item){if(/version:/i.test(item.tag)) {let modVersion=item.tag.trim().replace('version:','v');downloadTitle="[workshop-"+mid+"]"+modData.title+(modVersion?" "+modVersion:"")+".zip";}});if(!modData.file_url) {GM_xmlhttpRequest({url:'https://backend-0'+_HostID + '-prd.steamworkshopdownloader.io/api/download/request',method: 'post',data : JSON.stringify({"publishedFileId": mid,"collectionId":null,"extract":true,"hidden":false,"direct":false,"autodownload":true}),responseType : 'json',headers : {'content-type' : 'application/x-www-form-urlencoded',},onload: function(re){console.log(re, re.response, 'https://backend-0'+_HostID + '-prd.steamworkshopdownloader.io/api/download/transmit?uuid='+re.response.uuid);GM_xmlhttpRequest({url : 'https://backend-0'+_HostID + '-prd.steamworkshopdownloader.io/api/download/status',method: 'post',data : JSON.stringify({"uuids": re.response.uuid}),responseType : 'json',headers : {'content-type' : 'application/x-www-form-urlencoded',},onload: function(se){console.log(se);GM_xmlhttpRequest({url:'https://backend-0'+_HostID + '-prd.steamworkshopdownloader.io/api/download/transmit?uuid='+re.response.uuid,method: 'get',headers : {'content-type' : 'application/x-www-form-urlencoded',},onload : function(de){console.log('下载开始', de);GM_download({url: 'https://backend-0'+_HostID + '-prd.steamworkshopdownloader.io/api/download/transmit?uuid='+re.response.uuid,name: downloadTitle,saveAs : true,});}});jQuery('#download_ModBtn').html('MOD 请求成功');}})}});} else {//直链下载modData.tags.forEach(function(item){if(/version:/i.test(item.tag)) {let modVersion=item.tag.trim().replace('version:','v');downloadTitle="[workshop-"+mid+"]"+modData.title+(modVersion?" "+modVersion:"")+".zip";}});GM_download({url: modData.file_url,name: downloadTitle,saveAs : true,});jQuery(target).html('直链MOD 请求成功');}break;default :jQuery('#download_ModBtn').text('请求失败 ' + e.status);}/*let data=e.response, downloadTitle="[workshop-"+mid+"]"+data.title+(modVersion?" "+modVersion:"")+".zip";GM_download({url: data.url,name: downloadTitle,saveAs : true,});*/},onerror: function(e){console.error('error', e);}});/* API 已失效GM_xmlhttpRequest({url:'https://5.5w.pw/api?mid='+mid,method: 'get',responseType : 'json',onload: function(e){console.log(e);let data=e.response, downloadTitle="[workshop-"+mid+"]"+data.title+(modVersion?" "+modVersion:"")+".zip";GM_download({url: data.url,name: downloadTitle,saveAs : true,});},onerror: function(e){console.error('error', e);}});*/}} else if(webHost=='t.vvwall.com') {GM_addStyle(`input[name="mid"]{padding: 0 10px;}`);$('button.starts').click(function(){addMObserver('#des', function(){console.log($('code#des').text());$('code#des').html(markdown.toHTML($('code#des').text()));});});let workshop_A=$('<a id="workshop">').text('创意工坊');let dlbtn=$('#dlbtn').removeAttr('onclick target').click(function(e){let inputText=$('input[name="mid"]').val().trim(),id=getUrlParam('id', inputText, inputText),modTitle=$('#modtitle').text().trim(),downloadTitle="[workshop-"+id+"]"+modTitle+".zip";workshop_A.attr({'href':'https://steamcommunity.com/sharedfiles/filedetails/?id='+id});GM_download({url: e.href,name: downloadTitle,saveAs : true,});e.preventDefault(); //阻止默认动作e.stopPropagation(); //阻止冒泡});$('.downloadbox').prepend(dlbtn);dlbtn.after(workshop_A);}if(location.hash) {$('input[name="mid"]').val(location.hash.replace('#',''));$('button.starts').click();}// Your code here...function addMObserver(selector, callback, Kill, option) {var watch = document.querySelector(selector);if (!watch) {return;}console.warn('watch:', watch, selector);var observer = new MutationObserver(function(mutations){console.log('mutations:', mutations);var nodeAdded = mutations.some(function(x){console.log(x);return x.addedNodes.length > 0;});console.log(nodeAdded);if (nodeAdded) {console.log(mutations, observer);callback(mutations, observer);if(Kill) {console.log('停止'+selector+'的监控');observer.disconnect();}}});observer.observe(watch, option||{childList: true, subtree: true});//}function getUrlParam(name, url, option, newVal) {//筛选参数,url 参数为数字时var search = url ? url.replace(/^.+\?/,'') : location.search;//网址传递的参数提取,如果传入了url参数则使用传入的参数,否则使用当前页面的网址参数var reg = new RegExp("(?:^|&)(" + name + ")=([^&]*)(?:&|$)", "i"); //正则筛选参数var str = search.replace(/^\?/,'').match(reg);console.log(str, option);if (str !== null) {switch(option) {case 0:return unescape(str[0]); //所筛选的完整参数串case 1:return unescape(str[1]); //所筛选的参数名case 2:return unescape(str[2]); //所筛选的参数值case 'new':return url.replace(str[1]+'='+str[2], str[1]+'='+newVal);default:return unescape(str[2]); //默认返回参数值}} else if(!str && option) {return option;} else {return null;}}})();