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)
$(title2)
Page
View in Google Books
`.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) } })()