|
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 |