Jump to content

User:Enterprisey/unblock-review.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Enterprisey (talk | contribs) at 21:29, 3 January 2019 (Add styling on "accept" button). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
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>
( function () {
    var UNBLOCK_REQ_COLOR = "rgb(235, 244, 255)";
    var SIGNATURE = "~~" + "~~";
    var ADVERT = " ([[User:Enterprisey/unblock-review|unblock-review]])";

    if( mw.config.get( "wgNamespaceNumber" ) === 3 ) {

        /**
         * Is there a signature (four tildes) present in the given text,
         * outside of a nowiki element?
         */
        function hasSig( text ) {

            // no literal signature?
            if( text.indexOf( SIGNATURE ) < 0 ) return false;

            // if there's a literal signature and no nowiki elements,
            // there must be a real signature
            if( text.indexOf( "<nowiki>" ) < 0 ) return true;

            // Save all nowiki spans
            var nowikiSpanStarts = []; // list of ignored span beginnings
            var nowikiSpanLengths = []; // list of ignored span lengths
            var NOWIKI_RE = /<nowiki>.*?<\/nowiki>/g;
            var spanMatch;
            do {
                spanMatch = NOWIKI_RE.exec( text );
                if( spanMatch ) {
                    nowikiSpanStarts.push( spanMatch.index );
                    nowikiSpanLengths.push( spanMatch[0].length );
                }
            } while( spanMatch );

            // So that we don't check every ignore span every time
            var nowikiSpanStartIdx = 0;

            var SIG_RE = new RegExp( SIGNATURE, "g" );
            var sigMatch;

            matchLoop:
            do {
                sigMatch = SIG_RE.exec( text );
                if( sigMatch ) {

                    // Check that we're not inside a nowiki
                    for( var nwIdx = nowikiSpanStartIdx; nwIdx <
                        nowikiSpanStarts.length; nwIdx++ ) {
                        if( sigMatch.index > nowikiSpanStarts[nwIdx] ) {
                            if ( sigMatch.index + sigMatch[0].length <=
                                nowikiSpanStarts[nwIdx] + nowikiSpanLengths[nwIdx] ) {

                                // Invalid sig
                                continue matchLoop;
                            } else {

                                // We'll never encounter this span again, since
                                // headers only get later and later in the wikitext
                                nowikiSpanStartIdx = nwIdx;
                            }
                        }
                    }

                    // We aren't inside a nowiki
                    return true;
                }
            } while( sigMatch );
            return false;
        }

        /**
         * Given the div of an unblock request, set up the UI and event
         * listeners.
         */
        function setUpUi( unblockDiv ) {
            var container = document.createElement( "table" );
            container.className = "unblock-review";
            var hrEl = unblockDiv.querySelector( "hr" );
            container.innerHTML = "<tr><td class='reason-container' rowspan='2'>" +
                "<textarea class='unblock-review-reason mw-ui-input'" +
                " placeholder='Reason for accepting/declining here'></textarea></td>" +
                "<td><button class='unblock-review-accept mw-ui-button mw-ui-progressive'>Accept</button></td></tr>" +
                "<tr><td><button class='unblock-review-decline mw-ui-button mw-ui-destructive'>Decline</button></td></tr>";
            unblockDiv.insertBefore( container, hrEl.previousElementSibling );
            var reasonArea = container.querySelector( "textarea" );
            $( container ).find( "button" ).click( function () {
                var action = $( this ).text().toLowerCase();
                var someText = hrEl.nextElementSibling.nextElementSibling.childNodes[0].textContent;
                console.log(someText);
                $.getJSON(
                    mw.util.wikiScript( "api" ),
                    {
                        format: "json",
                        action: "query",
                        prop: "revisions",
                        rvprop: "content",
                        rvlimit: 1,
                        titles: mw.config.get( "wgPageName" )
                    }
                ).done( function ( data ) {

                    // Extract wikitext from API response
                    var pageId = Object.keys(data.query.pages)[0];
                    wikitext = data.query.pages[pageId].revisions[0]["*"];

                    var textIdx = wikitext.indexOf( someText );
                    if( textIdx < 0 ) {
                        console.log( "Searching for target text failed!" );
                        return;
                    }

                    var startIdx = textIdx;
                    var i = 0;
                    while( wikitext[startIdx] != "{" && i < 50 ) {
                        startIdx--;
                        i++;
                    }
                    if( i == 50 ) {
                        console.log( "Searching backwards failed!" );
                        return;
                    }

                    startIdx--; // templates start with two opening curly braces

                    var initialText = wikitext.substring( startIdx, textIdx );

                    // Build reason
                    var reason = reasonArea.value;
                    if( !hasSig( reason ) ) reason = reason + " " + SIGNATURE;
                    wikitext = wikitext.replace( initialText + someText, "{" +
                        "{unblock reviewed|" + action + "=" + reason + "|1=" + someText );

                    var summary = ( action === "accept" ? "Accepting" : "Declining" ) +
                        " unblock request" + ADVERT;

                    ( new mw.Api() ).postWithToken( "csrf", {
                        action: "edit",
                        title: mw.config.get( "wgPageName" ),
                        summary: summary,
                        text: wikitext
                    } ).done ( function ( data ) {
                        if ( data && data.edit && data.edit.result && data.edit.result == "Success" ) {
                            window.location.reload( true );
                        } else {
                            console.log( data );
                        }
                    } );
                } );
            } );
        }

        $.when( $.ready, mw.loader.using( [ "mediawiki.api", "mediawiki.util" ] ) ).then( function () {
            mw.util.addCSS(
                ".unblock-review td { padding: 0 }" +
                "td.reason-container { padding-right: 1em; }" +
                ".unblock-review-reason { width: 25em; height: 5em }" );
            importStylesheet( "User:Enterprisey/mw-ui-button.css" );
            importStylesheet( "User:Enterprisey/mw-ui-input.css" );
            var userBlockBoxes = document.querySelectorAll( "div.user-block" );
            for( var i = 0, n = userBlockBoxes.length; i < n; i++ ) {
                if( userBlockBoxes[i].style["background-color"] !== UNBLOCK_REQ_COLOR ) {
                    continue;
                }
                
                // We now have a pending unblock request - add UI
                setUpUi( userBlockBoxes[i] );
            }
        } );
    }
} )();
// </nowiki>