""" IrcAdmin - handle normal IRC functions one would expect Copyright (C) 2010 Brian S. Stephan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ from ConfigParser import NoOptionError from extlib import irclib from Module import Module class IrcAdmin(Module): """Support miscellaneous IRC stuff --- joining channels, changing the nick, etc.""" def register_handlers(self): self.irc.server.add_global_handler('pubmsg', self.on_pub_or_privmsg, self.priority()) self.irc.server.add_global_handler('privmsg', self.on_pub_or_privmsg, self.priority()) self.irc.server.add_global_handler('welcome', self.on_connect, self.priority()) def unregister_handlers(self): self.irc.server.remove_global_handler('pubmsg', self.on_pub_or_privmsg) self.irc.server.remove_global_handler('privmsg', self.on_pub_or_privmsg) self.irc.server.remove_global_handler('welcome', self.on_connect) def on_connect(self, connection, event): """Set up handlers when the bot has connected to IRC.""" # user modes try: nick = self.config.get('dr.botzo', 'nick') usermode = self.config.get('dr.botzo', 'usermode') connection.mode(nick, usermode) except NoOptionError: pass # run automsg commands # TODO NOTE: if the bot is sending something that changes the vhost # (like 'hostserv on') we don't pick it up try: automsgs = self.config.get(self.__class__.__name__, 'automsg').split(',') for command in automsgs: connection.privmsg(command.split(' ')[0], ' '.join(command.split(' ')[1:])) except NoOptionError: pass # join the specified channels try: autojoins = self.config.get(self.__class__.__name__, 'autojoin').split(',') for channel in autojoins: if irclib.is_channel(channel): connection.join(channel) except NoOptionError: pass def do(self, connection, event, nick, userhost, what, admin_unlocked): """Try all the admin methods.""" # TODO: sophisticate. also, document all of these whats = what.split(' ') if whats[0] == '!join' and admin_unlocked and len(whats) >= 2: return self.irc.reply(event, self.sub_join_channel(connection, event, nick, userhost, what, admin_unlocked)) elif whats[0] == '!part' and admin_unlocked and len(whats) >= 2: return self.irc.reply(event, self.sub_part_channel(connection, event, nick, userhost, what, admin_unlocked)) elif whats[0] == '!quit' and admin_unlocked: return self.irc.reply(event, self.sub_quit_irc(connection, event, nick, userhost, what, admin_unlocked)) elif whats[0] == '!autojoin' and admin_unlocked and len(whats) >= 3: return self.irc.reply(event, self.sub_autojoin_manipulate(connection, event, nick, userhost, what, admin_unlocked)) elif whats[0] == '!save' and admin_unlocked: self.irc.save_modules() self.irc.save_config() return self.irc.reply(event, 'Saved.') elif whats[0] == '!nick' and admin_unlocked and len(whats) >= 2: return self.irc.reply(event, self.sub_change_nick(connection, event, nick, userhost, what, admin_unlocked)) elif whats[0] == '!load' and admin_unlocked and len(whats) >= 2: return self.irc.reply(event, self.sub_load_module(connection, event, nick, userhost, what, admin_unlocked)) elif whats[0] == '!unload' and admin_unlocked and len(whats) >= 2: return self.irc.reply(event, self.sub_unload_module(connection, event, nick, userhost, what, admin_unlocked)) elif whats[0] == '!modules': return self.irc.reply(event, self.sub_list_modules(connection, event, nick, userhost, what, admin_unlocked)) def sub_join_channel(self, connection, event, nick, userhost, what, admin_unlocked): whats = what.split(' ') channel = whats[1] if irclib.is_channel(channel): connection.join(channel) replystr = 'Joined ' + channel + '.' return replystr def sub_part_channel(self, connection, event, nick, userhost, what, admin_unlocked): whats = what.split(' ') target = event.target() channel = whats[1] if irclib.is_channel(channel): connection.part(channel, ' '.join(whats[2:])) if target != channel: replystr = 'Parted ' + channel + '.' return replystr def sub_quit_irc(self, connection, event, nick, userhost, what, admin_unlocked): whats = what.split(' ') self.irc.quit_irc(connection, ' '.join(whats[1:])) def sub_autojoin_manipulate(self, connection, event, nick, userhost, what, admin_unlocked): whats = what.split(' ') if whats[1] == 'add': try: # get existing list channel = whats[2] if irclib.is_channel(channel): channelset = set(self.config.get(self.__class__.__name__, 'autojoin').split(',')) channelset.add(channel) self.config.set(self.__class__.__name__, 'autojoin', ','.join(channelset)) replystr = 'Added ' + channel + ' to autojoin.' return replystr except NoOptionError: pass elif whats[1] == 'remove': try: # get existing list channel = whats[2] if irclib.is_channel(channel): channelset = set(self.config.get(self.__class__.__name__, 'autojoin').split(',')) channelset.discard(channel) self.config.set(self.__class__.__name__, 'autojoin', ','.join(channelset)) replystr = 'Removed ' + channel + ' from autojoin.' return replystr except NoOptionError: pass def sub_change_nick(self, connection, event, nick, userhost, what, admin_unlocked): whats = what.split(' ') newnick = whats[1] connection.nick(newnick) self.config.set('dr.botzo', 'nick', newnick) replystr = 'changed nickname' return replystr def sub_load_module(self, connection, event, nick, userhost, what, admin_unlocked): """Load a module (in both the python and dr.botzo sense) if not already loaded. """ whats = what.split(' ') return self.irc.load_module(whats[1]) def sub_unload_module(self, connection, event, nick, userhost, what, admin_unlocked): """Attempt to unload and del a module if it's loaded.""" whats = what.split(' ') return self.irc.unload_module(whats[1]) def sub_list_modules(self, connection, event, nick, userhost, what, admin_unlocked): """Get the list of loaded modules from DrBotIRC and display it.""" return ', '.join(self.irc.list_modules()) def help_description(self): """Return a quick list of commands or other summary, should be less than two lines. If you want the module hidden from "!help", return None here""" return "Perform admin-related functions." def help_summary(self): """Return a command summary or longer description of this module. If this returns None, the summary will be "no help available for module foo" """ return """Bot admin commands (do '!help IrcAdmin [cmd] for details): !join, !part, !quit, !autojoin, !save, !nick, !load, !unload, !modules""" def help_detail(self, command): """Return detailed help for the given command. Return None if there is no suitable help available""" key = command.strip() if key[0] == '!': key = key[1:] words = key.split() if len(words) == 0: return None elif words[0] == 'join': return "!join [channel] - cause the bot to /join [channel]" elif words[0] == 'part': return "!part [channel] - cause the bot to /part from [channel]" elif words[0] == 'quit': return "!quit - cause the bot to save itself and quit" elif words[0] == 'autojoin': return "!autojoin [channel] - cause the bot to join [channel] on startup" elif words[0] == 'save': return "!save - cause the bot to save config data to the config file" elif words[0] == 'nick': return "!nick - cause the bot to change its nick" elif words[0] == 'load': return "!load - make the bot load a module dynamically" elif words[0] == 'unload': return "!unload - unload a loaded module, removing its functionality" elif words[0] == 'modules': return "!modules - list the currently loaded modules" else: return None # vi:tabstop=4:expandtab:autoindent # kate: indent-mode python;indent-width 4;replace-tabs on;