User:Chlod/Scripts/GlobalUserToolbox.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.
// Global User Toolbox
// Author: Chlod
// Version: 1.0.0-REL

// Adds the {{User_toolbox}} template to all user pages and talk pages.
// https://en.wikipedia.org/w/api.php?action=parse&format=json&text=%7B%7BUser%20toolbox%7C1%3DChlod%7D%7D&contentmodel=wikitext

// Unless you know what you are doing, do NOT modify this.
// If you want to configure GUT, simply add a "gutOptions" variable before importing.
const defaultGUTOptions = {
	"include_userpages": true, // pages in the "User" namespace
	"include_talkpages": true, // pages in the "User talk" namespace
	"include_subpages": true, // pages in the "User" namespace that are subpages (have a '/')
	"include_talksubpages": true, // pages in the "User talk" namespace that are subpages (have a '/')
	"insert_at_top": true, // insert the toolbox at the top
	"ignore_existing": true, // if there is already a user toolbox, don't add another
};

const userPageRegex = /^User:[^\//]+$/gi;
const userSubpageRegex = /^User:.+$/gi;
const userTalkPageRegex = /^User(?:_|\s)talk:[^\//]+$/gi;
const userTalkSubpageRegex = /^User(?:_|\s)talk:.+$/gi;
const userPageBaseRegex = /^([^\\/\n]+)/gi;

if (gutOptions === undefined) // in case the user does not configure
	var gutOptions = defaultGUTOptions;
	
// fill in unset keys of the user's config
var gutKeys = Object.keys(gutOptions);
for (var i in defaultGUTOptions) {
	if (!gutKeys.includes(i))
		gutOptions[i] = defaultGUTOptions[i];
}

function parseParams(parameterObject) {
	var finalParams = "";
	
	for (var i in parameterObject) {
		finalParams += `${i}=${encodeURIComponent(parameterObject[i])}&`;
	}
	
	return finalParams.replace(/&+$/, "");
}

$(document).ready(function (){
	var pageName = mw.config.get("wgPageName");
	if (
			(gutOptions["include_userpages"] && userPageRegex.test(pageName)) ||
			(gutOptions["include_talkpages"] && userTalkPageRegex.test(pageName)) ||
			(gutOptions["include_subpages"] && userSubpageRegex.test(pageName)) ||
			(gutOptions["include_talksubpages"] && userTalkSubpageRegex.test(pageName))
		) {
		var user = userPageBaseRegex.exec(mw.config.get("wgTitle"));
		
		if (user === null || user[0] === undefined)
			return;
		
		user = user[0]; // remap
		
		if (gutOptions["ignore_existing"] && document.getElementById(`User_toolbox_for_${user}`) !== null)
			return;
		
		var url = "/w/api.php";
		var params = parseParams({
			action: "parse",
			format: "json",
			text: `{{User_toolbox|state=expanded|1=${user}}}`,
			contentmodel: "wikitext"
		});
		var http = new XMLHttpRequest();

		http.open("GET", `${url}?${params}`, true);
		http.onreadystatechange = () => {
			if (http.readyState == 4 && http.status == 200) {
				var res = http.responseText;
				
				var parse;
				try {
					parse = JSON.parse(res);
				} catch (e) { /* ignored */ }
				
				if (parse === null || parse === undefined) {
					console.error("Error parsing API response.");
					return;
				}
				
				if (parse["parse"] === undefined
					|| parse["parse"]["text"] === undefined
					|| parse["parse"]["text"]["*"] === undefined) {
					console.error("Oh, the humanity!\n\nGlobal User Toolbox could not verify the contents of the API response. Either an error has occurred, or the request has been tampered with. Maybe try refreshing?");
					console.log(parse);
					return;
				} else {
					parse = parse["parse"] // remap
				}
				
				var page_content = document.getElementById("mw-content-text");
				page_content.insertAdjacentHTML(gutOptions["insert_at_top"] ? "afterbegin" : "beforeend",
					`<div id="gut_output">${parse["text"]["*"]}</div>`);
			}
		};
		http.send(null);
	}
});