git.fiddlerwoaroof.com
scripts/ircBot.py
6728cae8
 #! /usr/bin/env python
baab37b8
 
 
 """
 An example IRC log bot - logs a channel's events to a file.
 
 If someone says the bot's name in the channel followed by a ':',
 e.g.
 
     <foo> logbot: hello!
 
 the bot will reply:
 
     <logbot> foo: I am a log bot
 
 Run this script with two arguments, the channel name the bot should
 connect to, and file to log to, e.g.:
 
     $ python ircLogBot.py test test.log
 
 will log channel #test to the file 'test.log'.
 
 To run the script:
 
     $ python ircLogBot.py <channel> <file>
 """
 
 
 # twisted imports
 from twisted.words.protocols import irc
 from twisted.internet import reactor, protocol, threads
 from twisted.python import log
 import base64
 
 # system imports
 import time, sys
 
 
 class MessageLogger:
     """
     An independent logger class (because separation of application
     and protocol logic is a good thing).
     """
     def __init__(self, bot):
         self.bot = bot
         self.user_queue = []
 
     def get_message(self):
         """Write a message to the file."""
         try:
             inp = raw_input('irc> ')
             return map(str.strip, inp.partition(':')[::2])
         except (EOFError, KeyboardInterrupt):
             reactor.callFromThread(reactor.stop)
             return (None,None)
 
     def send_message(self, res):
         user, message = res
         if user is not None:
             print '<%s> %s: %s' % (self.bot.nickname, user, message)
             self.user_queue.append(user)
             reactor.callFromThread(self.bot.msg, user, message)
 
     def handle(self, user, message):
         handled = self.user_queue != [] and self.user_queue.pop(0) == user
         if handled:
             print '\r<%s> %s: %s' % (user, self.bot.nickname, message)
         return handled
 
 
 class LogBot(irc.IRCClient):
     """A logging IRC bot."""
 
     nickname = base64.encodestring('fiddlerwoaroof')[:len('fiddlerwoaroof')]
 
     def connectionMade(self):
         irc.IRCClient.connectionMade(self)
6728cae8
         self.join('#lisp');
 
baab37b8
         self.handler = MessageLogger(self)
         d = threads.deferToThread(self.handler.get_message)
         d.addCallback(self.handler.send_message)
6728cae8
         reactor.callLater(5, self.changeNick)
 
     def changeNick(self):
         self.setNick(base64.encodestring(self.nickname)[:len(self.nickname)].strip())
         reactor.callLater( (random.random()-0.5)*2.5 + 5, self.changeNick )
baab37b8
 
     def privmsg(self, user, channel, msg):
         """This will get called when the bot receives a message."""
         user = user.split('!', 1)[0]
 
         # Check to see if they're sending me a private message
         if channel == self.nickname:
             handled = self.handler.handle(user, msg)
             if handled:
                 d = threads.deferToThread(self.handler.get_message)
                 d.addCallback(self.handler.send_message)
 
     # For fun, override the method that determines how a nickname is changed on
     # collisions. The default method appends an underscore.
     def alterCollidedNick(self, nickname):
         """
         Generate an altered version of a nickname that caused a collision in an
         effort to create an unused related name for subsequent registration.
         """
         return base64.encodestring(nickname)[:len(nickname)].strip()
 
 
 
 class LogBotFactory(protocol.ClientFactory):
     """A factory for LogBots.
 
     A new protocol instance will be created each time we connect to the server.
     """
 
     def buildProtocol(self, addr):
         p = LogBot()
         p.factory = self
         return p
 
     def clientConnectionLost(self, connector, reason):
         """If we get disconnected, reconnect to server."""
         connector.connect()
 
     def clientConnectionFailed(self, connector, reason):
         print "connection failed:", reason
         reactor.stop()
 
 
 if __name__ == '__main__':
     # create factory protocol and application
     f = LogBotFactory()
 
     # connect factory to this host and port
     reactor.connectTCP("irc.freenode.net", 6667, f)
 
     # run bot
     reactor.run()