diff --git a/requirements.txt b/requirements.txt index c2cd2ea..490757e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ lxml requests -cloudscraper garth diff --git a/setup.py b/setup.py index e00068f..7bd2b9d 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ def read(fname): "Topic :: Utilities", "License :: OSI Approved :: MIT License", ], - install_requires=["lxml", "requests", "cloudscraper", "garth"], + install_requires=["lxml", "requests", "garth"], entry_points={ "console_scripts": ["withings-sync=withings_sync.sync:main"], }, diff --git a/withings_sync/garmin.py b/withings_sync/garmin.py index 256edbc..c14ff45 100644 --- a/withings_sync/garmin.py +++ b/withings_sync/garmin.py @@ -1,8 +1,7 @@ """This module handles the Garmin connectivity.""" import logging -import cloudscraper import garth - +import os log = logging.getLogger("garmin") @@ -22,31 +21,34 @@ class APIException(Exception): class GarminConnect: """Main GarminConnect class""" - UPLOAD_URL = "https://connect.garmin.com/upload-service/upload/.fit" - - # From https://github.com/cpfair/tapiriik @staticmethod def get_session(email=None, password=None): - """tapiriik get_session code""" - session = cloudscraper.CloudScraper() - - try: - garth.login(email, password) - except Exception as ex: - raise APIException("Authentication failure: {}. Did you enter correct credentials?".format(ex)) + logged_in = False + if os.path.exists('./garmin_session'): + garth.resume('./garmin_session') + try: + garth.client.username + logged_in = True + except Exception: + pass + + if not logged_in: + try: + garth.login(email, password) + garth.save('./garmin_session') + except Exception as ex: + raise APIException("Authentication failure: {}. Did you enter correct credentials?".format(ex)) - session.headers.update({'NK': 'NT', 'authorization': garth.client.oauth2_token.__str__(), 'di-backend': 'connectapi.garmin.com'}) - return session @staticmethod def login(username, password): """login to Garmin""" return GarminConnect.get_session(email=username, password=password) - def upload_file(self, ffile, session): + def upload_file(self, ffile): """upload fit file to Garmin connect""" files = {"data": ("withings.fit", ffile)} - res = session.post(self.UPLOAD_URL, files=files, headers={"nk": "NT"}) + res = garth.client.post('connect', '/upload-service/upload/.fit', files=files, api=True, headers={'di-backend': 'connectapi.garmin.com'}) try: resp = res.json() if "detailedImportResult" not in resp: diff --git a/withings_sync/sync.py b/withings_sync/sync.py index 81e06fa..d65b93e 100644 --- a/withings_sync/sync.py +++ b/withings_sync/sync.py @@ -161,8 +161,8 @@ def date_parser(date_string): def sync_garmin(fit_file): """Sync generated fit file to Garmin Connect""" garmin = GarminConnect() - session = garmin.login(ARGS.garmin_username, ARGS.garmin_password) - return garmin.upload_file(fit_file.getvalue(), session) + garmin.login(ARGS.garmin_username, ARGS.garmin_password) + return garmin.upload_file(fit_file.getvalue()) def sync_trainerroad(last_weight):