strava-api-v2 0.1
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.
- data/.gitignore +18 -0
- data/.rvmrc +60 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +100 -0
- data/Rakefile +9 -0
- data/lib/strava/base_connection.rb +29 -0
- data/lib/strava/exceptions.rb +7 -0
- data/lib/strava/strava_response.rb +5 -0
- data/lib/strava/v1/clubs_request.rb +20 -0
- data/lib/strava/v1/connection.rb +22 -0
- data/lib/strava/v1/models/athlete.rb +15 -0
- data/lib/strava/v1/models/club.rb +14 -0
- data/lib/strava/v1/models/effort.rb +17 -0
- data/lib/strava/v1/models/ride.rb +23 -0
- data/lib/strava/v1/models/segment.rb +19 -0
- data/lib/strava/v1/models/stream.rb +17 -0
- data/lib/strava/v1/rides_request.rb +60 -0
- data/lib/strava/v1/segments_request.rb +31 -0
- data/lib/strava/v1/streams_request.rb +15 -0
- data/lib/strava/v2/auth_request.rb +17 -0
- data/lib/strava/v2/connection.rb +27 -0
- data/lib/strava/v2/efforts_request.rb +21 -0
- data/lib/strava/v2/models/athlete.rb +15 -0
- data/lib/strava/v2/models/auth.rb +15 -0
- data/lib/strava/v2/models/effort.rb +19 -0
- data/lib/strava/v2/models/segment.rb +26 -0
- data/lib/strava/v2/segments_request.rb +21 -0
- data/lib/strava/version.rb +3 -0
- data/strava-api-v2.gemspec +26 -0
- data/test/auth_test.rb +32 -0
- data/test/clubs_test.rb +31 -0
- data/test/efforts_v2_test.rb +34 -0
- data/test/rides_v1_test.rb +62 -0
- data/test/segments_v1_request_test.rb +39 -0
- data/test/segments_v2_request_test.rb +47 -0
- data/test/stream_test.rb +30 -0
- data/test/test_data.rb +52 -0
- data/test/v1_connection_test.rb +37 -0
- data/test/v2_connection_test.rb +37 -0
- metadata +190 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'strava/v1/models/segment'
|
2
|
+
|
3
|
+
module Strava
|
4
|
+
module V1
|
5
|
+
module SegmentRequest
|
6
|
+
SEGMENT_PARAMS_MAP = {
|
7
|
+
:club_id => :clubId,
|
8
|
+
:athlete_id => :athleteId,
|
9
|
+
:athlete_name => :athleteName,
|
10
|
+
:start_date => :startDate,
|
11
|
+
:end_date => :endDate,
|
12
|
+
:start_id => :startId,
|
13
|
+
:best => :best
|
14
|
+
}
|
15
|
+
|
16
|
+
def efforts_for_segment_path(id)
|
17
|
+
"segments/#{id}/efforts"
|
18
|
+
end
|
19
|
+
|
20
|
+
def segment_with_efforts(id, params = {})
|
21
|
+
final_params = {}
|
22
|
+
params.each_pair do |key, value|
|
23
|
+
raise RequestError.new if SEGMENT_PARAMS_MAP[key].nil?
|
24
|
+
final_params[SEGMENT_PARAMS_MAP[key]] = value
|
25
|
+
end
|
26
|
+
all_json = self.fetch(efforts_for_segment_path(id), final_params)
|
27
|
+
Segment.new(all_json["segment"], all_json["efforts"])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'strava/v2/models/auth'
|
2
|
+
|
3
|
+
module Strava
|
4
|
+
module V2
|
5
|
+
module AuthRequest
|
6
|
+
def login_path
|
7
|
+
'authentication/login'
|
8
|
+
end
|
9
|
+
|
10
|
+
def login(email, password)
|
11
|
+
auth = Auth.new(self.fetch(login_path(), {:email => email, :password => password}))
|
12
|
+
self.set_authorized_user(auth.athlete.id, auth.token)
|
13
|
+
return auth
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'strava/base_connection'
|
3
|
+
require 'strava/exceptions'
|
4
|
+
require 'strava/v2/auth_request'
|
5
|
+
require 'strava/v2/efforts_request'
|
6
|
+
require 'strava/v2/segments_request'
|
7
|
+
|
8
|
+
module Strava
|
9
|
+
module V2
|
10
|
+
class Connection
|
11
|
+
include HTTParty
|
12
|
+
include Strava::BaseConnection
|
13
|
+
include Strava::V2::AuthRequest
|
14
|
+
include Strava::V2::EffortsRequest
|
15
|
+
include Strava::V2::SegmentsRequest
|
16
|
+
|
17
|
+
attr_reader :user_id, :token
|
18
|
+
base_uri 'http://www.strava.com/api/v2'
|
19
|
+
format :json
|
20
|
+
|
21
|
+
def set_authorized_user(user_id, token)
|
22
|
+
@user_id = user_id
|
23
|
+
@token = token
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'strava/v2/models/effort'
|
2
|
+
|
3
|
+
module Strava
|
4
|
+
module V2
|
5
|
+
module EffortsRequest
|
6
|
+
def efforts_path(id)
|
7
|
+
"rides/#{id}/efforts"
|
8
|
+
end
|
9
|
+
|
10
|
+
def segments_for_ride(ride_id)
|
11
|
+
all_json = self.fetch(efforts_path(ride_id), {})
|
12
|
+
|
13
|
+
all_segments = []
|
14
|
+
all_json["efforts"].each { |effort_json|
|
15
|
+
all_segments.push(Segment.new(effort_json["segment"], [effort_json["effort"]]))
|
16
|
+
}
|
17
|
+
all_segments
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'strava/strava_response'
|
2
|
+
|
3
|
+
module Strava
|
4
|
+
module V2
|
5
|
+
class Athlete < StravaResponse
|
6
|
+
attr_reader :id, :name, :agreed_to_terms
|
7
|
+
|
8
|
+
def initialize(json_blob)
|
9
|
+
@id = json_blob["id"]
|
10
|
+
@name = json_blob["name"]
|
11
|
+
@agreed_to_terms = json_blob["agreed_to_terms"]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'strava/strava_response'
|
2
|
+
require 'strava/v2/models/athlete'
|
3
|
+
|
4
|
+
module Strava
|
5
|
+
module V2
|
6
|
+
class Auth < StravaResponse
|
7
|
+
attr_reader :token, :athlete
|
8
|
+
|
9
|
+
def initialize(json_blob)
|
10
|
+
@token = json_blob["token"]
|
11
|
+
@athlete = Athlete.new(json_blob["athlete"])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'strava/strava_response'
|
2
|
+
require 'strava/v2/models/segment'
|
3
|
+
|
4
|
+
module Strava
|
5
|
+
module V2
|
6
|
+
class Effort < StravaResponse
|
7
|
+
attr_reader :id, :elapsed_time, :moving_time, :distance
|
8
|
+
|
9
|
+
# Initialize the Effort
|
10
|
+
# ejs - the effort JSON
|
11
|
+
def initialize(ejs)
|
12
|
+
@id = ejs["id"]
|
13
|
+
@elapsed_time = ejs["elapsed_time"]
|
14
|
+
@moving_time = ejs["moving_time"]
|
15
|
+
@distance = ejs["distance"]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'strava/strava_response'
|
2
|
+
require 'strava/v2/models/effort'
|
3
|
+
|
4
|
+
module Strava
|
5
|
+
module V2
|
6
|
+
class Segment < StravaResponse
|
7
|
+
attr_reader :id, :efforts, :name, :climb_category, :start_latlng, :end_latlng, :average_grade
|
8
|
+
|
9
|
+
# include the efforts in the segment, if applicable
|
10
|
+
# jb - the json for the segment
|
11
|
+
# ejb - the json for the efforts, in a list
|
12
|
+
def initialize(jb, ejb)
|
13
|
+
@id = jb["id"]
|
14
|
+
@name = jb["name"]
|
15
|
+
@climb_category = jb["climb_category"]
|
16
|
+
@start_latlng = jb["start_latlng"]
|
17
|
+
@end_latlng = jb["end_latlng"]
|
18
|
+
@average_grade = jb["avg_grade"]
|
19
|
+
@efforts = []
|
20
|
+
ejb.each { |effort_json|
|
21
|
+
@efforts.push(Effort.new(effort_json))
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'strava/v2/models/segment'
|
2
|
+
|
3
|
+
module Strava
|
4
|
+
module V2
|
5
|
+
module SegmentsRequest
|
6
|
+
def segments_and_efforts_for_ride_path(ride_id)
|
7
|
+
"rides/#{ride_id}/efforts"
|
8
|
+
end
|
9
|
+
|
10
|
+
def segments_and_efforts_for_ride(ride_id)
|
11
|
+
all_json = self.fetch(segments_and_efforts_for_ride_path(ride_id), {})
|
12
|
+
all_segments = []
|
13
|
+
all_json["efforts"].each { |effort_json|
|
14
|
+
all_segments.push(Segment.new(effort_json["segment"], [effort_json["effort"]]))
|
15
|
+
}
|
16
|
+
all_segments
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'strava/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "strava-api-v2"
|
8
|
+
spec.version = Strava::VERSION
|
9
|
+
spec.authors = ["Luke StClair"]
|
10
|
+
spec.email = ["secureboot@gmail.com"]
|
11
|
+
spec.description = %q{API to access strava API, v2}
|
12
|
+
spec.summary = %q{Provides access to the strava v1 and v2 apis, which are soon to be deprecated}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "test-unit"
|
24
|
+
spec.add_development_dependency "httparty"
|
25
|
+
spec.add_development_dependency "mocha"
|
26
|
+
end
|
data/test/auth_test.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'mocha/setup'
|
3
|
+
require 'strava/v2/connection'
|
4
|
+
require 'strava/exceptions'
|
5
|
+
require 'strava/v2/models/athlete'
|
6
|
+
require 'json'
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
|
8
|
+
require 'test_data'
|
9
|
+
|
10
|
+
class AuthTest < Test::Unit::TestCase
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@s = Strava::V2::Connection.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_successful_auth
|
17
|
+
email = 'secureboot@gmail.com'
|
18
|
+
password = 'notatallreal'
|
19
|
+
|
20
|
+
Strava::V2::Connection.stubs(:get)
|
21
|
+
.with("/#{@s.login_path}", {:query => {:email => email, :password => password}})
|
22
|
+
.returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_login)))
|
23
|
+
result = @s.login(email, password)
|
24
|
+
assert_equal("thetoken", result.token)
|
25
|
+
# make sure the athlete parses out okay.
|
26
|
+
assert result.athlete.is_a?(Strava::V2::Athlete)
|
27
|
+
|
28
|
+
# be sure the auth for the connection gets set
|
29
|
+
assert_equal(7976, @s.user_id)
|
30
|
+
assert_equal("thetoken", @s.token)
|
31
|
+
end
|
32
|
+
end
|
data/test/clubs_test.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'mocha/setup'
|
3
|
+
require 'strava/v1/connection'
|
4
|
+
require 'strava/exceptions'
|
5
|
+
require 'strava/v1/models/club'
|
6
|
+
require 'json'
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
|
8
|
+
require 'test_data'
|
9
|
+
|
10
|
+
class ClubsTest < Test::Unit::TestCase
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@s = Strava::V1::Connection.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_clubs
|
17
|
+
club_name = "mission"
|
18
|
+
|
19
|
+
Strava::V1::Connection.stubs(:get)
|
20
|
+
.with("/clubs", {:query => {:name => club_name}})
|
21
|
+
.returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_clubs)))
|
22
|
+
|
23
|
+
clubs = @s.clubs(club_name)
|
24
|
+
|
25
|
+
assert clubs[0].is_a?(Strava::V1::Club)
|
26
|
+
assert_equal(11, clubs.length)
|
27
|
+
first = clubs[0]
|
28
|
+
assert_equal("Mission Cycling", first.name)
|
29
|
+
assert_equal(15, first.id)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'mocha/setup'
|
3
|
+
require 'strava/v2/connection'
|
4
|
+
require 'strava/exceptions'
|
5
|
+
require 'strava/v2/models/athlete'
|
6
|
+
require 'json'
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
|
8
|
+
require 'test_data'
|
9
|
+
|
10
|
+
class EffortsV2Test < Test::Unit::TestCase
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@s = Strava::V2::Connection.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_get_efforts_for_ride
|
17
|
+
ride_id = 448459
|
18
|
+
Strava::V2::Connection.stubs(:get)
|
19
|
+
.with("/rides/#{ride_id}/efforts", {:query => {}})
|
20
|
+
.returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_v2_efforts)))
|
21
|
+
segments = @s.segments_for_ride(ride_id)
|
22
|
+
effort = segments[0].efforts[0]
|
23
|
+
assert effort.is_a?(Strava::V2::Effort)
|
24
|
+
assert_equal(45665444, effort.id)
|
25
|
+
assert_equal(12, segments.length)
|
26
|
+
assert_equal(634, effort.elapsed_time)
|
27
|
+
assert_equal(634, effort.moving_time)
|
28
|
+
assert_equal(5342.8, effort.distance)
|
29
|
+
assert_equal(852034, segments[0].id)
|
30
|
+
assert_equal(1, segments[0].climb_category)
|
31
|
+
assert_equal([37.771132132038474,-122.45532101020217], segments[0].start_latlng)
|
32
|
+
assert_equal(-0.997671, segments[0].average_grade)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'mocha/setup'
|
3
|
+
require 'strava/v1/connection'
|
4
|
+
require 'strava/exceptions'
|
5
|
+
require 'strava/v1/models/athlete'
|
6
|
+
require 'json'
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
|
8
|
+
require 'test_data'
|
9
|
+
|
10
|
+
class RidesV1Test < Test::Unit::TestCase
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@s = Strava::V1::Connection.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_rides_with_no_params
|
17
|
+
Strava::V1::Connection.stubs(:get)
|
18
|
+
.with("/#{@s.rides_path}", {:query => {}})
|
19
|
+
.returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_rides_no_params)))
|
20
|
+
result = @s.rides()
|
21
|
+
assert_equal(50, result.length)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_rides_with_invalid_param
|
25
|
+
assert_raise Strava::RequestError do
|
26
|
+
@s.rides({:made_up => "whatever"})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_rides_with_two_valid_params
|
31
|
+
Strava::V1::Connection.stubs(:get)
|
32
|
+
.with("/#{@s.rides_path}", {:query => {:startId => 77563, :offset => 50}})
|
33
|
+
.returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_ride_start_id_and_offset)))
|
34
|
+
rides = @s.rides({:start_id => 77563, :offset => 50})
|
35
|
+
|
36
|
+
assert_equal(52127040, rides[0].id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_getting_efforts_for_a_ride
|
40
|
+
ride_id = 77563
|
41
|
+
Strava::V1::Connection.stubs(:get)
|
42
|
+
.with("/rides/#{ride_id}/efforts", {:query => {}})
|
43
|
+
.returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_efforts)))
|
44
|
+
ride = @s.ride_with_efforts(ride_id)
|
45
|
+
assert_equal(ride_id, ride.id)
|
46
|
+
assert_equal(5819602, ride.segments[0].efforts[0].id)
|
47
|
+
assert_equal(640366, ride.segments[0].id)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_show_ride_details
|
51
|
+
ride_id = 77563
|
52
|
+
Strava::V1::Connection.stubs(:get)
|
53
|
+
.with("/rides/#{ride_id}", {:query => {}})
|
54
|
+
.returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_show_ride_deets)))
|
55
|
+
ride = @s.ride(ride_id)
|
56
|
+
assert_equal(82369.1, ride.distance)
|
57
|
+
assert_equal(1441.02, ride.elevation_gain)
|
58
|
+
assert_equal("02/28/10 San Francisco, CA", ride.name)
|
59
|
+
assert_equal("julianbill", ride.athlete.username)
|
60
|
+
assert_equal(1139, ride.athlete.id)
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'mocha/setup'
|
3
|
+
require 'strava/v1/connection'
|
4
|
+
require 'strava/v1/segments_request'
|
5
|
+
require 'strava/exceptions'
|
6
|
+
require 'json'
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
|
8
|
+
require 'test_data'
|
9
|
+
|
10
|
+
class SegmentsV1RequestTest < Test::Unit::TestCase
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@s = Strava::V1::Connection.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_get_efforts_for_segment
|
17
|
+
segment_id = 229781
|
18
|
+
|
19
|
+
Strava::V1::Connection.stubs(:get)
|
20
|
+
.with("/segments/#{segment_id}/efforts", {:query => {:best => true}})
|
21
|
+
.returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_v1_segment_efforts)))
|
22
|
+
segment = @s.segment_with_efforts(segment_id, {:best => true})
|
23
|
+
assert segment.is_a?(Strava::V1::Segment)
|
24
|
+
assert segment.efforts[0].is_a?(Strava::V1::Effort)
|
25
|
+
assert_equal(segment_id, segment.id)
|
26
|
+
assert_equal(50, segment.efforts.length)
|
27
|
+
first = segment.efforts[0]
|
28
|
+
assert_equal(801006623, first.id)
|
29
|
+
assert_equal(123529, first.athlete.id)
|
30
|
+
assert_equal("jimwhimpey", first.athlete.username)
|
31
|
+
assert_equal("Jim Whimpey", first.athlete.name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_segment_with_bad_param
|
35
|
+
assert_raise Strava::RequestError do
|
36
|
+
@s.segment_with_efforts(12345, {:made_up => "whatever"})
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|