terom@1: from twisted.words.protocols import irc terom@1: from twisted.internet import protocol terom@4: from twisted.python import log terom@6: import traceback terom@1: terom@1: import buffer terom@1: terom@13: from irc_config import * terom@1: terom@6: class ReplyException (Exception) : terom@6: def __init__ (self, reply) : terom@6: self.reply = reply terom@6: terom@4: class BotProtocol (irc.IRCClient, object) : terom@1: """ terom@1: Fixme IRC bot terom@1: """ terom@4: terom@4: def __init__ (self) : terom@4: self.nickname = NICKNAME terom@4: self.username = USERNAME terom@1: terom@1: # housekeeping terom@1: def connectionMade (self) : terom@1: log.msg("Connected") terom@4: super(BotProtocol, self).connectionMade() terom@6: terom@6: self.nexus = self.factory.nexus terom@1: terom@1: def connectionLost (self, reason) : terom@1: log.msg("Connection lost: %s" % reason) terom@4: super(BotProtocol, self).connectionLost(reason) terom@1: terom@1: def signedOn (self) : terom@4: log.msg("Signed on, joining channel %s" % CHANNEL) terom@1: self.join(CHANNEL) terom@1: terom@1: def joined (self, channel) : terom@1: log.msg("Joined channel %s" % channel) terom@4: terom@4: self.factory.connection = self terom@1: terom@1: # our actual functionality terom@1: def send (self, msg) : terom@4: msg = str(msg) terom@4: terom@4: if len(msg) > 480 : terom@4: log.msg("truncating: %s" % msg) terom@4: msg = msg[:480] + "..." terom@4: terom@4: msg = msg.replace("\n", "\\n").replace("\r", "\\r").replace("\0", "\\0") terom@4: terom@13: self.notice(CHANNEL, msg) terom@1: terom@1: def sendEvent (self, event) : terom@4: self.send("[%s.%s] %s" % (event.module.name, event.type, event.msg)) terom@1: terom@1: def moduleConnected (self, module, addr) : terom@4: self.send("{modules.%s} connected from %s:%d, version %s" % (module.name, addr.host, addr.port, module.version)) terom@1: terom@4: def moduleDisconnected (self, module, reason) : terom@4: self.send("{modules.%s} disconnected: %s" % (module.name, reason)) terom@6: terom@6: class _noDefault : pass terom@1: terom@6: def _lookupCommand (self, command, default=_noDefault) : terom@6: if '.' in command : terom@6: raise ReplyException("No support for module commands yet :P") terom@6: else : terom@6: method = getattr(self, "cmd_%s" % command, None) terom@1: terom@6: if method : terom@6: return method terom@6: elif default is self._noDefault : terom@6: raise ReplyException("No such command '%s'. See `help commands'" % command) terom@6: else : terom@6: return default terom@6: terom@6: def privmsg (self, user, channel, message) : terom@20: if message.lower().startswith(self.nickname.lower() + ':'): terom@6: me, command = message.split(":", 1) terom@6: terom@6: args = command.strip().split() terom@6: command = args.pop(0) terom@6: terom@6: try : terom@6: method = self._lookupCommand(command) terom@6: terom@6: reply = method(*args) terom@6: terom@6: if reply : terom@6: self.send(reply) terom@6: terom@6: except ReplyException, e : terom@6: self.send(e.reply) terom@6: terom@6: except Exception, e : terom@6: self.send("Error: %s: %s" % (e.__class__.__name__, e)) terom@6: traceback.print_exc() terom@6: terom@6: def cmd_help (self, cmd="help") : terom@6: """help - Display help about the given command or module""" terom@6: terom@6: method = self._lookupCommand(cmd, None) terom@6: terom@6: if method : terom@6: return method.__doc__ terom@6: else : terom@6: try : terom@6: module, addr = self.nexus.getModuleInfo(cmd) terom@6: terom@6: return "%s is version %d from %s:%d. Events: %s. See `commands %s' for a list of commands" % (module.name, module.version, addr.host, addr.port, ', '.join(module.event_types), module.name) terom@6: terom@6: except KeyError : terom@6: raise ReplyException("No command/module called `%s'. See `help commands'" % cmd) terom@6: terom@6: def cmd_commands (self, module=None) : terom@6: """commands [] - Show primary commands, or commands in the given module (see `help modules')""" terom@6: terom@6: if module : terom@6: raise ReplyException("No support for module commands yet :P") terom@6: else : terom@6: return "Commands: %s" % ', '.join( terom@6: attr_name.split('_', 1)[1] terom@6: for attr_name in BotProtocol.__dict__.iterkeys() terom@6: if attr_name.startswith("cmd_") terom@6: ) terom@6: terom@6: def cmd_modules (self) : terom@6: """modules - Show a list of connected modules""" terom@6: terom@6: return "Modules: %s" % ', '.join( terom@6: module.name terom@6: for module in self.nexus.getModules() terom@6: )