Closed ydc1992 closed 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);
};
有的图片是webp格式的