您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Download a DRM-free copy of your Dark Horse digital comics.
// ==UserScript== // @name Dark Horse Downloader // @namespace http://schiff.io/ // @version 0.3.1 // @description Download a DRM-free copy of your Dark Horse digital comics. // @author Hayden Schiff (oxguy3) // @match https://digital.darkhorse.com/read/* // @match https://digital.darkhorse.com/bookshelf* // @connect cloudfront.net // @grant GM_xmlhttpRequest // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.js // ==/UserScript== /** * DARK HORSE DOWNLOADER * Made by Hayden Schiff (oxguy3), license is Creative Commons Zero. * * This script makes it really easy to download a DRM-free copy of your digital * comics on Dark Horse Digital. Simply go to your Dark Horse bookshelf at * <https://digital.darkhorse.com/bookshelf>, then disable "Stack by Series" and * switch to Gallery View if you haven't already. You will now see a "Download" * button below all your comics. * * When you click the download button for any of your comics, it'll open the * reader for that comic, then start downloading the comic. A red box in the * middle of the screen will show you the progress of the download (be warned * that things will be a bit laggy while it's downloading. Once it's done, a * .CBZ file will pop into your downloads (if you aren't familiar, a .CBZ file * is just a zip file full of JPGs. You can easily open it with a reader app * or convert to PDF or whatever). */ (function() { 'use strict'; var pagesDone = 0; var pagesTotal = 0; // from http://stackoverflow.com/a/10073761/992504 function padToFive(number) { if (number <= 99999) { number = ("0000" + number).slice(-5); } return number; } // from http://stackoverflow.com/a/15832662/992504 function downloadURI(uri, name) { var link = document.createElement("a"); link.download = name; link.href = uri; document.body.appendChild(link); link.click(); document.body.removeChild(link); } // This is part of a hack to use base64 to work around Greasemonkey's lack of support // for responseType:blob on XHRs. Source: http://stackoverflow.com/a/8781262/992504 function customBase64Encode(inputStr) { var bbLen = 3, enCharLen = 4, inpLen = inputStr.length, inx = 0, jnx, keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/=", output = "", paddingBytes = 0; var bytebuffer = new Array(bbLen), encodedCharIndexes = new Array(enCharLen); while (inx < inpLen) { for (jnx = 0; jnx < bbLen; ++jnx) { /*--- Throw away high-order byte, as documented at: https://.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data */ if (inx < inpLen) bytebuffer[jnx] = inputStr.charCodeAt(inx++) & 0xff; else bytebuffer[jnx] = 0; } /*--- Get each encoded character, 6 bits at a time. index 0: first 6 bits index 1: second 6 bits (2 least significant bits from inputStr byte 1 + 4 most significant bits from byte 2) index 2: third 6 bits (4 least significant bits from inputStr byte 2 + 2 most significant bits from byte 3) index 3: forth 6 bits (6 least significant bits from inputStr byte 3) */ encodedCharIndexes[0] = bytebuffer[0] >> 2; encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4); encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6); encodedCharIndexes[3] = bytebuffer[2] & 0x3f; //--- Determine whether padding happened, and adjust accordingly. paddingBytes = inx - (inpLen - 1); switch (paddingBytes) { case 1: // Set last character to padding char encodedCharIndexes[3] = 64; break; case 2: // Set last 2 characters to padding char encodedCharIndexes[3] = 64; encodedCharIndexes[2] = 64; break; default: break; // No padding - proceed } /*--- Now grab each appropriate character out of our keystring, based on our index array and append it to the output string. */ for (jnx = 0; jnx < enCharLen; ++jnx) output += keyStr.charAt(encodedCharIndexes[jnx]); } return output; } function updatePagesDoneCounter() { if (pagesDone % 5 === 0) { document.getElementById("dhdl_status").textContent = "Downloading " + pagesDone + " of " + pagesTotal + " pages..."; } } // add download buttons to the bookshelf if (window.location.pathname == "/bookshelf") { // TODO: check if "stack by series" is enabled, and if so, don't add the download buttons var books = document.getElementsByClassName("bookshelf-item"); for (var i = 0; i < books.length; i++) { var book = books[i]; var btn = document.createElement("a"); btn.setAttribute("href", "/read/" + book.id + "#download"); btn.setAttribute("class", "button blue collection-read"); btn.setAttribute("style", "margin-top: 6px;"); btn.textContent = "Download"; book.appendChild(btn); } } else if (window.location.pathname.startsWith("/read/")) { if (window.location.hash == "#download") { // create box for showing status of download var box = document.createElement("div"); box.id = "dhdl_box"; box.setAttribute("style", "background-color:#ffaaaa; border:2px solid #111; border-radius:5px; opacity:0.9; text-align:center; font-size:22px; width:400px; height:150px; margin:auto; position:absolute; top:0; left:0; bottom:0; right:0; z-index:10000;"); var boxTitle = document.createElement("h1"); boxTitle.textContent = "Dark Horse Downloader"; box.appendChild(boxTitle); var boxStatus = document.createElement("p"); boxStatus.id = "dhdl_status"; boxStatus.textContent = "Starting up..."; box.appendChild(boxStatus); document.body.appendChild(box); var bookTitle = document.getElementById("bookreader-title").getElementsByTagName("h2")[0].textContent; var bookTitleSafe = bookTitle.replace(/\s+/gi, ' ').replace(/[^a-z0-9 ]/gi, '_'); var pageUrls = []; for (var i = 0; i < book_manifest.pages.length; i++) { var page = book_manifest.pages[i]; var url = window.location.protocol + "//" + window.location.host + book_manifest.base_url + page.src_image; pageUrls.push(url); } pagesTotal = book_manifest.pages.length; updatePagesDoneCounter(); // reverse order for right-to-left books (i.e. manga) if (book_manifest.is_rtl) { pageUrls.reverse(); } var zip = new JSZip(); Promise.all(pageUrls.map(function(url, index) { return new Promise(function(resolve) { GM_xmlhttpRequest({ method: "GET", url: url, onload: function(response) { zip.file(padToFive(index) + ".jpg", customBase64Encode(response.responseText), { base64: true }); pagesDone++; updatePagesDoneCounter(); resolve(); }, overrideMimeType: 'text/plain; charset=x-user-defined' }); }); })).then(function() { document.getElementById("dhdl_status").textContent = "Creating zip file..."; zip.generateAsync({ type: "blob" }).then(function(content) { document.getElementById("dhdl_status").textContent = "Done!"; downloadURI(URL.createObjectURL(content), bookTitleSafe + ".cbz"); setTimeout(function() { document.body.removeChild(box); }, 3000); }); }); } } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址