Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Borden <adborden@live.com>2013-04-17 15:46:25 (GMT)
committer Aaron Borden <adborden@live.com>2013-04-17 15:46:25 (GMT)
commit3d160c87403993347cfa67161c860972c6e5ba66 (patch)
treeee7f6bedd8dec02c0c02a53fbeaf65c8a8b626bb
parent367f24b01dc5e9eccddbc2b8b255b66110ebcc50 (diff)
Beginning implementation of GDrivegoogle-drive
-rw-r--r--extensions/web/google/google.py191
-rw-r--r--extensions/web/google/google_online_account.py17
2 files changed, 107 insertions, 101 deletions
diff --git a/extensions/web/google/google.py b/extensions/web/google/google.py
index 9ee669d..2d0373e 100644
--- a/extensions/web/google/google.py
+++ b/extensions/web/google/google.py
@@ -20,18 +20,46 @@
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
+import httplib
import json
import logging
-import pycurl
+import mimetypes
import time
import urllib
+import urllib2
+import os
from gi.repository import GObject
-class GDriveAccount():
+class GoogleAccount():
+ APP_ID = "634890811982.apps.googleusercontent.com"
+ SCOPE = [
+ 'https://www.googleapis.com/auth/drive.file',
+ 'https://www.googleapis.com/auth/userinfo.email'
+ ]
+ REDIRECT_URI = "http://localhost"
+
+ _refresh_token = ""
_access_token = ""
@classmethod
+ def auth_url(cls):
+ url = 'https://accounts.google.com/o/oauth2/auth'
+ params = [
+ ('client_id', cls.APP_ID),
+ ('redirect_uri', cls.REDIRECT_URI),
+ ('response_type', 'code'),
+ ('scope', ' '.join(cls.SCOPE)),
+ ('state', 'auth_cb')
+ ]
+
+ return "%s?%s" % (url, urllib.urlencode(params))
+
+ @classmethod
+ def set_refresh_token(cls, refresh_token):
+ cls._refresh_token = refresh_token
+
+ @classmethod
def set_access_token(cls, access_token):
cls._access_token = access_token
@@ -39,6 +67,17 @@ class GDriveAccount():
def access_token(cls):
return cls._access_token
+ @classmethod
+ def refresh_access_token(cls, token):
+ token_url = 'https://accounts.google.com/o/oauth2/token'
+ params = [
+ ('client_id', cls.APP_ID),
+ ('refresh_token', token),
+ ('grant_type', 'refresh_token')
+ ]
+
+ return json.load(urllib2.urlopen(token_url, urllib.urlencode(params)))
+
class GDriveObjectNotCreatedException(Exception):
pass
@@ -46,132 +85,86 @@ class GDriveBadCall(Exception):
pass
class GDriveFile(GObject.GObject):
- API_URL = 'https://www.googleapis.com/drive/v2'
- FILES_URL = "/files"
__gsignals__ = {
'file-created': (GObject.SignalFlags.RUN_FIRST, None, ([str])),
'file-create-failed': (GObject.SignalFlags.RUN_FIRST, None, ([str])),
}
- def __init__(self, fb_object_id=None):
+ def __init__(self, gdrive_object_id=None):
GObject.GObject.__init__(self)
- self.fb_object_id = fb_object_id
+ self.gdrive_object_id = gdrive_object_id
def create(self, file_path):
GObject.idle_add(self._create, file_path)
def check_created(self, method_name):
- if self.fb_object_id is None:
+ if self.gdrive_object_id is None:
errmsg = "Need to call create before calling %s" % (method_name)
raise GDriveObjectNotCreatedException(errmsg)
def _create(self, file_path):
- url = self.PHOTOS_URL % (GDriveAccount.access_token())
- c = pycurl.Curl()
- params = [('source', (c.FORM_FILE, file_path))]
-
- response = []
- def write_cb(buf):
- response.append(buf)
-
- result = self._http_call(url, params, write_cb, post=True)
- if result == 200:
- photo_id = self._id_from_response("".join(response))
- self.fb_object_id = photo_id
- self.emit('file-created', photo_id)
- else:
- logging.debug("_create failed, HTTP resp code: %d" % result)
-
- if result == 400:
- failed_reason = "Expired access token."
- elif result == 6:
- failed_reason = "Network is down."
- failed_reason += \
- "Please connect to the network and try again."
- else:
- failed_reason = "Failed reason unknown: %s" % (str(result))
-
- self.emit('photo-create-failed', failed_reason)
-
- def _id_from_response(self, response_str):
- response_object = json.loads(response_str)
-
- if not "id" in response_object:
- raise FbBadCall(response_str)
-
- fb_object_id = response_object['id'].encode('ascii', 'replace')
- return fb_object_id
-
- def _refresh_comments(self):
- """ this blocks """
- url = self.COMMENTS_URL % (self.fb_object_id)
+ # Upload the file
+ response = self._http_call('POST', '/upload/drive/v2/files?uploadType=media', file_path) #TODO use the resumable interface
+ if not self._check_success('_upload', response):
+ return
- logging.debug("_refresh_comments fetching %s" % (url))
+ data = json.loads(response.read())
+ if not 'id' in data:
+ raise GDriveBadCall(data)
- response_comments = []
- def write_cb(buf):
- response_comments.append(buf)
+ self.gdrive_object_id = data['id']
- ret = self._http_call(url, [], write_cb, post=False)
- if ret != 200:
- logging.debug("_refresh_comments failed, HTTP resp code: %d" % ret)
- self.emit('comments-download-failed',
- "Comments download failed: %d" % (ret))
- return
+ # Update metadata
+ url = '/drive/v2/files'
+ params = {
+ 'title': os.path.basename(file_path),
+ 'description': 'A Sugar Journal file'
+ }
- logging.debug("_refresh_comments: %s" % ("".join(response_comments)))
-
- try:
- response_data = json.loads("".join(response_comments))
- if 'data' not in response_data:
- logging.debug("No data inside the FB response")
- self.emit('comments-download-failed',
- "Comments download failed with no data")
- return
- except Exception as ex:
- logging.debug("Couldn't parse FB response: %s" % str(ex))
- self.emit('comments-download-failed',
- "Comments download failed: %s" % (str(ex)))
+ response = self._http_call('PUT', '%s/%s' % (url, self.gdrive_object_id), params)
+ if not self._check_success('_create', response):
return
- comments = []
- for c in response_data['data']:
- comment = {} # this should be an Object
- comment['from'] = c['from']['name']
- comment['message'] = c['message']
- comment['created_time'] = c['created_time']
- comment['like_count'] = c['like_count']
- comments.append(comment)
-
- if len(comments) > 0:
- self.emit('comments-downloaded', comments)
- else:
- self.emit('comments-download-failed', 'No comments found')
+ self.emit('file-created', self.gdrive_object_id)
- def _http_call(self, url, params, write_cb, post=False):
- app_auth_params = [('access_token', FbAccount.access_token())]
+ def _http_call(self, method, url, params = None):
+ if not params:
+ params = {}
- c = pycurl.Curl()
- c.setopt(c.WRITEFUNCTION, write_cb)
+ headers = {
+ 'Authorization': "Bearer %s" % (self.access_token())
+ }
- if post:
- c.setopt(c.POST, 1)
- c.setopt(c.HTTPPOST, app_auth_params + params)
+ if isinstance(params, basestring):
+ mimetype, encoding = mimetypes.guess_type(params, strict=False)
+ if mimetype:
+ headers['Content-Type'] = mimetype
+ if encoding:
+ headers['Content-Encoding'] = encoding
+ params = open(params, 'rb')
else:
- c.setopt(c.HTTPGET, 1)
- params_str = urllib.urlencode(app_auth_params + params)
- url = "%s?%s" % (url, params_str)
+ params = json.dumps(params)
+ headers['Content-Type'] = 'application/json'
- logging.debug("_http_call: %s" % (url))
+ conn = httplib.HTTPSConnection('www.googleapis.com')
+ conn.request(method, url, params, headers)
- c.setopt(c.URL, url)
- c.perform()
- result = c.getinfo(c.HTTP_CODE)
- c.close()
+ return conn.getresponse()
- return result
+ def _check_success(self, operation, response):
+ if response.status and response.status == 200:
+ return True
+
+ logging.debug("%s failed, HTTP resp code: %d" % (operation, response.status))
+ if response.status == 401:
+ failed_reason = "Expired access token."
+ else:
+ failed_reason = "Failed reason unknown: %s" % (str(response))
+ print failed_reason
+ self.emit('file-create-failed', failed_reason)
+ return False
if __name__ == '__main__':
import sys
@@ -180,7 +173,7 @@ if __name__ == '__main__':
exit(1)
access_token, file_path = sys.argv[1:3]
- GDriveAccount.set_access_token(access_token)
+ GoogleAccount.set_access_token(access_token)
def test_create_file(loop):
diff --git a/extensions/web/google/google_online_account.py b/extensions/web/google/google_online_account.py
index c0f556b..973510b 100644
--- a/extensions/web/google/google_online_account.py
+++ b/extensions/web/google/google_online_account.py
@@ -54,10 +54,20 @@ class GoogleOnlineAccount(online_account.OnlineAccount):
def __init__(self):
online_account.OnlineAccount.__init__(self)
self._client = GConf.Client.get_default()
- google.GDriveAccount.set_access_token(self._access_token())
+ google.GoogleAccount.set_refresh_token(self._refresh_token())
+ google.GoogleAccount.set_access_token(self._access_token())
+
+ if not self.is_active():
+ data = google.GoogleAccount.refresh_access_token(self._refresh_token())
+ client = self._client
+ client.set_string(self.ACCESS_TOKEN_KEY, data.access_token)
+ expiry_time = int(time.time()) + data.expires_in
+ client.set_int(self.ACCESS_TOKEN_KEY_EXPIRATION_DATE,
+ expiry_time)
+ google.GoogleAccount.set_access_token(self._access_token())
def is_configured(self):
- return self._access_token() is not None
+ return self._refresh_token() is not None
def is_active(self):
expiration_date = \
@@ -78,6 +88,9 @@ class GoogleOnlineAccount(online_account.OnlineAccount):
def get_refresh_button(self):
return FacebookRefreshButton(self.is_active())
+ def _refresh_token(self):
+ return self._client.get_string(self.REFRESH_TOKEN_KEY)
+
def _access_token(self):
return self._client.get_string(self.ACCESS_TOKEN_KEY)