Private
Public Access
1
0

intervals.icu fixes

This commit is contained in:
2024-12-28 15:13:04 +01:00
parent f36c98fe56
commit 63202ac2f1
6 changed files with 129 additions and 27 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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)

Binary file not shown.

View File

@@ -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)

View File

@@ -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)