Another cmoa.jp Downloader

用于网站cmoa.jp的下载。在顶部菜单选项左侧点击download按钮开始下载。按钮没有显示的话尝试刷新页面。图片每50页分为一部分进行压缩下载,压缩需要40-60秒,请不要关闭或刷新页面。

目前为 2023-04-16 提交的版本。查看 最新版本

// ==UserScript==
// @name         Another cmoa.jp Downloader
// @namespace    Ziran
// @version      2.1.0
// @description  用于网站cmoa.jp的下载。在顶部菜单选项左侧点击download按钮开始下载。按钮没有显示的话尝试刷新页面。图片每50页分为一部分进行压缩下载,压缩需要40-60秒,请不要关闭或刷新页面。
// @author       Ziran
// @match        https://www.cmoa.jp/bib/*
// @match        https://yomiho.cmoa.jp/bib/*
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/FileSaver.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.min.js
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    "use strict";

    let quality = "high";
    //Original

    function addSpeedreaderCanvas() {
        let canvas = document.createElement("canvas");
        canvas.id = "temp-canvas";
        canvas.style.cssText = `position: fixed;
                          top: 15%;
                          left: 5%;
                          height: 268px;
                          width: 187px;
                          background-color: pink;
                          z-index: 19;
                          visibility:hidden;`;

        document.body.appendChild(canvas);
    }

    function addSpeedreaderRadio() {
        let labelHigh = document.createElement("label");
        labelHigh.id = "quality-label-high";
        labelHigh.innerText = "高清";
        labelHigh.style.cssText = `position: fixed;
                          top: 11px;
                          left: 175px;
                          font-size:16px;`;
        let radioHigh = document.createElement("input");
        radioHigh.type = "radio";
        radioHigh.name = "quality";
        radioHigh.value = "high";
        radioHigh.checked = true;
        radioHigh.onclick = function (value) {
            quality = radioHigh.value;
        }

        let labelOriginal = document.createElement("label");
        labelOriginal.id = "quality-label-original";
        labelOriginal.innerText = "原图";
        labelOriginal.style.cssText = `position: fixed;
                          top: 11px;
                          left: 240px;
                          font-size: 16px;`;
        let radioOriginal = document.createElement("input");
        radioOriginal.type = "radio";
        radioOriginal.name = "quality";
        radioOriginal.value = "original";
        radioOriginal.onclick = function (value) {
            quality = radioOriginal.value;
        }

        let downloadingMessage = document.createElement("span");
        downloadingMessage.id = "downloading-message";
        downloadingMessage.innerText = "downloading……";
        downloadingMessage.style.cssText = `position: fixed;
                          top: 10px;
                          left: 70px;
                          font-size: 16px;
                          font-weight: 500;
                          visibility:hidden;`;

        let menu_header = document.getElementById("menu_header");
        menu_header.appendChild(labelHigh);
        labelHigh.appendChild(radioHigh);
        menu_header.appendChild(labelOriginal);
        labelOriginal.appendChild(radioOriginal);
        menu_header.appendChild(downloadingMessage);
    }

    function addSpeedreaderButton() {
        let button = document.createElement("button");
        button.id = "download-button";
        button.innerHTML = "download";
        button.style.cssText = `position: fixed;
                          top: 11px;
                          left: 70px;
                          font-size:16px;
                          border-style: none;
                          text-align:center;
                          vertical-align:baseline;`;

        button.onclick = async function () {
            changeDownloadStatus("on");
            let zip = new JSZip();
            let folder = zip.folder(__sreaderFunc__.contentInfo.items[0].SubTitle);
            let partCounter = 0;
            let partPages = 50;
            for (let i = 0; i < __sreaderFunc__.currentPageInfo.endPageNumber; i++) {
                partCounter = i + 1;
                if (partCounter % partPages == 0) {
                    await zip.generateAsync({ type: "blob" })
                        .then(function (content) {
                        saveAs(content, __sreaderFunc__.contentInfo.items[0].SubTitle + "_part" + Math.floor(partCounter / partPages).toString());
                    });
                    zip = new JSZip();
                    folder = zip.folder(__sreaderFunc__.contentInfo.items[0].SubTitle);
                }
                __sreaderFunc__.moveTo(i, !1);
                let content = document.getElementById("content-p" + (i + 1).toString());
                while (!content.hasChildNodes()) {
                    await sleep(200);
                }
                let ptimg = content.firstElementChild;
                while (!ptimg.hasChildNodes()) {
                    await sleep(200);
                    ptimg = content.firstElementChild;
                }
                let child = ptimg.firstElementChild;
                let img1 = child.firstElementChild;
                while (!img1.complete) {
                    await sleep(200);
                }
                child = child.nextElementSibling;
                let img2 = child.firstElementChild;
                while (!img2.complete) {
                    await sleep(200);
                }
                let img2Inset = parseFloat(child.style.inset.substring(0, child.style.inset.indexOf("%"))) / 100;
                child = child.nextElementSibling;
                let img3 = child.firstElementChild;
                while (!img3.complete) {
                    await sleep(200);
                }
                let img3Inset = parseFloat(child.style.inset.substring(0, child.style.inset.indexOf("%"))) / 100;
                let canvas = document.getElementById("temp-canvas");
                let ctx = canvas.getContext('2d');
                if (quality == "high") {
                    if (img1.naturalWidth > 800) {
                        let COQ = 800 / img1.naturalWidth;
                        canvas.width = 800;
                        canvas.height = COQ * (img3.naturalHeight / (1 - img3Inset));
                        ctx.drawImage(img1, 0, 0, 800, COQ * img1.naturalHeight);
                        ctx.drawImage(img2, 0, canvas.height * img2Inset, 800, COQ * img2.naturalHeight);
                        ctx.drawImage(img3, 0, canvas.height * img3Inset, 800, COQ * img3.naturalHeight);
                    } else {
                        canvas.width = img1.naturalWidth;
                        canvas.height = img3.naturalHeight / (1 - img3Inset);
                        ctx.drawImage(img1, 0, 0);
                        ctx.drawImage(img2, 0, canvas.height * img2Inset);
                        ctx.drawImage(img3, 0, canvas.height * img3Inset);
                    }
                    folder.file((i + 1).toString() + ".png", canvas.toDataURL().split(',')[1], { base64: true });
                } else if (quality == "original") {
                    canvas.width = img1.naturalWidth;
                    canvas.height = img3.naturalHeight / (1 - img3Inset);
                    ctx.drawImage(img1, 0, 0);
                    ctx.drawImage(img2, 0, canvas.height * img2Inset);
                    ctx.drawImage(img3, 0, canvas.height * img3Inset);
                    folder.file((i + 1).toString() + ".png", canvas.toDataURL().split(',')[1], { base64: true });
                } else {
                    console.log("quality does not exist.");
                }
            }
            if (partCounter % partPages != 0) {
                await zip.generateAsync({ type: "blob" })
                    .then(function (content) {
                    saveAs(content, __sreaderFunc__.contentInfo.items[0].SubTitle + "_part" + Math.ceil(partCounter / partPages).toString());
                });
            }
            changeDownloadStatus("off");
        };

        let menu_header = document.getElementById("menu_header");
        menu_header.appendChild(button);
    }

    function sleep(time) {
        return new Promise((resolve) => setTimeout(resolve, time));
    }

    function changeDownloadStatus(status) {
        let button = document.getElementById("download-button");
        let labelHigh = document.getElementById("quality-label-high");
        let labelOriginal = document.getElementById("quality-label-original");
        let downloadingMessage = document.getElementById("downloading-message");
        if (status == "on") {
            button.style.visibility = "hidden";
            labelHigh.style.visibility = "hidden";
            labelOriginal.style.visibility = "hidden";
            downloadingMessage.style.visibility = "visible";
        }
        else if (status == "off") {
            button.style.visibility = "visible";
            labelHigh.style.visibility = "visible";
            labelOriginal.style.visibility = "visible";
            downloadingMessage.style.visibility = "hidden";
        }
        return
    }

    function addReaderButton() {
        let button = document.createElement("button");
        button.id = "download-button";
        button.innerHTML = "download";
        button.style.cssText = `position: fixed;
                          top: 11px;
                          left: 70px;
                          font-size:16px;
                          border-style: none;
                          text-align:center;
                          vertical-align:baseline;`;

        button.onclick = async function () {
            let text = ZOM0KK.ZZN0AE.value;
            let title = '';
            title = text.match(/(?<=<title>).*(?=<\/title>)/)[0];
            text = text.replace(/<head>.*?<\/head>/s, '');
            text = text.replace(/<t-param indent="0".*?>/g, '\n');
            text = text.replace(/<.*?>/g, '');

            let sss = text.match(/&\$.*?;/g, '');
            for (let i = 0; i < sss.length; i++) {
                text = text.replace(sss[i], theZ2Q0F5(sss[i].slice(2,sss[i].length-1)));
            }

            while(text[0] === '\n'){
                text = text.slice(1,text.length);
            }

            let blob = new Blob([text], { type: "text/plain;charset=utf-8" });
            saveAs(blob, title + ".txt");
        };

        let menu_header = document.getElementById("ctmble_menu_upper_component_holder");
        menu_header.appendChild(button);
    }

    function theZ2Q0F5(ss) {
        let vs = Z2Q0F5(ss);
        let sb;
        let sp;
        let cd1;
        let cd2;
        ss = "";
        if (vs < 256) {
            sb = vs % 256;
            ss = String.fromCharCode(sb)
        } else if (vs >= 65536) {
            sp = vs - 65536;
            cd1 = 55296 | sp >> 10;
            cd2 = 56320 | sp & 1023;
            ss = String.fromCharCode(cd1, cd2)
        } else {
            ss = String.fromCharCode(vs)
        }
        return ss;
    }

    // Run script
    window.addEventListener("load", function () {
        if (document.documentURI.indexOf('cmoa.jp/bib/speedreader/') != -1) {
            addSpeedreaderButton();
            addSpeedreaderCanvas();
            addSpeedreaderRadio();
        }
        if (document.documentURI.indexOf('cmoa.jp/bib/reader/') != -1) {
            addReaderButton();
        }
    });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址