View text source at Wikipedia
/* jshint esversion: 5, laxbreak: true, undef: true, eqnull: true, maxerr: 999 */
/* globals console, window, $, mw */
$.when(
mw.loader.using([ "mediawiki.api"]),
$.ready
).then(function() {
var config = mw.config.get(['wgPageName', 'wgArticleId', 'wgNamespaceNumber']);
if (config.wgNamespaceNumber !== 0 || config.wgArticleId === 0) {
return;
}
var minMax = function(number, min, max) {
if (number < min) {
return min;
} else if (number > max) {
return max;
}
return number;
};
config.hours = minMax(window.EWC_hours || 24, 2, 72);
var api = new mw.Api({
ajax: {
headers: {
"Api-User-Agent": "EditWarChecker ( https://en.wikipedia.org/wiki/User:Evad37/EditWarChecker )"
}
}
});
api.get({
"action": "query",
"format": "json",
"prop": "revisions",
"titles": config.wgPageName,
"rvprop": "ids|timestamp|flags|comment|user|tags|size",
"rvslots": "*",
"rvlimit": "max",
"rvend": new Date(Date.now() - config.hours*60*60*1000).toISOString()
})
.then(function(response) {
var revertUsers = {};
var maxUserReverts = 0;
function addRevert(user) {
if (revertUsers[user]) {
revertUsers[user] = revertUsers[user]++;
} else {
revertUsers[user] = 1;
}
if (revertUsers[user] > maxUserReverts) {
maxUserReverts = revertUsers[user] ;
}
}
var reverts = (response.query.pages[config.wgArticleId].revisions || [])
.filter(function(revision, index, arr) {
// Edits tagged by system
if (revision.tags.includes("mw-undo") || revision.tags.includes("mw-rollback")) {
addRevert(revision.user);
return true;
}
// Edits with undo/revert comment
if (/(?:undo|undid|revert)/i.test(revision.comment)) {
addRevert(revision.user);
return true;
}
// Edits with same kB change but opposite signs
var thisEditDiffSize = revision.size - (arr[index+1] ? arr[index+1].size : NaN);
var prevEditDiffSize = (arr[index+1] ? arr[index+1].size : NaN) - (arr[index+2] ? arr[index+2].size : NaN);
var minDiffSize = 10; // prevent false positives from minor copyedits
if (thisEditDiffSize && prevEditDiffSize && thisEditDiffSize > minDiffSize && thisEditDiffSize === prevEditDiffSize * -1) {
addRevert(revision.user);
return true;
}
return false;
});
var revertCount = reverts.length;
var revertUsersCount = Object.keys(revertUsers).length;
var usersToList = $.map(revertUsers, function(reverts, user) {
return reverts > 3 ? user + " (" + reverts + ")" : null;
}).join(", ");
var message = "Approximately " + revertCount +
(revertCount===1
? " revert"
: " reversions"
) +
(revertUsersCount>0
? " by " + revertUsersCount +
(revertUsersCount===1
? " user"
: " users"
)
: ""
) +
" in the last " + config.hours + " hours." +
(usersToList
? "\nUsers with 4+ reverts: " + usersToList
: ""
);
var $symbol = $("<img width='20' height='20' style='float:right;cursor:pointer;' title='Edit war checker'>");
switch(true) {
// Grey (non-alert): No reverts, or single revert
case revertCount <= 1:
$symbol.attr("src", "https://upload.wikimedia.org/wikipedia/commons/e/e1/ButtonGray.svg");
break;
// Green alert: Everyone well within 3RR; not too many total reverts
case maxUserReverts <= 2 && revertCount <= 5:
$symbol.attr("src", "https://upload.wikimedia.org/wikipedia/commons/3/3c/ButtonGreen.svg");
break;
// Orange alert: One or more users at the 3RR limit; and/or quite a few reverts
case maxUserReverts <= 3 && revertCount <= 10:
$symbol.attr("src", "https://upload.wikimedia.org/wikipedia/commons/a/a6/ButtonOrange.svg");
break;
// Red alert: One or more users are passed the 3RR limit; and/or there are a lot of reverts
default:
$symbol.attr("src", "https://upload.wikimedia.org/wikipedia/commons/9/97/ButtonRed.svg");
break;
}
$symbol.click(function() {
mw.notify( message, { title: "Edit war checker", tag: "editWarCheck" } );
});
$('h1').append($symbol);
})
.catch(function(code, errorInfo) {
console.error("EditWarChecker error", errorInfo || code || "Unknown error");
var message = errorInfo && errorInfo.info || code.toString() || "Unknown error";
mw.notify(message, {title: "EditWarChecker failed to load"});
});
});