Dependency inject service ID, so that it can be stamped on friends and
[hermes] / package / src / org / maemo / hermes / engine / hermes.py
1 from org.maemo.hermes.engine.friend import Friend
2 from org.maemo.hermes.engine.contact import Contact
3 import evolution
4
5 class Hermes:
6     """Encapsulate the process of syncing online friends' information with the
7        Evolution contacts' database. This should be used as follows:
8        
9          * Initialise, passing in a GUI callback.
10          * Call Syncjob.
11          * Retrieve information on changes effected.
12          * Call update_contact to enact manual mapping.
13          
14        Copyright (c) Andrew Flegg <andrew@bleb.org> 2010.
15        Released under the Artistic Licence."""
16
17     
18     # -----------------------------------------------------------------------
19     def __init__(self, services, gui_progress):
20         """Constructor. Passed a list of services, and a callback method
21            which must implement the following API.
22                               
23              progress(i, j) - the application is currently processing friend 'i' of
24                               'j'. Should be used to provide the user a progress bar.
25         """
26         
27         # -- These fields are currently part of the API...
28         #
29         self.updated = []
30         self.matched = []
31         self.unmatched = []
32         self.friends = {}
33         self.addresses = None
34         
35         # -- Other initialisation...
36         #
37         self._services = services
38         self._progress = gui_progress
39     
40     
41     # -----------------------------------------------------------------------
42     def run(self, resync=False):
43         """Load information on the authenticated user's friends. Synchronise Facebook
44            profiles to contact database. If resync is false, no existing information
45            will be overwritten."""
46
47         class FakeContact():
48             def get_name(self):
49                 return "Fredrik Wendt"
50             def get_emails(self):
51                 return ["fredrik@wendt.se", "maemohermes@wendt.se"]
52             def get_photo(self):
53                 return None
54             def get_mapped_to(self):
55                 return set(["facebook", "gravatar"])
56         self.matched = [FakeContact()]
57  
58 #        self._sync_job = SyncJob(services, [FakeContact()], self.progress)
59 #        self._sync_job.run()
60 #        self._sync_job.get_unmatched_friends()
61 #        self._sync_job.get_updated_contacts()
62 #        self._sync_job.get_matched_contacts()
63         pass
64     
65     
66     # -----------------------------------------------------------------------
67     def run_alt(self, overwrite_existing_fields=False):
68         contacts = []
69         self.addresses = evolution.ebook.open_addressbook('default')
70         for contact in self.addresses.get_all_contacts():
71             contacts.append(Contact(self.addresses, contact))
72
73         # warm up
74         for service in self._services:
75             print "pre-process:", service.get_id()
76             for contact in contacts:
77                 service.pre_process_contact(contact)
78                 
79         # fetch data
80         for service in self._services:
81             print "process_friends:", service.get_id()
82             service.process_friends()
83         
84         # combine results into one friend
85         for contact in contacts:
86             result = Friend()
87             for service in self._services:
88                 print "process_contact:", service.get_id()
89                 friend = service.process_contact(contact)
90                 if friend:
91                     contact.add_mapping(service.get_id())
92                     friend.decorate(result)
93             
94             if result.get_name() is not None:
95                 self.update_contact(result, overwrite_existing_fields)
96             else:
97                 self.unmatched.add(contact)
98             
99         # give services a chance to create new contacts
100         for service in self._services:
101             print "create_contacts:", service.get_id()
102             for friend in service.create_contacts():
103                 self.create_contact_from_friend(friend)
104                 
105         # finalisation
106         for service in self._services:
107             print "finalize:", service.get_id()
108             service.finalise(self.updated, overwrite_existing_fields)
109             
110         # commit changes
111         for contact in self.updated:
112             print "committing changes to:", contact.get_name(), contact
113             self.addresses.commit_contact(contact.get_econtact())
114         
115
116     # -----------------------------------------------------------------------
117     def update_contact(self, contact, friend, resync=False):
118         """Update the given contact with information from the given friend."""
119         
120         print "updating contact ", contact, " with friend ", friend
121         self.updated.append(contact)
122         self.matched.append(contact)
123         if friend.get_source() is not None:
124             contact.add_mapping(friend.get_source())
125
126
127     # -----------------------------------------------------------------------
128     def create_contact_from_friend(self, friend):
129         econtact = evolution.ebook.EContact()
130         econtact.props.full_name = friend['name']
131         econtact.props.given_name = friend['first_name']
132         econtact.props.family_name = friend['last_name']
133         contact = Contact(self.addresses, econtact)
134                 
135         self.addresses.add_contact(contact)
136         self.update_contact(contact, friend)
137         
138         print "Created [%s]" % (contact.get_name())