qmsk/irclogs/log_line.py
changeset 140 6db2527b67cf
parent 97 6165f1ba458d
equal deleted inserted replaced
139:9c7769850195 140:6db2527b67cf
       
     1 """
       
     2     An IRC logfile consists of a series of lines/events
       
     3 """
       
     4 
       
     5 class LogTypes :
       
     6     """
       
     7         Definitions of the various LogLines types:
       
     8 
       
     9             LogTypes.RAW
       
    10             LogTypes.LOG_OPEN
       
    11             LogTypes.LOG_CLOSE
       
    12 
       
    13             LogTypes.MSG
       
    14             LogTypes.NOTICE
       
    15             LogTypes.ACTION
       
    16 
       
    17             LogTypes.JOIN
       
    18             LogTypes.PART
       
    19             LogTypes.KICK
       
    20             LogTypes.MODE
       
    21 
       
    22             LogTypes.NICK
       
    23             LogTypes.QUIT
       
    24 
       
    25             LogTypes.TOPIC
       
    26 
       
    27             LogTypes.SELF_NOTICE
       
    28             LogTypes.SELF_NICK
       
    29     """
       
    30  
       
    31     # list of LogType values by name
       
    32     LIST = [
       
    33         ## special
       
    34         # unknown type, may or may not have a timestamp, no source, only data
       
    35         ('RAW',         0x01),
       
    36 
       
    37         # log opened
       
    38         ('LOG_OPEN',    0x02),
       
    39 
       
    40         # log closed
       
    41         ('LOG_CLOSE',   0x03),
       
    42 
       
    43         ## messages
       
    44         # <source> sent message <data> to <channel>
       
    45         ('MSG',         0x10),
       
    46         
       
    47         # <source> sent notice with message <data> to <channel>
       
    48         ('NOTICE',      0x11),
       
    49 
       
    50         # <source> sent CTCP action with message <data> to <channel>
       
    51         ('ACTION',      0x12),
       
    52         
       
    53         ## user-channel stats
       
    54         # <source> joined <channel>
       
    55         ('JOIN',        0x21),
       
    56 
       
    57         # <source> left <channel> with message <data>
       
    58         ('PART',        0x22),
       
    59 
       
    60         # <source> kicked <target> from <channel> with message <data>
       
    61         ('KICK',        0x25),
       
    62      
       
    63         # <source> changed modes on <channel> with modestring <data>
       
    64         ('MODE',        0x26),
       
    65         
       
    66         ## user status
       
    67         # <source> changed nickname to <target>
       
    68         ('NICK',        0x31),
       
    69 
       
    70         # <source> quit the network with quit-message <data>
       
    71         ('QUIT',        0x32),
       
    72 
       
    73         ## general channel status
       
    74         # <source> changed the topic of <channel> to <data>
       
    75         # data may be None if the topic was unset
       
    76         ('TOPIC',       0x41),
       
    77 
       
    78         ## our own actions
       
    79         # we (<source>) sent a notice with message <data> to <channel>
       
    80         ('SELF_NOTICE', 0x51),
       
    81 
       
    82         # we (<source>) changed nickname to <target>
       
    83         ('SELF_NICK',   0x52),
       
    84 
       
    85         ## slightly weirder bits
       
    86         # netsplit between <source_hostname> and <target_hostname>, <data> is a space-separated list of <chanflags><nickname>s affected
       
    87         # 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
       
    88         ('NETSPLIT_START',  0x61),
       
    89 
       
    90         # netsplit over, <data> is a list of users affected, see NETSPLIT_START
       
    91         ('NETSPLIT_END',    0x062),
       
    92     ]
       
    93     
       
    94     @classmethod
       
    95     def name_from_code (cls, code) :
       
    96         """
       
    97             Looks up a LogType name by code
       
    98         """
       
    99 
       
   100         return dict((type, name) for name, type in cls.LIST)[code]
       
   101 
       
   102 # apply as attributes
       
   103 for name, code in LogTypes.LIST :
       
   104     setattr(LogTypes, name, code)
       
   105 
       
   106 # masks
       
   107 LogTypes._NETSPLIT_MASK = 0x60
       
   108 
       
   109 class LogLine (object) :
       
   110     """
       
   111         An event on some specific channel
       
   112     """
       
   113 
       
   114     # the LogChannel
       
   115     channel = None
       
   116 
       
   117     # the offset, only garunteed to be unique for a specific channel and date
       
   118     offset = None
       
   119 
       
   120     # the event type, as defiend in LogTypes
       
   121     type = None
       
   122 
       
   123     # the UTC timestamp of the event
       
   124     timestamp = None
       
   125 
       
   126     # the source, this should be a (nickname, username, hostname, chanflags) tuple
       
   127     source = None
       
   128 
       
   129     # possible target nickname for certain types (kick, nick)
       
   130     target = None
       
   131 
       
   132     # associated data (message, etc)
       
   133     data = None
       
   134     
       
   135     def __init__ (self, channel, offset, type, timestamp, source, target, data) :
       
   136         """
       
   137             Initialize with given values
       
   138         """
       
   139         
       
   140         self.channel = channel
       
   141         self.offset = offset
       
   142         self.type = type
       
   143         self.timestamp = timestamp
       
   144         self.source = source
       
   145         self.target = target
       
   146         self.data = data
       
   147     
       
   148     def format_type (self) :
       
   149         """
       
   150             Formats type as a string code
       
   151         """
       
   152 
       
   153         return LogTypes.name_from_code(self.type)
       
   154 
       
   155     def format_source (self) :
       
   156         """
       
   157             Formats source as [<chanflags>][<nickname>][!<username>][@<hostname>], omitting those parts that are missing.
       
   158 
       
   159             If all parts are None, this returns the empty string
       
   160         """
       
   161 
       
   162         nick, user, host, flags = self.source
       
   163 
       
   164         return "%s%s%s%s" % (
       
   165             flags if flags and flags != ' ' else '',
       
   166             nick if nick else '',
       
   167             '!' + user if user else '',
       
   168             '@' + host if host else ''
       
   169         )
       
   170    
       
   171     def __unicode__ (self) :
       
   172         return '\t'.join((
       
   173             self.channel.name,
       
   174             str(self.offset),
       
   175             self.format_type(),
       
   176             str(self.timestamp),
       
   177             self.format_source(),
       
   178             str(self.target),
       
   179             unicode(self.data)
       
   180         ))
       
   181 
       
   182     def __repr__ (self) :
       
   183         return "LogLine(%r, %s, %-12s, %s, %-35s, %-10s, %r)" % (
       
   184             self.channel, self.offset, self.format_type(), self.timestamp, self.format_source(), self.target, self.data
       
   185         )
       
   186