Dependency inject service ID, so that it can be stamped on friends and
[hermes] / package / src / org / maemo / hermes / engine / facebook / provider.py
1 from facebook import Facebook, FacebookError
2 import gnome.gconf
3 import gtk, hildon
4 import org.maemo.hermes.engine.provider
5 import org.maemo.hermes.engine.facebook.service
6
7 class Provider(org.maemo.hermes.engine.provider.Provider):
8     """Facebook provider for Hermes. 
9
10        This requires two gconf paths to contain Facebook application keys:
11            /apps/maemo/hermes/facebook_app
12            /apps/maemo/hermes/facebook_secret
13        
14        Copyright (c) Andrew Flegg <andrew@bleb.org> 2010.
15        Released under the Artistic Licence."""
16
17     # -----------------------------------------------------------------------
18     def __init__(self):
19         """Initialise the provider, and ensure the environment is going to work."""
20
21         self._gc = gnome.gconf.client_get_default()
22
23         key_app    = self._gc.get_string('/apps/maemo/hermes/facebook_app')
24         key_secret = self._gc.get_string('/apps/maemo/hermes/facebook_secret')
25         if key_app is None or key_secret is None:
26             raise Exception('No Facebook application keys found. Installation error.')
27         
28         self.fb = Facebook(key_app, key_secret)
29         self.fb.desktop = True
30
31         if self.fb.session_key is None:
32             self.fb.session_key = self._gc.get_string('/apps/maemo/hermes/facebook_session_key')
33             self.fb.secret = self._gc.get_string('/apps/maemo/hermes/facebook_secret_key')
34             self.fb.uid = self._gc.get_string('/apps/maemo/hermes/facebook_uid')
35
36
37     # -----------------------------------------------------------------------
38     def get_name(self):
39         """Return the display name of this service. An icon, of with the lower-case,
40            all-alphabetic version of this name is expected to be provided."""
41            
42         return 'Facebook'
43
44     
45     # -----------------------------------------------------------------------
46     def get_account_detail(self):
47         """Return the email address associated with the user, if available."""
48         
49         name = self._gc.get_string('/apps/maemo/hermes/facebook_user')
50         return name and name or _('Pending authorisation')
51     
52     
53     # -----------------------------------------------------------------------
54     def has_preferences(self):
55         """Whether or not this provider has any preferences. If it does not,
56            open_preferences must NOT be called; as the behaviour is undetermined."""
57            
58         return True
59     
60     
61     # -----------------------------------------------------------------------
62     def open_preferences(self, parent):
63         """Open the preferences for this provider as a child of the 'parent' widget."""
64
65         dialog = gtk.Dialog(self.get_name(), parent)
66         dialog.add_button(_('Disable'), gtk.RESPONSE_NO)
67         dialog.add_button(_('Enable'), gtk.RESPONSE_YES)
68         
69         checkbox = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
70         checkbox.set_label(_('Create birthday-only contacts'))
71         checkbox.set_active(self._gc.get_bool('/apps/maemo/hermes/facebook_birthday_only'))
72         dialog.vbox.add(checkbox)
73         dialog.vbox.add(gtk.Label("\n" + _('Note: authentication via web page') + "\n"))
74         
75         clear = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT,
76                               hildon.BUTTON_ARRANGEMENT_VERTICAL,
77                               title = _("Clear authorisation"))
78         clear.connect('clicked', self._clear_auth)
79         dialog.vbox.add(clear)
80         
81         dialog.show_all()
82         result = dialog.run()
83         dialog.hide()
84         if result == gtk.RESPONSE_CANCEL or result == gtk.RESPONSE_DELETE_EVENT:
85             return None
86     
87         self._gc.set_bool('/apps/maemo/hermes/facebook_birthday_only', checkbox.get_active())
88         return result == gtk.RESPONSE_YES
89
90
91     # -----------------------------------------------------------------------
92     def _clear_auth(self, event):
93         """Clear Facebook authorisation information. Triggered by pressing
94            the 'clear' button in the preferences dialogue."""
95         
96         self._gc.unset('/apps/maemo/hermes/facebook_session_key')
97         self._gc.unset('/apps/maemo/hermes/facebook_secret_key')
98         self._gc.unset('/apps/maemo/hermes/facebook_uid')
99         self._gc.unset('/apps/maemo/hermes/facebook_user')
100
101     
102     # -----------------------------------------------------------------------
103     def service(self, gui_callback):
104         """Return a service instance."""
105         
106         self._gui = gui_callback
107         
108         # Check the available session is still valid...
109         while True:
110             try:
111                 if self.fb.users.getLoggedInUser() and self.fb.session_key:
112                     break
113             except FacebookError:
114                 pass
115             self._do_fb_login()
116
117         return org.maemo.hermes.engine.facebook.service.Service(self.get_id(), self.fb, self._gc.get_bool('/apps/maemo/hermes/facebook_birthday_only'))
118
119
120     # -----------------------------------------------------------------------
121     def _do_fb_login(self):
122         """Perform authentication against Facebook and store the result in gconf
123              for later use. Uses the 'need_auth' and 'block_for_auth' methods on
124              the callback class. The former allows a message to warn the user
125              about what is about to happen to be shown; the second is to wait
126              for the user to confirm they have logged in."""
127         self.fb.session_key = None
128         self.fb.secret = None
129         self.fb.uid = None
130         
131         if self._gui:
132             self._gui.need_auth()
133             
134         self.fb.auth.createToken()
135         self.fb.login()
136         
137         if self._gui:
138             self._gui.block_for_auth()
139           
140         session = self.fb.auth.getSession()
141         self._gc.set_string('/apps/maemo/hermes/facebook_session_key', session['session_key'])
142         self._gc.set_string('/apps/maemo/hermes/facebook_secret_key', session['secret'])
143         self._gc.set_string('/apps/maemo/hermes/facebook_uid', str(session['uid']))
144
145         info = self.fb.users.getInfo([self.fb.uid], ['name'])
146         self._gc.set_string('/apps/maemo/hermes/facebook_user', info[0]['name'])
147