Mercurial > libervia-backend
comparison sat.tac @ 50:daa1f01a5332
SàT improvement:
- subscription & presence refactoring
- multilingual statuses are now correctly sent
- registration: error condition now specified in error message
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 07 Jan 2010 00:05:15 +1100 |
parents | d24629c631fc |
children | 6455fb62ff83 |
comparison
equal
deleted
inserted
replaced
49:9c79eb49d51f | 50:daa1f01a5332 |
---|---|
68 sat_id+=1 | 68 sat_id+=1 |
69 return "sat_id_"+str(sat_id) | 69 return "sat_id_"+str(sat_id) |
70 | 70 |
71 class SatXMPPClient(client.XMPPClient): | 71 class SatXMPPClient(client.XMPPClient): |
72 | 72 |
73 def __init__(self, jid, password, host=None, port=5222): | 73 def __init__(self, user_jid, password, host=None, port=5222): |
74 client.XMPPClient.__init__(self, jid, password, host, port) | 74 client.XMPPClient.__init__(self, user_jid, password, host, port) |
75 self.factory.clientConnectionLost = self.connectionLost | 75 self.factory.clientConnectionLost = self.connectionLost |
76 self.__connected=False | 76 self.__connected=False |
77 | 77 |
78 def _authd(self, xmlstream): | 78 def _authd(self, xmlstream): |
79 print "SatXMPPClient" | 79 print "SatXMPPClient" |
118 def __init__(self, host): | 118 def __init__(self, host): |
119 xmppim.RosterClientProtocol.__init__(self) | 119 xmppim.RosterClientProtocol.__init__(self) |
120 self.host = host | 120 self.host = host |
121 | 121 |
122 def rosterCb(self, roster): | 122 def rosterCb(self, roster): |
123 for jid, item in roster.iteritems(): | 123 for raw_jid, item in roster.iteritems(): |
124 info ("new contact in roster list: %s", jid) | 124 self.onRosterSet(item) |
125 #FIXME: fill attributes | |
126 self.host.memory.addContact(jid, {}, item.groups) | |
127 self.host.bridge.newContact(jid, {}, item.groups) | |
128 | 125 |
129 def requestRoster(self): | 126 def requestRoster(self): |
130 """ ask the server for Roster list """ | 127 """ ask the server for Roster list """ |
131 debug("requestRoster") | 128 debug("requestRoster") |
132 self.getRoster().addCallback(self.rosterCb) | 129 self.getRoster().addCallback(self.rosterCb) |
133 | 130 |
134 def removeItem(self, to): | 131 def removeItem(self, to): |
135 """Remove a contact from roster list""" | 132 """Remove a contact from roster list""" |
136 to_jid=jid.JID(to) | 133 xmppim.RosterClientProtocol.removeItem(self, to) |
137 xmppim.RosterClientProtocol.removeItem(self, to_jid) | |
138 #TODO: check IQ result | 134 #TODO: check IQ result |
139 | 135 |
140 def addItem(self, to): | 136 def addItem(self, to): |
141 """Add a contact to roster list""" | 137 """Add a contact to roster list""" |
142 to_jid=jid.JID(to) | 138 xmppim.RosterClientProtocol.addItem(self, to) |
143 xmppim.RosterClientProtocol.addItem(self, to_jid) | |
144 #TODO: check IQ result | 139 #TODO: check IQ result |
140 | |
141 def onRosterSet(self, item): | |
142 """Called when a new/update roster item is received""" | |
143 #TODO: send a signal to frontends | |
144 item_attr = {'to': str(item.subscriptionTo), | |
145 'from': str(item.subscriptionFrom), | |
146 'ask': str(item.ask) | |
147 } | |
148 if item.name: | |
149 item_attr['name'] = item.name | |
150 info ("new contact in roster list: %s", item.jid.full()) | |
151 self.host.memory.addContact(item.jid, item_attr, item.groups) | |
152 self.host.bridge.newContact(item.jid.full(), item_attr, item.groups) | |
153 | |
154 def onRosterRemove(self, entity): | |
155 """Called when a roster removal event is received""" | |
156 #TODO: send a signal to frontends | |
157 print "removing %s from roster list" % entity.full() | |
158 self.host.memory.delContact(entity) | |
145 | 159 |
146 class SatPresenceProtocol(xmppim.PresenceClientProtocol): | 160 class SatPresenceProtocol(xmppim.PresenceClientProtocol): |
147 | 161 |
148 def __init__(self, host): | 162 def __init__(self, host): |
149 xmppim.PresenceClientProtocol.__init__(self) | 163 xmppim.PresenceClientProtocol.__init__(self) |
150 self.host = host | 164 self.host = host |
151 | 165 |
152 def availableReceived(self, entity, show=None, statuses=None, priority=0): | 166 def availableReceived(self, entity, show=None, statuses=None, priority=0): |
153 info ("presence update for [%s]", entity) | 167 info ("presence update for [%s]", entity) |
154 | 168 |
155 ### we check if the status is not about subscription ### | 169 if statuses.has_key(None): #we only want string keys |
156 #FIXME: type is not needed anymore | 170 statuses["default"] = statuses[None] |
157 #TODO: management of differents statuses (differents languages) | 171 del statuses[None] |
158 status = statuses.values()[0] if len(statuses) else "" | 172 |
159 self.host.memory.addPresenceStatus(entity.full(), "", show or "", | 173 self.host.memory.addPresenceStatus(entity, show or "", |
160 status or "", int(priority)) | 174 int(priority), statuses) |
161 | 175 |
162 #now it's time to notify frontends | 176 #now it's time to notify frontends |
163 self.host.bridge.presenceUpdate(entity.full(), "", show or "", | 177 self.host.bridge.presenceUpdate(entity.full(), show or "", |
164 status or "", int(priority)) | 178 int(priority), statuses) |
165 | 179 |
166 def unavailableReceived(self, entity, statuses=None): | 180 def unavailableReceived(self, entity, statuses=None): |
167 #TODO: management of differents statuses (differents languages) | 181 if statuses and statuses.has_key(None): #we only want string keys |
168 status = statuses.values()[0] if len(statuses) else "" | 182 statuses["default"] = statuses[None] |
169 self.host.memory.addPresenceStatus(entity.full(), "unavailable", "", | 183 del statuses[None] |
170 status or "", 0) | 184 self.host.memory.addPresenceStatus(entity, "unavailable", 0, statuses) |
171 | 185 |
172 #now it's time to notify frontends | 186 #now it's time to notify frontends |
173 self.host.bridge.presenceUpdate(entity.full(), "unavailable", "", | 187 self.host.bridge.presenceUpdate(entity.full(), "unavailable", 0, statuses) |
174 status or "", 0) | 188 |
175 | 189 |
176 | 190 def available(self, entity=None, show=None, statuses=None, priority=0): |
191 if statuses and statuses.has_key('default'): | |
192 statuses[None] = statuses['default'] | |
193 del statuses['default'] | |
194 xmppim.PresenceClientProtocol.available(self, entity, show, statuses, priority) | |
195 | |
177 def subscribedReceived(self, entity): | 196 def subscribedReceived(self, entity): |
178 debug ("subscription approved for [%s]" % entity) | 197 debug ("subscription approved for [%s]" % entity.userhost()) |
198 self.host.memory.delWaitingSub(entity.userhost()) | |
199 self.host.bridge.subscribe('subscribed', entity.userhost()) | |
179 | 200 |
180 def unsubscribedReceived(self, entity): | 201 def unsubscribedReceived(self, entity): |
181 debug ("unsubscription confirmed for [%s]" % entity) | 202 debug ("unsubscription confirmed for [%s]" % entity.userhost()) |
203 self.host.memory.delWaitingSub(entity.userhost()) | |
204 self.host.bridge.subscribe('unsubscribed', entity.userhost()) | |
182 | 205 |
183 def subscribeReceived(self, entity): | 206 def subscribeReceived(self, entity): |
184 #FIXME: auto answer for subscribe request, must be checked ! | 207 debug ("subscription request for [%s]" % entity.userhost()) |
185 debug ("subscription request for [%s]" % entity) | 208 self.host.memory.addWaitingSub('subscribe', entity.userhost()) |
186 self.subscribed(entity) | 209 self.host.bridge.subscribe('subscribe', entity.userhost()) |
187 | 210 |
188 def unsubscribeReceived(self, entity): | 211 def unsubscribeReceived(self, entity): |
189 debug ("unsubscription asked for [%s]" % entity) | 212 debug ("unsubscription asked for [%s]" % entity.userhost()) |
213 self.host.memory.addWaitingSub('unsubscribe', entity.userhost()) | |
214 self.host.bridge.subscribe('unsubscribe', entity.userhost()) | |
190 | 215 |
191 class SatDiscoProtocol(disco.DiscoClientProtocol): | 216 class SatDiscoProtocol(disco.DiscoClientProtocol): |
192 def __init__(self, host): | 217 def __init__(self, host): |
193 disco.DiscoClientProtocol.__init__(self) | 218 disco.DiscoClientProtocol.__init__(self) |
194 | 219 |
241 if failure.value.condition == 'conflict': | 266 if failure.value.condition == 'conflict': |
242 answer_data['reason'] = 'conflict' | 267 answer_data['reason'] = 'conflict' |
243 answer_data={"message":"Username already exists, please choose an other one"} | 268 answer_data={"message":"Username already exists, please choose an other one"} |
244 else: | 269 else: |
245 answer_data['reason'] = 'unknown' | 270 answer_data['reason'] = 'unknown' |
246 answer_data={"message":"Registration failed"} | 271 answer_data={"message":"Registration failed (%s)" % str(failure.value.condition)} |
247 self.host.bridge.actionResult(answer_type, self.answer_id, answer_data) | 272 self.host.bridge.actionResult(answer_type, self.answer_id, answer_data) |
248 self.xmlstream.sendFooter() | 273 self.xmlstream.sendFooter() |
249 | 274 |
250 | 275 |
251 class SAT(service.Service): | 276 class SAT(service.Service): |
287 self.bridge.register("registerNewAccount", self.registerNewAccount) | 312 self.bridge.register("registerNewAccount", self.registerNewAccount) |
288 self.bridge.register("connect", self.connect) | 313 self.bridge.register("connect", self.connect) |
289 self.bridge.register("disconnect", self.disconnect) | 314 self.bridge.register("disconnect", self.disconnect) |
290 self.bridge.register("getContacts", self.memory.getContacts) | 315 self.bridge.register("getContacts", self.memory.getContacts) |
291 self.bridge.register("getPresenceStatus", self.memory.getPresenceStatus) | 316 self.bridge.register("getPresenceStatus", self.memory.getPresenceStatus) |
317 self.bridge.register("getWaitingSub", self.memory.getWaitingSub) | |
292 self.bridge.register("sendMessage", self.sendMessage) | 318 self.bridge.register("sendMessage", self.sendMessage) |
293 self.bridge.register("setParam", self.setParam) | 319 self.bridge.register("setParam", self.setParam) |
294 self.bridge.register("getParamA", self.memory.getParamA) | 320 self.bridge.register("getParamA", self.memory.getParamA) |
295 self.bridge.register("getParams", self.memory.getParams) | 321 self.bridge.register("getParams", self.memory.getParams) |
296 self.bridge.register("getParamsForCategory", self.memory.getParamsForCategory) | 322 self.bridge.register("getParamsForCategory", self.memory.getParamsForCategory) |
297 self.bridge.register("getParamsCategories", self.memory.getParamsCategories) | 323 self.bridge.register("getParamsCategories", self.memory.getParamsCategories) |
298 self.bridge.register("getHistory", self.memory.getHistory) | 324 self.bridge.register("getHistory", self.memory.getHistory) |
299 self.bridge.register("setPresence", self.setPresence) | 325 self.bridge.register("setPresence", self.setPresence) |
326 self.bridge.register("subscription", self.subscription) | |
300 self.bridge.register("addContact", self.addContact) | 327 self.bridge.register("addContact", self.addContact) |
301 self.bridge.register("delContact", self.delContact) | 328 self.bridge.register("delContact", self.delContact) |
302 self.bridge.register("isConnected", self.isConnected) | 329 self.bridge.register("isConnected", self.isConnected) |
303 self.bridge.register("launchAction", self.launchAction) | 330 self.bridge.register("launchAction", self.launchAction) |
304 self.bridge.register("confirmationAnswer", self.confirmationAnswer) | 331 self.bridge.register("confirmationAnswer", self.confirmationAnswer) |
521 self.xmlstream.send(message) | 548 self.xmlstream.send(message) |
522 self.memory.addToHistory(self.me, self.me, jid.JID(to), message["type"], unicode(msg)) | 549 self.memory.addToHistory(self.me, self.me, jid.JID(to), message["type"], unicode(msg)) |
523 self.bridge.newMessage(message['from'], unicode(msg), to=message['to']) #We send back the message, so all clients are aware of it | 550 self.bridge.newMessage(message['from'], unicode(msg), to=message['to']) #We send back the message, so all clients are aware of it |
524 | 551 |
525 | 552 |
526 def setPresence(self, to="", type="", show="", status="", priority=0): | 553 def setPresence(self, to="", show="", priority = 0, statuses={}): |
527 """Send our presence information""" | 554 """Send our presence information""" |
528 if not type in ["", "unavailable", "subscribed", "subscribe", | 555 to_jid = jid.JID(to) if to else None |
529 "unsubscribe", "unsubscribed", "prob", "error"]: | 556 self.presence.available(to_jid, show, statuses, priority) |
530 error("Type error !") | 557 |
531 #TODO: throw an error | 558 def subscription(self, type, raw_jid): |
532 return | 559 """Called to manage subscription""" |
533 to_jid=jid.JID(to) | 560 to_jid = jid.JID(raw_jid) |
534 status = None if not status else {None:status} #FIXME: use the proper way here (change signature to use dict) | 561 debug ('subsciption request [%s] for %s', type, to_jid.full()) |
535 #TODO: refactor subscription bridge API | 562 if type=="subscribe": |
536 if type=="": | |
537 self.presence.available(to_jid, show, status, priority) | |
538 elif type=="subscribe": | |
539 self.presence.subscribe(to_jid) | 563 self.presence.subscribe(to_jid) |
540 elif type=="subscribed": | 564 elif type=="subscribed": |
541 self.presence.subscribed(to_jid) | 565 self.presence.subscribed(to_jid) |
566 contact = self.memory.getContact(to_jid) | |
567 if not contact or not bool(contact['to']): #we automatically subscribe to 'to' presence | |
568 debug('sending automatic "to" subscription request') | |
569 self.subscription('subscribe', to_jid.userhost()) | |
542 elif type=="unsubscribe": | 570 elif type=="unsubscribe": |
543 self.presence.unsubscribe(to_jid) | 571 self.presence.unsubscribe(to_jid) |
544 elif type=="unsubscribed": | 572 elif type=="unsubscribed": |
545 self.presence.unsubscribed(to_jid) | 573 self.presence.unsubscribed(to_jid) |
546 | 574 |
547 | 575 |
548 def addContact(self, to): | 576 def addContact(self, to): |
549 """Add a contact in roster list""" | 577 """Add a contact in roster list""" |
550 to_jid=jid.JID(to) | 578 to_jid=jid.JID(to) |
551 self.roster.addItem(to_jid.userhost()) | 579 self.roster.addItem(to_jid) |
552 self.setPresence(to_jid.userhost(), "subscribe") | 580 self.presence.subscribe(to_jid) |
553 | 581 |
554 def delContact(self, to): | 582 def delContact(self, to): |
555 """Remove contact from roster list""" | 583 """Remove contact from roster list""" |
556 to_jid=jid.JID(to) | 584 to_jid=jid.JID(to) |
557 self.roster.removeItem(to_jid.userhost()) | 585 self.roster.removeItem(to_jid) |
586 self.presence.unsubscribe(to_jid) | |
558 self.bridge.contactDeleted(to) | 587 self.bridge.contactDeleted(to) |
559 | 588 |
560 | 589 |
561 ## callbacks ## | 590 ## callbacks ## |
562 | 591 |