Skip to content

Instantly share code, notes, and snippets.

@pirhoo
Created August 2, 2021 10:29
Show Gist options
  • Save pirhoo/346d101ac38e45e8675539ae441007db to your computer and use it in GitHub Desktop.
Save pirhoo/346d101ac38e45e8675539ae441007db to your computer and use it in GitHub Desktop.
Export a Fitbit dump (exercise-*.json files) to Strava
// yarn add strava-v3 glob-promise glob lodash
const strava = require('strava-v3');
const glob = require("glob-promise")
const _ = require("lodash")
strava.config({
client_id: "",
client_secret: "",
redirect_uri: "http://localhost/callback",
})
const activityNames = {
'Natation': 'Swim',
'Aérobic': 'Workout',
'Exercice d\'aérobie': 'Workout',
'Faire du surf, du bodysurf': ' Surfing',
'Jogging': 'Run',
'Musculation': 'Workout',
'Vélo d\'appartement': 'Ride',
'Vélo': 'Ride',
'Yoga, Ashtanga': 'Yoga',
}
function toStravaActivity (activity) {
return {
name: activityNames[activity.activityName],
type: activityNames[activity.activityName],
start_date_local: new Date(activity.startTime).toISOString(),
elapsed_time: activity.duration / 1000, // In seconds
description: 'Imported from Fitbit',
distance: activity.distance * 1000, // To meters
access_token: "",
}
}
async function createActivityOnStrava (activity, thottle = 1e4) {
try {
const { name, id, start_date } = await strava.activities.create(activity)
console.log(`↳ ${name} on ${start_date}: https://www.strava.com/activities/${id}`)
} catch(error) {
if (error.statusCode === 429) {
throw new Error('Creation stop: reached rate limit.')
}
console.error(error.statusCode, error.error.message)
} finally {
await new Promise(resolve => setTimeout(resolve, thottle))
}
}
async function main () {
const minDate = new Date('2018-03-11T11:53:34Z')
const files = await glob('exercise-*.json')
const activities = _.chain(files)
// Read all JSON
.reduce((all, file) => {
const set = require(`./${file}`)
return all.concat(set)
}, [])
// Filter only valid types
.filter(({ activityName }) => {
return activityName in activityNames
})
// Filter only activity avec a certain data
.filter(({ startTime }) => {
return new Date(startTime).getTime() > minDate.getTime()
})
// Convert to strata activity format
.map(toStravaActivity)
.value()
for (const index in activities) {
console.log(`Importing activity ${1 + Number(index)}/${activities.length}:`)
await createActivityOnStrava(activities[index])
}
}
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment