strava-ruby-client 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +710 -88
- data/bin/strava-webhooks.rb +56 -0
- data/lib/strava-ruby-client.rb +37 -0
- data/lib/strava/api/client.rb +11 -141
- data/lib/strava/api/endpoints/activities.rb +120 -0
- data/lib/strava/api/endpoints/athletes.rb +42 -0
- data/lib/strava/api/endpoints/clubs.rb +75 -0
- data/lib/strava/api/endpoints/gears.rb +18 -0
- data/lib/strava/api/endpoints/routes.rb +55 -0
- data/lib/strava/api/endpoints/running_races.rb +30 -0
- data/lib/strava/api/endpoints/segment_efforts.rb +33 -0
- data/lib/strava/api/endpoints/segments.rb +111 -0
- data/lib/strava/api/endpoints/streams.rb +61 -0
- data/lib/strava/api/endpoints/uploads.rb +40 -0
- data/lib/strava/logger.rb +1 -1
- data/lib/strava/models/achievement.rb +9 -0
- data/lib/strava/models/activity.rb +11 -5
- data/lib/strava/models/activity_stats.rb +17 -0
- data/lib/strava/models/activity_total.rb +17 -0
- data/lib/strava/models/athlete.rb +10 -0
- data/lib/strava/models/club.rb +6 -0
- data/lib/strava/models/club_admin.rb +13 -0
- data/lib/strava/models/club_member.rb +16 -0
- data/lib/strava/models/explorer_segment.rb +19 -0
- data/lib/strava/models/gear.rb +5 -0
- data/lib/strava/models/heart_rate_zone_ranges.rb +8 -0
- data/lib/strava/models/kudoser.rb +10 -0
- data/lib/strava/models/lap.rb +3 -0
- data/lib/strava/models/mixins/distance.rb +18 -0
- data/lib/strava/models/power_zone_ranges.rb +7 -0
- data/lib/strava/models/route.rb +27 -0
- data/lib/strava/models/running_race.rb +33 -0
- data/lib/strava/models/segment.rb +15 -3
- data/lib/strava/models/segment_effort.rb +7 -2
- data/lib/strava/models/segment_leaderboard.rb +10 -0
- data/lib/strava/models/segment_leaderboard_entry.rb +12 -0
- data/lib/strava/models/segment_stats.rb +15 -0
- data/lib/strava/models/stream.rb +10 -0
- data/lib/strava/models/stream_set.rb +17 -0
- data/lib/strava/models/upload.rb +11 -0
- data/lib/strava/models/zone_range.rb +8 -0
- data/lib/strava/models/zones.rb +8 -0
- data/lib/strava/version.rb +1 -1
- data/lib/strava/web/client.rb +11 -1
- data/lib/strava/web/connection.rb +1 -1
- data/lib/strava/webhooks/client.rb +58 -0
- data/lib/strava/webhooks/config.rb +33 -0
- data/lib/strava/webhooks/models/challenge.rb +15 -0
- data/lib/strava/webhooks/models/event.rb +15 -0
- data/lib/strava/webhooks/models/subscription.rb +14 -0
- metadata +37 -2
@@ -0,0 +1,18 @@
|
|
1
|
+
module Strava
|
2
|
+
module Api
|
3
|
+
module Endpoints
|
4
|
+
module Gears
|
5
|
+
#
|
6
|
+
# Returns an equipment using its identifier.
|
7
|
+
#
|
8
|
+
# @option options [String] :id
|
9
|
+
# Gear id.
|
10
|
+
#
|
11
|
+
def gear(id_or_options, options = {})
|
12
|
+
id, options = parse_args(id_or_options, options)
|
13
|
+
Strava::Models::Gear.new(get("gear/#{id}", options))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Strava
|
2
|
+
module Api
|
3
|
+
module Endpoints
|
4
|
+
module Routes
|
5
|
+
#
|
6
|
+
# Returns a GPX file of the route.
|
7
|
+
#
|
8
|
+
# @option options [String] :id
|
9
|
+
# Route id.
|
10
|
+
#
|
11
|
+
def export_route_gpx(id_or_options, options = {})
|
12
|
+
id, options = parse_args(id_or_options, options)
|
13
|
+
get "routes/#{id}/export_gpx", options
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Returns a TCS file of the route.
|
18
|
+
#
|
19
|
+
# @option options [String] :id
|
20
|
+
# Route id.
|
21
|
+
#
|
22
|
+
def export_route_tcx(id_or_options, options = {})
|
23
|
+
id, options = parse_args(id_or_options, options)
|
24
|
+
get "routes/#{id}/export_tcx", options
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Returns a route using its identifier.
|
29
|
+
#
|
30
|
+
# @option options [String] :id
|
31
|
+
# Route id.
|
32
|
+
#
|
33
|
+
def route(id_or_options, options = {})
|
34
|
+
id, options = parse_args(id_or_options, options)
|
35
|
+
Strava::Models::Route.new(get("routes/#{id}", options))
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Returns a list of the routes created by the authenticated athlete using their athlete ID.
|
40
|
+
#
|
41
|
+
# @option options [Integer] :id
|
42
|
+
# The identifier of the athlete.
|
43
|
+
# @option options [Integer] :page
|
44
|
+
# Page number.
|
45
|
+
# @option options [Integer] :per_page
|
46
|
+
# Number of items per page. Defaults to 30.
|
47
|
+
#
|
48
|
+
def athlete_routes(id_or_options, options = {}, &block)
|
49
|
+
id, options = parse_args(id_or_options, options)
|
50
|
+
paginate "athletes/#{id}/routes", options, Strava::Models::Route, &block
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Strava
|
2
|
+
module Api
|
3
|
+
module Endpoints
|
4
|
+
module RunningRaces
|
5
|
+
#
|
6
|
+
# Returns a running race for a given identifier.
|
7
|
+
#
|
8
|
+
# @option options [String] :id
|
9
|
+
# The identifier of the running race.
|
10
|
+
#
|
11
|
+
def running_race(id_or_options, options = {})
|
12
|
+
id, options = parse_args(id_or_options, options)
|
13
|
+
Strava::Models::RunningRace.new(get("running_races/#{id}", options))
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Returns a list running races based on a set of search criteria.
|
18
|
+
#
|
19
|
+
# @option options [Integer] :year
|
20
|
+
# Filters the list by a given year.
|
21
|
+
#
|
22
|
+
def running_races(options = {})
|
23
|
+
get('running_races', options).map do |row|
|
24
|
+
Strava::Models::RunningRace.new(row)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Strava
|
2
|
+
module Api
|
3
|
+
module Endpoints
|
4
|
+
module SegmentEfforts
|
5
|
+
#
|
6
|
+
# Returns a segment effort from an activity that is owned by the authenticated athlete.
|
7
|
+
#
|
8
|
+
# @option options [String] :id
|
9
|
+
# The identifier of the segment effort.
|
10
|
+
#
|
11
|
+
def segment_effort(id_or_options, options = {})
|
12
|
+
id, options = parse_args(id_or_options, options)
|
13
|
+
Strava::Models::SegmentEffort.new(get("segment_efforts/#{id}", options))
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Returns a set of the authenticated athlete's segment efforts for a given segment.
|
18
|
+
#
|
19
|
+
# @option options [Integer] :id
|
20
|
+
# The identifier of the segment.
|
21
|
+
# @option options [Integer] :page
|
22
|
+
# Page number.
|
23
|
+
# @option options [Integer] :per_page
|
24
|
+
# Number of items per page. Defaults to 30.
|
25
|
+
#
|
26
|
+
def segment_efforts(id_or_options, options = {}, &block)
|
27
|
+
id, options = parse_args(id_or_options, options)
|
28
|
+
paginate "segments/#{id}/all_efforts", options, Strava::Models::SegmentEffort, &block
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Strava
|
2
|
+
module Api
|
3
|
+
module Endpoints
|
4
|
+
module Segments
|
5
|
+
#
|
6
|
+
# Returns the top 10 segments matching a specified query.
|
7
|
+
#
|
8
|
+
# @option options [Array[Float]] :bounds
|
9
|
+
# The latitude and longitude for two points describing a rectangular boundary for the search: [southwest corner latitude, southwest corner longitude, northeast corner latitude, northeast corner longitude].
|
10
|
+
# @option options [String] :activity_type
|
11
|
+
# Desired activity type. May take one of the following values: running, riding.
|
12
|
+
# @option options [Integer] :min_cat
|
13
|
+
# The minimum climbing category.
|
14
|
+
# @option options [Integer] :max_cat
|
15
|
+
# The maximum climbing category.
|
16
|
+
#
|
17
|
+
def explore_segments(options = {})
|
18
|
+
throw ArgumentError.new('Required argument :bounds missing') if options[:bounds].nil?
|
19
|
+
bounds = options[:bounds]
|
20
|
+
bounds = bounds.map(&:to_s).join(',') if bounds.is_a?(Array)
|
21
|
+
get('segments/explore', options.merge(bounds: bounds))['segments'].map do |row|
|
22
|
+
Strava::Models::ExplorerSegment.new(row)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Returns the specified segment leaderboard.
|
28
|
+
#
|
29
|
+
# @option options [Integer] :id
|
30
|
+
# The identifier of the segment leaderboard.
|
31
|
+
# @option options [String] :gender
|
32
|
+
# Filter by gender.
|
33
|
+
# @option options [String] :age_group
|
34
|
+
# Filter by age group.
|
35
|
+
# @option options [String] :weight_class
|
36
|
+
# Filter by weight class.
|
37
|
+
# @option options [Boolean] :following
|
38
|
+
# Filter by friends of the authenticated athlete.
|
39
|
+
# @option options [Integer] :club_id
|
40
|
+
# Filter by club.
|
41
|
+
# @option options [String] :date_range
|
42
|
+
# Filter by date range.
|
43
|
+
# @option options [Integer] :context_entries
|
44
|
+
# ?
|
45
|
+
# @option options [Integer] :page
|
46
|
+
# Page number.
|
47
|
+
# @option options [Integer] :per_page
|
48
|
+
# Number of items per page. Defaults to 30.
|
49
|
+
#
|
50
|
+
def segment_leaderboard(id_or_options, options = {})
|
51
|
+
id, options = parse_args(id_or_options, options)
|
52
|
+
|
53
|
+
if block_given?
|
54
|
+
next_page = 1
|
55
|
+
total_count = 0
|
56
|
+
loop do
|
57
|
+
query = options.merge(page: next_page)
|
58
|
+
response = Strava::Models::SegmentLeaderboard.new(get("segments/#{id}/leaderboard", query))
|
59
|
+
total_count += response.entries.count
|
60
|
+
break unless response.entries.any?
|
61
|
+
|
62
|
+
yield response
|
63
|
+
break if total_count >= response.entry_count
|
64
|
+
|
65
|
+
next_page += 1
|
66
|
+
end
|
67
|
+
else
|
68
|
+
Strava::Models::SegmentLeaderboard.new(get("segments/#{id}/leaderboard", options))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# List of the authenticated athlete's starred segments.
|
74
|
+
#
|
75
|
+
# @option options [Integer] :page
|
76
|
+
# Page number.
|
77
|
+
# @option options [Integer] :per_page
|
78
|
+
# Number of items per page. Defaults to 30.
|
79
|
+
#
|
80
|
+
def starred_segments(options = {}, &block)
|
81
|
+
paginate 'segments/starred', options, Strava::Models::Segment, &block
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# Returns the specified segment.
|
86
|
+
#
|
87
|
+
# @option options [String] :id
|
88
|
+
# The identifier of the segment.
|
89
|
+
#
|
90
|
+
def segment(id_or_options, options = {})
|
91
|
+
id, options = parse_args(id_or_options, options)
|
92
|
+
Strava::Models::Segment.new(get("segments/#{id}", options))
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# Stars/Unstars the given segment for the authenticated athlete.
|
97
|
+
#
|
98
|
+
# @option options [String] :id
|
99
|
+
# The identifier of the segment to star.
|
100
|
+
# @option options [Boolean] :starred
|
101
|
+
# If true, star the segment; if false, unstar the segment.
|
102
|
+
#
|
103
|
+
def star_segment(id_or_options, options = {})
|
104
|
+
id, options = parse_args(id_or_options, options)
|
105
|
+
throw ArgumentError.new('Required argument :starred missing') if options[:starred].nil?
|
106
|
+
Strava::Models::Segment.new(put("segments/#{id}/starred", options))
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Strava
|
2
|
+
module Api
|
3
|
+
module Endpoints
|
4
|
+
module Streams
|
5
|
+
#
|
6
|
+
# Returns the given activity's streams.
|
7
|
+
#
|
8
|
+
# @option options [String] :id
|
9
|
+
# The identifier of the activity.
|
10
|
+
# @option options [Array[String]] :keys
|
11
|
+
# Desired stream types.
|
12
|
+
# @option options [Boolean] :key_by_type
|
13
|
+
# Must be true.
|
14
|
+
#
|
15
|
+
def activity_streams(id_or_options, options = {})
|
16
|
+
id, options = parse_args(id_or_options, options)
|
17
|
+
query = options.dup
|
18
|
+
query[:key_by_type] = true unless options.key?(:key_by_type)
|
19
|
+
query[:keys] = options[:keys].join(',') if options[:keys] && options[:keys].is_a?(Array)
|
20
|
+
Strava::Models::StreamSet.new(get("activities/#{id}/streams", query))
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Returns a set of streams for a segment effort completed by the authenticated athlete.
|
25
|
+
#
|
26
|
+
# @option options [String] :id
|
27
|
+
# The identifier of the segment effort.
|
28
|
+
# @option options [Array[String]] :keys
|
29
|
+
# The types of streams to return.
|
30
|
+
# @option options [Boolean] :key_by_type
|
31
|
+
# Must be true.
|
32
|
+
#
|
33
|
+
def segment_effort_streams(id_or_options, options = {})
|
34
|
+
id, options = parse_args(id_or_options, options)
|
35
|
+
query = options.dup
|
36
|
+
query[:key_by_type] = true unless options.key?(:key_by_type)
|
37
|
+
query[:keys] = options[:keys].join(',') if options[:keys] && options[:keys].is_a?(Array)
|
38
|
+
Strava::Models::StreamSet.new(get("segment_efforts/#{id}/streams", query))
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Returns the given segment's streams.
|
43
|
+
#
|
44
|
+
# @option options [String] :id
|
45
|
+
# The identifier of the segment.
|
46
|
+
# @option options [Array[String]] :keys
|
47
|
+
# The types of streams to return.
|
48
|
+
# @option options [Boolean] :key_by_type
|
49
|
+
# Must be true.
|
50
|
+
#
|
51
|
+
def segment_streams(id_or_options, options = {})
|
52
|
+
id, options = parse_args(id_or_options, options)
|
53
|
+
query = options.dup
|
54
|
+
query[:key_by_type] = true unless options.key?(:key_by_type)
|
55
|
+
query[:keys] = options[:keys].join(',') if options[:keys] && options[:keys].is_a?(Array)
|
56
|
+
Strava::Models::StreamSet.new(get("segments/#{id}/streams", query))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Strava
|
2
|
+
module Api
|
3
|
+
module Endpoints
|
4
|
+
module Uploads
|
5
|
+
#
|
6
|
+
# Uploads a new data file to create an activity from.
|
7
|
+
#
|
8
|
+
# @option options [File] :file
|
9
|
+
# The uploaded file.
|
10
|
+
# @option options [String] :name
|
11
|
+
# The desired name of the resulting activity.
|
12
|
+
# @option options [String] :description
|
13
|
+
# The desired description of the resulting activity.
|
14
|
+
# @option options [Boolean] :trainer
|
15
|
+
# Whether the resulting activity should be marked as having been performed on a trainer.
|
16
|
+
# @option options [Boolean] :commute
|
17
|
+
# Whether the resulting activity should be tagged as a commute.
|
18
|
+
# @option options [String] :data_type
|
19
|
+
# The format of the uploaded file.
|
20
|
+
# @option options [String] :external_id
|
21
|
+
# The desired external identifier of the resulting activity.
|
22
|
+
#
|
23
|
+
def create_upload(options = {})
|
24
|
+
Strava::Models::Upload.new(post('uploads', options))
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Returns an upload for a given identifier.
|
29
|
+
#
|
30
|
+
# @option options [String] :id
|
31
|
+
# The identifier of the upload.
|
32
|
+
#
|
33
|
+
def upload(id_or_options, options = {})
|
34
|
+
id, options = parse_args(id_or_options, options)
|
35
|
+
Strava::Models::Upload.new(get("uploads/#{id}", options))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/strava/logger.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Strava
|
2
2
|
module Models
|
3
3
|
class Activity < Model
|
4
|
-
include Mixins::
|
4
|
+
include Mixins::MetricDistance
|
5
5
|
include Mixins::Time
|
6
6
|
include Mixins::Elevation
|
7
7
|
|
@@ -65,10 +65,16 @@ module Strava
|
|
65
65
|
property 'laps', transform_with: ->(v) { v.map { |r| Strava::Models::Lap.new(r) } }
|
66
66
|
property 'gear', transform_with: ->(v) { Strava::Models::Gear.new(v) }
|
67
67
|
property 'device_name'
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
property 'average_cadence'
|
69
|
+
property 'average_temp'
|
70
|
+
property 'average_watts'
|
71
|
+
property 'weighted_average_watts'
|
72
|
+
property 'kilojoules'
|
73
|
+
property 'device_watts'
|
74
|
+
property 'max_watts'
|
75
|
+
property 'highlighted_kudosers', transform_with: ->(v) { v.map { |r| Strava::Models::Kudoser.new(r) } }
|
76
|
+
property 'segment_leaderboard_opt_out'
|
77
|
+
property 'leaderboard_opt_out'
|
72
78
|
|
73
79
|
def distance_s
|
74
80
|
if type == 'Swim'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Strava
|
2
|
+
module Models
|
3
|
+
class ActivityStats < Model
|
4
|
+
property 'biggest_ride_distance'
|
5
|
+
property 'biggest_climb_elevation_gain'
|
6
|
+
property 'recent_ride_totals', transform_with: ->(v) { Strava::Models::ActivityTotal.new(v) }
|
7
|
+
property 'recent_run_totals', transform_with: ->(v) { Strava::Models::ActivityTotal.new(v) }
|
8
|
+
property 'recent_swim_totals', transform_with: ->(v) { Strava::Models::ActivityTotal.new(v) }
|
9
|
+
property 'ytd_ride_totals', transform_with: ->(v) { Strava::Models::ActivityTotal.new(v) }
|
10
|
+
property 'ytd_run_totals', transform_with: ->(v) { Strava::Models::ActivityTotal.new(v) }
|
11
|
+
property 'ytd_swim_totals', transform_with: ->(v) { Strava::Models::ActivityTotal.new(v) }
|
12
|
+
property 'all_ride_totals', transform_with: ->(v) { Strava::Models::ActivityTotal.new(v) }
|
13
|
+
property 'all_run_totals', transform_with: ->(v) { Strava::Models::ActivityTotal.new(v) }
|
14
|
+
property 'all_swim_totals', transform_with: ->(v) { Strava::Models::ActivityTotal.new(v) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Strava
|
2
|
+
module Models
|
3
|
+
class ActivityTotal < Model
|
4
|
+
include Mixins::MetricDistance
|
5
|
+
include Mixins::Time
|
6
|
+
include Mixins::Elevation
|
7
|
+
|
8
|
+
property 'count'
|
9
|
+
property 'achievement_count'
|
10
|
+
property 'elevation_gain'
|
11
|
+
|
12
|
+
def total_elevation_gain
|
13
|
+
elevation_gain
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -20,6 +20,16 @@ module Strava
|
|
20
20
|
property 'follower'
|
21
21
|
property 'friend'
|
22
22
|
property 'summit'
|
23
|
+
property 'follower_count'
|
24
|
+
property 'friend_count'
|
25
|
+
property 'mutual_friend_count'
|
26
|
+
property 'athlete_type'
|
27
|
+
property 'date_preference'
|
28
|
+
property 'measurement_preference'
|
29
|
+
property 'clubs', transform_with: ->(v) { v.map { |r| Strava::Models::Club.new(r) } }
|
30
|
+
property 'weight'
|
31
|
+
property 'bikes', transform_with: ->(v) { v.map { |r| Strava::Models::Gear.new(r) } }
|
32
|
+
property 'shoes', transform_with: ->(v) { v.map { |r| Strava::Models::Gear.new(r) } }
|
23
33
|
|
24
34
|
def name
|
25
35
|
[firstname, lastname].compact.join(' ') if firstname || lastname
|