MediaWiki:Common.js/User:Fumple/PatrolTool.js
From Inkipedia, the Splatoon wiki
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.
function patroltool_error(data) { $("#funpl-patroltool").css("display", "none"); $("#funpl-patroltool-error").css("display", ""); $("#funpl-patroltool-error-text").text(data); console.error(data); throw new Error(data); } $(function () { try { //try catch all the lines! var namespaceselect = null, continuebutton = null, patrolbutton = null, cignorebutton = null, cblayout = null, cilayout = null, finalchanges = [], currentchange = -1, mwApi = new mw.Api(); mwApi.get({ "action": "query", "format": "json", "meta": "userinfo", "uiprop": "rights" }).done((data) => { console.log("[PatrolTool] Rights", data); if (data.query.userinfo.rights.includes("patrol")) { loadFilters(); } else if (data.query.userinfo.id != 0) { $("#funpl-patroltool").css("display", "none"); $("#funpl-patroltool-error").css("display", ""); $("#funpl-patroltool-error-text").html("You can't use this tool as you don't have the correct rights"); } else { $("#funpl-patroltool").css("display", "none"); $("#funpl-patroltool-error").css("display", ""); $("#funpl-patroltool-error-text").html("You can't use this tool as you don't have the correct rights<br>You're also logged out, maybe you want to <a href='/w/index.php?title=Special:UserLogin&returnto=User%3AFunPL%2FPatrolTool'>log in</a>"); } }).catch(patroltool_error); async function loadFilters() { try { await mw.loader.load("oojs-ui"); await mw.loader.load("oojs-ui-widgets"); $("#funpl-patroltool-header").text("Loading namespaces..."); mwApi.get({ "action": "query", "format": "json", "meta": "siteinfo", "siprop": "namespaces" }).done((data) => { console.log("namespaces", data); namespaceselect = new OO.ui.MenuTagMultiselectWidget({ "options": [{ "data": "*", "label": "All namespaces" }] }); var layout = new OO.ui.FieldLayout(namespaceselect, { "align": 'top', "label": 'Namespaces', "id": "funpl-patroltool-nss" }); continuebutton = new OO.ui.ButtonWidget({ label: 'Continue', icon: 'arrowNext' }); cblayout = new OO.ui.FieldLayout(continuebutton, { "align": 'top', "label": '', "id": "funpl-patroltool-cb", "notices": ["Pro tip: Want to save your filters? Bookmark this page after you click continue"] }); var url = new URL(window.location); if (url.searchParams.has("namespaces")) var urlns = url.searchParams.get("namespaces").split('|'); else var urlns = []; var selected = []; if (urlns.includes("*")) selected = selected.concat({ "data": "*", "label": "All namespaces" }); for (var nsid in data.query.namespaces) { namespaceselect.addOptions([{ "data": nsid, "label": data.query.namespaces[nsid]["*"] != "" ? data.query.namespaces[nsid]["*"] : "(Main)" }]) if (urlns.includes(nsid)) selected = selected.concat({ "data": nsid, "label": data.query.namespaces[nsid]["*"] != "" ? data.query.namespaces[nsid]["*"] : "(Main)" }); } namespaceselect.setValue(selected); $("#funpl-patroltool-header").text("Select filters"); $("#funpl-patroltool-loading").css("display", "none"); $("#funpl-patroltool").append(layout.$element); $("#funpl-patroltool").append(cblayout.$element); continuebutton.on("click", function () { continuebutton.disabled = true; continuebutton.updateDisabled(); namespaceselect.disabled = true; namespaceselect.updateDisabled(); $("#funpl-patroltool-header").text("Loading changes..."); cblayout.setNotices(["Loading... This might take a second"]); $("#funpl-patroltool-loading").css("display", ""); loadChanges(); }) }).catch(patroltool_error); } catch (ex) { patroltool_error(ex); } } async function loadChanges(rccontinue) { return new Promise(function (k, no) { try { var namespace = namespaceselect.getValue().includes("*") ? "*" : namespaceselect.getValue().join('|'); if (namespace == "") namespace = "*" var url = new URL(window.location); url.searchParams.set("namespaces", namespace); window.history.pushState("", "", url.toString()); var options = { "action": "query", "format": "json", "list": "recentchanges", "rcnamespace": namespace, "rcprop": "title|timestamp|ids|user|parsedcomment", "rcshow": "unpatrolled", "rcdir": "newer", "rclimit": "max" }; if (rccontinue != null) options.rccontinue = rccontinue; mwApi.get(options).done(async function (data) { console.log("rcdata", data); var changes = data.query.recentchanges; if (data.continue != null) { var cchanges = await loadChanges(data.continue.rccontinue); changes = changes.concat(cchanges); } if (rccontinue != null) { k(changes); return; } console.log(changes.length, changes); finalchanges = changes; window.patroltoolchanges = finalchanges; $("#funpl-patroltool-header").text("Ready!"); cblayout.setNotices(["Found " + changes.length + " changes", "Press continue to load the first edit"]); $("#funpl-patroltool-loading").css("display", "none"); continuebutton.disabled = false; continuebutton.updateDisabled(); continuebutton.off("click"); continuebutton.on("click", function () { continuebutton.off("click"); continuebutton.disabled = true; continuebutton.updateDisabled(); $("#funpl-patroltool-header").text("Preparing..."); cblayout.setNotices([]); $("#funpl-patroltool-loading").css("display", ""); $("#funpl-patroltool-nss").remove(); $("#funpl-patroltool-cb").remove(); $("#funpl-patroltool").append('<div id="funpl-patroltool-desc"></div>'); $("#funpl-patroltool").append('<h2 id="funpl-patroltool-diff-header">Diff</h2>'); $("#funpl-patroltool").append('<div id="funpl-patroltool-diff" class="diff"></div>'); patrolbutton = new OO.ui.ButtonWidget({ "label": "Mark as patrolled and continue", "icon": 'arrowNext', "disabled": true, "flags": ["primary", "progressive"] }); cignorebutton = new OO.ui.ButtonWidget({ "label": 'Ignore and continue', "icon": 'arrowNext', "disabled": true, "flags": ["progressive"] }); var toplayout = new OO.ui.HorizontalLayout({ items: [ patrolbutton, cignorebutton ] }); $("#funpl-patroltool").append(toplayout.$element); $("#funpl-patroltool").append('<h2 id="funpl-patroltool-preview-header">Page preview</h2>'); $("#funpl-patroltool").append('<div id="funpl-patroltool-preview"></div>'); loadNextChange(); }) }).catch(patroltool_error).catch(no); } catch (ex) { patroltool_error(ex); } }); } function loadNextChange() { loadChange(currentchange + 1); } function loadChange(i) { try { $("#funpl-patroltool-header").text("Loading..."); $("#funpl-patroltool-loading").css("display", ""); $("#funpl-patroltool-desc").html(''); $("#funpl-patroltool-diff").html(''); $("#funpl-patroltool-preview").html(''); currentchange = i; //and this is the place where we load the changes. how exciting var change = finalchanges[currentchange]; console.log("[PatrolTool] Loading change ", change); console.log("[PatrolTool] " + (i + 1) + "/" + finalchanges.length); console.log("[PatrolTool] Checking whether change " + i + " is patrolled"); mwApi.get({ //Try to find the edit in the unpatrolled section, if it isn't found, skip this edit as someone patrolled it "action": "query", "format": "json", "list": "recentchanges", "rcstart": finalchanges[currentchange].timestamp, "rcend": finalchanges[currentchange].timestamp, "rcshow": "unpatrolled" }).done((data) => { console.log("rccheck", data); if (data.query.recentchanges.length > 0) { console.log("[PatrolTool] Change " + i + " is not patrolled, loading it"); $("#funpl-patroltool-header").text('[' + change.type + '] ' + change.title); if (change.type == "edit") { mwApi.get({ //Get the diff "action": "compare", "format": "json", "fromrev": change.old_revid, "torev": change.revid, "prop": "diff|ids|title|user|parsedcomment" }).done((data) => { console.log("compare", data); let compare = data.compare; console.log("[PatrolTool] Loaded compare for change " + i); $("#funpl-patroltool-desc").html(`<table class="wikitable"> <tr><th></th><th>Previous change</th><th>This change</th></tr> <tr> <th>Page title</th> <td><a target="_blank" href="/wiki/${encode(compare.fromtitle)}">${compare.fromtitle.encodeHTML()}</a></td> <td><a target="_blank" href="/wiki/${encode(compare.totitle)}">${compare.totitle.encodeHTML()}</a></td> </tr> <tr> <th>Editor</th> <td><a target="_blank" href="/wiki/User:${encode(compare.fromuser)}">${compare.fromuser.encodeHTML()}</a> <a target="_blank" href="/wiki/User%20talk:${encode(compare.fromuser)}">(talk)</a></td> <td><a target="_blank" href="/wiki/User:${encode(compare.touser)}">${compare.touser.encodeHTML()}</a> <a target="_blank" href="/wiki/User%20talk:${encode(compare.touser)}">(talk)</a></td> </tr> <tr> <th>Edit summary</th> <td>${compare.fromparsedcomment}</td> <td>${compare.toparsedcomment}</td> </tr> <tr> <th>Date</th> <td>-</td> <td>${new Date(change.timestamp).toUTCString()}</td> </tr> <tr> <th></th> <td><a target="_blank" href="/wiki/${encode(compare.fromtitle)}?oldid=${urlSafe(compare.fromrevid)}">View</a></td> <td><a target="_blank" href="/wiki/${encode(compare.totitle)}?oldid=${urlSafe(compare.torevid)}">View</a></td> </tr> <tr> <th></th> <td><a target="_blank" href="/wiki/${encode(compare.fromtitle)}?action=edit&oldid=${urlSafe(compare.fromrevid)}">Edit</a></td> <td><a target="_blank" href="/wiki/${encode(compare.totitle)}?action=edit&oldid=${urlSafe(compare.torevid)}">Edit</a></td> </tr> <tr> <th></th> <td></td> <td><a target="_blank" href="/wiki/${encode(compare.totitle)}?action=edit&undoafter=${urlSafe(compare.fromrevid)}&undo=${urlSafe(compare.torevid)}">Undo</a></td> </tr> </table>`) $("#funpl-patroltool-diff").html(compare["*"]); mwApi.get({ "action": "parse", "format": "json", "oldid": compare.torevid }).done((parse) => { console.log("[PatrolTool] parse", parse); $("#funpl-patroltool-preview").html(parse.parse.text["*"]); $("#funpl-patroltool-preview").append('<div id="#funpl-patroltool-categories" class="catlinks"></div>'); let cattext = ""; for (var cat of parse.parse.categories) { cattext += '<li><a href="/wiki/Category:' + encode(cat["*"]) + '">' + cat["*"].encodeHTML() + '</a></li>'; } if (cattext != "") { $("#funpl-patroltool-categories").html("<b>Categories:</b> <ul>" + cattext + "</ul>"); } patrolbutton.disabled = false; patrolbutton.updateDisabled(); patrolbutton.off("click"); patrolbutton.on("click", function () { patrolbutton.off("click"); patrolbutton.disabled = true; patrolbutton.updateDisabled(); cignorebutton.off("click"); cignorebutton.disabled = true; cignorebutton.updateDisabled(); $("#funpl-patroltool-header").text("Loading..."); $("#funpl-patroltool-loading").css("display", ""); $("#funpl-patroltool-desc").html(''); $("#funpl-patroltool-diff").html(''); $("#funpl-patroltool-preview").html(''); mwApi.postWithToken("patrol", { "action": "patrol", "format": "json", "revid": compare.torevid }).done(function () { loadNextChange(); }).catch(function (err) { if (err == notpatrollable) { alert("Failed to patrol edit due to it being not patrolable"); loadNextChange(); } else { patroltool_error(err); } }); }); cignorebutton.disabled = false; cignorebutton.updateDisabled(); cignorebutton.off("click"); cignorebutton.on("click", function () { patrolbutton.off("click"); patrolbutton.disabled = true; patrolbutton.updateDisabled(); cignorebutton.off("click"); cignorebutton.disabled = true; cignorebutton.updateDisabled(); loadNextChange(); }); $("#funpl-patroltool-loading").css("display", "none"); }).catch(patroltool_error); }).catch(patroltool_error); } else { console.log("[PatrolTool] Ignored compare for change " + i); $("#funpl-patroltool-desc").html(`<table class="wikitable"> <tr><th></th><th>Previous change</th><th>This change</th></tr> <tr> <th>Page title</th> <td>-</td> <td><a target="_blank" href="/wiki/${encode(change.title)}">${change.title.encodeHTML()}</a></td> </tr> <tr> <th>Editor</th> <td>-</td> <td><a target="_blank" href="/wiki/User:${encode(change.user)}">${change.user.encodeHTML()}</a> <a target="_blank" href="/wiki/User%20talk:${encode(change.user)}">(talk)</a></td> </tr> <tr> <th>Edit summary</th> <td>-</td> <td>${change.parsedcomment}</td> </tr> <tr> <th></th> <td>-</td> <td><a target="_blank" href="/wiki/${encode(change.title)}?oldid=${urlSafe(change.revid)}">View</a></td> </tr> <tr> <th>Date</th> <td>-</td> <td>${new Date(change.timestamp).toLocaleString()}</td> </tr> <tr> <th></th> <td>-</td> <td><a target="_blank" href="/wiki/${encode(change.title)}?action=edit&oldid=${urlSafe(change.revid)}">Edit</a></td> </tr> </table>`) $("#funpl-patroltool-diff").html("No diff data available"); mwApi.get({ "action": "parse", "format": "json", "oldid": change.revid }).done((parse) => { console.log("[PatrolTool] parse", parse); $("#funpl-patroltool-preview").html(parse.parse.text["*"]); $("#funpl-patroltool-preview").append('<div id="#funpl-patroltool-categories" class="catlinks"></div>'); let cattext = ""; for (var cat of parse.parse.categories) { cattext += '<li><a href="/wiki/Category:' + encode(cat["*"]) + '">' + cat["*"].encodeHTML() + '</a></li>'; } if (cattext != "") { $("#funpl-patroltool-categories").html("<b>Categories:</b> <ul>" + cattext + "</ul>"); } patrolbutton.disabled = false; patrolbutton.updateDisabled(); patrolbutton.off("click"); patrolbutton.on("click", function () { patrolbutton.off("click"); patrolbutton.disabled = true; patrolbutton.updateDisabled(); cignorebutton.off("click"); cignorebutton.disabled = true; cignorebutton.updateDisabled(); $("#funpl-patroltool-header").text("Loading..."); $("#funpl-patroltool-loading").css("display", ""); $("#funpl-patroltool-desc").html(''); $("#funpl-patroltool-diff").html(''); $("#funpl-patroltool-preview").html(''); mwApi.postWithToken("patrol", { "action": "patrol", "format": "json", "revid": change.revid }).done(function () { loadNextChange(); }).catch(function (err) { if (err == notpatrollable) { alert("Failed to patrol edit due to it being not patrolable"); loadNextChange(); } else { patroltool_error(err); } }); }); cignorebutton.disabled = false; cignorebutton.updateDisabled(); cignorebutton.off("click"); cignorebutton.on("click", function () { patrolbutton.off("click"); patrolbutton.disabled = true; patrolbutton.updateDisabled(); cignorebutton.off("click"); cignorebutton.disabled = true; cignorebutton.updateDisabled(); loadNextChange(); }); $("#funpl-patroltool-loading").css("display", "none"); }).catch(patroltool_error); } } else { console.log("[PatrolTool] Change " + i + " is patrolled, skipping"); loadNextChange(); } }).catch(patroltool_error); } catch (ex) { patroltool_error(ex); } } window.loadChange = loadChange; if (!String.prototype.encodeHTML) { //https://stackoverflow.com/a/7918944 String.prototype.encodeHTML = function () { return this.replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/'/g, '''); }; } if (!String.prototype.decodeHTML) { //https://stackoverflow.com/a/7918944 String.prototype.decodeHTML = function () { return this.replace(/'/g, "'") .replace(/"/g, '"') .replace(/>/g, '>') .replace(/</g, '<') .replace(/&/g, '&'); }; } function encode(str) { return str.replace(/"/g, "\"") .replace(/\\/g, "\\\\"); } function urlSafe(str) { return encode(encodeURIComponent(str)); } } catch (err) { patroltool_error(err) } })