BinB阅读器捕获脚本(v016061)

用于binb阅读器v016061版本的漫画的获取脚本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         BinB阅读器捕获脚本(v016061)
// @namespace    summer-script
// @version      0.2.2
// @description  用于binb阅读器v016061版本的漫画的获取脚本
// @author       summer
// @match        https://gammaplus.takeshobo.co.jp/_files/*
// @match        https://www.comicride.jp/viewer/*
// @exclude      https://www.comicride.jp/viewer/*/HTML5/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    var btn = createBtn();
    var jsonUrls = getJsonUrls();
    btn.addEventListener('click', function() {
        run(jsonUrls, btn);
    });

    function run(jsonUrls, btn, counter) {
        var jsonPath = jsonUrls.shift();
        if (undefined === jsonPath) {
            btn.innerText = '获取完毕';
            return;
        }
        var coords, ptimg;
        counter = counter ? counter : 0;
        counter++;
        jsonGet(jsonPath).then(function(ret) {
            ptimg = ret;
            coords = decodeCoords(ptimg.views[0].coords, ptimg.resources);
            var imgPath = ptimg.resources[coords[0].resid].src;
            var imgSrc = getImgUrl(imgPath, jsonPath);
            return loadImg(imgSrc);
        })
        .then(function(img) {
            btn.innerText = '正在获取...(剩余'+jsonUrls.length+'页)';
            var orgwidth = ptimg.views[0].width;
            var orgheight = ptimg.views[0].height;
            var prefix = document.title;
            var filename = prefix + '-' + counter + '.png';
            var cv = toCanvas(img, coords, orgwidth, orgheight);
            toFile(cv, filename);
            run(jsonUrls, btn, counter);
        });
    }

    function loadImg(src) {
        var func = function(resolve) {
            var img = new Image();
            img.onload = function() {
                resolve(img);
            };
            img.onerror = function() {
                console.log('image['+src+'] load fail, retrying...');
                setTimeout(function() {
                    func(resolve);
                }, 2000);
            };
            img.src = src;
        }
        return new Promise(func);
    }

    function toCanvas(img, coords, width, height) {
        var cv = document.createElement('canvas');
        cv.width = width;
        cv.height = height;
        var ctx = cv.getContext('2d');
        for(var i in coords) {
            ctx.drawImage(
                img,
                coords[i].xsrc,
                coords[i].ysrc,
                coords[i].width,
                coords[i].height,
                coords[i].xdest,
                coords[i].ydest,
                coords[i].width,
                coords[i].height
            );
        }
        return cv;
    }

    function toFile(canvas, filename) {
        canvas.toBlob(function(blob) {
            var url = URL.createObjectURL(blob);
            var a = document.createElement('a');
            a.download = filename;
            a.href = url;
            a.click();
        });
    }

    function jsonGet(path) {
        var func = function(resolve) {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function() {
                if (XMLHttpRequest.DONE !== xhr.readyState) {
                    return;
                }
                if (200 !== xhr.status) {
                    return;
                }
                var ret;
                try {
                    ret = JSON.parse(xhr.responseText);
                } catch(err) {
                    ret = false;
                }
                resolve(ret);
            };
            xhr.open('GET', path);
            xhr.send();
        };
        return new Promise(func);
    }

    function createBtn() {
        var wrap = document.createElement('div');
        wrap.style.top = '6px';
        wrap.style.right = '8px';
        wrap.style.zIndex = '302';
        wrap.style.position = 'fixed';
        document.body.appendChild(wrap);
        var btn = document.createElement('button');
        btn.style.marginLeft = '8px';
        btn.style.padding = '8px';
        btn.style.background = '#fff';
        btn.style.border = '1px solid #aaa';
        btn.style.borderRadius = '4px';
        btn.style.minWidth = '112px';
        btn.style.color = '#000';
        btn.style.float = 'right';
        btn.style.cursor = 'pointer';
        btn.innerText = '下载';
        wrap.appendChild(btn);
        return btn;
    }

    function getJsonUrls() {
        var misc = document.getElementById('content')
                           .getElementsByTagName('div');
        var contents = [];
        for (var i = 0; i < misc.length; i++) {
            if (misc[i].hasAttribute('data-ptimg')) {
                contents.push(misc[i].getAttribute('data-ptimg'));
            }
        }
        return contents;
    }

    function decodeCoords(coordsData, resources) {
        var coordData, coordsNum = [];
        for (var i = 0; i < coordsData.length; i++) {
            coordData = coordsData[i];
            var reg = /^([^:]+):(\d+),(\d+)\+(\d+),(\d+)>(\d+),(\d+)$/;
            var n = coordData.match(reg);
            if (!n) {
                return false;
            }
            var r = n[1];
            if (!(r in resources)) {
                return false;
            }
            coordsNum.push({
                resid: r,
                xsrc: parseInt(n[2], 10),
                ysrc: parseInt(n[3], 10),
                width: parseInt(n[4], 10),
                height: parseInt(n[5], 10),
                xdest: parseInt(n[6], 10),
                ydest: parseInt(n[7], 10)
            });
        }
        return coordsNum;
    }

    function getImgUrl(imgPath, jsonPath) {
        var r;
        if (imgPath.indexOf('http://') + imgPath.indexOf('https://') !== -2) {
            r = imgPath;
        } else if ("" === imgPath) {
            r = jsonPath;
        } else if ("/" === imgPath[0]) {
            r = imgPath;
        } else if (".." === jsonPath){
            r = "../" + imgPath;
        } else if (jsonPath.match(/\/\.\.$/)){
            r = jsonPath + "/" + imgPath;
        } else if (-1 === jsonPath.indexOf("/")) {
            r = imgPath;
        } else {
            r = jsonPath.replace(/\/[^\/]*$/, "/") + imgPath;
        }
        if ("" === r) {
            return "";
        }
        var n = [];
        var i = r.replace(/\/+/g, "/")
                 .replace(/\/\.$/, "/")
                 .replace(/(^|\/)\.\.$/, "$1../")
                 .split("/").filter(function(t, i, n) {
                    return "." !== t
                  });
        for (r = 0; r < i.length; r++) {
            if (".." === i[r]) {
                if (n.length > 0) {
                    var e = n.pop();
                    "" === e ? n.push("") : ".." === e && n.push("..", "..")
                } else {
                    n.push("..");
                }
            } else {
                n.push(i[r]);
            }
        }
        var s = n.join("/");
        "" === s && (s = ".");
        return s;
    }
})();