Jump to content

User:DreamRimmer/MassMove.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.
//<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>