strava-ruby-client 0.4.3 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -1
- data/README.md +90 -88
- data/bin/strava-oauth-token +2 -2
- data/bin/strava-webhooks +2 -2
- data/lib/strava/api/client.rb +21 -2
- data/lib/strava/api/endpoints/routes.rb +2 -2
- data/lib/strava/api/endpoints/running_races.rb +0 -12
- data/lib/strava/api/endpoints/segments.rb +0 -46
- data/lib/strava/api/pagination.rb +60 -0
- data/lib/strava/api/ratelimit.rb +159 -0
- data/lib/strava/deep_copyable.rb +16 -0
- data/lib/strava/models/achievement.rb +1 -1
- data/lib/strava/models/activity.rb +48 -2
- data/lib/strava/models/activity_stats.rb +1 -1
- data/lib/strava/models/activity_total.rb +1 -1
- data/lib/strava/models/activity_zone.rb +1 -1
- data/lib/strava/models/athlete.rb +1 -2
- data/lib/strava/models/authorization.rb +1 -1
- data/lib/strava/models/club.rb +1 -1
- data/lib/strava/models/club_admin.rb +1 -1
- data/lib/strava/models/club_event.rb +1 -1
- data/lib/strava/models/club_member.rb +1 -1
- data/lib/strava/models/comment.rb +1 -1
- data/lib/strava/models/explorer_segment.rb +1 -1
- data/lib/strava/models/gear.rb +1 -1
- data/lib/strava/models/heart_rate_zone_ranges.rb +1 -1
- data/lib/strava/models/kudoser.rb +1 -1
- data/lib/strava/models/lap.rb +1 -1
- data/lib/strava/models/map.rb +1 -1
- data/lib/strava/models/mixins/http_response.rb +15 -0
- data/lib/strava/models/photo.rb +1 -1
- data/lib/strava/models/photos.rb +1 -1
- data/lib/strava/models/power_zone_ranges.rb +1 -1
- data/lib/strava/models/response.rb +9 -0
- data/lib/strava/models/route.rb +1 -1
- data/lib/strava/models/running_race.rb +1 -1
- data/lib/strava/models/segment.rb +1 -1
- data/lib/strava/models/segment_effort.rb +1 -1
- data/lib/strava/models/segment_stats.rb +1 -1
- data/lib/strava/models/similar_activities.rb +1 -1
- data/lib/strava/models/split.rb +1 -1
- data/lib/strava/models/stream.rb +1 -1
- data/lib/strava/models/stream_set.rb +1 -1
- data/lib/strava/models/timed_zone_range.rb +1 -1
- data/lib/strava/models/token.rb +1 -1
- data/lib/strava/models/trend.rb +1 -1
- data/lib/strava/models/upload.rb +1 -1
- data/lib/strava/models/zone_range.rb +1 -1
- data/lib/strava/models/zones.rb +1 -1
- data/lib/strava/version.rb +1 -1
- data/lib/strava/web/api_response.rb +17 -0
- data/lib/strava/web/client.rb +2 -2
- data/lib/strava/web/connection.rb +4 -4
- data/lib/strava/web/raise_response_error.rb +29 -0
- data/lib/strava/web/request.rb +3 -2
- data/lib/strava/web/response.rb +92 -0
- data/lib/strava/webhooks/models/subscription.rb +1 -1
- data/lib/strava-ruby-client.rb +9 -4
- metadata +17 -12
- data/lib/strava/models/segment_leaderboard.rb +0 -12
- data/lib/strava/models/segment_leaderboard_entry.rb +0 -14
- data/lib/strava/web/raise_error.rb +0 -31
@@ -0,0 +1,159 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Strava
|
4
|
+
module Api
|
5
|
+
class Ratelimit
|
6
|
+
def initialize(response)
|
7
|
+
@response = response
|
8
|
+
@headers = response.headers
|
9
|
+
@body = response.body
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
to_h.map do |k, v|
|
14
|
+
"#{k}: #{v}"
|
15
|
+
end.join(', ')
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# represents all valid ratelimits in a Hash
|
20
|
+
#
|
21
|
+
# @return [Hash] of ratelimits
|
22
|
+
#
|
23
|
+
def to_h
|
24
|
+
if limit?
|
25
|
+
{
|
26
|
+
limit: limit,
|
27
|
+
usage: usage,
|
28
|
+
total_day: total_day,
|
29
|
+
total_day_usage: total_day_usage,
|
30
|
+
total_day_remaining: total_day_remaining,
|
31
|
+
fifteen_minutes: fifteen_minutes,
|
32
|
+
fifteen_minutes_usage: fifteen_minutes_usage,
|
33
|
+
fifteen_minutes_remaining: fifteen_minutes_remaining
|
34
|
+
}
|
35
|
+
else
|
36
|
+
{}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# checks for presence of the header, as it is i.e. not included when
|
42
|
+
# asking for a token.
|
43
|
+
#
|
44
|
+
# @return [TrueClass]
|
45
|
+
#
|
46
|
+
def limit?
|
47
|
+
@headers.key?('x-ratelimit-limit')
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# returns a string containing the ratelimit for 15 minutes before the comma and
|
52
|
+
# the daily ratelimit after the comma
|
53
|
+
#
|
54
|
+
# @return [String] of the ratelimits for 15 minutes and per day separated by comma
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# ```ruby
|
58
|
+
# "600,30000"
|
59
|
+
# ```
|
60
|
+
#
|
61
|
+
def limit
|
62
|
+
@headers['x-ratelimit-limit']
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# returns a string containing the used ratelimit for 15 minutes before the comma and
|
67
|
+
# the daily ratelimit after the comma
|
68
|
+
#
|
69
|
+
# @return [String] of the used ratelimits for 15 minutes and per day separated by comma
|
70
|
+
#
|
71
|
+
# @example
|
72
|
+
# ```ruby
|
73
|
+
# "333,11337"
|
74
|
+
# ```
|
75
|
+
#
|
76
|
+
def usage
|
77
|
+
@headers['x-ratelimit-usage']
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# fifteen minute ratelimit
|
82
|
+
#
|
83
|
+
# @return [NilClass] if no ratelimit in http headers
|
84
|
+
# @return [Integer] representing the ratelimit
|
85
|
+
#
|
86
|
+
def fifteen_minutes
|
87
|
+
limit? ? extract_ratelimit!(limit).first : nil
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# total day ratelimit
|
92
|
+
#
|
93
|
+
# @return [NilClass] if no ratelimit in http headers
|
94
|
+
# @return [Integer] representing the ratelimit
|
95
|
+
#
|
96
|
+
def total_day
|
97
|
+
limit? ? extract_ratelimit!(limit).last : nil
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# fifteen minute ratelimit used
|
102
|
+
#
|
103
|
+
# @return [NilClass] if no ratelimit in http headers
|
104
|
+
# @return [Integer] representing the ratelimit
|
105
|
+
#
|
106
|
+
def fifteen_minutes_usage
|
107
|
+
limit? ? extract_ratelimit!(usage).first : nil
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# total day ratelimit used
|
112
|
+
#
|
113
|
+
# @return [NilClass] if no ratelimit in http headers
|
114
|
+
# @return [Integer] representing the ratelimit
|
115
|
+
#
|
116
|
+
def total_day_usage
|
117
|
+
limit? ? extract_ratelimit!(usage).last : nil
|
118
|
+
end
|
119
|
+
|
120
|
+
#
|
121
|
+
# fifteen minute ratelimit remaining
|
122
|
+
#
|
123
|
+
# @return [NilClass] if no ratelimit in http headers
|
124
|
+
# @return [Integer] representing the ratelimit
|
125
|
+
#
|
126
|
+
def fifteen_minutes_remaining
|
127
|
+
return nil unless fifteen_minutes && fifteen_minutes_usage
|
128
|
+
|
129
|
+
fifteen_minutes - fifteen_minutes_usage
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# total day ratelimit remaining
|
134
|
+
#
|
135
|
+
# @return [NilClass] if no ratelimit in http headers
|
136
|
+
# @return [Integer] representing the ratelimit
|
137
|
+
#
|
138
|
+
def total_day_remaining
|
139
|
+
return nil unless total_day && total_day_usage
|
140
|
+
|
141
|
+
total_day - total_day_usage
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
#
|
147
|
+
# ratelimit comes as a String of two Integers separated by comma
|
148
|
+
#
|
149
|
+
# @param [String] ratelimit
|
150
|
+
#
|
151
|
+
# @return [Array<Integer>]
|
152
|
+
#
|
153
|
+
def extract_ratelimit!(ratelimit)
|
154
|
+
@lookup_table_ratelimits ||= {}
|
155
|
+
@lookup_table_ratelimits[ratelimit] ||= ratelimit.split(',').map(&:to_i)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Strava
|
4
|
+
module DeepCopyable
|
5
|
+
#
|
6
|
+
# Ruby's way of creating a true deep copy/clone
|
7
|
+
#
|
8
|
+
# @param [Object] obj of any kind
|
9
|
+
#
|
10
|
+
# @return [Object] deep clone of what was passed into
|
11
|
+
#
|
12
|
+
def deep_copy(obj)
|
13
|
+
Marshal.load(Marshal.dump(obj))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Strava
|
4
4
|
module Models
|
5
|
-
class Activity <
|
5
|
+
class Activity < Strava::Models::Response
|
6
6
|
include Mixins::Time
|
7
7
|
include Mixins::Distance
|
8
8
|
include Mixins::Elevation
|
@@ -13,7 +13,8 @@ module Strava
|
|
13
13
|
property 'athlete', transform_with: ->(v) { Strava::Models::Athlete.new(v) }
|
14
14
|
property 'name'
|
15
15
|
property 'description'
|
16
|
-
property 'type'
|
16
|
+
property 'type' # deprecated
|
17
|
+
property 'sport_type'
|
17
18
|
property 'workout_type'
|
18
19
|
property 'id'
|
19
20
|
property 'external_id'
|
@@ -99,6 +100,51 @@ module Strava
|
|
99
100
|
"https://www.strava.com/activities/#{id}"
|
100
101
|
end
|
101
102
|
|
103
|
+
def sport_type_emoji
|
104
|
+
case sport_type
|
105
|
+
when 'AlpineSki' then '⛷️'
|
106
|
+
when 'BackcountrySki' then '🎿️'
|
107
|
+
# when "Canoeing" then ''
|
108
|
+
# when "Crossfit" then ''
|
109
|
+
# when "Elliptical" then ''
|
110
|
+
when 'Golf' then '🏌️'
|
111
|
+
# when "Handcycle" then ''
|
112
|
+
when 'Hike' then '🥾'
|
113
|
+
when 'IceSkate' then '⛸'
|
114
|
+
when 'InlineSkate' then "\u{1F6FC}"
|
115
|
+
# when "Kayaking" then ''
|
116
|
+
# when "Kitesurf" then ''
|
117
|
+
when 'MountainBikeRide', 'EMountainBikeRide' then '🚵'
|
118
|
+
# when "NordicSki" then ''
|
119
|
+
when 'Ride', 'EBikeRide', 'VirtualRide', 'GravelRide' then '🚴'
|
120
|
+
when 'RockClimbing' then '🧗'
|
121
|
+
# when 'RollerSki' then ''
|
122
|
+
when 'Rowing' then '🚣'
|
123
|
+
when 'Run', 'VirtualRun', 'TrailRun' then '🏃'
|
124
|
+
when 'Sail' then '⛵️'
|
125
|
+
when 'Skateboard' then '🛹'
|
126
|
+
when 'Snowboard' then '🏂'
|
127
|
+
# when 'Snowshoe' then ''
|
128
|
+
when 'Soccer' then '⚽️'
|
129
|
+
# when 'StairStepper' then ''
|
130
|
+
# when 'StandUpPaddling' then ''
|
131
|
+
when 'Surfing' then '🏄'
|
132
|
+
when 'Swim' then '🏊'
|
133
|
+
# when 'Velomobile' then ''
|
134
|
+
when 'Walk' then '🚶'
|
135
|
+
when 'WeightTraining' then '🏋️'
|
136
|
+
when 'Wheelchair' then '♿'
|
137
|
+
# when 'Windsurf' then ''
|
138
|
+
# when 'Workout' then ''
|
139
|
+
when 'Yoga' then '🧘'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
#
|
144
|
+
# @deprecated Use {#sport_type_emoji} instead.
|
145
|
+
#
|
146
|
+
# @return [String] precisely an emoji
|
147
|
+
#
|
102
148
|
def type_emoji
|
103
149
|
case type
|
104
150
|
when 'Run', 'VirtualRun' then '🏃'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Strava
|
4
4
|
module Models
|
5
|
-
class ActivityStats <
|
5
|
+
class ActivityStats < Strava::Models::Response
|
6
6
|
property 'biggest_ride_distance'
|
7
7
|
property 'biggest_climb_elevation_gain'
|
8
8
|
property 'recent_ride_totals', transform_with: ->(v) { Strava::Models::ActivityTotal.new(v) }
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Strava
|
4
4
|
module Models
|
5
|
-
class Athlete <
|
5
|
+
class Athlete < Strava::Models::Response
|
6
6
|
property 'id'
|
7
7
|
property 'username'
|
8
8
|
property 'resource_state'
|
@@ -18,7 +18,6 @@ module Strava
|
|
18
18
|
property 'badge_type_id'
|
19
19
|
property 'profile'
|
20
20
|
property 'profile_medium'
|
21
|
-
property 'email'
|
22
21
|
property 'follower'
|
23
22
|
property 'friend'
|
24
23
|
property 'summit'
|
data/lib/strava/models/club.rb
CHANGED
data/lib/strava/models/gear.rb
CHANGED
data/lib/strava/models/lap.rb
CHANGED
data/lib/strava/models/map.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Strava
|
4
|
+
module Models
|
5
|
+
module Mixins
|
6
|
+
module HttpResponse
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
property 'http_response', transform_with: ->(v) { Strava::Web::ApiResponse.new(v) }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/strava/models/photo.rb
CHANGED
data/lib/strava/models/photos.rb
CHANGED
data/lib/strava/models/route.rb
CHANGED
data/lib/strava/models/split.rb
CHANGED
data/lib/strava/models/stream.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Strava
|
4
4
|
module Models
|
5
|
-
class StreamSet <
|
5
|
+
class StreamSet < Strava::Models::Response
|
6
6
|
property 'distance', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
7
7
|
property 'time', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
8
8
|
property 'latlng', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
data/lib/strava/models/token.rb
CHANGED
data/lib/strava/models/trend.rb
CHANGED
data/lib/strava/models/upload.rb
CHANGED
data/lib/strava/models/zones.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Strava
|
4
4
|
module Models
|
5
|
-
class Zones <
|
5
|
+
class Zones < Strava::Models::Response
|
6
6
|
property 'heart_rate', transform_with: ->(v) { Strava::Models::HeartRateZoneRanges.new(v) }
|
7
7
|
property 'power', transform_with: ->(v) { Strava::Models::PowerZoneRanges.new(v) }
|
8
8
|
end
|
data/lib/strava/version.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Strava
|
4
|
+
module Web
|
5
|
+
class ApiResponse
|
6
|
+
attr_accessor :response, :ratelimit
|
7
|
+
|
8
|
+
#
|
9
|
+
# @param [Faraday::Response] http_response
|
10
|
+
#
|
11
|
+
def initialize(http_response)
|
12
|
+
@response = http_response
|
13
|
+
@ratelimit = Strava::Api::Ratelimit.new(@response)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|