Jump to content

User:Zeke Essiestudy/common.js

From Wikipedia, the free encyclopedia
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.
importScript('User:Writ Keeper/Scripts/orangeBar.js'); //Linkback: [[User:Writ Keeper/Scripts/orangeBar.js]]
//Tim's SPI helper script
//v.1.6.6
//Adapted from [[User:Mr.Z-man/closeAFD]]
importScript('User:Timotheus Canens/displaymessage.js');
 
if (!Array.prototype.indexOf) {  
	Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {  
		"use strict";  
		if (this === void 0 || this === null) {  
			throw new TypeError();  
		}  
		var t = Object(this);  
		var len = t.length >>> 0;  
		if (len === 0) {  
			return -1;  
		}  
		var n = 0;  
		if (arguments.length > 0) {  
			n = Number(arguments[1]);  
			if (n !== n) { // shortcut for verifying if it's NaN  
				n = 0;  
			} else if (n !== 0 && n !== Infinity && n !== -Infinity) {  
				n = (n > 0 || -1) * Math.floor(Math.abs(n));  
			}  
		}  
		if (n >= len) {  
			return -1;  
		}  
		var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);  
		for (; k < len; k++) {  
			if (k in t && t[k] === searchElement) {  
				return k;  
			}  
		}  
		return -1;  
	};  
}
 
if(!String.prototype.trim)
{
	String.prototype.trim = function(){
		return this.replace(/^\s+/, '').replace(/\s+$/, '');
	};
}
 
if (wgPageName.indexOf('Wikipedia:Sockpuppet_investigations/') != -1
		&& wgPageName.indexOf('Wikipedia:Sockpuppet_investigations/SPI/') == -1
		&& wgPageName.indexOf('/Archive') == -1) {
	var spiHelper_PageName = wgPageName.replace(/_/g, ' ');
	var spiHelper_CaseName = spiHelper_PageName.replace(/Wikipedia:Sockpuppet investigations\//g, '');
	var spiHelper_AJAXnumber = 0;
	var spiHelper_isAdmin = (wgUserGroups.toString().indexOf('sysop') != -1);
	var spiHelper_isCheckuser = (wgUserGroups.toString().indexOf('checkuser') != -1);
	var spiHelper_ActionsSelected = 
	{ CU_act : false, CU_new : false, Block : false, Note: false, Close: false, Archive: false };
	if(typeof(spiHelper_watchArchive) == 'undefined') spiHelper_watchArchive = "preferences";
	if(typeof(spiHelper_watchCase) == 'undefined') spiHelper_watchCase = "preferences";
	var spiHelper_usercount = 0;
	mw.loader.load('mediawiki.user');
 
	function spiHelper_init(){
 
		var pagetext = spiHelper_getPageText(spiHelper_PageName, false);
		var section_re = /=====[^=]*=====/;
		if(!section_re.test(pagetext)) return; // Nothing to do here.
		var spicasestatus_re = /\{\{\s*SPI case status\s*\|?\s*(\S*?)\s*\}\}/i;
		var result = spicasestatus_re.exec(pagetext);
		var casestatus = '';
		if(result != null){
			casestatus = result[1];
		}
 
		var hasCURequest = (casestatus != '' && !(/^(?:close|closed|CUdecline|CUdeclined)$/i.test(casestatus)));
		var canAddCURequest = (casestatus == '');
		var CUActiondefault = (/^(?:CU|checkuser|request|CUrequest)$/i.test(casestatus));
		var isClosed = /^(?:close|closed)$/i.test(casestatus);
 
		var text = '<h3>Handling SPI case</h3><ul>';
		if(hasCURequest)
			text += '<li><input type="checkbox"' + (CUActiondefault? ' checked="checked"' : '') + ' name="spiHelper_CU_Action" id="spiHelper_CU_Action" />' +
			'<label for="spiHelper_CU_Action">Act on CU request</label></li>';
		else if(canAddCURequest)
			text += '<li><input type="checkbox" name="spiHelper_CU_Request" id="spiHelper_CU_Request" />' +
			'<label for="spiHelper_CU_Request">Add CU request</label></li>';
		text += '<li><input type="checkbox" name="spiHelper_BlockTag" id="spiHelper_BlockTag" />' +
		'<label for="spiHelper_BlockTag">';
		text += spiHelper_isAdmin ? "Block/tag socks" : "Tag socks";
		text += '</label></li><li><input type="checkbox" name="spiHelper_Comment" id="spiHelper_Comment" />' +
		'<label for="spiHelper_Comment">Note/comment</label></li>';
		if(!isClosed)
			text += '<li><input type="checkbox" name="spiHelper_Close" id="spiHelper_Close" onchange="spiHelper_toggleArchive()" />' +
			'<label for="spiHelper_Close">Close case</label></li>';
		else
			text += '<li><input type="checkbox" disabled="true" name="spiHelper_Close" id="spiHelper_Close" />' +
			'<label for="spiHelper_Close">Close case</label></li>';
		if(isClosed)
			text += '<li><input type="checkbox" checked="checked" name="spiHelper_Archive" id="spiHelper_Archive" />' +
			'<label for="spiHelper_Archive">Archive case</label></li></ul>';
		else
			text += '<li><input type="checkbox" disabled="true" name="spiHelper_Archive" id="spiHelper_Archive" />' +
			'<label for="spiHelper_Archive">Archive case</label></li></ul>';
		text += '<input type="button" id="spiHelper_GenerateForm" name="spiHelper_GenerateForm" value="Continue" onclick="spiHelper_generateform()" />';
		displayMessage(text);
	}
 
	function spiHelper_toggleArchive(){
		document.getElementById("spiHelper_Archive").disabled = !document.getElementById("spiHelper_Close").checked;
		if(document.getElementById("spiHelper_Archive").disabled)
			document.getElementById("spiHelper_Archive").checked = false;
	}
 
	function spiHelper_generateform(){
		spiHelper_usercount = 0;
		if (document.getElementById("spiHelper_CU_Action") != null)
			spiHelper_ActionsSelected.CU_act = document.getElementById("spiHelper_CU_Action").checked;
		else if(document.getElementById("spiHelper_CU_Request") != null)
			spiHelper_ActionsSelected.CU_new = document.getElementById("spiHelper_CU_Request").checked;
		spiHelper_ActionsSelected.Block = document.getElementById("spiHelper_BlockTag").checked;
		spiHelper_ActionsSelected.Note = document.getElementById("spiHelper_Comment").checked;
		spiHelper_ActionsSelected.Close = document.getElementById("spiHelper_Close").checked;
		spiHelper_ActionsSelected.Archive = document.getElementById("spiHelper_Archive").checked;
		var pagetext = spiHelper_getPageText(spiHelper_PageName, false);
		if(!(spiHelper_ActionsSelected.CU_act||spiHelper_ActionsSelected.CU_new||spiHelper_ActionsSelected.Note
				||spiHelper_ActionsSelected.Close||spiHelper_ActionsSelected.Archive
				||spiHelper_ActionsSelected.Block)){
			displayMessage("");
			return;
		}
		var text = '<h3>Handling SPI case</h3>';
		if(spiHelper_ActionsSelected.CU_act){
			text += '<h4>Handling Checkuser request</h4>'
				+ '<ul><li><label for="spiHelper_CUAction">Checkuser request:</label>';
			if(spiHelper_isCheckuser){
				text += spiHelper_generateSelect('spiHelper_CUAction',
						[
						 { label: 'No action', selected : true, value: 'noaction' },
						 { label: 'Endorse for CU attention', value: 'endorse' },
						 { label: 'Decline CU', value: 'cudecline' },
						 { label: 'Place case on hold', value: 'cuhold' },
						 { label: 'Relist for another check', value: 'relist' },
						 { label: 'Request more information', value: 'moreinfo' },
						 { label: 'Mark as in progress', value: 'inprogress' },
						 { label: 'Mark as checked', value: 'checked' }
						 ]);
			}
			else {
				text += spiHelper_generateSelect('spiHelper_CUAction',
						[
						 { label: 'No action', selected : true, value: 'noaction' },
						 { label: 'Endorse for CU attention', value: 'endorse' },
						 { label: 'Decline CU', value: 'decline' },
						 { label: 'Place case on hold', value: 'hold' },
						 { label: 'Relist for another check', value: 'relist' },
						 { label: 'Request more information', value: 'moreinfo' },
						 { label: 'Mark as checked', value: 'checked' }
						 ]);
			}
			text +=  '</li> <li><label for="spiHelper_CUComment">Comment:</label>'
				+ '<input type="text" name="spiHelper_CUComment" size="80" id="spiHelper_CUComment" /></li></ul>';
		}
		if(spiHelper_ActionsSelected.CU_new){
			text += '<h4>Adding Checkuser request</h4>'
				+ '<ul><li><label for="spiHelper_CUComment">Comment:</label>'
				+ '<input type="text" name="spiHelper_CUComment" size="80" id="spiHelper_CUComment" /></li>'
				+'<li><input type="checkbox" checked="checked" name="spiHelper_CUSelf" id="spiHelper_CUSelf" /><label for="spiHelper_CUSelf">Mark request as endorsed</label></ul>';
		}
		if(spiHelper_ActionsSelected.Block ){
			if(spiHelper_isAdmin)
				text += '<h4>Blocking and tagging socks</h4>';
			else
				text += '<h4>Tagging socks</h4>';
			var checkuser_re = /\{\{\s*check(user|ip)\s*\|\s*(?:1=)?\s*([^\|\}]*?)\s*\}\}/gi;
			var results = pagetext.match(checkuser_re);
			var likelyusers = new Array(), likelyips = new Array(), possibleusers = new Array(), possibleips = new Array();
			likelyusers.push(spiHelper_CaseName);
			for(var i = 0; results != null && i < results.length; i++){
				var username = results[i].replace(checkuser_re, "$2");
				if(!(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(username)) && likelyusers.indexOf(username) == -1)
					likelyusers.push(username);
				else if(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(username) && likelyips.indexOf(username) == -1)
					likelyips.push(username);
			}
			var user_re = /\{\{\s*(?:user|vandal|IP)[^\|\}\{]*?\s*\|\s*(?:1=)?\s*([^\|\}]*?)\s*\}\}/gi;
			var userresults = pagetext.match(user_re);
			for(var i = 0; userresults != null && i < userresults.length; i++){
				var username = userresults[i].replace(user_re, "$1");
				if(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(username) && possibleips.indexOf(username) == -1
						&& likelyips.indexOf(username) == -1)
					possibleips.push(username);
				else if(possibleusers.indexOf(username) == -1 && likelyusers.indexOf(username) == -1)
					possibleusers.push(username);
 
			}
			if(spiHelper_isAdmin){
				text += '<ul><li><input type="checkbox" name="spiHelper_noblock" id="spiHelper_noblock" />' 
					 + '<label for="spiHelper_noblock">Do not make any blocks (this overrides the individual "Blk" boxes below)</label></li>'
					 + '<li><input type="checkbox" checked="checked" name="spiHelper_override" id="spiHelper_override" />' 
					 + '<label for="spiHelper_override">Override any existing blocks</label></li>'
					 + '<li><input type="checkbox" checked="checked" name="spiHelper_blocknoticemaster" id="spiHelper_blocknoticemaster" />' 
					 + '<label for="spiHelper_blocknoticemaster">Add talk page notice when (re)blocking the sockmaster.</label></li>'
					 + '<li><input type="checkbox" name="spiHelper_blocknoticesocks" id="spiHelper_blocknoticesocks" />' 
					 + '<label for="spiHelper_blocknoticesocks">Add talk page notice when blocking socks.</label></li>'
					 + '<li><input type="checkbox" name="spiHelper_blanktalk" id="spiHelper_blanktalk" />' 
					 + '<label for="spiHelper_blanktalk">Blank the talk page when adding talk notices.</label></li></ul>';
 
			}
			text += '<table> <tr><th>Username</th>' + (spiHelper_isAdmin? '<th>Blk?</th><th>Dur</th><th>ACB</th><th>AB/AO</th><th>NTP</th><th>NEM</th>' : '' ) + '<th>Tag</th></tr>';
 
			for(var i = 0; i < likelyusers.length; i++){
				spiHelper_usercount++;
				text += spiHelper_generateBlockTableLine(likelyusers[i], true, spiHelper_usercount, spiHelper_isAdmin);
			}
			for(var i = 0; i < likelyips.length; i++){
				spiHelper_usercount++;
				text += spiHelper_generateBlockTableLine(likelyips[i], true, spiHelper_usercount, spiHelper_isAdmin);
			}
			for(var i = 0; i < possibleusers.length; i++){
				spiHelper_usercount++;
				text += spiHelper_generateBlockTableLine(possibleusers[i], false, spiHelper_usercount, spiHelper_isAdmin);
			}
			for(var i = 0; i < possibleips.length; i++){
				spiHelper_usercount++;
				text += spiHelper_generateBlockTableLine(possibleips[i], false, spiHelper_usercount, spiHelper_isAdmin);
			}
			text += '</table>';
		}
		if(spiHelper_ActionsSelected.Note){
			text += '<h4>Commenting on case</h4>'
				+ '<ul><li><label for="spiHelper_CommentType">Comment label:</label>'
				+ spiHelper_generateSelect('spiHelper_CommentType',
						[
						 { label: 'None', selected : true, value: 'none' },
						 { label: 'Clerk note', value: 'clerknote' },
						 { label: 'Administrator note', value: 'adminnote' },
						 { label: 'Note', value: 'takenote' }
						 ]) + '</li>'
						 + '<li><label for="spiHelper_CommentText">Comment:</label>'
						 + '<input type="text" size="80" name="spiHelper_CommentText" id="spiHelper_CommentText" /></li></ul>';
		}
		if(spiHelper_ActionsSelected.Close){
			text += '<h4>Marking case as closed</h4>'
				+ '<ul><li><input type="checkbox" checked="checked" name="spiHelper_CloseCase" id="spiHelper_CloseCase" />'
				+ '<label for="spiHelper_CloseCase">Close this SPI case</label></li>'
				+ '<li><label for="spiHelper_Close_Comment">Closing comment: </label>'
				+ '<input type="text" size="80" name="spiHelper_Close_Comment" id="spiHelper_Close_Comment" /></li></ul>';
		}
		if(spiHelper_ActionsSelected.Archive){
			text += '<h4>Archiving case</h4>'
				+ '<ul><li><input type="checkbox" checked="checked" name="spiHelper_ArchiveCase" id="spiHelper_ArchiveCase" />'
				+ '<label for="spiHelper_ArchiveCase">Archive this SPI case</label></li>';
			if(spiHelper_ActionsSelected.Block||spiHelper_ActionsSelected.CU_act||spiHelper_ActionsSelected.Close||spiHelper_ActionsSelected.Note)
				text += '<li><input type="checkbox" name="spiHelper_ArchiveSingle" id="spiHelper_ArchiveSingle" />'
					+ '<label for="spiHelper_ArchiveSingle">Perform the above action and archiving in a single edit</label></li>';
			text += '</ul>';
		}
		text += '<input type="button" id="spiHelper_performActions" name="spiHelper_performActions" value="Done" onclick="spiHelper_performActions()" />';
		displayMessage(text);
	}
 
	function spiHelper_performActions(){
		if(spiHelper_ActionsSelected.CU_act){
			spiHelper_ActionsSelected.CUAction = document.getElementById('spiHelper_CUAction').value;
			spiHelper_ActionsSelected.CUComment = document.getElementById('spiHelper_CUComment').value;
		}
		else if(spiHelper_ActionsSelected.CU_new){
			spiHelper_ActionsSelected.CUComment = document.getElementById('spiHelper_CUComment').value;
			spiHelper_ActionsSelected.CUSelf = document.getElementById('spiHelper_CUSelf').checked;
		}
		if(spiHelper_ActionsSelected.Note){
			spiHelper_ActionsSelected.CommentType = document.getElementById('spiHelper_CommentType').value;
			spiHelper_ActionsSelected.Comment = document.getElementById('spiHelper_CommentText').value;
		}
		if(spiHelper_ActionsSelected.Block){
			spiHelper_ActionsSelected.Blocks = new Array();
			spiHelper_ActionsSelected.Tags = new Array();
			if(spiHelper_isAdmin && !document.getElementById('spiHelper_noblock').checked){
				var tagmaster = document.getElementById('spiHelper_blocknoticemaster').checked;
				var tagsocks = document.getElementById('spiHelper_blocknoticesocks').checked;
				spiHelper_ActionsSelected.BlankTalk = document.getElementById('spiHelper_blanktalk').checked;
				spiHelper_ActionsSelected.TagMaster = document.getElementById('spiHelper_blocknoticemaster').checked;
				spiHelper_ActionsSelected.OverrideExisting = document.getElementById('spiHelper_override').checked;
				for(var i = 1; i <= spiHelper_usercount; i++){
					if(document.getElementById('spiHelper_block_doblock' + i).checked){
						var noticetype = false;
 
						if(tagmaster && document.getElementById('spiHelper_block_tag' + i).value.indexOf("master") != -1){
							noticetype = "master";
						}
						else if(tagsocks && document.getElementById('spiHelper_block_tag' + i).value == "blocked"){
							noticetype = "suspectsock";
						}
						else if(tagsocks && document.getElementById('spiHelper_block_tag' + i).value != ""){
							noticetype = "sock";
						}
 
						var item = {
								username : document.getElementById('spiHelper_block_username' + i).value,
								duration : document.getElementById('spiHelper_block_duration' + i).value,
								acb : document.getElementById('spiHelper_block_acb' + i).checked,
								ab  : document.getElementById('spiHelper_block_ab' + i).checked,
								ntp : document.getElementById('spiHelper_block_tp' + i).checked,
								nem : document.getElementById('spiHelper_block_email' + i).checked,
								tpn : noticetype
						};
 
						spiHelper_ActionsSelected.Blocks.push(item);
					}
					if(document.getElementById('spiHelper_block_tag' + i).value != ""){
						var item = {
								username : document.getElementById('spiHelper_block_username' + i).value,
								tag : document.getElementById('spiHelper_block_tag' + i).value,
						};
						spiHelper_ActionsSelected.Tags.push(item);
					}
				}
			}
			else {
				for(var i = 1; i <= spiHelper_usercount; i++){
					if(document.getElementById('spiHelper_block_tag' + i).value != ""){
						var item = {
								username : document.getElementById('spiHelper_block_username' + i).value,
								tag : document.getElementById('spiHelper_block_tag' + i).value,
						};
						spiHelper_ActionsSelected.Tags.push(item);
					}
				}
			}
		}
		if(spiHelper_ActionsSelected.Close){
			spiHelper_ActionsSelected.Close = document.getElementById('spiHelper_CloseCase').checked;
			spiHelper_ActionsSelected.CloseComment = document.getElementById('spiHelper_Close_Comment').value;
		}
		if(spiHelper_ActionsSelected.Archive){
			spiHelper_ActionsSelected.Archive = document.getElementById('spiHelper_ArchiveCase').checked;
			if(document.getElementById('spiHelper_ArchiveSingle') != null)
				spiHelper_ActionsSelected.ArchiveSingle = document.getElementById('spiHelper_ArchiveSingle').checked;
			else
				spiHelper_ActionsSelected.ArchiveSingle = true;
		}
		displayMessage('<ul id="spiHelper_status"></ul><ul id="spiHelper_finish"></ul>');
		document.getElementById('spiHelper_finish').innerHTML += '<span id="spiHelper_finished_wrapper"><span id="spiHelper_finished_main" style="display:none"><li id="spiHelper_done"><b>Done (<a href="/wiki/'+encodeURI(spiHelper_PageName)+'?action=purge" title="'+spiHelper_PageName+'">Reload page</a>)</b></li></span></span>';
		var token = spiHelper_getToken(true);
		var pagetext = spiHelper_getPageText(spiHelper_PageName, true);
		var editsummary = "";
 
		var spicasestatus_re = /\{\{\s*SPI case status\s*\|?\s*(\S*?)\s*\}\}/i;
		var result = spicasestatus_re.exec(pagetext);
		if(result == null){
			pagetext = pagetext.replace("=====", "\{\{SPI case status\}\}\n=====");
			result = spicasestatus_re.exec(pagetext);
		}
		var casestatustext = result[0], casestatus = result[1];
 
		if(spiHelper_ActionsSelected.CU_act){
			var CUAction = spiHelper_ActionsSelected.CUAction;
			var CUComment = spiHelper_ActionsSelected.CUComment;
			if(CUAction != 'noaction')
				casestatus = CUAction;
			if(CUAction == "checked"){
				editsummary = "Marking request as checked";
			}
			else if(CUAction == "inprogress"){
				if(!/\{\{Inprogress\}\}/i.test(CUComment))
					CUComment = "\{\{Inprogress\}\} - " + CUComment;
				editsummary = "Marking request in progress";
			}
			else if(CUAction == "decline"){
				if(!/\{\{(?:Decline|Decline-IP)\}\}/i.test(CUComment))
					CUComment = "\{\{Decline\}\} - " + CUComment;
				editsummary = "Declining checkuser";
			}
			else if(CUAction == "cudecline"){
				if(!/\{\{(?:CUdeclined|Cudecline|declined)\}\}/i.test(CUComment))
					CUComment = "\{\{Cudecline\}\} - " + CUComment;
				editsummary = "Declining checkuser";
			}
			else if(CUAction == "endorse"){
				if(!/\{\{(?:Endorse|Selfendorse)\}\}/i.test(CUComment))
					CUComment = "\{\{Endorse\}\} - " + CUComment;
				editsummary = "Endorsing for checkuser attention";
			}
			else if(CUAction == "moreinfo"){
				if(!/\{\{moreinfo\}\}/i.test(CUComment))
					CUComment = "\{\{moreinfo\}\} - " + CUComment;
				editsummary = "Requesting additional information";
			}
			else if(CUAction == "relist"){
				if(!/\{\{relisted\}\}/i.test(CUComment))
					CUComment = "\{\{relisted\}\} - " + CUComment;
				editsummary = "Relisting case for another check";
			}
			else if(CUAction == "hold" || CUAction == "cuhold"){
				if(!/\{\{onhold\}\}/i.test(CUComment))
					CUComment = "\{\{onhold\}\} - " + CUComment;
				editsummary = "Placing checkuser request on hold";
			}
 
			if(CUComment != ''){
				CUComment += " \~\~\~\~";
				if(pagetext.indexOf("\n----") == -1)
					pagetext += "\n----";
				pagetext = pagetext.replace(/\s*\n----/, '\n*' + CUComment + '\n----');
			}
		}
 
		if(spiHelper_ActionsSelected.CU_new){
			var CUComment = spiHelper_ActionsSelected.CUComment;
			var newtext = '\n*';
			if(spiHelper_ActionsSelected.CUSelf){
				casestatus = "endorse";
				editsummary = "Adding checkuser request (self-endorsed for checkuser attention)";
				newtext += "{" + "{CURequest}} " + " - {" + "{Selfendorse}} ";
			}
			else {
				casestatus = "CUrequest";
				editsummary = "Adding checkuser request";
				newtext += "{" + "{CURequest}} ";
			}
			if(CUComment != '')
				newtext += "- ";
			newtext += CUComment + " \~\~\~\~";
			if(pagetext.indexOf("\n----") == -1)
				pagetext += "\n----";
			pagetext = pagetext.replace(/\s*\n----/, newtext + '\n----');
		}
		if(spiHelper_ActionsSelected.Block){
			var sockmaster = "";
			var sockcount = 0;
			for(var i = 0; i < spiHelper_ActionsSelected.Tags.length; i++){
				var isIP = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(spiHelper_ActionsSelected.Tags[i].username);
				if(isIP) continue; // do not support tagging IPs
				if(spiHelper_ActionsSelected.Tags[i].tag.indexOf("master") != -1){
					sockmaster = spiHelper_ActionsSelected.Tags[i].username;
					continue;
				}
				sockcount ++;
			}
			if(sockcount > 0 && sockmaster == "") sockmaster = prompt("Please enter the name of the sockmaster: ", spiHelper_CaseName);
 
			if(spiHelper_isAdmin){
				for(var i = 0; i < spiHelper_ActionsSelected.Blocks.length; i++){
					var isIP = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(spiHelper_ActionsSelected.Blocks[i].username);
					spiHelper_blockUser(
							spiHelper_ActionsSelected.Blocks[i].username,
							spiHelper_ActionsSelected.Blocks[i].duration,
							token,
							"Abusing [[WP:SOCK|multiple accounts]]: Please see: [[" + spiHelper_PageName + "]]",
							spiHelper_ActionsSelected.OverrideExisting,
							(isIP ? spiHelper_ActionsSelected.Blocks[i].ab : false),
							spiHelper_ActionsSelected.Blocks[i].acb,
							(isIP ? false : spiHelper_ActionsSelected.Blocks[i].ab),
							spiHelper_ActionsSelected.Blocks[i].ntp,
							spiHelper_ActionsSelected.Blocks[i].nem);
					if(spiHelper_ActionsSelected.TagMaster && spiHelper_ActionsSelected.Blocks[i].username == sockmaster)
						spiHelper_ActionsSelected.Blocks[i].tpn = "master";
					if(sockmaster != null && sockmaster != "" && spiHelper_ActionsSelected.Blocks[i].tpn){
						var newtext = '';
						if(spiHelper_ActionsSelected.Blocks[i].tpn.indexOf("sock") != -1){
							newtext = '== Blocked as a sockpuppet ==\n{' + '{subst:sockblock|master=' + sockmaster;
							if(spiHelper_ActionsSelected.Blocks[i].ntp)
								newtext += '|notalk=yes';
							if(spiHelper_ActionsSelected.Blocks[i].tpn.indexOf("suspect") != -1)
								newtext += '|suspected=yes';
							newtext += '|sig=yes}}';
						}
						else {
							newtext = '== Blocked for sockpuppetry ==\n{' + '{subst:sockblock|masterblock=yes|period=' + spiHelper_ActionsSelected.Blocks[i].duration;
							if(spiHelper_ActionsSelected.Blocks[i].ntp)
								newtext += '|notalk=yes';
							newtext += '|evidence= [[' + spiHelper_PageName + ']]|sig=yes}}';
						}
						if(!spiHelper_ActionsSelected.BlankTalk){
							var oldtext = spiHelper_getPageText("User talk:" + spiHelper_ActionsSelected.Blocks[i].username, true);
							if(oldtext != "")
								newtext = oldtext + '\n' + newtext;	
						}
						spiHelper_editPage("User talk:" + spiHelper_ActionsSelected.Blocks[i].username,
								newtext, token, "Adding sockpuppetry block notice per [[" + spiHelper_PageName+ "]]", false, null, "nochange");
					}
				}
			}
			if(sockmaster != null && sockmaster != ""){
				for(var i = 0; i < spiHelper_ActionsSelected.Tags.length; i++){
					var isIP = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(spiHelper_ActionsSelected.Tags[i].username);
					if(isIP) continue; // do not support tagging IPs
					var tagtext = "";
					if(spiHelper_ActionsSelected.Tags[i].tag == "blocked")
						tagtext = "{" + "{sockpuppet|1=" + sockmaster + "|2=blocked}}";
					else if(spiHelper_ActionsSelected.Tags[i].tag == "proven")
						tagtext = "{" + "{sockpuppet|1=" + sockmaster + "|2=proven}}";
					else if(spiHelper_ActionsSelected.Tags[i].tag == "confirmed")
						tagtext = "{" + "{sockpuppet|1=" + sockmaster + "|2=confirmed}}";
					else if(spiHelper_ActionsSelected.Tags[i].tag == "master")
						tagtext = "{" + "{sockmaster|blocked}}";
					else if(spiHelper_ActionsSelected.Tags[i].tag == "sockmasterchecked")
						tagtext = "{" + "{sockmaster|blocked|checked=yes}}";
					spiHelper_editPage("User:" + spiHelper_ActionsSelected.Tags[i].username, tagtext, token, "Adding sockpuppetry tag per [[" + spiHelper_PageName+ "]]", false, null, "nochange");
				}
			}
		}
		if(spiHelper_ActionsSelected.Note){
			if(pagetext.indexOf("\n----") == -1)
				pagetext += "\n----";
			if(spiHelper_ActionsSelected.Comment != ''){
				var newtext = '\n*';
				if(spiHelper_ActionsSelected.CommentType != 'none')
					newtext += "\{\{" + spiHelper_ActionsSelected.CommentType + "\}\} ";
				newtext += spiHelper_ActionsSelected.Comment + " \~\~\~\~\n";
				pagetext = pagetext.replace(/\s*\n----/, newtext + '----');
				if(editsummary != "")
					editsummary += ", comment";
				else
					editsummary = "Comment";
			}
 
		}
		if(spiHelper_ActionsSelected.Close){
			if(pagetext.indexOf("\n----") == -1)
				pagetext += "\n----";
			var newtext = '\n';
			if(spiHelper_ActionsSelected.CloseComment != '')
				newtext += '*' + spiHelper_ActionsSelected.CloseComment + " \~\~\~\~\n";
			casestatus = 'close';
			pagetext = pagetext.replace(/\s*\n----/, newtext + '----');
			if(editsummary != "")
				editsummary += ", marking case as closed";
			else
				editsummary = "Marking case as closed";
		}
 
		pagetext = pagetext.replace(casestatustext, "\{\{SPI case status|" + casestatus + "\}\}");
		casestatustext = "\{\{SPI case status|" + casestatus + "\}\}";
 
		if(spiHelper_ActionsSelected.Archive){
			if(spiHelper_ActionsSelected.ArchiveSingle){
				spiHelper_archiveCase(pagetext, editsummary, token);
			}
			else{
				var onComplete = function () {
					spiHelper_archiveCase(pagetext, "", token);
					document.getElementById('spiHelper_finished_main').style.display = '';
				};
				spiHelper_editPage(spiHelper_PageName, pagetext, token, editsummary, false, onComplete, spiHelper_watchCase);
			}
		}
		else
			spiHelper_editPage(spiHelper_PageName, pagetext, token, editsummary, false, null, spiHelper_watchCase);
		if(!spiHelper_ActionsSelected.Archive || spiHelper_ActionsSelected.ArchiveSingle)
			document.getElementById('spiHelper_finished_main').style.display = '';
	}
 
	function spiHelper_getToken(show) {
		return mw.user.tokens.get('editToken');
	}
 
	function spiHelper_archiveCase(pagetext, editsummary, token){
		var spicasestatus_re = /\{\{\s*SPI case status\s*\|?\s*(\S*?)\s*\}\}/gi;
		pagetext = pagetext.replace(spicasestatus_re, '');
		var section_re = /=====[^=]*=====/;
		var header = pagetext.substring(0, pagetext.search(section_re));
		header = header.replace(/<!--[\s\S]*?-->/g, '').trim();
		var newarchivetext = pagetext.substring(pagetext.search(section_re));
		var archivename = spiHelper_PageName + "/Archive";
		if(editsummary != "")
			editsummary += ", archiving case to [[" + archivename + "]]";
		else
			editsummary = "Archiving case to [[" + archivename + "]]";
		spiHelper_editPage(spiHelper_PageName, header, token, editsummary, false, null, spiHelper_watchCase);
		var archivetext = spiHelper_getPageText(archivename, true);
		if(archivetext == "")
			archivetext = "__" + "TOC__\n\{\{SPIarchive notice|1=" + spiHelper_CaseName + "\}\}\n\{\{SPIpriorcases\}\}";
		else
			archivetext = archivetext.replace(/<br\s*\/>\s*\{\{SPIpriorcases\}\}/gi, "\n\{\{SPIpriorcases}}"); // fmt fix whenever needed.
		archivetext += "\n" + newarchivetext;
		spiHelper_editPage(archivename, archivetext, token, "Archiving case from [[" + spiHelper_PageName + "]]", false, null, spiHelper_watchArchive);
	}
 
	function spiHelper_editPage(title, newtext, token, summary, createonly, onComplete, watch) {
		document.getElementById('spiHelper_finished_wrapper').innerHTML = '<span id="spiHelper_AJAX_finished_'+spiHelper_AJAXnumber+'" style="display:none">' + document.getElementById('spiHelper_finished_wrapper').innerHTML + '</span>';
		var func_id = spiHelper_AJAXnumber;
		spiHelper_AJAXnumber++;
		document.getElementById('spiHelper_status').innerHTML += '<li id="spiHelper_edit'+func_id+'">Editing <a href="/wiki/'+encodeURI(title)+'" title="'+title+'">'+title+'</a></li>';
		var req = sajax_init_object();
		var params = "action=edit&format=json&token="+encodeURIComponent(token)+"&title="+encodeURIComponent(title)+"&text="+encodeURIComponent(newtext)+"&notminor=1&watchlist="+encodeURIComponent(watch)+"&summary="+encodeURIComponent(summary);
		if(createonly)
			params += "&createonly=1";
		url = wgScriptPath + "/api.php";
		req.open("POST", url, true);
		req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		req.setRequestHeader("Content-length", params.length);
		req.setRequestHeader("Connection", "close");
		req.onreadystatechange = function() {
			if(req.readyState == 4 && req.status == 200) {
				response = eval('(' + req.responseText + ')');
				try {
					if (response['edit']['result'] == "Success") {
						document.getElementById('spiHelper_edit'+func_id).innerHTML = 'Saved <a href="/wiki/'+encodeURI(title)+'" title="'+title+'">'+title+'</a>';
						if(onComplete != null)
							onComplete();
					} else {
						document.getElementById('spiHelper_edit'+func_id).innerHTML = '<div style="color:red"><b>Edit failed on <a href="/wiki/'+encodeURI(title)+'" title="'+title+'">'+title+'</a></b></div>. Error info:' +response['error']['code'] + ' : ' + response['error']['info'];
					}
				}
				catch(err) {
					document.getElementById('spiHelper_edit'+func_id).innerHTML = '<div style="color:red"><b>Edit failed on <a href="/wiki/'+encodeURI(title)+'" title="'+title+'">'+title+'</a></b></div>'; alert(req.responseText);
				}
				document.getElementById('spiHelper_AJAX_finished_'+func_id).style.display = '';
				delete req;
			}
		};
		req.send(params);
	}
 
	function spiHelper_blockUser(user, duration, token, reason, reblock, anononly, accountcreation, autoblock, talkpage, email ) {
		document.getElementById('spiHelper_finished_wrapper').innerHTML = '<span id="spiHelper_AJAX_finished_'+spiHelper_AJAXnumber+'" style="display:none">' + document.getElementById('spiHelper_finished_wrapper').innerHTML + '</span>';
		var func_id = spiHelper_AJAXnumber;
		spiHelper_AJAXnumber++;
		document.getElementById('spiHelper_status').innerHTML += '<li id="spiHelper_block'+escape(user)+'">Blocking <a href="/wiki/User:'+encodeURI(user)+'" title="User:'+user+'">'+user+'</a></li>';
		var req = sajax_init_object();
		var params = "action=block&format=json&token="+encodeURIComponent(token)+"&user="+encodeURIComponent(user)+"&expiry="+encodeURIComponent(duration)+"&reason="+encodeURIComponent(reason);
		if( reblock ) params += "&reblock=1";
		if( anononly ) params += "&anononly=1";
		if( accountcreation  ) params += "&nocreate=1";
		if( autoblock ) params += "&autoblock=1";
		if( !talkpage ) params += "&allowusertalk=1";
		if( email ) params += "&noemail=1";
		url = wgScriptPath + "/api.php";
		req.open("POST", url, true);
		req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		req.setRequestHeader("Content-length", params.length);
		req.setRequestHeader("Connection", "close");
		req.onreadystatechange = function() {
			if(req.readyState == 4 && req.status == 200) {
				response = eval('(' + req.responseText + ')');
				try {
					if (response['block']) {
						document.getElementById('spiHelper_block'+escape(user)).innerHTML = 'Blocked <a href="/wiki/User:'+encodeURI(user)+'" title="User:'+user+'">'+user+'</a>';
					} else {
						document.getElementById('spiHelper_block'+escape(user)).innerHTML = '<div style="color:red"><b>Block failed on <a href="/wiki/User:'+encodeURI(user)+'" title="User:'+user+'">'+user+'</a></b></div>. Error info:' +response['error']['code'] + ' : ' + response['error']['info'];
					}
				}
				catch(err) {
					document.getElementById('spiHelper_block'+escape(user)).innerHTML = '<div style="color:red"><b>Blockfailed on <a href="/wiki/User:'+encodeURI(user)+'" title="User:'+user+'">'+user+'</a></b></div>';
				}
				document.getElementById('spiHelper_AJAX_finished_'+func_id).style.display = '';
				delete req;
			}
		};
		req.send(params);
	}
 
	function escapeHtmlChars(original){
		return original
		.replace(/&/g, "&amp;")
		.replace(/</g, "&lt;")
		.replace(/>/g, "&gt;")
		.replace(/"/g, "&quot;")
		.replace(/'/g, "&#039;");
	}
	function spiHelper_generateBlockTableLine(name, defaultblock, id, admin){
		var row = '<tr>';
		row += '<td><input type="text" name="spiHelper_block_username' + id + '" id="spiHelper_block_username' + id + 
		'" value="' + escapeHtmlChars(name)  + '" /></td>';
		if(admin){
			row += '<td><input type="checkbox" name="spiHelper_block_doblock' + id + '" id="spiHelper_block_doblock' + id + 
			'" ' + (defaultblock ? 'checked="checked" ' : '') + '/></td>';
			row += '<td><input type="text" name="spiHelper_block_duration' + id + '" id="spiHelper_block_duration' + id + 
			'" value="indefinite" /></td>';
			row += '<td><input type="checkbox" name="spiHelper_block_acb' + id + '" id="spiHelper_block_acb' + id + '" checked="checked" /></td>';
			row += '<td><input type="checkbox" name="spiHelper_block_ab' + id + '" id="spiHelper_block_ab' + id + '" checked="checked" /></td>';
			row += '<td><input type="checkbox" name="spiHelper_block_tp' + id + '" id="spiHelper_block_tp' + id + '" /></td>';
			row += '<td><input type="checkbox" name="spiHelper_block_email' + id + '" id="spiHelper_block_email' + id + '" /></td>';
		}
		row += '<td><select name="spiHelper_block_tag' + id + '" id="spiHelper_block_tag' + id + '" >' +
		'<option value=""> None </option>' +
		'<option value="blocked"> Suspected sock </option>' +
		'<option value="proven"> Proven sock </option>' +
		'<option value="confirmed"> CU confirmed sock </option>' +
		'<option value="master"> Blocked master </option>' +
		'<option value="sockmasterchecked"> CU confirmed master </option>' +
		'</select></td></tr>';
		return row;
	}
 
	function spiHelper_getPageText(title, show) {
		var func_id = spiHelper_AJAXnumber;
		spiHelper_AJAXnumber++;
		if(show){
			document.getElementById('spiHelper_status').innerHTML += '<li id="spiHelper_get'+func_id+'">Getting <a href="/wiki/'+encodeURI(title)+'" title="'+title+'">'+title+'</a></li>';
		}
		var req = sajax_init_object();
		req.open("GET", wgScriptPath + "/api.php?action=query&prop=revisions&rvprop=content&format=json&indexpageids=1&titles="+encodeURIComponent(title), false);
		req.send(null);
		var response = eval('(' + req.responseText + ')');
		pageid = response['query']['pageids'][0];
		if (pageid == "-1") {
			if(show){
				document.getElementById('spiHelper_get'+func_id).innerHTML = '<a class="new" href="/wiki/'+encodeURI(title)+'" title="'+title+'">'+title+'</a> does not exist';
			}
			delete req;
			return '';
		}
		pagetext = response['query']['pages'][pageid]['revisions'][0]['*'];
		delete req;
		if(show){
			document.getElementById('spiHelper_get'+func_id).innerHTML = 'Got <a href="/wiki/'+encodeURI(title)+'" title="'+title+'">'+title+'</a>';
		}
		return pagetext;
	}
 
	function spiHelper_generateSelect(title, options, onchange){
		var text = '<select name="' + title + '" id="' + title +'" ';
		if(onchange != null)
			text += 'onchange = "' + onchange + '" ';
		text+= '>';
		for(var i = 0; i < options.length; i ++){
			var o = options[i];
			text += '<option value="' + o.value + '" ';
			if(o.selected)
				text += 'selected="selected" ';
			text += '>' + o.label + '</option>';
		}
		text += "</select>";
		return text;
	}
 
	function spiHelper_oneClickArchive(){
		var pagetext = spiHelper_getPageText(spiHelper_PageName, false);
		if(!/=====[^=]*=====/.test(pagetext)){
			alert("Looks like the page has been archived already.");
			return;
		}
		displayMessage('<ul id="spiHelper_status"></ul><ul id="spiHelper_finish"></ul>');
		document.getElementById('spiHelper_finish').innerHTML += '<span id="spiHelper_finished_wrapper"><span id="spiHelper_finished_main" style="display:none"><li id="spiHelper_done"><b>Done (<a href="/wiki/'+encodeURI(spiHelper_PageName)+'?action=purge" title="'+spiHelper_PageName+'">Reload page</a>)</b></li></span></span>';
		var token = spiHelper_getToken(true);
		spiHelper_archiveCase(pagetext, '', token);
		document.getElementById('spiHelper_finished_main').style.display = '';
	}
 
	function spiHelper_addLink() {
		mw.util.addPortletLink("p-cactions", "javascript:spiHelper_init()", "SPI", "ca-spiHelper", "SPI");
		if(wgCategories.toString().indexOf('SPI cases awaiting archive') != -1)
			mw.util.addPortletLink("p-cactions", "javascript:spiHelper_oneClickArchive()", "SPI-Archive", "ca-spiHelperArchive", "SPI-Archive");
	}
	addOnloadHook(spiHelper_addLink);
}
function markBlocked( container ) {
 
var contentLinks = container ? $(container).find('a') : mw.util.$content.find('a').add('#ca-nstab-user a')
 
mw.util.addCSS('\
.user-blocked-temp{'   + (window.mbTempStyle||'opacity: 0.7; text-decoration: line-through') + '}\
.user-blocked-indef{'  + (window.mbIndefStyle||'opacity: 0.4; font-style: italic; text-decoration: line-through') + '}\
.user-blocked-tipbox{' + (window.mbTipBoxStyle||'font-size:smaller; background:#FFFFF0; border:1px solid #FEA; padding:0 0.3em; color:#AAA') + '}\
')
var mbTooltip =  window.mbTooltip || '; blocked ($1) by $2: $3 ($4 ago)'
 
//get all aliases for user: & user_talk:
var userNS = []
for( var ns in mw.config.get( 'wgNamespaceIds' ) ) 
  if( mw.config.get( 'wgNamespaceIds' )[ns] == 2 || mw.config.get( 'wgNamespaceIds' )[ns] == 3 ) 
    userNS.push( ns.replace(/_/g, ' ') + ':' )
 
//RegExp  for all titles that are  User:| User_talk: |  Special:Contributions/ (localized) | Special:Contributions/ (for userscripts)
var userTitleRX = new RegExp('^'
 + '(' + userNS.join('|')
 + '|Служебная:Вклад\\/|Special:Contributions\\/'
 + ')'
 + '([^\\/#]+)$', 'i')
 
//RegExp for links
var articleRX = new RegExp( '^' + mw.config.get( 'wgArticlePath' ).replace('$1', '') + '([^#]+)' )
var scriptRX =  new RegExp( '^' + mw.config.get( 'wgScript' ) + '\\?title=([^#&]+)' )
 
var userLinks = {}
var url, ma, pgTitle
 
 
//find all "user" links and save them in userLinks : { 'users': [<link1>, <link2>, ...], 'user2': [<link3>, <link3>, ...], ... }
contentLinks.each(function(i, lnk){
   url = $(lnk).attr('href')
   if( !url || url.charAt(0) != '/' ) return
   else if( ma = articleRX.exec(url) ) pgTitle = ma[1]
   else if( ma =  scriptRX.exec(url) ) pgTitle = ma[1]
   else return
   pgTitle = decodeURIComponent(pgTitle).replace(/_/g, ' ')
   user = userTitleRX.exec(pgTitle)
   if( !user ) return
   user = user[2]
   $(lnk).addClass('userlink')
   if ( !userLinks[user] ) userLinks[user] = []
   userLinks[user].push(lnk)
})
 
 
//convert users into array
var users = []
for (var u in userLinks) users.push(u)
if( users.length == 0 ) return
 
//API request
var serverTime, apiRequests = 0
var waitingCSS = mw.util.addCSS('a.userlink {opacity:' + (window.mbLoadingOpacity||0.85) + '}')
while( users.length > 0 ){
  apiRequests++
 $.post( 
    mw.util.wikiScript('api') + '?format=json&action=query',
    { list: 'blocks', bklimit: 100, bkusers: users.splice(0,50).join('|'),
      bkprop: 'user|by|timestamp|expiry|reason' }, //no need for 'id|flags'
    markLinks
  )
}
 
return //the end
 
 
 
//callback: receive data and mark links
function markLinks(resp, status, xhr){
 
  serverTime = new Date( xhr.getResponseHeader('Date') )
  var list, blk, tip, links, lnk
  if( !resp || !(list=resp.query) || !(list=list.blocks) ) return
 
  for( var i=0; i<list.length; i++){
    blk = list[i]
    if( /^in/.test(blk.expiry) ){
      clss = 'user-blocked-indef'
      blTime = blk.expiry
    }else{
      clss = 'user-blocked-temp'
      blTime = inHours ( parseTS(blk.expiry) - parseTS(blk.timestamp) )
    }
    tip = mbTooltip.replace('$1', blTime).replace('$2', blk.by).replace('$3', blk.reason)
          .replace('$4', inHours ( serverTime - parseTS(blk.timestamp) ) )
    links = userLinks[blk.user]
    for (var k=0; k<links.length; k++){
       lnk = $(links[k]).addClass(clss)
       if( window.mbTipBox )
         $('<span class=user-blocked-tipbox>#</span>').attr('title', tip).insertBefore(lnk)
       else
         lnk.attr( 'title', lnk.attr('title') + tip )
    }
  }
 
  if( --apiRequests == 0 ){ //last response
    waitingCSS.disabled = true
    $('#ca-showblocks').parent().remove() // remove added portlet link
  }
 
}
 
 
//--------AUX functions
 
//20081226220605  or  2008-01-26T06:34:19Z   -> date
function parseTS(ts){
 var m = ts.replace(/\D/g,'').match(/(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/)
 return new Date ( Date.UTC(m[1], m[2]-1, m[3], m[4], m[5], m[6]) )
}
 
function inHours(ms){ //milliseconds -> "2:30" or 5,06d or 21d
 var mm = Math.floor(ms/60000)
 if( !mm ) return Math.floor(ms/1000)+'s'
 var hh = Math.floor(mm/60); mm = mm % 60
 var dd = Math.floor(hh/24); hh = hh % 24
 if (dd) return dd + (dd<10?'.'+zz(hh):'') + 'd'
 else return hh + ':' + zz(mm)
}
 
function zz(v){ // 6 -> '06'
 if( v <= 9 ) v = '0' + v
 return v
}
 
 
}// -- end of main function
 
 
 
 
 
//start on some pages
switch( mw.config.get( 'wgAction' ) ){
 case 'edit':
 case 'submit':
   break
 case 'view':
   if( mw.config.get( 'wgNamespaceNumber' ) == 0 ) break
   //otherwise continue with default
 default: //  'history', 'purge'
  $(function(){
     if( window.mbNoAutoStart )
       mw.util.addPortletLink('p-cactions', 'javascript:markBlocked()', 'XX', 'ca-showblocks')
     else
       markBlocked()
  })
}
// based on http://en.wikipedia.org/wiki/User:Fran Rogers/dimorphism.js
// and on http://en.wikipedia.org/wiki/User:Splarka/sysopdectector.js
 
function UserinfoJsFormatQty(qty, singular, plural) {
    return String(qty).replace(/\d{1,3}(?=(\d{3})+(?!\d))/g, "$&,") + "\u00a0" + (qty == 1 ? singular : plural);
}
 
function UserinfoJsFormatDateRel(old) {
// The code below requires the computer's clock to be set correctly.
            var age = new Date().getTime() - old.getTime();
            var ageNumber, ageRemainder, ageWords;
            if(age < 60000) {
                // less than one minute old
                ageNumber = Math.floor(age / 1000);
                ageWords = UserinfoJsFormatQty(ageNumber, "second", "seconds");
            } else if(age < 3600000) {
                // less than one hour old
                ageNumber = Math.floor(age / 60000);
                ageWords = UserinfoJsFormatQty(ageNumber, "minute", "minutes");
            } else if(age < 86400000) {
                // less than one day old
                ageNumber = Math.floor(age / 3600000);
                ageWords = UserinfoJsFormatQty(ageNumber, "hour", "hours");
                ageRemainder = Math.floor((age - ageNumber * 3600000) / 60000);
            } else if(age < 604800000) {
                // less than one week old
                ageNumber = Math.floor(age / 86400000);
                ageWords = UserinfoJsFormatQty(ageNumber, "day", "days");
            } else if(age < 2592000000) {
                // less than one month old
                ageNumber = Math.floor(age / 604800000);
                ageWords = UserinfoJsFormatQty(ageNumber, "week", "weeks");
            } else if(age < 31536000000) {
                // less than one year old
                ageNumber = Math.floor(age / 2592000000);
                ageWords = UserinfoJsFormatQty(ageNumber, "month", "months");
            } else {
                // one year or older
                ageNumber = Math.floor(age / 31536000000);
                ageWords = UserinfoJsFormatQty(ageNumber, "year", "years");
                ageRemainder =
                    Math.floor((age - ageNumber * 31536000000) / 2592000000);
                if(ageRemainder) {
                    ageWords += " " +
                        UserinfoJsFormatQty(ageRemainder, "month", "months");
                }
           }
           return ageWords;
}
 
// If on a user or user talk page, and not a subpage...
if((mw.config.get("wgNamespaceNumber") == 2 || mw.config.get("wgNamespaceNumber") == 3) && !(/\//.test(mw.config.get("wgTitle")))) {   
    // add a hook to...
    mw.loader.using( ['es5-shim', 'mediawiki.util'], function() { $(function(){
        // Request the user's information from the API.
        // Note that this is allowed to be up to 5 minutes old.
        var et = encodeURIComponent(mw.config.get("wgTitle"));
 
        $.getJSON(mw.config.get("wgScriptPath") + "/api.php?format=json&action=query&list=users|usercontribs&usprop=blockinfo|editcount|gender|registration|groups&uclimit=1&ucprop=timestamp&ususers=" + et + "&ucuser=" + et + "&meta=allmessages&amfilter=grouppage")
        .done(function(query) {
            // When response arrives extract the information we need.
            if(!query.query) { return; } // Suggested by Gary King to avoid JS errors --PS 2010-08-25
            query = query.query;
            var user, invalid, missing, groups, groupPages={}, editcount, registration, blocked, gender, lastEdited;
            try {
                user = query.users[0];
                invalid = typeof user.invalid != "undefined";
                missing = typeof user.missing != "undefined";
                groups = (typeof user.groups == "object") ? user.groups : [];
                editcount = (typeof user.editcount == "number") ? user.editcount : null;
                registration = (typeof user.registration == "string") ?
                    new Date(user.registration) : null;
                blocked = typeof user.blockedby != "undefined";
                gender = (typeof user.gender == "string") ? user.gender : null;
                lastEdited = (typeof query.usercontribs[0] == "object") &&
                    (typeof query.usercontribs[0].timestamp == "string") ?
                    new Date(query.usercontribs[0].timestamp) : null;
                for (var am=0; am<query.allmessages.length; am++) {
                	groupPages[query.allmessages[am]["name"].replace("grouppage-","")] = query.allmessages[am]["*"].replace("{{ns:project}}:","Project:");
                }
            } catch(e) {
                return; // Not much to do if the server is returning an error (e.g. if the username is malformed).
            }
 
            // Format the information for on-screen display
 
            var statusText = "";
            var ipUser = false;
            var ipv4User = false;
            var ipv6User = false;
 
            // User status
            if(blocked) {
                statusText += "<a href=\"" + mw.config.get("wgScriptPath") +
                    "/index.php?title=Special:Log&amp;page=" + 
                    encodeURIComponent(mw.config.get("wgFormattedNamespaces")[2] + ":" + user.name) +
                    "&amp;type=block\">blocked</a> ";
            }
            if (missing) {
                statusText += "username not registered";
            } else if (invalid) {
                ipv4User = mw.util.isIPv4Address(user.name);
                ipv6User = mw.util.isIPv6Address(user.name);
                ipUser = ipv4User || ipv6User;
                if (ipv4User) {
                    statusText += "anonymous IPv4 user";
                } else if (ipv6User) {
                    statusText += "anonymous IPv6 user";
                } else {
                    statusText += "invalid username";
                }
            } else {
                // User is registered and may be in a privileged group. Below we have a list of user groups.
                // Only need the ones different from the software's name (or ones to exclude), though.
                var friendlyGroupNames = {
                    // Exclude implicit user group information provided by MW 1.17 --PS 2010-02-17
                    '*': false,
                    'user': false,
                    'autoconfirmed': false,
                    sysop: "administrator",
                    accountcreator: "account creator",
                    'import': "importer",
                    transwiki: "transwiki importer",
                    'ipblock-exempt': "IP block exemption",
                    oversight: "oversighter",
                    confirmed: "confirmed user",
                    abusefilter: "edit filter manager",
                    autoreviewer: "autopatrolled user", // Group has been renamed --PS 2010-07-06
                    epcoordinator: "Education Program course coordinator",
                    epcampus: "Education Program campus volunteer",
                    eponline: "Education Program online volunteer",
                    filemover: "file mover",
                    'massmessage-sender': "mass message sender",
                    templateeditor: "template editor"
                };
 
                var friendlyGroups = [];
                for(var i = 0; i < groups.length; ++i) {
                    var s = groups[i];
                    if(friendlyGroupNames.hasOwnProperty(s)) {
                        if(friendlyGroupNames[s]) {
                            friendlyGroups.push("<a href='/wiki/" + encodeURIComponent( groupPages[s] ) + "'>" + friendlyGroupNames[s] + "</a>");
                        }
                    } else {
                        friendlyGroups.push("<a href='/wiki/" + encodeURIComponent( groupPages[s] ) + "'>" + s + "</a>");
                    }
                }
                switch(friendlyGroups.length) {
                    case 0:
                        // User not in a privileged group
                        // Changed to "registered user" by request of [[User:Svanslyck]]
                        // --PS 2010-05-16
 
                        // statusText += "user";
                        if(blocked) {
                            statusText += "user";
                        } else {
                            statusText += "registered user";
                        }
                        break;
                    case 1:
                        statusText += friendlyGroups[0];
                        break;
                    case 2:
                        statusText += friendlyGroups[0] + " and " + friendlyGroups[1];
                        break;
                    default:
                        statusText += friendlyGroups.slice(0, -1).join(", ") +
                            ", and " + friendlyGroups[friendlyGroups.length - 1];
                        break;
                }
            }
 
            // Registration date
            if(registration) {
            	var firstLoggedUser = new Date("22:16, 7 September 2005"); // When the [[Special:Log/newusers]] was first activated
            	if(registration >= firstLoggedUser) {
            		statusText += ", <a href='" + mw.config.get("wgScriptPath") +
                    "/index.php?title=Special:Log&amp;type=newusers&amp;dir=prev&amp;limit=1&amp;user=" +
                    et + "'>" + UserinfoJsFormatDateRel(registration) + "</a> old";
            	} else {
            		statusText += ", <a href='" + mw.config.get("wgScriptPath") +
                    "/index.php?title=Special:ListUsers&amp;limit=1&amp;username=" +
                    et + "'>" + UserinfoJsFormatDateRel(registration) + "</a> old";
            	}
            }
 
            // Edit count
            if(editcount !== null) {
                statusText += ", with " +
                    "<a href=\"//tools.wmflabs.org/xtools-ec/?user=" +
                    encodeURIComponent(user.name) +
                    "&amp;project=en.wikipedia.org&amp;uselang=en\">" +
                    UserinfoJsFormatQty(editcount, "edit", "edits") + "</a>";
            }
 
            // Prefix status text with correct article
            if("AEIOaeio".indexOf(statusText.charAt(statusText.indexOf('>')+1)) >= 0) {
                statusText = "An " + statusText;
            } else {
                statusText = "A " + statusText;
            }
 
            // Add full stop to status text
            statusText += ".";
 
            // Last edited --PS 2010-06-27
            // Added link to contributions page --PS 2010-07-03
            if(lastEdited) {
                statusText += " Last edited <a href=\"" + mw.config.get("wgArticlePath").replace("$1", "Special:Contributions/" + encodeURIComponent(user.name)) + "\">" + UserinfoJsFormatDateRel(lastEdited) + " ago</a>.";
            }
 
            // Show the correct gender symbol
            var fh = document.getElementById("firstHeading") ||
                document.getElementById("section-0");
            // Add classes for blocked, registered, and anonymous users
            var newClasses = [];
            if(blocked) {
                newClasses.push("ps-blocked");
            }
            if(ipUser) {
                newClasses.push("ps-anonymous");
            } else if(invalid) {
                newClasses.push("ps-invalid");
            } else {
                newClasses.push("ps-registered");
            }
            fh.className += (fh.className.length ? " " : "") + groups.map(function(s) {
                return "ps-group-" + s;
            }).concat(newClasses).join(" ");
            var genderSpan = document.createElement("span");
            genderSpan.id = "ps-gender-" + (gender || "unknown");
            genderSpan.style.paddingLeft = "0.25em";
            genderSpan.style.fontFamily = '"Lucida Grande", "Lucida Sans Unicode", "sans-serif"';
            genderSpan.style.fontSize = "75%";
            var genderSymbol;
            switch(gender) {
                case "male": genderSymbol = "\u2642"; break;
                case "female": genderSymbol = "\u2640"; break;
                default: genderSymbol = ""; break;
            }
            genderSpan.appendChild(document.createTextNode(genderSymbol));
            fh.appendChild(genderSpan);
 
            // Now show the other information. Non-standard? Yes, but it gets the job done.
            // Add a period after the tagline when doing so. --PS 2010-07-03
 
            var ss = document.getElementById("siteSub");
            if(!ss) {
                ss = document.createElement("div");
                ss.id = "siteSub";
                ss.innerHTML = "From Wikipedia, the free encyclopedia";
                var bc = document.getElementById("bodyContent");
                bc.insertBefore(ss, bc.firstChild);
            }
            ss.innerHTML = '<span id="ps-userinfo">' + statusText + '</span> ' + ss.innerHTML + '.';
            ss.style.display = "block";
            });
    }); });
}
importScript('User:Lourdes/PageCuration.js'); // Linkback: [[User:Lourdes/PageCuration.js]]