2 import org.maemo.hermes.engine.service
4 from facebook import Facebook,FacebookError
5 from org.maemo.hermes.engine.names import canonical
6 from org.maemo.hermes.engine.friend import Friend
8 class Service(org.maemo.hermes.engine.service.Service):
9 """Facebook backend for Hermes.
11 This requires two gconf paths to contain Facebook application keys:
12 /apps/maemo/hermes/key_app
13 /apps/maemo/hermes/key_secret
15 Copyright (c) Andrew Flegg <andrew@bleb.org> 2010.
16 Released under the Artistic Licence."""
19 # -----------------------------------------------------------------------
20 def __init__(self, autocreate = False, gui_callback = None):
21 """Initialise the Facebook service, finding Facebook API keys in gconf and
22 having a gui_callback available."""
24 self._gc = gnome.gconf.client_get_default()
25 self._gui = gui_callback
26 self._autocreate = autocreate
28 # -- Check the environment is going to work...
30 if (self._gc.get_string('/desktop/gnome/url-handlers/http/command') == 'epiphany %s'):
31 raise Exception('Browser in gconf invalid (see NB#136012). Installation error.')
33 key_app = self._gc.get_string('/apps/maemo/hermes/key_app')
34 key_secret = self._gc.get_string('/apps/maemo/hermes/key_secret')
35 if key_app is None or key_secret is None:
36 raise Exception('No Facebook application keys found. Installation error.')
38 self.fb = Facebook(key_app, key_secret)
39 self.fb.desktop = True
42 self._friends_by_url = {}
43 self._friends_by_contact = {}
44 self._should_create = set()
49 # -----------------------------------------------------------------------
54 # -----------------------------------------------------------------------
55 def _do_fb_login(self):
56 """Perform authentication against Facebook and store the result in gconf
57 for later use. Uses the 'need_auth' and 'block_for_auth' methods on
58 the callback class. The former allows a message to warn the user
59 about what is about to happen to be shown; the second is to wait
60 for the user to confirm they have logged in."""
61 self.fb.session_key = None
68 self.fb.auth.createToken()
72 self._gui.block_for_auth()
74 session = self.fb.auth.getSession()
75 self._gc.set_string('/apps/maemo/hermes/session_key', session['session_key'])
76 self._gc.set_string('/apps/maemo/hermes/secret_key', session['secret'])
77 self._gc.set_string('/apps/maemo/hermes/uid', str(session['uid']))
80 # -----------------------------------------------------------------------
81 def get_friends(self):
82 """Return a list of friends from this service, or 'None' if manual mapping
86 return self._friends.values()
88 if self.fb.session_key is None:
89 self.fb.session_key = self._gc.get_string('/apps/maemo/hermes/session_key')
90 self.fb.secret = self._gc.get_string('/apps/maemo/hermes/secret_key')
91 self.fb.uid = self._gc.get_string('/apps/maemo/hermes/uid')
93 # Check the available session is still valid...
96 if self.fb.users.getLoggedInUser() and self.fb.session_key:
103 def if_defined(data, key, callback):
104 if key in data and data[key]:
108 attrs = ['uid', 'name', 'pic_big', 'birthday_date', 'profile_url', 'first_name', 'last_name', 'website']
109 for data in self.fb.users.getInfo(self.fb.friends.get(), attrs):
110 key = canonical(data['name'])
111 friend = Friend(data['name'])
112 self._friends[key] = friend
114 if 'profile_url' not in data:
115 data['profile_url'] = "http://www.facebook.com/profile.php?id=" + str(data['uid'])
117 self._friends_by_url[data['profile_url']] = friend
120 if_defined(data, 'website', friend.add_url)
121 if_defined(data, 'profile_url', friend.add_url)
122 if_defined(data, 'birthday_date', friend.set_birthday_date)
124 # exception from the rule:
125 # if_defined(data, 'pic_big', friend.set_photo_url)
126 friend.set_photo_url(data[attrs[2]])
128 if friend.has_birthday_date():
129 self._should_create.add(friend)
131 return self._friends.values()
134 # -----------------------------------------------------------------------
135 def pre_process_contact(self, contact):
137 if not self._friends:
140 for url in contact.get_urls():
141 if url in self._friends_by_url:
142 matched_friend = self._friends_by_url[url]
143 self._friends_by_contact[contact] = matched_friend
144 self._should_create.discard(matched_friend)
147 # -----------------------------------------------------------------------
148 def process_contact(self, contact, friend):
150 if not self._friends:
153 if self._friends_by_contact.has_key(contact):
154 friend.update(self._friends_by_contact[contact])
157 matched_friend = None
158 # we might get a hit if the friend has setup a URL with another service
159 for url in contact.get_urls():
160 if url in self._friends_by_url:
161 matched_friend = self._friends_by_url[url]
162 self._friends_by_contact[contact] = matched_friend
165 if not matched_friend:
166 for id in contact.get_identifiers():
167 if id in self._friends:
168 matched_friend = self._friends[id]
169 self._friends_by_contact[contact] = matched_friend
173 print contact.get_name(), " -> ", matched_friend
174 self._should_create.discard(matched_friend)
179 # -----------------------------------------------------------------------
180 def finalise(self, updated, overwrite = False):
181 """Once all contacts have been processed, allows for any tidy-up/additional
182 enrichment. If any contacts are updated at this stage, 'updated' should
185 if True or self._autocreate: # FIXME - remove True or
186 for friend in self._should_create:
187 print "Need to autocreate: %s (%s)" % (friend._attributes, friend._multi_attributes)