def main(): # Creating a log file and a logging function log = open("log.txt","a+") now = str(datetime.now()) def logger (message): log.write(now + " | " + message + "\n") print(message) # Opening the connection to Strava logger("Connecting to Strava") client = Client() # You need to run the strava_local_client.py script - with your application's ID and secret - to generate the access token. access_token = "442a2a9e4db1f7008fc96789e18c16e05875305d" # replace this with your token client.access_token = access_token athlete = client.get_athlete() logger("Now authenticated for " + athlete.firstname + " " + athlete.lastname) # We open the cardioactivities CSV file and start reading through it with open('logarun.csv') as csvfile: activities = csv.reader(csvfile) activity_counter = 0 for row in activities: if row[2] == 'time': continue if activity_counter >= 500: logger("Upload count at 500 - pausing uploads for 15 minutes to avoid rate-limit") time.sleep(900) activity_counter = 0 if row[0] not in log: logger("Manually uploading " + row[0]) duration = int(float(row[2])) # time in seconds dist = float(row[1])*1609.344 # convert miles to meters starttime = row[0] strava_activity_type = "Run" try: upload = client.create_activity( name = "logarun Run", start_date_local = starttime, elapsed_time = duration, distance = dist, description = "Shoe used: " + row[3], activity_type = strava_activity_type ) logger("Manually created " + row[0]) activity_counter += 1 except ConnectionError as err: logger("No Internet connection: {}".format(err)) exit(1) logger("Complete! Logged " + str(activity_counter) + " activities.")
def update_strava(request): """Will upload all training entries which are not yet uploaded to strava to strava.""" client = Client(access_token=get_access_token(request)) activities = get_item_list(request, Activity) for activity in activities: # If the strava_id is None than the activity as not uploaded # before. if activity.strava_id is None: log.debug("Upload of traing {id} to strava".format(id=activity.id)) strava = client.create_activity(activity.title, get_strava_activity_type(activity), activity.date, activity.duration.seconds, activity.description, activity.distance) activity.strava_id = strava.id
def main(): # Creating a log file and a logging function log = open("log.txt", "a+") now = str(datetime.now()) def logger(message): log.write(now + " | " + message + "\n") print(message) # Opening the connection to Strava logger("Connecting to Strava") client = Client() # You need to run the strava_local_client.py script - with your application's ID and secret - to generate the access token. access_token = "your_token" # replace this with your token client.access_token = access_token athlete = client.get_athlete() logger("Now authenticated for " + athlete.firstname + " " + athlete.lastname) # Creating an archive folder to put uploaded .gpx files archive = "../archive" # Function to convert the HH:MM:SS in the Runkeeper CSV to seconds def duration_calc(duration): # Splits the duration on the :, so we wind up with a 3-part array split_duration = str(duration).split(":") # If the array only has 2 elements, we know the activity was less than an hour if len(split_duration) == 2: hours = 0 minutes = int(split_duration[0]) seconds = int(split_duration[1]) else: hours = int(split_duration[0]) minutes = int(split_duration[1]) seconds = int(split_duration[2]) total_seconds = seconds + (minutes * 60) + (hours * 60 * 60) return total_seconds # Translate RunKeeper's activity codes to Strava's, could probably be cleverer def activity_translator(rk_type): if rk_type == "Running": return "Run" elif rk_type == "Cycling": return "Ride" elif rk_type == "Hiking": return "Hike" elif rk_type == "Walking": return "Walk" elif rk_type == "Swimming": return "Swim" elif rk_type == "Elliptical": return "Elliptical" else: return "None" # feel free to extend if you have other activities in your repertoire; Strava activity codes can be found in their API docs # We open the cardioactivities CSV file and start reading through it with open('cardioActivities.csv') as csvfile: activities = csv.DictReader(csvfile) activity_counter = 0 for row in activities: if activity_counter >= 599: logger( "Upload count at 599 - pausing uploads for 15 minutes to avoid rate-limit" ) time.sleep(900) activity_counter = 0 else: # used to have to check if we were trying to process the header row # no longer necessary when we process as a dictionary # if there is a gpx file listed, find it and upload it if ".gpx" in row['GPX File']: gpxfile = row['GPX File'] strava_activity_type = activity_translator(str( row['Type'])) if gpxfile in os.listdir('.'): logger("Uploading " + gpxfile) try: upload = client.upload_activity( activity_file=open(gpxfile, 'r'), data_type='gpx', private=False, description=row['Notes'], activity_type=strava_activity_type) except exc.ActivityUploadFailed as err: logger("Uploading problem raised: {}".format(err)) errStr = str(err) # deal with duplicate type of error, if duplicate then continue with next file, else stop if errStr.find('duplicate of activity'): logger( "Moving duplicate activity file {}".format( gpxfile)) shutil.move(gpxfile, archive) isDuplicate = True logger("Duplicate File " + gpxfile) else: exit(1) except ConnectionError as err: logger("No Internet connection: {}".format(err)) exit(1) logger("Upload succeeded.\nWaiting for response...") try: upResult = upload.wait() except HTTPError as err: logger( "Problem raised: {}\nExiting...".format(err)) exit(1) except: logger("Another problem occured, sorry...") exit(1) logger("Uploaded " + gpxfile + " - Activity id: " + str(upResult.id)) activity_counter += 1 shutil.move(gpxfile, archive) else: logger("No file found for " + gpxfile + "!") #if no gpx file, upload the data from the CSV else: if row['Activity Id'] not in log: logger("Manually uploading " + row['Activity Id']) # convert to total time in seconds dur = duration_calc(row['Duration']) # convert to meters dist = float(row['Distance (mi)']) * 1609.344 starttime = datetime.strptime(str(row['Date']), "%Y-%m-%d %H:%M:%S") strava_activity_type = activity_translator( str(row['Type'])) # designates part of day for name assignment above, matching Strava convention for GPS activities if 3 <= starttime.hour <= 11: part = "Morning " elif 12 <= starttime.hour <= 4: part = "Afternoon " elif 5 <= starttime.hour <= 7: part = "Evening " else: part = "Night " try: upload = client.create_activity( name=part + strava_activity_type + " (Manual)", start_date_local=starttime, elapsed_time=dur, distance=dist, description=row['Notes'], activity_type=strava_activity_type) logger("Manually created " + row['Activity Id']) activity_counter += 1 except ConnectionError as err: logger("No Internet connection: {}".format(err)) exit(1) logger("Complete! Logged " + str(activity_counter) + " activities.")
def main(): # Creating a log file and a logging function log = open("log.txt","a+") now = str(datetime.now()) def logger (message): log.write(now + " | " + message + "\n") print message # Opening the connection to Strava logger("Connecting to Strava") client = Client() # You need to run the strava_local_client.py script - with your application's ID and secret - to generate the access token. access_token = "your_token" # replace this with your token client.access_token = access_token athlete = client.get_athlete() logger("Now authenticated for " + athlete.firstname + " " + athlete.lastname) # Creating an archive folder to put uploaded .gpx files archive = "../archive" # Function to convert the HH:MM:SS in the Runkeeper CSV to seconds def duration_calc(duration): # Splits the duration on the :, so we wind up with a 3-part array split_duration = str(duration).split(":") # If the array only has 2 elements, we know the activity was less than an hour if len(split_duration) == 2: hours = 0 minutes = int(split_duration[0]) seconds = int(split_duration[1]) else: hours = int(split_duration[0]) minutes = int(split_duration[1]) seconds = int(split_duration[2]) total_seconds = seconds + (minutes*60) + (hours*60*60) return total_seconds # Translate RunKeeper's activity codes to Strava's, could probably be cleverer def activity_translator(rk_type): if rk_type == "Running": return "Run" elif rk_type == "Cycling": return "Ride" elif rk_type == "Hiking": return "Hike" elif rk_type == "Walking": return "Walk" elif rk_type == "Swimming": return "Swim" elif rk_type == "Elliptical": return "Elliptical" else: return "None" # feel free to extend if you have other activities in your repertoire; Strava activity codes can be found in their API docs # We open the cardioactivities CSV file and start reading through it with open('cardioActivities.csv', 'rb') as csvfile: activities = csv.reader(csvfile) activity_counter = 0 for row in activities: if activity_counter >= 599: logger("Upload count at 599 - pausing uploads for 15 minutes to avoid rate-limit") time.sleep(900) activity_counter = 0 else: pass if row[0] == "Date": pass else: # if there is a gpx file listed, find it and upload it if ".gpx" in row[11]: gpxfile = row[11] strava_activity_type = activity_translator(str(row[1])) if gpxfile in os.listdir('.'): logger("Uploading " + gpxfile) try: upload = client.upload_activity( activity_file = open(gpxfile,'r'), data_type = 'gpx', private = False, description = row[10], activity_type = strava_activity_type ) except exc.ActivityUploadFailed as err: logger("Uploading problem raised: {}".format(err)) errStr = str(err) # deal with duplicate type of error, if duplicate then continue with next file, else stop if errStr.find('duplicate of activity'): logger("Moving dulicate activity file {}".format(gpxfile)) shutil.move(gpxfile,archive) isDuplicate = True logger("Duplicate File " + gpxfile) else: exit(1) except ConnectionError as err: logger("No Internet connection: {}".format(err)) exit(1) logger("Upload succeeded.\nWaiting for response...") try: upResult = upload.wait() except HTTPError as err: logger("Problem raised: {}\nExiting...".format(err)) exit(1) except: logger("Another problem occured, sorry...") exit(1) logger("Uploaded " + gpxfile + " - Activity id: " + str(upResult.id)) activity_counter += 1 shutil.move(gpxfile, archive) else: logger("No file found for " + gpxfile + "!") #if no gpx file, upload the data from the CSV else: if row[0] not in log: logger("Manually uploading " + row[0]) dur = duration_calc(row[4]) dist = float(row[3])*1609.344 starttime = datetime.strptime(str(row[0]),"%Y-%m-%d %H:%M:%S") strava_activity_type = activity_translator(str(row[1])) # designates part of day for name assignment above, matching Strava convention for GPS activities if 3 <= starttime.hour <= 11: part = "Morning " elif 12 <= starttime.hour <= 4: part = "Afternoon " elif 5 <= starttime.hour <=7: part = "Evening " else: part = "Night " try: upload = client.create_activity( name = part + strava_activity_type + " (Manual)", start_date_local = starttime, elapsed_time = dur, distance = dist, description = row[10], activity_type = strava_activity_type ) logger("Manually created " + row[0]) activity_counter += 1 except ConnectionError as err: logger("No Internet connection: {}".format(err)) exit(1) logger("Complete! Logged " + str(activity_counter) + " activities.")
class Strava(object): def __init__(self, cfg): self.token = cfg.get('token') self.convert_swim = cfg.get('convert_swim') self.client = Client(access_token=self.token) self.athlete = self.client.get_athlete() self.activities = self.client.get_activities() print('Loading data for: {} {}'.format(self.athlete.firstname.encode('utf8'), self.athlete.lastname.encode('utf8'))) def json(self): out = [] for a in self.activities: out.append(self._format_activity(a)) return out def _format_activity(self, a): out = { 'measurement': 'activity', 'time': a.start_date.isoformat(), 'fields': { 'distance': a.distance.num, 'moving_time': a.moving_time.total_seconds(), 'elapsed_time': a.elapsed_time.total_seconds(), 'total_elevation_gain': a.total_elevation_gain.num, }, 'tags': { 'type': a.type, 'athlete': a.athlete.id, }, } return out def _get_param_from_activity(self, a): return { 'name': a.name, 'activity_type': a.type, 'start_date_local': a.start_date_local.isoformat(), 'elapsed_time': int(a.elapsed_time.total_seconds()), 'description': a.description, 'distance': a.distance, 'private': a.private, } def convert_swimming(self): print(self.convert_swim) lap_time_min = self.convert_swim['lap_time_min'] lap_time_max = self.convert_swim['lap_time_max'] lap_distance = self.convert_swim['lap_distance'] for a in self.activities: if a.type == 'Swim' and a.distance.num == 0 and not a.description and not re.match('DELETE:.*', a.name): print(self._format_activity(a)) problem = 0 distance = 0 # count laps and distances for lap in a.laps: if lap_time_min < lap.elapsed_time.total_seconds() < lap_time_max: distance += lap_distance else: problem += 1 break if problem == 0 and distance > 0: print('Fine:') new_activity = self._get_param_from_activity(a) new_activity['distance'] = float(distance) if not new_activity['description']: new_activity['description'] = 'Converted by Sport Sucker.\nActivity #{}'.format(a.id) print('Create new') print(new_activity) new_activity_saved = self.client.create_activity(**new_activity) if not a.description: self.client.update_activity( a.id, name='DELETE: {}'.format(a.name), description='Should be deleted, replaced by #{}'.format(new_activity_saved.id) ) else: print('UNABLE to convert swimming')
strava_activity_type = activity_translator(str(row[1])) # designates part of day for name assignment above, matching Strava convention for GPS activities if 3 <= starttime.hour <= 11: part = "Morning " elif 12 <= starttime.hour <= 4: part = "Afternoon " elif 5 <= starttime.hour <=7: part = "Evening " else: part = "Night " try: upload = client.create_activity( name = part + strava_activity_type + " (Manual)", start_date_local = starttime, elapsed_time = dur, distance = dist, description = row[10], activity_type = strava_activity_type ) logger("Manually created " + row[0]) activity_counter += 1 except ConnectionError as err: logger("No Internet connection: {}".format(err)) exit(1) logger("Complete! Logged " + str(activity_counter) + " activities.")
def uploadActivities(data, c_id, secret): # Creating a log file and a logging function log = open("log.txt", "a+") now = str(datetime.now()) def logger(message): log.write(now + " | " + message + "\n") print(message) # Opening the connection to Strava logger("Connecting to Strava") client = Client() updateClient(client, c_id, secret) # We open the cardioactivities CSV file and start reading through it days = data activity_counter = 0 for day in days: if activity_counter >= 500: logger( "Upload count at 500 - pausing uploads for 15 minutes to avoid rate-limit" ) time.sleep(900) activity_counter = 0 note = day['note'] date = day['date'] title = day['title'] for act in day['activities']: act_type = get_activity(act['type']) if (not is_uploadable(act_type)): continue logger("Manually uploading " + date) # extra if (act_type.startswith("Run")): shoes = act['Shoes'] extra = "\nShoes: " + shoes else: extra = "" if 'Distance' in act: dist = get_meters(float(act['Distance']), act['Units']) else: dist = None if 'Time' in act: duration = get_duration(act['Time']) else: duration = None try: upload = client.create_activity(name=title, start_date_local=date + "T00:00:00Z", elapsed_time=duration, distance=dist, description=note + extra, activity_type=act_type) logger("Manually created " + date) activity_counter += 1 except ConnectionError as err: logger("No Internet connection: {}".format(err)) exit(1) except: print("Lost authorization") updateClient(client, c_id, secret) note = "" # hack so note isn't repeated for doubles logger("Complete! Logged " + str(activity_counter) + " activities.")