Giter Club home page Giter Club logo

node-strava-v3's Introduction

strava-v3: Simple Node wrapper for Strava's v3 API

NPM Version NPM Downloads Build Status

Status

Supports many but not all Strava API endpoints:

  • oauth
  • athlete
  • athletes
  • activities
  • clubs
  • gear
  • running_races
  • routes
  • segments
  • segment_efforts
  • streams
  • uploads

Installation

npm install strava-v3

Import syntax

Importing only the library:

import strava from 'strava-v3';

Importing both the library as well as interfaces:

import { default as strava, Strava } from 'strava-v3';

Quick start

Promise API

const strava = require('strava-v3')
strava.config({...})
const payload = await strava.athlete.get({})
console.log(payload)

Callback API (Deprecated)

const strava = require('strava-v3');
strava.athlete.get({},function(err,payload,limits) {
    if(!err) {
        console.log(payload);
    }
    else {
        console.log(err);
    }
});

Usage

OAuth configuration

If you are writing an app that other Strava users will authorize against their own account, you'll need to use the OAuth flow. This requires that you provide a client_id, client_secret and redirect_uri that ultimately result in getting back an access_token which can be used for calls on behalf of that user.

You have three options to configure your OAuth calls:

Explicit configuration

Use explicit configuration, which will override both the config file and the environment variables:

var strava = require('strava-v3')
strava.config({
  "access_token"  : "Your apps access token (Required for Quickstart)",
  "client_id"     : "Your apps Client ID (Required for oauth)",
  "client_secret" : "Your apps Client Secret (Required for oauth)",
  "redirect_uri"  : "Your apps Authorization Redirection URI (Required for oauth)",
});
Environment variables

You may alternatively supply the values via environment variables named following the convention STRAVA_<keyName>, so

  • STRAVA_ACCESS_TOKEN = access_token
  • STRAVA_CLIENT_ID = client_id
  • STRAVA_CLIENT_SECRET = client_secret
  • STRAVA_REDIRECT_URI = redirect_uri

Config File (Deprecated)

The template strava_config file can be found at the modules root directory and has the following structure

{
  "access_token"  : "Your apps access token (Required for Quickstart)",
  "client_id"     : "Your apps Client ID (Required for oauth)",
  "client_secret" : "Your apps Client Secret (Required for oauth)",
  "redirect_uri"  : "Your apps Authorization Redirection URI (Required for oauth)",
}

General

API access is designed to be as closely similar in layout as possible to Strava's own architecture, with the general call definition being

var strava = require('strava-v3')

// Promise API
strava.<api endpoint>.<api endpoint option>(args)

// Callback API
strava.<api endpoint>.<api endpoint option>(args,callback)

Example usage:

var strava = require('strava-v3');
strava.athletes.get({id:12345},function(err,payload,limits) {
    //do something with your payload, track rate limits
});

Overriding the default access_token

You'll may want to use OAuth access_tokens on behalf of specific users once your app is in production. Using an access_token specific to a validated user allows for detailed athlete information, as well as the option for additional PUT/POST/DELETE privileges.

Use app-specific logic to retrieve the access\_token for a particular user, then create a Strava client for that user, with their token:

const stravaApi = require('strava-v3');

// ... get access_token from somewhere
strava = new stravaApi.client(access_token);

const payload = await strava.athlete.get({})

Less conveniently, you can also explictly pass an access_token to API calls:

Example usage:

const strava = require('strava-v3');
const payload = await strava.athlete.get({'access_token':'abcde'})

Dealing with pagination

For those API calls that support pagination, you can control both the page being retrieved and the number of responses to return per_page by adding the corresponding properties to args.

Example usage:

const strava = require('strava-v3');
const payload = await strava.athlete.listFollowers({
    page: 1,
    per_page: 2
});

Uploading files

To upload a file you'll have to pass in the data_type as specified in Strava's API reference as well as a string file designating the <filepath>/<filename>. If you want to get updates on the status of your upload pass in statusCallback along with the rest of your args - the wrapper will check on the upload once a second until complete.

Example usage:

const strava = require('strava-v3');
const payload = await strava.uploads.post({
    data_type: 'gpx',
    file: 'data/your_file.gpx',
    name: 'Epic times',
    statusCallback: (err,payload) => {
        //do something with your payload
    }
});

Rate limits

According to Strava's API each response contains information about rate limits. For more details see: Rate Limits

Returns null if X-Ratelimit-Limit or X-RateLimit-Usage headers are not provided

Global status

In our promise API, only the response body "payload" value is returned as a Bluebird promise. To track rate limiting we use a global counter accessible through strava.rateLimiting. The rate limiting status is updated with each request.

// returns true if the most recent request exceeded the rate limit
strava.rateLimiting.exceeded()

// returns the current decimal fraction (from 0 to 1) of rate used. The greater of the short and long term limits.
strava.rateLimiting.fractionReached();

Callback interface (Rate limits)

const strava = require('strava-v3');
strava.athlete.get({'access_token':'abcde'},function(err,payload,limits) {
    //do something with your payload, track rate limits
    console.log(limits);
    /*
    output:
    {
       shortTermUsage: 3,
       shortTermLimit: 600,
       longTermUsage: 12,
       longTermLimit: 30000
    }
    */
});

Supported API Endpoints

To used the Promise-based API, do not provide a callback. A promise will be returned.

See Strava API docs for returned data structures.

OAuth

  • strava.oauth.getRequestAccessURL(args)
  • strava.oauth.getToken(code,done) (Used to token exchange)
  • strava.oauth.refreshToken(code) (Callback API not supported)
  • strava.oauth.deauthorize(args,done)

Athlete

  • strava.athlete.get(args,done)
  • strava.athlete.update(args,done) // only 'weight' can be updated.
  • strava.athlete.listActivities(args,done) Get list of activity summaries
  • strava.athlete.listRoutes(args,done)
  • strava.athlete.listClubs(args,done)
  • strava.athlete.listZones(args,done)

Athletes

  • strava.athletes.get(args,done) Get a single activity. args.id is required
  • strava.athletes.stats(args,done)

Activities

  • strava.activities.get(args,done)
  • strava.activities.create(args,done)
  • strava.activities.update(args,done)
  • strava.activities.listFriends(args,done) -> deprecated at 2.2.0
  • strava.activities.listZones(args,done)
  • strava.activities.listLaps(args,done)
  • strava.activities.listComments(args,done)
  • strava.activities.listKudos(args,done)
  • strava.activities.listPhotos(args,done) -> deprecated at 2.2.0

Clubs

  • strava.clubs.get(args,done)
  • strava.clubs.listMembers(args,done)
  • strava.clubs.listActivities(args,done)
  • strava.clubs.listAdmins(args,done)

Gear

  • strava.gear.get(args,done)

Push Subscriptions

These methods Authenticate with a Client ID and Client Secret. Since they don't use OAuth, they are not available on the client object.

  • strava.pushSubscriptions.list({},done)
  • strava.pushSubscriptions.create({callback_url:...},done)
  • We set 'object_type to "activity" and "aspect_type" to "create" for you.
  • strava.pushSubscriptions.delete({id:...},done)

Running Races

  • strava.runningRaces.get(args,done)
  • strava.runningRaces.listRaces(args,done)

Routes

  • strava.routes.getFile({ id: routeId, file_type: 'gpx' },done) file_type may also be 'tcx'
  • strava.routes.get(args,done)

Segments

  • strava.segments.get(args,done)
  • strava.segments.listStarred(args,done)
  • strava.segments.listEfforts(args,done)
  • strava.segments.explore(args,done) Expects arg bounds as a comma separated string, for two points describing a rectangular boundary for the search: "southwest corner latitutde, southwest corner longitude, northeast corner latitude, northeast corner longitude".

Segment Efforts

  • strava.segmentEfforts.get(args,done)

Streams

  • strava.streams.activity(args,done)
  • strava.streams.effort(args,done)
  • strava.streams.segment(args,done)

Uploads

  • strava.uploads.post(args,done)

Error Handling

Except for the OAuth calls, errors will returned that are instanceof StatusCodeError when the HTTP status code is not 2xx. In the Promise-based API, the promise will be rejected. An error of type RequestError will be returned if the request fails for technical reasons. Example error checking:

     const errors = require('request-promise/errors')

    // Catch a non-2xx response with the Promise API
    badClient.athlete.get({})
        .catch(errors.StatusCodeError, function (e) {
        })

    badClient.athlete.get({},function(err,payload){
      // err will be instanceof errors.StatusCodeError
    }

The StatusCodeError object includes extra properties to help with debugging:

  • name is always StatusCodeError
  • statusCode contains the HTTP status code
  • message Contains the body of the response.
  • options Contains the option used in the request
  • response Contains the response object

Development

This package includes a full test suite runnable via yarn test. It will both lint and run shallow tests on API endpoints.

Running the tests

You'll first need to supply data/strava_config with an access_token that has both private read and write permissions. Look in ./scripts for a tool to help generate this token. Going forward we plan to more testing with a mocked version of the Strava API so testing with real account credentials are not required.

  • Make sure you've filled out all the fields in data/strava_config.
  • Use strava.oauth.getRequestAccessURL({scope:"view_private,write"}) to generate the request url and query it via your browser.
  • Strava will prompt you (the user) to allow access, say yes and you'll be sent to your Authorization Redirection URI - the parameter code will be included in the redirection url.
  • Exchange the code for a new access_token:
// access_token is at payload.access_token
const payload = await strava.oauth.getToken(authorizationCode)

Finally, the test suite has some expectations about the Strava account that it connects for the tests to pass. The following should be true about the Strava data in the account:

  • Must have at least one activity posted on Strava
  • Must have joined at least one club
  • Must have added at least one piece of gear (bike or shoes)
  • Must have created at least one route
  • Most recent activity with an achievement should also contain a segment

(Contributions to make the test suite more self-contained and robust by converting more tests to use nock are welcome!)

  • You're done! Paste the new access_token to data/strava_config and go run some tests:

yarn test.

How the tests work

Using the provided access_token tests will access each endpoint individually:

  • (For all GET endpoints) checks to ensure the correct type has been returned from the Strava.
  • (For PUT in athlete.update) changes some athlete properties, then changes them back.
  • (For POST/PUT/DELETE in activities.create/update/delete) first creates an activity, runs some operations on it, then deletes it.

Debugging

You can enable a debug mode for the underlying request module to see details about the raw HTTP requests and responses being sent back and forth from the Strava API.

To enable this, set this in the environment before this module is loaded:

NODE_DEBUG=request

You can also set `process.env.NODE_DEBUG='request' in your script before this module is loaded.

Resources

Author and Maintainer

Authored by Austin Brown [email protected] (http://austinjamesbrown.com/).

Currently Maintained by Mark Stosberg [email protected]

node-strava-v3's People

Contributors

a12k avatar danab avatar dependabot[bot] avatar dphrag avatar edilson avatar fastegg avatar firrae avatar lamereb avatar latorreoscar avatar lavolp3 avatar markstos avatar masterofpoppets avatar mcomella avatar nicjg avatar nik0kin avatar ntziolis avatar ozqu avatar paul-em avatar peltho avatar phschaad avatar pro-sumer avatar shraymonks avatar tcoyze avatar thibaultleouay avatar timosta avatar timostaudinger avatar unboundev avatar vlavrynovych avatar wesleyschlenker avatar yousefed avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-strava-v3's Issues

Creating activity for workouts with heartbeat rate

I'm trying to pull workout data from my FitBit and upload to Strava. Have to do this because, the official Strava-FitBit integration does not sync non-GPS related activities.

Is there a way to create an activity with the heartbeat rate?

The allowed list of parameters for creating an activity doesn't seem to include any such field.

giving kudos

how can I give kudos? It's documented in Strava's api, but here there is only retrieve kudos
thanks

Previously deleted Activities not being detected at upload

Hi There,

I notice that activities that I have deleted from Strava are not being detected in the same way that the web interface does:

screen shot 2015-05-11 at 11 34 47

The API docs say that 'The created activity has been deleted.' is a status but I'm wondering if maybe it doesn't work? Maybe this is a general API issue but I thought I would run it passed you first.

This code does an upload, then delete then re-uploads the same file:

var strava = require('strava-v3');

function upload(file, cb) {
  strava.uploads.post({
    data_type: 'fit',
    file: file,
    statusCallback: function(err, payload) {
      if (~payload.status.indexOf('still being processed')) return;

      cb(null, payload);
    }
  }, function(err, payload) {});
};

var file = '/Volumes/GARMIN/Garmin/Activities/2015-05-11-08-26-51.fit';

upload(file, function(err, upload1Payload) {
  if (err) return console.log('Error uploading Activity!', err);
  if (upload1Payload.error) {
    return console.log('Error uploading Activity!', upload1Payload.error);
  }

  console.log('Upload 1 success:', upload1Payload.status);

  strava.activities.delete({
    id: upload1Payload.activity_id
  }, function(err) {
    if (err) return console.log('Error deleting Activity 1!', err);

    console.log('Delete success!');

    upload(file, function(err, upload2Payload) {
      if (err) return console.log('Error uploading Activity 2!', err);
      if (upload2Payload.error) {
        return console.log('Error uploading Activity!', upload2Payload.error);
      }

      console.log('Upload 2 success:', upload2Payload.status);
    });
  });
});

I would expect something to fail or get a status indicating that the activity has previously deleted.

Edit: That outputs:

Upload 1 success: Your activity is ready.
Delete success!
Upload 2 success: Your activity is ready.

wish: Only "2xx" and "3xx" responses from Strava are considered successful.

As far as I'm aware, the only successful/expected responses from the Strava API are in the 200 range or the 300 range.

However, this module currently treats 4xx and 5xx responses as "successful", since the module largely passes through the response received from the REST calls. I confirmed that the request package doesn't even treat at 500 response as an error, since at the HTTP level, the HTTP request "succeeded":

var request = require('request');

request('http://httpstat.us/500', function (error, response, body) {
  console.log('error:', error); // Print the error if one occurred 
  console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received 
  console.log('body:', body); // Print the body
});

So currently with the node-strava-v3 module to do robust error checking, you have to first check that no err was returned from the request, then additional check that a 4xx or 5xx error was not returned.

Consider adopting the approach by the node-SES clients for the AWS email sending REST API:

https://github.com/aheckmann/node-ses/blob/ac619185d77604650987cfa0cb51c690f972ec43/lib/email.js#L218

It allows by for consolidated error handling by converting unexpected HTTP status codes into errors.

return an object to all "get" functions so we can cancel them

Would it be possible to return some sort of object reference to all "get" functions, so we can stop the get if need be? Like setTimeout or Tracker.autoRun allow - this will mean that it's possible to cancel upcoming get's from a componentWillUnmount lifecycle message, so that we don't get warnings when unmounted components are used in callbacks....

wish: set default User-Agent

Setting a default user agent string is something that Strava's own REST client in Go does:

https://github.com/strava/go.strava/blob/f5c7cee1038b80d25e3d262208d295c10ca2ac4b/service.go#L116

I'm thinking it might be 'node-strava-v3 '+version.

We can automatically introspect the package version from package.json just by calling require on package.json and reading the version property:

 var version = require('../package').version;

The primary place seeing this in their logs would be the Strava service itself. If there was a problem with how this library was accessing the Strava servers, having a consistent user agent string across requests would help Strava recognize that the common issue had to with a particular version of this library.

Strava API OAuth updates (Old code quits working October 15th, 2019)

In case you missed it, Strava is changing OAuth for their API
https://developers.strava.com/docs/oauth-updates

Important Dates

October 15, 2018

New OAuth endpoints for acquiring short-lived access tokens and refresh tokens are available. New scopes are available.

January 15, 2019

Email address is no longer part of the profile:read_all scope and is removed from the athlete model.

October 15, 2019

Forever tokens are rejected by the server. Old OAuth endpoints for obtaining forever tokens are removed.

Several fields including `workout_type` cannot be set via the API wrapper

I came across this because I tried to set the workout_type of my activities to Race instead of Run, which is the default. While it is returned when reading an activity, currently it cannot be set using the create/update functionality.

While the docs do not explicitly state that this is a feature, I got a confirmation from one of the Strava API devs that this is indeed supported. In fact, all fields that can be read should be writeable via the API. (See his answer below)

I think, we should extend the list of allowed fields for the create/update endpoints to reflect that. Any thoughts?

Hi Timo,

Setting the workout_type is supported and appears to be working โ€” I've just tried it on one of my own activities (see below for an example from the command-line using httpie and jq). Your application needs to have write access (see "access scopes" on http://strava.github.io/api/v3/oauth/).

$ http https://www.strava.com/api/v3/activities/595440342 'Authorization: Bearer <redacted>' | jq '.workout_type'
3
$ http PUT https://www.strava.com/api/v3/activities/595440342 'Authorization: Bearer <redacted>' workout_type=1 | jq '.workout_type'
1

I'd be happy to update the documentation if you think this isn't something that is clear. I would generally expect the fields returned from a read request to also be updatable by the client.

Cheers,
-j

strava.activities.get() not work

Hi there, i'm try to get activity from my athletes but, i got problem when i do it, i got unauthorized error in field "code". Thanks for response

test suite fails ungracefully when connected to an empty Strava account

For the tests to pass, you not only need to connect to a Strava account, you need the account to be populated with several bits of data:

  • Must have at least one activity posted on Strava
  • Must have joined at least one club
  • Must have added at least one piece of gear (bike or shoes)
  • Must have created at least one route
  • Must have at least one segment effort

Currently a number of unhandled exceptions are thrown if these criteria are not met. The test suite should ideally fail more gracefully, and these additional criteria for testing should also be documented. I'm working on this now.

Allow non-default configuration location

I'd like to have the ability to pass my API configuration rather than putting it in [app-root]/data/strava_config or env properties.

Ideally I would like to be able to pass a configuration object to the API. That would allow me to parse the configuration however I want and not have to add to my ever growing list of env props. If this is something that seems reasonable I can spend some time to create / submit a PR?

Include type information

including type information with this library would make use of it by third party developers much easier.

This would essentially mean converting this library to Typescript and transpiling the Ts files to js files (Which would be published to npm in the same way.
The end user would not see any difference (unless they wanted to use the types in which case life would be SO much easier).

Would you accept a pull request for this change?

segments.listEfforts doesn't allow to filter by athlete_id

Hello,

It looks like segments.listEfforts doesn't allow to filter by athlete_id. I think this is because the _qsAllowedProps doesn't contain "athlete_id".
I've added it locally in the segments.js file in my local project and it seems to resolve the issue:
//listSegments
, 'athlete_id'
, 'gender'
, 'age_group'
, 'weight_class'
, 'following'
, 'club_id'
, 'date_range'

I'm not sure how to submit a proposed change, not having contributed on a project with GitHub before.

Thanks,

Laurent.

Getting "done is not a function" when uploading file

Files are still uploaded, but I'm seeing this error in my logs:

TypeError: done is not a function
at [redacted]/node_modules/strava-v3/lib/uploads.js:33:5

I'm using the API like this:

const payload = await strava.uploads.post({
    access_token: accessToken,
    data_type: dataType,
    file: file
});

Cannot read property 'headers' of undefined

/Users/vlavrynovych/Workspace/vlavrynovych/strive/node_modules/strava-v3/lib/util.js in Request._callback at line 220:52

request(options, function (err, response, payload) {
        if (err) {
            console.log('api call error');
            console.log(err);
        }

        done(err, payload, parseRateLimits(response.headers)); // <----- this line
    });
};

function parseRateLimits(headers) {
    if(!headers[util.rateLimit] || !headers[util.rateUsage]) {
        return null;
    }

Error in typings

@nik0kin There seems to be an issue with the typings:

The following is allowed by the typings but results in strava being undefined during runtime

import { strava } from 'strava-v3' // 

So we tried using the default import and now strava is defined during runtime

import * as strava from 'strava-v3' // this results in strava being defined during runtime

But the issue with that:

  • there are api methods on the instance during runtime
  • but during dev time there are no api methods available only
    • defaults
      -strava

The typings suggest that strava does not use default exports, or at least in addition also exports the strava constant. Howveer that does not seem to be the case:

Looking at the js there seems to be only a single default export made, hence import { strava } syntax does not work:
https://github.com/UnbounDev/node-strava-v3/blob/a1bfcb3664e6ef4921c8c91b7a3cd295185ce70f/index.d.ts#L158
Should be:

declare const strava : Strava;

And:
https://github.com/UnbounDev/node-strava-v3/blob/a1bfcb3664e6ef4921c8c91b7a3cd295185ce70f/index.d.ts#L160
Should be

export = strava;

This is only a partial fix as this excludes all interfaces from being exported. in order for this to work add the following line at the end:

export as namespace strava;

Which allows users to access the interfaces as follows:

const routes: strava.ActivitiesRoutes

Inspiration taken from moment:
https://github.com/moment/moment/blob/63f3d52945bc773925b862c61ee7a322d4a33308/ts3.1-typings/moment.d.ts#L784

segment explore endpoint

having trouble submitting the bounds argument when trying to use the strava.segment.explore({ bounds: bbox }) endpoint.

submitting an array bbox like the documenation states but it appears it's turning it into a network call with bounds query param multiple times.

https://www.strava.com/api/v3/segments/explore?bounds=29.356924207076137&bounds=-98.57250982841194&bounds=29.513394912212963&bounds=-98.39284677158804&activity_type=riding

authenticator test causes other tests to fail

0ee9444 attempted to address a problem where the authenticator test failed to reset the state when it's done.

Today I confirmed the problem persists with a fresh checkout from master (v 1.14.0). If I run mocha test/athlete.js, the test passes, but if I run mocha test/authenticator.js test/athlete.js, the the athlete tests fail, complaining than an access key has not been provided.

I've confirmed I'm getting an ENOENT error, so this may that I've triggered tschaub/mock-fs#203 I trigger it on v6.10.2 and v4.4.2

I tried switching to the mock-fs-require-fix module mentioned in that ticket, but it didn't fix the issue.

I tried upgrading to [email protected], but that didn't fix the issue either.

I'm looking at the issue now.

strava.athlete.listActivities(args,done) rounds the lat and long values

When I use strava.athlete.listActivities(args,done) it rounds the latitude and longitude values. For example, on my last activty, it should read end_latlng: [40.823988,-73.944859] and instead it reads end_latlng: [ 40.82, -73.94 ].

If it is of any help, I'm using Meteor and I have the same behavior calling the API directly with Meteor.http but it is very specific to the strava website. (I have a local copy of my data available through a Web API app and it works as expected)

wish: explicit configuration

I'm interested in using this module in a large project that already has a centralized configuration system in place. Would there be willingness to accept a pull request that allows an explicit config to be loaded?

    var strava = require('strava-v3');
    strava.fetchConfig(config)
    strava.athlete.get(...);

This would be implemented by exposing the existing authenticator/fetchConfig() method on the main object and updating it to accept an explicit config. If an explicit configuration was provided, it would be preferred over the other options.

The change would be backwards compatible. If an explicit configuration was not provided, the functionality would remain as before.

oauth.getRequestAccessURL requires 'redirect_uri' but doesn't validate that it is provided

oauth.getRequestAccessURL should validate that redirect_uri is provided. It's a wasted API call to Strava to have them tell us the value is required when we can check if it's required ourselves. Throwing an exception would be sensible, since it's a programming error if the value is not provided.

The documentation for oath.getRequestAccessURL should also document that it requires the client_id and redirect_uri. Most API calls just require the access_token, so this is exceptional.

Wrong Rate limits

Hello, I try to found the best way to handle rate limits but I have some strange behaviors

const handleError = (err) => {
  const {
    shortTermUsage,
    shortTermLimit,
  } = strava.rateLimiting
  console.lg(shortTermUsage, shortTermLimit)

  throw new Error(err.message)
}

const payload = await strava.athlete.listActivities(args).catch(errors.StatusCodeError, handleError)

The error is:
429 - {"message":"Rate Limit Exceeded","errors":[{"resource":"Application","field":"rate limit","code":"exceeded"}]}

But shortTermUsage is 574 while shortTermLimit is 600

So my script stop. The next time I start my script and I go to handleError, shortTermUsage and shortTermLimit are equal to 0 like not initialized.

Did I miss something?

Upload Check unauthorized w/o strava_config

While the file upload works fine when passing the access_token explicitly instead of specifying it in the central strava_config file, the following status checks are unauthorized in this case.

The access token is not passed on via the arguments list from strava.uploads.post() to the subsequent _check() calls.

This does not prevent the upload of files, it only prevents the caller from determining whether and at which point the upload was successful. As a workaround, the access_token can be specified in the strava_config file, which is honored by the check calls.

401 unauthorized when trying to use user access token

Running into an issue where when my user authenticates and I try to use the access token I get back, it's unauthorized.

using this to get access token

connectToStrava: function() {
                window.location = `https://www.strava.com/oauth/authorize?client_id=${stravaClientId}&redirect_uri=http://localhost:8080/table-list&response_type=code&scope=activity:read_all`
            },

then calling getAthlete

const getAthlete = async (accessToken) => {
    return await new Promise((resolve, reject) => {
        strava.athlete.get({access_token: accessToken}, (err, payload, limits) => {
            if (err) {
                console.error(err)
                reject(err)
            } else {
                resolve(payload)
            }
        })
    })
}

This code functions if I use the access token from my strava config, but since that resets, it's not reliable in production... or am I using this incorrectly?

Unable to resolve module 'fs'

When using the dependency in a React Native project, i receive the following error:

Unable to resolve module 'fs' from node_modules/strava-v3/index.js

I am running node version v6.10.2.

Problem with listing athlete activities after the date

Hi,

I'm trying to fetch the athlete activities only after the certain date. I've read the Strava-v3 API and have added the after argument to the Strava server call:

var after = moment(afterDate)._d.getTime(); // returns seconds since UNIX epoch
strava.athlete.listActivities({'access_token':STRAVA_ACCESS_TOKEN, 
                                            id:STRAVA_CLIENT_ID, 
                                            after: after}, 
                                            callBack)

Without the after argument it fetches the latest 30 or so activities, while with after specified i do get the following error on the server:

{ message: 'Bad Request', errors: [ { resource: 'Application', field: 'after', code: 'future' } ] }

I'm running all this under the Meteor.js with all calls done on the server. Any thoughts on how to pass the after argument?

Missing Field activity:read_permission

Hello everyone,

I am missing the possibility to request an access_token with other scopes than scope: read
In my eyes it should be possible when requesting the token in outh.getToken to add an addition parameter where you can say for which scope you are asking the token.
Do you think it is possible to add this feature? Otherwise how do you do strava.athlete.listActivities without getting an 401 and this message {\"message\":\"Authorization Error\",\"errors\":[{\"resource\":\"AccessToken\",\"field\":\"activity:read_permission\",\"code\":\"missing\"}]}"

Authorization Errors with Premium Account

Hi, thanks for the great node wrapper!

I'm trying to get access to my personal beacon's (http://strava.github.io/api/partner/v3/beacon/#beacon_status_get) by using utils.getEndpoint.

I have this so far:

app.get('/beacon', function (req, res) {
  console.log(req.query.code);
  return strava.oauth.getToken(req.query.code, function (err, payload) {
    if (err) res.send(err);
    return strava_util.getEndpoint('beacon/status', {'access_token': payload.access_token}, function (err, payload) {
      if (!err) res.send(payload);
      else res.send(err);
    });
  });
});

The req.query.code is the code returned by the strava.oauth.getRequestAccessURL({scope:"view_private,write"}); url.

The error I get when making the beacon/status GET request is:

{
  "message": "Authorization Error",
  "errors": [
    {
      "resource": "Application",
      "field": "beacon_access",
      "code": "missing"
    }
  ]
}

strava_config not working / have to provide access_token for every call

I've followed the instructions to copy strava_config from node_modules into a new dir 'data' in the root of my application. I've updated it with my unique access_token.

However, my application throws an error that "you must include an access_token". I've tried moving the new data directory so it gets bundled along with the rest of my application files, but still no luck.

So now, every time I make a call I have to provide my access token as an arg. Any idea what is going on here? Thank you!

Connection to strava does not work

Hello,
I'm beginner to nodejs and i would like use your package.
I don't understand how to work. DO you have a complete tutorial for a beginner ?
When I make this:

strava.config({
    "access_token"  : "xxxmyTokenxxx",
    "client_id"     : "xxx",
    "client_secret" : "xxxxxxxxxxxxxxxxxx",
    "redirect_uri"  : "http://localhost:8082",
  });
strava.athlete.get({},function(err,payload,limits) {
        console.log(payload);
    });

I get an 401 error access_token code invalid, I don't understand why ? If I put my token in callback function it's ok !
How to call strava to connect my client ?

regards

Type definition issue with pushSubscription.

The type definition seems to export this interface:

export interface PushSubscriptionRoutes {
    list(args: any, done?: Callback): Promise<any>;
    create(args: any, done?: Callback): Promise<any>;
    delete(args: any, done?: Callback): Promise<any>;
}

However the pushSubscriptions.list implementation only takes a done arg:

pushSubscriptions.prototype.list = function (done) {
  var qs = this.client.getQS(['client_secret', 'client_id'], {
    client_secret: authenticator.getClientSecret(),
    client_id: authenticator.getClientId()
  })
  return this.client._requestHelper({
    headers: { Authorization: null },
    baseUrl: this.baseUrl,
    url: 'push_subscriptions?' + qs
  }, done)
}

The result is code that can't be compiled.

Problem when using getToken

Hi, really new to js and node so apologies if I am making a silly mistake. I can query endpoints ok so believe my config is correct but when I try to get a token I get a code error

app.get('/authorise', function (req, res) {
res.send(req.query.code);
console.log("Req code:" + req.query.code)

strava.oauth.getToken(req.query.code,function(err,payload) {
        console.log(payload);
    });

});

Req code:a071a41c25cdad487f36f6077673a82603188444

I get what appears to be a valid code but getToken fails with

{ message: 'Authorization Error',
errors: [ { resource: 'Application', field: '', code: 'invalid' } ] }

Thanks for the API wrapper and any support.
Wayne

Async Compliance issue?

Hi guys,

I might be missing something, but when trying to use Async with node-strava-v3, I always get this kind of error : "TypeError: this._listHelper is not a function" // whatever the function I'm trying to use.
Can you help me on this?

This works :
var async = require("async"); var strava = require('strava-v3'); var fs = require('fs'); async.map(['package.json', 'sequential3.js'], fs.stat, function(err, results){ console.log(results); });

but this does not :
async.map([{id: 123456}, {id: 12345}], strava.athletes.get, function(err, data){ if (err) { console.log("err: ", err)}; console.log(data); });

Any idea?
Thanks a ton!

segment Leaderboards kom_type element always returns "kom"

Caling a Segment Leaderboard, the kom_type seems to be always "kom", at least for me, also in running segments.
Example:
Segment 17261611 is a running segment.
Calling strava.segments.listLeaderboard({ "access_token": accessToken, id: id, "page": 1, "context_entries": 1, "per_page": 1} results in:

{"effort_count":12, "entry_count":12, "kom_type":"kom", "entries":[{"athlete_name":"Maarten H.", "elapsed_time":164, "moving_time":164, "start_date":"2011-04-23T06:02:42Z", "start_date_local":"2011-04-23T08:02:42Z", "rank":1}, {"athlete_name":"Felix K.", "elapsed_time":194, "moving_time":146, "start_date":"2018-03-30T15:44:32Z", "start_date_local":"2018-03-30T17:44:32Z", "rank":2}, {"athlete_name":"Dirk K.", "elapsed_time":205, "moving_time":157, "start_date":"2019-07-19T19:10:55Z", "start_date_local":"2019-07-19T21:10:55Z", "rank":3}, {"athlete_name":"Michael U.", "elapsed_time":208, "moving_time":208, "start_date":"2019-03-07T19:14:40Z", "start_date_local":"2019-03-07T20:14:40Z", "rank":4}, {"athlete_name":"Stefan E.", "elapsed_time":244, "moving_time":244, "start_date":"2019-02-07T07:04:46Z", "start_date_local":"2019-02-07T08:04:46Z", "rank":5}]}

List photos broken

activities.listPhotos doesn't work.

I'm fairly sure this is because it ignores the required photo_sources parameter

Propose dropping support for Node 0.10 and 0.11

Node .10 and .12 have been end-of-lifed.

If the minimum supported version was moved up to Node 4.x then we could use newer Node.js features in the docs and code like arrow functions.

Node .10 and .12 users would still have the option to use older versions of the module, or fork the module if they'd rather maintain a compatible version of node-strava-v3 instead of upgrading their Node version.

Optionally return an observable if no done method passed

for example:

clubs.get({myArgs}, function(err,payload){
    //do stuff
});

would still work but if no function is passed as the second argument an observable would be returned:

clubs.get({myArgs})
    .flatMap(returnedClubList => Rx.Observable.return(returnedClubList ))
    .flatMap(club => clubs.listMembers({getMembersFor: club}))
    .subscribe(clubMember => console.log("club member: " + clubMember);

this would return a list of all club members from all clubs returned from the initial call.

Would you accept a pull request for this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.