1232 lignes
39 Kio
JavaScript
1232 lignes
39 Kio
JavaScript
|
// ==UserScript==
|
||
|
// @name Let's panda!
|
||
|
// @namespace https://github.com/Sean2525/Let-s-panda
|
||
|
// @author sean2525, strong-Ting
|
||
|
// @description A login, view, download tool for exhentai & e-hentai
|
||
|
// @description:zh-tw 一個用於exhentai和e-hentai的登入、查看、下載的工具
|
||
|
// @description:zh-cn 一个用于exhentai和e-hentai的登录、查看、下载的工具
|
||
|
// @license MIT
|
||
|
// @require https://code.jquery.com/jquery-3.2.1.slim.min.js
|
||
|
// @include https://exhentai.org/
|
||
|
// @include https://exhentai.org/g/*
|
||
|
// @include https://e-hentai.org/g/*
|
||
|
// @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.4/jszip.min.js
|
||
|
// @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js
|
||
|
// @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
|
||
|
// @grant GM_xmlhttpRequest
|
||
|
// @grant GM.xmlHttpRequest
|
||
|
// @grant GM_setValue
|
||
|
// @grant GM_getValue
|
||
|
// @grant GM.setValue
|
||
|
// @grant GM.getValue
|
||
|
// @grant GM_notification
|
||
|
// @grant GM.notification
|
||
|
// @connect *
|
||
|
// @run-at document-end
|
||
|
// @version 0.2.17
|
||
|
// ==/UserScript==
|
||
|
|
||
|
jQuery(function ($) {
|
||
|
/**
|
||
|
* Output extension
|
||
|
* @type {String} zip
|
||
|
* cbz
|
||
|
*
|
||
|
* Tips: Convert .zip to .cbz
|
||
|
* Windows
|
||
|
* $ ren *.zip *.cbz
|
||
|
* Linux
|
||
|
* $ rename 's/\.zip$/\.cbz/' *.zip
|
||
|
*/
|
||
|
var outputExt = "zip"; // or 'cbz'
|
||
|
|
||
|
/**
|
||
|
* Multithreading
|
||
|
* @type {Number} [1 -> 32]
|
||
|
*/
|
||
|
var threading = 8;
|
||
|
|
||
|
/**
|
||
|
* Logging
|
||
|
* @type {Boolean}
|
||
|
*/
|
||
|
var debug = false;
|
||
|
|
||
|
|
||
|
var viewed = false;
|
||
|
const loginPage = () => {
|
||
|
let div = document.createElement("div");
|
||
|
div.className = "main";
|
||
|
let username = document.createElement("input");
|
||
|
let style = document.createElement("style");
|
||
|
style.innerHTML = `
|
||
|
body {
|
||
|
background-color: #212121;
|
||
|
}
|
||
|
.main {
|
||
|
display: -webkit-flex;
|
||
|
display: flex;
|
||
|
-webkit-flex-direction: column;
|
||
|
flex-direction: column;
|
||
|
-webkit-align-items: center;
|
||
|
align-items: center;
|
||
|
-webkit-justify-content: center;
|
||
|
justify-content: center;
|
||
|
height: ${window.innerHeight}px;
|
||
|
}
|
||
|
.flex-center{
|
||
|
display: -webkit-flex;
|
||
|
display: flex;
|
||
|
-webkit-align-items: center;
|
||
|
align-items: center;
|
||
|
-webkit-justify-content: center;
|
||
|
justify-content: center;
|
||
|
}
|
||
|
form {
|
||
|
display: -webkit-flex;
|
||
|
display: flex;
|
||
|
-webkit-flex-direction: column;
|
||
|
flex-direction: column;
|
||
|
-webkit-align-items: center;
|
||
|
align-items: center;
|
||
|
-webkit-justify-content: center;
|
||
|
justify-content: center;
|
||
|
}
|
||
|
.image {
|
||
|
position: relative;
|
||
|
margin: 0;
|
||
|
}
|
||
|
.input {
|
||
|
margin-top: 10px;
|
||
|
display: block;
|
||
|
height: 34px;
|
||
|
padding: 6px 12px;
|
||
|
font-size: 14px;
|
||
|
line-height: 1.42857143;
|
||
|
color: #555;
|
||
|
background-color: #fff;
|
||
|
background-image: none;
|
||
|
border: 1px solid #ccc;
|
||
|
border-radius: 4px;
|
||
|
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
|
||
|
box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
|
||
|
-webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
|
||
|
-o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
|
||
|
transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
|
||
|
}
|
||
|
.btn {
|
||
|
color: #fff;
|
||
|
background-color: #5cb85c;
|
||
|
border-color: #4cae4c;
|
||
|
margin-top: 10px;
|
||
|
display: inline-block;
|
||
|
font-weight: 400;
|
||
|
line-height: 1.25;
|
||
|
text-align: center;
|
||
|
white-space: nowrap;
|
||
|
vertical-align: middle;
|
||
|
-webkit-user-select: none;
|
||
|
-moz-user-select: none;
|
||
|
-ms-user-select: none;
|
||
|
user-select: none;
|
||
|
border: 1px solid transparent;
|
||
|
padding: .5rem 1rem;
|
||
|
font-size: 1rem;
|
||
|
border-radius: .25rem;
|
||
|
-webkit-transition: all .2s ease-in-out;
|
||
|
-o-transition: all .2s ease-in-out;
|
||
|
transition: all .2s ease-in-out;
|
||
|
}
|
||
|
.btn:hover {
|
||
|
background-color: #4da64d;
|
||
|
}
|
||
|
.btn-blue {
|
||
|
color: #fff;
|
||
|
background-color: #3832dd;
|
||
|
border-color: #3832dd;
|
||
|
display: inline-block;
|
||
|
font-weight: 400;
|
||
|
line-height: 1.0;
|
||
|
text-align: center;
|
||
|
white-space: nowrap;
|
||
|
vertical-align: middle;
|
||
|
-webkit-user-select: none;
|
||
|
-moz-user-select: none;
|
||
|
-ms-user-select: none;
|
||
|
user-select: none;
|
||
|
border: 1px solid transparent;
|
||
|
padding: .5rem 1rem;
|
||
|
font-size: 1rem;
|
||
|
border-radius: .25rem;
|
||
|
-webkit-transition: all .2s ease-in-out;
|
||
|
-o-transition: all .2s ease-in-out;
|
||
|
transition: all .2s ease-in-out;
|
||
|
}
|
||
|
.btn-blue:hover {
|
||
|
background-color: #1c15c8;
|
||
|
}
|
||
|
`;
|
||
|
$("head").append(style);
|
||
|
const setCookie = (headers) => {
|
||
|
//
|
||
|
try {
|
||
|
headers
|
||
|
.split("\r\n")
|
||
|
.find((x) => x.match("cookie"))
|
||
|
.replace("set-cookie: ", "")
|
||
|
.split("\n")
|
||
|
.map(
|
||
|
(x) =>
|
||
|
(document.cookie = x.replace(".e-hentai.org", ".exhentai.org") + " secure")
|
||
|
);
|
||
|
} catch (err) {
|
||
|
if (debug) console.log(err);
|
||
|
}
|
||
|
document.cookie =
|
||
|
"yay=; expires=Thu, 01 Jan 1970 00:00:00 UTC; domain=.exhentai.org; path=/; secure";
|
||
|
|
||
|
setTimeout(function () { window.location.reload() }, 3000);
|
||
|
};
|
||
|
const clearCookie = () => {
|
||
|
if (debug) console.log("Clearning cookies");
|
||
|
document.cookie =
|
||
|
"yay=; expires=Thu, 01 Jan 1970 00:00:00 UTC; domain=.exhentai.org; path=/; secure";
|
||
|
window.location.reload();
|
||
|
};
|
||
|
let form = document.createElement("form");
|
||
|
let login = document.createElement("button");
|
||
|
let wrapper = document.createElement("div");
|
||
|
let loadding = document.createElement("img");
|
||
|
let password = document.createElement("input");
|
||
|
username.placeholder = "Username"
|
||
|
password.placeholder = "Password"
|
||
|
let info = document.createElement("p");
|
||
|
let error = document.createElement("p");
|
||
|
info.innerHTML = `
|
||
|
<center>
|
||
|
If you can't log in, please visit the <a target="_blank" href="https://forums.e-hentai.org/index.php?act=Login&CODE=00" class='btn-blue'>Forums</a> and log in from there. <br >
|
||
|
Please make sure you are logged in successfully and then click this <button class="clearCookie btn-blue">button</button>
|
||
|
</center>
|
||
|
`;
|
||
|
info.style.color = "white";
|
||
|
username.type = "text";
|
||
|
username.className = "input";
|
||
|
password.type = "password";
|
||
|
password.className = "input";
|
||
|
loadding.src =
|
||
|
"data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==";
|
||
|
loadding.style.position = "relative";
|
||
|
info.hidden = true;
|
||
|
loadding.hidden = true;
|
||
|
login.addEventListener("click", () => {
|
||
|
loadding.hidden = false;
|
||
|
GM.xmlHttpRequest({
|
||
|
method: "POST",
|
||
|
url: "https://forums.e-hentai.org/index.php?act=Login&CODE=01",
|
||
|
data: `referer=https://forums.e-hentai.org/index.php?&b=&bt=&UserName=${username.value}&PassWord=${password.value}&CookieDate=1"}`,
|
||
|
headers: {
|
||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||
|
},
|
||
|
onload: function (response) {
|
||
|
if (debug) console.log(response);
|
||
|
if (/You are now logged/.exec(response.responseText)) {
|
||
|
error.style = "color:green";
|
||
|
error.innerText = "Login succeeded: you will be redirected to exhentai.org in 3 seconds, if you can't access exhentai, don't use private browsing. "
|
||
|
GM.notification("You will be redirected to exhentai.org in 3 seconds; if you can't access exhentai, don't use private browsing", "Login succeeded");
|
||
|
setCookie(response.responseHeaders);
|
||
|
} else if (/IF YOU DO NOT SEE THE CAPTCHA/.exec(response.responseText)) {
|
||
|
error.style = "color:red";
|
||
|
error.innerText = "Login failed: Please visit the forums directly and log in from there; reCaptcha has been enabled."
|
||
|
}
|
||
|
else {
|
||
|
error.style = "color:red";
|
||
|
error.innerText = "Login failed: Please check that your username and password are correct.";
|
||
|
}
|
||
|
info.hidden = false;
|
||
|
loadding.hidden = true;
|
||
|
},
|
||
|
onerror: function (err) {
|
||
|
console.error(err);
|
||
|
error.style = "color:red";
|
||
|
error.innerText("Login got error: Please contact me at https://github.com/MinoLiu/Let-s-panda/issues");
|
||
|
loadding.hidden = true;
|
||
|
},
|
||
|
});
|
||
|
});
|
||
|
login.className = "btn";
|
||
|
login.innerHTML = "Login";
|
||
|
form.append(username);
|
||
|
form.append(password);
|
||
|
wrapper.className = "flex-center";
|
||
|
wrapper.append(loadding);
|
||
|
wrapper.append(login);
|
||
|
form.append(wrapper);
|
||
|
form.addEventListener("submit", (e) => {
|
||
|
e.preventDefault();
|
||
|
});
|
||
|
var image = document.createElement("img");
|
||
|
image.className = "image";
|
||
|
image.src = "https://i.imgur.com/oX86mGf.png"
|
||
|
div.append(image);
|
||
|
div.append(form);
|
||
|
div.append(error);
|
||
|
div.append(info);
|
||
|
$("body").append(div);
|
||
|
$(".clearCookie").on("click", clearCookie);
|
||
|
};
|
||
|
|
||
|
const downloadPage = () => {
|
||
|
var zip = new JSZip(),
|
||
|
doc = document,
|
||
|
tit = doc.title,
|
||
|
$win = $(window),
|
||
|
loc = /https?:\/\/e[x-]hentai\.org\/g\/\d+\/\w+/.exec(doc.location.href)[0],
|
||
|
prevZip = false,
|
||
|
current = 0,
|
||
|
images = [],
|
||
|
total = 0,
|
||
|
final = 0,
|
||
|
failed = 0,
|
||
|
hrefs = [],
|
||
|
comicId = location.pathname.match(/\d+/)[0],
|
||
|
download = document.createElement("p");
|
||
|
|
||
|
const dlImg = ({ index, url, _ }, success, error) => {
|
||
|
var filename = url.replace(/.*\//g, "");
|
||
|
var extension = filename.split(".").pop();
|
||
|
filename = ("0000" + index).slice(-4) + "." + extension;
|
||
|
if (debug) console.log(filename, "progress");
|
||
|
GM.xmlHttpRequest({
|
||
|
method: "GET",
|
||
|
url: url,
|
||
|
responseType: "arraybuffer",
|
||
|
onload: function (response) {
|
||
|
final++;
|
||
|
success(response, filename);
|
||
|
},
|
||
|
onerror: function (err) {
|
||
|
final++;
|
||
|
error(err, filename);
|
||
|
},
|
||
|
});
|
||
|
};
|
||
|
|
||
|
const next = () => {
|
||
|
download.innerHTML = `<span style="margin-left:10px;">▶</span> <a href="#"> Downloading ${final}/${total}</a>`;
|
||
|
if (debug) console.log(final, current);
|
||
|
if (final < current) return;
|
||
|
final < total ? addZip() : genZip();
|
||
|
};
|
||
|
|
||
|
const end = () => {
|
||
|
$win.off("beforeunload");
|
||
|
if (failed > 0) {
|
||
|
alert("Some pages download failed, please unzip and check!");
|
||
|
}
|
||
|
if (debug) console.timeEnd("eHentai");
|
||
|
};
|
||
|
|
||
|
const genZip = () => {
|
||
|
zip
|
||
|
.generateAsync({
|
||
|
type: "blob",
|
||
|
})
|
||
|
.then(function (blob) {
|
||
|
var zipName =
|
||
|
tit.replace(/\s/g, "_") + "." + comicId + "." + outputExt;
|
||
|
|
||
|
if (prevZip) window.URL.revokeObjectURL(prevZip);
|
||
|
prevZip = blob;
|
||
|
|
||
|
saveAs(blob, zipName);
|
||
|
if (debug) console.log("COMPLETE");
|
||
|
download.innerHTML = `<span style="margin-left:10px;">▶</span> <a href="${window.URL.createObjectURL(
|
||
|
prevZip
|
||
|
)}" download="${zipName}"> Download completed!</a>`;
|
||
|
end();
|
||
|
});
|
||
|
};
|
||
|
|
||
|
const addZip = () => {
|
||
|
total = images.length;
|
||
|
var max = current + threading;
|
||
|
if (max > total) max = total;
|
||
|
for (current; current < max; current++) {
|
||
|
let _href = images[current];
|
||
|
dlImg(
|
||
|
_href,
|
||
|
function (response, filename) {
|
||
|
zip.file(filename, response.response);
|
||
|
if (debug) console.log(filename, "image success");
|
||
|
next();
|
||
|
},
|
||
|
function (err, filename) {
|
||
|
final--;
|
||
|
// retry backupUrl for once
|
||
|
GM.xmlHttpRequest({
|
||
|
method: "GET",
|
||
|
url: _href.backupUrl,
|
||
|
onload: function (response) {
|
||
|
let imgNo = parseInt(
|
||
|
response.responseText.match("startpage=(\\d+)").pop()
|
||
|
);
|
||
|
let img = new DOMParser()
|
||
|
.parseFromString(response.responseText, "text/html")
|
||
|
.querySelector("#img");
|
||
|
if (debug) console.log(imgNo, "backupUrl success");
|
||
|
_href.url = img.src;
|
||
|
dlImg(
|
||
|
_href,
|
||
|
function (response, filename) {
|
||
|
zip.file(filename, response.response);
|
||
|
if (debug) console.log(filename, "backupUrl image success");
|
||
|
next();
|
||
|
},
|
||
|
function (err, filename) {
|
||
|
failed++;
|
||
|
zip.file(
|
||
|
filename + "_" + comicId + "_error.gif",
|
||
|
"R0lGODdhBQAFAIACAAAAAP/eACwAAAAABQAFAAACCIwPkWerClIBADs=",
|
||
|
{
|
||
|
base64: true,
|
||
|
}
|
||
|
);
|
||
|
if (debug) console.log(filename, "backupUrl image error");
|
||
|
next();
|
||
|
}
|
||
|
);
|
||
|
},
|
||
|
onerror: function (err, filename) {
|
||
|
dlImg(
|
||
|
_href,
|
||
|
function (response, filename) {
|
||
|
zip.file(filename, response.response);
|
||
|
if (debug) console.log(filename, "retry image success");
|
||
|
next();
|
||
|
},
|
||
|
function (err, filename) {
|
||
|
failed++;
|
||
|
zip.file(
|
||
|
filename + "_" + comicId + "_error.gif",
|
||
|
"R0lGODdhBQAFAIACAAAAAP/eACwAAAAABQAFAAACCIwPkWerClIBADs=",
|
||
|
{
|
||
|
base64: true,
|
||
|
}
|
||
|
);
|
||
|
if (debug) console.log(filename, "retry url error");
|
||
|
next();
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Update image download status.
|
||
|
*/
|
||
|
const getImageNext = () => {
|
||
|
download.innerHTML = `<span style="margin-left:10px;">▶</span> <a href="#">Getting images ${final}/${hrefs.length}</a>`;
|
||
|
if (debug) console.log(final, current);
|
||
|
if (final < current) return;
|
||
|
final < hrefs.length
|
||
|
? getImage()
|
||
|
: (() => {
|
||
|
current = 0;
|
||
|
final = 0;
|
||
|
addZip();
|
||
|
})();
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Get all images from hrefs.
|
||
|
*/
|
||
|
const getImage = () => {
|
||
|
let max = current + threading;
|
||
|
if (max > hrefs.length) max = hrefs.length;
|
||
|
for (current; current < max; current++) {
|
||
|
if (debug) console.log(hrefs[current]);
|
||
|
let href = hrefs[current];
|
||
|
GM.xmlHttpRequest({
|
||
|
method: "GET",
|
||
|
url: hrefs[current],
|
||
|
onload: function (response) {
|
||
|
let imgNo = parseInt(
|
||
|
response.responseText.match("startpage=(\\d+)").pop()
|
||
|
);
|
||
|
let img = new DOMParser()
|
||
|
.parseFromString(response.responseText, "text/html")
|
||
|
.querySelector("#img");
|
||
|
if (debug) console.log(imgNo, "url success");
|
||
|
let src = href + "?nl=" + /nl\(\'(.*)\'\)/.exec(img.attributes.onerror.value)[1];
|
||
|
images.push({
|
||
|
index: imgNo,
|
||
|
url: img.src,
|
||
|
backupUrl: src,
|
||
|
});
|
||
|
final++;
|
||
|
getImageNext();
|
||
|
},
|
||
|
onerror: function (err) {
|
||
|
final++;
|
||
|
getImageNext();
|
||
|
if (debug) console.log(err);
|
||
|
},
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Get the href of all images from all pages.
|
||
|
*/
|
||
|
const getHref = () => {
|
||
|
childNodes = document.querySelector("table[class=ptt] tbody tr")
|
||
|
.childNodes;
|
||
|
let page = parseInt(
|
||
|
childNodes[childNodes.length - 2].textContent.replace(",", "")
|
||
|
);
|
||
|
for (let i = 0; i < page; i++) {
|
||
|
GM.xmlHttpRequest({
|
||
|
method: "GET",
|
||
|
url: `${loc}?p=${i}`,
|
||
|
onload: function (response) {
|
||
|
if (debug)
|
||
|
console.log(`page ${loc}?p=${i} detect ${response.responseText}`);
|
||
|
let imgs = [
|
||
|
...new DOMParser()
|
||
|
.parseFromString(response.responseText, "text/html")
|
||
|
.querySelectorAll(".gdtm a"),
|
||
|
];
|
||
|
if (!imgs.length)
|
||
|
imgs = [
|
||
|
...new DOMParser()
|
||
|
.parseFromString(response.responseText, "text/html")
|
||
|
.querySelectorAll(".gdtl a"),
|
||
|
];
|
||
|
if (!imgs.length) {
|
||
|
alert(
|
||
|
"There are some issue in the script\nplease open an issue on Github\nhttps://github.com/MinoLiu/Let-s-panda/issues"
|
||
|
);
|
||
|
}
|
||
|
imgs.forEach((v) => {
|
||
|
hrefs.push(v.href);
|
||
|
});
|
||
|
if (i == page - 1) {
|
||
|
getImage();
|
||
|
}
|
||
|
},
|
||
|
onerror: function (err) {
|
||
|
download.innerHTML =
|
||
|
'<span style="margin-left:10px;">▶</span> <a href="#">Get href failed</a>';
|
||
|
if (i == page - 1) {
|
||
|
getImage();
|
||
|
}
|
||
|
if (debug) console.log(err);
|
||
|
},
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
download.className = "g3";
|
||
|
download.innerHTML = `<span style="margin-left:10px;">▶</span> <a class="panda_download" href="#">Download</a>`;
|
||
|
$("#gd5").append(download);
|
||
|
$(".panda_download").on("click", () => {
|
||
|
if (threading < 1) threading = 1;
|
||
|
if (threading > 32) threading = 32;
|
||
|
if (debug) console.time("eHentai");
|
||
|
$win.on("beforeunload", function () {
|
||
|
return "Progress is running...";
|
||
|
});
|
||
|
download.innerHTML = `<span style="margin-left:10px;">▶</span> <a href="#">Start Download</a>`;
|
||
|
getHref();
|
||
|
});
|
||
|
};
|
||
|
|
||
|
|
||
|
function view() {
|
||
|
viewed = true;
|
||
|
if (threading < 1) threading = 1;
|
||
|
if (threading > 32) threading = 32;
|
||
|
var gdt = document.querySelector("#gdt");
|
||
|
var gdd = document.querySelector("#gdd");
|
||
|
var gdo4 = document.createElement("div");
|
||
|
gdo4.setAttribute("id", "gdo4");
|
||
|
$("body").append(gdo4);
|
||
|
|
||
|
let childNodes = document.querySelector("table[class=ptt] tbody tr")
|
||
|
.childNodes;
|
||
|
let lpPage = parseInt(
|
||
|
childNodes[childNodes.length - 2].textContent.replace(",", "")
|
||
|
);
|
||
|
|
||
|
var data = document
|
||
|
.querySelector("body div.gtb p.gpc")
|
||
|
.textContent.split(" ");
|
||
|
|
||
|
var minPic = parseInt(data[1].replace(",", ""));
|
||
|
var maxPic = parseInt(data[3].replace(",", ""));
|
||
|
|
||
|
var imgNum = parseInt(
|
||
|
gdd
|
||
|
.querySelector("#gdd tr:nth-child(n+6) td.gdt2")
|
||
|
.textContent.split(" ")[0]
|
||
|
);
|
||
|
|
||
|
|
||
|
viewer(lpPage, imgNum, minPic, maxPic);
|
||
|
|
||
|
async function viewer(lpPage, imgNum, minPic, maxPic) {
|
||
|
var Gallery = function (pageNum, imgNum, minPic, maxPic) {
|
||
|
this.pageNum = pageNum || 0;
|
||
|
this.imgNum = imgNum || 0;
|
||
|
this.loc = /https?:\/\/e[x-]hentai\.org\/g\/\d+\/\w+/.exec(location.href)[0];
|
||
|
this.padding = false;
|
||
|
this.current = 0;
|
||
|
this.final = 0;
|
||
|
};
|
||
|
var viewAll = await GM.getValue("view_all", true);
|
||
|
Gallery.prototype = {
|
||
|
imgHref: [],
|
||
|
imgList: [],
|
||
|
retry: 0,
|
||
|
getAllHref: function (nextID) {
|
||
|
if (nextID >= this.pageNum) {
|
||
|
this.loadNextImage();
|
||
|
return;
|
||
|
}
|
||
|
var that = this;
|
||
|
GM.xmlHttpRequest({
|
||
|
method: "GET",
|
||
|
url: `${this.loc}?p=${nextID}`,
|
||
|
onload: function (response) {
|
||
|
if (debug)
|
||
|
console.log(`page ${that.loc}?p=${nextID} detect ${response.responseText}`);
|
||
|
let imgs = [
|
||
|
...new DOMParser()
|
||
|
.parseFromString(response.responseText, "text/html")
|
||
|
.querySelectorAll(".gdtm a"),
|
||
|
];
|
||
|
if (!imgs.length)
|
||
|
imgs = [
|
||
|
...new DOMParser()
|
||
|
.parseFromString(response.responseText, "text/html")
|
||
|
.querySelectorAll(".gdtl a"),
|
||
|
];
|
||
|
if (!imgs.length) {
|
||
|
alert(
|
||
|
"There are some issue in the script\nplease open an issue on Github\nhttps://github.com/MinoLiu/Let-s-panda/issues"
|
||
|
);
|
||
|
}
|
||
|
imgs.forEach((v) => {
|
||
|
that.imgHref.push(v.href);
|
||
|
});
|
||
|
that.getAllHref(nextID + 1);
|
||
|
},
|
||
|
onerror: function (err) {
|
||
|
if (debug) console.log(err);
|
||
|
that.retry++;
|
||
|
if (that.retry > 2) {
|
||
|
alert(`Page number ${nextID + 1} load failed for 3 times.`);
|
||
|
that.getAllHref(nextID + 1);
|
||
|
} else {
|
||
|
that.getAllHref(nextID);
|
||
|
}
|
||
|
},
|
||
|
});
|
||
|
},
|
||
|
getHref: function (pageID) {
|
||
|
var that = this;
|
||
|
GM.xmlHttpRequest({
|
||
|
method: "GET",
|
||
|
url: `${this.loc}?p=${pageID}`,
|
||
|
onload: function (response) {
|
||
|
if (debug)
|
||
|
console.log(`page ${that.loc}?p=${pageID} detect ${response.responseText}`);
|
||
|
let imgs = [
|
||
|
...new DOMParser()
|
||
|
.parseFromString(response.responseText, "text/html")
|
||
|
.querySelectorAll(".gdtm a"),
|
||
|
];
|
||
|
if (!imgs.length)
|
||
|
imgs = [
|
||
|
...new DOMParser()
|
||
|
.parseFromString(response.responseText, "text/html")
|
||
|
.querySelectorAll(".gdtl a"),
|
||
|
];
|
||
|
if (!imgs.length) {
|
||
|
alert(
|
||
|
"There are some issue in the script\nplease open an issue on Github\nhttps://github.com/MinoLiu/Let-s-panda/issues"
|
||
|
);
|
||
|
}
|
||
|
imgs.forEach((v) => {
|
||
|
that.imgHref.push(v.href);
|
||
|
});
|
||
|
that.loadNextImage();
|
||
|
},
|
||
|
onerror: function (err) {
|
||
|
if (debug) console.log(err);
|
||
|
that.retry++;
|
||
|
if (that.retry > 2) {
|
||
|
alert(`Page number ${nextID + 1} load failed for 3 times.`);
|
||
|
that.loadNextImage();
|
||
|
} else {
|
||
|
that.getHref(nextID);
|
||
|
}
|
||
|
},
|
||
|
});
|
||
|
},
|
||
|
checkFunctional: function () {
|
||
|
return (this.imgNum > 41 && this.pageNum < 2) || this.imgNum !== 0;
|
||
|
},
|
||
|
loadNextImage: function () {
|
||
|
if (this.final < this.current) {
|
||
|
return;
|
||
|
}
|
||
|
this.loadPageUrls();
|
||
|
},
|
||
|
onSucceed: async function (response, href) {
|
||
|
let imgNo = parseInt(
|
||
|
response.responseText.match("startpage=(\\d+)").pop()
|
||
|
);
|
||
|
let img = new DOMParser()
|
||
|
.parseFromString(response.responseText, "text/html")
|
||
|
.querySelector("#img");
|
||
|
if (debug) console.log(imgNo, "success");
|
||
|
let src = href + "?nl=" + /nl\(\'(.*)\'\)/.exec(img.attributes.onerror.value)[1];
|
||
|
Gallery.prototype.imgList[imgNo - 1].setAttribute(
|
||
|
"data-href",
|
||
|
src
|
||
|
);
|
||
|
|
||
|
let timeoutId;
|
||
|
let timeoutDuration = 10000; // 10s
|
||
|
|
||
|
timeoutId = setTimeout(function () {
|
||
|
// timeout trigger error
|
||
|
Gallery.prototype.imgList[imgNo - 1].childNodes[0].dispatchEvent(new Event('error'));
|
||
|
}, timeoutDuration);
|
||
|
|
||
|
$(Gallery.prototype.imgList[imgNo - 1].childNodes[0]).on("load", function () {
|
||
|
// success clear timeoutId
|
||
|
clearTimeout(timeoutId);
|
||
|
});
|
||
|
|
||
|
$(Gallery.prototype.imgList[imgNo - 1].childNodes[0]).on(
|
||
|
"error",
|
||
|
function () {
|
||
|
var ajax = new XMLHttpRequest();
|
||
|
ajax.onreadystatechange = async function () {
|
||
|
if (debug) {
|
||
|
console.log(`Failed load ${Number(imgNo)}, getting backup image from ${src}.`);
|
||
|
}
|
||
|
if (4 == ajax.readyState && 200 == ajax.status) {
|
||
|
var _imgNo = parseInt(
|
||
|
ajax.responseText.match("startpage=(\\d+)").pop()
|
||
|
);
|
||
|
var imgDom = new DOMParser()
|
||
|
.parseFromString(ajax.responseText, "text/html")
|
||
|
.getElementById("img");
|
||
|
Gallery.prototype.imgList[_imgNo - 1].childNodes[0].src =
|
||
|
imgDom.src;
|
||
|
}
|
||
|
};
|
||
|
ajax.open("GET", src);
|
||
|
ajax.send(null);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
Gallery.prototype.imgList[imgNo - 1].childNodes[0].src = img.src;
|
||
|
|
||
|
this.loadNextImage();
|
||
|
},
|
||
|
onFailed: function (err, href) {
|
||
|
GM.xmlHttpRequest({
|
||
|
method: "GET",
|
||
|
url: href,
|
||
|
responseType: "document",
|
||
|
onload: function (response) {
|
||
|
that.onSucceed(response, href);
|
||
|
},
|
||
|
onerror: function (err) {
|
||
|
if (debug) console.log(err);
|
||
|
this.loadNextImage();
|
||
|
},
|
||
|
});
|
||
|
},
|
||
|
loadPageUrls: function () {
|
||
|
if (debug) {
|
||
|
console.log("load work");
|
||
|
}
|
||
|
let max = threading + this.current > this.imgHref.length ? this.imgHref.length : threading + this.current;
|
||
|
for (this.current; this.current < max; this.current++) {
|
||
|
let that = this;
|
||
|
let href = this.imgHref[this.current];
|
||
|
GM.xmlHttpRequest({
|
||
|
method: "GET",
|
||
|
url: href,
|
||
|
responseType: "document",
|
||
|
onload: function (response) {
|
||
|
that.final++;
|
||
|
that.onSucceed(response, href);
|
||
|
},
|
||
|
onerror: function (err) {
|
||
|
if (debug) console.log(err);
|
||
|
that.final++;
|
||
|
that.onFailed(err, href);
|
||
|
},
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
cleanGDT: function () {
|
||
|
while (gdt.firstChild && gdt.firstChild.className)
|
||
|
gdt.removeChild(gdt.firstChild);
|
||
|
},
|
||
|
|
||
|
generateImg: function (callback) {
|
||
|
for (var i = 0; i < this.imgNum; i++) {
|
||
|
if (i < maxPic && i >= minPic - 1) {
|
||
|
var img = document.createElement("img");
|
||
|
var a = document.createElement("a");
|
||
|
img.setAttribute("src", "https://ehgt.org/g/roller.gif");
|
||
|
img.setAttribute("loadding", "lazy");
|
||
|
a.appendChild(img);
|
||
|
this.imgList.push(a);
|
||
|
|
||
|
gdt.appendChild(a);
|
||
|
} else {
|
||
|
var img = document.createElement("img");
|
||
|
var a = document.createElement("a");
|
||
|
|
||
|
img.setAttribute("src", "https://ehgt.org/g/roller.gif");
|
||
|
img.setAttribute("loadding", "lazy");
|
||
|
a.appendChild(img);
|
||
|
|
||
|
this.imgList.push(a);
|
||
|
if (viewAll) gdt.appendChild(a);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gdt.style.textAlign = "center";
|
||
|
gdt.style.maxWidth = "100%";
|
||
|
|
||
|
gdo4.innerHTML = ""; //clear origin button(Normal Large)
|
||
|
|
||
|
var style = document.createElement("style");
|
||
|
style.type = "text/css";
|
||
|
style.innerHTML = `
|
||
|
div#gdo4{
|
||
|
position:fixed;
|
||
|
width: 212px;
|
||
|
height:32px;
|
||
|
left:unset;
|
||
|
right:10px;
|
||
|
bottom:0px;
|
||
|
top:unset;
|
||
|
text-align:right;
|
||
|
z-index:1;
|
||
|
background:#34353b;
|
||
|
border-radius:5%;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
.double {
|
||
|
font-weight: bold;
|
||
|
// margin: 0 2px 4px 2px;
|
||
|
float: left;
|
||
|
border-radius: 5px;
|
||
|
height:32px;
|
||
|
width: 32px;
|
||
|
//border: 1px solid #989898;
|
||
|
//background: #4f535b;
|
||
|
background-image: url(https://raw.githubusercontent.com/MinoLiu/Let-s-panda/master/icons/2_32.png);
|
||
|
}
|
||
|
|
||
|
.double:hover{
|
||
|
background: #4f535b;
|
||
|
background-image: url(https://raw.githubusercontent.com/MinoLiu/Let-s-panda/master/icons/2_32.png);
|
||
|
}
|
||
|
|
||
|
.single{
|
||
|
font-weight: bold;
|
||
|
// margin: 0 2px 4px 2px;
|
||
|
float: left;
|
||
|
border-radius: 5px;
|
||
|
height:32px;
|
||
|
width: 32px;
|
||
|
//border: 1px solid #989898;
|
||
|
// background: #4f535b;
|
||
|
background-image: url(https://raw.githubusercontent.com/MinoLiu/Let-s-panda/master/icons/1_32.png);
|
||
|
}
|
||
|
|
||
|
.size_pic{
|
||
|
font-weight: bold;
|
||
|
// margin: 0 2px 4px 2px;
|
||
|
float: left;
|
||
|
border-radius: 2px;
|
||
|
height:16px;
|
||
|
width: 16px;
|
||
|
//border: 1px solid #989898;
|
||
|
// background: #4f535b;
|
||
|
}
|
||
|
|
||
|
.single:hover{
|
||
|
background: #4f535b;
|
||
|
background-image: url(https://raw.githubusercontent.com/MinoLiu/Let-s-panda/master/icons/1_32.png);
|
||
|
|
||
|
}
|
||
|
|
||
|
.size_btn {
|
||
|
height: 32px;
|
||
|
width: 32px;
|
||
|
border-radius: 100%;
|
||
|
//font-family: Arial;
|
||
|
color: #ffffff;
|
||
|
font-size: 16px;
|
||
|
background: #4f535b;
|
||
|
text-decoration: none;
|
||
|
}
|
||
|
|
||
|
|
||
|
.pad_pic {
|
||
|
height: 32px;
|
||
|
width: 32px;
|
||
|
border-radius: 100%;
|
||
|
//font-family: Arial;
|
||
|
color: #ffffff;
|
||
|
font-size: 16px;
|
||
|
background: #4f535b;
|
||
|
text-decoration: none;
|
||
|
}
|
||
|
|
||
|
.size_btn:hover {
|
||
|
background: #a9adb1;
|
||
|
text-decoration: none;
|
||
|
}
|
||
|
`;
|
||
|
document.getElementsByTagName("head")[0].appendChild(style);
|
||
|
|
||
|
//show
|
||
|
|
||
|
var single_pic = document.createElement("div"); //create single button
|
||
|
single_pic.className = "single";
|
||
|
single_pic.innerHTML += "";
|
||
|
gdo4.appendChild(single_pic);
|
||
|
|
||
|
var double_pic = document.createElement("div"); //create double button
|
||
|
double_pic.className = "double";
|
||
|
double_pic.innerHTML = "";
|
||
|
gdo4.appendChild(double_pic);
|
||
|
|
||
|
var pad_pic = document.createElement("button");
|
||
|
pad_pic.className = "pad_pic";
|
||
|
pad_pic.innerHTML += "p";
|
||
|
gdo4.appendChild(pad_pic);
|
||
|
|
||
|
var full_pic = document.createElement("button");
|
||
|
full_pic.className = "pad_pic";
|
||
|
full_pic.innerHTML += "f";
|
||
|
gdo4.appendChild(full_pic);
|
||
|
|
||
|
var size_pic_reduce = document.createElement("button");
|
||
|
size_pic_reduce.className = "size_btn";
|
||
|
size_pic_reduce.innerHTML += "-";
|
||
|
gdo4.appendChild(size_pic_reduce);
|
||
|
|
||
|
var size_pic_add = document.createElement("button");
|
||
|
size_pic_add.className = "size_btn";
|
||
|
size_pic_add.innerHTML += "+";
|
||
|
gdo4.appendChild(size_pic_add);
|
||
|
|
||
|
document
|
||
|
.getElementById("gdo4")
|
||
|
.children[0] //when single button click change value of width
|
||
|
.addEventListener("click", async function (event) {
|
||
|
await GM.setValue("width", "0.7");
|
||
|
await GM.setValue("mode", "single");
|
||
|
await pic_width(await GM.getValue("width"));
|
||
|
$("wrap").remove();
|
||
|
|
||
|
wrap(await GM.getValue("width"));
|
||
|
});
|
||
|
|
||
|
document
|
||
|
.getElementById("gdo4")
|
||
|
.children[1] //when double button click change value of width
|
||
|
.addEventListener("click", async function (event) {
|
||
|
await GM.setValue("width", "0.49");
|
||
|
await GM.setValue("mode", "double");
|
||
|
let view_reverse = await GM.getValue("view_reverse", true);
|
||
|
GM.setValue("view_reverse", !view_reverse);
|
||
|
await pic_width(await GM.getValue("width"));
|
||
|
$("wrap").remove();
|
||
|
|
||
|
wrap(await GM.getValue("mode"));
|
||
|
});
|
||
|
|
||
|
var pad_img = document.createElement("img");
|
||
|
var pad_a = document.createElement("a");
|
||
|
pad_a.appendChild(pad_img);
|
||
|
|
||
|
document
|
||
|
.getElementById("gdo4")
|
||
|
.children[2].addEventListener("click", async (event) => {
|
||
|
this.padding = !this.padding;
|
||
|
const view_reverse = await GM.getValue("view_reverse", true);
|
||
|
await GM.setValue("view_reverse", false);
|
||
|
$("wrap").remove();
|
||
|
await wrap(await GM.getValue("mode"));
|
||
|
$("wrap").remove();
|
||
|
if (this.padding) {
|
||
|
this.imgList.unshift(pad_a);
|
||
|
gdt.insertBefore(pad_a, gdt.firstChild);
|
||
|
} else {
|
||
|
this.imgList.shift();
|
||
|
gdt.removeChild(pad_a);
|
||
|
}
|
||
|
await GM.setValue("view_reverse", view_reverse);
|
||
|
await wrap(await GM.getValue("mode"));
|
||
|
});
|
||
|
|
||
|
document
|
||
|
.getElementById("gdo4")
|
||
|
.children[3].addEventListener("click", async function (event) {
|
||
|
await GM.setValue("full_image", true);
|
||
|
await pic_width(0);
|
||
|
});
|
||
|
|
||
|
document
|
||
|
.getElementById("gdo4")
|
||
|
.children[4].addEventListener("click", async function (event) {
|
||
|
await GM.setValue("full_image", false);
|
||
|
var size_width = parseFloat(await GM.getValue("width"));
|
||
|
if (size_width > 0.2 && size_width < 1.5) {
|
||
|
size_width = size_width - 0.1;
|
||
|
GM.setValue("width", size_width);
|
||
|
}
|
||
|
let _width = await GM.getValue("width");
|
||
|
await pic_width(_width);
|
||
|
console.log(_width);
|
||
|
});
|
||
|
|
||
|
document
|
||
|
.getElementById("gdo4")
|
||
|
.children[5].addEventListener("click", async function (event) {
|
||
|
await GM.setValue("full_image", false);
|
||
|
var size_width = parseFloat(await GM.getValue("width"));
|
||
|
if (size_width > 0.1 && size_width < 1.4) {
|
||
|
size_width = size_width + 0.1;
|
||
|
GM.setValue("width", size_width);
|
||
|
}
|
||
|
let _width = await GM.getValue("width");
|
||
|
await pic_width(_width);
|
||
|
console.log(_width);
|
||
|
});
|
||
|
|
||
|
async function pic_width(
|
||
|
width //change width of pics
|
||
|
) {
|
||
|
for (var i = maxPic - minPic + 1; i > 0; i--) {
|
||
|
await resizeImg(width);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
callback && callback();
|
||
|
},
|
||
|
};
|
||
|
var g = new Gallery(lpPage, imgNum, minPic, maxPic);
|
||
|
|
||
|
if (g.checkFunctional()) {
|
||
|
var viewAll = await GM.getValue("view_all", true);
|
||
|
g.generateImg(function () {
|
||
|
if (g.pageNum && viewAll) {
|
||
|
g.getAllHref(0);
|
||
|
} else {
|
||
|
g.getHref(Number(document.querySelector("td.ptds").childNodes[0].text) - 1);
|
||
|
}
|
||
|
g.cleanGDT();
|
||
|
});
|
||
|
|
||
|
document.addEventListener("keydown", (e) => {
|
||
|
let nextImg = null;
|
||
|
|
||
|
if (e.code === "ArrowUp") {
|
||
|
for (let i = g.imgList.length - 1; i >= 0; i--) {
|
||
|
const img = g.imgList[i].childNodes[0];
|
||
|
const rect = img.getBoundingClientRect();
|
||
|
if (rect.top < -1) {
|
||
|
nextImg = img;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (e.code === "ArrowDown") {
|
||
|
for (let i = 0; i < g.imgList.length; i++) {
|
||
|
const img = g.imgList[i].childNodes[0];
|
||
|
const rect = img.getBoundingClientRect();
|
||
|
if (rect.top > 1) {
|
||
|
nextImg = img;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (nextImg !== null) {
|
||
|
e.preventDefault();
|
||
|
window.scrollTo({
|
||
|
top: nextImg.offsetTop,
|
||
|
});
|
||
|
}
|
||
|
})
|
||
|
|
||
|
await wrap(await GM.getValue("mode"));
|
||
|
} else {
|
||
|
alert(
|
||
|
"There are some issue in the script\nplease open an issue on Github\nhttps://github.com/MinoLiu/Let-s-panda/issues"
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var switchWrap = false;
|
||
|
|
||
|
const wrap = async (width) => {
|
||
|
let img = $("#gdt").find("a");
|
||
|
let gdt = document.getElementById("gdt");
|
||
|
if (switchWrap == true) {
|
||
|
for (let i = 0; i < img.length - 1; i++) {
|
||
|
if (i % 2 !== 1) {
|
||
|
gdt.insertBefore(img[i + 1], img[i]);
|
||
|
}
|
||
|
}
|
||
|
switchWrap = false;
|
||
|
}
|
||
|
|
||
|
if ((await GM.getValue("width")) == undefined) {
|
||
|
await GM.setValue("width", "0.49");
|
||
|
console.log("set width:0.49");
|
||
|
}
|
||
|
|
||
|
if ((await GM.getValue("mode")) == undefined) {
|
||
|
await GM.setValue("mode", "double");
|
||
|
console.log("set mode:double");
|
||
|
}
|
||
|
if ((await GM.getValue("view_reverse")) == undefined) {
|
||
|
await GM.setValue("view_reverse", true);
|
||
|
console.log("set view_reverse:true");
|
||
|
}
|
||
|
|
||
|
|
||
|
img = $("#gdt").find("a");
|
||
|
let view_reverse = (await GM.getValue("view_reverse", true));
|
||
|
for (let i = 0; i < img.length; i++) {
|
||
|
let wrap = document.createElement("wrap");
|
||
|
wrap.innerHTML = "<br>";
|
||
|
if ((await GM.getValue("mode")) == "single") {
|
||
|
gdt.insertBefore(wrap, img[i]);
|
||
|
} else if ((await GM.getValue("mode")) == "double") {
|
||
|
if (i % 2 !== 1) {
|
||
|
gdt.insertBefore(wrap, img[i]);
|
||
|
if (view_reverse && i != img.length - 1) {
|
||
|
switchWrap = true;
|
||
|
gdt.insertBefore(img[i + 1], img[i]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
await resizeImg(await GM.getValue("width"));
|
||
|
};
|
||
|
|
||
|
const resizeImg = async (width) => {
|
||
|
const full_image = (await GM.getValue("full_image"));
|
||
|
if (full_image == true) {
|
||
|
$("#gdt")
|
||
|
.find("img")
|
||
|
.css({ "height": "100vh", "width": "auto" });
|
||
|
} else {
|
||
|
$("#gdt")
|
||
|
.find("img")
|
||
|
.css({ "height": "auto", "width": $(window).width() * width });
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const adjustGmid = () => {
|
||
|
var height = $("#gd5").outerHeight(true);
|
||
|
height = height >= 330 ? height : 330;
|
||
|
$("#gmid").height(height);
|
||
|
$("#gd4").height(height);
|
||
|
};
|
||
|
|
||
|
const viewAllMode = async () => {
|
||
|
var view_all_btn = document.createElement("p");
|
||
|
var view_all = await GM.getValue("view_all", true);
|
||
|
|
||
|
view_all_btn.className = "g3";
|
||
|
view_all_btn.innerHTML = `<span style="margin-left:10px;">▶</span> <a class="panda_view_all" href="#">Viewer page(s): ${view_all ? "All" : "One"}</a>`;
|
||
|
$("#gd5").append(view_all_btn);
|
||
|
|
||
|
$(".panda_view_all").on("click", async () => {
|
||
|
view_all = await GM.getValue("view_all", true);
|
||
|
GM.setValue("view_all", !view_all);
|
||
|
$(".panda_view_all").html(
|
||
|
`Viewer page(s): ${view_all ? "All" : "One"}`
|
||
|
);
|
||
|
window.location.reload(true);
|
||
|
});
|
||
|
|
||
|
adjustGmid();
|
||
|
};
|
||
|
const viewMode = async () => {
|
||
|
var view_mode = await GM.getValue("view_mode", true);
|
||
|
var view_btn = document.createElement("p");
|
||
|
view_btn.className = "g3";
|
||
|
view_btn.innerHTML = `<span style="margin-left:10px;">▶</span> <a class="panda_view" href="#">Viewer ${view_mode ? "Enabled" : "Disabled"
|
||
|
}</a>`;
|
||
|
|
||
|
$("#gd5").append(view_btn);
|
||
|
|
||
|
$(".panda_view").on("click", async () => {
|
||
|
view_mode = await GM.getValue("view_mode", true);
|
||
|
GM.setValue("view_mode", !view_mode);
|
||
|
$(".panda_view").html(`Viewer ${!view_mode ? "Enabled" : "Disabled"}`);
|
||
|
if (view_mode) {
|
||
|
window.location.reload();
|
||
|
}
|
||
|
if (!view_mode && !viewed) {
|
||
|
viewAllMode();
|
||
|
view();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
if (view_mode) {
|
||
|
viewAllMode();
|
||
|
}
|
||
|
|
||
|
adjustGmid();
|
||
|
if (view_mode) {
|
||
|
// Stop image loadding for thumbnails.
|
||
|
var imageToStop = document.querySelector("#gdt").querySelectorAll("img");
|
||
|
imageToStop.forEach((img, key) => {
|
||
|
// Only load the first thumbnail.
|
||
|
if (key == 0) {
|
||
|
return;
|
||
|
}
|
||
|
img.src = "";
|
||
|
})
|
||
|
view();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if ((e = $("img")).length === 0 && (e = $("dev")).length === 0) {
|
||
|
loginPage();
|
||
|
} else if (window.location.href.match(/^https:\/\/e[x-]hentai\.org\/g/)) {
|
||
|
downloadPage();
|
||
|
viewMode();
|
||
|
}
|
||
|
});
|