<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://gw1wiki.ezgame.cc/index.php?action=history&amp;feed=atom&amp;title=Widget%3ABlock_robot</id>
	<title>Widget:Block robot - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://gw1wiki.ezgame.cc/index.php?action=history&amp;feed=atom&amp;title=Widget%3ABlock_robot"/>
	<link rel="alternate" type="text/html" href="https://gw1wiki.ezgame.cc/index.php?title=Widget:Block_robot&amp;action=history"/>
	<updated>2026-10-18T08:07:39Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://gw1wiki.ezgame.cc/index.php?title=Widget:Block_robot&amp;diff=3149&amp;oldid=prev</id>
		<title>gww&gt;Chieftain Alex at 21:53, 11 September 2026</title>
		<link rel="alternate" type="text/html" href="https://gw1wiki.ezgame.cc/index.php?title=Widget:Block_robot&amp;diff=3149&amp;oldid=prev"/>
		<updated>2026-09-11T21:53:00Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;noinclude&amp;gt;{{#Widget:Block robot}}&lt;br /&gt;
== Description ==&lt;br /&gt;
This widget facilitates the automation of repetitive block/unblock tasks for spambots. If you are making a lot of changes, make sure to login to a bot account before using this page.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
This widget has no parameters.&lt;br /&gt;
&lt;br /&gt;
[[Category:Widgets]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&amp;lt;includeonly&amp;gt;&amp;lt;div id=&amp;quot;widgettarget&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;!--{counter assign=&amp;quot;BlockRobot_counter&amp;quot; name=&amp;quot;BlockRobot_counter&amp;quot;}--&amp;gt;&amp;lt;!--{if $BlockRobot_counter eq 1}--&amp;gt;&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
/* CSS for bulk edit tool */&lt;br /&gt;
#listwrapper {&lt;br /&gt;
  width: 100%;&lt;br /&gt;
  clear: both;&lt;br /&gt;
}&lt;br /&gt;
#listwrapper &amp;gt; table {&lt;br /&gt;
  width: 100%;&lt;br /&gt;
}&lt;br /&gt;
#titlebar {&lt;br /&gt;
  border: 1px solid #555;&lt;br /&gt;
  background-color: #777;&lt;br /&gt;
  padding: 3px 0px;&lt;br /&gt;
  width: 100%;&lt;br /&gt;
  color: #EEE;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
  font-size: 12pt;&lt;br /&gt;
}&lt;br /&gt;
.contentwrapper {&lt;br /&gt;
  border: 1px solid #555;&lt;br /&gt;
  margin-top: 2px;&lt;br /&gt;
  background-color: #DDD;&lt;br /&gt;
  width: 100%;&lt;br /&gt;
}&lt;br /&gt;
.contentwrapper &amp;gt; table {&lt;br /&gt;
  width: 100%;&lt;br /&gt;
  border-spacing: 5px;&lt;br /&gt;
}&lt;br /&gt;
.contentwrapper td {&lt;br /&gt;
  border: 1px solid #555;&lt;br /&gt;
  background-color: #EEE;&lt;br /&gt;
  padding: 5px;&lt;br /&gt;
  font-family: consolas;&lt;br /&gt;
  vertical-align: top;&lt;br /&gt;
}&lt;br /&gt;
#listoperators {&lt;br /&gt;
  min-width: 222px;&lt;br /&gt;
  width: 30%;&lt;br /&gt;
}&lt;br /&gt;
#fullwrapper input[type=text] {&lt;br /&gt;
  width: 99%;&lt;br /&gt;
  padding: 3px 2px;&lt;br /&gt;
}&lt;br /&gt;
#fullwrapper input[type=button] {&lt;br /&gt;
  width: 70px;&lt;br /&gt;
  margin: 0px 2px;&lt;br /&gt;
}&lt;br /&gt;
#fullwrapper select {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
  height: 27px;&lt;br /&gt;
}&lt;br /&gt;
#listinput textarea {&lt;br /&gt;
  overflow-y: scroll;&lt;br /&gt;
  height: 515px;&lt;br /&gt;
}&lt;br /&gt;
#listsucceed {&lt;br /&gt;
  background-color: #9F9;&lt;br /&gt;
  white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
#listsucceed div {&lt;br /&gt;
  height: 500px;&lt;br /&gt;
  overflow-y: scroll;&lt;br /&gt;
}&lt;br /&gt;
#listfailed {&lt;br /&gt;
  background-color: #F99;&lt;br /&gt;
  white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
#listfailed div {&lt;br /&gt;
  max-height: 100px;&lt;br /&gt;
  overflow-y: scroll;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
/* WIDGET: BLOCK ROBOT */&lt;br /&gt;
function mwBlockScript () {&lt;br /&gt;
&lt;br /&gt;
    // Make the GUI.&lt;br /&gt;
    function makeTaskGUI () {&lt;br /&gt;
        // Initialise frame with required options.&lt;br /&gt;
        var UIframe = $('&amp;lt;div id=&amp;quot;fullwrapper&amp;quot;&amp;gt;'&lt;br /&gt;
                            +'&amp;lt;div id=&amp;quot;titlebar&amp;quot;&amp;gt;AJAX spambot blocking script&amp;lt;/div&amp;gt;'&lt;br /&gt;
                            +'&amp;lt;div class=&amp;quot;contentwrapper&amp;quot;&amp;gt;'&lt;br /&gt;
                                +'&amp;lt;table&amp;gt;&amp;lt;tbody&amp;gt;'&lt;br /&gt;
                                    +'&amp;lt;tr&amp;gt;'&lt;br /&gt;
                                        +'&amp;lt;td colspan=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;textarea id=&amp;quot;listsummary&amp;quot; type=&amp;quot;text&amp;quot; placeholder=&amp;quot;Insert edit summary here.&amp;quot; rows=&amp;quot;1&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;'&lt;br /&gt;
                                    +'&amp;lt;/tr&amp;gt;'&lt;br /&gt;
                                    +'&amp;lt;tr&amp;gt;'&lt;br /&gt;
                                        +'&amp;lt;td id=&amp;quot;listinput&amp;quot; rowspan=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;textarea&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;'&lt;br /&gt;
                                        +'&amp;lt;td id=&amp;quot;listsucceed&amp;quot;&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/td&amp;gt;'&lt;br /&gt;
                                    +'&amp;lt;/tr&amp;gt;'&lt;br /&gt;
                                    +'&amp;lt;tr&amp;gt;'&lt;br /&gt;
                                        +'&amp;lt;td id=&amp;quot;listfailed&amp;quot;&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/td&amp;gt;'&lt;br /&gt;
                                    +'&amp;lt;/tr&amp;gt;'&lt;br /&gt;
                                    +'&amp;lt;tr&amp;gt;'&lt;br /&gt;
                                        +'&amp;lt;td id=&amp;quot;listprogress&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;'&lt;br /&gt;
                                        +'&amp;lt;td id=&amp;quot;listoperators&amp;quot;&amp;gt;'&lt;br /&gt;
                                            +'&amp;lt;select id=&amp;quot;listmode&amp;quot; name=&amp;quot;mode&amp;quot;&amp;gt;'&lt;br /&gt;
                                                +'&amp;lt;option value=&amp;quot;blank&amp;quot; selected&amp;gt;(blank)&amp;lt;/option&amp;gt;'&lt;br /&gt;
                                                +'&amp;lt;option value=&amp;quot;block&amp;quot;&amp;gt;Block&amp;lt;/option&amp;gt;'&lt;br /&gt;
                                                +'&amp;lt;option value=&amp;quot;unblock&amp;quot;&amp;gt;Unblock&amp;lt;/option&amp;gt;'&lt;br /&gt;
                                            +'&amp;lt;/select&amp;gt;'&lt;br /&gt;
                                            +'&amp;lt;input name=&amp;quot;run&amp;quot; type=&amp;quot;button&amp;quot; value=&amp;quot;Run&amp;quot;&amp;gt;'&lt;br /&gt;
                                            +'&amp;lt;input name=&amp;quot;reset&amp;quot; type=&amp;quot;button&amp;quot; value=&amp;quot;Reset&amp;quot;&amp;gt;'&lt;br /&gt;
                                        +'&amp;lt;/td&amp;gt;'&lt;br /&gt;
                                    +'&amp;lt;/tr&amp;gt;'&lt;br /&gt;
                                +'&amp;lt;/tbody&amp;gt;&amp;lt;/table&amp;gt;'&lt;br /&gt;
                            +'&amp;lt;/div&amp;gt;'&lt;br /&gt;
                        +'&amp;lt;/div&amp;gt;');&lt;br /&gt;
        $('#widgettarget').html(UIframe);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Helper function&lt;br /&gt;
    function isAnonymousUser(username) {&lt;br /&gt;
        // Pattern of the form 111.111.1.1&lt;br /&gt;
        const pattern = /(\d+)\.(\d+)\.(\d+)\.(\d+)/i;&lt;br /&gt;
        var res = username.match(pattern);&lt;br /&gt;
      	if (res) {&lt;br /&gt;
            return true;&lt;br /&gt;
        } else {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Extract information from the GUI.&lt;br /&gt;
    function getCurrentTaskFromGUI() {&lt;br /&gt;
&lt;br /&gt;
        // Define variables&lt;br /&gt;
        var mode = $('#listmode').val();&lt;br /&gt;
        var summary = '';&lt;br /&gt;
        var username = '';&lt;br /&gt;
&lt;br /&gt;
        // Obtain the list of potential pages&lt;br /&gt;
        var allpages = [];&lt;br /&gt;
        allpages = $('#listinput textarea').val().split('\n');&lt;br /&gt;
&lt;br /&gt;
        // Take the first line away from the potential pages and add to the processing box.&lt;br /&gt;
        var currentline = allpages.shift();&lt;br /&gt;
        $('#listprogress').text(currentline);&lt;br /&gt;
&lt;br /&gt;
        // Return allpages back to the form without the top line&lt;br /&gt;
        $('#listinput textarea').val(allpages.join('\n'));&lt;br /&gt;
&lt;br /&gt;
        // Check list entry isn't blank&lt;br /&gt;
        var currentpages = currentline.split('&amp;gt;');&lt;br /&gt;
        if (currentpages.length &amp;gt; 0) {&lt;br /&gt;
            username = currentpages[0].trim();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Get summary&lt;br /&gt;
        summary = $('#listsummary').val();&lt;br /&gt;
&lt;br /&gt;
        // Verify inprogress isn't blank&lt;br /&gt;
        if ( $('#listprogress').text() == '' ) {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Need to pass a different set of options for each operation&lt;br /&gt;
        var options = {};&lt;br /&gt;
        switch (mode) {&lt;br /&gt;
            case &amp;quot;block&amp;quot;:&lt;br /&gt;
                // Block target user&lt;br /&gt;
                options = {&lt;br /&gt;
                    action: 'block',&lt;br /&gt;
                    expiry: ( isAnonymousUser(username) ? '1 year' : 'infinite' ),&lt;br /&gt;
                    reason: summary,&lt;br /&gt;
                    user: username,&lt;br /&gt;
                    reblock: true, // Without this, if they have an existing block (even a short 3 day one), the API would otherwise throw an alreadyblocked message.&lt;br /&gt;
                    bot: true&lt;br /&gt;
                };&lt;br /&gt;
                tokenOperation(options);&lt;br /&gt;
            break;&lt;br /&gt;
            case &amp;quot;unblock&amp;quot;:&lt;br /&gt;
                // Unblock target user&lt;br /&gt;
                options = {&lt;br /&gt;
                    action: 'unblock',&lt;br /&gt;
                    reason: summary,&lt;br /&gt;
                    user: username,&lt;br /&gt;
                    bot: true&lt;br /&gt;
                };&lt;br /&gt;
                tokenOperation(options);&lt;br /&gt;
            break;&lt;br /&gt;
            default:&lt;br /&gt;
                // Do nothing and abort.&lt;br /&gt;
                return;&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Perform an operation using the currently active account with a token.&lt;br /&gt;
    function tokenOperation (options) {&lt;br /&gt;
        // console.log(options);&lt;br /&gt;
        var pagetitle = options.user;&lt;br /&gt;
        api.postWithToken( &amp;quot;csrf&amp;quot;, options )&lt;br /&gt;
        .done( function( result, jqXHR ) {&lt;br /&gt;
            $('#listsucceed div').html( $('#listprogress').text() + '&amp;lt;br&amp;gt;' + $('#listsucceed div').html());&lt;br /&gt;
            $('#listprogress').text('');&lt;br /&gt;
            if ( $('#listinput textarea').val() !== '' ) {&lt;br /&gt;
                getCurrentTaskFromGUI();&lt;br /&gt;
            }&lt;br /&gt;
        })&lt;br /&gt;
        .fail( function(code, result) {&lt;br /&gt;
            // Actually it didn't &amp;quot;fail&amp;quot; per-se if they were already blocked indefinitely&lt;br /&gt;
            if ( code == 'alreadyblocked') {&lt;br /&gt;
                $('#listsucceed div').html( $('#listprogress').text() + ' --&amp;gt; already blocked' + '&amp;lt;br&amp;gt;' + $('#listsucceed div').html());&lt;br /&gt;
                $('#listprogress').text('');&lt;br /&gt;
&lt;br /&gt;
                // Continue&lt;br /&gt;
                getCurrentTaskFromGUI();&lt;br /&gt;
            } else {&lt;br /&gt;
                $('#listfailed div').html( $('#listprogress').text() + '&amp;lt;br&amp;gt;' + $('#listfailed div').html());&lt;br /&gt;
                $('#listprogress').text('');&lt;br /&gt;
                if ( code === &amp;quot;http&amp;quot; ) {&lt;br /&gt;
                    console.log( pagetitle + &amp;quot;: HTTP error: &amp;quot; + result.textStatus );&lt;br /&gt;
                } else if ( code === &amp;quot;ok-but-empty&amp;quot; ) {&lt;br /&gt;
                    console.log( pagetitle + &amp;quot;: Got an empty response from the server&amp;quot; );&lt;br /&gt;
                } else {&lt;br /&gt;
                    console.log( pagetitle + &amp;quot;: API error: &amp;quot; + code );&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Make the API connection, set up the GUI, respond to button pushes, loop through elements&lt;br /&gt;
    function mainTaskFunction () {&lt;br /&gt;
        // When user clicks run, pick up the current function and cycle through the list&lt;br /&gt;
        $('input[name=&amp;quot;run&amp;quot;]').click(function() {&lt;br /&gt;
            console.log('user clicked run.');&lt;br /&gt;
            if ( $('#listmode').val() == 'blank' ) {&lt;br /&gt;
                console.log('User did not select a mode. Abort!');&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            getCurrentTaskFromGUI();&lt;br /&gt;
        });&lt;br /&gt;
        // When user clicks reset, blank all fields&lt;br /&gt;
        $('input[name=&amp;quot;reset&amp;quot;]').click(function() {&lt;br /&gt;
            console.log('user clicked reset.');&lt;br /&gt;
            $('#listmode').val('blank');&lt;br /&gt;
            $('#listsucceed div').html('');&lt;br /&gt;
            $('#listfailed').html('');&lt;br /&gt;
            $('#listinput textarea').text('');&lt;br /&gt;
            $('#listprogress').text('');&lt;br /&gt;
            $('#listprogress').text('');&lt;br /&gt;
            $('#listsummary').val('');&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Prepare MediaWiki API functions&lt;br /&gt;
    var api = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
    // Create the user interface&lt;br /&gt;
    makeTaskGUI();&lt;br /&gt;
&lt;br /&gt;
    // Add functions to the interface&lt;br /&gt;
    mainTaskFunction();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// DEFER LOADING SCRIPT UNTIL JQUERY IS READY. WAIT 40MS BETWEEN ATTEMPTS.&lt;br /&gt;
function defer(method) {&lt;br /&gt;
    if (window.jQuery) {&lt;br /&gt;
        method();&lt;br /&gt;
    } else {&lt;br /&gt;
        setTimeout(function() { defer(method) }, 240);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// INITIALISATION&lt;br /&gt;
defer(function () {&lt;br /&gt;
    mw.loader.using('mediawiki.api', function () {&lt;br /&gt;
        var userrights = mw.config.get('wgUserGroups');&lt;br /&gt;
        var pageurl = window.location.href;&lt;br /&gt;
        if (userrights.indexOf('sysop') &amp;gt; -1) {&lt;br /&gt;
            mwBlockScript();&lt;br /&gt;
        } else {&lt;br /&gt;
            console.log('Insufficient user rights: '+JSON.stringify(userrights));&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;!--{/if}--&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>gww&gt;Chieftain Alex</name></author>
	</entry>
</feed>