User:SD0001/massMoveRevert.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/*
	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 '<a href="' + mw.util.getUrl(target) + '" target="_blank" title="' + target + '">' + text + '</a>';
			}
		);
	});

}

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);
		});
	});

}