first attempt on c2
This commit is contained in:
1
rowers/integrations/__init__.py
Normal file
1
rowers/integrations/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .c2 import C2Integration
|
||||
450
rowers/integrations/c2.py
Normal file
450
rowers/integrations/c2.py
Normal file
@@ -0,0 +1,450 @@
|
||||
from .integrations import SyncIntegration, NoTokenError
|
||||
from rowers.models import User, Rower, Workout, TombStone
|
||||
from rowingdata import rowingdata
|
||||
import numpy as np
|
||||
import datetime
|
||||
import json
|
||||
import urllib
|
||||
from rowers.utils import dologging, uniqify
|
||||
from django.utils import timezone
|
||||
import requests
|
||||
from pytz.exceptions import UnknownTimeZoneError
|
||||
import pytz
|
||||
|
||||
from rowsandall_app.settings import (
|
||||
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
|
||||
UPLOAD_SERVICE_URL, UPLOAD_SERVICE_SECRET
|
||||
)
|
||||
|
||||
from rowers.tasks import (
|
||||
handle_c2_import_stroke_data, handle_c2_sync, handle_c2_async_workout,
|
||||
handle_c2_getworkout
|
||||
)
|
||||
import django_rq
|
||||
queue = django_rq.get_queue('default')
|
||||
queuelow = django_rq.get_queue('low')
|
||||
queuehigh = django_rq.get_queue('high')
|
||||
|
||||
from rowers.utils import myqueue, dologging
|
||||
|
||||
from requests import Request, Session
|
||||
|
||||
import rowers.mytypes as mytypes
|
||||
from rowers.rower_rules import is_workout_user, ispromember
|
||||
|
||||
def default(o): # pragma: no cover
|
||||
if isinstance(o, numpy.int64):
|
||||
return int(o)
|
||||
raise TypeError
|
||||
|
||||
# convert datetime object to seconds
|
||||
def makeseconds(t):
|
||||
seconds = t.hour*3600.+t.minute*60.+t.second+0.1*int(t.microsecond/1.e5)
|
||||
return seconds
|
||||
|
||||
# convert our weight class code to Concept2 weight class code
|
||||
|
||||
|
||||
def c2wc(weightclass):
|
||||
if (weightclass == "lwt"): # pragma: no cover
|
||||
res = "L"
|
||||
else:
|
||||
res = "H"
|
||||
|
||||
return res
|
||||
|
||||
|
||||
class C2Integration(SyncIntegration):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(C2Integration, self).__init__(self, *args, **kwargs)
|
||||
self.oauth_data = {
|
||||
'client_id': C2_CLIENT_ID,
|
||||
'client_secret': C2_CLIENT_SECRET,
|
||||
'redirect_uri': C2_REDIRECT_URI,
|
||||
'autorization_uri': "https://log.concept2.com/oauth/authorize",
|
||||
'content_type': 'application/x-www-form-urlencoded',
|
||||
'tokenname': 'c2token',
|
||||
'refreshtokenname': 'c2refreshtoken',
|
||||
'expirydatename': 'tokenexpirydate',
|
||||
'bearer_auth': True,
|
||||
'base_url': "https://log.concept2.com/oauth/access_token",
|
||||
'scope': 'write',
|
||||
}
|
||||
|
||||
def get_token(self, code, *args, **kwargs):
|
||||
messg = ''
|
||||
scope = "user:read,results:write"
|
||||
|
||||
post_data = {"grant_type": "authorization_code",
|
||||
"code": code,
|
||||
"redirect_uri": C2_REDIRECT_URI,
|
||||
"client_secret": C2_CLIENT_SECRET,
|
||||
"client_id": C2_CLIENT_ID,
|
||||
}
|
||||
headers = {'user-agent': 'sanderroosendaal'}
|
||||
url = "https://log.concept2.com/oauth/access_token"
|
||||
s = Session()
|
||||
req = Request('POST', url, data=post_data, headers=headers)
|
||||
|
||||
prepped = req.prepare()
|
||||
prepped.body += "&scope="
|
||||
prepped.body += scope
|
||||
|
||||
response = s.send(prepped)
|
||||
|
||||
token_json = response.json()
|
||||
|
||||
try:
|
||||
status_code = response.status_code
|
||||
except AttributeError: # pragma: no cover
|
||||
return (0, response.text)
|
||||
|
||||
if status_code == 200:
|
||||
thetoken = token_json['access_token']
|
||||
expires_in = token_json['expires_in']
|
||||
refresh_token = token_json['refresh_token']
|
||||
else: # pragma: no cover
|
||||
raise NoTokenError("No Token")
|
||||
|
||||
|
||||
return (thetoken, expires_in, refresh_token, messg)
|
||||
|
||||
|
||||
def open(self, *args, **kwargs):
|
||||
return super(C2Integration, self).open(*args, **kwargs)
|
||||
|
||||
def token_refresh(self, *args, **kwargs):
|
||||
return super(C2Integration, self).open(*args, **kwargs)
|
||||
|
||||
def make_authorization_url(self, *args, **kwargs):
|
||||
scope = "user:read,results:write"
|
||||
|
||||
params = {"client_id": C2_CLIENT_ID,
|
||||
"response_type": "code",
|
||||
"redirect_uri": C2_REDIRECT_URI}
|
||||
url = "https://log.concept2.com/oauth/authorize?" + \
|
||||
urllib.parse.urlencode(params)
|
||||
url += "&scope="+scope
|
||||
return url
|
||||
|
||||
def get_userid(self, *args, **kwargs):
|
||||
_ = self.open()
|
||||
access_token = self.rower.c2token
|
||||
authorizationstring = str('Bearer ' + access_token)
|
||||
headers = {'Authorization': authorizationstring,
|
||||
'user-agent': 'sanderroosendaal',
|
||||
'Content-Type': 'application/json'}
|
||||
url = "https://log.concept2.com/api/users/me"
|
||||
try:
|
||||
response = requests.get(url, headers=headers)
|
||||
except: # pragma: no cover
|
||||
return 0
|
||||
|
||||
try:
|
||||
me_json = response.json()
|
||||
except: # pragma: no cover
|
||||
return 0
|
||||
try:
|
||||
res = me_json['data']['id']
|
||||
except KeyError: # pragma: no cover
|
||||
return 0
|
||||
|
||||
return res
|
||||
|
||||
def createworkoutdata(self, w, *args, **kwargs) -> dict:
|
||||
filename = w.csvfilename
|
||||
try:
|
||||
row = rowingdata(csvfile=filename)
|
||||
except IOError: # pragma: no cover
|
||||
return 0
|
||||
|
||||
try:
|
||||
averagehr = int(row.df[' HRCur (bpm)'].mean())
|
||||
maxhr = int(row.df[' HRCur (bpm)'].max())
|
||||
except (ValueError, KeyError): # pragma: no cover
|
||||
averagehr = 0
|
||||
maxhr = 0
|
||||
|
||||
# Calculate intervalstats
|
||||
itime, idist, itype = row.intervalstats_values()
|
||||
lapnames = range(len(itime))
|
||||
nrintervals = len(itime)
|
||||
|
||||
try:
|
||||
lapnames = row.df[' lapIdx'].unique()
|
||||
except KeyError: # pragma: no cover
|
||||
pass
|
||||
|
||||
if len(lapnames) != nrintervals:
|
||||
newlapnames = []
|
||||
for name in lapnames:
|
||||
newlapnames += [name, name]
|
||||
lapnames = newlapnames
|
||||
intervaldata = []
|
||||
for i in range(nrintervals):
|
||||
if itime[i] > 0:
|
||||
mask = (row.df[' lapIdx'] == lapnames[i]) & (
|
||||
row.df[' WorkoutState'] == itype[i])
|
||||
try:
|
||||
spmav = int(row.df[' Cadence (stokes/min)']
|
||||
[mask].mean().astype(int))
|
||||
hrav = int(row.df[' HRCur (bpm)'][mask].mean().astype(int))
|
||||
except AttributeError: # pragma: no cover
|
||||
try:
|
||||
spmav = int(row.df[' Cadence (stokes/min)'][mask].mean())
|
||||
hrav = int(row.df[' HRCur (bpm)'][mask].mean())
|
||||
except ValueError:
|
||||
spmav = 0
|
||||
try:
|
||||
hrav = int(row.df[' HRCur (bpm)'][mask].mean())
|
||||
except ValuError:
|
||||
hrav = 0
|
||||
intervaldict = {
|
||||
'type': 'distance',
|
||||
'time': int(10*itime[i]),
|
||||
'distance': int(idist[i]),
|
||||
'heart_rate': {
|
||||
'average': hrav,
|
||||
},
|
||||
'stroke_rate': spmav,
|
||||
}
|
||||
intervaldata.append(intervaldict)
|
||||
|
||||
# adding diff, trying to see if this is valid
|
||||
t = 10*row.df.loc[:, 'TimeStamp (sec)'].values - \
|
||||
10*row.df.loc[:, 'TimeStamp (sec)'].iloc[0]
|
||||
try:
|
||||
t[0] = t[1]
|
||||
except IndexError: # pragma: no cover
|
||||
pass
|
||||
|
||||
d = 10*row.df.loc[:, ' Horizontal (meters)'].values
|
||||
try:
|
||||
d[0] = d[1]
|
||||
except IndexError: # pragma: no cover
|
||||
pass
|
||||
|
||||
p = abs(10*row.df.loc[:, ' Stroke500mPace (sec/500m)'].values)
|
||||
p = np.clip(p, 0, 3600)
|
||||
if w.workouttype == 'bike': # pragma: no cover
|
||||
p = 2.0*p
|
||||
|
||||
t = t.astype(int)
|
||||
d = d.astype(int)
|
||||
p = p.astype(int)
|
||||
spm = row.df[' Cadence (stokes/min)'].astype(int)
|
||||
|
||||
try:
|
||||
spm[0] = spm[1]
|
||||
except (KeyError, IndexError): # pragma: no cover
|
||||
spm = 0*t
|
||||
try:
|
||||
hr = row.df[' HRCur (bpm)'].astype(int)
|
||||
except ValueError: # pragma: no cover
|
||||
hr = 0*d
|
||||
stroke_data = []
|
||||
|
||||
t = t.tolist()
|
||||
d = d.tolist()
|
||||
p = p.tolist()
|
||||
spm = spm.tolist()
|
||||
hr = hr.tolist()
|
||||
|
||||
for i in range(len(t)):
|
||||
thisrecord = {"t": t[i],
|
||||
"d": d[i],
|
||||
"p": p[i],
|
||||
"spm": spm[i],
|
||||
"hr": hr[i]}
|
||||
stroke_data.append(thisrecord)
|
||||
|
||||
try:
|
||||
durationstr = datetime.datetime.strptime(
|
||||
str(w.duration), "%H:%M:%S.%f")
|
||||
except ValueError:
|
||||
durationstr = datetime.datetime.strptime(str(w.duration), "%H:%M:%S")
|
||||
|
||||
workouttype = w.workouttype
|
||||
if workouttype in mytypes.otwtypes:
|
||||
workouttype = 'water'
|
||||
|
||||
if w.timezone == 'tzutc()': # pragma: no cover
|
||||
w.timezone = 'UTC'
|
||||
w.save()
|
||||
|
||||
try:
|
||||
wendtime = w.startdatetime.astimezone(pytz.timezone(
|
||||
w.timezone))+datetime.timedelta(seconds=makeseconds(durationstr))
|
||||
except UnknownTimeZoneError:
|
||||
wendtime = w.startdatetime.astimezone(pytz.utc)+datetime.timedelta(seconds=makeseconds(durationstr))
|
||||
|
||||
data = {
|
||||
"type": mytypes.c2mapping[workouttype],
|
||||
# w.startdatetime.isoformat(),
|
||||
"date": wendtime.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
"stroke_count": int(row.stroke_count),
|
||||
"timezone": w.timezone,
|
||||
"distance": int(w.distance),
|
||||
"time": int(10*makeseconds(durationstr)),
|
||||
"weight_class": c2wc(w.weightcategory),
|
||||
"comments": w.notes,
|
||||
'stroke_rate': int(row.df[' Cadence (stokes/min)'].mean()),
|
||||
'drag_factor': int(row.dragfactor),
|
||||
"heart_rate": {
|
||||
"average": averagehr,
|
||||
"max": maxhr,
|
||||
},
|
||||
"stroke_data": stroke_data,
|
||||
'workout': {
|
||||
'splits': intervaldata,
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def workout_export(self, workout, *args, **kwargs) -> str:
|
||||
try:
|
||||
if mytypes.c2mapping[workout.workouttype] is None: # pragma: no cover
|
||||
return "0"
|
||||
except KeyError: # pragma: no cover
|
||||
return "0"
|
||||
|
||||
_ = self.open()
|
||||
r = self.rower
|
||||
user = self.user
|
||||
|
||||
if (is_workout_user(user, workout)):
|
||||
c2userid = self.get_userid()
|
||||
if not c2userid: # pragma: no cover
|
||||
raise NoTokenError("User has no token")
|
||||
|
||||
dologging('debuglog.log',
|
||||
'Upload to C2 user {userid}'.format(userid=user.id))
|
||||
data = self.createworkoutdata(workout)
|
||||
dologging('c2_log.log', json.dumps(data))
|
||||
|
||||
if data == 0: # pragma: no cover
|
||||
return 0
|
||||
|
||||
authorizationstring = str('Bearer ' + r.c2token)
|
||||
headers = {'Authorization': authorizationstring,
|
||||
'user-agent': 'sanderroosendaal',
|
||||
'Content-Type': 'application/json'}
|
||||
|
||||
url = "https://log.concept2.com/api/users/%s/results" % (c2userid)
|
||||
|
||||
_ = myqueue(queue,
|
||||
handle_c2_sync,
|
||||
workout.id,
|
||||
url,
|
||||
headers,
|
||||
json.dumps(data, default=default))
|
||||
c2id = 0
|
||||
|
||||
return c2id
|
||||
|
||||
|
||||
|
||||
def get_workout(self, id):
|
||||
_ = self.open()
|
||||
_ = myqueue(queuehigh,
|
||||
handle_c2_getworkout,
|
||||
self.user.id,
|
||||
self.rower.c2token,
|
||||
id,
|
||||
self.rower.defaulttimezone)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
def get_workouts(self, *args, **kwargs):
|
||||
page = kwargs.get('page',1)
|
||||
|
||||
try:
|
||||
_ = self.open()
|
||||
except NoTokenError:
|
||||
return 0
|
||||
|
||||
# this part to get_workout_list
|
||||
workouts = self.get_workout_list(page=page)
|
||||
|
||||
counter = 0
|
||||
for workout in workouts:
|
||||
c2id = workout['id']
|
||||
if workout['new'] == 'NEW':
|
||||
self.get_workout(c2id)
|
||||
|
||||
return 1
|
||||
|
||||
# should be unified to workout list
|
||||
def get_workout_list(self, *args, **kwargs):
|
||||
page = kwargs.get('page',1)
|
||||
r = self.rower
|
||||
if (r.c2token == '') or (r.c2token is None): # pragma: no cover
|
||||
s = "Token doesn't exist. Need to authorize"
|
||||
return custom_exception_handler(401, s)
|
||||
elif (timezone.now() > r.tokenexpirydate): # pragma: no cover
|
||||
s = "Token expired. Needs to refresh."
|
||||
|
||||
return custom_exception_handler(401, s)
|
||||
|
||||
# ready to fetch. Hurray
|
||||
authorizationstring = str('Bearer ' + r.c2token)
|
||||
headers = {'Authorization': authorizationstring,
|
||||
'user-agent': 'sanderroosendaal',
|
||||
'Content-Type': 'application/json'}
|
||||
url = "https://log.concept2.com/api/users/me/results"
|
||||
url += "?page={page}".format(page=page)
|
||||
|
||||
res = requests.get(url, headers=headers)
|
||||
|
||||
if (res.status_code != 200): # pragma: no cover
|
||||
return []
|
||||
|
||||
workouts = []
|
||||
c2ids = [item['id'] for item in res.json()['data']]
|
||||
knownc2ids = uniqify([
|
||||
w.uploadedtoc2 for w in Workout.objects.filter(user=self.rower)
|
||||
])
|
||||
tombstones = [
|
||||
t.uploadedtoc2 for t in TombStone.objects.filter(user=self.rower)
|
||||
]
|
||||
parkedids = []
|
||||
try:
|
||||
with open('c2blocked.json', 'r') as c2blocked:
|
||||
jsondata = json.load(c2blocked)
|
||||
parkedids = jsondata['ids']
|
||||
except: # pragma: no cover
|
||||
pass
|
||||
|
||||
knownc2ids = uniqify(knownc2ids+tombstones+parkedids)
|
||||
for item in res.json()['data']:
|
||||
d = item['distance']
|
||||
i = item['id']
|
||||
ttot = item['time_formatted']
|
||||
s = item['date']
|
||||
r = item['type']
|
||||
s2 = item['source']
|
||||
c = item['comments']
|
||||
if i in knownc2ids:
|
||||
nnn = ''
|
||||
else: # pragma: no cover
|
||||
nnn = 'NEW'
|
||||
keys = ['id', 'distance', 'duration', 'starttime',
|
||||
'rowtype', 'source', 'comment', 'new']
|
||||
values = [i, d, ttot, s, r, s2, c, nnn]
|
||||
ress = dict(zip(keys, values))
|
||||
workouts.append(ress)
|
||||
|
||||
return workouts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# just as a quick test during development
|
||||
u = User.objects.get(id=1)
|
||||
|
||||
c2_integration_1 = C2Integration(u)
|
||||
250
rowers/integrations/integrations.py
Normal file
250
rowers/integrations/integrations.py
Normal file
@@ -0,0 +1,250 @@
|
||||
from abc import ABCMeta, ABC, abstractmethod
|
||||
from importlib import import_module
|
||||
from rowers.models import Rower, User
|
||||
from rowers.utils import NoTokenError
|
||||
|
||||
import requests
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
import arrow
|
||||
import urllib
|
||||
from uuid import uuid4
|
||||
|
||||
|
||||
|
||||
class SyncIntegration(metaclass=ABCMeta):
|
||||
oauth_data = {
|
||||
'tokenname':'token',
|
||||
'expirydatename':'exp',
|
||||
'refreshtokenname':'r',
|
||||
'redirect_uri': 'r',
|
||||
'client_secret': 's',
|
||||
'base_uri': 's'
|
||||
}
|
||||
|
||||
user = User()
|
||||
rower = Rower()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
user = args[1]
|
||||
self.user = user
|
||||
self.rower = user.rower
|
||||
|
||||
@classmethod
|
||||
def __subclasshook__(cls, subclass):
|
||||
return (hasattr(subclass, 'get_token') and
|
||||
callable(subclass.get_token) or
|
||||
NotImplemented)
|
||||
|
||||
|
||||
@abstractmethod
|
||||
def createworkoutdata(w, *args, **kwargs) -> dict:
|
||||
return {}
|
||||
|
||||
@abstractmethod
|
||||
def workout_export(workout, *args, **kwargs) -> str:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_workouts(*args, **kwargs) -> int:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_workout(id) -> int:
|
||||
pass
|
||||
|
||||
# need to unify workout list
|
||||
@abstractmethod
|
||||
def get_workout_list(*args, **kwargs) -> list:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def make_authorization_url(self, *args, **kwargs) -> str: # pragma: no cover
|
||||
# Generate a random string for the state parameter
|
||||
# Save it for use later to prevent xsrf attacks
|
||||
|
||||
state = str(uuid4())
|
||||
|
||||
params = {"client_id": self.oauth_data['client_id'],
|
||||
"response_type": "code",
|
||||
"redirect_uri": self.oauth_data['redirect_uri'],
|
||||
"scope": self.oauth_data['scope'],
|
||||
"state": state}
|
||||
|
||||
url = oauth_data['authorizaton_uri']+urllib.parse.urlencode(params)
|
||||
|
||||
return url
|
||||
|
||||
|
||||
@abstractmethod
|
||||
def get_token(self, code, *args, **kwargs) -> (str, int, str):
|
||||
redirect_uri = self.oauth_data['redirect_uri']
|
||||
client_secret = self.oauth_data['client_secret']
|
||||
client_id = self.oauth_data['client_id']
|
||||
base_uri = self.oauth_data['base_url']
|
||||
|
||||
post_data = {"grant_type": "authorization_code",
|
||||
"code": code,
|
||||
"redirect_uri": redirect_uri,
|
||||
"client_secret": client_secret,
|
||||
"client_id": client_id,
|
||||
}
|
||||
|
||||
try:
|
||||
headers = self.oauth_data['headers']
|
||||
except KeyError:
|
||||
headers = {'Accept': 'application/json',
|
||||
'Api-Key': client_id,
|
||||
'Content-Type': 'application/json',
|
||||
'user-agent': 'sanderroosendaal'}
|
||||
|
||||
if 'grant_type' in self.oauth_data:
|
||||
if self.oauth_data['grant_type']:
|
||||
post_data['grant_type'] = self.oauth_data['grant_type']
|
||||
if 'strava' in self.oauth_data['autorization_uri']:
|
||||
post_data['grant_type'] = "authorization_code"
|
||||
|
||||
if 'json' in self.oauth_data['content_type']:
|
||||
response = requests.post(
|
||||
base_uri,
|
||||
data=json.dumps(post_data),
|
||||
headers=headers)
|
||||
else: # pragma: no cover
|
||||
response = requests.post(
|
||||
base_uri,
|
||||
data=post_data,
|
||||
headers=headers, verify=False)
|
||||
|
||||
if response.status_code == 200 or response.status_code == 201:
|
||||
token_json = response.json()
|
||||
try:
|
||||
thetoken = token_json['access_token']
|
||||
except KeyError: # pragma: no cover
|
||||
raise NoTokenError("Failed to obtain token")
|
||||
try:
|
||||
refresh_token = token_json['refresh_token']
|
||||
except KeyError: # pragma: no cover
|
||||
refresh_token = ''
|
||||
try:
|
||||
expires_in = token_json['expires_in']
|
||||
except KeyError: # pragma: no cover
|
||||
expires_in = 0
|
||||
try:
|
||||
expires_in = int(expires_in)
|
||||
except (ValueError, TypeError): # pragma: no cover
|
||||
expires_in = 0
|
||||
else: # pragma: no cover
|
||||
raise NoTokenError("Failed to obtain token")
|
||||
|
||||
return [thetoken, expires_in, refresh_token]
|
||||
|
||||
|
||||
@abstractmethod
|
||||
def open(self, *args, **kwargs) -> str:
|
||||
token = getattr(self.rower, self.oauth_data['tokenname'])
|
||||
|
||||
try:
|
||||
tokenexpirydate = getattr(self.rower, self.oauth_data['expirydatename'])
|
||||
except (TypeError, AttributeError, KeyError): # pragma: no cover
|
||||
tokenexpirydate = None
|
||||
|
||||
if (token == '') or (token is None):
|
||||
raise NoTokenError("User has no token")
|
||||
else:
|
||||
tokenname = self.oauth_data['tokenname']
|
||||
refreshtokenname = self.oauth_data['refreshtokenname']
|
||||
expirydatename = self.oauth_data['expirydatename']
|
||||
if tokenexpirydate and timezone.now()+timedelta(seconds=60) > tokenexpirydate:
|
||||
token = self.token_refresh()
|
||||
elif tokenexpirydate is None and expirydatename is not None and 'strava' in expirydatename: # pragma: no cover
|
||||
token = self.token_refresh()
|
||||
|
||||
return token
|
||||
|
||||
def do_refresh_token(self, *args, **kwargs) -> (str, int, str):
|
||||
post_data = {"grant_type": "refresh_token",
|
||||
"client_secret": self.oauth_data['client_secret'],
|
||||
"client_id": self.oauth_data['client_id'],
|
||||
"refresh_token": refreshtoken,
|
||||
}
|
||||
headers = {'user-agent': 'sanderroosendaal',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': self.oauth_data['content_type']}
|
||||
|
||||
# for Strava
|
||||
if 'grant_type' in self.oauth_data:
|
||||
if self.oauth_data['grant_type']:
|
||||
post_data['grant_type'] = self.oauth_data['grant_type']
|
||||
|
||||
if self.oauth_data['bearer_auth']:
|
||||
headers['authorization'] = 'Bearer %s' % access_token
|
||||
|
||||
baseurl = self.oauth_data['base_url']
|
||||
|
||||
if 'json' in self.oauth_data['content_type']:
|
||||
try:
|
||||
response = requests.post(baseurl,
|
||||
data=json.dumps(post_data),
|
||||
headers=headers, verify=False)
|
||||
except: # pragma: no cover
|
||||
raise NoTokenError("Failed to get token")
|
||||
else:
|
||||
try:
|
||||
response = requests.post(baseurl,
|
||||
data=post_data,
|
||||
headers=headers, verify=False,
|
||||
)
|
||||
except: # pragma: no cover
|
||||
raise NoTokenError("Failed to get token")
|
||||
|
||||
if response.status_code == 200 or response.status_code == 201:
|
||||
token_json = response.json()
|
||||
else: # pragma: no cover
|
||||
raise NoTokenError("User has no token")
|
||||
|
||||
try:
|
||||
thetoken = token_json['access_token']
|
||||
except KeyError: # pragma: no cover
|
||||
raise NoTokenError("User has no token")
|
||||
|
||||
try:
|
||||
expires_in = token_json['expires_in']
|
||||
except KeyError:
|
||||
try:
|
||||
expires_at = arrow.get(token_json['expires_at']).timestamp()
|
||||
expires_in = expires_at - arrow.now().timestamp()
|
||||
except KeyError: # pragma: no cover
|
||||
expires_in = 0
|
||||
try:
|
||||
refresh_token = token_json['refresh_token']
|
||||
except KeyError: # pragma: no cover
|
||||
refresh_token = refreshtoken
|
||||
try:
|
||||
expires_in = int(expires_in)
|
||||
except (TypeError, ValueError): # pragma: no cover
|
||||
expires_in = 0
|
||||
|
||||
return [thetoken, expires_in, refresh_token]
|
||||
|
||||
|
||||
@abstractmethod
|
||||
def token_refresh(self, *args, **kwargs) -> str:
|
||||
refreshtoken = getattr(self.rower, oauth['refreshtokenname'])
|
||||
|
||||
if not refreshtoken:
|
||||
refreshtoken = getattr(self.rower, oauth['tokenname'])
|
||||
|
||||
access_token, expires_in, refresh_token = self.do_refresh_token()
|
||||
expirydatetime = timezone.now()+timedelta(seconds=expires_in)
|
||||
|
||||
setattr(self.rower, tokenname, access_token)
|
||||
if expirydatename is not None:
|
||||
setattr(self.rower, expirydatename, expirydatetime)
|
||||
if refreshtokenname is not None:
|
||||
setattr(self.rower, refreshtokenname, refresh_token)
|
||||
|
||||
self.rower.save()
|
||||
|
||||
return access_token
|
||||
|
||||
|
||||
Reference in New Issue
Block a user