User:SD0001/massMoveRevert.js

/*	Script to mass revert page moves by a user Will only work for admins because of rate limits. To use, add importScript('User:SD0001/massMoveRevert.js'); // User:SD0001/massMoveRevert.js to your common.js page Go to the relevant user contribs, and select "MMR" (short for Mass Move Revert) from the "More" dropdown. If you abuse this tool, it is your fault, not mine. This tool will NOT suppress any redirects, nor delete pages to make way for a move.

$.when(	mw.loader.using(['ext.gadget.morebits', 'mediawiki.api']),	$.ready ).then(function {

// non-admins have tight rate limits on moving pages, so this script won't work if (!Morebits.userIsSysop) { return; }

user = mw.config.get('wgRelevantUserName'); // var is omitted for a reason if (!user) { return; }

mw.util.addPortletLink('p-cactions', '#', 'MMR', 'mmr-portlet', 'Mass move revert tool'); $('#mmr-portlet').click(callback);

});

var movedata = {}; var user = null;

function callback { var Window = new Morebits.simpleWindow(630, 600); Window.setTitle('Mass Move Revert Tool');

var form = new Morebits.quickForm(evaluate);

form.append({		type: 'div',		label: 'Uncheck any moves that you don\'t want to revert',		style: 'font-weight: bold; font-size: 13px'	});

form.append({		type: 'div',		id: 'mmrWorkArea',		className: 'morebits-scrollbox',		style: 'max-height: 36em'	});

form.append({		type: 'input',		label: 'Reason for reverting: ',		name: 'reason',		size: '80px'	});

form.append({ type: 'submit', label: 'Revert selected moves' });

var result = form.render; Window.setContent(result); Window.display;

getMoves.then(makeUI) }

function getMoves {

$('#mmrWorkArea').text('Loading...').css('font-size', '13px');

return new mw.Api.get({		"action": "query",		"format": "json",		"list": "logevents",		"formatversion": "2",		"letype": "move",		"leprop": "title|user|details|comment",		"leuser": mw.config.get('wgRelevantUserName'),		"lelimit": "5000"	}).then(function(data) {		var moves = data.query.logevents;		moves.forEach(function(move) { movedata[move.title] = { dest: move.params.target_title, summary: move.comment };		});	}); }

function makeUI {

var items = Object.keys(movedata).map(function(fromtitle, idx) {		var totitle = movedata[fromtitle].dest;		var summary = movedata[fromtitle].summary;		return {			label:  + fromtitle +  + ' moved to ' + totitle + '' + (summary ? ' (' + summary + ')' : ''),			value: idx,			checked: true		};	});

var text = new Morebits.quickForm.element({		type: 'div',		label: 'Loaded ' + Object.keys(movedata).length + ' moves done by ' + user	});

var list = new Morebits.quickForm.element({		type: 'checkbox',		name: 'pages',		list: items	});

$('#mmrWorkArea').empty.append(		text.render,		list.render	); Morebits.checkboxShiftClickSupport(Morebits.quickForm.getElements($('#mmrWorkArea')[0], 'pages'));

$('#mmrWorkArea label').each(function {		this.innerHTML = this.innerHTML.replace( /\[\[:?(?:([^\|\]]+?)\|)?([^\]\|]+?)\]\]/g, function(_, target, text) { if (!target) { target = text; }				return '' + text + ''; }		);	});

}

function evaluate(event) { var form = event.target;

var worklist = Object.keys(movedata).map(function(page, idx) {		if ( $('[name=pages][value=' + idx + ']', form).is(':checked') ) {			return {				movefrom: movedata[page].dest, // reversed order				moveto: page			};		}	}).filter(function(e) { return e; }); // filter out undefineds

var len = worklist.length;

var reason = form.reason.value.trim; if (!reason) { return alert('You need to provide a reason, you hear me?'); }

if (!confirm('Are you sure that you want to revert ' + len + ' page moves?')) { return; }

Morebits.simpleWindow.setButtonsEnabled(false); Morebits.status.init(form);

revertMoves(worklist, reason);

}

function revertMoves(worklist, reason) {

var op = new Morebits.batchOperation('Reverting moves'); op.setPageList(worklist); op.run(function worker(item) {

var st = new Morebits.status('Moving ' + item.movefrom + ' to ' + item.moveto); st.info('Doing');

// setTimeout(function {		// 	op.workerSuccess;		// 	st.info('Done');		// }, 1000);

var p = new Morebits.wiki.page(item.movefrom); p.setMoveDestination(item.moveto); p.setEditSummary(reason); p.move(function {			op.workerSuccess;			st.info('Done');		}, function(e) {			op.workerFailure;			st.error('Failed: ' + e.errorCode + ': ' + e.errorText);		}); });

}