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