User:Firefly/more-block-info.js

function mbi_logTimestampToWikiTimestamp(logTimestamp) { const logDatetime = new Date(logTimestamp); return (       logDatetime.toLocaleString("en-GB", { hour: "2-digit", minute: "2-digit", }) +       ", " +        logDatetime.toLocaleString("en-GB", { 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, isPartial) { return ` ${timestamp}  ${blockActor}  talk contribs  ${isPartial && ' partially '|| ''}blocked  ${user}  talk  with an expiration time of ${blockExpiry} ${blockOptions} (${blockComment}) (unblock | <a href="/wiki/Special:Block/${user}" title="Special:Block/${user}">change block</a>) </li>`; }

function mbi_getWarningboxLocked(username, logid, timestamp, lockActor, lockComment) { return `<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}) </li> </ul> <a href="https://meta.wikimedia.org/wiki/Special:CentralAuth/${username}">View full log</a> `; }

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);        //const parsedComment = await mbi_parseWikitext(blockEntry.comment);        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, "partial" in blockEntry );   });    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_parseWikitext(wikitext, stripParaTag = true) { const api = new mw.Api; const apiResponse = await api.post({       action: "parse",        format: "json",        text: wikitext,        prop: "text",        disableeditsection: 1,        formatversion: "2",    }); const parsedText = apiResponse.parse.text; if (stripParaTag) { let div = document.createElement("div"); div.innerHTML = parsedText; const pHtml = div.getElementsByTagName("p")[0].innerHTML; return pHtml.trim; } else { return parsedText.trim; } }

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.replace("[[", "[[meta:"); // Crude fix for wikilinks in lock comments intending to point to Meta-Wiki pages       const parsedComment = await mbi_parseWikitext(rawComment);        const retVal = {            logid: logEvent.logid,            lockActor: logEvent.user,            lockComment: parsedComment,            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:Global locks']").parent.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("wgPageName").includes("Special:Contributions")) {        mw.util.addCSS("div.more-block-info-box.mw-warning-with-logexcerpt.mw-warning-with-logexcerpt.mw-warning-with-logexcerpt { " + "border: 1px solid #7196bc; " + "background-color: #dbedff; " + "}");        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); }   } });