您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Descarga capítulos en yanmaga.jp con scroll automático y opción de merge como webtoon
当前为
// ==UserScript== // @name Yanmaga Downloader + Scroll + Webtoon Merge // @namespace yanmaga-downloader // @version 1.2 // @description Descarga capítulos en yanmaga.jp con scroll automático y opción de merge como webtoon // @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'; // Espera hasta que carguen las imágenes const init = () => { const imgs = document.querySelectorAll('img'); if (imgs.length === 0) return setTimeout(init, 500); createUI(); }; init(); function createUI() { if (document.getElementById('yanmaga-download-ui')) return; const container = document.createElement('div'); container.id = 'yanmaga-download-ui'; Object.assign(container.style, { position: 'fixed', top: '10px', right: '10px', zIndex: 9999, display: 'flex', flexDirection: 'column', gap: '5px' }); document.body.appendChild(container); const zipBtn = makeButton('📥 ZIP'); const webBtn = makeButton('🖼️ Webtoon Merge'); const scrollBtn = makeButton('⬇️ Auto Scroll'); container.append(zipBtn, webBtn, scrollBtn); zipBtn.onclick = () => downloadZIP(zipBtn); webBtn.onclick = () => downloadWebtoon(webBtn); scrollBtn.onclick = () => autoScroll(scrollBtn); } function makeButton(text) { const btn = document.createElement('button'); btn.textContent = text; Object.assign(btn.style, { background: '#e11d48', color: '#fff', padding: '8px 12px', border: 'none', borderRadius: '5px', cursor: 'pointer' }); return btn; } async function downloadZIP(btn) { btn.disabled = true; btn.textContent = 'Descargando ZIP...'; try { const imgs = document.querySelectorAll('img'); const zip = new JSZip(); let count = 0; for (const img of imgs) { const url = img.src; if (!url) continue; const blob = await fetch(url).then(r => r.blob()); const name = String(++count).padStart(3, '0') + '.jpg'; zip.file(name, blob); console.log(`Añadida ${name} — ${img.naturalWidth}×${img.naturalHeight}`); } const content = await zip.generateAsync({ type: 'blob' }); saveAs(content, 'yanmaga_capitulo.zip'); alert(`Listo: ${count} imágenes en ZIP`); } catch(e) { console.error(e); alert('Error al descargar ZIP'); } btn.disabled = false; btn.textContent = '📥 ZIP'; } async function downloadWebtoon(btn) { btn.disabled = true; btn.textContent = 'Generando imagen...'; try { const imgs = [...document.querySelectorAll('img')]; const bitmaps = await Promise.all(imgs.map(i => fetch(i.src).then(r => r.blob()).then(createImageBitmap))); const width = Math.max(...bitmaps.map(b => b.width)); const height = bitmaps.reduce((a,b) => a + b.height, 0); const canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; const ctx = canvas.getContext('2d'); let y=0; for (const bm of bitmaps) { ctx.drawImage(bm, 0, y); y += bm.height; } canvas.toBlob(blob => saveAs(blob, 'yanmaga_webtoon.jpg'), 'image/jpeg', 1); } catch(e) { console.error(e); alert('Error al crear imagen webtoon'); } btn.disabled = false; btn.textContent = '🖼️ Webtoon Merge'; } function autoScroll(btn) { const imgs = [...document.querySelectorAll('img')]; if (imgs.length === 0) return alert('No se detectaron imágenes.'); btn.disabled = true; let i = 0; const scrollInterval = setInterval(() => { if (i >= imgs.length) { clearInterval(scrollInterval); btn.disabled = false; return; } imgs[i].scrollIntoView({ behavior: 'smooth' }); i++; }, 800); } })();