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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/README.md +710 -88
  4. data/bin/strava-webhooks.rb +56 -0
  5. data/lib/strava-ruby-client.rb +37 -0
  6. data/lib/strava/api/client.rb +11 -141
  7. data/lib/strava/api/endpoints/activities.rb +120 -0
  8. data/lib/strava/api/endpoints/athletes.rb +42 -0
  9. data/lib/strava/api/endpoints/clubs.rb +75 -0
  10. data/lib/strava/api/endpoints/gears.rb +18 -0
  11. data/lib/strava/api/endpoints/routes.rb +55 -0
  12. data/lib/strava/api/endpoints/running_races.rb +30 -0
  13. data/lib/strava/api/endpoints/segment_efforts.rb +33 -0
  14. data/lib/strava/api/endpoints/segments.rb +111 -0
  15. data/lib/strava/api/endpoints/streams.rb +61 -0
  16. data/lib/strava/api/endpoints/uploads.rb +40 -0
  17. data/lib/strava/logger.rb +1 -1
  18. data/lib/strava/models/achievement.rb +9 -0
  19. data/lib/strava/models/activity.rb +11 -5
  20. data/lib/strava/models/activity_stats.rb +17 -0
  21. data/lib/strava/models/activity_total.rb +17 -0
  22. data/lib/strava/models/athlete.rb +10 -0
  23. data/lib/strava/models/club.rb +6 -0
  24. data/lib/strava/models/club_admin.rb +13 -0
  25. data/lib/strava/models/club_member.rb +16 -0
  26. data/lib/strava/models/explorer_segment.rb +19 -0
  27. data/lib/strava/models/gear.rb +5 -0
  28. data/lib/strava/models/heart_rate_zone_ranges.rb +8 -0
  29. data/lib/strava/models/kudoser.rb +10 -0
  30. data/lib/strava/models/lap.rb +3 -0
  31. data/lib/strava/models/mixins/distance.rb +18 -0
  32. data/lib/strava/models/power_zone_ranges.rb +7 -0
  33. data/lib/strava/models/route.rb +27 -0
  34. data/lib/strava/models/running_race.rb +33 -0
  35. data/lib/strava/models/segment.rb +15 -3
  36. data/lib/strava/models/segment_effort.rb +7 -2
  37. data/lib/strava/models/segment_leaderboard.rb +10 -0
  38. data/lib/strava/models/segment_leaderboard_entry.rb +12 -0
  39. data/lib/strava/models/segment_stats.rb +15 -0
  40. data/lib/strava/models/stream.rb +10 -0
  41. data/lib/strava/models/stream_set.rb +17 -0
  42. data/lib/strava/models/upload.rb +11 -0
  43. data/lib/strava/models/zone_range.rb +8 -0
  44. data/lib/strava/models/zones.rb +8 -0
  45. data/lib/strava/version.rb +1 -1
  46. data/lib/strava/web/client.rb +11 -1
  47. data/lib/strava/web/connection.rb +1 -1
  48. data/lib/strava/webhooks/client.rb +58 -0
  49. data/lib/strava/webhooks/config.rb +33 -0
  50. data/lib/strava/webhooks/models/challenge.rb +15 -0
  51. data/lib/strava/webhooks/models/event.rb +15 -0
  52. data/lib/strava/webhooks/models/subscription.rb +14 -0
  53. 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
@@ -2,7 +2,7 @@ require 'logger'
2
2
 
3
3
  module Strava
4
4
  class Logger < ::Logger
5
- def self.default
5
+ def self.logger
6
6
  @logger ||= begin
7
7
  logger = new STDOUT
8
8
  logger.level = Logger::WARN
@@ -0,0 +1,9 @@
1
+ module Strava
2
+ module Models
3
+ class Achievement < Model
4
+ property 'rank'
5
+ property 'type'
6
+ property 'type_id'
7
+ end
8
+ end
9
+ end
@@ -1,7 +1,7 @@
1
1
  module Strava
2
2
  module Models
3
3
  class Activity < Model
4
- include Mixins::Distance
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
- def units
70
- :metric
71
- end
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