127 lines
4.6 KiB
Python
127 lines
4.6 KiB
Python
import logging
|
|
import requests
|
|
import pickle
|
|
import os.path
|
|
import json
|
|
import re
|
|
import sys
|
|
import subprocess
|
|
|
|
from io import StringIO
|
|
from datetime import timedelta
|
|
|
|
class Flow:
|
|
format = '%d.%m.%Y'
|
|
zip = False # zipped downloads not yet implemented
|
|
|
|
def __init__(self, logger = None, period = 2, file = 'flow-session.dat', jsondir = 'json', datadir = 'data', persist = True, restart = False):
|
|
self.logger = logger or logging.getLogger(__name__)
|
|
self.jsondir = jsondir
|
|
self.datadir = datadir
|
|
if not os.path.exists(jsondir):
|
|
os.makedirs(jsondir)
|
|
if not os.path.exists(datadir):
|
|
os.makedirs(datadir)
|
|
|
|
self.period = 2 # weeks
|
|
self.file = file
|
|
self.persist = persist
|
|
self.restart = restart
|
|
if not restart and persist and os.path.exists(file):
|
|
self.logger.info('Reading session from file')
|
|
file = open(self.file, 'rb')
|
|
session_dump = file.read()
|
|
self.session = pickle.loads(session_dump)
|
|
file.close()
|
|
else:
|
|
self.session = requests.Session()
|
|
pass
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, type, value, traceback):
|
|
if self.persist:
|
|
self.logger.info('Writing session to file')
|
|
session_dump = pickle.dumps(self.session)
|
|
file = open(self.file, 'wb')
|
|
file.write(session_dump)
|
|
file.close()
|
|
|
|
def isLoggedIn(self):
|
|
self.logger.info('Checking login status')
|
|
result = self.session.get('https://flow.polar.com/training/')
|
|
return result.status_code is 200
|
|
|
|
def login(self, email, password):
|
|
if not self.restart and self.isLoggedIn():
|
|
self.logger.info('Skip login')
|
|
return True
|
|
self.logger.info('Logging in')
|
|
result = self.session.post(
|
|
'https://flow.polar.com/login',
|
|
data = {
|
|
'email' : email,
|
|
'password' : password
|
|
},
|
|
verify = True
|
|
)
|
|
return result.status_code is 200
|
|
|
|
def generateRanges(self, start, end, period = None, format = None):
|
|
period = period or self.period
|
|
format = format or self.format
|
|
end_tmp = start
|
|
while end_tmp < end:
|
|
start = end_tmp + timedelta(days = 1)
|
|
end_tmp = start + timedelta(days = 7 * period)
|
|
start_f = start.strftime(format)
|
|
end_f = min(end, end_tmp).strftime(format)
|
|
yield (start_f, end_f)
|
|
|
|
def getEventsInRange(self, start, end):
|
|
ranges = self.generateRanges(start, end)
|
|
for range in ranges:
|
|
url = 'https://flow.polar.com/training/getCalendarEvents?start=%s&end=%s' % range
|
|
result = self.session.get(url)
|
|
if result.status_code is 200:
|
|
filename = '{}/{} - {}.json'.format(self.jsondir, range[0], range[1])
|
|
self.logger.info('Writing event json to %s' % filename)
|
|
file = open(filename, 'wb')
|
|
file.write(result.text.encode('latin-1'))
|
|
file.close()
|
|
|
|
def downloadTraining(self, id):
|
|
types = ('tcx', 'csv', 'gpx')
|
|
for type in types:
|
|
url = 'https://flow.polar.com/training/analysis/%d/export/%s/%s' % (id, type, str(self.zip).lower())
|
|
result = self.session.get(url)
|
|
if result.status_code is 200:
|
|
content_disposition = result.headers['Content-Disposition']
|
|
match = re.search('filename="([^"]+)";', content_disposition)
|
|
if match is not None:
|
|
filename = '{}/{}'.format(self.datadir, match.group(1))
|
|
self.logger.info('Writing training to {}'.format(filename))
|
|
file = open(filename, 'wb')
|
|
file.write(result.text.encode('latin-1'))
|
|
file.close()
|
|
|
|
def parseCalenderEvents(self):
|
|
for root, dirs, filenames in os.walk(self.jsondir):
|
|
for filename in filenames:
|
|
self.logger.info('Parsing file %s' % filename)
|
|
file = open('{}/{}'.format(root, filename), 'r')
|
|
contents = json.load(StringIO(file.read()))
|
|
file.close()
|
|
for item in contents:
|
|
self.downloadTraining(item['listItemId'])
|
|
|
|
def processTraining(self, session):
|
|
proc = subprocess.Popen(['RScript','test.R', session], stdout = subprocess.PIPE, universal_newlines = True)
|
|
while True:
|
|
line = proc.stdout.readline()
|
|
if line != '':
|
|
print("test:", line.rstrip())
|
|
else:
|
|
break
|