Permalink
Browse files

- Merged jprieur's branch

This merge brings enhancements to the AddressBook concerning contact
management, and invites management. It also brings initial support for the
Offline messenging and content roaming.
  • Loading branch information...
1 parent 55f1f54 commit 72bfb1dd10d6af667a59d7aed11b97975815768b @asabil asabil committed Aug 6, 2007
@@ -102,6 +102,37 @@ class AddressBookState(object):
SYNCHRONIZED = 2
"""The addressbook is already synchornized"""
+class PendingContact(object):
+
+ def __init__(self, account, network, display_name='', invite_message=''):
+ self._account = account
+ self._network = network
+ self._display_name = display_name
+ self._invite_message = invite_message
+
+ @property
+ def account(self):
+ return self._account
+
+ @property
+ def network(self):
+ return self._network
+
+ @property
+ def display_name(self):
+ return self._display_name
+
+ @property
+ def invite_message(self):
+ return self._invite_message
+
+ def __eq__(self, pending_contact):
+ return self._account == pending_contact.account & \
+ self._network == pending_contact.network
+
+ def __str__(self):
+ return "%s (%s) %s %s" % (self.account, self.display_name,
+ self.network, self.invite_message)
class AddressBook(gobject.GObject):
@@ -149,7 +180,11 @@ class AddressBook(gobject.GObject):
"State",
"The state of the addressbook.",
0, 2, AddressBookState.NOT_SYNCHRONIZED,
- gobject.PARAM_READABLE)
+ gobject.PARAM_READABLE),
+ "pending-contacts" : (gobject.TYPE_PYOBJECT,
+ "Pending contacts",
+ "The pending contacts",
+ gobject.PARAM_READABLE)
}
def __init__(self, sso, proxies=None):
@@ -160,7 +195,8 @@ def __init__(self, sso, proxies=None):
self._sharing = sharing.Sharing(sso, proxies)
self.__state = AddressBookState.NOT_SYNCHRONIZED
-
+ self.__pending_contacts = set()
+
self.groups = {}
self.contacts = AddressBookStorage()
self._profile = None
@@ -184,11 +220,39 @@ def __set_state(self, state):
state = property(__get_state)
_state = property(__get_state, __set_state)
+ def __get_pending_contacts(self):
+ return self.__pending_contacts
+ def __set_pending_contacts(self, pending_contacts):
+ self.__pending_contacts = pending_contacts
+ self.notify("pending-contacts")
+ pending_contacts = property(__get_pending_contacts)
+ _pending_contacts = property(__get_pending_contacts,
+ __set_pending_contacts)
+
@property
def profile(self):
return self._profile
# Public API
+ def accept_contact_invitation(self, pending_contact, add_to_contact_list=True):
+ self._pending_contacts.discard(pending_contact)
+ ai = scenario.AcceptInviteScenario(self._ab, self._sharing,
+ (self.__accept_contact_invitation_cb),
+ (self.__common_errback,),
+ add_to_contact_list)
+ ai.account = pending_contact.account
+ ai.network = pending_contact.network
+ ai()
+
+ def decline_contact_invitation(self, pending_contact):
+ self._pending_contacts.discard(pending_contact)
+ di = scenario.DeclineInviteScenario(self._ab, self._sharing,
+ (self.__decline_contact_invitation_cb),
+ (self.__common_errback,))
+ di.account = pending_contact.account
+ di.network = pending_contact.network
+ di()
+
def add_messenger_contact(self, account):
am = scenario.MessengerContactAddScenario(self._ab,
(self.__add_messenger_contact_cb,),
@@ -232,18 +296,16 @@ def block_contact(self, contact):
bc = scenario.BlockContactScenario(self._sharing,
(self.__common_callback, 'contact-blocked', contact),
(self.__common_errback,))
- # bc.type = contact.type
- bc.type = 'Passport'
bc.account = contact.account
+ bc.network = contact.network_id
bc()
def unblock_contact(self, contact):
uc = scenario.UnblockContactScenario(self._sharing,
(self.__common_callback, 'contact-unblocked', contact),
(self.__common_errback,))
- # uc.type = contact.type
- uc.type = 'Passport'
uc.account = contact.account
+ uc.network = contact.network_id
uc()
def add_group(self, group_name):
@@ -260,7 +322,6 @@ def delete_group(self, group):
dg.group_guid = group.id
dg()
-
def rename_group(self, group, new_name):
rg = scenario.GroupRenameScenario(self._ab,
(self.__rename_group_cb, group, new_name),
@@ -280,11 +341,54 @@ def add_contact_to_group(self, group, contact):
def delete_contact_from_group(self, group, contact):
dc = scenario.GroupContactDeleteScenario(self._ab,
(self.__delete_contact_from_group_cb, group, contact),
- (self.__common_errback,))
+ (self.__commonq_errback,))
dc.group_guid = group.id
dc.contact_guid = contact.id
dc()
+ # End of public API
+ def _check_pending_invitations(self):
+ cp = scenario.CheckPendingInviteScenario(self._sharing,
+ (self.__update_memberships,),
+ (self.__common_errback,))
+ cp()
+
+ def __update_memberships(self, memberships):
+ for member in memberships:
+ if isinstance(member, sharing.PassportMember):
+ network = profile.NetworkID.MSN
+ elif isinstance(member, sharing.EmailMember):
+ network = profile.NetworkID.EXTERNAL
+
+ contacts = self.contacts.search_by_account(member.Account)
+
+ contact = None
+ for c in contacts:
+ if c.network_id == network:
+ contact = c
+ break
+
+ if contact is None:
+ # Pending contact
+ msg = member.Annotations.get('MSN.IM.InviteMessage', '')
+ p = PendingContact(member.Account.encode("utf-8"), network,
+ member.DisplayName.encode("utf-8"),
+ msg.encode("utf-8"))
+ self._pending_contacts.add(p)
+ else:
+ for role in member.Roles:
+ if role == "Allow":
+ membership = profile.Membership.ALLOW
+ elif role == "Block":
+ membership = profile.Membership.BLOCK
+ elif role == "Reverse":
+ membership = profile.Membership.REVERSE
+ elif role == "Pending":
+ membership = profile.Membership.PENDING
+ else:
+ raise NotImplementedError("Unknown Membership Type : " + membership)
+ contact._add_membership(membership)
+
# Callbacks
def __initial_sync_callback(self, address_book, memberships):
ab = address_book.ab
@@ -349,32 +453,15 @@ def __initial_sync_callback(self, address_book, memberships):
self._profile = c
else:
self.contacts.add(c)
-
- for member in memberships:
- if member.Type != "Passport":
- #FIXME: maybe we want to avoid filtering
- continue
-
- contact = self.contacts\
- .search_by_account(member.Account)[0]
- if contact is None:
- continue
+ self.__update_memberships(memberships)
+ self._state = AddressBookState.SYNCHRONIZED
- for role in member.Roles:
- if role == "Allow":
- membership = profile.Membership.ALLOW
- elif role == "Block":
- membership = profile.Membership.BLOCK
- elif role == "Reverse":
- membership = profile.Membership.REVERSE
- elif role == "Pending":
- membership = profile.Membership.PENDING
- else:
- raise NotImplementedError("Unknown Membership Type : " + membership)
+ def __accept_contact_invitation_cb(self, contact_guid, address_book_delta):
+ self.__add_messenger_contact_cb(self, contact_guid, address_book_delta)
- contact._add_membership(membership)
- self._state = AddressBookState.SYNCHRONIZED
+ def __decline_contact_invitation_cb(self):
+ pass
def __add_messenger_contact_cb(self, contact_guid, address_book_delta):
contacts = address_book_delta.contacts
@@ -398,7 +485,6 @@ def __add_messenger_contact_cb(self, contact_guid, address_book_delta):
if display_name == "":
display_name = external_email.Email
-
c = profile.Contact(contact.Id,
profile.NetworkID.EXTERNAL,
external_email.Email.encode("utf-8"),
@@ -509,11 +595,19 @@ def address_book_state_changed(address_book, pspec):
print "Group : %s (%s)" % (guid, group.name)
for contact in address_book.contacts:
- print "Contact : %s (%s) %s %s" % (contact.account,
- contact.display_name,
- contact.network_id,
- contact.memberships)
-
+ print "Contact : %s (%s) %s" % \
+ (contact.account,
+ contact.display_name,
+ contact.network_id)
+
+ for pending in address_book.pending_contacts:
+ print "Pending contact : %s" % pending
+
+ #address_book._check_pending_invitations()
+ #address_book.accept_contact_invitation(address_book.pending_contacts.pop())
+ #print address_book.pending_contacts.pop()
+ #address_book.accept_contact_invitation(address_book.pending_contacts.pop())
+
#address_book.add_group("callback test6")
#address_book.delete_group(address_book.groups.values()[0])
#address_book.rename_group(address_book.groups.values()[0], "new group name")
@@ -523,6 +617,7 @@ def address_book_state_changed(address_book, pspec):
# address_book.contacts[0])
#address_book.block_contact(address_book.contacts.search_by_account('pymsn.rewrite@yahoo.com')[0])
#address_book.unblock_contact(address_book.contacts[0])
+ #address_book.block_contact(address_book.contacts[0])
#address_book.delete_contact(address_book.contacts[2])
#address_book.add_messenger_contact("tryggve2@gmail.com")
@@ -17,12 +17,15 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
from pymsn.service.AddressBook.scenario.base import BaseScenario
+from pymsn.profile import NetworkID
+
+from pymsn.service.AddressBook.scenario import *
__all__ = ['AcceptInviteScenario']
class AcceptInviteScenario(BaseScenario):
def __init__(self, ab, sharing, callback, errback, add_to_contact_list=True,
- type='', account='', state='Accepted'):
+ account='', network=NetworkID.MSN, state='Accepted'):
"""Accepts an invitation.
@param ab: the address book service
@@ -35,24 +38,39 @@ def __init__(self, ab, sharing, callback, errback, add_to_contact_list=True,
self.__sharing = sharing
self.__add_to_contact_list = add_to_contact_list
- self.type = type
self.account = account
+ self.network = network
self.state = state
+ def _type(self):
+ if self.network == NetworkID.MSN:
+ return 'Passport'
+ elif self.network == NetworkID.EXTERNAL:
+ return 'Email'
+
def execute(self):
if self.__add_to_contact_list:
- contact_info = { 'passport_name' : self.account }
- self.__ab.ContactAdd((self.__add_contact_callback,),
- (self.__add_contact_errback,),
- self._scenario, contact_info, {})
- else:
- self.__add_contact_callback()
-
- def __add_contact_callback(self):
+ if self.network == NetworkID.MSN:
+ am = MessengerContactAddScenario(self.__ab,
+ (self.__add_contact_callback,),
+ (self.__add_contact_errback,),
+ self.account)
+ am()
+ elif self.network == NetworkID.EXTERNAL:
+ em = ExternalContactAddScenario(self.__ab,
+ (self.__add_contact_callback,),
+ (self.__add_contact_errback,),
+ self.account)
+ em()
self.__sharing.DeleteMember((self.__delete_member_callback,),
(self.__delete_member_errback,),
- self._scenario, 'Pending', self.type,
+ self._scenario, 'Pending', self._type(),
self.state, self.account)
+
+ def __add_contact_callback(self, contact_guid):
+ self._ab.FindAll((self.__find_all_callback, contact_guid),
+ (self.__find_all_errback, contact_guid),
+ self._scenario, True)
def __add_contact_errback(self):
errback = self._errback[0]
@@ -62,7 +80,7 @@ def __add_contact_errback(self):
def __delete_member_callback(self):
self.__sharing.AddMember((self.__add_member_callback,),
(self.__add_member_errback,),
- self._scenario, 'Allow', self.type,
+ self._scenario, 'Allow', self._type(),
self.state, self.account)
def __delete_member_errback(self):
@@ -78,3 +96,13 @@ def __add_member_errback(self):
errback = self._errback[0]
args = self._errback[1:]
errback(reason, *args)
+
+ def __find_all_callback(self, delta, contact_guid):
+ callback = self._callback
+ callback[0](contact_guid, delta, *callback[1:])
+
+ def __find_all_errback(self, reason):
+ errback = self._errback[0]
+ args = self._errback[1:]
+ errback(reason, *args)
+
Oops, something went wrong.

0 comments on commit 72bfb1d

Please sign in to comment.