// ==UserScript== // @name Steam库移除助手 // @namespace http://tampermonkey.net/ // @version 0.1 // @description 快速移除Steam库中受限、正在了解和被Ban的游戏 // @author lyzlyslyc // @match http*://steamcommunity.com/*/games/* // @match http*://help.steampowered.com/* // @icon https://store.steampowered.com/favicon.ico // @resource data https://cdn.jsdelivr.net/gh/lyzlyslyc/Scripts/SteamLimitedGames.json // @grant GM_getResourceText // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @connect help.steampowered.com // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/456523/Steam%E5%BA%93%E7%A7%BB%E9%99%A4%E5%8A%A9%E6%89%8B.user.js // @updateURL https://update.greasyfork.icu/scripts/456523/Steam%E5%BA%93%E7%A7%BB%E9%99%A4%E5%8A%A9%E6%89%8B.meta.js // ==/UserScript== (function() { 'use strict'; // Your code here... let removeList = GM_getValue("removeList"); if(removeList===undefined)removeList={}; if(document.domain=="help.steampowered.com"){ let applist = []; let success = 0; let fail = 0; let div; let rows = {}; let currentThread = 0; let maxThread = 5; let removeInterval_ms = 1000; let thread = null; initializeDiv(); let table = document.getElementById("gameRemoveTable"); for(let appid in removeList){ if(removeList[appid].remove==true){ applist.push(appid); rows[appid] = addGame(appid,removeList[appid].name); } } if(applist.length>0){ document.getElementById("remove_gamecount").innerText=applist.length; div.style.display = ""; } function initializeDiv(){ div = document.createElement("div"); div.id="gameRemoveDiv"; div.innerHTML = `

检测到需要移除的游戏

0
appid游戏名状态
开始移除
`; div.style.display = "none"; document.body.append(div); $J('').appendTo($J("head")); let btnStart = document.getElementById("btnStartRemove"); btnStart.addEventListener("click",()=>{ if(thread!=null){ btnStart.innerText="开始移除"; clearInterval(thread); thread=null; return; } btnStart.innerText="停止移除"; thread = setInterval(removeLoop,removeInterval_ms); }) } function addGame(appid,name){ let row = table.tBodies[0].insertRow(0); let appidCell=row.insertCell(0); let nameCell=row.insertCell(1); let statusCell = row.insertCell(2); //let deleteCell = row.insertCell(3); appidCell.innerText=appid; nameCell.innerText=name; statusCell.innerText="未开始"; //deleteCell.innerText="×"; return row; } function removeLoop(){ while(currentThreaddoRemovePackage(params)).then(res=>{ if(res.success==true){ rows[appid].style.background="green"; rows[appid].cells[2].innerText="成功"; delete removeList[appid]; GM_setValue("removeList",removeList); } else { rows[appid].style.background="red"; rows[appid].cells[2].innerText="失败"; delete removeList[appid]; GM_setValue("removeList",removeList); } }).catch(err=>{ console.log(err); rows[appid].style.background="red"; rows[appid].cells[2].innerText=err; }).finally(()=>{currentThread--;}) } } else{ let data; try{ data = JSON.parse(GM_getResourceText("data")); } catch(e){ alert("Steam库移除助手:获取受限游戏数据失败,请刷新重试!"); console.log(e); } //添加筛选面板 $J(``).appendTo("head"); $J("#gameslist_controls").after($J(`
移除筛选
  显示受限  显示了解中  显示被Ban  选择免费  选择有卡  选择全部  仅显示已选择  已选择2  前往客服页面移除
`)); let chkShowLimited = document.querySelector("#chkShowLimited"); let chkShowLearning = document.querySelector("#chkShowLearning"); let chkShowBanned = document.querySelector("#chkShowBanned"); let chkShowListed = document.querySelector("#chkShowListed"); chkShowLimited.addEventListener("click",()=>handleFilterClick()); chkShowLearning.addEventListener("click",()=>handleFilterClick()); chkShowListed.addEventListener("click",()=>handleFilterClick()); chkShowBanned.addEventListener("click",()=>handleFilterClick()); //移除免费 document.querySelector("#chkRemoveFree").addEventListener("click",(e)=>{ document.querySelector("#games_list_row_container").style.display = "none"; if(e.currentTarget.checked){ document.querySelectorAll("#games_list_rows .gameListRow:not(.filtered)").forEach(row=>{ //如果没显示,且是勾选事件,则不显示的不会被加入列表 if(row.style.display=="none")return; if(data.FOD[row.appid]){ handleRemoveButtonClick(row.btn,row.appid,row.name,true); } }) } else{ document.querySelectorAll("#games_list_rows .gameListRow").forEach(row=>{ if(data.FOD[row.appid]){ if(row.btn.isOnList!=e.currentTarget.checked)handleRemoveButtonClick(row.btn,row.appid,row.name,false); } }); } document.querySelector("#games_list_row_container").style.display = ""; GM_setValue("removeList",removeList); handleFilterClick(); countSelectedGames(); }) //移除有卡 document.querySelector("#chkRemoveCards").addEventListener("click",(e)=>{ document.querySelector("#games_list_row_container").style.display = "none"; if(e.currentTarget.checked){ document.querySelectorAll("#games_list_rows .gameListRow:not(.filtered)").forEach(row=>{ //如果没显示,且是勾选事件,则不显示的不会被加入列表 if(row.style.display=="none")return; if(data.cards[row.appid]){ handleRemoveButtonClick(row.btn,row.appid,row.name,true); } }) } else{ document.querySelectorAll("#games_list_rows .gameListRow").forEach(row=>{ if(data.cards[row.appid]){ if(row.btn.isOnList!=e.currentTarget.checked)handleRemoveButtonClick(row.btn,row.appid,row.name,false); } }); } document.querySelector("#games_list_row_container").style.display = ""; GM_setValue("removeList",removeList); handleFilterClick(); countSelectedGames(); }) //移除全部 document.querySelector("#chkRemoveAll").addEventListener("click",(e)=>{ document.querySelector("#games_list_row_container").style.display = "none"; if(e.currentTarget.checked){ document.querySelectorAll("#games_list_rows .gameListRow:not(.filtered)").forEach(row=>{ if(row.style.display=="none")return; handleRemoveButtonClick(row.btn,row.appid,row.name,true); }) } else{ document.querySelectorAll("#games_list_rows .gameListRow").forEach(row=>{ //如果列表状态和勾选状态不一致,就点击按钮 if(row.btn.isOnList!=e.currentTarget.checked)handleRemoveButtonClick(row.btn,row.appid,row.name,false); }); } GM_setValue("removeList",removeList); document.querySelector("#games_list_row_container").style.display = ""; handleFilterClick(); countSelectedGames(); }) //添加移除按钮 addButtons(); //添加表格变化监视 let observer = new MutationObserver((mutations)=>{ console.log(mutations); handleFilterClick(); countSelectedGames(); }); observer.observe(document.querySelector("#games_list_rows"),{attributes:true,attributeFilter: ['style'],subtree:true }); countSelectedGames(); function toggleText(btn){ if(btn.isOnList)btn.innerText = "移出移除列表"; else btn.innerText = "加入移除列表"; } async function addButtons(){ let limitedCount = 0; let learningCount = 0; let bannedCount = 0; let fodCount = 0; document.querySelector("#games_list_row_container").style.display = "none"; document.querySelectorAll("#games_list_rows .gameListRow").forEach(row=>{ //提取游戏appid和游戏名 row.appid = row.id.match(/\d+/)[0]; row.name = row.querySelector(".gameListRowItemName").innerText; //创建按钮 let btn = document.createElement("a"); btn.className = "pullup_item remove_item"; btn.href = `javascript:void(0);`; btn.style = "padding:3px;"; btn.isOnList = (removeList[row.appid]&&removeList[row.appid].remove==true); toggleText(btn); btn.addEventListener("click",()=>{handleRemoveButtonClick(btn,row.appid,row.name);GM_setValue("removeList",removeList);countSelectedGames();}) row.querySelector(".bottom_controls").append(btn); row.btn=btn; if(data.limited[row.appid])limitedCount++; if(data.learning[row.appid])learningCount++; if(data.banned[row.appid])bannedCount++; let tags = $J(""); if(data.FOD[row.appid]){ tags[0].innerText+="免费 "; $J(row.querySelector(".gameListRowItemName")).after(tags); if(data.limited[row.appid]||data.learning[row.appid]||data.banned[row.appid])fodCount++; } if(data.cards[row.appid]){ tags[0].innerText+="有卡 "; $J(row.querySelector(".gameListRowItemName")).after(tags); } }) document.querySelector("#games_list_row_container").style.display = ""; console.log(`共${limitedCount}个受限游戏,${learningCount}个正在了解游戏,${bannedCount}被Ban游戏,这些游戏中有${fodCount}个免费游戏。`); } async function handleRemoveButtonClick(btn,appid,name,isOnList){ if(isOnList)btn.isOnList=isOnList; else btn.isOnList=!btn.isOnList; if(removeList[appid])removeList[appid].remove=btn.isOnList; else removeList[appid] = {name:name,remove:btn.isOnList}; toggleText(btn,btn.isOnList); } async function handleFilterClick(){ document.querySelector("#games_list_row_container").style.display = "none"; document.querySelectorAll("#games_list_rows .gameListRow").forEach(row=>{ let appid = row.id.match(/\d+/)[0]; let name = row.querySelector(".gameListRowItemName").innerText; let filtered = false; //仅显示已选择 if(chkShowListed.checked)filtered = !row.querySelector(".remove_item").isOnList; //如果都没有选择,就都不筛选 if((!chkShowLimited.checked)&&(!chkShowLearning.checked)&&(!chkShowBanned.checked))filtered||=false; //如果选择至少一个,且不游戏在相应名单中,就将游戏筛选 else filtered ||=!((chkShowLimited.checked&&data.limited[appid])||(chkShowLearning.checked&&data.learning[appid])||(chkShowBanned.checked&&data.banned[appid])); $J(row).toggleClass("filtered",filtered); }); document.querySelector("#games_list_row_container").style.display = ""; } function countSelectedGames(){ let count = 0; document.querySelectorAll("#games_list_rows .gameListRow").forEach(row=>{ if(row.btn.isOnList)count++; }); document.getElementById("removeCount").innerText=count; } } function getAjaxParams(appid){ return new Promise((resolve,reject)=>{ GM_xmlhttpRequest({ url:`https://help.steampowered.com/zh-cn/wizard/HelpWithGameIssue/?appid=${appid}&issueid=123`, method:"GET", timeout:5000, onload:(res)=>{ let text = res.responseText; if(text.search("m_steamid")==-1){ reject("Steam客服页面未登录"); return; } let match = text.match(/g_sessionID = "([0-9a-zA-Z]+)";/); if(match==null){ reject("未获取到Steam客服页面SessionID"); return; } let parser = new DOMParser(); let doc = parser.parseFromString(text,"text/html"); let packageid = doc.querySelector("#packageid").value; resolve({ appid:appid, packageid:packageid, sessionid: match[1], wizard_ajax: 1, gamepad: 0 }); }, ontimeout:()=>{reject(`获取参数超时`)}, onerror:(err)=>{reject(`获取参数出错:`+JSON.stringify(err))} }) }) } function doRemovePackage(ajaxParams){ return new Promise((resolve,reject)=>{ $J.ajax({ type: 'POST', url: 'https://help.steampowered.com/zh-cn/wizard/AjaxDoPackageRemove', data: `packageid=${ajaxParams.packageid}&appid=${ajaxParams.appid}&sessionid=${ajaxParams.sessionid}&wizard_ajax=1&gamepad=0` }).fail((xhr)=>reject(`移除出错`)) .done((res)=>{ resolve(res); }) }) } })();