From 1838bef6ed391719dbf7cefa6a0dba085ee599c2 Mon Sep 17 00:00:00 2001 From: FurryHead <furryhead14@yahoo.com> Date: Fri, 17 Jun 2011 20:35:13 +0000 Subject: [PATCH] Added kick event; Misc syntax fixes; Auth plugin almost done dgfsdfgdshf%^#$^&@!#%^@% --- guppy.py | 2 + irc.py | 82 ++++++++++++++++++++------- plugins/auth.py | 120 +++++++++++++++++++++++++++++----------- plugins/channeltools.py | 1 + plugins/ddg.py | 1 + plugins/die.py | 1 + plugins/dns.py | 1 + plugins/dynacode.py | 1 + plugins/info.py | 26 +-------- plugins/ping.py | 1 + plugins/plugintools.py | 1 + plugins/printer.py | 7 +++ plugins/rpn.py | 1 + plugins/smack.py | 1 + plugins/tinyurl.py | 1 + plugins/wikipedia.py | 1 + 16 files changed, 173 insertions(+), 75 deletions(-) diff --git a/guppy.py b/guppy.py index 8a494f9..72e0f50 100644 --- a/guppy.py +++ b/guppy.py @@ -86,6 +86,8 @@ class main(object): for client in threading.enumerate(): if client.__class__.__name__ != "_MainThread": client.doQuit("Keyboard interrupt.") + time.sleep(1) + client.pluginManager.unloadAllPlugins() def my_raw(self,prompt="", default=""): ret = raw_input("%s [%s]: "%(prompt,default)) diff --git a/irc.py b/irc.py index bd8c815..0ff3c18 100644 --- a/irc.py +++ b/irc.py @@ -1,4 +1,4 @@ -import socket, os, threading +import socket, os, threading, re import plugins class PluginManager(object): @@ -15,8 +15,8 @@ class PluginManager(object): "disconnect": [ ], "action" : [ ], "nick" : [ ], + "kick" : [ ], "mode" : [ ], - "ping" : [ ], "command" : { }, } @@ -161,7 +161,7 @@ class PluginManager(object): def unloadAllPlugins(self): errs = {} - for plugin in self.plugins: + for plugin in self.plugins.copy().keys(): err = self.unloadPlugin(plugin.lower()) if err is not None: errs[plugin] = err @@ -184,6 +184,7 @@ class IRC(threading.Thread): self.prnt("Plugin "+k+" error loading: "+v) self.running = False + self.userlist = { } def _readline(self): ret = [] @@ -223,6 +224,8 @@ class IRC(threading.Thread): except socket.timeout: raise IOError("Connection was broken.") + if not self.running: continue + if data == "": self.prnt("Connection lost to server.") self.running = False @@ -241,8 +244,9 @@ class IRC(threading.Thread): self.running = False continue - # Takes the ':Nick!Ident@Host' chunk and assigns Nick to user - user = words[0].split(":")[1].split("!")[0] + # Takes the ':Nick!Ident@Host' chunk and assigns (nick,ident,host) to user + chunk = words[0].split(":")[1] + user = (chunk.split("!")[0], chunk.split("!")[1].split("@")[0], chunk.split("!")[0].split("@")[1]) if words[1] == "433": #There was a nick collision @@ -259,9 +263,18 @@ class IRC(threading.Thread): for chan in [k for k in self.config["channels"].split(",") if k != '']: self.doJoin(chan) + elif words[1] == "353": + #user list, if it's large, we only got part of it. + words = [k for k in data.replace(" =", "").split(" ") if k != ''] + if self.userlist.get(words[3], None) is None: + self.userlist[words[3]] = [] + + userlist = [u.strip(":") for u in words[3:]] + self.userlist[words[3]] += userlist + elif words[1] == "PRIVMSG": # We got a message - channel = (words[2] if words[2] != self.config["nickname"] else user) + channel = (words[2] if words[2] != self.config["nickname"] else user[0]) 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 @@ -272,27 +285,45 @@ class IRC(threading.Thread): cmd = args[0][len(self.config["comchar"]):] args.pop(0) self.pluginManager.event("message", channel, user, message) - self.pluginManager.event("command", channel, user, cmd, args) + self.pluginManager.event("command", channel, user, cmd.lower(), args) else: - # Strings not found, it's a message - self.pluginManager.event("message", channel, user, message) + if re.match("^"+self.config["nickname"]+"[^A-Za-z0-9] .+$", message): + #Someone addressed us, it's a command (probably) + args = message.split(" ") + cmd = args[1] + args = args[2:] + self.pluginManager.event("message", channel, user, message) + self.pluginManager.event("command", channel, user, cmd.lower(), args) + else: + #Nothing was found, it has to be a message + self.pluginManager.event("message", channel, user, message) elif words[1] == "JOIN": # Someone joined a channel that we're in - if user != self.config["nickname"]: + if user[0] != self.config["nickname"]: self.pluginManager.event("join", words[2].strip(":"), user) + self.userlist[words[2].strip(":")].append(user) elif words[1] == "PART": if user != self.config["nickname"]: # Someone parted a channel we're in - self.pluginManager.event("part", words[2], user, " ".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 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 in self.userlist[k]: + self.userlist[k].remove(user) + self.userlist[k].append(words[2].strip(":")) self.pluginManager.event("nick", user, words[2].strip(":")) elif words[1] == "MODE": @@ -301,6 +332,13 @@ class IRC(threading.Thread): self.pluginManager.event("mode", words[2], user, words[3], words[4]) except IndexError: # words[4] is not valid, it wasn't set on a user self.pluginManager.event("mode", words[2], user, words[3], "") + + elif words[1] == "KICK": + #someone kicked someone + if self.userlist.get(words[2].lower(), None) is not None: + self.userlist[words[2].lower()].remove(words[3]) + + self.pluginManager.event("kick", words[2], user, words[3], words[4][1:]) #end of loop if self.goodstart: @@ -324,9 +362,9 @@ class IRC(threading.Thread): self.sendLine("PRIVMSG "+channel+" :\x01ACTION "+action+" \x01") self.pluginManager.event("action", channel, self.config["nickname"], action) - def doQuit(self, message=None): - self.sendLine("QUIT :" + (message or "")) - self.pluginManager.event("quit", self.config["nickname"], (message or "")) + def doQuit(self, message=""): + self.sendLine("QUIT :" + message) + self.pluginManager.event("quit", self.config["nickname"], message) self.running = False def doNotice(self, user, message): @@ -340,11 +378,17 @@ class IRC(threading.Thread): def doJoin(self, channel): self.sendLine("JOIN "+channel) self.pluginManager.event("join", channel, 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) - def doPart(self, channel, message=None): + def doPart(self, channel, message=""): self.sendLine("PART "+channel) - self.pluginManager.event("part", channel, self.config["nickname"], (message or "")) + if channel in self.userlist.keys(): + del self.userlist[channel] + self.pluginManager.event("part", channel, self.config["nickname"], message) - def doMode(self, channel, mode, user=None): - self.sendLine("MODE "+channel+" "+mode+(user if user is not None else "")) - self.pluginManager.event("mode", channel, self.config["nickname"], mode, (user if user is not None else "")) + def doMode(self, channel, mode, user=""): + self.sendLine("MODE "+channel+" "+mode+user) + self.pluginManager.event("mode", channel, self.config["nickname"], mode, user) diff --git a/plugins/auth.py b/plugins/auth.py index e4db452..cc1467e 100644 --- a/plugins/auth.py +++ b/plugins/auth.py @@ -6,14 +6,54 @@ class Auth(object): self.server = server self.commands = [ "addadmin", "addmod", "deladmin", "delmod", "admins", "mods", "owners", "passwd", "identify" ] self.owners = {} + self.authed_owner_hosts = [] self.admins = {} + self.authed_admin_hosts = [] self.mods = {} + self.authed_mod_hosts = [] self.server.handle("command", self.handle_command, self.commands) + self.server.handle("part", self.handle_part) + self.server.handle("quit", self.handle_quit) + self.server.handle("nick", self.handle_nick) self.authdir = self.server.config["confdir"] + "network-auth-users/" self.authfile = self.authdir + self.server.config["network"] + "-auth.cfg" self._loadusers() + + def _checkAuth(self, user): + user = user[0] + stillOn = False + for ch in self.server.userlist.keys(): + if user in self.server.userlist[ch]: + stillOn = True + + if not stillOn: + if user.lower() in self.owners.keys(): + self.owners[user.lower()][1] = False + elif user.lower() in self.admins.keys(): + self.admins[user.lower()][1] = False + elif user.lower() in self.mods.keys(): + self.mods[user.lower()][1] = False + + def handle_quit(self, user, message): + self._checkAuth(user) + + def handle_part(self, channel, user, message): + self._checkAuth(user) + + def handle_nick(self, oldnick, newnick): + if self.isOwner(oldnick): + print self.owners + self.owners[newnick.lower()] = self.owners[oldnick.lower()] + del self.owners[oldnick.lower()] + elif self.isAdmin(oldnick): + self.admins[newnick.lower()] = self.admins[oldnick.lower()] + del self.admins[oldnick.lower()] + elif self.isMod(oldnick): + self.mods[newnick.lower()] = self.mods[oldnick.lower()] + 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": @@ -22,43 +62,43 @@ class Auth(object): self.server.doMessage(channel, user+": My moderators are: "+" ".join(self.mods)) elif cmd == "passwd": if channel == user: - if user in self.owners.keys(): - if self.owners[user][1]: + if user.lower() in self.owners.keys(): + if self.owners[user.lower()][1]: if len(args) < 1: self.server.doMessage(channel, user+": Not enough arguments.") return if len(args) >= 2: - self.owners[user][0] = args[1] + self.owners[user.lower()][0] = args[1] self.server.doMessage(channel, user+": Password successfully changed.") else: - self.owners[user][0] = args[0] + self.owners[user.lower()][0] = args[0] self.server.doMessage(channel, user+": Password successfully changed.") - elif user in self.admins.keys(): - if self.admins[user][1]: + elif user.lower() in self.admins.keys(): + if self.admins[user.lower()][1]: if len(args) < 1: self.server.doMessage(channel, user+": Not enough arguments.") return if len(args) >= 2: - self.admins[user][0] = args[1] + self.admins[user.lower()][0] = args[1] self.server.doMessage(channel, user+": Password successfully changed.") else: - self.admins[user][0] = args[0] + self.admins[user.lower()][0] = args[0] self.server.doMessage(channel, user+": Password successfully changed.") - elif user in self.mods.keys(): - if self.mods[user][1]: + elif user.lower() in self.mods.keys(): + if self.mods[user.lower()][1]: if len(args) < 1: self.server.doMessage(channel, user+": Not enough arguments.") return if len(args) >= 2: - self.mods[user][0] = args[1] + self.mods[user.lower()][0] = args[1] self.server.doMessage(channel, user+": Password successfully changed.") else: - self.mods[user][0] = args[0] + self.mods[user.lower()][0] = args[0] self.server.doMessage(channel, user+": Password successfully changed.") else: @@ -72,27 +112,27 @@ class Auth(object): self.server.doMessage(channel, user+": Not enough arguments.") return if channel == user: - if user in self.owners.keys(): - if self.owners[user][1]: + if user.lower() in self.owners.keys(): + if self.owners[user.lower()][1]: self.server.doMessage(channel, user+": You are already identified.") - elif args[0] == self.owners[user][0]: - self.owners[user][1] = True + elif args[0] == self.owners[user.lower()][0]: + self.owners[user.lower()][1] = True self.server.doMessage(channel, user+": You are now identified for "+user) else: self.server.doMessage(channel, user+": Invalid password.") - elif user in self.admins.keys(): - if self.admins[user][1]: + elif user.lower() in self.admins.keys(): + if self.admins[user.lower()][1]: self.server.doMessage(channel, user+": You are already identified.") - elif args[0] == self.admins[user][0]: - self.admins[user][1] = True + elif args[0] == self.admins[user.lower()][0]: + self.admins[user.lower()][1] = True self.server.doMessage(channel, user+": You are now identified for "+user) else: self.server.doMessage(channel, user+": Invalid password.") - elif user in self.mods.keys(): - if self.mods[user][1]: + elif user.lower() in self.mods.keys(): + if self.mods[user.lower()][1]: self.server.doMessage(channel, user+": You are already identified.") - elif args[0] == self.mods[user][0]: - self.mods[user][1] = True + elif args[0] == self.mods[user.lower()][0]: + self.mods[user.lower()][1] = True self.server.doMessage(channel, user+": You are now identified for "+user) else: self.server.doMessage(channel, user+": Invalid password.") @@ -118,15 +158,29 @@ class Auth(object): if args[0] in self.mods.keys(): del self.mods[args[0]] - def _saveusers(self): + #save users + def __del__(self): if not os.path.isdir(self.authdir): os.mkdir(self.authdir) fh = open(self.authfile, "w") + if not self.configParser.has_section("owners"): + self.configParser.add_section("owners") + if not self.configParser.has_section("admins"): + self.configParser.add_section("admins") + if not self.configParser.has_section("mods"): + self.configParser.add_section("mods") + + for user in self.owners.keys(): + self.configParser.set("owners",user,self.owners[user][0]) + for user in self.admins.keys(): + self.configParser.set("admins",user,self.admins[user][0]) + for user in self.mods.keys(): + self.configParser.set("mods",user,self.mods[user][0]) + self.configParser.write(fh) fh.close() - __del__ = _saveusers def _loadusers(self): if os.path.isfile(self.authfile): @@ -136,15 +190,15 @@ class Auth(object): for section in self.configParser.sections(): if section == "owners": for user,pswd in self.configParser.items(section): - self.owners[user] = [pswd, pswd == ''] + self.owners[user.lower()] = [pswd, pswd == ''] elif section == "admins": for user,pswd in self.configParser.items(section): - self.admins[user] = [pswd, pswd == ''] + self.admins[user.lower()] = [pswd, pswd == ''] elif section == "mods": for user,pswd in self.configParser.items(section): - self.mods[user] = [pswd, pswd == ''] + self.mods[user.lower()] = [pswd, pswd == ''] - onick = self.server.config["owner_nick"] + onick = self.server.config["owner_nick"].lower() if not onick in self.owners.keys(): if getattr(self, "configParser", None) is None: self.configParser = ConfigParser.RawConfigParser() @@ -156,16 +210,16 @@ class Auth(object): self.owners[onick] = ['', True] def isOwner(self, user): - return user in self.owners and self.owners[user][1] + return user.lower() in self.owners and self.owners[user.lower()][1] def isAdmin(self, user): - if user in self.admins and self.admins[user][1]: + if user.lower() in self.admins and self.admins[user.lower()][1]: return True else: return self.isOwner(user) def isMod(self, user): - if user in self.mods and self.mods[user][1]: + if user.lower() in self.mods and self.mods[user.lower()][1]: return True elif self.isAdmin(user): return True diff --git a/plugins/channeltools.py b/plugins/channeltools.py index 92f3e6b..f19288f 100644 --- a/plugins/channeltools.py +++ b/plugins/channeltools.py @@ -7,6 +7,7 @@ class ChannelTools(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").isAdmin(user): if len(args) < 1: self.server.doMessage(channel, user+": Not enough arguments.") diff --git a/plugins/ddg.py b/plugins/ddg.py index 86ad9c4..85ad9b6 100644 --- a/plugins/ddg.py +++ b/plugins/ddg.py @@ -13,6 +13,7 @@ class ddg(object): self.server.handle("command", self.handle_command, self.commands) def handle_command(self, channel, user, cmd, args): + user = user[0] if cmd == "ddg": if len(args) < 1: self.server.doMessage(channel, user+": DuckDuckGo.com Zero-Click infoboxes search. Syntax: ddg <query>.") diff --git a/plugins/die.py b/plugins/die.py index e5cffc1..2d6c0a1 100644 --- a/plugins/die.py +++ b/plugins/die.py @@ -8,6 +8,7 @@ class Die(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").isOwner(user): self.server.doMessage(channel, user + " wants me to leave, but I'll be back!") self.server.doQuit() diff --git a/plugins/dns.py b/plugins/dns.py index 5967502..06e91d7 100644 --- a/plugins/dns.py +++ b/plugins/dns.py @@ -12,6 +12,7 @@ class dns(object): self.server.handle("command", self.handle_command, self.commands) def handle_command(self, channel, user, cmd, args): + user = user[0] if cmd == "dns": if len(args) < 1: self.server.doMessage(channel, user+": Return a fully qualified domain name for a list of space-separated IPs or hostnames.") diff --git a/plugins/dynacode.py b/plugins/dynacode.py index d2a81be..c2fb71c 100644 --- a/plugins/dynacode.py +++ b/plugins/dynacode.py @@ -9,6 +9,7 @@ class DynaCode(object): self.env = { } def handle_command(self, channel, user, cmd, args): + user = user[0] if self.server.getPlugin("auth").isOwner(user) and cmd == "py": if len(args) < 1: self.server.doMessage(channel, user+": Not enough arguments.") diff --git a/plugins/info.py b/plugins/info.py index 2f638dd..ab40a30 100644 --- a/plugins/info.py +++ b/plugins/info.py @@ -4,9 +4,8 @@ import os, re class Info(object): def __init__(self, server): self.server = server - self.commands = [ "what", "learn", "forget", "fulldb" ] + self.commands = [ "what", "who", "learn", "forget", "fulldb" ] self.server.handle("command", self.handle_command, self.commands) - self.server.handle("message", self.handle_message) self.dbfile = self.server.config["confdir"] + "info.db" self.infodb = {} self.badchars = re.compile("[?]") @@ -33,7 +32,8 @@ class Info(object): return [None, None] def handle_command(self, channel, user, cmd, args, info_silent = False): - if cmd == "what": + user = user[0] + if cmd == "what" or cmd == "who": for i in range(0, len(args)): args[i] = self.badchars.sub("", args[i]) @@ -121,23 +121,3 @@ class Info(object): self.server.doMessage(channel, "I don't know what "+tmp+" is.") elif cmd == "fulldb": self.server.doMessage(channel, user+": My database contains (separated by '#'): "+" # ".join(self.infodb.keys())) - - def handle_message(self, channel, user, message): - if message.lower().startswith("what"): - args = message.split(" ")[1:] - self.handle_command(channel, user, "what", args, True) - - elif re.match("^.+( is ).+$", message.lower()) and not message.startswith(self.server.config["comchar"]) and not user == self.server.config["nickname"]: - - args = message.split(" ") - for i in range(0, len(args)): - if i > 4: return - if args[i] == "is": - args[i] = "as" - break - - self.handle_command(channel, user, "learn", args, True) - - elif message.startswith("forget"): - args = message.split(" ")[1:] - self.handle_command(channel, user, "forget", args, True) diff --git a/plugins/ping.py b/plugins/ping.py index ce16deb..1f5bd36 100644 --- a/plugins/ping.py +++ b/plugins/ping.py @@ -7,6 +7,7 @@ class Ping(object): self.server.handle("command", self.handle_command, self.commands) def handle_command(self, channel, user, cmd, args): + user = user[0] if cmd == "ping": if len(args) > 0: self.server.doMessage(channel, user+": Pong "+" ".join(args)) diff --git a/plugins/plugintools.py b/plugins/plugintools.py index 9a744bb..5a2ae34 100644 --- a/plugins/plugintools.py +++ b/plugins/plugintools.py @@ -9,6 +9,7 @@ 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 7976483..7a84566 100644 --- a/plugins/printer.py +++ b/plugins/printer.py @@ -18,22 +18,29 @@ 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): + user = user[0] 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_mode(self, channel, user, mode, otheruser): + user = user[0] self.prnt("%s set mode %s on %s" % (user, mode, otheruser if otheruser != "" else channel)) diff --git a/plugins/rpn.py b/plugins/rpn.py index 16147fc..79dab01 100644 --- a/plugins/rpn.py +++ b/plugins/rpn.py @@ -10,6 +10,7 @@ class rpn(object): self.server.handle("command", self.handle_command, self.commands) def handle_command(self, channel, user, cmd, args): + user = user[0] if cmd == "rpn": if len(args) < 1: self.server.doMessage(channel, user+": reverse-polish-notation calculator. syntax: rpn 2 4 1 + / gives 2/5.") diff --git a/plugins/smack.py b/plugins/smack.py index f4b33b7..27a6311 100644 --- a/plugins/smack.py +++ b/plugins/smack.py @@ -15,6 +15,7 @@ class Smack(object): ] def handle_command(self, channel, user, cmd, args): + user = user[0] if cmd == "smack" and len(args) > 0: self.server.doAction(channel, "smacks "+args[0]+" with a "+self.objects[random.Random().randint(0, len(self.objects)-1)]+"!") diff --git a/plugins/tinyurl.py b/plugins/tinyurl.py index cb4c22a..f5a1ca6 100644 --- a/plugins/tinyurl.py +++ b/plugins/tinyurl.py @@ -8,6 +8,7 @@ class TinyURL(object): self.server.handle("command", self.handle_command, self.commands) def handle_command(self, channel, user, cmd, args): + user = user[0] if cmd == "tinyurl": if len(args) < 1: self.server.doMessage(channel, user+": Not enough arguments.") diff --git a/plugins/wikipedia.py b/plugins/wikipedia.py index 16691a5..c1db907 100644 --- a/plugins/wikipedia.py +++ b/plugins/wikipedia.py @@ -9,6 +9,7 @@ class Wikipedia(object): self.server.handle("command", self.handle_command, self.commands) def handle_command(self, channel, user, cmd, args): + user = user[0] if cmd == "wiki": if len(args) < 1: self.server.doMessage(channel, user+": What should I search for on Wikipedia?") -- GitLab