eternalphane / UserScripts

My greasemonkey/tampermonkey scripts
MIT License
12 stars 5 forks source link

算法更新了 #12

Closed ydc1992 closed 1 year ago

ydc1992 commented 2 years ago

有的图片是webp格式的

// ==UserScript==
// @name         18comic漫画下载
// @namespace    http://github.com/eternalphane/Userscripts/
// @version      1.0.5
// @description  从18comic上下载cbz格式(整话阅读)或webp格式(分页阅读)的漫画
// @author       eternalphane
// @license      MIT
// @match        https://18comic.vip/photo/*
// @match        https://18comic.org/photo/*
// @match        https://18comic.bet/photo/*
// @match        https://18comic1.one/photo/*
// @match        https://18comic2.one/photo/*
// @match        https://jmcomic.asia/photo/*
// @connect      cdn-msp.18comic.vip
// @connect      cdn-msp.18comic.org
// @require      https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @require      https://unpkg.com/jszip@3.5.0/dist/jszip.min.js
// @resource     css https://raw.githubusercontent.com/eternalphane/UserScripts/master/18comic%20Downloader/overlay.css
// @resource     html https://raw.githubusercontent.com/eternalphane/UserScripts/master/18comic%20Downloader/overlay.html
// @grant        GM_getResourceText
// @grant        GM.getResourceText
// @grant        GM_addStyle
// @grant        GM.addStyle
// @grant        GM_xmlhttpRequest
// @grant        GM.xmlHttpRequest
// ==/UserScript==

function get_num(e, t) {
    var a = 10;
    if (e >= 268850) {
        var n = e + t;
        switch (n = (n = (n = md5(n)).substr(-1)).charCodeAt(),
        n %= 10) {
        case 0:
            a = 2;
            break;
        case 1:
            a = 4;
            break;
        case 2:
            a = 6;
            break;
        case 3:
            a = 8;
            break;
        case 4:
            a = 10;
            break;
        case 5:
            a = 12;
            break;
        case 6:
            a = 14;
            break;
        case 7:
            a = 16;
            break;
        case 8:
            a = 18;
            break;
        case 9:
            a = 20
        }
    }
    return a
}

(async () => {
    const btn = document.querySelector('.menu-bolock i.fa-download').parentElement;
    if (location.search) {
        return btn.addEventListener('click', async e => {
            e.preventDefault();
            // album_photo_00012.webp
            const page = document.querySelector('div[id*=".jpg"]');

            save(
                await download(page.querySelector('img').getAttribute('data-original')),
                `${page.id.slice(0, -4)}.webp`
            );
        });
    }
    GM.addStyle(await GM.getResourceText('css'));
    const overlay = document.createElement('div');
    overlay.id = 'dl-overlay';
    overlay.innerHTML = await GM.getResourceText('html');
    overlay.hidden = true;
    document.body.appendChild(overlay);
    const circle = overlay.querySelectorAll('circle')[1];
    const number = overlay.querySelector('span');
    const msg = overlay.querySelector('h2');
    const updateProgress = (percent, text) => {
        circle.style.strokeDasharray = `${percent} 100`;
        number.innerText = Math.round(percent);
        text != undefined && (msg.innerText = text);
    };
    btn.addEventListener('click', async e => {
        e.preventDefault();
        if (!overlay.hidden) {
            return;
        }
        overlay.hidden = false;
        document.body.classList.add('noscroll');
        var pages = [...document.querySelectorAll('div[id*=".jpg"]')];
        if(pages.length==0){
            pages =[...document.querySelectorAll('div[id*=".webp"]')];
        }
        const total = pages.length;
        let progress = 0;
        updateProgress(0, 'Downloading...');
        const zip = new JSZip;
        await Promise.all(pages.map(async page => {
            zip.file(`${page.id.slice(0, -4)}.webp`, await download(
                page.querySelector('img').getAttribute('data-original')
            ));
            updateProgress(++progress * 100 / total);
        }));
        updateProgress(0, 'Compressing...');
        // TODO: Select output format? (cbz, cbt, pdf)
        save(
            await zip.generateAsync({
                type: 'blob',
                compression: 'DEFLATE',
                compressionOptions: { level: 9 },
                mimeType: 'application/vnd.comicbook+zip'
            }, (meta) => updateProgress(meta.percent)),
            `${document.querySelector('.panel-heading .pull-left').textContent.trim()}.cbz`
        );
        document.body.classList.remove('noscroll');
        overlay.hidden = true;
    });
})();

/**
 * @param {string} url
 */
const download = async url => {
    const img = new Image;
    img.src = URL.createObjectURL((await new Promise((resolve, reject) => GM.xmlHttpRequest({
        url,
        method: 'GET',
        responseType: 'blob',
        onload: resolve,
        onerror: reject
    }))).response);
    await new Promise((resolve, reject) => (img.onload = resolve, img.onerror = reject));
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    // `aid`, `scramble_id` and `md5` are both global variables
    if ((!url.includes('.jpg') &&!url.includes('.webp') ) ||aid < scramble_id) {
        ctx.drawImage(img, 0, 0);
    } else {
      var d = img.naturalWidth;
      var i = img.naturalHeight;
      canvas.width = d;
      canvas.height = i;

        r = url.slice(url.lastIndexOf('/')+1).split('.')[0]
        var s = get_num(aid, r);
        l = parseInt(i % s);
        for (var o = d, m = 0; m < s; m++) {
            var c = Math.floor(i / s);
            g = c * m;
            h = i - c * (m + 1) - l;
            0 == m ? c += l : g += l;
            ctx.drawImage(img, 0, h, o, c, 0, g, o, c);
        }

    }
    URL.revokeObjectURL(img.src);
    // TODO: Select image type? Change quality?
    return new Promise(resolve => canvas.toBlob(resolve, 'image/webp', 0.9));
};

const save = (blob, filename) => {
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = filename;
    a.click();
    URL.revokeObjectURL(a.href);
};
sahsu commented 1 year ago

allow msp2

// ==UserScript==
// @name         18comic漫畫下載
// @namespace    http://github.com/eternalphane/Userscripts/
// @version      1.0.5
// @description  從18comic上下載cbz格式(整話閱讀)或webp格式(分頁閱讀)的漫畫
// @author       eternalphane
// @license      MIT
// @match        https://18comic.vip/photo/*
// @match        https://cdn-msp*.18comic.vip/*
// @match        https://18comic.org/photo/*
// @match        https://18comic.bet/photo/*
// @match        https://18comic1.one/photo/*
// @match        https://18comic2.one/photo/*
// @match        https://jmcomic.asia/photo/*
// @connect      cdn-msp.18comic.vip
// @connect      cdn-msp.18comic.org
// @connect      cdn-msp2.18comic.vip
// @require      https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @require      https://unpkg.com/jszip@3.5.0/dist/jszip.min.js
// @resource     css https://raw.githubusercontent.com/eternalphane/UserScripts/master/18comic%20Downloader/overlay.css
// @resource     html https://raw.githubusercontent.com/eternalphane/UserScripts/master/18comic%20Downloader/overlay.html
// @grant        GM_getResourceText
// @grant        GM.getResourceText
// @grant        GM_addStyle
// @grant        GM.addStyle
// @grant        GM_xmlhttpRequest
// @grant        GM.xmlHttpRequest
// ==/UserScript==

function get_num(e, t) {
    var a = 10;
    if (e >= 268850) {
        var n = e + t;
        switch (n = (n = (n = md5(n)).substr(-1)).charCodeAt(),
        n %= 10) {
        case 0:
            a = 2;
            break;
        case 1:
            a = 4;
            break;
        case 2:
            a = 6;
            break;
        case 3:
            a = 8;
            break;
        case 4:
            a = 10;
            break;
        case 5:
            a = 12;
            break;
        case 6:
            a = 14;
            break;
        case 7:
            a = 16;
            break;
        case 8:
            a = 18;
            break;
        case 9:
            a = 20
        }
    }
    return a
}

(async () => {
    const btn = document.querySelector('.menu-bolock i.fa-download').parentElement;
    if (location.search) {
        return btn.addEventListener('click', async e => {
            e.preventDefault();
            // album_photo_00012.webp
            const page = document.querySelector('div[id*=".jpg"]');

            save(
                await download(page.querySelector('img').getAttribute('data-original')),
                `${page.id.slice(0, -4)}.webp`
            );
        });
    }
    GM.addStyle(await GM.getResourceText('css'));
    const overlay = document.createElement('div');
    overlay.id = 'dl-overlay';
    overlay.innerHTML = await GM.getResourceText('html');
    overlay.hidden = true;
    document.body.appendChild(overlay);
    const circle = overlay.querySelectorAll('circle')[1];
    const number = overlay.querySelector('span');
    const msg = overlay.querySelector('h2');
    const updateProgress = (percent, text) => {
        circle.style.strokeDasharray = `${percent} 100`;
        number.innerText = Math.round(percent);
        text != undefined && (msg.innerText = text);
    };
    btn.addEventListener('click', async e => {
        e.preventDefault();
        if (!overlay.hidden) {
            return;
        }
        overlay.hidden = false;
        document.body.classList.add('noscroll');
        var pages = [...document.querySelectorAll('div[id*=".jpg"]')];
        if(pages.length==0){
            pages =[...document.querySelectorAll('div[id*=".webp"]')];
        }
        const total = pages.length;
        let progress = 0;
        updateProgress(0, 'Downloading...');
        const zip = new JSZip;
        await Promise.all(pages.map(async page => {
            zip.file(`${page.id.slice(0, -4)}.webp`, await download(
                page.querySelector('img').getAttribute('data-original')
            ));
            updateProgress(++progress * 100 / total);
        }));
        updateProgress(0, 'Compressing...');
        // TODO: Select output format? (cbz, cbt, pdf)
        save(
            await zip.generateAsync({
                type: 'blob',
                compression: 'DEFLATE',
                compressionOptions: { level: 9 },
                mimeType: 'application/vnd.comicbook+zip'
            }, (meta) => updateProgress(meta.percent)),
            `${document.querySelector('.panel-heading .pull-left').textContent.trim()}.cbz`
        );
        document.body.classList.remove('noscroll');
        overlay.hidden = true;
    });
})();

/**
 * @param {string} url
 */
const download = async url => {
    const img = new Image;
    img.src = URL.createObjectURL((await new Promise((resolve, reject) => GM.xmlHttpRequest({
        url,
        method: 'GET',
        responseType: 'blob',
        onload: resolve,
        onerror: reject
    }))).response);
    await new Promise((resolve, reject) => (img.onload = resolve, img.onerror = reject));
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    // `aid`, `scramble_id` and `md5` are both global variables
    if ((!url.includes('.jpg') &&!url.includes('.webp') ) ||aid < scramble_id) {
        ctx.drawImage(img, 0, 0);
    } else {
      var d = img.naturalWidth;
      var i = img.naturalHeight;
      canvas.width = d;
      canvas.height = i;

        r = url.slice(url.lastIndexOf('/')+1).split('.')[0]
        var s = get_num(aid, r);
        l = parseInt(i % s);
        for (var o = d, m = 0; m < s; m++) {
            var c = Math.floor(i / s);
            g = c * m;
            h = i - c * (m + 1) - l;
            0 == m ? c += l : g += l;
            ctx.drawImage(img, 0, h, o, c, 0, g, o, c);
        }

    }
    URL.revokeObjectURL(img.src);
    // TODO: Select image type? Change quality?
    return new Promise(resolve => canvas.toBlob(resolve, 'image/webp', 0.9));
};

const save = (blob, filename) => {
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = filename;
    a.click();
    URL.revokeObjectURL(a.href);
};