qmsk/irclogs/log_line.py
changeset 140 6db2527b67cf
parent 97 6165f1ba458d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/irclogs/log_line.py	Sun Sep 13 01:15:56 2009 +0300
@@ -0,0 +1,186 @@
+"""
+    An IRC logfile consists of a series of lines/events
+"""
+
+class LogTypes :
+    """
+        Definitions of the various LogLines types:
+
+            LogTypes.RAW
+            LogTypes.LOG_OPEN
+            LogTypes.LOG_CLOSE
+
+            LogTypes.MSG
+            LogTypes.NOTICE
+            LogTypes.ACTION
+
+            LogTypes.JOIN
+            LogTypes.PART
+            LogTypes.KICK
+            LogTypes.MODE
+
+            LogTypes.NICK
+            LogTypes.QUIT
+
+            LogTypes.TOPIC
+
+            LogTypes.SELF_NOTICE
+            LogTypes.SELF_NICK
+    """
+ 
+    # list of LogType values by name
+    LIST = [
+        ## special
+        # unknown type, may or may not have a timestamp, no source, only data
+        ('RAW',         0x01),
+
+        # log opened
+        ('LOG_OPEN',    0x02),
+
+        # log closed
+        ('LOG_CLOSE',   0x03),
+
+        ## messages
+        # <source> sent message <data> to <channel>
+        ('MSG',         0x10),
+        
+        # <source> sent notice with message <data> to <channel>
+        ('NOTICE',      0x11),
+
+        # <source> sent CTCP action with message <data> to <channel>
+        ('ACTION',      0x12),
+        
+        ## user-channel stats
+        # <source> joined <channel>
+        ('JOIN',        0x21),
+
+        # <source> left <channel> with message <data>
+        ('PART',        0x22),
+
+        # <source> kicked <target> from <channel> with message <data>
+        ('KICK',        0x25),
+     
+        # <source> changed modes on <channel> with modestring <data>
+        ('MODE',        0x26),
+        
+        ## user status
+        # <source> changed nickname to <target>
+        ('NICK',        0x31),
+
+        # <source> quit the network with quit-message <data>
+        ('QUIT',        0x32),
+
+        ## general channel status
+        # <source> changed the topic of <channel> to <data>
+        # data may be None if the topic was unset
+        ('TOPIC',       0x41),
+
+        ## our own actions
+        # we (<source>) sent a notice with message <data> to <channel>
+        ('SELF_NOTICE', 0x51),
+
+        # we (<source>) changed nickname to <target>
+        ('SELF_NICK',   0x52),
+
+        ## slightly weirder bits
+        # netsplit between <source_hostname> and <target_hostname>, <data> is a space-separated list of <chanflags><nickname>s affected
+        # the last item in the list of nicknames may also be of the form "+<count>", where count is the number of additional, but hidden, nicknames affected
+        ('NETSPLIT_START',  0x61),
+
+        # netsplit over, <data> is a list of users affected, see NETSPLIT_START
+        ('NETSPLIT_END',    0x062),
+    ]
+    
+    @classmethod
+    def name_from_code (cls, code) :
+        """
+            Looks up a LogType name by code
+        """
+
+        return dict((type, name) for name, type in cls.LIST)[code]
+
+# apply as attributes
+for name, code in LogTypes.LIST :
+    setattr(LogTypes, name, code)
+
+# masks
+LogTypes._NETSPLIT_MASK = 0x60
+
+class LogLine (object) :
+    """
+        An event on some specific channel
+    """
+
+    # the LogChannel
+    channel = None
+
+    # the offset, only garunteed to be unique for a specific channel and date
+    offset = None
+
+    # the event type, as defiend in LogTypes
+    type = None
+
+    # the UTC timestamp of the event
+    timestamp = None
+
+    # the source, this should be a (nickname, username, hostname, chanflags) tuple
+    source = None
+
+    # possible target nickname for certain types (kick, nick)
+    target = None
+
+    # associated data (message, etc)
+    data = None
+    
+    def __init__ (self, channel, offset, type, timestamp, source, target, data) :
+        """
+            Initialize with given values
+        """
+        
+        self.channel = channel
+        self.offset = offset
+        self.type = type
+        self.timestamp = timestamp
+        self.source = source
+        self.target = target
+        self.data = data
+    
+    def format_type (self) :
+        """
+            Formats type as a string code
+        """
+
+        return LogTypes.name_from_code(self.type)
+
+    def format_source (self) :
+        """
+            Formats source as [<chanflags>][<nickname>][!<username>][@<hostname>], omitting those parts that are missing.
+
+            If all parts are None, this returns the empty string
+        """
+
+        nick, user, host, flags = self.source
+
+        return "%s%s%s%s" % (
+            flags if flags and flags != ' ' else '',
+            nick if nick else '',
+            '!' + user if user else '',
+            '@' + host if host else ''
+        )
+   
+    def __unicode__ (self) :
+        return '\t'.join((
+            self.channel.name,
+            str(self.offset),
+            self.format_type(),
+            str(self.timestamp),
+            self.format_source(),
+            str(self.target),
+            unicode(self.data)
+        ))
+
+    def __repr__ (self) :
+        return "LogLine(%r, %s, %-12s, %s, %-35s, %-10s, %r)" % (
+            self.channel, self.offset, self.format_type(), self.timestamp, self.format_source(), self.target, self.data
+        )
+