strava-ruby-client 0.2.0 → 0.3.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.
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
@@ -17,6 +17,12 @@ module Strava
17
17
  property 'featured'
18
18
  property 'verified'
19
19
  property 'url'
20
+ property 'membership'
21
+ property 'admin'
22
+ property 'owner'
23
+ property 'description'
24
+ property 'club_type'
25
+ property 'following_count'
20
26
 
21
27
  def strava_url
22
28
  "https://www.strava.com/clubs/#{url || id}"
@@ -0,0 +1,13 @@
1
+ module Strava
2
+ module Models
3
+ class ClubAdmin < Model
4
+ property 'resource_state'
5
+ property 'firstname'
6
+ property 'lastname'
7
+
8
+ def name
9
+ [firstname, lastname].compact.join(' ') if firstname || lastname
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ module Strava
2
+ module Models
3
+ class ClubMember < Model
4
+ property 'resource_state'
5
+ property 'firstname'
6
+ property 'lastname'
7
+ property 'owner'
8
+ property 'admin'
9
+ property 'membership'
10
+
11
+ def name
12
+ [firstname, lastname].compact.join(' ') if firstname || lastname
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module Strava
2
+ module Models
3
+ class ExplorerSegment < Model
4
+ include Mixins::MetricDistance
5
+
6
+ property 'id'
7
+ property 'resource_state'
8
+ property 'name'
9
+ property 'climb_category'
10
+ property 'climb_category_desc'
11
+ property 'avg_grade'
12
+ property 'start_latlng'
13
+ property 'end_latlng'
14
+ property 'elev_difference'
15
+ property 'points'
16
+ property 'starred'
17
+ end
18
+ end
19
+ end
@@ -1,11 +1,16 @@
1
1
  module Strava
2
2
  module Models
3
3
  class Gear < Model
4
+ include Mixins::MetricDistance
5
+
4
6
  property 'id'
5
7
  property 'resource_state'
6
8
  property 'distance'
7
9
  property 'name'
8
10
  property 'primary'
11
+ property 'brand_name'
12
+ property 'model_name'
13
+ property 'description'
9
14
  end
10
15
  end
11
16
  end
@@ -0,0 +1,8 @@
1
+ module Strava
2
+ module Models
3
+ class HeartRateZoneRanges < Model
4
+ property 'custom_zones'
5
+ property 'zones', transform_with: ->(v) { v.map { |r| Strava::Models::ZoneRange.new(r) } }
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ module Strava
2
+ module Models
3
+ class Kudoser < Model
4
+ property 'destination_url'
5
+ property 'display_name'
6
+ property 'avatar_url'
7
+ property 'show_name'
8
+ end
9
+ end
10
+ end
@@ -21,6 +21,9 @@ module Strava
21
21
  property 'lap_index'
22
22
  property 'split'
23
23
  property 'pace_zone'
24
+ property 'average_cadence'
25
+ property 'device_watts'
26
+ property 'average_watts'
24
27
  end
25
28
  end
26
29
  end
@@ -68,6 +68,24 @@ module Strava
68
68
  end
69
69
  end
70
70
  end
71
+
72
+ module MetricDistance
73
+ extend ActiveSupport::Concern
74
+ include Strava::Models::Mixins::Distance
75
+
76
+ def units
77
+ :metric
78
+ end
79
+ end
80
+
81
+ module ImperialDistance
82
+ extend ActiveSupport::Concern
83
+ include Strava::Models::Mixins::Distance
84
+
85
+ def units
86
+ :imperial
87
+ end
88
+ end
71
89
  end
72
90
  end
73
91
  end
@@ -0,0 +1,7 @@
1
+ module Strava
2
+ module Models
3
+ class PowerZoneRanges < Model
4
+ property 'zones', transform_with: ->(v) { v.map { |r| Strava::Models::ZoneRange.new(r) } }
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ module Strava
2
+ module Models
3
+ class Route < Model
4
+ include Mixins::MetricDistance
5
+ include Mixins::Elevation
6
+ include Mixins::Time
7
+
8
+ property 'id'
9
+ property 'athlete', transform_with: ->(v) { Strava::Models::Athlete.new(v) }
10
+ property 'name'
11
+ property 'description'
12
+ property 'total_elevation_gain', from: 'elevation_gain'
13
+ property 'map', transform_with: ->(v) { Strava::Models::Map.new(v) }
14
+ property 'private'
15
+ property 'resource_state'
16
+ property 'starred'
17
+ property 'sub_type'
18
+ property 'timestamp', transform_with: ->(v) { Time.at(v) }
19
+ property 'created_at', transform_with: ->(v) { Time.parse(v) }
20
+ property 'updated_at', transform_with: ->(v) { Time.parse(v) }
21
+ property 'type'
22
+ property 'estimated_moving_time'
23
+ property 'moving_time', from: 'estimated_moving_time'
24
+ property 'segments', transform_with: ->(v) { v.map { |r| Strava::Models::Segment.new(r) } }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ module Strava
2
+ module Models
3
+ class RunningRace < Model
4
+ include Mixins::MetricDistance
5
+
6
+ property 'id'
7
+ property 'resource_state'
8
+ property 'name'
9
+ property 'running_race_type'
10
+ property 'distance'
11
+ property 'start_date_local', transform_with: ->(v) { Time.parse(v) }
12
+ property 'city'
13
+ property 'state'
14
+ property 'country'
15
+ property 'route_ids'
16
+ property 'measurement_preference'
17
+ property 'url'
18
+ property 'website_url'
19
+ property 'status'
20
+
21
+ def strava_url
22
+ "https://www.strava.com/running-races/#{url}" if url
23
+ end
24
+
25
+ def distance_s
26
+ case measurement_preference
27
+ when 'meters' then distance_in_kilometers_s
28
+ when 'feet' then distance_in_miles_s
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,7 +1,9 @@
1
1
  module Strava
2
2
  module Models
3
3
  class Segment < Model
4
- include Mixins::Distance
4
+ include Mixins::MetricDistance
5
+ include Mixins::Elevation
6
+ include Mixins::Time
5
7
 
6
8
  property 'id'
7
9
  property 'resource_state'
@@ -24,9 +26,19 @@ module Strava
24
26
  property 'private'
25
27
  property 'hazardous'
26
28
  property 'starred'
29
+ property 'created_at', transform_with: ->(v) { Time.parse(v) }
30
+ property 'updated_at', transform_with: ->(v) { Time.parse(v) }
31
+ property 'map', transform_with: ->(v) { Strava::Models::Map.new(v) }
32
+ property 'effort_count'
33
+ property 'athlete_count'
34
+ property 'star_count'
35
+ property 'athlete_segment_stats', transform_with: ->(v) { Strava::Models::SegmentStats.new(v) }
36
+ property 'pr_time'
37
+ property 'athlete_pr_effort', transform_with: ->(v) { Strava::Models::SegmentEffort.new(v) }
38
+ property 'starred_date', transform_with: ->(v) { Time.parse(v) }
27
39
 
28
- def units
29
- :metric
40
+ def elapsed_time
41
+ pr_time
30
42
  end
31
43
  end
32
44
  end
@@ -1,6 +1,7 @@
1
1
  module Strava
2
2
  module Models
3
3
  class SegmentEffort < Model
4
+ include Mixins::MetricDistance
4
5
  include Mixins::Time
5
6
 
6
7
  property 'id'
@@ -10,15 +11,19 @@ module Strava
10
11
  property 'athlete', transform_with: ->(v) { Strava::Models::Athlete.new(v) }
11
12
  property 'start_date', transform_with: ->(v) { Time.parse(v) }
12
13
  property 'start_date_local', transform_with: ->(v) { Time.parse(v) }
13
- property 'distance'
14
14
  property 'start_index'
15
15
  property 'end_index'
16
16
  property 'average_heartrate'
17
17
  property 'max_heartrate'
18
18
  property 'segment', transform_with: ->(v) { Strava::Models::Segment.new(v) }
19
- property 'achievements'
19
+ property 'achievements', transform_with: ->(v) { v.map { |r| Strava::Models::Achievement.new(r) } }
20
20
  property 'hidden'
21
21
  property 'pr_rank'
22
+ property 'average_cadence'
23
+ property 'device_watts'
24
+ property 'average_watts'
25
+ property 'athlete_segment_stats', transform_with: ->(v) { Strava::Models::SegmentStats.new(v) }
26
+ property 'is_kom'
22
27
  end
23
28
  end
24
29
  end
@@ -0,0 +1,10 @@
1
+ module Strava
2
+ module Models
3
+ class SegmentLeaderboard < Model
4
+ property 'effort_count'
5
+ property 'entry_count'
6
+ property 'kom_type'
7
+ property 'entries', transform_with: ->(v) { v.map { |r| SegmentLeaderboardEntry.new(r) } }
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module Strava
2
+ module Models
3
+ class SegmentLeaderboardEntry < Model
4
+ include Mixins::Time
5
+
6
+ property 'athlete_name'
7
+ property 'start_date', transform_with: ->(v) { Time.parse(v) }
8
+ property 'start_date_local', transform_with: ->(v) { Time.parse(v) }
9
+ property 'rank'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ module Strava
2
+ module Models
3
+ class SegmentStats < Model
4
+ include Mixins::Time
5
+
6
+ property 'pr_elapsed_time'
7
+ property 'pr_date', transform_with: ->(v) { Date.parse(v) }
8
+ property 'effort_count'
9
+
10
+ def elapsed_time
11
+ pr_elapsed_time
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ module Strava
2
+ module Models
3
+ class Stream < Model
4
+ property 'original_size'
5
+ property 'resolution'
6
+ property 'series_type'
7
+ property 'data'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ module Strava
2
+ module Models
3
+ class StreamSet < Model
4
+ property 'distance', transform_with: ->(v) { Strava::Models::Stream.new(v) }
5
+ property 'time', transform_with: ->(v) { Strava::Models::Stream.new(v) }
6
+ property 'latlng', transform_with: ->(v) { Strava::Models::Stream.new(v) }
7
+ property 'altitude', transform_with: ->(v) { Strava::Models::Stream.new(v) }
8
+ property 'velocity_smooth', transform_with: ->(v) { Strava::Models::Stream.new(v) }
9
+ property 'heartrate', transform_with: ->(v) { Strava::Models::Stream.new(v) }
10
+ property 'cadence', transform_with: ->(v) { Strava::Models::Stream.new(v) }
11
+ property 'watts', transform_with: ->(v) { Strava::Models::Stream.new(v) }
12
+ property 'temp', transform_with: ->(v) { Strava::Models::Stream.new(v) }
13
+ property 'moving', transform_with: ->(v) { Strava::Models::Stream.new(v) }
14
+ property 'grade_smooth', transform_with: ->(v) { Strava::Models::Stream.new(v) }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module Strava
2
+ module Models
3
+ class Upload < Model
4
+ property 'id'
5
+ property 'external_id'
6
+ property 'error'
7
+ property 'status'
8
+ property 'activity_id'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ module Strava
2
+ module Models
3
+ class ZoneRange < Model
4
+ property 'max'
5
+ property 'min'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Strava
2
+ module Models
3
+ class Zones < Model
4
+ property 'heart_rate', transform_with: ->(v) { Strava::Models::HeartRateZoneRanges.new(v) }
5
+ property 'power', transform_with: ->(v) { Strava::Models::PowerZoneRanges.new(v) }
6
+ end
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module Strava
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
@@ -10,7 +10,7 @@ module Strava
10
10
  Strava::Web::Config::ATTRIBUTES.each do |key|
11
11
  send("#{key}=", options[key] || Strava::Web.config.send(key))
12
12
  end
13
- @logger ||= Strava::Logger.default
13
+ @logger ||= Strava::Logger.logger
14
14
  end
15
15
 
16
16
  def endpoint
@@ -26,6 +26,16 @@ module Strava
26
26
  Config
27
27
  end
28
28
  end
29
+
30
+ def parse_args(id_or_options, options = {})
31
+ if id_or_options.is_a?(Hash)
32
+ throw ArgumentError.new('Required argument :id missing') if id_or_options[:id].nil?
33
+ [id_or_options[:id], id_or_options.except(:id)]
34
+ else
35
+ throw ArgumentError.new('Required argument :id missing') if id_or_options.nil?
36
+ [id_or_options, options]
37
+ end
38
+ end
29
39
  end
30
40
  end
31
41
  end
@@ -25,7 +25,7 @@ module Strava
25
25
  connection.use ::Faraday::Request::Multipart
26
26
  connection.use ::Faraday::Request::UrlEncoded
27
27
  connection.use ::Strava::Web::Response::RaiseError
28
- connection.use ::FaradayMiddleware::ParseJson
28
+ connection.use ::FaradayMiddleware::ParseJson, content_type: /\bjson$/
29
29
  connection.response :logger, logger if logger
30
30
  connection.adapter ::Faraday.default_adapter
31
31
  end
@@ -0,0 +1,58 @@
1
+ module Strava
2
+ module Webhooks
3
+ class Client < Strava::Web::Client
4
+ attr_accessor(*Config::ATTRIBUTES)
5
+
6
+ def initialize(options = {})
7
+ Strava::Webhooks::Config::ATTRIBUTES.each do |key|
8
+ send("#{key}=", options[key] || Strava::Webhooks.config.send(key))
9
+ end
10
+ super
11
+ end
12
+
13
+ def request(method, path, options)
14
+ super method, path, { client_id: client_id, client_secret: client_secret }.merge(options)
15
+ end
16
+
17
+ #
18
+ # Get existing push subscriptions.
19
+ #
20
+ def push_subscriptions(options = {})
21
+ get('push_subscriptions', options).map do |row|
22
+ Strava::Webhooks::Models::Subscription.new(row)
23
+ end
24
+ end
25
+
26
+ #
27
+ # Delete an existing push subscription.
28
+ #
29
+ def delete_push_subscription(id_or_options, options = {})
30
+ id, options = parse_args(id_or_options, options)
31
+ delete("push_subscriptions/#{id}", options)
32
+ nil
33
+ end
34
+
35
+ #
36
+ # Create a subscription.
37
+ #
38
+ # @option options [String] :callback_url
39
+ # Address where webhook events will be sent.
40
+ # @option options [String] :verify_token
41
+ # String chosen by the application owner for client security. An identical string should be returned by Strava's subscription service.
42
+ #
43
+ def create_push_subscription(options = {})
44
+ Strava::Webhooks::Models::Subscription.new(post('push_subscriptions', options))
45
+ end
46
+
47
+ class << self
48
+ def configure
49
+ block_given? ? yield(Config) : Config
50
+ end
51
+
52
+ def config
53
+ Config
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end