您需要先安装一个扩展,例如 篡改猴、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 // @version 2.4 // @include http://e-hentai.org/* // @include https://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 // @run-at document-start // ==/UserScript== // // Based on version 2.1.3 of E-Hentai Automated Downloads by etc see https://sleazyfork.org/en/scripts/1604-e-hentai-automated-downloads . Thanks to etc for the original. // // // Settings can now be found at top of ehentai settings page and should persist through versions. // 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 saveDownloadsAsVisits = GM_getValue('saveDownloadsAsVisits', 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 saveDownloadsAsVisits = GM.getValue('saveDownloadsAsVisits', 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) && saveDownloadsAsVisits) { var countDownloads = true; } else var countDownloads = false; if (typeof(Promise) === 'undefined') { console.warn('Browser does not support promises, aborting.'); return; } /*----------------------- Assets (icons and GIFs) -----------------------*/ var ASSETS = { downloadIcon: generateSvgIcon(1792, 'rgb(0,0,0)', 'M1344 1344q0-26-19-45t-45-19-45 19-19 45 19 45 45 19 45-19 19-45zm256 0q0-26-19-45t-45-19-45 19-19 ' + '45 19 45 45 19 45-19 19-45zm128-224v320q0 40-28 68t-68 28h-1472q-40 0-68-28t-28-68v-320q0-40 28-68t' + '68-28h465l135 136q58 56 136 56t136-56l136-136h464q40 0 68 28t28 68zm-325-569q17 41-14 70l-448 448q-' + '18 19-45 19t-45-19l-448-448q-31-29-14-70 17-39 59-39h256v-448q0-26 19-45t45-19h256q26 0 45 19t19 45' + 'v448h256q42 0 59 39z'), torrentIcon: generateSvgIcon(1792, 'rgb(0,0,0)', 'M1216 928q0-14-9-23t-23-9h-224v-352q0-13-9.5-22.5t-22.5-9.5h-192q-13 0-22.5 9.5t-9.5 22.5v352h-224q' + '-13 0-22.5 9.5t-9.5 22.5q0 14 9 23l352 352q9 9 23 9t23-9l351-351q10-12 10-24zm640 224q0 159-112.5 2' + '71.5t-271.5 112.5h-1088q-185 0-316.5-131.5t-131.5-316.5q0-130 70-240t188-165q-2-30-2-43 0-212 150-3' + '62t362-150q156 0 285.5 87t188.5 231q71-62 166-62 106 0 181 75t75 181q0 76-41 138 130 31 213.5 135.5' + 't83.5 238.5z'), pickerIcon: generateSvgIcon(1792, 'rgb(252,0,97)', 'M1333 566q18 20 7 44l-540 1157q-13 25-42 25-4 0-14-2-17-5-25.5-19t-4.5-30l197-808-406 101q-4 1-12 1' + '-18 0-31-11-18-15-13-39l201-825q4-14 16-23t28-9h328q19 0 32 12.5t13 29.5q0 8-5 18l-171 463 396-98q8' + '-2 12-2 19 0 34 15z'), doneIcon: generateSvgIcon(1792, '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-1' + '8 46 0 27 18 45l362 362q19 19 45 19 27 0 46-19l543-543q18-18 18-45zm252 162q0 209-103 385.5t-279.5 2' + '79.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'), loadingGif: 'url(data:image/gif;base64,' + 'R0lGODlhEgASAMQaAHl5d66urMXFw3l5dpSUk5WVlKOjoq+vrsbGw6Sko7u7uaWlpbm5t3h4doiIhtLSz4aGhJaWlsbGxNHRzrC' + 'wr5SUkqKiobq6uNHRz4eHhf///wAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAaACwAAAAAEgASAAAFaq' + 'AmjmRplstyrkmbrCNFaUZtaFF0HvyhWRZNYVgwBY4BEmFJOB1NlYpJoYBpHI7RZXtZZb4ZEbd7AodFDIYVAjFJJCYA4ISoI0hyu' + 'UnAF2geDxoDgwMnfBoYiRgaDQ1WiIqPJBMTkpYaIQAAIfkEBQoAGgAsAQABABAAEAAABWSgJo4aRZEoeaxHOiqKFsyBtizopV9y' + 'nfwJ0o43MhgNKAYjZbGQJBLXKBLRIK4IaWFbEHgFUoKYoPFKRZUK6fFIORwojBxDytgzpDkdANDc8SQTExp8fBoQEGcDiwNnJA0' + 'NLiEAACH5BAUKABoALAEAAQAQABAAAAVloCaOmqKQKHmtVzpKksa2FIUiOKIxjHb8B5JgKCAFjgHUMHUkPR6u0WKhwVgx0YQ2cc' + 'W6DGCDZjKJiiwWEgCQikRQ6zWpQC+QBviBxuHQEP4EKA0NGhmGGRoVFWaHiGYjEBAuIQAAIfkEBQoAGgAsAQABABAAEAAABWSgJ' + 'o6aJJEoiaxIOj6PJsyCpigopmNyff0X0o43AgZJk0mKwSABAK4RhaJ5PqOH7GHAHUQD4ICm0YiKwCSHI7VYoDLwDClBT5Di8khE' + 'Y+gbUBAQGgWEBRoWFmYEiwRmJBUVLiEAACH5BAUKABoALAEAAQAQABAAAAVloCaO2vOQKImtWDoCgMa2koTCsDZNGuIjpIFwQBI' + 'YBahGI2UkORyukUKhyVgz0Yv2csW6thcNBBIVMRikSCRFoaAK8ALpQD+QCHiCZrHQBP4BKBUVGgmGCX6BUQaMBmUkFhYuIQAAIf' + 'kEBQoAGgAsAQABABAAEAAABWagJo4aAJAoaZrp6DjaIA/a86BZnmlNo2FADEm3GwWFJAgkNZmQIpHWSCLRFK4FKWKLIHgJUoFYo' + 'KlUpCIxabFIKRSohDxButgvJIPeoKFQNHd4JBYWGgeHBxoMDGgBjgFoJI4tIQAAIfkEBQoAGgAsAQABABAAEAAABWSgJo6a45Ao' + 'ma1ZOkaRxrYAgBZ4oUGQVtckgpBAGhgHqEol1WiQFgvX6PHQJK4JKWaLMXgNWq7GYpGKJhMShZKSSFCH+IGEqCNIgXxAo1BoBIA' + 'CKHkaF4YXf4JSh4hmIwwMLiEAACH5BAUKABoALAEAAQAQABAAAAVloCaOWhSRKFmsRToui0bMhOY4aKInWlVpmWCGZCgaSMIhyW' + 'JJQSAkCsU1AgA0h+yBarUGvgHqYDzQfKmiRoOkUKQeD9RlfiFh7hgSvS6RaPB5JAwMGgiGCBoTE2gCjQJoJI0uIQAAOw==)' }; /*--------- 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('mouseup', 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(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 (countDownloads){ ehvStore(data);} } 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) { temp.button.previousSibling.dispatchEvent(new MouseEvent("mouseup")); } 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, lastUpdateDate) { 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; if (currentScore >= score) return; currentScore = score; currentCandidate = candidate; }); return currentCandidate; } /*-------------- Download Steps --------------*/ function obtainArchiverKey(data) { return xhr({ method: 'GET', url: format('{0}//{1}/g/{2}/{3}', window.location.protocol, window.location.host, data.galleryId, data.galleryToken) }) .then(function (response) { var div = parseHTML(response.responseText); var target = div.querySelector('[onclick*="archiver.php"]'); if (target) { var tokens = target.getAttribute('onclick').match(/or=([^'"]+)/); if (tokens) data.archiverKey = tokens[1]; } return data; }).then(function (data) { if (!data.archiverKey) { return xhr({ method: 'POST', url: apiurl, body: JSON.stringify({ 'method': 'gdata', 'gidlist': [[data.galleryId, data.galleryToken]] }), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, }).then(function (response) { data.archiverKey = JSON.parse(response.responseText).gmetadata[0].archiver_key; return data; }) } else return data; }).then(function (data) { if (!data.archiverKey) data.error = 'could not resolve archiver key'; if (data.error) return Promise.reject(data); else return data; }); } 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 = []; var findValue = function (text) { var target = xpathFind(forms[i], 'span', text); return (target ? target.nextSibling.textContent.trim() : null); }; for (var i = 0; i < forms.length; ++i) { var link = forms[i].querySelector('a'); if (!link) continue; // Gather torrent data var posted = new Date(findValue('Posted')), size = findValue('Size'), seeds = parseInt(findValue('Seeds'), 10) || 0; size = parseFloat(size, 10) * (/MB/i.test(size) ? 1024 : (/GB/i.test(size) ? 1024 * 1024 : 1)); // Ignore torrents with invalid sizes or no seeds or older than newest update if (size === 0 || size < (imageLowSizeLimit * data.length) || size > (data.size * 1.05) || size > (imageSizeLimit * data.length) || seeds === 0 || (posted < data.date)) continue; candidates.push({ link: link.href, date: posted, size: size, seeds: seeds }); } if (candidates.length === 0) data.error = 'could not find any suitable torrent'; else data.fileUrl = pickTorrent(candidates, data.date).link if (data.error) return Promise.reject(data); else return data; }); } function confirmDownloadRequest(data) { return xhr({ method: 'GET', url: format('{0}//{1}/archiver.php?gid={2}&token={3}&or={4}', window.location.protocol, window.location.host, data.galleryId, data.galleryToken, data.archiverKey.replace(/--/, '-')) }) .then(function (response) { var div = parseHTML(response.responseText); var costLabel = xpathFind(div, '*', 'Download Cost:'); var sizeLabel = xpathFind(div, '*', 'Estimated Size:'); 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 confirmDownloadRequestResized(data) { return xhr({ method: 'GET', url: format('{0}//{1}/archiver.php?gid={2}&token={3}&or={4}', window.location.protocol, window.location.host, data.galleryId, data.galleryToken, data.archiverKey.replace(/--/, '-')) }) .then(function (response) { var div = parseHTML(response.responseText); var cost = document.evaluate("/div[1]/div[1]/div[2]/div/strong", div, null, 9, null).singleNodeValue.textContent.trim(); var size = document.evaluate("/div[1]/div[1]/div[2]/p/strong", div, null, 9, null).singleNodeValue.textContent.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) { return xhr({ method: 'POST', url: format('{0}//{1}/archiver.php?gid={2}&token={3}&or={4}', window.location.protocol, window.location.host, data.galleryId, data.galleryToken, data.archiverKey.replace(/--/, '-')), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'dltype=org&dlcheck=Download+Original+Archive', }) .then(function (response) { var div = parseHTML(response.responseText); var 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 submitDownloadRequestResized(data) { return xhr({ method: 'POST', url: format('{0}//{1}/archiver.php?gid={2}&token={3}&or={4}', window.location.protocol, window.location.host, data.galleryId, data.galleryToken, data.archiverKey.replace(/--/, '-')), headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'dltype=res&dlcheck=Download+Resample+Archive', }) .then(function (response) { var div = parseHTML(response.responseText); var 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) { var a = document.createElement('a'); a.href = data.fileUrl; document.body.appendChild(a); a.click(); document.body.removeChild(a); document.body.appendChild(a); return Promise.resolve(data); } function getGalleryData(target) { return xhr({ method: 'GET', url: target }).then(function (response) { var div = parseHTML(response.responseText); gallerySize = xpathFind(div, 'td', 'File Size:').nextSibling.textContent.trim(); if (gallerySize) gallerySize = parseFloat(gallerySize, 10) * (/MB/i.test(gallerySize) ? 1024 : (/GB/i.test(gallerySize) ? 1024 * 1024 : 1)); //in KB var galleryLength = xpathFind(div, 'td', 'Length:').nextSibling.textContent.trim().split(' ')[0]; var galleryDate = new Date(xpathFind(div, 'td', 'Posted:').nextSibling.textContent.trim()); return [galleryDate, gallerySize, galleryLength]; }); } /*---------------- State Management ----------------*/ var archiveQueue = {}, torrentQueue = {}; function requestDownload(e) { var isTorrent = /torrentLink/.test(e.target.className); if (/working|requested/.test(e.target.className)) return; if (e.which !== 1 && (e.which !== 3 || isTorrent)) 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) { // Try to find out gallery's last update date if possible var galleryDate = xpathFind(document, 'td', 'Posted:'); // gallery page if (galleryDate) galleryDate = galleryDate.nextSibling; else // thumbnail mode galleryDate = document.evaluate('./ancestor::tr/td[@class="itd"]', e.target, null, 9, null).singleNodeValue; if (galleryDate !== null) galleryDate = new Date(galleryDate.textContent.trim()); // Gather data torrentQueue[galleryId] = { token: galleryToken, button: e.target }; obtainTorrentFile({ galleryId: galleryId, galleryToken: galleryToken, isTorrent: true, date: galleryDate }) .then(downloadFile) .then(updateUI) .catch(handleFailure); } if (!isTorrent) { archiveQueue[galleryId] = { token: galleryToken, button: e.target }; var promise = obtainArchiverKey({ galleryId: galleryId, galleryToken: galleryToken, isTorrent: false }); if (askConfirmation) promise = promise.then(confirmDownloadRequest); promise .then(submitDownloadRequest) .then(waitForDownloadLink) .then(downloadFile) .then(updateUI) .catch(handleFailure); } return false; } async function requestDownloadResized(e) { var isTorrent = /torrentLink/.test(e.target.className); if (/working|requested/.test(e.target.className)) return; if (e.which !== 1 && (e.which !== 3 || isTorrent)) 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 (window.location.href == e.target.getAttribute('target')) { var gallerySize = xpathFind(document, 'td', 'File Size:').nextSibling.textContent.trim(); if (gallerySize) gallerySize = parseFloat(gallerySize, 10) * (/MB/i.test(gallerySize) ? 1024 : (/GB/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')); } if (isTorrent) { // Gather data torrentQueue[galleryId] = { token: galleryToken, button: e.target }; obtainTorrentFile({ galleryId: galleryId, galleryToken: galleryToken, isTorrent: true, date: galleryDate, size: gallerySize, length: galleryLength }) .then(downloadFile) .then(updateUI) .catch(handleFailure); } if (!isTorrent) { if ((gallerySize / galleryLength) < imageSizeLimit) { archiveQueue[galleryId] = { token: galleryToken, button: e.target }; var promise = obtainArchiverKey({ galleryId: galleryId, galleryToken: galleryToken, isTorrent: false }); if (askConfirmation) promise = promise.then(confirmDownloadRequest); promise .then(submitDownloadRequest) .then(waitForDownloadLink) .then(downloadFile) .then(updateUI) .catch(handleFailure); } else { archiveQueue[galleryId] = { token: galleryToken, button: e.target }; var promise = obtainArchiverKey({ galleryId: galleryId, galleryToken: galleryToken, isTorrent: false }); if (askConfirmation) promise = promise.then(confirmDownloadRequestResized); promise .then(submitDownloadRequestResized) .then(waitForDownloadLink) .then(downloadFile) .then(updateUI) .catch(handleFailure); } } return false; } /*-------- UI Setup --------*/ window.addEventListener('load', function () { // document.querySelectorAll('.gl3m, .gl3c, .gl1e').forEach((button) => { // button.onclick = null // }); // button generation (thumbnail) var thumbnails = document.querySelectorAll('.gl3t'), n = thumbnails.length; while (n-- > 0) { createButton({ title: 'Automated download', target: thumbnails[n].querySelector('a').href, className: 'automatedButton downloadLink', onClick: requestDownloadResized, style: { bottom: 0, right: -2 }, parent: thumbnails[n] }); createButton({ title: 'Torrent download', target: thumbnails[n].querySelector('a').href, className: 'automatedButton torrentLink', onClick: requestDownloadResized, style: { bottom: 0, left: -1 }, parent: thumbnails[n] }); } // button generation (extended) var erows = document.querySelectorAll('.gl1e > div > a'), n = erows.length; while (n-- > 0) { createButton({ type: 'div', title: 'Automated Resized download', target: erows[n].href, className: 'automatedInline downloadLink', onClick: requestDownloadResized, style: { 'margin-left': 33 }, parent: erows[n].parentNode.parentNode.nextSibling.firstChild.firstChild.lastChild }); createButton({ type: 'div', title: 'Torrent download', target: erows[n].href, className: 'automatedInline torrentLink', onClick: requestDownloadResized, style: { 'margin-left': 10 }, parent: erows[n].parentNode.parentNode.nextSibling.firstChild.firstChild.lastChild }); } // button generation (compact) var crows = document.querySelectorAll('.gl3c > a'), n = crows.length; while (n-- > 0) { createButton({ type: 'div', title: 'Automated Resized download', target: crows[n].href, className: 'automatedInline downloadLink', onClick: requestDownloadResized, style: { bottom: 0, right: -1 }, parent: crows[n].parentNode }); createButton({ type: 'div', title: 'Torrent download', target: crows[n].href, className: 'automatedInline torrentLink', onClick: requestDownloadResized, 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 Resized download', target: rows[n].href, className: 'automatedInline downloadLink', onClick: requestDownloadResized, style: { bottom: 0, right: 0 }, parent: rows[n].parentNode }); createButton({ type: 'div', title: 'Torrent download', target: rows[n].href, className: 'automatedInline torrentLink', onClick: requestDownloadResized, style: { bottom: 0, right: 23 }, parent: rows[n].parentNode }); } // button generation (gallery) var krows = document.querySelectorAll('#gd5'), n = krows.length; while (n-- > 0) { createButton({ type: 'div', title: 'Automated resized download', target: window.location.href, className: 'automatedInline downloadLink', onClick: requestDownloadResized, style: { 'margin-left': 23 }, parent: krows[n] }); createButton({ type: 'div', title: 'Torrent download', target: window.location.href, className: 'automatedInline torrentLink', onClick: requestDownloadResized, style: { 'margin-left': 0 }, parent: krows[n] }); } // document style var style = document.createElement('style'); style.innerHTML = // Icons and colors '.downloadLink { background-image: ' + ASSETS.downloadIcon + '; background-color: rgb(220,98,98); }' + '.torrentLink { background-image: ' + ASSETS.torrentIcon + '; background-color: rgb(98,182,210); }' + '.requested { background-image: ' + ASSETS.doneIcon + '; }' + '.requested, .working { background-color: rgba(128,226,126,1); }' + '.working { background-image: ' + ASSETS.loadingGif + ' !important; background-repeat: no-repeat; }' + '.automatedPicker { background-image: ' + ASSETS.pickerIcon + '; }' + '.automatedButton:hover, .automatedInline:hover { background-color: rgba(255,199,139,1) }' + // Positioning '#gd1 > div, .gl3t, .gl1e > div { position: relative; }' + 'div.it4 { position: absolute!important; right: 0px!important; }' + //compensating for buttons 'div.it5 { position: absolute!important; left: 48px!important; height: 14px !important;}' + 'div.i { margin-left: -16px!important; }' + 'div.in { margin-left: -42px!important; margin-top: 3px!important; background: black!important; }' + 'div.in:hover { opacity: 0!important;}' + 'div.it3 { margin-top: -6px!important; }' + 'td.itu {overflow: hidden !important; position: absolute !important; height: 14px !important;}' + // Backgrounds '.automatedButton { background-size: 20px 20px; background-position: 5px 5px; background-repeat: no-repeat; }' + '.automatedPicker { background-size: 12px 12px; background-position: 2px 2px; background-repeat: no-repeat; }' + '.automatedInline { background-size: 13px 13px; background-position: 5px 5px; background-repeat: no-repeat; }' + // Others (thumbnail mode) '.automatedButton { display: none; 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:hover .automatedButton, .gl3t:hover .automatedButton, .gl1e > div:hover .automatedButton,' + ' .automatedButton.working, .automatedButton.requested { display: block !important; }' + // ' .gl3e > .gldown > a {left: -30px; position: absolute;}' + // Others (list mode) '.automatedPicker { width: 16px; height: 16px; float: left; cursor: pointer; }' + '.automatedPicker > div { display: none; z-index: 100; position: absolute; top: -4px; text-align: center; }' + '.automatedPicker:hover > div, .automatedPicker > div:hover { display: block; }' + '.automatedInline { position: absolute; z-index: 100; border: 1px solid black; width: 23px; height: 23px; display: inline-block; }' + '.automatedInline:first-child { border-right: none !important; }'; document.head.appendChild(style); //store value for gallery size threshold if (window.location.pathname == "/uconfig.php") { var sdcheckstate = ''; if (downloadIfNoTorrentFound) { sdcheckstate = 'checked="true"'; } var ehcheckstate = ''; if (saveDownloadsAsVisits) { ehcheckstate = 'checked="true"'; } var settingsdiv = document.createElement('div'); var ehvisitedsetting = '<span>Count downloaded galleries in E-H Visited script (requires https://sleazyfork.org/en/scripts/377945-e-h-visited )</span><input id="ehvisitedcountdownloads" type="checkbox" ' + ehcheckstate + '><br>'; 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>' + ehvisitedsetting + '<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('saveDownloadsAsVisits', document.getElementById("ehvisitedcountdownloads").checked); GM_setValue('imageSizeLimit', document.getElementById("imagesizeconfig").value); } else if (typeof(GM) !== 'undefined') { GM.setValue('downloadIfNoTorrentFound', document.getElementById("autodownload").checked); GM.setValue('saveDownloadsAsVisits', document.getElementById("ehvisitedcountdownloads").checked); GM.setValue('imageSizeLimit', document.getElementById("imagesizeconfig").value); } else reject(new Error('GM methods not working')); }) } }, false);