core: fixed several subscription scheme issues + removed most of profile_key default value in core.sat_main and core.xmmp (source of bugs) + contact update

This commit is contained in:
Goffi 2011-05-28 20:28:21 +02:00
commit ca30c9359b
3 changed files with 81 additions and 40 deletions

View file

@ -34,6 +34,7 @@ from twisted.words.xish import domish
from twisted.internet import reactor
from wokkel import compat
from wokkel.xmppim import RosterItem
from sat.bridge.DBus import DBusBridge
import logging
@ -128,6 +129,7 @@ class SAT(service.Service):
self.bridge.register("setPresence", self.setPresence)
self.bridge.register("subscription", self.subscription)
self.bridge.register("addContact", self.addContact)
self.bridge.register("updateContact", self.updateContact)
self.bridge.register("delContact", self.delContact)
self.bridge.register("isConnected", self.isConnected)
self.bridge.register("launchAction", self.launchAction)
@ -235,7 +237,7 @@ class SAT(service.Service):
current.startService()
def disconnect(self, profile_key='@DEFAULT@'):
def disconnect(self, profile_key):
"""disconnect from jabber server"""
if (not self.isConnected(profile_key)):
info(_("not connected !"))
@ -322,7 +324,7 @@ class SAT(service.Service):
else:
self.actionResult(action_id, "SUPPRESS", {})
def submitForm(self, action, target, fields, profile_key='@DEFAULT@'):
def submitForm(self, action, target, fields, profile_key):
"""submit a form
@param target: target jid where we are submitting
@param fields: list of tuples (name, value)
@ -351,12 +353,12 @@ class SAT(service.Service):
## Client management ##
def setParam(self, name, value, category, profile_key='@DEFAULT@'):
def setParam(self, name, value, category, profile_key):
"""set wanted paramater and notice observers"""
info (_("setting param: %(name)s=%(value)s in category %(category)s") % {'name':name, 'value':value, 'category':category})
self.memory.setParam(name, value, category, profile_key)
def isConnected(self, profile_key='@DEFAULT@'):
def isConnected(self, profile_key):
"""Return connection status of profile
@param profile_key: key_word or profile name to determine profile name
@return True if connected
@ -369,7 +371,7 @@ class SAT(service.Service):
return False
return self.profiles[profile].isConnected()
def launchAction(self, type, data, profile_key='@DEFAULT@'):
def launchAction(self, type, data, profile_key):
"""Launch a specific action asked by client
@param type: action type (button)
@param data: needed data to launch the action
@ -429,7 +431,7 @@ class SAT(service.Service):
int(priority), statuses, profile)
def subscription(self, subs_type, raw_jid, profile_key='@DEFAULT@'):
def subscription(self, subs_type, raw_jid, profile_key):
"""Called to manage subscription
@param subs_type: subsciption type (cf RFC 3921)
@param raw_jid: unicode entity's jid
@ -442,17 +444,12 @@ class SAT(service.Service):
self.profiles[profile].presence.subscribe(to_jid)
elif subs_type=="subscribed":
self.profiles[profile].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 subs_type=="unsubscribe":
self.profiles[profile].presence.unsubscribe(to_jid)
elif subs_type=="unsubscribed":
self.profiles[profile].presence.unsubscribed(to_jid)
def addContact(self, to, profile_key='@DEFAULT@'):
def addContact(self, to, profile_key):
"""Add a contact in roster list"""
profile = self.memory.getProfileName(profile_key)
assert(profile)
@ -460,7 +457,18 @@ class SAT(service.Service):
#self.profiles[profile].roster.addItem(to_jid) XXX: disabled (cf http://wokkel.ik.nu/ticket/56))
self.profiles[profile].presence.subscribe(to_jid)
def delContact(self, to, profile_key='@DEFAULT@'):
def updateContact(self, to, name, groups, profile_key):
"""update a contact in roster list"""
profile = self.memory.getProfileName(profile_key)
assert(profile)
to_jid = jid.JID(to)
groups = set(groups)
roster_item = RosterItem(to_jid)
roster_item.name = name or None
roster_item.groups = set(groups)
self.profiles[profile].roster.updateItem(roster_item)
def delContact(self, to, profile_key):
"""Remove contact from roster list"""
profile = self.memory.getProfileName(profile_key)
assert(profile)

View file

@ -139,6 +139,22 @@ class SatRosterProtocol(xmppim.RosterClientProtocol):
#xmppim.RosterClientProtocol.addItem(self, to)
#TODO: check IQ result"""
def updateItem(self, roster_item):
"""
Update an item of the contact list.
@param roster_item: item to update
"""
iq = compat.IQ(self.xmlstream, 'set')
iq.addElement((xmppim.NS_ROSTER, 'query'))
item = iq.query.addElement('item')
item['jid'] = roster_item.jid.userhost()
if roster_item.name:
item['name'] = roster_item.name
for group in roster_item.groups:
item.addElement('group', content=group)
return iq.send()
def onRosterSet(self, item):
"""Called when a new/update roster item is received"""
#TODO: send a signal to frontends
@ -206,25 +222,44 @@ class SatPresenceProtocol(xmppim.PresenceClientProtocol):
statuses[None] = statuses['default']
del statuses['default']
xmppim.PresenceClientProtocol.available(self, entity, show, statuses, priority)
def subscribed(self, entity):
xmppim.PresenceClientProtocol.subscribed(self, entity)
self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
contact = self.host.memory.getContact(entity, self.parent.profile)
if not contact or contact[0]['to'] == 'False': #we automatically subscribe to 'to' presence
debug(_('sending automatic "from" subscription request'))
self.subscribe(entity)
def unsubscribed(self, entity):
xmppim.PresenceClientProtocol.unsubscribed(self, entity)
self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
def subscribedReceived(self, entity):
debug (_("subscription approved for [%s]") % entity.userhost())
self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
self.host.bridge.subscribe('subscribed', entity.userhost(), self.parent.profile)
def unsubscribedReceived(self, entity):
debug (_("unsubscription confirmed for [%s]") % entity.userhost())
self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
self.host.bridge.subscribe('unsubscribed', entity.userhost(), self.parent.profile)
def subscribeReceived(self, entity):
debug (_("subscription request for [%s]") % entity.userhost())
self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile)
self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile)
debug (_("subscription request from [%s]") % entity.userhost())
contact = self.host.memory.getContact(entity, self.parent.profile)
if contact and contact[0]['to'] == 'True':
#We automatically accept subscription if we are already subscribed to contact presence
debug(_('sending automatic subscription acceptance'))
self.subscribed(entity)
else:
self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile)
self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile)
def unsubscribeReceived(self, entity):
debug (_("unsubscription asked for [%s]") % entity.userhost())
self.host.memory.addWaitingSub('unsubscribe', entity.userhost(), self.parent.profile)
contact = self.host.memory.getContact(entity, self.parent.profile)
if contact and contact[0]['from'] == 'True': #we automatically remove contact
debug(_('automatic contact deletion'))
self.host.delContact(entity.userhost(), self.parent.profile)
self.host.bridge.subscribe('unsubscribe', entity.userhost(), self.parent.profile)
class SatDiscoProtocol(disco.DiscoClientProtocol):

View file

@ -291,7 +291,7 @@ class Param():
return prof_xml
def getParamsUI(self, profile_key='@DEFAULT@'):
def getParamsUI(self, profile_key):
"""Return a SàT XMLUI for parameters, with given profile"""
profile = self.getProfileName(profile_key)
if not profile:
@ -300,7 +300,7 @@ class Param():
param_xml = self.getParams(profile)
return paramsXml2xmlUI(param_xml)
def getParams(self, profile_key='@DEFAULT@'):
def getParams(self, profile_key):
"""Construct xml for asked profile
Take params xml as skeleton"""
profile = self.getProfileName(profile_key)
@ -313,7 +313,7 @@ class Param():
return return_xml
def getParamsForCategory(self, category, profile_key='@DEFAULT@'):
def getParamsForCategory(self, category, profile_key):
"""Return node's xml for selected category"""
#TODO: manage category of general type (without existant profile)
profile = self.getProfileName(profile_key)
@ -359,7 +359,7 @@ class Param():
categories.append(cat.getAttribute("name"))
return categories
def setParam(self, name, value, category, profile_key='@DEFAULT@'):
def setParam(self, name, value, category, profile_key):
"""Set a parameter, return None if the parameter is not in param xml"""
profile = self.getProfileName(profile_key)
if not profile:
@ -573,7 +573,7 @@ class Memory:
else:
return list(entities)[0] if entities else None
def hasServerFeature(self, feature, profile_key='@DEFAULT@'):
def hasServerFeature(self, feature, profile_key):
"""Tell if the server of the profile has the required feature"""
profile = self.getProfileName(profile_key)
if not profile:
@ -583,7 +583,7 @@ class Memory:
return feature in self.server_features[profile]
def addContact(self, contact_jid, attributes, groups, profile_key='@DEFAULT@'):
def addContact(self, contact_jid, attributes, groups, profile_key):
debug("Memory addContact: %s",contact_jid.userhost())
profile = self.getProfileName(profile_key)
if not profile:
@ -595,7 +595,7 @@ class Memory:
self.contacts[profile] = {}
self.contacts[profile][contact_jid.userhost()]=[attributes, groups]
def delContact(self, contact_jid, profile_key='@DEFAULT@'):
def delContact(self, contact_jid, profile_key):
debug("Memory delContact: %s",contact_jid.userhost())
profile = self.getProfileName(profile_key)
if not profile:
@ -604,17 +604,15 @@ class Memory:
if self.contacts.has_key(profile) and self.contacts[profile].has_key(contact_jid.userhost()):
del self.contacts[profile][contact_jid.userhost()]
def getContact(self, contact_jid, profile_key='@DEFAULT@'):
def getContact(self, contact_jid, profile_key):
profile = self.getProfileName(profile_key)
if not profile:
error(_('Asking a contact for a non-existant profile'))
return None
if self.contacts.has_key(profile) and self.contacts[profile].has_key(contact_jid.userhost()):
self.contacts[profile][contact_jid.userhost()]
else:
return None
return self.contacts[profile][contact_jid.userhost()]
def getContacts(self, profile_key='@DEFAULT@'):
def getContacts(self, profile_key):
"""Return list of contacts for given profile
@param profile_key: profile key
@return list of [contact, attr, groups]"""
@ -630,7 +628,7 @@ class Memory:
ret.append([contact, attr, groups ])
return ret
def addPresenceStatus(self, contact_jid, show, priority, statuses, profile_key='@DEFAULT@'):
def addPresenceStatus(self, contact_jid, show, priority, statuses, profile_key):
profile = self.getProfileName(profile_key)
if not profile:
error(_('Trying to add presence status to a non-existant profile'))
@ -657,7 +655,7 @@ class Memory:
if self.subscriptions.has_key(profile) and self.subscriptions[profile].has_key(contact_jid):
del self.subscriptions[profile][contact_jid]
def getWaitingSub(self, profile_key='@DEFAULT@'):
def getWaitingSub(self, profile_key):
"""Called to get a list of currently waiting subscription requests"""
profile = self.getProfileName(profile_key)
if not profile:
@ -668,7 +666,7 @@ class Memory:
return self.subscriptions[profile]
def getPresenceStatus(self, profile_key='@DEFAULT@'):
def getPresenceStatus(self, profile_key):
profile = self.getProfileName(profile_key)
if not profile:
error(_('Asking contacts for a non-existant profile'))
@ -678,22 +676,22 @@ class Memory:
debug ("Memory getPresenceStatus (%s)", self.presenceStatus[profile])
return self.presenceStatus[profile]
def getParamA(self, name, category, attr="value", profile_key="@DEFAULT@"):
def getParamA(self, name, category, attr="value", profile_key='@DEFAULT@'):
return self.params.getParamA(name, category, attr, profile_key)
def getParamsUI(self, profile_key='@DEFAULT@'):
def getParamsUI(self, profile_key):
return self.params.getParamsUI(profile_key)
def getParams(self, profile_key='@DEFAULT@'):
def getParams(self, profile_key):
return self.params.getParams(profile_key)
def getParamsForCategory(self, category, profile_key='@DEFAULT@'):
def getParamsForCategory(self, category, profile_key):
return self.params.getParamsForCategory(category, profile_key)
def getParamsCategories(self):
return self.params.getParamsCategories()
def setParam(self, name, value, category, profile_key='@DEFAULT@'):
def setParam(self, name, value, category, profile_key):
return self.params.setParam(name, value, category, profile_key)
def importParams(self, xml):