dblock / strava-ruby-client Goto Github PK
View Code? Open in Web Editor NEWA complete Ruby client for the Strava API v3.
Home Page: https://code.dblock.org/2018/11/27/writing-a-new-strava-api-ruby-client.html
License: MIT License
A complete Ruby client for the Strava API v3.
Home Page: https://code.dblock.org/2018/11/27/writing-a-new-strava-api-ruby-client.html
License: MIT License
https://developers.strava.com/docs/changelog/ added:
Oct 18, 2022
Deprecate page and per_page params on the activity comments endpoint. Please start using page_size and after_cursor instead to request paginated results. Responses provided using the new query params include an additive, backwards compatible change, populating the cursor field on each comment.
see Readme for this project: https://github.com/dblock/strava-ruby-client#list-activity-comments
This is poor design from Strava.
"start_date" : "2018-02-16T14:56:25Z",
"timezone" : "(GMT-08:00) America/Los_Angeles",
"start_date_local" : "2018-02-16T06:56:25Z"
Those date/times are both ISO, but both are in UTC. If you just parse them, you'll get an incorrect value for "start_date_local" unless you only care about the hour of the day.
The correct value in this example is 2018-02-16T06:56:25-08:00.
The heavy lifting of setting this thing up is done, all Athlete APIs are implemented, so now we just need API implementations.
Everything remaining from https://developers.strava.com/docs/reference
Applications can revoke access to an athlete’s data. This will invalidate all refresh tokens and access tokens that the application has for the athlete, and the application will be removed from the athlete’s apps settings page. All requests made using invalidated tokens will receive a 401 Unauthorized response.
The endpoint is POST https://www.strava.com/oauth/deauthorize.
Thank you for writing this gem! It's been great to work with, and saves so much time. I'm just writing a little training journal tool for myself to archive TrainingPeaks and Strava data. When accessing Activities, I kept getting auth errors. It turns out there are some extra fun hoops to jump through to get the permissions created to access Activities, which you can read about on this blog post: https://www.markhneedham.com/blog/2020/12/15/strava-authorization-error-missing-read-permission/
Just an FYI for anyone else having this problem, and also to potentially update docs to make folks aware.
Great library, thanks for developing and maintaining it!
I've discovered an issue when calling to_json
on an activity due to activesupport -> json.rb
breaking on the http_response
object. I realize this isn't in your lib directly, but wanted to point it out as it'd be nice to be able to serialize an activity without a workaround.
strava-ruby-client: 1.0.0
Ruby: 3.1.2.p20
activity.to_json
../3.1.0/gems/activesupport-7.0.3.1/lib/active_support/core_ext/object/json.rb:159:in `initialize_dup': stack level too deep (SystemStackError)
The object causing the issue is http_response
.
Work around:
activity.delete('http_response')
activity.to_json # => { .... }
Ala slack-ruby/slack-ruby-client#161
Should be able to provide a block into each API that would paginate over results.
I would like to know what might cause an activity upload status to remain on: "Your activity is still being processed."
Code
def self.upload_activity_to_strava(user_id, hd_activity_id)
user = User.find(user_id)
hd_activity = HdActivity.find(hd_activity_id)
activity_upload = nil
if !user.blank? && !user.strava_auth_code.blank? && !hd_activity.blank?
if user.strava_token_expiration < Time.now
StravaMyModelClient.refresh_user_token(user_id)
user.reload
end
client = Strava::Api::Client.new(
access_token: user.strava_access_token
)
file_name = StravaMyModelClient.build_activity_gpx(hd_activity_id)
activity_upload = client.create_upload(
file: Faraday::UploadIO.new(file_name, 'application/gpx+xml'),
data_type: 'gpx',
external_id: 'strava-ruby-client-upload',
name: "Virtual #{hd_activity.hd_race.display_name}",
description: "#{hd_activity.name} #{hd_activity.metric_distance.to_f.round(2).to_s} m",
type: 'Run'
)
puts activity_upload.status
end
end
Terminal
file_name: /tmp/606f44b972b30251168f7b1f.gpx
$ vim /tmp/606f44b972b30251168f7b1f.gpx
$ cat /tmp/606f44b972b30251168f7b1f.gpx
<?xml version="1.0"?>
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1" creator="GPX RubyGem 1.0.0 -- http://dougfales.github.io/gpx/" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<metadata>
<name>606f44b972b30251168f7b1f.gpx</name>
<time>2021-04-08T19:28:44+00:00</time>
<bound minlat="90.0" minlon="180.0" maxlat="-90.0" maxlon="-180.0"/>
</metadata>
<wpt lat="34.14319964919367" lon="34.14319964919367">
<time>2021-04-08T18:01:28+00:00</time>
<ele>1802.0</ele>
<name>Waypoint [34.14319964919367, -118.26633248905605]</name>
</wpt>
<wpt lat="34.14337272131732" lon="34.14337272131732">
<time>2021-04-08T18:02:22+00:00</time>
<ele>1805.0</ele>
<name>Waypoint [34.14337272131732, -118.26525667999938]</name>
</wpt>
<wpt lat="34.143531606889205" lon="34.143531606889205">
<time>2021-04-08T18:03:21+00:00</time>
<ele>1805.0</ele>
<name>Waypoint [34.143531606889205, -118.26426905201292]</name>
</wpt>
<wpt lat="34.14367772460674" lon="34.14367772460674">
<time>2021-04-08T18:04:31+00:00</time>
<ele>1806.0</ele>
<name>Waypoint [34.14367772460674, -118.26336078698965]</name>
</wpt>
<wpt lat="34.14391055916302" lon="34.14391055916302">
<time>2021-04-08T18:05:23+00:00</time>
<ele>1802.0</ele>
<name>Waypoint [34.14391055916302, -118.26231086281064]</name>
</wpt>
<wpt lat="34.14412607487465" lon="34.14412607487465">
<time>2021-04-08T18:06:24+00:00</time>
<ele>1803.0</ele>
<name>Waypoint [34.14412607487465, -118.26133903216558]</name>
</wpt>
<wpt lat="34.14431672833044" lon="34.14431672833044">
<time>2021-04-08T18:07:23+00:00</time>
<ele>1808.0</ele>
<name>Waypoint [34.14431672833044, -118.26041510279569]</name>
</wpt>
<wpt lat="34.14451073143204" lon="34.14451073143204">
<time>2021-04-08T18:08:28+00:00</time>
<ele>1800.0</ele>
<name>Waypoint [34.14451073143204, -118.25939976463064]</name>
</wpt>
<wpt lat="34.14474356369262" lon="34.14474356369262">
<time>2021-04-08T18:09:33+00:00</time>
<ele>1800.0</ele>
<name>Waypoint [34.14474356369262, -118.25834984045163]</name>
</wpt>
<wpt lat="34.14495907727932" lon="34.14495907727932">
<time>2021-04-08T18:10:33+00:00</time>
<ele>1803.0</ele>
<name>Waypoint [34.14495907727932, -118.25737800980657]</name>
</wpt>
<wpt lat="34.14511658052343" lon="34.14511658052343">
<time>2021-04-08T18:11:32+00:00</time>
<ele>1804.0</ele>
<name>Waypoint [34.14511658052343, -118.25629871502171]</name>
</wpt>
<wpt lat="34.14534500221772" lon="34.14534500221772">
<time>2021-04-08T18:12:28+00:00</time>
<ele>1804.0</ele>
<name>Waypoint [34.14534500221772, -118.2551917430408]</name>
</wpt>
<wpt lat="34.14549475872339" lon="34.14549475872339">
<time>2021-04-08T18:13:49+00:00</time>
<ele>1804.0</ele>
<name>Waypoint [34.14549475872339, -118.25416552832729]</name>
</wpt>
<wpt lat="34.14565226096881" lon="34.14565226096881">
<time>2021-04-08T18:14:22+00:00</time>
<ele>1807.0</ele>
<name>Waypoint [34.14565226096881, -118.25308623354239]</name>
</wpt>
<wpt lat="34.14584291617914" lon="34.14584291617914">
<time>2021-04-08T18:15:22+00:00</time>
<ele>1809.0</ele>
<name>Waypoint [34.14584291617914, -118.25208840120777]</name>
</wpt>
<wpt lat="34.1459965447889" lon="34.1459965447889">
<time>2021-04-08T18:16:31+00:00</time>
<ele>1810.0</ele>
<name>Waypoint [34.1459965447889, -118.2510356464586]</name>
</wpt>
<wpt lat="34.14612822623206" lon="34.14612822623206">
<time>2021-04-08T18:17:21+00:00</time>
<ele>1806.0</ele>
<name>Waypoint [34.14612822623206, -118.25013328524503]</name>
</wpt>
<wpt lat="34.14630598463142" lon="34.14630598463142">
<time>2021-04-08T18:18:23+00:00</time>
<ele>1801.0</ele>
<name>Waypoint [34.14630598463142, -118.24912279756417]</name>
</wpt>
<wpt lat="34.146503827443716" lon="34.146503827443716">
<time>2021-04-08T18:19:30+00:00</time>
<ele>1809.0</ele>
<name>Waypoint [34.146503827443716, -118.24816400293503]</name>
</wpt>
<wpt lat="34.14667608438103" lon="34.14667608438103">
<time>2021-04-08T18:20:22+00:00</time>
<ele>1803.0</ele>
<name>Waypoint [34.14667608438103, -118.2472624526678]</name>
</wpt>
<wpt lat="34.14684765877311" lon="34.14684765877311">
<time>2021-04-08T18:21:21+00:00</time>
<ele>1808.0</ele>
<name>Waypoint [34.14684765877311, -118.24628711238454]</name>
</wpt>
<wpt lat="34.147033144210404" lon="34.147033144210404">
<time>2021-04-08T18:22:23+00:00</time>
<ele>1808.0</ele>
<name>Waypoint [34.147033144210404, -118.24523269045672]</name>
</wpt>
<wpt lat="34.1472137619943" lon="34.1472137619943">
<time>2021-04-08T18:23:28+00:00</time>
<ele>1806.0</ele>
<name>Waypoint [34.1472137619943, -118.24428737561341]</name>
</wpt>
<wpt lat="34.147365547565386" lon="34.147365547565386">
<time>2021-04-08T18:24:31+00:00</time>
<ele>1806.0</ele>
<name>Waypoint [34.147365547565386, -118.24334383816205]</name>
</wpt>
<wpt lat="34.14755954366568" lon="34.14755954366568">
<time>2021-04-08T18:25:30+00:00</time>
<ele>1809.0</ele>
<name>Waypoint [34.14755954366568, -118.242328499997]</name>
</wpt>
<wpt lat="34.14775918208439" lon="34.14775918208439">
<time>2021-04-08T18:26:23+00:00</time>
<ele>1801.0</ele>
<name>Waypoint [34.14775918208439, -118.24136098905305]</name>
</wpt>
<wpt lat="34.147951625879244" lon="34.147951625879244">
<time>2021-04-08T18:27:25+00:00</time>
<ele>1806.0</ele>
<name>Waypoint [34.147951625879244, -118.24042834336835]</name>
</wpt>
<wpt lat="34.14817675204603" lon="34.14817675204603">
<time>2021-04-08T18:28:25+00:00</time>
<ele>1802.0</ele>
<name>Waypoint [34.14817675204603, -118.23941312742666]</name>
</wpt>
<wpt lat="34.14836907392115" lon="34.14836907392115">
<time>2021-04-08T18:29:21+00:00</time>
<ele>1808.0</ele>
<name>Waypoint [34.14836907392115, -118.23840654217682]</name>
</wpt>
<wpt lat="34.14857495754123" lon="34.14857495754123">
<time>2021-04-08T18:30:22+00:00</time>
<ele>1807.0</ele>
<name>Waypoint [34.14857495754123, -118.23747809682843]</name>
</wpt>
<wpt lat="34.14873241479673" lon="34.14873241479673">
<time>2021-04-08T18:31:32+00:00</time>
<ele>1807.0</ele>
<name>Waypoint [34.14873241479673, -118.23649928694898]</name>
</wpt>
<wpt lat="34.14893637339585" lon="34.14893637339585">
<time>2021-04-08T18:32:24+00:00</time>
<ele>1800.0</ele>
<name>Waypoint [34.14893637339585, -118.23557951865992]</name>
</wpt>
<wpt lat="34.1491485981498" lon="34.1491485981498">
<time>2021-04-08T18:33:21+00:00</time>
<ele>1802.0</ele>
<name>Waypoint [34.1491485981498, -118.23455099351231]</name>
</wpt>
<wpt lat="34.14930747285886" lon="34.14930747285886">
<time>2021-04-08T18:34:25+00:00</time>
<ele>1802.0</ele>
<name>Waypoint [34.14930747285886, -118.23356336552585]</name>
</wpt>
<wpt lat="34.14945205856929" lon="34.14945205856929">
<time>2021-04-08T18:35:21+00:00</time>
<ele>1804.0</ele>
<name>Waypoint [34.14945205856929, -118.23257253752664]</name>
</wpt>
<wpt lat="34.14960438967502" lon="34.14960438967502">
<time>2021-04-08T18:36:24+00:00</time>
<ele>1807.0</ele>
<name>Waypoint [34.14960438967502, -118.23152862945601]</name>
</wpt>
<wpt lat="34.14983528378196" lon="34.14983528378196">
<time>2021-04-08T18:37:21+00:00</time>
<ele>1810.0</ele>
<name>Waypoint [34.14983528378196, -118.2304873823363]</name>
</wpt>
<wpt lat="34.14999557571077" lon="34.14999557571077">
<time>2021-04-08T18:38:26+00:00</time>
<ele>1810.0</ele>
<name>Waypoint [34.14999557571077, -118.22949093624283]</name>
</wpt>
<wpt lat="34.15018723684638" lon="34.15018723684638">
<time>2021-04-08T18:39:30+00:00</time>
<ele>1808.0</ele>
<name>Waypoint [34.15018723684638, -118.2284013669174]</name>
</wpt>
<wpt lat="34.15034731220097" lon="34.15034731220097">
<time>2021-04-08T18:40:21+00:00</time>
<ele>1808.0</ele>
<name>Waypoint [34.15034731220097, -118.22730437877541]</name>
</wpt>
<wpt lat="34.15057571975148" lon="34.15057571975148">
<time>2021-04-08T18:41:23+00:00</time>
<ele>1804.0</ele>
<name>Waypoint [34.15057571975148, -118.22619740679453]</name>
</wpt>
<wpt lat="34.15071513959741" lon="34.15071513959741">
<time>2021-04-08T18:42:24+00:00</time>
<ele>1806.0</ele>
<name>Waypoint [34.15071513959741, -118.22524196550957]</name>
</wpt>
<wpt lat="34.15090937513301" lon="34.15090937513301">
<time>2021-04-08T18:43:34+00:00</time>
<ele>1802.0</ele>
<name>Waypoint [34.15090937513301, -118.22430060351007]</name>
</wpt>
<wpt lat="34.151055249019635" lon="34.151055249019635">
<time>2021-04-08T18:44:35+00:00</time>
<ele>1809.0</ele>
<name>Waypoint [34.151055249019635, -118.22330092883229]</name>
</wpt>
<wpt lat="34.15126094278173" lon="34.15126094278173">
<time>2021-04-08T18:45:25+00:00</time>
<ele>1802.0</ele>
<name>Waypoint [34.15126094278173, -118.22222432026072]</name>
</wpt>
<wpt lat="34.151415852450725" lon="34.151415852450725">
<time>2021-04-08T18:46:24+00:00</time>
<ele>1801.0</ele>
<name>Waypoint [34.151415852450725, -118.22116271883299]</name>
</wpt>
<wpt lat="34.15155656182049" lon="34.15155656182049">
<time>2021-04-08T18:47:28+00:00</time>
<ele>1803.0</ele>
<name>Waypoint [34.15155656182049, -118.22019843086946]</name>
</wpt>
<wpt lat="34.15173276317261" lon="34.15173276317261">
<time>2021-04-08T18:48:33+00:00</time>
<ele>1804.0</ele>
<name>Waypoint [34.15173276317261, -118.21919673003804]</name>
</wpt>
<wpt lat="34.1518973069387" lon="34.1518973069387">
<time>2021-04-08T18:49:29+00:00</time>
<ele>1809.0</ele>
<name>Waypoint [34.1518973069387, -118.2181738296235]</name>
</wpt>
<wpt lat="34.152097409768984" lon="34.152097409768984">
<time>2021-04-08T18:50:39+00:00</time>
<ele>1804.0</ele>
<name>Waypoint [34.152097409768984, -118.21727141545308]</name>
</wpt>
<wpt lat="34.15229164212581" lon="34.15229164212581">
<time>2021-04-08T18:51:30+00:00</time>
<ele>1809.0</ele>
<name>Waypoint [34.15229164212581, -118.21633005345359]</name>
</wpt>
<wpt lat="34.15253022510133" lon="34.15253022510133">
<time>2021-04-08T18:52:22+00:00</time>
<ele>1810.0</ele>
<name>Waypoint [34.15253022510133, -118.21525409809657]</name>
</wpt>
<wpt lat="34.152710370438" lon="34.152710370438">
<time>2021-04-08T18:53:29+00:00</time>
<ele>1809.0</ele>
<name>Waypoint [34.152710370438, -118.2141341985048]</name>
</wpt>
<wpt lat="34.15284462319693" lon="34.15284462319693">
<time>2021-04-08T18:54:25+00:00</time>
<ele>1807.0</ele>
<name>Waypoint [34.15284462319693, -118.21321414393411]</name>
</wpt>
<wpt lat="34.15305503970175" lon="34.15305503970175">
<time>2021-04-08T18:55:35+00:00</time>
<ele>1807.0</ele>
<name>Waypoint [34.15305503970175, -118.2121943351013]</name>
</wpt>
<wpt lat="34.153218873151914" lon="34.153218873151914">
<time>2021-04-08T18:56:32+00:00</time>
<ele>1809.0</ele>
<name>Waypoint [34.153218873151914, -118.21126292906504]</name>
</wpt>
<wpt lat="34.15336781102291" lon="34.15336781102291">
<time>2021-04-08T18:57:25+00:00</time>
<ele>1810.0</ele>
<name>Waypoint [34.15336781102291, -118.21033702782772]</name>
</wpt>
</gpx>
Thank you
Tried with https://github.com/tranquiliste/tcx_reader but ran into https://github.com/tranquiliste/tcx_reader/issues/1.
Haven't tried https://github.com/rubyist/guppy.
All activity photos were removed in PR #77
it says the strava api has no support for activity photos, but actually that's wrong. See this discussion on the strava dev forms
You just need to add a size param to the route that's bigger than any photos you want it to return .
Hi,
Currently client.running_races
is returning a 404. I would like to know if the API endpoint has been removed from Strava? Is there a replacement for it?
Thank you
Hi,
I wrote a little "private" application to download my data and put them on a .xls file and .klm (no web) using strava-api-v3. Now it is not working animore.
I read strava instructions and I am very confused about what I have to do to move on in terms of conversion.
I also have found strava-ruby-client gem more recently updated and I tried to restart from scratch (ultimately I need an array with my data).
Can you please post a little example on how the workflow process can be implemented?
here is my code:
client = Strava::OAuth::Client.new(
client_id: "19",
client_secret: "f8e677"
)
puts client
redirect_url = client.authorize_url(
client_id: "1*****9",
client_secret: "f8****e677",
redirect_uri: 'localhost',
approval_prompt: 'auto',
response_type: 'code',
scope: 'activity:read_all'
)
puts redirect_url
response = client.oauth_token()
I get this error: /strava-ruby-client-0.3.1/lib/strava/web/raise_error.rb:15:in `on_complete': Bad Request (Strava::Errors::Fault)
thanks in advance
benny
Currently https://github.com/dblock/strava-ruby-client/blob/master/bin/strava-oauth-token specifies a list of hard-coded scopes. Make this a parameter and default to read.
Generally that should be a proper command line tool using ghi like https://github.com/dblock/fue.
Coming from node-strava/node-strava-v3#125, ensure that IDs aren't truncated and/or are cast to a string when they cannot be parsed. All IDs here are just declared as property
.
Start a server and handle the redirect to localhost in https://github.com/dblock/strava-ruby-client/blob/master/bin/oauth-token.rb instead of asking to copy-paste the token.
Travis is MIA, even though https://app.travis-ci.com/github/dblock/strava-ruby-client/builds shows stuff. Get rid of it.
I managed to re-enable travis, the badge needs to be updated.
The replacing attribute will be sport_type
.
https://developers.strava.com/docs/changelog/
June 15, 2022
Introduction of activity sport_type. This is the preferred field to use moving forward, as opposed to type, which is now considered deprecated. Please note: this change is backward compatible and type will still be supported. The SportType enumeration is distinct from ActivityType in that it includes new types (e.g. MountainBikeRide). In requests where both type and sport_type are present, type will be ignored.
$ dotenv bundle exec strava-oauth-token
bundler: command not found: strava-oauth-token
gem is already in the repo, but needs to be required, too
# .rubocop.yml
require:
- rubocop-rspec
Couldn't make it work for the Bearer header. Currently having to constantly edit new YMLs and replace the access token with access-token
when a new cassette is recorded.
See https://developers.strava.com/docs/#client-code
Strava can respond with a rate limit error providing the time when the next request can be made.
Hello, I would like to know how to receive updates on new activities from all the users that authorized my app on Strava.
Do I need one web hook subscription for each user or just one global subscription for all users. Does create_push_subscription
take any additional parameters? Thank you in advance.
Input
callback_url = "https://[mydomain].com/api/strava_challenge"
raise "Missing callback_url." unless callback_url
webhook_client.logger.info "Subscribing to #{callback_url} ..."
subscription = webhook_client.create_push_subscription(callback_url: callback_url, verify_token: "token")
puts subscription.id
Output
# subscription.id
integer ID
https://developers.strava.com/docs/changelog/
May 8, 2020
Improved list segment effort endpoint at a new URI. Added start_date_local and end_date_local. The old endpoint is deprecated and will redirect to the new URI as on June 18th, 2020.
https://developers.strava.com/docs/reference/#api-SegmentEfforts-getEffortsBySegmentId
Hello Dblock,
I installed everything on my raspberry pi, but how do I have to start from there?
Sorry for this 'beginner' question.
Best regards,
Jop
Hi
I have just finished migrating https://github.com/ylecuyer/onmove200 to this gem. overall it went seamlessly except for the error class which doesn't report error and status when doing an upload.
The raw body looks like this:
{:status=>400, :headers=>{"date"=>"Wed, 18 Dec 2019 22:40:08 GMT", "content-type"=>"application/json; charset=utf-8", "transfer-encoding"=>"chunked", "connection"=>"close", "cache-control"=>"no-cache", "via"=>"1.1 linkerd", "x-download-options"=>"noopen", "status"=>"400 Bad Request", "x-ratelimit-limit"=>"600,30000", "x-request-id"=>"c7a703a2-2943-4568-ad0e-4feb5457d982", "referrer-policy"=>"strict-origin-when-cross-origin", "x-frame-options"=>"SAMEORIGIN,DENY", "x-ratelimit-usage"=>"6,35", "x-content-type-options"=>"nosniff", "x-permitted-cross-domain-policies"=>"none", "vary"=>"Origin", "x-xss-protection"=>"1; mode=block"}, :body=>{"id"=>3132246002, "id_str"=>"3132246002", "external_id"=>"ACT_0007.OMD.gpx", "error"=>"ACT_0007.OMD.gpx duplicate of activity 2941970362", "status"=>"There was an error processing your activity.", "activity_id"=>nil}}
But the Strava::Errors::Fault
only reports message
and errors
which don't exist: https://github.com/dblock/strava-ruby-client/blob/master/lib/strava/errors/fault.rb
For the moment I have added both error
and status
: https://github.com/ylecuyer/strava-ruby-client/blob/master/lib/strava/errors/fault.rb
Do you know if the error message format changed ? Or is it just this endpoint with funky format?
If the fix is worth it, I'll open a PR
Here's my rails console commands:
photos = client.activity_photos(activity.id)
# returns a bunch of photos
photo = photos.first
=> #<Strava::Api::Pagination:0x0000000107cc1f48
@collection=
[{"unique_id"=>"1e5bacd2-9fee-409f-8dd9-be7c33a653ce",
"athlete_id"=>38072598,
"activity_id"=>9216986893,
"activity_name"=>"Great day ",
"resource_state"=>2,
"caption"=>"",
"source"=>1,
"uploaded_at"=>2023-06-06 23:52:49 UTC,
"created_at"=>2023-06-06 19:04:17 UTC,
"created_at_local"=>2023-06-06 13:04:17 UTC,
"urls"=>{"1800"=>"https://d3nn82uaxijpm6.cloudfront.net/assets/media/placeholder-photo@4x-13b0b44cfa828acc8b95d8dc4b8157d87666aa1ea8ef814c6ec36cd542d2b756.png"},
"sizes"=>{"1800"=>[1372, 1000]},
"default_photo"=>false},
That URL is a placeholder image - how do I get the real image URL?
You can click https://d3nn82uaxijpm6.cloudfront.net/assets/media/placeholder-photo@4x-13b0b44cfa828acc8b95d8dc4b8157d87666aa1ea8ef814c6ec36cd542d2b756.png - it's a very boring grey arrow. What I actually want is https://dgtzuqphqg23d.cloudfront.net/d-SgDjqAYTTEb2_uXnhC0UoND2CErBxV38KFl_uPO0g-1536x2048.jpg, a very pretty traffic cone.
How do I get from one to the other?
the endpoint and logic for handling group events is currently missing:
events = client.send :get '/groups/:id/group_events', {}
# events[0]
{"id"=>339353,
"resource_state"=>2,
"title"=>"Erste Gruppenfahrt (Ø25kmh)",
"description"=>"",
"club_id"=>456773,
"club"=>
{"id"=>456773,
"resource_state"=>1,
"name"=>"Rennrad Mainz Wiesbaden Rheinhessen"},
"organizing_athlete"=>
{"id"=>7,
"username"=>"XXX",
"resource_state"=>2,
"firstname"=>"XXX",
"lastname"=>"YYY",
"bio"=>nil,
"city"=>"ZZZ",
"state"=>"",
"country"=>"",
"sex"=>"",
"premium"=>true,
"summit"=>true,
"created_at"=>"2011-09-05T10:41:23Z",
"updated_at"=>"2021-06-25T16:04:11Z",
"badge_type_id"=>1,
"weight"=>85.0,
"profile_medium"=>
"https://dgalywyr863hv.cloudfront.net/pictures/athletes/7/7/5/medium.jpg",
"profile"=>
"https://dgalywyr863hv.cloudfront.net/pictures/athletes/7/7/5/large.jpg",
"friend"=>nil,
"follower"=>nil,
"blocked"=>false,
"can_follow"=>true},
"activity_type"=>"Ride",
"created_at"=>"2018-06-13T09:59:58Z",
"route_id"=>nil,
"route"=>nil,
"women_only"=>false,
"private"=>false,
"skill_levels"=>1,
"terrain"=>0,
"upcoming_occurrences"=>["2018-06-13T15:00:00Z"],
"zone"=>"Europe/Berlin",
"address"=>"Bootshaus, Mainz",
"joined"=>true,
"start_latlng"=>[49.99241, 8.28793]}
i am working on implementing the model and methods with pagination
Allow activity(id: 1234)
, activity(1234)
as well as activity('1234')
.
Hi, According to the Strava dashboard the access token expires. But the refresh token does not.
I would like to know if it is possible to get the most recent non expired access-token, using only the refresh-token, in a backend app, without user interaction?
Currently my backend uses:
Strava::Api::Client.new(
access_token: ACCESS_TOKEN
)
But the token expires often.
Thanks
Descent is Ascent + (Start Elevation - End Elevation). Start Elevation and End Elevation can be obtained from AltitudeStream.
Something that can talk to Strava on the command line, ala https://github.com/dblock/fue and https://github.com/gravityblast/mini-strava/blob/master/bin/mini-strava
This is easiest to explain by example:
activity = client.athlete_activities.last
activity.class
=> Strava::Models::Activity
activity.id
=> 2957731094
activity.name
=> "Morning Run"
# This is actually a SummaryActivity (see here https://developers.strava.com/docs/reference/#api-models-SummaryActivity) and so its missing certain fields like description
activity.description
=> nil
activity = client.activity(2957731094)
activity.class
=> Strava::Models::Activity
activity.id
=> 2957731094
activity.name
=> "Morning Run"
# This is actually a DetailedActivity (see here https://developers.strava.com/docs/reference/#api-models-DetailedActivity) and so it contains data for fields like description
=> "What a beautiful day for a run"
My work around for this API weirdness is:
client.athlete_activities(per_page: 30) do |activity_summary|
activity = client.activity(activity_summary.id)
end
But I think it would be much clearer if client.athlete_activities
returned [Strava::Models::SummaryActivity]
and client.activity
returned a Strava::Models::DetailedActivity
.
What do you think?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.