1
2
3
4
5
6 """ an ircevent is extracted from the IRC string received from the server """
7
8 __copyright__ = 'this file is in the public domain'
9
10 from gozerbot.generic import rlog, stripident, fix_format, fromenc
11 import time, re, types, copy
12
13 cpy = copy.deepcopy
14
16 """ create ievent.args and ievent.rest .. this is needed because \
17 ircevents might be created outside the parse() function """
18 try:
19 ievent.args = ievent.txt.split()[1:]
20 except ValueError:
21 ievent.args = []
22 try:
23 cmnd, ievent.rest = ievent.txt.split(' ', 1)
24 except ValueError:
25 ievent.rest = ""
26 ievent.command = ievent.txt.split(' ')[0]
27
29
30 """ represents an IRC event """
31
33 self.jabber = False
34 self.groupchat = False
35 self.cmnd = None
36 self.prefix = u""
37 self.postfix = u""
38 self.target = u""
39 self.arguments = []
40 self.nick = u""
41 self.user = u""
42 self.ruserhost = u""
43 self.userhost = u""
44 self.stripped = u""
45 self.resource = u""
46 self.channel = u""
47 self.origtxt = u""
48 self.txt = u""
49 self.command = u""
50 self.alias = u""
51 self.aliased = u""
52 self.time = time.time()
53 self.msg = False
54 self.args = []
55 self.rest = u""
56 self.usercmnd = 0
57 self.bot = None
58 self.sock = None
59 self.allowqueue = True
60 self.closequeue = True
61 self.inqueue = None
62 self.queues = []
63 self.printto = None
64 self.speed = 0
65 self.groups = None
66 self.cc = u""
67 self.jid = None
68 self.jidchange = None
69 self.conn = None
70 self.to = None
71 self.denied = False
72 self.options = {}
73 self.optionset = []
74 self.filter = []
75 if ievent:
76 self.copyin(ievent)
77
79 """ copy ievent """
80 self.cmnd = cpy(ievent.cmnd)
81 self.prefix = cpy(ievent.prefix)
82 self.postfix = cpy(ievent.postfix)
83 self.target = cpy(ievent.target)
84 self.arguments = list(ievent.arguments)
85 self.nick = cpy(ievent.nick)
86 self.user = cpy(ievent.user)
87 self.ruserhost = cpy(ievent.ruserhost)
88 self.userhost = cpy(ievent.userhost)
89 self.stripped = cpy(ievent.stripped)
90 self.resource = cpy(ievent.resource)
91 self.channel = cpy(ievent.channel)
92 self.origtxt = cpy(ievent.origtxt)
93 self.txt = cpy(ievent.txt)
94 self.command = cpy(ievent.command)
95 self.alias = cpy(ievent.alias)
96 self.aliased = cpy(ievent.aliased)
97 self.time = ievent.time
98 self.msg = cpy(ievent.msg)
99 self.args = list(ievent.args)
100 self.rest = cpy(ievent.rest)
101 self.usercmnd = cpy(ievent.usercmnd)
102 self.bot = ievent.bot
103 self.sock = ievent.sock
104 self.printto = ievent.printto
105 self.speed = int(ievent.speed)
106 self.inqueue = ievent.inqueue
107 self.allowqueue = cpy(ievent.allowqueue)
108 self.closequeue = cpy(ievent.closequeue)
109 self.queues = list(ievent.queues)
110 self.cc = cpy(ievent.cc)
111 self.jid = ievent.jid
112 self.jidchange = ievent.jidchange
113 self.conn = ievent.conn
114 self.to = ievent.to
115 self.denied = ievent.denied
116 self.options = dict(ievent.options)
117 self.optionset = list(ievent.optionset)
118 self.filter = list(ievent.filter)
119 self.jabber = bool(ievent.jabber)
120
122 return "cmnd=%s prefix=%s postfix=%s arguments=%s nick=%s user=%s \
123 userhost=%s channel=%s txt='%s' command=%s args=%s rest=%s speed=%s options=%s" % \
124 (self.cmnd, self.prefix, self.postfix, self.arguments, self.nick, self.user, \
125 self.userhost, self.channel, self.txt, self.command, self.args, self.rest, \
126 self.speed, self.options)
127
129 if self.bot:
130 self.bot.gcevents += 1
131
133 if not self.filter:
134 return False
135 for filter in self.filter:
136 if filter in txt:
137 return False
138 return True
139
140 - def parse(self, bot, rawstr):
141 """ parse raw string into ircevent """
142 self.bot = bot
143 bot.nrevents += 1
144 rawstr = rawstr.rstrip()
145 splitted = re.split('\s+', rawstr)
146
147 if not rawstr[0] == ':':
148
149 splitted.insert(0, ":none!none@none")
150 rawstr = ":none!none@none " + rawstr
151 self.prefix = splitted[0][1:]
152
153 nickuser = self.prefix.split('!')
154 if len(nickuser) == 2:
155 self.nick = nickuser[0]
156 self.userhost = nickuser[1]
157 self.cmnd = splitted[1]
158 if pfc.has_key(self.cmnd):
159 self.arguments = splitted[2:pfc[self.cmnd]+2]
160 txtsplit = re.split('\s+', rawstr, pfc[self.cmnd]+2)
161 self.txt = txtsplit[-1]
162 else:
163 self.arguments = splitted[2:]
164
165 if self.arguments:
166 self.target = self.arguments[0]
167 self.postfix = ' '.join(self.arguments)
168
169 if self.target and self.target.startswith(':'):
170 self.txt = ' '.join(self.arguments)
171
172 if self.txt:
173 if self.txt[0] == ":":
174 self.txt = self.txt[1:]
175 rlog(0, 'ircevent',"%s %s %s" % (self.cmnd, self.arguments, self.txt))
176
177 if self.cmnd == 'PING':
178 self.speed = 10
179 if self.cmnd == 'PRIVMSG':
180 self.channel = self.arguments[0]
181 elif self.cmnd == 'JOIN' or self.cmnd == 'PART':
182 if self.arguments:
183 self.channel = self.arguments[0]
184 else:
185 self.channel = self.txt
186 elif self.cmnd == 'MODE':
187 self.channel = self.arguments[0]
188 elif self.cmnd == 'TOPIC':
189 self.channel = self.arguments[0]
190 elif self.cmnd == 'KICK':
191 self.channel = self.arguments[0]
192 elif self.cmnd == '353':
193 self.channel = self.arguments[2]
194 elif self.cmnd == '324':
195 self.channel = self.arguments[1]
196 if self.userhost:
197
198 self.ruserhost = self.userhost
199 self.userhost = stripident(self.userhost)
200
201 self.stripped = self.userhost
202
203 self.user = self.userhost.split('@')[0]
204 self.origtxt = self.txt
205 self.channel = self.channel.strip()
206 rlog(-1, 'ircevent', self)
207 try:
208 nr = int(self.cmnd)
209 if nr > 399:
210 rlog(10, bot.name + '.error', '%s: %s %s' % (self.cmnd, \
211 self.arguments, self.txt))
212 except ValueError:
213 pass
214 return self
215
216 - def reply(self, txt, result=None, nick=None, dot=False, nritems=False, \
217 nr=False, fromm=None):
218 """ reply txt .. first check if queue then if DCC then /msg
219 otherwise assume channel
220 """
221 if result == []:
222 return
223 restxt = ""
224 if type(result) == types.DictType:
225 for i, j in result.iteritems():
226 if type(j) == types.ListType:
227 try:
228 z = ' .. '.join(j)
229 except TypeError:
230 z = unicode(j)
231 else:
232 z = j
233 if dot == True:
234 restxt += "%s: %s %s " % (i, z, ' .. ')
235 elif dot:
236 restxt += "%s: %s %s " % (i, z, dot)
237 else:
238 restxt += "%s: %s " % (i, z)
239 if restxt:
240 if dot == True:
241 restxt = restxt[:-6]
242 elif dot:
243 restxt = restxt[:-len(dot)]
244 lt = False
245 if type(txt) == types.ListType and not result:
246 result = txt
247 origtxt = u""
248 lt = True
249 else:
250 origtxt = txt
251 if result:
252 lt = True
253 if self.queues:
254 for i in self.queues:
255 if restxt:
256 i.put_nowait(restxt)
257 elif lt:
258 for j in result:
259 i.put_nowait(j)
260 else:
261 i.put_nowait(txt)
262 return
263 if not self.bot:
264 rlog(10, 'irc', 'no bot defined in ircevent')
265 return
266 pretxt = origtxt
267 if lt and not restxt:
268 res = []
269 for i in result:
270 if type(i) == types.ListType or type(i) == types.TupleType:
271 try:
272 res.append(u' .. '.join(i))
273 except TypeError:
274 res.extend(i)
275 else:
276 res.append(i)
277 result = res
278 if nritems:
279 if len(result) > 1:
280 pretxt += "(%s items) .. " % len(result)
281 txtlist = result
282 if not nr is False:
283 try:
284 start = int(nr)
285 except ValueError:
286 start = 0
287 txtlist2 = []
288 teller = start
289 for i in txtlist:
290 txtlist2.append(u"%s) %s" % (teller, i))
291 teller += 1
292 txtlist = txtlist2
293 txtl = []
294 for item in txtlist:
295 txtl.append(unicode(item))
296 txtlist = txtl
297 if dot == True:
298 restxt = ' .. '.join(txtlist)
299 elif dot:
300 restxt = dot.join(txtlist)
301 else:
302 restxt = ' '.join(txtlist)
303 if pretxt:
304 restxt = pretxt + restxt
305 if self.filtered(restxt):
306 return
307 if self.cmnd == 'DCC' and self.sock:
308 self.bot.say(self.sock, restxt, speed=self.speed)
309 return
310 if nick:
311 self.bot.say(nick, restxt, fromm=nick, speed=self.speed)
312 return
313 if self.msg:
314 self.bot.say(self.nick, restxt, fromm=self.nick, speed=self.speed)
315 return
316
317 silent = False
318 channel = self.printto or self.channel
319 try:
320 silent = self.bot.channels[channel]['silent']
321 except (KeyError, TypeError):
322 pass
323 fromm = fromm or self.nick
324 if silent:
325 self.bot.say(self.nick, restxt, fromm=fromm, \
326 speed=self.speed)
327 return
328 if self.printto:
329 self.bot.say(self.printto, restxt, fromm=fromm, \
330 speed=self.speed)
331 return
332 else:
333 self.bot.say(self.channel, restxt, fromm=fromm, \
334 speed=self.speed)
335
337 """ show what arguments are missing """
338 if self.origtxt:
339 splitted = self.origtxt.split()
340 if self.bot.nick in splitted[0]:
341 try:
342 cmnd = splitted[1]
343 except IndexError:
344 cmnd = splitted[0]
345 elif 'cmnd' in splitted[0]:
346 try:
347 cmnd = splitted[2]
348 except IndexError:
349 cmnd = splitted[0]
350 else:
351 if self.msg:
352 cmnd = splitted[0]
353 else:
354 if self.aliased:
355 cmnd = self.aliased
356 else:
357 cmnd = splitted[0][1:]
358 self.reply(cmnd + ' ' + txt)
359 else:
360 self.reply('missing origtxt: %s' % txt)
361
362
363
364 pfc = {}
365 pfc['NICK'] = 0
366 pfc['QUIT'] = 0
367 pfc['SQUIT'] = 1
368 pfc['JOIN'] = 0
369 pfc['PART'] = 1
370 pfc['TOPIC'] = 1
371 pfc['KICK'] = 2
372 pfc['PRIVMSG'] = 1
373 pfc['NOTICE'] = 1
374 pfc['SQUERY'] = 1
375 pfc['PING'] = 0
376 pfc['ERROR'] =