1 import org.maemo.hermes.engine.service
3 from org.maemo.hermes.engine.names import canonical
4 from org.maemo.hermes.engine.friend import Friend
6 class Service(org.maemo.hermes.engine.service.Service):
7 """Facebook backend for Hermes.
9 Copyright (c) Andrew Flegg <andrew@bleb.org> 2010.
10 Copyright (c) Fredrik Wendt <fredrik@wendt.se> 2010.
11 Released under the Artistic Licence."""
13 attrs = ['uid', 'name', 'pic_big', 'birthday_date', 'profile_url', 'first_name', 'last_name', 'website']
16 # -----------------------------------------------------------------------
17 def __init__(self, service_id, facebook, create_birthday_only = False):
19 self._service_id = service_id
20 self._create_birthday_only = create_birthday_only
22 self._friends_by_name = {}
23 self._friends_by_url = {}
24 self._friends_by_contact = {}
25 self._contacts_by_friend = {}
26 self._friends_without_contact = set()
27 self._known_urls = set()
30 # -----------------------------------------------------------------------
31 def get_friends_to_create_contacts_for(self):
33 if self._create_birthday_only:
34 for friend in self._friends_without_contact:
35 friends.append(friend)
40 # -----------------------------------------------------------------------
41 def get_friends(self):
42 """Returns all friends on Facebook"""
44 return self._friends_by_url.values()
47 # -----------------------------------------------------------------------
48 def get_contacts_with_match(self):
49 """Returns a dict, where each key value pair is a contact (key) that
50 matched a friend (value)"""
52 return self._friends_by_contact
55 # -----------------------------------------------------------------------
56 def get_unmatched_friends(self):
57 """Returns a list of all friends that didn't match a contact."""
59 return self._friends_without_contact
62 # -----------------------------------------------------------------------
63 def pre_process_contact(self, contact):
64 """Registers URLs of all previous mappings, and makes sure that any
65 friend with such a URL don't get match by name."""
67 for url in contact.get_urls():
68 self._known_urls.add(url)
71 # -----------------------------------------------------------------------
72 def process_friends(self):
73 """Retreives data from Facebook and parse that into Friend
76 def if_defined(data, key, callback):
77 if key in data and data[key]:
80 friends_data = self._get_friends_data()
81 for data in friends_data:
82 friend = Friend(data['name'])
84 if 'profile_url' not in data:
85 data['profile_url'] = "http://www.facebook.com/profile.php?id=" + str(data['uid'])
87 if_defined(data, 'website', friend.add_url)
88 if_defined(data, 'profile_url', friend.add_url)
89 if_defined(data, 'birthday_date', friend.set_birthday_date)
91 if_defined(data, 'pic_big', friend.set_photo_url)
93 url = data['profile_url']
95 self._register_friend(friend)
98 # -----------------------------------------------------------------------
99 def process_contact(self, contact):
100 """If the contact is matched with a friend, that friend is returned,
103 matched_friend = None
104 if self._friends_by_contact.has_key(contact):
105 matched_friend = self._friends_by_contact[contact]
107 # we might get a hit if the friend has setup a URL with another service,
108 # such as putting the id link to Facebook on the Twitter account's profile
109 if not matched_friend:
110 for url in contact.get_urls():
111 if url in self._friends_by_url:
112 matched_friend = self._friends_by_url[url]
113 self._register_match(contact, matched_friend)
116 if not matched_friend:
117 for id in contact.get_identifiers():
118 if id in self._friends_by_name:
119 matched_friend = self._friends_by_name.pop(id)
120 self._register_match(contact, matched_friend)
123 return matched_friend
126 # -----------------------------------------------------------------------
127 def _register_friend(self, friend):
128 self._friends_without_contact.add(friend)
130 for url in friend.get_urls():
131 if self.is_profile_url(url):
132 self._friends_by_url[url] = friend
134 if self._allow_friend_to_match_by_name(friend):
135 key = canonical(friend.get_name())
136 self._friends_by_name[key] = friend
139 # -----------------------------------------------------------------------
140 def is_profile_url(self, url):
141 """Return True if this is a URL for this service."""
143 return url and "facebook.com" in url
146 # -----------------------------------------------------------------------
147 def _allow_friend_to_match_by_name(self, friend):
148 for url in friend.get_urls():
149 if url in self._known_urls:
154 # -----------------------------------------------------------------------
155 def _register_match(self, contact, friend):
156 friend.set_contact(contact)
157 self._friends_without_contact.discard(friend)
158 self._friends_by_contact[contact] = friend
159 self._contacts_by_friend[friend] = contact
162 # -----------------------------------------------------------------------
163 def _get_friends_data(self):
164 """Returns a list of dicts, where each dict represents the raw data
167 return self.fb.users.getInfo(self.fb.friends.get(), Service.attrs)