def authenticate(): ## Strava API uses OAuth2, which requires users to manually allow permission, which generates ## a token only valid for a number of hours. ## get API client id and secret from config file config = configparser.ConfigParser() config.read("credentials.cfg") client_id = config.get('credentials', 'client_id') client_secret = config.get('credentials', 'client_secret') client = Client(rate_limiter=limiter.DefaultRateLimiter()) authorize_url = client.authorization_url( client_id=client_id, redirect_uri='http://localhost:8282/authorized') ## getting token -- pretty manual process for now webbrowser.open_new_tab(authorize_url) code = input('Enter Temporary Code: ') code = str(code) ## authenticate using API credntials + token token_response = client.exchange_code_for_token( client_id=client_id, client_secret=client_secret, code=code) return client
def get(request): """ Request -and store- a strava access token. """ client = Client() # Extract the code from the response code = request.GET.get('code') access_token = client.exchange_code_for_token( client_id=settings.STRAVA_CLIENT_ID, client_secret=settings.STRAVA_CLIENT_SECRET, code=code ) strava_athlete = client.get_athlete() try: athlete = Athlete.objects.get(strava_id=strava_athlete.id) athlete.strava_token = access_token except Athlete.DoesNotExist: athlete = Athlete(strava_id=strava_athlete.id, strava_token=access_token) athlete.save() cache_key = _get_cache_key(request) cache.delete(cache_key) redir_url = '{}?start_date={}&end_date={}'.format( reverse_lazy('strava-summary'), _get_start_date(request), _get_end_date(request) ) return HttpResponseRedirect(redir_url)
def get(self): code = self.request.get('code') client = Client() access_token = client.exchange_code_for_token(client_id=conf.SV_CLIENT_ID, client_secret=conf.SV_CLIENT_SECRET, code=code) user_id = UserManager().AddUserToken(access_token) self.redirect('/user/{0}'.format(user_id))
def auth_done(request): code = request.GET.get('code') client = Client() access_token = client.exchange_code_for_token(client_id=CLIENT_ID, client_secret=CLIENT_SECRET, code=code) request.session['access_token'] = access_token return redirect('home')
def get_token(client_id, client_secret, code): """Exchange a temporary code for a permanent token""" client = Client() response = client.exchange_code_for_token(client_id = client_id, client_secret = client_secret, code = code) print("[+] A new permanent token was generated, with the following details:\n\t- access token: {}\n\t- refresh access token: {}\n\t- expireS at: {}".format(response["access_token"], response["refresh_token"], response["expires_at"]))
def authorization(): code = request.args.get('code') client = Client() access_token = client.exchange_code_for_token(client_id=MY_STRAVA_CLIENT_ID, client_secret=MY_STRAVA_CLIENT_SECRET, code=code) response = redirect("/") response.set_cookie('access_token', access_token) return response
def oauth_authorized(): client = Client() code = request.args.get('code') access_token = client.exchange_code_for_token( client_id=CLIENT_ID, client_secret=CLIENT_SECRET, code=code) session['access_token'] = access_token return redirect(url_for('index'))
def authorized(): code = request.args.get('code') page = request.args.get('page') client = Client() token_struct = client.exchange_code_for_token(client_id=CLIENT_ID, client_secret=CLIENT_SECRET, code=code) session['token_struct'] = token_struct return redirect(page, code=302)
def oauth_authorized(): client = Client() code = request.args.get('code') access_token = client.exchange_code_for_token( client_id=CLIENT_ID, client_secret=CLIENT_SECRET, code=code) session['access_token'] = access_token return redirect(url_for('index'))
def __init__(self, token): if not token: client = Client() url = client.authorization_url(client_id=STRAVA_APP_ID, redirect_uri='http://localhost:8000/') code = input(f"Open {url}, copy code once redirected: ") token_response = client.exchange_code_for_token(client_id=STRAVA_APP_ID, client_secret=STRAVA_CLIENT_SECRET, code=code) self.STRAVA_ACCESS_TOKEN = token_response['access_token'] else: self.STRAVA_ACCESS_TOKEN = token
def create_authentication_token(): logger = logging.getLogger("authenticator.create_authentication_token") client = Client() logger.info( "This is a one-time operation to generate the required authentication tokens for the app. Please follow the steps carefully" ) logger.info("") logger.info( "Follow the instructions here: https://developers.strava.com/docs/getting-started/#account to create an 'API Application'" ) logger.info( "The important bits: Set the 'authorization callback domain' to 'localhost'" ) logger.info( "Make a note of the 'Client ID' and 'Client Secret' values (you may have to click 'show' to see the value of the secret" ) logger.info("") logger.info( "Create a file called 'client.secret' and place it in the strava_data directory" ) input("Once you have performed the above steps, hit enter") MY_STRAVA_CLIENT_ID, MY_STRAVA_CLIENT_SECRET = open( '/opt/strava_data/client.secret').read().strip().split(',') logger.info( 'Client ID ({}) and secret read from file'.format(MY_STRAVA_CLIENT_ID)) url = client.authorization_url( client_id=MY_STRAVA_CLIENT_ID, redirect_uri='http://127.0.0.1:5000/authorization', scope=[ 'read_all', 'profile:read_all', 'activity:read_all', 'profile:write', 'activity:write' ]) logger.info("Open the following URL in a browser and approve access:") logger.info(url) auth_url_eg = "http://127.0.0.1:5000/authorization?state=&code=1e6878eb4b0175123e87bd8d708c40717448ac33&scope=read,activity:read_all,profile:read_all,read_all" code_eg = "1e6878eb4b0175123e87bd8d708c40717448ac33" logger.info( "The re-directed URL will look something like this: {}, please enter just the 'code' value now e.g. {}" .format(auth_url_eg, code_eg)) CODE = input() access_token = client.exchange_code_for_token( client_id=MY_STRAVA_CLIENT_ID, client_secret=MY_STRAVA_CLIENT_SECRET, code=CODE) logger.info( "Access_token: {}, outputting to local file".format(access_token)) with open('/opt/strava_data/access_token.pickle', 'wb') as f: pickle.dump(access_token, f)
def set_access_token(request): """ Exchange the provided code for an access token and store it """ # Our strava code json = request.json_body code = json['code'] # If we don't have a strava secret, we can't make the key exchange if 'strava' not in request.registry.settings['secrets']: request.response.status_int = 500 return # Exchange the code for an access token # The API will throw an unspecified error if code is invalid. # Catch that rather than taking down the server. access_token = "" try: client = StravaClient() access_token = client.exchange_code_for_token( client_id=request.registry.settings['secrets']['strava'] ['strava_id'], client_secret=request.registry.settings['secrets']['strava'] ['strava_secret'], code=code) except: # Return an error request.response.status_int = 502 return # Our admin object admin = _get_admin(request) #Create the access token if it doesn't exist, or update the stored one if not admin.exists_document('strava_access_token'): # Store the access token admin.create_document({'strava_access_token': access_token}, doc_id='strava_access_token') else: # Update the stored access token stored_access_token = admin.get_document('strava_access_token') try: admin.update_document({ 'strava_access_token': access_token, '_id': 'strava_access_token', '_rev': stored_access_token['_rev'] }) except: # We likely hit a race condition where the _rev is no longer valid. Return accordingly. request.response.status_int = 409 return # Return appropriately request.response.status_int = 200 return {'access_token': access_token}
def parse_args(args): access_token_file_name = args.output_file client = Client() access_token_does_exist = os.path.isfile(access_token_file_name) access_token_doesnt_exist = not (access_token_does_exist) access_token_expired = True if access_token_does_exist: with open(access_token_file_name, "r") as f: token_response = json.load(f) token_response = json.loads(token_response) token_expiry_time = token_response["expires_at"] current_time = time.time() access_token_expired = current_time > token_expiry_time if access_token_doesnt_exist or access_token_expired: client_id = args.client_id client_secret = args.client_secret scope = [ "read", "read_all", "profile:read_all", "activity:read", "activity:read_all", ] authorize_url = client.authorization_url( client_id=client_id, redirect_uri="http://localhost:5000/authorized", scope=scope, ) # Open the authorization url print("Opening: " + authorize_url) webbrowser.open(authorize_url) # Get code entered_code = str(input("Please enter code: ")) # Exchange code for token: token_response = client.exchange_code_for_token( client_id=client_id, client_secret=client_secret, code=entered_code ) # Save it to file so we can use it until it expires. access_token_string = json.dumps(token_response) with open(access_token_file_name, "w+") as f: json.dump(access_token_string, f) # Now we have a token_response dict either from file or from the # Strava API access_token = token_response["access_token"] refresh_token = token_response["refresh_token"] print("access_token:", access_token) print("refresh_token", refresh_token)
def authorized_callback(): client = Client() # Extract the code from your webapp response code = request.args.get('code') access_token = client.exchange_code_for_token( client_id=CONSTANTS.CLIENT_ID, client_secret=CONSTANTS.CLIENT_SECRET, code=code) # Now store that access token along with athlete details add_athlete(access_token) #return jsonify({"status": "success"}) return redirect("http://34.211.61.161:3000/", code=302)
def auth(): try: code = request.args["code"] c = Client() token = c.exchange_code_for_token(app.config['STRAVA_ID'], app.config['STRAVA_SECRET'], code) except (KeyError, requests.exceptions.HTTPError): return redirect("/") session["token"] = c.access_token = token a = c.get_athlete() # Technically shouldn't be needed as the athlete details are returned in the oauth call session["athlete"] = {"firstname": a.firstname, "picture": a.profile_medium} return redirect("/")
def set_access_token(request): """ Exchange the provided code for an access token and store it """ # Our strava code json = request.json_body code = json['code'] # If we don't have a strava secret, we can't make the key exchange if 'strava' not in request.registry.settings['secrets']: request.response.status_int = 500 return # Exchange the code for an access token # The API will throw an unspecified error if code is invalid. # Catch that rather than taking down the server. access_token = "" try: client = StravaClient() access_token = client.exchange_code_for_token(client_id=request.registry.settings['secrets']['strava']['strava_id'], client_secret=request.registry.settings['secrets']['strava']['strava_secret'], code=code) except: # Return an error request.response.status_int = 502 return # Our admin object admin = _get_admin(request) #Create the access token if it doesn't exist, or update the stored one if not admin.exists_document('strava_access_token'): # Store the access token admin.create_document({'strava_access_token': access_token}, doc_id='strava_access_token') else: # Update the stored access token stored_access_token = admin.get_document('strava_access_token') try: admin.update_document({'strava_access_token': access_token, '_id':'strava_access_token', '_rev':stored_access_token['_rev']}) except: # We likely hit a race condition where the _rev is no longer valid. Return accordingly. request.response.status_int = 409 return # Return appropriately request.response.status_int = 200 return { 'access_token': access_token }
def get_client(): client = Client() authorize_url = client.authorization_url( client_id=26273, redirect_uri='https://localhost:8080', scope=['read', 'read_all', 'activity:read_all']) code = '299ad7943b6eb478247684620d87e341cfdcb6a2' access_token = client.exchange_code_for_token( client_id=26273, client_secret='80f4236b6e958701dbeebb8c09c99e9d2fb71d1a', code=code) client.access_token = access_token['access_token'] return client
def strava_login(): code = request.args.get('code') client = Client() cid = current_app.config['STRAVA_CLIENT_ID'] csecret = current_app.config['STRAVA_CLIENT_SECRET'] access_token = client.exchange_code_for_token(client_id=cid, client_secret=csecret, code=code) athlete = client.get_athlete() email = athlete.email send_user_to_dataservice(email, access_token) session['user'] = email session['token'] = access_token return redirect('/')
def authorized(): # get access token to make requests client = Client() code = request.args.get('code') client.access_token = client.exchange_code_for_token(client_id=creds.client_id, client_secret=creds.client_secret, code=code) # add id and secret # get data today = datetime.datetime.strptime(str(datetime.date.today()), "%Y-%m-%d") one_month_ago = today - dateutil.relativedelta.relativedelta(months=1) athlete = client.get_athlete() activities = client.get_activities(after=one_month_ago) rides = toolkit.get_activity_types(activities, 'ride') runs = toolkit.get_activity_types(activities, 'run') ride_set = ActivitySet("Rides", rides) run_set = ActivitySet("Runs", runs) return render_template('main.html', athlete=athlete, activity_sets=[ride_set, run_set])
def index(request): user = None if (request.user.is_authenticated): user = AuthUser.objects.get(user_id=request.user.id) client = Client() authorize_url = client.authorization_url(client_id=24429, redirect_uri="http://localhost:8000/main") #get code from get #Get Code from webapp response code = request.GET.get('code') if (request.GET.get('code') != None) else '' start_pos, end_pos, a_polyline = '', '', '' if (code != '' and request.user.is_authenticated): access_token = client.exchange_code_for_token(client_id=24429, client_secret=config_vars.STRAVA_CLIENT_SECRET, code=code) user_model = AuthUser.objects.get(user_id=request.user.id) # Store User Access Token in DB if (user_model is not None): user_model.auth_code = access_token user_model.save() # Set Access Token On Client if (request.user.is_authenticated and user.auth_code != ''): pprint("User Logged in and has an auth code") client.access_token = user.auth_code athlete = client.get_athlete() full_activity = client.get_activity(1486441471, True) a_polyline = full_activity.map.polyline start_pos = full_activity.start_latlng end_pos = full_activity.end_latlng return render(request, "index.html", { "auth_url": authorize_url, "start_pos": start_pos, "end_pos": end_pos, "polyline": a_polyline, "user_is_authenticated": request.user.is_authenticated })
def strava_redirect(request): auth_code = request.GET.get("code") client = Client() access_token = client.exchange_code_for_token(CLIENT_ID, CLIENT_SECRET, auth_code) client.access_token = access_token global accesToken accesToken = access_token athlete = client.get_athlete() currentUser = User.objects.get(pk=request.user.id) currentUser.profile.stravaAccessToken = access_token currentUser.profile.save() return render(request, 'strava_redirect.html', {'athlete_name': athlete.username})
def auth_success(request): temp_code = request.GET.get('code') # temp auth code print(temp_code) client = Client() token = client.exchange_code_for_token(5928, 'a486a0b19c8d16aef41090371b7726dc510ee4a7', temp_code) if not athlete.objects.filter(pk=client.get_athlete().id): new_athlete = athlete( id = client.get_athlete().id, firstname = client.get_athlete().firstname, lastname = client.get_athlete().lastname, access_token = token ) new_athlete.save() data_scraper(after_utc, before_utc, client.get_athlete().id) result = 'added' else: result = 'already exists' return render(request, 'auth_success.html', {'leaderboard':get_leaderboard(), 'result':result})
def strava_client(client_id=None, client_secret=None, refresh_token=None, access_token=None): client = Client() if access_token is None: authorize_url = client.authorization_url( client_id=client_id, redirect_uri='http://localhost:8282/authorized', scope='view_private,write') logging.info("Go to %s" % (authorize_url)) code = raw_input("Code: ") client.access_token = client.exchange_code_for_token( client_id=client_id, client_secret=client_secret, code=code) logging.info("Access Token = %s" % (client.access_token)) else: client.access_token = access_token return client
def authenticate(): """Authenticate user from Strava""" client = Client() code = request.args.get("code", None) try: token_response = client.exchange_code_for_token( client_id=STRAVA_CLIENT_ID, client_secret=STRAVA_SECRET, code=code) LOGGER.debug(token_response) session["strava_access_token"] = token_response["access_token"] session["strava_refresh_token"] = token_response["refresh_token"] session["strava_expires_at"] = token_response["expires_at"] except Exception as e: LOGGER.info(e) LOGGER.warning("Authentication failed") pass # return "Done" return redirect("/", code=302)
def auth_success(request): temp_code = request.GET.get('code') # temp auth code print(temp_code) client = Client() token = client.exchange_code_for_token( 5928, 'a486a0b19c8d16aef41090371b7726dc510ee4a7', temp_code) if not athlete.objects.filter(pk=client.get_athlete().id): new_athlete = athlete(id=client.get_athlete().id, firstname=client.get_athlete().firstname, lastname=client.get_athlete().lastname, access_token=token) new_athlete.save() data_scraper(after_utc, before_utc, client.get_athlete().id) result = 'added' else: result = 'already exists' return render(request, 'auth_success.html', { 'leaderboard': get_leaderboard(), 'result': result })
def main(): user_id = input("user id: ") access_token = input("access token: ") client = Client(access_token) #Build url or authorizing app url = client.authorization_url( client_id=user_id, redirect_uri='http://127.0.0.1:5000/authorization', approval_prompt='auto', scope='activity:read_all') print(url) #Extract access code from url response access_code = input("access code: ") client_secret = input("client secret: ") #Get permanent access token permanent_access_token = client.exchange_code_for_token( user_id, client_secret, access_code) print(permanent_access_token)
class StrvaSignIn(StravaAuthSignIn): def __init__(self): super(StrvaSignIn, self).__init__('Strava') self.StravaClient = Client() def authorize(self): return redirect( self.StravaClient.authorization_url( client_id=self.consumer_id, redirect_uri=self.get_callback_url())) def callback(self): if 'code' not in request.args: return None access_token = self.StravaClient.exchange_code_for_token( client_id=self.consumer_id, client_secret=self.consumer_secret, code=request.args['code']) social_id = session['social_id'] user = User.query.filter_by(social_id=social_id).first() user.stravatoken = access_token self.StravaClient.access_token = access_token user.athlete_id = self.StravaClient.get_athlete().id db.session.commit() a = Athlete.query.get(user.athlete_id) if a is None: dbathlete = Athlete( id=user.athlete_id, stravatoken=access_token, firstname=self.StravaClient.get_athlete().firstname, lastname=self.StravaClient.get_athlete().lastname) db.session.add(dbathlete) else: dbathlete = Athlete.query.filter_by(id=user.athlete_id).first() dbathlete.stravatoken = access_token dbathlete.firstname = self.StravaClient.get_athlete().firstname dbathlete.lastname = self.StravaClient.get_athlete().lastname db.session.add(dbathlete) db.session.commit() return (user, self.StravaClient.get_athlete())
def token_exchange(self, request): if 'code' in request.data: try: strava_client = Client() response = strava_client.exchange_code_for_token(SOCIAL_AUTH_STRAVA_KEY, SOCIAL_AUTH_STRAVA_SECRET, request.data['code']) leet = Athlete.objects.get(pk=request.user.pk) leet.strava_api_token = response leet.save() except HTTPError as e: code = e.args[0][:3] message = e.args[0][3:] return Response({ 'status': code, 'message': message }, status=int(code)) else: return Response({ 'status': 'Bad Request', 'message': '"code" is required' }, status=status.HTTP_400_BAD_REQUEST) return Response({}, status.HTTP_201_CREATED)
def auth(): try: code = request.args["code"] c = Client() token = c.exchange_code_for_token(app.config['STRAVA_ID'], app.config['STRAVA_SECRET'], code) except (KeyError, requests.exceptions.HTTPError): return redirect("/") session["token"] = c.access_token = token a = c.get_athlete() # Technically shouldn't be needed as the athlete details are returned in the oauth call session["athlete"] = {"name": a.firstname, "picture": a.profile_medium, "id": a.id} # lookup athlete in db cur = g.db.execute('select * from users where id = {}'.format(a.id)) x = cur.fetchall() print x if not x: # Create the object in the db cur = g.db.cursor() cur.execute('insert into users (id, name, picture) values (?, ?, ?)', (a.id, a.firstname, a.profile)) g.db.commit() cur.close() return redirect("/")
def logged_in(): """ Method called by Strava (redirect) that includes parameters. - state - code - error """ error = request.args.get('error') state = request.args.get('state') if error: return render_template('login_error.html', error=error) else: code = request.args.get('code') client = Client() access_token = client.exchange_code_for_token( client_id=app.config['STRAVA_CLIENT_ID'], client_secret=app.config['STRAVA_CLIENT_SECRET'], code=code) # Probably here you'd want to store this somewhere -- e.g. in a database. strava_athlete = client.get_athlete() return render_template('login_results.html', athlete=strava_athlete, access_token=access_token)
def auth(request): client = Client() if request.method == "POST": form = forms.CreateUserForm(request.POST) if form.is_valid(): userName = form.cleaned_data["username"] userPass = form.cleaned_data["password"] userMail = form.cleaned_data["mail"] userToken = form.cleaned_data["token"] user = User.objects.create_user( userName, userMail, userPass) # Nous créons un nouvel utilisateur user.save() profil = Profile(user=user, user_token=userToken) profil.save() else: form = forms.CreateUserForm() code = request.GET['code'] access_token = client.exchange_code_for_token( client_id=13966, client_secret='a67b6efd42d941633fd631b35df2d22ae9b566c1', code=code) return render(request, 'auth.html', locals())
port = httpd.server_address[1] authorize_url = client.authorization_url( client_id=APP["id"], redirect_uri="http://localhost:%d/authorized" % port, scope="write") print "Now open the following URL and authorise this application." print "Then Strava should send you to a localhost:%d URL handled by this script." % port print "If that fails, rerun this script passing the code= value as an argument." print print authorize_url # "code" gets updated once Strava calls us back. while not code: httpd.handle_request() access_token = client.exchange_code_for_token( client_id=APP["id"], client_secret=APP["client_secret"], code=code) client.access_token = access_token athlete = client.get_athlete() print print "Logged in as %s <%s>. Writing access token to file %s" % (athlete.firstname, athlete.email, FN) f = file(FN, "w") os.chmod(FN, 0600) # file won't do this as an extra argument, grrr f.write(access_token)
class StravaAccess: ''' Retrieves data from Strava API, using slightly interactive OAuth2 protocol, requiring user to log in, click approve, paste returned URL ''' CACHE_FILE = os.path.join(os.path.dirname(__file__), r'strava_token.json') def __init__(self): self.client = Client() self.token_cache = {} self.load_token_cache() if time.time() > self.token_cache['expire']: print('Access token {old_token} expired, refreshing...'.format( old_token=self.token_cache['atoken'])) refresh_response = self.client.refresh_access_token( client_id=keychain.app['client_id'], client_secret=keychain.app['client_secret'], refresh_token=self.token_cache['rtoken']) self.token_cache['atoken'] = refresh_response['access_token'] self.token_cache['rtoken'] = refresh_response['refresh_token'] self.token_cache['expire'] = refresh_response['expires_at'] self.save_token_cache() self.client.access_token = self.token_cache['atoken'] self.client.refresh_token = self.token_cache['rtoken'] self.client.token_expires_at = self.token_cache['expire'] def authorize_app(self): ''' Opens new tab in default browser to Strava OAuth2 site for our app User is asked to authorize in browser User is asked to paste redirect URL (not a real URL but I don't want to set up a web server to capture this) Parses the redirect URL for code in query and uses it to generate token for user ''' # Generate code from url copy from url on redirect redirect_domain = 'https://localhost/urlforauth/' authorize_url = self.client.authorization_url( client_id=keychain.app['client_id'], redirect_uri=redirect_domain) webbrowser.open_new_tab(authorize_url) print('Please Authorize application access in browser.') redirect_url_with_code = input( 'URL redirect after authorization (e.g. %s...) :' % redirect_domain) parsed_url = urllib.parse.urlparse(redirect_url_with_code) try: code = urllib.parse.parse_qs(parsed_url.query)['code'][0] except KeyError: raise KeyError( 'Invalid URL, expected copied URL from browser after clicking authorize containing auth code.' ) token_response = self.client.exchange_code_for_token( client_id=keychain.app['client_id'], client_secret=keychain.app['client_secret'], code=code) self.token_cache = { 'atoken': token_response['access_token'], 'rtoken': token_response['refresh_token'], 'expire': token_response['expires_at'] } self.save_token_cache() def load_token_cache(self): ''' load or initialize self.token_cache dictionary keys: atoken, rtoken, expire ''' print('Loading token cache ({cache_file})...'.format( cache_file=self.CACHE_FILE)) try: with open(self.CACHE_FILE, 'r') as json_file: self.token_cache = json.load(json_file) except FileNotFoundError: print( 'Could not load token cache, proceeding with full authorization...' ) self.authorize_app() def save_token_cache(self): print('Saving token cache ({cache_file})...'.format( cache_file=self.CACHE_FILE)) with open(self.CACHE_FILE, 'w') as json_file: json.dump(self.token_cache, json_file)
class Strava(object): def __init__(self): self.client_id = current_app.config['STRAVA_CLIENT_ID'] self.client_secret = current_app.config['STRAVA_CLIENT_SECRET'] self.redirect_uri = url_for('strava.confirm_auth', _external=True) self.client = StravaClient() self._activity_type = 'ride' # rides or runs self._activities = None @property def activity_type(self): return self._activity_type @activity_type.setter def activity_type(self, value): self._activity_type = value self._activities = None @property def athlete(self): return self.client.get_athlete() @property def activities(self): if not self._activities: # current_year = datetime.datetime.now().year # after = datetime.datetime(current_year - 2, 12, 25) self._activities = Activities(self.client.get_activities(), self.activity_type) return self._activities @classmethod def authorization_url(cls): self = cls() return self.client.authorization_url(client_id=self.client_id, redirect_uri=self.redirect_uri) def get_access_token(self, code): return self.client.exchange_code_for_token( client_id=self.client_id, client_secret=self.client_secret, code=code) @classmethod def athlete_by_code(cls, code): self = cls() self.client.access_token = self.get_access_token(code) return self.athlete @classmethod def athlete_by_token(cls, token): self = cls() self.client.access_token = token return self.athlete @classmethod def activities_by_token(cls, token): self = cls() self.client.access_token = token return self.activities @classmethod def by_token(cls, token): self = cls() self.client.access_token = token return self
client_id = cfg.get("StravaClient", "ClientId") client_secret = cfg.get("StravaClient", "ClientSecret") port = int(cfg.get("Application", "Port")) # setup webserver for authentication redirect httpd = http.server.HTTPServer(('127.0.0.1', port), AuthHandler) # The url to authorize from authorize_url = client.authorization_url(client_id=client_id, redirect_uri='http://localhost:{port}/authorized'.format(port=port), scope='view_private,write') # Open the url in your browser webbrowser.open(authorize_url, new=0, autoraise=True) # wait until you click the authorize link in the browser httpd.handle_request() code = httpd.code # Get the token token = client.exchange_code_for_token(client_id=client_id, client_secret=client_secret, code=code) # Now store that access token in the config cfg.set("UserAcct", "Token", token) with open("stravamng.cfg", "w") as cfg_file: cfg.write(cfg_file) client.access_token = token # do stuff athlete = client.get_athlete() print("For {id}, I now have an access token {token}".format(id=athlete.id, token=token))
class Strava: """Class to interact with Strava API""" # pylint: disable=too-many-instance-attributes # pylint: disable=invalid-name # CH1.5: Global variables in a class # CH1.5: Easy way to create a list cols = 'id name type start_date_local average_heartrate' \ ' distance average_speed elapsed_time'.split() funcs = [] def __init__(self, api_file, local_db_fp, verbose=False, update=True): # Read API parameters from CSV file if os.path.isfile(api_file): api = pd.read_csv(api_file) else: raise FileNotFoundError('API key file not found') # Initialise local variables and objects self._client_id = api['client_id'] self._client_secret = api['client_secret'] self._code = api['code'] self._local_db_fp = local_db_fp self._client = Client() self._access_token = self._client.exchange_code_for_token( client_id=self._client_id, client_secret=self._client_secret, code=self._code) self._last_remote_id = None self._verbose = verbose # Handle exceptions in requesting the access token if not self._access_token: raise ConnectionError( 'Client did not receive a valid access token') # Verify if local database exists if os.path.isfile(self._local_db_fp): # Read from file and sort by id if self._verbose: print('Reading local database from: %s' % self._local_db_fp) self._db = pd.read_csv(self._local_db_fp, index_col='id') self._db.sort_values(by=['id'], inplace=True) else: # Create new DataFrame self._db = pd.DataFrame(columns=self.cols) self._db.set_index('id', drop=True, inplace=True) if self._verbose: print('Local database contains %d entries' % len(self)) if update: # Verify if local database up to date if not self._local_db_in_sync(): if self._verbose: print('Local database not in sync, downloading...') self._update_local_db() self._save_local_db() if self._verbose: print('Local database now contains %d entries' % len(self)) else: if self._verbose: print('Local database in sync') def __repr__(self): return 'Strava(%d)' % len(self) def __len__(self): # CH1.5: Custom special method return len(self._db.index) def __getitem__(self, row): # CH1.5: Custom special method return self._db.iloc[[row]] def __call__(self): # CH5.152: Custom __call__ method self.update() if self._verbose: print('Update completed') def decorator_factory(scope): # CH 7.194: Decorators def decorator(func): def wrapper(self, *args, **kwargs): self.funcs.append(Functions(func.__name__, scope)) return func(self, *args, **kwargs) return wrapper return decorator @decorator_factory('private') def _last_local_id(self): if self: last_local_id = self._db.iloc[[-1]].index.item() else: last_local_id = None return last_local_id @decorator_factory('private') def _local_db_in_sync(self): activity = self._client.get_activities(limit=1) activity = activity.next() self._last_remote_id = int(activity.id) return self._last_remote_id == self._last_local_id() @decorator_factory('private') def _update_local_db(self): last_start_date = None if self: last_start_date = str( self._db['start_date_local'].tail(1).values[0]) activities = self._client.get_activities(after=last_start_date) data = [] for activity in activities: if int(activity.id) != self._last_local_id(): my_dict = activity.to_dict() data.append([activity.id] + [my_dict.get(x) for x in self.cols[1:]]) else: # All new activities processed break df = pd.DataFrame(data, columns=self.cols) df['average_speed'] *= 3.6 df['distance'] /= 1000 df.set_index('id', drop=True, inplace=True) self._db = pd.concat([self._db, df]) self._db.sort_values(by=['id'], inplace=True) @decorator_factory('private') def _save_local_db(self): self._db.to_csv(self._local_db_fp) @decorator_factory('public') def update(self, in_memory=False): """Update local database and store to disk if requested""" self._update_local_db() if not in_memory: self._save_local_db() @decorator_factory('public') def filter(self, activity_type='', name=''): """Filter database based on activity type and name""" df = self._db if activity_type: df = df[df['type'].str.contains(activity_type)] if name: df = df[df['name'].str.contains(name)] return df
from stravalib.client import Client from config import * import functions #connection stuff client = Client() authorize_url = client.authorization_url( client_id=C_ID, redirect_uri='http://localhost:8282/authorized') access_token = client.exchange_code_for_token(client_id=C_ID, client_secret=C_SECRET, code=CODE) client.access_token = access_token #getting activites activities = client.get_club_activities(club_id=CLUB, limit=200) #getting activities already recorded done = functions.get_array('done') #going through activities data = [] for run in activities: #using local activity start date as a metric since using IDs feels shady if (str(run.start_date) not in done): #taking only runs if (run.type == 'Run'): data.append(run.start_date_local) data.append(run.elapsed_time) data.append(run.distance) data.append(run.total_elevation_gain) data.append(run.pr_count)
# The url to authorize from authorize_url = client.authorization_url( client_id=client_id, redirect_uri='http://localhost:{port}/authorized'.format( port=port), scope='view_private,write') # Open the url in your browser webbrowser.open(authorize_url, new=0, autoraise=True) # wait until you click the authorize link in the browser httpd.handle_request() code = httpd.code # Get the token token = client.exchange_code_for_token(client_id=client_id, client_secret=client_secret, code=code) # Now store that access token in the config cfg.set("UserAcct", "Token", token) with open("stravamng.cfg", "w") as cfg_file: cfg.write(cfg_file) client.access_token = token # do stuff athlete = client.get_athlete() print("For {id}, I now have an access token {token}".format(id=athlete.id, token=token))
class Strava(object): def __init__(self): self.client_id = current_app.config['STRAVA_CLIENT_ID'] self.client_secret = current_app.config['STRAVA_CLIENT_SECRET'] self.redirect_uri = url_for('strava.confirm_auth', _external=True) self.client = StravaClient() self._activity_type = 'ride' # rides or runs self._activities = None @property def activity_type(self): return self._activity_type @activity_type.setter def activity_type(self, value): self._activity_type = value self._activities = None @property def athlete(self): return self.client.get_athlete() @property def activities(self): if not self._activities: # current_year = datetime.datetime.now().year # after = datetime.datetime(current_year - 2, 12, 25) self._activities = Activities(self.client.get_activities(), self.activity_type) return self._activities @classmethod def authorization_url(cls): self = cls() return self.client.authorization_url(client_id=self.client_id, redirect_uri=self.redirect_uri) def get_access_token(self, code): return self.client.exchange_code_for_token(client_id=self.client_id, client_secret=self.client_secret, code=code) @classmethod def athlete_by_code(cls, code): self = cls() self.client.access_token = self.get_access_token(code) return self.athlete @classmethod def athlete_by_token(cls, token): self = cls() self.client.access_token = token return self.athlete @classmethod def activities_by_token(cls, token): self = cls() self.client.access_token = token return self.activities @classmethod def by_token(cls, token): self = cls() self.client.access_token = token return self
class stravaImporter(object): def __init__(self): self.client = Client() self.API_CALL_PAUSE_SECONDS = 1.5 # 40 requests per minute # the self-authorization is NOT working right now -- using hard-coded URL / ACCESS_CODE right now #url = self.client.authorization_url(client_id=CLIENT_ID, # redirect_uri='http://localhost:5000/authorization') #code = request.args.get('code') # or whatever flask does #url = 'http://www.strava.com/oauth/authorize?client_id=16424&response_type=code&redirect_uri=http://localhost/5001&approval_prompt=force&scope=write' #print(url) access_token = self.client.exchange_code_for_token( client_id=CLIENT_ID, client_secret=CLIENT_SECRET, code=ACCESS_CODE) # Now store that access token somewhere (a database?) self.client.access_token = access_token # retrieve the athlete self.athlete = self.client.get_athlete() print("For {}, I now have an access token".format(self.athlete.id)) # name of tables in model self.user_TBL = 'users' self.activity_TBL = 'activities' self.streams_TBL = 'streams' self.gear_TBL = 'gear' # streams to extract from strava self.streams = [ 'time', 'latlng', 'distance', 'altitude', 'velocity_smooth', 'heartrate', 'cadence', 'temp', 'moving', 'grade_smooth' ] def get_activities(self, before=None, after=None, limit=None): """ Get activities and the related metadata from strava """ return list( self.client.get_activities(before=before, after=after, limit=limit)) def get_streams(self, activity_id): # download the entire stream: `resolution` = `all` (default) # download all stream_types except `power` try: s = self.client.get_activity_streams(activity_id, types=self.streams) return s except: print('Could not get streams for activity {0}. Manual upload?'. format(activity_id)) return def stream_to_DF(self, s): """ Convert a Strava Stream to a pandas DF """ return pd.DataFrame.from_dict({k: s[k].data for k in s.keys()}) def add_user(self, username, email=None, fname=None, lname=None, password=None): """ Add a user to the DB""" s = Session() try: u = User(username=username, email=email, fname=fname, lname=lname, password=password, strava_id=self.athlete.id) s.add(u) s.commit() return int(u.id) except SQLAlchemyError as err: s.rollback() print('Error: \n', err) raise s.close() return def add_streams(self, user_id, s_id): """ Add Strava data streams for a given user_id and activity_id """ # get the strava streams for that activity stream = self.get_streams(s_id) # convert the streams to a DF if stream is not None: s = Session() df = self.stream_to_DF(stream) # add `user_id` to the DF df['user_id'] = user_id # add `activity_id` to the DF df['activity_id'] = s.query( Activity.id).filter_by(strava_id=s_id.astype(str)).one()[0] try: df.to_sql(self.streams_TBL, engine, if_exists='append', index=False) s.commit() except: s.rollback() print('Error: `add_streams` cannot write event to DB. \n') raise s.close() else: print('Error: Stream is empty for User {0}, Activity {1}'.format( user_id, s_id)) return def add_activity(self, user_id, before=None, after=None, limit=None, add_streams=True): """ Get & add a list of activities from strava """ # get the list of activities from strava activities = self.get_activities(before=before, after=after, limit=limit) activities = activities # transform activities to a DF ready for Postgres df = self.munge_activity(activities) df['user_id'] = user_id s = Session() try: df.to_sql(self.activity_TBL, engine, if_exists='append', index=False) s.commit() print('Added {0} activities from Strava.\n'.format( len(df.strava_id))) except: s.rollback() print('Error: `add_activity` cannot write event to DB. \n') raise s.close() # if needed, add the streams as well if add_streams is True: size = len(df.strava_id) for (i, strava_id) in enumerate(df.strava_id): print('Fetching data streams for {0}: {1} of {2}'.format( strava_id, i, size), end='\r') time.sleep( self.API_CALL_PAUSE_SECONDS) # limit API call to 40 / min self.add_streams(user_id, strava_id) print('Added `Streams` for {0} activities from Strava.'.format( len(df.strava_id))) return def strip_units(self, df, cols): """ strip units from columns -- changes dtype from `object` to `float`""" d = { 'average_speed': ' m / s', 'max_speed': ' m / s', 'distance': ' m', 'total_elevation_gain': ' m' } for col in cols: if col in df.columns: df[col] = pd.to_numeric(df[col].astype('str').str.strip( d[col]), errors='coerce') return df def munge_activity(self, activities): """ Get `activities` ready for Postgres DB """ # `stravalib`.`activity` attributes to import fields = [ 'athlete_count', 'average_cadence', 'average_heartrate', 'average_speed', 'distance', 'elapsed_time', 'elev_high', 'elev_low', 'end_latlng', 'external_id', 'gear_id', 'has_heartrate', 'id', 'location_city', 'location_country', 'location_state', 'manual', 'max_heartrate', 'max_speed', 'moving_time', 'name', 'pr_count', 'start_date', 'start_date_local', 'start_latitude', 'start_latlng', 'start_longitude', 'suffer_score', 'timezone', 'total_elevation_gain', 'type', 'upload_id', 'workout_type' ] # convert `activities` into a df with `fields` as columns df = pd.DataFrame([[getattr(i, j) for j in fields] for i in activities], columns=fields) # rename since `id` will be an internal DB `id` df.rename(columns={'id': 'strava_id'}, inplace=True) # pandas or SQL does not support units, so strip the units from the fields # could be worth adding units when the tables are imported # I want GIS support, so can't really move to JSONB or BSON cols_to_strip = ('average_speed', 'max_speed', 'distance', 'total_elevation_gain') df = self.strip_units(df, cols_to_strip) # pd.to_sql does not yet support TZ, so strip it. for now. # also does not suport timedelta ... maybe I have to ditch `pd.to_sql` # https://github.com/pandas-dev/pandas/issues/9086 df.start_date = pd.DatetimeIndex(df.start_date).tz_convert(None) df.timezone = df.timezone.astype(str) return df
gear = None # # Date range to retrieve. Defaults to 2 weeks, but can be overridden # by providing a different # of days in the command line. # numdays = 14 if (len(sys.argv) > 1): numdays=int(sys.argv[1]) now=datetime.datetime.now() then=now - datetime.timedelta(numdays) # # Authenticate with Strava. # token_response = client.exchange_code_for_token(client_id=client_id, client_secret=client_secret, code=client_code) client.access_token = token_response['access_token'] client.refresh_token = token_response['refresh_token'] client.expires_at = token_response['expires_at'] athlete = client.get_athlete() print("Retrieving records of the past {days} days for {id}: {firstname} {lastname}".format( days=numdays, id=athlete.id, firstname=athlete.firstname, lastname=athlete.lastname)) activities = list(client.get_activities(after=then, before=now)) activities.reverse() for activity in activities: if (activity.gear_id is None): gear_name = "N/A"
def get_token(self, code): client = Client(requests_session=self.session) return client.exchange_code_for_token(self.CLIENT_ID, self.client_secret, code)
def token_exchange(code): client = Client() token = client.exchange_code_for_token(client_id=config.client_id, client_secret=config.client_secret, code=code) return token