from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals from __future__ import unicode_literals, absolute_import # All the functionality needed to connect to Runkeeper from rowers.imports import * # Python import gzip 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') 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, UPLOAD_SERVICE_URL, UPLOAD_SERVICE_SECRET ) from rowers.tasks import handle_rp3_async_workout from celery import Celery,app from django_rq import job import time #from async_messages import message_user,messages 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', } from rowers.rower_rules import is_workout_user graphql_url = "https://rp3rowing-app.com/graphql" # Checks if user has UnderArmour token, renews them if they are expired def rp3_open(user): 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 client_auth = requests.auth.HTTPBasicAuth(RP3_CLIENT_KEY, RP3_CLIENT_SECRET) post_data = { "client_id":RP3_CLIENT_KEY, "grant_type": "authorization_code", "code": code, "redirect_uri":RP3_REDIRECT_URI, "client_secret": RP3_CLIENT_SECRET, } headers = { 'Content-Type': 'application/x-www-form-urlencoded', } 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): r = Rower.objects.get(user=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) ]) newids = [rp3id for rp3id in rp3ids if not rp3id in knownrp3ids] for id in newids: startdatetime = workouts_list.loc[id,'executed_at'] dologging('rp3_import.log',startdatetime) 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): # 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 r = Rower.objects.get(user=user) 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' r = Rower.objects.get(user=user) 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, } 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']