Greasy Fork

Greasy Fork is available in English.

Yanmaga Manga Capture & ZIP

Captura páginas completas del manga en yanmaga.jp y permite descargarlas en un ZIP.

当前为 2025-06-17 提交的版本,查看 最新版本

// ==UserScript==
// @name         Yanmaga Manga Capture & ZIP
// @namespace    yanmaga-capture
// @version      1.7
// @description  Captura páginas completas del manga en yanmaga.jp y permite descargarlas en un ZIP.
// @author       ChatGPT
// @match        https://yanmaga.jp/viewer/*
// @require      https://cdn.jsdelivr.net/npm/jszip@3/dist/jszip.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/FileSaver.min.js
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    const capturedImages = [];
    const container = document.createElement('div');
    container.style = 'position: fixed; top: 10px; right: 10px; z-index: 10000; display: flex; flex-direction: column; gap: 6px;';

    const captureBtn = document.createElement('button');
    captureBtn.textContent = '📸 Capturar páginas';
    const zipBtn = document.createElement('button');
    zipBtn.textContent = '⬇️ Descargar ZIP';

    [captureBtn, zipBtn].forEach(btn => {
        btn.style = 'padding: 6px 10px; background: #222; color: #fff; border: none; border-radius: 4px; cursor: pointer;';
        container.appendChild(btn);
    });
    document.body.appendChild(container);

    const gallery = document.createElement('div');
    gallery.style = 'position: fixed; bottom: 10px; left: 10px; background: rgba(255,255,255,0.9); padding: 8px; max-height: 50vh; overflow-y: auto; z-index: 9999; border: 1px solid #ccc;';
    document.body.appendChild(gallery);

    function addToGallery(img, index) {
        const wrapper = document.createElement('div');
        wrapper.style = 'margin-bottom: 8px;';
        const label = document.createElement('div');
        label.textContent = `📄 Página ${String(index + 1).padStart(3, '0')} - ${img.naturalWidth}x${img.naturalHeight}`;
        label.style = 'font-size: 12px; margin-bottom: 4px;';
        wrapper.appendChild(label);
        wrapper.appendChild(img);
        img.style.maxWidth = '120px';
        gallery.appendChild(wrapper);
    }

    captureBtn.onclick = () => {
        const allImgs = [...document.querySelectorAll('img')];
        const mangaPages = allImgs.filter(img => img.src.includes('/viewer/pages/'));
        if (mangaPages.length === 0) {
            alert('No se encontraron imágenes de manga visibles.');
            return;
        }

        capturedImages.length = 0;
        gallery.innerHTML = '';

        mangaPages.forEach((img, idx) => {
            const newImg = new Image();
            newImg.crossOrigin = 'anonymous';
            newImg.src = img.src;
            newImg.onload = () => {
                capturedImages.push({ name: `pagina_${String(idx + 1).padStart(3, '0')}_${img.naturalWidth}x${img.naturalHeight}.jpg`, img: newImg });
                addToGallery(newImg, idx);
            };
        });
    };

    zipBtn.onclick = async () => {
        if (capturedImages.length === 0) {
            alert('No hay imágenes capturadas. Usa "Capturar páginas" primero.');
            return;
        }

        const zip = new JSZip();
        for (let i = 0; i < capturedImages.length; i++) {
            const { name, img } = capturedImages[i];
            const canvas = document.createElement('canvas');
            canvas.width = img.naturalWidth;
            canvas.height = img.naturalHeight;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0);
            const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/jpeg'));
            zip.file(name, blob);
        }

        const blobZip = await zip.generateAsync({ type: 'blob' });
        saveAs(blobZip, 'yanmaga_manga.zip');
    };
})();