User:RoySmith/tag-check.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
Documentation for this user script can be added at User:RoySmith/tag-check. |
//
// Main function.
//
async function checkTags(content) {
content.find("span.cuEntry").each(async function() {
const userNode = $(this).find("a[href*='/User:']")[0];
const parseTree = await getParseTree("User:" + userNode.text);
if (parseTree !== null) {
const status = tagStatus(parseTree);
if ('tagType' in status) {
$(this).before("<span style=\"background-color:"
+ status.color
+ "; border:darkgrey solid 1px; padding:1px;\" title=\""
+ status.tooltip
+ "\">"
+ status.tagType
+ " </span>");
}
}
});
};
//
// Given a page title (ex: "User:Foo"), return a Promise of a JSON
// parse tree.
//
// On any kind of error, null is returned.
//
async function getParseTree(pageTitle) {
try {
const page = await $.get('/api/rest_v1/page/html/' + pageTitle);
const jsonText = findSpiTemplate(page);
return JSON.parse(jsonText);
} catch (error) {
return null;
}
};
//
// Given the parsoid text of a page, find the SPI-related template.
//
// Page is whatever a '/api/rest_v1/page/html/' API call returns. The
// data-mw attribute for the template is returned as a JSON string.
//
// If the page contains multiple SPI templates, the first one is used.
//
function findSpiTemplate(page) {
const $html = $($.parseHTML(page));
const template = $html.find('[typeof~="mw:Transclusion"]').filter(function() {
try {
const data = JSON.parse($(this).attr('data-mw'));
return data["parts"][0]["template"]["target"]["wt"].match(/[sS]ock/);
} catch(err) {
return false;
}
});
return template.attr('data-mw');
};
//
// Handle redirected template names. This is playing whack-a-mole;
// it should really be handled on the server side.
//
function emulateRedirects(rawTemplateName) {
switch(rawTemplateName) {
case 'sockmaster':
return 'sockpuppeteer';
default:
return rawTemplateName;
}
}
//
// Return an object describing how to style a SPI tag indicator.
//
// tagType: "M" for a sockmater, "P" for a sockpuppet
// color: what color to make the box.
// tooltip: a text description of the type of tag
//
// If there is no SPI tag, an empty object is returned.
//
function tagStatus(parseTree) {
const template = parseTree.parts[0].template;
const rawTemplateName = template.target.wt.trim();
const templateName = emulateRedirects(rawTemplateName).toLowerCase();
let tagType = null;
let typeParam = null;
if (templateName == 'sockpuppeteer') {
tagType = "M";
const params = template.params;
if ('1' in params) {
typeParam = params[1].wt.trim();
} else {
typeParam = 'suspected';
}
} else if (templateName == 'sock' || templateName == 'sockpuppet') {
tagType = "P";
typeParam = template.params[2].wt.trim();
} else if (templateName == 'checked sockpuppet') {
tagType = "P";
typeParam = 'confirmed';
} else {
return {};
}
if (typeParam == 'suspected') {
return {
tagType: tagType,
color: "#ffffff",
tooltip: "suspected"
};
}
if (typeParam == 'blocked') {
return {
tagType: tagType,
color: "#ffff66",
tooltip: "blocked"
};
}
if (typeParam == 'proven') {
return {
tagType: tagType,
color: "#ffcc99",
tooltip: "proven"
};
}
if (typeParam == 'confirmed') {
return {
tagType: tagType,
color: "#ff3300",
tooltip: "confirmed"
}
}
if (typeParam == 'banned') {
return {
tagType: tagType,
color: "#7a00ff61",
tooltip: "banned"
}
}
return {
tagType: tagType,
color: "#ffffff",
tooltip: "unknown"
};
}
// There's probably a nicer way to do this. The check for mw being undefined
// lets us import this file into QUnit for testing.
if (typeof mw !== "undefined") {
// Cribbed from User:Writ Keeper/Scripts/cuStaleness.js
mw.hook('wikipage.content').add(function (content) {
const titleRegex = /Wikipedia:Sockpuppet_investigations\/[^\/]+/;
const sandboxRegex = /User:RoySmith\/sandbox/;
//only use on a SPI page (or my sandbox for testing)
const pageName = mw.config.get("wgPageName");
if (titleRegex.test(pageName) || sandboxRegex.test(pageName)) {
checkTags(content);
}
});
};