comparison participant.py @ 0:4c842d23d4ce

Initial commit, version 0.1 Signed-off-by: Charly COSTE <changaco@changaco.net>
author Charly COSTE <changaco@changaco.net>
date Sun, 16 Aug 2009 01:47:03 +0200
parents
children 3f651f4fdb4f
comparison
equal deleted inserted replaced
-1:000000000000 0:4c842d23d4ce
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16
17
18 import muc
19 xmpp = muc.xmpp
20 del muc
21 import irclib
22 from encoding import *
23 from threading import Thread
24 from time import sleep
25
26
27 class participant:
28 def __init__(self, owner_bridge, protocol, nickname):
29 self.bridge = owner_bridge
30 self.protocol = protocol
31 self.nickname = nickname
32 self.irc_connection = None
33 self.xmpp_c = None
34 if protocol == 'xmpp':
35 self.createDuplicateOnIRC()
36 elif protocol == 'irc':
37 self.createDuplicateOnXMPP()
38 else:
39 raise Exception('Internal Error: bad protocol')
40 quit(1)
41
42
43 def createDuplicateOnXMPP(self):
44 if self.xmpp_c != None or self.irc_connection != None or self.protocol == 'both' or self.bridge.mode == 'minimal':
45 return
46 self.xmpp_c = xmpp.client.Client(self.bridge.bot.jid.getDomain(), debug=[])
47 self.xmpp_c.connect()
48 self.xmpp_c.auth(self.bridge.bot.jid.getNode(), self.bridge.bot.password, resource=self.nickname)
49 self.xmpp_c.RegisterHandler('presence', self.bridge.bot._xmpp_presence_handler)
50 self.xmpp_c.RegisterHandler('iq', self.bridge.bot._xmpp_iq_handler)
51 self.xmpp_c.RegisterHandler('message', self.bridge.bot._xmpp_message_handler)
52 self.xmpp_thread = Thread(target=self._xmpp_loop)
53 self.xmpp_thread.start()
54 self.xmpp_c.sendInitPresence()
55 self.muc = xmpp.muc(self.bridge.xmpp_room.room_jid)
56 self.muc.join(self.xmpp_c, self.nickname, status='From IRC', callback=self._xmpp_join_callback)
57
58
59 def createDuplicateOnIRC(self):
60 if self.irc_connection != None or self.xmpp_c != None or self.protocol == 'both' or self.bridge.mode != 'normal':
61 return
62 sleep(1) # try to prevent "reconnecting too fast" shit
63 self.irc_connection = self.bridge.bot.irc.server()
64 self.irc_connection.bridge = self.bridge
65 self.irc_connection.nick_callback = self._irc_nick_callback
66 self.irc_connection.connect(self.bridge.irc_server, self.bridge.irc_port, self.nickname)
67
68
69 def _irc_nick_callback(self, error):
70 if error == None:
71 self.irc_connection.join(self.bridge.irc_room)
72 self.irc_connection.nick_callback = None
73 self.bridge.bot.error('===> Debug: "'+self.nickname+'" duplicate succesfully created on IRC side of bridge "'+str(self.bridge)+'"', debug=True)
74 elif self.protocol != 'both':
75 if error == 'nicknameinuse':
76 self.bridge.bot.error('===> Debug: "'+self.nickname+'" is already used in the IRC chan of bridge "'+str(self.bridge)+'"', debug=True)
77 self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used on both rooms, please avoid that if possible')
78 self.protocol = 'both'
79 self.irc_connection.close()
80 self.irc_connection = None
81 elif error == 'erroneusnickname':
82 self.bridge.bot.error('===> Debug: "'+self.nickname+'" got "erroneusnickname" on bridge "'+str(self.bridge)+'"', debug=True)
83 self.bridge.say('[Warning] The nickname "'+self.nickname+'" contains non-ASCII characters and cannot be used in the IRC channel, please avoid that if possible')
84 self.irc_connection.close()
85 self.irc_connection = None
86
87
88 def _xmpp_join_callback(self, errors):
89 if len(errors) == 0:
90 self.bridge.bot.error('===> Debug: "'+self.nickname+'" duplicate succesfully created on XMPP side of bridge "'+str(self.bridge)+'"', debug=True)
91 elif self.protocol != 'both':
92 for error in errors:
93 try:
94 raise error
95 except xmpp.muc.NicknameConflict:
96 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)
97 self.bridge.say('[Warning] The nickname "'+self.nickname+'" is used on both rooms or reserved on the XMPP server, please avoid that if possible')
98 self.protocol = 'both'
99 self.xmpp_c = None
100
101
102 def _xmpp_loop(self):
103 while True:
104 if self.xmpp_c != None:
105 self.xmpp_c.Process(5)
106 else:
107 sleep(5)
108
109
110 def changeNickname(self, newnick, on_protocol):
111 if self.protocol == 'xmpp':
112 if on_protocol == 'xmpp':
113 raise Exception('Internal Error: wanted to change nickname on bad protocol')
114 if self.irc_connection:
115 self.irc_connection.nick(newnick)
116 self.nickname = newnick
117 elif self.protocol == 'irc':
118 if on_protocol == 'irc':
119 raise Exception('Internal Error: wanted to change nickname on bad protocol')
120 if self.muc:
121 self.muc.change_nick(newnick, callback=self._xmpp_join_callback)
122 self.nickname = newnick
123 elif self.protocol == 'both':
124 if on_protocol == 'irc':
125 self.protocol = 'xmpp'
126 self.createDuplicateOnIRC()
127 elif on_protocol == 'xmpp':
128 self.protocol = 'irc'
129 self.createDuplicateOnXMPP()
130
131
132 def sayOnIRC(self, message):
133 try:
134 if self.protocol == 'irc':
135 raise Exception('Internal Error: "'+self.nickname+'" comes from IRC')
136 elif self.protocol == 'both' or self.irc_connection == None:
137 self.bridge.irc_connection.privmsg(self.bridge.irc_room, '<'+self.nickname+'> '+message)
138 else:
139 self.irc_connection.privmsg(self.bridge.irc_room, message)
140 except EncodingException:
141 self.bridge.say('[Warning] "'+self.nickname+'" is sending messages using an unknown encoding')
142
143
144 def sayOnIRCTo(self, to, message):
145 if self.protocol == 'irc':
146 raise Exception('Internal Error: "'+self.nickname+'" comes from IRC')
147 elif self.irc_connection == None:
148 if self.bridge.mode != 'normal':
149 self.bridge.getParticipant(to).sayOnXMPPTo(self.nickname, 'Sorry but cross-protocol private messages are disabled in limited mode.')
150 else:
151 self.bridge.getParticipant(to).sayOnXMPPTo(self.nickname, 'Sorry but you cannot send cross-protocol private messages because I don\'t have an IRC duplicate with your nickname.')
152 else:
153 try:
154 self.irc_connection.privmsg(to, message)
155 except EncodingException:
156 self.bridge.say('[Warning] "'+self.nickname+'" is sending messages using an unknown encoding')
157
158
159 def sayOnXMPP(self, message):
160 if self.protocol == 'xmpp':
161 raise Exception('Internal Error: "'+self.nickname+'" comes from XMPP')
162 elif self.protocol == 'both' or self.xmpp_c == None:
163 self.bridge.xmpp_room.say('<'+self.nickname+'> '+auto_decode(message))
164 else:
165 try:
166 self.muc.say(auto_decode(message))
167 except EncodingException:
168 self.bridge.say('[Warning] "'+self.nickname+'" is sending messages using an unknown encoding')
169
170
171 def sayOnXMPPTo(self, to, message):
172 if self.protocol == 'xmpp':
173 raise Exception('Internal Error: "'+self.nickname+'" comes from XMPP')
174 else:
175 try:
176 self.muc.sayTo(to, auto_decode(message))
177 except EncodingException:
178 self.bridge.say('[Warning] "'+self.nickname+'" is sending messages using an unknown encoding')
179
180
181 def leave(self, message):
182 if message == None:
183 message = ''
184 try:
185 self.muc.leave(message)
186 except AttributeError:
187 pass
188 try:
189 self.irc_connection.disconnect(message)
190 except AttributeError:
191 pass
192 self.nickname = None
193
194
195 def __del__(self):
196 if self.nickname != None:
197 self.leave('')