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 = 1000; // Milliseconds to give each file to upload before timing out: 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. 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 completed = 0;		var timedOut = [];		document.getElementById('bulkUploadButton').disabled = true;		$('#bulkUploadStatus').empty;		$('#bulkUploadStatus').append('Starting upload... ');

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

async function uploadFile(file, uploadParams) { 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; }				if (timedOut.length > 0) { $('#bulkUploadStatus').append('The following uploads are still running in the background and may never complete; recommend retrying: ' + timedOut + ' ') }			});			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. '); }				});			} catch (e) {				console.error(e);			} finally {				await timeout(SLEEPTIME);				return true;			}		}		var files = $('#bulkUploadFiles')[0].files;

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 uploa func, wait until it completes or times out before going to next file const response = await uploadFile(file, uploadParams); }		}		iterateFiles; }); });