User:MarkusRost/common.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.
;(function($, mw) {
	'use strict';

	const config = mw.config.get([
		'wgUserLanguage',
		'wgMonthNames',
		'wgPageName'
	]);
	if (config.wgPageName !== 'User:Magiczocker/Tracker') return;

	var output = [],
		elements = {},
		length,
		count = 0,
		username = '',
		i18n,
		wikis;

	/**
	 * Log error to console.
	 * @param {string} msg - Error message.
	 */
	function log(msg) {
		console.log('[LookupContribs]', msg);
	}

	/**
	 * Generates the wiki URL from wiki name.
	 * @param {string} wikiName - Name of the wiki.
	 * @param {string} wikiLang - Optional wiki language for non-en wikis.
	 * @returns {string} Generated wiki link.
	 */
	function generateLink(wikiName, wikiLang) {
		return 'https://' + wikiName + '.wiki.gg' + (wikiLang ? '/' + wikiLang : '');
	}

	/**
	 * Generates a wiki link.
	 * @param {string} wiki - Wiki name
	 * @param {string} page - Wiki article or special page.
	 * @param {string} text - Link text.
	 * @returns {string} Generated wiki link.
	 */
	function wikiLink(wiki, page, text, hover_text) {
		return '<a href="' + wiki + '/wiki/' + page + '" title="' + hover_text + '">' + text + '</a>';
	}

	/**
	 * Formats time from ISO format to english date format.
	 * @param {string} date - Date in ISO format.
	 * @returns {string} Formatted time and date.
	 */
	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 '';
		}
	}

	/**
	 * Filter irrelevant user groups from an array.
	 * @param {object} groups - Array with all user groups.
	 * @returns {string} Fitered array.
	 */
	function filterEntry(groups) {
		return !['*', 'user', 'autoconfirmed'].includes(groups);
	}

	/**
	 * Generates output table.
	 */
	function done() {
		const table = document.createElement('table');
		table.classList = 'wikitable';
		table.style.width = '100%';
		table.innerHTML =
			'<thead>' +
				'<tr>' +
					'<th>' + i18n['wikis-title'] + '</th>' +
					'<th>' + i18n['wikis-url'] + '</th>' +
					'<th>' + i18n['wikis-last-edited'] + '</th>' +
					'<th>' + i18n['wikis-edits'] + '</th>' +
					'<th>' + i18n['wikis-rights'] + '</th>' +
					'<th>' + i18n['wikis-blocked'] + '</th>' +
				'</tr>' +
			'</thead>' +
			'<tbody>' +
			'</tbody>';
		const tbody = table.querySelector('tbody');

		for (var i=0; i<output.length; i++) {
			if (output[i].timestamp.length > 0 || output[i].blocks) {
				const row = tbody.insertRow(),
					title = row.insertCell(0),
					url = row.insertCell(1),
					edit = row.insertCell(2),
					edits = row.insertCell(3),
					rights = row.insertCell(4),
					blocks = row.insertCell(5),
					groups = output[i].groups.filter(filterEntry);

				title.textContent = output[i].name;
				url.innerHTML = wikiLink(
					output[i].host,
					'User:' + username,
					output[i].host,
					i18n['wikis-url-content']
						.replace('$1', username)
						.replace('$2', output[i].name)
				);
				edit.textContent = formatDate(output[i].timestamp);
				edits.innerHTML = wikiLink(
					output[i].host,
					'Special:Contributions/' + username,
					output[i].editcount,
					i18n['wikis-edits-content' + (output[i].editcount === 1 ? '' : '-plural')]
						.replace('$1', output[i].editcount)
						.replace('$2', output[i].name)
				);
				rights.textContent = groups.join(', ');
				blocks.innerHTML = wikiLink(
					output[i].host,
					'Special:Log/block?page=User:' + username,
					output[i].blocks ? 'Y' : '—',
					i18n['wikis-blocked-content']
				);
			}
		}
		elements.wikis.textContent = '';
		$(table).tablesorter();
		elements.wikis.append(table);
		elements.button.disabled = false;
	}

	/**
	 * Update receive count and message.
	 */
	function updateCount() {
		count++;
		elements.wikis.textContent = i18n['wikis-checking']
			.replace('$1', count)
			.replace('$2', length);
		if (count === length) done();
	}

	/**
	 * Query userdata from wiki.
	 * @param {string} host - URL of the wiki.
	 * @param {number} id - Index for the output table.
	 */
	function sendRequest(host, id) {
		fetch(host + '/api.php' +
			'?action=query' +
			'&format=json' +
			'&list=users%7Cusercontribs' +
			'&formatversion=2' +
			'&usprop=editcount%7Cgroups%7Cblockinfo' +
			'&ususers=' + encodeURIComponent(elements.input.value) +
			'&uclimit=1' +
			'&ucuser=' + encodeURIComponent(elements.input.value) +
			'&ucprop=timestamp' +
			'&origin=*' +
			'&meta=siteinfo' +
			'&siprop=general'
		).then(function(response) {
			return response.json();
		}).then(function(data) {
			const user = data.query.users[0];
			output[id] = {
				name: data.query.general.sitename,
				host: host,
				editcount: user.editcount,
				groups: user.groups,
				timestamp: data.query.usercontribs[0] ? data.query.usercontribs[0].timestamp : '',
				blocks: user.blockid,
				id: id
			};
			updateCount();
		}).catch(function(error) {
			log(error);
			updateCount();
		});
	}

	/**
	 * Initiate wiki list.
	 */
	function lookupWikis() {
		length = wikis.length;
		for (var i=0; i<length; i++) {
			sendRequest(wikis[i], i);
		}
	}

	/**
	 * Query list with all wikis.
	 */
	function getWikis() {
		fetch('https://support.wiki.gg/wiki/User:MarkusRost/wikis.json?action=raw')
		.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
					if (lang === 'en') return generateLink(wiki.name);
					return generateLink(wiki.name, lang);
				});
			});
			lookupWikis();
		}).catch(log);
	}

	/**
	 * Button action to start the process.
	 */
	function start() {
		if (elements.button.disabled) return;

		// Reset
		count = 0;
		output = [];
		elements.userinfo.innerHTML = i18n['main-loading'];
		elements.wikis.innerHTML = '';

		if (elements.input.value.length === 0) return;
		elements.button.disabled = true;

		fetch('https://support.wiki.gg/api.php' +
			'?action=query' +
			'&format=json' +
			'&origin=*' +
			'&list=users' +
			'&formatversion=2' +
			'&usprop=gender%7Cregistration%7Cemailable' +
			'&ususers=' + encodeURIComponent(elements.input.value)
		).then(function(response) {
			return response.json();
		}).then(function(data) {
			const users = data.query.users[0];
			if (users.missing || users.invalid) {
				elements.userinfo.innerHTML =
					'<div class="mw-message-box-error errorbox mw-message-box">' +
						i18n['global-error'].replace('$1', elements.input.value) +
					'</div>';
				elements.button.disabled = false;
			} else {
				username = users.name;
				elements.userinfo.innerHTML =
					'<fieldset>' +
						'<legend>' + i18n['global-header'] + '</legend>' +
						'<strong>' + i18n['global-username'] + '</strong> ' + users.name + '<br>' +
						'<strong>' + i18n['global-id'] + '</strong> #' + users.userid + '<br>' +
						'<strong>' + i18n['global-gender'] + '</strong> ' + users.gender + '<br>' +
						'<strong>' + i18n['global-emailable'] + '</strong> ' + (users.emailable ? 'Yes' : 'No') + '<br>' +
						'<strong>' + i18n['global-registration'] + '</strong> ' + formatDate(users.registration) +
					'</fieldset>';
				elements.wikis.textContent = i18n['main-loading'];
				if (wikis) {
					lookupWikis();
				} else {
					getWikis();
				}
			}
		}).catch(log);
	}

	/**
	 * Initializes the script.
	 * @param {object} i18no - Translation strings.
	 */
	function init(i18no) {
		i18n = i18no[config.wgUserLanguage] || i18no.en;
		document.getElementById('globalTracker').innerHTML =
			'<fieldset>' +
				'<legend>' + i18n['main-header'] + '</legend>' +
				'<input type="text" name="target" size="50" placeholder="' + i18n['main-placeholder'] + '">&nbsp;' +
				'<input type="submit" class="button" value="' + i18n['main-button'] + '">' +
			'</fieldset>' +
			'<div id="tracker-userinfo"></div>' +
			'<div id="tracker-wikis"></div>';
		elements = {
			input: document.querySelector('fieldset > input[type="text"]'),
			button: document.querySelector('fieldset > input[type="submit"]'),
			userinfo: document.getElementById('tracker-userinfo'),
			wikis: document.getElementById('tracker-wikis')
		};
		elements.button.addEventListener('click', start);
		elements.input.addEventListener('keypress', function(e) {
			if (e.keyCode === 13) start();
		});
	}

	/**
	 * Query list with all translations.
	 */
	function preload() {
		fetch('https://support.wiki.gg/wiki/User:Magiczocker/i18n.json?action=raw')
		.then(function(response) {
			return response.json();
		}).then(init)
		.catch(log);
	}

	mw.loader.using( ['jquery.tablesorter'] ).then(preload);
})(window.jQuery, window.mediaWiki);