您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Upload a large gallery in small batches
// ==UserScript== // @name EhBatchUpload // @namespace http://tampermonkey.net/ // @version 2025-06-17 // @description Upload a large gallery in small batches // @author 4piu // @license MIT // @match https://upload.e-hentai.org/managegallery* // @match https://upld.exhentai.org/upld/managegallery* // @icon https://www.google.com/s2/favicons?sz=64&domain=e-hentai.org // @grant none // ==/UserScript== (function() { 'use strict'; let batchSize = 5; let filesToUpload = []; let filesUploaded = 0; let totalFiles = 0; let currentBatch = 0; let totalBatches = 0; let batchPercent = 0; let uploadInProgress = false; let uploadMessage = ''; // Create a progress display element function createProgressDisplay() { const progressDiv = document.createElement('div'); progressDiv.id = 'batchProgress'; progressDiv.style.cssText = 'padding: 10px; border: 1px solid;'; progressDiv.innerHTML = '<p id="uploadMessage" style="font-weight: bold;"></p>' + '<p>Status: <span id="batchStatus">Idle</span></p>' + '<p>Files Uploaded: <span id="filesUploaded">0</span>/<span id="totalFiles">0</span> <span id="totalPercent"></span></p>' + '<p>Current Batch: <span id="currentBatch">0</span>/<span id="totalBatches">0</span> <span id="batchPercent"></span></p>'; document.getElementById('u').appendChild(progressDiv); } // Create a input box for batch size function createBatchSizeInput() { const batchSizeInputDiv = document.createElement('div'); batchSizeInputDiv.innerHTML = '<label for="batchSizeInput">Batch size</label>' + `<input type="number" id="batchSizeInput" name="batchSizeInput" value="${batchSize}" style="width: 40px; line-height: 19px; border: 2px solid; margin: 3px 1px 0; padding: 1px 3px 3px; border-radius: 3px;">`; document.getElementById('uploadbutton').parentNode.appendChild(batchSizeInputDiv); } // Update progress display function updateProgressDisplay() { document.getElementById('batchStatus').textContent = uploadInProgress ? 'Uploading...' : 'Idle'; document.getElementById('filesUploaded').textContent = filesUploaded; document.getElementById('totalFiles').textContent = totalFiles; document.getElementById('totalPercent').textContent = uploadInProgress? `[${(filesUploaded / totalFiles * 100).toFixed(1)}%]` : ''; document.getElementById('currentBatch').textContent = currentBatch + 1; document.getElementById('totalBatches').textContent = totalBatches; document.getElementById('batchPercent').textContent = uploadInProgress? `[${batchPercent.toFixed(1)}%]` : ''; document.getElementById('uploadMessage').textContent = uploadMessage; } // Upload a single batch of files function uploadBatch(batchFiles) { if (batchFiles.length === 0) { currentBatch++; uploadNextBatch(); return; } const formData = new FormData(); batchFiles.forEach(file => formData.append('files[]', file)); // Copy hidden inputs from original form const originalForm = document.getElementById('uploadform'); const hiddenInputs = originalForm.querySelectorAll('input[type="hidden"]'); hiddenInputs.forEach(input => { formData.append(input.name, input.value); }); uploadInProgress = true; updateProgressDisplay(); const xhr = new XMLHttpRequest(); xhr.open('POST', originalForm.action, true); xhr.upload.onprogress = function(e) { if (e.lengthComputable) { batchPercent = (e.loaded / e.total) * 100; updateProgressDisplay(); } }; xhr.onload = function() { if (xhr.status === 200) { currentBatch < totalBatches && currentBatch++; filesToUpload = filesToUpload.slice(batchFiles.length); filesUploaded = totalFiles - filesToUpload.length; uploadInProgress = false; updateProgressDisplay(); uploadNextBatch(); } else { uploadMessage = `Error uploading batch ${currentBatch + 1}: ${xhr.statusText}`; uploadInProgress = false; updateProgressDisplay(); document.getElementById('batchSizeInput').disabled = false; } }; xhr.onerror = function() { uploadMessage = `Error uploading batch ${currentBatch + 1}: Network Error`; uploadInProgress = false; updateProgressDisplay(); document.getElementById('batchSizeInput').disabled = false; }; xhr.send(formData); } // Start uploading the next batch function uploadNextBatch() { if (currentBatch >= totalBatches || filesToUpload.length === 0) { uploadMessage = 'All batches uploaded successfully! Please refresh page to see results. '; uploadInProgress = false; updateProgressDisplay(); document.getElementById('batchSizeInput').disabled = false; return; } const start = 0; const end = Math.min(batchSize, filesToUpload.length); const batchFiles = filesToUpload.slice(start, end); uploadBatch(batchFiles); } // Override the original submit_upload function function overrideSubmitUpload() { window.submit_upload = function() { if (uploadInProgress) { alert('Upload in progress. Please wait until the current batch completes.'); return; } const fileInput = document.getElementById('uploadfiles'); if (!fileInput.files.length) { alert('Please select files to upload.'); return; } if (!disable_submit()) { return; } const batchSizeInput = document.getElementById('batchSizeInput'); batchSize = parseInt(batchSizeInput.value) || batchSize; // Fallback to current value if invalid batchSizeInput.disabled = true; filesToUpload = Array.from(fileInput.files); totalFiles = filesToUpload.length; filesUploaded = 0; totalBatches = Math.ceil(filesToUpload.length / batchSize); currentBatch = 0; document.getElementById('uploadbutton').value = 'Uploading...'; updateProgressDisplay(); uploadNextBatch(); }; } // Initialize the script function init() { createProgressDisplay(); createBatchSizeInput(); overrideSubmitUpload(); console.info('EhBatchUpload loaded'); } // Run initialization when DOM is fully loaded if (document.readyState === 'complete') { init(); } else { window.addEventListener('load', init); } })();