diff --git a/src/common/contacts.py b/src/common/contacts.py index b4234d15d..7b50626e6 100644 --- a/src/common/contacts.py +++ b/src/common/contacts.py @@ -33,29 +33,20 @@ import common.gajim from common.caps import NullClientCaps, FEATURE_BLACKLIST -class Contact(object): - '''Information concerning each contact''' - def __init__(self, jid='', name='', groups=[], show='', status='', sub='', - ask='', resource='', priority=0, keyID='', client_caps=None, caps_cache=None, - our_chatstate=None, chatstate=None, last_status_time=None, msg_id = None, - composing_xep = None, mood={}, tune={}, - activity={}): +class CommonContact(object): + + def __init__(self, jid, resource, show, status, name, our_chatstate, + composing_xep, chatstate, client_caps=None, caps_cache=None): + self.jid = jid - self.name = name - self.contact_name = '' # nick choosen by contact - self.groups = groups + self.resource = resource self.show = show self.status = status - self.sub = sub - self.ask = ask - self.resource = resource - self.priority = priority - self.keyID = keyID - - # Entity Capabilities + self.name = name + self.client_caps = client_caps or NullClientCaps() self._caps_cache = caps_cache or common.gajim.capscache - + # please read xep-85 http://www.xmpp.org/extensions/xep-0085.html # we keep track of xep85 support with the peer by three extra states: # None, False and 'ask' @@ -64,14 +55,70 @@ class Contact(object): # 'ask' if we sent the first 'active' chatstate and are waiting for reply # this holds what WE SEND to contact (our current chatstate) self.our_chatstate = our_chatstate - self.msg_id = msg_id # tell which XEP we're using for composing state # None = have to ask, XEP-0022 = use this xep, # XEP-0085 = use this xep, False = no composing support self.composing_xep = composing_xep # this is contact's chatstate self.chatstate = chatstate + + def get_full_jid(self): + raise NotImplementedError + + def get_shown_name(self): + raise NotImplementedError + + def supports(self, requested_feature): + ''' + Returns True if the contact has advertised to support the feature + identified by the given namespace. False otherwise. + ''' + if self.show == 'offline': + # Unfortunately, if all resources are offline, the contact + # includes the last resource that was online. Check for its + # show, so we can be sure it's existant. Otherwise, we still + # return caps for a contact that has no resources left. + return False + else: + return self._client_supports(requested_feature) + + def _client_supports(self, requested_feature): + lookup_item = self.client_caps.get_cache_lookup_strategy() + cache_item = lookup_item(self._caps_cache) + + supported_features = cache_item.features + if requested_feature in supported_features: + return True + elif supported_features == [] and cache_item.queried in (0, 1): + # assume feature is supported, if we don't know yet, what the client + # is capable of + return requested_feature not in FEATURE_BLACKLIST + else: + return False + + +class Contact(CommonContact): + '''Information concerning each contact''' + def __init__(self, jid='', name='', groups=[], show='', status='', sub='', + ask='', resource='', priority=0, keyID='', client_caps=None, caps_cache=None, + our_chatstate=None, chatstate=None, last_status_time=None, msg_id = None, + composing_xep=None, mood={}, tune={}, activity={}): + + CommonContact.__init__(self, jid, resource, show, status, name, + our_chatstate, composing_xep, chatstate, client_caps=client_caps, + caps_cache=caps_cache) + + self.contact_name = '' # nick choosen by contact + self.groups = groups + + self.sub = sub + self.ask = ask + + self.priority = priority + self.keyID = keyID + self.msg_id = msg_id self.last_status_time = last_status_time + self.mood = mood.copy() self.tune = tune.copy() self.activity = activity.copy() @@ -136,81 +183,25 @@ class Contact(object): return False - def supports(self, requested_feature): - if self.show == 'offline': - # Unfortunately, if all resources are offline, the contact - # includes the last resource that was online. Check for its - # show, so we can be sure it's existant. Otherwise, we still - # return caps for a contact that has no resources left. - return False - else: - return self._client_supports(requested_feature) - - def _client_supports(self, requested_feature): - lookup = self.client_caps.get_cache_lookup_strategy() - cache_item = lookup(self._caps_cache) - - supported_features = cache_item.features - if requested_feature in supported_features: - return True - elif supported_features == [] and cache_item.queried in (0, 1): - # assume feature is supported, if we don't know yet, what the client - # is capable of - return requested_feature not in FEATURE_BLACKLIST - else: - return False - -class GC_Contact: +class GC_Contact(CommonContact): '''Information concerning each groupchat contact''' def __init__(self, room_jid='', name='', show='', status='', role='', - affiliation='', jid = '', resource = '', our_chatstate = None, - composing_xep = None, chatstate = None): + affiliation='', jid='', resource='', our_chatstate=None, + composing_xep=None, chatstate=None): + + CommonContact.__init__(self, jid, resource, show, status, name, + our_chatstate, composing_xep, chatstate) + self.room_jid = room_jid - self.name = name - self.show = show - self.status = status self.role = role self.affiliation = affiliation - self.jid = jid - self.resource = resource - # Entity Capabilities - self.client_caps = NullClientCaps() - self._caps_cache = common.gajim.capscache - - self.our_chatstate = our_chatstate - self.composing_xep = composing_xep - self.chatstate = chatstate - def get_full_jid(self): return self.room_jid + '/' + self.name def get_shown_name(self): return self.name - def supports(self, requested_feature): - if self.show == 'offline': - # Unfortunately, if all resources are offline, the contact - # includes the last resource that was online. Check for its - # show, so we can be sure it's existant. Otherwise, we still - # return caps for a contact that has no resources left. - return False - else: - return self._client_supports(requested_feature) - - def _client_supports(self, requested_feature): - lookup_item = self.client_caps.get_cache_lookup_strategy() - cache_item = lookup_item(self._caps_cache) - - supported_features = cache_item.features - if requested_feature in supported_features: - return True - elif supported_features == [] and cache_item.queried in (0, 1): - # assume feature is supported, if we don't know yet, what the client - # is capable of - return requested_feature not in FEATURE_BLACKLIST - else: - return False class Contacts: '''Information concerning all contacts and groupchat contacts''' diff --git a/test/runtests.py b/test/runtests.py index 1feb80e60..fa95009f4 100755 --- a/test/runtests.py +++ b/test/runtests.py @@ -40,6 +40,7 @@ modules = ( 'test_xmpp_dispatcher_nb', 'test_xmpp_transports_nb', 'test_resolver', 'test_caps', + 'test_contacts', ) #modules = () diff --git a/test/test_contacts.py b/test/test_contacts.py index 1fe3dc033..f75917cfb 100644 --- a/test/test_contacts.py +++ b/test/test_contacts.py @@ -6,14 +6,16 @@ import unittest import lib lib.setup_env() -from common.contacts import Contact, GC_Contact +from common.contacts import CommonContact, Contact, GC_Contact from common.caps import NullClientCaps from common.xmpp import NS_MUC class TestCommonContact(unittest.TestCase): def setUp(self): - self.contact = Contact() + self.contact = CommonContact(jid='', resource='', show='', status='', + name='', our_chatstate=None, composing_xep=None, chatstate=None, + client_caps=None, caps_cache=None) def test_default_client_supports(self): '''