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.
// <nowiki>

mw.loader.using([ 'mediawiki.api', 'mediawiki.jqueryMsg' ], function() {
	let isIP = mw.util.isIPAddress;
	mw.loader.load(`${window.location.origin + mw.config.get("wgScriptPath")}/index.php?title=User:Awesome_Aasim/usergroups.css&action=raw&ctype=text/css`, "text/css");
	mw.loader.load(`${window.location.origin + mw.config.get("wgScriptPath")}/index.php?title=MediaWiki:Usergroups.css&action=raw&ctype=text/css`, "text/css");
	if (!window.userGroupsLoaded) {
		window.userGroupsLoaded = true;
		window.userGroupsCache = window.userGroupsCache ?? {};
		$(document).ready(async function() {
			let user;
			if (mw.config.get("wgNamespaceNumber") == 2 || mw.config.get("wgNamespaceNumber") == 3) {
				user = mw.config.get("wgTitle").split("/")[0];
			} else if (mw.config.get("wgNamespaceNumber") == -1) {
				user = mw.config.get("wgTitle").split("/")[1] ? mw.config.get("wgTitle").split("/")[1] : null;
			} else {
				return;
			}
			user = decodeURIComponent(user);
			if (user) {
				let res = await $.get(mw.config.get('wgScriptPath') + '/api.php', {
					action: "query",
					list: "users|blocks",
					ususers: user,
					usprop: "groups|blockinfo",
					bkusers: isIP(user) ? undefined : user,
					bkip: isIP(user) ? user : undefined,
					format: "json"
				});
				if (!res.error) {
					var userdata = res.query.users[0];
					var blockdata = res.query.blocks.length > 0 ? res.query.blocks[0] : null;
					var usergroups = "";
					var messagesArray = [];
					var linksArray = [];
					if (userdata.invalid === null || userdata.invalid === undefined) {
						for (let group of userdata.groups) {
							messagesArray.push(`group-${group}-member`);
							linksArray.push(`grouppage-${group}`);
						}
					}
					messagesArray.push('blockedtitle');
					await new mw.Api().loadMessagesIfMissing(messagesArray);
					await new mw.Api().loadMessagesIfMissing(linksArray, {amlang: mw.config.get("wgContentLanguage")});
					$("#siteSub").text("");
					$("#siteSub").css("display", "block");
					$("#siteSub").append($('<div style="font-family:sans-serif;font-style: normal;" id="usergroups"></div>'));
					if (userdata.blockid || blockdata) {
						// readd block ID
						$("#firstHeading").append(`&nbsp;(<b><a href="${mw.config.get("wgScriptPath")}/index.php?title=Special:BlockList&wpTarget=${user}">${mw.message(`blockedtitle`)}</a></b>)`);
					}
					if (userdata.invalid === null || userdata.invalid === undefined) {
						for (let group of userdata.groups) {
							if (group == "*" || group == "user") continue;
							$("#usergroups").append(`<span class="usergroup usergroup-${group}"><a href="${mw.config.get("wgArticlePath").replace(/\$1/g, mw.message(`grouppage-${group}`).exists() ? mw.message(`grouppage-${group}`).parse() : `Project:${group}`)}">${mw.message(`group-${group}-member`).parse()}</a></span>&nbsp;`);
						}
					}
				} else {
					console.error(res.error);
				}
			}
		});
		$(document).ready(function() {
			$(".mw-userlink").each(async function() {
				let that = this;
				let url = new URL($(this).attr("href"), location.origin);
				let user = url.searchParams.get("title") ? url.searchParams.get("title").replace(mw.config.get("wgFormattedNamespaces")[2] + ":", "") : url.pathname.replace(mw.config.get("wgArticlePath").replace("$1", mw.config.get("wgFormattedNamespaces")[2] + ":"), "").replaceAll("_", " ");
				user = decodeURIComponent(user);
				if (user.split("/").length > 1) return;
				if (window.userGroupsCache[user]) {
					return;
				} else {
					window.userGroupsCache[user] = true;
				}
				let res = typeof window.userGroupsCache[user] == "object" ? window.userGroupsCache[user] : await $.get(mw.config.get('wgScriptPath') + '/api.php', {
					action: "query",
					list: "users|blocks",
					ususers: user,
					usprop: "groups|blockinfo",
					bkusers: isIP(user) ? undefined : user,
					bkip: isIP(user) ? user : undefined,
					format: "json"
				});
				if (res.error) {
					console.error(res.error);
					delete window.userGroupsCache[user];
				} else {
					window.userGroupsCache[user] = res;
					var userdata = res.query.users.length > 0 ? res.query.users[0] : {};
					var blockdata = res.query.blocks.length > 0 ? res.query.blocks[0] : null;
					var classString = "";
					classString += 'usergroup ';
					if (userdata.blockid) {
						classString += "usergroup-blocked ";
						if (userdata.blockpartial !== null && userdata.blockpartial !== undefined) {
							classString += "usergroup-blockedpartial ";
						}
					} else if (blockdata) {
						classString += "usergroup-blocked ";
						if (blockdata.partial !== null && blockdata.partial !== undefined) {
							classString += "usergroup-blockedpartial ";
						}
					}
					if (userdata.invalid === null || userdata.invalid === undefined) {
						for (let group of userdata.groups) {
							if (group == "*" || group == "user") continue;
							classString += `usergroup-${group} `;
						}
					}
					$(`.mw-userlink`).each(function() {
						let url = new URL($(this).attr("href"), location.origin);
						let uuser = url.searchParams.get("title") ? url.searchParams.get("title").replace(mw.config.get("wgFormattedNamespaces")[2] + ":", "") : url.pathname.replace(mw.config.get("wgArticlePath").replace("$1", mw.config.get("wgFormattedNamespaces")[2] + ":"), "").replaceAll("_", " ");
						uuser = decodeURIComponent(uuser);
						if (uuser.split("/").length > 1) return;
						if (uuser != user) return;
						let $enclosure = $('<span></span>');
						$(this).before($enclosure);
						$enclosure.append($(this));
						$enclosure.addClass(classString);
					});
				}
			});
		});
	}
});
// </nowiki>