comparison participant.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 d062efcfbe9d
children 75a03f10a863
comparison
equal deleted inserted replaced
117:d062efcfbe9d 118:b29fd5696a78
20 del muc 20 del muc
21 from irclib import ServerNotConnectedError, ServerConnection 21 from irclib import ServerNotConnectedError, ServerConnection
22 from encoding import * 22 from encoding import *
23 from threading import Thread 23 from threading import Thread
24 from time import sleep 24 from time import sleep
25 import re
25 26
26 27
27 class participant: 28 class participant:
28 def __init__(self, owner_bridge, protocol, nickname, real_jid=None): 29 def __init__(self, owner_bridge, protocol, nickname, real_jid=None):
29 self.bot_admin = False 30 self.bot_admin = False
30 self.real_jid = real_jid 31 self.real_jid = real_jid
31 self.bridge = owner_bridge 32 self.bridge = owner_bridge
32 self.protocol = protocol 33 self.protocol = protocol
33 self.nickname = nickname 34 self.nickname = nickname
35 self.duplicate_nickname = self.nickname
34 self.irc_connection = None 36 self.irc_connection = None
35 self.xmpp_c = None 37 self.xmpp_c = None
36 self.muc = None 38 self.muc = None
37 if protocol == 'xmpp': 39 if protocol == 'xmpp' and self.bridge.mode in ['normal', 'bypass']:
38 self.createDuplicateOnIRC() 40 self.createDuplicateOnIRC()
39 elif protocol == 'irc': 41 elif protocol == 'irc' and self.bridge.mode != 'minimal':
40 self.createDuplicateOnXMPP() 42 self.createDuplicateOnXMPP()
41 else: 43
42 raise Exception('[Internal Error] bad protocol') 44
45 def _get_new_duplicate_nickname(self):
46 new_duplicate_nickname = self.duplicate_nickname
47 for i in xrange(5):
48 new_duplicate_nickname = new_duplicate_nickname+'_'
49 if not self.bridge.hasParticipant(new_duplicate_nickname):
50 return new_duplicate_nickname
51 return None
43 52
44 53
45 def createDuplicateOnXMPP(self): 54 def createDuplicateOnXMPP(self):
46 if isinstance(self.xmpp_c, xmpp.client.Client) or isinstance(self.irc_connection, ServerConnection) or self.bridge.mode == 'minimal' or self.nickname == 'ChanServ': 55 if isinstance(self.xmpp_c, xmpp.client.Client) or isinstance(self.irc_connection, ServerConnection):
47 return 56 return
48 self.xmpp_c = self.bridge.bot.get_xmpp_connection(self.nickname) 57 self.xmpp_c = self.bridge.bot.get_xmpp_connection(self.duplicate_nickname)
49 self.muc = xmpp.muc(self.bridge.xmpp_room_jid) 58 self.muc = xmpp.muc(self.bridge.xmpp_room_jid)
50 self.muc.join(self.xmpp_c, self.nickname, status='From IRC', callback=self._xmpp_join_callback) 59 self.join_muc()
60
61
62 def join_muc(self):
63 self.muc.join(self.xmpp_c, self.duplicate_nickname, status='From IRC', callback=self._xmpp_join_callback)
51 64
52 65
53 def _xmpp_join_callback(self, errors): 66 def _xmpp_join_callback(self, errors):
54 if len(errors) == 0: 67 if len(errors) == 0:
55 self.bridge.bot.error('===> Debug: "'+self.nickname+'" duplicate succesfully created on XMPP side of bridge "'+str(self.bridge)+'"', debug=True) 68 m = '===> Debug: "'+self.nickname+'" duplicate succesfully created on XMPP side of bridge "'+str(self.bridge)+'"'
69 if self.nickname != self.duplicate_nickname:
70 m += ' using nickname "'+self.duplicate_nickname+'"'
71 self.bridge.say('[Info] "'+self.nickname+'" will appear as "'+self.duplicate_nickname+'" on XMPP because its real nickname is reserved or contains unauthorized characters')
72 self.bridge.bot.error(m, debug=True)
56 elif self.xmpp_c != 'both': 73 elif self.xmpp_c != 'both':
57 for error in errors: 74 for error in errors:
58 try: 75 try:
59 raise error 76 raise error
60 except xmpp.muc.NicknameConflict: 77 except xmpp.muc.NicknameConflict as e:
61 self.bridge.bot.error('===> Debug: "'+self.nickname+'" is already used in the XMPP MUC or reserved on the XMPP server of bridge "'+str(self.bridge)+'"', debug=True) 78 if xmpp.protocol.JID(e.args[0]).getResource() != self.duplicate_nickname:
62 self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used on both rooms or reserved on the XMPP server, please avoid that if possible') 79 return
63 if self.muc.connected == True: 80
64 self.muc.leave('Changed nickname to "'+self.nickname+'"') 81 if self.bridge.mode == 'bypass':
82 new_duplicate_nickname = self._get_new_duplicate_nickname()
83 if new_duplicate_nickname != None:
84 self.bridge.bot.error('===> Debug: "'+self.duplicate_nickname+'" is already used in the XMPP MUC or reserved on the XMPP server of bridge "'+str(self.bridge)+'", trying "'+new_duplicate_nickname+'"', debug=True)
85 if self.duplicate_nickname == self.nickname:
86 self.bridge.say('[Info] The nickname "'+self.duplicate_nickname+'" is used on both rooms or reserved on the XMPP server, please avoid that if possible')
87 self.duplicate_nickname = new_duplicate_nickname
88 if isinstance(self.xmpp_c, xmpp.client.Client):
89 self.bridge.bot.close_xmpp_connection(self.nickname)
90 self.xmpp_c = None
91 self.createDuplicateOnXMPP()
92 return
93
94 else:
95 self.bridge.bot.error('===> Debug: "'+self.nickname+'" is already used in the XMPP MUC or reserved on the XMPP server of bridge "'+str(self.bridge)+'"', debug=True)
96 self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used on both rooms or reserved on the XMPP server, please avoid that if possible')
97 if self.muc.connected == True:
98 self.muc.leave('Changed nickname to "'+self.nickname+'"')
65 except xmpp.muc.RoomIsFull: 99 except xmpp.muc.RoomIsFull:
66 self.bridge.bot.error('[Warning] XMPP MUC of bridge "'+str(self.bridge)+'" is full', send_to_admins=True) 100 self.bridge.bot.error('[Warning] XMPP MUC of bridge "'+str(self.bridge)+'" is full', send_to_admins=True)
67 self.bridge.say('[Warning] XMPP room is full') 101 self.bridge.say('[Warning] XMPP room is full')
68 102
69 if isinstance(self.xmpp_c, xmpp.client.Client): 103 if isinstance(self.xmpp_c, xmpp.client.Client):
70 self.bridge.bot.close_xmpp_connection(self.nickname) 104 self.bridge.bot.close_xmpp_connection(self.nickname)
71 self.xmpp_c = None 105 self.xmpp_c = None
72 106
73 107
74 def createDuplicateOnIRC(self): 108 def createDuplicateOnIRC(self):
75 if isinstance(self.xmpp_c, xmpp.client.Client) or isinstance(self.irc_connection, ServerConnection) or self.bridge.mode != 'normal': 109 if isinstance(self.xmpp_c, xmpp.client.Client) or isinstance(self.irc_connection, ServerConnection):
76 return 110 return
77 sleep(1) # try to prevent "reconnecting too fast" shit 111 sleep(1) # try to prevent "reconnecting too fast" shit
78 self.irc_connection = self.bridge.bot.irc.server(self.bridge.irc_server, self.bridge.irc_port, self.nickname) 112 self.irc_connection = self.bridge.bot.irc.server(self.bridge.irc_server, self.bridge.irc_port, self.duplicate_nickname)
79 self.irc_connection.connect(nick_callback=self._irc_nick_callback) 113 self.irc_connection.connect(nick_callback=self._irc_nick_callback)
80 114
81 115
82 def _irc_nick_callback(self, error, arguments=[]): 116 def _irc_nick_callback(self, error, arguments=[]):
83 if error == None: 117 if error == None:
84 self.irc_connection.join(self.bridge.irc_room) 118 self.irc_connection.join(self.bridge.irc_room)
85 self.bridge.bot.error('===> Debug: "'+self.nickname+'" duplicate succesfully created on IRC side of bridge "'+str(self.bridge)+'"', debug=True) 119 m = '===> Debug: "'+self.nickname+'" duplicate succesfully created on IRC side of bridge "'+str(self.bridge)+'"'
120 if self.nickname != self.duplicate_nickname:
121 m += ' using nickname "'+self.duplicate_nickname+'"'
122 self.bridge.say('[Info] "'+self.nickname+'" will appear as "'+self.duplicate_nickname+'" on IRC because its real nickname is reserved or contains unauthorized characters')
123 self.bridge.bot.error(m, debug=True)
124
86 elif self.irc_connection != 'both': 125 elif self.irc_connection != 'both':
87 if error == 'nicknameinuse': 126
88 self.bridge.bot.error('===> Debug: "'+self.nickname+'" is used or reserved on the IRC server of bridge "'+str(self.bridge)+'"', debug=True) 127 if error in ['nicknameinuse', 'nickcollision']:
89 self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used or reserved on the IRC server, please avoid that if possible') 128 if arguments[0].arguments()[0] != self.duplicate_nickname:
90 elif error == 'nickcollision': 129 return
91 self.bridge.bot.error('===> Debug: "'+self.nickname+'" is used or reserved on the IRC server of bridge "'+str(self.bridge)+'"', debug=True) 130
92 self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used or reserved on the IRC server, please avoid that if possible') 131 if self.bridge.mode == 'bypass':
132 new_duplicate_nickname = self._get_new_duplicate_nickname()
133 if new_duplicate_nickname != None:
134 self.bridge.bot.error('===> Debug: "'+self.duplicate_nickname+'" is already used or reserved on the IRC server of bridge "'+str(self.bridge)+'", trying "'+new_duplicate_nickname+'"', debug=True)
135 if self.duplicate_nickname == self.nickname:
136 self.bridge.say('[Info] The nickname "'+self.duplicate_nickname+'" is used or reserved on the IRC server, please avoid that if possible')
137 self.duplicate_nickname = new_duplicate_nickname
138 if isinstance(self.irc_connection, ServerConnection):
139 self.irc_connection.close('')
140 self.irc_connection = error
141 self.createDuplicateOnIRC()
142 return
143
144 else:
145 self.bridge.bot.error('===> Debug: "'+self.nickname+'" is used or reserved on the IRC server of bridge "'+str(self.bridge)+'"', debug=True)
146 self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used or reserved on the IRC server, please avoid that if possible')
147
93 elif error == 'erroneusnickname': 148 elif error == 'erroneusnickname':
94 self.bridge.bot.error('===> Debug: "'+self.nickname+'" got "erroneusnickname" on bridge "'+str(self.bridge)+'"', debug=True) 149 if self.bridge.mode == 'bypass':
95 self.bridge.say('[Warning] The nickname "'+self.nickname+'" contains unauthorized characters and cannot be used in the IRC channel, please avoid that if possible') 150 self.duplicate_nickname = re.sub('[^a-zA-Z]', '', self.nickname)
151 if isinstance(self.irc_connection, ServerConnection):
152 self.irc_connection.close('')
153 self.irc_connection = error
154 self.createDuplicateOnIRC()
155 return
156 else:
157 self.bridge.bot.error('===> Debug: "'+self.nickname+'" got "erroneusnickname" on bridge "'+str(self.bridge)+'"', debug=True)
158 self.bridge.say('[Warning] The nickname "'+self.nickname+'" contains unauthorized characters and cannot be used in the IRC channel, please avoid that if possible')
159
96 elif error == 'nicknametoolong': 160 elif error == 'nicknametoolong':
97 self.bridge.bot.error('===> Debug: "'+self.nickname+'" got "nicknametoolong" on bridge "'+str(self.bridge)+'"', debug=True) 161 self.bridge.bot.error('===> Debug: "'+self.nickname+'" got "nicknametoolong" on bridge "'+str(self.bridge)+'"', debug=True)
98 self.bridge.say('[Warning] The nickname "'+self.nickname+'" is too long (limit seems to be '+str(arguments[0])+') and cannot be used in the IRC channel, please avoid that if possible') 162 self.bridge.say('[Warning] The nickname "'+self.nickname+'" is too long (limit seems to be '+str(arguments[0])+') and cannot be used in the IRC channel, please avoid that if possible')
163
99 else: 164 else:
100 self.bridge.bot.error('===> Debug: unknown error while adding "'+self.nickname+'" to IRC side of bridge "'+str(self.bridge)+'"', debug=True) 165 self.bridge.bot.error('===> Debug: unknown error while adding "'+self.nickname+'" to IRC side of bridge "'+str(self.bridge)+'"', debug=True)
101 self.bridge.say('[Warning] unknown error while adding "'+self.nickname+'" to IRC side of bridge') 166 self.bridge.say('[Warning] unknown error while adding "'+self.nickname+'" to IRC side of bridge')
102 167
103 if isinstance(self.irc_connection, ServerConnection): 168 if isinstance(self.irc_connection, ServerConnection):
115 self._close_irc_connection('unwanted nick change') 180 self._close_irc_connection('unwanted nick change')
116 self.irc_connection = 'unwanted nick change' 181 self.irc_connection = 'unwanted nick change'
117 182
118 else: 183 else:
119 self.nickname = newnick 184 self.nickname = newnick
185 self.duplicate_nickname = newnick
120 if isinstance(self.irc_connection, ServerConnection): 186 if isinstance(self.irc_connection, ServerConnection):
121 if self.irc_connection.used_by == 1: 187 if self.irc_connection.used_by == 1:
122 self.irc_connection.nick(newnick, callback=self._irc_nick_callback) 188 self.irc_connection.nick(newnick, callback=self._irc_nick_callback)
123 else: 189 else:
124 self._close_irc_connection('Changed nickname') 190 self._close_irc_connection('Changed nickname')
133 self._close_xmpp_connection('unwanted nick change') 199 self._close_xmpp_connection('unwanted nick change')
134 self.xmpp_c = 'unwanted nick change' 200 self.xmpp_c = 'unwanted nick change'
135 201
136 else: 202 else:
137 self.nickname = newnick 203 self.nickname = newnick
204 self.duplicate_nickname = newnick
138 if isinstance(self.xmpp_c, xmpp.client.Client): 205 if isinstance(self.xmpp_c, xmpp.client.Client):
139 for b in self.bridge.bot.bridges: 206 for b in self.bridge.bot.bridges:
140 if b.hasParticipant(oldnick) and b.irc_server != self.bridge.irc_server: 207 if b.hasParticipant(oldnick) and b.irc_server != self.bridge.irc_server:
141 self.muc.leave(message='Changed nickname to "'+self.nickname+'"') 208 self.muc.leave(message='Changed nickname to "'+self.nickname+'"')
142 self.xmpp_c = None 209 self.xmpp_c = None
225 def leave(self, message): 292 def leave(self, message):
226 if message == None: 293 if message == None:
227 message = '' 294 message = ''
228 self._close_xmpp_connection(message) 295 self._close_xmpp_connection(message)
229 self._close_irc_connection(message) 296 self._close_irc_connection(message)
230 self.nickname = None
231 297
232 298
233 def _close_xmpp_connection(self, message): 299 def _close_xmpp_connection(self, message):
234 if isinstance(self.xmpp_c, xmpp.client.Client): 300 if isinstance(self.xmpp_c, xmpp.client.Client):
235 self.muc.leave(auto_decode(message)) 301 self.muc.leave(auto_decode(message))
254 r += '\nself.muc.connected='+str(self.muc.connected) 320 r += '\nself.muc.connected='+str(self.muc.connected)
255 return r 321 return r
256 322
257 323
258 def __del__(self): 324 def __del__(self):
259 if self.nickname != None: 325 self.leave('')
260 self.leave('')