comparison bridge.py @ 118:b29fd5696a78

new mode bypass and new method bridge.changeMode Signed-off-by: Charly COSTE <changaco@changaco.net>
author Charly COSTE <changaco@changaco.net>
date Sat, 28 Nov 2009 23:47:11 +0100
parents 0ae0f8836a7a
children de00bbe026a7
comparison
equal deleted inserted replaced
117:d062efcfbe9d 118:b29fd5696a78
36 _notice = 2 36 _notice = 2
37 _warning = 3 37 _warning = 3
38 _error = 4 38 _error = 4
39 _nothing = 5 39 _nothing = 5
40 _say_levels = ['all', 'info', 'notice', 'warning', 'error', 'nothing'] 40 _say_levels = ['all', 'info', 'notice', 'warning', 'error', 'nothing']
41 _modes = ['normal', 'limited', 'minimal'] 41 _modes = ['normal', 'bypass', 'limited', 'minimal']
42 42
43 43
44 def __init__(self, owner_bot, xmpp_room_jid, irc_room, irc_server, mode, say_level, irc_port=6667): 44 def __init__(self, owner_bot, xmpp_room_jid, irc_room, irc_server, mode, say_level, irc_port=6667):
45 """Create a new bridge.""" 45 """Create a new bridge."""
46 self.bot = owner_bot 46 self.bot = owner_bot
142 p = self.getParticipant(nickname) 142 p = self.getParticipant(nickname)
143 if p.protocol != from_protocol: 143 if p.protocol != from_protocol:
144 if from_protocol == 'irc' and isinstance(p.irc_connection, ServerConnection) and p.irc_connection.really_connected == True or from_protocol == 'xmpp' and isinstance(p.xmpp_c, xmpp.client.Client) and isinstance(p.muc, xmpp.muc): 144 if from_protocol == 'irc' and isinstance(p.irc_connection, ServerConnection) and p.irc_connection.really_connected == True or from_protocol == 'xmpp' and isinstance(p.xmpp_c, xmpp.client.Client) and isinstance(p.muc, xmpp.muc):
145 if irc_id: 145 if irc_id:
146 p.irc_connection.irc_id = irc_id 146 p.irc_connection.irc_id = irc_id
147 return 147 return p
148 self.bot.error('===> Debug: "'+nickname+'" is on both sides of bridge "'+str(self)+'"', debug=True) 148 self.bot.error('===> Debug: "'+nickname+'" is on both sides of bridge "'+str(self)+'"', debug=True)
149 self.say('[Warning] The nickname "'+nickname+'" is used on both sides of the bridge, please avoid that if possible') 149 self.say('[Warning] The nickname "'+nickname+'" is used on both sides of the bridge, please avoid that if possible')
150 if isinstance(p.irc_connection, ServerConnection): 150 if isinstance(p.irc_connection, ServerConnection):
151 p.irc_connection.close('') 151 p.irc_connection.close('')
152 if p.irc_connection != 'both': 152 if p.irc_connection != 'both':
157 if p.xmpp_c != 'both': 157 if p.xmpp_c != 'both':
158 p.xmpp_c = 'both' 158 p.xmpp_c = 'both'
159 return p 159 return p
160 except NoSuchParticipantException: 160 except NoSuchParticipantException:
161 pass 161 pass
162
163 if nickname == 'ChanServ' and from_protocol == 'irc':
164 return
165
162 self.lock.acquire() 166 self.lock.acquire()
163 self.bot.error('===> Debug: adding participant "'+nickname+'" from "'+from_protocol+'" to bridge "'+str(self)+'"', debug=True) 167 self.bot.error('===> Debug: adding participant "'+nickname+'" from "'+from_protocol+'" to bridge "'+str(self)+'"', debug=True)
164 try: 168 try:
165 p = participant(self, from_protocol, nickname, real_jid=real_jid) 169 p = participant(self, from_protocol, nickname, real_jid=real_jid)
166 except IOError: 170 except IOError:
170 self.bot.error('===> Debug: unknown error while adding participant "'+nickname+'" from "'+from_protocol+'" to bridge "'+str(self)+'"', debug=True) 174 self.bot.error('===> Debug: unknown error while adding participant "'+nickname+'" from "'+from_protocol+'" to bridge "'+str(self)+'"', debug=True)
171 traceback.print_exc() 175 traceback.print_exc()
172 return 176 return
173 self.participants.append(p) 177 self.participants.append(p)
174 self.lock.release() 178 self.lock.release()
175 if self.mode != 'normal': 179 if self.mode not in ['normal', 'bypass']:
176 if from_protocol == 'xmpp': 180 if from_protocol == 'xmpp':
177 xmpp_participants_nicknames = self.get_participants_nicknames_list(protocols=['xmpp']) 181 xmpp_participants_nicknames = self.get_participants_nicknames_list(protocols=['xmpp'])
178 self.say('[Info] Participants on XMPP: '+' '.join(xmpp_participants_nicknames), on_xmpp=False) 182 self.say('[Info] Participants on XMPP: '+' '.join(xmpp_participants_nicknames), on_xmpp=False)
179 elif self.mode == 'minimal' and from_protocol == 'irc': 183 elif self.mode == 'minimal' and from_protocol == 'irc':
180 irc_participants_nicknames = self.get_participants_nicknames_list(protocols=['irc']) 184 irc_participants_nicknames = self.get_participants_nicknames_list(protocols=['irc'])
181 self.say('[Info] Participants on IRC: '+' '.join(irc_participants_nicknames), on_irc=False) 185 self.say('[Info] Participants on IRC: '+' '.join(irc_participants_nicknames), on_irc=False)
182 return p 186 return p
183 187
184 188
189 def changeMode(self, new_mode):
190 if new_mode == self.mode:
191 return 'Mode is already equal to '+self.mode
192
193 unhandled = 'Error: unhandled mode changing from '+self.mode+' to '+new_mode
194
195 if new_mode in ['normal', 'bypass']:
196
197 if self.mode[-7:] == 'limited':
198 # From [{normal,bypass}-]limited to {normal,bypass}
199 pass # duplicates of XMPP users are created below
200
201 elif self.mode == 'minimal':
202 # From minimal to {normal,bypass}
203 # create duplicates of IRC users, duplicates of XMPP users are created below
204 for p in self.participants:
205 if p.protocol == 'irc':
206 p.createDuplicateOnXMPP()
207
208 else:
209 # Unhandled mode changing
210 return unhandled
211
212 # create duplicates of XMPP users
213 for p in self.participants:
214 if p.protocol == 'xmpp':
215 p.createDuplicateOnIRC()
216
217 elif new_mode[-7:] == 'limited':
218
219 i = 0
220 for p in self.participants:
221 if p.protocol == 'xmpp':
222 i += 1
223 p._close_irc_connection('Bridge is switching to limited mode')
224
225 if new_mode[-8:] == '-limited':
226 # to {normal,bypass}-limited
227 self.irc_connections_limit = i
228 self.bot.error('===> Bridge is switching to limited mode. Limit seems to be '+str(self.irc_connections_limit)+' on "'+self.irc_server+'".')
229 self.say('[Warning] Bridge is switching to limited mode, it means that it will be transparent for XMPP users but not for IRC users, this is due to the IRC servers\' per-IP-address connections\' limit number which seems to be '+str(self.irc_connections_limit)+' on "'+self.irc_server+'".')
230 xmpp_participants_nicknames = self.get_participants_nicknames_list(protocols=['xmpp'])
231 self.say('[Info] Participants on XMPP: '+' '.join(xmpp_participants_nicknames), on_xmpp=False)
232 return
233
234 elif new_mode == 'minimal':
235 for p in self.participants:
236 p.leave('Bridge is switching to limited mode')
237
238 else:
239 # Unhandled mode changing
240 return unhandled
241
242 self.mode = new_mode
243 self.bot.error('===> Bridge is switching from '+self.mode+' to '+new_mode+' mode.')
244 self.say('[Notice] Bridge is switching from '+self.mode+' to '+new_mode+' mode.')
245
246
185 def getParticipant(self, nickname): 247 def getParticipant(self, nickname):
186 """Returns a participant object if there is a participant using nickname in the bridge. Raises a NoSuchParticipantException otherwise.""" 248 """Returns a participant object if there is a participant using nickname in the bridge. Raises a NoSuchParticipantException otherwise."""
187 self.lock.acquire() 249 self.lock.acquire()
188 for participant_ in self.participants: 250 for p in self.participants:
189 if participant_.nickname == nickname: 251 if nickname in [p.nickname, p.duplicate_nickname]:
190 self.lock.release() 252 self.lock.release()
191 return participant_ 253 return p
192 self.lock.release() 254 self.lock.release()
193 raise NoSuchParticipantException('there is no participant using the nickname "'+nickname+'" in this bridge') 255 raise NoSuchParticipantException('there is no participant using the nickname "'+nickname+'" in this bridge')
194 256
195 257
196 def get_participants_nicknames_list(self, protocols=['irc', 'xmpp']): 258 def get_participants_nicknames_list(self, protocols=['irc', 'xmpp']):
266 del p 328 del p
267 self.lock.release() 329 self.lock.release()
268 if left_protocol == 'xmpp': 330 if left_protocol == 'xmpp':
269 xmpp_participants_nicknames = self.get_participants_nicknames_list(protocols=['xmpp']) 331 xmpp_participants_nicknames = self.get_participants_nicknames_list(protocols=['xmpp'])
270 if self.irc_connections_limit != -1 and self.irc_connections_limit > len(xmpp_participants_nicknames): 332 if self.irc_connections_limit != -1 and self.irc_connections_limit > len(xmpp_participants_nicknames):
271 self.switchFromLimitedToNormalMode() 333 self.changeMode(self.mode[:-8])
272 if self.mode != 'normal': 334 if self.mode not in ['normal', 'bypass']:
273 self.say('[Info] Participants on XMPP: '+' '.join(xmpp_participants_nicknames), on_xmpp=False) 335 self.say('[Info] Participants on XMPP: '+' '.join(xmpp_participants_nicknames), on_xmpp=False)
274 elif left_protocol == 'irc': 336 elif left_protocol == 'irc':
275 if self.mode == 'minimal': 337 if self.mode == 'minimal':
276 irc_participants_nicknames = self.get_participants_nicknames_list(protocols=['irc']) 338 irc_participants_nicknames = self.get_participants_nicknames_list(protocols=['irc'])
277 self.say('[Info] Participants on IRC: '+' '.join(irc_participants_nicknames), on_irc=False) 339 self.say('[Info] Participants on IRC: '+' '.join(irc_participants_nicknames), on_irc=False)
334 p.leave(message) 396 p.leave(message)
335 del p 397 del p
336 self.participants = [] 398 self.participants = []
337 399
338 400
339 def switchFromLimitedToNormalMode(self):
340 if self.mode != 'normal-limited':
341 return
342 self.bot.error('===> Bridge is switching to normal mode.')
343 self.say('[Notice] Bridge is switching to normal mode.')
344 self.mode = 'normal'
345 for p in self.participants:
346 if p.protocol == 'xmpp':
347 p.createDuplicateOnIRC()
348
349
350 def switchFromNormalToLimitedMode(self):
351 if self.mode != 'normal':
352 return
353 self.mode = 'normal-limited'
354 i = 0
355 for p in self.participants:
356 if p.protocol == 'xmpp':
357 i += 1
358 if isinstance(self.irc_connection, ServerConnection):
359 p.irc_connection.close('Bridge is switching to limited mode')
360 p.irc_connection = None
361 self.irc_connections_limit = i
362 self.bot.error('===> Bridge is switching to limited mode. Limit seems to be '+str(self.irc_connections_limit)+' on "'+self.irc_server+'".')
363 self.say('[Warning] Bridge is switching to limited mode, it means that it will be transparent for XMPP users but not for IRC users, this is due to the IRC servers\' per-IP-address connections\' limit number which seems to be '+str(self.irc_connections_limit)+' on "'+self.irc_server+'".')
364 xmpp_participants_nicknames = self.get_participants_nicknames_list(protocols=['xmpp'])
365 self.say('[Info] Participants on XMPP: '+' '.join(xmpp_participants_nicknames), on_xmpp=False)
366
367
368 def __str__(self): 401 def __str__(self):
369 return self.irc_room+'@'+self.irc_server+' <-> '+self.xmpp_room_jid 402 return self.irc_room+'@'+self.irc_server+' <-> '+self.xmpp_room_jid
370 403
371 404
372 def __del__(self): 405 def __del__(self):