Who Downvoted Me!?

Find out who downvoted your StackOverflow answer.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Who Downvoted Me!?
// @namespace   geneticcoder.com
// @description Find out who downvoted your StackOverflow answer.
// @include     http://stackoverflow.com/questions/*
// @version     1
// @grant       none
// ==/UserScript==

/**
 * This script will check if you have an answer on the current page, if so,
 * it will check the reputation of every other user who posted an answer or
 * comment on the page every n seconds and if your vote has gone down it will
 * tell you the name of any users who's reputation has gone down since the vote.
 * 
 * This works because it costs 1 reputation to downvote on S.O.
 * 
 * The only ocnfigurable parameter is the "runInterval" variable directly below.
 */

// How ofter should the script check for changes (seconds).
var runInterval = 10;

(function () {

	// Hold info abuot other users on the page
	var users = {};
	// My username
	var username = "";
	// My current score
	var myscore = 0;

	function main() {
		// What's my username
		getMyUsername(function (un) {
			username = un;
			// Get my question score
			myscore = getAnswerScore();
			if(myscore === false) 
				return console.log("You have no answers on this page. Killing WhoDownvotedMe.js.");
			// Get all users on the page's rep
			checkUsers(function(scores){ users = scores; });
			// Compare and check every n seconds
			setInterval(compareScores, (runInterval*1000));
		});
		
		return "Running WhoDownvotedMe.js.";
	}
	
	function compareScores(){
		var me = getAnswerScore();
		// My score is the same, just update stuff
		if(me >= myscore){
			myscore = me;
			checkUsers(function(scores){ users = scores; });
		}
		// If my votes have dropped, check to see if anyone else's have as well
		else{
			var possibles = [];
			checkUsers(function(scores){ 
				for(var u in scores){
					if(!scores.hasOwnProperty(u)) continue;
					if(undefined === users[u]) users[u] = scores[u];
					if(scores[u] < users[u]) possibles.push({
						user: u,
						lost: (users[u] - scores[u])
					});
				}
				users = scores;
				var message = "Your answer has been downvoted.\n\n";
				if(!possibles.length) message += "It is unclear who voted.";
				else{
					message += "Possible downvoters are: \n";
					for(var i=0; i<possibles.length; i++)
						message += 
							possibles[i].user + " (-"+possibles[i].lost+" points)\n";
				}
				alert(message);
			});
		}
	}
	
	function getMyUsername(cb) {
		var url = "http://stackoverflow.com" + $(".profile-me").attr("href");
		$.ajax({
			url: url
		}).done(function (r) {
			var un = $(r).find(".name").text().trim();
			cb(un);
		});
	}

	function getAnswerScore() {
		var rep = false;
		$(".answer").find(".user-details a").each(function () {
			var un = $(this).text().trim();
			if (un === username) {
				var score = $(this).parent().parent().
					parent().parent().parent().
					parent().parent().parent().
					find(".vote-count-post").text().trim();
				rep = parseInt(score);
			}
		});
		return rep;
	}

	function checkUsers(cb) {
		var unique = [];
		var scores = {};
		var active_requests = 0;
		// Gather info about other users on the page
		$(".user-details").find("a").add(".comment-user").each(function () {
			var href = $(this).attr("href");
			var url = "http://stackoverflow.com" + href;
			var un = $(this).text();
			if(un === username || unique.indexOf(un) > -1) return;
			else unique.push(un);
			active_requests++;
			(function (un) {
				$.ajax({
					url: url
				}).done(function (r) {
					active_requests--;
					var un_span = $(r).find(".avatar-card").find(".reputation").eq(0);
					un_span.find("span").remove();
					var rep = un_span.text().trim();
					scores[un] = parseInt(rep.replace(/\D/g,''));
					if(active_requests === 0) cb(scores);
				});
			})(un);
		});
	}

	return main();

})();