User:Ahecht/Scripts/useridentifier.js

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.
/* User Identifier (based on [[User:Anomie/useridentifier.js]])

If you want to use this script, simply add the following line to your monobook.js:

mw.loader.load('//en.wikipedia.org/w/index.php?title=User:Ahecht/sandbox/Scripts/useridentifier.js'); // Linkback: [[:en:User:Ahecht/sandbox/Scripts/useridentifier.js]]
*/

var UserIdentifier={
	images:{
		loc:{
			'**':'//upload.wikimedia.org/wikipedia/commons/thumb/7/77/Wikipedia_svg_logo.svg/20px-Wikipedia_svg_logo.svg.png',
			'bot':'//upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Crystal_Clear_action_run.png/20px-Crystal_Clear_action_run.png',
			'sysop':'//upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Mop.svg/20px-Mop.svg.png',
			'bureaucrat':'//upload.wikimedia.org/wikipedia/commons/thumb/a/ac/Human-preferences-desktop.svg/20px-Human-preferences-desktop.svg.png',
			'checkuser':'//upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Gnome-searchtool.svg/20px-Gnome-searchtool.svg.png',
			'reviewer':'//upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Wikipedia_Reviewer.svg/20px-Wikipedia_Reviewer.svg.png',
			'accountcreator':'//upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Wikipedia_Accountcreators_v2.svg/20px-Wikipedia_Accountcreators_v2.svg.png',
			'suppress':'//upload.wikimedia.org/wikipedia/commons/thumb/0/06/Oversight_logo.png/20px-Oversight_logo.png',
			'rollbacker':'//upload.wikimedia.org/wikipedia/commons/thumb/d/df/Wikipedia_Rollback.svg/20px-Wikipedia_Rollback.svg.png',
			'filemover':'//upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Wikipedia_File_mover.svg/20px-Wikipedia_File_mover.svg.png',
			'autoreviewer':'//upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Wikipedia_Autopatrolled.svg/20px-Wikipedia_Autopatrolled.svg.png',
			'abusefilter':'//upload.wikimedia.org/wikipedia/commons/thumb/6/64/Wikipedia-Crystal_clear-advancedsetting.png/20px-Wikipedia-Crystal_clear-advancedsetting.png',
			'templateeditor':'//upload.wikimedia.org/wikipedia/commons/thumb/4/41/Wikipedia_Template_editor_icon_%281%29.svg/20px-Wikipedia_Template_editor_icon_%281%29.svg.png',
			'massmessage-sender':'//upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Wikipedia_mass_messenger.svg/20px-Wikipedia_mass_messenger.svg.png',
			'extendedmover':'//upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Wikipedia_page_mover.svg/20px-Wikipedia_page_mover.svg.png',
			'patroller':'//upload.wikimedia.org/wikipedia/commons/thumb/5/57/Wikipedia_New_page_reviewer.svg/20px-Wikipedia_New_page_reviewer.svg.png',
			'eventcoordinator': '//upload.wikimedia.org/wikipedia/commons/thumb/c/c6/Wikipedia_Event_coordinator.svg/20px-Wikipedia_Event_coordinator.svg.png',
			'interface-admin': '//upload.wikimedia.org/wikipedia/commons/thumb/e/eb/Wikipedia_Interface_administrator.svg/20px-Wikipedia_Interface_administrator.svg.png',
			'temporary-account-viewer':'//upload.wikimedia.org/wikipedia/commons/thumb/e/e0/TAIV_Wikipedia.svg/20px-TAIV_Wikipedia.svg.png',
			'temp':'//upload.wikimedia.org/wikipedia/commons/thumb/9/92/Codex_icon_userTemporary_color-progressive.svg/20px-Codex_icon_userTemporary_color-progressive.svg.png',
			'temp (expired)':'//upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Codex_icon_userTemporary_color-placeholder.svg/20px-Codex_icon_userTemporary_color-placeholder.svg.png'
		},
		glob:{
			'steward':'//upload.wikimedia.org/wikipedia/commons/thumb/7/75/Wikimedia_Community_Logo.svg/20px-Wikimedia_Community_Logo.svg.png',
			'Global_rollback': '//upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Meta-Wiki_Global_rollback-2000px.png/20px-Meta-Wiki_Global_rollback-2000px.png',
			'global-rollbacker': '//upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Meta-Wiki_Global_rollback-2000px.png/20px-Meta-Wiki_Global_rollback-2000px.png',
			'global-sysop' : '//upload.wikimedia.org/wikipedia/commons/thumb/5/57/Meta-Wiki_Global_sysop-2000px.png/20px-Meta-Wiki_Global_sysop-2000px.png',
			'Global_sysops' : '//upload.wikimedia.org/wikipedia/commons/thumb/5/57/Meta-Wiki_Global_sysop-2000px.png/20px-Meta-Wiki_Global_sysop-2000px.png',
			'global-renamer' : '//upload.wikimedia.org/wikipedia/commons/thumb/5/58/Global_renamer-logo.svg/20px-Global_renamer-logo.svg.png',
			'Global_renamer' : '//upload.wikimedia.org/wikipedia/commons/thumb/5/58/Global_renamer-logo.svg/20px-Global_renamer-logo.svg.png',
			'global-temporary-account-viewer':'//upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Global_temporary_account_IP_viewers.svg/20px-Global_temporary_account_IP_viewers.svg.png',
		}
	},

	make_callback: function () {
		var uinfo = {
			groups: {loc: [], glob: []},
			groupIndex: {},
			globalIndex: {},
			fields: {},
			lastedit: null,
			lastevent: null
		};

		var popup, icons;

		function buildDivs() {
			if (!icons) {
				icons = document.getElementById('userid-icons');
				if (!icons) {
					icons = document.createElement('DIV');
					icons.id = 'userid-icons';
					icons.className = 'metadata';
					Object.assign(icons.style, {
						display: 'inline-block', cursor: 'pointer'
					});
				}
			}
			if (!popup) {
				popup = document.getElementById('userid-popup');
				if (!popup) {
					popup = document.createElement('DIV');
					popup.id = 'userid-popup';
					Object.assign(popup.style, {
						display:'none',	position:'absolute', background:'#eef',	border:'1px solid black', padding:'3px', zIndex:'1000'
					});
				}
			}
		}

		function renderIcons() {
			buildDivs();
			icons.innerHTML = '';

			var fragments = {loc: document.createDocumentFragment(), glob: document.createDocumentFragment()};
			var el;
			
			['loc', 'glob'].forEach((source) => {
				for (let i = uinfo.groups[source].length - 1; i >= 0; i--) {
					const gName = uinfo.groups[source][i];
					const icon = UserIdentifier.images[source][gName];
					if (!icon) continue;
			
					el = document.createElement('IMG');
					Object.assign(el, {src: icon, width: 20, height: 20, title: gName});
					fragments[source].appendChild(el);
				}
			});

			var gen=document.createElement('SPAN');
			if(uinfo.fields.gender=='male'){
				gen.appendChild(document.createTextNode('♂'));
				gen.style.color='#89CFF0';
			} else if(uinfo.fields.gender=='female'){
				gen.appendChild(document.createTextNode('♀'));
				gen.style.color='#F4C2C2';
			}
			if(gen.firstChild) {
				gen.style.fontSize='16px';
				gen.title=uinfo.fields.gender;
				icons.appendChild(gen);
			}
			
			if (!fragments.loc.firstChild && !fragments.glob.firstChild) {
				el = document.createElement('IMG');
				el.src = UserIdentifier.images.loc['**'];
				el.width = 20;
				el.height = 20;
				icons.appendChild(el);
			} else {
				icons.appendChild(fragments.loc);
				icons.appendChild(fragments.glob);
			}
		}

		function renderPopup() {
			buildDivs();
			popup.innerHTML = '';

			var labels = {
				registration: 'Registered: ',
				expiry: 'Expire',
				last: 'Last ',
				editcount: 'Edits: ',
				emailable: 'Emailable: ',
				gender: 'Gender: '
			}

			for (const [field, label] of Object.entries(labels)) {
				if (uinfo.fields[field] != null && uinfo.fields[field] !== '') {
					popup.appendChild(document.createTextNode(label + uinfo.fields[field]));
					popup.appendChild(document.createElement('BR'));
				}
			}

			if (uinfo.groups.loc.length) {
				popup.appendChild(document.createTextNode('Groups: ' + uinfo.groups.loc.join(', ')));
				popup.appendChild(document.createElement('BR'));
			}

			if (uinfo.groups.glob.length) {
				popup.appendChild(document.createTextNode('Global groups: ' + uinfo.groups.glob.join(', ')));
			}
		}

		return function (r) {
			var id = r.requestid;

			if (id === 'localusers') {
				var u0 = r?.query?.users?.[0];
				
				if (typeof u0 === 'object') {
					if (u0.groups) {
						u0.groups.forEach((g) => {
							if (!uinfo.groupIndex[g]) {
								uinfo.groupIndex[g] = 1;
								uinfo.groups.loc.push(g);
							}
						});

						if (u0.groups.indexOf('temp') !== -1 && u0.registration) {
							var exp = new Date(new Date(u0.registration).getTime() + 90 * 86400000);
							uinfo.fields.expiry = (u0.tempexpired ? 'd: ' : 's: ') + exp.toISOString().split('.')[0] + 'Z';
							if (u0.tempexpired) {
								uinfo.groups.loc.splice(uinfo.groups.loc.indexOf('temp'), 1, 'temp (expired)');
							}
						}
					}

					Object.assign(uinfo.fields, {
						registration: u0.registration || '',
						editcount: u0.editcount,
						gender: u0.gender,
						emailable: (typeof u0.emailable !== 'undefined') ? 'yes' : 'no'
					});
				}

				var guig = r?.query?.globaluserinfo?.groups;

				if (typeof guig === 'object') {
					guig.forEach((g) => {
						if (!uinfo.globalIndex[g]) {
							uinfo.globalIndex[g] = 1;
							uinfo.groups.glob.push(g);
						}
					});
				}

			} else if (id === 'metausers' && typeof r?.query?.users?.[0]?.groups === 'object') {
				r.query.users[0].groups.forEach((g) => {
					if (/^global/i.test(g) && !uinfo.globalIndex[g]) {
						uinfo.globalIndex[g] = 1;
						uinfo.groups.glob.push(g);
					}
				});

			} else if (id === 'contribs' && typeof r?.query?.usercontribs === 'object') {
				uinfo.lastedit = r.query.usercontribs.length ? r.query.usercontribs[0].timestamp : 'never';

			} else if (id === 'log' && typeof r?.query?.logevents === 'object') {
				uinfo.lastevent = r.query.logevents.length ? r.query.logevents[0].timestamp : 'never';
			}

			if (uinfo.lastedit === 'never' && uinfo.lastevent === 'never') {
				uinfo.fields.last = 'edit/action: never';
			} else if (!uinfo.lastedit || (uinfo.lastevent && Date.parse(uinfo.lastevent) > Date.parse(uinfo.lastedit))) {
				uinfo.fields.last = 'logged action: ' + uinfo.lastevent;
			} else {
				uinfo.fields.last = 'edit: ' + uinfo.lastedit;
			}

			renderIcons();
			renderPopup();

			var h = document.getElementById('firstHeading');
			if (h && !icons.parentNode) h.insertBefore(icons, h.firstChild);

			if (!popup.parentNode) {
				var bar = document.querySelector('.vector-page-toolbar');
				if (bar) bar.insertBefore(popup, bar.firstChild);
				else if (h && h.parentNode) h.parentNode.insertBefore(popup, h.nextSibling);
			}

			icons.onclick = function () {
				popup.style.display = popup.style.display ? '' : 'none';
			};
			popup.onclick = function () {
				popup.style.display = 'none';
			};
		};
	},

	IDUser: function (name) {
		mw.loader.using('mediawiki.util', function () {
			name = decodeURIComponent(name).replace(/_/g, ' ');
			var cb = UserIdentifier.make_callback();

			var reqs = [
				{
					list:'users',
					ususers:name,
					usprop:'editcount|groups|registration|emailable|gender|tempexpired',
					meta:'globaluserinfo',
					guiuser:name,
					guiprop:'groups',
					requestid:'localusers'
				},
				{
					list:'users',
					ususers:name,
					usprop:'groups',
					origin:'*',
					requestid:'metausers'
				},
				{
					list:'usercontribs',
					ucuser:name,
					ucprop:'timestamp',
					uclimit:1,
					requestid:'contribs'
				},
				{
					list:'logevents',
					leuser:name,
					leprop:'timestamp',
					lelimit:1,
					requestid:'log'
				}
			];

			for (var i = 0; i < reqs.length; i++) {
				$.ajax({
					url:reqs[i].requestid === 'metausers'
						? '//meta.wikimedia.org/w/api.php'
						: mw.util.wikiScript('api'),
					type:'POST',
					dataType:'json',
					data:$.extend({}, reqs[i], { action:'query', format:'json' }),
					success:cb
				});
			}

			mw.util.addPortletLink(
				'p-cactions',
				mw.util.wikiScript() + '?title=Special%3ACentralAuth/' + encodeURIComponent(name),
				'SUL'
			);
		});
	},

	onLoad: function () {
		if (mw.config.get('wgRelevantUserName')) {
			UserIdentifier.IDUser(mw.config.get('wgRelevantUserName'));
		}
	}
};

$(document).ready(UserIdentifier.onLoad);