Dependency inject service ID, so that it can be stamped on friends and
[hermes] / package / src / org / maemo / hermes / engine / twitter / service.py
index f20384f..9042076 100644 (file)
-import org.maemo.hermes.engine.service
-
-import twitter
 from org.maemo.hermes.engine.names import canonical
+import org.maemo.hermes.engine.service
 
 class Service(org.maemo.hermes.engine.service.Service):
     """Twitter backend for Hermes.
        
        Copyright (c) Andrew Flegg <andrew@bleb.org> 2010.
+       Copyright (c) Fredrik Wendt <fredrik@wendt.se> 2010.
        Released under the Artistic Licence."""
        
        
     # -----------------------------------------------------------------------
-    def __init__(self, username, password, gui_callback = None):
-        """Initialise the Twitter service, using the given credentials and
-           having a gui_callback available."""
-        
-        self._gui = gui_callback
-        self._username = username
-        self._password = password
+    def __init__(self, service_id, twitterApi):
+        org.maemo.hermes.engine.service.Service.__init__(self, service_id)
+
+        self._twitter = twitterApi
         
-        self._friends = None
+        self._friends_by_name = {}
         self._friends_by_url = {}
+        self._friends_by_contact = {}
+        self._friends = []
+        self._known_urls = set()
+    
+    
+    # -----------------------------------------------------------------------
+    def pre_process_contact(self, contact):
+        """Registers URLs of all previous mappings, and makes sure that any Friends with those
+           URLs don't get match by name."""
+        for url in contact.get_urls():
+            self._known_urls.add(url)
+
 
-   
     # -----------------------------------------------------------------------
-    def get_friends(self):
-        """Return a list of friends from this service, or 'None' if manual mapping
-           is not supported."""
-           
-        if self._friends:
-            return self._friends.values()
-        
-        self._friends = {}
-        
-        api = twitter.Api(username=self._username, password=self._password)
-        for tweeter in api.GetFriends():
-            key    = canonical(tweeter.name)
-            url    = 'http://twitter.com/%s' % (tweeter.screen_name)
-            friend = {'name':          tweeter.name, 'pic': tweeter.profile_image_url,
-                      'birthday_date': None,         'profile_url': url,
-                      'homepage':      tweeter.url,  'account': 'twitter'}
-            if friend['pic'].find('/default_profile') > -1:
-                friend['pic'] = None
+    def process_friends(self):
+        for tweeter in self._get_tweeters():
+            key = canonical(tweeter.name)
+            url = 'http://twitter.com/%s' % (tweeter.screen_name)
+            friend = self._create_friend(tweeter.name)
+            friend.set_nickname(tweeter.screen_name)
+            friend.add_url(url)
+            friend.add_url(tweeter.url)
+            if '/default_profile' not in tweeter.profile_image_url:
+                friend.set_photo_url(tweeter.profile_image_url)
           
-            self._friends[key] = friend
+            self._friends.append(friend)
             self._friends_by_url[url] = friend
-                
-        return self._friends.values()
+            if url not in self._known_urls:
+                self._friends_by_name[key] = friend
 
     
     # -----------------------------------------------------------------------
-    def process_contact(self, contact, overwrite = False, friend = None):
-        """Called for each contact in the address book. Any friends linked to
-           from the contact should have their matching updated. The backend should 
-           enrich the contact with any meta-data it can; and return 'True' if any
-           information was updated. If 'friend' is provided, the information should
-           be retrieved from friend. This will be one of the entries from 
-           'get_friends' when manual mapping is being done."""
-           
-        if not self._friends:
-            self.get_friends()
-            
-        matched_friend = None
-        for url in contact.get_urls():
-            if url in self._friends_by_url:
-                matched_friend = self._friends_by_url[url]
-                break
-
-        if not matched_friend:
-            for id in contact.get_identifiers():
-                if id in self._friends:
-                    matched_friend = self._friends[id]
-                    break
-                
-        if matched_friend:
-            print contact.get_name(), " -> ", matched_friend['profile_url']
-        else:
-            print contact.get_name(), " no match to Twitter with ", contact.get_identifiers()
-            
+    def process_contact(self, contact):
+        if self._friends_by_contact.has_key(contact) or \
+            self._match_contact_to_friend_by_urls(contact) or \
+            self._match_contact_to_friend_by_identifiers(contact):
+            return self._get_friend_by_contact(contact)
+        
+        return None
     
     
     # -----------------------------------------------------------------------
-    def finalise(self, updated, overwrite = False):
-        """Once all contacts have been processed, allows for any tidy-up/additional
-           enrichment. If any contacts are updated at this stage, 'updated' should
-           be added to."""
-           
+    def finalise(self, updated, overwrite=False):
         pass
+
+
+    # -----------------------------------------------------------------------
+    def get_contacts_with_match(self):
+        return self._friends_by_contact
+    
+
+    # -----------------------------------------------------------------------
+    def get_unmatched_friends(self):
+        return self._friends
+    
+
+    # -----------------------------------------------------------------------
+    def _get_tweeters(self):
+        return self._twitter.GetFriends()
+    
+    
+    # -----------------------------------------------------------------------
+    def _get_friend_by_contact(self, contact):
+        return self._friends_by_contact[contact]
+
+
+    def _match_contact_to_friend_by_urls(self, contact):
+        for url in contact.get_urls():
+            if url in self._friends_by_url:
+                matched_friend = self._friends_by_url[url]
+                self._register_match(contact, matched_friend)
+                return True
+            
+        return False
+
+
+    def _match_contact_to_friend_by_identifiers(self, contact):
+        for id in contact.get_identifiers():
+            if id in self._friends_by_name:
+                matched_friend = self._friends_by_name[id]
+                self._register_match(contact, matched_friend)
+                return True
+            
+        return False
+
+
+    def _register_match(self, contact, friend):
+        friend.set_contact(contact)
+        self._friends_by_contact[contact] = friend
+        self._friends.remove(friend)
+