User:PleaseStand/userinfo-dev.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.
// based on http://en.wikipedia.org/wiki/User:Fran_Rogers/dimorphism.js 
// and on http://en.wikipedia.org/wiki/User:Splarka/sysopdectector.js

( function ( mw, $ ) {

	var h = mw.html,
		api,
		ns = mw.config.get( 'wgNamespaceNumber' ),
		title = mw.config.get( 'wgTitle' );

	// Bail out unless on a user or user talk page, and not a subpage.
	if ( ns !== 2 && ns !== 3 || title.indexOf( '/' ) >= 0 ) {
		return;
	}

	// TODO: add additional languages
	mw.messages.set( {
		'ps-userinfo-gendersymbol-male': '♂',
		'ps-userinfo-gendersymbol-female': '♀',
		'ps-userinfo-gendersymbol-unknown': '',
		'ps-userinfo-itemseparator': '$1\u00a0| $2',
		'ps-userinfo-groupseparator': '$1, $2',

		'ps-userinfo-seconds': '$1 {{PLURAL:$1|second|seconds}}',
		'ps-userinfo-minutes': '$1 {{PLURAL:$1|minute|minutes}}',
		'ps-userinfo-hours': '$1 {{PLURAL:$1|hour|hours}}',
		'ps-userinfo-days': '$1 {{PLURAL:$1|day|days}}',
		'ps-userinfo-weeks': '$1 {{PLURAL:$1|week|weeks}}',
		'ps-userinfo-months': '$1 {{PLURAL:$1|month|months}}',
		'ps-userinfo-years': '$1 {{PLURAL:$1|year|years}}',
		'ps-userinfo-years-months': '$1 {{PLURAL:$1|year|years}} $2 {{PLURAL:$2|month|months}}',

		'ps-userinfo-blocked': 'BLOCKED',
		'ps-userinfo-editcount': '$1 {{PLURAL:$1|edit|edits}}',
		'ps-userinfo-invalid': 'invalid username',
		'ps-userinfo-ipv4': 'IPv4 address',
		'ps-userinfo-ipv6': 'IPv6 address',
		'ps-userinfo-lastedited': 'last edited [$2 $1 ago]',
		'ps-userinfo-missing': 'username not registered',
		'ps-userinfo-registration': '$1 old',
		'ps-userinfo-user': '{{GENDER:$1|registered user}}'
	} );

	/**
	 * Get the user's information by performing an AJAX request and processing the response.
	 * @param {string} userName The user to retrieve information for
	 * @return {jQuery.Deferred}
	 */
	function getInfo( userName ) {
		return api.get( {
			action: 'query',
			list: 'users|usercontribs',
			maxage: 300,
			uclimit: 1,
			ucprop: 'timestamp',
			ucuser: userName,
			usprop: 'blockinfo|editcount|gender|registration|groups',
			ususers: userName
		} ).then( function ( data ) {
			var query = data.query, user = query.users[0], contribs = query.usercontribs;

			return {
				name: userName,
				isInvalid: 'invalid' in user,
				isIPv4: mw.util.isIPv4Address( userName ),
				isIPv6: mw.util.isIPv6Address( userName ),
				isMissing: 'missing' in user,
				groups: user.groups || [],
				editCount: 'editcount' in user ? user.editcount : null,
				registration: user.registration ? new Date( user.registration ) : null,
				isBlocked: 'blockexpiry' in user,
				gender: user.gender || 'unknown',
				lastEdited: ( contribs && contribs[0] ) ? new Date( contribs[0].timestamp ) : null
			};
		} );
	}

	/**
	 * Display the user's information on screen.
	 * @param info Information about the user
	 */
	function displayInfo( info ) {
		var userPrefix = mw.config.get( 'wgFormattedNamespaces' )[2] + ':',
			items = [],
			groups = [],
			text = '';

		if ( info.isBlocked ) {
			items.push( h.element( 'a', { href:
				mw.util.wikiScript( 'index' ) + '?' + $.param( {
					title: 'Special:Log',
					page: userPrefix + info.name
				} )
			}, new h.Raw( h.element( 'strong', {}, mw.msg( 'ps-userinfo-blocked' ) ) ) ) );
		}

		if ( info.isMissing ) {
			items.push( mw.message( 'ps-userinfo-missing' ).escaped() );
		} else if ( info.isIPv4 ) {
			items.push( mw.message( 'ps-userinfo-ipv4' ).escaped() );
		} else if ( info.isIPv6 ) {
			items.push( mw.message( 'ps-userinfo-ipv6' ).escaped() );
		} else if ( info.isInvalid ) {
			items.push( mw.message( 'ps-userinfo-invalid' ).escaped() );
		} else {
			$.each( info.groups, function ( i, v ) {
				if ( $.inArray( v, ['*', 'user', 'named', 'autoconfirmed'] ) < 0 ) {
					groups.push( mw.message( 'group-' + v + '-member', info.gender ).escaped() );
				}
			} );
			if ( groups.length ) {
				items.push( groups.join( mw.message( 'ps-userinfo-groupseparator', '', '' ).escaped() ) );
			} else {
				items.push( mw.message( 'ps-userinfo-user', info.gender ).escaped() );
			}

			if ( info.registration ) {
				items.push( mw.message(
					'ps-userinfo-registration',
					buildDurationMessage( info.registration, new Date() ).text(),
					info.gender
				).escaped() );
			}

			if ( info.editCount !== null ) {
				items.push( h.element( 'a', { href:
					'https://xtools.wmcloud.org/ec/' +
					encodeURIComponent( location.hostname ) + '/' +
					encodeURIComponent( info.name )
				}, mw.message( 'ps-userinfo-editcount', info.editCount ).text() ) );
			}
		}

		if ( info.lastEdited ) {
			items.push( mw.message(
				'ps-userinfo-lastedited',
				buildDurationMessage( info.lastEdited, new Date() ).escaped(),
				$( '<a>' ).prop( 'href', mw.util.getUrl( 'Special:Contributions/' + info.name ) ),
				mw.html.escape( info.name )
			).parse() );
		}

		// Add the gender symbol after the user's name
		$( '<span>' )
			.prop( 'id', 'ps-gender-' + info.gender )
			.css( {
				paddingLeft: '0.25em',
				fontFamily: '"Lucida Grande", "Lucida Sans Unicode", sans-serif',
				fontSize: '75%'
			} )
			.text( mw.msg( 'ps-userinfo-gendersymbol-' + info.gender ) )
			.appendTo( '#firstHeading' );

		// Replace the subtitle with the rest of the info
		$( '#siteSub' ).html( items.join( mw.message( 'ps-userinfo-itemseparator', '', '' ).escaped() ) );
	}

	/**
	 * Load messages corresponding to MediaWiki user groups into mw.messages.
	 * @return {jQuery.Deferred}
	 */
	function loadGroupMemberMessages() {
		return api.get( {
			action: 'query',
			amfilter: '-member',
			amlang: mw.config.get( 'wgUserLanguage' ),
			amprefix: 'group-',
			maxage: 86400,
			meta: 'allmessages'
		} ).then( function ( data ) {
			$.each( data.query.allmessages, function ( i, message ) {
				mw.messages.set( message.name, message['*'] );
			} );
		} );
	}

	/**
	 * Convert a duration to a message object.
	 * @param {Date} start The duration's start
	 * @param {Date} end The duration's end
	 * @return {mediaWiki.Message}
	 */
	function buildDurationMessage( start, end ) {
		var age = ( end - start ) / 1000; // start with seconds
		if ( age < 60 ) {
			return mw.message( 'ps-userinfo-seconds', Math.floor( age ) );
		}

		age /= 60; // convert to minutes
		if ( age < 60 ) {
			return mw.message( 'ps-userinfo-minutes', Math.floor( age ) );
		}

		age /= 60; // convert to hours
		if ( age < 24 ) {
			return mw.message( 'ps-userinfo-hours', Math.floor( age ) );
		}

		age /= 24; // convert to days
		if ( age < 7 ) {
			return mw.message( 'ps-userinfo-days', Math.floor( age ) );
		}

		age /= 7; // convert to weeks
		if ( age < 4.3481 ) {
			return mw.message( 'ps-userinfo-weeks', Math.floor( age ) );
		}

		age /= 4.3481; // convert to months
		if ( age < 12 ) {
			return mw.message( 'ps-userinfo-months', Math.floor( age ) );
		}

		// convert to years and months
		var years = Math.floor( age / 12 ), months = Math.floor( age % 12 );
		if ( months ) {
			return mw.message( 'ps-userinfo-years-months', years, months );
		}
		return mw.message( 'ps-userinfo-years', years );
	}

	mw.loader.using( [
		'mediawiki.api',
		'mediawiki.jqueryMsg',
		'mediawiki.language',
		'mediawiki.util'
	], function () {
		api = new mw.Api();
		loadGroupMemberMessages().done( function () {
			getInfo( title ).done( displayInfo );
		} );
	} );
	
} )( mediaWiki, jQuery );