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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -2
  3. data/README.md +47 -58
  4. data/lib/strava/api/client.rb +69 -0
  5. data/lib/strava/api/config.rb +40 -0
  6. data/lib/strava/api/cursor.rb +32 -1
  7. data/lib/strava/api/endpoints/activities.rb +197 -57
  8. data/lib/strava/api/endpoints/athletes.rb +64 -8
  9. data/lib/strava/api/endpoints/clubs.rb +24 -59
  10. data/lib/strava/api/endpoints/gears.rb +11 -2
  11. data/lib/strava/api/endpoints/oauth.rb +45 -0
  12. data/lib/strava/api/endpoints/routes.rb +20 -13
  13. data/lib/strava/api/endpoints/segment_efforts.rb +15 -8
  14. data/lib/strava/api/endpoints/segments.rb +74 -21
  15. data/lib/strava/api/endpoints/streams.rb +22 -18
  16. data/lib/strava/api/endpoints/uploads.rb +12 -2
  17. data/lib/strava/api/pagination.rb +25 -0
  18. data/lib/strava/api/ratelimit.rb +34 -0
  19. data/lib/strava/deep_copyable.rb +20 -1
  20. data/lib/strava/errors/fault.rb +32 -0
  21. data/lib/strava/errors/ratelimit_error.rb +35 -0
  22. data/lib/strava/errors/upload_error.rb +55 -0
  23. data/lib/strava/logger.rb +27 -0
  24. data/lib/strava/models/achievement.rb +28 -1
  25. data/lib/strava/models/activity_stats.rb +47 -1
  26. data/lib/strava/models/activity_total.rb +25 -1
  27. data/lib/strava/models/activity_zone.rb +39 -2
  28. data/lib/strava/models/authorization.rb +13 -0
  29. data/lib/strava/models/base_stream.rb +22 -1
  30. data/lib/strava/models/club_event.rb +64 -1
  31. data/lib/strava/models/comment.rb +39 -1
  32. data/lib/strava/models/destination.rb +28 -1
  33. data/lib/strava/models/detailed_activity.rb +203 -2
  34. data/lib/strava/models/detailed_athlete.rb +104 -2
  35. data/lib/strava/models/detailed_club.rb +76 -2
  36. data/lib/strava/models/detailed_gear.rb +45 -2
  37. data/lib/strava/models/detailed_photo.rb +61 -1
  38. data/lib/strava/models/detailed_photos.rb +29 -1
  39. data/lib/strava/models/detailed_segment.rb +89 -2
  40. data/lib/strava/models/detailed_segment_effort.rb +92 -3
  41. data/lib/strava/models/explorer_segment.rb +55 -2
  42. data/lib/strava/models/heart_rate_zone_ranges.rb +29 -1
  43. data/lib/strava/models/kudoser.rb +29 -1
  44. data/lib/strava/models/lap.rb +62 -2
  45. data/lib/strava/models/lat_lng.rb +42 -4
  46. data/lib/strava/models/local_legend.rb +41 -1
  47. data/lib/strava/models/map.rb +31 -0
  48. data/lib/strava/models/meta_activity.rb +15 -2
  49. data/lib/strava/models/meta_athlete.rb +17 -2
  50. data/lib/strava/models/meta_club.rb +15 -1
  51. data/lib/strava/models/mixins/average_speed.rb +81 -3
  52. data/lib/strava/models/mixins/distance.rb +25 -0
  53. data/lib/strava/models/mixins/elapsed_time.rb +18 -0
  54. data/lib/strava/models/mixins/elevation_difference.rb +42 -0
  55. data/lib/strava/models/mixins/elevation_gain.rb +39 -0
  56. data/lib/strava/models/mixins/estimated_moving_time.rb +18 -0
  57. data/lib/strava/models/mixins/http_response.rb +36 -0
  58. data/lib/strava/models/mixins/moving_time.rb +18 -0
  59. data/lib/strava/models/mixins/sport_type.rb +39 -1
  60. data/lib/strava/models/mixins/start_date_local.rb +40 -24
  61. data/lib/strava/models/mixins/time_in_hours.rb +23 -0
  62. data/lib/strava/models/mixins/total_elevation_gain.rb +42 -0
  63. data/lib/strava/models/model.rb +14 -0
  64. data/lib/strava/models/photos_summary.rb +26 -2
  65. data/lib/strava/models/photos_summary_primary.rb +28 -2
  66. data/lib/strava/models/power_zone_ranges.rb +23 -1
  67. data/lib/strava/models/response.rb +18 -0
  68. data/lib/strava/models/route.rb +63 -2
  69. data/lib/strava/models/similar_activities.rb +57 -1
  70. data/lib/strava/models/split.rb +27 -2
  71. data/lib/strava/models/stats_visibility.rb +24 -1
  72. data/lib/strava/models/stream.rb +107 -0
  73. data/lib/strava/models/stream_set.rb +52 -1
  74. data/lib/strava/models/summary_activity.rb +145 -2
  75. data/lib/strava/models/summary_athlete.rb +54 -1
  76. data/lib/strava/models/summary_club.rb +61 -2
  77. data/lib/strava/models/summary_gear.rb +31 -2
  78. data/lib/strava/models/summary_pr_segment_effort.rb +32 -2
  79. data/lib/strava/models/summary_segment.rb +80 -2
  80. data/lib/strava/models/summary_segment_effort.rb +32 -1
  81. data/lib/strava/models/timed_zone_range.rb +24 -1
  82. data/lib/strava/models/token.rb +31 -0
  83. data/lib/strava/models/trend.rb +38 -1
  84. data/lib/strava/models/updatable_activity.rb +36 -1
  85. data/lib/strava/models/upload.rb +50 -1
  86. data/lib/strava/models/waypoint.rb +31 -1
  87. data/lib/strava/models/xoms.rb +35 -1
  88. data/lib/strava/models/zone_range.rb +20 -1
  89. data/lib/strava/models/zones.rb +32 -1
  90. data/lib/strava/oauth/client.rb +107 -19
  91. data/lib/strava/oauth/config.rb +41 -0
  92. data/lib/strava/version.rb +1 -1
  93. data/lib/strava/web/api_response.rb +28 -2
  94. data/lib/strava/web/client.rb +72 -2
  95. data/lib/strava/web/config.rb +40 -0
  96. data/lib/strava/web/connection.rb +39 -0
  97. data/lib/strava/web/raise_response_error.rb +47 -0
  98. data/lib/strava/web/request.rb +56 -0
  99. data/lib/strava/web/response.rb +18 -0
  100. data/lib/strava/webhooks/client.rb +108 -7
  101. data/lib/strava/webhooks/config.rb +44 -0
  102. data/lib/strava/webhooks/models/challenge.rb +40 -0
  103. data/lib/strava/webhooks/models/event.rb +50 -0
  104. data/lib/strava/webhooks/models/subscription.rb +27 -0
  105. data/lib/strava-ruby-client.rb +0 -2
  106. metadata +2 -4
  107. data/lib/strava/models/club_activity.rb +0 -22
  108. data/lib/strava/models/club_athlete.rb +0 -21
@@ -2,10 +2,41 @@
2
2
 
3
3
  module Strava
4
4
  module Web
5
+ #
6
+ # Faraday middleware that raises exceptions for HTTP error responses.
7
+ #
8
+ # This middleware intercepts HTTP responses and raises appropriate exceptions
9
+ # based on the status code. It handles common HTTP error statuses and maps them
10
+ # to specific Strava error classes, including special handling for rate limiting
11
+ # (429) and resource not found (404) responses.
12
+ #
13
+ # @see Faraday::Middleware
14
+ # @see Strava::Errors::Fault
15
+ # @see Strava::Errors::RatelimitError
16
+ #
5
17
  class RaiseResponseError < ::Faraday::Middleware
18
+ # @return [Hash] Default options inherited from Faraday's RaiseError middleware
6
19
  DEFAULT_OPTIONS = Faraday::Response::RaiseError::DEFAULT_OPTIONS
20
+
21
+ # @return [Range] HTTP status codes that are considered client errors (400-599)
7
22
  CLIENT_ERROR_STATUSES = (400...600)
8
23
 
24
+ #
25
+ # Callback invoked when an HTTP response is complete.
26
+ #
27
+ # Examines the HTTP status code and raises appropriate exceptions:
28
+ # - 404: Faraday::ResourceNotFound
29
+ # - 407: Faraday::ConnectionFailed (proxy authentication required)
30
+ # - 429: Strava::Errors::RatelimitError (rate limit exceeded)
31
+ # - 400-599: Strava::Errors::Fault (general client/server errors)
32
+ #
33
+ # @param env [Faraday::Env] The Faraday request/response environment
34
+ # @raise [Faraday::ResourceNotFound] When resource is not found (404)
35
+ # @raise [Faraday::ConnectionFailed] When proxy authentication fails (407)
36
+ # @raise [Strava::Errors::RatelimitError] When rate limit is exceeded (429)
37
+ # @raise [Strava::Errors::Fault] For other client/server errors (400-599)
38
+ # @return [void]
39
+ #
9
40
  def on_complete(env)
10
41
  case env[:status]
11
42
  when 404
@@ -20,6 +51,16 @@ module Strava
20
51
  end
21
52
  end
22
53
 
54
+ #
55
+ # Extracts response values from the Faraday environment.
56
+ #
57
+ # Builds a hash containing response information (status, headers, body)
58
+ # and optionally includes request details if the middleware is configured
59
+ # with `include_request: true`.
60
+ #
61
+ # @param env [Faraday::Env] The Faraday request/response environment
62
+ # @return [Hash] Response values including status, headers, body, and optionally request details
63
+ #
23
64
  def response_values(env)
24
65
  response = {
25
66
  status: env.status,
@@ -43,6 +84,12 @@ module Strava
43
84
  )
44
85
  end
45
86
 
87
+ #
88
+ # Extracts and decodes query parameters from the request URL.
89
+ #
90
+ # @param env [Faraday::Env] The Faraday request/response environment
91
+ # @return [Hash] Decoded query parameters
92
+ #
46
93
  def query_params(env)
47
94
  env.request.params_encoder ||= Faraday::Utils.default_params_encoder
48
95
  env.params_encoder.decode(env.url.query)
@@ -2,25 +2,81 @@
2
2
 
3
3
  module Strava
4
4
  module Web
5
+ #
6
+ # HTTP request methods for Strava web clients.
7
+ #
8
+ # This module provides GET, POST, PUT, and DELETE HTTP methods for making
9
+ # requests to Strava APIs. All methods return a wrapped response object
10
+ # that provides easy access to response data and metadata.
11
+ #
12
+ # @api private
13
+ #
5
14
  module Request
15
+ #
16
+ # Perform an HTTP GET request.
17
+ #
18
+ # @param path [String] The API path (relative to endpoint)
19
+ # @param options [Hash] Query parameters and options
20
+ #
21
+ # @return [Strava::Web::Response] Wrapped HTTP response
22
+ #
6
23
  def get(path, options = {})
7
24
  request(:get, path, options)
8
25
  end
9
26
 
27
+ #
28
+ # Perform an HTTP POST request.
29
+ #
30
+ # @param path [String] The API path (relative to endpoint)
31
+ # @param options [Hash] Request body parameters and options
32
+ #
33
+ # @return [Strava::Web::Response] Wrapped HTTP response
34
+ #
10
35
  def post(path, options = {})
11
36
  request(:post, path, options)
12
37
  end
13
38
 
39
+ #
40
+ # Perform an HTTP PUT request.
41
+ #
42
+ # @param path [String] The API path (relative to endpoint)
43
+ # @param options [Hash] Request body parameters and options
44
+ #
45
+ # @return [Strava::Web::Response] Wrapped HTTP response
46
+ #
14
47
  def put(path, options = {})
15
48
  request(:put, path, options)
16
49
  end
17
50
 
51
+ #
52
+ # Perform an HTTP DELETE request.
53
+ #
54
+ # @param path [String] The API path (relative to endpoint)
55
+ # @param options [Hash] Query parameters and options
56
+ #
57
+ # @return [Strava::Web::Response] Wrapped HTTP response
58
+ #
18
59
  def delete(path, options = {})
19
60
  request(:delete, path, options)
20
61
  end
21
62
 
22
63
  private
23
64
 
65
+ #
66
+ # Executes an HTTP request with the specified method.
67
+ #
68
+ # Constructs the full URL from the endpoint and path, sends the request
69
+ # using Faraday, and wraps the response in a Strava::Web::Response object.
70
+ #
71
+ # @api private
72
+ # @param method [Symbol] HTTP method (:get, :post, :put, :delete)
73
+ # @param path [String] The API path (relative to endpoint)
74
+ # @param options [Hash] Request parameters and options
75
+ # @option options [String] :endpoint Override the default endpoint URL
76
+ # @option options [Hash] :request Faraday request options (timeouts, etc.)
77
+ #
78
+ # @return [Strava::Web::Response] Wrapped HTTP response
79
+ #
24
80
  def request(method, path, options)
25
81
  options = options.dup if options.key?(:request) || options.key?(:endpoint)
26
82
  root = options.delete(:endpoint) || endpoint
@@ -75,6 +75,17 @@ module Strava
75
75
  end
76
76
  end
77
77
 
78
+ #
79
+ # Delegates missing methods to the response body or array.
80
+ #
81
+ # If the response is an array, delegates methods to the array.
82
+ # Otherwise, delegates to the response body hash, allowing access
83
+ # to response fields as if they were methods.
84
+ #
85
+ # @param method_symbol [Symbol] The method name to forward
86
+ # @param args [Array] Arguments to pass to the method
87
+ # @return [Object] Result from the delegated method
88
+ #
78
89
  def method_missing(method_symbol, ...)
79
90
  case @response
80
91
  when Array
@@ -84,6 +95,13 @@ module Strava
84
95
  end
85
96
  end
86
97
 
98
+ #
99
+ # Checks if the response body or array responds to a method.
100
+ #
101
+ # @param method_name [Symbol] The method name to check
102
+ # @param include_private [Boolean] Whether to include private methods
103
+ # @return [Boolean] true if the response responds to the method
104
+ #
87
105
  def respond_to_missing?(method_name, include_private = false)
88
106
  super
89
107
  end
@@ -2,9 +2,49 @@
2
2
 
3
3
  module Strava
4
4
  module Webhooks
5
+ #
6
+ # Webhooks client for Strava push subscriptions.
7
+ #
8
+ # Strava provides webhooks for receiving real-time updates about athlete activities
9
+ # and other events. This client manages webhook subscriptions (create, list, delete).
10
+ #
11
+ # Before creating a subscription, you must implement an HTTP endpoint that:
12
+ # 1. Handles GET requests for subscription validation (Challenge)
13
+ # 2. Handles POST requests for webhook events (Event)
14
+ #
15
+ # @example Create and manage a webhook subscription
16
+ # client = Strava::Webhooks::Client.new(
17
+ # client_id: "your_client_id",
18
+ # client_secret: "your_client_secret"
19
+ # )
20
+ #
21
+ # # Create subscription
22
+ # subscription = client.create_push_subscription(
23
+ # callback_url: 'https://myapp.com/strava/webhook',
24
+ # verify_token: 'my_verify_token'
25
+ # )
26
+ #
27
+ # # List subscriptions
28
+ # subscriptions = client.push_subscriptions
29
+ #
30
+ # # Delete subscription
31
+ # client.delete_push_subscription(subscription.id)
32
+ #
33
+ # @see https://developers.strava.com/docs/webhooks/
34
+ # @see Strava::Webhooks::Models::Challenge
35
+ # @see Strava::Webhooks::Models::Event
36
+ #
5
37
  class Client < Strava::Web::Client
6
38
  attr_accessor(*Config::ATTRIBUTES)
7
39
 
40
+ #
41
+ # Initialize a new Webhooks client.
42
+ #
43
+ # @param [Hash] options Configuration options
44
+ # @option options [String] :client_id Strava application client ID (required)
45
+ # @option options [String] :client_secret Strava application client secret (required)
46
+ # @option options [String] :endpoint API endpoint URL (defaults to https://www.strava.com/api/v3)
47
+ #
8
48
  def initialize(options = {})
9
49
  Strava::Webhooks::Config::ATTRIBUTES.each do |key|
10
50
  send("#{key}=", options[key] || Strava::Webhooks.config.send(key))
@@ -17,7 +57,20 @@ module Strava
17
57
  end
18
58
 
19
59
  #
20
- # Get existing push subscriptions.
60
+ # List existing push subscriptions.
61
+ #
62
+ # Returns all active webhook subscriptions for your application.
63
+ # Typically, Strava only allows one subscription per application.
64
+ #
65
+ # @param [Hash] options Additional options
66
+ #
67
+ # @return [Array<Strava::Webhooks::Models::Subscription>] Array of subscriptions
68
+ #
69
+ # @example List subscriptions
70
+ # subscriptions = client.push_subscriptions
71
+ # subscriptions.each { |sub| puts "ID: #{sub.id}, URL: #{sub.callback_url}" }
72
+ #
73
+ # @see https://developers.strava.com/docs/webhooks/
21
74
  #
22
75
  def push_subscriptions(options = {})
23
76
  get('push_subscriptions', options).map do |row|
@@ -26,7 +79,20 @@ module Strava
26
79
  end
27
80
 
28
81
  #
29
- # Delete an existing push subscription.
82
+ # Delete a push subscription.
83
+ #
84
+ # Removes an existing webhook subscription by ID. After deletion,
85
+ # your application will no longer receive webhook events.
86
+ #
87
+ # @param [Integer, Hash] id_or_options Subscription ID or options hash with :id key
88
+ # @param [Hash] options Additional options
89
+ #
90
+ # @return [nil]
91
+ #
92
+ # @example Delete subscription
93
+ # client.delete_push_subscription(12345)
94
+ #
95
+ # @see https://developers.strava.com/docs/webhooks/
30
96
  #
31
97
  def delete_push_subscription(id_or_options, options = {})
32
98
  id, options = parse_args(id_or_options, options)
@@ -35,22 +101,57 @@ module Strava
35
101
  end
36
102
 
37
103
  #
38
- # Create a subscription.
104
+ # Create a new push subscription.
105
+ #
106
+ # Creates a webhook subscription for receiving real-time activity updates.
107
+ # Your callback URL must be publicly accessible and handle both GET (for validation)
108
+ # and POST (for events) requests.
109
+ #
110
+ # Strava will send a GET request to validate your callback URL before creating
111
+ # the subscription. Your endpoint must respond with the challenge token.
112
+ #
113
+ # @param [Hash] options Subscription parameters
114
+ # @option options [String] :callback_url Public HTTPS URL where webhook events will be sent (required)
115
+ # @option options [String] :verify_token Token for validating webhook challenges (required)
116
+ #
117
+ # @return [Strava::Webhooks::Models::Subscription] The created subscription
118
+ #
119
+ # @example Create subscription
120
+ # subscription = client.create_push_subscription(
121
+ # callback_url: 'https://myapp.com/strava/webhook',
122
+ # verify_token: 'my_secret_token_123'
123
+ # )
124
+ # puts "Subscription ID: #{subscription.id}"
39
125
  #
40
- # @option options [String] :callback_url
41
- # Address where webhook events will be sent.
42
- # @option options [String] :verify_token
43
- # String chosen by the application owner for client security. An identical string should be returned by Strava's subscription service.
126
+ # @see https://developers.strava.com/docs/webhooks/
127
+ # @see Strava::Webhooks::Models::Challenge
44
128
  #
45
129
  def create_push_subscription(options = {})
46
130
  Strava::Webhooks::Models::Subscription.new(post('push_subscriptions', options))
47
131
  end
48
132
 
49
133
  class << self
134
+ #
135
+ # Configure the Webhooks client with a block.
136
+ #
137
+ # @yield [Config] Yields the configuration module for setup
138
+ # @return [Module] The Config module
139
+ #
140
+ # @example
141
+ # Strava::Webhooks::Client.configure do |config|
142
+ # config.client_id = ENV['STRAVA_CLIENT_ID']
143
+ # config.client_secret = ENV['STRAVA_CLIENT_SECRET']
144
+ # end
145
+ #
50
146
  def configure
51
147
  block_given? ? yield(Config) : Config
52
148
  end
53
149
 
150
+ #
151
+ # Returns the current Webhooks client configuration.
152
+ #
153
+ # @return [Module] The Config module
154
+ #
54
155
  def config
55
156
  Config
56
157
  end
@@ -2,9 +2,28 @@
2
2
 
3
3
  module Strava
4
4
  module Webhooks
5
+ #
6
+ # Configuration module for the Webhooks client.
7
+ #
8
+ # This module manages webhook-specific configuration settings including the
9
+ # API endpoint URL and application credentials (client ID and secret) required
10
+ # for managing webhook subscriptions.
11
+ #
12
+ # Webhooks allow your application to receive real-time notifications when
13
+ # athletes create new activities or update their profile information.
14
+ #
15
+ # @example Configure Webhooks client
16
+ # Strava::Webhooks.configure do |config|
17
+ # config.client_id = ENV['STRAVA_CLIENT_ID']
18
+ # config.client_secret = ENV['STRAVA_CLIENT_SECRET']
19
+ # end
20
+ #
21
+ # @see https://developers.strava.com/docs/webhooks/
22
+ #
5
23
  module Config
6
24
  extend self
7
25
 
26
+ # @return [Array<Symbol>] List of configurable webhook attributes
8
27
  ATTRIBUTES = %i[
9
28
  endpoint
10
29
  client_id
@@ -13,6 +32,14 @@ module Strava
13
32
 
14
33
  attr_accessor(*Config::ATTRIBUTES)
15
34
 
35
+ #
36
+ # Reset configuration to default values.
37
+ #
38
+ # Sets the endpoint to the default Strava API v3 URL and clears
39
+ # the client credentials.
40
+ #
41
+ # @return [void]
42
+ #
16
43
  def reset
17
44
  self.endpoint = 'https://www.strava.com/api/v3'
18
45
  self.client_id = nil
@@ -21,10 +48,27 @@ module Strava
21
48
  end
22
49
 
23
50
  class << self
51
+ #
52
+ # Configure the Webhooks client with a block.
53
+ #
54
+ # @yield [Config] Yields the configuration module for setup
55
+ # @return [Module] The Config module
56
+ #
57
+ # @example
58
+ # Strava::Webhooks.configure do |config|
59
+ # config.client_id = '12345'
60
+ # config.client_secret = 'your_client_secret'
61
+ # end
62
+ #
24
63
  def configure
25
64
  block_given? ? yield(Config) : Config
26
65
  end
27
66
 
67
+ #
68
+ # Returns the current Webhooks configuration.
69
+ #
70
+ # @return [Module] The Config module
71
+ #
28
72
  def config
29
73
  Config
30
74
  end
@@ -3,11 +3,51 @@
3
3
  module Strava
4
4
  module Webhooks
5
5
  module Models
6
+ #
7
+ # Represents a webhook subscription validation challenge.
8
+ #
9
+ # When creating a webhook subscription, Strava sends a GET request to your
10
+ # callback URL with challenge parameters. Your application must validate the
11
+ # verify_token and respond with the challenge value.
12
+ #
13
+ # @example Handle webhook challenge in Rails
14
+ # def webhook
15
+ # if request.get?
16
+ # challenge = Strava::Webhooks::Models::Challenge.new(request.query_parameters)
17
+ # if challenge.verify_token == ENV['STRAVA_VERIFY_TOKEN']
18
+ # render json: challenge.response
19
+ # else
20
+ # head :forbidden
21
+ # end
22
+ # end
23
+ # end
24
+ #
25
+ # @example Handle challenge in Sinatra
26
+ # get '/webhook' do
27
+ # challenge = Strava::Webhooks::Models::Challenge.new(params)
28
+ # halt 403 unless challenge.verify_token == ENV['STRAVA_VERIFY_TOKEN']
29
+ # content_type :json
30
+ # challenge.response.to_json
31
+ # end
32
+ #
33
+ # @see Strava::Webhooks::Client#create_push_subscription
34
+ # @see https://developers.strava.com/docs/webhooks/
35
+ #
6
36
  class Challenge < Hashie::Trash
37
+ # @return [String] Subscription mode, typically "subscribe"
7
38
  property 'mode', from: 'hub.mode'
39
+
40
+ # @return [String] Verification token to validate the request
8
41
  property 'verify_token', from: 'hub.verify_token'
42
+
43
+ # @return [String] Challenge value that must be echoed back
9
44
  property 'challenge', from: 'hub.challenge'
10
45
 
46
+ #
47
+ # Returns the response hash that should be sent back to Strava.
48
+ #
49
+ # @return [Hash] Response containing the challenge value
50
+ #
11
51
  def response
12
52
  { 'hub.challenge' => challenge }
13
53
  end
@@ -3,13 +3,63 @@
3
3
  module Strava
4
4
  module Webhooks
5
5
  module Models
6
+ #
7
+ # Represents a webhook event from Strava.
8
+ #
9
+ # After successfully creating a webhook subscription, Strava will send POST
10
+ # requests to your callback URL when activity events occur. Events include
11
+ # activity creation, updates, and deletions.
12
+ #
13
+ # @example Handle webhook event in Rails
14
+ # def webhook
15
+ # if request.post?
16
+ # event = Strava::Webhooks::Models::Event.new(JSON.parse(request.body.read))
17
+ #
18
+ # case event.object_type
19
+ # when 'activity'
20
+ # case event.aspect_type
21
+ # when 'create'
22
+ # # Fetch and process the new activity
23
+ # activity = client.activity(event.id)
24
+ # process_new_activity(activity)
25
+ # when 'update'
26
+ # # Handle activity update
27
+ # puts "Activity #{event.id} updated: #{event.updates.inspect}"
28
+ # when 'delete'
29
+ # # Handle activity deletion
30
+ # delete_activity(event.id)
31
+ # end
32
+ # when 'athlete'
33
+ # # Handle athlete updates (authorization revoked, etc.)
34
+ # end
35
+ #
36
+ # head :ok
37
+ # end
38
+ # end
39
+ #
40
+ # @see Strava::Webhooks::Client#create_push_subscription
41
+ # @see https://developers.strava.com/docs/webhooks/
42
+ #
6
43
  class Event < Hashie::Trash
44
+ # @return [String] Type of object (e.g., "activity", "athlete")
7
45
  property 'object_type'
46
+
47
+ # @return [Integer] ID of the object (activity ID, athlete ID, etc.)
8
48
  property 'id', from: 'object_id'
49
+
50
+ # @return [String] Type of event: "create", "update", or "delete"
9
51
  property 'aspect_type'
52
+
53
+ # @return [Hash] Map of updated properties (only for update events)
10
54
  property 'updates'
55
+
56
+ # @return [Integer] Athlete ID who owns the object
11
57
  property 'owner_id'
58
+
59
+ # @return [Integer] ID of the webhook subscription
12
60
  property 'subscription_id'
61
+
62
+ # @return [Time] Timestamp when the event occurred
13
63
  property 'event_time', transform_with: ->(v) { Time.at(v) }
14
64
  end
15
65
  end
@@ -3,12 +3,39 @@
3
3
  module Strava
4
4
  module Webhooks
5
5
  module Models
6
+ #
7
+ # Represents a webhook subscription.
8
+ #
9
+ # Webhook subscriptions allow your application to receive real-time notifications
10
+ # when athletes create or update activities, or update their profile information.
11
+ # Each subscription is associated with a callback URL where events will be posted.
12
+ #
13
+ # @example List subscriptions
14
+ # subscriptions = client.subscriptions
15
+ # subscriptions.each do |sub|
16
+ # puts "Subscription #{sub.id}: #{sub.callback_url}"
17
+ # end
18
+ #
19
+ # @see Strava::Webhooks::Client
20
+ # @see https://developers.strava.com/docs/webhooks/
21
+ #
6
22
  class Subscription < Strava::Models::Response
23
+ # @return [Integer] The subscription ID
7
24
  property 'id'
25
+
26
+ # @return [Integer] The ID of the application that created the subscription
8
27
  property 'application_id'
28
+
29
+ # @return [String] The callback URL where webhook events will be posted
9
30
  property 'callback_url'
31
+
32
+ # @return [Integer] Resource state indicator
10
33
  property 'resource_state'
34
+
35
+ # @return [Time] When the subscription was created
11
36
  property 'created_at', transform_with: ->(v) { Time.parse(v) }
37
+
38
+ # @return [Time] When the subscription was last updated
12
39
  property 'updated_at', transform_with: ->(v) { Time.parse(v) }
13
40
  end
14
41
  end
@@ -44,8 +44,6 @@ require_relative 'strava/models/activity_stats'
44
44
  require_relative 'strava/models/activity_total'
45
45
  require_relative 'strava/models/activity_zone'
46
46
  require_relative 'strava/models/base_stream'
47
- require_relative 'strava/models/club_activity'
48
- require_relative 'strava/models/club_athlete'
49
47
  require_relative 'strava/models/club_event'
50
48
  require_relative 'strava/models/comment'
51
49
  require_relative 'strava/models/destination'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strava-ruby-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.pre.2
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Doubrovkine
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-22 00:00:00.000000000 Z
11
+ date: 2026-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -108,8 +108,6 @@ files:
108
108
  - lib/strava/models/activity_zone.rb
109
109
  - lib/strava/models/authorization.rb
110
110
  - lib/strava/models/base_stream.rb
111
- - lib/strava/models/club_activity.rb
112
- - lib/strava/models/club_athlete.rb
113
111
  - lib/strava/models/club_event.rb
114
112
  - lib/strava/models/comment.rb
115
113
  - lib/strava/models/destination.rb
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Strava
4
- module Models
5
- # https://developers.strava.com/docs/reference/#api-models-ClubActivity
6
- class ClubActivity < Strava::Models::Response
7
- include Mixins::ElevationGain
8
- include Mixins::SportType
9
-
10
- property 'athlete', transform_with: ->(v) { Strava::Models::MetaAthlete.new(v) }
11
- property 'name'
12
- include Mixins::Distance
13
- include Mixins::MovingTime
14
- include Mixins::ElapsedTime
15
- include Mixins::TotalElevationGain
16
- include Mixins::SportType
17
- property 'workout_type'
18
- # undocumented
19
- property 'resource_state'
20
- end
21
- end
22
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Strava
4
- module Models
5
- # https://developers.strava.com/docs/reference/#api-models-ClubAthlete
6
- class ClubAthlete < Strava::Models::Response
7
- property 'resource_state'
8
- property 'firstname'
9
- property 'lastname'
10
- property 'member'
11
- property 'admin'
12
- property 'owner'
13
- # undocumented
14
- property 'membership'
15
-
16
- def name
17
- [firstname, lastname].compact.join(' ') if firstname || lastname
18
- end
19
- end
20
- end
21
- end