User:Chieftain Alex/monobook.js

From Guild Wars 2 Wiki
Jump to navigationJump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/* <pre> */
if (document.readyState === 'loading') {
    // Loading hasn't finished yet (status loading)
    console.log('User:Chieftain Alex/monobook.js: alexJS function - dom content at loading state, adding event listener to trigger alexJS function.', document.readyState);
    document.addEventListener('DOMContentLoaded', alexJS);
} else {
    // 'DOMContentLoaded' has already fired
    console.log('User:Chieftain Alex/monobook.js: alexCommonJS function - dom content either at complete or interactive state, proceeding to alexJS function.');
    alexJS();
}

function alexJS (){
console.log('mw',mw);

    mw.loader.load( '/index.php?title=User:Chieftain_Alex/AToolsMonobook.js&action=raw&ctype=text/javascript' );
    
    var cfg = mw.config;
    hideRCUser(cfg);
    addJobQueuetoSpecialStatistics(cfg);
    deletelogTable(cfg);
    blocklogTable(cfg);
    usercreationlogTable(cfg);
    abuselogTable(cfg);
}

// Hiding users in recent changes
function hideRCUser(cfg) {
    if (cfg.get('wgPageName') == 'Special:RecentChanges') {
        // Helper function
        Array.prototype.unique = function() {
            return this.filter(function (el, i, self) {
                return self.indexOf(el) === i;
            });
        };
        
        // ----------- FREE TEXT FILTER BOX -----------
        // Create a data entry box (free text)
        $('fieldset.rcoptions tbody').append('<tr><td class="mw-label"><label for="namefilter">Hide user:</label></td><td><input id="namefilter" size="20" value=""> <input id="namefilter-button" type="button" value="Apply"> Suggestions: <span id="namesuggestions"></span></td></tr>');

        // Bind event to data entry box (free text)
        $('#namefilter-button').click(function(e){
            var name = $('#namefilter').val().trim().replace(/ /g,'_');
            $('head').append('<style class="hideusers" type="text/css" >' + '.mw-changeslist-line' + '.User-' + name.replace(/ /g,'_') + ' { display: none; }' + '</style>');
        });

        // Move apply button for namespace selection to correct row
        $('.namespaceForm .mw-input').append( '<input type="submit" value="Apply">' );

        // Remove now useless tag filter row
        $('.tagfilterForm').remove();

        // ----------- SUGGESTED NAMES -----------
        // Add user-name to each row
        var allusers = $.map($('.mw-changeslist-line.mw-changeslist-edit'), function(x){
            // May be multiple users if using nested view
            var u = $('.mw-userlink', x);
            var users = $.map(u, function(y){
                return $(y).text().replace(/ /g,'_'); // store names with underscore
            });

            // Remove duplicates from row
            users = users.unique();

            // Check if more than one user
            if (users.length > 1) {
                $(x).addClass( 'User-' + 'Multiple' );
            } else {
                $.map(users, function(y) {
                    $(x).addClass( 'User-' + y);
                });
            }

            return users;
        });

        // Identify which users edited how many times
        var total = allusers.length;
        var cut_off_percent = 0.05; // 5%

        const occurrences = allusers.reduce(function (acc, curr) {
            return acc[curr] ? ++acc[curr] : acc[curr] = 1, acc
        }, {});

        // Remove any editors with a tiny contribution
        $.map(occurrences, function(x, k){
            if (x < (total * cut_off_percent)) {
                delete occurrences[k];
            }
        });

        var user_shortlist = Object.keys(occurrences);
        if (user_shortlist.length > 0) {
            // Sort remaining users high to low
            user_shortlist = user_shortlist.sort(function(a,b){
                return occurrences[a] < occurrences[b];
            });

            // Add list of names as links beside the hide user button as suggestions
            $('#namesuggestions').append( $.map(user_shortlist, function(x){
                return '<a username="' + x + '">' + x.replace(/_/g,' ') + '</a> (' + occurrences[x] + ')'
            }).join(', ') );

            // Bind events
            $('#namesuggestions a').click(function(e){
                var name = $(this).attr('username');
                $('head').append('<style class="hideusers" type="text/css" >' + '.mw-changeslist-line' + '.User-' + name.replace(/_/g,'_') + ' { display: none; }' + '</style>');
            });
        }
    }
}

// Scripts to use when viewing the Abuse Log
function abuselogTable(cfg) {
    if (cfg.get('wgPageName') == 'Special:AbuseLog') {
        // Make the array into a table
        function makeTableHTML(data) {
            var columns = Object.keys(data[0]);
            var result = '<table id="abuselogtable" class="wikitable" rules="all"><tr>';
            $.each(columns, function(i,v) { result += '<th style="text-align:left;">' + v + '</th>' });
            result += '</tr>';
            $.each(data, function(i,v) {
                result += '<tr>';
                $.each(columns, function(ii,vv){
                  if ( typeof v[vv] == 'object') {
                    result += '<td>' + '<a class="' + v[vv][2] + '" href="' + v[vv][0] + '">' + v[vv][1] + '</a>' + '</td>';
                  } else if (v[vv].substring(0,4) == 'http') {
                    result += '<td>' + '<a href="' + v[vv] + '">' + v[vv].replace('https://wiki.guildwars2.com/wiki/','') + '</a>' + '</td>';
                  } else {
                    result += '<td>' + v[vv] + '</td>';
                  }
                });
                result += '</tr>';
            });
            result += '</table>';
            return result;
        }

        // Make an array from the wall of text
        var counter = 0;
        var abuselog = $.map( $('body.page-Special_AbuseLog ul.plainlinks li'), function(v) {
          counter += 1;
          return {
             'Timestamp': v.childNodes[0].data.replace(': ',''),
             'Caught user': v.childNodes[1].innerText,
             'Block': [v.childNodes[3].childNodes[(v.childNodes[3].childNodes.length - 2)].href, '(block)', ''],
             'Action': v.childNodes[6].textContent.replace(', performing the action "','').replace('" on ',''),
             'Target page': [v.childNodes[7].href, v.childNodes[7].innerText.substring(0, 60), v.childNodes[7].className],
             'Response': v.childNodes[8].textContent.split('\n')[1].replace('Actions taken: ','').replace(';',''),
             'Filter': v.childNodes[5].innerText.replace('filter ','') + ': ' + v.childNodes[8].textContent.split('\n')[2].replace('Filter description: ','').slice(0, -2),
             'log details': [v.childNodes[9].href, 'examine']
          };
        });

        // Replace the wall of text with a table
        if (counter > 0) {
          $('body.page-Special_AbuseLog ul.plainlinks').replaceWith(makeTableHTML(abuselog));
        }
    }
}

// Scripts to use when viewing the Delete Log
function deletelogTable(cfg) {
    if (cfg.get('wgPageName') == 'Special:Log/delete' || (cfg.get('wgPageName') == 'Special:Log' && new URLSearchParams(window.location.search).get('type') == 'delete') ) {
        // Make the array into a table
        function makeTableHTML(data) {
            if (data.length == 0) {
                return '(no data)'
            }

            var columns = Object.keys(data[0]);
            var result = '<table id="deletelogtable" class="wikitable" rules="all"><tr>';
            $.each(columns, function(i,v) { result += '<th style="text-align:left;">' + v + '</th>' });
            result += '</tr>';
            $.each(data, function(i,v) {
                result += '<tr>';
                $.each(columns, function(ii,vv){
                    result += '<td>' + v[vv] + '</td>';
                });
                result += '</tr>';
            });
            result += '</table>';
            return result;
        }
        
        // Remove unnecessary tags
        $('.mw-thanks-thank-link').remove();

        // Make an array from the wall of text
        var counter = 0;
        var deletelog = $.map( $('#mw-log-deleterevision-submit ul li.mw-logline-delete'), function(v) {
            counter += 1;

            // Note deletion comment/reason is an optional field.
            // and the view/restore link does not appear if the action was Restore.
            var action = v.childNodes[7].textContent.trim();
            
            if (action == 'deleted page') {
                return {
                    'Timestamp': v.children[1].textContent,
                    'Admin': v.children[2].innerHTML,
                    'Action': v.childNodes[7].textContent,
                    'Page': v.children[4].innerHTML,
                    'Comment': (v.children.length == 6 ? '(no comment)' : v.children[5].innerHTML),
                    'Link': (v.children.length == 6 ? v.children[5].innerHTML : v.children[6].innerHTML)
                };
            }
            if (action == 'restored page') {
                return {
                    'Timestamp': v.children[1].textContent,
                    'Admin': v.children[2].innerHTML,
                    'Action': v.childNodes[7].textContent,
                    'Page': v.children[4].innerHTML,
                    'Comment': (v.children.length == 5 ? '(no comment)' : v.children[5].innerHTML),
                    'Link': ''
                };
            }
        });

        // Add css rule
        $('head').append('<style type="text/css">' + '#deletelogtable td {  white-space: nowrap; max-width: 600px; overflow: hidden; }' + '</style>');

        // Replace the wall of text with a table
        if (counter > 0) {
            $('#mw-content-text ul').replaceWith( makeTableHTML(deletelog) );
        }
    }
}

// Scripts to use when viewing the Block Log
function blocklogTable(cfg) {
    if (cfg.get('wgPageName') == 'Special:Log/block' || (cfg.get('wgPageName') == 'Special:Log' && new URLSearchParams(window.location.search).get('type') == 'block') ) {
        // Make the array into a table
        function makeTableHTML(data) {
            if (data.length == 0) {
                return '(no data)'
            }

            var columns = Object.keys(data[0]);
            var result = '<table id="blocklogtable" class="wikitable" rules="all"><tr>';
            $.each(columns, function(i,v) { result += '<th style="text-align:left;">' + v + '</th>' });
            result += '</tr>';
            $.each(data, function(i,v) {
                result += '<tr>';
                $.each(columns, function(ii,vv){
                  if ( typeof v[vv] == 'object') {
                    result += '<td>' + '<a class="' + v[vv][2] + '" href="' + v[vv][0] + '">' + v[vv][1] + '</a>' + '</td>';
                  } else {
                    result += '<td>' + v[vv] + '</td>';
                  }
                });
                result += '</tr>';
            });
            result += '</table>';
            return result;
        }

        // Remove tags for mobile edits etc (added at some point in 2021)
        $('.mw-tag-markers').remove();

        // Make an array from the wall of text
        var counter = 0;
        var nomatchlog = [];
        var blocklog = $.map( $('#mw-log-deleterevision-submit ul li.mw-logline-block'), function(v) {
            counter += 1;
            
            // Clean up the plaintext with a trim and a few "find and replace" operations - Remove the links from the admin in question
            // then remove the links from the user or anonymous user.
            var plaintext = v.textContent.trim().replace('talk contribs block blocked','blocked');
            plaintext = plaintext.replace(' talk with an expiration',' with an expiration').replace(' talk contribs','').replace(' (unblock | change block)','');
            
            // Match on the pattern
            var pattern = /^(\d{2}:\d{2}, \d+ \w+ \d{4}) (.*?) blocked (.*?) with an expiration time of (.*?) \((?:.*?)\) \((.*?)\)$/;
            var m = plaintext.match(pattern);
            
            // Check something matched
            if (m) {
                return {
                    'Admin': m[2],
                    'Timestamp': m[1],
                    'Caught user': m[3],
                    'Duration': m[4],
                    'Reason': m[5],
                    'Contribs': ['https://wiki.guildwars2.com/wiki/Special:Contributions/' + m[3], 'contribs'],
                    'Abuse log': ['https://wiki.guildwars2.com/index.php?title=Special:AbuseLog&wpSearchUser=' + m[3], 'abuse log'],
                    'Block': ['https://wiki.guildwars2.com/wiki/Special:Block/' + m[3], 'block'],
                    'Unblock': ['https://wiki.guildwars2.com/wiki/Special:Unblock/' + m[3], 'unblock']
                };
            } else {
                // Match on second pattern
                var pattern2 = /^(\d{2}:\d{2}, \d+ \w+ \d{4}) (.*?) block changed block settings for (.*?) talk contribs with an expiration time of (.*?) \((?:.*?)\) \((.*?)\)$/;
                m = plaintext.match(pattern2);
                
                if (m) {
                    return {
                        'Admin': m[2],
                        'Timestamp': m[1],
                        'Caught user': m[3],
                        'Duration': m[4],
                        'Reason': m[5],
                        'Contribs': ['https://wiki.guildwars2.com/wiki/Special:Contributions/' + m[3], 'contribs'],
                        'Abuse log': ['https://wiki.guildwars2.com/index.php?title=Special:AbuseLog&wpSearchUser=' + m[3], 'abuse log'],
                        'Block': ['https://wiki.guildwars2.com/wiki/Special:Block/' + m[3], 'block'],
                        'Unblock': ['https://wiki.guildwars2.com/wiki/Special:Unblock/' + m[3], 'unblock']
                    };
                } else {
                    nomatchlog.push({
                        'Plaintext': plaintext
                    });
                    return;
                }
            }
        });

        // Replace the wall of text with a table
        if (counter > 0) {
            $('#mw-content-text ul').replaceWith( makeTableHTML(blocklog) );
            $('#blocklogtable').after( makeTableHTML(nomatchlog) );
        }
    }
}

// Scripts to use when viewing the User Creation Log
function usercreationlogTable(cfg) {
    if (cfg.get('wgPageName') == 'Special:Log/newusers' || (cfg.get('wgPageName') == 'Special:Log' && new URLSearchParams(window.location.search).get('type') == 'newusers') ) {
        // Make the array into a table
        function makeTableHTML(data) {
            if (data.length == 0) {
                return '(no data)'
            }

            var columns = Object.keys(data[0]);
            var result = '<table id="usercreationlogtable" class="wikitable" rules="all"><tr>';
            $.each(columns, function(i,v) { result += '<th style="text-align:left;">' + v + '</th>' });
            result += '</tr>';
            $.each(data, function(i,v) {
                result += '<tr>';
                $.each(columns, function(ii,vv){
                  if ( typeof v[vv] == 'object') {
                    result += '<td>' + '<a class="' + v[vv][2] + '" href="' + v[vv][0] + '">' + v[vv][1] + '</a>' + '</td>';
                  } else {
                    result += '<td>' + v[vv] + '</td>';
                  }
                });
                result += '</tr>';
            });
            result += '</table>';
            return result;
        }

        // Make an array from the wall of text
        var counter = 0;
        var nomatchlog = [];
        var blocklog = $.map( $('#mw-log-deleterevision-submit ul li.mw-logline-newusers'), function(v) {
            counter += 1;
            
            // Clean up the plaintext with a trim and a few "find and replace" operations - Remove the links from the admin in question
            // then remove the links from the user or anonymous user.
            var plaintext = v.textContent.trim().replace('talk contribs block was created','created');
            
            // Match on the pattern
            var pattern = /^(\d{2}:\d{2}, \d+ \w+ \d{4}) User account (.*?) created(?:|.*?)$/;
            var m = plaintext.match(pattern);
            
            // Check something matched
            if (m) {
                return {
                    'Timestamp': m[1],
                    'Created user': m[2],
                    'Contribs': ['https://wiki.guildwars2.com/wiki/Special:Contributions/' + m[2], 'contribs'],
                    'Abuse log': ['https://wiki.guildwars2.com/index.php?title=Special:AbuseLog&wpSearchUser=' + m[2], 'abuse log'],
                    'Block': ['https://wiki.guildwars2.com/wiki/Special:Block/' + m[2], 'block'],
                    'Unblock': ['https://wiki.guildwars2.com/wiki/Special:Unblock/' + m[2], 'unblock']
                };
            } else {
                nomatchlog.push({
                    'Plaintext': plaintext
                });
                return;
            }
        });

        // Replace the wall of text with a table
        if (counter > 0) {
            $('#mw-log-deleterevision-submit ul').replaceWith( makeTableHTML(blocklog) );
            $('#usercreationlogtable').after( makeTableHTML(nomatchlog) );
        }
    }
}

// Job queue - Query wiki API with ajax for the job queue statistic, copied from [[User:Dr ishmael/monobook.js]]
function addJobQueuetoSpecialStatistics (cfg) {
    if (cfg.get('wgCanonicalSpecialPageName') === 'Statistics') {
        $.getJSON('/api.php?action=query&format=json&meta=siteinfo&siprop=statistics').done(function (data){
            var jobqueue = data['query']['statistics']['jobs'] || 0;
            $('<tr class="mw-statistics-jobs"><td>Job queue</td><td class="mw-statistics-numbers">'+jobqueue+'</td></tr>').insertAfter('.mw-statistics-edits-average');
        })
    }
}

/* </pre> */