diff --git a/irc.py b/irc.py
index 8c170ce0fb9b7a312d6b0e0d65878ffec6870624..abd701a66b76c34c78035d99147f8b165e74734a 100644
--- a/irc.py
+++ b/irc.py
@@ -1,6 +1,12 @@
 import socket, os, threading, re
 import plugins
 
+class User(str):
+    def __init__(self, nick):
+        super(User, self).__init__(self, nick)
+        self.ident = ""
+        self.host = ""
+
 class PluginManager(object):
     def __init__(self, server):
         self.server = server
@@ -49,10 +55,8 @@ class PluginManager(object):
     def event(self, eventName, *args):
         eventName = eventName.lower()
         if eventName == "command":
-            handler = None
-            try:
-                handler = self.handlers[eventName][args[2].lower()]
-            except KeyError,ke: 
+            handler = self.handlers[eventName].get(args[2].lower(), None)
+            if handler is None:
                 return #no such command
                 
             try:
@@ -208,7 +212,7 @@ class IRC(threading.Thread):
             self.goodstart = False
         
         if self.goodstart:
-            ident = self.config["ident"] if self.config["ident"] != "" else self.config["nickname"]
+            self.config["ident"] = ident = self.config["ident"] if self.config["ident"] != "" else self.config["nickname"]
             self.sendLine("USER "+ident+" * * *")
             self.sendLine("NICK "+self.config["nickname"])
         
@@ -247,13 +251,12 @@ class IRC(threading.Thread):
             # Takes the ':Nick!Ident@Host' chunk and assigns (nick,ident,host) to user
             user = None
             if words[0].find("!") != -1:
-                nick = words[0][words[0].find(":") + 1:words[0].find('!')]
-                ident = words[0][words[0].find('!') + 1:words[0].find('@')]
-                host = words[0][words[0].find('@') + 1:]
-                user = (nick,ident,host)
+                user = User(words[0][words[0].find(":") + 1:words[0].find('!')])
+                user.ident = words[0][words[0].find('!') + 1:words[0].find('@')]
+                user.host = words[0][words[0].find('@') + 1:]
             else:
-                nick = words[0][words[0].find(":") + 1:]
-                user = (nick, "", "")
+                #it's our nick, in the format ":NickName"
+                user = User(words[0][words[0].find(":") + 1:])
                 
             if words[1] == "433":
                 #There was a nick collision
@@ -281,7 +284,7 @@ class IRC(threading.Thread):
             
             elif words[1] == "PRIVMSG":
                 # We got a message
-                channel = (words[2] if words[2] != self.config["nickname"] else user[0])
+                channel = (words[2] if words[2] != self.config["nickname"] else user)
                 message = data[data.find(":", data.find(channel[(channel.find("-") == -1 and 1 or channel.find("-")):]))+1:]
                 if message.find("\x01ACTION") == 0:
                     # String was found, it's an action
@@ -307,29 +310,29 @@ class IRC(threading.Thread):
             
             elif words[1] == "JOIN":
                 # Someone joined a channel that we're in
-                if user[0] != self.config["nickname"]:
+                if user != self.config["nickname"]:
                     self.pluginManager.event("join", words[2].strip(":"), user)
-                    self.userlist[words[2].strip(":")].append(user[0])
+                    self.userlist[words[2].strip(":")].append(user)
             
             elif words[1] == "PART":
-                if user[0] != self.config["nickname"]:
+                if user != self.config["nickname"]:
                     # Someone parted a channel we're in
-                    if user[0] in self.userlist[words[2].strip(":")]:
-                        self.userlist[words[2]].remove(user[0])
-                    self.pluginManager.event("part", words[2].strip(":"), user[0], " ".join(words[3:]))
+                    if user in self.userlist[words[2].strip(":")]:
+                        self.userlist[words[2]].remove(user)
+                    self.pluginManager.event("part", words[2].strip(":"), user, " ".join(words[3:]))
             
             elif words[1] == "QUIT":
                 # Someone quit the server
                 for k in self.userlist.keys():
-                    if user[0] in self.userlist[k]:
-                        self.userlist[k].remove(user[0])
+                    if user in self.userlist[k]:
+                        self.userlist[k].remove(user)
                 self.pluginManager.event("quit", user, " ".join(words[2:])[1:]) 
             
             elif words[1] == "NICK":
                 # Someone changed their nickname 
                 for k in self.userlist.keys():
-                    if user[0] in self.userlist[k]:
-                        self.userlist[k].remove(user[0])
+                    if user in self.userlist[k]:
+                        self.userlist[k].remove(user)
                         self.userlist[k].append(words[2].strip(":"))
                 self.pluginManager.event("nick", user, words[2].strip(":"))
             
@@ -363,15 +366,15 @@ class IRC(threading.Thread):
     
     def doMessage(self, channel, message):
         self.sendLine("PRIVMSG "+channel+" :"+message)
-        self.pluginManager.event("message", channel, (self.config["nickname"],"",""), message)
+        self.pluginManager.event("message", channel, User(self.config["nickname"]), message)
         
     def doAction(self, channel, action):
         self.sendLine("PRIVMSG "+channel+" :\x01ACTION "+action+" \x01")
-        self.pluginManager.event("action", channel, (self.config["nickname"],"",""), action)
+        self.pluginManager.event("action", channel, User(self.config["nickname"]), action)
     
     def doQuit(self, message=""):
         self.sendLine("QUIT :" + message)
-        self.pluginManager.event("quit", (self.config["nickname"],"",""), message)
+        self.pluginManager.event("quit", User(self.config["nickname"]), message)
         self.running = False
     
     def doNotice(self, user, message):
@@ -379,23 +382,23 @@ class IRC(threading.Thread):
     
     def doNick(self, newnick):
         self.sendLine("NICK " + newnick)
-        self.pluginManager.event("nick", self.config["nickname"], (newnick,"",""))
+        self.pluginManager.event("nick", User(self.config["nickname"]), User(newnick))
         self.config["nickname"] = newnick
     
     def doJoin(self, channel):
         self.sendLine("JOIN "+channel)
-        self.pluginManager.event("join", channel, (self.config["nickname"],"",""))
+        self.pluginManager.event("join", channel, User(self.config["nickname"]))
 
     def doKick(self, channel, user, message=""):
         self.sendLine("KICK %s %s :%s" % (channel, user, message))
-        self.pluginManager.event("kick", channel, (self.config["nickname"],"",""), user, message)
+        self.pluginManager.event("kick", channel, User(self.config["nickname"]), user, message)
         
     def doPart(self, channel, message=""):
         self.sendLine("PART "+channel)
         if channel in self.userlist.keys():
             del self.userlist[channel]
-        self.pluginManager.event("part", channel, (self.config["nickname"],"",""), message)
+        self.pluginManager.event("part", channel, User(self.config["nickname"]), message)
     
     def doMode(self, channel, mode, user=""):
         self.sendLine("MODE "+channel+" "+mode+user)
-        self.pluginManager.event("mode", channel, (self.config["nickname"],"",""), mode, user)
+        self.pluginManager.event("mode", channel, User(self.config["nickname"]), mode, user)
diff --git a/plugins/auth.py b/plugins/auth.py
index cc1467ec8cb9d0003dcd03ff24c0c67f629a145c..8bb45a654b81f6de5049f87d44db9f3600f5849e 100644
--- a/plugins/auth.py
+++ b/plugins/auth.py
@@ -53,7 +53,6 @@ class Auth(object):
             del self.mods[oldnick.lower()]
         
     def handle_command(self, channel, user, cmd, args):
-        user = user[0]
         if cmd == "owners":
             self.server.doMessage(channel, user+": My owners are: "+" ".join(self.owners))
         elif cmd == "admins":
diff --git a/plugins/bbot.py b/plugins/bbot.py
new file mode 100644
index 0000000000000000000000000000000000000000..394c166a1b151e253d292e789fafe60c3a950212
--- /dev/null
+++ b/plugins/bbot.py
@@ -0,0 +1,75 @@
+import re
+import time
+ 
+@plugin
+class Blockbot(object):
+    def __init__(self, server):
+        self.server = server
+        self.prnt = server.prnt
+        
+        self.server.handle("message", self.handle_message)
+ 
+        findlist = [
+            'you will be  unable to connect to freenode  unless you are using sasl'
+        ]
+        self.mps_limit = 4
+        self.storage_time = 25
+        self.repeat_limit = 3
+        self.repeat_1word = 4
+ 
+        # Compile Spam Strings        
+        self.findlist = []
+        if findlist:
+            for each in findlist:
+                self.findlist.append(re.compile(each))
+ 
+        # Load Default Data
+        self.msglist = []
+        #self.lastnot = ('BBot', time.time(), 'sdkljfls')
+ 
+    def handle_message(self, channel, nick, message):
+        """ Called when a message is received """
+        self.msglist.insert(0, (nick, channel, message,
+                                time.time()))
+ 
+        # Check for spam strings
+        ldata = message.lower()
+        for each in self.findlist:
+            if re.search(each, ldata):
+                self.server.doKick(channel, nick, 'You have matched a spam string and have been banned, if you this is a mistake, contact a channel op to be unbanned')
+                return
+ 
+        # Extract messages by this user
+        user_msgs = []
+        for msg in self.msglist:
+            if msg[0] == nick:
+                user_msgs.append((nick, msg[1], msg[2], msg[3]))
+ 
+        # Check for flooding
+        if self.get_mps(user_msgs) > self.mps_limit:
+            self.server.doKick(channel, nick,'Please do not flood')
+            self.msglist.pop(0)
+ 
+        # Check for repeats
+        strings = []
+        repeats = 0
+        for msg in user_msgs:
+            if msg[2] not in strings:
+                strings.append(msg[2])
+            else:
+                repeats += 1
+        if repeats > self.repeat_limit-1:
+            self.server.doKick(channel, nick, 'Do not repeat yourself...')
+            self.msglist.pop(0)
+ 
+        # Clear out old messages
+        now = time.time()
+        for msg in self.msglist:
+            if now - msg[3] > self.storage_time:
+                self.msglist.remove(msg)
+       
+    def get_mps(self, user_msgs):
+        '''Count the number of messages sent per second'''
+        time_range = user_msgs[0][3] - user_msgs[-1][3]
+        mps =  len(user_msgs) / time_range
+        return mps
diff --git a/plugins/blockbot.py b/plugins/blockbot.py
new file mode 100644
index 0000000000000000000000000000000000000000..394c166a1b151e253d292e789fafe60c3a950212
--- /dev/null
+++ b/plugins/blockbot.py
@@ -0,0 +1,75 @@
+import re
+import time
+ 
+@plugin
+class Blockbot(object):
+    def __init__(self, server):
+        self.server = server
+        self.prnt = server.prnt
+        
+        self.server.handle("message", self.handle_message)
+ 
+        findlist = [
+            'you will be  unable to connect to freenode  unless you are using sasl'
+        ]
+        self.mps_limit = 4
+        self.storage_time = 25
+        self.repeat_limit = 3
+        self.repeat_1word = 4
+ 
+        # Compile Spam Strings        
+        self.findlist = []
+        if findlist:
+            for each in findlist:
+                self.findlist.append(re.compile(each))
+ 
+        # Load Default Data
+        self.msglist = []
+        #self.lastnot = ('BBot', time.time(), 'sdkljfls')
+ 
+    def handle_message(self, channel, nick, message):
+        """ Called when a message is received """
+        self.msglist.insert(0, (nick, channel, message,
+                                time.time()))
+ 
+        # Check for spam strings
+        ldata = message.lower()
+        for each in self.findlist:
+            if re.search(each, ldata):
+                self.server.doKick(channel, nick, 'You have matched a spam string and have been banned, if you this is a mistake, contact a channel op to be unbanned')
+                return
+ 
+        # Extract messages by this user
+        user_msgs = []
+        for msg in self.msglist:
+            if msg[0] == nick:
+                user_msgs.append((nick, msg[1], msg[2], msg[3]))
+ 
+        # Check for flooding
+        if self.get_mps(user_msgs) > self.mps_limit:
+            self.server.doKick(channel, nick,'Please do not flood')
+            self.msglist.pop(0)
+ 
+        # Check for repeats
+        strings = []
+        repeats = 0
+        for msg in user_msgs:
+            if msg[2] not in strings:
+                strings.append(msg[2])
+            else:
+                repeats += 1
+        if repeats > self.repeat_limit-1:
+            self.server.doKick(channel, nick, 'Do not repeat yourself...')
+            self.msglist.pop(0)
+ 
+        # Clear out old messages
+        now = time.time()
+        for msg in self.msglist:
+            if now - msg[3] > self.storage_time:
+                self.msglist.remove(msg)
+       
+    def get_mps(self, user_msgs):
+        '''Count the number of messages sent per second'''
+        time_range = user_msgs[0][3] - user_msgs[-1][3]
+        mps =  len(user_msgs) / time_range
+        return mps
diff --git a/plugins/info.py b/plugins/info.py
index ab40a30098070cf2424c360e5462c81d8a3bf928..2dafe567b2c68b0e03bef8f85d7c04341dc8f1ec 100644
--- a/plugins/info.py
+++ b/plugins/info.py
@@ -32,7 +32,6 @@ class Info(object):
         return [None, None]
         
     def handle_command(self, channel, user, cmd, args, info_silent = False):
-        user = user[0]
         if cmd == "what" or cmd == "who":
             for i in range(0, len(args)):
                 args[i] = self.badchars.sub("", args[i])
diff --git a/plugins/plugintools.py b/plugins/plugintools.py
index 5a2ae340e0732e1088097063ba7d8fc2a0579f01..9a744bbb8744d145a5a594f5f689e08076fd0c63 100644
--- a/plugins/plugintools.py
+++ b/plugins/plugintools.py
@@ -9,7 +9,6 @@ class PluginLoader(object):
         self.server.handle("command", self.handle_command, self.commands)
         
     def handle_command(self, channel, user, cmd, args):
-        user = user[0]
         if self.server.getPlugin("auth").isMod(user):
             if cmd == "reloadall":
                 self.server.pluginManager.unloadAllPlugins()
diff --git a/plugins/printer.py b/plugins/printer.py
index 7a8456610c315ef719d53bcf16ca0e23b01c3eb3..2647c660e410a6410ac695ba5636c9228b860002 100644
--- a/plugins/printer.py
+++ b/plugins/printer.py
@@ -18,11 +18,9 @@ class Printer(object):
         self.prnt("I have disconnected from %s" % server)
     
     def handle_message(self, channel, user, message):
-        user = user[0]
         self.prnt("<%s> %s: %s" % (channel, user, message))
     
     def handle_action(self, channel, user, action):
-        user = user[0]
         self.prnt("<%s> * %s %s" % (channel, user, action))
     
     def handle_join(self, channel, user):
@@ -30,17 +28,16 @@ class Printer(object):
         self.prnt("%s has joined %s" % (user, channel))
         
     def handle_part(self, channel, user, message):
-        user = user[0]
         self.prnt("%s has left %s (%s)" % (user, channel, message))
         
     def handle_quit(self, user, message):
-        user = user[0]
         self.prnt("%s has quit (%s)" % (user, message))
     
     def handle_nick(self, oldnick, newnick):
-        user = user[0]
         self.prnt("%s is now known as %s" % (oldnick, newnick))
     
+    def handle_kick(self, channel, user, userkicked, message):
+        self.prnt("%s has kicked %s from %s (%s)" % (user, userkicked, channel, message))
+    
     def handle_mode(self, channel, user, mode, otheruser):
-        user = user[0]
         self.prnt("%s set mode %s on %s" % (user, mode, otheruser if otheruser != "" else channel))