SàT improvement:

- subscription & presence refactoring
- multilingual statuses are now correctly sent
- registration: error condition now specified in error message
This commit is contained in:
Goffi 2010-01-07 00:05:15 +11:00
commit 94dd813a9a

125
sat.tac
View file

@ -70,8 +70,8 @@ def sat_next_id():
class SatXMPPClient(client.XMPPClient):
def __init__(self, jid, password, host=None, port=5222):
client.XMPPClient.__init__(self, jid, password, host, port)
def __init__(self, user_jid, password, host=None, port=5222):
client.XMPPClient.__init__(self, user_jid, password, host, port)
self.factory.clientConnectionLost = self.connectionLost
self.__connected=False
@ -120,11 +120,8 @@ class SatRosterProtocol(xmppim.RosterClientProtocol):
self.host = host
def rosterCb(self, roster):
for jid, item in roster.iteritems():
info ("new contact in roster list: %s", jid)
#FIXME: fill attributes
self.host.memory.addContact(jid, {}, item.groups)
self.host.bridge.newContact(jid, {}, item.groups)
for raw_jid, item in roster.iteritems():
self.onRosterSet(item)
def requestRoster(self):
""" ask the server for Roster list """
@ -133,16 +130,33 @@ class SatRosterProtocol(xmppim.RosterClientProtocol):
def removeItem(self, to):
"""Remove a contact from roster list"""
to_jid=jid.JID(to)
xmppim.RosterClientProtocol.removeItem(self, to_jid)
xmppim.RosterClientProtocol.removeItem(self, to)
#TODO: check IQ result
def addItem(self, to):
"""Add a contact to roster list"""
to_jid=jid.JID(to)
xmppim.RosterClientProtocol.addItem(self, to_jid)
xmppim.RosterClientProtocol.addItem(self, to)
#TODO: check IQ result
def onRosterSet(self, item):
"""Called when a new/update roster item is received"""
#TODO: send a signal to frontends
item_attr = {'to': str(item.subscriptionTo),
'from': str(item.subscriptionFrom),
'ask': str(item.ask)
}
if item.name:
item_attr['name'] = item.name
info ("new contact in roster list: %s", item.jid.full())
self.host.memory.addContact(item.jid, item_attr, item.groups)
self.host.bridge.newContact(item.jid.full(), item_attr, item.groups)
def onRosterRemove(self, entity):
"""Called when a roster removal event is received"""
#TODO: send a signal to frontends
print "removing %s from roster list" % entity.full()
self.host.memory.delContact(entity)
class SatPresenceProtocol(xmppim.PresenceClientProtocol):
def __init__(self, host):
@ -151,42 +165,53 @@ class SatPresenceProtocol(xmppim.PresenceClientProtocol):
def availableReceived(self, entity, show=None, statuses=None, priority=0):
info ("presence update for [%s]", entity)
if statuses.has_key(None): #we only want string keys
statuses["default"] = statuses[None]
del statuses[None]
### we check if the status is not about subscription ###
#FIXME: type is not needed anymore
#TODO: management of differents statuses (differents languages)
status = statuses.values()[0] if len(statuses) else ""
self.host.memory.addPresenceStatus(entity.full(), "", show or "",
status or "", int(priority))
self.host.memory.addPresenceStatus(entity, show or "",
int(priority), statuses)
#now it's time to notify frontends
self.host.bridge.presenceUpdate(entity.full(), "", show or "",
status or "", int(priority))
self.host.bridge.presenceUpdate(entity.full(), show or "",
int(priority), statuses)
def unavailableReceived(self, entity, statuses=None):
#TODO: management of differents statuses (differents languages)
status = statuses.values()[0] if len(statuses) else ""
self.host.memory.addPresenceStatus(entity.full(), "unavailable", "",
status or "", 0)
if statuses and statuses.has_key(None): #we only want string keys
statuses["default"] = statuses[None]
del statuses[None]
self.host.memory.addPresenceStatus(entity, "unavailable", 0, statuses)
#now it's time to notify frontends
self.host.bridge.presenceUpdate(entity.full(), "unavailable", "",
status or "", 0)
self.host.bridge.presenceUpdate(entity.full(), "unavailable", 0, statuses)
def available(self, entity=None, show=None, statuses=None, priority=0):
if statuses and statuses.has_key('default'):
statuses[None] = statuses['default']
del statuses['default']
xmppim.PresenceClientProtocol.available(self, entity, show, statuses, priority)
def subscribedReceived(self, entity):
debug ("subscription approved for [%s]" % entity)
debug ("subscription approved for [%s]" % entity.userhost())
self.host.memory.delWaitingSub(entity.userhost())
self.host.bridge.subscribe('subscribed', entity.userhost())
def unsubscribedReceived(self, entity):
debug ("unsubscription confirmed for [%s]" % entity)
debug ("unsubscription confirmed for [%s]" % entity.userhost())
self.host.memory.delWaitingSub(entity.userhost())
self.host.bridge.subscribe('unsubscribed', entity.userhost())
def subscribeReceived(self, entity):
#FIXME: auto answer for subscribe request, must be checked !
debug ("subscription request for [%s]" % entity)
self.subscribed(entity)
debug ("subscription request for [%s]" % entity.userhost())
self.host.memory.addWaitingSub('subscribe', entity.userhost())
self.host.bridge.subscribe('subscribe', entity.userhost())
def unsubscribeReceived(self, entity):
debug ("unsubscription asked for [%s]" % entity)
debug ("unsubscription asked for [%s]" % entity.userhost())
self.host.memory.addWaitingSub('unsubscribe', entity.userhost())
self.host.bridge.subscribe('unsubscribe', entity.userhost())
class SatDiscoProtocol(disco.DiscoClientProtocol):
def __init__(self, host):
@ -243,7 +268,7 @@ class RegisteringAuthenticator(xmlstream.ConnectAuthenticator):
answer_data={"message":"Username already exists, please choose an other one"}
else:
answer_data['reason'] = 'unknown'
answer_data={"message":"Registration failed"}
answer_data={"message":"Registration failed (%s)" % str(failure.value.condition)}
self.host.bridge.actionResult(answer_type, self.answer_id, answer_data)
self.xmlstream.sendFooter()
@ -289,6 +314,7 @@ class SAT(service.Service):
self.bridge.register("disconnect", self.disconnect)
self.bridge.register("getContacts", self.memory.getContacts)
self.bridge.register("getPresenceStatus", self.memory.getPresenceStatus)
self.bridge.register("getWaitingSub", self.memory.getWaitingSub)
self.bridge.register("sendMessage", self.sendMessage)
self.bridge.register("setParam", self.setParam)
self.bridge.register("getParamA", self.memory.getParamA)
@ -297,6 +323,7 @@ class SAT(service.Service):
self.bridge.register("getParamsCategories", self.memory.getParamsCategories)
self.bridge.register("getHistory", self.memory.getHistory)
self.bridge.register("setPresence", self.setPresence)
self.bridge.register("subscription", self.subscription)
self.bridge.register("addContact", self.addContact)
self.bridge.register("delContact", self.delContact)
self.bridge.register("isConnected", self.isConnected)
@ -523,22 +550,23 @@ class SAT(service.Service):
self.bridge.newMessage(message['from'], unicode(msg), to=message['to']) #We send back the message, so all clients are aware of it
def setPresence(self, to="", type="", show="", status="", priority=0):
def setPresence(self, to="", show="", priority = 0, statuses={}):
"""Send our presence information"""
if not type in ["", "unavailable", "subscribed", "subscribe",
"unsubscribe", "unsubscribed", "prob", "error"]:
error("Type error !")
#TODO: throw an error
return
to_jid=jid.JID(to)
status = None if not status else {None:status} #FIXME: use the proper way here (change signature to use dict)
#TODO: refactor subscription bridge API
if type=="":
self.presence.available(to_jid, show, status, priority)
elif type=="subscribe":
to_jid = jid.JID(to) if to else None
self.presence.available(to_jid, show, statuses, priority)
def subscription(self, type, raw_jid):
"""Called to manage subscription"""
to_jid = jid.JID(raw_jid)
debug ('subsciption request [%s] for %s', type, to_jid.full())
if type=="subscribe":
self.presence.subscribe(to_jid)
elif type=="subscribed":
self.presence.subscribed(to_jid)
contact = self.memory.getContact(to_jid)
if not contact or not bool(contact['to']): #we automatically subscribe to 'to' presence
debug('sending automatic "to" subscription request')
self.subscription('subscribe', to_jid.userhost())
elif type=="unsubscribe":
self.presence.unsubscribe(to_jid)
elif type=="unsubscribed":
@ -548,13 +576,14 @@ class SAT(service.Service):
def addContact(self, to):
"""Add a contact in roster list"""
to_jid=jid.JID(to)
self.roster.addItem(to_jid.userhost())
self.setPresence(to_jid.userhost(), "subscribe")
self.roster.addItem(to_jid)
self.presence.subscribe(to_jid)
def delContact(self, to):
"""Remove contact from roster list"""
to_jid=jid.JID(to)
self.roster.removeItem(to_jid.userhost())
self.roster.removeItem(to_jid)
self.presence.unsubscribe(to_jid)
self.bridge.contactDeleted(to)