Refactored Google plugins with support multiple scopes and a simpler API and added Google Fit plugin

This commit is contained in:
Fabio Manganiello 2019-03-14 01:12:39 +01:00
parent 022262eb78
commit 55c0896b31
6 changed files with 84 additions and 50 deletions

View File

@ -33,7 +33,7 @@ class GooglePlugin(Plugin):
* **google-api-python-client** (``pip install google-api-python-client``)
"""
def __init__(self, scopes, *args, **kwargs):
def __init__(self, scopes=None, *args, **kwargs):
"""
Initialized the Google plugin with the required scopes.
@ -42,11 +42,25 @@ class GooglePlugin(Plugin):
"""
super().__init__(*args, **kwargs)
self.credentials = {}
self._scopes = scopes or []
for scope in scopes:
self.credentials[scope] = get_credentials(scope)
scopes = ' '.join(sorted(self._scopes))
self.credentials = {
scopes: get_credentials(scopes)
}
def get_service(self, service, version, scopes=None):
import httplib2
from apiclient import discovery
if scopes is None:
scopes = getattr(self, 'scopes') if hasattr(self, 'scopes') else []
scopes = ' '.join(sorted(scopes))
credentials = self.credentials[scopes]
http = credentials.authorize(httplib2.Http())
return discovery.build(service, version, http=http, cache_discovery=False)
# vim:sw=4:ts=4:et:

View File

@ -4,11 +4,8 @@
import base64
import datetime
import httplib2
import os
from apiclient import discovery
from platypush.plugins import action
from platypush.plugins.google import GooglePlugin
from platypush.plugins.calendar import CalendarInterface
@ -33,7 +30,7 @@ class GoogleCalendarPlugin(GooglePlugin, CalendarInterface):
"""
now = datetime.datetime.utcnow().isoformat() + 'Z'
service = self._get_service()
service = self.get_service('calendar', 'v3')
result = service.events().list(calendarId='primary', timeMin=now,
maxResults=max_results, singleEvents=True,
orderBy='startTime').execute()
@ -42,14 +39,5 @@ class GoogleCalendarPlugin(GooglePlugin, CalendarInterface):
return events
def _get_service(self, scope=None):
if scope is None:
scope = self.scopes[0]
credentials = self.credentials[scope]
http = credentials.authorize(httplib2.Http())
return discovery.build('calendar', 'v3', http=http, cache_discovery=False)
# vim:sw=4:ts=4:et:

View File

@ -8,21 +8,19 @@ from oauth2client import tools
from oauth2client.file import Storage
def get_credentials_filename(scope):
def get_credentials_filename(*scopes):
from platypush.config import Config
scope_name = scope.split('/')[-1]
scope_name = '-'.join([scope.split('/')[-1] for scope in scopes])
credentials_dir = os.path.join(
Config.get('workdir'), 'credentials', 'google')
if not os.path.exists(credentials_dir):
os.makedirs(credentials_dir)
os.makedirs(credentials_dir, exist_ok=True)
return os.path.join(credentials_dir, scope_name + '.json')
def get_credentials(scope):
credentials_file = get_credentials_filename(scope)
credentials_file = get_credentials_filename(*sorted(scope.split(' ')))
if not os.path.exists(credentials_file):
raise RuntimeError(('Credentials file {} not found. Generate it through:\n' +
'\tpython -m platypush.plugins.google.credentials "{}" ' +
@ -43,7 +41,7 @@ def get_credentials(scope):
def generate_credentials(client_secret_path, scope):
credentials_file = get_credentials_filename(scope)
credentials_file = get_credentials_filename(*sorted(scope.split(' ')))
store = Storage(credentials_file)
flow = client.flow_from_clientsecrets(client_secret_path, scope)
@ -62,7 +60,7 @@ def main():
"""
scope = sys.argv.pop(1) if len(sys.argv) > 1 \
else input('Comma separated list of OAuth scopes: ')
else input('Space separated list of OAuth scopes: ')
client_secret_path = os.path.expanduser(
sys.argv.pop(1) if len(sys.argv) > 1

View File

@ -0,0 +1,55 @@
from apiclient import discovery
from platypush.plugins import action
from platypush.plugins.google import GooglePlugin
class GoogleFitPlugin(GooglePlugin):
"""
Google Fit plugin
"""
scopes = ['https://www.googleapis.com/auth/fitness.activity.read',
'https://www.googleapis.com/auth/fitness.body.read',
'https://www.googleapis.com/auth/fitness.body_temperature.read',
'https://www.googleapis.com/auth/fitness.location.read']
def __init__(self, user_id='me', *args, **kwargs):
"""
:param user_id: Default Google user_id (default: 'me', default
configured account user)
:type user_id: str or int
"""
super().__init__(scopes=self.scopes, *args, **kwargs)
self.user_id = user_id
@action
def get_data_sources(self, user_id=None):
"""
Get the available data sources for the specified user_id
"""
service = self.get_service(service='fitness', version='v1')
sources = service.users().dataSources(). \
list(userId=user_id or self.user_id).execute()
return sources['dataSource']
@action
def get_data(self, data_source_id, user_id=None):
"""
Get raw data for the specified data_source_id
:param data_source_id: Data source ID, see `get_data_sources`
:type data_source_id: str
"""
service = self.get_service(service='fitness', version='v1')
return service.users().dataSources().dataPointChanges() \
.list(dataSourceId=data_source_id, userId=user_id or self.user_id) \
.execute().get('insertedDataPoint', [])
# vim:sw=4:ts=4:et:

View File

@ -87,7 +87,7 @@ class GoogleMailPlugin(GooglePlugin):
msg.add_header('Content-Disposition', 'attachment', filename=filename)
message.attach(msg)
service = self._get_service()
service = self.get_service('gmail', 'v1')
body = { 'raw': base64.urlsafe_b64encode(message.as_bytes()).decode() }
message = (service.users().messages().send(
userId='me', body=body).execute())
@ -100,18 +100,10 @@ class GoogleMailPlugin(GooglePlugin):
"""
Returns the available labels on the GMail account
"""
service = self._get_service()
service = self.get_service('gmail', 'v1')
results = service.users().labels().list(userId='me').execute()
labels = results.get('labels', [])
return labels
def _get_service(self):
scope = self.scopes[0]
credentials = self.credentials[scope]
http = credentials.authorize(httplib2.Http())
return discovery.build('gmail', 'v1', http=http, cache_discovery=False)
# vim:sw=4:ts=4:et:

View File

@ -4,11 +4,8 @@
import base64
import datetime
import httplib2
import os
from apiclient import discovery
from platypush.plugins import action
from platypush.plugins.google import GooglePlugin
from platypush.plugins.calendar import CalendarInterface
@ -62,7 +59,7 @@ class GoogleYoutubePlugin(GooglePlugin, CalendarInterface):
if isinstance(types, list):
types = ','.join(types)
service = self._get_service()
service = self.get_service('youtube', 'v3')
result = service.search().list(part=parts, q=query, type=types,
maxResults=max_results,
**kwargs).execute()
@ -71,14 +68,4 @@ class GoogleYoutubePlugin(GooglePlugin, CalendarInterface):
return events
def _get_service(self, scope=None):
if scope is None:
scope = self.scopes[0]
credentials = self.credentials[scope]
http = credentials.authorize(httplib2.Http())
return discovery.build('youtube', 'v3', http=http, cache_discovery=False)
# vim:sw=4:ts=4:et: