Greasy Fork

Greasy Fork is available in English.

Yanmaga Manga Gallery + ZIP Downloader

Captura imágenes de manga en yanmaga.jp, muestra galería y descarga en ZIP con dimensiones reales en el nombre del archivo

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

// ==UserScript==
// @name         Yanmaga Manga Gallery + ZIP Downloader
// @namespace    yanmaga-capture-gallery
// @version      1.3
// @description  Captura imágenes de manga en yanmaga.jp, muestra galería y descarga en ZIP con dimensiones reales en el nombre del archivo
// @author       
// @license      MIT
// @match        https://yanmaga.jp/viewer/*
// @require      https://cdn.jsdelivr.net/npm/jszip@3/dist/jszip.min.js
// @require      https://cdn.jsdelivr.net/npm/file-saver@2/dist/FileSaver.min.js
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    let capturedImages = [];

    function waitForImagesAndInjectUI() {
        const images = document.querySelectorAll('img');
        if (images.length === 0) return setTimeout(waitForImagesAndInjectUI, 500);

        if (!document.getElementById('gallery-panel')) {
            injectGalleryPanel();
        }
    }

    function injectGalleryPanel() {
        // Botón principal
        const btn = document.createElement('button');
        btn.textContent = '📸 Capturar + Galería';
        Object.assign(btn.style, {
            position: 'fixed',
            top: '10px',
            left: '10px',
            zIndex: 9999,
            background: '#1f2937',
            color: '#fff',
            padding: '10px',
            border: 'none',
            borderRadius: '6px',
            fontSize: '14px',
            cursor: 'pointer'
        });
        btn.onclick = captureImagesToGallery;
        document.body.appendChild(btn);

        // Panel galería
        const panel = document.createElement('div');
        panel.id = 'gallery-panel';
        Object.assign(panel.style, {
            position: 'fixed',
            top: '60px',
            left: '10px',
            width: '300px',
            maxHeight: '80vh',
            overflowY: 'auto',
            backgroundColor: '#ffffffee',
            border: '2px solid #111',
            borderRadius: '6px',
            padding: '10px',
            zIndex: 9998,
            fontSize: '12px'
        });
        panel.innerHTML = `
            <strong>📂 Imágenes Capturadas:</strong>
            <div id="image-list" style="margin-top:10px; display:flex; flex-direction:column; gap:6px;"></div>
            <button id="download-zip-btn" style="margin-top:10px; padding:6px; background:#10b981; color:#fff; border:none; border-radius:4px; cursor:pointer;">⬇️ Descargar ZIP</button>
        `;
        document.body.appendChild(panel);

        // Evento para descargar ZIP
        document.getElementById('download-zip-btn').onclick = downloadCapturedImages;
    }

    async function captureImagesToGallery() {
        const images = [...document.querySelectorAll('img')];
        if (images.length === 0) {
            alert('No se encontraron imágenes.');
            return;
        }

        for (let i = 0; i < images.length; i++) {
            const img = images[i];
            const url = img.src;
            if (!url || capturedImages.some(c => c.url === url)) continue;

            try {
                const blob = await fetch(url).then(res => res.blob());
                const bitmap = await createImageBitmap(blob);
                const width = bitmap.width;
                const height = bitmap.height;
                const fileName = `pagina_${String(capturedImages.length + 1).padStart(3, '0')}_${width}x${height}.jpg`;

                capturedImages.push({ blob, fileName, url });

                const imgEl = document.createElement('div');
                imgEl.textContent = `✅ ${fileName}`;
                document.getElementById('image-list').appendChild(imgEl);
                console.log(`Capturada: ${fileName}`);
            } catch (err) {
                console.warn(`Error con imagen ${url}`, err);
            }
        }

        alert(`📸 Capturadas ${capturedImages.length} imágenes. Puedes descargarlas en ZIP.`);
    }

    async function downloadCapturedImages() {
        if (capturedImages.length === 0) {
            alert('No hay imágenes capturadas aún.');
            return;
        }

        const zip = new JSZip();
        for (const img of capturedImages) {
            zip.file(img.fileName, img.blob);
        }

        const content = await zip.generateAsync({ type: 'blob' });
        saveAs(content, 'yanmaga_capitulo.zip');
        alert(`📥 ZIP generado con ${capturedImages.length} imágenes`);
    }

    waitForImagesAndInjectUI();
})();