User:SD0001/massMoveRevert.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
![]() | Documentation for this user script can be added at User:SD0001/massMoveRevert. |
/*
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);
});
});
}