Package gozerbot :: Module ircevent
[hide private]
[frames] | no frames]

Source Code for Module gozerbot.ircevent

  1  # gozerbot/ircevent.py 
  2  # 
  3  # 
  4  # http://www.irchelp.org/irchelp/rfc/rfc2812.txt 
  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   
15 -def makeargrest(ievent):
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
28 -class Ircevent(object):
29 30 """ represents an IRC event """ 31
32 - def __init__(self, ievent=None):
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
78 - def copyin(self, ievent):
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
121 - def __str__(self):
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
128 - def __del__(self):
129 if self.bot: 130 self.bot.gcevents += 1
131
132 - def filtered(self, txt):
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 # check if there is a prefix (: in front) 147 if not rawstr[0] == ':': 148 # no prefix .. 1st word is command 149 splitted.insert(0, ":none!none@none") 150 rawstr = ":none!none@none " + rawstr 151 self.prefix = splitted[0][1:] 152 # get nick/userhost 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 # 1st argument is target 165 if self.arguments: 166 self.target = self.arguments[0] 167 self.postfix = ' '.join(self.arguments) 168 # check if target is text 169 if self.target and self.target.startswith(':'): 170 self.txt = ' '.join(self.arguments) 171 # strip strarting ':' from txt 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 # determine channel 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 # userhost before possible stripident 198 self.ruserhost = self.userhost 199 self.userhost = stripident(self.userhost) 200 # jabber compat .. this is userhost on irc 201 self.stripped = self.userhost 202 # determine user 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 # check if bot is in silent mode .. if so use /msg 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
336 - def missing(self, txt):
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 # postfix count aka how many arguments 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'] =