From b58ba932fd27bb2683e1545eb91a10d7b2ef58f7 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Fri, 21 May 2021 09:36:38 +0200
Subject: [PATCH] removed UnderArmour / MapMyFitness
---
rowers/admin.py | 2 -
rowers/c2stuff.py | 78 +--
rowers/models.py | 7 -
rowers/tasks.py | 36 +-
rowers/templates/export.html | 209 -------
rowers/templates/imports.html | 137 -----
rowers/templates/menu_other.html | 1 -
rowers/templates/menu_workout.html | 15 -
rowers/templates/menu_workouts.html | 1 -
rowers/templates/rower_exportsettings.html | 6 +-
rowers/templates/underarmour_list_import.html | 41 --
rowers/tests/test_imports.py | 103 ----
rowers/traverselinktest.py | 1 -
rowers/underarmourstuff.py | 544 ------------------
rowers/uploads.py | 13 +-
rowers/urls.py | 5 -
rowers/utils.py | 9 +
rowers/views/importviews.py | 350 +----------
rowers/views/statements.py | 6 +-
rowers/views/userviews.py | 1 -
rowers/views/workoutviews.py | 15 -
rowsandall_app/urls.py | 1 -
22 files changed, 54 insertions(+), 1527 deletions(-)
delete mode 100644 rowers/templates/export.html
delete mode 100644 rowers/templates/imports.html
delete mode 100644 rowers/templates/underarmour_list_import.html
delete mode 100644 rowers/underarmourstuff.py
diff --git a/rowers/admin.py b/rowers/admin.py
index 9b6be6ab..5c179e88 100644
--- a/rowers/admin.py
+++ b/rowers/admin.py
@@ -46,8 +46,6 @@ class RowerInline(admin.StackedInline):
'sporttrackstoken','sporttrackstokenexpirydate',
'sporttracksrefreshtoken',
'sporttracks_auto_export',
- 'underarmourtoken','underarmourtokenexpirydate',
- 'underarmourrefreshtoken',
'mapmyfitness_auto_export',
'tptoken','tptokenexpirydate','tprefreshtoken',
'trainingpeaks_auto_export',
diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py
index 3f3346ac..e533a713 100644
--- a/rowers/c2stuff.py
+++ b/rowers/c2stuff.py
@@ -22,15 +22,7 @@ from scipy import optimize
from json.decoder import JSONDecodeError
from pytz.exceptions import UnknownTimeZoneError
-
-def dologging(s):
- tstamp = time.localtime()
- timestamp = time.strftime('%b-%d-%Y %H:%M:%S', tstamp)
- with open('debuglog.log','a') as f:
- f.write('\n')
- f.write(timestamp)
- f.write(' ')
- f.write(s)
+from rowers.utils import dologging
from rowsandall_app.settings import (
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
@@ -39,6 +31,7 @@ from rowsandall_app.settings import (
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')
@@ -840,64 +833,15 @@ def get_workout(user,c2id,do_async=False):
elif (timezone.now()>r.tokenexpirydate):
s = "Token expired. Needs to refresh."
return custom_exception_handler(401,s),0
- else:
- # 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/"+str(c2id)
- s = requests.get(url,headers=headers)
- if s.status_code != 200: # pragma: no cover
- if s.status_code == 404:
- raise PermissionDenied("You have no access to this resource")
- else:
- s = "Something went wrong with the import"
- return custom_exception_handler(401,s), 0
+ job = myqueue(queuehigh,
+ handle_c2_getworkout,
+ user.id,
+ r.c2token,
+ c2id,
+ r.defaulttimezone)
- data = s.json()['data']
- alldata = {c2id:data}
- splitdata = None
- #with open('c2temp.json','w') as f:
- # f.write(json.dumps(s.json()))
- # print(s.json())
-
- if do_async:
- print('aap',alldata)
- job = myqueue(queuehigh,
- handle_c2_async_workout,
- alldata,
- r.user.id,
- r.c2token,
- c2id,
- 0,
- r.defaulttimezone)
-
- return data, pd.DataFrame()
-
-
- if 'workout' in data:
- if 'splits' in data['workout']: # pragma: no cover
- splitdata = data['workout']['splits']
- elif 'intervals' in data['workout']: # pragma: no cover
- splitdata = data['workout']['intervals']
- else: # pragma: no cover
- splitdata = None
-
- # Check if workout has stroke data, and get the stroke data
-
- if data['stroke_data']:
- res2 = get_c2_workout_strokes(user,c2id)
- if res2.status_code == 200:
- strokedata = pd.DataFrame.from_dict(res2.json()['data'])
- else: # pragma: no cover
- strokedata = pd.DataFrame()
- else: # pragma: no cover
- strokedata = pd.DataFrame()
-
-
- return data,strokedata
+ return 1
# Get stroke data belonging to C2 ID
def get_c2_workout_strokes(user,c2id):
@@ -1027,9 +971,9 @@ def workout_c2_upload(user,w,asynchron=False):
if not c2userid: # pragma: no cover
raise NoTokenError("User has no token")
- dologging('Upload to C2 user {userid}'.format(userid=user.id))
+ dologging('debuglog.log','Upload to C2 user {userid}'.format(userid=user.id))
data = createc2workoutdata(w)
- dologging(json.dumps(data))
+ dologging('debuglog.log',json.dumps(data))
if data == 0: # pragma: no cover
return "Error: No data file. Contact info@rowsandall.com if the problem persists",0
diff --git a/rowers/models.py b/rowers/models.py
index d5449391..7b72f243 100644
--- a/rowers/models.py
+++ b/rowers/models.py
@@ -988,10 +988,6 @@ class Rower(models.Model):
sporttracksrefreshtoken = models.CharField(default='',max_length=200,
blank=True,null=True)
sporttracks_auto_export = models.BooleanField(default=False)
- underarmourtoken = models.CharField(default='',max_length=200,blank=True,null=True)
- underarmourtokenexpirydate = models.DateTimeField(blank=True,null=True)
- underarmourrefreshtoken = models.CharField(default='',max_length=200,
- blank=True,null=True)
mapmyfitness_auto_export = models.BooleanField(default=False)
tptoken = models.CharField(default='',max_length=1000,blank=True,null=True)
tptokenexpirydate = models.DateTimeField(blank=True,null=True)
@@ -3201,7 +3197,6 @@ class Workout(models.Model):
maxhr = models.BigIntegerField(blank=True,null=True)
uploadedtostrava = models.BigIntegerField(default=0)
uploadedtosporttracks = models.BigIntegerField(default=0)
- uploadedtounderarmour = models.BigIntegerField(default=0)
uploadedtotp = models.BigIntegerField(default=0)
uploadedtorunkeeper = models.BigIntegerField(default=0)
uploadedtogarmin = models.BigIntegerField(default=0)
@@ -3283,7 +3278,6 @@ class TombStone(models.Model):
uploadedtoc2 = models.IntegerField(default=0)
uploadedtostrava = models.BigIntegerField(default=0)
uploadedtosporttracks = models.BigIntegerField(default=0)
- uploadedtounderarmour = models.BigIntegerField(default=0)
uploadedtotp = models.BigIntegerField(default=0)
uploadedtorunkeeper = models.BigIntegerField(default=0)
uploadedtonk = models.BigIntegerField(default=0)
@@ -3294,7 +3288,6 @@ def create_tombstone_on_delete(sender, instance, **kwargs):
user=instance.user,
uploadedtoc2 = instance.uploadedtoc2,
uploadedtostrava = instance.uploadedtostrava,
- uploadedtounderarmour = instance.uploadedtounderarmour,
uploadedtotp = instance.uploadedtotp,
uploadedtorunkeeper = instance.uploadedtorunkeeper,
uploadedtonk = instance.uploadedtonk
diff --git a/rowers/tasks.py b/rowers/tasks.py
index 72a9528a..df1a1c5d 100644
--- a/rowers/tasks.py
+++ b/rowers/tasks.py
@@ -25,6 +25,8 @@ from rowingdata import rowingdata as rdata
from datetime import timedelta
from sqlalchemy import create_engine
+from rowers.imports import splituadata
+
#from celery import app
from rowers.celery import app
from celery import shared_task
@@ -64,7 +66,7 @@ from django_rq import job
from django.utils import timezone
from django.utils.html import strip_tags
-from rowers.utils import deserialize_list,ewmovingaverage,wavg
+from rowers.utils import deserialize_list,ewmovingaverage,wavg,dologging
from rowers.emails import htmlstrip
from rowers import mytypes
@@ -125,15 +127,6 @@ from rowers.courseutils import (
InvalidTrajectoryError
)
-def dologging(s):
- tstamp = time.localtime()
- timestamp = time.strftime('%b-%d-%Y %H:%M:%S', tstamp)
- with open('debuglog.log','a') as f:
- f.write('\n')
- f.write(timestamp)
- f.write(' ')
- f.write(s)
-
# Concept2 logbook sends over split data for each interval
# We use it here to generate a custom summary
# Some users complained about small differences
@@ -2985,7 +2978,23 @@ def handle_nk_async_workout(alldata,userid,nktoken,nkid,delaysec,defaulttimezone
# return
return workoutid
+@app.task
+def handle_c2_getworkout(userid,c2token,c2id,defaulttimezone,debug=False,**kwargs):
+ authorizationstring = str('Bearer ' + c2token)
+ headers = {'Authorization': authorizationstring,
+ 'user-agent': 'sanderroosendaal',
+ 'Content-Type': 'application/json'}
+ url = "https://log.concept2.com/api/users/me/results/"+str(c2id)
+ s = requests.get(url,headers=headers)
+ if s.status_code != 200: # pragma: no cover
+ return 0
+
+ data = s.json()['data']
+ alldata = {c2id:data}
+ splitdata = None
+
+ return handle_c2_async_workout(alldata,userid,c2token,c2id,0,defaulttimezone)
@app.task
def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone,debug=False,**kwargs):
@@ -3007,8 +3016,8 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
weightclass = data['weight_class']
s = 'User {userid}, C2 ID {c2id}'.format(userid=userid,c2id=c2id)
- dologging(s)
- dologging(json.dumps(data))
+ dologging('debuglog.log',s)
+ dologging('debuglog.log',json.dumps(data))
try:
title = data['name']
@@ -3041,7 +3050,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
s = 'Time zone {timezone}, stardatetime {startdatetime}, duration {duration}'.format(
timezone=timezone,startdatetime=startdatetime,
duration=duration)
- dologging(s)
+ dologging('debuglog.log',s)
@@ -3246,6 +3255,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
return workoutid
+
@app.task
def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debug=False,**kwargs):
fetchresolution = 'high'
diff --git a/rowers/templates/export.html b/rowers/templates/export.html
deleted file mode 100644
index e28275c0..00000000
--- a/rowers/templates/export.html
+++ /dev/null
@@ -1,209 +0,0 @@
-{% extends "base.html" %}
-{% load static %}
-{% load rowerfilters %}
-
-{% block title %}Export {% endblock %}
-
-{% block content %}
-
-
-
-
Connect
-
-
-
Click one of the below logos to connect to the service of your choice.
- You only need to do this once. After that, the site will have access until you
- revoke the authorization for the "rowingdata" app.
-
-
-

-
-
-
-

-
-
-
-
-

-
-
-
-
-
-
-
Export Settings
-
-
-
-
-
-
-
-
-{% endblock %}
diff --git a/rowers/templates/imports.html b/rowers/templates/imports.html
deleted file mode 100644
index f2bd719a..00000000
--- a/rowers/templates/imports.html
+++ /dev/null
@@ -1,137 +0,0 @@
- {% extends "base.html" %}
- {% block title %}Import Workouts{% endblock title %}
- {% block content %}
-
-
-
Import Workouts
-
-
-
-
-
-
-
-
-
Import workouts from Strava
-
-
-
-
-
-
-
-
-
-
Import workouts from the Concept2 logbook
-
-
-
-
-
-
-
-
Import workouts from SportTracks
-
-
-
-
-
-
-
-
-
-
Import workouts from RunKeeper
-
-
-
-
-
-
-
-
-
-
Import workouts from MapMyFitness/UnderArmour
-
-
-
-
-
-
-
-
-
-
Import workouts from Polar Flow.
Note: No workout selection possible. Automatically imports all new workouts
-
-
-
-
-
-
Connect
-
-
-
Click one of the below logos to connect to the service of your choice.
- You only need to do this once. After that, the site will have
- access until you
- revoke the authorization for the "rowingdata" app.
-
-
-

-
-
-
-

-
-
-
-
-

-
-
-
-
-
-
Auto Import/Export Settings
-
-
-
Use the form below to set your auto import/export settings.
- As we implement auto import/export for various partner sites, this form will be expanded.
-
-
Auto Import = rowsandall.com will regularly poll the partner site for new
- workouts and automatically import new workouts
-
-
-
Auto Export = New workouts uploaded to rowsandall.com will be automatically synchronized
- to the partner site
-
-
These settings only have effect if you are a user on one
- of the paid plans
-
-
-
-
-
-
-
- {% endblock content %}
-
diff --git a/rowers/templates/menu_other.html b/rowers/templates/menu_other.html
index b565018e..71789d84 100644
--- a/rowers/templates/menu_other.html
+++ b/rowers/templates/menu_other.html
@@ -39,7 +39,6 @@
Strava
RunKeeper
SportTracks
- MapMyFitness
Polar
diff --git a/rowers/templates/menu_workout.html b/rowers/templates/menu_workout.html
index 96313d6d..2b77156f 100644
--- a/rowers/templates/menu_workout.html
+++ b/rowers/templates/menu_workout.html
@@ -207,21 +207,6 @@
{% endif %}
-
- {% if workout.uploadedtounderarmour %}
-
- MapMyFitness
-
- {% elif user.rower.underarmourtoken == None or user.rower.underarmourtoken == '' %}
-
- Connect to MapMyFitness
-
- {% else %}
-
- MapMyFitness
-
- {% endif %}
-
{% if workout.uploadedtotp %}
diff --git a/rowers/templates/menu_workouts.html b/rowers/templates/menu_workouts.html
index 12931af6..82045548 100644
--- a/rowers/templates/menu_workouts.html
+++ b/rowers/templates/menu_workouts.html
@@ -42,7 +42,6 @@
Strava
RunKeeper
SportTracks
- MapMyFitness
Polar
RP3
diff --git a/rowers/templates/rower_exportsettings.html b/rowers/templates/rower_exportsettings.html
index e631af88..d6aabe5d 100644
--- a/rowers/templates/rower_exportsettings.html
+++ b/rowers/templates/rower_exportsettings.html
@@ -17,9 +17,6 @@
{% if rower.sporttrackstoken is not None and rower.sporttrackstoken != '' %}
SportTracks,
{% endif %}
- {% if rower.underarmourtoken is not None and rower.underarmourtoken != '' %}
- Under Armour (MapMyFitness),
- {% endif %}
{% if rower.tptoken is not None and rower.tptoken != '' %}
TrainingPeaks,
{% endif %}
@@ -66,7 +63,7 @@
automatically auto-sync workouts from Garmin to Rowsandall (but not in the other direction). If you
want to export our structured workout sessions to your Garmin device, you have to set the "Garmin Activity"
to a activity type that is supported by your watch. Not all watches support "Custom" activities, so
- you may have to set your activity to Run or Ride while rowing.
+ you may have to set your activity to Run or Ride while rowing.
Strava Auto Import also imports activity changes on Strava to Rowsandall, except when you delete
@@ -80,7 +77,6 @@



-

Available on MapMyFitness (UnderArmour)
-{% if workouts %}
-
-
-
- | Import |
- Date/Time |
- Duration |
- Total Distance |
- Type |
-
-
-
- {% for workout in workouts %}
-
- |
- Import |
- {{ workout|ualookup:'starttime' }} |
- {{ workout|ualookup:'duration' }} |
- {{ workout|ualookup:'distance' }} m |
- {{ workout|ualookup:'type' }} |
-
-
- {% endfor %}
-
-
-{% else %}
- No workouts found. We only list workouts with time data series.
-{% endif %}
-{% endblock %}
-
-{% block sidebar %}
-{% include 'menu_workouts.html' %}
-{% endblock %}
diff --git a/rowers/tests/test_imports.py b/rowers/tests/test_imports.py
index 7da2bcdf..d49285a0 100644
--- a/rowers/tests/test_imports.py
+++ b/rowers/tests/test_imports.py
@@ -1149,109 +1149,6 @@ class RunKeeperObjects(DjangoTestCase):
-@pytest.mark.django_db
-@override_settings(TESTING=True)
-class UAObjects(DjangoTestCase):
- def setUp(self):
- self.c = Client()
- self.u = User.objects.create_user('john',
- 'sander@ds.ds',
- 'koeinsloot')
-
- self.u.first_name = 'John'
- self.u.last_name = 'Sander'
- self.u.save()
- self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
- gdproptindate=timezone.now()
- )
-
-
- self.r.underarmourtoken = '12'
- self.r.underarmourrefreshtoken = '12'
- self.r.underarmourtokenexpirydate = arrow.get(datetime.datetime.now()+datetime.timedelta(days=1)).datetime
- self.r.save()
-
- self.c.login(username='john',password='koeinsloot')
-
- self.nu = datetime.datetime.now()
-
- filename = 'rowers/tests/testdata/testdata.csv'
-
- rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2,
- hrut1=self.r.ut1,hrat=self.r.at,
- hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp)
- row = rdata(csvfile=filename,rower=rr)
- totaldist = row.df['cum_dist'].max()
- totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
- totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]
-
-
- hours = int(totaltime/3600.)
- minutes = int((totaltime - 3600.*hours)/60.)
- seconds = int(totaltime - 3600.*hours - 60.*minutes)
- tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds))
-
- duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
-
-
- workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
- workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
-
- self.w = Workout.objects.create(
- name='testworkout',workouttype='water',
- user=self.r,date=self.nu.strftime('%Y-%m-%d'),
- starttime=workoutstarttime,
- startdatetime=row.rowdatetime,
- duration=duration,distance=totaldist,
- csvfilename=filename
- )
-
- @patch('rowers.imports.requests.post', side_effect=mocked_requests)
- def test_underarmour_callback(self, mock_post):
- response = self.c.get('/underarmour_callback?code=dsdoij232s',follow=True)
-
-
- self.assertEqual(response.status_code, 200)
-
-
- @patch('rowers.underarmourstuff.requests.post', side_effect=mocked_requests)
- def test_underarmour_token_refresh(self, mock_post):
- response = self.c.get('/rowers/me/underarmourrefresh/',follow=True)
-
- self.assertEqual(response.status_code, 200)
-
-
- @patch('rowers.underarmourstuff.requests.post', side_effect=mocked_requests)
- @patch('rowers.underarmourstuff.requests.get', side_effect=mocked_requests)
- def test_underarmour_upload(self, mock_get, mock_post):
- response = self.c.get('/rowers/workout/'+encoded1+'/underarmouruploadw/')
-
- self.assertRedirects(response,
- expected_url = '/rowers/workout/'+encoded1+'/edit/',
- status_code=302,target_status_code=200)
-
- self.assertEqual(response.url, '/rowers/workout/'+encoded1+'/edit/')
- self.assertEqual(response.status_code, 302)
-
- @patch('rowers.underarmourstuff.requests.get', side_effect=mocked_requests)
- def test_underarmour_list(self, mock_get):
- response = self.c.get('/rowers/workout/underarmourimport',follow=True)
-
- self.assertEqual(response.status_code,200)
-
- @patch('rowers.imports.requests.get', side_effect=mocked_requests)
- @patch('rowers.dataprep.create_engine')
- def test_underarmour_import(self, mock_get, mocked_sqlalchemy):
-
- response = self.c.get('/rowers/workout/underarmourimport/12/',follow=True)
-
- self.assertRedirects(response,
- expected_url='/rowers/workout/'+encoded2+'/edit/',
- status_code=302,target_status_code=200)
-
- self.assertEqual(response.status_code, 200)
-
-
#@pytest.mark.django_db
@override_settings(TESTING=True)
class TPObjects(DjangoTestCase):
diff --git a/rowers/traverselinktest.py b/rowers/traverselinktest.py
index 3856fb44..0b07477f 100644
--- a/rowers/traverselinktest.py
+++ b/rowers/traverselinktest.py
@@ -99,7 +99,6 @@ class TraverseLinksTest(TestCase):
'.*authorize.*',
'.*youtu.*',
'.*earth.*',
- '.*underarmour.*',
'.*runkeeper.*',
'.*c2list.*',
'.*stravaimport.*',
diff --git a/rowers/underarmourstuff.py b/rowers/underarmourstuff.py
deleted file mode 100644
index 33003a22..00000000
--- a/rowers/underarmourstuff.py
+++ /dev/null
@@ -1,544 +0,0 @@
-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
-from rowers.imports import *
-
-import numpy
-
-import rowers.mytypes as mytypes
-from rowers.mytypes import otwtypes
-from rowers.rower_rules import is_workout_user
-
-from rowsandall_app.settings import (
- UNDERARMOUR_CLIENT_KEY,
- UNDERARMOUR_CLIENT_SECRET,
- UNDERARMOUR_REDIRECT_URI,
- )
-
-oauth_data = {
- 'client_id': UNDERARMOUR_CLIENT_KEY,
- 'client_secret': UNDERARMOUR_CLIENT_SECRET,
- 'redirect_uri': UNDERARMOUR_REDIRECT_URI,
- 'autorization_uri': "https://www.mapmyfitness.com/v7.1/oauth2/uacf/authorize/",
- 'content_type': 'application/x-www-form-urlencoded',
- 'tokenname': 'underarmourtoken',
- 'refreshtokenname': 'underarmourrefreshtoken',
- 'expirydatename': 'underarmourtokenexpirydate',
- 'bearer_auth': True,
- 'base_url': "https://api.ua.com/v7.1/oauth2/access_token/",
- 'scope':'write',
- }
-
-# Checks if user has UnderArmour token, renews them if they are expired
-def underarmour_open(user):
- return imports_open(user,oauth_data)
-
-# Refresh ST token using refresh token
-def do_refresh_token(refreshtoken,access_token):
- return imports_do_refresh_token(
- refreshtoken,oauth_data,access_token=access_token
- )
-
-# Exchange access code for long-lived access token
-def get_token(code):
- return imports_get_token(code,oauth_data)
-
-# Make authorization URL including random string
-def make_authorization_url(request):
- return imports_make_authorization_url(oauth_data) # pragma: no cover
-
-# Get list of workouts available on Underarmour
-def get_underarmour_workout_list(user):
- r = Rower.objects.get(user=user)
- if (r.underarmourtoken == '') or (r.underarmourtoken is None):
- s = "Token doesn't exist. Need to authorize"
- return custom_exception_handler(401,s)
- else:
- # ready to fetch. Hurray
- authorizationstring = str('Bearer ' + r.underarmourtoken)
- headers = {'Authorization': authorizationstring,
- 'Api-Key': UNDERARMOUR_CLIENT_KEY,
- 'user-agent': 'sanderroosendaal',
- 'Content-Type': 'application/json'}
- url = "https://api.ua.com/v7.1/workout/?user="+str(get_userid(r.underarmourtoken))+"&order_by=-start_datetime"
-
- s = requests.get(url,headers=headers)
-
-
- return s
-
-# Get workout summary data by Underarmour ID
-def get_workout(user,underarmourid,do_async=False):
- r = Rower.objects.get(user=user)
- if (r.underarmourtoken == '') or (r.underarmourtoken is None): # pragma: no cover
- return custom_exception_handler(401,s)
- s = "Token doesn't exist. Need to authorize"
- else:
- # ready to fetch. Hurray
- authorizationstring = str('Bearer ' + r.underarmourtoken)
- headers = {'Authorization': authorizationstring,
- 'Api-Key': UNDERARMOUR_CLIENT_KEY,
- 'user-agent': 'sanderroosendaal',
- 'Content-Type': 'application/json'}
- url = "https://api.ua.com/v7.1/workout/"+str(underarmourid)+"/?field_set=time_series"
- s = requests.get(url,headers=headers)
-
- data = s.json()
-
- strokedata = pd.DataFrame.from_dict({
- key: pd.Series(value) for key, value in data.items()
- })
-
- return data,strokedata
-
-
-# Create Workout Data for upload to Underarmour
-def createunderarmourworkoutdata(w):
- filename = w.csvfilename
- try:
- row = rowingdata(csvfile=filename)
- except: # pragma: no cover
- return 0
-
- st = w.startdatetime.astimezone(pytz.timezone(w.timezone))
- start_time = st.isoformat()
-
- averagehr = int(row.df[' HRCur (bpm)'].mean())
- minhr = int(row.df[' HRCur (bpm)'].min())
- maxhr = int(row.df[' HRCur (bpm)'].max())
- averagespm = int(row.df[' Cadence (stokes/min)'].mean()/2.)
- minspm = int(row.df[' Cadence (stokes/min)'].min()/2.)
- maxspm = int(row.df[' Cadence (stokes/min)'].max()/2.)
- maxhr = int(row.df[' HRCur (bpm)'].max())
- duration = w.duration.hour*3600
- duration += w.duration.minute*60
- duration += w.duration.second
- duration += +1.0e-6*w.duration.microsecond
- name = w.name
- try:
- notes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com'
- except TypeError:
- notes = 'from '+w.workoutsource+' via rowsandall.com'
-
- # adding diff, trying to see if this is valid
- #t = row.df.loc[:,'TimeStamp (sec)'].values-10*row.df.ix[0,'TimeStamp (sec)']
- t = row.df.loc[:,'TimeStamp (sec)'].values #-row.df.ix[0,'TimeStamp (sec)']
-
- # t += arrow.get(st).timestamp()
-
- # t[0] = t[1]
-
- d = row.df.loc[:,'cum_dist'].values
- d[0] = d[1]
- t = t.astype(float).tolist()
-
-
-
-
- d = d.astype(int).tolist()
- spm = row.df[' Cadence (stokes/min)'].astype(int).tolist()
- spm[0] = spm[1]
- hr = row.df[' HRCur (bpm)'].astype(int).tolist()
- speed = row.df[' AverageBoatSpeed (m/s)']
- speedmin = float(row.df[' AverageBoatSpeed (m/s)'].min())
- speedmax = float(row.df[' AverageBoatSpeed (m/s)'].max())
- speedmean = float(row.df[' AverageBoatSpeed (m/s)'].mean())
- speed = speed.replace(np.inf,0).tolist()
-
-
-
- haslatlon=1
-
- try: # pragma: no cover
- lat = row.df[' latitude']
- lon = row.df[' longitude']
- if not lat.std() and not lon.std():
- haslatlon = 0
- except KeyError:
- haslatlon = 0
-
-
- # path data
- if haslatlon: # pragma: no cover
- locdata = []
- for e in zip(t,lat.values,lon.values):
- point = {
- 'lat':e[1],
- 'lng':e[2],
- 'elevation':0,
- }
- locdata.append([e[0],point])
-
- hrdata = []
- for e in zip(t,hr):
- point = [e[0],
- e[1]
- ]
- hrdata.append(point)
-
- distancedata = []
- for e in zip(t,d):
- point = [e[0],
- e[1]
- ]
- distancedata.append(point)
-
- spmdata = []
- for e in zip(t,spm):
- spmdata.append([e[0],e[1]])
-
-
- timeseries = {
- "distance": distancedata,
- "heartrate": hrdata,
- "cadence": spmdata,
- }
-
-
-
- aggregates = {
- "elapsed_time_total": int(duration),
- "active_time_total": int(duration),
- "distance_total": int(max(d)),
- "heartrate_avg": averagehr,
- "heart_rate_min": minhr,
- "heart_rate_max": maxhr,
- "speed_min": speedmin,
- "speed_max": speedmax,
- "speed_avg": speedmean,
- "cadence_min": minspm,
- "cadence_max": maxspm,
- "cadence_avg": averagespm,
- }
-
-
- if haslatlon: # pragma: no cover
- timeseries["position"] = locdata
-
- data = {
- "start_datetime": start_time,
- "name": name,
- "has_time_series": True,
- "time_series": timeseries,
- "aggregates": aggregates,
- "start_locale_timezone": "Etc/UTC",
- "activity_type": "/v7.1/activity_type/128/",
- "notes": notes,
- }
-
- return data
-
-# Obtain Underarmour Workout ID and activity type
-def get_idfromuri(user,links):
- id = links['self'][0]['id']
- typeid = links['activity_type'][0]['id']
-
- typename = get_typefromid(typeid,user)
-
- return id,typename
-
-def getidfromresponse(response):
- t = response.json()
-
- links = t["_links"]
-
- id = links["self"][0]["id"]
-
- return int(id)
-
-def refresh_ua_actlist(user): # pragma: no cover
- r = Rower.objects.get(user=user)
- authorizationstring = str('Bearer ' + r.underarmourtoken)
- headers = {'Authorization': authorizationstring,
- 'Api-Key': UNDERARMOUR_CLIENT_KEY,
- 'user-agent': 'sanderroosendaal',
- 'Content-Type': 'application/json'}
- url = "https://api.ua.com/v7.1/activity_type/"
- response = requests.get(url,headers=headers)
-
- me_json = response.json()
- types = me_json["_embedded"]["activity_types"]
- w = {int(t["_links"]["self"][0]["id"]):t["name"] for t in types}
- wdf = pd.Series(w,name='Name')
- wdf.to_csv('static/rigging/ua2.csv',index_label='id',header=True)
- return w
-
-try:
- activities = pd.read_csv('static/rigging/ua2.csv',index_col='id')
- actdict = activities.to_dict()['Name']
-except: # pragma: no cover
- actdict = {}
-
-
-def get_typefromid(typeid,user):
- r = Rower.objects.get(user=user)
- try:
- res = actdict[int(typeid)]
- except KeyError: # pragma: no cover
- authorizationstring = str('Bearer ' + r.underarmourtoken)
- headers = {'Authorization': authorizationstring,
- 'Api-Key': UNDERARMOUR_CLIENT_KEY,
- 'user-agent': 'sanderroosendaal',
- 'Content-Type': 'application/json'}
- url = "https://api.ua.com/v7.1/activity_type/"+str(typeid)
- response = requests.get(url,headers=headers)
-
- me_json = response.json()
-
- try:
- res = me_json['name']
- except KeyError:
- res = 0
-
- return res
-
-
-
-# Get user id, having access token
-# Handy for checking if the API access is working
-def get_userid(access_token):
- authorizationstring = str('Bearer ' + access_token)
- headers = {'Authorization': authorizationstring,
- 'Api-Key': UNDERARMOUR_CLIENT_KEY,
- 'user-agent': 'sanderroosendaal',
- 'Content-Type': 'application/json'}
-
- url = "https://api.ua.com/v7.1/user/self/"
- response = requests.get(url,headers=headers)
-
- me_json = response.json()
-
- try:
- res = me_json['id']
- except KeyError: # pragma: no cover
- res = 0
-
- return res
-
-def default(o): # pragma: no cover
- if isinstance(o, numpy.int64): return int(o)
- raise TypeError
-
-
-def workout_ua_upload(user,w): # pragma: no cover
- message = "Uploading to MapMyFitness"
- uaid = 0
-
- r = w.user
-
- thetoken = underarmour_open(r.user)
-
- # ready to upload. Hurray
-
- if (is_workout_user(user,w)):
- data = createunderarmourworkoutdata(w)
-# return HttpResponse(json.dumps(data))
- if not data:
- message = "Data error"
- uaid = 0
- return message, uaid
-
- 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"
- w.uploadedtounderarmour = -1
- uaid = -1
- w.save()
- elif (response.status_code == 201 or response.status_code==200):
- uaid = getidfromresponse(response)
- w.uploadedtounderarmour = uaid
- w.save()
- return 'Successfully synchronized with MapMyFitness',uaid
- else:
- s = response
- message = "Something went wrong in workout_underarmour_upload_view: %s - %s" % (s.reason,s.text)
- uaid = 0
- return message, uaid
-
- else:
- message = "You are not authorized to upload this workout"
- uaid = 0
- return message, uaid
-
- return message, uaid
-
-# Create workout from SportTracks Data, which are slightly different
-# than Strava or Concept2 data
-def add_workout_from_data(user,importid,data,strokedata,
- source='mapmyfitness',
- workoutsource='mapmyfitness'):
- workouttype = 'water'
-
- try:
- comments = data['notes']
- except: # pragma: no cover
- comments = ''
-
- try:
- thetimezone = tz(data['start_locale_timezone'])
- except:
- thetimezone = 'UTC'
-
- r = Rower.objects.get(user=user)
- try:
- rowdatetime = iso8601.parse_date(data['start_datetime'])
- except iso8601.ParseError: # pragma: no cover
- try:
- rowdatetime = datetime.strptime(data['start_datetime'],"%Y-%m-%d %H:%M:%S")
- rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
- except:
- try:
- rowdatetime = parser.parse(data['start_datetime'])
- rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
- except:
- rowdatetime = datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S")
- rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
- starttimeunix = arrow.get(rowdatetime).timestamp()
-
-
- try:
- title = data['name']
- except: # pragma: no cover
- title = "Imported data"
-
- timeseries = data['time_series']
-
- # position, distance, speed, cadence, power,
-
- try:
- res = splituadata(timeseries['distance'])
- distance = res[1]
- times_distance = res[0]
- except KeyError: # pragma: no cover
- message = "Error. No distance data"
- return (0,message)
-
-
- try:
- l = timeseries['position']
-
- res = splituadata(l)
- times_location = res[0]
- latlong = res[1]
- latcoord = []
- loncoord = []
-
- for coord in latlong:
- lat = coord['lat']
- lon = coord['lng']
- latcoord.append(lat)
- loncoord.append(lon)
- except: # pragma: no cover
- times_location = times_distance
- latcoord = np.zeros(len(times_distance))
- loncoord = np.zeros(len(times_distance))
- if workouttype in otwtypes:
- workouttype = 'rower'
-
- try:
- res = splituadata(timeseries['cadence'])
- times_spm = res[0]
- spm = res[1]
- except KeyError: # pragma: no cover
- times_spm = times_distance
- spm = 0*times_distance
-
- try:
- res = splituadata(timeseries['heartrate'])
- hr = res[1]
- times_hr = res[0]
- except KeyError: # pragma: no cover
- times_hr = times_distance
- hr = 0*times_distance
-
-
- # create data series and remove duplicates
- distseries = pd.Series(distance,index=times_distance)
- distseries = distseries.groupby(distseries.index).first()
- latseries = pd.Series(latcoord,index=times_location)
- latseries = latseries.groupby(latseries.index).first()
- lonseries = pd.Series(loncoord,index=times_location)
- lonseries = lonseries.groupby(lonseries.index).first()
- spmseries = pd.Series(spm,index=times_spm)
- spmseries = spmseries.groupby(spmseries.index).first()
- hrseries = pd.Series(hr,index=times_hr)
- hrseries = hrseries.groupby(hrseries.index).first()
-
-
- # Create dicts and big dataframe
- d = {
- ' Horizontal (meters)': distseries,
- ' latitude': latseries,
- ' longitude': lonseries,
- ' Cadence (stokes/min)': spmseries,
- ' HRCur (bpm)' : hrseries,
- }
-
-
-
- df = pd.DataFrame(d)
-
- df = df.groupby(level=0).last()
-
- cum_time = df.index.values
- df[' ElapsedTime (sec)'] = cum_time
-
- velo = df[' Horizontal (meters)'].diff()/df[' ElapsedTime (sec)'].diff()
-
- df[' Power (watts)'] = 0.0*velo
-
- nr_rows = len(velo.values)
-
- df[' DriveLength (meters)'] = np.zeros(nr_rows)
- df[' StrokeDistance (meters)'] = np.zeros(nr_rows)
- df[' DriveTime (ms)'] = np.zeros(nr_rows)
- df[' StrokeRecoveryTime (ms)'] = np.zeros(nr_rows)
- df[' AverageDriveForce (lbs)'] = np.zeros(nr_rows)
- df[' PeakDriveForce (lbs)'] = np.zeros(nr_rows)
- df[' lapIdx'] = np.zeros(nr_rows)
-
-
-
- unixtime = cum_time+starttimeunix
- unixtime[0] = starttimeunix
-
- df['TimeStamp (sec)'] = unixtime
-
-
- dt = np.diff(cum_time).mean()
- wsize = round(5./dt)
-
- df = df.fillna(0)
-
- df.sort_values(by='TimeStamp (sec)',ascending=True)
-
- timestr = strftime("%Y%m%d-%H%M%S")
-
- csvfilename ='media/{code}_{importid}.csv'.format(
- importid=importid,
- code = uuid4().hex[:16]
- )
-
- res = df.to_csv(csvfilename+'.gz',index_label='index',
- compression='gzip')
-
- id,message = dataprep.save_workout_database(csvfilename,r,
- workouttype=workouttype,
- workoutsource='mapmyfitness',
- dosmooth=r.dosmooth,
- title=title,
- notes=comments)
-
- return (id,message)
diff --git a/rowers/uploads.py b/rowers/uploads.py
index dd2d7cb1..43706369 100644
--- a/rowers/uploads.py
+++ b/rowers/uploads.py
@@ -125,7 +125,6 @@ def matchsync(line):
tester4 = tester+'(.*)(strava)'
tester5 = tester+'(.*)((st)|(sporttracks))'
tester6 = tester+'(.*)((rk)|(runkeeper))'
- tester7 = tester+'(.*)((mapmyfitness)|(underarmour)|(ua))'
tester = re.compile(tester)
@@ -262,8 +261,6 @@ def getsyncoptions(uploadoptions,values): # pragma: no cover
uploadoptions['upload_to_SportTracks'] = True
if v in ['rk','runkeeper']:
uploadoptions['upload_to_RunKeeper'] = True
- if v in ['ua','underarmour','mapmyfitness']:
- uploadoptions['upload_to_MapMyFitness'] = True
except AttributeError:
pass
@@ -491,7 +488,7 @@ import rowers.c2stuff as c2stuff
import rowers.stravastuff as stravastuff
import rowers.sporttracksstuff as sporttracksstuff
import rowers.runkeeperstuff as runkeeperstuff
-import rowers.underarmourstuff as underarmourstuff
+
import rowers.tpstuff as tpstuff
from rowers.rower_rules import is_promember
@@ -653,14 +650,6 @@ def do_sync(w,options, quick=False):
message = "Please connect to Runkeeper first"
id = 0
- if ('upload_to_MapMyFitness' in options and options['upload_to_MapMyFitness']) or (w.user.mapmyfitness_auto_export): # pragma: no cover
- try:
- message,id = underarmourstuff.workout_ua_upload(
- w.user.user,w
- )
- except NoTokenError:
- message = "Please connect to MapMyFitness first"
- id = 0
if ('upload_to_TrainingPeaks' in options and options['upload_to_TrainingPeaks']) or (w.user.trainingpeaks_auto_export): # pragma: no cover
diff --git a/rowers/urls.py b/rowers/urls.py
index 7f002f21..8e91944d 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -510,14 +510,11 @@ urlpatterns = [
re_path(r'^workout/polarimport/user/(?P\d+)/',views.workout_polarimport_view,name='workout_polarimport_view'),
re_path(r'^workout/runkeeperimport/$',views.workout_runkeeperimport_view,name='workout_runkeeperimport_view'),
re_path(r'^workout/runkeeperimport/user/(?P\d+)/$',views.workout_runkeeperimport_view,name='workout_runkeeperimport_view'),
- re_path(r'^workout/underarmourimport/user/(?P\d+)/$',views.workout_underarmourimport_view,name='workout_underarmourimport_view'),
- re_path(r'^workout/underarmourimport/$',views.workout_underarmourimport_view,name='workout_underarmourimport_view'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/c2uploadw/$',views.workout_c2_upload_view,name='workout_c2_upload_view'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/stravauploadw/$',views.workout_strava_upload_view,name='workout_strava_upload_view'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/recalcsummary/$',views.workout_recalcsummary_view,name='workout_recalcsummary_view'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/sporttracksuploadw/$',views.workout_sporttracks_upload_view,name='workout_sporttracks_upload_view'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/runkeeperuploadw/$',views.workout_runkeeper_upload_view,name='workout_runkeeper_upload_view'),
- re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/underarmouruploadw/$',views.workout_underarmour_upload_view,name='workout_underarmour_upload_view'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/tpuploadw/$',views.workout_tp_upload_view,name='workout_tp_upload_view'),
re_path(r'^multi-compare/workout/(?P\b[0-9A-Fa-f]+\b)/user/(?P\d+)/$',views.multi_compare_view,
name='multi_compare_view'),
@@ -600,12 +597,10 @@ urlpatterns = [
re_path(r'^me/stravaauthorize/$',views.rower_strava_authorize,name='rower_strava_authorize'),
re_path(r'^me/garminauthorize/$',views.rower_garmin_authorize,name='rower_garmin_authorize'),
re_path(r'^me/sporttracksauthorize/$',views.rower_sporttracks_authorize,name='rower_sporttracks_authorize'),
- re_path(r'^me/underarmourauthorize/$',views.rower_underarmour_authorize,name='rower_underarmour_authorize'),
re_path(r'^me/tpauthorize/$',views.rower_tp_authorize,name='rower_tp_authorize'),
re_path(r'^me/rp3authorize/$',views.rower_rp3_authorize,name='rower_rp3_authorize'),
re_path(r'^me/runkeeperauthorize/$',views.rower_runkeeper_authorize,name='rower_runkeeper_authorize'),
re_path(r'^me/sporttracksrefresh/$',views.rower_sporttracks_token_refresh,name='rower_sporttracks_token_refresh'),
- re_path(r'^me/underarmourrefresh/$',views.rower_underarmour_token_refresh,name='rower_underarmoud_token_refresh'),
re_path(r'^me/tprefresh/$',views.rower_tp_token_refresh,name='rower_tp_token_refresh'),
re_path(r'^me/c2refresh/$',views.rower_c2_token_refresh,name='rower_c2_token_refresh'),
re_path(r'^me/favoritecharts/$',views.rower_favoritecharts_view,name='rower_favoritecharts_view'),
diff --git a/rowers/utils.py b/rowers/utils.py
index 0c1a35d4..2722def7 100644
--- a/rowers/utils.py
+++ b/rowers/utils.py
@@ -105,6 +105,15 @@ info_calls = [
import random
+def dologging(filename,s):
+ tstamp = time.localtime()
+ timestamp = time.strftime('%b-%d-%Y %H:%M:%S', tstamp)
+ with open('filename','a') as f:
+ f.write('\n')
+ f.write(timestamp)
+ f.write(' ')
+ f.write(s)
+
def to_pace(pace):
minutes, seconds = divmod(pace,60)
seconds, rest = divmod(seconds, 1)
diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py
index eee66152..c1740e50 100644
--- a/rowers/views/importviews.py
+++ b/rowers/views/importviews.py
@@ -286,66 +286,6 @@ def workout_runkeeper_upload_view(request,id=0):
return HttpResponseRedirect(url) # pragma: no cover
-# Upload workout to Underarmour
-@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
-def workout_underarmour_upload_view(request,id=0):
- message = ""
- w = get_workout(id)
- r = w.user
-
- try:
- thetoken = underarmour_open(r.user)
- except NoTokenError: # pragma: no cover
- return HttpResponseRedirect("/rowers/me/underarmourauthorize/")
-
- # ready to upload. Hurray
-
-
- data = underarmourstuff.createunderarmourworkoutdata(w)
- if not data: # pragma: no cover
- 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 ): # pragma: no cover # pragma: no cover
- 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: # pragma: no cover
- s = response
- message = "Something went wrong in workout_underarmour_upload_view: %s " % s.reason
- messages.error(request,message)
-
- url = reverse(r.defaultlandingpage,
- kwargs = {
- 'id':encoder.encode_hex(w.id),
- }) # pragma: no cover
-
- return HttpResponseRedirect(url) # pragma: no cover
# Upload workout to SportTracks
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid)
@@ -525,24 +465,8 @@ def rower_sporttracks_authorize(request): # pragma: no cover
return HttpResponseRedirect(url)
-# Underarmour Authorization
-@login_required()
-def rower_underarmour_authorize(request): # pragma: no cover
- # 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
+# RP3 Authorization
@login_required()
def rower_rp3_authorize(request): # pragma: no cover
# Generate a random string for the state parameter
@@ -557,7 +481,7 @@ def rower_rp3_authorize(request): # pragma: no cover
return HttpResponseRedirect(url)
-# Underarmour Authorization
+# TrainingPeaks Authorization
@login_required()
def rower_tp_authorize(request): # pragma: no cover
# Generate a random string for the state parameter
@@ -603,33 +527,6 @@ def rower_c2_token_refresh(request):
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
@@ -1086,29 +983,6 @@ def rower_process_sporttrackscallback(request):
-# 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. Please check your import/export settings"
- messages.info(request,successmessage)
- url = reverse('rower_exportsettings_view')
- return HttpResponseRedirect(url)
# Process RP3 callback
@login_required()
@@ -1680,56 +1554,6 @@ def workout_runkeeperimport_view(request,message="",userid=0):
return HttpResponse(res) # pragma: no cover
-# The page where you select which RunKeeper workout to import
-@login_required()
-@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
-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: # pragma: no cover
- 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) # pragma: no cover
# the page where you select which Polar workout to Import
@login_required()
@@ -2032,7 +1856,6 @@ importlistviews = {
'runkeeper':'workout_runkeeperimport_view',
'sporttracks':'workout_sporttracksimport_view',
'trainingpeaks':'workout_view',
- 'underarmour':'workout_underarmourimport_view',
'nk':'workout_nkimport_view',
}
@@ -2044,7 +1867,6 @@ importsources = {
'runkeeper':runkeeperstuff,
'sporttracks':sporttracksstuff,
'trainingpeaks':tpstuff,
- 'underarmour':underarmourstuff,
'nk':nkstuff,
}
@@ -2071,178 +1893,20 @@ def workout_getrp3importview(request,externalid):
return HttpResponseRedirect(url)
@login_required()
-def workout_getimportview(request,externalid,source = 'c2',do_async=False):
- data,strokedata = importsources[source].get_workout(request.user,externalid,
+def workout_getimportview(request,externalid,source = 'c2',do_async=True):
+ result = importsources[source].get_workout(request.user,externalid,
do_async=do_async)
- if do_async: # pragma: no cover
+ if result: # pragma: no cover
messages.info(request,"Your workout will be imported in the background")
# this should return to the respective import list page
- url = reverse(importlistviews[source])
- return HttpResponseRedirect(url)
-
- if not data: # pragma: no cover
- messages.error(request,"No strokedata received")
- url = reverse('workouts_view')
-
- return HttpResponseRedirect(url)
-
-
- try:
- workouttype = mytypes.c2mappinginv[data['type']]
- except KeyError:
- workouttype = 'rower'
-
-
- # 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: # pragma: no cover
- 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')
-
- try:
- notes = data['comments']
- name = notes[:40]
- except (KeyError,TypeError):
- comments = 'C2 Import Workout from {startdatetime}'.format(startdatetime=startdatetime)
- name = notes
-
- 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 = name
- w.notes = notes
- 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: # pragma: no cover
- 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: # pragma: no cover
- w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename,workouttype=workouttype)
- 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(csvfile=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': # pragma: no cover
- w.uploadedtopolar = externalid
- elif source == 'runkeeper':
- w.uploadedtorunkeeper = externalid
- elif source == 'sporttracks':
- w.uploadedtosporttracks = externalid
- elif source == 'trainingpeaks': # pragma: no cover
- w.uploadedtotp = externalid
- elif source == 'underarmour':
- w.uploadedtounderarmour = externalid
-
- w.save()
-
- if message: # pragma: no cover
- messages.error(request,message)
-
- r = getrower(request.user)
-
- url = reverse(r.defaultlandingpage,
- kwargs = {
- 'id':encoder.encode_hex(w.id)
- })
+ messages.error(request,'Error getting the workout')
+ url = reverse(importlistviews[source])
return HttpResponseRedirect(url)
-
-
-
# Imports all new workouts from SportTracks
@login_required()
def workout_getsporttracksworkout_all(request):
diff --git a/rowers/views/statements.py b/rowers/views/statements.py
index b74f1616..4b8c9ff1 100644
--- a/rowers/views/statements.py
+++ b/rowers/views/statements.py
@@ -167,8 +167,8 @@ import rowers.garmin_stuff as garmin_stuff
from rowers.stravastuff import strava_open
import rowers.polarstuff as polarstuff
import rowers.sporttracksstuff as sporttracksstuff
-import rowers.underarmourstuff as underarmourstuff
-from rowers.underarmourstuff import underarmour_open
+
+
import rowers.tpstuff as tpstuff
import rowers.runkeeperstuff as runkeeperstuff
import rowers.rp3stuff as rp3stuff
@@ -180,8 +180,6 @@ from rowsandall_app.settings import (
POLAR_CLIENT_ID, POLAR_REDIRECT_URI, POLAR_CLIENT_SECRET,
SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI,
SPORTTRACKS_CLIENT_SECRET,
- UNDERARMOUR_CLIENT_ID, UNDERARMOUR_REDIRECT_URI,
- UNDERARMOUR_CLIENT_SECRET,UNDERARMOUR_CLIENT_KEY,
RUNKEEPER_CLIENT_ID,RUNKEEPER_REDIRECT_URI,RUNKEEPER_CLIENT_SECRET,
TP_CLIENT_ID,TP_REDIRECT_URI,TP_CLIENT_KEY,TP_CLIENT_SECRET,
RP3_CLIENT_ID,RP3_REDIRECT_URI,RP3_CLIENT_KEY,RP3_CLIENT_SECRET,
diff --git a/rowers/views/userviews.py b/rowers/views/userviews.py
index 2d7104c1..ac73312c 100644
--- a/rowers/views/userviews.py
+++ b/rowers/views/userviews.py
@@ -329,7 +329,6 @@ def rower_exportsettings_view(request,userid=0):
'polar_auto_import':'polartoken',
'c2_auto_export':'c2token',
'c2_auto_import':'c2token',
- 'mapmyfitness_auto_export':'underarmourtoken',
'runkeeper_auto_export':'runkeepertoken',
'sporttracks_auto_export':'sporttrackstoken',
'strava_auto_export':'stravatoken',
diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py
index ec44ea1a..8f23454d 100644
--- a/rowers/views/workoutviews.py
+++ b/rowers/views/workoutviews.py
@@ -5270,21 +5270,6 @@ def workout_upload_view(request,
messages.error(request,message)
- if (upload_to_ua): # pragma: no cover
- try:
- message,id = underarmourstuff.workout_ua_upload(
- request.user,w
- )
- except NoTokenError:
- message = "Please connect to MapMyFitness first"
- id = 0
-
- if id>1:
- messages.info(request,message)
- else:
- messages.error(request,message)
-
-
if (upload_to_tp): # pragma: no cover
try:
message,id = tpstuff.workout_tp_upload(
diff --git a/rowsandall_app/urls.py b/rowsandall_app/urls.py
index a7d76249..6cf79af8 100644
--- a/rowsandall_app/urls.py
+++ b/rowsandall_app/urls.py
@@ -74,7 +74,6 @@ urlpatterns += [
re_path(r'^stravacall\_back',rowersviews.rower_process_stravacallback),
re_path(r'^garmin\_callback',rowersviews.rower_process_garmincallback),
re_path(r'^sporttracks\_callback',rowersviews.rower_process_sporttrackscallback),
- re_path(r'^underarmour\_callback',rowersviews.rower_process_underarmourcallback),
re_path(r'^polarflowcallback',rowersviews.rower_process_polarcallback),
re_path(r'^runkeeper\_callback',rowersviews.rower_process_runkeepercallback),
re_path(r'^tp\_callback',rowersviews.rower_process_tpcallback),