comparison bot.py @ 232:02c58515edde

improved Bot._xmpp_message_handler Signed-off-by: Charly COSTE <changaco@changaco.net>
author Charly COSTE <changaco@changaco.net>
date Sun, 07 Mar 2010 23:35:31 +0100
parents d5a126cf119c
children 533a5db79389
comparison
equal deleted inserted replaced
231:5f1e9211af03 232:02c58515edde
281 elif resource != bridge.bot.nickname: 281 elif resource != bridge.bot.nickname:
282 real_jid = None 282 real_jid = None
283 if item and item.has_attr('jid'): 283 if item and item.has_attr('jid'):
284 real_jid = item.getAttr('jid') 284 real_jid = item.getAttr('jid')
285 285
286 p = bridge.add_participant('xmpp', resource, real_jid) 286 p = bridge.add_participant('xmpp', resource, real_jid=real_jid)
287 287
288 # if we have the real jid check if the participant is a bot admin 288 # if we have the real jid check if the participant is a bot admin
289 if real_jid and isinstance(p, Participant): 289 if real_jid and isinstance(p, Participant):
290 for admin in self.admins: 290 for admin in self.admins:
291 if xmpp.protocol.JID(admin.jid).bareMatch(real_jid): 291 if xmpp.protocol.JID(admin.jid).bareMatch(real_jid):
319 xmpp_c = dispatcher._owner 319 xmpp_c = dispatcher._owner
320 320
321 if message.getBody() == None: 321 if message.getBody() == None:
322 return 322 return
323 323
324
325 # Private message
324 if message.getType() == 'chat': 326 if message.getType() == 'chat':
325 from_bare_jid = unicode(message.getFrom().getNode()+'@'+message.getFrom().getDomain()) 327 from_bare_jid = unicode(message.getFrom().getNode()+'@'+message.getFrom().getDomain())
326 for bridge in self.bridges: 328
327 if from_bare_jid == bridge.xmpp_room_jid: 329 try:
328 # message comes from a room participant 330 bridge = self.get_bridge(xmpp_room_jid=from_bare_jid)
331 except KeyError:
332 bridge = None
333
334 if bridge:
335 # message comes from a room participant
336 self.error(2, 'Received XMPP chat message.\n'+message.__str__(fancy=1), debug=True)
337
338 try:
339 from_ = bridge.get_participant(message.getFrom().getResource())
340 to_ = bridge.get_participant(xmpp_c.nickname)
329 341
330 self.error(2, 'Received XMPP chat message.\n'+message.__str__(fancy=1), debug=True) 342 from_.say_on_irc_to(to_.nickname, message.getBody())
331 343
332 try: 344 except Bridge.NoSuchParticipantException:
333 from_ = bridge.get_participant(message.getFrom().getResource()) 345 if xmpp_c.nickname == self.nickname:
334 to_ = bridge.get_participant(xmpp_c.nickname) 346 r = self.respond(str(message.getBody()), participant=from_)
335 347 if isinstance(r, basestring) and len(r) > 0:
336 from_.say_on_irc_to(to_.nickname, message.getBody()) 348 s = xmpp.protocol.Message(to=message.getFrom(), body=r, typ='chat')
337 349 self.error(2, 'Sending\n'+s.__str__(fancy=1), debug=True)
338 except Bridge.NoSuchParticipantException: 350 xmpp_c.send(s)
339 if xmpp_c.nickname == self.nickname: 351 else:
340 r = self.respond(str(message.getBody()), participant=from_) 352 self.error(1, 'won\'t answer.', debug=True)
341 if isinstance(r, basestring) and len(r) > 0:
342 s = xmpp.protocol.Message(to=message.getFrom(), body=r, typ='chat')
343 self.error(2, 'Sending\n'+s.__str__(fancy=1), debug=True)
344 xmpp_c.send(s)
345 else:
346 self.error(1, 'won\'t answer.', debug=True)
347 return
348 self.error(say_levels.debug, 'XMPP chat message not relayed', no_debug_add='\n'+message.__str__(fancy=1))
349 return 353 return
350 354 self.error(say_levels.debug, 'XMPP chat message not relayed', no_debug_add='\n'+message.__str__(fancy=1))
351 # message does not come from a room 355 return
352 if xmpp_c.nickname == self.nickname: 356
357 else:
358 # message does not come from a room participant
359 if xmpp_c.nickname != self.nickname:
360 self.error(1, 'Ignoring XMPP chat message not received on bot connection.', debug=True)
361 return
362
353 self.error(2, 'Received XMPP chat message.\n'+message.__str__(fancy=1), debug=True) 363 self.error(2, 'Received XMPP chat message.\n'+message.__str__(fancy=1), debug=True)
354 364
355 # Find out if the message comes from a bot admin 365 # Find out if the message comes from a bot admin
356 bot_admin = False 366 bot_admin = False
357 for admin in self.admins: 367 for admin in self.admins:
363 r = self.respond(str(message.getBody()), bot_admin=bot_admin) 373 r = self.respond(str(message.getBody()), bot_admin=bot_admin)
364 if isinstance(r, basestring) and len(r) > 0: 374 if isinstance(r, basestring) and len(r) > 0:
365 s = xmpp.protocol.Message(to=message.getFrom(), body=r, typ='chat') 375 s = xmpp.protocol.Message(to=message.getFrom(), body=r, typ='chat')
366 self.error(2, 'Sending\n'+s.__str__(fancy=1), debug=True) 376 self.error(2, 'Sending\n'+s.__str__(fancy=1), debug=True)
367 xmpp_c.send(s) 377 xmpp_c.send(s)
368 378
369 else: 379
370 self.error(1, 'Ignoring XMPP chat message not received on bot connection.', debug=True) 380 # MUC message
371
372 elif message.getType() == 'groupchat': 381 elif message.getType() == 'groupchat':
373 # message comes from a room
374 382
375 for child in message.getChildren(): 383 for child in message.getChildren():
376 if child.getName() == 'delay': 384 if child.getName() == 'delay':
377 # MUC delayed message 385 # MUC delayed message
378 return 386 return
379 387
380 if xmpp_c.nickname != self.nickname: 388 if xmpp_c.nickname != self.nickname:
381 self.error(1, 'Ignoring XMPP MUC message not received on bot connection.', debug=True) 389 self.error(1, 'Ignoring XMPP MUC message not received on bot connection.', debug=True)
382 return 390 return
383 391
384
385 from_ = xmpp.protocol.JID(message.getFrom()) 392 from_ = xmpp.protocol.JID(message.getFrom())
386 393
387 if unicode(from_.getResource()) == self.nickname: 394 resource = unicode(from_.getResource())
395
396 if resource == self.nickname:
388 self.error(1, 'Ignoring XMPP MUC message sent by self.', debug=True) 397 self.error(1, 'Ignoring XMPP MUC message sent by self.', debug=True)
389 return 398 return
390 399
391 room_jid = unicode(from_.getNode()+'@'+from_.getDomain()) 400 room_jid = unicode(from_.getNode()+'@'+from_.getDomain())
392 for bridge in self.bridges: 401 bridge = self.get_bridge(xmpp_room_jid=room_jid)
393 if room_jid == bridge.xmpp_room_jid: 402
394 resource = unicode(from_.getResource()) 403 if resource == '':
395 if resource == '': 404 # message comes from the room itself
396 # message comes from the room itself 405 self.error(1, 'Ignoring XMPP groupchat message sent by the room.', debug=True)
397 self.error(1, 'Ignoring XMPP groupchat message sent by the room.', debug=True) 406 return
398 return 407 else:
399 else: 408 # message comes from a participant of the room
400 # message comes from a participant of the room 409 self.error(2, 'Received XMPP groupchat message.\n'+message.__str__(fancy=1), debug=True)
401 self.error(2, 'Received XMPP groupchat message.\n'+message.__str__(fancy=1), debug=True) 410
402 411 try:
403 try: 412 participant = bridge.get_participant(resource)
404 participant = bridge.get_participant(resource) 413 participant.say_on_irc(message.getBody())
405 except Bridge.NoSuchParticipantException: 414 except Bridge.NoSuchParticipantException:
406 if resource != self.nickname: 415 bridge.say_on_behalf(resource, message.getBody(), 'irc', action=(message.getBody()[:4] == '/me '))
407 self.error(say_levels.debug, 'NoSuchParticipantException "'+resource+'" on "'+str(bridge)+'", WTF ?', no_debug_add='\n'+message.__str__(fancy=1)) 416
408 return 417 return
409 418
410 participant.say_on_irc(message.getBody()) 419
411 return 420 # Error message
412
413 elif message.getType() == 'error': 421 elif message.getType() == 'error':
414 for b in self.bridges: 422 try:
415 if message.getFrom() == b.xmpp_room_jid: 423 b = self.get_bridge(xmpp_room_jid=message.getFrom())
416 # message comes from a room 424 except KeyError:
417 for c in message.getChildren(): 425 self.error(say_levels.debug, 'received unknown error message\n'+message.__str__(fancy=1))
418 if c.getName() == 'error': 426 return
419 for cc in c.getChildren(): 427
420 if cc.getNamespace() == 'urn:ietf:params:xml:ns:xmpp-stanzas' and cc.getName() != 'text': 428 for c in message.getChildren():
421 err = cc.getName() 429 if c.getName() == 'error':
422 if err in ['not-acceptable', 'not-allowed']: 430 for cc in c.getChildren():
423 # we sent a message to a room we are not in 431 if cc.getNamespace() == 'urn:ietf:params:xml:ns:xmpp-stanzas' and cc.getName() != 'text':
424 # can be due to a MUC server restart 432 err = cc.getName()
425 # can be a concurrency bug 433 if err in ['not-acceptable', 'not-allowed']:
426 if xmpp_c.nickname == self.nickname: 434 # we sent a message to a room we are not in
427 b.restart(message='Automatic restart of bridge') 435 # can be due to a MUC server restart
428 else: 436 # can be a concurrency bug
429 try: 437 if xmpp_c.nickname == self.nickname:
430 p = b.get_participant(xmpp_c.nickname) 438 b.restart(message='Automatic restart of bridge')
431 p.say_on_XMPP_through_bridge(message.getBody()) 439 else:
432 except Bridge.NoSuchParticipantException: 440 try:
433 b.restart(message='Automatic restart of bridge') 441 p = b.get_participant(xmpp_c.nickname)
434 442 p.say_on_XMPP_through_bridge(message.getBody())
435 elif err == 'forbidden': 443 except Bridge.NoSuchParticipantException:
436 # we don't have the permission to speak 444 b.restart(message='Automatic restart of bridge')
437 # let's remove the bridge and tell admins 445
438 self.error(say_levels.error, 'Not allowed to speak on the XMPP MUC of bridge '+str(b)+', stopping it', send_to_admins=True) 446 elif err == 'forbidden':
439 b.stop(message='Not allowed to speak on the XMPP MUC, stopping the bridge') 447 # we don't have the permission to speak
440 else: 448 # let's remove the bridge and tell admins
441 self.error(say_levels.debug, 'recevied unknown error message\n'+message.__str__(fancy=1)) 449 self.error(say_levels.error, 'Not allowed to speak on the XMPP MUC of bridge '+str(b)+', stopping it', send_to_admins=True)
442 return 450 b.stop(message='Not allowed to speak on the XMPP MUC, stopping the bridge')
443 451 else:
444 self.error(say_levels.debug, 'received unknown error message\n'+message.__str__(fancy=1)) 452 self.error(say_levels.debug, 'recevied unknown error message\n'+message.__str__(fancy=1))
445 453
454 return
455
456
457 # Unknown message type
446 else: 458 else:
447 self.error(say_levels.debug, 'Received XMPP message of unknown type "'+str(message.getType())+'".\n'+message.__str__(fancy=1)) 459 self.error(say_levels.debug, 'Received XMPP message of unknown type "'+str(message.getType())+'".\n'+message.__str__(fancy=1))
448 460
449 461
450 def _irc_event_handler(self, connection, event): 462 def _irc_event_handler(self, connection, event):
643 else: 655 else:
644 action = False 656 action = False
645 if isinstance(from_, Participant): 657 if isinstance(from_, Participant):
646 from_.say_on_xmpp(message, action=action) 658 from_.say_on_xmpp(message, action=action)
647 else: 659 else:
648 bridge.say_on_behalf(source_nickname, message, action=action) 660 bridge.say_on_behalf(source_nickname, message, 'xmpp', action=action)
649 return 661 return
650 662
651 663
652 # Mode event 664 # Mode event
653 if event.eventtype() == 'mode': 665 if event.eventtype() == 'mode':
718 730
719 See Bot.iter_bridges for the list of args""" 731 See Bot.iter_bridges for the list of args"""
720 732
721 bridges = [b for b in self.iter_bridges(**kwargs)] 733 bridges = [b for b in self.iter_bridges(**kwargs)]
722 if len(bridges) == 0: 734 if len(bridges) == 0:
723 raise Exception, 'no bridge matching '+str(kwargs) 735 raise KeyError, 'no bridge matching '+str(kwargs)
724 elif len(bridges) > 1: 736 elif len(bridges) > 1:
725 raise Exception, 'more than one bridge matching '+str(kwargs)+'\n'+'\n'.join([str(b) for b in bridges]) 737 raise Exception, 'more than one bridge matching '+str(kwargs)+'\n'+'\n'.join([str(b) for b in bridges])
726 return bridges[0] 738 return bridges[0]
727 739
728 740