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>
// @ts-check
// Companion to markblocked - asynchronously marks users with talk page access revoked
// Chunks borrowed from [[User:Krinkle/Scripts/CVNSimpleOverlay_wiki.js]],
// [[User:GeneralNotability/ip-ext-info.js]], and [[MediaWiki:Gadget-markblocked.js]]
// Named "mark-rocked" as this script was forked from [[User:GeneralNotability/mark-locked.js]]
// By [[User:Frostly]]

/**
 * Get all userlinks on the page
 *
 * @param {JQuery} $content page contents
 * @return {Map} list of unique users on the page and their corresponding links
 */
 function rockedUsers_getUsers($content) {
	const userLinks = new Map();

	// Get all aliases for user: & user_talk: (taken from markblocked)
	const userNS = [];
	for (const ns in mw.config.get( 'wgNamespaceIds' ) ) {
		if (mw.config.get('wgNamespaceIds')[ns] === 2 || mw.config.get('wgNamespaceIds')[ns] === 3) {
			userNS.push(mw.util.escapeRegExp(ns.replace(/_/g, ' ')) + ':');
		}
	}

	// RegExp for all titles that are  User:| User_talk: | Special:Contributions/ (for userscripts)
	const userTitleRX = new RegExp('^(' + userNS.join('|') + '|Special:Contrib(?:ution)?s\\/|Special:CentralAuth\\/)+([^\\/#]+)$', 'i');
	const articleRX = new RegExp(mw.config.get('wgArticlePath').replace('$1', '') + '([^#]+)');
	const redlinkRX = new RegExp(mw.config.get('wgScript') + '\\?title=([^#&]+)');
	$('a', $content).each(function () {
		if (!$(this).attr('href')) {
			// Ignore if the <a> doesn't have a href
			return;
		}
		let articleTitleReMatch = articleRX.exec($(this).attr('href').toString());
		if (!articleTitleReMatch) {
			// Try the redlink check
			articleTitleReMatch = redlinkRX.exec($(this).attr('href').toString());
			if (!articleTitleReMatch) {
				return;
			}
		}
		let pgTitle;
		try {
			pgTitle = decodeURIComponent(articleTitleReMatch[1]).replace(/_/g, ' ');
		} catch (error) {
			// Happens sometimes on non-username paths, like if there's a slash in the path
			return;
		}
		const userTitleReMatch = userTitleRX.exec(pgTitle);
		if (!userTitleReMatch) {
			return;
		}
		const username = userTitleReMatch[2];
		if (!mw.util.isIPAddress(username, true)) {
			if (!userLinks.get(username)) {
				userLinks.set(username, []);
			}
			userLinks.get(username).push($(this));
		}
	});
	return userLinks;
}

/**
 * Check whether a user has talk page access revoked
 *
 * @param {string} user Username to check
 *
 * @return {Promise<boolean>} Whether the user in question has talk page access
 */
async function revokedUsers_isRevoked(user) {
	user = user.charAt(0).toUpperCase() + user.slice(1)
	const api = new mw.Api();
	try {
		const response = await api.get({
			action: 'query',
			list: 'blocks',
			formatversion: '2',
			bklimit: '1',
			bkusers: user,
			bkprop: 'flags'
		});
		if (response.query.blocks.length === 0) {
			// If the length is 0, then we couldn't find the global user
			return false;
		}
		// If the 'locked' field is present, then the user is locked
		return 'allowusertalk' in response.query.blocks[0];
	} catch (error) {
		return false;
	}
}

// On window load, get all the users on the page and check if they have talk page access
$.when( $.ready, mw.loader.using( 'mediawiki.util' ) ).then( function () {
	mw.hook('wikipage.content').add(function ($content) {
		const usersOnPage = rockedUsers_getUsers($content);
		usersOnPage.forEach(async (val, key, _) => {
			const userRocked = await revokedUsers_isRevoked(key);
			if (userRocked) {
				val.forEach(($link) => {
					// $link.css({ opacity: 0.4, 'border-bottom-size': 'thick', 'border-bottom-style': 'dashed', 'border-bottom-color': 'red' });
					// document.getElementById("myspan").textContent="newtext";
					$link.text($link.text() + '🤫');
				});
			}
		});
	});
});
// </nowiki>