您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Manga downloader for jumptoon.com
// ==UserScript== // @name JumptoonDownloader // @namespace https://github.com/Timesient/manga-download-scripts // @version 0.3 // @license GPL-3.0 // @author Timesient // @description Manga downloader for jumptoon.com // @icon https://jumptoon.com/favicon.ico // @homepageURL https://gf.qytechs.cn/scripts/497457-jumptoondownloader // @supportURL https://github.com/Timesient/manga-download-scripts/issues // @match https://jumptoon.com/* // @require https://unpkg.com/[email protected]/dist/axios.min.js // @require https://unpkg.com/[email protected]/dist/jszip.min.js // @require https://unpkg.com/[email protected]/dist/FileSaver.min.js // @require https://update.gf.qytechs.cn/scripts/451810/1398192/ImageDownloaderLib.js // @grant GM_info // @grant GM_xmlhttpRequest // ==/UserScript== (async function(axios, JSZip, saveAs, ImageDownloader) { 'use strict'; // reload page when enter or leave chapter const re = /https:\/\/jumptoon\.com\/series\/.*\/episodes\/(?<episodeID>\d+)\/.*/; const oldHref = window.location.href; const timer = setInterval(() => { const newHref = window.location.href; if (re.exec(newHref)?.groups?.episodeID === re.exec(oldHref)?.groups?.episodeID) return; if (re.test(newHref) || re.test(oldHref)) { clearInterval(timer); window.location.reload(); } }, 200); // return if not reading chapter now if (!re.test(oldHref)) return; // get episode content unsafeWindow.__userscript_temp__ = []; const functionBodyString = Array .from(document.querySelectorAll('script')) .filter(element => element.textContent.includes('seriesEpisodeContent')) .pop() .textContent .replace('self.__next_f.push', 'window.__userscript_temp__.push'); new Function(functionBodyString)(); const contentString = unsafeWindow.__userscript_temp__.pop().pop(); const content = JSON.parse(contentString.slice(contentString.indexOf('[['))).shift().pop().seriesEpisodeContent; // get title & pages & seed const title = `${content.seriesEpisodeEdge.node.notation}${content.seriesEpisodeEdge.node.title ? ' ' + content.seriesEpisodeEdge.node.title : ''}`; const pages = content.pageList; const seed = `${content.seriesId}:${content.number}`.split('').reduce((acc, cur) => acc + cur.codePointAt(0), 0); const scrambleAlgorithmType = content.scrambleAlgorithmType; // setup ImageDownloader ImageDownloader.init({ maxImageAmount: pages.length, getImagePromises, title }); // add style patch const downloadBtn = document.getElementById('ImageDownloader-DownloadButton'); if (downloadBtn) downloadBtn.style.textAlign = 'center'; // collect promises of image function getImagePromises(startNum, endNum) { return pages .slice(startNum - 1, endNum) .map(page => getDecryptedImage(page) .then(ImageDownloader.fulfillHandler) .catch(ImageDownloader.rejectHandler) ); } // get decrypted image function getDecryptedImage(page) { return new Promise(async resolve => { const imageArrayBuffer = await axios.get(page.imageUrl, { responseType: 'arraybuffer' }).then(res => res.data); const image = document.createElement('img'); image.src = 'data:image/jpg;base64,' + window.btoa(new Uint8Array(imageArrayBuffer).reduce((data, byte) => data + String.fromCharCode(byte), '')); image.onload = function () { // create canvas const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.width = page.width; canvas.height = page.height; // get coords const coords = getCoords(seed, scrambleAlgorithmType, page.width, this.width, page.height); // draw pieces for (const coord of coords) { ctx.drawImage(this, ...coord); } canvas.toBlob(resolve); } }); } // seed, scrambleAlgorithmType, page.width, scrambledImage.width, page.height function getCoords(e, i, t, s, r) { const X = (e) => ({ next: () => e = (1664525 * e + 1013904223) % 4294967296 }); const e4 = (e, i, t) => { let s = Array.from({ length: i}, (e, i) => i) , r = i; 0 !== t && r--; let a = X(e); for (let e = r; e > 1; e--) { let i = a.next() % e; [s[i],s[e - 1]] = [s[e - 1], s[i]] } return s; } const eQ = { V1: { splitWidth: 12, paddingWidth: 3, blankWidth: 3 }, V2: { splitWidth: 20, paddingWidth: 15, blankWidth: 1 } } let {splitWidth: a, blankWidth: n, paddingWidth: o} = eQ[i] , l = a + n + 2 * o , d = Math.floor(s / l) , c = t % a , u = e4(e, d, c) , m = Array.from({ length: d }) , p = []; for (let e of u) m[u[e]] = e; for (let e = 0; e < d; e++) { let i = m[e] * l + o , t = e * a; p.push([i, 0, a, r, t, 0, a, r]) } if (c) { let e = d * l + o , i = d * a; p.push([e, 0, c, r, i, 0, c, r]) } return p; } })(axios, JSZip, saveAs, ImageDownloader);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址