diff --git a/garminscript.py b/garminscript.py index a946efc8..b288cd1e 100644 --- a/garminscript.py +++ b/garminscript.py @@ -1,17 +1,21 @@ from requests_oauthlib import OAuth1Session, OAuth1 import hmac import hashlib +import arrow +import datetime +import json import requests from urllib.parse import quote_plus as rawurlencode import logging +import uuid -logging.basicConfig() -logging.getLogger().setLevel(logging.DEBUG) -requests_log = logging.getLogger("requests.packages.urllib3") -requests_log.setLevel(logging.DEBUG) -requests_log.propagate = True +#logging.basicConfig() +#logging.getLogger().setLevel(logging.DEBUG) +#requests_log = logging.getLogger("requests.packages.urllib3") +#requests_log.setLevel(logging.DEBUG) +#requests_log.propagate = True payload = { @@ -24,27 +28,54 @@ payload = { 'workoutSourceId': 'Rowsandall.com', 'steps': [ { - 'type': 'Step', 'stepOrder': 0, - 'repeatType': 'Step', + 'type': 'WorkoutStep', 'stepOrder': 0, + #'repeatType': 'Step', 'repeatValue': 1, - 'intensity': 'Active', + 'intensity': 'ACTIVE', 'description': '0', 'durationType': 'TIME', 'durationValue': 1800, - 'durationValueType': '', - 'targetType': 'Power', + 'durationValueType': 'METER', + 'targetType': 'POWER', 'targetValue': 1226, - 'targetValueLow': 0, 'targetValueHigh': (0,) + 'targetValueLow': None, + 'targetValueHigh': None, } ] } -payload = {} +payload = { + "workoutName": "Test", + "description": "Test", + "sport": "CYCLING", + "steps": [ + { + "type": "WorkoutStep", + "stepOrder": 1, + "intensity": "INTERVAL", + "description": "Free Ride", + "durationType": "TIME", + "durationValue": 300, + "durationValueType": None, + "targetType": "POWER", + "targetValue": None, + "targetValueLow": 0, + "targetValueHigh": 0.7, + "targetValueType": "PERCENT", + "exerciseCategory": None + }]} -oauth_consumer_key = b'ca29ba5e-6868-4468-987d-4ee60a1f04bf' -oauth_consumer_secret = b'SKRqjML9mOBV7BcPpN7LsbuDNDtvLOvRiyo' -oauth_token = b'79454eab-bf82-4329-9de2-82a6bd911498' -oauth_token_secret = b'DihdHJ2ThEdbsyoStpPTEmYh5F52L697HhD' + +print(json.dumps(payload)) + + +oauth_consumer_key = 'ca29ba5e-6868-4468-987d-4ee60a1f04bf' +oauth_consumer_secret = 'SKRqjML9mOBV7BcPpN7LsbuDNDtvLOvRiyo' +oauth_token = '79454eab-bf82-4329-9de2-82a6bd911498' +oauth_token_secret = 'DihdHJ2ThEdbsyoStpPTEmYh5F52L697HhD' + +oauth_token='673806b7-aa7b-4064-8290-2dd1b0236ae6' +oauth_token_secret='Ci0m4nKLs4Cfpnw856s2BKQRlDJa6nxdmX5' authheaders = OAuth1(client_key=oauth_consumer_key, client_secret=oauth_consumer_secret, @@ -55,29 +86,13 @@ authheaders = OAuth1(client_key=oauth_consumer_key, ) -url = 'https://apis.garmin.com/training-api/workout/' +url = 'https://apis.garmin.com/training-api/workout' + +response = requests.post(url,auth=authheaders,json=payload) +#therequest = requests.prepare_request() -response = requests.post(url,payload,auth=authheaders) # build base_string -base_string1 = b'POST&https%3A%2F%2Fapis.garmin.com%2Ftraining-api%2Fworkout%2F&description%3DUploaded%2520from%2520Rowsandall.com%26estimatedDistanceInMeters%3D6936%26estimatedDurationInSecs%3D1800%26oauth_consumer_key%3Dca29ba5e-6868-4468-987d-4ee60a1f04bf%26oauth_nonce%3D163208869057942765101620205416%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1620205416%26oauth_token%3D79454eab-bf82-4329-9de2-82a6bd911498%26oauth_version%3D1.0%26sport%3DGENERIC%26steps%3Ddescription%26steps%3DdurationType%26steps%3DdurationValue%26steps%3DdurationValueType%26steps%3Dintensity%26steps%3DrepeatType%26steps%3DrepeatValue%26steps%3DstepOrder%26steps%3DtargetType%26steps%3DtargetValue%26steps%3DtargetValueHigh%26steps%3DtargetValueLow%26steps%3Dtype%26workoutName%3D30min%2520at%2520threshold%26workoutProvider%3DRowsandall.com%26workoutSourceId%3DRowsandall.com' - -base_stringa = b'POST&https%3A%2F%2Fapis.garmin.com%2Ftraining-api%2Fworkout%2F&oauth_consumer_key%3Dca29ba5e-6868-4468-987d-4ee60a1f04bf%26oauth_nonce%3D90559685229655402871620208938%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1620208938%26oauth_token%3D79454eab-bf82-4329-9de2-82a6bd911498%26oauth_version%3D1.0' -base_string2 = b'POST&https%3A%2F%2Fapis.garmin.com%2Ftraining-api%2Fworkout%2F&oauth_consumer_key%3Dca29ba5e-6868-4468-987d-4ee60a1f04bf%26oauth_nonce%3DIyk9Ambokd2%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1620138340%26oauth_token%3D673806b7-aa7b-4064-8290-2dd1b0236ae6%26oauth_version%3D1.0' - - -base_string3 = b'POST&https%3A%2F%2Fapis.garmin.com%2Ftraining-api%2Fworkout&oauth_consumer_key%3Dca29ba5e-6868-4468-987d-4ee60a1f04bf%26oauth_nonce%3D90559685229655402871620208938%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1620208938%26oauth_token%3D79454eab-bf82-4329-9de2-82a6bd911498%26oauth_version%3D1.0' - -auth = b'&'.join([oauth_consumer_secret,oauth_token_secret]) -signingKey = bytes(rawurlencode(oauth_consumer_secret) + "&" + rawurlencode(oauth_token_secret),'utf-8') -print(auth) -print(signingKey) -print(base_string3) - -sig = hmac.new(signingKey, base_string3, hashlib.sha1) print(response.status_code) print(response.text) - - -print(sig.hexdigest().encode()) diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py index 28084073..4a931a70 100644 --- a/rowers/c2stuff.py +++ b/rowers/c2stuff.py @@ -22,6 +22,8 @@ import json from scipy import optimize from json.decoder import JSONDecodeError +from pytz.exceptions import UnknownTimeZoneError + from rowsandall_app.settings import ( C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, UPLOAD_SERVICE_URL, UPLOAD_SERVICE_SECRET @@ -1079,8 +1081,10 @@ def add_workout_from_data(user,importid,data,strokedata, except: # pragma: no cover comments = ' ' - - thetimezone = pytz.timezone(data['timezone']) + try: + thetimezone = pytz.timezone(data['timezone']) + except UnknownTimeZoneError: + thetimezone = 'UTC' r = Rower.objects.get(user=user) @@ -1228,7 +1232,10 @@ def add_workout_from_data(user,importid,data,strokedata, w = Workout.objects.get(id=id) - local_tz = pytz.timezone(data['timezone']) + try: + local_tz = pytz.timezone(data['timezone']) + except UnknownTimeZoneError: + local_tz = pytz.utc # local_tz = pytz.timezone(thetimezone) w.startdatetime = w.startdatetime.astimezone(local_tz) diff --git a/rowers/tests/mocks.py b/rowers/tests/mocks.py index 66ba56bf..eddf1473 100644 --- a/rowers/tests/mocks.py +++ b/rowers/tests/mocks.py @@ -719,6 +719,8 @@ def mocked_requests(*args, **kwargs): with open('rowers/tests/testdata/c2_timezone2.json','r') as infile: c2timezoneworkoutdata2 = json.load(infile) + with open('rowers/tests/testdata/c2_timezonebad.json','r') as infile: + c2timezoneworkoutdatabad = json.load(infile) with open('rowers/tests/testdata/c2jsonstrokedata.txt','r') as infile: c2strokedata = json.load(infile) @@ -1192,6 +1194,8 @@ def mocked_requests(*args, **kwargs): return MockResponse(c2workoutdata,200) elif '31' in args[0]: return MockResponse(c2timezoneworkoutdata2,200) + elif '32' in args[0]: + return MockResponse(c2timezoneworkoutdatabad,200) else: return MockResponse(c2timezoneworkoutdata,200) elif c2workoutlisttester.match(args[0]): diff --git a/rowers/tests/test_imports.py b/rowers/tests/test_imports.py index bfef0eee..7bd662ef 100644 --- a/rowers/tests/test_imports.py +++ b/rowers/tests/test_imports.py @@ -277,6 +277,22 @@ class C2Objects(DjangoTestCase): w = Workout.objects.get(id=2) self.assertEqual(w.timezone,'Europe/Prague') + + @patch('rowers.c2stuff.requests.get', side_effect=mocked_requests) + @patch('rowers.dataprep.create_engine') + def test_c2_import_tz3(self, mock_get, mocked_sqlalchemy): + + response = self.c.get('/rowers/workout/c2import/32/',follow=True) + + self.assertRedirects(response, + expected_url='/rowers/workout/'+encoded2+'/edit/', + status_code=302,target_status_code=200) + + self.assertEqual(response.status_code, 200) + + w = Workout.objects.get(id=2) + self.assertEqual(w.timezone,'UTC') + @patch('rowers.c2stuff.requests.get', side_effect=mocked_requests) @patch('rowers.dataprep.create_engine') def test_c2_import_tz2(self, mock_get, mocked_sqlalchemy):