User:Agent Isai/poweruser.js

/** @Description: @Author: Steef389 - 2010-2013 by de:User:Steef389/js/user_status.js; @Author: Perhelion - adapted 2016, modified & simplified & fallback language @Revision: 20:17, 2 October 2018 (UTC) See also de:Benutzer:Schnark/js/letzteredit, de:Benutzer:Schnark/js/extratabs /* eslint indent:["error","tab",{"outerIIFEBody":0}], one-var:0, vars-on-top:0, camelcase:0, no-underscore-dangle:0 */ /* global jQuery, mediaWiki, indexedDB*/ (function ($, mw) { 'use strict'; // var us = {}; var project = window.project || mw.config.get('wgDBname'); var msg, i18n = {	en: {		noReason: 'reason removed',		blockCmt: 'no block comment',		never: 'never',		not: ' not ',		block: 'blocked',		and: '$1 and$2',		// load : "loading…",		count: 'Count',		noedit: 'None (only deleted contributions?)',		// noav : "not available",		nodb: '‹not in database›',		noGrp: 'no extended group',		dates: ['years', 'months', 'days', 'hours', 'minutes', 'seconds'],		date: ['year', 'month', 'day', 'hour', 'minute', 'second'],		nosec: 'less than one ',		curtimeDiff: ' Locale time difference to server time in s: ',		thxGn: 'given',		thxRd: 'received',		nova: 'new',		ago: '$1 ago',		blocklog: 'Block log',		// Title-lines		contrib: 'Edits: ',		usub: 'Subpages⬇',		thxGvng: 'Thanksgivings: ',		reviews: 'Active reviews: ',		regdate: 'Registration: ',		laedit: 'Last edited: ', lala: 'Last log activity', fiedit: 'First edit: ', blocks: 'Block-status: ', loGrp: 'Local user-groups: ', glGrp: 'Global user-groups: ', blockEnd: 'Block-end: ', blocker: 'Blocker: ', blockReason: 'Block-reason: ' },	de: { noReason: 'Begründung entfernt', blockCmt: 'kein Sperrkommentar', never: 'nie', not: ' nicht ', block: 'gesperrt', and: '$1 und$2', // load : "wird geladen…", count: 'Anzahl', noedit: 'Keiner (nur gelöschte Beiträge?)', // noav : "nicht verfügbar", nodb: '‹nicht in Datenbank›', noGrp: 'keine erweiterte Gruppe', date: ['Jahr', 'Monat', 'Tag', 'Stunde', 'Minute', 'Sekunde'], dates: ['Jahren', 'Monaten', 'Tagen', 'Stunden', 'Minuten', 'Sekunden'], nosec: 'vor weniger als einer ', curtimeDiff: ' Lokale Zeit-Differenz zur Server-Zeit in s: ', thxGn: 'gegeben', thxRd: 'erhalten', nova: 'neu', ago: 'vor $1', blocklog: 'Benutzersperr-Logbuch', // Zeilentitel thxGvng: 'Danksagungen: ', contrib: 'Edits: ', // "Bearbeitungen: ", usub: 'Unterseiten⬇', reviews: 'Aktive Sichtungen: ', regdate: 'Registrierungsdatum: ', laedit: 'Letzter Edit: ', lala: 'Letzte Log-Aktivität', fiedit: 'Erster Edit: ', blocks: 'Sperrstatus: ', loGrp: 'Lokale Benutzergruppen: ', glGrp: 'Globale Benutzergruppen: ', blockEnd: 'Sperr-Ende: ', blocker: 'Sperrender: ', blockReason: 'Sperrbegründung: ' } };
 * Eng: This script shows on user-pages some information about the user
 * Deu: Dieses Script zeigt auf Userseiten einige Informationen über den User an
 * @Required modules: mediawiki.util, mediawiki.api, mediawiki.language, mediawiki.cookie, jquery.spinner
 * @TODO: fakeLoader, group since when?, edits/day, Error msg on maxlag instead of disapear
 * better IP support

var data; /* = { // JSON cache timestamp: "", timediff: "", editcount: "", groups: "", gender: "", lastedit: "", firstedit: "", reviews: "", glGrp: "" {array} };*/

var us = mw.libs.userstatus = { name: 'Userstatus', version: 1.79, // Config lastEditSeconds: false, // Show seconds of last edit styleMissingData: 'color:#999;font-size:90%;', // Styles for missing entries styleLoading: 'font-style:italic;', styleBlocked: 'color:#c00', styleNotBlocked: 'color:#080', viewPatrolNumber: false, // Primary for DeWP, supports a direct bot activation. lang: mw.config.get('wgUserLanguage'), user: mw.config.get('wgTitle'), cookie: [], thanks: 0, patrols: 0, actions: [], dbVersion: 0,

getLocalNames: function (groups, specialpage) { if (groups) { var arr = []; specialpage = specialpage || 'ListGroupRights'; for (var i = 0; i < groups.length; ++i) { var g = groups[i]; var n = us.groupNames[g]; // Link it				if (n) arr.push('' + n + ''); // arr.push('<a href="#" onclick="mw.libs.userstatus.goGroupPage(event)" title="' +				// arr.push(n);				else arr.push(g);			}			// log("GetLocalNames ", arr, groups);			groups = arr.join(', ').replace(/(.*),([^,]*)$/, msg.and); // String		}		return groups;	},

/* goGroupPage: function (e) { if (e.target) { var $e = $(e.target); $e.injectSpinner("grp"); var title = "grouppage-" + $e.attr('title'); $e.attr('target', '_blank'); $e.off('click').attr('onclick', ''); e.preventDefault; us.ajaxRequest("&smaxage=86400&meta=allmessages&amenableparser=1&amincludelocal=1&amfrom="+ title +"&amto="+ title +"&amprefix=grouppage-&amlang=" + mw.config.get("wgContentLanguage"), function (aw) { $.removeSpinner("grp"); if (!aw || !aw.query) return; aw = aw.query.allmessages; if (aw.length) window.open("/wiki/" + aw[0]["*"]); } ); } return false; },*/

writeGroups: function (groups) { groups = us.getLocalNames(groups); if (!groups) { groups = $(' ', {				style: us.styleMissingData + us.styleLoading,				text: msg.noGrp			}); }

us.loading_groups.replaceWith(groups); },

getGroupNames: function (aw) { if (!aw || !aw.query) return; aw = aw.query.allmessages; var al = aw.length; var groups = {}; while (al--) { var an = aw[al]; var name = an.name; if (/^group-/.test(name)) { name = RegExp.rightContext || name.substring(6); groups[name] = an['*']; }		}		us.groupNames = groups; // mw.log("groupNames: ", us.groupNames); us.init; },

ajaxRequest: function (params, onSuccess, trial) { // mw.log("ajaxRequest", params, onSuccess, trial); var url = us.api; if (!(params instanceof Object)) { // Workaround for mw.Api bug url += params + '&maxage=2419200&smaxage=2419200'; params = {}; } else { params.maxlag = 3; params.maxage = 2419200; params.smaxage = 2419200; // params.timeout = 2400; if (trial) params.maxlag *= trial; // params.timeout *= trial;

}		var api = $.getJSON(url, params, onSuccess) /*	$.ajax( {		dataType: 'json',		url: url,		data: params,		cache: true,		success: onSuccess	} )*/ /* var api = new mw.Api // Buggy ? Too much timeout errors ! .get(params, { timeout: 2400 * (trial || 1) })*/ .fail(function (jqXHR, status) {				var note = 'Timeout fail, maybe try again!';				var error = [us.name + ': AJAX-Request failed ', note, params, jqXHR, status];				if (trial) {					if (!status.textStatus || (status.textStatus !== 'timeout' && jqXHR !== 'maxlag')) note = $(' Fehler bitte Perhelion melden. Konkrete Error: ' + jqXHR + ' ');					mw.notify(note, { title: us.name + ':', type: 'error' });					note = '';					if (!(params instanceof Object) && /list=usercontribs/.test(params)) { // Fallback only						us.actions.push({ params: params, func: onSuccess });						us.us_last_edit_loading.replaceWith($('', {							// "class" : "mw-userlink",							title: 'Contributions ' + us.user,							href: '/w/index.php?title=Special:Contributions/' + us.user,							text: '?',							click: us.doRequest						}));					// $.removeSpinner("contribs");					}				} else if (status.textStatus === 'timeout' || jqXHR === 'maxlag') { // Try once again					api.abort;					mw.log.warn(error);					return us.ajaxRequest(params, onSuccess, 2);				}				mw.log.warn(error);			}); },

getThanks: function (e) { var params = '&list=logevents&continue=-%7C%7C&leprop=&letype=thanks&ledir=newer&lelimit=max'; /* { list : "logevents", leprop : "", letype : "thanks", ledir : "newer", lelimit : 500 };*/		if (e instanceof Object) { if (e.target) { // reset if (us.e) { // TODO should be synchron requests allowed? return mw.notify('Synchron requests are not yet supported.', {						title: us.name + ':',						type: 'error'					}); }

e = e.target; us.e = $(e); us.e.attr('title', us.e.text); us.e.text(''); us.e.injectSpinner('thx'); us.thanks = 0; } else if (e.lecontinue) { params += '&lecontinue=' + e.lecontinue; // params.lecontinue = e.lecontinue; }			if (us.e.attr('title') === msg.thxGn) params += '&leuser=' + us.user; // params.leuser = us.user; else // if (us.e === msg.thxrc) params += '&letitle=User:' + us.user; // params.letitle = "User:" + us.user; }		us.actions.push({			params: params,			func: us.writeThanks		}); us.doRequest; },

writeThanks: function (uq) { if (!uq.query || !uq.query.logevents) return mw.log.warn(uq); var e = us.e;		var user = 'page='; var aw = uq.query.logevents; us.thanks += aw.length; mw.log(us.thanks); if (uq.continue) return us.getThanks(uq.continue); if (e[0].title === msg.thxGn) user += '&user='; user += us.user; $.removeSpinner('thx'); e.text(us.thanks); e.off('click'); e[0].target = '_blank'; e[0].href = '/w/index.php?title=Special%3ALog&type=thanks&' + user + '&year=&month=-1&tagfilter=&hide_thanks_log=0'; delete us.e;	},

getUploads: function (e) { // "&list=usercontribs&uclimit=max&ucuser=Perhelion&ucnamespace=6&ucprop=ids&ucshow=new		var params = /* { list: "logevents", leprop: "ids", letype: "upload", ledir: "newer", leuser: us.user, lelimit: 500 }*/ '&list=logevents&letype=upload&ledir=newer&lelimit=max&leuser=' + us.user;		function _start(u) {			var text = u.text;			u.prop('title', text);			u.text('');			u.injectSpinner('upload' + text);			u.data('upl', 0);			u.data('del', 0);		}

if (e instanceof Object) { if (e.target) { // Reset if (us.e) { // No synchron requests allowed return mw.notify('Synchron requests are not yet supported.', {						title: us.name + ':',						type: 'error'					}); }

e = e.target; us.e = $(e); if (us.e.text !== msg.nova) { us.e2 = us.e.nextAll('a').eq(0); if (us.e2.text === msg.nova) _start(us.e2); else delete us.e2; }				_start(us.e); } else if (e.lecontinue) { params += '&lecontinue=' + e.lecontinue; } params += '&leprop=ids'; if (us.e.prop('title') === msg.nova) params += '&leaction=upload/upload'; // params.leaction = "upload/upload"; else if (us.e2) params += '|type'; }		us.actions.push({			params: params,			func: us.writeUploads		}); us.doRequest; },

writeUploads: function (uq) { if (!uq.query || !uq.query.logevents || !us.e) return mw.log(uq, us.e); function _insert(e) { $.removeSpinner('upload' + e.prop('title')); e.text(''); e.off('click'); e.append(e.data('del'),				$(' ', { style: us.styleMissingData + us.styleLoading, text: ' (+' + (e.data('upl') - e.data('del')) + ' del.)' }));			e[0].target = '_blank'; e[0].href = '/w/index.php?title=Special:Log&type=upload&user=' + us.user + '&subtype=' + ((e[0].title === msg.nova) ? 'upload' : ''); // "//commons.wikimedia.org/wiki/Special:ListFiles/" + us.user; }		var e = us.e;		var e2 = us.e2; var aw = uq.query.logevents; var alen = aw.length, i = 0; var del = e.data('del'); if (e2) { var upl = e2.data('upl'); var del2 = e2.data('del'); for (i; i < alen; ++i) { var a = aw[i]; var c = a.pageid ? 1 : 0;				if (a.action === 'upload') { upl++; del2 += c;				} del += c;			} e2.data('upl', upl); e2.data('del', del2); } else { for (i; i < alen; ++i) if (aw[i].pageid) del++;

}		e.data('upl', e.data('upl') + alen); e.data('del', del); if (uq.continue) return us.getUploads(uq.continue);

_insert(e); if (e2) { _insert(e2); delete us.e2; }		delete us.e;	},

/**	* @Main write function *	* @param {json} uq user query, used also without api * @return {object} writing the results */	writeCommonInfo: function (uq) { // mw.log( uq ); var aw = uq.query; if (!aw || !aw.users[0] || Object.prototype.hasOwnProperty.call(aw, 'missing') || Object.prototype.hasOwnProperty.call(aw.users[0], 'invalid')) return us.statusBox.remove; aw = aw.users[0]; var edits = aw.editcount, groups = data.groups || aw.groups, blocked = data.blockreason || aw.blockexpiry, gender = data.gender || aw.gender, uploads = $('', {				// href: '#',				title: msg.count,				text: msg.nova,				style: us.styleLoading,				click: us.getUploads			}); if (aw.registration) data.registration = aw.registration;

us.now = us.getDateFromTimestamp(uq.curtimestamp || us.now || mw.now); us.user = us.user.replace(/ /g, '_'); // encodeURIComponent? us.first = 1;

if (edits) { // Write last edit if (data.editcount && data.lastedit && data.editcount === edits) { uq.query.usercontribs = [{ timestamp: data.lastedit }				];				us.writeLastEdit(uq); } else { // console.log(["writeLastEdit data", data.lastedit, data.registration || data.firstedit]); data.editcount = edits; us.loading_last_edit.css('display', 'block'); us.actions.push({					params: /* { smaxage: 9000, maxage: 9000, requestid: "contribs", list : "usercontribs", ucprop: "timestamp", uclimit : 1, uccontinue: new Date(us.now).toISOString.replace(/[^\d]/g, ).slice(0,14) + "|2", // workaround for timeout bug!? ucstart: us.now.toISOString, ucend: data.lastedit || (data.registration || data.firstedit)? new Date(data.registration || data.firstedit).toISOString: undefined, // faster? ucuser : us.user, // ucdir: "older" }*/ '&list=usercontribs&ucuser=' + us.user + '&uclimit=1&uccontinue=' + (new Date(us.now).toISOString.replace(/[^\d]/g, ).slice(0, 14) + '|2'),					func: us.writeLastEdit				}); }			$('#t-contributions').remove; // we setted a new one } else { us.writeLastEdit({}); }

if (groups) { edits = $('', {				title: 'Supercount User Analysis',				href: '//tools.wmflabs.org/supercount/index.php?user=' + us.user + '&project=' + location.hostname,				text: edits			}); if ($.inArray('bot', groups) === -1) { us.review = $.inArray('editor', groups) !== -1; // FIXME: Due bug T136493 patrols are not working correct if (us.review /* || $.inArray("patroller", groups) !== -1 || $.inArray("sysop", groups) !== -1 */) { if (typeof data.reviews === 'number') { // De Powerusers: Benutzer:HRoestBot/Nachsichten us.writePatrolCount(data.reviews); } else if (typeof data.reviews === 'undefined' && us.viewPatrolNumber && project === 'dewiki') { us.actions.push({							params: {								prop: 'revisions',								rvlimit: 1,								rvprop: 'content',								titles: 'User:' + us.user + '/Sichterbeiträge'							},							func: us.writeBotPatrolCount						}); }

} else if (us.viewPatrolNumber) { us.us_patrolcount_loading.parent.remove; } edits = [ edits, ' • ', $('', { // XTools						href: '//xtools.wmflabs.org/ec' + mw.config.get('wgServer').substr(1) + '/' + us.user,						title: 'Edit Counter – analysis of user contributions',						text: 'XTools',						style: us.styleLoading,						target: '_blank'					}), ' • ', $('', { // MyGallery						href: '//commons.wikimedia.org/w/index.php?title=Commons:MyGallery/' +						us.user + '&withJS=MediaWiki:JSONListUploads.js',						title: 'Commons tool: JSONListUploads.js',						text: (project === 'commonswiki' ? '' : 'c:') + 'MyGallery',						style: us.styleLoading,						target: '_blank'					}), ' • ', (project !== 'commonswiki' ? $('', { href: '/wiki/Special:ListFiles/' + us.user, text: 'Upload', title: 'Special:Listfiles', style: us.styleLoading }) : 'Upload'), (us.lang === 'de' ? '-' : ' ') + msg.count + ': ', uploads.clone(1).text('total'), ' / ', uploads ];				if (!$('#t-subpages').length) { // Subpages edits.push($('', { href: mw.util.getUrl('Special:Prefixindex/User:' + us.user + '/'), text: ' • ' + msg.usub, style: us.styleMissingData + us.styleLoading }));				}

} else if (us.us_patrolcount_loading) { us.us_patrolcount_loading.parent.remove; } us.loading_editcount.replaceWith(edits);

if (!aw.implicitgroups && !data.groups) { aw.implicitgroups = ['*', 'user', 'autoconfirmed']; if (groups.length < 4) aw.implicitgroups.pop; // bit hacky }

data.groups = $.grep(groups, function (n) { // Exclude not needed items				return $.inArray(n, aw.implicitgroups) === -1;			}); us.writeGroups(data.groups); $('#t-userrights').remove; // we setted a new one }

if (!data.registration) { us.actions.push({				params: '&list=logevents&leprop=timestamp|type&letype=newusers&lelimit=1&ledir=newer&leend=2005-12-30T00:00:00Z&leuser=' + us.user,				func: us.writeRegistration			}); if (data.firstedit) { uq.query.usercontribs = [{ timestamp: data.firstedit }				];				us.writeFirstEdit(uq); } else if (edits) { // get first edit before around 22:16, 7 September 2005 us.actions.push({					params: {						list: 'usercontribs',						ucuser: us.user,						uclimit: 1,						ucend: '2005-09-08T00:00:00Z', // faster?						ucdir: 'newer', // List oldest first!! Note: ucstart has to be before ucend.						ucprop: 'timestamp'					},					func: us.writeFirstEdit				}); }		} else { us.writeRegistration(data.registration); }

us.loading_blocked.replaceWith($('', { style: ((blocked) ? us.styleBlocked : us.styleNotBlocked), id: 'us_block_status_span', href: '/w/index.php?title=Special:Log/block&page=User:' + us.user, title: msg.blocklog, text: ((blocked) ? ' ' : msg.not) + msg.block }));

if (blocked) { data.blockreason = aw.blockreason || ' '; us.ul.append([				$('', { id: 'us_block_time' }).append([ $('').text('• ' + msg.blockEnd), $.createSpinner('us_block_time_loading') ]),				$('', { id: 'us_block_reason' }).append([ $('').text('• ' + msg.blockReason), $.createSpinner('us_block_reason_loading') ]),				$('<li>', { id: 'us_blocker' }).append([ $('<b>').text('• ' + msg.blocker), $.createSpinner('us_blocker_loading') ])			]);			// if (!data.locked) us.actions.push({				params: {					list: 'logevents',					letitle: 'User:' + us.user,					letype: 'block',					lelimit: 1				},				func: us.writeBlockDetail			}); }

if (data.glGrp && !data.locked) { // TODO 1.31.0-wmf get also local group info uq.query.globaluserinfo = { groups: (data.glGrp.length) ? data.glGrp : null };			us.writeGlobalGroup(uq); } else { us.actions.push({				params: /* {				meta : "globaluserinfo",				guiuser : us.user,				guiprop : "groups"				}*/				'&meta=globaluserinfo&guiprop=groups&guiuser=' + us.user,				func: us.writeGlobalGroup			}); }

if (gender) { data.gender = gender; var genderSn = ''; switch (gender) { case 'male': genderSn = ' \u2642'; break; case 'female': genderSn = ' \u2640'; }			genderSn = $(' ', {				id: 'ps-gender-' + gender,				style: 'font-size:80%',				text: genderSn			}); $('#firstHeading').append(genderSn); }		if (us.actions.length) us.doRequest; },

createBox: function { /* Box erstellen */ var statusBox = $(' ', {			style: 'border-bottom:1px solid #aaa;text-shadow:1px 1px 1px #eff;', // padding:1px			id: 'us_box'		}); if (mw.config.get('skin') === 'vector') // Fix size in vector statusBox.css('font-size', '0.8em');

// var spanFrag = $(" ", {style: us.styleLoading, text: msg.load}); var spanFrag = $.createSpinner; us.loading_editcount = spanFrag.clone; us.loading_registration = spanFrag.clone; us.loading_groups = spanFrag.clone; us.loading_blocked = spanFrag.clone; us.us_global_group_loading = spanFrag.clone; us.us_last_edit_loading = $.createSpinner('contribs'); us.loading_last_edit = $('<li>', {			// id : "us_last_edit",			// style : "display: none" //if (edits)		}); us.us_global_group = $('<li>', {			// id: "us_global_group",			style: 'display: none'		}); var thx = $('', {			// href: '#',			title: msg.count,			text: msg.thxRd,			style: us.styleLoading,			click: us.getThanks		}); var $userrights = $('#t-userrights a'); var $contributions = $('#t-contributions a');

if ($userrights.length) { $userrights.attr('title', $userrights.text); } else { $userrights = $('', {				href: '/wiki/Special:UserRights/' + us.user			}); }

if ($contributions.length) { $contributions.attr('title', $contributions.text); } else { $contributions = $('', {				href: '/wiki/Special:Contributions/' + us.user			}); }

var ul = $('<ul>', {			style: 'list-style: none'		}).append($('<li>', { id: 'us_editcount' }).append([ $('<b>').append($contributions.text(msg.contrib)), us.loading_editcount]));

// Sichtungen/Patrols us.us_log_count = $(' '); if (us.viewPatrolNumber) { us.us_patrolcount_loading = $('', {				style: us.styleLoading,				// href: '#',				click: us.getPatrolCount,				text: msg.count			}); us.us_log_count = $(' ').append([				$('<b>').text(msg.reviews), us.us_patrolcount_loading, ' • '			]); }		ul.append(us.us_log_count) .append($('<li>', { id: 'us_reg_date' }).append([ $('<b>').text(msg.regdate), us.loading_registration, $('', {					target: '_blank',					style: 'float:right;' + us.styleMissingData,					href: 'https://tools.wmflabs.org/meta/userpages/' + us.user,					title: 'Find this users pages on all Wikimedia wikis.',					text: '• User pages'				}) ]))

// Lokale Gruppen .append($('<li>' /*, { id : "us_local_group" }*/).append([ $('<b>').append($userrights.text(msg.loGrp)), us.loading_groups, $('', {					target: '_blank',					style: 'float:right;' + us.styleMissingData,					href: 'https://tools.wmflabs.org/meta/stalktoy/' + us.user,					title: 'View global details about this user across all Wikimedia wikis.',					text: '• Stalk toy'				}) ]))		// 'Global Groups' .append(us.us_global_group.append([ $('<b>').append(					$('', { href: '/w/index.php?title=Special:GlobalUsers&limit=1&username=' + us.user, text: msg.glGrp })),				us.us_global_group_loading, $('', {					target: '_blank',					style: 'float:right;' + us.styleMissingData,					href: 'https://tools.wmflabs.org/meta/globalgroups/',					title: 'A review of extra permissions assigned to global groups on Wikimedia Foundation wikis.',					text: '• GlobalGroups'				}) ]))		// Letzter Edit .append(us.loading_last_edit.append([ $('<b>').text(msg.laedit), us.us_last_edit_loading, ' ', $('', {					target: '_blank',					style: us.styleMissingData,					href: '/w/index.php?title=Special:Log/' + us.user + '&hide_thanks_log=0&hide_patrol_log=0&hide_tag_log=0',					title: msg.lala,					text: '• LLA'				}), $('', {					target: '_blank',					style: 'float:right;' + us.styleMissingData,					href: 'https://tools.wmflabs.org/meta/crossactivity/' + us.user,					title: 'Measures user\'s latest edit, bureaucrat, or sysop activity on all wikis.',					text: '• CrossActivity'				}) ]));

statusBox.append(ul);

// Block & thx us.ul = $('<ul>', {			style: 'list-style:none'		}).append($('<li>', { id: 'us_block_status' }).append([ $('<b>').text(msg.blocks), us.loading_blocked, ' • ',			$('<b>').text(msg.thxGvng), thx, ' / ', thx.clone(1).text(msg.thxGn), // Purge link removeDataStore $('', {				// target: '_blank',				style: 'float:right;' + us.styleMissingData,				// href: '#',				title: 'Delete data store for this user',				text: 'purge',				click: us.removeDataStore			}) ])		);

statusBox.append(us.ul); $('#firstHeading').after(statusBox); us.statusBox = statusBox; },

removeDataStore: function (e) { var key = project + us.user, // name = us.name + us.user, db = window.indexedDB; e.preventDefault;

if (!db || !us.dbVersion) return mw.cookie.set(key, null); var request = db.open(us.name, us.dbVersion + 1); // sure the key exists

request.onerror = function (e) { mw.log.warn('Error removing data: ${e}', key, e.oldVersion, e.target.result.version); };		request.onupgradeneeded = function (/* e*/) { db = this.result; if (!db.objectStoreNames.contains(key)) { mw.log.warn('No stored object found: ', e.oldVersion, db.version, key); return; }			// mw.log("deleteObjectStore", key, db.version, db.objectStoreNames.contains(key)); db.deleteObjectStore(key); };		request.onsuccess = function (/* e*/) { db = this.result; if (!db.objectStoreNames.contains(key)) { us.dbVersion = db.version; // mw.log(`Successfully removed ${key}: ${e.target.result}`, db.version); db.close; us.init; // Restart // us.createBox;us.run;// needs new box // location.reload; return; }			// console.warn(`Successfully open but fail on remove: ${e.target.result}`, key, e.oldVersion, db.version); };	},

setCookie: function { var domain = (mw.config.get('wgNoticeProject') === 'wikipedia') ? 'wikipedia.org' : ''; var name = us.name + us.user; /**		* @param {string} key (for "glGrp": deprecated) * @param {json} data * @return {void} */		var _saveCookie = function (key, data) { mw.cookie.set(name, JSON.stringify(data), {				prefix: key,				expires: 600000, // Save 1 week				domain: domain			}); };

if (!us.actions[0] && JSON && data.editcount) { if (us.cookie.length) window.clearTimeout(us.cookie.shift);

// Check only once var saveData = window.indexedDB ? /**				* @param {string} name (for "glGrp": deprecated) * @param {json} JSdata * @param {integer} version */				function (name, JSdata, version) { // _saveIDB var store, key = (name || project) + us.user, // ?? db = window.indexedDB, request = {}; data = { // TODO: Maybe extend name: key, data: JSdata };					request = db.open(us.name, (version || undefined)); // indexedDB.deleteDatabase("Userstatus")

request.onupgradeneeded = function { db = this.result; mw.log(db.version + ' onupgradeDB ' + db.objectStoreNames.contains(key)); if (!db.objectStoreNames.contains(key)) { // New store = db.createObjectStore(key, {								keyPath: 'name'							}); store.createIndex('data', 'data', {								unique: false							}); // Use transaction oncomplete to make sure the objectStore creation is finished before adding data into it. store.transaction.oncomplete = function { // Store values in the newly created objectStore. mw.log(db.version + ' onupgradeDB.transaction.complete store ' + db.objectStoreNames.contains(key));

store = db.transaction(key, 'readwrite').objectStore(key); var req = store.get(key); req.onsuccess = function { mw.log('Success writeDb.transaction close', this.result); // db.close; };							};						} else { mw.log.warn('saveDB FAIL'); } };

request.onerror = function { _saveCookie(name, JSdata); mw.log.warn(us.name, 'saved data as cookie. Failed openDB:', this.error.message); };

request.onsuccess = function { db = this.result; us.dbVersion = db.version; db.onversionchange = function { us.dbVersion = db.version; mw.log('closedDB'); db.close; };						mw.log(name, db.versio + ' onsuccess ' + db.objectStoreNames.contains(key)); if (db.objectStoreNames.contains(key)) { // Overwrite store = db.transaction(key, 'readwrite').objectStore(key); var req = store.put(data); // mw.log("openDb get users:", db.objectStoreNames); req.onsuccess = function { if (this.result) // only one mw.log('replaceDB store DONE:', this.result, req); else // Try new version? saveData(name, JSdata, us.dbVersion + 1); };							req.onerror = function { mw.log.warn(us.name, key, 'replaceDB store FAIL:', this.error); };

} else { saveData(name, JSdata, us.dbVersion + 1); }					};				} :				_saveCookie;

us.cookie.push(setTimeout(function (us) { // prevent double exec if (us.cookie.length === 1) { data.timestamp = new Date.valueOf; if (!data.registration) delete data.registration; if (data.gender && data.gender === 'unknown') delete data.gender; // window.clearTimeout(us.cookie.shift); // us.cookie[0] saveData('', data); mw.log('Do save ' + us.name + ': ' + JSON.stringify(data)); } else if (us.cookie.length) { window.clearTimeout(us.cookie.shift); // delete previous us.setCookie; // try again }			}, 500, us)); }

},

/**	doRequest: function { var action = us.actions.shift; if (action) us.ajaxRequest(action.params, action.func); if (us.actions.length) { window.setTimeout(function (thisObj) {				thisObj.doRequest;			}, 100, us); }
 * API in race condition
 * @param {array} us.actions
 * @var {json: param, callback} action

},

getDateDiff: function (now, date) { var dStr = []; var d = { years: 0, months: 0, days: 0, hours: 0, minutes: 0, seconds: 0 };		var diffDays = 0;

if (now > date) { diffDays = Math.floor((now - date) / 86400000);

if (diffDays > 27) { // Years and Months var year = now.getFullYear; d.years = date.getFullYear; date.setFullYear(year); d.years = year - d.years; d.months = date.getMonth; var months = now.getMonth; if (date > now) { // the date month >= now month d.years--; d.months = 12 - d.months + months; date.setFullYear(year - 1); } else { d.months = months - d.months; }

var days = date.getDate; d.days = now.getDate;

if (d.days < days) { d.days += (new Date(new Date(year, months) - 1000).getDate) - days; d.months--; months--; } else { d.days -= days; } date = new Date(year, months, days, date.getHours, date.getMinutes, date.getSeconds); }

if (now < date) date = new Date(date - 1000); // Diff days and lower var s = Math.abs(now - date) / 1000; d.seconds = Math.floor(s % 60); s = s / 60; d.minutes = Math.floor(s % 60); s = s / 60; d.hours = Math.floor(s % 24); d.days = Math.floor(s / 24);

for (var i = 0, dlen = msg.date.length; i < dlen; ++i) { var t = d[i18n.en.dates[i]]; if (t) dStr.push(t + ' ' + ((t > 1) ? msg.dates[i] : msg.date[i])); }		}		return (dStr.length) ? dStr.join(', ').replace(/(.*),([^,]*)/, msg.and).replace(/(.*)/, msg.ago) + ((d.months + d.years) ? ' = ' + diffDays + ' ' + msg.dates[2] : '') : msg.nosec; },

getDateFromTimestamp: function (t) { if (!t) return false; t = new Date(t); return isNaN(t.valueOf) ? false : t;	},

writeRegistration: function (aw) { // mw.log(aw); if (aw) { if (aw instanceof Object) { if (!aw || !aw.query) return; aw = aw.query.logevents; if (aw && aw.length && aw[0].action === 'newusers') aw = aw[0].timestamp; }			if (!(aw instanceof Object)) { us.loading_registration.replaceWith(us.formatDate(aw) + ' ',					$(' ', { style: us.styleMissingData, text: '(' + us.getDateDiff(us.now, us.getDateFromTimestamp(aw)) + ')' }));				data.registration = aw; return us.setCookie; }		}		us.loading_registration.replaceWith($(' ', { style: us.styleMissingData + us.styleLoading, text: msg.nodb }));	},

writeFirstEdit: function (aw) { var date = aw.query.usercontribs; if (!date.length) return; date = data.firstedit = date[0].timestamp; $('#us_reg_date').append(			$('<li>').append([ $('<b>', {					text: '• ' + msg.fiedit				}), us.formatDate(date) + ' ', $(' ', {					style: us.styleMissingData,					text: '(' + us.getDateDiff(us.now, us.getDateFromTimestamp(date)) + ')'				}) ]));	},

writeLastEdit: function (aw) { var uc = aw.query; if (!uc || !uc.usercontribs || !uc.usercontribs.length) { return us.us_last_edit_loading.replaceWith($(' ', { style: us.styleMissingData, text: msg.noedit }));		}

uc = uc.usercontribs; var date = data.lastedit = uc[0].timestamp; // console.log(date, uc);

us.us_last_edit_loading.replaceWith(us.getDateDiff(us.now, us.getDateFromTimestamp(date)), ' ',			$(' ', { style: us.styleMissingData, text: '(' + us.formatDate(date) + ')' }));		data.timediff = mw.now - us.now; $('#us_editcount').append(			$(' ', { style: 'float:right;' + us.styleMissingData, text: msg.curtimeDiff /* + " – " + us.formatDate(now)*/ }).append( $('<b>', {					text: Math.round(data.timediff / 1000)				}))); us.setCookie; },

writeGlobalGroup: function (aw) { aw = aw.query.globaluserinfo; var groups = data.glGrp = aw.groups; if (groups && groups.length) { us.us_global_group_loading.replaceWith(us.getLocalNames(groups, 'GlobalGroupPermissions')); us.us_global_group.css('display', 'block'); }

// Global lock? if (aw.locked !== undefined) { data.locked = 1; /* 			us.actions.push( {			params: {				"list": "logevents",				"leprop": "user|timestamp|comment",				"letype": "globalauth",				"letitle": 'User:' + us.user + '@global',				"lelimit": "1"			}, func: us.writeGlobalBlock		} ); us.doRequest; */ mw.loader.using('mediawiki.ForeignApi').done(function {				var Api = (project === 'metawiki') ? mw.Api : mw.ForeignApi;				Api = new Api('https://meta.miraheze.org/w/api.php');				Api.get({ action: 'query', list: 'logevents', leprop: 'user|timestamp|comment', letype: 'globalauth', letitle: 'User:' + us.user + '@global', lelimit: '1' }).done(us.writeGlobalBlock);			}); }		us.setCookie; },	// /w/api.php?action=query&format=json&list=logevents&leprop=user%7Ctimestamp%7Ccomment&letype=globalauth&letitle=User%3APerhelion%40global&lelimit=1 writeGlobalBlock: function (aw) { if (!aw.query) return mw.log('API FAIL:', aw); aw = aw.query.logevents[0]; $('#us_block_status_span').replaceWith($('', { style: us.styleBlocked, id: 'us_block_status_span', href: '//meta.miraheze.org/w/index.php?title=Special:Log/&type=globalauth&user=&page=User%3A' + us.user + '%40global', title: msg.blocklog, text: 'locked (global)' })			.append($(' ', {				style: us.styleMissingData,				text: ' – ' + us.formatDate(aw.timestamp)			}))		);

$('#us_block_status').parent.append([			$('<li>', { // id: 'us_block_reason' }).append([ $('<b>').text('• ' + msg.blockReason), us.parseComment(aw.comment) ]),			$('<li>', { // id: 'us_blocker' }).append([ $('<b>').text('• ' + msg.blocker), $('', {					'class': 'mw-userlink',					'title': 'User:' + aw.user,					'href': mw.util.getUrl('User:' + aw.user),					'text': aw.user				}) ])		]);	},

// /w/api.php?action=query&format=json&list=logevents&letype=block&letitle=User%3AErwin_Lindemann writeBlockDetail: function (aw) { var duration = 'infinite', expiry = ''; if (aw.query) { aw = aw.query.logevents[0]; if (aw && aw.params) { duration = aw.params.duration; if (/in(de)?finite/.test(duration)) expiry = msg.never; else expiry = us.formatDate(aw.params.expiry); } else if (!aw || !aw.commenthidden) { aw = { commenthidden: 1 }; }		// mw.log("writeBlockDetail:", aw, expiry); }		duration = $('#us_block_status_span').text(msg.block + ' (' + duration + ')'); if (aw.timestamp) duration.append($(' ', { style: us.styleMissingData, text: ' – ' + us.formatDate(aw.timestamp) }));		if (expiry) $('#mw-spinner-us_block_time_loading').replaceWith(expiry); else $('#us_block_time').remove; $('#mw-spinner-us_block_reason_loading').replaceWith(us.parseComment(aw.comment, (aw.commenthidden))); if (aw.user) $('#mw-spinner-us_blocker_loading').replaceWith($('', { 'class': 'mw-userlink', 'title': 'User:' + aw.user, 'href': mw.util.getUrl('User:' + aw.user), 'text': aw.user }));		else $('#mw-spinner-us_blocker_loading').replaceWith(msg.nodb); },

writeBotPatrolCount: function (aw) { aw = aw.query; var patrols = ''; if (aw) { for (var key in aw.pages) { if (key !== '-1') { patrols += parseInt(aw.pages[key].revisions[0]['*'], 10); break; }			}		}

if (patrols) return us.writePatrolCount(patrols); },

writePatrolCount: function (aw) { // log(aw); if (aw instanceof Object) { var ql = aw.query.logevents; if (!ql) return; us.patrols += ql.length; if (aw.continue) return us.getPatrolCount(aw.continue); $.removeSpinner('pat'); aw = us.patrols; }		us.us_patrolcount_loading.replaceWith($('', { title: 'Review-Log', href: '/w/index.php?title=Special:Log&type=' + (us.review ? 'review&subtype=accept' : 'patrol&subtype=patrol') + '&user=' + us.user, text: aw		})); data.reviews = aw; us.setCookie; },

getPatrolCount: function (e) { // Reviews only on some Wikis like de	// mw.log(us.review,e) var params = /* { list : "logevents", ledir : "newer", leprop : "", // letype : "patrol", leaction : "patrol/patrol", leuser : , lelimit : 500 }*/ '&list=logevents&leprop=&ledir=newer&lelimit=max&leuser=' + us.user + '&leaction=' + (us.review ? 'review/approve' : 'patrol/patrol'); // params.leaction = "review/approve"; // params.letype = "review"; if (e instanceof Object) { if (e.target) { // reset $(e.target).injectSpinner('pat'); us.patrols = 0; } else if (e.lecontinue) { // params.lecontinue = e.lecontinue; params += '&lecontinue=' + e.lecontinue; }		}

us.actions.push({			params: params,			func: us.writePatrolCount		}); us.doRequest; },

parseComment: function (text, hidden) { var comment = $(' ', {	'class': 'comment' });

if (typeof (text) === 'undefined') { if (hidden) { return comment.append(msg.noReason).css('color', '#999'); } else { mw.notify($(' Fehler bitte Perhelion</a> melden: Undefined comment at page ' + us.user + ' '), {					title: us.name + ':',					type: 'error'				}); return comment.append('undefined').css('color', 'red'); }		} else if (!text) { return comment.append(msg.blockCmt).css('color', '#999'); }

var intLink = /(.*?)\[\[((.*?)\|)?(.*?)\]\](.*)/; var suche = text; var erg; while ((erg = intLink.exec(suche)) !== null) { erg[3] = (erg[2]) ? $('<a>', {					href: mw.util.getUrl(erg[3]),					title: erg[3]				}) : $('<a>', {					href: mw.util.getUrl(erg[4]),					title: erg[4]				}); comment.append([erg[1], erg[3].text(erg[4])]); suche = erg[5]; }		return comment.append(suche); },

formatDate: function (datum) { if (!(datum instanceof Object)) datum = new Date(datum); try { datum = datum.toLocaleDateString(us.lang, {				weekday: 'long',				year: 'numeric',				month: 'long',				day: 'numeric',				hour: 'numeric',				minute: 'numeric',				second: 'numeric'			}); } catch (e) { if (e.name === 'RangeError') datum = datum.toLocaleString; }		return datum; },

getStoredData: function { var store, key = project + us.user, db, request; try { request = indexedDB.open(us.name); request.onsuccess = function { db = this.result; db.onversionchange = function { mw.log('closedDb'); db.close; };				mw.log(db.version + ' successDb ' + db.objectStoreNames.contains(key), key); if (db.objectStoreNames.contains(key)) { store = db.transaction(key, 'readonly').objectStore(key); store.transaction.oncomplete = function { // mw.log("readDb.transaction.oncomplete runDataStore", data); us.runDataStore; db.close; };					var req = store.get(key); // mw.log("openDb get user:", store, req); req.onsuccess = function { if (this.result) { mw.log('openDb get user DONE:', this.result); data = this.result.data; } else { us.getCookie(this.error); } };					req.onerror = function { us.getCookie(this.error); };				} else { us.getCookie('new user'); }			};			request.onerror = function { us.getCookie(this.error); };		} catch (e) { // console.warn(e); us.getCookie('unknownError'); }	},

getCookie: function (err) { mw.log(us.name + ' FAIL open indexedDB store, try get cookie: ' + (err || '')); data = mw.cookie.get(us.name + us.user); us.runDataStore; },

initI18N: function (i18n) { var i, chain = mw.language.getFallbackLanguageChain; for (i = chain.length - 1; i >= 0; i--) if (chain[i] in i18n) msg = i18n[chain[i]]; },

init: function { if (this.statusBox || (this.statusBox = $('#us_box'))[0]) this.statusBox.remove; this.usprop = 'blockinfo|editcount|gender|groups|implicitgroups|registration'; this.self = mw.config.get('wgUserName') === this.user; this.initI18N(i18n); this.createBox; if (!this.first) { // as purge button if (!this.lastEditSeconds) msg.date.pop; msg.nosec += msg.date.slice(-1)[0]; if (mw.cookie && JSON) { if (window.indexedDB) { // us.getStoredData("GlGrp"); this.getStoredData; } else { // us.getCookie("GlGrp"); this.getCookie; }			} else this.run; } else this.run; // mw.hook( 'resourceloader.loadEnd' ).add( function { us.run; } ); },

runDataStore: function { if (data) { // Max 255 Bytes for Cookie // mw.log( 'data', data, decodeURI( data ), 'glGrp: ', data.glGrp ); if (typeof data === 'string') { try { data = JSON.parse(data); } catch (e) { mw.log.warn(e, data); data = {}; }			}			var q = { query: {} };			q.query.users = [data]; // data.glGrp = data.glGrp || this.glGrpStore; if (data.timestamp) this.now = mw.now - data.timediff; else // if (glGrp) q.query.globaluserinfo = { groups : glGrp }; // mw.log("data parsed", data, "Time: ", data.timestamp, data.timediff, "glGrp: ", data.glGrp, q); if (Math.abs((mw.now - data.timestamp - data.timediff) / 1000) < 90) // only if 1.5 min // q.curtimestamp = us.now; // Speedup: Maybe only if lastedit is minimum one day old? // mw.log(us.name + " RUN fast mode"); return this.writeCommonInfo(q);

if (data.editcount) this.usprop = 'editcount'; // Minimize API request }		data = data || {}; // data.glGrp = this.glGrpStore; mw.log('run' + this.name, data, data.glGrp); this.run; // mw.hook( 'resourceloader.loadEnd' ).add( us.run ); },

run: function { if (this.self) { // Omit API-request data.glGrp = mw.config.get('wgGlobalGroups'); return this.writeCommonInfo({				query: {					users: [{						editcount: mw.config.get('wgUserEditCount'),						registration: mw.config.get('wgUserRegistration'),						groups: mw.config.get('wgUserGroups'),						blockreason: '' // we self should know :P					}]				}			}); }		$(function {		// Start API-request (in race condition)			us.ajaxRequest({ curtimestamp: us.now ? 0 : 1,				list: 'users', ususers: us.user, usprop: us.usprop }, us.writeCommonInfo);		}); } };

if ([2, 3].indexOf(mw.config.get('wgNamespaceNumber')) !== -1 && us.user.indexOf('/') === -1 && (!mw.config.get('wgArticleId') || mw.config.get('wgAction') === 'view')) { $(document).trigger('loadWikiScript', us); $.when(mw.loader.using(['mediawiki.util', 'mediawiki.api', 'mediawiki.language', 'mediawiki.cookie', 'jquery.spinner']),		$.ready).then(function {		us.api = '//' + location.hostname + mw.util.wikiScript('api') + '?action=query&format=json';		us.ajaxRequest('&maxage=2419200&smaxage=2419200&meta=allmessages&amenableparser=1&amincludelocal=1&amprefix=group-', us.getGroupNames);		if (!mw.libs.viewerInfo) // Number of observers			mw.loader.load('//meta.wikimedia.org/w/index.php?title=User:Perhelion/viewerInfo.js&action=raw&ctype=text/javascript');

}); } // mw.log = function{console.log(arguments);}; }(jQuery, mediaWiki)); // EOF

// MARK BLOCKED //Forked from User:Burninthruthesky/Gadget-markblocked.js

function markBlocked( container ) { var contentLinks;

// Collect all the links in the page's content if ( container ) { contentLinks = $( container ).find( 'a' ); } else if ( mw.util.$content ) { contentLinks = mw.util.$content.find( 'a' ).add( '#ca-nstab-user a' ); } else { contentLinks = $; }

mw.util.addCSS('\	a.user-blocked-temp {'  + ( window.mbTempStyle || 'opacity: 0.7; text-decoration: line-through' ) + '}\	a.user-blocked-indef {'  + ( window.mbIndefStyle || 'opacity: 0.4; font-style: italic; text-decoration: line-through' ) + '}\	a.user-blocked-partial {' + (window.mbPartialStyle || 'text-decoration: underline; text-decoration-style: dotted') + '}\	.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/ (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 externalRX = new RegExp("https?:"+mw.config.get("wgServer")+"(.+)");

var userLinks = {}; var extUserLinks = {}; var url, ma, pgTitle;

//find all "user" links and save them in userLinks : { 'users': [, , ...], 'user2': [ , , ...], ... }	contentLinks.each( function( i, lnk ) {		url = $( lnk ).attr( 'href' );		var regexResult = externalRX.exec(url);		if(regexResult != null)		{			url = regexResult[1];		}		if ( !url || url.charAt(0) != '/' ) {			return;		}		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 );		if ($( lnk ).hasClass( 'external' ) && url.match(/User:/)) {			if ( !extUserLinks[user] ) {				extUserLinks[user] = [];			}		extUserLinks[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|flags'				//no need for 'id|flags'			},			markLinks		); }

//Make an array of external links to user pages var extUsers = []; for ( var u in extUserLinks ) { extUsers.push( u ); }	//Find out which don't exist and redlink them while ( extUsers.length > 0 ) { $.getJSON(			mw.util.wikiScript('api'),			{				format: 'json',				action: 'query',				titles: 'User:' + extUsers.splice( 0, 50 ).join( '|User:' )			}		) .done(function ( data ) { 				for ( page in data.query.pages ) {					if ( data.query.pages[page].missing != null ) { 						// colour the links red						user = data.query.pages[page].title.match(/^User:(.*)/)[1];						extUserLinks[user].forEach( function (lnk) { $( lnk ).addClass ( 'new' ); $( lnk ).removeClass ( 'external' ); // otherwise it stays blue. })					}				}			});	}

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]; var partialBlock = false; if (typeof blk.partial != "undefined") { clss = 'user-blocked-partial'; partialBlock = true; }			if ( /^in/.test( blk.expiry ) ) { if(!partialBlock) { clss = 'user-blocked-indef'; }				blTime = blk.expiry; } else { if(!partialBlock) { 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 ) { $( ' # ' ).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'; }		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' $.when( $.ready, mw.loader.using( 'mediawiki.util' ) ).then( function {			if ( mw.util.$content && mw.util.$content.hasClass( 'mw-body' ) ) {				if ( window.mbNoAutoStart ) {					mw.util.addPortletLink( 'p-cactions', 'javascript:markBlocked', 'XX', 'ca-showblocks' );				} else {					markBlocked;				}			} 		} ); }

// DIFF // $.when( $.ready, mw.loader.using( [ "mediawiki.util" ] ) ).then( function {    var suffix = mw.config.get( "wgDiffNewId" );    var page;    if( suffix ) {        if( document.getElementsByClassName( "diff-multi" ).length || mw.config.get("wgCanonicalSpecialPageName") === "ComparePages" ) {           suffix = mw.config.get( "wgDiffOldId" ) + "/" + suffix;        }        page = "Special:Diff/" + suffix;    } else {        var oldidMatch = mw.util.getParamValue( "oldid" );        if( oldidMatch ) {            page = "Special:Permalink/" + oldidMatch;        } else return; // nothing to do here    }

var permalinkEl = $( " " ).append(       "Permalink to this " + ( suffix ? "diff" : "oldid" ) + ": ",       $( " " )            .attr( { "id": "diff-permalink-link" } )            .val( page ),        $( " " )            .text( "Copy" )            .css( { "padding": "0.5em", "cursor": "pointer", "margin-left": "0.5em" } )            .click( function  { document.getElementById( "diff-permalink-link" ).select; document.execCommand( "copy" ); } ) );

$( "#diff-permalink-link" ).attr( "size", page.length ); // resize to diff length

if( suffix ) { $( "#bodyContent" ).prepend( permalinkEl ); } else { $( "#contentSub" ).after( permalinkEl ); } } ); //