// ==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;
}
})();