diff --git a/rowers/forms.py b/rowers/forms.py index fa3f1b4b..0ebc5fb3 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -554,6 +554,9 @@ class UploadOptionsForm(forms.Form): upload_to_TrainingPeaks = forms.BooleanField(initial=False, required=False, label='Export to TrainingPeaks') + upload_to_Intervals = forms.BooleanField(initial=False, + required=False, + label='Export to Intervals') # do_physics = forms.BooleanField(initial=False,required=False,label='Power Estimate (OTW)') makeprivate = forms.BooleanField(initial=False, required=False, label='Make Workout Private') diff --git a/rowers/integrations/intervals.py b/rowers/integrations/intervals.py index 2669907f..4437019e 100644 --- a/rowers/integrations/intervals.py +++ b/rowers/integrations/intervals.py @@ -183,6 +183,7 @@ class IntervalsIntegration(SyncIntegration): thetype = mytypes.intervalsmapping[workout.workouttype] response = requests.put(url, headers=headers, json={'type': thetype}) + if response.status_code not in [200, 201]: return 0 @@ -260,8 +261,31 @@ class IntervalsIntegration(SyncIntegration): self.rower.intervals_token, id) - def get_workouts(workout, *args, **kwargs) -> list: - return NotImplemented + return 1 + + def get_workouts(self, *args, **kwargs): + startdate = timezone.now() - timedelta(days=7) + enddate = timezone.now() + timedelta(days=1) + startdatestring = kwargs.get(startdate,"") + enddatestring = kwargs.get(enddate,"") + + try: + startdate = arrow.get(startdatestring).datetime + except: + pass + try: + enddate = arrow.get(enddatestring).datetime + except: + pass + + count = 0 + workouts = self.get_workout_list(startdate=startdate, enddate=enddate) + for workout in workouts: + if workout['new'] == 'NEW': + self.get_workout(workout['id']) + count +=1 + + return count def make_authorization_url(self, *args, **kwargs): return super(IntervalsIntegration, self).make_authorization_url(*args, **kwargs) diff --git a/rowers/management/commands/getsyncids.py b/rowers/management/commands/getsyncids.py index a2f9bf75..806a7218 100644 --- a/rowers/management/commands/getsyncids.py +++ b/rowers/management/commands/getsyncids.py @@ -24,7 +24,8 @@ class Command(BaseCommand): record.sporttracksid = w.uploadedtosporttracks if w.uploadedtoc2: record.c2id = w.uploadedtoc2 - + if w.uploadedtointervals: + record.intervalsid = w.uploadedtointervals try: record.save() except IntegrityError: @@ -52,7 +53,8 @@ class Command(BaseCommand): record.sporttracksid = w.uploadedtosporttracks if w.uploadedtoc2: record.c2id = w.uploadedtoc2 - + if w.uploadedtointervals: + record.intervalsid = w.uploadedtointervals try: record.save() except IntegrityError: diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py index 6d12ff71..be02ab17 100644 --- a/rowers/management/commands/processemail.py +++ b/rowers/management/commands/processemail.py @@ -117,5 +117,16 @@ class Command(BaseCommand): lines = traceback.format_exception(exc_type, exc_value, exc_traceback) dologging('processemail.log', ''.join('!! ' + line for line in lines)) + rowers = Rower.objects.filter(intervals_auto_import=True) + for r in rowers: + try: + if user_is_not_basic(r.user) or user_is_coachee(r.user): + intervals_integration = IntervalsIntegration(r.user) + _ = intervals_integration.get_workouts() + except: + exc_type, exc_value, exc_traceback = sys.exc_info() + lines = traceback.format_exception(exc_type, exc_value, exc_traceback) + dologging('processemail.log', ''.join('!! ' + line for line in lines)) + self.stdout.write(self.style.SUCCESS( 'Successfully processed email attachments')) diff --git a/rowers/models.py b/rowers/models.py index 259f9f55..f4715081 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -4557,7 +4557,9 @@ class RowerExportForm(ModelForm): 'strava_auto_import', 'strava_auto_delete', 'trainingpeaks_auto_export', - 'rp3_auto_import' + 'rp3_auto_import', + 'intervals_auto_import', + 'intervals_auto_export', ] # Simple form to set rower's Functional Threshold Power diff --git a/rowers/templates/rower_exportsettings.html b/rowers/templates/rower_exportsettings.html index 866a771a..b6aae035 100644 --- a/rowers/templates/rower_exportsettings.html +++ b/rowers/templates/rower_exportsettings.html @@ -32,10 +32,13 @@ Strava, {% endif %} {% if rower.rp3token is not None and rower.rp3token != '' %} - RP3 + RP3, {% endif %} {% if rower.rojabo_token is not None and rower.rojabo_token != '' %} - Rojabo + Rojabo, + {% endif %} + {% if rower.intervals_token is not None and rower.intervals_token != '' %} + Intervals.icu {% endif %}

diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz index 4ab2f8bd..6ae0e309 100644 Binary files a/rowers/tests/testdata/testdata.tcx.gz and b/rowers/tests/testdata/testdata.tcx.gz differ diff --git a/rowers/uploads.py b/rowers/uploads.py index b13881a9..bb587c21 100644 --- a/rowers/uploads.py +++ b/rowers/uploads.py @@ -130,11 +130,14 @@ def make_plot(r, w, f1, f2, plottype, title, imagename='', plotnr=0): def do_sync(w, options, quick=False): - do_strava_export = w.user.strava_auto_export - try: - do_strava_export = options['upload_to_Strava'] or do_strava_export - except KeyError: - pass + do_strava_export = False + if w.user.strava_auto_export is True: + do_strava_export = True + else: + try: + do_strava_export = options['upload_to_Strava'] or do_strava_export + except KeyError: + pass try: if options['stravaid'] != 0 and options['stravaid'] != '': # pragma: no cover @@ -146,11 +149,15 @@ def do_sync(w, options, quick=False): except KeyError: pass - do_icu_export = w.user.intervals_auto_export - try: - do_icu_export = options['upload_to_Intervals'] or do_icu_export - except KeyError: - pass + do_icu_export = False + if w.user.intervals_auto_export is True: + do_icu_export = True + else: + try: + do_icu_export = options['upload_to_Intervals'] + except KeyError: + pass + try: if options['intervalsid'] != 0 and options['intervalsid'] != '': # pragma: no cover @@ -193,11 +200,14 @@ def do_sync(w, options, quick=False): except KeyError: pass - do_c2_export = w.user.c2_auto_export - try: - do_c2_export = options['upload_to_C2'] or do_c2_export - except KeyError: - pass + do_c2_export = False + if w.user.c2_auto_export is True: + do_c2_export = True + else: + try: + do_c2_export = options['upload_to_C2'] or do_c2_export + except KeyError: + pass try: if options['c2id'] != 0 and options['c2id'] != '': # pragma: no cover @@ -266,7 +276,7 @@ def do_sync(w, options, quick=False): id = 0 message = "Please connect to Intervals.icu first" except Exception as e: - dologging( + dologging( 'intervals.icu.log', e ) diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index a250e4aa..14112726 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -5247,6 +5247,7 @@ def workout_upload_view(request, upload_to_strava = uploadoptions.get('upload_to_Strava', False) upload_to_st = uploadoptions.get('upload_to_SportTracks', False) upload_to_tp = uploadoptions.get('upload_to_TrainingPeaks', False) + upload_to_intervals = uploadoptions.get('upload_to_Intervals', False) response = {} if request.method == 'POST': @@ -5296,6 +5297,7 @@ def workout_upload_view(request, upload_to_strava = optionsform.cleaned_data['upload_to_Strava'] upload_to_st = optionsform.cleaned_data['upload_to_SportTracks'] upload_to_tp = optionsform.cleaned_data['upload_to_TrainingPeaks'] + upload_to_intervals = optionsform.cleaned_data['upload_to_Intervals'] makeprivate = optionsform.cleaned_data['makeprivate'] landingpage = optionsform.cleaned_data['landingpage'] raceid = optionsform.cleaned_data['raceid'] @@ -5313,6 +5315,7 @@ def workout_upload_view(request, 'upload_to_Strava': upload_to_strava, 'upload_to_SportTracks': upload_to_st, 'upload_to_TrainingPeaks': upload_to_tp, + 'upload_to_Intervals': upload_to_intervals, 'landingpage': landingpage, 'boattype': boattype, 'rpe': rpe, @@ -5447,6 +5450,14 @@ def workout_upload_view(request, message = "Please connect to TrainingPeaks first" messages.error(request, message) + if (upload_to_intervals): + intervals_integration = IntervalsIntegration(request.user) + try: + id = intervals_integration.workout_export(w) + except NoTokenError: + message = "Please connect to Intervals.icu first" + messages.error(request, message) + if int(registrationid) < 0: # pragma: no cover race = VirtualRace.objects.get(id=-int(registrationid)) if race.sessiontype == 'race':