strava-ruby-client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/.rubocop.yml +15 -0
- data/.rubocop_todo.yml +47 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +125 -0
- data/Dangerfile +2 -0
- data/Gemfile +15 -0
- data/LICENSE.md +22 -0
- data/README.md +231 -0
- data/RELEASING.md +61 -0
- data/Rakefile +17 -0
- data/bin/oauth-token.rb +28 -0
- data/lib/strava-ruby-client.rb +30 -0
- data/lib/strava/api/client.rb +38 -0
- data/lib/strava/api/config.rb +31 -0
- data/lib/strava/errors/fault.rb +13 -0
- data/lib/strava/logger.rb +13 -0
- data/lib/strava/models/activity.rb +57 -0
- data/lib/strava/models/athlete.rb +25 -0
- data/lib/strava/models/map.rb +9 -0
- data/lib/strava/models/model.rb +5 -0
- data/lib/strava/models/token.rb +12 -0
- data/lib/strava/oauth/client.rb +70 -0
- data/lib/strava/oauth/config.rb +33 -0
- data/lib/strava/version.rb +3 -0
- data/lib/strava/web/client.rb +31 -0
- data/lib/strava/web/config.rb +41 -0
- data/lib/strava/web/connection.rb +35 -0
- data/lib/strava/web/raise_error.rb +29 -0
- data/lib/strava/web/request.rb +38 -0
- data/spec/fixtures/strava/client_athlete.yml +59 -0
- data/spec/fixtures/strava/client_athlete_activities.yml +121 -0
- data/spec/fixtures/strava/oauth_token_authorization_code.yml +53 -0
- data/spec/fixtures/strava/oauth_token_invalid_client.yml +50 -0
- data/spec/fixtures/strava/oauth_token_invalid_code.yml +50 -0
- data/spec/fixtures/strava/oauth_token_refresh_token.yml +52 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/strava/api/client_spec.rb +36 -0
- data/spec/strava/api/config_spec.rb +22 -0
- data/spec/strava/oauth/client_spec.rb +120 -0
- data/spec/strava/oauth/config_spec.rb +24 -0
- data/spec/strava/version_spec.rb +7 -0
- data/spec/strava/web/client_spec.rb +9 -0
- data/spec/strava/web/config_spec.rb +4 -0
- data/spec/support/shared/it_behaves_like_web_client.rb +131 -0
- data/spec/support/vcr.rb +12 -0
- data/strava-ruby-client.gemspec +21 -0
- metadata +150 -0
data/RELEASING.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Releasing Strava-Ruby-Client
|
2
|
+
|
3
|
+
There're no hard rules about when to release strava-ruby-client. Release bug fixes frequently, features not so frequently and breaking API changes rarely.
|
4
|
+
|
5
|
+
### Release
|
6
|
+
|
7
|
+
Run tests, check that all tests succeed locally.
|
8
|
+
|
9
|
+
```
|
10
|
+
bundle install
|
11
|
+
rake
|
12
|
+
```
|
13
|
+
|
14
|
+
Check that the last build succeeded in [Travis CI](https://travis-ci.org/dblock/strava-ruby-client) for all supported platforms.
|
15
|
+
|
16
|
+
Change "Next" in [CHANGELOG.md](CHANGELOG.md) to the current date.
|
17
|
+
|
18
|
+
```
|
19
|
+
### 0.2.2 (7/10/2015)
|
20
|
+
```
|
21
|
+
|
22
|
+
Remove the line with "Your contribution here.", since there will be no more contributions to this release.
|
23
|
+
|
24
|
+
Commit your changes.
|
25
|
+
|
26
|
+
```
|
27
|
+
git add CHANGELOG.md
|
28
|
+
git commit -m "Preparing for release, 0.2.2."
|
29
|
+
git push origin master
|
30
|
+
```
|
31
|
+
|
32
|
+
Release.
|
33
|
+
|
34
|
+
```
|
35
|
+
$ rake release
|
36
|
+
|
37
|
+
strava-ruby-client 0.2.2 built to pkg/strava-ruby-client-0.2.2.gem.
|
38
|
+
Tagged v0.2.2.
|
39
|
+
Pushed git commits and tags.
|
40
|
+
Pushed strava-ruby-client 0.2.2 to rubygems.org.
|
41
|
+
```
|
42
|
+
|
43
|
+
### Prepare for the Next Version
|
44
|
+
|
45
|
+
Add the next release to [CHANGELOG.md](CHANGELOG.md).
|
46
|
+
|
47
|
+
```
|
48
|
+
### 0.2.3 (Next)
|
49
|
+
|
50
|
+
* Your contribution here.
|
51
|
+
```
|
52
|
+
|
53
|
+
Increment the third version number in [lib/strava/version.rb](lib/strava/version.rb).
|
54
|
+
|
55
|
+
Commit your changes.
|
56
|
+
|
57
|
+
```
|
58
|
+
git add CHANGELOG.md lib/strava/version.rb
|
59
|
+
git commit -m "Preparing for next development iteration, 0.2.3."
|
60
|
+
git push origin master
|
61
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
|
5
|
+
Bundler.setup :default, :development
|
6
|
+
|
7
|
+
require 'rspec/core'
|
8
|
+
require 'rspec/core/rake_task'
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
11
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'rubocop/rake_task'
|
15
|
+
RuboCop::RakeTask.new
|
16
|
+
|
17
|
+
task default: %i[rubocop spec]
|
data/bin/oauth-token.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'dotenv/load'
|
4
|
+
require 'strava-ruby-client'
|
5
|
+
|
6
|
+
client = Strava::OAuth::Client.new(
|
7
|
+
client_id: ENV['STRAVA_CLIENT_ID'],
|
8
|
+
client_secret: ENV['STRAVA_CLIENT_SECRET']
|
9
|
+
)
|
10
|
+
|
11
|
+
redirect_url = client.authorize_url(
|
12
|
+
redirect_uri: 'http://localhost',
|
13
|
+
response_type: 'code',
|
14
|
+
scope: 'activity:read'
|
15
|
+
)
|
16
|
+
|
17
|
+
STDOUT.write "Opening browser at #{redirect_url}\n"
|
18
|
+
system 'open', redirect_url
|
19
|
+
|
20
|
+
STDOUT.write 'Copy paste the code from the redirect URL: '
|
21
|
+
code = gets.strip
|
22
|
+
|
23
|
+
response = client.oauth_token(code: code)
|
24
|
+
|
25
|
+
puts "token_type: #{response.token_type}"
|
26
|
+
puts "refresh_token: #{response.refresh_token}"
|
27
|
+
puts "access_token: #{response.access_token}"
|
28
|
+
puts "expires_at: #{response.expires_at}"
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
require 'json'
|
4
|
+
require 'logger'
|
5
|
+
require 'hashie'
|
6
|
+
require 'active_support/core_ext/object/to_query'
|
7
|
+
require 'time'
|
8
|
+
|
9
|
+
require_relative 'strava/version'
|
10
|
+
require_relative 'strava/logger'
|
11
|
+
|
12
|
+
require_relative 'strava/errors/fault'
|
13
|
+
|
14
|
+
require_relative 'strava/models/model'
|
15
|
+
require_relative 'strava/models/token'
|
16
|
+
require_relative 'strava/models/athlete'
|
17
|
+
require_relative 'strava/models/map'
|
18
|
+
require_relative 'strava/models/activity'
|
19
|
+
|
20
|
+
require_relative 'strava/web/raise_error'
|
21
|
+
require_relative 'strava/web/connection'
|
22
|
+
require_relative 'strava/web/request'
|
23
|
+
require_relative 'strava/web/config'
|
24
|
+
require_relative 'strava/web/client'
|
25
|
+
|
26
|
+
require_relative 'strava/oauth/config'
|
27
|
+
require_relative 'strava/oauth/client'
|
28
|
+
|
29
|
+
require_relative 'strava/api/config'
|
30
|
+
require_relative 'strava/api/client'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Strava
|
2
|
+
module Api
|
3
|
+
class Client < Strava::Web::Client
|
4
|
+
attr_accessor(*Config::ATTRIBUTES)
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
Config::ATTRIBUTES.each do |key|
|
8
|
+
send("#{key}=", options[key] || Strava::Api.config.send(key))
|
9
|
+
end
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def headers
|
14
|
+
{ 'Authorization' => "Bearer #{access_token}" }
|
15
|
+
end
|
16
|
+
|
17
|
+
def athlete
|
18
|
+
Strava::Models::Athlete.new(get('athlete'))
|
19
|
+
end
|
20
|
+
|
21
|
+
def athlete_activities(options = {})
|
22
|
+
get('athlete/activities', options).map do |activity|
|
23
|
+
Strava::Models::Activity.new(activity)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class << self
|
28
|
+
def configure
|
29
|
+
block_given? ? yield(Config) : Config
|
30
|
+
end
|
31
|
+
|
32
|
+
def config
|
33
|
+
Config
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Strava
|
2
|
+
module Api
|
3
|
+
module Config
|
4
|
+
extend self
|
5
|
+
|
6
|
+
ATTRIBUTES = %i[
|
7
|
+
endpoint
|
8
|
+
access_token
|
9
|
+
].freeze
|
10
|
+
|
11
|
+
attr_accessor(*Config::ATTRIBUTES)
|
12
|
+
|
13
|
+
def reset
|
14
|
+
self.endpoint = 'https://www.strava.com/api/v3'
|
15
|
+
self.access_token = nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def configure
|
21
|
+
block_given? ? yield(Config) : Config
|
22
|
+
end
|
23
|
+
|
24
|
+
def config
|
25
|
+
Config
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Strava::Api::Config.reset
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Strava
|
2
|
+
module Models
|
3
|
+
class Activity < Model
|
4
|
+
property 'id'
|
5
|
+
property 'resource_state'
|
6
|
+
property 'athlete', transform_with: ->(v) { Strava::Models::Athlete.new(v) }
|
7
|
+
property 'name'
|
8
|
+
property 'distance'
|
9
|
+
property 'moving_time'
|
10
|
+
property 'elapsed_time'
|
11
|
+
property 'total_elevation_gain'
|
12
|
+
property 'type'
|
13
|
+
property 'workout_type'
|
14
|
+
property 'id'
|
15
|
+
property 'external_id'
|
16
|
+
property 'upload_id'
|
17
|
+
property 'start_date', transform_with: ->(v) { Time.parse(v) }
|
18
|
+
property 'start_date_local', transform_with: ->(v) { Time.parse(v) }
|
19
|
+
property 'timezone'
|
20
|
+
property 'utc_offset'
|
21
|
+
property 'start_latlng'
|
22
|
+
property 'end_latlng'
|
23
|
+
property 'location_city'
|
24
|
+
property 'location_state'
|
25
|
+
property 'location_country'
|
26
|
+
property 'start_latitude'
|
27
|
+
property 'start_longitude'
|
28
|
+
property 'achievement_count'
|
29
|
+
property 'kudos_count'
|
30
|
+
property 'comment_count'
|
31
|
+
property 'athlete_count'
|
32
|
+
property 'photo_count'
|
33
|
+
property 'map', transform_with: ->(v) { Strava::Models::Map.new(v) }
|
34
|
+
property 'trainer'
|
35
|
+
property 'commute'
|
36
|
+
property 'manual'
|
37
|
+
property 'private'
|
38
|
+
property 'visibility'
|
39
|
+
property 'flagged'
|
40
|
+
property 'gear_id'
|
41
|
+
property 'from_accepted_tag'
|
42
|
+
property 'average_speed'
|
43
|
+
property 'max_speed'
|
44
|
+
property 'has_heartrate'
|
45
|
+
property 'average_heartrate'
|
46
|
+
property 'max_heartrate'
|
47
|
+
property 'heartrate_opt_out'
|
48
|
+
property 'display_hide_heartrate_option'
|
49
|
+
property 'elev_high'
|
50
|
+
property 'elev_low'
|
51
|
+
property 'pr_count'
|
52
|
+
property 'total_photo_count'
|
53
|
+
property 'has_kudoed'
|
54
|
+
property 'suffer_score'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Strava
|
2
|
+
module Models
|
3
|
+
class Athlete < Model
|
4
|
+
property 'id'
|
5
|
+
property 'username'
|
6
|
+
property 'resource_state'
|
7
|
+
property 'firstname'
|
8
|
+
property 'lastname'
|
9
|
+
property 'city'
|
10
|
+
property 'state'
|
11
|
+
property 'country'
|
12
|
+
property 'sex'
|
13
|
+
property 'premium'
|
14
|
+
property 'created_at', transform_with: ->(v) { Time.parse(v) }
|
15
|
+
property 'updated_at', transform_with: ->(v) { Time.parse(v) }
|
16
|
+
property 'badge_type_id'
|
17
|
+
property 'profile'
|
18
|
+
property 'profile_medium'
|
19
|
+
property 'email'
|
20
|
+
property 'follower'
|
21
|
+
property 'friend'
|
22
|
+
property 'summit'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Strava
|
2
|
+
module Models
|
3
|
+
class Token < Model
|
4
|
+
property 'token_type'
|
5
|
+
property 'access_token'
|
6
|
+
property 'refresh_token'
|
7
|
+
property 'expires_in'
|
8
|
+
property 'expires_at', transform_with: ->(v) { Time.at(v) }
|
9
|
+
property 'athlete', transform_with: ->(v) { Strava::Models::Athlete.new(v) }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Strava
|
2
|
+
module OAuth
|
3
|
+
class Client < Strava::Web::Client
|
4
|
+
attr_accessor(*Config::ATTRIBUTES)
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
Strava::OAuth::Config::ATTRIBUTES.each do |key|
|
8
|
+
send("#{key}=", options[key] || Strava::OAuth.config.send(key))
|
9
|
+
end
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# Obtain the request access URL.
|
15
|
+
#
|
16
|
+
# @option options [Object] :redirect_uri
|
17
|
+
# URL to which the user will be redirected after authentication.
|
18
|
+
# @option options [Object] :response_type
|
19
|
+
# Must be code.
|
20
|
+
# @option options [Object] :approval_prompt
|
21
|
+
# Prompt behavior, force or auto.
|
22
|
+
# @option options [Object] :scope
|
23
|
+
# Requested scopes, as a comma delimited string.
|
24
|
+
# @option options [Object] :state
|
25
|
+
# Returned in the redirect URI.
|
26
|
+
# @see https://developers.strava.com/docs/authentication/
|
27
|
+
# @return [String] URL to redirect the user to.
|
28
|
+
def authorize_url(options = {})
|
29
|
+
query = options.merge(
|
30
|
+
client_id: client_id || raise(ArgumentError, 'Missing Strava client id.'),
|
31
|
+
response_type: options[:response_type] || 'code',
|
32
|
+
redirect_uri: options[:redirect_uri] || 'http://localhost',
|
33
|
+
approval_prompt: options[:approval_prompt] || 'auto',
|
34
|
+
scope: options[:scope] || 'read'
|
35
|
+
)
|
36
|
+
|
37
|
+
[endpoint, "authorize?#{query.to_query}"].join('/')
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Complete the authentication process.
|
42
|
+
#
|
43
|
+
# @option options [Object] :code
|
44
|
+
# The code parameter obtained in the redirect.
|
45
|
+
# @option options [Object] :grant_type
|
46
|
+
# The grant type for the request.
|
47
|
+
# @see https://developers.strava.com/docs/authentication/
|
48
|
+
# @return [Hash] Token information.
|
49
|
+
def oauth_token(options = {})
|
50
|
+
query = options.merge(
|
51
|
+
client_id: client_id || raise(ArgumentError, 'Missing Strava client id.'),
|
52
|
+
client_secret: client_secret || raise(ArgumentError, 'Missing Strava client secret.'),
|
53
|
+
grant_type: options[:grant_type] || 'authorization_code'
|
54
|
+
)
|
55
|
+
|
56
|
+
Strava::Models::Token.new(post('token', query))
|
57
|
+
end
|
58
|
+
|
59
|
+
class << self
|
60
|
+
def configure
|
61
|
+
block_given? ? yield(Config) : Config
|
62
|
+
end
|
63
|
+
|
64
|
+
def config
|
65
|
+
Config
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Strava
|
2
|
+
module OAuth
|
3
|
+
module Config
|
4
|
+
extend self
|
5
|
+
|
6
|
+
ATTRIBUTES = %i[
|
7
|
+
endpoint
|
8
|
+
client_id
|
9
|
+
client_secret
|
10
|
+
].freeze
|
11
|
+
|
12
|
+
attr_accessor(*Config::ATTRIBUTES)
|
13
|
+
|
14
|
+
def reset
|
15
|
+
self.endpoint = 'https://www.strava.com/oauth'
|
16
|
+
self.client_id = nil
|
17
|
+
self.client_secret = nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def configure
|
23
|
+
block_given? ? yield(Config) : Config
|
24
|
+
end
|
25
|
+
|
26
|
+
def config
|
27
|
+
Config
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Strava::OAuth::Config.reset
|