comparison bot.py @ 124:99f3dee1fad7

code cleaning Signed-off-by: Charly COSTE <changaco@changaco.net>
author Charly COSTE <changaco@changaco.net>
date Wed, 13 Jan 2010 23:08:44 +0100
parents 9e90e15913a7
children eb65b875be0a
comparison
equal deleted inserted replaced
123:75a03f10a863 124:99f3dee1fad7
13 # 13 #
14 # You should have received a copy of the GNU General Public License 14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>. 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16
17 17
18 import re
19 import shlex
20 import sys
21 import threading
22 from time import sleep
23 import traceback
24 import xml.parsers.expat
25
26 from argparse_modified import ArgumentParser
27 from encoding import *
18 import irclib 28 import irclib
19 import muc 29 import muc
20 xmpp = muc.xmpp 30 xmpp = muc.xmpp
21 del muc 31 del muc
22 import threading 32
23 from bridge import * 33 from bridge import Bridge
24 from time import sleep 34 from participant import Participant
25 import re
26 import sys
27 import xml.parsers.expat
28 import traceback
29 from argparse_modified import *
30 import shlex
31 35
32 36
33 class bot(Thread): 37 class Bot(threading.Thread):
34 38
35 commands = ['xmpp-participants', 'irc-participants', 'bridges'] 39 commands = ['xmpp-participants', 'irc-participants', 'bridges']
36 admin_commands = ['add-bridge', 'add-xmpp-admin', 'halt', 'remove-bridge', 'restart-bot', 'restart-bridge', 'stop-bridge'] 40 admin_commands = ['add-bridge', 'add-xmpp-admin', 'halt', 'remove-bridge', 'restart-bot', 'restart-bridge', 'stop-bridge']
37 41
38 def __init__(self, jid, password, nickname, admins_jid=[], error_fd=sys.stderr, debug=False): 42 def __init__(self, jid, password, nickname, admins_jid=[], error_fd=sys.stderr, debug=False):
39 Thread.__init__(self) 43 threading.Thread.__init__(self)
40 self.bare_jid = xmpp.protocol.JID(jid=jid) 44 self.bare_jid = xmpp.protocol.JID(jid=jid)
41 self.bare_jid.setResource('') 45 self.bare_jid.setResource('')
42 self.nickname = nickname 46 self.nickname = nickname
43 self.password = password 47 self.password = password
44 self.error_fd = error_fd 48 self.error_fd = error_fd
47 self.bridges = [] 51 self.bridges = []
48 self.xmpp_connections = {} 52 self.xmpp_connections = {}
49 self.irc = irclib.IRC() 53 self.irc = irclib.IRC()
50 self.irc.bot = self 54 self.irc.bot = self
51 self.irc.add_global_handler('all_events', self._irc_event_handler) 55 self.irc.add_global_handler('all_events', self._irc_event_handler)
52 self.irc_thread = Thread(target=self.irc.process_forever) 56 self.irc_thread = threading.Thread(target=self.irc.process_forever)
53 self.irc_thread.start() 57 self.irc_thread.start()
54 # Open connection with XMPP server 58 # Open connection with XMPP server
55 try: 59 try:
56 self.xmpp_c = self.get_xmpp_connection(self.nickname) 60 self.xmpp_c = self.get_xmpp_connection(self.nickname)
57 except: 61 except:
58 self.error('[Error] XMPP Connection failed') 62 self.error('[Error] XMPP Connection failed')
59 raise 63 raise
60 self.xmpp_thread = Thread(target=self._xmpp_loop) 64 self.xmpp_thread = threading.Thread(target=self._xmpp_loop)
61 self.xmpp_thread.start() 65 self.xmpp_thread.start()
62 66
63 67
64 def error(self, s, debug=False, send_to_admins=False): 68 def error(self, s, debug=False, send_to_admins=False):
65 """Output an error message.""" 69 """Output an error message."""
173 item = x.getTag('item') 177 item = x.getTag('item')
174 178
175 if presence.getType() == 'unavailable': 179 if presence.getType() == 'unavailable':
176 try: 180 try:
177 p = bridge.getParticipant(resource) 181 p = bridge.getParticipant(resource)
178 except NoSuchParticipantException: 182 except Bridge.NoSuchParticipantException:
179 p = None 183 p = None
180 184
181 if x and x.getTag('status', attrs={'code': '303'}): 185 if x and x.getTag('status', attrs={'code': '303'}):
182 # participant changed its nickname 186 # participant changed its nickname
183 if p == None: 187 if p == None:
273 real_jid = item.getAttr('jid') 277 real_jid = item.getAttr('jid')
274 278
275 p = bridge.addParticipant('xmpp', resource, real_jid) 279 p = bridge.addParticipant('xmpp', resource, real_jid)
276 280
277 # if we have the real jid check if the participant is a bot admin 281 # if we have the real jid check if the participant is a bot admin
278 if real_jid and isinstance(p, participant): 282 if real_jid and isinstance(p, Participant):
279 for jid in self.admins_jid: 283 for jid in self.admins_jid:
280 if xmpp.protocol.JID(jid).bareMatch(real_jid): 284 if xmpp.protocol.JID(jid).bareMatch(real_jid):
281 p.bot_admin = True 285 p.bot_admin = True
282 break 286 break
283 287
322 from_ = bridge.getParticipant(message.getFrom().getResource()) 326 from_ = bridge.getParticipant(message.getFrom().getResource())
323 to_ = bridge.getParticipant(xmpp_c.nickname) 327 to_ = bridge.getParticipant(xmpp_c.nickname)
324 328
325 from_.sayOnIRCTo(to_.nickname, message.getBody()) 329 from_.sayOnIRCTo(to_.nickname, message.getBody())
326 330
327 except NoSuchParticipantException: 331 except Bridge.NoSuchParticipantException:
328 if xmpp_c.nickname == self.nickname: 332 if xmpp_c.nickname == self.nickname:
329 r = self.respond(str(message.getBody()), participant_=from_) 333 r = self.respond(str(message.getBody()), participant=from_)
330 if isinstance(r, basestring) and len(r) > 0: 334 if isinstance(r, basestring) and len(r) > 0:
331 s = xmpp.protocol.Message(to=message.getFrom(), body=r, typ='chat') 335 s = xmpp.protocol.Message(to=message.getFrom(), body=r, typ='chat')
332 self.error('==> Debug: Sending', debug=True) 336 self.error('==> Debug: Sending', debug=True)
333 self.error(s.__str__(fancy=1), debug=True) 337 self.error(s.__str__(fancy=1), debug=True)
334 xmpp_c.send(s) 338 xmpp_c.send(s)
392 # message comes from a participant of the room 396 # message comes from a participant of the room
393 self.error('==> Debug: Received XMPP groupchat message.', debug=True) 397 self.error('==> Debug: Received XMPP groupchat message.', debug=True)
394 self.error(message.__str__(fancy=1), debug=True) 398 self.error(message.__str__(fancy=1), debug=True)
395 399
396 try: 400 try:
397 participant_ = bridge.getParticipant(resource) 401 participant = bridge.getParticipant(resource)
398 except NoSuchParticipantException: 402 except Bridge.NoSuchParticipantException:
399 if resource != self.nickname: 403 if resource != self.nickname:
400 self.error('=> Debug: NoSuchParticipantException "'+resource+'" on "'+str(bridge)+'", WTF ?', debug=True) 404 self.error('=> Debug: NoSuchParticipantException "'+resource+'" on "'+str(bridge)+'", WTF ?', debug=True)
401 return 405 return
402 406
403 participant_.sayOnIRC(message.getBody()) 407 participant.sayOnIRC(message.getBody())
404 return 408 return
405 409
406 elif message.getType() == 'error': 410 elif message.getType() == 'error':
407 for b in self.bridges: 411 for b in self.bridges:
408 if message.getFrom() == b.xmpp_room_jid: 412 if message.getFrom() == b.xmpp_room_jid:
506 continue 510 continue
507 511
508 try: 512 try:
509 from_ = bridge.getParticipant(nickname) 513 from_ = bridge.getParticipant(nickname)
510 514
511 except NoSuchParticipantException: 515 except Bridge.NoSuchParticipantException:
512 continue 516 continue
513 517
514 518
515 # Private message 519 # Private message
516 if event.eventtype() == 'privmsg': 520 if event.eventtype() == 'privmsg':
521 to_ = bridge.getParticipant(event.target().split('!')[0]) 525 to_ = bridge.getParticipant(event.target().split('!')[0])
522 self.error(event_str, debug=True) 526 self.error(event_str, debug=True)
523 from_.sayOnXMPPTo(to_.nickname, event.arguments()[0]) 527 from_.sayOnXMPPTo(to_.nickname, event.arguments()[0])
524 return 528 return
525 529
526 except NoSuchParticipantException: 530 except Bridge.NoSuchParticipantException:
527 if event.target().split('!')[0] == self.nickname: 531 if event.target().split('!')[0] == self.nickname:
528 # Message is for the bot 532 # Message is for the bot
529 self.error(event_str, debug=True) 533 self.error(event_str, debug=True)
530 connection.privmsg(from_.nickname, self.respond(event.arguments()[0])) 534 connection.privmsg(from_.nickname, self.respond(event.arguments()[0]))
531 return 535 return
544 if len(event.arguments()) > 1: 548 if len(event.arguments()) > 1:
545 bridge.removeParticipant('irc', kicked.nickname, 'Kicked by '+nickname+' with reason: '+event.arguments()[1]) 549 bridge.removeParticipant('irc', kicked.nickname, 'Kicked by '+nickname+' with reason: '+event.arguments()[1])
546 else: 550 else:
547 bridge.removeParticipant('irc', kicked.nickname, 'Kicked by '+nickname+' (no reason was given)') 551 bridge.removeParticipant('irc', kicked.nickname, 'Kicked by '+nickname+' (no reason was given)')
548 return 552 return
549 except NoSuchParticipantException: 553 except Bridge.NoSuchParticipantException:
550 self.error('=> Debug: a participant that was not here has been kicked ? WTF ?') 554 self.error('=> Debug: a participant that was not here has been kicked ? WTF ?')
551 return 555 return
552 else: 556 else:
553 continue 557 continue
554 558
617 self.error(event_str, debug=True) 621 self.error(event_str, debug=True)
618 self.error('[Notice] the nickname "'+event.target()+'" is banned from the IRC chan of bridge "'+str(bridge)+'"') 622 self.error('[Notice] the nickname "'+event.target()+'" is banned from the IRC chan of bridge "'+str(bridge)+'"')
619 bridge.say('[Warning] the nickname "'+event.target()+'" is banned from the IRC chan') 623 bridge.say('[Warning] the nickname "'+event.target()+'" is banned from the IRC chan')
620 else: 624 else:
621 self.error('=> Debug: ignoring '+event.eventtype(), debug=True) 625 self.error('=> Debug: ignoring '+event.eventtype(), debug=True)
622 except NoSuchParticipantException: 626 except Bridge.NoSuchParticipantException:
623 self.error('=> Debug: no such participant. WTF ?') 627 self.error('=> Debug: no such participant. WTF ?')
624 return 628 return
625 629
626 return 630 return
627 631
671 p.irc_connection.part(bridge.irc_room, message=message) 675 p.irc_connection.part(bridge.irc_room, message=message)
672 p.irc_connection.used_by -= 1 676 p.irc_connection.used_by -= 1
673 if p.irc_connection.used_by < 1: 677 if p.irc_connection.used_by < 1:
674 p.irc_connection.close(message) 678 p.irc_connection.close(message)
675 p.irc_connection = None 679 p.irc_connection = None
676 except NoSuchParticipantException: 680 except Bridge.NoSuchParticipantException:
677 pass 681 pass
678 return 682 return
679 683
680 684
681 # Nickname callbacks 685 # Nickname callbacks
704 pass 708 pass
705 709
706 710
707 def new_bridge(self, xmpp_room, irc_room, irc_server, mode, say_level, irc_port=6667): 711 def new_bridge(self, xmpp_room, irc_room, irc_server, mode, say_level, irc_port=6667):
708 """Create a bridge between xmpp_room and irc_room at irc_server.""" 712 """Create a bridge between xmpp_room and irc_room at irc_server."""
709 b = bridge(self, xmpp_room, irc_room, irc_server, mode, say_level, irc_port=irc_port) 713 b = Bridge(self, xmpp_room, irc_room, irc_server, mode, say_level, irc_port=irc_port)
710 self.bridges.append(b) 714 self.bridges.append(b)
711 return b 715 return b
712 716
713 717
714 def findBridges(self, str_array): 718 def findBridges(self, str_array):
817 def removeBridge(self, bridge, message='Removing bridge'): 821 def removeBridge(self, bridge, message='Removing bridge'):
818 self.bridges.remove(bridge) 822 self.bridges.remove(bridge)
819 bridge.stop(message) 823 bridge.stop(message)
820 824
821 825
822 def respond(self, message, participant_=None, bot_admin=False): 826 def respond(self, message, participant=None, bot_admin=False):
823 ret = '' 827 ret = ''
824 command = shlex.split(message) 828 command = shlex.split(message)
825 args_array = [] 829 args_array = []
826 if len(command) > 1: 830 if len(command) > 1:
827 args_array = command[1:] 831 args_array = command[1:]
828 command = command[0] 832 command = command[0]
829 833
830 if isinstance(participant_, participant) and bot_admin != participant_.bot_admin: 834 if isinstance(participant, participant) and bot_admin != participant.bot_admin:
831 bot_admin = participant_.bot_admin 835 bot_admin = participant.bot_admin
832 836
833 if command == 'xmpp-participants': 837 if command == 'xmpp-participants':
834 if not isinstance(participant_, participant): 838 if not isinstance(participant, participant):
835 for b in self.bridges: 839 for b in self.bridges:
836 xmpp_participants_nicknames = b.get_participants_nicknames_list(protocols=['xmpp']) 840 xmpp_participants_nicknames = b.get_participants_nicknames_list(protocols=['xmpp'])
837 ret += '\nparticipants on '+b.xmpp_room_jid+' ('+str(len(xmpp_participants_nicknames))+'): '+' '.join(xmpp_participants_nicknames) 841 ret += '\nparticipants on '+b.xmpp_room_jid+' ('+str(len(xmpp_participants_nicknames))+'): '+' '.join(xmpp_participants_nicknames)
838 return ret 842 return ret
839 else: 843 else:
840 xmpp_participants_nicknames = participant_.bridge.get_participants_nicknames_list(protocols=['xmpp']) 844 xmpp_participants_nicknames = participant.bridge.get_participants_nicknames_list(protocols=['xmpp'])
841 return '\nparticipants on '+participant_.bridge.xmpp_room_jid+' ('+str(len(xmpp_participants_nicknames))+'): '+' '.join(xmpp_participants_nicknames) 845 return '\nparticipants on '+participant.bridge.xmpp_room_jid+' ('+str(len(xmpp_participants_nicknames))+'): '+' '.join(xmpp_participants_nicknames)
842 846
843 elif command == 'irc-participants': 847 elif command == 'irc-participants':
844 if not isinstance(participant_, participant): 848 if not isinstance(participant, participant):
845 for b in self.bridges: 849 for b in self.bridges:
846 irc_participants_nicknames = b.get_participants_nicknames_list(protocols=['irc']) 850 irc_participants_nicknames = b.get_participants_nicknames_list(protocols=['irc'])
847 ret += '\nparticipants on '+b.irc_room+' at '+b.irc_server+' ('+str(len(irc_participants_nicknames))+'): '+' '.join(irc_participants_nicknames) 851 ret += '\nparticipants on '+b.irc_room+' at '+b.irc_server+' ('+str(len(irc_participants_nicknames))+'): '+' '.join(irc_participants_nicknames)
848 return ret 852 return ret
849 else: 853 else:
850 irc_participants_nicknames = participant_.bridge.get_participants_nicknames_list(protocols=['irc']) 854 irc_participants_nicknames = participant.bridge.get_participants_nicknames_list(protocols=['irc'])
851 return '\nparticipants on '+participant_.bridge.irc_room+' at '+participant_.bridge.irc_server+' ('+str(len(irc_participants_nicknames))+'): '+' '.join(irc_participants_nicknames) 855 return '\nparticipants on '+participant.bridge.irc_room+' at '+participant.bridge.irc_server+' ('+str(len(irc_participants_nicknames))+'): '+' '.join(irc_participants_nicknames)
852 856
853 elif command == 'bridges': 857 elif command == 'bridges':
854 parser = ArgumentParser(prog=command) 858 parser = ArgumentParser(prog=command)
855 parser.add_argument('--show-mode', default=False, action='store_true') 859 parser.add_argument('--show-mode', default=False, action='store_true')
856 parser.add_argument('--show-say-level', default=False, action='store_true') 860 parser.add_argument('--show-say-level', default=False, action='store_true')
857 parser.add_argument('--show-participants', default=False, action='store_true') 861 parser.add_argument('--show-participants', default=False, action='store_true')
858 try: 862 try:
859 args = parser.parse_args(args_array) 863 args = parser.parse_args(args_array)
860 except ParseException as e: 864 except ArgumentParser.ParseException as e:
861 return '\n'+e.args[1] 865 return '\n'+e.args[1]
862 ret = 'List of bridges:' 866 ret = 'List of bridges:'
863 for i, b in enumerate(self.bridges): 867 for i, b in enumerate(self.bridges):
864 ret += '\n'+str(i+1)+' - '+str(b) 868 ret += '\n'+str(i+1)+' - '+str(b)
865 if args.show_mode: 869 if args.show_mode:
887 parser.add_argument('--mode', choices=bridge._modes, default='normal') 891 parser.add_argument('--mode', choices=bridge._modes, default='normal')
888 parser.add_argument('--say-level', choices=bridge._say_levels, default='all') 892 parser.add_argument('--say-level', choices=bridge._say_levels, default='all')
889 parser.add_argument('--irc-port', type=int, default=6667) 893 parser.add_argument('--irc-port', type=int, default=6667)
890 try: 894 try:
891 args = parser.parse_args(args_array) 895 args = parser.parse_args(args_array)
892 except ParseException as e: 896 except ArgumentParser.ParseException as e:
893 return '\n'+e.args[1] 897 return '\n'+e.args[1]
894 898
895 self.new_bridge(args.xmpp_room_jid, args.irc_chan, args.irc_server, args.mode, args.say_level, irc_port=args.irc_port) 899 self.new_bridge(args.xmpp_room_jid, args.irc_chan, args.irc_server, args.mode, args.say_level, irc_port=args.irc_port)
896 900
897 return 'Bridge added.' 901 return 'Bridge added.'
899 elif command == 'add-xmpp-admin': 903 elif command == 'add-xmpp-admin':
900 parser = ArgumentParser(prog=command) 904 parser = ArgumentParser(prog=command)
901 parser.add_argument('jid', type=str) 905 parser.add_argument('jid', type=str)
902 try: 906 try:
903 args = parser.parse_args(args_array) 907 args = parser.parse_args(args_array)
904 except ParseException as e: 908 except ArgumentParser.ParseException as e:
905 return '\n'+e.args[1] 909 return '\n'+e.args[1]
906 self.admins_jid.append(args.jid) 910 self.admins_jid.append(args.jid)
907 for b in self.bridges: 911 for b in self.bridges:
908 for p in b.participants: 912 for p in b.participants:
909 if p.real_jid != None and xmpp.protocol.JID(args.jid).bareMatch(p.real_jid): 913 if p.real_jid != None and xmpp.protocol.JID(args.jid).bareMatch(p.real_jid):
920 924
921 925
922 elif command in ['remove-bridge', 'restart-bridge', 'stop-bridge']: 926 elif command in ['remove-bridge', 'restart-bridge', 'stop-bridge']:
923 # we need to know which bridge the command is for 927 # we need to know which bridge the command is for
924 if len(args_array) == 0: 928 if len(args_array) == 0:
925 if isinstance(participant_, participant): 929 if isinstance(participant, participant):
926 b = participant_.bridge 930 b = participant.bridge
927 else: 931 else:
928 return 'You must specify a bridge. '+self.respond('bridges') 932 return 'You must specify a bridge. '+self.respond('bridges')
929 else: 933 else:
930 try: 934 try:
931 bn = int(args_array[0]) 935 bn = int(args_array[0])