User:Interiot/Tool2/code.js: Difference between revisions

Content deleted Content added
note that Tool2 doesn't work for some reason, and Tool1 is one alternative
old junk
 
(One intermediate revision by one other user not shown)
Line 1:
// blanked as script was no longer working, and had been inactive for years.
// see http://paperlined.org/apps/wikipedia/Tool2/ for instructions on adding this to your monobook.js
mw.log.warn( 'You installed the userscript [[User:Interiot/Tool2/code.js]]\n'
 
+ 'It has been deprecated and you should remove it.' );
// To run this tool on other servers:
// 1. copy this script to the target server (this is required because of javascript cross-site security restrictions)
 
// 2. update the following URL
// for example: "User:Interiot/Tool2/code.js"
var tool2_url = "User:Interiot/Tool2/code.js";
 
// 3. update this namespace list, extracted from something like http://en.wikiquote.org/wiki/Special:Export//
// These *should not* have colons after them.
var namespaces = [
"Talk",
"User",
"User talk",
"Wikiquote",
"Wikiquote talk",
"Image",
"Image talk",
"MediaWiki",
"MediaWiki talk",
"Template",
"Template talk",
"Help",
"Help talk",
"Category",
"Category talk",
// 3b. these two project project entries are not added by Special:Export, and might or might not need to be updated
"Wikipedia",
"Wikipedia talk"
];
 
namespaces[100] = "Portal";
namespaces[101] = "Portal talk";
 
// 4. update this date-parser to match the format and language of your specific wiki. Feel free to contact Interiot regarding this, if you can't find another
// copy of this script that uses the same language.
// input: a text string from Special:Contributions. output: a javascript Date object
// documentation: http://www.quirksmode.org/js/introdate.html#parse, http://www.elated.com/tutorials/programming/javascript/dates/
function date_parse(text) {
var matches = text.match(/^([0-9:]+), +([0-9]+) +([a-z]+) +([0-9]+)$/i);
if (!matches) {
//dump_text("XXX"); // for debugging
return matches;
}
 
parseme = matches[3] + ", " + matches[2] + " " + matches[4] + " " + matches[1] + ":00";
 
//dump_text(parseme); // for debugging
 
var dt = new Date();
dt.setTime( Date.parse(parseme));
 
//dump_text(dt.toLocaleString()); // for debugging
 
return dt;
}
 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ end of server-specific configuration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 
 
// TODO:
// - the current document.___location method doesn't work when the page is accessed sans-mod_rewrite
// - test with non-ASCII characters
// - non-ascii usernames
// - ??
 
 
 
var prefix = "";
var params = parse_params();
 
addOnloadFunction(function() {
var path_len = document.___location.pathname.length;
// trigger once we view the right page
if (document.___location.pathname.substring(path_len - tool2_url.length, path_len) == tool2_url) {
// get the prefix (needs to be fixed to work sans-mod_rewrite
prefix = document.___location.protocol + "//" + document.___location.host + "/"
+ document.___location.pathname.substring(1, path_len - tool2_url.length);
 
// blank the inner contents of the page
var bodyContent = document.getElementById("bodyContent");
while (bodyContent.childNodes.length > 0) bodyContent.removeChild(bodyContent.lastChild);
 
//if (document.___location.search.length == 0) {
//generate_input_form(bodyContent);
//} else {
//generate_main_report(bodyContent);
//}
generate_redirect_notice(bodyContent);
}
});
 
function generate_input_form(bodyContent) {
bodyContent.innerHTML = "This counter doesn't currently work. Please use <a href='http://tools.wikimedia.de/~interiot/cgi-bin/Tool1/wannabe_kate'>Tool1</a> or <a href='http://en.wikipedia.org/wiki/Wikipedia:WikiProject_edit_counters'>one of the other edit counters</a>.";
}
 
function generate_input_form(bodyContent) {
if (navigator.userAgent.toLowerCase().indexOf('msie')+1)
{
bodyContent.innerHTML = "This counter does not currently work in Internet Explorer. Please <a href='http://www.getfirefox.com'>get Firefox</a> or use <a href='http://en.wikipedia.org/wiki/Wikipedia:WikiProject_edit_counters/Flcelloguy%27s_Tool'>Flcelloguy's Tool</a> instead.";
}
else
{
bodyContent.innerHTML =
"<form><table><tr><td>Username <td><input maxlength=128 name=username value='' id=username title='username'>" +
" <tr><td> <td><input type=submit value='Submit'>" +
"</table></form>";
 
var form = bodyContent.getElementsByTagName("form")[0];
form.method = "get";
form.action = document.___location;
 
document.getElementById("username").focus();
}
}
 
function generate_main_report() {
fetch_data(params["username"].replace(/\+/g, " "),
"", output_main_report, 0, []);
}
 
 
function add_stats_row(left_col, right_col) {
var row = document.createElement("tr");
var left = document.createElement("td");
var right = document.createElement("td");
document.getElementById("basic_stats").appendChild(row);
row.appendChild(left);
row.appendChild(right);
//left.innerHTML = left_col;
left.appendChild( document.createTextNode(left_col) );
right.appendChild( document.createTextNode(right_col) );
return row;
}
 
function output_main_report(history) {
// -- generate summary statistics
var unique_articles = new Array();
var namespace_numedits = new Array();
for (var i=0; i<namespaces.length; i++) {
namespace_numedits[ namespaces[i] ] = 0;
}
namespace_numedits[""] = 0;
for (var i=0; i<history.length; i++) {
var h = history[i];
unique_articles[ h["title"] ]++;
namespace_numedits[ h["namespace"] ]++;
}
var unique_articles_keys = keys(unique_articles);
 
// -- output report
var table = document.createElement("table");
table.id = "basic_stats";
document.getElementById("bodyContent").appendChild(table);
 
add_stats_row("Username", params["username"].replace(/\+/g, " "));
add_stats_row("Total edits", history.length);
add_stats_row("Distinct pages edited", unique_articles_keys.length);
add_stats_row("Average edits/page", new Number(history.length / unique_articles_keys.length).toFixed(3));
add_stats_row("First edit", history[ history.length-1 ]["date_text"] );
 
// add a blank row
add_stats_row("", "").childNodes[0].style.height = "1em";
 
add_stats_row("(main)", namespace_numedits[""]);
for (var i=0; i<namespaces.length; i++) {
var nmspc = namespaces[i];
if (namespace_numedits[nmspc]) {
add_stats_row(nmspc, namespace_numedits[nmspc]);
}
}
}
 
 
 
// ===================================== HTML-scraping backend =========================================
 
function add_loading_notice() {
if (document.getElementById("loading_notice"))
return;
var loading = document.createElement("div");
loading.id = "loading_notice";
loading.innerHTML = "<br><br>Retrieving data<blink>...</blink>";
document.getElementById("bodyContent").appendChild(loading);
}
function remove_loading_notice() {
var loading = document.getElementById("loading_notice");
if (!loading) return;
loading.parentNode.removeChild(loading);
}
 
var offset_regexp = /href="[^"]+:Contributions[^"]+offset=(\d+)/gi;
function fetch_data(username, end_date, handler, offset, page_list) {
add_loading_notice();
var url = prefix + "Special:Contributions/" + username + "?offset=" + offset + "&limit=5000";
loadXMLDoc(url,
function (request) {
var next_offset = 0;
if (request.readyState != 4) return;
if (request.status == 200) {
page_list.push(request.responseText);
//dump_text(request.responseText);
 
// see if there's another pageful to get
var matches = map( function(p){
return p.match( /(\d+)$/ )[0];
}, request.responseText.match( offset_regexp ) );
for (var i=0; i<matches.length; i++) {
var v = matches[i] * 1;
if (v != 0 && (offset == 0 || v < offset)) {
next_offset = v;
break;
}
}
}
 
//next_offset = 0; // for testing only, retrieve just the first page of results
 
if (next_offset == 0) {
parse_data(page_list, handler);
} else {
// tail recurse
fetch_data(username, end_date, handler, next_offset, page_list);
}
});
}
 
 
// input: a list of strings, each string containing the HTML from a single page
// output: a list, where each individual entry is a specific edit from history
function parse_data(page_list, handler) {
//var total_len = 0;
//for (var i=0; i<page_list.length; i++) total_len += page_list[i].length;
//alert("parsing " + page_list.length + " pages comprising " + total_len + " total bytes");
 
var last_history_ent = [];
last_history_ent["title"] = "";
last_history_ent["oldid"] = "";
 
var edit_history = new Array();
for (var pagecnt=0; pagecnt<page_list.length; pagecnt++) {
var matches = page_list[pagecnt].match( /^<li>[^(]+\(<a href="[^"]+action=history.*/gim );
//dump_lines(matches);
for (var matchcnt=0; matchcnt<matches.length; matchcnt++) {
var history_text = matches[matchcnt];
 
var history_entry = new Array();
history_entry["date_text"] = history_text.match( /^<li>([^(<]+)/i )[1]
.replace( / +$/, "");
history_entry["date"] = date_parse( history_entry["date_text"] );
history_entry["title"] = history_text.match( /title="([^"]+)"/i )[1]
.replace( /&quot;/g, "\"")
.replace( /&amp;/g, "&");
var find_comment = history_text.replace(/<span class="autocomment">.*?<\/span> ?/, "");
history_entry["comment"] = ifmatch(find_comment.match( /<span class='comment'>(.*?)<\/span>/ ))
.replace(/^\((.*)\)$/, "$1");
history_entry["minor"] = /<span class="minor"/.test(history_text);
history_entry["oldid"] = ifmatch(history_text.match(/oldid=([0-9]+)/i));
 
history_entry["namespace"] = "";
for (var nmspc_ctr=0; nmspc_ctr<namespaces.length; nmspc_ctr++) {
var nmspc = namespaces[nmspc_ctr] + ":";
if (history_entry["title"].substring(0, nmspc.length) == nmspc) {
history_entry["namespace"] = namespaces[nmspc_ctr];
break;
}
}
 
//dump_object(history_entry);
 
if (history_entry["title"] != last_history_ent["title"] || history_entry["oldid"] != last_history_ent["oldid"])
edit_history.push(history_entry);
last_history_ent = history_entry;
}
}
 
remove_loading_notice();
 
handler(edit_history);
}
 
 
 
 
// ===================================== test/debug functions =========================================
 
function dump_text(text) {
//alert("dump_text, with text of size " + text.length);
 
var pre = document.createElement("pre");
 
var div = document.createElement("div");
div.style.width = "60em";
div.style.maxHeight = "40em";
div.style.overflow = "auto";
 
pre.appendChild(document.createTextNode(text));
div.appendChild(pre);
document.getElementById("bodyContent").appendChild(div);
}
 
function dump_lines(ary) {
dump_text("--> " + ary.join("\n--> "));
}
 
function dump_object(obj) {
var toString = "";
for (var prop in obj) {
toString += prop + ": " + obj[prop] + "\n";
}
dump_text(toString);
}
 
 
// ===================================== utility functions =========================================
 
function addOnloadFunction(f) {
if (window.addEventListener) window.addEventListener("load",f,false);
else if (window.attachEvent) window.attachEvent("onload",f);
else {
var oldOnload='_old_onload_'+addOnloadFunction.uid;
addOnloadFunction[oldOnload] = window.onload ? window.onload : function () {};
window.onload = function() { addOnloadFunction[oldOnload](); f(); }
++addOnloadFunction.uid;
}
}
 
 
function parse_params() {
var pairs = document.___location.search.substring(1).split("&");
var ret = [];
for (var i=0; i < pairs.length; i++) {
var values = pairs[i].split("=");
ret[values[0]] = unescape(values[1]);
}
return ret;
}
 
 
function loadXMLDoc(url, handler)
{
// branch for native XMLHttpRequest object
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = function () {handler(req)};
req.open("GET", url, true);
req.send(null);
// branch for IE/Windows ActiveX version
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange = function () {handler(req)};
req.open("GET", url, true);
req.send();
}
}
}
 
 
// see http://search.cpan.org/dist/perl/pod/perlfunc.pod#map
function map (handler, list) {
var ret = new Array();
for (var i=0; i<list.length; i++) {
ret[i] = handler( list[i] );
// ret.push( handler( list[i] ) );
}
return ret;
}
 
// see http://search.cpan.org/dist/perl/pod/perlfunc.pod#keys
function keys (obj) {
var ret = new Array();
for (var key in obj) {
ret.push(key);
}
return ret;
}
 
 
function ifmatch(ary) {
if (ary && ary.length >= 2) {
return ary[1];
} else {
return "";
}
}