strava 0.1.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 +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +6 -0
- data/.yardopts +1 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +21 -0
- data/README.md +302 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/strava.rb +79 -0
- data/lib/strava/activity.rb +224 -0
- data/lib/strava/adapters/httparty_adapter.rb +9 -0
- data/lib/strava/athlete.rb +378 -0
- data/lib/strava/base.rb +86 -0
- data/lib/strava/client.rb +65 -0
- data/lib/strava/club.rb +164 -0
- data/lib/strava/club_announcement.rb +28 -0
- data/lib/strava/comment.rb +36 -0
- data/lib/strava/error.rb +15 -0
- data/lib/strava/gear.rb +41 -0
- data/lib/strava/group_event.rb +62 -0
- data/lib/strava/lap.rb +39 -0
- data/lib/strava/leaderboard.rb +57 -0
- data/lib/strava/leaderboard_entry.rb +48 -0
- data/lib/strava/photo.rb +50 -0
- data/lib/strava/route.rb +51 -0
- data/lib/strava/running_race.rb +50 -0
- data/lib/strava/segment.rb +100 -0
- data/lib/strava/segment_effort.rb +45 -0
- data/lib/strava/stream.rb +33 -0
- data/lib/strava/stream_set.rb +62 -0
- data/lib/strava/usage.rb +38 -0
- data/lib/strava/version.rb +4 -0
- data/strava.gemspec +29 -0
- metadata +135 -0
@@ -0,0 +1,224 @@
|
|
1
|
+
module Strava
|
2
|
+
# Class to represent Strava Activity
|
3
|
+
# @see https://strava.github.io/api/v3/activities/ Strava Activity API Docs
|
4
|
+
class Activity < Base
|
5
|
+
ATTRIBUTES = [:external_id, :upload_id, :athlete, :name, :description, :distance, :moving_time, :elapsed_time, :total_elevation_gain, :elev_high, :elev_low, :type, :start_date, :start_date_local, :timezone, :start_latlng, :end_latlng, :location_city, :location_state, :location_country, :achievement_count, :kudos_count, :comment_count, :athlete_count, :photo_count, :total_photo_count, :map, :trainer, :commute, :manual, :private, :device_name, :embed_token, :flagged, :workout_type, :gear_id, :average_speed, :max_speed, :average_cadence, :average_temp, :average_watts, :max_watts, :weighted_average_watts, :kilojoules, :device_watts, :has_heartrate, :average_heartrate, :max_heartrate, :calories, :suffer_score, :has_kudoed, :splits_metric, :splits_standard, :best_efforts] # activity attributes, all have getter method
|
6
|
+
attr_reader *ATTRIBUTES
|
7
|
+
attr_reader :photos_info, :gear
|
8
|
+
|
9
|
+
# Set up instance variables upon instantiation.
|
10
|
+
#
|
11
|
+
# @abstract
|
12
|
+
# @return [void]
|
13
|
+
private def set_ivars
|
14
|
+
@kudos = {}
|
15
|
+
@comments = {}
|
16
|
+
@photos = {}
|
17
|
+
@laps = {}
|
18
|
+
@segment_efforts = {}
|
19
|
+
@related = {}
|
20
|
+
@streams = StreamSet.new
|
21
|
+
end
|
22
|
+
|
23
|
+
# Updates activity with passed data attributes.
|
24
|
+
#
|
25
|
+
# @param data [Hash] data hash containing activity data
|
26
|
+
# @return [self]
|
27
|
+
private def update(data, **opts)
|
28
|
+
@response = data
|
29
|
+
@id = data["id"]
|
30
|
+
@resource_state = data['resource_state']
|
31
|
+
@photos_info = data['photos']
|
32
|
+
@laps_info = data['laps']
|
33
|
+
@gear = Gear.new(data['gear'], client: client) if data['gear']
|
34
|
+
ATTRIBUTES.each do |attr|
|
35
|
+
instance_variable_set("@#{attr}", data[attr.to_s])
|
36
|
+
end
|
37
|
+
|
38
|
+
parse_data(@segment_efforts, data["segment_efforts"], klass: SegmentEffort, client: @client) if data["segment_efforts"]
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def segment_efforts
|
43
|
+
@segment_efforts.values
|
44
|
+
end
|
45
|
+
|
46
|
+
def kudos(per_page: nil, page: nil)
|
47
|
+
if page || per_page
|
48
|
+
get_kudos(per_page: per_page, page: page)
|
49
|
+
else
|
50
|
+
get_kudos if @kudos.empty?
|
51
|
+
@kudos.values
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def comments(per_page: nil, page: nil)
|
56
|
+
if page || per_page
|
57
|
+
get_comments(per_page: per_page, page: page)
|
58
|
+
else
|
59
|
+
get_comments if @comments.empty?
|
60
|
+
@comments.values
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def photos(per_page: nil, page: nil)
|
65
|
+
if page || per_page
|
66
|
+
get_photos(per_page: per_page, page: page)
|
67
|
+
else
|
68
|
+
get_photos if @photos.empty?
|
69
|
+
@photos.values
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Activities that were matched as “with this group”. The number equals activity.athlete_count-1. Pagination is supported.
|
74
|
+
# @return [Strava::Activity] Related activities
|
75
|
+
def related(per_page: nil, page: nil)
|
76
|
+
if page || per_page
|
77
|
+
get_related(per_page: per_page, page: page)
|
78
|
+
else
|
79
|
+
get_related if @related.empty?
|
80
|
+
@related.values
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def streams(types = [:time, :distance, :latlng], **params)
|
85
|
+
get_streams(types, **params) if @streams.empty?
|
86
|
+
@streams
|
87
|
+
end
|
88
|
+
|
89
|
+
def zones
|
90
|
+
get_zones unless @zones
|
91
|
+
@zones
|
92
|
+
end
|
93
|
+
|
94
|
+
def laps
|
95
|
+
get_laps if @laps.empty?
|
96
|
+
@laps.values
|
97
|
+
end
|
98
|
+
|
99
|
+
def comment(message)
|
100
|
+
res = client.post(path_comments, text: message).to_h
|
101
|
+
end
|
102
|
+
|
103
|
+
def kudo
|
104
|
+
res = client.post(path_kudos).to_h
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def get_details
|
109
|
+
return self if detailed?
|
110
|
+
res = client.get(path_base).to_h
|
111
|
+
update(res)
|
112
|
+
end
|
113
|
+
def get_kudos(per_page: nil, page: nil)
|
114
|
+
res = client.get(path_kudos, per_page: per_page, page: page).to_a
|
115
|
+
parse_data(@kudos, res, klass: Athlete, client: @client)
|
116
|
+
end
|
117
|
+
def get_comments(per_page: nil, page: nil)
|
118
|
+
res = client.get(path_comments, per_page: per_page, page: page).to_a
|
119
|
+
parse_data(@comments, res, klass: Comment, client: @client)
|
120
|
+
end
|
121
|
+
def get_photos(per_page: nil, page: nil)
|
122
|
+
res = client.get(path_photos, per_page: per_page, page: page).to_a
|
123
|
+
parse_data(@photos, res, klass: Photo, client: @client)
|
124
|
+
end
|
125
|
+
def get_related(per_page: nil, page: nil)
|
126
|
+
res = client.get(path_related, per_page: per_page, page: page).to_a
|
127
|
+
parse_data(@related, res, klass: Activity, client: @client)
|
128
|
+
end
|
129
|
+
def get_streams(types = '', **params)
|
130
|
+
res = client.get(path_streams + types.join(','), **params).to_a
|
131
|
+
@streams.update(res)
|
132
|
+
end
|
133
|
+
def get_zones
|
134
|
+
res = client.get(path_zones).to_a
|
135
|
+
@zones = res
|
136
|
+
end
|
137
|
+
def get_laps
|
138
|
+
res = client.get(path_laps).to_a
|
139
|
+
parse_data(@laps, res, klass: Lap, client: @client)
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
def path_base
|
144
|
+
"activities/#{id}"
|
145
|
+
end
|
146
|
+
def path_kudos
|
147
|
+
"#{path_base}/kudos"
|
148
|
+
end
|
149
|
+
def path_comments
|
150
|
+
"#{path_base}/comments"
|
151
|
+
end
|
152
|
+
def path_photos
|
153
|
+
"#{path_base}/photos?photo_sources=true"
|
154
|
+
end
|
155
|
+
def path_related
|
156
|
+
"#{path_base}/related"
|
157
|
+
end
|
158
|
+
def path_streams
|
159
|
+
"#{path_base}/streams/"
|
160
|
+
end
|
161
|
+
def path_zones
|
162
|
+
"#{path_base}/zones"
|
163
|
+
end
|
164
|
+
def path_laps
|
165
|
+
"#{path_base}/laps"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
activity_types = [
|
171
|
+
'Ride',
|
172
|
+
'Kitesurf',
|
173
|
+
'Run',
|
174
|
+
'NordicSki',
|
175
|
+
'Swim',
|
176
|
+
'RockClimbing',
|
177
|
+
'Hike',
|
178
|
+
'RollerSki',
|
179
|
+
'Walk',
|
180
|
+
'Rowing',
|
181
|
+
'AlpineSki',
|
182
|
+
'Snowboard',
|
183
|
+
'BackcountrySki',
|
184
|
+
'Snowshoe',
|
185
|
+
'Canoeing',
|
186
|
+
'StairStepper',
|
187
|
+
'Crossfit',
|
188
|
+
'StandUpPaddling',
|
189
|
+
'EBikeRide',
|
190
|
+
'Surfing',
|
191
|
+
'Elliptical',
|
192
|
+
'VirtualRide',
|
193
|
+
'IceSkate',
|
194
|
+
'WeightTraining',
|
195
|
+
'InlineSkate',
|
196
|
+
'Windsurf',
|
197
|
+
'Kayaking',
|
198
|
+
'Workout',
|
199
|
+
'Yoga',
|
200
|
+
]
|
201
|
+
|
202
|
+
__END__
|
203
|
+
|
204
|
+
ca = Strava::Athlete.current_athlete;
|
205
|
+
act = ca.activities.first;
|
206
|
+
act.get_details
|
207
|
+
act.comments
|
208
|
+
|
209
|
+
|
210
|
+
ca = Strava::Athlete.current_athlete;
|
211
|
+
act = ca.activities.detect{|a| a.response['kudos_count'] > 0 }
|
212
|
+
act.get_kudos
|
213
|
+
ca = Strava::Athlete.current_athlete;
|
214
|
+
ca.activities;
|
215
|
+
ca.activities(page: 2);
|
216
|
+
ca.activities(page: 3);
|
217
|
+
ca.activities(page: 4);
|
218
|
+
act = ca.activities.detect{|a| a.response['comment_count'] > 0 && a.response['kudos_count'] > 0 }
|
219
|
+
act.kudos
|
220
|
+
act.photos
|
221
|
+
act.comments
|
222
|
+
act = ca.activities.detect{|a| a.response['comment_count'] > 0 }
|
223
|
+
act.get_comments
|
224
|
+
|
@@ -0,0 +1,378 @@
|
|
1
|
+
module Strava
|
2
|
+
# Strava Athlete class. For the most part, API interaction deals with the currently authenticated athlete.
|
3
|
+
#
|
4
|
+
# There are mixins available to provide convenient ways to instantiate an athlete, see {Strava.model} for more information.
|
5
|
+
#
|
6
|
+
# Usage:
|
7
|
+
#
|
8
|
+
# ca = Strava::Athlete.current_athlete(access_token)
|
9
|
+
# ca.firstname # => 'John'
|
10
|
+
# ca.lastname # => 'Applestrava'
|
11
|
+
# ca.profile # => 'http://pics.com/227615/large.jpg'
|
12
|
+
#
|
13
|
+
# @see https://strava.github.io/api/v3/athlete/ Strava Docs - Athlete
|
14
|
+
class Athlete < Base
|
15
|
+
|
16
|
+
attr_reader :firstname, :lastname, :profile_medium, :profile, :city, :state, :country, :sex, :friend, :follower, :premium, :created_at, :updated_at, :follower_count, :friend_count, :mutual_friend_count, :athlete_type, :date_preference, :measurement_preference, :email, :ftp, :weight, :bikes, :shoes
|
17
|
+
|
18
|
+
# Set up instance variables upon instantiation.
|
19
|
+
#
|
20
|
+
# @abstract
|
21
|
+
# @return [void]
|
22
|
+
private def set_ivars
|
23
|
+
@activities = {}
|
24
|
+
@friends_activities = {}
|
25
|
+
@routes = {}
|
26
|
+
@connections = {}
|
27
|
+
@both_following = {}
|
28
|
+
@koms = {}
|
29
|
+
@gear = {}
|
30
|
+
@clubs = {}
|
31
|
+
@heatmaps = {}
|
32
|
+
@starred_segments = {}
|
33
|
+
|
34
|
+
@friends = []
|
35
|
+
@followers = []
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(data, client: nil, token: nil, **opts)
|
39
|
+
@current = !!opts[:current]
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
# Update an existing athlete.
|
44
|
+
# Used by other methods in the gem.
|
45
|
+
# Should not be used directly.
|
46
|
+
#
|
47
|
+
# @private
|
48
|
+
# @param data [Hash] data to update the athlete with
|
49
|
+
# @return [self]
|
50
|
+
def update(data, **opts)
|
51
|
+
@id = data["id"]
|
52
|
+
@username = data["username"]
|
53
|
+
@resource_state = data["resource_state"]
|
54
|
+
@firstname = data["firstname"]
|
55
|
+
@lastname = data["lastname"]
|
56
|
+
@city = data["city"]
|
57
|
+
@state = data["state"]
|
58
|
+
@country = data["country"]
|
59
|
+
@sex = data["sex"]
|
60
|
+
@premium = data["premium"]
|
61
|
+
@created_at = data["created_at"]
|
62
|
+
@updated_at = data["updated_at"]
|
63
|
+
@badge_type_id = data["badge_type_id"]
|
64
|
+
@profile_medium = data["profile_medium"]
|
65
|
+
@profile = data["profile"]
|
66
|
+
@friend = data["friend"]
|
67
|
+
@follower = data["follower"]
|
68
|
+
@follower_count = data["follower_count"]
|
69
|
+
@friend_count = data["friend_count"]
|
70
|
+
@mutual_friend_count = data["mutual_friend_count"]
|
71
|
+
@athlete_type = data["athlete_type"]
|
72
|
+
@date_preference = data["date_preference"]
|
73
|
+
@measurement_preference = data["measurement_preference"]
|
74
|
+
@email = data["email"]
|
75
|
+
@ftp = data["ftp"]
|
76
|
+
@weight = data["weight"]
|
77
|
+
@bikes = parse_data(@gear, data['bikes'], klass: Gear, client: @client)
|
78
|
+
@shoes = parse_data(@gear, data['shoes'], klass: Gear, client: @client)
|
79
|
+
|
80
|
+
parse_data(@clubs, data['clubs'], klass: Club, client: @client)
|
81
|
+
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
# Whether this is the currently authenticated athlete.
|
86
|
+
# Strava's API has reduced access for athletes other than the currently authenticated one.
|
87
|
+
#
|
88
|
+
# @return [Boolean]
|
89
|
+
def current?
|
90
|
+
@current
|
91
|
+
end
|
92
|
+
|
93
|
+
## Non athlete specific methods
|
94
|
+
|
95
|
+
# Retrieve running races.
|
96
|
+
# This is not related to the current athlete, but does require an access token.
|
97
|
+
#
|
98
|
+
# Also available via {RunningRace.list_races}
|
99
|
+
#
|
100
|
+
# @param year [Integer] Year to retrieve races for
|
101
|
+
def list_races(year = Time.now.year)
|
102
|
+
client.list_races(year)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Segment Explorer will find popular segments within a given area.
|
106
|
+
# Requires a comma separated list of bounding box corners.
|
107
|
+
#
|
108
|
+
# Also available via {Segment.explorer}
|
109
|
+
#
|
110
|
+
# @param bounds [String] ‘sw.lat,sw.lng,ne.lat,ne.lng’ or alternatively, ‘south,west,north,east’
|
111
|
+
def segment_explorer(bounds = '37.821362,-122.505373,37.842038,-122.465977')
|
112
|
+
client.segment_explorer(bounds)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Gear list. Includes shoes and bikes.
|
116
|
+
#
|
117
|
+
# @return [Array<Gear>] Athlete's gear
|
118
|
+
def gear
|
119
|
+
@gear.values
|
120
|
+
end
|
121
|
+
|
122
|
+
# Activities belonging to this user.
|
123
|
+
# If no activities have been retrieved, an API call will be made.
|
124
|
+
# If activities exist, they will be returned.
|
125
|
+
# Pagination is supported, and will always trigger an API call.
|
126
|
+
# Paged requests will return the activities from that page.
|
127
|
+
# Non-paged calls will return all downloaded activities.
|
128
|
+
|
129
|
+
def activities(per_page: nil, page: nil)
|
130
|
+
if page || per_page
|
131
|
+
get_activities(per_page: per_page, page: page)
|
132
|
+
else
|
133
|
+
get_activities if @activities.empty?
|
134
|
+
@activities.values
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# not working, not listed in docs
|
139
|
+
# def heatmaps(per_page: nil, page: nil)
|
140
|
+
# if page || per_page
|
141
|
+
# get_heatmaps(per_page: per_page, page: page)
|
142
|
+
# else
|
143
|
+
# get_heatmaps if @heatmaps.empty?
|
144
|
+
# @heatmaps.values
|
145
|
+
# end
|
146
|
+
# end
|
147
|
+
|
148
|
+
def friends_activities(per_page: nil, page: nil, before: nil)
|
149
|
+
if page || per_page
|
150
|
+
get_friends_activities(per_page: per_page, page: page)
|
151
|
+
else
|
152
|
+
get_friends_activities if @friends_activities.empty?
|
153
|
+
@friends_activities.values
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def stats
|
158
|
+
@stats || get_stats
|
159
|
+
end
|
160
|
+
alias :totals :stats
|
161
|
+
|
162
|
+
def zones
|
163
|
+
@zones || get_zones
|
164
|
+
end
|
165
|
+
|
166
|
+
def koms(per_page: nil, page: nil)
|
167
|
+
if page || per_page
|
168
|
+
get_koms(per_page: per_page, page: page)
|
169
|
+
else
|
170
|
+
get_koms if @koms.empty?
|
171
|
+
@koms.values
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def clubs
|
176
|
+
get_clubs if @clubs.empty?
|
177
|
+
@clubs.values
|
178
|
+
end
|
179
|
+
|
180
|
+
def routes(per_page: nil, page: nil)
|
181
|
+
if page || per_page
|
182
|
+
get_routes(per_page: per_page, page: page)
|
183
|
+
else
|
184
|
+
get_routes if @routes.empty?
|
185
|
+
@routes.values
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def starred_segments(per_page: nil, page: nil)
|
190
|
+
if page || per_page
|
191
|
+
get_starred_segments(per_page: per_page, page: page)
|
192
|
+
else
|
193
|
+
get_starred_segments if @starred_segments.empty?
|
194
|
+
@starred_segments.values
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def friends(per_page: nil, page: nil)
|
199
|
+
# paginate('friends', struct: Array, per_page: per_page, page: page)
|
200
|
+
if page || per_page
|
201
|
+
get_friends(per_page: per_page, page: page)
|
202
|
+
else
|
203
|
+
get_friends if @friends.empty?
|
204
|
+
@friends.uniq(&:id)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def followers(per_page: nil, page: nil)
|
209
|
+
# paginate('followers', struct: Array, per_page: per_page, page: page)
|
210
|
+
if page || per_page
|
211
|
+
get_followers(per_page: per_page, page: page)
|
212
|
+
else
|
213
|
+
get_followers if @followers.empty?
|
214
|
+
@followers.uniq(&:id)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def both_following(other_athlete, per_page: nil, page: nil)
|
219
|
+
other_id = other_athlete.is_a?(Athlete) ? other_athlete.id : other_athlete
|
220
|
+
if page || per_page
|
221
|
+
get_both_following(other_id, per_page: per_page, page: page)
|
222
|
+
else
|
223
|
+
get_both_following(other_id) if @both_following[other_id].nil?
|
224
|
+
@both_following[other_id]
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
## retrieval methods
|
229
|
+
def get_details
|
230
|
+
return self if detailed?
|
231
|
+
res = client.get(path_base).to_h
|
232
|
+
update(res)
|
233
|
+
end
|
234
|
+
|
235
|
+
private def get_activities(per_page: nil, page: nil)
|
236
|
+
res = client.get(path_activities, per_page: per_page, page: page).to_a
|
237
|
+
parse_data(@activities, res, klass: Activity, client: @client)
|
238
|
+
end
|
239
|
+
|
240
|
+
# not working, not listed in docs
|
241
|
+
# private def get_heatmaps(per_page: nil, page: nil)
|
242
|
+
# res = client.get(path_heatmaps, per_page: per_page, page: page).to_a
|
243
|
+
# parse_data(@heatmaps, res, klass: Base, client: @client)
|
244
|
+
# end
|
245
|
+
|
246
|
+
private def get_friends_activities(per_page: nil, page: nil, before: nil)
|
247
|
+
res = client.get(path_friends_activities, per_page: per_page, page: page, before: before).to_a
|
248
|
+
parse_data(@friends_activities, res, klass: Activity, client: @client)
|
249
|
+
end
|
250
|
+
|
251
|
+
private def get_stats
|
252
|
+
@stats = client.get(path_stats).to_h
|
253
|
+
end
|
254
|
+
|
255
|
+
private def get_zones
|
256
|
+
@zones = client.get(path_zones).to_h
|
257
|
+
end
|
258
|
+
|
259
|
+
private def get_koms(per_page: nil, page: nil)
|
260
|
+
res = client.get(path_koms, per_page: per_page, page: page).to_a
|
261
|
+
parse_data(@koms, res, klass: SegmentEffort, client: @client)
|
262
|
+
end
|
263
|
+
|
264
|
+
private def get_clubs(per_page: nil, page: nil)
|
265
|
+
res = client.get(path_clubs, per_page: per_page, page: page).to_a
|
266
|
+
parse_data(@clubs, res, klass: Club, client: @client)
|
267
|
+
end
|
268
|
+
|
269
|
+
private def get_routes(per_page: nil, page: nil)
|
270
|
+
res = client.get(path_routes, per_page: per_page, page: page).to_a
|
271
|
+
parse_data(@routes, res, klass: Route, client: @client)
|
272
|
+
end
|
273
|
+
|
274
|
+
private def get_starred_segments(per_page: nil, page: nil)
|
275
|
+
res = client.get(path_starred_segments, per_page: per_page, page: page).to_a
|
276
|
+
parse_data(@starred_segments, res, klass: Segment, client: @client)
|
277
|
+
end
|
278
|
+
|
279
|
+
private def get_friends(per_page: nil, page: nil)
|
280
|
+
res = client.get(path_friends, per_page: per_page, page: page).to_a
|
281
|
+
data = parse_data(@connections, res, klass: self.class, client: @client)
|
282
|
+
@friends.concat(data)
|
283
|
+
data
|
284
|
+
end
|
285
|
+
|
286
|
+
private def get_followers(per_page: nil, page: nil)
|
287
|
+
res = client.get(path_followers, per_page: per_page, page: page).to_a
|
288
|
+
data = parse_data(@connections, res, klass: self.class, client: @client)
|
289
|
+
@followers.concat(data)
|
290
|
+
data
|
291
|
+
end
|
292
|
+
|
293
|
+
private def get_both_following(other_id, per_page: nil, page: nil)
|
294
|
+
res = client.get(path_both_following(other_id), per_page: per_page, page: page).to_a
|
295
|
+
@both_following[other_id] = parse_data(@connections, res, klass: self.class, client: @client)
|
296
|
+
end
|
297
|
+
|
298
|
+
def path_base
|
299
|
+
current? ? 'athlete' : "athletes/#{id}"
|
300
|
+
end
|
301
|
+
|
302
|
+
private def path_activities
|
303
|
+
current? ? "athlete/activities" : raise('Need to be current athlete')
|
304
|
+
end
|
305
|
+
|
306
|
+
# not working, not listed in docs
|
307
|
+
# http://strava.github.io/api/v3/heatmaps/
|
308
|
+
# private def path_heatmaps
|
309
|
+
# current? ? "athlete/heatmaps" : raise('Need to be current athlete')
|
310
|
+
# end
|
311
|
+
|
312
|
+
private def path_friends_activities
|
313
|
+
current? ? "activities/following" : raise('Need to be current athlete')
|
314
|
+
end
|
315
|
+
|
316
|
+
private def path_stats
|
317
|
+
current? ? "athletes/#{id}/stats" : raise('Need to be current athlete')
|
318
|
+
end
|
319
|
+
|
320
|
+
private def path_zones
|
321
|
+
current? ? "athlete/zones" : raise('Need to be current athlete')
|
322
|
+
end
|
323
|
+
|
324
|
+
private def path_koms
|
325
|
+
"athletes/#{id}/koms"
|
326
|
+
end
|
327
|
+
|
328
|
+
private def path_clubs
|
329
|
+
current? ? "athlete/clubs" : raise('Need to be current athlete')
|
330
|
+
end
|
331
|
+
|
332
|
+
private def path_routes
|
333
|
+
"athletes/#{id}/routes"
|
334
|
+
end
|
335
|
+
|
336
|
+
private def path_starred_segments
|
337
|
+
current? ? "segments/starred" : "athletes/#{id}/segments/starred"
|
338
|
+
end
|
339
|
+
|
340
|
+
private def path_followers
|
341
|
+
current? ? "athlete/followers" : "athletes/#{id}/followers"
|
342
|
+
end
|
343
|
+
private def path_friends
|
344
|
+
current? ? "athlete/friends" : "athletes/#{id}/friends"
|
345
|
+
end
|
346
|
+
private def path_both_following(other_id)
|
347
|
+
current? ? "athletes/#{other_id}/friends" : raise('Need to be current athlete')
|
348
|
+
end
|
349
|
+
|
350
|
+
private
|
351
|
+
|
352
|
+
class << self
|
353
|
+
# Retrieve the currently authenticated athlete.
|
354
|
+
# Will make request to Strava API.
|
355
|
+
#
|
356
|
+
# @param token [String] access token for athlete
|
357
|
+
# @return [Athlete] currently authenticated athlete
|
358
|
+
def current_athlete(token = "ca16caf5b4cb8b57016541f470ae6b3a8aea2252")
|
359
|
+
client = Client.new(token)
|
360
|
+
res = client.get('athlete').to_h
|
361
|
+
new(res, client: client, current: true)
|
362
|
+
end
|
363
|
+
|
364
|
+
# def path(endpoint)
|
365
|
+
# paths[endpoint]
|
366
|
+
# end
|
367
|
+
# def paths
|
368
|
+
# @paths ||= {
|
369
|
+
# current: 'athlete',
|
370
|
+
# }.freeze
|
371
|
+
# end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
__END__
|
377
|
+
|
378
|
+
ca = Strava::Athlete.current_athlete
|