User:NguoiDungKhongDinhDanh/more-block-info.js

// For attribution: User:Firefly/more-block-info.js

function mbi_logTimestampToWikiTimestamp(logTimestamp) { const logDatetime = new Date(logTimestamp); return (		logDatetime.toLocaleString('en-GB', { timeZone: 'UTC', hour: '2-digit', minute: '2-digit', }) +		', ' +		logDatetime.toLocaleString('en-GB', { timeZone: 'UTC', day: 'numeric', month: 'long', year: 'numeric', })	); }

function mbi_getBlockOptionsString(blockEntry) { let retVal = ' (';	if ('nocreate' in blockEntry) {		// ACB		retVal += 'account creation blocked, ';	}	if (!('allowusertalk' in blockEntry)) {		// NTP		retVal += 'cannot edit own talk page, ';	}	retVal += ')'; retVal = retVal.replace(', )', ')').replace(, ); return retVal; }

function mbi_getBlockDisplayListItem(user, logid, timestamp, blockActor, blockComment, blockExpiry, blockOptions) { var block = `` + `${timestamp} ` + ` ${blockActor}  ` + ` ` +			` ` +				`talk` + ` ` +			` ` +				`contribs` + ` ` +		` blocked ` + `` + ` ${user} ` + ` ` + ` ` +			` ` +				`talk` + ` ` +		` with an expiration time of ` + `${blockExpiry} ${blockOptions} ` + ` (` +			blockComment				.replace(/\[\[(:?(?:[^|]+?))\|([^|]+?)\]\]/g, '$2')				.replace(/\[\[(:?([^|]+?))\]\]/g, '<a href="/wiki/$1">$2</a>') +		`) ` + ` (` +			`<a href="/wiki/Special:Unblock/${user}" title="Special:Unblock/${user}">unblock</a> | ` +			`<a href="/wiki/Special:Block/${user}" title="Special:Block/${user}">change block</a>` +		`) ` + `</li>`; return block; }

function mbi_getWarningboxLocked(username, logid, timestamp, lockActor, lockComment) { var lock = `<div class="warningbox mw-warning-with-logexcerpt mw-content-ltr more-block-info-box more-block-info-locked" dir="ltr" lang="en">` + ` This account is currently globally locked. The latest ` + ` <a class="external text" \ href="https://meta.wikimedia.org/wiki/Special:CentralAuth/${username}">global account change log</a> ` + `entry is provided below for reference: ` + `<ul class="mw-logevent-loglines">` + `<li>` + `<a href="https://meta.wikimedia.org/w/index.php?title=Special:Log&logid=${logid}">${timestamp}</a> ` + `<a href="https://meta.wikimedia.org/wiki/User:${lockActor}" class="mw-userlink userlink" \ title="User:${lockActor}"> ${lockActor} </a> ` + ` ` +					` ` +						`<a href="https://meta.wikimedia.org/wiki/User_talk:${lockActor}" class="mw-usertoollinks-talk userlink" \ title="User talk:${lockActor}">talk</a>` + ` ` +					` ` +					`<a href="https://meta.wikimedia.org/wiki/Special:Contributions/${lockActor}" \ class="mw-usertoollinks-contribs userlink" title="Special:Contributions/${lockActor}">contribs</a>` + ` ` +				` changed status for global account ` + `<a href="/wiki/User:${username}" class="mw-userlink userlink user-blocked-indef"> ${username} </a> ` + ` ` +					`<a href="/wiki/User_talk:${username}" class="mw-usertoollinks-talk userlink user-blocked-indef">talk</a>` + ` ` +					`<a href="/wiki/Special:Contributions/${username}" \ class="mw-usertoollinks-contribs userlink user-blocked-indef">contribs</a> ` + ` : set locked; unset (none) (` +					lockComment						.replace(/\[\[(:?(?:[^|]+?))\|([^|]+?)\]\]/g, '<a href="//meta.wikimedia.org/wiki/$1">$2</a>')						.replace(/\[\[(:?([^|]+?))\]\]/g, '<a href="//meta.wikimedia.org/wiki/$1">$2</a>') +				`) ` + `</li>` + `</ul> ` + `<a href="https://meta.wikimedia.org/wiki/Special:CentralAuth/${username}">View full log</a>` + ` `;	return lock; }

function mbi_HtmlEncode(rawString) { return $(' ').text(rawString).html; }

function mbi_insertMbiBox(boxContent) { let blockedNoticeElemList = $('.mw-contributions-blocked-notice');

// If there's an existing block box, append after it	// If not, just shove our box at the top of the content element if (blockedNoticeElemList.length > 0) { $($('.mw-contributions-blocked-notice')[0]).after(boxContent); } else { $('#mw-content-text').prepend(boxContent); } }

async function mbi_getWarningboxRangeblocks(rangeblocks) { let liConcat = ''; rangeblocks.forEach(function (blockEntry) {		//const blockEntry = rangeblocks[cidr].blockEntries[0];		const blockOptions = mbi_getBlockOptionsString(blockEntry);		liConcat += mbi_getBlockDisplayListItem( blockEntry.user.replace('User:', ''), blockEntry.id, mbi_logTimestampToWikiTimestamp(blockEntry.timestamp), blockEntry.by, mbi_HtmlEncode(blockEntry.reason), // HTML-encode the block summary as they often contain hidden notes mbi_logTimestampToWikiTimestamp(blockEntry.expiry), blockOptions );	});	return `<div class="warningbox mw-warning-with-logexcerpt mw-content-ltr more-block-info-box more-block-info-rangeblocks" \ dir="ltr" lang="en">` + ` This IP address is currently subject to one or more rangeblocks. A list of these rangeblocks is below: ` + `<ul class="mw-logevent-loglines">${liConcat}</ul>` + ` `; }

// Shamelessly nicked from User:GeneralNotability/mark-locked.js async function mbi_isLocked(user) { const api = new mw.Api; try { const response = await api.get({			action: 'query',			list: 'globalallusers',			agulimit: '1',			agufrom: user,			aguto: user,			aguprop: 'lockinfo',		}); if (response.query.globalallusers.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 'locked' in response.query.globalallusers[0]; } catch (error) { return false; } }

async function mbi_getRangeblocks(user) { const retVal = { currentlyBlocked: false, everBlocked: false, blockEntries: [], };	const api = new mw.Api; try { const response = await api.post({			action: 'query',			list: 'blocks',			bkip: user,		});

let retVal = [];

response.query.blocks.forEach(function (block) {			if (block.user.includes('/')) {				retVal.push(block);			}		});

return retVal; } catch (error) { return undefined; } }

/*async function mbi_getBlockEntries(user) { const now = Date.now;

function blockIsCurrent(blockLogEntry) { return new Date(blockLogEntry.params.expiry) > now; }

const retVal = { currentlyBlocked: false, everBlocked: false, blockEntries: [], };	const api = new mw.Api; try { const response = await api.post({			action: 'query',			list: 'logevents',			letitle: `User:${user}`,			letype: 'block',		}); const blockEntries = response.query.logevents; if (blockEntries.length > 0) { // user/range has been blocked at least once retVal.everBlocked = true; retVal.currentlyBlocked = blockIsCurrent(blockEntries[0]); retVal.blockEntries = blockEntries; }		return retVal; } catch (error) { return undefined; } }*/

async function mbi_getLockLogEntry(user) { const api = new mw.Api; try { const response = await $.post('https://meta.wikimedia.org/w/api.php', {			action: 'query',			list: 'logevents',			lelimit: '1',			letitle: `User:${user}@global`,			leaction: 'globalauth/setstatus',			origin: '*',			format: 'json',		});

const logEvent = response.query.logevents[0]; const wikiTimestamp = mbi_logTimestampToWikiTimestamp(logEvent.timestamp); const rawComment = logEvent.comment; const retVal = { logid: logEvent.logid, lockActor: logEvent.user, lockComment: rawComment, timestamp: wikiTimestamp, };		return retVal; } catch (error) { console.log(error); return undefined; } }

async function mbi_handleRegisteredUser(relevantUserName) { const userLocked = await mbi_isLocked(relevantUserName); if (userLocked) { const lockLogEntry = await mbi_getLockLogEntry(relevantUserName); const lockedBox = mbi_getWarningboxLocked(			relevantUserName,			lockLogEntry.logid,			lockLogEntry.timestamp,			lockLogEntry.lockActor,			lockLogEntry.lockComment		); $('a[title^="m:Special:CentralAuth/"]').parent.remove; // Remove "this account is globally locked" box mbi_insertMbiBox(lockedBox); } }

async function mbi_handleIPOrRange(relevantUserName) { const ipRangeBlocks = await mbi_getRangeblocks(relevantUserName); if (ipRangeBlocks.length > 0) { // If there's only one block returned, and it matches the rangeblock already displayed // then don't duplicate it		if (ipRangeBlocks.length == 1) { const existingRange = $('.mw-warning-with-logexcerpt>ul>li>a.mw-anonuserlink'); if (existingRange.length > 0) { const existingRangeIP = existingRange.attr('href').split('/').slice(3).join('/'); if (existingRangeIP === ipRangeBlocks[0].user.replace('User:', '')) { return; }			}		}		const rangeblockBox = await mbi_getWarningboxRangeblocks(ipRangeBlocks); mbi_insertMbiBox(rangeblockBox); } }

$.when($.ready, mw.loader.using('mediawiki.util')).then(async function {	if (mw.config.get('wgCanonicalSpecialPageName') === 'Contributions') {		mw.util.addCSS(` div.more-block-info-box { margin-bottom: 16px; border: 1px solid #7196bc; background-color: #dbedff; padding: 12px 24px; }		`);		const relevantUserName = mw.config.get('wgRelevantUserName');		if (relevantUserName !== null) {			// wgRelevantUserName is null for IP ranges (see phab T206954)			const isip = mw.util.isIPAddress(relevantUserName, true);			if (!isip) {				// No point checking for locks if IP, IPs cannot be locked				mbi_handleRegisteredUser(relevantUserName);			} else {				mbi_handleIPOrRange(relevantUserName);			}		} else {			// We're naively assuming an IP range			// Have to extract range manually from URL as wgRelevantUserName is null			const queryParamsRaw = window.location.search;			let ipRange;			if (queryParamsRaw === '') {				ipRange = mw.config.get('wgPageName').split('/').slice(1).join('/');			} else {				const queryParams = new URLSearchParams(queryString);				ipRange = queryParams.get('target');			}			mbi_handleIPOrRange(ipRange);		}	} });