User:DreamRimmer/MassMove.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. |
![]() | This user script seems to have a documentation page at User:DreamRimmer/MassMove. |
//<nowiki>
// Based on [[:meta:User:Indic-TechCom/Script/massMover.js]]
// Advanced functionality
$(document).ready(function() {
function initializeMassMove() {
$('#mw-content-text > p').remove();
$('#firstHeading').text('MassMove');
var pagesTextarea = new OO.ui.MultilineTextInputWidget({
placeholder: 'Enter list of pages (one per line)',
autosize: true,
rows: 10
}),
searchInputField = new OO.ui.TextInputWidget({
placeholder: 'Search'
}),
replaceInputField = new OO.ui.TextInputWidget({
placeholder: 'Replace'
}),
reasonInputField = new OO.ui.TextInputWidget({
placeholder: 'Reason for moving'
}),
regexOptionField = new OO.ui.FieldLayout(
regexCheckbox = new OO.ui.CheckboxInputWidget({
selected: false
}), {
label: 'Use regular expression for search',
align: 'inline'
}),
redirectOptionField = '',
previewButton = new OO.ui.ButtonWidget({
label: 'Preview Move',
flags: ['primary']
}),
startButton = new OO.ui.ButtonWidget({
label: 'Start Move',
icon: 'alert',
flags: ['primary', 'progressive'],
disabled: true
}),
cancelButton = new OO.ui.ButtonWidget({
label: 'Cancel',
flags: ['primary', 'destructive'],
href: 'https:' + mw.config.get('wgServer')
}),
logContainer = $("<div>").hide();
var labels = {
pagesLabel: $('<p>').text('Pages to Move:').css('font-weight', 'bold'),
searchLabel: $('<p>').text('Search:').css('font-weight', 'bold'),
replaceLabel: $('<p>').text('Replace:').css('font-weight', 'bold'),
reasonLabel: $('<p>').text('Reason:').css('font-weight', 'bold')
};
if ($.inArray('sysop', mw.config.get('wgUserGroups')) !== -1 || $.inArray('extendedmover', mw.config.get('wgUserGroups')) !== -1) {
redirectOptionField = new OO.ui.FieldLayout(
redirectCheckbox = new OO.ui.CheckboxInputWidget({
selected: false
}), {
label: "Don't leave a redirect behind (use with caution)",
align: 'inline'
});
}
$('#mw-content-text').append(
labels.pagesLabel, pagesTextarea.$element,
labels.searchLabel, searchInputField.$element,
labels.replaceLabel, replaceInputField.$element,
labels.reasonLabel, reasonInputField.$element,
regexOptionField.$element,
redirectOptionField ? redirectOptionField.$element : '',
'<br/>',
previewButton.$element,
startButton.$element,
cancelButton.$element,
'<br/>',
logContainer
);
function movePage(oldPage, newPage, reason, removeRedirect, callback) {
(new mw.Api({
ajax: {
headers: {
'Api-User-Agent': 'en:User:DreamRimmer/MassMove.js'
}
}
})).postWithToken('csrf', {
action: 'move',
from: oldPage,
to: newPage,
reason: reason,
movetalk: 1,
noredirect: removeRedirect
}, {
async: false
}).done(function(data) {
callback(null, data, oldPage);
}).fail(function(code, data) {
callback(code, data, oldPage);
});
}
function escapeSpecialChars(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}
function showAlert(message) {
alert("Error: " + message);
}
function handleMoveResponse(err, data, page) {
var logList = $("<ul>").appendTo(logContainer);
if (err) {
logList.append("<li>Failed to move page <b>" + page + "</b>: " + err + "</li>");
} else if (data.move) {
logList.append("<li><b>" + data.move.from + "</b> moved to <b>" + data.move.to + "</b>.</li>");
}
}
function previewMoving() {
var pages = pagesTextarea.getValue().replace(/^\s*[\r\n]/gm, '').split("\n"),
searchTerm = searchInputField.getValue().trim(),
replacementTerm = replaceInputField.getValue().trim(),
removeRedirect = false,
useRegex = regexCheckbox.isSelected();
if (pages[0].trim() === "" || searchTerm === "" || replacementTerm === "") {
showAlert("Please fill in all fields.");
return;
}
logContainer.empty();
$("<h1>").wrapInner("<span class='mw-headline'>Move preview</span>").appendTo(logContainer);
logContainer.show();
if ($.inArray('sysop', mw.config.get('wgUserGroups')) !== -1 || $.inArray('extendedmover', mw.config.get('wgUserGroups')) !== -1) {
removeRedirect = redirectCheckbox.isSelected();
}
var logList = $("<ul>").appendTo(logContainer);
pages.forEach(function(page) {
page = page.trim();
var newPageName;
if (!useRegex) {
searchTerm = escapeSpecialChars(searchTerm);
newPageName = page.replace(searchTerm, replacementTerm);
} else {
try {
searchTerm = new RegExp(searchTerm, 'gi');
newPageName = page.replace(searchTerm, replacementTerm);
} catch (e) {
logList.append("<li>Invalid regex for page <b>" + page + "</b>: " + e.message + "</li>");
return;
}
}
logList.append("<li><b>" + page + "</b> will be moved to <b>" + newPageName + "</b> (Redirect: " + (removeRedirect ? "No" : "Yes") + ")</li>");
});
startButton.setDisabled(false);
}
function startMoving() {
var pages = pagesTextarea.getValue().replace(/^\s*[\r\n]/gm, '').split("\n"),
searchTerm = searchInputField.getValue().trim(),
replacementTerm = replaceInputField.getValue().trim(),
reason = reasonInputField.getValue().trim() + " (using [[User:DreamRimmer/MassMove|MassMove.js]])",
removeRedirect = false,
useRegex = regexCheckbox.isSelected();
if (pages[0].trim() === "" || searchTerm === "" || replacementTerm === "") {
showAlert("Please fill in all fields.");
return;
}
logContainer.empty();
$("<h1>").wrapInner("<span class='mw-headline'>Move log</span>").appendTo(logContainer);
logContainer.show();
if ($.inArray('sysop', mw.config.get('wgUserGroups')) !== -1 || $.inArray('extendedmover', mw.config.get('wgUserGroups')) !== -1) {
removeRedirect = redirectCheckbox.isSelected();
}
var currentIndex = 0;
var isSysop = $.inArray('sysop', mw.config.get('wgUserGroups')) !== -1;
function getRandomSleepTime() {
var sleepTimes = [6000, 7000, 8000];
return sleepTimes[Math.floor(Math.random() * sleepTimes.length)];
}
function processNextPage() {
if (currentIndex >= pages.length) {
return;
}
var page = pages[currentIndex].trim(),
newPageName;
if (!useRegex) {
searchTerm = escapeSpecialChars(searchTerm);
newPageName = page.replace(searchTerm, replacementTerm);
} else {
try {
searchTerm = new RegExp(searchTerm, 'gi');
newPageName = page.replace(searchTerm, replacementTerm);
} catch (e) {
alert("Invalid regex: " + e.message);
currentIndex++;
processNextPage();
return;
}
}
movePage(page, newPageName, reason, removeRedirect, function(err, data) {
handleMoveResponse(err, data, page);
currentIndex++;
if (!err) {
if (isSysop) {
setTimeout(processNextPage, 2000);
} else {
setTimeout(processNextPage, getRandomSleepTime());
}
} else {
processNextPage();
}
});
}
processNextPage();
}
previewButton.on('click', previewMoving);
startButton.on('click', startMoving);
}
$.when(mw.loader.using('mediawiki.util'), $.ready).then(function() {
mw.util.addPortletLink(
'p-tb',
mw.util.getUrl('Special:BlankPage/MassMove'),
'MassMove'
);
});
if (mw.config.get('wgCanonicalSpecialPageName') === 'Blankpage' && mw.config.get('wgTitle').split('/', 2)[1] === 'MassMove') {
$.when(mw.loader.using('oojs-ui-core'), $.ready).then(function() {
initializeMassMove();
});
}
});
//</nowiki>