Jump to content

User:DreamRimmer/test.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.
mw.loader.using(['mediawiki.api', 'mediawiki.util', 'oojs-ui'], function () {
    'use strict';
    const api = new mw.Api();
    let token = null;

    async function getToken() {
        try {
            const res = await api.get({
                action: 'query',
                meta: 'tokens',
                type: 'csrf'
            });
            token = res.query.tokens.csrftoken;
        } catch (e) {
            console.error('Error getting token:', e);
            throw e;
        }
    }

    function UserInputWidget(type) {
        OO.ui.Widget.call(this);
        this.textInput = new OO.ui.TextInputWidget({
            placeholder: type === 'rename' ? 'Old username' : 'Enter username',
            required: true
        });
        if (type === 'rename') {
            this.newTextInput = new OO.ui.TextInputWidget({
                placeholder: 'New username',
                required: true
            });
            this.layout = new OO.ui.HorizontalLayout({
                items: [this.textInput, this.newTextInput]
            });
        } else {
            this.layout = new OO.ui.HorizontalLayout({
                items: [this.textInput]
            });
        }
        this.$element
            .addClass('userInputWidget')
            .css({
                'margin-bottom': '4px'
            });
        this.$element.append(this.layout.$element);
    }
    OO.inheritClass(UserInputWidget, OO.ui.Widget);

    function createUserField(type) {
        return new UserInputWidget(type);
    }

    function ManageRALDialog(config) {
        ManageRALDialog.super.call(this, config);
    }
    OO.inheritClass(ManageRALDialog, OO.ui.ProcessDialog);

    ManageRALDialog.static.name = 'manageRALDialog';
    ManageRALDialog.static.title = 'Manage RAL';
    ManageRALDialog.static.actions = [
        { action: 'accept', label: 'Submit', flags: ['primary', 'progressive'] },
        { action: 'cancel', label: 'Cancel', flags: 'safe' }
    ];

    ManageRALDialog.prototype.initialize = function () {
        ManageRALDialog.super.prototype.initialize.apply(this, arguments);
        this.actionDropdown = new OO.ui.DropdownInputWidget({
            options: [
                { data: 'add', label: 'Add users' },
                { data: 'remove', label: 'Remove users' },
                { data: 'rename', label: 'Rename users' }
            ],
            value: 'add'
        });
        this.userContainer = new OO.ui.FieldsetLayout({
            label: 'Users:'
        });
        this.userContainer.addItems([createUserField('add')]);
        this.actionDropdown.on('change', (value) => {
            this.userContainer.clearItems();
            this.userContainer.addItems([createUserField(value)]);
            this.updateSize();
        });
        const addButton = new OO.ui.ButtonWidget({
            label: '+',
            flags: ['progressive']
        });
        addButton.$element.css({
            'margin-top': '4px'
        });
        addButton.on('click', () => {
            this.userContainer.addItems([createUserField(this.actionDropdown.getValue())]);
            this.updateSize();
        });
        this.content = new OO.ui.PanelLayout({ padded: true, expanded: false });
        this.content.$element.append(
            new OO.ui.FieldsetLayout({
                items: [
                    new OO.ui.FieldLayout(this.actionDropdown, { label: 'Action:', align: 'top' }),
                    this.userContainer,
                    new OO.ui.FieldLayout(addButton)
                ]
            }).$element
        );
        this.$body.append(this.content.$element);
        this.alertContainer = new OO.ui.LabelWidget({ label: '' });
        this.alertContainer.$element.css({ 
            padding: '5px',
            margin: '5px 0',
            display: 'none'
        });
        this.$body.append(this.alertContainer.$element);
    };

    ManageRALDialog.prototype.getBodyHeight = function () {
        return this.content.$element.outerHeight(true) + this.alertContainer.$element.outerHeight(true) + 20;
    };

    ManageRALDialog.prototype.getActionProcess = function (action) {
        if (action === 'accept') {
            return new OO.ui.Process(async () => {
                const users = this.userContainer.items.map(widget => {
                    return {
                        oldUsername: widget.textInput.getValue(),
                        newUsername: widget.newTextInput ? widget.newTextInput.getValue() : null
                    };
                }).filter(user => user.oldUsername);
                const actionType = this.actionDropdown.getValue();
                if (users.length === 0) {
                    this.showAlert('Please enter at least one username.', 'error');
                    return;
                }
                const result = await editRALPage(users, actionType);
                let message = '';
                if (actionType === 'add') {
                    if (result.added.length) message += 'Added: ' + result.added.join(', ') + '. ';
                    if (result.alreadyExists.length) message += 'Already in list: ' + result.alreadyExists.join(', ') + '.';
                } else if (actionType === 'remove') {
                    if (result.removed.length) message += 'Removed: ' + result.removed.join(', ') + '. ';
                    if (result.failedRemove.length) message += 'Failed to remove: ' + result.failedRemove.join(', ') + '.';
                } else if (actionType === 'rename') {
                    if (result.renamed.length) message += 'Renamed: ' + result.renamed.join(', ') + '. ';
                    if (result.failedRename.length) message += 'Failed to rename: ' + result.failedRename.join(', ') + '.';
                }
                this.showAlert(message, 'success');
                setTimeout(() => {
                    window.location.href = mw.util.getUrl('User:DreamRimmer/sandbox', { diff: 'cur' });
                    this.close({ action: 'accept' });
                }, 6000);
            });
        } else if (action === 'cancel') {
            return new OO.ui.Process(() => {
                this.close({ action: 'cancel' });
            });
        }
    };

    ManageRALDialog.prototype.showAlert = function (message, type) {
        this.alertContainer.setLabel(message);
        this.alertContainer.$element.css('color', type === 'error' ? 'red' : 'green');
        this.alertContainer.$element.show();
        this.updateSize();
    };

    async function editRALPage(users, actionType) {
        if (!token) await getToken();
        const res = await api.get({
            action: 'query',
            prop: 'revisions',
            titles: 'User:DreamRimmer/sandbox',
            rvprop: 'content',
            format: 'json'
        });
        const pages = res.query.pages;
        const data = pages[Object.keys(pages)[0]];
        let content = data.revisions[0]['*'];
        const startMarker = '<!-- DannyS712 bot III: autopatrol list start -->';
        const endMarker = '<!-- DannyS712 bot III: autopatrol list end -->';
        const startIndex = content.indexOf(startMarker) + startMarker.length;
        const endIndex = content.indexOf(endMarker);
        let listContent = content.substring(startIndex, endIndex).trim().split('\n').filter(line => line.trim());
        let added = [], alreadyExists = [], removed = [], failedRemove = [], renamed = [], failedRename = [];

        users.forEach(user => {
            const oldUserEntry = `* {{user2|${user.oldUsername}}}`;
            const newUserEntry = `* {{user2|${user.newUsername}}}`;
            if (actionType === 'add') {
                if (!listContent.includes(oldUserEntry)) {
                    listContent.push(oldUserEntry);
                    added.push(user.oldUsername);
                } else {
                    alreadyExists.push(user.oldUsername);
                }
            } else if (actionType === 'remove') {
                const index = listContent.indexOf(oldUserEntry);
                if (index !== -1) {
                    listContent.splice(index, 1);
                    removed.push(user.oldUsername);
                } else {
                    failedRemove.push(user.oldUsername);
                }
            } else if (actionType === 'rename') {
                if (user.newUsername) {
                    const index = listContent.indexOf(oldUserEntry);
                    if (index !== -1) {
                        listContent.splice(index, 1);
                        const insertionIndex = listContent.findIndex(entry => entry > newUserEntry);
                        if (insertionIndex === -1) {
                            listContent.push(newUserEntry);
                        } else {
                            listContent.splice(insertionIndex, 0, newUserEntry);
                        }
                        renamed.push(user.oldUsername + '->' + user.newUsername);
                    } else {
                        failedRename.push(user.oldUsername);
                    }
                }
            }
        });
        const newListContent = listContent.join('\n');
        const newContent = content.substring(0, startIndex) + '\n' + newListContent + '\n' + content.substring(endIndex);
        const editResult = await api.postWithToken('csrf', {
            action: 'edit',
            title: 'User:DreamRimmer/sandbox',
            text: newContent,
            summary: `Updating RAL`,
            format: 'json'
        });
        return { added, alreadyExists, removed, failedRemove, renamed, failedRename, revisionId: editResult.edit.newrevid };
    }

    function init() {
        if (mw.config.get('wgPageName') !== 'User_talk:DreamRimmer/sandbox') {
            return;
        }

        const button = new OO.ui.ButtonWidget({
            label: 'Manage RAL',
            flags: ['primary', 'progressive']
        });
        button.$element.css({
            position: 'fixed',
            bottom: '20px',
            right: '5px',
            zIndex: 1000,
            margin: '5px'
        });
        document.body.appendChild(button.$element[0]);

        button.on('click', function () {
            const windowManager = new OO.ui.WindowManager();
            $(document.body).append(windowManager.$element);
            const manageRALDialog = new ManageRALDialog({ size: 'medium' });
            windowManager.addWindows([manageRALDialog]);
            windowManager.openWindow(manageRALDialog);
        });
    }

    init();
});