diff --git a/guppy.py b/guppy.py index 9ab335639e39bed94c4e3371103ccc2d698e9fec..8a494f9e5c8f2384a8191ccc50cd5ff52c86b363 100644 --- a/guppy.py +++ b/guppy.py @@ -68,7 +68,7 @@ class main(object): def start(self): for section in self.config.sections(): server_config = {} - server_config["host"] = section + server_config["network"] = section server_config["confdir"] = self.directory for item,value in self.config.items(section): server_config[item] = value @@ -105,28 +105,30 @@ class main(object): self.config = ConfigParser.RawConfigParser() getting_servers = True while getting_servers: - currentServer = self.my_raw("IRC server to connect to") + currentNetwork = self.my_raw("IRC network name") try: - self.config.add_section(currentServer) + self.config.add_section(currentNetwork) except ConfigParser.DuplicateSectionError: overwrite = self.my_raw("Server already exists! Overwrite? (yes/no)", "no").lower() while overwrite != "yes" and overwrite != "y" and overwrite != "no" and overwrite != "n": - overwrite = self.my_raw("Invalid option. Overwrite configuration for "+currentServer+"? (yes/no)", "no").lower() + overwrite = self.my_raw("Invalid option. Overwrite configuration for "+currentNetwork+"? (yes/no)", "no").lower() if overwrite.lower() == "no" or overwrite.lower() == "n": continue #go back to top of "while getting_servers:" #else continue out of try/except - self.set(currentServer,'channels',"Channels to automatically join (comma-separated, no spaces)") - self.set(currentServer,'nickname',"My nickname") - self.set(currentServer,'ident',"My ident") - self.set(currentServer,'ns_name',"NickServ username (if there is none, press ENTER)") - self.set(currentServer,'ns_pwd',"NickServ password (if there is none, press ENTER)") - self.set(currentServer,'port',"Port", "6667") - self.set(currentServer,"comchar","My command char", "-") - self.set(currentServer,"plugins","Plugins to load on startup (comma-separated, no spaces)", "auth,printer,pluginloader") + self.set(currentNetwork,'host',"The IRC network host to connect to") + self.set(currentNetwork,'channels',"Channels to automatically join (comma-separated, no spaces)") + self.set(currentNetwork,'nickname',"My nickname") + self.set(currentNetwork,'ident',"My ident") + self.set(currentNetwork,'owner_nick',"Your username (use the auth plugin to set a password)") + self.set(currentNetwork,'ns_name',"NickServ username (if there is none, press ENTER)") + self.set(currentNetwork,'ns_pwd',"NickServ password (if there is none, press ENTER)") + self.set(currentNetwork,'port',"Port", "6667") + self.set(currentNetwork,"comchar","My command char", "-") + self.set(currentNetwork,"plugins","Plugins to load on startup (comma-separated, no spaces)", "auth,printer,pluginloader") - another_server = self.my_raw("All done with "+currentServer+". Add another server? (yes/no)", "no").lower() + another_server = self.my_raw("All done with "+currentNetwork+". Add another server? (yes/no)", "no").lower() while another_server != "yes" and another_server != "y" and another_server != "no" and another_server != "n": another_server = self.my_raw("Invalid option. Do you want to add another server? (yes/no)", "no").lower() diff --git a/irc.py b/irc.py index 217f40712c1bc597b1c10cdac7c3768a5b5a525f..769b10ff5af0b3e2bfc6e70c945bcfd7f0a1c423 100644 --- a/irc.py +++ b/irc.py @@ -151,7 +151,7 @@ class PluginManager(object): def loadAllPlugins(self): errs = {} - plugins = self.server.config["plugins"].split(",") + plugins = [k for k in self.server.config["plugins"].split(",") if k != ''] for plugin in plugins: err = self.loadPlugin(plugin.lower()) if err is not None: @@ -178,7 +178,11 @@ class IRC(threading.Thread): self.handlers = self.pluginManager.handlers self.plugins = self.pluginManager.plugins self.getPlugin = self.pluginManager.getPlugin - self.pluginManager.loadAllPlugins() + errs = self.pluginManager.loadAllPlugins() + if errs: + for k,v in errs.items(): + self.prnt("Plugin "+k+" error loading: "+v) + self.running = False def _readline(self): @@ -231,15 +235,15 @@ class IRC(threading.Thread): # (make sure to send whatever follows the PING, in case they send a random hash) self.sendLine("PONG " + data[5:]) continue - - # Takes the ':Nick!Ident@Host' chunk and assigns Nick to user - try: - user = words[0].split(":")[1].split("!")[0] - except IndexError: + elif words[0] == "ERROR": + #there was an error, we probably had a KeyboardInterrupt self.prnt("Connection lost to server.") self.running = False continue + # Takes the ':Nick!Ident@Host' chunk and assigns Nick to user + user = words[0].split(":")[1].split("!")[0] + if words[1] == "433": #There was a nick collision self.config["nickname"] = self.config["nickname"] + "_" @@ -252,7 +256,7 @@ class IRC(threading.Thread): self.pluginManager.event("connect", self.config["host"]) - for chan in self.config["channels"].split(","): + for chan in [k for k in self.config["channels"].split(",") if k != '']: self.doJoin(chan) elif words[1] == "PRIVMSG": diff --git a/plugins/auth.py b/plugins/auth.py index a9664c8bc437c5b71aa7597699fc249973885e98..e4db452c1c657acb2978c4b79d17ae1acf17d336 100644 --- a/plugins/auth.py +++ b/plugins/auth.py @@ -4,21 +4,101 @@ import os, ConfigParser class Auth(object): def __init__(self, server): self.server = server - self.commands = [ "addadmin", "addmod", "deladmin", "delmod", "admins", "mods", "owners" ] - self.owners = [] - self.admins = [] - self.mods = [] + self.commands = [ "addadmin", "addmod", "deladmin", "delmod", "admins", "mods", "owners", "passwd", "identify" ] + self.owners = {} + self.admins = {} + self.mods = {} self.server.handle("command", self.handle_command, self.commands) - self.authfile = self.server.config["confdir"] + "auth.conf" + self.authdir = self.server.config["confdir"] + "network-auth-users/" + self.authfile = self.authdir + self.server.config["network"] + "-auth.cfg" self._loadusers() def handle_command(self, channel, user, cmd, args): if cmd == "owners": - self.server.doMessage(channel, user+": My owners are "+" ".join(self.owners)) + self.server.doMessage(channel, user+": My owners are: "+" ".join(self.owners)) elif cmd == "admins": self.server.doMessage(channel, user+": My administrators are: "+" ".join(self.admins)) elif cmd == "mods": 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 len(args) < 1: + self.server.doMessage(channel, user+": Not enough arguments.") + return + + if len(args) >= 2: + self.owners[user][0] = args[1] + self.server.doMessage(channel, user+": Password successfully changed.") + else: + self.owners[user][0] = args[0] + self.server.doMessage(channel, user+": Password successfully changed.") + + elif user in self.admins.keys(): + if self.admins[user][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.server.doMessage(channel, user+": Password successfully changed.") + else: + self.admins[user][0] = args[0] + self.server.doMessage(channel, user+": Password successfully changed.") + + elif user in self.mods.keys(): + if self.mods[user][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.server.doMessage(channel, user+": Password successfully changed.") + else: + self.mods[user][0] = args[0] + self.server.doMessage(channel, user+": Password successfully changed.") + + else: + self.server.doMessage(channel, user+": You are not in the owners/admins/mods lists.") + return + else: + self.server.doMessage(channel, user+": Please do that using private messaging.") + return + elif cmd == "identify": + if len(args) < 1: + self.server.doMessage(channel, user+": Not enough arguments.") + return + if channel == user: + if user in self.owners.keys(): + if self.owners[user][1]: + self.server.doMessage(channel, user+": You are already identified.") + elif args[0] == self.owners[user][0]: + self.owners[user][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]: + self.server.doMessage(channel, user+": You are already identified.") + elif args[0] == self.admins[user][0]: + self.admins[user][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]: + self.server.doMessage(channel, user+": You are already identified.") + elif args[0] == self.mods[user][0]: + self.mods[user][1] = True + self.server.doMessage(channel, user+": You are now identified for "+user) + else: + self.server.doMessage(channel, user+": Invalid password.") + else: + self.server.doMessage(channel, user+": Please do that using private messaging.") + return elif self.isOwner(user): if len(args) < 1: @@ -26,48 +106,69 @@ class Auth(object): return if cmd == "addadmin": - if args[0] in self.admins: return - self.admins.append(args[0]) + if args[0] in self.admins.keys(): return + self.admins[args[0]] = ['', False] elif cmd == "addmod": - if args[0] in self.mods: return - self.mods.append(args[0]) + if args[0] in self.mods.keys(): return + self.mods[args[0]] = ['', False] elif cmd == "deladmin": - if args[0] in self.admins: - self.admins.remove(args[0]) + if args[0] in self.admins.keys(): + del self.admins[args[0]] elif cmd == "delmod": - if args[0] in self.mods: - self.mods.remove(args[0]) + if args[0] in self.mods.keys(): + del self.mods[args[0]] - def _loadusers(self): - if not os.path.isfile(self.authfile): - return + def _saveusers(self): + if not os.path.isdir(self.authdir): + os.mkdir(self.authdir) + + fh = open(self.authfile, "w") + self.configParser.write(fh) + fh.close() - self.configParser = ConfigParser.RawConfigParser() - self.configParser.read(self.authfile) - for section in self.configParser.sections(): - if section == self.server.config["host"]: - for key,values in self.configParser.items(section): - if key == "owners": - self.owners += values.split(",") - elif key == "admins": - self.admins += values.split(",") - elif key == "mods": - self.mods += values.split(",") + __del__ = _saveusers + + def _loadusers(self): + if os.path.isfile(self.authfile): + self.configParser = ConfigParser.RawConfigParser() + self.configParser.read(self.authfile) + + for section in self.configParser.sections(): + if section == "owners": + for user,pswd in self.configParser.items(section): + self.owners[user] = [pswd, pswd == ''] + elif section == "admins": + for user,pswd in self.configParser.items(section): + self.admins[user] = [pswd, pswd == ''] + elif section == "mods": + for user,pswd in self.configParser.items(section): + self.mods[user] = [pswd, pswd == ''] + + onick = self.server.config["owner_nick"] + if not onick in self.owners.keys(): + if getattr(self, "configParser", None) is None: + self.configParser = ConfigParser.RawConfigParser() + self.configParser.add_section("owners") + self.configParser.add_section("admins") + self.configParser.add_section("mods") + + self.configParser.set("owners", onick, '') + self.owners[onick] = ['', True] def isOwner(self, user): - return user in self.owners + return user in self.owners and self.owners[user][1] def isAdmin(self, user): - if user in self.admins: + if user in self.admins and self.admins[user][1]: return True else: - return user in self.owners + return self.isOwner(user) def isMod(self, user): - if user in self.mods: + if user in self.mods and self.mods[user][1]: return True - elif user in self.admins: + elif self.isAdmin(user): return True else: - return user in self.owners + return self.isOwner(user) diff --git a/plugins/plugintools.py b/plugins/plugintools.py index 2b593e0a24852293e207f31a4e31b500672e2e1a..9a744bbb8744d145a5a594f5f689e08076fd0c63 100644 --- a/plugins/plugintools.py +++ b/plugins/plugintools.py @@ -52,7 +52,7 @@ class PluginLoader(object): elif cmd == "reload": err = self.server.pluginManager.reloadPlugin(args[0]) if err is not None and err: - self.server.doMessage(channel, user+": Exception reloading plugin "+args[0]+": "+" ".join([v for k,v in err.items()])) + self.server.doMessage(channel, user+": Exception reloading plugin "+args[0]+": "+" ".join([k+": "+v for k,v in err.items()])) else: self.server.doMessage(channel, user+": Successfully reloaded plugin "+args[0]+".") elif cmd == "loaded":