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
@@ -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