Skip to content

Instantly share code, notes, and snippets.

@0r
Forked from grantstephens/sync.py
Created September 9, 2020 23:38
Show Gist options
  • Save 0r/2bf9bfa2c6c011c357e828b6aaaf83e4 to your computer and use it in GitHub Desktop.
Save 0r/2bf9bfa2c6c011c357e828b6aaaf83e4 to your computer and use it in GitHub Desktop.
Garmin Connect Sync Script for Linux (python)
# Syncs files on a garmin device to garmin connect and keeps a local copy.
# auth.json contains your garmin connect username(email) and password.
import json
import os
import shutil
import requests
def auth():
session = requests.Session()
with open('auth.json', 'r') as fn:
data = json.load(fn)
data.update({'eventId': 'submit', 'embed': 'true', })
base_url = 'https://sso.garmin.com/sso'
url_prefix = 'https://connect.garmin.com'
params = {
'service': url_prefix+'/post-auth/login', 'clientId': 'GarminConnect',
'gauthHost': base_url, 'consumeServiceTicket': 'false',
}
preResp = session.get(base_url+'/login', params=params)
ssoResp = session.post(base_url+'/login', params=params,
data=data, allow_redirects=False)
gcRedeemResp = session.get(url_prefix+'/post-auth/login',
allow_redirects=False)
max_redirect_count = 7
current_redirect_count = 1
while True:
url = gcRedeemResp.headers['location']
# Fix up relative redirects.
if url.startswith('/'):
url = url_prefix + url
url_prefix = '/'.join(url.split('/')[:3])
gcRedeemResp = session.get(url, allow_redirects=False)
if ((current_redirect_count >= max_redirect_count) and
(gcRedeemResp.status_code != 200)):
raise Exception('GC redeem %d/%d error %s %s' % (
current_redirect_count, max_redirect_count,
gcRedeemResp.status_code, gcRedeemResp.text))
if gcRedeemResp.status_code == 200 or gcRedeemResp.status_code == 404:
break
current_redirect_count += 1
if current_redirect_count > max_redirect_count:
break
session.headers.update({'Referer': 'https://grant.stephens.com'})
return session
def upload(path, fn, session):
url_prefix = 'https://connect.garmin.com'
return session.post(url_prefix+'/modern/proxy/upload-service/upload/.fit',
files={
'data': (fn, open(os.path.join(path, fn), 'rb'))},
headers={'nk': 'NT'})
if __name__ == "__main__":
session = auth()
path = '/media/{}/GARMIN/Garmin/Activity'.format(
os.environ.get('USERNAME'))
for fn in os.listdir(path):
print('Uploading: {}'.format(fn))
result = upload(path, fn, session).json()
if len(result['detailedImportResult']['successes']) == 1:
print('Moving: {}'.format(fn))
os.makedirs(fn.split('-')[0]+'test', exist_ok=True)
shutil.move(os.path.join(path, fn),
os.path.join(fn.split('-')[0], fn))
else:
os.makedirs('errors', exist_ok=True)
shutil.move(os.path.join(path, fn),
os.path.join('errors', fn))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment