forked from kees/hrv-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathelitehrv-sync.py
executable file
·129 lines (110 loc) · 4.05 KB
/
elitehrv-sync.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/env python3
# EliteHRV is fantastic, but doesn't have a very good export method. This fetches the raw JSON.
# Sad that it's not over https, though it made traffic analysis easier! ;)
# © 2015 Kees Cook <[email protected]>
# License: GPLv3
import os, sys, requests
import simplejson as json
def fetch(url, headers, data):
r = requests.post(url, headers=headers, data=data)
response = r.content.decode("utf-8")
if r.status_code != 200:
print("%d %s" % (r.status_code, r.reason), file=sys.stderr)
print(response, file=sys.stderr)
sys.exit(1)
try:
decoded = json.loads(response)
except:
print(response, file=sys.stderr)
raise
return decoded
def merge_list(key, master, latest, complain=False):
# If a list is called "entries", the unique index is "entryId".
# If a list is called "sleeps", the unique index is "sleepId".
index = key
index = index.replace('iesTo','yTo')
index = index.replace('sTo','To')
if index.endswith('ies'):
index = "%syId" % (index[:-3])
elif index.endswith('s'):
index = "%sId" % (index[:-1])
else:
print("How do I merge key '%s'?" % (key), file=sys.stderr)
sys.exit(1)
# Find existing positions.
ids = dict()
for pos in range(len(master)):
ids[master[pos][index]] = pos
# Merge matching Ids.
for pos in range(len(latest)):
newid = latest[pos][index]
if newid in ids:
merge(master[ids[newid]], latest[pos], complain)
else:
master.append(latest[pos])
def merge(master, latest, complain=False):
for key in latest:
if not key in master:
master[key] = latest[key]
if isinstance(latest[key], dict):
merge(master[key], latest[key], complain)
elif isinstance(latest[key], list):
merge_list(key, master[key], latest[key], complain)
elif master[key] != latest[key]:
if complain:
print("Mismatch for id %s key %s master:%s latest:%s", query['entryId'], key, master[key], latest[key], file=sys.stderr)
else:
master[key] = latest[key]
try:
email = sys.argv[1]
password = sys.argv[2]
datafile = None
if len(sys.argv) > 3:
datafile = sys.argv[3]
except:
print("Usage: %s EMAIL PASSWORD [DATA.json]\n", sys.argv[0])
sys.exit(1)
if datafile:
try:
data = json.load(open(datafile))
except FileNotFoundError:
data = dict()
else:
data = dict()
headers = {'user-agent': '''Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.121 Mobile Safari/537.36'''}
common = { 'deviceModel': 'Nexus 5',
'devicePlatform': 'Android',
'deviceVersion': '5.1.1',
'version': '2.0.8',
'locale': 'en-US',
}
query = dict(common)
query['email'] = email
query['password'] = password
print("Fetching session ...", file=sys.stderr)
login = fetch("http://app.elitehrv.com/application/index/login", headers=headers, data=query)
# Refresh dict with latest values.
merge(data, login)
# Install authenticated session.
common['sessionId'] = data['sessionId']
# Fetch full entry details for each entry.
count = 0
for entry in data['entries']:
count += 1
# Assume that if we have rrs in the entry, it's already up to date.
if 'rrs' in entry:
continue
query = dict(common)
query['entryId'] = entry['entryId']
print("Fetching entry %d ..." % (entry['entryId']), file=sys.stderr)
detailed = fetch("http://app.elitehrv.com/application/entry/get", headers=headers, data=query)
# I would expect only to _add_ the rrs or other missing fields, so complain if not.
merge(entry, detailed['entry'], complain=True)
if datafile:
output = open("%s.new" % (datafile), "w")
else:
output = sys.stdout
print(json.dumps(data, sort_keys=True, indent=4), file=output)
print("Wrote %d entr%s." % (count, "y" if count == 1 else "ies"), file=sys.stderr)
if datafile:
os.rename("%s.new" % (datafile), datafile)