diff --git a/rowers/integrations/intervals.py b/rowers/integrations/intervals.py
index 4e0ac680..b6498821 100644
--- a/rowers/integrations/intervals.py
+++ b/rowers/integrations/intervals.py
@@ -63,7 +63,7 @@ class IntervalsIntegration(SyncIntegration):
'base_url': 'https://intervals.icu/api/v1/',
'grant_type': 'refresh_token',
'headers': headers,
- 'scope': 'ACTIVITY:WRITE, LIBRARY:READ',
+ 'scope': 'ACTIVITY:WRITE, LIBRARY:READ, CALENDAR:WRITE',
}
def get_token(self, code, *args, **kwargs):
@@ -297,5 +297,48 @@ class IntervalsIntegration(SyncIntegration):
def token_refresh(self, *args, **kwargs):
return super(IntervalsIntegration, self).token_refresh(*args, **kwargs)
+ def get_plannedsessions_list(self, *args, **kwargs):
+ _ = self.open()
+ r = self.rower
+
+ headers = {
+ 'Authorization': 'Bearer ' + r.intervals_token,
+ }
+
+ # first get the folders - we need the folder id for the next call
+ url = self.oauth_data['base_url'] + 'athlete/0/folders'
+ response = requests.get(url, headers=headers)
+ if response.status_code != 200:
+ return []
+
+ data = response.json()
+ # get all elements in the list where start_date_local is not None
+ folders = [x for x in data if x['start_date_local']]
+ for plan in folders:
+ plan_start_date = arrow.get(plan['start_date_local']).datetime
+ for session in plan["children"]:
+ session["date"] = (plan_start_date+timedelta(days=session["day"])).date()
+
+ return folders
+
+ def get_plannedsession(self, id, *args, **kwargs):
+ _ = self.open()
+ r = self.rower
+
+ url = self.oauth_data['base_url'] + 'athlete/0/workouts/' + str(id)
+ headers = {
+ 'Authorization': 'Bearer ' + r.intervals_token,
+ }
+
+ response = requests.get(url, headers=headers)
+
+ if response.status_code != 200:
+ dologging('intervals.icu.log', response.text)
+ return 0
+
+ data = response.json()
+
+ return data
+
diff --git a/rowers/templates/intervals_list_import.html b/rowers/templates/intervals_list_import.html
new file mode 100644
index 00000000..ea3b410a
--- /dev/null
+++ b/rowers/templates/intervals_list_import.html
@@ -0,0 +1,47 @@
+{% extends "newbase.html" %}
+{% load static %}
+{% load rowerfilters %}
+
+{% block title %}Sessions on intervals.icu{% endblock %}
+
+{% block main %}
+
Sessions on Intervals.icu
+{% if folders %}
+
+{% endif %}
+{% endblock %}
diff --git a/rowers/urls.py b/rowers/urls.py
index 5a4484da..71bb2228 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -630,6 +630,8 @@ urlpatterns = [
views.workout_undo_smoothenpace_view, name='workout_undo_smoothenpace_view'),
re_path(r'^session/rojaboimport/$', views.workout_rojaboimport_view,
name='workout_rojaboimport_view'),
+ re_path(r'^session/intervalsimport/$', views.plannedsession_intervalsimport_view,
+ name='plannedsession_intervalsimport_view'),
re_path(r'^workout/(?P\w+.*)import/$',
views.workout_import_view, name='workout_import_view'),
re_path(r'^workout/(?P\w+.*)import/(?P\d+)/$',
diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py
index a02527b0..c145347a 100644
--- a/rowers/views/importviews.py
+++ b/rowers/views/importviews.py
@@ -681,8 +681,51 @@ def rower_process_testcallback(request): # pragma: no cover
return HttpResponse(text)
+# view to list planned sessions from intervals.icu
+@login_required()
+@user_passes_test(isplanmember, login_url="/rowers/paidplans/",
+ message="This functionality requires a Self-coach plan or higher",
+ redirect_field_name=None)
+def plannedsession_intervalsimport_view(request, message="", userid=0):
+ r = getrequestrower(request, userid=userid)
+ if r.user != request.user:
+ messages.error(
+ request, 'You can only access your own workouts on Intervals.icu, not those of your athletes')
+ url = reverse('plannedsession_intervalsimport_view',
+ kwargs={'userid': request.user.id})
+ return HttpResponseRedirect(url)
+
+ integration = importsources['intervals'](request.user)
+ sessions_list = integration.get_plannedsessions_list()
+
+ if request.method == 'POST': # pragma: no cover
+ try:
+ tdict = dict(request.POST.lists())
+ print(tdict)
+ ids = tdict['session']
+ sessionids = [int(id) for id in ids]
+ for sessionid in sessionids:
+ try:
+ _ = integration.get_plannedsession(sessionid)
+ except NoTokenError:
+ pass
+ messages.info(
+ request,
+ 'Your Intervals.icu planned sessions will be imported in the background.'
+ ' It may take a few minutes before they appear.')
+ url = reverse('plannedsessions_view')
+ return HttpResponseRedirect(url)
+ except KeyError:
+ pass
+
+ return render(request, 'intervals_list_import.html',
+ {
+ 'folders': sessions_list,
+ 'rower': r,
+ 'active': 'nav-plans',
+ })
+
-# The page where you select which Strava workout to import
@login_required()
@user_passes_test(isplanmember, login_url="/rowers/paidplans/",
message="This functionality requires a Self-coach plan or higher",