您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A modified version of E-Hentai Automated Downloads by etc. that selects between resized and uncompressed archives based on size and also ignores out of date torrents.
// ==UserScript== // @name Sensible sized E-Hentai Automated Downloads // @description A modified version of E-Hentai Automated Downloads by etc. that selects between resized and uncompressed archives based on size and also ignores out of date torrents. // @namespace https://greasyfork.org/users/212175-brozilian // @author brozilian // @include http://e-hentai.org/* // @include https://e-hentai.org/* // @include http://g.e-hentai.org/* // @include https://g.e-hentai.org/* // @include http://exhentai.org/* // @include https://exhentai.org/* // @grant GM_xmlhttpRequest // @grant GM.xmlHttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM.setValue // @grant GM.getValue // @grant GM_openInTab // @grant GM.openInTab // @run-at document-start // @version 2.5 // ==/UserScript== // Based on version 2.2.0 of E-Hentai Automated Downloads by etc see https://sleazyfork.org/en/scripts/1604-e-hentai-automated-downloads/ . // Thanks to etc/ etc 2 for the original. // TO CONFIGURE: // Go to https://exhentai.org/uconfig.php or https://e-hentai.org/uconfig.php and set the values for your personal image size limit and to enable // integration with E-H Visited or EhxVisited. Settings should appear at the top of the page. Remember to click save. // I cannot provide any guarantee for compatibility with E-H Visited or EhxVisited if either script is updated, so use at your own risk. I have switched to E // Exhvisited and disabled updates for it on my own machine to avoid any potential issues as well as keeping a backup of its data. if (typeof GM_getValue !== "undefined") { var imageSizeLimit = GM_getValue("imageSizeLimit", 1500); var imageLowSizeLimit = GM_getValue("imageLowSizeLimit", 20); //Smallest size per image in KB to reject small torrents var downloadIfNoTorrentFound = GM_getValue("downloadIfNoTorrentFound", true); var ehvisitedsetting = GM_getValue("ehvisitedsetting", false); var ehxvisitedsetting = GM_getValue("ehxvisitedsetting", false); } else if (typeof GM !== "undefined") { var imageSizeLimit = GM.getValue("imageSizeLimit", 1500); var imageLowSizeLimit = GM.getValue("imageLowSizeLimit", 20); //Smallest size per image in KB to reject small torrents var downloadIfNoTorrentFound = GM.getValue("downloadIfNoTorrentFound", true); var ehvisitedsetting = GM.getValue("ehvisitedsetting", false); var ehxvisitedsetting = GM.getValue("ehxvisitedsetting", false); } else reject(new Error("GM methods not working")); var apiurl = "https://" + window.location.host + "/api.php"; var storageName = "ehVisited"; //name of object, to avoid clash with old installs function ehvStore(data) { var sto = localStorage.getItem(storageName); var vis = JSON.parse(sto); var ccc = data.galleryId + "." + data.galleryToken; vis["data"][ccc] = Date.now(); localStorage.setItem(storageName, JSON.stringify(vis)); return; } if (localStorage.getItem(storageName) && ehvisitedsetting) { var ehvisitedcountdownloads = true; } else { var ehvisitedcountdownloads = false; } //store value for gallery size threshold if (window.location.pathname == "/uconfig.php") { var sdcheckstate = ""; if (downloadIfNoTorrentFound) { sdcheckstate = 'checked="true"'; } var ehvisitedcheckstate = ""; if (ehvisitedsetting) { ehvisitedcheckstate = 'checked="true"'; } var ehxvisitedcheckstate = ""; if (ehxvisitedsetting) { ehxvisitedcheckstate = 'checked="true"'; } var settingsdiv = document.createElement("div"); var ehvisitedsettingspan = '<span>Count downloaded galleries in E-H Visited script (requires https://sleazyfork.org/en/scripts/377945-e-h-visited )</span><input id="ehvisitedcheckbox" type="checkbox" ' + ehvisitedcheckstate + "><br>"; var ehxvisitedsettingspan = '<span>Count downloaded galleries in EhxVisited script (requires https://sleazyfork.org/en/scripts/391711-ehxvisited )</span><input id="exhvisitedcheckbox" type="checkbox" ' + ehxvisitedcheckstate + "><br>"; } if (typeof Promise === "undefined") { console.warn("Browser does not support promises, aborting."); return; } /*----------------------- Assets (icons and GIFs) -----------------------*/ var ASSETS = { downloadIcon: generateSvgIcon( 1500, "rgb(0,0,0)", "M370.333 0h200q21 0 35.5 14.5t14.5 35.5v550h291q21 0 26 11.5t-8 27.5l-427 522q-13 16-32 16t-32-16l-427-522q-13-16-8-27.5t26-11.5h291V50q0-21 14.5-35.5t35.5-14.5z" ), torrentIcon: generateSvgIcon( 1300, "rgb(0,0,0)", "M932 12.667l248 230q14 14 14 35t-14 35l-248 230q-14 14-24.5 10t-10.5-25v-150H497v-200h400v-150q0-21 10.5-25t24.5 10zm-735 365h-50q-21 0-35.5-14.5t-14.5-35.5v-100q0-21 14.5-35.5t35.5-14.5h50v200zm200 0H297v-200h100v200zm-382 365l247-230q14-14 24.5-10t10.5 25v150h400v200H297v150q0 21-10.5 25t-24.5-10l-247-230q-15-14-15-35t15-35zm882 135H797v-200h100v200zm100-200h51q20 0 34.5 14.5t14.5 35.5v100q0 21-14.5 35.5t-34.5 14.5h-51v-200z" ), doneIcon: generateSvgIcon( 1800, "rgb(0,0,0)", "M1412 734q0-28-18-46l-91-90q-19-19-45-19t-45 19l-408 407-226-226q-19-19-45-19t-45 19l-91 90q-18 18-18 46 0 27 18 45l362 362q19 19 45 19 27 0 46-19l543-543q18-18 18-45zm252 162q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z" ), loadingIcon: generateSvgIcon( 1900, "rgb(0,0,0)", "M462 1394q0 53-37.5 90.5T334 1522q-52 0-90-38t-38-90q0-53 37.5-90.5T334 1266t90.5 37.5T462 1394zm498 206q0 53-37.5 90.5T832 1728t-90.5-37.5T704 1600t37.5-90.5T832 1472t90.5 37.5T960 1600zM256 896q0 53-37.5 90.5T128 1024t-90.5-37.5T0 896t37.5-90.5T128 768t90.5 37.5T256 896zm1202 498q0 52-38 90t-90 38q-53 0-90.5-37.5T1202 1394t37.5-90.5 90.5-37.5 90.5 37.5 37.5 90.5zM494 398q0 66-47 113t-113 47-113-47-47-113 47-113 113-47 113 47 47 113zm1170 498q0 53-37.5 90.5T1536 1024t-90.5-37.5T1408 896t37.5-90.5T1536 768t90.5 37.5T1664 896zm-640-704q0 80-56 136t-136 56-136-56-56-136 56-136T832 0t136 56 56 136zm530 206q0 93-66 158.5T1330 622q-93 0-158.5-65.5T1106 398q0-92 65.5-158t158.5-66q92 0 158 66t66 158z" ), }; /*--------- Utilities ---------*/ function generateSvgIcon(size, color, data) { return format( 'url("data:image/svg+xml,' + "<svg width='{0}' height='{0}' viewBox='0 0 {0} {0}' xmlns='http://www.w3.org/2000/svg'>" + "<path fill='{1}' d='{2}'/></svg>\")", size, color, data ); } function createButton(data) { var result = document.createElement( data.hasOwnProperty("type") ? data.type : "a" ); if (data.hasOwnProperty("className")) result.className = data.className; if (data.hasOwnProperty("title")) result.title = data.title; if (data.hasOwnProperty("onClick")) { result.addEventListener("mousedown", data.onClick, false); result.addEventListener( "click", function (e) { e.preventDefault(); }, false ); result.addEventListener( "contextmenu", function (e) { e.preventDefault(); }, false ); } if (data.hasOwnProperty("parent")) data.parent.appendChild(result); if (data.hasOwnProperty("target")) result.setAttribute("target", data.target); if (data.hasOwnProperty("style")) result.style.cssText = Object.keys(data.style) .map(function (x) { return x + ": " + data.style[x] + "px"; }) .join("; "); return result; } function format(varargs) { var pattern = arguments[0]; for (var i = 1; i < arguments.length; ++i) pattern = pattern.replace( new RegExp("\\{" + (i - 1) + "\\}", "g"), arguments[i] ); return pattern; } function xhr(data) { return new Promise(function (resolve, reject) { var request = { method: data.method, url: data.url, onload: function () { resolve.apply(this, arguments); }, onerror: function () { reject.apply(this, arguments); }, }; if (data.headers) request.headers = data.headers; if (data.body && data.body.constructor == String) request.data = data.body; else if (data.body) request.data = JSON.stringify(data.body); if (typeof GM_xmlhttpRequest !== "undefined") GM_xmlhttpRequest(request); else if (typeof GM !== "undefined" && GM.xmlHttpRequest) GM.xmlHttpRequest(request); else reject(new Error("Could not submit XHR request")); }); } function parseHTML(html) { var div = document.createElement("div"); div.innerHTML = html.replace(/src=/g, "no-src="); return div; } function updateUI(data) { if (!data || data.error) return; var temp = data.isTorrent ? torrentQueue[data.galleryId] : archiveQueue[data.galleryId]; temp.button.className = temp.button.className.replace(/\s*working/, "") + " requested"; if (ehvisitedcountdownloads) { ehvStore(data); } if (ehxvisitedsetting) { temp.button.parentNode.parentNode.classList.add("ehx-visited"); ehxvisitedaddGallery("down", data.galleryId + "." + data.galleryToken); ehxvisitedaddGallery("galleries", data.galleryId + "." + data.galleryToken); } } function handleFailure(data) { if (!data) return; var temp = data.isTorrent ? torrentQueue[data.galleryId] : archiveQueue[data.galleryId]; temp.button.className = temp.button.className.replace(/\s*working/, ""); if ( data.error == "could not find any suitable torrent" && downloadIfNoTorrentFound ) { console.log(temp.button.previousSibling); temp.button.previousSibling.dispatchEvent(new MouseEvent("mousedown")); } else if (data.error !== "aborted") alert( "Could not complete operation.\nReason: " + (data.error || "unknown") ); } function xpathFind(root, nodeType, text) { return document.evaluate( ".//" + (nodeType || "*") + '[contains(text(), "' + text + '")]', root, null, 9, null ).singleNodeValue; } function pickTorrent(candidates) { var currentScore = 0, currentCandidate = null; // Get max values var maxSeeds = candidates.reduce(function (p, n) { return Math.max(p, n.seeds); }, 0); var maxSize = candidates.reduce(function (p, n) { return Math.max(p, n.size); }, 0); // Calculate scores candidates.forEach(function (candidate) { var seedScore = candidate.seeds / maxSeeds; var sizeScore = candidate.size / maxSize; // Total score var score = seedScore * sizeScore; //console.log(score) if (score > currentScore) { currentScore = score; currentCandidate = candidate; } }); if (currentScore == 0) { data.error = "could not find any suitable torrent"; console.log("no suitable torrent"); return Promise.reject(data); } else { console.log( "picked candidate: " + currentCandidate.link + " date: " + currentCandidate.date + " size: " + currentCandidate.size + " seeds: " + currentCandidate.seeds ); return currentCandidate; } } /*-------------- Download Steps --------------*/ //get gallery data to check date, size and length function getGalleryData(target) { return xhr({ method: "GET", url: target, }).then(function (response) { var fulldiv = parseHTML(response.responseText); var gallerySize = xpathFind( fulldiv, "td", "File Size:" ).nextSibling.textContent.trim(); gallerySize = parseFloat(gallerySize) * (/MiB/i.test(gallerySize) ? 1024 : /GiB/i.test(gallerySize) ? 1024 * 1024 : 1); //in KB var galleryLength = xpathFind(fulldiv, "td", "Length:") .nextSibling.textContent.trim() .split(" ")[0]; var galleryDate = new Date( xpathFind(fulldiv, "td", "Posted:").nextSibling.textContent.trim() ); return [galleryDate, gallerySize, galleryLength]; }); } /* //mock GM_xmlhttpRequest code for troubleshooting function GM_xmlhttpRequest(details) { fetch(details.url, { method: details.method || 'GET', headers: details.headers, body: details.data, }) .then(response => response.text()) .then(data => details.onload({ responseText: data })) .catch(error => details.onerror(error)); } */ function ehxvisitedaddGallery(store, gid) { const request = indexedDB.open("ehxvisited", 2); request.onupgradeneeded = (e) => { // Generate our database if it's not there db = e.target.result; if (!db.objectStoreNames.contains("galleries")) db.createObjectStore("galleries", { keyPath: "id" }); if (!db.objectStoreNames.contains("hidden")) db.createObjectStore("hidden", { keyPath: "id" }); if (!db.objectStoreNames.contains("down")) db.createObjectStore("down", { keyPath: "id" }); }; request.onsuccess = (e) => { db = e.target.result; var objStore = db.transaction(store, "readwrite").objectStore(store); var openRequest = objStore.openCursor(gid); openRequest.onsuccess = (e) => { var cursor = openRequest.result; if (cursor) { // Update entry if key exists cursor.update({ id: gid, visited: Date.now() }); console.log("EhxVisited: Updated " + gid); } else { // Otherwise, add entry objStore.add({ id: gid, visited: Date.now() }); console.log("EhxVisited: Added " + gid); } }; openRequest.onerror = (e) => { console.log( `EhxVisited: Something bad happened with gallery ${gid}: ${e.target.error}` ); }; }; } function obtainTorrentFile(data) { return xhr({ method: "GET", url: format( "{0}//{1}/gallerytorrents.php?gid={2}&t={3}", window.location.protocol, window.location.host, data.galleryId, data.galleryToken ), }).then(function (response) { var div = parseHTML(response.responseText); var forms = div.querySelectorAll("form"), candidates = [], size = 0; for (var i = 0; i < forms.length - 1; ++i) { size = xpathFind( forms[i], "span", "Size:" ).nextSibling.textContent.trim(); size = parseFloat(size) * (/MiB/i.test(size) ? 1024 : /GiB/i.test(size) ? 1024 * 1024 : 1); var posted = xpathFind( forms[i], "span", "Posted:" ).nextSibling.nextSibling.textContent.trim(); posted = new Date(posted); var seeds = xpathFind( forms[i], "span", "Seeds:" ).nextSibling.textContent.trim(); seeds = parseInt(seeds, 10) || 0; var link = forms[i].querySelector("a"); if (!link) continue; console.log( "link: " + link.href + " date: " + posted + " size: " + size + " seeds: " + seeds ); if (posted - data.date < 0) { console.log("old torrent"); continue; } if (size < imageLowSizeLimit) { console.log("low torrent size"); continue; } if (size > data.galleryLength * imageSizeLimit) { console.log("large torrent size"); continue; } if (seeds == 0) { console.log("no seeds"); continue; } candidates.push({ link: link.href, date: posted, size: size, seeds: seeds, }); console.log( "candidate link: " + link.href + " date: " + posted + " size: " + size + " seeds: " + seeds ); } if (candidates.length === 0) { data.error = "could not find any suitable torrent"; console.log("no suitable torrent"); return Promise.reject(data); } else { data.fileUrl = pickTorrent(candidates).link; return data; } }); } function confirmDownloadRequest(data) { return xhr({ method: "GET", url: format( "{0}//{1}/archiver.php?gid={2}&token={3}", window.location.protocol, window.location.host, data.galleryId, data.galleryToken ), }).then(function (response) { var div = parseHTML(response.responseText); if (data.gallerySize / data.galleryLength < imageSizeLimit) { var costLabel = div.querySelector( 'input[value="Download Original Archive"]' ).parentNode.parentNode.previousSibling.previousSibling; var sizeLabel = div.querySelector( 'input[value="Download Original Archive"]' ).parentNode.parentNode.nextSibling.nextSibling; } else { var costLabel = div.querySelector( 'input[value="Download Resample Archive"]' ).parentNode.parentNode.previousSibling.previousSibling; var sizeLabel = div.querySelector( 'input[value="Download Resample Archive"]' ).parentNode.parentNode.nextSibling.nextSibling; } if (!costLabel || !sizeLabel) return data; var cost = costLabel.textContent.replace(/^.+:/, "").trim(); var size = sizeLabel.textContent.replace(/^.+:/, "").trim(); var proceed = confirm( format("Size: {0}\nCost: {1}\n\nProceed?", size, cost) ); if (proceed) return data; data.error = "aborted"; return Promise.reject(data); }); } function submitDownloadRequest(data) { var bodytext = "dltype=org&dlcheck=Download+Original+Archive"; if (data.gallerySize / data.galleryLength > imageSizeLimit) { bodytext = "dltype=res&dlcheck=Download+Resample+Archive"; } return xhr({ method: "POST", url: format( "{0}//{1}/archiver.php?gid={2}&token={3}", window.location.protocol, window.location.host, data.galleryId, data.galleryToken ), headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: bodytext, }).then(function (response) { var div = parseHTML(response.responseText); var url, target = div.querySelector("#continue > a"); if (target) url = target.href; else { var targets = div.querySelectorAll("script"); for (var i = 0; i < targets.length; ++i) { var match = targets[i].textContent.match(/location\s*=\s*"(.+?)"/); if (!match) continue; url = match[1]; break; } } if (url) data.archiverUrl = url; else data.error = "could not resolve archiver URL"; if (data.error) return Promise.reject(data); else return data; }); } function waitForDownloadLink(data) { return xhr({ method: "GET", url: data.archiverUrl, }) .then(function (response) { if (/The file was successfully prepared/i.test(response.responseText)) { var div = parseHTML(response.responseText); var target = div.querySelector("#db a"); if (target) { var archiverUrl = new URL(data.archiverUrl); data.fileUrl = archiverUrl.protocol + "//" + archiverUrl.host + target.getAttribute("href"); } else data.error = "could not resolve file URL"; } else data.error = "archiver did not provide file URL"; if (data.error) return Promise.reject(data); else return data; }) .catch(function () { if (data.error) return Promise.reject(data); data.error = "could not contact archiver"; if (/https/.test(window.location.protocol)) { data.error += "; this is most likely caused by mixed-content security policies enforced by the" + " browser that need to be disabled by the user. If you have no clue how to do that, you" + ' should probably Google "how to disable mixed-content blocking".'; } else { data.error += "; please check whether your browser is not blocking XHR requests towards" + " 3rd-party URLs"; } return Promise.reject(data); }); } function downloadFile(data) { downloadQueue = downloadQueue.then(function () { if (typeof GM_openInTab !== "undefined") GM_openInTab(data.fileUrl, true); else if (typeof GM !== "undefined" && GM.openInTab) GM.openInTab(data.fileUrl, true); else { var a = document.createElement("a"); a.href = data.fileUrl; document.body.appendChild(a); a.click(); document.body.removeChild(a); } return new Promise(function (resolve) { setTimeout(resolve, 500); }); }); return Promise.resolve(data); } /*---------------- State Management ----------------*/ var archiveQueue = {}, torrentQueue = {}; var downloadQueue = Promise.resolve(); async function requestDownload(e) { var isTorrent = /torrentLink/.test(e.target.className); if (/working|requested/.test(e.target.className)) return; if (isTorrent && e.which !== 1) return; e.preventDefault(); e.stopPropagation(); e.target.className += " working"; var tokens = e.target .getAttribute("target") .match(/\/g\/(\d+)\/([0-9a-z]+)/i); var galleryId = parseInt(tokens[1], 10), galleryToken = tokens[2]; var askConfirmation = !isTorrent && e.which === 3; if (!isTorrent) { archiveQueue[galleryId] = { token: galleryToken, button: e.target }; //modifying to get gallery data and pass on to further logic in archive selection if (window.location.href == e.target.getAttribute("target")) { var gallerySize = xpathFind( document, "td", "File Size:" ).nextSibling.textContent.trim(); gallerySize = parseFloat(gallerySize) * (/MiB/i.test(gallerySize) ? 1024 : /GiB/i.test(gallerySize) ? 1024 * 1024 : 1); //in KB var galleryLength = xpathFind(document, "td", "Length:") .nextSibling.textContent.trim() .split(" ")[0]; var galleryDate = new Date( xpathFind(document, "td", "Posted:").nextSibling.textContent.trim() ); } else { var [galleryDate, gallerySize, galleryLength] = await getGalleryData( e.target.getAttribute("target") ); } var promise = Promise.resolve({ galleryId: galleryId, galleryToken: galleryToken, date: galleryDate, gallerySize: gallerySize, galleryLength: galleryLength, isTorrent: false, }); if (askConfirmation) promise = promise.then(confirmDownloadRequest); promise .then(submitDownloadRequest) .then(waitForDownloadLink) .then(downloadFile) .then(updateUI) .catch(handleFailure); } else { // Try to find out gallery's last update date if possible // Gather data torrentQueue[galleryId] = { token: galleryToken, button: e.target }; if (window.location.href == e.target.getAttribute("target")) { var gallerySize = xpathFind( document, "td", "File Size:" ).nextSibling.textContent.trim(); gallerySize = parseFloat(gallerySize) * (/MiB/i.test(gallerySize) ? 1024 : /GiB/i.test(gallerySize) ? 1024 * 1024 : 1); //in KB var galleryLength = xpathFind(document, "td", "Length:") .nextSibling.textContent.trim() .split(" ")[0]; var galleryDate = new Date( xpathFind(document, "td", "Posted:").nextSibling.textContent.trim() ); } else { var [galleryDate, gallerySize, galleryLength] = await getGalleryData( e.target.getAttribute("target") ); } obtainTorrentFile({ galleryId: galleryId, galleryToken: galleryToken, isTorrent: true, date: galleryDate, gallerySize: gallerySize, galleryLength: galleryLength, }) .then(downloadFile) .then(updateUI) .catch(handleFailure); } return false; } /*-------- UI Setup --------*/ window.addEventListener( "load", function () { // button generation (thumbnail / extended) var thumbnails = document.querySelectorAll(".gl3t, .gl1e > div"), n = thumbnails.length; while (n-- > 0) { createButton({ title: "Automated download", target: thumbnails[n].querySelector("a").href, className: "automatedButton downloadLink", onClick: requestDownload, style: { bottom: 0, right: -2 }, parent: thumbnails[n], }); createButton({ title: "Torrent download", target: thumbnails[n].querySelector("a").href, className: "automatedButton torrentLink", onClick: requestDownload, style: { bottom: 0, left: -1 }, parent: thumbnails[n], }); } // button generation (compact) var crows = document.querySelectorAll(".gl3c > a"), n = crows.length; while (n-- > 0) { createButton({ type: "div", title: "Automated download", target: crows[n].href, className: "automatedButton downloadLink", onClick: requestDownload, style: { bottom: 0, right: -1 }, parent: crows[n].parentNode, }); createButton({ type: "div", title: "Torrent download", target: crows[n].href, className: "automatedButton torrentLink", onClick: requestDownload, style: { bottom: 23, right: -1 }, parent: crows[n].parentNode, }); } //button generation (minimal and minimal+) var rows = document.querySelectorAll(".gl3m > a"), n = rows.length; while (n-- > 0) { createButton({ type: "div", title: "Automated download", target: rows[n].href, className: "automatedButton downloadLink", onClick: requestDownload, style: { position: "absolute", bottom: 0, right: 0, zIndex: 10 }, parent: rows[n].parentNode, }); createButton({ type: "div", title: "Torrent download", target: rows[n].href, className: "automatedButton torrentLink", onClick: requestDownload, style: { position: "absolute", bottom: 0, right: 23, zIndex: 10 }, parent: rows[n].parentNode, }); } // button generation (gallery) var bigThumbnail = document.querySelector("#gd5"); if (bigThumbnail !== null) { createButton({ title: "Automated download", target: window.location.href, className: "automatedButton downloadLink", onClick: requestDownload, style: { "margin-top": 23, "margin-left": 30 }, parent: bigThumbnail, }); createButton({ title: "Torrent download", target: window.location.href, className: "automatedButton torrentLink", onClick: requestDownload, style: { "margin-top": 23 }, parent: bigThumbnail, }); } // document style var style = document.createElement("style"); style.innerHTML = // Icons and colors ".downloadLink:not(.working) { background-image: " + ASSETS.downloadIcon + "; background-color: rgb(220,98,98); background-position: 7px 7px; }" + ".torrentLink:not(.working) { background-image: " + ASSETS.torrentIcon + "; background-color: rgb(98,182,210); background-position: 5px 6px; }" + ".requested { background-image: " + ASSETS.doneIcon + " !important; background-position: 4px 5px !important; }" + ".requested { background-color: rgba(128,226,126,1) !important; }" + ".working { background-color: rgba(255,128,192,1) !important; }" + ".working:before {" + 'content: ""; top: 1px; left: 0; width: 28px; height: 28px; position: absolute; animation: eh-spin 2s linear infinite;' + "background-image: " + ASSETS.loadingIcon + "; background-size: 20px 20px; background-position: 5px 5px; background-repeat: no-repeat;" + "}" + ".automatedButton:hover { background-color: rgba(255,199,139,1) }" + // Positioning "#gd1 > div, .gl3t, .gl1e > div { position: relative; }" + // Backgrounds ".automatedButton { background-size: 20px 20px; background-repeat: no-repeat; }" + // Others (thumbnail mode) ".automatedButton {" + "position: absolute; text-align: left; cursor: pointer;" + "color: white; margin-right: 1px; font-size: 20px; line-height: 11px; width: 28px; height: 28px;" + "}" + ".automatedButton.downloadLink { border-radius: 0 0 5px 0 !important; }" + ".automatedButton.torrentLink { border-radius: 0 0 0 5px !important; }" + "#gd1 > div > .automatedButton { border-radius: 0 0 0 0 !important; }" + ".automatedButton.working { font-size: 0px; }" + "#gd1 > div .automatedButton, .gl3t .automatedButton, .gl1e > div .automatedButton, .automatedButton.working, .automatedButton.requested { display: block !important; }" + "@keyframes eh-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }" + "@-webkit-keyframes eh-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }" + "@-moz-keyframes eh-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }"; document.head.appendChild(style); if (window.location.pathname == "/uconfig.php") { settingsdiv.innerHTML = "<h2>Sensible sized E-Hentai Automated Downloads settings</h2><br><span>Image size limit in KB. Default is 1500 i.e. 1.5MB </span>" + '<input id="imagesizeconfig" type="text" value=' + imageSizeLimit + " ><br><span>Start a direct download if no appropriate torrent is " + 'available </span><input id="autodownload" type="checkbox" ' + sdcheckstate + "><br>" + ehvisitedsettingspan + ehxvisitedsettingspan + '<input type="button" id="savescriptsettings" value="Save">'; document .getElementById("outer") .insertBefore(settingsdiv, document.getElementById("profile_outer")); document .getElementById("savescriptsettings") .addEventListener("click", function () { if (isNaN(document.getElementById("imagesizeconfig").value)) { alert("Needs to be a number"); } else if (typeof GM_setValue !== "undefined") { GM_setValue( "downloadIfNoTorrentFound", document.getElementById("autodownload").checked ); GM_setValue( "ehvisitedsetting", document.getElementById("ehvisitedcheckbox").checked ); GM_setValue( "ehxvisitedsetting", document.getElementById("exhvisitedcheckbox").checked ); GM_setValue( "imageSizeLimit", document.getElementById("imagesizeconfig").value ); } else if (typeof GM !== "undefined") { GM.setValue( "downloadIfNoTorrentFound", document.getElementById("autodownload").checked ); GM.setValue( "ehvisitedsetting", document.getElementById("ehvisitedcheckbox").checked ); GM.setValue( "ehxvisitedsetting", document.getElementById("exhvisitedcheckbox").checked ); GM.setValue( "imageSizeLimit", document.getElementById("imagesizeconfig").value ); } else reject(new Error("GM methods not working")); }); } }, false );