diff --git a/rowers/nkstuff.py b/rowers/nkstuff.py new file mode 100644 index 00000000..37d91aba --- /dev/null +++ b/rowers/nkstuff.py @@ -0,0 +1,142 @@ +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 + +import time +from time import strftime + +import requests + +#https://oauth-stage.nkrowlink.com/oauth/authorizegrant_type=authorization_code&response_type=code&client_id=rowsandall-staging&scope=read&state=fc8fc3d8-ce0a-443e-838a-1c06fb5317c6&redirect_uri=https%3A%2F%2Fdunav.ngrok.io%2Fnk_callback%2F +#https://oauth-stage.nkrowlink.com/oauth/authorize?grant_type=authorization_code&response_type=code&client_id=rowsandall-staging&scope=read&state=1234&redirect_uri=https%3A%2F%2Fdev.rowsandall.com%2Fnk_callback + +from requests_oauthlib import OAuth2Session + +import django_rq +queue = django_rq.get_queue('default') +queuelow = django_rq.get_queue('low') +queuehigh = django_rq.get_queue('low') + +from rowers.rower_rules import is_workout_user, ispromember + +from iso8601 import ParseError +from rowers.utils import myqueue + +import rowers.mytypes as mytypes +import gzip + +from rowsandall_app.settings import ( + NK_CLIENT_ID, NK_REDIRECT_URI, NK_CLIENT_SECRET, + SITE_URL, NK_API_LOCATION + ) + +try: + from json.decoder import JSONDecodeError +except ImportError: + JSONDecodeError = ValueError + +from rowers.imports import * + +oauth_data = { + 'client_id': NK_CLIENT_ID, + 'client_secret': NK_CLIENT_SECRET, + 'redirect_uri': NK_REDIRECT_URI, + 'autorization_uri': "https://oauth-stage.nkrowlink.com/oauth/authorize", + 'content_type': 'application/json', + 'tokenname': 'nktoken', + 'refreshtokenname': 'nkrefreshtoken', + 'expirydatename': 'nktokenexpirydate', + 'bearer_auth': True, + 'base_url': "https://oauth-stage.nkrowlink.com/oauth/token", + 'scope':'read', + } + +def get_token(code): + #client_id = oauth_data['client_id'] + #client_secret = oauth_data['client_secret'] + #base_uri = oauth_data['base_url'] + + #callbackuri = 'https://'+callbackuri[9:] + #print(callbackuri) + + #nk = OAuth2Session(client_id) + #token = nk.fetch_token(base_uri,client_secret=client_secret,authorization_response=callbackuri) + + #print(token) + #return [0,0,0] + return imports_get_token(code, oauth_data) + +def nk_open(user): + t = time.localtime() + timestamp = time.strftime('%b-%d-%Y_%H%M', t) + token = imports_open(user,oauth_data) + return token + +def do_refresh_token(refreshtoken): + return imports_do_refresh_token(refreshtoken, oauth_data) + +def rower_nk_token_refresh(user): + r = Rower.objects.get(user=user) + res = do_refresh_token(r.nkrefreshtoken) + access_token = res[0] + expires_in = res[1] + refresh_token = res[2] + expirydatetime = timezone.now()+timedelta(seconds=expires_in) + + r.nktoken = access_token + r.nktokenexpirydate = expirydatetime + r.nkrefreshtoken = refresh_token + r.save() + + return r.nktoken + +def make_authorization_url(request): + return imports_make_authorization_url(oauth_data) + +def get_nk_workout_list(user,fake=False): + r = Rower.objects.get(user=user) + + if (r.nktoken == '') or (r.nktoken is None): + s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) + elif (r.nktokenexpirydate is None or timezone.now()+timedelta(seconds=3599)>r.nktokenexpirydate): + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s) + else: + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.nktoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + + url = NK_API_LOCATION+"api/v1/sessions" + + params = {} # start / end time + + s = requests.get(url,headers=headers,params=params) + + return s + +def get_nk_workout_strokes(user,nkid): + r = Rower.objects.get(user=user) + + if (r.nktoken == '') or (r.nktoken is None): + return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" + elif (timezone.now()>r.tokenexpirydate): + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s) + else: + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.nktoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://log.concept2.com/api/users/me/results/"+str(nkid)+"/strokes" + s = requests.get(url,headers=headers) + + return s +# +#def get_workout(user,nkid): diff --git a/rowers/templates/acc_activate_email.html b/rowers/templates/acc_activate_email.html new file mode 100644 index 00000000..2c4f4e1e --- /dev/null +++ b/rowers/templates/acc_activate_email.html @@ -0,0 +1,7 @@ +{% autoescape off %} +Hi {{ user.username }}, +Please click on the link to confirm your registration, + +http://{{ domain }}{% url 'useractivate' uidb64=uid token=token %} +If you think, it's not you, then just ignore this email. +{% endautoescape %} diff --git a/rowers/templates/nk_list_import.html b/rowers/templates/nk_list_import.html new file mode 100644 index 00000000..44ae0554 --- /dev/null +++ b/rowers/templates/nk_list_import.html @@ -0,0 +1,58 @@ +{% extends "newbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block title %}Workouts{% endblock %} + +{% block main %} +
This imports all workouts that have not been imported to rowsandall.com. + The action may take a longer time to process, so please be patient. Click on Import in the list below to import an individual workout. +
+| Import | +Name | +Date | +Duration | +Distance | +New | +
|---|---|---|---|---|---|
| + Import | +{{ workout|lookup:'name' }} | +{{ workout|lookup:'starttime' }} | +{{ workout|lookup:'duration' }} | +{{ workout|lookup:'distance' }} m | +{{ workout|lookup:'new' }} | +
+ No workouts found +
+ {% endif %} + {% endblock %} + +{% block sidebar %} +{% include 'menu_workouts.html' %} +{% endblock %} diff --git a/rowers/tests/testdata/nkworkouts.txt b/rowers/tests/testdata/nkworkouts.txt new file mode 100644 index 00000000..320a47cc --- /dev/null +++ b/rowers/tests/testdata/nkworkouts.txt @@ -0,0 +1,84 @@ +[ + { + "id": 1, + "name": "JustGo-7189M", + "type": 0, + "speedInput": 0, + "startTime": 1614264826, + "endTime": 1614269826, + "location": "Some Location", + "deviceId": 11, + "elapsedTime": 1140000, + "totalDistanceImp": 2920.69, + "totalDistanceGps": 2286.5, + "avgPaceImp": 195159.36302723, + "avgPaceGps": 250466.812537141, + "avgStrokeRate": 19.5, + "distStrokeImp": 8.51, + "distStrokeGps": 6.77, + "avgHeartRate": 158, + "totalStrokeCount": 343, + "totalCalories": 4959900, + "avgCalHour": 4482062.35252774, + "avgSpeedGps": 2, + "avgSpeedImp": 2.56, + "avgPower": 68.6979270660324, + "avgCatch": -46.7961491475831, + "avgSlip": 16.1616225246003, + "avgFinish": 48.1512290049444, + "avgWash": 22.9514686031976, + "avgForceAvg": 114.502194258813, + "avgWork": 210.785493336831, + "avgForceMax": 249.481436977143, + "avgMaxForceAngle": 4.75378911974861, + "startGpsLat": 39.7356346, + "startGpsLon": -75.5581928, + "intervals": [ + { + "id": 1, + "sessionId": 1, + "startTime": 1614264826, + "intervalNumber": 1, + "sessionStrokeStartIndex": 473, + "sessionStrokeEndIndex": 674, + "sessionStrokeCount": 91, + "elapsedTime": 1140000, + "totalDistanceImp": 2920.69, + "totalDistanceGps": 2286.5, + "avgPaceImp": 195159.36302723, + "avgPaceGps": 250466.812537141, + "avgStrokeRate": 19.5, + "distStrokeImp": 8.51, + "distStrokeGps": 6.77, + "avgHeartRate": 158, + "totalStrokeCount": 343, + "totalCalories": 4959900, + "avgCalHour": 4482062.35252774, + "avgSpeedGps": 2, + "avgSpeedImp": 2.56, + "avgPower": 68.6979270660324, + "avgCatch": -46.7961491475831, + "avgSlip": 16.1616225246003, + "avgFinish": 48.1512290049444, + "avgWash": 22.9514686031976, + "avgForceAvg": 114.502194258813, + "avgWork": 210.785493336831, + "avgForceMax": 249.481436977143, + "avgMaxForceAngle": 4.75378911974861, + "startGpsLat": 39.7356346, + "startGpsLon": -75.5581928 + } + ], + "oarlockSessions": [ + { + "id": 1, + "sessionId": 1, + "boatName": "Fast Boat", + "seatNumber": 3, + "portStarboard": 0, + "oarLength": 284, + "oarInboardLength": 85 + } + ] + } +] diff --git a/rowers/tokens.py b/rowers/tokens.py new file mode 100644 index 00000000..e4d10f6e --- /dev/null +++ b/rowers/tokens.py @@ -0,0 +1,12 @@ +from django.contrib.auth.tokens import PasswordResetTokenGenerator +from django.utils import six + + +class AccountActivationTokenGenerator(PasswordResetTokenGenerator): + def _make_hash_value(self, user, timestamp): + return ( + six.text_type(user.pk) + six.text_type(timestamp) + + six.text_type(user.is_active) + ) + +account_activation_token = AccountActivationTokenGenerator() diff --git a/rowers/urls.py b/rowers/urls.py index 99959d6c..434c291d 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -729,6 +729,7 @@ urlpatterns = [ re_path(r'^legal', TemplateView.as_view(template_name='legal.html'),name='legal'), re_path(r'^register/$',views.rower_register_view,name='rower_register_view'), re_path(r'^coachregister/$',views.freecoach_register_view,name='freecoach_register_view'), + path('activate/