strava-ruby-client 3.0.0.pre.2 → 3.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 +4 -4
- data/CHANGELOG.md +15 -2
- data/README.md +47 -58
- data/lib/strava/api/client.rb +69 -0
- data/lib/strava/api/config.rb +40 -0
- data/lib/strava/api/cursor.rb +32 -1
- data/lib/strava/api/endpoints/activities.rb +197 -57
- data/lib/strava/api/endpoints/athletes.rb +64 -8
- data/lib/strava/api/endpoints/clubs.rb +24 -59
- data/lib/strava/api/endpoints/gears.rb +11 -2
- data/lib/strava/api/endpoints/oauth.rb +45 -0
- data/lib/strava/api/endpoints/routes.rb +20 -13
- data/lib/strava/api/endpoints/segment_efforts.rb +15 -8
- data/lib/strava/api/endpoints/segments.rb +74 -21
- data/lib/strava/api/endpoints/streams.rb +22 -18
- data/lib/strava/api/endpoints/uploads.rb +12 -2
- data/lib/strava/api/pagination.rb +25 -0
- data/lib/strava/api/ratelimit.rb +34 -0
- data/lib/strava/deep_copyable.rb +20 -1
- data/lib/strava/errors/fault.rb +32 -0
- data/lib/strava/errors/ratelimit_error.rb +35 -0
- data/lib/strava/errors/upload_error.rb +55 -0
- data/lib/strava/logger.rb +27 -0
- data/lib/strava/models/achievement.rb +28 -1
- data/lib/strava/models/activity_stats.rb +47 -1
- data/lib/strava/models/activity_total.rb +25 -1
- data/lib/strava/models/activity_zone.rb +39 -2
- data/lib/strava/models/authorization.rb +13 -0
- data/lib/strava/models/base_stream.rb +22 -1
- data/lib/strava/models/club_event.rb +64 -1
- data/lib/strava/models/comment.rb +39 -1
- data/lib/strava/models/destination.rb +28 -1
- data/lib/strava/models/detailed_activity.rb +203 -2
- data/lib/strava/models/detailed_athlete.rb +104 -2
- data/lib/strava/models/detailed_club.rb +76 -2
- data/lib/strava/models/detailed_gear.rb +45 -2
- data/lib/strava/models/detailed_photo.rb +61 -1
- data/lib/strava/models/detailed_photos.rb +29 -1
- data/lib/strava/models/detailed_segment.rb +89 -2
- data/lib/strava/models/detailed_segment_effort.rb +92 -3
- data/lib/strava/models/explorer_segment.rb +55 -2
- data/lib/strava/models/heart_rate_zone_ranges.rb +29 -1
- data/lib/strava/models/kudoser.rb +29 -1
- data/lib/strava/models/lap.rb +62 -2
- data/lib/strava/models/lat_lng.rb +42 -4
- data/lib/strava/models/local_legend.rb +41 -1
- data/lib/strava/models/map.rb +31 -0
- data/lib/strava/models/meta_activity.rb +15 -2
- data/lib/strava/models/meta_athlete.rb +17 -2
- data/lib/strava/models/meta_club.rb +15 -1
- data/lib/strava/models/mixins/average_speed.rb +81 -3
- data/lib/strava/models/mixins/distance.rb +25 -0
- data/lib/strava/models/mixins/elapsed_time.rb +18 -0
- data/lib/strava/models/mixins/elevation_difference.rb +42 -0
- data/lib/strava/models/mixins/elevation_gain.rb +39 -0
- data/lib/strava/models/mixins/estimated_moving_time.rb +18 -0
- data/lib/strava/models/mixins/http_response.rb +36 -0
- data/lib/strava/models/mixins/moving_time.rb +18 -0
- data/lib/strava/models/mixins/sport_type.rb +39 -1
- data/lib/strava/models/mixins/start_date_local.rb +40 -24
- data/lib/strava/models/mixins/time_in_hours.rb +23 -0
- data/lib/strava/models/mixins/total_elevation_gain.rb +42 -0
- data/lib/strava/models/model.rb +14 -0
- data/lib/strava/models/photos_summary.rb +26 -2
- data/lib/strava/models/photos_summary_primary.rb +28 -2
- data/lib/strava/models/power_zone_ranges.rb +23 -1
- data/lib/strava/models/response.rb +18 -0
- data/lib/strava/models/route.rb +63 -2
- data/lib/strava/models/similar_activities.rb +57 -1
- data/lib/strava/models/split.rb +27 -2
- data/lib/strava/models/stats_visibility.rb +24 -1
- data/lib/strava/models/stream.rb +107 -0
- data/lib/strava/models/stream_set.rb +52 -1
- data/lib/strava/models/summary_activity.rb +145 -2
- data/lib/strava/models/summary_athlete.rb +54 -1
- data/lib/strava/models/summary_club.rb +61 -2
- data/lib/strava/models/summary_gear.rb +31 -2
- data/lib/strava/models/summary_pr_segment_effort.rb +32 -2
- data/lib/strava/models/summary_segment.rb +80 -2
- data/lib/strava/models/summary_segment_effort.rb +32 -1
- data/lib/strava/models/timed_zone_range.rb +24 -1
- data/lib/strava/models/token.rb +31 -0
- data/lib/strava/models/trend.rb +38 -1
- data/lib/strava/models/updatable_activity.rb +36 -1
- data/lib/strava/models/upload.rb +50 -1
- data/lib/strava/models/waypoint.rb +31 -1
- data/lib/strava/models/xoms.rb +35 -1
- data/lib/strava/models/zone_range.rb +20 -1
- data/lib/strava/models/zones.rb +32 -1
- data/lib/strava/oauth/client.rb +107 -19
- data/lib/strava/oauth/config.rb +41 -0
- data/lib/strava/version.rb +1 -1
- data/lib/strava/web/api_response.rb +28 -2
- data/lib/strava/web/client.rb +72 -2
- data/lib/strava/web/config.rb +40 -0
- data/lib/strava/web/connection.rb +39 -0
- data/lib/strava/web/raise_response_error.rb +47 -0
- data/lib/strava/web/request.rb +56 -0
- data/lib/strava/web/response.rb +18 -0
- data/lib/strava/webhooks/client.rb +108 -7
- data/lib/strava/webhooks/config.rb +44 -0
- data/lib/strava/webhooks/models/challenge.rb +40 -0
- data/lib/strava/webhooks/models/event.rb +50 -0
- data/lib/strava/webhooks/models/subscription.rb +27 -0
- data/lib/strava-ruby-client.rb +0 -2
- metadata +2 -4
- data/lib/strava/models/club_activity.rb +0 -22
- data/lib/strava/models/club_athlete.rb +0 -21
|
@@ -2,30 +2,89 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents summary information about a Strava club.
|
|
7
|
+
#
|
|
8
|
+
# Contains basic club information without detailed membership data.
|
|
9
|
+
# This is typically returned when listing athlete's clubs or as a
|
|
10
|
+
# reference within other models.
|
|
11
|
+
#
|
|
12
|
+
# @example List athlete's clubs
|
|
13
|
+
# clubs = client.athlete_clubs
|
|
14
|
+
# clubs.each do |club|
|
|
15
|
+
# puts "#{club.name} - #{club.member_count} members"
|
|
16
|
+
# puts club.strava_url
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# @see DetailedClub
|
|
20
|
+
# @see https://developers.strava.com/docs/reference/#api-models-SummaryClub
|
|
21
|
+
#
|
|
6
22
|
class SummaryClub < Strava::Models::Response
|
|
23
|
+
# @return [Integer] Club identifier
|
|
7
24
|
property 'id'
|
|
25
|
+
|
|
26
|
+
# @return [Integer] Resource state indicator (1=meta, 2=summary, 3=detailed)
|
|
8
27
|
property 'resource_state'
|
|
28
|
+
|
|
29
|
+
# @return [String] Club name
|
|
9
30
|
property 'name'
|
|
31
|
+
|
|
32
|
+
# @return [String] URL to medium-sized profile picture
|
|
10
33
|
property 'profile_medium'
|
|
34
|
+
|
|
35
|
+
# @return [String] URL to club cover photo
|
|
11
36
|
property 'cover_photo'
|
|
37
|
+
|
|
38
|
+
# @return [String] URL to smaller club cover photo
|
|
12
39
|
property 'cover_photo_small'
|
|
40
|
+
|
|
41
|
+
# @return [String] Primary sport type (e.g., "cycling", "running", "other")
|
|
13
42
|
property 'sport_type'
|
|
43
|
+
|
|
44
|
+
# @return [Array<String>] List of activity types the club supports
|
|
14
45
|
property 'activity_types'
|
|
46
|
+
|
|
47
|
+
# @return [String] City where club is located
|
|
15
48
|
property 'city'
|
|
49
|
+
|
|
50
|
+
# @return [String] State/province where club is located
|
|
16
51
|
property 'state'
|
|
52
|
+
|
|
53
|
+
# @return [String] Country where club is located
|
|
17
54
|
property 'country'
|
|
55
|
+
|
|
56
|
+
# @return [Boolean] Whether club is private
|
|
18
57
|
property 'private'
|
|
58
|
+
|
|
59
|
+
# @return [Integer] Number of club members
|
|
19
60
|
property 'member_count'
|
|
61
|
+
|
|
62
|
+
# @return [Boolean] Whether club is featured by Strava
|
|
20
63
|
property 'featured'
|
|
64
|
+
|
|
65
|
+
# @return [Boolean] Whether club is verified by Strava
|
|
21
66
|
property 'verified'
|
|
67
|
+
|
|
68
|
+
# @return [String] Club URL slug
|
|
22
69
|
property 'url'
|
|
23
|
-
|
|
70
|
+
|
|
71
|
+
# @return [String] URL to full-sized profile picture
|
|
24
72
|
property 'profile'
|
|
73
|
+
|
|
74
|
+
# @return [String] Icon representing the activity types
|
|
25
75
|
property 'activity_types_icon'
|
|
76
|
+
|
|
77
|
+
# @return [Array<Integer>] Dimensions of cover photo [width, height]
|
|
26
78
|
property 'dimensions'
|
|
79
|
+
|
|
80
|
+
# @return [String] Localized sport type string
|
|
27
81
|
property 'localized_sport_type'
|
|
28
82
|
|
|
83
|
+
#
|
|
84
|
+
# Returns the Strava web URL for this club.
|
|
85
|
+
#
|
|
86
|
+
# @return [String] Full URL to view the club on Strava.com
|
|
87
|
+
#
|
|
29
88
|
def strava_url
|
|
30
89
|
"https://www.strava.com/clubs/#{url || id}"
|
|
31
90
|
end
|
|
@@ -2,16 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents summary information about athlete's equipment/gear.
|
|
7
|
+
#
|
|
8
|
+
# Contains basic gear information without detailed specifications.
|
|
9
|
+
# Typically returned as part of athlete profile or activity data.
|
|
10
|
+
#
|
|
11
|
+
# Includes the Distance mixin for formatting accumulated distance.
|
|
12
|
+
#
|
|
13
|
+
# @example Access gear from athlete profile
|
|
14
|
+
# athlete = client.athlete
|
|
15
|
+
# athlete.bikes.each do |bike|
|
|
16
|
+
# puts "#{bike.name}: #{bike.distance_s}"
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# @see DetailedGear
|
|
20
|
+
# @see https://developers.strava.com/docs/reference/#api-models-SummaryGear
|
|
21
|
+
#
|
|
6
22
|
class SummaryGear < Strava::Models::Response
|
|
23
|
+
# @return [String] Gear identifier (e.g., "b12345" for bike, "g12345" for shoes)
|
|
7
24
|
property 'id'
|
|
25
|
+
|
|
26
|
+
# @return [Integer] Resource state indicator
|
|
8
27
|
property 'resource_state'
|
|
28
|
+
|
|
29
|
+
# @return [Boolean] Whether this is the athlete's primary gear for this type
|
|
9
30
|
property 'primary'
|
|
31
|
+
|
|
32
|
+
# @return [String] Gear name/title
|
|
10
33
|
property 'name'
|
|
34
|
+
|
|
11
35
|
include Mixins::Distance
|
|
12
|
-
|
|
36
|
+
|
|
37
|
+
# @return [String] Nickname for the gear
|
|
13
38
|
property 'nickname'
|
|
39
|
+
|
|
40
|
+
# @return [Boolean] Whether gear has been retired/is no longer in use
|
|
14
41
|
property 'retired'
|
|
42
|
+
|
|
43
|
+
# @return [Float] Distance in meters after conversion (likely for imperial users)
|
|
15
44
|
property 'converted_distance'
|
|
16
45
|
end
|
|
17
46
|
end
|
|
@@ -2,14 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents an athlete's personal record (PR) on a segment.
|
|
7
|
+
#
|
|
8
|
+
# Contains information about the athlete's best effort on a particular segment,
|
|
9
|
+
# including when it was achieved and how many times they've attempted the segment.
|
|
10
|
+
#
|
|
11
|
+
# @see https://developers.strava.com/docs/reference/#api-models-SummaryPRSegmentEffort Strava API SummaryPRSegmentEffort reference
|
|
12
|
+
# @see Strava::Models::SummarySegment
|
|
13
|
+
# @see Strava::Models::DetailedSegmentEffort
|
|
14
|
+
#
|
|
15
|
+
# @example Accessing PR information from a segment
|
|
16
|
+
# segment = client.segment(1234567)
|
|
17
|
+
# if segment.athlete_pr_effort
|
|
18
|
+
# pr = segment.athlete_pr_effort
|
|
19
|
+
# puts "Your PR: #{pr.pr_elapsed_time} seconds"
|
|
20
|
+
# puts "Set on: #{pr.pr_date}"
|
|
21
|
+
# puts "Total attempts: #{pr.effort_count}"
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
6
24
|
class SummaryPRSegmentEffort < Strava::Models::Response
|
|
25
|
+
# @return [Integer, nil] Activity ID where the PR was achieved
|
|
7
26
|
property 'pr_activity_id'
|
|
27
|
+
|
|
28
|
+
# @return [Integer, nil] Elapsed time for the PR effort in seconds
|
|
8
29
|
property 'pr_elapsed_time'
|
|
30
|
+
|
|
31
|
+
# @return [Date, nil] Date when the PR was set
|
|
9
32
|
property 'pr_date', transform_with: ->(v) { Date.parse(v) }
|
|
33
|
+
|
|
34
|
+
# @return [Integer] Total number of times the athlete has attempted this segment
|
|
10
35
|
property 'effort_count'
|
|
11
|
-
|
|
36
|
+
|
|
37
|
+
# @return [String, nil] Visibility setting for the PR effort
|
|
38
|
+
# @note Not documented by Strava API
|
|
12
39
|
property 'pr_visibility'
|
|
40
|
+
|
|
41
|
+
# @return [String, nil] Visibility setting for the activity containing the PR
|
|
42
|
+
# @note Not documented by Strava API
|
|
13
43
|
property 'pr_activity_visibility'
|
|
14
44
|
end
|
|
15
45
|
end
|
|
@@ -2,32 +2,110 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents summary information about a segment.
|
|
7
|
+
#
|
|
8
|
+
# A segment is a specific section of road or trail that athletes can compete on.
|
|
9
|
+
# This summary version contains key information about the segment including
|
|
10
|
+
# location, elevation, and the athlete's personal stats on it.
|
|
11
|
+
#
|
|
12
|
+
# @see https://developers.strava.com/docs/reference/#api-models-SummarySegment Strava API SummarySegment reference
|
|
13
|
+
# @see Strava::Models::DetailedSegment
|
|
14
|
+
# @see Strava::Models::ExplorerSegment
|
|
15
|
+
# @see Strava::Models::SummaryPRSegmentEffort
|
|
16
|
+
#
|
|
17
|
+
# @example Accessing segment information from an effort
|
|
18
|
+
# activity = client.activity(1234567890)
|
|
19
|
+
# activity.segment_efforts.each do |effort|
|
|
20
|
+
# segment = effort.segment
|
|
21
|
+
# puts "#{segment.name} (#{segment.distance_s})"
|
|
22
|
+
# puts " Location: #{segment.city}, #{segment.state}, #{segment.country}"
|
|
23
|
+
# puts " Grade: #{segment.average_grade}% (max: #{segment.maximum_grade}%)"
|
|
24
|
+
# puts " Elevation: #{segment.elevation_low}m - #{segment.elevation_high}m"
|
|
25
|
+
#
|
|
26
|
+
# if segment.athlete_pr_effort
|
|
27
|
+
# puts " Your PR: #{segment.athlete_pr_effort.pr_elapsed_time}s"
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
6
31
|
class SummarySegment < Strava::Models::Response
|
|
32
|
+
# @return [Integer] Unique identifier for this segment
|
|
7
33
|
property 'id'
|
|
34
|
+
|
|
35
|
+
# @return [String] Name of the segment
|
|
8
36
|
property 'name'
|
|
37
|
+
|
|
38
|
+
# @return [String] Activity type this segment is for ("Ride" or "Run")
|
|
9
39
|
property 'activity_type'
|
|
40
|
+
|
|
41
|
+
# Includes distance in meters and conversion helper methods
|
|
10
42
|
include Mixins::Distance
|
|
43
|
+
|
|
44
|
+
# @return [Float] Average grade/incline as a percentage
|
|
11
45
|
property 'average_grade'
|
|
46
|
+
|
|
47
|
+
# @return [Float] Maximum grade/incline as a percentage
|
|
12
48
|
property 'maximum_grade'
|
|
49
|
+
|
|
50
|
+
# @return [Float] Highest elevation point on the segment in meters
|
|
13
51
|
property 'elevation_high'
|
|
52
|
+
|
|
53
|
+
# @return [Float] Lowest elevation point on the segment in meters
|
|
14
54
|
property 'elevation_low'
|
|
55
|
+
|
|
56
|
+
# @return [LatLng] GPS coordinates of segment start point
|
|
15
57
|
property 'start_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
|
|
58
|
+
|
|
59
|
+
# @return [LatLng] GPS coordinates of segment end point
|
|
16
60
|
property 'end_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
|
|
61
|
+
|
|
62
|
+
# @return [Integer] Climb category (0=uncategorized, 5=easiest, 1=hardest, HC=hors catégorie)
|
|
17
63
|
property 'climb_category'
|
|
64
|
+
|
|
65
|
+
# @return [String, nil] City where the segment is located
|
|
18
66
|
property 'city'
|
|
67
|
+
|
|
68
|
+
# @return [String, nil] State/province where the segment is located
|
|
19
69
|
property 'state'
|
|
70
|
+
|
|
71
|
+
# @return [String, nil] Country where the segment is located
|
|
20
72
|
property 'country'
|
|
73
|
+
|
|
74
|
+
# @return [Boolean] Whether this is a private segment
|
|
21
75
|
property 'private'
|
|
76
|
+
|
|
77
|
+
# @return [SummaryPRSegmentEffort, nil] Athlete's personal record on this segment
|
|
22
78
|
property 'athlete_pr_effort', transform_with: ->(v) { Strava::Models::SummaryPRSegmentEffort.new(v) }
|
|
79
|
+
|
|
80
|
+
# @return [SummarySegmentEffort, nil] Athlete's statistics for this segment
|
|
23
81
|
property 'athlete_segment_stats', transform_with: ->(v) { Strava::Models::SummarySegmentEffort.new(v) }
|
|
24
|
-
|
|
82
|
+
|
|
83
|
+
# @return [Integer] Resource state indicator
|
|
84
|
+
# @note Not documented by Strava API
|
|
25
85
|
property 'resource_state'
|
|
86
|
+
|
|
87
|
+
# @return [String, nil] URL or path to elevation profile visualization
|
|
88
|
+
# @note Not documented by Strava API
|
|
26
89
|
property 'elevation_profile'
|
|
90
|
+
|
|
91
|
+
# @return [Array, nil] Array of elevation profile data
|
|
92
|
+
# @note Not documented by Strava API
|
|
27
93
|
property 'elevation_profiles'
|
|
94
|
+
|
|
95
|
+
# @return [Boolean, nil] Whether this segment has been flagged as hazardous
|
|
96
|
+
# @note Not documented by Strava API
|
|
28
97
|
property 'hazardous'
|
|
98
|
+
|
|
99
|
+
# @return [Boolean, nil] Whether the current athlete has starred this segment
|
|
100
|
+
# @note Not documented by Strava API
|
|
29
101
|
property 'starred'
|
|
102
|
+
|
|
103
|
+
# @return [Time, nil] Date when the athlete starred this segment
|
|
104
|
+
# @note Not documented by Strava API
|
|
30
105
|
property 'starred_date', transform_with: ->(v) { Time.parse(v) }
|
|
106
|
+
|
|
107
|
+
# @return [Integer, nil] Athlete's PR time on this segment in seconds
|
|
108
|
+
# @note Not documented by Strava API
|
|
31
109
|
property 'pr_time'
|
|
32
110
|
end
|
|
33
111
|
end
|
|
@@ -2,14 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents a summary of a segment effort within an activity.
|
|
7
|
+
#
|
|
8
|
+
# A segment effort is an attempt at a defined segment (a portion of road or trail).
|
|
9
|
+
# This summary version contains basic information about the effort without
|
|
10
|
+
# detailed statistics.
|
|
11
|
+
#
|
|
12
|
+
# @see https://developers.strava.com/docs/reference/#api-models-SummarySegmentEffort Strava API SummarySegmentEffort reference
|
|
13
|
+
# @see Strava::Models::DetailedSegmentEffort
|
|
14
|
+
# @see Strava::Models::DetailedActivity#segment_efforts
|
|
15
|
+
#
|
|
16
|
+
# @example Accessing segment efforts from an activity
|
|
17
|
+
# activity = client.activity(1234567890)
|
|
18
|
+
# activity.segment_efforts.each do |effort|
|
|
19
|
+
# puts "#{effort.name}: #{effort.elapsed_time_in_hours_s}"
|
|
20
|
+
# puts " KOM: #{effort.is_kom}"
|
|
21
|
+
# puts " Distance: #{effort.distance_s}"
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
6
24
|
class SummarySegmentEffort < Strava::Models::Response
|
|
25
|
+
# @return [Integer] Unique identifier for this segment effort
|
|
7
26
|
property 'id'
|
|
27
|
+
|
|
28
|
+
# @return [Integer] ID of the activity containing this segment effort
|
|
8
29
|
property 'activity_id'
|
|
30
|
+
|
|
31
|
+
# Includes elapsed_time (total time including stops) and helper methods
|
|
9
32
|
include Mixins::ElapsedTime
|
|
33
|
+
|
|
34
|
+
# @return [Time] Start time of the segment effort in UTC
|
|
10
35
|
property 'start_date', transform_with: ->(v) { Time.parse(v) }
|
|
36
|
+
|
|
37
|
+
# Includes start_date_local with timezone handling
|
|
11
38
|
include Mixins::StartDateLocal
|
|
39
|
+
|
|
40
|
+
# Includes distance in meters and conversion helper methods
|
|
12
41
|
include Mixins::Distance
|
|
42
|
+
|
|
43
|
+
# @return [Boolean] Whether this effort achieved KOM (King/Queen of the Mountain)
|
|
13
44
|
property 'is_kom'
|
|
14
45
|
end
|
|
15
46
|
end
|
|
@@ -2,10 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents a training zone range with time spent in that zone.
|
|
7
|
+
#
|
|
8
|
+
# Used in activity zone distributions to show how much time was spent
|
|
9
|
+
# at different intensity levels during an activity.
|
|
10
|
+
#
|
|
11
|
+
# @see https://developers.strava.com/docs/reference/#api-models-TimedZoneRange Strava API TimedZoneRange reference
|
|
12
|
+
# @see Strava::Models::ZoneRange
|
|
13
|
+
# @see Strava::Models::ActivityZone
|
|
14
|
+
#
|
|
15
|
+
# @example Viewing time distribution across zones
|
|
16
|
+
# zones = client.activity_zones(1234567890)
|
|
17
|
+
# hr_zone = zones.find { |z| z.type == 'heartrate' }
|
|
18
|
+
#
|
|
19
|
+
# hr_zone.distribution_buckets.each_with_index do |bucket, i|
|
|
20
|
+
# minutes = bucket.time / 60
|
|
21
|
+
# puts "Zone #{i + 1} (#{bucket.min}-#{bucket.max} bpm): #{minutes} minutes"
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
6
24
|
class TimedZoneRange < Strava::Models::Response
|
|
25
|
+
# @return [Integer] Maximum value for this zone (e.g., maximum heart rate or power)
|
|
7
26
|
property 'max'
|
|
27
|
+
|
|
28
|
+
# @return [Integer] Minimum value for this zone (e.g., minimum heart rate or power)
|
|
8
29
|
property 'min'
|
|
30
|
+
|
|
31
|
+
# @return [Integer] Time spent in this zone in seconds
|
|
9
32
|
property 'time'
|
|
10
33
|
end
|
|
11
34
|
end
|
data/lib/strava/models/token.rb
CHANGED
|
@@ -2,12 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
+
#
|
|
6
|
+
# Represents an OAuth token response from Strava.
|
|
7
|
+
#
|
|
8
|
+
# This model is returned when exchanging an authorization code for an access token
|
|
9
|
+
# or when refreshing an expired token. It contains the access token, refresh token,
|
|
10
|
+
# expiration time, and basic athlete information.
|
|
11
|
+
#
|
|
12
|
+
# Tokens expire after a period of time (typically 6 hours). When a token expires,
|
|
13
|
+
# use the refresh_token to obtain a new access_token via the OAuth flow.
|
|
14
|
+
#
|
|
15
|
+
# @example Inspecting token information
|
|
16
|
+
# token = client.oauth_token(code: 'auth_code')
|
|
17
|
+
# puts "Access Token: #{token.access_token}"
|
|
18
|
+
# puts "Refresh Token: #{token.refresh_token}"
|
|
19
|
+
# puts "Expires at: #{token.expires_at}"
|
|
20
|
+
# puts "Athlete: #{token.athlete.firstname} #{token.athlete.lastname}"
|
|
21
|
+
#
|
|
22
|
+
# @see Strava::OAuth::Client#oauth_token
|
|
23
|
+
# @see https://developers.strava.com/docs/authentication/
|
|
24
|
+
#
|
|
5
25
|
class Token < Strava::Models::Response
|
|
26
|
+
# @return [String] Type of token, typically "Bearer"
|
|
6
27
|
property 'token_type'
|
|
28
|
+
|
|
29
|
+
# @return [String] OAuth access token for API authentication
|
|
7
30
|
property 'access_token'
|
|
31
|
+
|
|
32
|
+
# @return [String] Refresh token for obtaining new access tokens
|
|
8
33
|
property 'refresh_token'
|
|
34
|
+
|
|
35
|
+
# @return [Integer] Number of seconds until token expires
|
|
9
36
|
property 'expires_in'
|
|
37
|
+
|
|
38
|
+
# @return [Time] Expiration time of the access token
|
|
10
39
|
property 'expires_at', transform_with: ->(v) { Time.at(v) }
|
|
40
|
+
|
|
41
|
+
# @return [Strava::Models::SummaryAthlete] Summary of the authenticated athlete
|
|
11
42
|
property 'athlete', transform_with: ->(v) { Strava::Models::SummaryAthlete.new(v) }
|
|
12
43
|
end
|
|
13
44
|
end
|
data/lib/strava/models/trend.rb
CHANGED
|
@@ -2,13 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents performance trend data.
|
|
7
|
+
#
|
|
8
|
+
# Contains trend information about speed and performance over time,
|
|
9
|
+
# showing whether performance is improving, declining, or staying consistent.
|
|
10
|
+
# This model is not documented in the official Strava API reference.
|
|
11
|
+
#
|
|
12
|
+
# @note This model is not documented by Strava API documentation. Properties
|
|
13
|
+
# are inferred from API responses.
|
|
14
|
+
#
|
|
15
|
+
# @see Strava::Models::SimilarActivities
|
|
16
|
+
#
|
|
17
|
+
# @example Accessing trend data
|
|
18
|
+
# activity = client.activity(1234567890)
|
|
19
|
+
# if activity.similar_activities&.trend
|
|
20
|
+
# trend = activity.similar_activities.trend
|
|
21
|
+
# puts "Trend direction: #{trend.direction}"
|
|
22
|
+
# puts "Speed range: #{trend.min_speed} - #{trend.max_speed} m/s"
|
|
23
|
+
# puts "Current activity index: #{trend.current_activity_index}"
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
6
26
|
class Trend < Strava::Models::Response
|
|
27
|
+
# @return [Array, nil] Array of speed values showing the trend
|
|
28
|
+
# @note Not documented by Strava API
|
|
7
29
|
property 'speeds'
|
|
30
|
+
|
|
31
|
+
# @return [Integer, nil] Index of current activity in the trend series
|
|
32
|
+
# @note Not documented by Strava API
|
|
8
33
|
property 'current_activity_index'
|
|
34
|
+
|
|
35
|
+
# @return [Float, nil] Minimum speed in the trend in meters per second
|
|
36
|
+
# @note Not documented by Strava API
|
|
9
37
|
property 'min_speed'
|
|
38
|
+
|
|
39
|
+
# @return [Float, nil] Median speed in the trend in meters per second
|
|
40
|
+
# @note Not documented by Strava API
|
|
10
41
|
property 'mid_speed'
|
|
42
|
+
|
|
43
|
+
# @return [Float, nil] Maximum speed in the trend in meters per second
|
|
44
|
+
# @note Not documented by Strava API
|
|
11
45
|
property 'max_speed'
|
|
46
|
+
|
|
47
|
+
# @return [Integer, nil] Trend direction indicator (e.g., -1=declining, 0=stable, 1=improving)
|
|
48
|
+
# @note Not documented by Strava API
|
|
12
49
|
property 'direction'
|
|
13
50
|
end
|
|
14
51
|
end
|
|
@@ -2,14 +2,49 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents the response from updating an activity.
|
|
7
|
+
#
|
|
8
|
+
# When you update an activity using the update_activity endpoint, Strava returns
|
|
9
|
+
# this model containing the fields that were successfully updated. This is a subset
|
|
10
|
+
# of the full activity data.
|
|
11
|
+
#
|
|
12
|
+
# @see https://developers.strava.com/docs/reference/#api-models-UpdatableActivity Strava API UpdatableActivity reference
|
|
13
|
+
# @see Strava::Api::Client#update_activity
|
|
14
|
+
# @see Strava::Models::DetailedActivity
|
|
15
|
+
#
|
|
16
|
+
# @example Updating activity properties
|
|
17
|
+
# updated = client.update_activity(1234567890,
|
|
18
|
+
# name: "Morning Run",
|
|
19
|
+
# description: "Great weather today!",
|
|
20
|
+
# commute: false,
|
|
21
|
+
# trainer: false,
|
|
22
|
+
# gear_id: "g12345"
|
|
23
|
+
# )
|
|
24
|
+
#
|
|
25
|
+
# puts "Activity renamed to: #{updated.name}"
|
|
26
|
+
# puts "Gear ID: #{updated.gear_id}"
|
|
27
|
+
#
|
|
6
28
|
class UpdatableActivity < Strava::Models::Response
|
|
29
|
+
# @return [Boolean, nil] Whether this activity is a commute
|
|
7
30
|
property 'commute'
|
|
31
|
+
|
|
32
|
+
# @return [Boolean, nil] Whether this activity was done on a trainer/treadmill
|
|
8
33
|
property 'trainer'
|
|
34
|
+
|
|
35
|
+
# @return [Boolean, nil] Whether to hide this activity from the home feed
|
|
9
36
|
property 'hide_from_home'
|
|
37
|
+
|
|
38
|
+
# @return [String, nil] Description of the activity
|
|
10
39
|
property 'description'
|
|
40
|
+
|
|
41
|
+
# @return [String, nil] Name/title of the activity
|
|
11
42
|
property 'name'
|
|
43
|
+
|
|
44
|
+
# @return [String, nil] Sport type (e.g., "Run", "Ride", "Swim")
|
|
12
45
|
property 'sport_type'
|
|
46
|
+
|
|
47
|
+
# @return [String, nil] ID of the gear (shoes/bike) used for this activity
|
|
13
48
|
property 'gear_id'
|
|
14
49
|
end
|
|
15
50
|
end
|
data/lib/strava/models/upload.rb
CHANGED
|
@@ -2,20 +2,69 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents an activity file upload status.
|
|
7
|
+
#
|
|
8
|
+
# When uploading activity files (GPX, TCX, FIT) to Strava, the upload is processed
|
|
9
|
+
# asynchronously. This model tracks the upload status and provides helper methods
|
|
10
|
+
# to check if processing is complete.
|
|
11
|
+
#
|
|
12
|
+
# @example Upload and poll for completion
|
|
13
|
+
# upload = client.create_upload(
|
|
14
|
+
# file: Faraday::UploadIO.new('activity.gpx', 'application/gpx+xml'),
|
|
15
|
+
# data_type: 'gpx'
|
|
16
|
+
# )
|
|
17
|
+
#
|
|
18
|
+
# while upload.processing?
|
|
19
|
+
# sleep 2
|
|
20
|
+
# upload = client.upload(upload.id)
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# if upload.error
|
|
24
|
+
# puts "Upload failed: #{upload.error}"
|
|
25
|
+
# else
|
|
26
|
+
# puts "Activity created: #{upload.activity_id}"
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# @see Strava::Api::Client#create_upload
|
|
30
|
+
# @see Strava::Api::Client#upload
|
|
31
|
+
# @see https://developers.strava.com/docs/reference/#api-models-Upload
|
|
32
|
+
#
|
|
6
33
|
class Upload < Strava::Models::Response
|
|
34
|
+
# @return [Integer] Upload ID
|
|
7
35
|
property 'id'
|
|
36
|
+
|
|
37
|
+
# @return [String] Upload ID as string
|
|
8
38
|
property 'id_str'
|
|
39
|
+
|
|
40
|
+
# @return [String] External identifier for the upload
|
|
9
41
|
property 'external_id'
|
|
42
|
+
|
|
43
|
+
# @return [String, nil] Error message if upload failed
|
|
10
44
|
property 'error'
|
|
45
|
+
|
|
46
|
+
# @return [String] Status message (e.g., "Your activity is ready.", "Your activity is still being processed.")
|
|
11
47
|
property 'status'
|
|
48
|
+
|
|
49
|
+
# @return [Integer, nil] Activity ID once processing is complete
|
|
12
50
|
property 'activity_id'
|
|
13
51
|
|
|
52
|
+
#
|
|
53
|
+
# Checks if the upload is still processing.
|
|
54
|
+
#
|
|
55
|
+
# @return [Boolean] true if upload is still being processed
|
|
56
|
+
# @raise [Strava::Errors::UploadError] if upload failed with an error
|
|
57
|
+
#
|
|
14
58
|
def processing?
|
|
15
59
|
validate!
|
|
16
60
|
activity_id.nil?
|
|
17
61
|
end
|
|
18
62
|
|
|
63
|
+
#
|
|
64
|
+
# Checks if the upload has completed processing.
|
|
65
|
+
#
|
|
66
|
+
# @return [Boolean] true if upload processing is complete
|
|
67
|
+
#
|
|
19
68
|
def processed?
|
|
20
69
|
!processing?
|
|
21
70
|
end
|
|
@@ -2,13 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents a waypoint on a route.
|
|
7
|
+
#
|
|
8
|
+
# Waypoints are markers along a route that can indicate points of interest,
|
|
9
|
+
# turns, or other significant locations. They include GPS coordinates and
|
|
10
|
+
# descriptive information.
|
|
11
|
+
#
|
|
12
|
+
# @see https://developers.strava.com/docs/reference/#api-models-Waypoint Strava API Waypoint reference
|
|
13
|
+
# @see Strava::Models::Route
|
|
14
|
+
# @see Strava::Models::LatLng
|
|
15
|
+
#
|
|
16
|
+
# @example Accessing route waypoints
|
|
17
|
+
# route = client.route(1234567)
|
|
18
|
+
# route.waypoints.each do |waypoint|
|
|
19
|
+
# puts "#{waypoint.title}: #{waypoint.description}"
|
|
20
|
+
# puts " Location: #{waypoint.latlng.lat}, #{waypoint.latlng.lng}"
|
|
21
|
+
# puts " Distance into route: #{waypoint.distance_into_route}m"
|
|
22
|
+
# puts " Categories: #{waypoint.categories.join(', ')}"
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
6
25
|
class Waypoint < Strava::Models::Response
|
|
26
|
+
# @return [LatLng] GPS coordinates of the waypoint
|
|
7
27
|
property 'latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
|
|
28
|
+
|
|
29
|
+
# @return [LatLng, nil] Target GPS coordinates (may differ from latlng for snapped waypoints)
|
|
8
30
|
property 'target_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
|
|
31
|
+
|
|
32
|
+
# @return [Array<String>] Categories or types for this waypoint (e.g., ["water", "rest"])
|
|
9
33
|
property 'categories'
|
|
34
|
+
|
|
35
|
+
# @return [String] Title or name of the waypoint
|
|
10
36
|
property 'title'
|
|
37
|
+
|
|
38
|
+
# @return [String, nil] Detailed description of the waypoint
|
|
11
39
|
property 'description'
|
|
40
|
+
|
|
41
|
+
# @return [Float] Distance from the start of the route to this waypoint in meters
|
|
12
42
|
property 'distance_into_route'
|
|
13
43
|
end
|
|
14
44
|
end
|