2 import org.maemo.hermes.engine.service
4 from facebook import Facebook
5 from org.maemo.hermes.engine.names import canonical
7 class Service(org.maemo.hermes.engine.service.Service):
8 """Facebook backend for Hermes.
10 This requires two gconf paths to contain Facebook application keys:
11 /apps/maemo/hermes/key_app
12 /apps/maemo/hermes/key_secret
14 Copyright (c) Andrew Flegg <andrew@bleb.org> 2010.
15 Released under the Artistic Licence."""
18 # -----------------------------------------------------------------------
19 def __init__(self, autocreate = False, gui_callback = None):
20 """Initialise the Facebook service, finding Facebook API keys in gconf and
21 having a gui_callback available."""
23 self._gc = gnome.gconf.client_get_default()
24 self._gui = gui_callback
25 self._autocreate = autocreate
27 # -- Check the environment is going to work...
29 if (self._gc.get_string('/desktop/gnome/url-handlers/http/command') == 'epiphany %s'):
30 raise Exception('Browser in gconf invalid (see NB#136012). Installation error.')
32 key_app = self._gc.get_string('/apps/maemo/hermes/key_app')
33 key_secret = self._gc.get_string('/apps/maemo/hermes/key_secret')
34 if key_app is None or key_secret is None:
35 raise Exception('No Facebook application keys found. Installation error.')
37 self.fb = Facebook(key_app, key_secret)
38 self.fb.desktop = True
41 self._friends_by_url = {}
42 self._should_create = set()
45 # -----------------------------------------------------------------------
46 def _do_fb_login(self):
47 """Perform authentication against Facebook and store the result in gconf
48 for later use. Uses the 'need_auth' and 'block_for_auth' methods on
49 the callback class. The former allows a message to warn the user
50 about what is about to happen to be shown; the second is to wait
51 for the user to confirm they have logged in."""
52 self.fb.session_key = None
59 self.fb.auth.createToken()
63 self._gui.block_for_auth()
65 session = self.fb.auth.getSession()
66 self._gc.set_string('/apps/maemo/hermes/session_key', session['session_key'])
67 self._gc.set_string('/apps/maemo/hermes/secret_key', session['secret'])
68 self._gc.set_string('/apps/maemo/hermes/uid', str(session['uid']))
71 # -----------------------------------------------------------------------
72 def get_friends(self):
73 """Return a list of friends from this service, or 'None' if manual mapping
77 return self._friends.values()
79 if self.fb.session_key is None:
80 self.fb.session_key = self._gc.get_string('/apps/maemo/hermes/session_key')
81 self.fb.secret = self._gc.get_string('/apps/maemo/hermes/secret_key')
82 self.fb.uid = self._gc.get_string('/apps/maemo/hermes/uid')
84 # Check the available session is still valid...
87 if self.fb.users.getLoggedInUser() and self.fb.session_key:
94 attrs = ['uid', 'name', 'pic_big', 'birthday_date', 'profile_url', 'first_name', 'last_name', 'website']
95 for friend in self.fb.users.getInfo(self.fb.friends.get(), attrs):
97 friend['key']= canonical(friend['name'])
98 self._friends[friend['key']] = friend
100 if 'profile_url' not in friend:
101 friend['profile_url'] = "http://www.facebook.com/profile.php?id=" + str(friend ['uid'])
103 self._friends_by_url[friend['profile_url']] = friend
104 friend['pic'] = friend[attrs[2]]
105 friend['account'] = 'Facebook'
107 if 'website' in friend and friend['website']:
108 friend['homepage'] = friend['website']
110 if 'birthday_date' in friend and friend['birthday_date']:
111 self._should_create.add(friend['profile_url'])
113 return self._friends.values()
116 # -----------------------------------------------------------------------
117 def process_contact(self, contact, overwrite = False, friend = None):
118 """Called for each contact in the address book. Any friends linked to
119 from the contact should have their matching updated. The backend should
120 enrich the contact with any meta-data it can; and return 'True' if any
121 information was updated. If 'friend' is provided, the information should
122 be retrieved from friend. This will be one of the entries from
123 'get_friends' when manual mapping is being done."""
125 if not self._friends:
128 matched_friend = None
129 for url in contact.get_urls():
130 if url in self._friends_by_url:
131 matched_friend = self._friends_by_url[url]
134 if not matched_friend:
135 for id in contact.get_identifiers():
136 if id in self._friends:
137 matched_friend = self._friends[id]
141 print contact.get_name(), " -> ", matched_friend['profile_url']
142 self._should_create.discard(matched_friend['profile_url'])
144 print contact.get_name(), " no match to Facebook with ", contact.get_identifiers()
148 # -----------------------------------------------------------------------
149 def finalise(self, updated, overwrite = False):
150 """Once all contacts have been processed, allows for any tidy-up/additional
151 enrichment. If any contacts are updated at this stage, 'updated' should
155 for url in self._should_create:
156 print "Need to autocreate:", self._friends_by_url[url]