//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;