// ==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
);