Warning: fopen(/www/sites/update.greasyfork.icu/index/store/temp/f7afdfe4f089d1468eb8ffe6010ed898.js): failed to open stream: No space left on device in /www/sites/update.greasyfork.icu/index/scriptControl.php on line 65
// ==UserScript==
// @name Google Books Preview Downloader
// @namespace https://greasyfork.org/en/users/85671-jcunews
// @version 1.0.3
// @license AGPLv3
// @author jcunews
// @description Add link to download Google Books preview pages into a ZIP file including a book viewer HTML application for use with a web browser (use web browser's zoom feature to zoom in/out pages).
// @include /^https:\/\/books\.google\.com\/books\?.*$/
// @include /^https:\/\/books\.google\.com?\.[a-z]{2}\/books\?.*$/
// @include /^https:\/\/books\.google\.[a-z]{2}\/books\?.*$/
// @require https://cdn.jsdelivr.net/gh/nindogo/tiny_zip_js@4fa0ae770e32bac5181c83d8c5c6a9f59f853e12/tiny_zip.js
// @grant none
// @downloadURL https://update.greasyfork.icu/scripts/445971/Google%20Books%20Preview%20Downloader.user.js
// @updateURL https://update.greasyfork.icu/scripts/445971/Google%20Books%20Preview%20Downloader.meta.js
// ==/UserScript==
((em, dd, dp, dt, ic, dl, rl, pi, pc, dc, tz, ns, fe, ou, z) => {
function cl(e) {
clearInterval(dt);
if (fe && (fe !== 1)) alert(em);
dp.remove();
document.body.style.pointerEvents = ""
}
function fer(e) {
fe = e;
if (--dc === 0) cl(e)
}
function html(s, e) {
(e = document.createElement("DIV")).textContent = s;
return e.innerHTML
}
function gi(ii, ti, si, ct) {
if (fe) return;
dc++;
fetch(ii.page[si].src + "&w=" + dd[1].max_resolution_image_width).then(r => ((ct = r.headers.get("content-type")), r.arrayBuffer())).then((a, b) => {
dc--;
tz.add(ns[ti] = `${("000" + (ti + 1)).substr(-4)}-${ii.page[si].pid}${
dd[0].page[ti].title ? " " + dd[0].page[ti].title.replace(/[\*:\\\|\<\>\/\?]/, "-") : ""
}.${ct ? ct.match(/\/(.*)/)[1].replace("jpeg", "jpg") : "png"}`, new Uint8Array(a));
if (++pc === dl) {
(new Blob([`
$(title)
`.replace(/\$\(dltime\)/g, (new Date).toGMTString()
).replace(/\$\(gburl\)/g, location.href.match(/^[^#]+/)[0]
).replace(/\$\(title\)/,
b = `${dd[1].title}${(si = document.querySelector('.gb-volume-title span')?.textContent?.trim()) ? ", " + si : ""
}${dd[1].publisher ? ", " + dd[1].publisher : ""}, ${dd[1].volume_id}`
).replace(/\$\(title2\)/g, html(b)
).replace(/\$\(pagemax\)/, dd[0].page.length
).replace(/\$\[([^\]]+)\]/g, "${$1}"
)], {type: "text/html"})).arrayBuffer().then(a => {
tz.add("viewer.html", new Uint8Array(a));
if (ou) URL.revokeObjectURL(ou);
(ct = document.createElement("A")).href = ou = URL.createObjectURL(tz.generate());
ct.download = `${b}.zip`;
ct.style.display = "none";
document.body.appendChild(ct).click();
ct.remove();
cl()
})
}
}).catch(fer)
}
function nx(av) {
try {
if (!confirm(
`Book preview has ${dd[0].page.length} page(s).
Rough estimated download size is ${
(() => {
if (av >= 1024*1048576) {
return parseFloat((av / 1024*1048576).toFixed(2)) + "GB"
} else if (av >= 1048576) {
return parseFloat((av / 1048576).toFixed(2)) + "MB"
} else return parseFloat((av / 1024).toFixed(2)) + "KB"
})()} based only from ${rl.length} already loaded page(s).
\nProceed with the download?`)) return;
ic = document.createElement("DIV");
dl = dd[0].page.length;
rl = Math.ceil(dl / 4);
pi = 0;
pc = 0;
dc = 0;
tz = new tiny_zip;
ns = [];
document.body.style.pointerEvents = "none";
dpp.textContent = `Retrieving pages (1/${dl})...`;
document.documentElement.append(dp);
dt = setInterval(() => (dpp.textContent = `Retrieving pages (${pc}/${dl})...`), 100);
for (let ri = 0; ri < rl; ri++) {
if (fe) break;
let i = ri;
dc++;
fetch(`/books?id=${dd[1].volume_id}&pg=${dd[0].page[i * 4].pid}&jscmd=click3`).then(r => r.json()).then((j, d, k, x, y) => {
dc--;
if (fe) return;
gi(j, i * 4, 0);
z++;
d = 1;
if (i) { x = 2; y = 5
} else { x = 1; y = 4 }
while ((x < y) && (pi < dl)) {
if ((k = i * 4 + d) >= dl) break;
gi(j, k, x);
d++;
x++
}
}).catch(fer)
}
if (fe) cl()
} catch(z) {
alert(em, cl())
}
}
em = "Failed to retrieve data due to site changes.";
if (dd = document.querySelector(".gback+script")) try {
(dp = document.createElement("DIV")).id = "gbpdujs";
dp.innerHTML = ``;
dpp = dp.lastChild;
dd = JSON.parse("[" + dd.text.match(/_OC_Run\((.*)\);/)[1] + "]");
if (!(ic = document.querySelector(".menu_content p"))) throw 0;
ic.insertAdjacentHTML("afterend", 'Download preview pages
');
ic.nextElementSibling.onclick = function() {
this.style.pointerEvents = "none";
if (!(rl = Array.from(viewport.querySelectorAll('img[src*="/books/content"]')).splice(0, 3)).length) return alert(em);
dl = 0;
(function gii(this_, i) {
fetch(rl[i].src, {method: "HEAD"}).then(r => {
dl += parseInt(r.headers.get("content-length"));
if (++i < rl.length) {
gii(this_, i)
} else {
this_.style.pointerEvents = "";
nx(dl / rl.length * dd[0].page.length)
}
}).catch(e => {
this_.style.pointerEvents = "";
fer(e)
})
})(this, 0)
}
} catch(z) {
alert(em)
}
})()