Skip to content

Instantly share code, notes, and snippets.

@mrzmyr
Created January 7, 2019 13:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrzmyr/7d0153f5b65a4316145f4f7789202f96 to your computer and use it in GitHub Desktop.
Save mrzmyr/7d0153f5b65a4316145f4f7789202f96 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import cherrypy
import os
import sys
import threading
import traceback
import webbrowser
from base64 import b64encode
from fitbit.api import Fitbit
from oauthlib.oauth2.rfc6749.errors import MismatchingStateError, MissingTokenError
class OAuth2Server:
def __init__(self, client_id, client_secret,
redirect_uri='http://127.0.0.1:8080/'):
""" Initialize the FitbitOauth2Client """
self.success_html = """
<h1>You are now authorized to access the Fitbit API!</h1>
<br/><h3>You can close this window</h3>"""
self.failure_html = """
<h1>ERROR: %s</h1><br/><h3>You can close this window</h3>%s"""
self.fitbit = Fitbit(
client_id,
client_secret,
redirect_uri=redirect_uri,
timeout=10,
)
def browser_authorize(self):
"""
Open a browser to the authorization url and spool up a CherryPy
server to accept the response
"""
url, _ = self.fitbit.client.authorize_token_url()
# Open the web browser in a new thread for command-line browser support
threading.Timer(1, webbrowser.open, args=(url,)).start()
cherrypy.quickstart(self)
@cherrypy.expose
def index(self, state, code=None, error=None):
"""
Receive a Fitbit response containing a verification code. Use the code
to fetch the access_token.
"""
error = None
if code:
try:
self.fitbit.client.fetch_access_token(code)
except MissingTokenError:
error = self._fmt_failure(
'Missing access token parameter.</br>Please check that '
'you are using the correct client_secret')
except MismatchingStateError:
error = self._fmt_failure('CSRF Warning! Mismatching state')
else:
error = self._fmt_failure('Unknown error while authenticating')
# Use a thread to shutdown cherrypy so we can return HTML first
self._shutdown_cherrypy()
return error if error else self.success_html
def _fmt_failure(self, message):
tb = traceback.format_tb(sys.exc_info()[2])
tb_html = '<pre>%s</pre>' % ('\n'.join(tb)) if tb else ''
return self.failure_html % (message, tb_html)
def _shutdown_cherrypy(self):
""" Shutdown cherrypy in one second, if it's running """
if cherrypy.engine.state == cherrypy.engine.states.STARTED:
threading.Timer(1, cherrypy.engine.exit).start()
if __name__ == '__main__':
if not (len(sys.argv) == 3):
print("Arguments: client_id and client_secret")
sys.exit(1)
server = OAuth2Server(*sys.argv[1:])
server.browser_authorize()
profile = server.fitbit.user_profile_get()
print('You are authorized to access data for the user: {}'.format(
profile['user']['fullName']))
print('TOKEN\n=====\n')
for key, value in server.fitbit.client.session.token.items():
print('{} = {}'.format(key, value))
import fitbit
import gather_keys_oauth2 as Oauth2
import datetime
import json
def save_json(path, data):
with open(path, 'w') as outfile:
json.dump(data, outfile)
CLIENT_ID = ''
CLIENT_SECRET = ''
server = Oauth2.OAuth2Server(CLIENT_ID, CLIENT_SECRET)
server.browser_authorize()
ACCESS_TOKEN = str(server.fitbit.client.session.token['access_token'])
REFRESH_TOKEN = str(server.fitbit.client.session.token['refresh_token'])
authd_client = fitbit.Fitbit(
CLIENT_ID,
CLIENT_SECRET,
oauth2=True,
access_token=ACCESS_TOKEN,
refresh_token=REFRESH_TOKEN
)
y = str((datetime.datetime.now() - datetime.timedelta(days=14)).strftime("%Y-%m-%d"))
steps = authd_client.intraday_time_series('activities/steps', base_date=y)
heart = authd_client.intraday_time_series('activities/heart', base_date=y)
profile = authd_client.user_profile_get()
save_json('./dist/steps.json', steps)
save_json('./dist/heart.json', heart)
save_json('./dist/profile.json', profile)
authd_client.sleep()
fitbit==0.3.0
CherryPy==18.1.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment