NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @namespace https://openuserjs.org/users/Weinur2 // @name Gamebanana trashed files search // @description https://gamebanana.com/search?mid=SearchResults&query=&game=*§ion=* // @copyright 2021, Weinur2 (https://openuserjs.org/users/Weinur2) // @license MIT // @version 0.0.0 // @author Weinur // @match https://gamebanana.com/search?mid=SearchResults&query=&game=*&vl[page]=*§ion=* // @require https://code.jquery.com/jquery-3.5.1.min.js // @run-at document-start // @grant GM_setValue // @grant GM_getValue // @grant GM_listValues // ==/UserScript== var saveItem = "gwitems"; var loadString = ""; var currentItems = {}; var usedFastMethod = false; function toNumber(number, float = false) { var typeOfNumber = typeof number; switch(typeOfNumber) { case "number": return number; break; case "string": return float ? parseFloat(number) : parseInt(number, 10); break; case "default": return -1; break; } return -1; } function toInt(number) { return Math.round(toNumber(number)); } function toFloat(number) { return toNumber(number, true); } function log(message, varName, debug) { if(varName) { message = varName + ": " + message; } if(debug) { alert(message); } else { console.log(message); } } function copyToClipboard (text) { if (navigator.clipboard) { // default: modern asynchronous API return navigator.clipboard.writeText(text); } else if (window.clipboardData && window.clipboardData.setData) { // for IE11 window.clipboardData.setData('Text', text); return Promise.resolve(); } else { // workaround: create dummy input var input = $('<input type="text" value="test">'); input.val(text); document.body.append(input.get(0)); input.focus(); input.select(); document.execCommand('copy'); input.remove(); return Promise.resolve(); } } function startLoading(start = true) { $("body, html").toggleClass("loading", start); } function startProgress(start = true) { $("body, html").toggleClass("progress", start); } function getPercentValueFloat(loaded, total) { return loaded / total * 100; } function getPercentValue(loaded, total) { return Math.round(getPercentValueFloat(loaded, total)); } function setProgressBarValue(value, start = false) { if(start) startProgress(); $(".progressSpinner").css("--progress-percent", value); } function getCurrentProgressBarValue() { return toInt($(".progressSpinner").css("--progress-percent")); } function addProgressBarValue(value, stop = false, stopTimeout = 0) { var currentPercent = getCurrentProgressBarValue(); var nextPercent = Math.round(currentPercent + value); nextPercent = nextPercent >= 100 ? 100 : nextPercent; setProgressBarValue(nextPercent); if(stop && nextPercent == 100) { setTimeout(function() { startProgress(false); }, stopTimeout); } } function setProgressBarValueFloat(value) { $(".progressSpinner").css("--progress-percent-float", value); } function getCurrentProgressBarValueFloat() { return toFloat($(".progressSpinner").css("--progress-percent-float")); } function addProgressBarValueFloat(value, stop = false, stopTimeout = 0) { var currentPercent = getCurrentProgressBarValueFloat(); var nextPercent = currentPercent + value; nextPercent = nextPercent >= 100 ? 100 : nextPercent; var nextPercentRound = Math.round(nextPercent); setProgressBarValueFloat(nextPercent); setProgressBarValue(nextPercentRound); if(stop && nextPercentRound == 100) { setTimeout(function() { startProgress(false); setProgressBarValue(0); setProgressBarValueFloat(0); }, stopTimeout); } } function deleteMe(percent, itemType, id) { var record = $(this).closest("record"); if(!record.length) { var ele = "a.we" + itemType + "Id_" + id; record = $(ele).closest("record"); } if(record.length) { record.remove(); } addProgressBarValueFloat(percent, true, 1000); log("buja"); } function save(itemType, id, set) { var item = itemType + "_" + id; currentItems[item] = set; GM_setValue(item, set); } function saveItems() { var newItems = {}; var items = currentItems; for (let key of Object.keys(items)) { let value = currentItems[key]; if(value !== undefined) newItems[key] = value; } for (let key of GM_listValues()) { let value = GM_getValue(key); if(value !== undefined) newItems[key] = value; } currentItems = newItems; var saveString = btoa(JSON.stringify(newItems)); localStorage.setItem(saveItem, saveString); return saveString; } function load() { if(loadString !== "") { currentItems = JSON.parse(atob(loadString)); } var saveString = saveItems(); console.log("saveThis (to clipboard):"); console.log(saveString); copyToClipboard(saveString); } //load(); function getCurrentItem(itemType, id) { return currentItems[itemType + "_" + id]; } function fetchURLEx(url, callbackTrue, callbackFalse, callbackError) { const myInit = { method: 'GET', headers: { 'pragma': 'no-cache', 'cache-control': 'no-cache', 'sec-ch-ua': '"Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"', 'origin': 'https://gamebanana.com', 'sec-ch-ua-mobile': '?0', 'sec-fetch-site': 'cross-site', 'sec-fetch-mode': 'cors', 'sec-fetch-dest': 'font', 'referer': 'https://fonts.googleapis.com/', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', 'accept': '*/*', 'x-client-data': 'CIe2yQEIorbJAQjEtskBCKmdygEI0qDKAQj4x8oBCLKaywEI5JzLAQioncsB', 'accept-language': 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7', 'accept-encoding': 'gzip, deflate, br', } }; let myRequest = new Request(url, myInit); fetch(myRequest).then(function(response) { if(!response.ok) { throw Error(response.statusText); } return response.text(); }).then(function(text) { var trashed = text.indexOf("TrashNoticeModule") >= 0; var private = text.indexOf("PrivateAccessNoticeModule") >= 0; if(trashed || private) { callbackTrue(trashed, private); } else { callbackFalse(); } }).catch(function(error) { callbackError(error); }); } function callbackFileDownload(percent, itemType, id, itemTypes, trashed, private) { $(this).data("itemType", itemType) .data("id", id) .data("itemTypes", itemTypes) .toggleClass("fileDownload", true) .toggleClass("trashedFile", trashed) .toggleClass("privateFile", private); addProgressBarValueFloat(percent, true, 1000); } function downloadURLEx(url, fileName, mirror) { setProgressBarValue(0, true); var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'blob'; xhr.onprogress = function(pe) { console.log('progress'); if (pe.lengthComputable) { var percent = getPercentValue(pe.loaded, pe.total); setProgressBarValue(percent >= 99 ? 99 : percent); } }; xhr.onload = function(e) { if (this.status == 200) { addProgressBarValue(100, true, 1000); var blob = this.response; //TODO fallback needed for IE8 & IE9 if (navigator.appVersion.toString().indexOf('.NET') > 0) { //IE 10+ window.navigator.msSaveBlob(blob, fileName); } else { //Firefox, Chrome var a = document.createElement("a"); var blobUrl = window.URL.createObjectURL(new Blob([blob], {type: blob.type})); document.body.appendChild(a); a.style = "display: none"; a.href = blobUrl; a.download = fileName; a.click(); $(a).remove(); } } else if(mirror) { downloadURLEx(mirror, fileName); } else { addProgressBarValue(100, true, 1000); } }; xhr.send(); } function callbackFiles(itemType, id, item, itemTypes) { $(Object.keys(item)).each(function() { var downloadURL = item[this]; var downloadURL_ = "https://files.gamebanana.com/" + itemTypes + "/" + this; downloadURLEx(downloadURL_, this, itemTypes, downloadURL); }); } function downloadFiles(itemType, id, itemTypes) { var item = getCurrentItem(itemType + "_files", id); if(item !== undefined) { if(item) callbackFiles(itemType, id, item, itemTypes); return; } $.getJSON("https://api.gamebanana.com/Core/Item/Data", { itemtype: itemType, fields: "Files().aFiles()", itemid: id, }, function(response) { var downloadLinks = {}; $(response).each(function(i, itemI) { $(Object.keys(this)).each(function(j, itemJ) { var that = itemI[itemJ]; downloadLinks[that._sFile] = that._sDownloadUrl; }); }); item = downloadLinks; save(itemType + "_files", id, item); callbackFiles(itemType, id, item, itemTypes); }).done(function() { log('getJSON request succeeded!'); }) .fail(function(jqXHR, textStatus, errorThrown) { log('getJSON request failed! ' + textStatus); usedFastMethod = false; }) .always(function() { log('getJSON request ended!');}); } function isBan(percent, itemType, id, callback, callbackDownload, itemTypes) { var item = getCurrentItem(itemType, id); if(item !== undefined) { if(!item) { callback(percent, itemType, id); } else { callbackDownload(percent, itemType, id, itemTypes ? itemTypes : itemType.toLowerCase() + "s"); } return; } if(itemTypes) { fetchURLEx("/" + itemTypes + "/" + id, function(trashed, private) { save(itemType, id, true); callbackDownload(percent, itemType, id, itemTypes, trashed, private); }, function() { save(itemType, id, false); callback(percent, itemType, id); }, function(error) { addProgressBarValueFloat(percent, true, 1000); }); return; } $.getJSON("https://api.gamebanana.com/Core/Item/Data", { itemtype: itemType, fields: "Trash().bIsTrashed()", itemid: id, }, function(response) { log(response, "response"); var string = response.toString().toLowerCase(); var good = string.indexOf("true") >= 0; save(itemType, id, good); if(!good) { callback(percent, itemType, id); } else { callbackDownload(percent, itemType, id, itemTypes ? itemTypes : itemType.toLowerCase() + "s", true, false); } }).done(function() { log('getJSON request succeeded!'); }) .fail(function(jqXHR, textStatus, errorThrown) { log('getJSON request failed! ' + textStatus); usedFastMethod = false; addProgressBarValueFloat(percent, true, 1000); }) .always(function() { log('getJSON request ended!');}); } function getButtonHtml(id, title) { var html = `<div style="float: left; margin-left: 1em;" id="${id}Div"><button type="button" class="ExtendedContentButton" id="${id}Button"><spriteicon class="MiscIcon ShowContentIcon"></spriteicon><span>${title}</span></button></div>`; return html; } function createButtons(cssStyles) { $( ".InfiniteScroller" ).css(cssStyles).after( getButtonHtml("trashedFilesOnly", "Show trashed/private files only!") ) .after( getButtonHtml("autoScroll", "Show all elements!") ); $( "#trashedFilesOnlyDiv, #autoScrollDiv" ).css(cssStyles).css("margin-left", "1em"); } function handler(cssStyles) { if( $( "#trashedFilesOnlyDiv" ).length ) return; createButtons(cssStyles); $(window).on("scroll", function() { if( ! $( "#trashedFilesOnlyDiv" ).length ) createButtons(cssStyles); var element = $( ".InfiniteScroller" ); if(element.length) { element.css(cssStyles); } else { $( "#autoScrollDiv" ).remove(); $( "#trashedFilesOnlyDiv[style]" ).removeAttr("style"); } }); } function infiScroller() { var infi = $(".InfiniteScroller"); if(infi.length) { infi.get(0).scrollIntoView(); infi.find("button").trigger("click"); } else { $("body, html").toggleClass("loading", false); var element = $( "#trashedFilesOnlyDiv" ); if(element.length) element.get(0).scrollIntoView(); return; } window.setTimeout(infiScroller, 500); } function getCss() { var style = document.createElement("style"); style.innerHTML = ` html.loading, html.progress { overflow-y: hidden; pointer-events: none; } body.not(.loading) .loadingspinner, body:not(.progress) .progressSpinner { display: none; } body.loading, body.progress { height: 100vh; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; width: 100%; overflow-y: scroll; display: block; pointer-events: none; } body.loading:after, body.progress:after { display: block; content: ""; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: grey; pointer-events: none; z-index: 999999999999999; opacity: 0.5; } body.loading .loadingspinner { pointer-events: none; width: 200px; height: 200px; border: 20px solid transparent; border-color: #eee; border-top-color: #3E67EC; border-radius: 100%; animation: loadingspin 1s linear infinite; z-index: 10000000000000000000; left: calc(50% - 100px); top: calc(50% - 100px); position: fixed; box-sizing: border-box; } body.progress .progressSpinner { pointer-events: none; width: 250px; height: 250px; z-index: 10000000000000000000; left: calc(50% - 125px); top: calc(50% - 125px); position: fixed; box-sizing: border-box; --progress-percent: 0; --progress-percent-float: 0; display: grid; place-content: center; transform: scale(1); clip-path: circle(49%); color: #ff4d4d; width: 250px; height: 250px; } body.progress .progressSpinner:before, body.progress .progressSpinner:after { grid-row: 1; grid-column: 1; font-size: 16px; } body.progress .progressSpinner:before { border: solid 2em transparent; padding: 6em; border-radius: 50%; box-shadow: inset 0 0 0 0.5em currentcolor; --progress-slice: calc(360deg/16); --progress-s-gap: calc(0.2*var(--progress-slice)); --progress-solid: calc((1 - 0.2)*var(--progress-slice)); background: repeating-conic-gradient(from calc(.5*var(--progress-s-gap)), currentcolor 0% var(--progress-solid), transparent 0% var(--progress-slice)) border-box; filter: blur(0.5px); --progress-mask: conic-gradient(red 0% calc(var(--progress-percent)*1%), rgba(255, 0, 0, .3) 0%), linear-gradient(red, red) border-box, radial-gradient(red 0% 5.5em, transparent calc(5.5em + 1px) calc(5.75em - 1px), red 5.75em calc(6em + 1px), transparent calc(6em + 2px)); -webkit-mask: var(--progress-mask); -webkit-mask-composite: source-in, source-out; mask: var(--progress-mask); mask-composite: exclude; content: ''; } body.progress .progressSpinner:after { place-self: center; counter-reset: percent var(--progress-percent); font: 3.75em consolas, monaco, ubuntu mono, monospace; content: counter(percent) '%'; } @keyframes progress { 90%, 100% { --progress-percent: 100; } } @keyframes loadingspin { 100% { transform: rotate(360deg) } } a.Name.fileDownload { position: relative; display: block; } a.Name.fileDownload:after { display: block; position: absolute; top: 0; right: 0; bottom: 0; content: "Download"; opacity: 0.8; border-radius: 3px; font-size: var(--ButtonFontSize); font-family: var(--ButtonFontFamily); outline: none; background: var(--ButtonBackground); color: var(--ButtonFontColor); } a.Name.fileDownload:hover:after { opacity: 1.0; } a.Name.fileDownload.trashedFile:after { content: "Download (trashed)"; } a.Name.fileDownload.privateFile:after { content: "Download (private)"; } a.Name.fileDownload.trashedFile.privateFile:after { content: "Download (trashed / private)"; } `; return $(style); } function getLoading() { return $('<div class="loadingspinner"></div>'); } function getProgressBar() { return $('<div class="progressSpinner"></div>'); } function getURLParams() { var params = $(location).attr("search").split("&"); var newParams = {}; $(params).each(function(i) { var paramKeyValue = this.split("="); newParams[paramKeyValue[0]] = paramKeyValue[1]; }); return newParams; } $(document).ready(function() { var urlParams = getURLParams(); var section = urlParams["section"]; var sections = section + "s"; sections = sections.toLowerCase(); $("body").data("gwsection", section).data("gwsections", sections); getCss().appendTo("body"); getLoading().appendTo("body"); getProgressBar().appendTo("body"); var cssStyles = { "margin-top": "2em", "margin-bottom": "2em", "float": "left" }; var buttonCss = { "background": "#1c272e", "color": "var(--DefaultBlueColor)" }; handler(cssStyles); $("body").on("click", ".Controls a[title]", function() { $(".InfiniteScroller").triggerHandler("check"); }); $("body").on("mouseover touchmove touchend touchcancel check", ".InfiniteScroller", function(e) { handler(cssStyles); }); $("body").on("click", "#autoScrollDiv", function() { $("body, html").toggleClass("loading", true); infiScroller(); }); $("body").on("click", "#trashedFilesOnlyDiv", function() { setProgressBarValueFloat(0); setProgressBarValue(0, true); var selector = 'records.List recordcell a.Name[href^="https://gamebanana.com/' + sections + '/"]'; var elements = $(selector); var length = elements.length; var percent = getPercentValueFloat(1, length); elements.each(function(i) { console.log("Element: " + i); var that = this; var id = $(that).attr("href").split(sections + "/"); id = parseInt(id[1], 10); $(that).toggleClass("we" + section + "Id_" + id, true); setTimeout(function() { isBan(percent, section, id, deleteMe.bind(that), callbackFileDownload.bind(that), usedFastMethod ? false : sections); }, usedFastMethod ? 3600 : 0); }); var button = $("#trashedFilesOnlyButton").css(buttonCss); setTimeout(function() { button.filter("[style]").removeAttr("style"); }, 700); return false; }); $("body").on("click", "a.Name.fileDownload", function(event) { var element = $(this); event.preventDefault(); setProgressBarValue(0, true); downloadFiles(element.data("itemType"), element.data("id"), element.data("itemTypes")); }); });