intervals.icu fixes
This commit is contained in:
@@ -1406,7 +1406,12 @@ def get_title_from_fit(filename):
|
|||||||
|
|
||||||
return title
|
return title
|
||||||
|
|
||||||
def get_workouttype_from_fit(filename, workouttype='water'):
|
def get_workouttype_from_fit(filename, workouttype=None):
|
||||||
|
if workouttype is None:
|
||||||
|
workouttype = 'water'
|
||||||
|
workouttype_orig = ''
|
||||||
|
else:
|
||||||
|
workouttype_orig = workouttype
|
||||||
try:
|
try:
|
||||||
fitfile = FitFile(filename, check_crc=False)
|
fitfile = FitFile(filename, check_crc=False)
|
||||||
except FitHeaderError: # pragma: no cover
|
except FitHeaderError: # pragma: no cover
|
||||||
@@ -1435,6 +1440,8 @@ def get_workouttype_from_fit(filename, workouttype='water'):
|
|||||||
workouttype = mytypes.fitmappinginv[fittype]
|
workouttype = mytypes.fitmappinginv[fittype]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
if workouttype_orig in ['water', 'rower']:
|
||||||
|
workouttype = workouttype_orig
|
||||||
|
|
||||||
return workouttype
|
return workouttype
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
from .integrations import SyncIntegration, NoTokenError, create_or_update_syncrecord, get_known_ids
|
from .integrations import SyncIntegration, NoTokenError, create_or_update_syncrecord, get_known_ids
|
||||||
from rowers.models import Rower, User, Workout, TombStone, PlannedSession
|
from rowers.models import Rower, User, Workout, TombStone, PlannedSession
|
||||||
from rowingdata import rowingdata
|
from rowingdata import rowingdata
|
||||||
|
from rowingdata import FITParser as FP
|
||||||
|
from rowingdata.otherparsers import FitSummaryData
|
||||||
from rowers.rower_rules import user_is_not_basic, user_is_coachee
|
from rowers.rower_rules import user_is_not_basic, user_is_coachee
|
||||||
|
|
||||||
from rowers import mytypes
|
from rowers import mytypes
|
||||||
|
import shutil
|
||||||
from rowers.rower_rules import is_workout_user, ispromember
|
from rowers.rower_rules import is_workout_user, ispromember
|
||||||
from rowers.utils import myqueue, dologging, custom_exception_handler
|
from rowers.utils import myqueue, dologging, custom_exception_handler
|
||||||
from rowers.tasks import handle_intervals_getworkout
|
from rowers.tasks import handle_intervals_getworkout
|
||||||
@@ -22,7 +24,8 @@ import rowers.dataprep as dataprep
|
|||||||
from rowers.opaque import encoder
|
from rowers.opaque import encoder
|
||||||
|
|
||||||
from rowsandall_app.settings import (
|
from rowsandall_app.settings import (
|
||||||
INTERVALS_CLIENT_ID, INTERVALS_REDIRECT_URI, INTERVALS_CLIENT_SECRET, SITE_URL
|
INTERVALS_CLIENT_ID, INTERVALS_REDIRECT_URI, INTERVALS_CLIENT_SECRET, SITE_URL,
|
||||||
|
UPLOAD_SERVICE_SECRET, UPLOAD_SERVICE_URL
|
||||||
)
|
)
|
||||||
|
|
||||||
import django_rq
|
import django_rq
|
||||||
@@ -273,11 +276,102 @@ class IntervalsIntegration(SyncIntegration):
|
|||||||
|
|
||||||
return workouts
|
return workouts
|
||||||
|
|
||||||
|
def update_workout(self, id, *args, **kwargs) -> int:
|
||||||
|
_ = self.open()
|
||||||
|
r = self.rower
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Authorization': 'Bearer ' + r.intervals_token,
|
||||||
|
}
|
||||||
|
url = self.oauth_data['base_url'] + 'activity/' + str(id)
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
if response.status_code != 200:
|
||||||
|
dologging('intervals.icu.log', response.text)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
ws = Workout.objects.filter(uploadedtointervals=id)
|
||||||
|
|
||||||
|
for w in ws:
|
||||||
|
try:
|
||||||
|
w.name = data['name']
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
w.notes = data['description']
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
w.workouttype = mytypes.intervalsmappinginv[data['type']]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
w.save()
|
||||||
|
|
||||||
|
# we stop here now
|
||||||
|
return 1
|
||||||
|
|
||||||
|
url = self.oauth_data['base_url'] + 'activity/' + str(id) + '/fit-file'
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
if response.status_code != 200:
|
||||||
|
dologging('intervals.icu.log', response.text)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
fit_data = response.content
|
||||||
|
fit_filename = 'media/intervals_' + str(id) + '.fit'
|
||||||
|
with open(fit_filename, 'wb') as f:
|
||||||
|
f.write(fit_data)
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
row = FP(fit_filename)
|
||||||
|
rowdata = rowingdata(df=row.df)
|
||||||
|
rowsummary = FitSummaryData(fit_filename)
|
||||||
|
except Exception as e:
|
||||||
|
dologging('intervals.icu.log', e)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
for w in ws:
|
||||||
|
# copy fit_file to random file name using shutil
|
||||||
|
temp_filename = 'media/' + str(uuid4()) + '.fit'
|
||||||
|
try:
|
||||||
|
shutil.copy(fit_filename, temp_filename)
|
||||||
|
|
||||||
|
|
||||||
|
uploadoptions = {
|
||||||
|
'secret': UPLOAD_SERVICE_SECRET,
|
||||||
|
'user': self.rower.user.id,
|
||||||
|
'boattype': '1x',
|
||||||
|
'workouttype': w.workouttype,
|
||||||
|
'file': temp_filename,
|
||||||
|
'intervalsid': id,
|
||||||
|
'id': w.id,
|
||||||
|
}
|
||||||
|
url = UPLOAD_SERVICE_URL
|
||||||
|
response = requests.post(url, data=uploadoptions)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
dologging('intervals.icu.log', e)
|
||||||
|
|
||||||
|
# remove fit_file
|
||||||
|
try:
|
||||||
|
os.remove(fit_filename)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
def get_workout(self, id, *args, **kwargs) -> int:
|
def get_workout(self, id, *args, **kwargs) -> int:
|
||||||
_ = self.open()
|
_ = self.open()
|
||||||
r = self.rower
|
r = self.rower
|
||||||
|
|
||||||
|
# check if workout with this id already exists
|
||||||
|
known_interval_ids = get_known_ids(r, 'intervalsid')
|
||||||
|
if id in known_interval_ids:
|
||||||
|
return self.update_workout(id)
|
||||||
|
|
||||||
record = create_or_update_syncrecord(r, None, intervalsid=id)
|
record = create_or_update_syncrecord(r, None, intervalsid=id)
|
||||||
|
|
||||||
_ = myqueue(queuehigh,
|
_ = myqueue(queuehigh,
|
||||||
@@ -583,8 +677,8 @@ class IntervalsIntegration(SyncIntegration):
|
|||||||
id = record['id']
|
id = record['id']
|
||||||
try:
|
try:
|
||||||
ws = Workout.objects.filter(uploadedtointervals=id)
|
ws = Workout.objects.filter(uploadedtointervals=id)
|
||||||
if w.user == self.rower:
|
|
||||||
for w in ws:
|
for w in ws:
|
||||||
|
if w.user == self.rower:
|
||||||
w.delete()
|
w.delete()
|
||||||
except Workout.DoesNotExist:
|
except Workout.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
@@ -592,3 +686,17 @@ class IntervalsIntegration(SyncIntegration):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
def update_activities(self, event, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
record = event["activity"]
|
||||||
|
except KeyError:
|
||||||
|
records = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
id = record['id']
|
||||||
|
result = self.update_workout(id)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|||||||
@@ -3582,7 +3582,6 @@ def handle_intervals_getworkout(rower, intervalstoken, workoutid, debug=False, *
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
workouttype = 'water'
|
workouttype = 'water'
|
||||||
|
|
||||||
|
|
||||||
url = "https://intervals.icu/api/v1/activity/{workoutid}/fit-file".format(workoutid=workoutid)
|
url = "https://intervals.icu/api/v1/activity/{workoutid}/fit-file".format(workoutid=workoutid)
|
||||||
|
|
||||||
response = requests.get(url, headers=headers)
|
response = requests.get(url, headers=headers)
|
||||||
|
|||||||
BIN
rowers/tests/testdata/testdata.tcx.gz
vendored
BIN
rowers/tests/testdata/testdata.tcx.gz
vendored
Binary file not shown.
@@ -942,7 +942,6 @@ def intervals_webhook_view(request):
|
|||||||
|
|
||||||
webhook_type = None
|
webhook_type = None
|
||||||
|
|
||||||
|
|
||||||
for event in events:
|
for event in events:
|
||||||
try:
|
try:
|
||||||
athlete_id = event['athlete_id']
|
athlete_id = event['athlete_id']
|
||||||
@@ -964,6 +963,9 @@ def intervals_webhook_view(request):
|
|||||||
if webhook_type.lower() == 'activity_uploaded':
|
if webhook_type.lower() == 'activity_uploaded':
|
||||||
integration.import_activities(event)
|
integration.import_activities(event)
|
||||||
|
|
||||||
|
if webhook_type.lower() == 'activity_updated':
|
||||||
|
integration.update_activities(event)
|
||||||
|
|
||||||
if webhook_type.lower() == 'activity_deleted':
|
if webhook_type.lower() == 'activity_deleted':
|
||||||
integration.delete_activities(event)
|
integration.delete_activities(event)
|
||||||
|
|
||||||
|
|||||||
@@ -1131,18 +1131,8 @@ def workouts_join_select(request,
|
|||||||
|
|
||||||
r = getrequestrower(request, userid=userid)
|
r = getrequestrower(request, userid=userid)
|
||||||
|
|
||||||
if 'waterboattype' in request.session:
|
|
||||||
waterboattype = request.session['waterboattype']
|
|
||||||
else:
|
|
||||||
waterboattype = mytypes.waterboattype+mytypes.ergtype
|
waterboattype = mytypes.waterboattype+mytypes.ergtype
|
||||||
|
|
||||||
if 'modalities' in request.session:
|
|
||||||
modalities = request.session['modalities']
|
|
||||||
if len(modalities) > 1: # pragma: no cover
|
|
||||||
modality = 'all'
|
|
||||||
else:
|
|
||||||
modality = modalities[0]
|
|
||||||
else:
|
|
||||||
modalities = [m[0] for m in mytypes.workouttypes]
|
modalities = [m[0] for m in mytypes.workouttypes]
|
||||||
modality = 'all'
|
modality = 'all'
|
||||||
|
|
||||||
@@ -1154,8 +1144,6 @@ def workouts_join_select(request,
|
|||||||
enddate = dateform.cleaned_data['enddate']
|
enddate = dateform.cleaned_data['enddate']
|
||||||
startdatestring = startdate.strftime('%Y-%m-%d')
|
startdatestring = startdate.strftime('%Y-%m-%d')
|
||||||
enddatestring = enddate.strftime('%Y-%m-%d')
|
enddatestring = enddate.strftime('%Y-%m-%d')
|
||||||
request.session['startdate'] = startdatestring
|
|
||||||
request.session['enddate'] = enddatestring
|
|
||||||
if modalityform.is_valid():
|
if modalityform.is_valid():
|
||||||
modality = modalityform.cleaned_data['modality']
|
modality = modalityform.cleaned_data['modality']
|
||||||
waterboattype = modalityform.cleaned_data['waterboattype']
|
waterboattype = modalityform.cleaned_data['waterboattype']
|
||||||
@@ -1164,11 +1152,7 @@ def workouts_join_select(request,
|
|||||||
else:
|
else:
|
||||||
modalities = [modality]
|
modalities = [modality]
|
||||||
|
|
||||||
if modality != 'water': # pragma: no cover
|
|
||||||
waterboattype = [b[0] for b in mytypes.boattypes]
|
|
||||||
|
|
||||||
request.session['modalities'] = modalities
|
|
||||||
request.session['waterboattype'] = waterboattype
|
|
||||||
else:
|
else:
|
||||||
dateform = DateRangeForm(initial={
|
dateform = DateRangeForm(initial={
|
||||||
'startdate': startdate,
|
'startdate': startdate,
|
||||||
@@ -1211,6 +1195,7 @@ def workouts_join_select(request,
|
|||||||
startdatetime__lte=enddate,
|
startdatetime__lte=enddate,
|
||||||
workouttype__in=modalities).order_by("-date", "-starttime").exclude(boattype__in=negtypes)
|
workouttype__in=modalities).order_by("-date", "-starttime").exclude(boattype__in=negtypes)
|
||||||
|
|
||||||
|
|
||||||
query = request.GET.get('q')
|
query = request.GET.get('q')
|
||||||
if query: # pragma: no cover
|
if query: # pragma: no cover
|
||||||
query_list = query.split()
|
query_list = query.split()
|
||||||
@@ -4954,6 +4939,7 @@ def workout_upload_api(request):
|
|||||||
message = {'status': 'false', 'message': 'invalid credentials'}
|
message = {'status': 'false', 'message': 'invalid credentials'}
|
||||||
return JSONResponse(status=403, data=message)
|
return JSONResponse(status=403, data=message)
|
||||||
|
|
||||||
|
|
||||||
form = DocumentsForm(post_data)
|
form = DocumentsForm(post_data)
|
||||||
optionsform = TeamUploadOptionsForm(post_data)
|
optionsform = TeamUploadOptionsForm(post_data)
|
||||||
rowerform = TeamInviteForm(post_data)
|
rowerform = TeamInviteForm(post_data)
|
||||||
|
|||||||
Reference in New Issue
Block a user