rewrite to match new service API and enable some testing
[hermes] / package / src / org / maemo / hermes / engine / facebook / service.py
1 import org.maemo.hermes.engine.service
2
3 from org.maemo.hermes.engine.names import canonical
4
5 class Service(org.maemo.hermes.engine.service.Service):
6     """Facebook backend for Hermes.
7                 
8        Copyright (c) Andrew Flegg <andrew@bleb.org> 2010.
9        Copyright (c) Fredrik Wendt <fredrik@wendt.se> 2010.
10        Released under the Artistic Licence."""
11        
12     attrs = ['uid', 'name', 'pic_big', 'birthday_date', 'profile_url', 'first_name', 'last_name', 'website']
13        
14     # -----------------------------------------------------------------------
15     def __init__(self, facebook, autocreate = False, gui_callback = None):
16         """Initialise the Facebook service, finding Facebook API keys in gconf and
17            having a gui_callback available."""
18         
19         self._gui = gui_callback
20         self._autocreate = autocreate
21         self.fb = facebook
22         
23         self._friends_by_id = {}
24         self._friends_by_url = {}
25         self._friends_by_contact = {}
26         self._contacts_by_friend = {}
27         self._friends_without_contact = set()
28         self._known_urls = set()
29
30
31     # -----------------------------------------------------------------------
32     def get_name(self):
33         return "Facebook"
34     
35     
36     # -----------------------------------------------------------------------
37     def get_friends(self):
38         return self._contacts_by_friend.keys()
39     
40     
41     def get_contacts_with_match(self):
42         return self._friends_by_contact
43     
44     def get_unmatched_friends(self):
45         return self._friends_by_id.values()
46
47     # -----------------------------------------------------------------------
48     def pre_process_contact(self, contact):
49         """Registers URLs of all previous mappings, and makes sure that any Friends with those
50            URLs don't get match by name."""
51         for url in contact.get_urls():
52             self._known_urls.add(url)
53     
54     
55     # -----------------------------------------------------------------------
56     def process_friends(self):
57         
58         def if_defined(data, key, callback):
59             if key in data and data[key]:
60                 callback(data[key])
61         
62         friends_data = self._get_friends_data()
63         for data in friends_data:
64             key = canonical(data['name']) # FIXME: deal with name collision
65             friend = self._create_friend(data['name'])
66         
67             if 'profile_url' not in data:
68                 data['profile_url'] = "http://www.facebook.com/profile.php?id=" + str(data['uid'])
69         
70             if_defined(data, 'website', friend.add_url)
71             if_defined(data, 'profile_url', friend.add_url)
72             if_defined(data, 'birthday_date', friend.set_birthday_date)
73
74             if_defined(data, 'pic_big', friend.set_photo_url)
75             
76             if friend.has_birthday_date(): # FIXME: remove this, either you want to add your contacts or not? 
77                 self._friends_without_contact.add(friend)
78             url = data['profile_url']
79             self._friends_by_url[url] = friend
80             
81             if url not in self._known_urls:
82                 self._friends_by_id[key] = friend
83
84     # -----------------------------------------------------------------------
85     def process_contact(self, contact):
86         if self._friends_by_contact.has_key(contact):
87             return
88         
89         matched_friend = None
90         # we might get a hit if the friend has setup a URL with another service,
91         # such as putting the id link to Facebook on the Twitter account's profile
92         for url in contact.get_urls():
93             if url in self._friends_by_url:
94                 matched_friend = self._friends_by_url[url]
95                 self._register_match(contact, matched_friend)
96                 print contact.get_name(), " -> match by url -> ", matched_friend
97                 break
98
99         if not matched_friend:
100             for id in contact.get_identifiers():
101                 if id in self._friends_by_id:
102                     matched_friend = self._friends_by_id.pop(id)
103                     self._register_match(contact, matched_friend)
104                     print contact.get_name(), " -> match by name -> ", matched_friend
105                     break
106     
107
108     # -----------------------------------------------------------------------
109     def _register_match(self, contact, friend):
110         self._friends_without_contact.discard(friend)
111         self._friends_by_contact[contact] = friend
112         self._contacts_by_friend[friend] = contact
113
114     # -----------------------------------------------------------------------
115     def _get_friends_data(self):
116         """Returns a list of dicts, where each dict represents a friend/contact"""
117         
118         return self.fb.users.getInfo(self.fb.friends.get(), Service.attrs)