from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals from rowers.views.statements import * import numpy def default(o): if isinstance(o, numpy.int64): return int(o) raise TypeError # Send workout to TP @login_required() def workout_tp_upload_view(request,id=0): message = "" r = getrower(request.user) res = -1 try: thetoken = tp_open(r.user) except NoTokenError: return HttpResponseRedirect("/rowers/me/tpauthorize/") # ready to upload. Hurray w = get_workout_permitted(request.user,id) r = w.user if (checkworkoutuser(request.user,w)): tcxfile = tpstuff.createtpworkoutdata(w) if tcxfile: res,reason,status_code,headers = tpstuff.uploadactivity( r.tptoken,tcxfile, name=w.name ) if res == 0: message = "Upload to TrainingPeaks failed with status code "+str(status_code)+": "+reason try: os.remove(tcxfile) except WindowsError: pass messages.error(request,message) else: # res != 0 w.uploadedtotp = res w.save() os.remove(tcxfile) messages.info(request,'Uploaded to TrainingPeaks') else: # no tcxfile message = "Upload to TrainingPeaks failed" w.uploadedtotp = -1 w.save() messages.error(request,message) else: # not allowed to upload message = "You are not allowed to export this workout to TP" messages.error(request,message) url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) # Send workout to Strava # abundance of error logging here because there were/are some bugs @login_required() def workout_strava_upload_view(request,id=0): message = "" r = getrower(request.user) res = -1 try: thetoken = strava_open(request.user) except NoTokenError: return HttpResponseRedirect("/rowers/me/stravaauthorize/") if (r.stravatoken == '') or (r.stravatoken is None): s = "Token doesn't exist. Need to authorize" return HttpResponseRedirect("/rowers/me/stravaauthorize/") else: # ready to upload. Hurray w = get_workout_permitted(request.user,id) r = w.user if (checkworkoutuser(request.user,w)): try: tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w) if tcxfile: with open(tcxfile,'rb') as f: try: newnotes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com' except TypeError: newnotes = 'from '+w.workoutsource+' via rowsandall.com' if w.workouttype in mytypes.rowtypes: activity_type = r.stravaexportas else: activity_type = mytypes.stravamapping[w.workouttype] res,mes = stravastuff.handle_stravaexport( f,w.name, r.stravatoken, description=newnotes, activity_type=activity_type) if res==0: messages.error(request,mes) w.uploadedtostrava = -1 w.save() try: os.remove(tcxfile) except WindowsError: pass url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id), }) response = HttpResponseRedirect(url) return response try: w.uploadedtostrava = res w.save() try: os.remove(tcxfile) except WindowsError: pass url = reverse('workout_edit_view',kwargs={'id':w.id}) messages.info(request,mes) except: with open("media/stravaerrors.log","a") as errorlog: errorstring = str(sys.exc_info()[0]) timestr = strftime("%Y%m%d-%H%M%S") errorlog.write(timestr+errorstring+"\r\n") errorlog.write("views.py line 826\r\n") message = 'Error: '+errorstring messages.error(request,message) else: # No tcxfile message = "Strava Data error "+tcxmessg messages.error(request,message) w.uploadedtostrava = -1 w.save() url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id), }) response = HttpResponseRedirect(url) url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id), } ) response = HttpResponseRedirect(url) except ActivityUploadFailed as e: message = "Strava Upload error: %s" % e messages.error(request,message) w.uploadedtostrava = -1 w.save() os.remove(tcxfile) url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id), }) response = HttpResponseRedirect(url) return response # Upload workout to Concept2 logbook @login_required() def workout_c2_upload_view(request,id=0): message = "" # ready to upload. Hurray w = get_workout(id) r = w.user try: message,c2id = c2stuff.workout_c2_upload(request.user,w) except NoTokenError: return HttpResponseRedirect("/rowers/me/c2authorize/") if message and c2id <=0: messages.error(request,message) elif message: messages.info(request,message) url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id) }) response = HttpResponseRedirect(url) return response # Upload workout to RunKeeper @login_required() def workout_runkeeper_upload_view(request,id=0): message = "" w = get_workout(id) r = w.user try: thetoken = runkeeper_open(r.user) except NoTokenError: return HttpResponseRedirect("/rowers/me/runkeeperauthorize/") # ready to upload. Hurray if (checkworkoutuser(request.user,w)): data = runkeeperstuff.createrunkeeperworkoutdata(w) if not data: message = "Data error" messages.error(request,message) url = reverse(r.defaultlandingpage, kwargs = { 'id':id, }) return HttpResponseRedirect(url) authorizationstring = str('Bearer ' + thetoken) headers = {'Authorization': authorizationstring, 'user-agent': 'sanderroosendaal', 'Content-Type': 'application/vnd.com.runkeeper.NewFitnessActivity+json', 'Content-Length':'nnn'} url = "https://api.runkeeper.com/fitnessActivities" response = requests.post(url,headers=headers,data=json.dumps(data,default=default)) # check for duplicate error first if (response.status_code == 409 ): message = "Duplicate error" messages.error(request,message) w.uploadedtorunkeeper = -1 w.save() elif (response.status_code == 201 or response.status_code==200): runkeeperid = runkeeperstuff.getidfromresponse(response) w.uploadedtorunkeeper = runkeeperid w.save() url = reverse('workout_edit_view', kwargs={'id':encoder.encode_hex(w.id)}) return HttpResponseRedirect(url) else: s = response message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text) messages.error(request,message) else: message = "You are not authorized to upload this workout" messages.error(request,message) url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) # Upload workout to Underarmour @login_required() def workout_underarmour_upload_view(request,id=0): message = "" w = get_workout(id) r = w.user try: thetoken = underarmour_open(r.user) except NoTokenError: return HttpResponseRedirect("/rowers/me/underarmourauthorize/") # ready to upload. Hurray if (checkworkoutuser(request.user,w)): data = underarmourstuff.createunderarmourworkoutdata(w) if not data: message = "Data error" messages.error(request,message) url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) authorizationstring = str('Bearer ' + thetoken) headers = {'Authorization': authorizationstring, 'Api-Key': UNDERARMOUR_CLIENT_KEY, 'user-agent': 'sanderroosendaal', 'Content-Type': 'application/json', } url = "https://api.ua.com/v7.1/workout/" response = requests.post(url,headers=headers,data=json.dumps(data,default=default)) # check for duplicate error first if (response.status_code == 409 ): message = "Duplicate error" messages.error(request,message) w.uploadedtounderarmour = -1 w.save() elif (response.status_code == 201 or response.status_code==200): underarmourid = underarmourstuff.getidfromresponse(response) w.uploadedtounderarmour = underarmourid w.save() url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)}) return HttpResponseRedirect(url) else: s = response message = "Something went wrong in workout_underarmour_upload_view: %s " % s.reason messages.error(request,message) else: message = "You are not authorized to upload this workout" messages.error(request,message) url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) # Upload workout to SportTracks @login_required() def workout_sporttracks_upload_view(request,id=0): message = "" # ready to upload. Hurray w = get_workout(id) r = w.user try: thetoken = sporttracks_open(r.user) except NoTokenError: return HttpResponseRedirect("/rowers/me/sporttracksauthorize/") if (checkworkoutuser(request.user,w)): data = sporttracksstuff.createsporttracksworkoutdata(w) if not data: message = "Data error" messages.error(request,message) url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) authorizationstring = str('Bearer ' + thetoken) headers = {'Authorization': authorizationstring, 'user-agent': 'sanderroosendaal', 'Content-Type': 'application/json'} url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json" response = requests.post(url,headers=headers,data=json.dumps(data,default=default)) # check for duplicate error first if (response.status_code == 409 ): message = "Duplicate error" messages.error(request,message) w.uploadedtosporttracks = -1 w.save() elif (response.status_code == 201 or response.status_code==200): s= response.json() sporttracksid = sporttracksstuff.getidfromresponse(response) w.uploadedtosporttracks = sporttracksid w.save() message = "Upload to SportTracks was successful" messages.info(request,message) url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)}) return HttpResponseRedirect(url) else: s = response message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason messages.error(request,message) else: message = "You are not authorized to upload this workout" messages.error(request,message) url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) # Concept2 authorization @login_required() def rower_c2_authorize(request): # Generate a random string for the state parameter # Save it for use later to prevent xsrf attacks state = str(uuid4()) scope = "user:read,results:write" params = {"client_id": C2_CLIENT_ID, "response_type": "code", "redirect_uri": C2_REDIRECT_URI} url = "http://log.concept2.com/oauth/authorize?"+ urllib.parse.urlencode(params) url += "&scope="+scope return HttpResponseRedirect(url) # Strava Authorization @login_required() def rower_strava_authorize(request): # Generate a random string for the state parameter # Save it for use later to prevent xsrf attacks state = str(uuid4()) params = {"client_id": STRAVA_CLIENT_ID, "response_type": "code", "redirect_uri": STRAVA_REDIRECT_URI, "scope": "activity:write,activity:read_all"} url = "https://www.strava.com/oauth/authorize?"+ urllib.parse.urlencode(params) return HttpResponseRedirect(url) # Polar Authorization @login_required() def rower_polar_authorize(request): state = str(uuid4()) params = {"client_id": POLAR_CLIENT_ID, "response_type": "code", "redirect_uri": POLAR_REDIRECT_URI, "state": state, # "scope":"accesslink.read_all" } url = "https://flow.polar.com/oauth2/authorization?" +urllib.parse.urlencode(params) return HttpResponseRedirect(url) # Runkeeper authorization @login_required() def rower_runkeeper_authorize(request): # Generate a random string for the state parameter # Save it for use later to prevent xsrf attacks state = str(uuid4()) params = {"client_id": RUNKEEPER_CLIENT_ID, "response_type": "code", "state": state, "redirect_uri": RUNKEEPER_REDIRECT_URI} url = "https://runkeeper.com/apps/authorize?"+ urllib.parse.urlencode(params) return HttpResponseRedirect(url) # SportTracks Authorization @login_required() def rower_sporttracks_authorize(request): # Generate a random string for the state parameter # Save it for use later to prevent xsrf attacks state = str(uuid4()) params = {"client_id": SPORTTRACKS_CLIENT_ID, "response_type": "code", "state": state, "redirect_uri": SPORTTRACKS_REDIRECT_URI} url = "https://api.sporttracks.mobi/oauth2/authorize?"+ urllib.parse.urlencode(params) return HttpResponseRedirect(url) # Underarmour Authorization @login_required() def rower_underarmour_authorize(request): # Generate a random string for the state parameter # Save it for use later to prevent xsrf attacks state = str(uuid4()) redirect_uri = UNDERARMOUR_REDIRECT_URI url = 'https://www.mapmyfitness.com/v7.1/oauth2/authorize/?' \ 'client_id={0}&response_type=code&redirect_uri={1}'.format( UNDERARMOUR_CLIENT_KEY, redirect_uri ) return HttpResponseRedirect(url) # Underarmour Authorization @login_required() def rower_tp_authorize(request): # Generate a random string for the state parameter # Save it for use later to prevent xsrf attacks state = str(uuid4()) params = {"client_id": TP_CLIENT_KEY, "response_type": "code", "redirect_uri": TP_REDIRECT_URI, "scope": "file:write", } url = "https://oauth.trainingpeaks.com/oauth/authorize/?" +urllib.parse.urlencode(params) return HttpResponseRedirect(url) # Concept2 token refresh. URL for manual refresh. Not visible to users @login_required() def rower_c2_token_refresh(request): r = getrower(request.user) res = c2stuff.do_refresh_token(r.c2refreshtoken) if res[0] != None: access_token = res[0] expires_in = res[1] refresh_token = res[2] expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in) r = getrower(request.user) r.c2token = access_token r.tokenexpirydate = expirydatetime r.c2refreshtoken = refresh_token r.save() successmessage = "Tokens refreshed. Good to go" messages.info(request,successmessage) else: message = "Something went wrong (refreshing tokens). Please reauthorize:" messages.error(request,message) url = reverse('workouts_view') return HttpResponseRedirect(url) # Underarmour token refresh. URL for manual refresh. Not visible to users @login_required() def rower_underarmour_token_refresh(request): r = getrower(request.user) res = underarmourstuff.do_refresh_token( r.underarmourrefreshtoken, r.underarmourtoken ) access_token = res[0] expires_in = res[1] refresh_token = res[2] expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in) r = getrower(request.user) r.underarmourtoken = access_token r.underarmourtokenexpirydate = expirydatetime r.underarmourrefreshtoken = refresh_token r.save() successmessage = "Tokens refreshed. Good to go" messages.info(request,successmessage) url = reverse('workouts_view') return HttpResponseRedirect(url) # TrainingPeaks token refresh. URL for manual refresh. Not visible to users @login_required() def rower_tp_token_refresh(request): r = getrower(request.user) res = tpstuff.do_refresh_token( r.tprefreshtoken, ) access_token = res[0] expires_in = res[1] refresh_token = res[2] expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in) r = getrower(request.user) r.tptoken = access_token r.tptokenexpirydate = expirydatetime r.tprefreshtoken = refresh_token r.save() successmessage = "Tokens refreshed. Good to go" messages.info(request,successmessage) url = reverse('workouts_view') return HttpResponseRedirect(url) # SportTracks token refresh. URL for manual refresh. Not visible to users @login_required() def rower_sporttracks_token_refresh(request): r = getrower(request.user) res = sporttracksstuff.do_refresh_token( r.sporttracksrefreshtoken, ) access_token = res[0] expires_in = res[1] refresh_token = res[2] expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in) r = getrower(request.user) r.sporttrackstoken = access_token r.sporttrackstokenexpirydate = expirydatetime r.sporttracksrefreshtoken = refresh_token r.save() successmessage = "Tokens refreshed. Good to go" messages.info(request,successmessage) url = reverse('workouts_view') return HttpResponseRedirect(url) # Concept2 Callback @login_required() def rower_process_callback(request): try: code = request.GET['code'] res = c2stuff.get_token(code) except MultiValueDictKeyError: message = "The resource owner or authorization server denied the request" messages.error(request,message) url = reverse('workouts_view') return HttpResponseRedirect(url) access_token = res[0] if access_token == 0: message = res[1] message += ' Contact info@rowsandall.com if this behavior persists.' messages.error(request,message) url = reverse('workouts_view') return HttpResponseRedirect(url) expires_in = res[1] refresh_token = res[2] expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in) r = getrower(request.user) r.c2token = access_token r.tokenexpirydate = expirydatetime r.c2refreshtoken = refresh_token r.save() successmessage = "Tokens stored. Good to go" messages.info(request,successmessage) url = reverse('workouts_view') return HttpResponseRedirect(url) # dummy @login_required() def rower_process_twittercallback(request): return "dummy" # Process Polar Callback @login_required() def rower_process_polarcallback(request): try: code = request.GET['code'] except MultiValueDictKeyError: try: message = request.GET['error'] except MultiValueDictKeyError: message = "access error" messages.error(request,message) url = reverse('workouts_view') return HttpResponseRedirect(url) access_token, expires_in, user_id = polarstuff.get_token(code) expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in) r = getrower(request.user) r.polartoken = access_token r.polartokenexpirydate = expirydatetime r.polaruserid = user_id r.save() successmessage = "Tokens stored. Good to go" messages.info(request,successmessage) url = reverse('workouts_view') return HttpResponseRedirect(url) # Process Strava Callback @login_required() def rower_process_stravacallback(request): try: code = request.GET['code'] scope = request.GET['scope'] except MultiValueDictKeyError: try: message = request.GET['error'] except MultiValueDictKeyError: message = "access error" messages.error(request,message) url = reverse('workouts_view') return HttpResponseRedirect(url) res = stravastuff.get_token(code) if res[0]: access_token = res[0] expires_in = res[1] refresh_token = res[2] expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in) r = getrower(request.user) r.stravatoken = access_token r.stravatokenexpirydate = expirydatetime r.stravarefreshtoken = refresh_token r.save() successmessage = "Tokens stored. Good to go" messages.info(request,successmessage) url = reverse('workouts_view') return HttpResponseRedirect(url) else: message = "Something went wrong with the Strava authorization" messages.error(request,message) url = reverse('workouts_view') return HttpResponseRedirect(url) # Process Runkeeper callback @login_required() def rower_process_runkeepercallback(request): code = request.GET['code'] res = runkeeperstuff.get_token(code) access_token = res[0] if access_token == 0: messages.error(request,"Something went wrong importing the token") url = reverse('workouts_view') return HttpResponseRedirect(url) r = getrower(request.user) r.runkeepertoken = access_token r.save() successmessage = "Tokens stored. Good to go" messages.info(request,successmessage) url = reverse('workouts_view') return HttpResponseRedirect(url) # Process SportTracks callback @login_required() def rower_process_sporttrackscallback(request): code = request.GET['code'] res = sporttracksstuff.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) r.sporttrackstoken = access_token r.sporttrackstokenexpirydate = expirydatetime r.sporttracksrefreshtoken = refresh_token r.save() successmessage = "Tokens stored. Good to go" messages.info(request,successmessage) url = reverse('workouts_view') return HttpResponseRedirect(url) # Process Underarmour callback @login_required() def rower_process_underarmourcallback(request): code = request.GET['code'] res = underarmourstuff.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) r.underarmourtoken = access_token r.underarmourtokenexpirydate = expirydatetime r.underarmourrefreshtoken = refresh_token r.save() successmessage = "Tokens stored. Good to go" messages.info(request,successmessage) url = reverse('workouts_view') return HttpResponseRedirect(url) # Process TrainingPeaks callback @login_required() def rower_process_tpcallback(request): code = request.GET['code'] res = tpstuff.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) r.tptoken = access_token r.tptokenexpirydate = expirydatetime r.tprefreshtoken = refresh_token r.save() successmessage = "Tokens stored. Good to go" messages.info(request,successmessage) url = reverse('workouts_view') return HttpResponseRedirect(url) # Process Own API callback - for API testing purposes @login_required() def rower_process_testcallback(request): code = request.GET['code'] res = ownapistuff.get_token(code) access_token = res[0] expires_in = res[1] refresh_token = res[2] expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in) text = "Access Token:\n" text += access_token text += "\n\nRefresh Token:\n" text += refresh_token return HttpResponse(text) # The page where you select which Strava workout to import @login_required() def workout_stravaimport_view(request,message="",userid=0): r = getrequestrower(request,userid=userid) if r.user != request.user: messages.info(request,"You cannot import other people's workouts from Strava") try: thetoken = strava_open(request.user) except NoTokenError: return HttpResponseRedirect("/rowers/me/stravaauthorize/") res = stravastuff.get_strava_workout_list(request.user) if (res.status_code != 200): 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_stravaimport_view" messages.error(request,message) url = reverse('workouts_view') return HttpResponseRedirect(url) else: workouts = [] r = getrower(request.user) stravaids = [int(item['id']) for item in res.json()] stravadata = [{ 'id':int(item['id']), 'elapsed_time':item['elapsed_time'], 'start_date':item['start_date'], } for item in res.json()] wfailed = Workout.objects.filter(user=r,uploadedtostrava=-1) for w in wfailed: for item in stravadata: elapsed_time = item['elapsed_time'] start_date = item['start_date'] stravaid = item['id'] if arrow.get(start_date) == arrow.get(w.startdatetime): elapsed_td = datetime.timedelta(seconds=int(elapsed_time)) elapsed_time = datetime.datetime.strptime( str(elapsed_td), "%H:%M:%S" ) if str(elapsed_time)[-7:] == str(w.duration)[-7:]: w.uploadedtostrava = int(stravaid) w.save() knownstravaids = uniqify([ w.uploadedtostrava for w in Workout.objects.filter(user=r) ]) newids = [stravaid for stravaid in stravaids if not stravaid in knownstravaids] for item in res.json(): d = int(float(item['distance'])) i = item['id'] if i in knownstravaids: nnn = '' else: nnn = 'NEW' n = item['name'] ttot = str(datetime.timedelta(seconds=int(float(item['elapsed_time'])))) s = item['start_date'] r = item['type'] keys = ['id','distance','duration','starttime','type','name','new'] values = [i,d,ttot,s,r,n,nnn] res = dict(zip(keys,values)) workouts.append(res) breadcrumbs = [ { 'url':'/rowers/list-workouts/', 'name':'Workouts' }, { 'url':reverse('workout_stravaimport_view'), 'name':'Strava' }, ] r = getrower(request.user) return render(request,'strava_list_import.html', {'workouts':workouts, 'rower':r, 'active':'nav-workouts', 'breadcrumbs':breadcrumbs, 'teams':get_my_teams(request.user), }) return HttpResponse(res) # The page where you select which RunKeeper workout to import @login_required() def workout_runkeeperimport_view(request,message="",userid=0): res = runkeeperstuff.get_runkeeper_workout_list(request.user) if (res.status_code != 200): if (res.status_code == 401): r = getrower(request.user) if (r.runkeepertoken == '') or (r.runkeepertoken is None): s = "Token doesn't exist. Need to authorize" return HttpResponseRedirect("/rowers/me/runkeeperauthorize/") message = "Something went wrong in workout_runkeeperimport_view" messages.error(request,message) if settings.DEBUG: return HttpResponse(res) else: url = reverse('workouts_view') return HttpResponseRedirect(url) workouts = [] for item in res.json()['items']: d = int(float(item['total_distance'])) i = getidfromuri(item['uri']) ttot = str(datetime.timedelta(seconds=int(float(item['duration'])))) s = item['start_time'] r = item['type'] keys = ['id','distance','duration','starttime','type'] values = [i,d,ttot,s,r] res = dict(zip(keys,values)) workouts.append(res) breadcrumbs = [ { 'url':'/rowers/list-workouts/', 'name':'Workouts' }, { 'url':reverse('workout_runkeeperimport_view'), 'name':'Runkeeper' } ] r = getrower(request.user) return render(request,'runkeeper_list_import.html', {'workouts':workouts, 'rower':r, 'active':'nav-workouts', 'breadcrumbs':breadcrumbs, 'teams':get_my_teams(request.user), }) return HttpResponse(res) # The page where you select which RunKeeper workout to import @login_required() def workout_underarmourimport_view(request,message="",userid=0): res = underarmourstuff.get_underarmour_workout_list(request.user) if (res.status_code != 200): return HttpResponseRedirect("/rowers/me/underarmourauthorize/") workouts = [] items = res.json()['_embedded']['workouts'] for item in items: s = item['start_datetime'] i,r = underarmourstuff.get_idfromuri(request.user,item['_links']) n = item['name'] try: d = item['aggregates']['distance_total'] except KeyError: d = 0 try: ttot = item['aggregates']['active_time_total'] except KeyError: ttot = 0 keys = ['id','distance','duration','starttime','type'] values = [i,d,ttot,s,r] thedict = dict(zip(keys,values)) workouts.append(thedict) rower = getrower(request.user) breadcrumbs = [ { 'url':'/rowers/list-workouts/', 'name':'Workouts' }, { 'url':reverse('workout_c2import_view'), 'name':'Concept2' }, ] return render(request,'underarmour_list_import.html', {'workouts':workouts, 'breadcrumbs':breadcrumbs, 'rower':rower, 'active':'nav-workouts', 'teams':get_my_teams(request.user), }) return HttpResponse(res) # the page where you select which Polar workout to Import @login_required() def workout_polarimport_view(request,userid=0): exercises = polarstuff.get_polar_workouts(request.user) workouts = [] try: a = exercises.status_code if a == 401: messages.error(request,'Not authorized. You need to connect to Polar first') url = reverse('workouts_view') return HttpResponseRedirect(url) except: pass for exercise in exercises: try: d = exercise['distance'] except KeyError: d = 0 i = exercise['id'] transactionid = exercise['transaction-id'] starttime = exercise['start-time'] rowtype = exercise['sport'] durationstring = exercise['duration'] duration = isodate.parse_duration(durationstring) keys = ['id','distance','duration','starttime','type','transactionid'] values = [i,d,duration,starttime,rowtype,transactionid] res = dict(zip(keys,values)) workouts.append(res) breadcrumbs = [ { 'url':'/rowers/list-workouts/', 'name':'Workouts' }, { 'url':reverse('workout_polarimport_view'), 'name':'Polar' }, ] r = getrower(request.user) return render(request, 'polar_list_import.html', { 'workouts':workouts, 'active':'nav-workouts', 'rower':r, 'breadcrumbs':breadcrumbs, 'teams':get_my_teams(request.user), }) # The page where you select which SportTracks workout to import @login_required() def workout_sporttracksimport_view(request,message="",userid=0): res = sporttracksstuff.get_sporttracks_workout_list(request.user) if (res.status_code != 200): if (res.status_code == 401): r = getrower(request.user) if (r.sporttrackstoken == '') or (r.sporttrackstoken is None): s = "Token doesn't exist. Need to authorize" return HttpResponseRedirect("/rowers/me/sporttracksauthorize/") else: return HttpResponseRedirect("/rowers/me/sporttracksrefresh/") message = "Something went wrong in workout_sporttracksimport_view" messages.error(request,message) if settings.DEBUG: return HttpResponse(res) else: url = reverse('workouts_view') return HttpResponseRedirect(url) workouts = [] r = getrower(request.user) stids = [int(getidfromuri(item['uri'])) for item in res.json()['items']] knownstids = uniqify([ w.uploadedtosporttracks for w in Workout.objects.filter(user=r) ]) newids = [stid for stid in stids if not stid in knownstids] for item in res.json()['items']: d = int(float(item['total_distance'])) i = int(getidfromuri(item['uri'])) if i in knownstids: nnn = '' else: nnn = 'NEW' n = item['name'] ttot = str(datetime.timedelta(seconds=int(float(item['duration'])))) s = item['start_time'] r = item['type'] keys = ['id','distance','duration','starttime','type','name','new'] values = [i,d,ttot,s,r,n,nnn] res = dict(zip(keys,values)) workouts.append(res) r = getrower(request.user) breadcrumbs = [ { 'url':'/rowers/list-workouts/', 'name':'Workouts' }, { 'url':reverse('workout_sporttracksimport_view'), 'name':'SportTracks' }, ] return render(request,'sporttracks_list_import.html', {'workouts':workouts, 'breadcrumbs':breadcrumbs, 'active':'nav-workouts', 'rower':r, 'teams':get_my_teams(request.user), }) return HttpResponse(res) # List of workouts on Concept2 logbook. This view only used for debugging @login_required() def c2listdebug_view(request,page=1,message=""): try: thetoken = c2_open(request.user) except NoTokenError: return HttpResponseRedirect("/rowers/me/c2authorize/") r = getrower(request.user) res = c2stuff.get_c2_workout_list(request.user,page=page) if (res.status_code != 200): message = "Something went wrong in workout_c2import_view (C2 token renewal)" messages.error(request,message) if settings.DEBUG: return HttpResponse(res) else: url = reverse('workouts_view') return HttpResponseRedirect(url) else: workouts = [] 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'] keys = ['id','distance','duration','starttime','rowtype','source','comment'] values = [i,d,ttot,s,r,s2,c] res = dict(zip(keys,values)) workouts.append(res) return render(request, 'c2_list_import2.html', {'workouts':workouts, 'teams':get_my_teams(request.user), }) # Import all unknown workouts available on Concept2 logbook @login_required() def workout_getc2workout_all(request,page=1,message=""): try: thetoken = c2_open(request.user) except NoTokenError: return HttpResponseRedirect("/rowers/me/c2authorize/") res = c2stuff.get_c2_workout_list(request.user,page=page) if (res.status_code != 200): message = "Something went wrong in workout_c2import_view (C2 token refresh)" messages.error(request,message) else: r = getrower(request.user) c2ids = [item['id'] for item in res.json()['data']] alldata = {} for item in res.json()['data']: alldata[item['id']] = item knownc2ids = uniqify([ w.uploadedtoc2 for w in Workout.objects.filter(user=r) ]) newids = [c2id for c2id in c2ids if not c2id in knownc2ids] for c2id in newids: workoutid = c2stuff.create_async_workout(alldata, request.user,c2id) url = reverse('workouts_view') return HttpResponseRedirect(url) # List of workouts available on Concept2 logbook - for import @login_required() def workout_c2import_view(request,page=1,userid=0,message=""): r = getrequestrower(request,userid=userid) if r.user != request.user: messages.info(request,"You cannot import other people's workouts from Concept2") r = getrower(request.user) try: thetoken = c2_open(request.user) except NoTokenError: return HttpResponseRedirect("/rowers/me/c2authorize/") res = c2stuff.get_c2_workout_list(request.user,page=page) if (res.status_code != 200): message = "Something went wrong in workout_c2import_view (C2 token refresh)" messages.error(request,message) url = reverse('workouts_view') return HttpResponseRedirect(url) workouts = [] c2ids = [item['id'] for item in res.json()['data']] knownc2ids = uniqify([ w.uploadedtoc2 for w in Workout.objects.filter(user=r) ]) newids = [c2id for c2id in c2ids if not c2id in knownc2ids] 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: nnn = 'NEW' keys = ['id','distance','duration','starttime','rowtype','source','comment','new'] values = [i,d,ttot,s,r,s2,c,nnn] res = dict(zip(keys,values)) workouts.append(res) breadcrumbs = [ { 'url':'/rowers/list-workouts/', 'name':'Workouts' }, { 'url':reverse('workout_c2import_view'), 'name':'Concept2' }, { 'url':reverse('workout_c2import_view',kwargs={'page':page}), 'name':'Page '+str(page) } ] r = getrower(request.user) return render(request, 'c2_list_import2.html', {'workouts':workouts, 'rower':r, 'active':'nav-workouts', 'breadcrumbs':breadcrumbs, 'teams':get_my_teams(request.user), 'page':page, }) importsources = { 'c2':c2stuff, 'strava':stravastuff, 'polar':polarstuff, 'ownapi':ownapistuff, 'runkeeper':runkeeperstuff, 'sporttracks':sporttracksstuff, 'trainingpeaks':tpstuff, 'underarmour':underarmourstuff } @login_required() def workout_getimportview(request,externalid,source = 'c2'): res = importsources[source].get_workout(request.user,externalid) if not res[0]: messages.error(request,res[1]) url = reverse('workouts_view') return HttpResponseRedirect(url) strokedata = res[1] data = res[0] # Now works only for C2 try: if strokedata == 0: messages.error(request,'An error occurred importing the workout from Concept2') url = reverse('workouts_view') return HttpResponseRedirect(url) except ValueError: pass if strokedata.empty: print('aap') distance = data['distance'] c2id = data['id'] workouttype = mytypes.c2mappinginv[data['type']] verified = data['verified'] startdatetime = iso8601.parse_date(data['date']) weightclass = data['weight_class'] weightcategory = 'hwt' if weightclass == "L": weightcategory = 'lwt' totaltime = data['time']/10. duration = dataprep.totaltime_sec_to_string(totaltime) duration = datetime.datetime.strptime(duration,'%H:%M:%S.%f').time() try: timezone_str = data['timezone'] except: timezone_str = 'UTC' if timezone_str is None: timezone_str = 'UTC' workoutdate = startdatetime.astimezone( pytz.timezone(timezone_str) ).strftime('%Y-%m-%d') starttime = startdatetime.astimezone( pytz.timezone(timezone_str) ).strftime('%H:%M:%S') r = getrower(request.user) id, message = dataprep.create_row_df(r, distance, duration, startdatetime, workouttype=workouttype) w = Workout.objects.get(id=id) w.uploadedtoc2 = c2id w.name = 'Imported from C2' w.workouttype = workouttype w.save() message = "This workout does not have any stroke data associated with it. We created synthetic stroke data." messages.info(request,message) url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id), }) return HttpResponseRedirect(url) # strokedata not empty - continue id,message = importsources[source].add_workout_from_data( request.user, externalid,data, strokedata, source=source, workoutsource=source) w = get_workout(encoder.encode_hex(id)) if 'workout' in data: if 'splits' in data['workout']: splitdata = data['workout']['splits'] elif 'intervals' in data['workout']: splitdata = data['workout']['intervals'] else: splitdata = False else: splitdata = False # splitdata (only for C2) if splitdata: w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename) w.save() from rowingdata.trainingparser import getlist # set stroke data in CSV file if sa: values = getlist(sa) units = getlist(sa,sel='unit') types = getlist(sa,sel='type') rowdata = rdata(w.csvfilename) if rowdata: rowdata.updateintervaldata(values, units,types,results) rowdata.write_csv(w.csvfilename,gzip=True) dataprep.update_strokedata(w.id,rowdata.df) if source == 'strava': w.uploadedtostrava = externalid elif source == 'c2': w.uploadedtoc2 = externalid elif source == 'polar': w.uploadedtopolar = externalid elif source == 'runkeeper': w.uploadedtorunkeeper = externalid elif source == 'sporttracks': w.uploadedtosporttracks = externalid elif source == 'trainingpeaks': w.uploadedtotp = externalid elif source == 'underarmour': w.uploadedtounderarmour = externalid w.save() if message: messages.error(request,message) r = getrower(request.user) url = reverse(r.defaultlandingpage, kwargs = { 'id':encoder.encode_hex(w.id) }) return HttpResponseRedirect(url) # Imports all new workouts from SportTracks @login_required() def workout_getsporttracksworkout_all(request): res = sporttracksstuff.get_sporttracks_workout_list(request.user) if (res.status_code == 200): r = getrower(request.user) stids = [int(getidfromuri(item['uri'])) for item in res.json()['items']] knownstids = uniqify([ w.uploadedtosporttracks for w in Workout.objects.filter(user=r) ]) newids = [stid for stid in stids if not stid in knownstids] for sporttracksid in newids: res = sporttracksstuff.get_sporttracks_workout( request.user,sporttracksid) data = res.json() id,message = add_workout_from_stdata( request.user,sporttracksid,data ) if id==0: messages.error(request,message) else: w = Workout.objects.get(id=id) w.uploadedtosporttracks=sporttracksid w.save() url = reverse('workouts_view') return HttpResponseRedirect(url) # Imports all new workouts from SportTracks @login_required() def workout_getstravaworkout_all(request): r = getrower(request.user) res = stravastuff.get_strava_workouts(r) if res == 1: messages.info(request,"Your workouts are being imported and should appear on the site in the next 15 minutes") else: messages.error(request,"Couldn't import Strava workouts ") url = reverse('workouts_view') return HttpResponseRedirect(url) # Imports all new workouts from SportTracks @login_required() def workout_getstravaworkout_next(request): r = Rower.objects.get(user=request.user) res = stravastuff.get_strava_workout_list(r.user) if (res.status_code != 200): return 0 else: stravaids = [int(item['id']) for item in res.json()] alldata = {} for item in res.json(): alldata[item['id']] = item knownstravaids = uniqify([ w.uploadedtostrava for w in Workout.objects.filter(user=r) ]) newids = [stravaid for stravaid in stravaids if not stravaid in knownstravaids] theid = newids[0] workoutid = stravastuff.create_async_workout(alldata,r.user,stravaid,debug=True) url = reverse('workouts_view') return HttpResponseRedirect(url)