Jump to content

User:Martijn Hoekstra/checkrange.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
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.
//stuff for sanity-checking rangeblocks
 
var checkrange = {
  check_months : 1,
  check_days : 0,
  check_years : 0,
  min_edits : 1,
  ip_prefixes : [],
  range : "92.41.0.0/22",
  ips : {},
  num_ips : 0,
  startdate: {},

  addlink : function() {
    return mw.util.addPortletLink(
    	"p-cactions",
    	"#",
    	"Check range",
    	"ca-rangeChecker",
    	"Check range"
    	);
  },

  init : function() {
  	console.debug("called init");
    this.num_ips = 0;
    this.ips = {};
    this.show_form();
    var default_startdate = this.get_default_startdate();
    var default_minedits = this.min_edits;
    var default_range = "";
    var ranges_on_page = document.body.innerHTML.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}/);
    if (ranges_on_page ){
      default_range = ranges_on_page[0];
    }
    mw.log("default range:" + default_range);
    document.getElementById("checkrange_range").value = default_range;
    document.getElementById("checkrange_minedits").value = default_minedits;
    document.getElementById("checkrange_startyear").value = default_startdate.getFullYear();
    document.getElementById("checkrange_startmonth").value = (default_startdate.getMonth() + 1);
    document.getElementById("checkrange_startdate").value = default_startdate.getDate();
  },

  get_default_startdate : function() {
    var now = new Date();
    return new Date(now.getUTCFullYear() - this.check_years, now.getUTCMonth() - this.check_months, now.getUTCDate() - this.check_days);
  },

   
  show_form : function() {
    var form = '<div id="checkrange_form">' + 
               '<h3>Give parameters for the block you want to test</h3>' + 
               '<label>start date: (year, month, day)</label>' + 
               '<input type="text" id="checkrange_startyear" "name=checkrange_startyear" size="4" maxlength="4" />' + 
               '<input type="text" id="checkrange_startmonth" name="checkrange_startmonth" size="2" maxlength="2" />' +
               '<input type="text" id="checkrange_startdate" name="checkrange_startmonth" size="2" maxlength="2" /> <br />' +
               '<label for="checkrange_minedits">with at least</label>'+
               '<input type="text" id="checkrange_minedits" name = "checkrange_minedits" size="2" maxlength="2">' +
               '<label for="checkrange_minedits">edits in this period</label><br />' + 
               '<label for="checkrange_range">range:</label>' +
               '<input type="text" id="checkrange_range" name="checkrange_range">' +
               '<input type="button" id="checkrange_start" name="checkrange_start" value="calculate" onclick="checkrange.start_check()" />' + 
               '</div>';
    mediaWiki.notify(form);
  },

  start_check : function(){
    var startyear = parseInt(document.getElementById("checkrange_startyear").value, 10);
    var startmonth = parseInt(document.getElementById("checkrange_startmonth").value, 10) - 1;
    var startdate = parseInt(document.getElementById("checkrange_startdate").value, 10);
    this.startdate = new Date(startyear, startmonth, startdate);
    var myrange = document.getElementById("checkrange_range").value;
    var found = myrange.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}/);
    if (found){
      this.range = found[0];
    } else {
      alert("misformatted range");
      return;
    }
    var my_min_edits = parseInt(document.getElementById("checkrange_minedits").value);
    if (isNaN(my_min_edits)){
      alert("misformatted min edits");
      return;
    } else {
      this.min_edits = my_min_edits;
    }
    this.get_recently_active_ips();
  },

  showbox : function() {
    var message = "<h1>getting active IP's</h1>";
    message += "prefixes:<ul id='prefixlist'></ul>";
    message += "unique IP's <span id='IPs'>0</span>";
    mediaWiki.notify(message);
  },
 
  add_prefix : function(prefix){ 
    this.ip_prefixes.push(prefix);
    var msg_prefixes = document.getElementById('prefixlist');
    var listitem = document.createElement('li');
    listitem.appendChild(document.createTextNode(prefix + ' ' ));
    var s = document.createElement("span");
    s.id = prefix;
    s.innerText = 'fetching';
    listitem.appendChild(s);
    msg_prefixes.appendChild(listitem);
  },

  get_recently_active_ips : function (){
    var used_ips = {};
    this.showbox();
    this.get_active_ips();
 },

  get_active_ips: function(){
    var calls = this.construct_api_calls();
    for (var next_call in calls){
      this.get_ips(calls[next_call], calls[next_call]);
    }
  },

  get_ips : function(base_url, call_url){
    var prefix = call_url.match(/ucuserprefix=([^&]*)/)[1];
    $.getJSON(call_url, function(data) {
      var usercontribs = data.query.usercontribs;
      for(var item in usercontribs){
        var realitem=usercontribs[item];
        if (checkrange.check_timestamp(realitem.timestamp)){
          if (checkrange.ips.hasOwnProperty(realitem.user)){
            checkrange.ips[realitem.user] ++;
          } else {
            checkrange.ips[realitem.user] = 1;
          }
          if (checkrange.ips[realitem.user] == checkrange.min_edits) {
             checkrange.num_ips += 1;
             document.getElementById("IPs").innerText=checkrange.num_ips;
          }
        }
      }
      if (data.hasOwnProperty("query-continue")){
        var next_call_postfix = data["query-continue"].usercontribs.uccontinue;
        if (next_call_postfix){
          mw.log("more for "+prefix);
          mw.log(base_url + "&uccontinue="+next_call_postfix);
          document.getElementById(prefix).innerText='fetching more';
          checkrange.get_ips(base_url, base_url + "&uccontinue="+next_call_postfix);
        } else {
          mw.log("huh? no next_call_postfix, but there is a query-continue");
          mw.log(data("query-continue"));
        }
      } else {
        document.getElementById(prefix).innerHTML='<b>done</b>';
        mw.log("done for "+prefix);
      }
    });
  },

  check_timestamp : function(timestamp){
    //2010-10-09T06:22:05Z
    var date = timestamp.split("T")[0];
    var year = parseInt(date.substring(0,4), 10);
    var month = parseInt(date.substring(5,2), 10)-1;
    var day = parseInt(date.substring(8,2), 10);
    var timestamp_date = new Date(year, month, day);
    return (timestamp_date > this.startdate);
  },

  construct_api_calls : function(){
//    var api_call_base_url = "https://en.wikipedia.org/w/api.php?action=query&list=usercontribs&format=json&rawcontinue=&ucuserprefix=";
    var api_call_base_url = "/w/api.php?action=query&list=usercontribs&format=json&rawcontinue=&ucuserprefix=";
    var api_calls = [];
    this.ip_prefixes = [];
    this.get_prefixes();
    for (var prefix in this.ip_prefixes){
      api_calls.push(api_call_base_url + this.ip_prefixes[prefix]);
      mw.log(api_call_base_url + this.ip_prefixes[prefix]);
    }
    return api_calls;
  },

  get_prefixes_notdone : function(){
    var prefixes = [];
    var parts = this.range.split('/');
    var start = parts[0];
    var size = parseInt(parts[1]);
    var num_fixed_octets = Math.floor((size + 1)/8);
    mw.log("fixed octets: " + num_fixed_octets);
    var octets = $.map(start.split('.'), function(n){
      return parseInt(n);
    });
    mw.log(octets);
    var factor = (8 * (num_fixed_octets +1) - size) % 8;
    mw.log("factor: " + factor);
    if (!confirm("factor: " + factor)){
      return;
    }
    var num_blocks = 1 << factor;
    mw.log('num blocks: ' + num_blocks);
    var max_octet = octets[num_fixed_octets] + num_blocks - 1;
    mw.log('max octet: ' + max_octet);
    var current_octet = octets[num_fixed_octets];
    while(current_octet <= max_octet){
    mw.log('current octet: ' + current_octet);
      var prefix = "";
      for(var i = 0; i < num_fixed_octets; i++){
        prefix += octets[i] + '.';
      }
      prefix += current_octet;
      if (size > 24) prefix += '.';
      this.add_prefix(prefix);
      mw.log(prefix);
      current_octet++;
    }
  },

  get_prefixes : function(){
    var prefixes = [];
    var parts = this.range.split('/');
    var start = parts[0];
    var size = parseInt(parts[1]);

    var octets = $.map(start.split('.'), function(n){
      return parseInt(n);
    });

    var range = this.range.split('.');

    var octet1 = parseInt(range[0]);
    var octet2 = parseInt(range[1]);
    var octet3 = parseInt(range[2]);
    var octet4 = parseInt(range[3]);
    
    var factor = 0;
    var num_blocks = 1;
 
    //now the annoying part
    if (size <= 8) {
      factor = 8 - size;
      num_blocks = 1 << factor;
      max_octet = octets[0] + num_blocks - 1;
      var current_octet = octets[0];
      while(current_octet1 <= max_octet1){
        this.add_prefix(current_octet.toString() + '.');
        current_octet++;
      }
    } else if (size > 8 && size <= 16){
      factor = 16 - size;
      num_blocks = 1 << factor;
      max_octet2 = octet2 + num_blocks - 1;
      var current_octet2 = octet2;
      while(current_octet2 <= max_octet2){
        this.add_prefix(octet1.toString() + '.' + current_octet2.toString() + '.', prefixes);
        current_octet2++;
      }
    } else if (size > 16 && size <= 24){
      factor = 24 - size;
      num_blocks = 1 << factor;
      max_octet3 = octet3 + num_blocks - 1;
      var current_octet3 = octet3;
      while(current_octet3 <= max_octet3){
        this.add_prefix(octet1.toString() + '.' + octet2.toString() + '.' + current_octet3.toString() + '.');
        current_octet3++;
      }
    } else {
      factor = 32 - size;
      var num_d = 1 << factor;
      max_octet4 = octet4 + num_d - 1;
      var current_octet4 = octet4;
      while(current_octet4 <= max_octet4){
        this.add_prefix(octet1.toString() + '.' + octet2.toString() + '.' + octet3.toString() + '.' + current_octet4.toString());
        current_octet4++;
      }
    }
  }
}

jQuery( function(){
  var link = checkrange.addlink();
  console.debug("link is", link);
  link.click(function(e){
  	e.preventDefault();
  	checkrange.init()
  	});
});

// Expose globally
window.checkrange = checkrange;