--- /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
+ )
+