MediaWiki:Gadget-BulkUpload/Runtime.js

/** * Turns Special:BulkUpload into a bulk upload form. Filenames are kept as-is and all files will have the same information. * Created by SuperHamster on Nookipedia (https://nookipedia.com/wiki/User:SuperHamster) * Licensed under CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0/) **/

(function {	"use strict";

// Set title of page as it appears in the browser tab:: const PAGETITLE = "Bulk upload form - Animal Crossing Wiki - Nookipedia"; // List of warnings that always result in upload failure, even if ignorewarnings is checked: const FATALWARNINGS = ["fileexists-no-change", "verification-error", "abusefilter-disallowed"]; // Milliseconds to wait between uploads, to avoid rate limiting: const SLEEPTIME = 500; // Milliseconds to give each file to upload before moving to the next file: const TIMEOUT = 30000; // Default file description that is loaded in the form: const DEFAULTDESCRIPTION = `== Summary ==

Licensing
`;

document.title = PAGETITLE; $('#firstHeading').html('Bulk upload form'); $('#bodyContent').empty; $('#bodyContent').append(' Use this form to upload multiple files at once. Filenames are kept as-is and all files will have the same information. Uploads through this tool are marked as bot edits in recent changes. To cancel an upload that is in progress, simply navigate away from this page. '); var htmlUploadForm = ` Files and info Select files:  File description ` + DEFAULTDESCRIPTION + ` Ignore warnings (check to override existing files) Upload files Upload status Waiting for user to start upload. `;	$('#bodyContent').append(htmlUploadForm); document.getElementById('bulkUploadButton').addEventListener("click", function {		const api = new mw.Api;		var started = 0;		var completed = 0;		var timedOut = [];		document.getElementById('bulkUploadButton').disabled = true;		$('#bulkUploadStatus').empty;

function timeout(ms) { return new Promise(resolve => { setTimeout( => resolve('timed out'), ms)}); }

async function uploadFile(file, uploadParams) { started++; $('#bulkUploadStatus').append('Starting upload for ' + file.name + '... '); let uploadPromise = api.upload(file, uploadParams).always(response => {				completed++;				var status = "";				if (timedOut.includes(file.name)) {					timedOut = timedOut.filter(item => item !== file.name);				}				if (typeof response === 'object') {					if (response.hasOwnProperty('upload') && upload.result == 'Success') {						status = 'Upload succeeded for ' + file.name;					} else {						status = 'Upload failed for ' + file.name + ' due to unknown error';					}				} else if (typeof response === 'string') {					if (FATALWARNINGS.includes(response)) {						status = 'Upload failed for ' + file.name + ' with error "' + response + '"';					} else {						if ($('#bulkUploadIgnoreWarnings').is(':checked')) {							status = 'Upload succeeded for ' + file.name + ' with warning "' + response + '"';						} else {							status = 'Upload failed for ' + file.name + ' with error "' + response + '"'; }					}				} else { status = 'Upload failed for ' + file.name + ' due to unknown error'; }				$('#bulkUploadStatus').append(status + ' (' + completed + ' out of ' + files.length + ') '); if (completed == files.length) { $('#bulkUploadStatus').append(' Done! '); document.getElementById('bulkUploadButton').disabled = false; }			});			try {				var onTimeout = timeout(TIMEOUT);				await Promise.race([uploadPromise, onTimeout]).then((value) => { if (value === 'timed out') { timedOut.push(file.name); $('#bulkUploadStatus').append(file.name + ' is taking a long time to upload; moving to the next file. '); }					if (started == files.length && timedOut.length > 0) { $('#bulkUploadStatus').append('The following uploads are still running in the background and may be stuck; recommend retrying: ' + timedOut + ' ') }				}).catch((value) => { if (value === 'timed out') { timedOut.push(file.name); $('#bulkUploadStatus').append(file.name + ' is taking a long time to upload; moving to the next file. '); }					if (started == files.length && timedOut.length > 0) { $('#bulkUploadStatus').append('The following uploads are still running in the background and may be stuck; recommend retrying: ' + timedOut + ' ') }				})			} catch (e) {				console.error(e);			} finally {				await timeout(SLEEPTIME);				return true;			}		}

async function iterateFiles { // Remove duplicates: const uniqueFiles = [...new Set(files)];

// Iterate through files and set upload params: for (const file of uniqueFiles) { var uploadParams = {}; if($('#bulkUploadIgnoreWarnings').is(':checked')) { uploadParams = { filename: file.name, text: $('#bulkUploadInfo').val, comment: "Uploaded via bulk upload gadget", ignorewarnings: "yes", format: "json" };				} else { uploadParams = { filename: file.name, text: $('#bulkUploadInfo').val, comment: "Uploaded via bulk upload gadget", format: "json" };				}

// Call upload func, wait until it completes or times out before going to next file const response = await uploadFile(file, uploadParams); }		}

var files = $('#bulkUploadFiles')[0].files; iterateFiles; }); });