Mercurial > xib
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]) |