calendly 0.1.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a6dc0f127f4092b13891a3e4515f513973f23fc287ed6ee5b4b2cfd76f46f68
4
- data.tar.gz: bc724082ae45976974c064899a63080a2ab1b9fea521fa301706c7e732efd9e3
3
+ metadata.gz: 3656dc7886aad2a35932152a25f601d2160bed7f53b4ead91e67eb4cb82bb433
4
+ data.tar.gz: 337d5637a69e30e1dcc943ac1332f38b1675e3d55e0c09049d9308661b4edbe3
5
5
  SHA512:
6
- metadata.gz: 885928fabc15c7a08c6a670255b5da769a5e59637d2832e863dd7b54a2146217544a3fdfd2461714ce4e9819adbbcc95deb12eaece81fa45167893b97f0101d1
7
- data.tar.gz: 1a010d94d5feaa3c2103dc10608cb20364fadcaddc0cfa51f5b7e39ed062bbd218d6c40e1d86e84f384035230500f7141b30cc9cfd95006abe5160f05f6039d1
6
+ metadata.gz: 32d0c18ebb375a99fb1b23b4365f99ba5957ebbbfed497690ef7d6db8bb0e0ada413853a927892963af62cc21afe39ad6f8d5740831af2e4e881fcc8e9bb5017
7
+ data.tar.gz: 81a59436778d27892dd325496bc234bea9380fba303b872a2d04ba6ea4b18d73b94d3a13133f7b90f2a68f19a994263ef464a60332239df3f61e064a6d116841
@@ -23,12 +23,11 @@ Metrics/BlockNesting:
23
23
  Max: 2
24
24
 
25
25
  Layout/LineLength:
26
- AllowURI: true
27
- Enabled: false
26
+ Max: 120
28
27
 
29
28
  Metrics/MethodLength:
30
29
  CountComments: false
31
- Max: 15
30
+ Max: 20
32
31
 
33
32
  Metrics/ParameterLists:
34
33
  Max: 4
@@ -39,10 +38,10 @@ Metrics/AbcSize:
39
38
 
40
39
  Style/CollectionMethods:
41
40
  PreferredMethods:
42
- map: 'collect'
43
- reduce: 'inject'
44
- find: 'detect'
45
- find_all: 'select'
41
+ map: "collect"
42
+ reduce: "inject"
43
+ find: "detect"
44
+ find_all: "select"
46
45
 
47
46
  Style/Documentation:
48
47
  Enabled: false
@@ -60,10 +59,13 @@ Style/ExpandPathArguments:
60
59
  Enabled: false
61
60
 
62
61
  Style/HashSyntax:
63
- EnforcedStyle: hash_rockets
62
+ EnforcedStyle: ruby19
64
63
 
65
64
  Style/Lambda:
66
65
  Enabled: false
67
66
 
68
67
  Style/RaiseArgs:
69
- EnforcedStyle: compact
68
+ EnforcedStyle: compact
69
+
70
+ Style/AsciiComments:
71
+ Enabled: false
@@ -1,23 +1,49 @@
1
- # 0.1.0
1
+ # CHANGELOG
2
+
3
+ ## 0.3.0
4
+
5
+ - remove zeitwerk dependency. (refs #16)
6
+
7
+ ## 0.2.0
8
+
9
+ - save fetched data in cache. (refs #14)
10
+
11
+ ## 0.1.3
12
+
13
+ - support webhook APIs (refs #9)
14
+ - `GET /webhook_subscriptions`
15
+ - `GET /webhook_subscriptions/{webhook_uuid}`
16
+ - `POST /webhook_subscriptions`
17
+ - `DELETE /webhook_subscriptions/{webhook_uuid}`
18
+
19
+ ## 0.1.2
20
+
21
+ - fix rubocop warnings.
22
+
23
+ ## 0.1.1
24
+
25
+ - add tests to make coverage 100%.
26
+
27
+ ## 0.1.0
2
28
 
3
29
  - define methods to access associated resources with each model.
4
30
  - rename methods:
5
31
  - `Calendly::Client#events` to `Calendly::Client#scheduled_events`
6
32
 
7
- # 0.0.7.alpha
33
+ ## 0.0.7.alpha
8
34
 
9
35
  - support APIs
10
36
  - `POST /organizations/{uuid}/invitations`
11
37
  - `DELETE /organizations/{org_uuid}/invitations/{invitation_uuid}`
12
38
  - `DELETE /organization_memberships/{uuid}`
13
39
 
14
- # 0.0.6.alpha
40
+ ## 0.0.6.alpha
15
41
 
16
42
  - support APIs
17
43
  - `GET /organizations/{uuid}/invitations`
18
44
  - `GET /organizations/{organization_uuid}/invitations/{invitation_uuid}`
19
45
 
20
- # 0.0.5.alpha
46
+ ## 0.0.5.alpha
21
47
 
22
48
  - support APIs
23
49
  - `GET /organization_memberships`
@@ -26,24 +52,24 @@
26
52
  - Invitee#event to Invitee#event_uri
27
53
  - Event#event_type to Event#event_type_uri
28
54
 
29
- # 0.0.4.alpha
55
+ ## 0.0.4.alpha
30
56
 
31
57
  - support APIs
32
58
  - `GET /scheduled_events/{event_uuid}/invitees`
33
59
  - `GET /scheduled_events/{event_uuid}/invitees/{invitee_uuid}`
34
60
 
35
- # 0.0.3.alpha
61
+ ## 0.0.3.alpha
36
62
 
37
63
  - support APIs
38
64
  - `GET /scheduled_events`
39
65
  - `GET /scheduled_events/{uuid}`
40
66
 
41
- # 0.0.2.alpha
67
+ ## 0.0.2.alpha
42
68
 
43
69
  - support APIs
44
70
  - `GET /event_types`
45
71
 
46
- # 0.0.1.alpha
72
+ ## 0.0.1.alpha
47
73
 
48
74
  - Initial release
49
75
  - support APIs
data/README.md CHANGED
@@ -5,37 +5,7 @@
5
5
  [![Gem Version](https://badge.fury.io/rb/calendly.svg)](http://badge.fury.io/rb/calendly)
6
6
  [![license](https://img.shields.io/github/license/koshilife/calendly-api-ruby-client)](https://github.com/koshilife/calendly-api-ruby-client/blob/master/LICENSE.txt)
7
7
 
8
- ## About
9
-
10
- These client libraries are created for [Calendly v2 APIs](https://calendly.stoplight.io/docs/gh/calendly/api-docs).
11
-
12
- As of August 2020, Calendly v2 API is currently undergoing an upgrade.
13
- This library is trying to follow and support for the upgrade.
14
-
15
- As of now the supported statuses each Calendly API are as below.
16
-
17
- ## Supported statuses each Calendly API
18
-
19
- - User
20
- - [x] Get basic information about a user
21
- - EventType
22
- - [ ] Get Event Type (This endpoint hasn't been released yet.)
23
- - [x] User Event Types
24
- - Organization
25
- - [x] Get Organization Invitation
26
- - [x] Get Organization Invitations
27
- - [x] Get Organization Membership
28
- - [x] Get a list of Organization Memberships
29
- - [x] Invite a person to Organization
30
- - [x] Remove a User from an Organization
31
- - [x] Revoke Organization Invitation
32
- - ScheduledEvent
33
- - [x] Get Event
34
- - [x] Get Invitee of an Event
35
- - [x] Get List of Event Invitees
36
- - [x] Get List of User Events
37
- - Webhook V2
38
- - These endpoints havn't been released yet.
8
+ These client libraries are created for [Calendly v2 APIs](https://calendly.stoplight.io/).
39
9
 
40
10
  ## Installation
41
11
 
@@ -55,6 +25,8 @@ Or install it yourself as:
55
25
 
56
26
  ## Usage
57
27
 
28
+ ### Basic
29
+
58
30
  The APIs client needs access token.
59
31
  This client setup step is below.
60
32
 
@@ -116,7 +88,50 @@ invitation.status
116
88
 
117
89
  # cancel the invitation
118
90
  invitation.delete
91
+ ```
92
+
93
+ ### Webhook
94
+
95
+ The webhook usage is below.
96
+
97
+ ```ruby
98
+ events = ['invitee.created', 'invitee.canceled']
99
+ own_member = client.me.organization_membership
100
+ org = own_member.organization
101
+
102
+ # create user scope webhook
103
+ url = 'https://example.com/received_event'
104
+ user_webhook = own_member.create_user_scope_webhook(url, events)
105
+ # => #<Calendly::WebhookSubscription uuid:USER_WEBHOOK_001>
106
+
107
+ # list of user scope webhooks
108
+ own_member.user_scope_webhooks
109
+ # => [#<Calendly::WebhookSubscription uuid:USER_WEBHOOK_001>]
110
+
111
+ # delete the webhook
112
+ user_webhook.delete
113
+ # => true
119
114
 
115
+
116
+ # create organization scope webhook
117
+ url = 'https://example.com/received_event'
118
+ org_webhook = org.create_webhook(url, events)
119
+ # => #<Calendly::WebhookSubscription uuid:ORG_WEBHOOK_001>
120
+
121
+ # list of organization scope webhooks
122
+ org.webhooks
123
+ # => [#<Calendly::WebhookSubscription uuid:ORG_WEBHOOK_001>]
124
+
125
+ # delete the webhook
126
+ org_webhook.delete
127
+ # => true
128
+ ```
129
+
130
+ ### Logging
131
+
132
+ This library supports a configurable logger.
133
+
134
+ ```ruby
120
135
  # if the log level set :debug, you can get the request/response information.
121
136
  Calendly.configuration.logger.level = :debug
122
137
  invitation = my_org.create_invitation('foobar@example.com')
@@ -124,6 +139,8 @@ invitation = my_org.create_invitation('foobar@example.com')
124
139
  # D, [2020-08-10T10:48:16] DEBUG -- : Response status:201, body:{"resource":{"created_at":"2020-08-10T10:48:16.051159Z","email":"foobar@example.com","last_sent_at":"2020-08-10T10:48:16.096518Z","organization":"https://api.calendly.com/organizations/ORG001","status":"pending","updated_at":"2020-08-10T10:48:16.051159Z","uri":"https://api.calendly.com/organizations/ORG001/invitations/INV001"}}
125
140
  ```
126
141
 
142
+ More in-depth method documentation can be found at [RubyDoc.info](https://www.rubydoc.info/gems/calendly/).
143
+
127
144
  ## Contributing
128
145
 
129
146
  Bug reports and pull requests are welcome on [GitHub](https://github.com/koshilife/calendly-api-ruby-client). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
data/Rakefile CHANGED
@@ -1,10 +1,12 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
3
5
 
4
6
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
8
10
  end
9
11
 
10
- task :default => :test
12
+ task default: :test
@@ -29,7 +29,6 @@ Gem::Specification.new do |spec|
29
29
  spec.require_paths = ['lib']
30
30
 
31
31
  spec.add_runtime_dependency 'oauth2', '>= 1.4.4'
32
- spec.add_runtime_dependency 'zeitwerk', '>= 2.3.0'
33
32
 
34
33
  spec.add_development_dependency 'bundler'
35
34
  spec.add_development_dependency 'codecov'
@@ -1,9 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'zeitwerk'
4
- loader = Zeitwerk::Loader.for_gem
5
- loader.collapse('**/models')
6
- loader.setup
3
+ Dir[
4
+ File.join(
5
+ File.dirname(__FILE__),
6
+ 'calendly',
7
+ '**',
8
+ '*'
9
+ )
10
+ ].sort.each do |f|
11
+ next if File.directory? f
12
+
13
+ require f
14
+ end
7
15
 
8
16
  # module for Calendly apis client
9
17
  module Calendly
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'calendly/error'
4
+
3
5
  module Calendly
4
6
  # Calendly apis client error object.
5
- class ApiError < Calendly::Error
7
+ class ApiError < Error
6
8
  # @return [Faraday::Response]
7
9
  attr_reader :response
8
10
  # @return [Integer]
@@ -25,9 +27,9 @@ module Calendly
25
27
  "\#<#{self.class}:#{object_id} title:#{title}, status:#{status}>"
26
28
  end
27
29
 
28
- private
30
+ private
29
31
 
30
- def set_attributes_from_response
32
+ def set_attributes_from_response # rubocop:disable Metrics/CyclomaticComplexity
31
33
  return unless response
32
34
  return unless response.respond_to? :body
33
35
 
@@ -4,14 +4,15 @@ require 'oauth2'
4
4
 
5
5
  module Calendly
6
6
  # Calendly apis client.
7
- class Client
7
+ class Client # rubocop:disable Metrics/ClassLength
8
+ include Loggable
8
9
  API_HOST = 'https://api.calendly.com'
9
10
  AUTH_API_HOST = 'https://auth.calendly.com'
10
11
 
11
12
  # @param [String] token a Calendly's access token.
13
+ # @raise [Calendly::Error] if the token is empty.
12
14
  def initialize(token = nil)
13
15
  @config = Calendly.configuration
14
- @logger = @config.logger
15
16
  @token = token || Calendly.configuration.token
16
17
 
17
18
  check_not_empty @token, 'token'
@@ -38,8 +39,8 @@ module Calendly
38
39
  #
39
40
  # Refresh access token.
40
41
  #
41
- # @raise [Calendly::Error] if the client_id is empty.
42
- # @raise [Calendly::Error] if the client_secret is empty.
42
+ # @raise [Calendly::Error] if Calendly.configuration.client_id is empty.
43
+ # @raise [Calendly::Error] if Calendly.configuration.client_secret is empty.
43
44
  # @raise [Calendly::ApiError] if the api returns error code.
44
45
  # @since 0.0.7
45
46
  def refresh!
@@ -58,11 +59,21 @@ module Calendly
58
59
  # @raise [Calendly::ApiError] if the api returns error code.
59
60
  # @since 0.0.1
60
61
  def current_user
61
- user
62
+ return @cached_current_user if @cached_current_user
63
+
64
+ @cached_current_user = user
62
65
  end
63
66
 
64
67
  alias me current_user
65
68
 
69
+ # @since 0.2.0
70
+ def current_user!
71
+ @cached_current_user = nil
72
+ current_user
73
+ end
74
+
75
+ alias me! current_user!
76
+
66
77
  #
67
78
  # Get basic information about a user
68
79
  #
@@ -95,7 +106,7 @@ module Calendly
95
106
  check_not_empty user_uri, 'user_uri'
96
107
 
97
108
  opts_keys = %i[count page_token sort]
98
- params = { user: user_uri }
109
+ params = {user: user_uri}
99
110
  params = merge_options opts, opts_keys, params
100
111
  body = request :get, 'event_types', params: params
101
112
 
@@ -124,12 +135,12 @@ module Calendly
124
135
  # @param [String] user_uri the specified user (user's uri).
125
136
  # @param [Hash] opts the optional request parameters.
126
137
  # @option opts [Integer] :count Number of rows to return.
127
- # @option opts [String] :invitee_email Return events scheduled with the specified invitee email
138
+ # @option opts [String] :invitee_email Return events scheduled with the specified invitee email.
128
139
  # @option opts [String] :max_start_time Upper bound (inclusive) for an event's start time to filter by.
129
140
  # @option opts [String] :min_start_time Lower bound (inclusive) for an event's start time to filter by.
130
141
  # @option opts [String] :page_token Pass this to get the next portion of collection.
131
142
  # @option opts [String] :sort Order results by the specified field and directin. Accepts comma-separated list of {field}:{direction} values.
132
- # @option opts [String] :status Whether the scheduled event is active or canceled
143
+ # @option opts [String] :status Whether the scheduled event is active or canceled.
133
144
  # @return [Array<Array<Calendly::Event>, Hash>]
134
145
  # - [Array<Calendly::Event>] events
135
146
  # - [Hash] next_params the parameters to get next data. if thre is no next it returns nil.
@@ -140,7 +151,7 @@ module Calendly
140
151
  check_not_empty user_uri, 'user_uri'
141
152
 
142
153
  opts_keys = %i[count invitee_email max_start_time min_start_time page_token sort status]
143
- params = { user: user_uri }
154
+ params = {user: user_uri}
144
155
  params = merge_options opts, opts_keys, params
145
156
  body = request :get, 'scheduled_events', params: params
146
157
 
@@ -227,7 +238,7 @@ module Calendly
227
238
  check_not_empty org_uri, 'org_uri'
228
239
 
229
240
  opts_keys = %i[count email page_token]
230
- params = { organization: org_uri }
241
+ params = {organization: org_uri}
231
242
  params = merge_options opts, opts_keys, params
232
243
  body = request :get, 'organization_memberships', params: params
233
244
 
@@ -254,7 +265,7 @@ module Calendly
254
265
  check_not_empty user_uri, 'user_uri'
255
266
 
256
267
  opts_keys = %i[count email page_token]
257
- params = { user: user_uri }
268
+ params = {user: user_uri}
258
269
  params = merge_options opts, opts_keys, params
259
270
  body = request :get, 'organization_memberships', params: params
260
271
 
@@ -273,15 +284,15 @@ module Calendly
273
284
  # @since 0.0.7
274
285
  def delete_membership(uuid)
275
286
  check_not_empty uuid, 'uuid'
276
- request :delete, "organization_memberships/#{uuid}", expected_status: 204
287
+ request :delete, "organization_memberships/#{uuid}"
277
288
  true
278
289
  end
279
290
 
280
291
  #
281
292
  # Returns an Organization Invitation.
282
293
  #
283
- # @param [String] org_uuid the specified organization (organization's uri).
284
- # @param [String] inv_uuid the specified invitation (organization invitation's uri).
294
+ # @param [String] org_uuid the specified organization (organization's uuid).
295
+ # @param [String] inv_uuid the specified invitation (organization invitation's uuid).
285
296
  # @return [Calendly::OrganizationInvitation]
286
297
  # @raise [Calendly::Error] if the org_uuid arg is empty.
287
298
  # @raise [Calendly::Error] if the inv_uuid arg is empty.
@@ -298,7 +309,7 @@ module Calendly
298
309
  #
299
310
  # Get Organization Invitations.
300
311
  #
301
- # @param [String] uuid the specified organization (organization's uri).
312
+ # @param [String] uuid the specified organization (organization's uuid).
302
313
  # @param [Hash] opts the optional request parameters.
303
314
  # @option opts [Integer] :count Number of rows to return.
304
315
  # @option opts [String] :email Filter by email.
@@ -326,7 +337,7 @@ module Calendly
326
337
  #
327
338
  # Invite a person to an Organization.
328
339
  #
329
- # @param [String] uuid the specified organization (organization's uri).
340
+ # @param [String] uuid the specified organization (organization's uuid).
330
341
  # @param [String] email Email of the person being invited.
331
342
  # @return [Calendly::OrganizationInvitation]
332
343
  # @raise [Calendly::Error] if the uuid arg is empty.
@@ -339,8 +350,7 @@ module Calendly
339
350
  body = request(
340
351
  :post,
341
352
  "organizations/#{uuid}/invitations",
342
- body: { email: email },
343
- expected_status: 201
353
+ body: {email: email}
344
354
  )
345
355
  OrganizationInvitation.new body[:resource], self
346
356
  end
@@ -348,8 +358,8 @@ module Calendly
348
358
  #
349
359
  # Revoke Organization Invitation.
350
360
  #
351
- # @param [String] org_uuid the specified organization (organization's uri).
352
- # @param [String] inv_uuid the specified invitation (organization invitation's uri).
361
+ # @param [String] org_uuid the specified organization (organization's uuid).
362
+ # @param [String] inv_uuid the specified invitation (organization invitation's uuid).
353
363
  # @return [true]
354
364
  # @raise [Calendly::Error] if the org_uuid arg is empty.
355
365
  # @raise [Calendly::Error] if the inv_uuid arg is empty.
@@ -358,40 +368,134 @@ module Calendly
358
368
  def delete_invitation(org_uuid, inv_uuid)
359
369
  check_not_empty org_uuid, 'org_uuid'
360
370
  check_not_empty inv_uuid, 'inv_uuid'
361
- request(
362
- :delete,
363
- "organizations/#{org_uuid}/invitations/#{inv_uuid}",
364
- expected_status: 204
365
- )
371
+ request :delete, "organizations/#{org_uuid}/invitations/#{inv_uuid}"
366
372
  true
367
373
  end
368
374
 
369
- private
375
+ #
376
+ # Get a webhook subscription for an organization or user with a specified UUID.
377
+ #
378
+ # @param [String] uuid the specified webhook (webhook's uuid).
379
+ # @return [Calendly::WebhookSubscription]
380
+ # @raise [Calendly::Error] if the uuid arg is empty.
381
+ # @raise [Calendly::ApiError] if the api returns error code.
382
+ # @since 0.1.3
383
+ def webhook(uuid)
384
+ check_not_empty uuid, 'uuid'
385
+ body = request :get, "webhook_subscriptions/#{uuid}"
386
+ WebhookSubscription.new body[:resource], self
387
+ end
370
388
 
371
- def debug_log(msg)
372
- return unless @logger
389
+ #
390
+ # Get List of organization scope Webhooks.
391
+ #
392
+ # @param [String] org_uri the specified organization (organization's uri).
393
+ # @param [Hash] opts the optional request parameters.
394
+ # @option opts [Integer] :count Number of rows to return.
395
+ # @option opts [String] :page_token Pass this to get the next portion of collection.
396
+ # @option opts [String] :sort Order results by the specified field and directin. Accepts comma-separated list of {field}:{direction} values.
397
+ # @return [Array<Array<Calendly::WebhookSubscription>, Hash>]
398
+ # - [Array<Calendly::WebhookSubscription>] webhooks
399
+ # - [Hash] next_params the parameters to get next data. if thre is no next it returns nil.
400
+ # @raise [Calendly::Error] if the org_uri arg is empty.
401
+ # @raise [Calendly::ApiError] if the api returns error code.
402
+ # @since 0.1.3
403
+ def webhooks(org_uri, opts = {})
404
+ check_not_empty org_uri, 'org_uri'
373
405
 
374
- @logger.debug msg
406
+ opts_keys = %i[count page_token sort]
407
+ params = {organization: org_uri, scope: 'organization'}
408
+ params = merge_options opts, opts_keys, params
409
+ body = request :get, 'webhook_subscriptions', params: params
410
+ items = body[:collection] || []
411
+ evs = items.map { |item| WebhookSubscription.new item, self }
412
+ [evs, next_page_params(body)]
375
413
  end
376
414
 
377
- def request(method, path, params: nil, body: nil, expected_status: nil)
415
+ #
416
+ # Get List of user scope Webhooks.
417
+ #
418
+ # @param [String] org_uri the specified organization (organization's uri).
419
+ # @param [String] user_uri the specified user (user's uri).
420
+ # @param [Hash] opts the optional request parameters.
421
+ # @option opts [Integer] :count Number of rows to return.
422
+ # @option opts [String] :page_token Pass this to get the next portion of collection.
423
+ # @option opts [String] :sort Order results by the specified field and directin. Accepts comma-separated list of {field}:{direction} values.
424
+ # @return [Array<Array<Calendly::WebhookSubscription>, Hash>]
425
+ # - [Array<Calendly::WebhookSubscription>] webhooks
426
+ # - [Hash] next_params the parameters to get next data. if thre is no next it returns nil.
427
+ # @raise [Calendly::Error] if the org_uri arg is empty.
428
+ # @raise [Calendly::Error] if the user_uri arg is empty.
429
+ # @raise [Calendly::ApiError] if the api returns error code.
430
+ # @since 0.1.3
431
+ def user_scope_webhooks(org_uri, user_uri, opts = {})
432
+ check_not_empty org_uri, 'org_uri'
433
+ check_not_empty user_uri, 'user_uri'
434
+
435
+ opts_keys = %i[count page_token sort]
436
+ params = {organization: org_uri, user: user_uri, scope: 'user'}
437
+ params = merge_options opts, opts_keys, params
438
+ body = request :get, 'webhook_subscriptions', params: params
439
+ items = body[:collection] || []
440
+ evs = items.map { |item| WebhookSubscription.new item, self }
441
+ [evs, next_page_params(body)]
442
+ end
443
+
444
+ #
445
+ # Create a webhook subscription for an organization or user.
446
+ #
447
+ # @param [String] url Canonical reference (unique identifier) for the resource.
448
+ # @param [Array<String>] events List of user events to subscribe to. options: invitee.created or invitee.canceled
449
+ # @param [String] org_uri The unique reference to the organization that the webhook will be tied to.
450
+ # @param [String] user_uri The unique reference to the user that the webhook will be tied to.
451
+ # @return [Calendly::WebhookSubscription]
452
+ # @raise [Calendly::Error] if the url arg is empty.
453
+ # @raise [Calendly::Error] if the events arg is empty.
454
+ # @raise [Calendly::Error] if the org_uri arg is empty.
455
+ # @raise [Calendly::ApiError] if the api returns error code.
456
+ # @since 0.1.3
457
+ def create_webhook(url, events, org_uri, user_uri = nil)
458
+ check_not_empty url, 'url'
459
+ check_not_empty events, 'events'
460
+ check_not_empty org_uri, 'org_uri'
461
+
462
+ params = {url: url, events: events, organization: org_uri}
463
+ if user_uri
464
+ params[:scope] = 'user'
465
+ params[:user] = user_uri
466
+ else
467
+ params[:scope] = 'organization'
468
+ end
469
+ body = request(:post, 'webhook_subscriptions', body: params)
470
+ WebhookSubscription.new body[:resource], self
471
+ end
472
+
473
+ #
474
+ # Delete a webhook subscription for an organization or user with a specified UUID.
475
+ #
476
+ # @param [String] uuid the specified webhook (webhook's uuid).
477
+ # @return [true]
478
+ # @raise [Calendly::Error] if the uuid arg is empty.
479
+ # @raise [Calendly::ApiError] if the api returns error code.
480
+ # @since 0.1.3
481
+ def delete_webhook(uuid)
482
+ check_not_empty uuid, 'uuid'
483
+ request :delete, "webhook_subscriptions/#{uuid}"
484
+ true
485
+ end
486
+
487
+ private
488
+
489
+ def request(method, path, params: nil, body: nil)
378
490
  debug_log "Request #{method.to_s.upcase} #{API_HOST}/#{path} params:#{params}, body:#{body}"
379
491
  res = access_token.request(method, path, params: params, body: body)
380
492
  debug_log "Response status:#{res.status}, body:#{res.body}"
381
- validate_status_code res, expected_status
382
493
  parse_as_json res
383
494
  rescue OAuth2::Error => e
384
495
  res = e.response.response
385
496
  raise ApiError.new res, e
386
497
  end
387
498
 
388
- def validate_status_code(res, expected_status)
389
- return unless expected_status
390
- return if expected_status == res.status
391
-
392
- raise ApiError.new res, message: 'unexpected http status returned.'
393
- end
394
-
395
499
  def parse_as_json(res)
396
500
  return if blank? res.body
397
501
 
@@ -401,12 +505,13 @@ module Calendly
401
505
  end
402
506
 
403
507
  def check_not_empty(value, name)
404
- raise Calendly::Error, "#{name} is required." if blank? value
508
+ raise Error.new("#{name} is required.") if blank? value
405
509
  end
406
510
 
407
511
  def blank?(value)
408
512
  return true if value.nil?
409
513
  return true if value.to_s.empty?
514
+ return true if value.is_a?(Array) && value.empty?
410
515
 
411
516
  false
412
517
  end