User:Evad37/EditWarChecker.js

/* 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 = $("");

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"});

});

});