User:Magiczocker/LookupUser.js

From Support Wiki
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/* jshint esversion: 6 */
( function ( $, mw ) {
	'use strict';

	const config = mw.config.get( [
			'wgLegalTitleChars',
			'wgUserLanguage',
			'wgMonthNames',
			'wgPageName'
		] ),
		globalgroups = ['bureaucrat', 'autoconfirmed'];

	var paused = false,
		output = [],
		elements = {},
		input,
		button,
		widget,
		length,
		count = 0,
		found = 0,
		username = '',
		i18n,
		tbody,
		table,
		wikis,
		regex = new RegExp('^[' + config.wgLegalTitleChars + ']+$');

	if ( config.wgPageName !== 'User:Magiczocker/LookupUser' ) {
		return;
	}

	function log( msg ) {
		console.log( '[LookupContribs]', msg );
	}

	function wikiLink( wiki, page, text, title, query ) {
		return mw.html.element( 'a', {
			href: wiki + mw.util.getUrl( page ) + (query || ''),
			title: title
		}, text );
	}

	function formatDate( date ) {
		if ( date.length ) {
			const d = new Date( date );
			return ( '0' + d.getHours() ).slice( -2 ) + ':' + ( '0' + d.getMinutes() ).slice( -2 ) + ', ' + // Time
			d.getDate() + ' ' + config.wgMonthNames[ d.getMonth() + 1 ] + ' ' + d.getFullYear(); // Date
		} else {
			return '';
		}
	}

	function filterEntry( groups ) {
		return ![ '*', 'user', 'autoconfirmed' ].concat( globalgroups ).includes( groups );
	}

	function updateCount() {
		count++;
		if ( count === length ) {
			widget.setNotices( [] );
			widget.setSuccess( [ mw.format(i18n['wikis-found'], mw.language.convertNumber(found), mw.language.convertNumber(length)) ] );
			$( table ).tablesorter();
			input.setReadOnly(false);
			button.setDisabled(false);
		} else {
			widget.setNotices( [ mw.format(i18n['wikis-checking'], mw.language.convertNumber(count), mw.language.convertNumber(length)) ] );
		}
	}

	function unpause() {
		paused = false;
		process();
	}

	function pause() {
		paused = true;
		setTimeout( unpause, 5000 );
	}

	function process() {
		if ( paused ) {
			return;
		}
		const host = wikis[ count ];
		if ( host ) {
			const username = input.getValue().trim();
			var queryArgs = {
				action: 'query',
				format: 'json',
				list: [ 'users', 'usercontribs' ].join( '|' ),
				formatversion: 2,
				uclimit: 1,
				ucprop: 'timestamp',
				origin: '*'
			};

			if ( mw.util.isIPAddress(username, true) ) {
				queryArgs.usprop = [ 'editcount', 'blockinfo' ].join( '|' );
				queryArgs.ucuser = username;
			} else {
				queryArgs.usprop = [ 'editcount', 'groups', 'blockinfo' ].join( '|' );
				if ( /^#\d+$/.test(username) ) {
					var userid = username.slice(1);
					queryArgs.ususerids = userid;
					queryArgs.ucuserids = userid;
				}
				else {
					queryArgs.ususers = username;
					queryArgs.ucuser = username;
				}
			}

			fetch( host + '/api.php?' + new URLSearchParams( queryArgs ), {
				method: 'GET'
			} ).then( function ( response ) {
				return response.json();
			} ).then( function ( data ) {
				const user = data.query.users[ 0 ] || {
						groups: [],
						editcount: 0
					},
					row = tbody.insertRow(),
					url = row.insertCell(),
					edit = row.insertCell(),
					edits = row.insertCell(),
					rights = row.insertCell(),
					blocks = row.insertCell(),
					groups = mw.util.isIPAddress(username, true) ? [] : user.groups.filter( filterEntry ),
					timestamp = data.query.usercontribs[ 0 ] ? data.query.usercontribs[ 0 ].timestamp : '';

				if ( timestamp.length || user.blockid ) {
					found++;
				} else {
					row.style.display = 'none';
				}

				url.innerHTML = wikiLink(
					host,
					( mw.util.isIPAddress(username, true) ? 'Special:Contributions/' : 'User:' ) + username,
					host,
					mw.format(i18n['wikis-url-content'], username, host)
				);
				edit.textContent = formatDate( timestamp );
				edits.innerHTML = wikiLink(
					host,
					'Special:Contributions/' + username,
					mw.language.convertNumber(user.editcount),
					mw.format(
						mw.language.convertPlural(user.editcount, i18n['wikis-edits-content']),
						mw.language.convertNumber(user.editcount),
						host
					)
				);
				if ( mw.util.isIPAddress(username, true) ) rights.remove();
				else rights.textContent = groups.filter(filterEntry).join(', ');
				blocks.innerHTML = wikiLink(
					host,
					'Special:Log/block?page=User:' + username,
					user.blockid ? 'Y' : '—',
					i18n[ 'wikis-blocked-content' ]
				);

				updateCount();
				process();
			} ).catch( function ( error ) {
				pause();
				log( error );
			} );
		} else {
			log( 'Done' );
		}
	}

	function getWikis() {
		fetch( 'https://support.wiki.gg/wiki/User:Magiczocker/list.json?action=raw', {
			method: 'GET'
		} ).then( function ( response ) {
			return response.json();
		} ).then( function ( data ) {
			wikis = data.flatMap( function ( wiki ) {
				return wiki.lang.map( function ( lang ) {
					// [name].wiki.gg/en redirects to [name].wiki.gg
					return 'https://' + wiki.name + '.wiki.gg' + ( lang === 'en' ? '' : '/' + lang );
				} );
			} );
			length = wikis.length;
			process();
		} ).catch( log );
	}

	function lookupWikis() {
		table = document.createElement( 'table' );
		table.classList = 'wikitable';
		table.style.width = '100%';
		table.innerHTML =
			'<thead>' +
				'<tr>' +
					mw.html.element( 'th', {}, i18n['wikis-title'] ) +
					mw.html.element( 'th', {}, i18n['wikis-last-edited'] ) +
					mw.html.element( 'th', {}, i18n['wikis-edits'] ) +
					( mw.util.isIPAddress(username, true) ? '' : mw.html.element( 'th', {}, i18n['wikis-rights'] ) ) +
					mw.html.element( 'th', {}, i18n['wikis-blocked'] ) +
				'</tr>' +
			'</thead>' +
			'<tbody>' +
			'</tbody>';
		tbody = table.querySelector( 'tbody' );
		elements.wikis.append( table );
		if ( wikis ) {
			process();
		} else {
			getWikis();
		}
	}

	function start() {
		if (input.isReadOnly() || button.isDisabled()) return;

		// Reset
		count = 0;
		found = 0;
		output = [];
		elements.userinfo.textContent = '';
		elements.wikis.textContent = '';
		widget.setSuccess( [] );
		widget.setNotices( [] );
		widget.setWarnings( [] );
		widget.setErrors( [] );
		username = input.getValue().trim();

		if (!username.length) return;
		input.setReadOnly(true);
		button.setDisabled(true);
		widget.setNotices( [ i18n['main-loading'] ] );

		// IPs
		if ( mw.util.isIPAddress(username, true) ) {
			username = mw.util.sanitizeIP(username);
			elements.userinfo.innerHTML =
				'<fieldset>' +
					mw.html.element( 'legend', {}, i18n['global-header'] ) +
					'<div>' + mw.html.element( 'strong', {}, i18n['global-username'] ) + ' ' + mw.html.escape( mw.util.prettifyIP( username ) ) + '</div>' +
				'</fieldset>';
			lookupWikis();
			return;
		}

		// Usernames
		var queryArgs = {
			action: 'query',
			format: 'json',
			origin: '*',
			list: 'users',
			usprop: [
				'gender',
				'groups',
				'registration',
				'emailable'
			].join( '|' ),
			formatversion: 2
		};
		if ( /^#\d+$/.test(username) ) queryArgs.ususerids = username.slice(1);
		else queryArgs.ususers = username;
		fetch( 'https://support.wiki.gg/api.php?' + new URLSearchParams( queryArgs ), {
			method: 'GET'
		} ).then( function ( response ) {
			return response.json();
		} ).then( function ( data ) {
			var users = data.query.users[ 0 ];
			if ( users.missing || users.invalid ) {
				widget.setNotices( [] );
				widget.setErrors( [ mw.format(i18n['global-error'], username) ] );
				input.setReadOnly(false);
				button.setDisabled(false);
			} else {
				username = users.name;
				elements.userinfo.innerHTML =
					'<fieldset>' +
						mw.html.element( 'legend', {}, i18n['global-header'] ) +
						'<div>' + mw.html.element( 'strong', {}, i18n['global-username'] ) + ' ' + mw.html.escape( users.name ) + '</div>' +
						'<div>' + mw.html.element( 'strong', {}, i18n['global-id'] ) + ' ' + mw.html.escape( '#' + users.userid ) + '</div>' +
						'<div>' + mw.html.element( 'strong', {}, i18n['global-groups'] ) + ' ' + mw.html.escape( users.groups.filter( function (groups) {
							return globalgroups.includes(groups);
						} ).join(', ') ) + '</div>' +
						'<div>' + mw.html.element( 'strong', {}, i18n['global-registration'] ) + ' ' + mw.html.escape( users.registration ? formatDate(users.registration) : i18n['registration-unknown'] ) + '</div>' +
						'<div>' + mw.html.element( 'strong', {}, i18n['global-emailable'] ) + ' ' + mw.html.escape( users.emailable ? 'Yes' : 'No' ) + '</div>' +
						'<div>' + mw.html.element( 'strong', {}, i18n['global-gender'] ) + ' ' + mw.html.escape( i18n.gender[users.gender] || users.gender ) + '</div>' +
					'</fieldset>';
				lookupWikis();
			}
		} ).catch( log );
	}

	/**
	 * Initializes the script.
	 * @param {Object} $content - Page content.
	 */
	function init( $content ) {
		var main = $content.find( '#globalTracker:not(.loaded)' )[ 0 ];
		if ( !main ) {
			return;
		}
		main.classList.add( 'loaded' );
		main.innerHTML = '';
		input = new mw.widgets.UserInputWidget( {
			required: true,
			validate: function(inputValue) {
				inputValue = inputValue.trim();
				if ( regex.test(inputValue) && !/[:/]/.test(inputValue) ) return true;
				if ( mw.util.isIPAddress(inputValue, true) ) {
					if ( mw.util.isIPAddress(inputValue, false) ) return true;
					var iprange = inputValue.split('/')[1];
					if ( mw.util.isIPv4Address(inputValue, true) && iprange < 16 ) return false;
					if ( mw.util.isIPv6Address(inputValue, true) && iprange < 32 ) return false;
					return true;
				}
				if ( /^#\d+$/.test(inputValue) ) return true;
				return false;
			},
			placeholder: i18n['main-placeholder']
		} );
		button = new OO.ui.ButtonWidget( {
			label: i18n['main-button'],
			flags: ['primary', 'progressive']
		} );
		widget = new OO.ui.ActionFieldLayout(
			input, button, {
				id: 'globalTracker',
				label: i18n['main-header'],
				align: 'top'
			}
		);
		$(main).append(
			widget.$element,
			$('<div>').attr('id', 'tracker-userinfo'),
			$('<div>').attr('id', 'tracker-wikis')
		);
		elements = {
			userinfo: $content.find('#tracker-userinfo')[0],
			wikis: $content.find('#tracker-wikis')[0]
		};
		input.on('enter', function() {
			input.getValidity().done(start);
		});
		button.on('click', function() {
			input.getValidity().done(start);
		});
		const targetParam = mw.util.getParamValue('target');
		if (targetParam) {
			input.setValue(targetParam);
			input.getValidity().done(start);
		}
	}

	mw.loader.using( [
		'oojs-ui-widgets',
		'mediawiki.widgets.UserInputWidget',
		'jquery.tablesorter',
		'mediawiki.language',
		'mediawiki.util'
	] ).then( function () {
		/* Load i18n */
		fetch( 'https://support.wiki.gg/wiki/User:Magiczocker/LookupUser-i18n.json?action=raw', {
			method: 'GET'
		} ).then( function ( response ) {
			return response.json();
		} ).then( function ( i18no ) {
			i18n = i18no[ config.wgUserLanguage ] || i18no.en;
			mw.hook( 'wikipage.content' ).add( init );
		} ).catch( log );
	} );
}( window.jQuery, window.mediaWiki ) );