function WatchPlugin(bot) {
	var self = this;
	self.name = "watch";
	self.help = "WATCH plugin";
	self.depend = [];

	self.listArray = [];
	self.listCallbacks = [];

	self.statData = {};
	self.statCallbacks = [];

	self.isonCallbacks = [];

	self.watch = function(args) {
		args.unshift("WATCH");
		bot.send.apply(bot, args);
	};

	self.add = function(nick) {
		self.watch(["+" + nick]);
	};

	self.remove = function(nick) {
		self.watch(["-" + nick]);
	};

	self.change = function(from, to) {
		self.watch(["-" + from, "+" + to]);
	};

	self.list = function(callback) {
		if (self.listCallbacks.length == 0)
			self.watch(["l"]);

		self.listCallbacks.push(callback);
	};

	self.stat = function(callback) {
		if (self.statCallbacks.length == 0) {
			self.watch(["s"]);
			self.statData.list = [];
		}

		self.statCallbacks.push(callback);
	};

	self.ison = function(nicks, callback) {
		nicks.unshift("ISON");
		bot.send.apply(bot, nicks);

		self.isonCallbacks.push(callback);
	};

	self.emitEvents = {
		"600": "watch#logon",
		"601": "watch#logoff",
		"604": "watch#nowon",
		"605": "watch#nowoff"
	};

	self.events = {
		"raw": function(message) {
			switch (message.rawCommand) {
			case "600": // logon
			case "601": // logoff
			case "604": // nowon
			case "605": // nowoff
				var watch = {
					nick: message.args[1],
					user: message.args[2],
					host: message.args[3],
					logon: new Date(message.args[4] * 1000)
				};

				if (message.rawCommand == "604" && self.listCallbacks.length > 0) {
					self.listArray.push(watch);
				}

				bot.emit(self.emitEvents[message.rawCommand], watch);
				break;

			case "603": // watchstat
				var re = /You have (\d+) and are on (\d+) WATCH entries/;
				var match = message.args[1].match(re);
				if (match && self.statCallbacks.length > 0) {
					self.statData.have = parseInt(match[1]);
					self.statData.on = parseInt(match[2]);
				}
				break;

			case "606": // watchlist
				if (self.statCallbacks.length > 0) {
					self.statData.list = self.statData.list.concat(message.args[1].split(" "));
				}
				break;

			case "607": // end of watchlist
				for (var i = 0; i < self.listCallbacks.length; i++) {
					self.listCallbacks[i](self.listArray);
				}

				for (var i = 0; i < self.statCallbacks.length; i++) {
					var data = self.statData;
					self.statCallbacks[i](data.have, data.on, data.list);
				}

				self.listCallbacks = [];
				self.listArray = [];
				self.statCallbacks = [];
				self.statData = {};
				break;

			case "303": // ISON reply
				var callback = self.isonCallbacks.shift();
				callback(message.args[1].trim().split(" "));
				break;
			}
		}
	}
}

module.exports = WatchPlugin;

@@ -2104,24 +2104,160 @@
 f watchlist%0A
+%09%09%09%09var re = /End of WATCH (%5Cw)/;%0A%09%09%09%09var match = message.args%5B1%5D.match(re);%0A%09%09%09%09if (match) %7B%0A%09%09%09%09%09switch (match%5B1%5D) %7B%0A%09%09%09%09%09case %22l%22:%0A%09%09
 %09%09%09%09for (var
@@ -2299,32 +2299,34 @@
 th; i++) %7B%0A%09%09%09%09%09
+%09%09
 self.listCallbac
@@ -2348,27 +2348,117 @@
 Array);%0A%09%09%09%09
+%09%09
 %7D%0A%0A
+%09%09%09%09%09%09self.listCallbacks = %5B%5D;%0A%09%09%09%09%09%09self.listArray = %5B%5D;%0A%09%09%09%09%09break;%0A%0A%09%09%09%09%09case %22s%22:%0A%09%09
 %09%09%09%09for (var
@@ -2499,24 +2499,26 @@
 gth; i++) %7B%0A
+%09%09
 %09%09%09%09%09var dat
@@ -2537,24 +2537,26 @@
 tData;%0A%09%09%09%09%09
+%09%09
 self.statCal
@@ -2597,27 +2597,31 @@
 .list);%0A%09%09%09%09
+%09%09
 %7D%0A%0A
+%09%09
 %09%09%09%09self.lis
@@ -2609,35 +2609,35 @@
 %09%09%7D%0A%0A%09%09%09%09%09%09self.
-lis
+sta
 tCallbacks = %5B%5D;
@@ -2645,81 +2645,55 @@
 %09%09%09%09
+%09%09
 self.
-listArray = %5B%5D
+statData = %7B%7D
 ;%0A%09%09%09%09
-self.statCallbacks = %5B%5D;%0A%09%09%09%09self.statData = %7B%7D;
+%09%09break;%0A%09%09%09%09%09%7D%0A%09%09%09%09%7D
 %0A%09%09%09

Stop WATCHlist endings from interfering