User:TheAstorPastor/common.js: Difference between revisions

From Test Wiki
Jump to navigation Jump to search
Content deleted Content added
Undo revision 60266 by TheAstorPastor (talk)
Tags: Replaced Undo Reverted
No edit summary
Tag: Reverted
Line 1: Line 1:
// Only run on Test Wiki:Request for Permissions page
if (mw.config.get('wgTitle') === 'Request for permissions' &&
mw.config.get('wgNamespaceNumber') === 4) { // NS 4 is "Project" namespace (Test Wiki:)


$(document).ready(function() {
//importScript('User:Joepayne/grantBureaucrat.js'); // Backlink: [[User:Joepayne/grantBureaucrat.js]]
// Initialize the script
importScript('User:Joepayne/stripRights.js'); // Backlink: [[User:Joepayne/stripRights.js]]
testWikiRfPManager.init();
//importScript('User:MacFan4000/grantAdmin.js'); // Backlink: [[User:MacFan4000/grantAdmin.js]]
});
//importScript('User:Kiteretsu/js/all-in-one.js'); // Backlink: [[User:Kiteretsu/js/all-in-one.js]]

//importScript('User:DodoMan/chatbot.js'); // Backlink: [[User:DodoMan/chatbot.js]]
const testWikiRfPManager = {
importScript('User:JJBullet/findInactiveSysops.js'); // Backlink: [[User:JJBullet/findInactiveSysops.js]]
// Configuration
importScript('User:Harvici/find-archived-section.js'); // Backlink: [[User:Harvici/find-archived-section.js]]
config: {
importScript('User:Harvici/UTCLiveClock.js'); // Backlink: [[User:Harvici/UTCLiveClock.js]]
// Rights that can be assigned with corresponding templates
importScript('User:Harvici/Twinkle-preferences-toolbar.js'); // Backlink: [[User:Harvici/Twinkle-preferences-toolbar.js]]
rights: {
importScript('User:Kiteretsu/rollbackSum.js'); // Backlink: [[User:Kiteretsu/rollbackSum.js]]
'sysop': {
importScript('User:Kiteretsu/DiscussionCloser.js'); // Backlink: [[User:Kiteretsu/DiscussionCloser.js]]
displayName: 'Administrator',
importScript('User:TheAstorPastor/VisualEditorEverywhere.js'); // Backlink: [[User:TheAstorPastor/VisualEditorEverywhere.js]]
template: '{{administrator granted}} [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:57, 11 April 2025 (UTC)'
},
'bureaucrat': {
displayName: 'Bureaucrat',
template: '{{bureaucrat granted}} [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:57, 11 April 2025 (UTC)'
},
'interface-admin': {
displayName: 'Interface Administrator',
template: '{{interface administrator granted}} [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:57, 11 April 2025 (UTC)'
},
'non-stewardsuppress': {
displayName: 'Suppressor',
template: '{{done}}. [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:57, 11 April 2025 (UTC)'
},
'abusefilter-admin': {
displayName: 'Abuse Filter Administrator',
template: '{{done}}. [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:57, 11 April 2025 (UTC)'
}
}
},

// Initialize the script
init: function() {
// Check if user has the required permissions
if (!mw.config.get('wgUserGroups').includes('sysop')) {
console.log('TestWiki RfP Manager: User does not have sysop rights');
return;
}

// Load required styles
this.loadStyles();
// Process each RfP section
this.processRfPSections();
},

// Load CSS styles for the script
loadStyles: function() {
mw.loader.addStyleTag(`
.twrm-container {
background-color: #f8f9fa;
border: 1px solid #a2a9b1;
border-radius: 3px;
padding: 12px;
margin: 10px 0;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
.twrm-header {
font-weight: bold;
margin-bottom: 8px;
color: #222;
font-size: 14px;
padding-bottom: 5px;
border-bottom: 1px solid #eaecf0;
}
.twrm-controls {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
margin-bottom: 8px;
}
.twrm-select {
padding: 6px 8px;
border: 1px solid #a2a9b1;
border-radius: 2px;
background-color: white;
min-width: 200px;
}
.twrm-button {
padding: 6px 12px;
background-color: #36c;
color: white;
border: none;
border-radius: 2px;
cursor: pointer;
font-weight: bold;
}
.twrm-button:hover {
background-color: #447ff5;
}
.twrm-button:disabled {
background-color: #c8ccd1;
cursor: not-allowed;
}
.twrm-result {
margin-top: 10px;
padding: 8px;
background-color: #eaf3ff;
border: 1px solid #c8ccd1;
border-radius: 2px;
display: none;
}
.twrm-copy-button {
padding: 4px 8px;
background-color: #f8f9fa;
border: 1px solid #a2a9b1;
border-radius: 2px;
margin-top: 8px;
cursor: pointer;
}
.twrm-copy-button:hover {
background-color: #eaecf0;
}
.twrm-user-info {
margin-bottom: 8px;
font-style: italic;
}
.twrm-success {
color: #14866d;
font-weight: bold;
margin-top: 5px;
display: none;
}
`);
},

// Process all RfP sections on the page
processRfPSections: function() {
const self = this;
// Find all h2 headers which typically denote user request sections
$('.mw-parser-output > h2').each(function() {
const $header = $(this);
const username = $header.find('.mw-headline').text().trim();
if (username) {
// Find the section content
let $section = $header.nextUntil('h2, h1');
// Extract requested right from the section
const requestedRight = self.extractRequestedRight($section);
// Create rights manager UI
self.createRightsManagerUI($header, username, requestedRight);
}
});
},

// Extract the requested right from section content
extractRequestedRight: function($section) {
let rightText = '';
// Look for the "Requested right" line
$section.each(function() {
const text = $(this).text();
if (text.includes('Requested right')) {
// Extract the right from the text
const match = text.match(/Requested right[:\s]*([^*\n]+)/i);
if (match && match[1]) {
rightText = match[1].trim();
}
return false; // Break the loop
}
});

// Map common variations to our defined rights
const rightMap = {
'administrator': 'sysop',
'admin': 'sysop',
'sysop': 'sysop',
'bureaucrat': 'bureaucrat',
'crat': 'bureaucrat',
'interface administrator': 'interface-admin',
'interface admin': 'interface-admin',
'suppressor': 'non-stewardsuppress',
'suppress': 'non-stewardsuppress',
'abuse filter administrator': 'abusefilter-admin',
'abusefilter admin': 'abusefilter-admin',
'abuse filter admin': 'abusefilter-admin'
};
// Try to match the requested right
for (const [key, value] of Object.entries(rightMap)) {
if (rightText.toLowerCase().includes(key.toLowerCase())) {
return value;
}
}
return ''; // No match found
},

// Create the UI for managing rights
createRightsManagerUI: function($header, username, preselectedRight) {
const self = this;
// Create container
const $container = $('<div>')
.addClass('twrm-container')
.insertAfter($header);
// Create header
$('<div>')
.addClass('twrm-header')
.text('Rights Manager')
.appendTo($container);
// Add user info
$('<div>')
.addClass('twrm-user-info')
.text(`Request by: ${username}`)
.appendTo($container);
// Create controls container
const $controls = $('<div>')
.addClass('twrm-controls')
.appendTo($container);
// Create right selection dropdown
const $select = $('<select>')
.addClass('twrm-select')
.appendTo($controls);
// Add default option
$('<option>')
.val('')
.text('Select right to grant...')
.appendTo($select);
// Add options for each available right
for (const [right, config] of Object.entries(this.config.rights)) {
$('<option>')
.val(right)
.text(config.displayName)
.prop('selected', right === preselectedRight)
.appendTo($select);
}
// Create grant button
const $grantButton = $('<button>')
.addClass('twrm-button')
.text('Grant Rights')
.prop('disabled', !preselectedRight)
.appendTo($controls);
// Create API button
const $apiButton = $('<button>')
.addClass('twrm-button')
.text('Grant via API')
.prop('disabled', !preselectedRight)
.appendTo($controls);
// Create result container
const $result = $('<div>')
.addClass('twrm-result')
.appendTo($container);
// Create copy button
const $copyButton = $('<button>')
.addClass('twrm-copy-button')
.text('Copy to Clipboard')
.appendTo($result);
// Create success message
const $success = $('<div>')
.addClass('twrm-success')
.text('Rights granted successfully!')
.appendTo($container);
// Handle select change
$select.on('change', function() {
const hasSelection = $(this).val() !== '';
$grantButton.prop('disabled', !hasSelection);
$apiButton.prop('disabled', !hasSelection);
$result.hide();
$success.hide();
});
// Handle grant button click
$grantButton.on('click', function() {
const selectedRight = $select.val();
if (selectedRight && self.config.rights[selectedRight]) {
// Show template response
$result.show().text(self.config.rights[selectedRight].template);
}
});
// Handle API button click
$apiButton.on('click', function() {
const selectedRight = $select.val();
if (selectedRight && self.config.rights[selectedRight]) {
// Set button to loading state
const originalText = $apiButton.text();
$apiButton.text('Processing...').prop('disabled', true);
// Grant the right using MediaWiki API
self.grantRightViaAPI(username, selectedRight)
.then(function(success) {
if (success) {
$success.show();
$result.show().text(self.config.rights[selectedRight].template);
} else {
$result.show().text('Error granting rights. Please try again or use manual method.');
}
})
.catch(function() {
$result.show().text('Error granting rights. Please try again or use manual method.');
})
.finally(function() {
// Reset button state
$apiButton.text(originalText).prop('disabled', false);
});
}
});
// Handle copy button click
$copyButton.on('click', function() {
const textToCopy = $result.text();
navigator.clipboard.writeText(textToCopy).then(function() {
$copyButton.text('Copied!');
setTimeout(function() {
$copyButton.text('Copy to Clipboard');
}, 2000);
});
});
},

// Grant rights via MediaWiki API
grantRightViaAPI: function(username, right) {
return new Promise(function(resolve) {
// Get API token
mw.user.getToken('csrf').then(function(token) {
// Make API request to grant right
new mw.Api().postWithToken('csrf', {
action: 'userrights',
user: username,
add: right,
reason: 'Granted per request on [[Test Wiki:Request for Permissions]]',
token: token
})
.done(function() {
resolve(true);
})
.fail(function() {
resolve(false);
});
});
});
}
};
}

Revision as of 13:57, 11 April 2025

// Only run on Test Wiki:Request for Permissions page
if (mw.config.get('wgTitle') === 'Request for permissions' && 
    mw.config.get('wgNamespaceNumber') === 4) { // NS 4 is "Project" namespace (Test Wiki:)

    $(document).ready(function() {
        // Initialize the script
        testWikiRfPManager.init();
    });

    const testWikiRfPManager = {
        // Configuration
        config: {
            // Rights that can be assigned with corresponding templates
            rights: {
                'sysop': {
                    displayName: 'Administrator',
                    template: '{{administrator granted}} [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:57, 11 April 2025 (UTC)'
                },
                'bureaucrat': {
                    displayName: 'Bureaucrat',
                    template: '{{bureaucrat granted}} [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:57, 11 April 2025 (UTC)'
                },
                'interface-admin': {
                    displayName: 'Interface Administrator',
                    template: '{{interface administrator granted}} [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:57, 11 April 2025 (UTC)'
                },
                'non-stewardsuppress': {
                    displayName: 'Suppressor',
                    template: '{{done}}. [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:57, 11 April 2025 (UTC)'
                },
                'abusefilter-admin': {
                    displayName: 'Abuse Filter Administrator',
                    template: '{{done}}. [[User:TheAstorPastor|<span style="font-family:Segoe print; color:#8B0000; text-shadow:gray 0.2em 0.2em 0.4em;">The AP </span>]] ([[User talk:TheAstorPastor|<span style="font-family:Segoe print; color:#AA336A">''talk''</span>]]) 13:57, 11 April 2025 (UTC)'
                }
            }
        },

        // Initialize the script
        init: function() {
            // Check if user has the required permissions
            if (!mw.config.get('wgUserGroups').includes('sysop')) {
                console.log('TestWiki RfP Manager: User does not have sysop rights');
                return;
            }

            // Load required styles
            this.loadStyles();
            
            // Process each RfP section
            this.processRfPSections();
        },

        // Load CSS styles for the script
        loadStyles: function() {
            mw.loader.addStyleTag(`
                .twrm-container {
                    background-color: #f8f9fa;
                    border: 1px solid #a2a9b1;
                    border-radius: 3px;
                    padding: 12px;
                    margin: 10px 0;
                    box-shadow: 0 1px 2px rgba(0,0,0,0.1);
                }
                .twrm-header {
                    font-weight: bold;
                    margin-bottom: 8px;
                    color: #222;
                    font-size: 14px;
                    padding-bottom: 5px;
                    border-bottom: 1px solid #eaecf0;
                }
                .twrm-controls {
                    display: flex;
                    flex-wrap: wrap;
                    gap: 10px;
                    align-items: center;
                    margin-bottom: 8px;
                }
                .twrm-select {
                    padding: 6px 8px;
                    border: 1px solid #a2a9b1;
                    border-radius: 2px;
                    background-color: white;
                    min-width: 200px;
                }
                .twrm-button {
                    padding: 6px 12px;
                    background-color: #36c;
                    color: white;
                    border: none;
                    border-radius: 2px;
                    cursor: pointer;
                    font-weight: bold;
                }
                .twrm-button:hover {
                    background-color: #447ff5;
                }
                .twrm-button:disabled {
                    background-color: #c8ccd1;
                    cursor: not-allowed;
                }
                .twrm-result {
                    margin-top: 10px;
                    padding: 8px;
                    background-color: #eaf3ff;
                    border: 1px solid #c8ccd1;
                    border-radius: 2px;
                    display: none;
                }
                .twrm-copy-button {
                    padding: 4px 8px;
                    background-color: #f8f9fa;
                    border: 1px solid #a2a9b1;
                    border-radius: 2px;
                    margin-top: 8px;
                    cursor: pointer;
                }
                .twrm-copy-button:hover {
                    background-color: #eaecf0;
                }
                .twrm-user-info {
                    margin-bottom: 8px;
                    font-style: italic;
                }
                .twrm-success {
                    color: #14866d;
                    font-weight: bold;
                    margin-top: 5px;
                    display: none;
                }
            `);
        },

        // Process all RfP sections on the page
        processRfPSections: function() {
            const self = this;
            
            // Find all h2 headers which typically denote user request sections
            $('.mw-parser-output > h2').each(function() {
                const $header = $(this);
                const username = $header.find('.mw-headline').text().trim();
                
                if (username) {
                    // Find the section content
                    let $section = $header.nextUntil('h2, h1');
                    
                    // Extract requested right from the section
                    const requestedRight = self.extractRequestedRight($section);
                    
                    // Create rights manager UI
                    self.createRightsManagerUI($header, username, requestedRight);
                }
            });
        },

        // Extract the requested right from section content
        extractRequestedRight: function($section) {
            let rightText = '';
            
            // Look for the "Requested right" line
            $section.each(function() {
                const text = $(this).text();
                if (text.includes('Requested right')) {
                    // Extract the right from the text
                    const match = text.match(/Requested right[:\s]*([^*\n]+)/i);
                    if (match && match[1]) {
                        rightText = match[1].trim();
                    }
                    return false; // Break the loop
                }
            });

            // Map common variations to our defined rights
            const rightMap = {
                'administrator': 'sysop',
                'admin': 'sysop',
                'sysop': 'sysop',
                'bureaucrat': 'bureaucrat',
                'crat': 'bureaucrat',
                'interface administrator': 'interface-admin',
                'interface admin': 'interface-admin',
                'suppressor': 'non-stewardsuppress',
                'suppress': 'non-stewardsuppress',
                'abuse filter administrator': 'abusefilter-admin',
                'abusefilter admin': 'abusefilter-admin',
                'abuse filter admin': 'abusefilter-admin'
            };
            
            // Try to match the requested right
            for (const [key, value] of Object.entries(rightMap)) {
                if (rightText.toLowerCase().includes(key.toLowerCase())) {
                    return value;
                }
            }
            
            return ''; // No match found
        },

        // Create the UI for managing rights
        createRightsManagerUI: function($header, username, preselectedRight) {
            const self = this;
            
            // Create container
            const $container = $('<div>')
                .addClass('twrm-container')
                .insertAfter($header);
                
            // Create header
            $('<div>')
                .addClass('twrm-header')
                .text('Rights Manager')
                .appendTo($container);
                
            // Add user info
            $('<div>')
                .addClass('twrm-user-info')
                .text(`Request by: ${username}`)
                .appendTo($container);
                
            // Create controls container
            const $controls = $('<div>')
                .addClass('twrm-controls')
                .appendTo($container);
                
            // Create right selection dropdown
            const $select = $('<select>')
                .addClass('twrm-select')
                .appendTo($controls);
                
            // Add default option
            $('<option>')
                .val('')
                .text('Select right to grant...')
                .appendTo($select);
                
            // Add options for each available right
            for (const [right, config] of Object.entries(this.config.rights)) {
                $('<option>')
                    .val(right)
                    .text(config.displayName)
                    .prop('selected', right === preselectedRight)
                    .appendTo($select);
            }
            
            // Create grant button
            const $grantButton = $('<button>')
                .addClass('twrm-button')
                .text('Grant Rights')
                .prop('disabled', !preselectedRight)
                .appendTo($controls);
                
            // Create API button
            const $apiButton = $('<button>')
                .addClass('twrm-button')
                .text('Grant via API')
                .prop('disabled', !preselectedRight)
                .appendTo($controls);
                
            // Create result container
            const $result = $('<div>')
                .addClass('twrm-result')
                .appendTo($container);
                
            // Create copy button
            const $copyButton = $('<button>')
                .addClass('twrm-copy-button')
                .text('Copy to Clipboard')
                .appendTo($result);
                
            // Create success message
            const $success = $('<div>')
                .addClass('twrm-success')
                .text('Rights granted successfully!')
                .appendTo($container);
                
            // Handle select change
            $select.on('change', function() {
                const hasSelection = $(this).val() !== '';
                $grantButton.prop('disabled', !hasSelection);
                $apiButton.prop('disabled', !hasSelection);
                $result.hide();
                $success.hide();
            });
            
            // Handle grant button click
            $grantButton.on('click', function() {
                const selectedRight = $select.val();
                if (selectedRight && self.config.rights[selectedRight]) {
                    // Show template response
                    $result.show().text(self.config.rights[selectedRight].template);
                }
            });
            
            // Handle API button click
            $apiButton.on('click', function() {
                const selectedRight = $select.val();
                if (selectedRight && self.config.rights[selectedRight]) {
                    // Set button to loading state
                    const originalText = $apiButton.text();
                    $apiButton.text('Processing...').prop('disabled', true);
                    
                    // Grant the right using MediaWiki API
                    self.grantRightViaAPI(username, selectedRight)
                        .then(function(success) {
                            if (success) {
                                $success.show();
                                $result.show().text(self.config.rights[selectedRight].template);
                            } else {
                                $result.show().text('Error granting rights. Please try again or use manual method.');
                            }
                        })
                        .catch(function() {
                            $result.show().text('Error granting rights. Please try again or use manual method.');
                        })
                        .finally(function() {
                            // Reset button state
                            $apiButton.text(originalText).prop('disabled', false);
                        });
                }
            });
            
            // Handle copy button click
            $copyButton.on('click', function() {
                const textToCopy = $result.text();
                navigator.clipboard.writeText(textToCopy).then(function() {
                    $copyButton.text('Copied!');
                    setTimeout(function() {
                        $copyButton.text('Copy to Clipboard');
                    }, 2000);
                });
            });
        },

        // Grant rights via MediaWiki API
        grantRightViaAPI: function(username, right) {
            return new Promise(function(resolve) {
                // Get API token
                mw.user.getToken('csrf').then(function(token) {
                    // Make API request to grant right
                    new mw.Api().postWithToken('csrf', {
                        action: 'userrights',
                        user: username,
                        add: right,
                        reason: 'Granted per request on [[Test Wiki:Request for Permissions]]',
                        token: token
                    })
                    .done(function() {
                        resolve(true);
                    })
                    .fail(function() {
                        resolve(false);
                    });
                });
            });
        }
    };
}