merge, moved tests around
[hermes] / package / src / org / maemo / hermes / engine / twitter / service.py
index a6f4748..273b99d 100644 (file)
@@ -1,28 +1,23 @@
-import org.maemo.hermes.engine.service
-
-import twitter
 from org.maemo.hermes.engine.names import canonical
-from org.maemo.hermes.engine.friend import Friend
+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."""
+    def __init__(self, twitterApi):
+        self._twitter = twitterApi
         
-        self._gui = gui_callback
-        self._username = username
-        self._password = password
-        
-        self._friends = None
+        self._friends_by_name = {}
         self._friends_by_url = {}
         self._friends_by_contact = {}
+        self._friends = []
+        self._known_urls = set()
 
    
     # -----------------------------------------------------------------------
@@ -31,76 +26,85 @@ class Service(org.maemo.hermes.engine.service.Service):
     
     
     # -----------------------------------------------------------------------
-    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 = Friend(tweeter.name)
+    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 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 pre_process_contact(self, contact):
-        if not self._friends:
-            self.get_friends()
-            
-        for url in contact.get_urls():
-            if url in self._friends_by_url:
-                matched_friend = self._friends_by_url[url]
-                self._friends_by_contact[contact] = matched_friend
-
-
-    # -----------------------------------------------------------------------
-    def process_contact(self, contact, friend):
-        """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()
-        
+    def process_contact(self, contact):
         if self._friends_by_contact.has_key(contact):
-            friend.update(self._friends_by_contact[contact])
             return
         
-        for id in contact.get_identifiers():
-            if id in self._friends:
-                matched_friend = self._friends[id]
-                print contact.get_name(), " -> ", matched_friend
-                if matched_friend in self._friends_by_contact.values():
-                    print "COLLISSION avoided for %s" % friend
-                else:
-                    print "Match found %s" % friend
-                    self._friends_by_contact[contact] = matched_friend
-                    friend.update(matched_friend)
-                
+        if self._match_contact_to_friend_by_urls(contact):
+            return
+        
+        self._match_contact_to_friend_by_identifiers(contact)
     
     
     # -----------------------------------------------------------------------
-    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 _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)
+                print contact.get_name(), " -> url -> ", 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]
+                print contact.get_name(), " -> name -> ", matched_friend
+                self._register_match(contact, matched_friend)
+                return True
+            
+        return False
+
+
+    def _register_match(self, contact, friend):
+        self._friends_by_contact[contact] = friend
+        self._friends.remove(friend)
+