Jump to content

User:Evad37/EditWarChecker.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/* 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", "/media/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", "/media/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", "/media/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", "/media/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"});
	});
});