MediaWiki:Gadget-InfoboxChecker.js
Jump to navigation
Jump to search
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
/* ToDo:
* - How to compare 'leveling' from Infobox-familiar?
*/
;(function(window, $, mw) {
'use strict';
const config = mw.config.get([
'wgCanonicalSpecialPageName',
'wgContentLanguage',
'wgTitle'
]);
if (window.InfoboxCheckerLoaded || !(config.wgCanonicalSpecialPageName === 'Blankpage' && config.wgTitle.endsWith('/InfoboxChecker'))) return;
window.InfoboxCheckerLoaded = true;
var wArea;
var rArea;
var paused = true;
var lastTimeout;
var buttons;
var OO;
var links = {};
var root = document.getElementById('mw-content-text');
var sources = {};
var locLines = {};
var costs = {};
var queryParams = {
action: "query",
format: "json",
prop: "langlinks|pageprops",
titles: "Pilfer",
formatversion: 2,
ppprop: "infoboxes",
origin: "*"
};
var wikiApiUrl = 'https://undermine.wiki.gg/$lang/api.php';
document.getElementById('firstHeading').textContent = 'Infobox checker';
mw.loader.load([
// main
'jquery',
'oojs-ui',
'oojs-ui-core',
'oojs-ui-widgets',
// Icons
'oojs-ui.styles.icons-alerts', // notice, error
'oojs-ui.styles.icons-content', // history
'oojs-ui.styles.icons-editing-advanced', // language
'oojs-ui.styles.icons-interactions', // check
'oojs-ui.styles.icons-media', // play, pause
'oojs-ui.styles.icons-moderation', // trash
]);
mw.loader.using(['mediawiki.api']).then(function() {
return new mw.Api().loadMessagesIfMissing([
'pagetitle'
], {amlang: config.wgContentLanguage});
}).then(function() {
document.title = mw.msg('pagetitle').replace('$1', 'Infobox checker');
});
root.innerHTML = '<div id="toolbar">' +
'</div>' +
'<div style="display:flex;margin-top:10px;background:rgba(var(--theme-accent-color--rgb),.7)">' +
'<div id="leftArea"> <!-- Contains the list to process -->' +
'<textarea id="pageList" rows="30" cols="50" disabled>' +
'</textarea>' +
'</div>' +
'<div id="rightArea" style="display:none;"> <!-- Display logs in listview; Entries toggabled -->' +
'</div>' +
'<div id="watermarkArea">' +
'</div>';
var pageList = document.getElementById("pageList");
function getHashCode(str) { // By MoatShrimp
var h1 = 5381;
var h2 = h1;
for (var i = 0; i < str.length; i += 2) {
h1 = (((h1 << 5) + h1)|0) ^ str.charCodeAt(i);
if (i+1 == str.length) {break;}
h2 = (((h2 << 5) + h2)|0) ^ str.charCodeAt(i+1);
}
return (h1 + Math.imul(h2, 1566083941))|0;
}
function loadLocFile(event) {
var file = event.target.result;
var ignore_next = false;
var inside_string = false;
var locdb_cur_string = [];
var locdb_cur_param = 0;
var locdb_lines = [[]];
for (var i = 0; i < file.length; i++) {
var c = file.substring(i, i + 1);
if (c === "\"") {
if (ignore_next) {
ignore_next = false;
} else if (inside_string && file.substring(i + 1, i + 2) === "\"") {
ignore_next = true;
locdb_cur_string.push(c);
} else {
inside_string = !inside_string;
}
} else if (!inside_string && (c === "," || c === "\n")) {
locdb_lines[locdb_lines.length - 1][locdb_cur_param] = locdb_cur_string.join("");
locdb_cur_string = [];
locdb_cur_param++;
if (c === "\n") {
locLines[String(getHashCode(locdb_lines[locdb_lines.length - 1][0]))] = locdb_lines[locdb_lines.length - 1];
locdb_lines[locdb_lines.length] = [];
locdb_cur_param = 0;
}
} else {
locdb_cur_string.push(c);
}
}
buttons.interwikiBtn.setValue(true);
}
var sourcesDummy = document.createElement("div");
function getSources(a) {
for (var value in a) {
if (a[value] && typeof(a[value]) === "object") {
if (a[value].source) {
sourcesDummy.innerHTML = a[value].value;
if (sourcesDummy.children.length && a[value].value.substring(0, 1).match("<")) {
sources[a[value].source] = sourcesDummy.children[0].innerText;
} else {
sources[a[value].source] = a[value].value;
}
continue;
}
getSources(a[value]);
}
}
}
var statusWeight = {
progress: 0,
success: 1,
failed: 2
};
function toggleEntries(type, state) {
var ele = root.querySelectorAll('div[data-status="' + type + '"]');
for (var i = 0; i < ele.length; i++) {
ele[i].style.display = (!state && "none" || "inherit");
}
if (document.querySelector('div.eventEntry[style*="inherit"]')) {
rArea.style.display = "unset";
wArea.style.display = "none";
} else {
rArea.style.display = "none";
wArea.style.display = "unset";
}
}
function addStatusEntry(ele, name, compare1, compare2, entry) {
if (typeof(compare2) == "string") {
console.log("OLD:");
console.log(compare2);
compare2 = compare2.replaceAll(/\s+$/gm, "\n").replace(/\n$/,"");
console.log("NEW:");
console.log(compare2);
}
var stat = String(compare1) === String(compare2) && "success" || "failed";
if (buttons[stat].getValue() && ele.dataset.status !== stat) {
ele.style.display = "inherit";
}
if (stat === "success") {
toggleEntries("success", buttons.success.getValue());
} else {
toggleEntries("failed", buttons.failed.getValue());
}
var stEle = ele.querySelector(".status");
if (statusWeight[ele.dataset.status] < statusWeight[stat]) ele.dataset.status = stat;
var ele2 = ele.getElementsByClassName("statusEntry")[0];
if (ele2.querySelector("div").dataset.temp) stEle.removeChild(ele2); // Remove temporary entry
var newEle = document.createElement("div");
newEle.className = "statusEntry";
var newEle2 = document.createElement("div");
var newEle3 = document.createElement("span");
newEle2.innerText = entry;
newEle3.className = "comparedResult " + stat;
newEle3.innerText = stat;
if (stat === "failed") {
newEle3.innerHTML += "<br/>Got \"" + compare1 + "\"<br/>Expected \"" + compare2 + "\"";
}
newEle.appendChild(newEle2);
newEle2.appendChild(newEle3);
stEle.appendChild(newEle);
}
var sourceTranslations = { // DE, RU
ability1: ["fähigkeit1"],
ability2: ["fähigkeit2"],
ability3: ["fähigkeit3"],
abilitydesc1: ["fähigkeitdesc1"],
abilitydesc2: ["fähigkeitdesc2"],
abilitydesc3: ["fähigkeitdesc3"],
attack1: ["attacke1"],
attack2: ["attacke2"],
attack3: ["attacke3"],
blessing: ["segen"],
"craft cost": ["herstellungskosten"],
damage1: ["schaden1"],
damage2: ["schaden2"],
damage3: ["schaden3"],
damagetype1: ["schadensart1"],
damagetype2: ["schadensart2"],
damagetype3: ["schadensart3"],
description: ["beschreibung"],
"description extended": ["beschreibung erweitert"],
difficulty: ["schwierigkeit"],
effect: ["effekt"],
"effect extended": ["effekt erweitert"],
health: ["gesundheit"],
longdesc: ["lange beschreibung"],
"major curse": ["starker fluch"],
"minor curse": ["schwacher fluch"],
rarity: ["seltenheit"],
"shop cost": ["ladenkosten"],
"shop cost othermine": ["ladenkosten othermine"],
strong: ["stärke"],
weak: ["schwäche"],
};
var rarityTranslations = { // DE, RU
Common: ["Allgemein", "Обычный"],
Rare: ["Selten", "Редкий"],
Legendary: ["Legendär", "Легендарный"],
};
var curCostType = "";
function getCosts(a) {
for (var value in a) {
if (a[value] && a[value].MData && a[value].MData.$Ref) {
var n = links[a[value].MData.$Ref].Name;
if (curCostType === "Alternate" && n === "ResourceGold") n = "ResourceGoldOthermine";
costs[n] = a[value].MAmount;
continue;
} else if (typeof(a[value]) === "object") {
if (a[value].Type) {
curCostType = a[value].Type;
}
getCosts(a[value]);
continue;
}
}
}
function getTranslatedSources(val, lang) {
if (lang === "en") return val;
return sourceTranslations[val] && sourceTranslations[val][Number(lang !== "de")] || val;
}
function getTranslatedValue(val, lang) {
if (typeof(val) !== "object") return val;
if (lang === "en" || val.Key === 0) return val.Value;
return locLines[val.Key] && locLines[val.Key][lang === "de" && 6 || 13] || "<Not found>"; // 6: de, 13: ru
}
function log(msg) {
console.log('[%cInfoboxChecker%c] ' + msg, 'color:orange', 'color:inherit');
}
function compare(ele, lang) { // values: collection of infobox-data
if (!links[sources.guid]) {
addStatusEntry(ele, lang + " " + sources.guid, "No data present", "Present data", "GUID not found");
return;
}
log('Start');
log('Language: ' + lang);
console.log(sources);
console.log(links[sources.guid]);
log('Done');
var a = lang + " " + sources.guid;
var gTS = getTranslatedSources;
var gTV = getTranslatedValue;
var ab = links[sources.guid].Abilities || [];
var at = links[sources.guid].Attacks || [];
var d = gTS("longdesc", lang);
if (sources[d]) {
sources[d] = sources[d].replaceAll(" <br/>", "<br/>").replaceAll("<br/>", "\n");
}
costs = {};
getCosts(links[sources.guid].CostGroups || []);
var hasLongdesc = typeof(sources[gTS("longdesc", lang)]) == "string";
var is_Penance = (sources[gTS("guid", lang)] || "") == "e9015ba93a0448daa19dcee8a34bc5da";
console.log(costs);
var to_process = [
["ability1", ab[0] && ab[0].Name || "", "Ability Name #1"],
["ability2", ab[1] && ab[1].Name || "", "Ability Name #2"],
["ability3", ab[2] && ab[2].Name || "", "Ability Name #3"],
["abilitydesc1", ab[0] && ab[0].Description || "", "Ability Description #1"],
["abilitydesc2", ab[1] && ab[1].Description || "", "Ability Description #2"],
["abilitydesc3", ab[2] && ab[2].Description || "", "Ability Description #3"],
["attack1", at[0] && at[0].DisplayName || "", "Damage Name #1"],
["attack2", at[1] && at[1].DisplayName || "", "Damage Name #2"],
["attack3", at[2] && at[2].DisplayName || "", "Damage Name #3"],
["damage1", at[0] && at[0].Amount || "", "Damage #1"],
["damage2", at[1] && at[1].Amount || "", "Damage #2"],
["damage3", at[2] && at[2].Amount || "", "Damage #3"],
["damagetype1", at[0] && at[0].DamageType || "", "Damage Type #1"],
["damagetype2", at[1] && at[1].DamageType || "", "Damage Type #2"],
["damagetype3", at[2] && at[2].DamageType || "", "Damage Type #3"],
[hasLongdesc && "description" || "effect", links[sources.guid].Description || "", "Effect"],
["description extended", links[sources.guid].ExtendedFlavor, "Effect (Expanded)"],
["difficulty", links[sources.guid].Difficulty || "", "Difficulty"],
["health", String(is_Penance && costs.HealthHP || links[sources.guid].Hp || ""), is_Penance && "Health-Cost" || "Health"],
[hasLongdesc && "longdesc" || "description", links[sources.guid].Flavor || "", "Description"],
["effect extended", links[sources.guid].ExtendedDescription, "Description (Expanded)"],
["rarity", links[sources.guid].Rarity || "", "Rarity"],
["strong", links[sources.guid].Strength || "", "Strength"],
["weak", links[sources.guid].Weakness || "", "Weakness"],
["blessing", String(costs.Blessing || ""), "Blessing"],
["shop cost", String(costs.ResourceGold || ""), "Gold"],
["shop cost othermine", String(costs.ResourceGoldOthermine || ""), "Gold (Othermine)"],
["major curse", String(costs.CurseMajor || ""), "Major Curse"],
["minor curse", String(costs.CurseMinor || ""), "Minor Curse"],
["craft cost", String(costs.ResourceThorium || ""), "Thorium"],
];
for (var i = 0; i < to_process.length; i++) {
var b = sources[gTS(to_process[i][0], lang)];
var c = gTV(to_process[i][1], lang);
if (b || String(c).length) {
if (lang !== "en" && to_process[i][0] == "rarity") {
c = rarityTranslations[c] && rarityTranslations[c][Number(lang !== "de")] || c;
}
addStatusEntry(ele, a, b, c, to_process[i][2]);
}
}
}
function checkPage(page, lang) { // Loads from wiki
rArea.style.display = "unset";
wArea.style.display = "none";
var ele = document.createElement("div");
ele.className = "eventEntry";
ele.dataset.status = "progress";
ele.style.display = "inherit";
var ele2 = document.createElement("div");
ele2.className = "title";
ele2.innerHTML = '<a href="https://undermine.wiki.gg/' + (lang && lang + "/" || "") + "wiki/" + page + '">' + page + (lang && " (" + lang + ")" || "") + '</a>';
var ele3 = document.createElement("div");
ele3.className = "status";
var ele4 = document.createElement("div");
ele4.className = "statusEntry";
var ele5 = document.createElement("div");
ele5.innerText = "Loading..";
ele5.dataset.temp = ".";
ele.appendChild(ele2);
ele.appendChild(ele3);
ele3.appendChild(ele4);
ele4.appendChild(ele5);
rArea.appendChild(ele);
var url = new URL(wikiApiUrl.replace("$lang", lang || ""));
queryParams.titles = page;
var qP = Object.keys(queryParams);
for (var i = 0; i < qP.length; i++) {
url.searchParams.set(qP[i], queryParams[qP[i]]);
}
var request = new XMLHttpRequest();
request.open('POST', url.href);
request.responseType = 'json';
request.onload = function() {
var response = request.response;
ele5.innerText = "Comparing..";
var orgGUID;
if (lang) {
orgGUID = sources.guid;
}
sources = {};
var d = JSON.parse(response.query.pages && response.query.pages[0].pageprops && response.query.pages[0].pageprops.infoboxes || "[]");
console.log(d);
getSources(d);
var abcd = "en";
if (lang) {
abcd = lang;
} else if (sources.guid) {
var g = sources.guid.match(/\w{12}4\w{19}/g);
if (g && g.length) {
sources.guid = g[0];
}
}
sources.guid = sources.guid || orgGUID;
compare(ele, abcd);
if (buttons.interwikiBtn.getValue() && !lang) {
var langs = response.query.pages[0].langlinks;
for (var i = 0; i < langs.length; i++) {
checkPage(langs[i].title, langs[i].lang);
}
}
};
request.send();
}
function start() {
if (paused) {
if (lastTimeout) {
clearTimeout(lastTimeout);
}
lastTimeout = undefined;
return;
}
var content = pageList.value.split("\n");
if (content.length > 0 && content[0].length > 0) {
checkPage(content[0]);
content.shift();
pageList.value = content.join("\n");
lastTimeout = setTimeout(start, 1000);
} else {
paused = true;
buttons.playBtn.setIcon("play");
start();
}
}
function setupToolbar() {
buttons = [];
buttons.interwikiBtn = new OO.ui.ToggleButtonWidget( {
framed: false,
icon: "language",
label: "Enables interwiki",
invisibleLabel: true,
title: "Enable comparing of interwiki-pages."
} );
buttons.trashBtn = new OO.ui.ButtonInputWidget( {
framed: false,
icon: "trash",
label: "Clears the log",
invisibleLabel: true,
title: "Clear log-entries."
} );
buttons.playBtn = new OO.ui.ButtonInputWidget( {
framed: false,
icon: "play",
label: "Start",
invisibleLabel: true,
title: "Start comparing.."
} );
buttons.success = new OO.ui.ToggleButtonWidget( {
framed: false,
icon: "check",
label: "Toggle visibility of success log-entries.",
invisibleLabel: true,
title: "Toggle success log-entries.",
value: true
} );
buttons.failed = new OO.ui.ToggleButtonWidget( {
framed: false,
icon: "error",
label: "Toggle visibility of failed log-entries.",
invisibleLabel: true,
title: "Toggle failed log-entries.",
value: true
} );
buttons.interwikiBtn.on("click", function() {
if (buttons.interwikiBtn.getValue()) {
buttons.interwikiBtn.setValue(false);
lf.click();
}
});
buttons.trashBtn.on("click", function() {
rArea.innerHTML = "";
rArea.style.display = "none";
wArea.style.display = "unset";
});
buttons.playBtn.on("click", function() {
paused = !paused;
buttons.playBtn.setIcon(paused && "play" || "pause");
start();
});
buttons.success.on("click", function() {
toggleEntries("success", buttons.success.getValue());
});
buttons.failed.on("click", function() {
toggleEntries("failed", buttons.failed.getValue());
});
document.getElementById("toolbar").innerHTML = '<label id="locFileLabel" style="display:none;" for="locFile">Open a localization file</label>' +
'<input type="file" id="locFile" style="display:none;" autocomplete="off" accept=".bytes"/>';
var lf = document.getElementById("locFile");
lf.onchange = function(e) {
var reader = new FileReader();
reader.onabort = function() {
buttons.interwikiBtn.setValue(false);
lf.value = "";
};
reader.onload = function(readerEvent) {
loadLocFile(readerEvent);
lf.value = "";
};
reader.readAsText(e.target.files[0]);
};
var group1 = new OO.ui.ButtonGroupWidget({items: [
buttons.interwikiBtn,
buttons.trashBtn,
buttons.playBtn
]});
var group2 = new OO.ui.ButtonGroupWidget({items: [
buttons.success,
buttons.failed
]});
document.getElementById("toolbar").appendChild(group1.$element.get(0));
document.getElementById("toolbar").appendChild(group2.$element.get(0));
}
mw.loader.using(['jquery', 'oojs-ui', 'oojs-ui-core', 'oojs-ui-widgets']).then(function(require) {
OO = require('oojs');
wArea = document.getElementById("watermarkArea");
rArea = document.getElementById("rightArea");
var loadingWarning = new OO.ui.ButtonWidget( {
icon: 'notice',
label: 'Downloading required data..',
disabled: true
} );
var watermark = document.createElement("div");
watermark.style["text-align"] = "center";
var historyIcn = new OO.ui.IconWidget( {
icon: 'history',
label: '',
title: '',
invisibleLabel: true,
disabled: true
} );
var hIcn = historyIcn.$element.get(0);
hIcn.style.transform = "scale(3)";
hIcn.style["margin-top"] = "20px";
watermark.appendChild(hIcn);
wArea.appendChild(watermark);
document.getElementById("toolbar").appendChild(loadingWarning.$element.get(0));
$.getJSON("https://knugel.github.io/undermine-data/data/DataObjects.json", function(result) {
links = {};
for (var i = 0; i < result.length; i++) {
links[result[i].Guid] = result[i];
}
pageList.disabled = false;
setupToolbar();
});
});
})(window, window.jQuery, window.mediaWiki);