diff --git a/rowers/imports.py b/rowers/imports.py new file mode 100644 index 00000000..9bdbc226 --- /dev/null +++ b/rowers/imports.py @@ -0,0 +1,239 @@ +# All the functionality to connect to SportTracks + +# Python +import oauth2 as oauth +import cgi +import pytz +import requests +import requests.auth +import json +from django.utils import timezone +from datetime import datetime +import arrow +import numpy as np +from dateutil import parser +import time +from time import strftime + +import dataprep +import math +from math import sin,cos,atan2,sqrt +import os,sys +import urllib +import iso8601 +from uuid import uuid4 + +# Django +from django.shortcuts import render_to_response +from django.http import HttpResponseRedirect, HttpResponse,JsonResponse +from django.conf import settings +from django.contrib.auth import authenticate, login, logout +from django.contrib.auth.models import User +from django.contrib.auth.decorators import login_required + +# Project +# from .models import Profile +from rowingdata import rowingdata +import pandas as pd +from rowers.models import Rower,Workout,checkworkoutuser +from rowers import types +from rowsandall_app.settings import ( + C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, + STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, + STRAVA_CLIENT_SECRET, SPORTTRACKS_CLIENT_SECRET, + SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI + ) + +from utils import ( + NoTokenError, custom_exception_handler, ewmovingaverage, + geo_distance + ) + + +# Splits SportTracks data which is one long sequence of +# [t,[lat,lon],t2,[lat2,lon2] ...] +# to [t,t2,t3, ...], [[lat,long],[lat2,long2],... +def splitstdata(lijst): + t = [] + latlong = [] + while len(lijst)>=2: + t.append(lijst[0]) + latlong.append(lijst[1]) + lijst = lijst[2:] + + return [np.array(t),np.array(latlong)] + +def splituadata(lijst): + t = [] + y = [] + for d in lijst: + t.append(d[0]) + y.append(d[1]) + + return np.array(t),np.array(y) + +def imports_open(user,oauth_data): + r = Rower.objects.get(user=user) + token = getattr(r,oauth_data['tokenname']) + try: + refreshtoken = getattr(r,oauth_data['refreshtokenname']) + except AttributeError: + refreshtoken = None + + try: + tokenexpirydate = getattr(r,oauthdata['expirydatename']) + except AttributeError: + tokenexpirydate = None + + if (token == '') or (token is None): + s = "Token doesn't exist. Need to authorize" + raise NoTokenError("User has no token") + else: + if tokenexpirydate and timezone.now()>tokenexpirydate: + token = imports_token_refresh( + user,oauth_data, + ) + + return token + + +# Refresh ST token using refresh token +def imports_do_refresh_token(refreshtoken,oauth_data,access_token=''): + client_auth = requests.auth.HTTPBasicAuth( + oauth_data['client_id'], + oauth_data['client_secret'] + ) + + post_data = {"grant_type": "refresh_token", + "client_secret": client_secret, + "client_id": client_id, + "refresh_token": refreshtoken, + } + headers = {'user-agent': 'sanderroosendaal', + 'Accept': 'application/json', + 'Content-Type': oauth_data['content_type']} + + if oauth_data['bearer_auth']: + + headers['authorization'] = 'Bearer %s' % access_token + + baseurl = oauth_data['base_url'] + + if 'json' in oauth_data['content_type']: + response = requests.post(baseurl, + data=json.dumps(post_data), + headers=headers) + else: + response = requests.post(baseurl, + data=post_data, + headers=headers) + + token_json = response.json() + thetoken = token_json['access_token'] + expires_in = token_json['expires_in'] + try: + refresh_token = token_json['refresh_token'] + except KeyError: + refresh_token = refreshtoken + try: + expires_in = int(expires_in) + except (TypeError,ValueError): + expires_in = 0 + + + return [thetoken,expires_in,refresh_token] + +# Exchange ST access code for long-lived ST access token +def imports_get_token( + code,oauth_data + ): + + redirect_uri = oauth_data['redirect_uri'] + client_secret = oauth_data['client_secret'] + client_id = oauth_data['client_id'] + base_uri = oauth_data['base_url'] + + + client_auth = requests.auth.HTTPBasicAuth( + client_id,client_secret + ) + + post_data = {"grant_type": "authorization_code", + "code": code, + "redirect_uri": redirect_uri, + "client_secret": client_secret, + "client_id": client_id, + } + + headers = {'Accept': 'application/json', + 'Api-Key': client_id, + 'Content-Type': 'application/json'} + + + if 'json' in oauth_data['content_type']: + response = requests.post( + base_uri, + data=json.dumps(post_data), + headers=headers) + else: + response = requests.post( + base_uri, + data=post_data, + headers=headers) + + if response.status_code == 200 or response.status_code == 201: + token_json = response.json() + thetoken = token_json['access_token'] + expires_in = token_json['expires_in'] + try: + refresh_token = token_json['refresh_token'] + except KeyError: + refresh_token = refreshtoken + try: + expires_in = int(expires_in) + except (ValueError,TypeError): + expires_in = 0 + else: + return [0,0,0] + + + return [thetoken,expires_in,refresh_token] + +# Make authorization URL including random string +def imports_make_authorization_url(oauth_data): + # Generate a random string for the state parameter + # Save it for use later to prevent xsrf attacks + + state = str(uuid4()) + + params = {"client_id": oauth_data['client_id'], + "response_type": "code", + "redirect_uri": oauth_data['redirect_uri'], + "scope":"write", + "state":state} + + + import urllib + url = oauth_data['authorizaton_uri']+authorization_uri+urllib.urlencode(params) + + return HttpResponseRedirect(url) + +# This is token refresh. Looks for tokens in our database, then refreshes +def imports_token_refresh(user,tokenname,refreshtokenname,expirydatename): + r = Rower.objects.get(user=user) + + refreshtoken = getattr(r,refreshtokennname) + + res = imports_do_refresh_token(refreshtoken) + access_token = res[0] + expires_in = res[1] + refresh_token = res[2] + expirydatetime = timezone.now()+timedelta(seconds=expires_in) + + setattr(r,tokenname,access_token) + setattr(r,expirydatename,expirydatetime) + setattr(r,refreshtokenname,refresh_token) + + r.save() + return r.sporttrackstoken + diff --git a/rowers/underarmourstuff.py b/rowers/underarmourstuff.py index f0ec9db5..87eeb85f 100644 --- a/rowers/underarmourstuff.py +++ b/rowers/underarmourstuff.py @@ -1,164 +1,41 @@ -# All the functionality needed to connect to Runkeeper - -# Python -import oauth2 as oauth -import cgi -import pytz -import requests -import requests.auth -import json -from django.utils import timezone -from datetime import datetime,timedelta -import arrow -import numpy as np -from dateutil import parser -import time -from time import strftime -import arrow -import dataprep -import math -from math import sin,cos,atan2,sqrt -import os,sys -import urllib -import iso8601 -from uuid import uuid4 - -# Django -from django.shortcuts import render_to_response -from django.http import HttpResponseRedirect, HttpResponse,JsonResponse -from django.conf import settings -from django.contrib.auth import authenticate, login, logout -from django.contrib.auth.models import User -from django.contrib.auth.decorators import login_required - -# Project -# from .models import Profile -from rowingdata import rowingdata -import pandas as pd -from rowers.models import Rower,Workout,checkworkoutuser +from rowers.imports import * from rowsandall_app.settings import ( - C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, - STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, - UNDERARMOUR_CLIENT_ID, UNDERARMOUR_CLIENT_SECRET, - UNDERARMOUR_REDIRECT_URI,UNDERARMOUR_CLIENT_KEY, + UNDERARMOUR_CLIENT_KEY, + UNDERARMOUR_CLIENT_SECRET, + UNDERARMOUR_REDIRECT_URI, ) -from utils import NoTokenError,ewmovingaverage - -from utils import geo_distance, custom_exception_handler - -def splituadata(lijst): - t = [] - y = [] - for d in lijst: - t.append(d[0]) - y.append(d[1]) - - return np.array(t),np.array(y) - +oauth_data = { + 'client_id': UNDERARMOUR_CLIENT_KEY, + 'client_secret': UNDERARMOUR_CLIENT_SECRET, + 'redirect_uri': UNDERARMOUR_REDIRECT_URI, + 'autorization_uri': "https://www.mapmyfitness.com/v7.1/oauth2/uacf/authorize/", + 'content_type': 'application/x-www-form-urlencoded', + 'tokenname': 'underarmourtoken', + 'refreshtokenname': 'underarmourrefreshtoken', + 'expirydatename': 'underarmourtokenexpirydate', + 'bearer_auth': True, + 'base_url': "https://api.ua.com/v7.1/oauth2/access_token/", + } # Checks if user has UnderArmour token, renews them if they are expired def underarmour_open(user): - r = Rower.objects.get(user=user) - if (r.underarmourtoken == '') or (r.underarmourtoken is None): - s = "Token doesn't exist. Need to authorize" - raise NoTokenError("User has no token") - else: - if (timezone.now()>r.underarmourtokenexpirydate): - res = do_refresh_token( - r.underarmourrefreshtoken,r.underarmourtoken - ) - access_token = res[0] - expires_in = res[1] - refresh_token = res[2] - - expirydatetime = timezone.now()+timedelta(seconds=expires_in) - - r = getrower(request.user) - r.underarmourtoken = access_token - r.underarmourtokenexpirydate = expirydatetime - r.underarmourrefreshtoken = refresh_token - - r.save() - thetoken = r.underarmourtoken - else: - thetoken = r.underarmourtoken - - return thetoken + return imports_open(user,oauth_data) # Refresh ST token using refresh token def do_refresh_token(refreshtoken,access_token): - client_auth = requests.auth.HTTPBasicAuth(UNDERARMOUR_CLIENT_KEY, UNDERARMOUR_CLIENT_SECRET) - post_data = {"grant_type": "refresh_token", - "client_secret": UNDERARMOUR_CLIENT_SECRET, - "client_id":UNDERARMOUR_CLIENT_KEY, - "refresh_token": refreshtoken, - } - headers = {'user-agent': 'sanderroosendaal', - "Api-Key":UNDERARMOUR_CLIENT_KEY, - 'Accept': 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - 'authorization': 'Bearer %s' % access_token} - - url = "https://api.ua.com/v7.1/oauth2/access_token/" - - response = requests.post(url, - data=post_data, - headers=headers) - - token_json = response.json() - thetoken = token_json['access_token'] - expires_in = token_json['expires_in'] - try: - refresh_token = token_json['refresh_token'] - except KeyError: - refresh_token = refreshtoken - - return [thetoken,expires_in,refresh_token] + return imports_do_refresh_token( + refreshtoken,oauth_data,access_token=access_token + ) # Exchange access code for long-lived access token def get_token(code): - client_auth = requests.auth.HTTPBasicAuth(UNDERARMOUR_CLIENT_KEY, UNDERARMOUR_CLIENT_SECRET) - post_data = { - "grant_type": "authorization_code", - "code": code, - "client_secret": UNDERARMOUR_CLIENT_SECRET, - "client_id":UNDERARMOUR_CLIENT_KEY, - } - headers = { - 'user-agent': 'sanderroosendaal', - "Api-Key":UNDERARMOUR_CLIENT_KEY, - } - - response = requests.post("https://api.ua.com/v7.1/oauth2/access_token/", - data=post_data, - headers=headers) - try: - token_json = response.json() - thetoken = token_json['access_token'] - expires_in = token_json['expires_in'] - refresh_token = token_json['refresh_token'] - except KeyError: - thetoken = 0 - expires_in = 30 - refresh_token = '' - - return thetoken,expires_in,refresh_token + return imports_get_token(code,oauth_data) # Make authorization URL including random string def make_authorization_url(request): - # Generate a random string for the state parameter - # Save it for use later to prevent xsrf attacks - state = str(uuid4()) - - params = {"client_id": UNDERARMOUR_CLIENT_KEY, - "response_type": "code", - "redirect_uri": UNDERARMOUR_REDIRECT_URI, - } - url = "https://www.mapmyfitness.com/v7.1/oauth2/uacf/authorize/" +urllib.urlencode(params) - - return HttpResponseRedirect(url) + return imports_make_authorization_url(oauth_data) # Get list of workouts available on Underarmour def get_underarmour_workout_list(user):