+from org.maemo.hermes.engine.friend import Friend
+from org.maemo.hermes.engine.contact import Contact
+import evolution
+
class Hermes:
"""Encapsulate the process of syncing online friends' information with the
- Evolution contacts' database. This should be used as follows:
+ Evolution contacts' database.
- * Initialise, passing in a GUI callback.
- * Call Syncjob.
- * Retrieve information on changes effected.
- * Call update_contact to enact manual mapping.
-
Copyright (c) Andrew Flegg <andrew@bleb.org> 2010.
Released under the Artistic Licence."""
# -----------------------------------------------------------------------
- def __init__(self, services, gui_progress):
- """Constructor. Passed a list of services, and a callback method
- which must implement the following API.
-
- progress(i, j) - the application is currently processing friend 'i' of
- 'j'. Should be used to provide the user a progress bar.
- """
+ def __init__(self, services, gui_progress=None):
+ """Constructor. Passed a list of services, and a
+ method which will be invoked with three arguments:
+ str Name of current step
+ int Current position
+ int Maximum value of position."""
+
# -- These fields are currently part of the API...
#
- self.updated = []
- self.matched = []
+ self.updated = []
+ self.matched = []
self.unmatched = []
- self.friends = {}
- self.addresses = None
+ self.friends = {}
+ self.address_book = None
# -- Other initialisation...
#
self._services = services
- self._progress = gui_progress
+ self._progress = gui_progress or (lambda msg, i, j: None)
# -----------------------------------------------------------------------
- def run(self, resync = False):
- """Load information on the authenticated user's friends. Synchronise Facebook
- profiles to contact database. If resync is false, no existing information
- will be overwritten."""
+ def run(self, overwrite_existing_fields=False):
+ self._progress("Reading contacts...", 1, 10000)
+
+ contacts = []
+ self.address_book = self._get_address_book()
+ for econtact in self.address_book.get_all_contacts():
+ contacts.append(self._create_contact_wrapper(econtact))
- class FakeContact():
- def get_name(self):
- return "Fredrik Wendt"
- def get_emails(self):
- return ["fredrik@wendt.se","maemohermes@wendt.se"]
- def get_photo(self):
- return None
- self.matched = [FakeContact()]
-
-# self._sync_job = SyncJob(services, [FakeContact()], self.progress)
-# self._sync_job.run()
-# self._sync_job.get_unmatched_friends()
-# self._sync_job.get_updated_contacts()
-# self._sync_job.get_matched_contacts()
- pass
+ # work out progress bar info
+ total_contacts = len(contacts) * len(self._services)
+ total_ticks = 6 * total_contacts # Number of distinct loops below
+ # warm up
+ current_tick = 1
+ for service in self._services:
+ print "pre-process:", service.get_id()
+ for contact in contacts:
+ self._progress("Pre-processing contacts...", current_tick, total_ticks)
+ current_tick += 1
+ service.pre_process_contact(contact)
+
+ # fetch data
+ for service in self._services:
+ print "process_friends:", service.get_id()
+ self._progress("Reading friends...", current_tick, total_ticks)
+ current_tick += len(contacts)
+ service.process_friends()
+
+ # combine results into one friend
+ for contact in contacts:
+ result = Friend()
+ for service in self._services:
+ print "process_contact:", service.get_id()
+ self._progress("Processing contacts...", current_tick, total_ticks)
+ current_tick += 1
+ friend = service.process_contact(contact)
+ if friend:
+ contact.add_mapping(service.get_id())
+ result.update_from_friend(friend)
+
+ if result.get_name() is not None:
+ self.update_contact(contact, result, overwrite_existing_fields)
+ else:
+ self.unmatched.append(contact)
+
+ # give services a chance to create new contacts
+ for service in self._services:
+ print "create_contacts:", service.get_id()
+ to_create = service.get_friends_to_create_contacts_for()
+ tick_increment = len(contacts) / (len(to_create) or 1)
+ print tick_increment, to_create
+ for friend in to_create:
+ friend.set_source(service.get_id())
+ self._progress("Creating contacts...", current_tick, total_ticks)
+ current_tick += tick_increment
+ self.create_contact_from_friend(friend)
+
+ # finalisation
+ for service in self._services:
+ print "finalize:", service.get_id()
+ self._progress("Finalising...", current_tick, total_ticks)
+ current_tick += len(contacts)
+ service.finalise(self.updated, overwrite_existing_fields)
+ for friend in service.get_unmatched_friends():
+ friend.set_source(service.get_id())
+ key = unicode(friend.get_name()).encode('trans') + "_" + service.get_id()
+ self.friends[key] = friend
+
+ # commit changes
+ tick_increment = total_contacts / (len(self.updated) or 1)
+ print tick_increment, self.updated
+ for contact in self.updated:
+ print "committing changes to:", contact.get_name(), contact
+ self._progress("Saving changes...", current_tick, total_ticks)
+ current_tick += tick_increment
+ self.address_book.commit_contact(contact.get_econtact())
+
+ self._progress('Finished', 1, -1)
+
# -----------------------------------------------------------------------
- def update_contact(self, contact, friend, resync = False):
+ def update_contact(self, contact, friend, resync=False, commit=False):
"""Update the given contact with information from the given friend."""
- pass
-
-"""
- friends = ()
- for service in services:
- for friend in service.get_friends():
- friends.add(friend)
+ print "updating contact ", contact, " with friend ", friend
+ if friend.update_contact(contact, resync):
+ self.updated.append(contact)
+ if commit:
+ self.address_book.commit_contact(contact.get_econtact())
- all_contacts = get_contacts_as_set()
- contacts = set()
- updated_contacts = set()
- for econtact in addressbook.get_all_contacts():
- contact = Contact(addressbook, econtact)
- contacts.add(contact)
- for service in something.get_services_by_prioritisation():
- if service.process_contact(contact):
- updated_contacts.add(contact)
+ self.matched.append(contact)
+ if friend.get_source() is not None:
+ contact.add_mapping(friend.get_source())
- for service in something.get_services_by_prioritisation():
- service.finalise(updated_contacts)
- for contact in updated_contacts:
- contact.save()
-"""
+ # -----------------------------------------------------------------------
+ def create_contact_from_friend(self, friend):
+ econtact = self._create_empty_contact(friend)
+ contact = self._create_contact_wrapper(econtact)
+
+ self.address_book.add_contact(contact.get_econtact())
+ self.update_contact(contact, friend)
+
+ print "Created [%s]" % (contact.get_name())
+
+
+ # -----------------------------------------------------------------------
+ def _get_address_book(self):
+ return evolution.ebook.open_addressbook('default')
+
+ # -----------------------------------------------------------------------
+ def _create_empty_contact(self, friend):
+ econtact = evolution.ebook.EContact()
+ econtact.props.given_name = friend['first_name']
+ econtact.props.family_name = friend['last_name']
+ econtact.props.full_name = friend.get_name()
+ return econtact
+
+ # -----------------------------------------------------------------------
+ def _create_contact_wrapper(self, econtact):
+ return Contact(self.address_book, econtact)