diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py index a14cf6b2..feb15a12 100644 --- a/rowers/management/commands/processemail.py +++ b/rowers/management/commands/processemail.py @@ -207,6 +207,10 @@ class Command(BaseCommand): if user_is_not_basic(r.user): c2stuff.get_c2_workouts(r) + rowers = Rower.objects.filter(rp3_auto_import=True) + for r in rowers: + if user_is_not_basic(r.user): + res = rp3stuff.get_rp3_workouts(r) messages = Message.objects.filter(mailbox_id = workoutmailbox.id) message_ids = [m.id for m in messages] diff --git a/rowers/models.py b/rowers/models.py index 362fc604..ab28bf6c 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -995,6 +995,8 @@ class Rower(models.Model): rp3refreshtoken = models.TextField(default='',max_length=1000, blank=True,null=True) + rp3_auto_import = models.BooleanField(default=False) + trainingpeaks_auto_export = models.BooleanField(default=False) polartoken = models.CharField(default='',max_length=1000,blank=True,null=True) @@ -3836,6 +3838,7 @@ class RowerExportForm(ModelForm): 'strava_auto_import', 'strava_auto_delete', 'trainingpeaks_auto_export', + 'rp3_auto_import' ] # Simple form to set rower's Functional Threshold Power diff --git a/rowers/rp3stuff.py b/rowers/rp3stuff.py index 3b733b88..a4f9e99e 100644 --- a/rowers/rp3stuff.py +++ b/rowers/rp3stuff.py @@ -12,16 +12,24 @@ import gzip import base64 from io import BytesIO +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 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_SECRET, RP3_REDIRECT_URI,RP3_CLIENT_KEY, - RP3_CLIENT_ID, RP3_CLIENT_KEY, RP3_REDIRECT_URI, RP3_CLIENT_SECRET, + RP3_CLIENT_ID, RP3_CLIENT_KEY, RP3_REDIRECT_URI, RP3_CLIENT_SECRET, UPLOAD_SERVICE_URL, UPLOAD_SERVICE_SECRET ) +from rowers.tasks import handle_rp3_async_workout + from celery import Celery,app from django_rq import job @@ -60,14 +68,14 @@ def do_refresh_token(refreshtoken): def get_token(code): client_auth = requests.auth.HTTPBasicAuth(RP3_CLIENT_KEY, RP3_CLIENT_SECRET) post_data = { - "client_id":RP3_CLIENT_KEY, + "client_id":RP3_CLIENT_KEY, "grant_type": "authorization_code", "code": code, "redirect_uri":RP3_REDIRECT_URI, - "client_secret": RP3_CLIENT_SECRET, + "client_secret": RP3_CLIENT_SECRET, } headers = { - 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Type': 'application/x-www-form-urlencoded', } response = requests.post( @@ -107,13 +115,49 @@ def get_rp3_workout_list(user): } }""" response = requests.post( - url=graphql_url, - headers=headers, - json={'query': get_workouts_list} - ) + url=graphql_url, + headers=headers, + json={'query': get_workouts_list} + ) return response +def get_rp3_workouts(rower,do_async=True): + 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 + + workouts_list = pd.json_normalize(res.json()['data']['workouts']) + rp3ids = workouts_list['id'].values + workouts_list.set_index('id',inplace=True) + + knownrp3ids = uniqify([ + w.uploadedtorp3 for w in Workout.objects.filter(user=rower) + ]) + + newids = [rp3id for rp3id in rp3ids if not rp3id in knownrp3ids] + + for id in newids: + startdatetime = workouts_list.loc[id,'executed_at'] + + job = myqueue( + queuehigh, + handle_rp3_async_workout, + rower.user.id, + auth_token, + id, + startdatetime, + 10, + ) + + return 1 + def download_rp3_file(url,auth_token,filename): headers = {'Authorization': 'Bearer ' + auth_token } @@ -129,11 +173,11 @@ def get_rp3_workout_token(workout_id,auth_token,waittime=3,max_attempts=20): headers = {'Authorization': 'Bearer ' + auth_token } get_download_link = """{ - download(workout_id: """ + str(workout_id) + """, type:csv){ - id - status - link - } + download(workout_id: """ + str(workout_id) + """, type:csv){ + id + status + link + } }""" have_link = False @@ -144,7 +188,7 @@ def get_rp3_workout_token(workout_id,auth_token,waittime=3,max_attempts=20): url=graphql_url, headers=headers, json={'query': get_download_link} - ) + ) if response.status_code != 200: have_link = True diff --git a/rowers/tasks.py b/rowers/tasks.py index f22a3aab..c841185f 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -2872,7 +2872,7 @@ def add2(x, y,debug=False,**kwargs): graphql_url = "https://rp3rowing-app.com/graphql" @app.task -def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,debug=False,**kwargs): +def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,max_attempts,debug=False,**kwargs): headers = {'Authorization': 'Bearer ' + rp3token } get_download_link = """{ @@ -2886,7 +2886,7 @@ def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,debug=False,**k have_link = False download_url = '' counter = 0 - max_attempts = 20 + #max_attempts = 20 waittime = 3 while not have_link: response = requests.post( @@ -2895,6 +2895,7 @@ def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,debug=False,**k json={'query': get_download_link} ) + if response.status_code != 200: have_link = True @@ -2915,6 +2916,7 @@ def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,debug=False,**k return 0 filename = 'media/RP3Import_'+str(rp3id)+'.csv' + res = requests.get(download_url,headers=headers) if not startdatetime: @@ -2933,7 +2935,7 @@ def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,debug=False,**k 'file': filename, 'workouttype':'dynamic', 'boattype':'1x', - 'rp3id':rp3id, + 'rp3id':int(rp3id), 'startdatetime':startdatetime, } diff --git a/rowers/templates/rp3_list_import.html b/rowers/templates/rp3_list_import.html index 919e2242..5827dda7 100644 --- a/rowers/templates/rp3_list_import.html +++ b/rowers/templates/rp3_list_import.html @@ -7,6 +7,7 @@ {% block main %}