Download manga + WebP/JPG + ZIP
// ==UserScript==
// @name DoujinDesu Downloader
// @namespace https://doujin.desu.xxx/
// @version 2.6
// @description Download manga + WebP/JPG + ZIP
// @author qxyraxp
// @license MIT
// @match https://doujin.desu.xxx/*
// @match http://doujin.desu.xxx/*
// @grant GM_download
// @grant GM_xmlhttpRequest
// @run-at document-start
// ==/UserScript==
(function () {
'use strict';
let imageURLs = [];
let panelOpen = false;
let autoScanInterval = null;
// Base64 icons (circular 32x32)
const ICON_FLOAT = 'data:image/png;base64,' + `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`;
const ICON_SELECTED = 'data:image/png;base64,' + `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`;
const ICON_ZIP = 'data:image/png;base64,' + `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`;
// ==================== Minimal ZIP ====================
function crc32(buf) {
let c = ~0;
for (let i = 0; i < buf.length; i++) {
c ^= buf[i];
for (let k = 0; k < 8; k++) c = (c >>> 1) ^ (0xedb88320 & -(c & 1));
}
return ~c >>> 0;
}
function createZip(files) {
const localHeaders = [], fileDatas = [];
let offset = 0;
for (const f of files) {
const nameBytes = new TextEncoder().encode(f.name);
const data = f.data;
const crc = crc32(data);
const local = new Uint8Array(30 + nameBytes.length);
const v = new DataView(local.buffer);
v.setUint32(0, 0x04034b50, true);
v.setUint16(4, 20, true);
v.setUint16(8, 0, true);
v.setUint32(14, crc, true);
v.setUint32(18, data.length, true);
v.setUint32(22, data.length, true);
v.setUint16(26, nameBytes.length, true);
local.set(nameBytes, 30);
localHeaders.push({ header: local, offset, crc, size: data.length });
fileDatas.push(data);
offset += local.length + data.length;
}
const centralParts = [];
let centralSize = 0;
for (let i = 0; i < files.length; i++) {
const h = localHeaders[i];
const nameBytes = new TextEncoder().encode(files[i].name);
const central = new Uint8Array(46 + nameBytes.length);
const v = new DataView(central.buffer);
v.setUint32(0, 0x02014b50, true);
v.setUint16(4, 20, true);
v.setUint16(6, 20, true);
v.setUint32(16, h.crc, true);
v.setUint32(20, h.size, true);
v.setUint32(24, h.size, true);
v.setUint16(28, nameBytes.length, true);
v.setUint32(42, h.offset, true);
central.set(nameBytes, 46);
centralParts.push(central);
centralSize += central.length;
}
const end = new Uint8Array(22);
const ev = new DataView(end.buffer);
ev.setUint32(0, 0x06054b50, true);
ev.setUint16(8, files.length, true);
ev.setUint16(10, files.length, true);
ev.setUint32(12, centralSize, true);
ev.setUint32(16, offset, true);
const total = offset + centralSize + 22;
const zip = new Uint8Array(total);
let pos = 0;
for (let i = 0; i < files.length; i++) {
zip.set(localHeaders[i].header, pos); pos += localHeaders[i].header.length;
zip.set(fileDatas[i], pos); pos += fileDatas[i].length;
}
for (const c of centralParts) { zip.set(c, pos); pos += c.length; }
zip.set(end, pos);
return new Blob([zip], { type: 'application/zip' });
}
// ==================== Ambil Judul ====================
function getTitle() {
try {
const h1 = document.querySelector('h1.text-xl') ||
document.querySelector('h1.font-black') ||
document.querySelector('h1');
if (h1) {
let text = h1.textContent.trim()
.replace(/[\\/:*?"<>|]/g, '')
.replace(/\s+/g, ' ')
.trim();
if (text.length > 3) return text.slice(0, 80);
}
let pageTitle = document.title || '';
pageTitle = pageTitle.replace(/\s*[-|–]\s*DoujinDesu.*$/i, '').trim();
if (pageTitle.length > 3) {
return pageTitle.replace(/[\\/:*?"<>|]/g, '').slice(0, 80);
}
} catch (e) {}
return '';
}
// ==================== Deteksi ====================
function isTargetImage(url) {
if (!url || typeof url !== 'string') return false;
const u = url.toLowerCase();
const isImageExt = u.includes('.webp') || u.includes('.jpg') || u.includes('.jpeg') || u.includes('.png');
if (!isImageExt) return false;
return (
u.includes('amz-ch.desu.pics') ||
u.includes('desu.pics') ||
u.includes('x-amz-') ||
u.includes('storage/uploads') ||
/\/[a-z0-9]{18,}\.(webp|jpg|jpeg|png)/i.test(u)
);
}
function addUrl(url) {
if (!url || imageURLs.includes(url)) return false;
if (isTargetImage(url)) {
imageURLs.push(url);
return true;
}
return false;
}
function scanXAmz() {
let changed = false;
const newUrls = [];
document.querySelectorAll('img').forEach(img => {
const candidates = [img.src, img.currentSrc, img.dataset.src];
for (const src of candidates) {
if (src && isTargetImage(src) && !newUrls.includes(src) && !imageURLs.includes(src)) {
newUrls.push(src);
}
}
});
try {
performance.getEntriesByType('resource').forEach(entry => {
if (isTargetImage(entry.name) && !newUrls.includes(entry.name) && !imageURLs.includes(entry.name)) {
newUrls.push(entry.name);
}
});
} catch (e) {}
if (newUrls.length > 0) {
imageURLs.push(...newUrls);
changed = true;
}
if (changed) updatePanel();
return changed;
}
if ('PerformanceObserver' in window) {
try {
new PerformanceObserver((list) => {
let changed = false;
for (const entry of list.getEntries()) {
if (addUrl(entry.name)) changed = true;
}
if (changed) updatePanel();
}).observe({ type: 'resource', buffered: true });
} catch (e) {}
}
// ==================== UI ====================
function createButton() {
if (document.getElementById('xamz-open-button')) return;
const btn = document.createElement('button');
btn.id = 'xamz-open-button';
btn.innerHTML = `<img src="${ICON_FLOAT}" style="width:22px;height:22px;vertical-align:middle;margin-right:6px;border-radius:50%;"> DoujinDesu DL`;
Object.assign(btn.style, {
position: 'fixed', right: '15px', bottom: '15px', zIndex: '2147483647',
background: '#ff2d95', color: '#000', border: 'none', borderRadius: '8px',
padding: '8px 14px', fontSize: '14px', fontWeight: 'bold', cursor: 'pointer',
boxShadow: '0 3px 15px rgba(255,45,149,.5)', display: 'flex', alignItems: 'center'
});
btn.onclick = openPanel;
document.body.appendChild(btn);
}
function openPanel() {
if (panelOpen) return;
panelOpen = true;
scanXAmz();
autoScanInterval = setInterval(() => {
if (panelOpen) scanXAmz();
}, 2000);
const autoTitle = getTitle();
const overlay = document.createElement('div');
overlay.id = 'xamz-overlay';
overlay.innerHTML = `
<div id="xamz-box">
<div id="xamz-header">
<div><b>📚 DoujinDesu Downloader by qxyraxp</b> <span id="xamz-count">0 gambar</span></div>
<button id="xamz-close">✕</button>
</div>
<div id="xamz-toolbar">
<button id="xamz-refresh">🔄 Refresh</button>
<button id="xamz-select-all">☑ Semua</button>
<button id="xamz-select-none">☐ Batal</button>
<button id="xamz-download-selected"><img src="${ICON_SELECTED}" style="width:18px;height:18px;vertical-align:middle;margin-right:5px;border-radius:50%;"> Download Terpilih</button>
<button id="xamz-download-zip"><img src="${ICON_ZIP}" style="width:18px;height:18px;vertical-align:middle;margin-right:5px;border-radius:50%;"> Download ZIP</button>
</div>
<div id="xamz-zipname-row">
<label>Nama ZIP:</label>
<input id="xamz-zipname" type="text" value="${autoTitle}" placeholder="Nama file ZIP...">
</div>
<div id="xamz-status"></div>
<div id="xamz-grid"></div>
</div>
`;
document.body.appendChild(overlay);
createStyles();
document.getElementById('xamz-close').onclick = closePanel;
document.getElementById('xamz-refresh').onclick = () => { scanXAmz(); updatePanel(); };
document.getElementById('xamz-select-all').onclick = () => {
document.querySelectorAll('#xamz-grid input[type="checkbox"]').forEach(cb => cb.checked = true);
};
document.getElementById('xamz-select-none').onclick = () => {
document.querySelectorAll('#xamz-grid input[type="checkbox"]').forEach(cb => cb.checked = false);
};
document.getElementById('xamz-download-selected').onclick = downloadSelected;
document.getElementById('xamz-download-zip').onclick = downloadAsZip;
updatePanel();
}
function closePanel() {
document.getElementById('xamz-overlay')?.remove();
panelOpen = false;
if (autoScanInterval) {
clearInterval(autoScanInterval);
autoScanInterval = null;
}
}
function createStyles() {
if (document.getElementById('xamz-style')) return;
const style = document.createElement('style');
style.id = 'xamz-style';
style.textContent = `
#xamz-overlay{position:fixed;inset:0;z-index:2147483646;background:rgba(0,0,0,.85);font-family:Arial,sans-serif;color:#fff}
#xamz-box{position:absolute;left:3%;right:3%;top:3%;bottom:3%;background:#0a0a0a;border:2px solid #ff2d95;border-radius:12px;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 0 30px rgba(255,45,149,.3)}
#xamz-header{min-height:55px;background:#1a0011;display:flex;align-items:center;padding:0 15px;border-bottom:1px solid #ff2d95}
#xamz-count{margin-left:10px;color:#ff9ec8;font-size:13px}
#xamz-close{margin-left:auto;background:#ff2d95;color:#000;border:none;border-radius:6px;padding:7px 13px;cursor:pointer;font-weight:bold}
#xamz-close:hover{background:#ff5caf}
#xamz-toolbar{background:#12000c;padding:9px;display:flex;flex-wrap:wrap;gap:7px;border-bottom:1px solid #ff2d95}
#xamz-toolbar button{background:#ff2d95;color:#000;border:1px solid #ff2d95;border-radius:6px;padding:8px 12px;cursor:pointer;font-weight:bold;display:flex;align-items:center}
#xamz-toolbar button:hover{background:#ff5caf;border-color:#ff5caf}
#xamz-zipname-row{background:#0f000a;padding:8px 12px;display:flex;align-items:center;gap:10px;border-bottom:1px solid #ff2d95}
#xamz-zipname-row label{font-size:12px;color:#ff9ec8;white-space:nowrap}
#xamz-zipname{flex:1;padding:7px 10px;border-radius:6px;border:1px solid #ff2d95;background:#1a0011;color:#fff;font-size:13px}
#xamz-zipname:focus{outline:none;border-color:#ff5caf;box-shadow:0 0 0 2px rgba(255,45,149,.3)}
#xamz-status{min-height:22px;padding:6px 12px;color:#ff9ec8;font-size:12px}
#xamz-grid{flex:1;overflow:auto;padding:12px;display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px;align-content:start;background:#0a0a0a}
.xamz-item{position:relative;background:#12000c;border:1px solid #ff2d95;border-radius:7px;padding:7px}
.xamz-item:hover{border-color:#ff5caf;box-shadow:0 0 10px rgba(255,45,149,.4)}
.xamz-item img{width:100%;height:250px;object-fit:contain;display:block;background:#000;border-radius:4px;cursor:pointer}
.xamz-item label{display:flex;align-items:center;gap:7px;margin-top:7px;font-size:12px;color:#ff9ec8}
.xamz-number{position:absolute;left:12px;top:12px;background:rgba(255,45,149,.9);color:#000;padding:3px 7px;border-radius:4px;font-size:12px;font-weight:bold}
`;
document.head.appendChild(style);
}
function updatePanel() {
const grid = document.getElementById('xamz-grid');
if (!grid) return;
document.getElementById('xamz-count').textContent = imageURLs.length + ' gambar';
grid.innerHTML = '';
if (!imageURLs.length) {
grid.innerHTML = `<div style="grid-column:1/-1;text-align:center;padding:50px;color:#ff9ec8">
Scroll halaman sampai gambar muncul, lalu tekan Refresh
</div>`;
return;
}
imageURLs.forEach((url, index) => {
const item = document.createElement('div');
item.className = 'xamz-item';
item.innerHTML = `
<div class="xamz-number">${String(index + 1).padStart(3, '0')}</div>
<img src="${url}" loading="eager" data-index="${index}">
<label><input type="checkbox" checked data-index="${index}"> Panel ${index + 1}</label>
`;
const img = item.querySelector('img');
const checkbox = item.querySelector('input[type="checkbox"]');
img.addEventListener('click', () => {
checkbox.checked = !checkbox.checked;
});
grid.appendChild(item);
});
}
function getSelectedIndexes() {
return [...document.querySelectorAll('#xamz-grid input:checked')].map(cb => +cb.dataset.index);
}
function downloadSelected() {
const indexes = getSelectedIndexes();
if (!indexes.length) return alert('Pilih dulu panelnya');
startDownloads(indexes);
}
// ==================== ZIP ====================
async function downloadAsZip() {
const indexes = getSelectedIndexes();
if (!indexes.length) return alert('Pilih dulu panelnya');
let zipName = (document.getElementById('xamz-zipname')?.value || '').trim()
.replace(/[\\/:*?"<>|]/g, '');
if (!zipName) zipName = 'DoujinDesu';
if (!zipName.toLowerCase().endsWith('.zip')) zipName += '.zip';
const status = document.getElementById('xamz-status');
const files = [];
let ok = 0, fail = 0;
status.textContent = `⏳ Mengambil gambar 0/${indexes.length}`;
for (let i = 0; i < indexes.length; i++) {
const idx = indexes[i];
status.textContent = `⏳ Mengambil gambar ${i + 1}/${indexes.length}`;
try {
const blob = await fetchImageAsBlob(imageURLs[idx]);
if (blob) {
const ext = getExtFromUrl(imageURLs[idx]);
const name = String(idx + 1).padStart(3, '0') + '.' + ext;
files.push({ name, data: new Uint8Array(await blob.arrayBuffer()) });
ok++;
} else fail++;
} catch (e) {
fail++;
}
await new Promise(r => setTimeout(r, 120));
}
if (ok === 0) {
status.textContent = '❌ Tidak ada gambar yang berhasil diambil';
return;
}
status.textContent = '⏳ Membuat ZIP...';
try {
const zipBlob = createZip(files);
const a = document.createElement('a');
a.href = URL.createObjectURL(zipBlob);
a.download = zipName;
a.click();
URL.revokeObjectURL(a.href);
status.textContent = `✅ ZIP berhasil! ${ok} gambar${fail > 0 ? `, ${fail} gagal` : ''}`;
} catch (e) {
status.textContent = '❌ Gagal membuat ZIP';
}
}
// ==================== Helper ====================
function getExtFromUrl(url) {
try {
const pathname = new URL(url).pathname.toLowerCase();
if (pathname.endsWith('.webp')) return 'webp';
if (pathname.endsWith('.jpg') || pathname.endsWith('.jpeg')) return 'jpg';
if (pathname.endsWith('.png')) return 'png';
} catch (e) {}
return 'jpg';
}
function fetchImageAsBlob(url) {
return new Promise((resolve) => {
const img = [...document.querySelectorAll('#xamz-grid img')].find(i => i.src === url);
if (img && img.complete && img.naturalWidth > 0) {
try {
const canvas = document.createElement('canvas');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
canvas.getContext('2d').drawImage(img, 0, 0);
const ext = getExtFromUrl(url);
const mime = ext === 'webp' ? 'image/webp' : 'image/jpeg';
canvas.toBlob(b => resolve(b), mime, 0.92);
return;
} catch (e) {}
}
GM_xmlhttpRequest({
method: 'GET',
url: url,
responseType: 'arraybuffer',
headers: {
'Referer': location.href,
'Origin': location.origin,
'Accept': 'image/webp,image/jpeg,image/*,*/*;q=0.8'
},
onload: (res) => {
if (res.status >= 200 && res.status < 300) {
let mime = 'image/jpeg';
const ct = (res.responseHeaders || '').toLowerCase();
if (ct.includes('image/webp')) mime = 'image/webp';
else if (ct.includes('image/png')) mime = 'image/png';
resolve(new Blob([res.response], { type: mime }));
} else resolve(null);
},
onerror: () => resolve(null),
ontimeout: () => resolve(null)
});
});
}
async function downloadOne(index) {
const url = imageURLs[index];
const ext = getExtFromUrl(url);
const filename = String(index + 1).padStart(3, '0') + '.' + ext;
try {
const blob = await fetchImageAsBlob(url);
if (blob) {
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = filename;
a.click();
URL.revokeObjectURL(a.href);
return true;
}
} catch (e) {}
try {
await new Promise((resolve, reject) => {
GM_download({ url, name: filename, saveAs: false, onload: resolve, onerror: reject });
});
return true;
} catch (e) {}
return false;
}
function startDownloads(indexes) {
const status = document.getElementById('xamz-status');
let ok = 0, fail = 0;
status.textContent = `⏳ 0/${indexes.length}`;
(async () => {
for (let i = 0; i < indexes.length; i++) {
status.textContent = `⏳ ${i + 1}/${indexes.length}`;
if (await downloadOne(indexes[i])) ok++;
else fail++;
await new Promise(r => setTimeout(r, 300));
}
status.textContent = `✅ Berhasil ${ok}, gagal ${fail}`;
})();
}
function init() {
if (!document.body) return setTimeout(init, 300);
createButton();
setTimeout(scanXAmz, 1500);
setTimeout(scanXAmz, 4000);
}
init();
})();