Mercurial > xib
comparison bridge.py @ 180:102f895347ff
added a required "importance" argument to Bot.error()
Signed-off-by: Charly COSTE <changaco@changaco.net>
author | Charly COSTE <changaco@changaco.net> |
---|---|
date | Sat, 13 Feb 2010 16:32:28 +0100 |
parents | f6c6708c6c0e |
children | 60ee2b914616 |
comparison
equal
deleted
inserted
replaced
179:f6c6708c6c0e | 180:102f895347ff |
---|---|
23 import muc | 23 import muc |
24 xmpp = muc.xmpp | 24 xmpp = muc.xmpp |
25 del muc | 25 del muc |
26 | 26 |
27 from participant import Participant | 27 from participant import Participant |
28 import say_levels | |
28 | 29 |
29 | 30 |
30 class Bridge: | 31 class Bridge: |
31 | 32 |
32 _all = 0 | 33 modes = ['bypass', 'normal', 'limited', 'minimal'] |
33 _info = 1 | |
34 _notice = 2 | |
35 _warning = 3 | |
36 _error = 4 | |
37 _nothing = 5 | |
38 _say_levels = ['all', 'info', 'notice', 'warning', 'error', 'nothing'] | |
39 _modes = ['normal', 'bypass', 'limited', 'minimal'] | |
40 | |
41 | 34 |
42 class NoSuchParticipantException(Exception): pass | 35 class NoSuchParticipantException(Exception): pass |
43 | 36 |
44 | 37 |
45 def __init__(self, owner_bot, xmpp_room_jid, irc_room, irc_server, mode, say_level, irc_port=6667, irc_connection_interval=None, irc_charsets=None): | 38 def __init__(self, owner_bot, xmpp_room_jid, irc_room, irc_server, mode, say_level, irc_port=6667, irc_connection_interval=None, irc_charsets=None): |
49 self.irc_port = irc_port | 42 self.irc_port = irc_port |
50 self.irc_room = irc_room.lower() | 43 self.irc_room = irc_room.lower() |
51 self.irc_connection_interval = irc_connection_interval | 44 self.irc_connection_interval = irc_connection_interval |
52 self.irc_charsets = irc_charsets | 45 self.irc_charsets = irc_charsets |
53 self.xmpp_room_jid = xmpp_room_jid | 46 self.xmpp_room_jid = xmpp_room_jid |
54 if hasattr(self.__class__, '_'+say_level): | 47 self.say_level = say_level |
55 self.say_level = getattr(self.__class__, '_'+say_level) | |
56 else: | |
57 raise Exception('[Error] "'+say_level+'" is not a correct value for a bridge\'s "say_level" attribute') | |
58 self.participants = [] | 48 self.participants = [] |
59 if mode not in self.__class__._modes: | 49 if mode not in self.__class__.modes: |
60 raise Exception('[Error] "'+mode+'" is not a correct value for a bridge\'s "mode" attribute') | 50 raise Exception('[Error] "'+mode+'" is not a correct value for a bridge\'s "mode" attribute') |
61 self.mode = mode | 51 self.mode = mode |
62 | 52 |
63 self.lock = threading.RLock() | 53 self.lock = threading.RLock() |
64 | 54 |
72 | 62 |
73 # Join IRC room | 63 # Join IRC room |
74 self.irc_connection = self.bot.irc.open_connection(self.irc_server, self.irc_port, self.bot.nickname, delay=self.irc_connection_interval) | 64 self.irc_connection = self.bot.irc.open_connection(self.irc_server, self.irc_port, self.bot.nickname, delay=self.irc_connection_interval) |
75 self.irc_connection.connect(nick_callback=self._irc_nick_callback, charsets=self.irc_charsets) | 65 self.irc_connection.connect(nick_callback=self._irc_nick_callback, charsets=self.irc_charsets) |
76 | 66 |
77 self.bot.error('[Notice] bridge "'+str(self)+'" is running in '+self.mode+' mode and a say_level of "'+self.__class__._say_levels[self.say_level]+'"') | 67 self.bot.error(say_levels.notice, 'bridge "'+str(self)+'" is running in '+self.mode+' mode and a say_level of "'+str(self.say_level)+'"') |
78 | 68 |
79 | 69 |
80 def _join_irc_failed(self): | 70 def _join_irc_failed(self): |
81 self.bot.error('[Error] failed to connect to the IRC chan of bridge "'+str(self)+'", stopping bridge', send_to_admins=True) | 71 self.bot.error(say_levels.error, 'failed to connect to the IRC chan of bridge "'+str(self)+'", stopping bridge', send_to_admins=True) |
82 self.stop(message='failed to connect to the IRC chan') | 72 self.stop(message='failed to connect to the IRC chan') |
83 | 73 |
84 | 74 |
85 def _irc_nick_callback(self, error, arguments=[]): | 75 def _irc_nick_callback(self, error, arguments=[]): |
86 if error == None: | 76 if error == None: |
87 if self.mode == None: | 77 if self.mode == None: |
88 return | 78 return |
89 self.irc_connection.join(self.irc_room) | 79 self.irc_connection.join(self.irc_room) |
90 self.bot.error('===> Debug: successfully connected on IRC side of bridge "'+str(self)+'"', debug=True) | 80 self.bot.error(3, 'successfully connected on IRC side of bridge "'+str(self)+'"', debug=True) |
91 self.say('[Notice] bridge "'+str(self)+'" is running in '+self.mode+' mode', on_xmpp=False) | 81 self.say(say_levels.notice, 'bridge "'+str(self)+'" is running in '+self.mode+' mode', on_xmpp=False) |
92 if self.mode not in ['normal', 'bypass']: | 82 if self.mode not in ['normal', 'bypass']: |
93 self.show_participants_list_on(protocols=['irc']) | 83 self.show_participants_list_on(protocols=['irc']) |
94 else: | 84 else: |
95 self.mode = None | 85 self.mode = None |
96 if self.xmpp_room.connected == True: | 86 if self.xmpp_room.connected == True: |
97 self.say('[Error] failed to connect to the IRC chan, leaving ...', on_irc=False) | 87 self.say(say_levels.error, 'failed to connect to the IRC chan, leaving ...', on_irc=False) |
98 try: | 88 try: |
99 if error == 'nicknameinuse': | 89 if error == 'nicknameinuse': |
100 raise Exception('[Error] "'+self.bot.nickname+'" is already used in the IRC chan or reserved on the IRC server of bridge "'+str(self)+'"') | 90 raise Exception('[Error] "'+self.bot.nickname+'" is already used in the IRC chan or reserved on the IRC server of bridge "'+str(self)+'"') |
101 elif error == 'nickcollision': | 91 elif error == 'nickcollision': |
102 raise Exception('[Error] "'+self.bot.nickname+'" is already used or reserved on the IRC server of bridge "'+str(self)+'"') | 92 raise Exception('[Error] "'+self.bot.nickname+'" is already used or reserved on the IRC server of bridge "'+str(self)+'"') |
123 if len(errors) == 0: | 113 if len(errors) == 0: |
124 if hasattr(self, 'reconnecting'): | 114 if hasattr(self, 'reconnecting'): |
125 del self.reconnecting | 115 del self.reconnecting |
126 if self.mode == None: | 116 if self.mode == None: |
127 return | 117 return |
128 self.bot.error('===> Debug: succesfully connected on XMPP side of bridge "'+str(self)+'"', debug=True) | 118 self.bot.error(3, 'succesfully connected on XMPP side of bridge "'+str(self)+'"', debug=True) |
129 self.say('[Notice] bridge "'+str(self)+'" is running in '+self.mode+' mode', on_irc=False) | 119 self.say(say_levels.notice, 'bridge "'+str(self)+'" is running in '+self.mode+' mode', on_irc=False) |
130 else: | 120 else: |
131 self.mode = None | 121 self.mode = None |
132 if self.irc_connection.really_connected == True: | 122 if self.irc_connection.really_connected == True: |
133 self.say('[Error] failed to connect to the XMPP room, leaving ...', on_xmpp=False) | 123 self.say(say_levels.error, 'failed to connect to the XMPP room, leaving ...', on_xmpp=False) |
134 for error in errors: | 124 for error in errors: |
135 try: | 125 try: |
136 raise error | 126 raise error |
137 except xmpp.muc.RemoteServerNotFound: | 127 except xmpp.muc.RemoteServerNotFound: |
138 self._RemoteServerNotFound_handler() | 128 self._RemoteServerNotFound_handler() |
139 except: | 129 except: |
140 trace = traceback.format_exc() | 130 trace = traceback.format_exc() |
141 self.bot.error('[Error] failed to connect to the XMPP room of bridge "'+str(self)+'", stopping bridge\n'+trace, send_to_admins=True) | 131 self.bot.error(say_levels.error, 'failed to connect to the XMPP room of bridge "'+str(self)+'", stopping bridge\n'+trace, send_to_admins=True) |
142 self.stop(message='failed to connect to the XMPP room') | 132 self.stop(message='failed to connect to the XMPP room') |
143 | 133 |
144 | 134 |
145 def addParticipant(self, from_protocol, nickname, real_jid=None, irc_id=None): | 135 def addParticipant(self, from_protocol, nickname, real_jid=None, irc_id=None): |
146 """Add a participant to the bridge.""" | 136 """Add a participant to the bridge.""" |
147 if (from_protocol == 'irc' and nickname == self.bot.nickname) or (from_protocol == 'xmpp' and nickname == self.bot.nickname): | 137 if (from_protocol == 'irc' and nickname == self.bot.nickname) or (from_protocol == 'xmpp' and nickname == self.bot.nickname): |
148 self.bot.error('===> Debug: not adding self ('+self.bot.nickname+') to bridge "'+str(self)+'"', debug=True) | 138 self.bot.error(3, 'not adding self ('+self.bot.nickname+') to bridge "'+str(self)+'"', debug=True) |
149 return | 139 return |
150 try: | 140 try: |
151 p = self.getParticipant(nickname) | 141 p = self.getParticipant(nickname) |
152 if p.protocol != from_protocol: | 142 if p.protocol != from_protocol: |
153 if from_protocol == 'irc' and isinstance(p.irc_connection, ServerConnection) and p.irc_connection.really_connected == True and p.irc_connection.real_nickname == nickname or from_protocol == 'xmpp' and isinstance(p.xmpp_c, xmpp.client.Client) and isinstance(p.muc, xmpp.muc) and p.xmpp_c.nickname == nickname: | 143 if from_protocol == 'irc' and isinstance(p.irc_connection, ServerConnection) and p.irc_connection.really_connected == True and p.irc_connection.real_nickname == nickname or from_protocol == 'xmpp' and isinstance(p.xmpp_c, xmpp.client.Client) and isinstance(p.muc, xmpp.muc) and p.xmpp_c.nickname == nickname: |
161 | 151 |
162 if nickname == 'ChanServ' and from_protocol == 'irc': | 152 if nickname == 'ChanServ' and from_protocol == 'irc': |
163 return | 153 return |
164 | 154 |
165 self.lock.acquire() | 155 self.lock.acquire() |
166 self.bot.error('===> Debug: adding participant "'+nickname+'" from "'+from_protocol+'" to bridge "'+str(self)+'"', debug=True) | 156 self.bot.error(3, 'adding participant "'+nickname+'" from "'+from_protocol+'" to bridge "'+str(self)+'"', debug=True) |
167 try: | 157 try: |
168 p = Participant(self, from_protocol, nickname, real_jid=real_jid) | 158 p = Participant(self, from_protocol, nickname, real_jid=real_jid) |
169 except IOError: | 159 except IOError: |
170 self.bot.error('===> Debug: IOError while adding participant "'+nickname+'" from "'+from_protocol+'" to bridge "'+str(self)+'", reconnectiong ...', debug=True) | 160 self.bot.error(3, 'IOError while adding participant "'+nickname+'" from "'+from_protocol+'" to bridge "'+str(self)+'", reconnectiong ...', debug=True) |
171 p.xmpp_c.reconnectAndReauth() | 161 p.xmpp_c.reconnectAndReauth() |
172 except: | 162 except: |
173 self.bot.error('===> Debug: unknown error while adding participant "'+nickname+'" from "'+from_protocol+'" to bridge "'+str(self)+'"', debug=True) | 163 self.bot.error(3, 'unknown error while adding participant "'+nickname+'" from "'+from_protocol+'" to bridge "'+str(self)+'"', debug=True) |
174 traceback.print_exc() | 164 traceback.print_exc() |
175 return | 165 return |
176 self.participants.append(p) | 166 self.participants.append(p) |
177 self.lock.release() | 167 self.lock.release() |
178 if self.mode not in ['normal', 'bypass']: | 168 if self.mode not in ['normal', 'bypass']: |
247 # From bypass to * | 237 # From bypass to * |
248 for p in self.participants: | 238 for p in self.participants: |
249 if p.nickname != p.duplicate_nickname: | 239 if p.nickname != p.duplicate_nickname: |
250 p.leave('Bridge is switching to '+new_mode+' mode') | 240 p.leave('Bridge is switching to '+new_mode+' mode') |
251 | 241 |
252 self.say('[Notice] Bridge is switching from '+old_mode+' to '+new_mode+' mode.', log=True) | 242 self.say(say_levels.notice, 'Bridge is switching from '+old_mode+' to '+new_mode+' mode.', log=True) |
253 | 243 |
254 | 244 |
255 def getParticipant(self, nickname): | 245 def getParticipant(self, nickname): |
256 """Returns a participant object if there is a participant using nickname in the bridge. Raises a NoSuchParticipantException otherwise.""" | 246 """Returns a participant object if there is a participant using nickname in the bridge. Raises a NoSuchParticipantException otherwise.""" |
257 self.lock.acquire() | 247 self.lock.acquire() |
326 | 316 |
327 else: | 317 else: |
328 raise Exception('[Internal Error] bad protocol') | 318 raise Exception('[Internal Error] bad protocol') |
329 | 319 |
330 if was_on_both == True: | 320 if was_on_both == True: |
331 self.bot.error('===> Debug: "'+nickname+'" was on both sides of bridge "'+str(self)+'" but left '+left_protocol, debug=True) | 321 self.bot.error(3, '"'+nickname+'" was on both sides of bridge "'+str(self)+'" but left '+left_protocol, debug=True) |
332 | 322 |
333 elif was_on_both == False: | 323 elif was_on_both == False: |
334 self.lock.acquire() | 324 self.lock.acquire() |
335 self.bot.error('===> Debug: removing participant "'+nickname+'" from bridge "'+str(self)+'"', debug=True) | 325 self.bot.error(3, 'removing participant "'+nickname+'" from bridge "'+str(self)+'"', debug=True) |
336 self.participants.remove(p) | 326 self.participants.remove(p) |
337 p.leave(leave_message) | 327 p.leave(leave_message) |
338 del p | 328 del p |
339 self.lock.release() | 329 self.lock.release() |
340 if left_protocol == 'xmpp': | 330 if left_protocol == 'xmpp': |
343 elif left_protocol == 'irc': | 333 elif left_protocol == 'irc': |
344 if self.mode == 'minimal': | 334 if self.mode == 'minimal': |
345 self.show_participants_list_on(protocols=['xmpp']) | 335 self.show_participants_list_on(protocols=['xmpp']) |
346 | 336 |
347 else: | 337 else: |
348 self.bot.error('=> Debug: Bad decision tree, p.protocol='+p.protocol+' left_protocol='+left_protocol+'\np.xmpp_c='+str(p.xmpp_c)+'\np.irc_connection='+str(p.irc_connection), debug=True) | 338 self.bot.error(1, 'Bad decision tree, p.protocol='+p.protocol+' left_protocol='+left_protocol+'\np.xmpp_c='+str(p.xmpp_c)+'\np.irc_connection='+str(p.irc_connection), debug=True) |
349 | 339 |
350 | 340 |
351 def restart(self): | 341 def restart(self): |
352 """Restart the bridge""" | 342 """Restart the bridge""" |
353 | 343 |
354 # Tell admins | 344 # Tell admins |
355 self.bot.error('Restarting bridge '+str(self), send_to_admins=True) | 345 self.bot.error(-1, 'Restarting bridge '+str(self), send_to_admins=True) |
356 | 346 |
357 # Stop the bridge | 347 # Stop the bridge |
358 self.stop(message='Restarting bridge') | 348 self.stop(message='Restarting bridge') |
359 | 349 |
360 # Recreate the bridge | 350 # Recreate the bridge |
361 self.init2() | 351 self.init2() |
362 | 352 |
363 | 353 |
364 def say(self, message, on_irc=True, on_xmpp=True, log=False): | 354 def say(self, importance, message, on_irc=True, on_xmpp=True, log=False, send_to_admins=False): |
365 """Make the bot say something.""" | 355 """Make the bot say something.""" |
366 if message[0] != '[': | 356 message = self.bot.format_message(importance, message) |
367 raise Exception('[Internal Error] message does not start with "["') | 357 if log or send_to_admins: |
368 if log: | 358 self.bot.error(importance, message+' ('+str(self)+')', send_to_admins=send_to_admins) |
369 self.bot.error(message+' ('+str(self)+')') | 359 if importance < self.say_level: |
370 if self.say_level == self.__class__._nothing: | |
371 return | |
372 level = re.findall('^\[(Info|Notice|Warning|Error)\]', message) | |
373 if len(level) == 0: | |
374 raise Exception('[Internal Error] unknown message importance "'+re.findall('^\[([^[\]]+)', message)[0]+'"') | |
375 level = level[0].lower() | |
376 if getattr(self.__class__, '_'+level) < self.say_level: | |
377 return | 360 return |
378 if on_xmpp == True: | 361 if on_xmpp == True: |
379 self.xmpp_room.say(message) | 362 self.xmpp_room.say(message) |
380 if on_irc == True: | 363 if on_irc == True: |
381 self.irc_connection.privmsg(self.irc_room, message) | 364 self.irc_connection.privmsg(self.irc_room, message) |
382 | 365 |
383 | 366 |
384 def show_participants_list_on(self, protocols=[]): | 367 def show_participants_list_on(self, protocols=[]): |
385 if 'irc' in protocols and self.irc_connection.really_connected: | 368 if 'irc' in protocols and self.irc_connection.really_connected: |
386 xmpp_participants_nicknames = self.get_participants_nicknames_list(protocols=['xmpp']) | 369 xmpp_participants_nicknames = self.get_participants_nicknames_list(protocols=['xmpp']) |
387 self.say('[Info] Participants on XMPP: '+' '.join(xmpp_participants_nicknames), on_xmpp=False) | 370 self.say(say_levels.info, 'Participants on XMPP: '+' '.join(xmpp_participants_nicknames), on_xmpp=False) |
388 if 'xmpp' in protocols: | 371 if 'xmpp' in protocols: |
389 irc_participants_nicknames = self.get_participants_nicknames_list(protocols=['irc']) | 372 irc_participants_nicknames = self.get_participants_nicknames_list(protocols=['irc']) |
390 self.say('[Info] Participants on IRC: '+' '.join(irc_participants_nicknames), on_irc=False) | 373 self.say(say_levels.info, 'Participants on IRC: '+' '.join(irc_participants_nicknames), on_irc=False) |
391 | 374 |
392 | 375 |
393 def stop(self, message='Stopping bridge'): | 376 def stop(self, message='Stopping bridge'): |
394 """Stop the bridge""" | 377 """Stop the bridge""" |
395 | 378 |