🏠 Home 

YnjnDownloader

Manga downloader for ynjn.jp


安装此脚本?
// ==UserScript==
// @name         YnjnDownloader
// @namespace    https://github.com/Timesient/manga-download-scripts
// @version      0.7
// @license      GPL-3.0
// @author       Timesient
// @description  Manga downloader for ynjn.jp
// @icon         https://public.ynjn.jp/web/img/common/favicon.ico
// @homepageURL  https://greasyfork.org/scripts/455206-ynjndownloader
// @supportURL   https://github.com/Timesient/manga-download-scripts/issues
// @match        https://ynjn.jp/viewer/*
// @require      https://unpkg.com/[email protected]/dist/axios.min.js
// @require      https://unpkg.com/[email protected]/dist/jszip.min.js
// @require      https://unpkg.com/[email protected]/dist/FileSaver.min.js
// @require      https://update.greasyfork.org/scripts/451810/1398192/ImageDownloaderLib.js
// @grant        GM_info
// @grant        GM_xmlhttpRequest
// ==/UserScript==
(async function(axios, JSZip, saveAs, ImageDownloader) {
'use strict';
// get title and pages
const { title_id, episode_id } = window.location.href.match(/viewer\/(?<title_id>\d+)\/(?<episode_id>\d+)/).groups;
const config = await axios.get(`https://webapi.ynjn.jp/viewer?title_id=${title_id}&episode_id=${episode_id}`).then(res => res.data.data);
const title = config.viewer_navigation.name;
const pages = config.pages.filter(page => page.manga_page).map(page => page.manga_page);
// setup ImageDownloader
ImageDownloader.init({
maxImageAmount: pages.length,
getImagePromises,
title
});
// collect promises of image
function getImagePromises(startNum, endNum) {
return pages
.slice(startNum - 1, endNum)
.map(page => getDecryptedImage(page)
.then(ImageDownloader.fulfillHandler)
.catch(ImageDownloader.rejectHandler)
);
}
// get decrypted image
function getDecryptedImage(page) {
return new Promise(async resolve => {
const imageArrayBuffer = await new Promise(resolve => {
GM_xmlhttpRequest({
method: 'GET',
url: page.page_image_url,
responseType: 'arraybuffer',
onload: res => resolve(res.response)
});
});
const image = document.createElement('img');
image.src = 'data:image/jpg;base64,' + window.btoa(new Uint8Array(imageArrayBuffer).reduce((data, byte) => data + String.fromCharCode(byte), ''));
image.onload = function () {
// create canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = page.image_horizontal_size;
canvas.height = page.image_vertical_size;
// draw pieces on correct position
const pieceWidth = Math.floor(this.width / 4);
const pieceHeight = Math.floor(this.height / 4);
for (let i = 0; i < 16; i++) {
let srcX = i % 4 * pieceWidth;
let srcY = Math.floor(i / 4) * pieceHeight;
let j = i % 4 * 4 + Math.floor(i / 4);
let destX = j % 4 * pieceWidth;
let destY = Math.floor(j / 4) * pieceHeight;
ctx.drawImage(this, srcX, srcY, pieceWidth, pieceHeight, destX, destY, pieceWidth, pieceHeight);
}
canvas.toBlob(resolve);
}
});
}
})(axios, JSZip, saveAs, ImageDownloader);