strava-ruby-client 0.4.3 → 1.0.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 +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
|