rp3, untested
This commit is contained in:
@@ -2,3 +2,4 @@ from .c2 import C2Integration
|
||||
from .strava import StravaIntegration
|
||||
from .nk import NKIntegration
|
||||
from .sporttracks import SportTracksIntegration
|
||||
from .rp3 import RP3Integration
|
||||
|
||||
252
rowers/integrations/rp3.py
Normal file
252
rowers/integrations/rp3.py
Normal file
@@ -0,0 +1,252 @@
|
||||
from .integrations import SyncIntegration, NoTokenError
|
||||
from rowers.models import User, Rower, Workout, TombStone
|
||||
|
||||
from rowers.tasks import handle_rp3_async_workout
|
||||
from rowsandall_app.settings import (
|
||||
RP3_CLIENT_ID, RP3_CLIENT_KEY, RP3_REDIRECT_URI, RP3_CLIENT_SECRET,
|
||||
UPLOAD_SERVICE_URL, UPLOAD_SERVICE_SECRET
|
||||
)
|
||||
|
||||
from rowers.utils import myqueue, NoTokenError, dologging, uniqify
|
||||
from django.utils import timezone
|
||||
import requests
|
||||
import pandas as pd
|
||||
import arrow
|
||||
import django_rq
|
||||
queue = django_rq.get_queue('default')
|
||||
queuelow = django_rq.get_queue('low')
|
||||
queuehigh = django_rq.get_queue('high')
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
graphql_url = "https://rp3rowing-app.com/graphql"
|
||||
|
||||
|
||||
class RP3Integration(SyncIntegration):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(RP3Integration, self).__init__(*args, **kwargs)
|
||||
self.oauth_data = {
|
||||
'client_id': RP3_CLIENT_ID,
|
||||
'client_secret': RP3_CLIENT_SECRET,
|
||||
'redirect_uri': RP3_REDIRECT_URI,
|
||||
'autorization_uri': "https://rp3rowing-app.com/oauth/authorize?",
|
||||
'content_type': 'application/x-www-form-urlencoded',
|
||||
# 'content_type': 'application/json',
|
||||
'tokenname': 'rp3token',
|
||||
'refreshtokenname': 'rp3refreshtoken',
|
||||
'expirydatename': 'rp3tokenexpirydate',
|
||||
'bearer_auth': False,
|
||||
'base_url': "https://rp3rowing-app.com/oauth/token",
|
||||
'scope': 'read,write',
|
||||
}
|
||||
|
||||
|
||||
def createworkoutdata(self, w, *args, **kwargs):
|
||||
return None
|
||||
|
||||
|
||||
def workout_export(self, workout, *args, **kwargs) -> str:
|
||||
pass
|
||||
|
||||
|
||||
def get_workouts(self, *args, **kwargs) -> int:
|
||||
auth_token = self.open()
|
||||
|
||||
r = self.rower
|
||||
workouts_json = self.get_workout_list_json()
|
||||
|
||||
workouts_list = pd.json_normalize(workouts_json['data']['workouts'])
|
||||
|
||||
try:
|
||||
rp3ids = workouts_list['id'].values
|
||||
workouts_list.set_index('id',inpace=True)
|
||||
except (KeyError, IndexError):
|
||||
return 0
|
||||
|
||||
knownrp3ids = uniqify([
|
||||
w.uploadedtorp3 for w in Workout.objects.filter(user=rower)
|
||||
])
|
||||
|
||||
dologging('rp3_import.log',rp3ids)
|
||||
|
||||
newids = [rp3id for rp3id in rp3ids if rp3id not in knownrp3ids]
|
||||
|
||||
dologging('rp3_import.log',newids)
|
||||
|
||||
for id in newids:
|
||||
startdatetime = workouts_list.loc[id, 'executed_at_ios8601']
|
||||
dologging('rp3_import.log', startdatetime)
|
||||
|
||||
_ = myqueue(
|
||||
queuehigh,
|
||||
handle_rp3_async_workout,
|
||||
self.user.id,
|
||||
auth_token,
|
||||
id,
|
||||
startdatetime,
|
||||
20,
|
||||
{'timezone':self.rower.defaulttimezone}
|
||||
)
|
||||
|
||||
return 1
|
||||
|
||||
def get_workout(self, id, *args, **kwargs) -> int:
|
||||
startdatetime = kwargs.get('startdatetime', None)
|
||||
if not startdatetime:
|
||||
startdatetime = str(timezone.now())
|
||||
|
||||
auth_token = self.open()
|
||||
_ = myqueue(
|
||||
queuehigh,
|
||||
handle_rp3_async_workout,
|
||||
self.user.id,
|
||||
auth_token,
|
||||
id,
|
||||
startdatetime,
|
||||
20,
|
||||
timezone = self.rower.defaulttimezone
|
||||
)
|
||||
|
||||
def get_workout_schema(self, *args, **kwargs) -> dict:
|
||||
auth_token = self.open()
|
||||
headers = {'Authorization': 'Bearer ' + auth_token}
|
||||
get_schema = """{
|
||||
__type(name:"Workout") {
|
||||
name
|
||||
fields {
|
||||
name
|
||||
description
|
||||
type {
|
||||
name
|
||||
kind
|
||||
ofType {
|
||||
name
|
||||
kind
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
response = requests.post(
|
||||
url = graphql_url,
|
||||
headers=headers,
|
||||
json={'query':get_schema}
|
||||
)
|
||||
return response.json()
|
||||
|
||||
def get_workout_list_json(self, *args, **kwargs) -> dict:
|
||||
auth_token = self.open()
|
||||
r = self.rower
|
||||
|
||||
headers = {'Authorization': 'Bearer ' + auth_token}
|
||||
|
||||
get_workouts_list = """{
|
||||
workouts{
|
||||
id
|
||||
executed_at_iso8601
|
||||
}
|
||||
}"""
|
||||
|
||||
response = requests.post(
|
||||
url=graphql_url,
|
||||
headers=headers,
|
||||
json={'query': get_workouts_list}
|
||||
)
|
||||
|
||||
if (response.status_code != 200): # pragma: no cover
|
||||
raise NoTokenError("Need to authorize")
|
||||
|
||||
return response.json()
|
||||
|
||||
def get_workout_list(self, *args, **kwargs) -> list:
|
||||
r = self.rower
|
||||
|
||||
workouts_json = self.get_workout_list_json(*args, **kwargs)
|
||||
|
||||
workouts_list = pd.json_normalize(workouts_json['data']['workouts'])
|
||||
|
||||
knownrp3ids = uniqify([
|
||||
w.uploadedtorp3 for w in Workout.objects.filter(user=r)
|
||||
])
|
||||
|
||||
workouts = []
|
||||
|
||||
for key, data in workouts_list.iterrows():
|
||||
print(data)
|
||||
try:
|
||||
i = data['id']
|
||||
except KeyError: # pragma: no cover
|
||||
i = 0
|
||||
if i in knownrp3ids: # pragma: no cover
|
||||
nnn = ''
|
||||
else:
|
||||
nnn = 'NEW'
|
||||
|
||||
try:
|
||||
s = arrow.get(data['executed_at_iso8601']).isoformat()
|
||||
except KeyError: # pragma: no cover
|
||||
s = ''
|
||||
|
||||
keys = ['id', 'distance', 'duration', 'starttime',
|
||||
'rowtype', 'source', 'name', 'new']
|
||||
values = [i, '', '', s, '', 'rp3', '', nnn]
|
||||
|
||||
res = dict(zip(keys, values))
|
||||
|
||||
workouts.append(res)
|
||||
|
||||
|
||||
return workouts
|
||||
|
||||
|
||||
def make_authorization_url(self, *args, **kwargs) -> str: # pragma: no cover
|
||||
return super(RP3Integration, self).make_authorization_url(*args, **krags)
|
||||
|
||||
def get_token(self, code, *args, **kwargs) -> (str, int, str):
|
||||
post_data = {
|
||||
"client_id": RP3_CLIENT_KEY,
|
||||
"grant_type": "authorization_code",
|
||||
"code": code,
|
||||
"redirect_uri": RP3_REDIRECT_URI,
|
||||
"client_secret": RP3_CLIENT_SECRET,
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
"https://rp3rowing-app.com/oauth/token",
|
||||
data=post_data, verify=False,
|
||||
)
|
||||
|
||||
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 = ""
|
||||
expires_in = 0
|
||||
refresh_token = ""
|
||||
|
||||
return thetoken, expires_in, refresh_token
|
||||
|
||||
|
||||
def open(self, *args, **kwargs) -> str:
|
||||
tokenexpirydate = self.user.rower.rp3tokenexpirydate
|
||||
if tokenexpirydate is None:
|
||||
raise NoTokenError("No Token")
|
||||
if tokenexpirydate is not None and timezone.now()-timedelta(days=120)>tokenexpirydate:
|
||||
self.rower.rp3tokenexpirydate = timezone.now()-timedelta(days=1)
|
||||
self.rower.save()
|
||||
raise NoTokenError("No Token")
|
||||
return super(RP3Integration, self).open()
|
||||
|
||||
|
||||
def token_refresh(self, *args, **kwargs) -> str:
|
||||
return super(RP3Integration, self).token_refresh(*args, **kwargs)
|
||||
|
||||
|
||||
# just as a quick test during development
|
||||
u = User.objects.get(id=1)
|
||||
|
||||
integration_1 = RP3Integration(u)
|
||||
|
||||
@@ -1,267 +0,0 @@
|
||||
from celery import Celery, app
|
||||
from rowers.rower_rules import is_workout_user
|
||||
import time
|
||||
from django_rq import job
|
||||
from rowers.tasks import handle_rp3_async_workout
|
||||
from rowsandall_app.settings import (
|
||||
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
|
||||
STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET,
|
||||
RP3_CLIENT_ID, RP3_CLIENT_KEY, RP3_REDIRECT_URI, RP3_CLIENT_SECRET,
|
||||
UPLOAD_SERVICE_URL, UPLOAD_SERVICE_SECRET
|
||||
)
|
||||
from rowers.utils import myqueue, NoTokenError
|
||||
# All the functionality needed to connect to Runkeeper
|
||||
from rowers.imports import *
|
||||
|
||||
# Python
|
||||
import gzip
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
import base64
|
||||
from io import BytesIO
|
||||
|
||||
from rowers.utils import dologging
|
||||
|
||||
import django_rq
|
||||
queue = django_rq.get_queue('default')
|
||||
queuelow = django_rq.get_queue('low')
|
||||
queuehigh = django_rq.get_queue('high')
|
||||
|
||||
|
||||
oauth_data = {
|
||||
'client_id': RP3_CLIENT_ID,
|
||||
'client_secret': RP3_CLIENT_SECRET,
|
||||
'redirect_uri': RP3_REDIRECT_URI,
|
||||
'autorization_uri': "https://rp3rowing-app.com/oauth/authorize?",
|
||||
'content_type': 'application/x-www-form-urlencoded',
|
||||
# 'content_type': 'application/json',
|
||||
'tokenname': 'rp3token',
|
||||
'refreshtokenname': 'rp3refreshtoken',
|
||||
'expirydatename': 'rp3tokenexpirydate',
|
||||
'bearer_auth': False,
|
||||
'base_url': "https://rp3rowing-app.com/oauth/token",
|
||||
'scope': 'read,write',
|
||||
}
|
||||
|
||||
|
||||
graphql_url = "https://rp3rowing-app.com/graphql"
|
||||
|
||||
|
||||
# Checks if user has UnderArmour token, renews them if they are expired
|
||||
def rp3_open(user):
|
||||
tokenexpirydate = user.rower.rp3tokenexpirydate
|
||||
if tokenexpirydate is None:
|
||||
raise NoTokenError("No Token")
|
||||
if tokenexpirydate is not None and timezone.now()-timedelta(days=120)>tokenexpirydate:
|
||||
user.rower.rp3tokenexpirydate = timezone.now()-timedelta(days=1)
|
||||
user.rower.save()
|
||||
raise NoTokenError("No Token")
|
||||
return imports_open(user, oauth_data)
|
||||
|
||||
# Refresh ST token using refresh token
|
||||
|
||||
|
||||
def do_refresh_token(refreshtoken): # pragma: no cover
|
||||
return imports_do_refresh_token(refreshtoken, oauth_data)
|
||||
|
||||
# Exchange access code for long-lived access token
|
||||
|
||||
|
||||
def get_token(code): # pragma: no cover
|
||||
post_data = {
|
||||
"client_id": RP3_CLIENT_KEY,
|
||||
"grant_type": "authorization_code",
|
||||
"code": code,
|
||||
"redirect_uri": RP3_REDIRECT_URI,
|
||||
"client_secret": RP3_CLIENT_SECRET,
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
"https://rp3rowing-app.com/oauth/token",
|
||||
data=post_data, verify=False,
|
||||
)
|
||||
|
||||
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 = 0
|
||||
refresh_token = 0
|
||||
|
||||
return thetoken, expires_in, refresh_token
|
||||
|
||||
# Make authorization URL including random string
|
||||
|
||||
|
||||
def make_authorization_url(request): # pragma: no cover
|
||||
return imports_make_authorization_url(oauth_data)
|
||||
|
||||
|
||||
def get_rp3_workout_list(user):
|
||||
auth_token = rp3_open(user)
|
||||
|
||||
headers = {'Authorization': 'Bearer ' + auth_token}
|
||||
|
||||
get_workouts_list = """{
|
||||
workouts{
|
||||
id
|
||||
executed_at
|
||||
}
|
||||
}"""
|
||||
|
||||
response = requests.post(
|
||||
url=graphql_url,
|
||||
headers=headers,
|
||||
json={'query': get_workouts_list}
|
||||
)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def get_rp3_workouts(rower, do_async=True): # pragma: no cover
|
||||
try:
|
||||
auth_token = rp3_open(rower.user)
|
||||
except NoTokenError:
|
||||
return 0
|
||||
|
||||
res = get_rp3_workout_list(rower.user)
|
||||
|
||||
if (res.status_code != 200):
|
||||
return 0
|
||||
|
||||
s = '{d}'.format(d=res.json())
|
||||
dologging('rp3_import.log', s)
|
||||
workouts_list = pd.json_normalize(res.json()['data']['workouts'])
|
||||
try:
|
||||
rp3ids = workouts_list['id'].values
|
||||
workouts_list.set_index('id', inplace=True)
|
||||
except (KeyError, IndexError):
|
||||
return 0
|
||||
|
||||
knownrp3ids = uniqify([
|
||||
w.uploadedtorp3 for w in Workout.objects.filter(user=rower)
|
||||
])
|
||||
|
||||
dologging('rp3_import.log',rp3ids)
|
||||
|
||||
newids = [rp3id for rp3id in rp3ids if rp3id not in knownrp3ids]
|
||||
|
||||
dologging('rp3_import.log',newids)
|
||||
|
||||
for id in newids:
|
||||
startdatetime = workouts_list.loc[id, 'executed_at']
|
||||
dologging('rp3_import.log', startdatetime)
|
||||
|
||||
_ = myqueue(
|
||||
queuehigh,
|
||||
handle_rp3_async_workout,
|
||||
rower.user.id,
|
||||
auth_token,
|
||||
id,
|
||||
startdatetime,
|
||||
20,
|
||||
)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
def download_rp3_file(url, auth_token, filename): # pragma: no cover
|
||||
headers = {'Authorization': 'Bearer ' + auth_token}
|
||||
|
||||
res = requests.get(url, headers=headers)
|
||||
|
||||
if res.status_code == 200:
|
||||
with open(filename, 'wb') as f:
|
||||
f.write(res.content)
|
||||
|
||||
return res.status_code
|
||||
|
||||
|
||||
def get_rp3_workout_token(workout_id, auth_token, waittime=3, max_attempts=20): # pragma: no cover
|
||||
headers = {'Authorization': 'Bearer ' + auth_token}
|
||||
|
||||
get_download_link = """{
|
||||
download(workout_id: """ + str(workout_id) + """, type:csv){
|
||||
id
|
||||
status
|
||||
link
|
||||
}
|
||||
}"""
|
||||
|
||||
have_link = False
|
||||
download_url = ''
|
||||
counter = 0
|
||||
while not have_link:
|
||||
response = requests.post(
|
||||
url=graphql_url,
|
||||
headers=headers,
|
||||
json={'query': get_download_link}
|
||||
)
|
||||
|
||||
if response.status_code != 200:
|
||||
have_link = True
|
||||
|
||||
workout_download_details = pd.json_normalize(
|
||||
response.json()['data']['download'])
|
||||
|
||||
if workout_download_details.iat[0, 1] == 'ready':
|
||||
download_url = workout_download_details.iat[0, 2]
|
||||
have_link = True
|
||||
|
||||
counter += 1
|
||||
|
||||
if counter > max_attempts:
|
||||
have_link = True
|
||||
|
||||
time.sleep(waittime)
|
||||
|
||||
return download_url
|
||||
|
||||
|
||||
def get_rp3_workout_link(user, workout_id, waittime=3, max_attempts=20): # pragma: no cover
|
||||
auth_token = rp3_open(user)
|
||||
|
||||
return get_rp3_workout_token(workout_id, auth_token, waittime=waittime, max_attempts=max_attempts)
|
||||
|
||||
|
||||
def get_rp3_workout(user, workout_id, startdatetime=None): # pragma: no cover
|
||||
url = get_rp3_workout_link(user, workout_id)
|
||||
filename = 'media/RP3Import_'+str(workout_id)+'.csv'
|
||||
|
||||
auth_token = rp3_open(user)
|
||||
|
||||
if not startdatetime:
|
||||
startdatetime = str(timezone.now())
|
||||
|
||||
status_code = download_rp3_file(url, auth_token, filename)
|
||||
|
||||
if status_code != 200:
|
||||
return 0
|
||||
|
||||
userid = user.id
|
||||
|
||||
uploadoptions = {
|
||||
'secret': UPLOAD_SERVICE_SECRET,
|
||||
'user': userid,
|
||||
'file': filename,
|
||||
'workouttype': 'dynamic',
|
||||
'boattype': '1x',
|
||||
'rp3id': workout_id,
|
||||
'startdatetime': startdatetime,
|
||||
'timezone': str(user.rower.defaulttimezone)
|
||||
}
|
||||
|
||||
session = requests.session()
|
||||
newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'}
|
||||
session.headers.update(newHeaders)
|
||||
|
||||
response = session.post(UPLOAD_SERVICE_URL, json=uploadoptions)
|
||||
|
||||
if response.status_code != 200:
|
||||
return 0
|
||||
|
||||
return response.json()['id']
|
||||
@@ -3158,6 +3158,9 @@ def handle_update_wps(rid, types, ids, mode, debug=False, **kwargs):
|
||||
|
||||
@app.task
|
||||
def handle_rp3_async_workout(userid, rp3token, rp3id, startdatetime, max_attempts, debug=False, **kwargs):
|
||||
|
||||
timezone = kwargs.get('timezone', 'UTC')
|
||||
|
||||
headers = {'Authorization': 'Bearer ' + rp3token}
|
||||
|
||||
get_download_link = """{
|
||||
@@ -3239,8 +3242,11 @@ def handle_rp3_async_workout(userid, rp3token, rp3id, startdatetime, max_attempt
|
||||
'boattype': '1x',
|
||||
'rp3id': int(rp3id),
|
||||
'startdatetime': startdatetime,
|
||||
'timezone': timezone,
|
||||
}
|
||||
|
||||
print(uploadoptions)
|
||||
|
||||
session = requests.session()
|
||||
newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'}
|
||||
session.headers.update(newHeaders)
|
||||
|
||||
@@ -971,8 +971,8 @@ class RP3Objects(DjangoTestCase):
|
||||
csvfilename=filename
|
||||
)
|
||||
|
||||
@patch('rowers.rp3stuff.requests.get', side_effect=mocked_requests)
|
||||
@patch('rowers.rp3stuff.requests.post', side_effect=mocked_requests)
|
||||
@patch('rowers.integrations.rp3.requests.get', side_effect=mocked_requests)
|
||||
@patch('rowers.integrations.rp3.requests.post', side_effect=mocked_requests)
|
||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
||||
def test_rp3_import(self, mock_get, mockpost,
|
||||
mocked_getsmallrowdata_db):
|
||||
@@ -1002,7 +1002,7 @@ class RP3Objects(DjangoTestCase):
|
||||
res = tasks.handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,max_attempts)
|
||||
self.assertEqual(res,1)
|
||||
|
||||
@patch('rowers.rp3stuff.requests.post', side_effect=mocked_requests)
|
||||
@patch('rowers.integrations.rp3.requests.post', side_effect=mocked_requests)
|
||||
def notest_rp3_callback(self, mock_post):
|
||||
response = self.c.get('/rp3_callback?code=absdef23&scope=read',follow=True)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
BIN
rowers/tests/testdata/testdata.tcx.gz
vendored
BIN
rowers/tests/testdata/testdata.tcx.gz
vendored
Binary file not shown.
@@ -235,9 +235,9 @@ def do_sync(w, options, quick=False):
|
||||
|
||||
do_st_export = w.user.sporttracks_auto_export
|
||||
|
||||
if options['sporttracksid'] != 0 and options['sporttracksid'] != '':
|
||||
w.uploadedtosporttracks = options['sporttracksid']
|
||||
|
||||
sporttracksid = options.get('sporttracksid','')
|
||||
if sporttracksid != 0 and sporttracksid != '':
|
||||
w.uploadedtosporttracks = sporttracksid
|
||||
w.save()
|
||||
do_st_export = False
|
||||
try: # pragma: no cover
|
||||
|
||||
@@ -725,11 +725,9 @@ def rower_process_rp3callback(request): # pragma: no cover
|
||||
url = reverse('rower_exportsettings_view')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
res = rp3stuff.get_token(code)
|
||||
rp3_integration = RP3Integration(request.user)
|
||||
access_token, expires_in, refresh_token = rp3_integration.get_token(code)
|
||||
|
||||
access_token = res[0]
|
||||
expires_in = res[1]
|
||||
refresh_token = res[2]
|
||||
expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)
|
||||
|
||||
r = getrower(request.user)
|
||||
@@ -803,56 +801,39 @@ def rower_process_testcallback(request): # pragma: no cover
|
||||
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
|
||||
def workout_rp3import_view(request, userid=0):
|
||||
r = getrequestrower(request, userid=userid)
|
||||
rp3_integration = RP3Integration(request.user)
|
||||
|
||||
try:
|
||||
_ = rp3stuff.rp3_open(request.user)
|
||||
_ = rp3_integration.open()
|
||||
except NoTokenError: # pragma: no cover
|
||||
url = reverse('rower_rp3_authorize')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
res = rp3stuff.get_rp3_workout_list(request.user)
|
||||
workouts = rp3_integration.get_workout_list()
|
||||
datedict = {}
|
||||
for workout in workouts:
|
||||
datedict[workout['id']] = workout['starttime']
|
||||
|
||||
if (res.status_code != 200): # pragma: no cover
|
||||
if (res.status_code == 401):
|
||||
r = getrower(request.user)
|
||||
if (r.stravatoken == '') or (r.stravatoken is None):
|
||||
s = "Token doesn't exist. Need to authorize"
|
||||
return HttpResponseRedirect("/rowers/me/stravaauthorize/")
|
||||
message = "Something went wrong in workout_rp3import_view"
|
||||
messages.error(request, message)
|
||||
url = reverse('workouts_view')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
workouts_list = pd.json_normalize(res.json()['data']['workouts'])
|
||||
if request.method == "POST":
|
||||
try: # pragma: no cover
|
||||
tdict = dict(request.POST.lists())
|
||||
ids = tdict['workoutid']
|
||||
rp3ids = [int(id) for id in ids]
|
||||
|
||||
knownrp3ids = uniqify([
|
||||
w.uploadedtorp3 for w in Workout.objects.filter(user=r)
|
||||
])
|
||||
|
||||
workouts = []
|
||||
|
||||
for key, data in workouts_list.iterrows():
|
||||
try:
|
||||
i = data['id']
|
||||
for rp3id in rp3ids:
|
||||
rp3_integration.get_workout(rp3id,startdatetime=datedict[rp3id])
|
||||
# done, redirect to workouts list
|
||||
messages.info(
|
||||
request,
|
||||
'Your RP3 workouts will be imported in the background.'
|
||||
' It may take a few minutes before they appear.')
|
||||
url = reverse('workouts_view')
|
||||
return HttpResponseRedirect(url)
|
||||
except KeyError: # pragma: no cover
|
||||
i = 0
|
||||
if i in knownrp3ids: # pragma: no cover
|
||||
nnn = ''
|
||||
else:
|
||||
nnn = 'NEW'
|
||||
|
||||
try:
|
||||
s = data['executed_at']
|
||||
except KeyError: # pragma: no cover
|
||||
s = ''
|
||||
|
||||
keys = ['id', 'starttime', 'new']
|
||||
values = [i, s, nnn]
|
||||
|
||||
res = dict(zip(keys, values))
|
||||
|
||||
workouts.append(res)
|
||||
pass
|
||||
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
'url': '/rowers/list-workouts/',
|
||||
@@ -864,13 +845,18 @@ def workout_rp3import_view(request, userid=0):
|
||||
},
|
||||
]
|
||||
|
||||
return render(request, 'rp3_list_import.html',
|
||||
checknew = request.GET.get('selectallnew', False)
|
||||
|
||||
|
||||
return render(request, 'list_import.html',
|
||||
{
|
||||
'workouts': workouts,
|
||||
'rower': r,
|
||||
'active': 'nav-workouts',
|
||||
'breadcrumbs': breadcrumbs,
|
||||
'teams': get_my_teams(request.user)
|
||||
'teams': get_my_teams(request.user),
|
||||
'integration': 'RP3',
|
||||
'checknew': checknew,
|
||||
})
|
||||
|
||||
# The page where you select which Strava workout to import
|
||||
@@ -1461,7 +1447,8 @@ def workout_getrp3workout_all(request): # pragma: no cover
|
||||
|
||||
r = getrequestrower(request)
|
||||
|
||||
result = rp3stuff.get_rp3_workouts(r, do_async=True)
|
||||
rp3_integration = RP3Integration(request.user)
|
||||
result = rp3_integration.get_workouts()
|
||||
|
||||
if result:
|
||||
messages.info(
|
||||
@@ -1582,21 +1569,12 @@ def workout_getrp3importview(request, externalid):
|
||||
r = getrequestrower(request)
|
||||
if r.user != request.user: # pragma: no cover
|
||||
messages.error(
|
||||
request, 'You can only access your own workouts on the NK Logbook, not those of your athletes')
|
||||
request, 'You can only access your own workouts on the RP3 Logbook, not those of your athletes')
|
||||
url = reverse('workout_rp3import_view', kwargs={
|
||||
'userid': request.user.id})
|
||||
return HttpResponseRedirect(url)
|
||||
token = rp3stuff.rp3_open(r.user)
|
||||
startdatetime = request.GET.get('startdatetime')
|
||||
|
||||
_ = myqueue(queuehigh,
|
||||
handle_rp3_async_workout,
|
||||
r.user.id,
|
||||
token,
|
||||
externalid,
|
||||
startdatetime,
|
||||
20,
|
||||
)
|
||||
rp3_integration = RP3Integration(request.user)
|
||||
result = rp3_integration.get_workout(externalid)
|
||||
|
||||
messages.info(request, 'The workout will be imported in the background')
|
||||
|
||||
@@ -1684,8 +1662,11 @@ def workout_getimportview(request, externalid, source='c2', do_async=True):
|
||||
@login_required()
|
||||
def workout_getsporttracksworkout_all(request):
|
||||
st_integration = SportTracksIntegration(request.user)
|
||||
_ = st_integration.get_workouts()
|
||||
messages.info(request,"Your SportTracks workouts will be imported in the background")
|
||||
try:
|
||||
_ = st_integration.get_workouts()
|
||||
messages.info(request,"Your SportTracks workouts will be imported in the background")
|
||||
except NoTokenError:
|
||||
messages.error(request,"You have to connect to SportTracks first")
|
||||
|
||||
url = reverse('workouts_view')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
@@ -193,7 +193,7 @@ import sys
|
||||
import datetime
|
||||
import iso8601
|
||||
import rowers.rojabo_stuff as rojabo_stuff
|
||||
from rowers.rp3stuff import rp3_open
|
||||
|
||||
from rowers.tpstuff import tp_open
|
||||
from iso8601 import ParseError
|
||||
|
||||
@@ -206,7 +206,7 @@ import rowers.polarstuff as polarstuff
|
||||
from rowers.integrations import *
|
||||
|
||||
import rowers.tpstuff as tpstuff
|
||||
import rowers.rp3stuff as rp3stuff
|
||||
|
||||
import rowers.ownapistuff as ownapistuff
|
||||
from rowers.ownapistuff import TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_REDIRECT_URI
|
||||
from rowsandall_app.settings import (
|
||||
|
||||
Reference in New Issue
Block a user