Commits

Benoit C committed b8dadc7

spaces not tabs

Comments (0)

Files changed (1)

+#!/usr/bin/env python
+
+# twisted imports
+from twisted.words.protocols import irc
+from twisted.internet import reactor, protocol
+from twisted.python import log
+
+# system imports
+import time, sys, os
+import random
+
+# yaml for yml configuration
+import yaml
+
+
+class ChannelLogger:
+    def __init__(self, conf, channel):
+        #just for live replies
+        self.lived = []
+        self.conf = conf
+        self.channel = channel
+        self.interval = 60 * 60 * 24 #one day
+        date = time.strftime("%Y_%m_%d", time.localtime(time.time()))
+        self.file = file("%s%s%s_%s.log" %
+            (conf['logdir'], os.sep, channel, date), 'a+'
+        )
+        current_time = int(time.time())
+        t = time.localtime(current_time)
+        r = (60 * 24 * 24) - ((t[3] * 60 + t[4] ) * 60 + t[5])
+        self.rollat = current_time + r
+
+    def roll(self):
+        self.file.close()
+        date = time.strftime("%Y_%m_%d", time.localtime(time.time()))
+        self.file = file("%s%s%s_%s.log" %
+            (self.conf['logdir'], os.sep, self.channel, date), 'a+'
+        )
+
+    def log(self, message):
+        current_time = time.time()
+        if current_time >= self.rollat:
+            self.roll()
+        t = time.localtime(int(current_time))
+        timestamp = time.strftime("[%H:%M]", time.localtime(time.time()))
+        self.file.write("%s %s\n" % (timestamp, message))
+        self.file.flush()
+
+    def live(self, message):
+        if len(self.lived) > 10000:
+            self.lived.remove(self.lived[0])
+        self.lived.append(message)
+
+    def close(self):
+        self.file.close()
+
+    def get_random(self):
+        """return random sentence from self.live"""
+        import random
+        nb = random.randint(0, len(self.lived) - 1)
+        return self.lived[nb]
+
+class MessageLogger:
+    """
+    An independent logger class (because separation of application
+    and protocol logic is a good thing).
+    """
+    def __init__(self, conf):
+        self.conf = conf
+        self.chan = {}
+
+    def __getitem__(self, key):
+        if key not in self.chan:
+            return None
+        return self.chan[key]
+
+    def live(self, chan, message):
+        self[chan].live(message)
+
+
+    def log(self, chan, message):
+        """Write a message to the file."""
+        if chan not in self.chan.keys():
+            self.chan[chan] = ChannelLogger(
+                self.conf, chan
+            )
+        self[chan].log(message)
+
+    def logall(self, message):
+        for chan in self.chan.keys():
+            self[chan].log(message)
+
+    def close(self):
+        for chan in self.chan.keys():
+            self[chan].close()
+
+    def random(self, channel):
+        return self.chan[channel].get_random()
+
+
+
+
+class LogBot(irc.IRCClient):
+    """A logging IRC bot."""
+    
+    nickname = 'Autiste'
+
+    def __init__(self):
+        self.keywords = {
+            'hello': self.hello,
+            'kikoo': self.kikoo,
+        }
+
+    def connectionMade(self):
+        self.logger = MessageLogger(self.factory.conf)
+        irc.IRCClient.connectionMade(self)
+
+    def connectionLost(self, reason):
+        irc.IRCClient.connectionLost(self, reason)
+        self.logger.logall(
+                "[disconnected at %s]" % 
+                time.asctime(time.localtime(time.time())))
+        self.logger.close()
+
+    # words callbacks
+
+    def hello(self, channel, nick):
+        self.say(channel, "hello %s!" % nick)
+
+    def kikoo(self, channel, nick):
+        self.say(channel, "kikoo %s!" % nick)
+
+    def words_callback(self, word, channel, nick):
+        if word in self.keywords:
+            method = self.keywords[word]
+            method(channel, nick)
+            return True
+        return False
+
+    def random_sentence(self, channel, nick):
+        try:
+            self.say(
+                channel, "%s: %s" % (nick, self.logger.random(channel))
+            )
+        except:
+            pass
+
+    # callbacks for events
+    def userJoined(self, user, channel):
+        self.logger.log(
+                channel, 
+                "-!- %s has joined %s" % (user, channel)
+        )
+
+        self.mode(channel, True, "o", None, user)
+        pass
+
+    def signedOn(self):
+        """Called when bot has succesfully signed on to server."""
+        for channel in self.factory.conf["channels"]:
+            print "joining %s" % channel
+            self.join(channel)
+
+    def joined(self, channel):
+        """This will get called when the bot joins the channel."""
+        self.logger.log(channel, "[I have joined %s]" % channel)
+
+    def privmsg(self, user, channel, msg):
+        """This will get called when the bot receives a message."""
+        user = user.split('!', 1)[0]
+        self.logger.log(channel, "(%s) %s" % (user, msg))
+        if msg.startswith(self.nickname + ":"):
+            words = msg.split(' ')
+            if len(words) > 1:
+                if not self.words_callback(words[1], channel, user):
+                    self.random_sentence(channel, user)
+        else:
+            self.logger.live(channel, msg)
+
+    def action(self, user, channel, msg):
+        """This will get called when the bot sees someone do an action."""
+        user = user.split('!', 1)[0]
+        self.logger.log(channel, "* %s %s" % (user, msg))
+
+
+
+class LogBotFactory(protocol.ClientFactory):
+    """A factory for LogBots.
+
+    A new protocol instance will be created each time we connect to the server.
+    """
+
+    # the class of the protocol to build when new connection is made
+    protocol = LogBot
+
+    def __init__(self, conf):
+        self.conf = conf
+
+    def clientConnectionLost(self, connector, reason):
+        """If we get disconnected, reconnect to server."""
+        connector.connect()
+
+    def clientConnectionFailed(self, connector, reason):
+        print "connection failed:", reason
+        connector.connect()
+
+
+if __name__ == '__main__':
+    # initialize logging
+    #log.startLogging(sys.stdout)
+   
+    # configuration
+    if len(sys.argv) != 2:
+        print "Usage : %s <blah.yml>" % sys.argv[0]
+        sys.exit()
+    content = file(sys.argv[1]).read()
+    conf = yaml.load(content)
+    for server in conf['servers']:
+        server_conf = conf['servers'][server]
+
+        f = LogBotFactory(server_conf)
+        reactor.connectTCP(server_conf["host"], int(server_conf["port"]), f)
+        reactor.run()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.