calendly 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/.github/workflows/gem-push.yml +37 -0
- data/.github/workflows/test.yml +21 -0
- data/.gitignore +10 -0
- data/.rubocom.yml +69 -0
- data/CHANGELOG.md +50 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +137 -0
- data/Rakefile +10 -0
- data/bin/console +7 -0
- data/bin/setup +6 -0
- data/calendly.gemspec +40 -0
- data/lib/calendly/api_error.rb +42 -0
- data/lib/calendly/client.rb +442 -0
- data/lib/calendly/configuration.rb +26 -0
- data/lib/calendly/error.rb +23 -0
- data/lib/calendly/models/event.rb +99 -0
- data/lib/calendly/models/event_type.rb +88 -0
- data/lib/calendly/models/invitee.rb +77 -0
- data/lib/calendly/models/invitee_question_and_answer.rb +19 -0
- data/lib/calendly/models/invitee_tracking.rb +28 -0
- data/lib/calendly/models/location.rb +53 -0
- data/lib/calendly/models/model_utils.rb +105 -0
- data/lib/calendly/models/organization.rb +63 -0
- data/lib/calendly/models/organization_invitation.rb +67 -0
- data/lib/calendly/models/organization_membership.rb +56 -0
- data/lib/calendly/models/user.rb +100 -0
- data/lib/calendly/version.rb +5 -0
- data/lib/calendly.rb +19 -0
- metadata +189 -0
@@ -0,0 +1,442 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'oauth2'
|
4
|
+
|
5
|
+
module Calendly
|
6
|
+
# Calendly apis client.
|
7
|
+
class Client
|
8
|
+
API_HOST = 'https://api.calendly.com'
|
9
|
+
AUTH_API_HOST = 'https://auth.calendly.com'
|
10
|
+
|
11
|
+
# @param [String] token a Calendly's access token.
|
12
|
+
def initialize(token = nil)
|
13
|
+
@config = Calendly.configuration
|
14
|
+
@logger = @config.logger
|
15
|
+
@token = token || Calendly.configuration.token
|
16
|
+
|
17
|
+
check_not_empty @token, 'token'
|
18
|
+
check_token
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Get access token object.
|
23
|
+
#
|
24
|
+
# @return [OAuth2::AccessToken]
|
25
|
+
# @since 0.0.1
|
26
|
+
def access_token
|
27
|
+
return @access_token if defined? @access_token
|
28
|
+
|
29
|
+
client = OAuth2::Client.new(@config.client_id,
|
30
|
+
@config.client_secret, client_options)
|
31
|
+
@access_token = OAuth2::AccessToken.new(
|
32
|
+
client, @token,
|
33
|
+
refresh_token: @config.refresh_token,
|
34
|
+
expires_at: @config.token_expires_at
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Refresh access token.
|
40
|
+
#
|
41
|
+
# @raise [Calendly::Error] if the client_id is empty.
|
42
|
+
# @raise [Calendly::Error] if the client_secret is empty.
|
43
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
44
|
+
# @since 0.0.7
|
45
|
+
def refresh!
|
46
|
+
check_not_empty @config.client_id, 'client_id'
|
47
|
+
check_not_empty @config.client_secret, 'client_secret'
|
48
|
+
@access_token = access_token.refresh!
|
49
|
+
rescue OAuth2::Error => e
|
50
|
+
res = e.response.response
|
51
|
+
raise ApiError.new res, e
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Get basic information about current user.
|
56
|
+
#
|
57
|
+
# @return [Calendly::User]
|
58
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
59
|
+
# @since 0.0.1
|
60
|
+
def current_user
|
61
|
+
user
|
62
|
+
end
|
63
|
+
|
64
|
+
alias me current_user
|
65
|
+
|
66
|
+
#
|
67
|
+
# Get basic information about a user
|
68
|
+
#
|
69
|
+
# @param [String] uuid User unique identifier, or the constant "me" to reference the caller
|
70
|
+
# @return [Calendly::User]
|
71
|
+
# @raise [Calendly::Error] if the uuid arg is empty.
|
72
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
73
|
+
# @since 0.0.1
|
74
|
+
def user(uuid = 'me')
|
75
|
+
check_not_empty uuid, 'uuid'
|
76
|
+
body = request :get, "users/#{uuid}"
|
77
|
+
User.new body[:resource], self
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# Returns all Event Types associated with a specified User.
|
82
|
+
#
|
83
|
+
# @param [String] user_uri the specified user (user's uri).
|
84
|
+
# @param [Hash] opts the optional request parameters.
|
85
|
+
# @option opts [Integer] :count Number of rows to return.
|
86
|
+
# @option opts [String] :page_token Pass this to get the next portion of collection.
|
87
|
+
# @option opts [String] :sort Order results by the specified field and direction. Accepts comma-separated list of {field}:{direction} values.
|
88
|
+
# @return [Array<Array<Calendly::EventType>, Hash>]
|
89
|
+
# - [Array<Calendly::EventType>] event_types
|
90
|
+
# - [Hash] next_params the parameters to get next data. if thre is no next it returns nil.
|
91
|
+
# @raise [Calendly::Error] if the user_uri arg is empty.
|
92
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
93
|
+
# @since 0.0.2
|
94
|
+
def event_types(user_uri, opts = {})
|
95
|
+
check_not_empty user_uri, 'user_uri'
|
96
|
+
|
97
|
+
opts_keys = %i[count page_token sort]
|
98
|
+
params = { user: user_uri }
|
99
|
+
params = merge_options opts, opts_keys, params
|
100
|
+
body = request :get, 'event_types', params: params
|
101
|
+
|
102
|
+
items = body[:collection] || []
|
103
|
+
ev_types = items.map { |item| EventType.new item, self }
|
104
|
+
[ev_types, next_page_params(body)]
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# Returns a single Event by its URI.
|
109
|
+
#
|
110
|
+
# @param [String] uuid the specified event (event's uuid).
|
111
|
+
# @return [Calendly::Event]
|
112
|
+
# @raise [Calendly::Error] if the uuid arg is empty.
|
113
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
114
|
+
# @since 0.0.3
|
115
|
+
def scheduled_event(uuid)
|
116
|
+
check_not_empty uuid, 'uuid'
|
117
|
+
body = request :get, "scheduled_events/#{uuid}"
|
118
|
+
Event.new body[:resource], self
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# Get List of User Events.
|
123
|
+
#
|
124
|
+
# @param [String] user_uri the specified user (user's uri).
|
125
|
+
# @param [Hash] opts the optional request parameters.
|
126
|
+
# @option opts [Integer] :count Number of rows to return.
|
127
|
+
# @option opts [String] :invitee_email Return events scheduled with the specified invitee email
|
128
|
+
# @option opts [String] :max_start_time Upper bound (inclusive) for an event's start time to filter by.
|
129
|
+
# @option opts [String] :min_start_time Lower bound (inclusive) for an event's start time to filter by.
|
130
|
+
# @option opts [String] :page_token Pass this to get the next portion of collection.
|
131
|
+
# @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
|
133
|
+
# @return [Array<Array<Calendly::Event>, Hash>]
|
134
|
+
# - [Array<Calendly::Event>] events
|
135
|
+
# - [Hash] next_params the parameters to get next data. if thre is no next it returns nil.
|
136
|
+
# @raise [Calendly::Error] if the user_uri arg is empty.
|
137
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
138
|
+
# @since 0.0.3
|
139
|
+
def scheduled_events(user_uri, opts = {})
|
140
|
+
check_not_empty user_uri, 'user_uri'
|
141
|
+
|
142
|
+
opts_keys = %i[count invitee_email max_start_time min_start_time page_token sort status]
|
143
|
+
params = { user: user_uri }
|
144
|
+
params = merge_options opts, opts_keys, params
|
145
|
+
body = request :get, 'scheduled_events', params: params
|
146
|
+
|
147
|
+
items = body[:collection] || []
|
148
|
+
evs = items.map { |item| Event.new item, self }
|
149
|
+
[evs, next_page_params(body)]
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# Get Invitee of an Event
|
154
|
+
# Returns a single Invitee by their URI.
|
155
|
+
#
|
156
|
+
# @param [String] ev_uuid the specified event (event's uuid).
|
157
|
+
# @param [String] inv_uuid the specified invitee (invitee's uuid).
|
158
|
+
# @return [Calendly::Invitee]
|
159
|
+
# @raise [Calendly::Error] if the ev_uuid arg is empty.
|
160
|
+
# @raise [Calendly::Error] if the inv_uuid arg is empty.
|
161
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
162
|
+
# @since 0.0.4
|
163
|
+
def event_invitee(ev_uuid, inv_uuid)
|
164
|
+
check_not_empty ev_uuid, 'ev_uuid'
|
165
|
+
check_not_empty inv_uuid, 'inv_uuid'
|
166
|
+
body = request :get, "scheduled_events/#{ev_uuid}/invitees/#{inv_uuid}"
|
167
|
+
Invitee.new body[:resource], self
|
168
|
+
end
|
169
|
+
|
170
|
+
#
|
171
|
+
# Get List of Event Invitees.
|
172
|
+
#
|
173
|
+
# @param [String] uuid the specified event (event's uuid).
|
174
|
+
# @param [Hash] opts the optional request parameters.
|
175
|
+
# @option opts [Integer] :count Number of rows to return.
|
176
|
+
# @option opts [String] :email Filter by email.
|
177
|
+
# @option opts [String] :page_token Pass this to get the next portion of collection.
|
178
|
+
# @option opts [String] :sort Order results by the specified field and directin. Accepts comma-separated list of {field}:{direction} values.
|
179
|
+
# @option opts [String] :status Whether the scheduled event is active or canceled.
|
180
|
+
# @return [Array<Array<Calendly::Invitee>, Hash>]
|
181
|
+
# - [Array<Calendly::Invitee>] invitees
|
182
|
+
# - [Hash] next_params the parameters to get next data. if thre is no next it returns nil.
|
183
|
+
# @raise [Calendly::Error] if the uuid arg is empty.
|
184
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
185
|
+
# @since 0.0.4
|
186
|
+
def event_invitees(uuid, opts = {})
|
187
|
+
check_not_empty uuid, 'uuid'
|
188
|
+
|
189
|
+
opts_keys = %i[count email page_token sort status]
|
190
|
+
params = merge_options opts, opts_keys
|
191
|
+
body = request :get, "scheduled_events/#{uuid}/invitees", params: params
|
192
|
+
|
193
|
+
items = body[:collection] || []
|
194
|
+
evs = items.map { |item| Invitee.new item, self }
|
195
|
+
[evs, next_page_params(body)]
|
196
|
+
end
|
197
|
+
|
198
|
+
#
|
199
|
+
# Returns information about a user's organization membership
|
200
|
+
#
|
201
|
+
# @param [String] uuid the specified membership (organization membership's uuid).
|
202
|
+
# @return [Calendly::OrganizationMembership]
|
203
|
+
# @raise [Calendly::Error] if the uuid arg is empty.
|
204
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
205
|
+
# @since 0.0.5
|
206
|
+
def membership(uuid)
|
207
|
+
check_not_empty uuid, 'uuid'
|
208
|
+
body = request :get, "organization_memberships/#{uuid}"
|
209
|
+
OrganizationMembership.new body[:resource], self
|
210
|
+
end
|
211
|
+
|
212
|
+
#
|
213
|
+
# Get List memberships of all users belonging to an organization.
|
214
|
+
#
|
215
|
+
# @param [String] org_uri the specified organization (organization's uri).
|
216
|
+
# @param [Hash] opts the optional request parameters.
|
217
|
+
# @option opts [Integer] :count Number of rows to return.
|
218
|
+
# @option opts [String] :email Filter by email.
|
219
|
+
# @option opts [String] :page_token Pass this to get the next portion of collection.
|
220
|
+
# @return [Array<Array<Calendly::OrganizationMembership>, Hash>]
|
221
|
+
# - [Array<Calendly::OrganizationMembership>] memberships
|
222
|
+
# - [Hash] next_params the parameters to get next data. if thre is no next it returns nil.
|
223
|
+
# @raise [Calendly::Error] if the org_uri arg is empty.
|
224
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
225
|
+
# @since 0.0.5
|
226
|
+
def memberships(org_uri, opts = {})
|
227
|
+
check_not_empty org_uri, 'org_uri'
|
228
|
+
|
229
|
+
opts_keys = %i[count email page_token]
|
230
|
+
params = { organization: org_uri }
|
231
|
+
params = merge_options opts, opts_keys, params
|
232
|
+
body = request :get, 'organization_memberships', params: params
|
233
|
+
|
234
|
+
items = body[:collection] || []
|
235
|
+
memberships = items.map { |item| OrganizationMembership.new item, self }
|
236
|
+
[memberships, next_page_params(body)]
|
237
|
+
end
|
238
|
+
|
239
|
+
#
|
240
|
+
# Get List memberships of all users belonging to an organization by user.
|
241
|
+
#
|
242
|
+
# @param [String] user_uri the specified user (user's uri).
|
243
|
+
# @param [Hash] opts the optional request parameters.
|
244
|
+
# @option opts [Integer] :count Number of rows to return.
|
245
|
+
# @option opts [String] :email Filter by email.
|
246
|
+
# @option opts [String] :page_token Pass this to get the next portion of collection.
|
247
|
+
# @return [Array<Array<Calendly::OrganizationMembership>, Hash>]
|
248
|
+
# - [Array<Calendly::OrganizationMembership>] memberships
|
249
|
+
# - [Hash] next_params the parameters to get next data. if thre is no next it returns nil.
|
250
|
+
# @raise [Calendly::Error] if the user_uri arg is empty.
|
251
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
252
|
+
# @since 0.0.5
|
253
|
+
def memberships_by_user(user_uri, opts = {})
|
254
|
+
check_not_empty user_uri, 'user_uri'
|
255
|
+
|
256
|
+
opts_keys = %i[count email page_token]
|
257
|
+
params = { user: user_uri }
|
258
|
+
params = merge_options opts, opts_keys, params
|
259
|
+
body = request :get, 'organization_memberships', params: params
|
260
|
+
|
261
|
+
items = body[:collection] || []
|
262
|
+
memberships = items.map { |item| OrganizationMembership.new item, self }
|
263
|
+
[memberships, next_page_params(body)]
|
264
|
+
end
|
265
|
+
|
266
|
+
#
|
267
|
+
# Remove a User from an Organization.
|
268
|
+
#
|
269
|
+
# @param [String] uuid the specified memberhip (organization memberhips's uuid).
|
270
|
+
# @return [true]
|
271
|
+
# @raise [Calendly::Error] if the uuid arg is empty.
|
272
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
273
|
+
# @since 0.0.7
|
274
|
+
def delete_membership(uuid)
|
275
|
+
check_not_empty uuid, 'uuid'
|
276
|
+
request :delete, "organization_memberships/#{uuid}", expected_status: 204
|
277
|
+
true
|
278
|
+
end
|
279
|
+
|
280
|
+
#
|
281
|
+
# Returns an Organization Invitation.
|
282
|
+
#
|
283
|
+
# @param [String] org_uuid the specified organization (organization's uri).
|
284
|
+
# @param [String] inv_uuid the specified invitation (organization invitation's uri).
|
285
|
+
# @return [Calendly::OrganizationInvitation]
|
286
|
+
# @raise [Calendly::Error] if the org_uuid arg is empty.
|
287
|
+
# @raise [Calendly::Error] if the inv_uuid arg is empty.
|
288
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
289
|
+
# @since 0.0.6
|
290
|
+
def invitation(org_uuid, inv_uuid)
|
291
|
+
check_not_empty org_uuid, 'org_uuid'
|
292
|
+
check_not_empty inv_uuid, 'inv_uuid'
|
293
|
+
|
294
|
+
body = request :get, "organizations/#{org_uuid}/invitations/#{inv_uuid}"
|
295
|
+
OrganizationInvitation.new body[:resource], self
|
296
|
+
end
|
297
|
+
|
298
|
+
#
|
299
|
+
# Get Organization Invitations.
|
300
|
+
#
|
301
|
+
# @param [String] uuid the specified organization (organization's uri).
|
302
|
+
# @param [Hash] opts the optional request parameters.
|
303
|
+
# @option opts [Integer] :count Number of rows to return.
|
304
|
+
# @option opts [String] :email Filter by email.
|
305
|
+
# @option opts [String] :page_token Pass this to get the next portion of collection.
|
306
|
+
# @option opts [String] :sort Order results by the specified field and directin. Accepts comma-separated list of {field}:{direction} values.
|
307
|
+
# @option opts [String] :status Filter by status.
|
308
|
+
# @return [<Array<Array<Calendly::OrganizationInvitation>, Hash>]
|
309
|
+
# - [Array<Calendly::OrganizationInvitation>] organizations
|
310
|
+
# - [Hash] next_params the parameters to get next data. if thre is no next it returns nil.
|
311
|
+
# @raise [Calendly::Error] if the uuid arg is empty.
|
312
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
313
|
+
# @since 0.0.6
|
314
|
+
def invitations(uuid, opts = {})
|
315
|
+
check_not_empty uuid, 'uuid'
|
316
|
+
|
317
|
+
opts_keys = %i[count email page_token sort status]
|
318
|
+
params = merge_options opts, opts_keys
|
319
|
+
|
320
|
+
body = request :get, "organizations/#{uuid}/invitations", params: params
|
321
|
+
items = body[:collection] || []
|
322
|
+
evs = items.map { |item| OrganizationInvitation.new item, self }
|
323
|
+
[evs, next_page_params(body)]
|
324
|
+
end
|
325
|
+
|
326
|
+
#
|
327
|
+
# Invite a person to an Organization.
|
328
|
+
#
|
329
|
+
# @param [String] uuid the specified organization (organization's uri).
|
330
|
+
# @param [String] email Email of the person being invited.
|
331
|
+
# @return [Calendly::OrganizationInvitation]
|
332
|
+
# @raise [Calendly::Error] if the uuid arg is empty.
|
333
|
+
# @raise [Calendly::Error] if the email arg is empty.
|
334
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
335
|
+
# @since 0.0.7
|
336
|
+
def create_invitation(uuid, email)
|
337
|
+
check_not_empty uuid, 'uuid'
|
338
|
+
check_not_empty email, 'email'
|
339
|
+
body = request(
|
340
|
+
:post,
|
341
|
+
"organizations/#{uuid}/invitations",
|
342
|
+
body: { email: email },
|
343
|
+
expected_status: 201
|
344
|
+
)
|
345
|
+
OrganizationInvitation.new body[:resource], self
|
346
|
+
end
|
347
|
+
|
348
|
+
#
|
349
|
+
# Revoke Organization Invitation.
|
350
|
+
#
|
351
|
+
# @param [String] org_uuid the specified organization (organization's uri).
|
352
|
+
# @param [String] inv_uuid the specified invitation (organization invitation's uri).
|
353
|
+
# @return [true]
|
354
|
+
# @raise [Calendly::Error] if the org_uuid arg is empty.
|
355
|
+
# @raise [Calendly::Error] if the inv_uuid arg is empty.
|
356
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
357
|
+
# @since 0.0.7
|
358
|
+
def delete_invitation(org_uuid, inv_uuid)
|
359
|
+
check_not_empty org_uuid, 'org_uuid'
|
360
|
+
check_not_empty inv_uuid, 'inv_uuid'
|
361
|
+
request(
|
362
|
+
:delete,
|
363
|
+
"organizations/#{org_uuid}/invitations/#{inv_uuid}",
|
364
|
+
expected_status: 204
|
365
|
+
)
|
366
|
+
true
|
367
|
+
end
|
368
|
+
|
369
|
+
private
|
370
|
+
|
371
|
+
def debug_log(msg)
|
372
|
+
return unless @logger
|
373
|
+
|
374
|
+
@logger.debug msg
|
375
|
+
end
|
376
|
+
|
377
|
+
def request(method, path, params: nil, body: nil, expected_status: nil)
|
378
|
+
debug_log "Request #{method.to_s.upcase} #{API_HOST}/#{path} params:#{params}, body:#{body}"
|
379
|
+
res = access_token.request(method, path, params: params, body: body)
|
380
|
+
debug_log "Response status:#{res.status}, body:#{res.body}"
|
381
|
+
validate_status_code res, expected_status
|
382
|
+
parse_as_json res
|
383
|
+
rescue OAuth2::Error => e
|
384
|
+
res = e.response.response
|
385
|
+
raise ApiError.new res, e
|
386
|
+
end
|
387
|
+
|
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
|
+
def parse_as_json(res)
|
396
|
+
return if blank? res.body
|
397
|
+
|
398
|
+
JSON.parse res.body, symbolize_names: true
|
399
|
+
rescue JSON::ParserError => e
|
400
|
+
raise ApiError.new res, e
|
401
|
+
end
|
402
|
+
|
403
|
+
def check_not_empty(value, name)
|
404
|
+
raise Calendly::Error, "#{name} is required." if blank? value
|
405
|
+
end
|
406
|
+
|
407
|
+
def blank?(value)
|
408
|
+
return true if value.nil?
|
409
|
+
return true if value.to_s.empty?
|
410
|
+
|
411
|
+
false
|
412
|
+
end
|
413
|
+
|
414
|
+
def check_token
|
415
|
+
refresh! if access_token.expired?
|
416
|
+
end
|
417
|
+
|
418
|
+
def client_options
|
419
|
+
{
|
420
|
+
site: API_HOST,
|
421
|
+
authorize_url: "#{AUTH_API_HOST}/oauth/authorize",
|
422
|
+
token_url: "#{AUTH_API_HOST}/oauth/token"
|
423
|
+
}
|
424
|
+
end
|
425
|
+
|
426
|
+
def merge_options(opts, filters, params = {})
|
427
|
+
return params unless opts.is_a? Hash
|
428
|
+
|
429
|
+
permitted_opts = opts.transform_keys(&:to_sym).slice(*filters)
|
430
|
+
params.merge permitted_opts
|
431
|
+
end
|
432
|
+
|
433
|
+
def next_page_params(body)
|
434
|
+
return unless body[:pagination]
|
435
|
+
return unless body[:pagination][:next_page]
|
436
|
+
|
437
|
+
uri = URI.parse body[:pagination][:next_page]
|
438
|
+
params = Hash[URI.decode_www_form(uri.query)]
|
439
|
+
params.transform_keys(&:to_sym)
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module Calendly
|
6
|
+
# Calendly apis client configuration.
|
7
|
+
class Configuration
|
8
|
+
# @return [String]
|
9
|
+
attr_accessor :client_id
|
10
|
+
# @return [String]
|
11
|
+
attr_accessor :client_secret
|
12
|
+
# @return [String]
|
13
|
+
attr_accessor :token
|
14
|
+
# @return [String]
|
15
|
+
attr_accessor :refresh_token
|
16
|
+
# @return [Integer]
|
17
|
+
attr_accessor :token_expires_at
|
18
|
+
# @return [Logger]
|
19
|
+
attr_accessor :logger
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@logger = Logger.new STDOUT
|
23
|
+
@logger.level = :warn
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Calendly
|
4
|
+
# calendly module's base error object
|
5
|
+
class Error < StandardError
|
6
|
+
def initialize(message = nil)
|
7
|
+
@logger = Calendly.configuration.logger
|
8
|
+
msg = "#{self.class} occured."
|
9
|
+
msg += " status:#{status}" if respond_to?(:status)
|
10
|
+
msg += " message:#{message}"
|
11
|
+
log msg
|
12
|
+
super message
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def log(msg, level = :warn)
|
18
|
+
return if @logger.nil?
|
19
|
+
|
20
|
+
@logger.send level, msg
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Calendly
|
4
|
+
# Calendly's event model.
|
5
|
+
# A meeting that has been scheduled
|
6
|
+
class Event
|
7
|
+
include ModelUtils
|
8
|
+
UUID_RE = %r{\A#{Client::API_HOST}/scheduled_events/(\w+)\z}.freeze
|
9
|
+
TIME_FIELDS = %i[start_time end_time created_at updated_at].freeze
|
10
|
+
ASSOCIATION = { event_type: EventType }.freeze
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
# unique id of the Event object.
|
14
|
+
attr_accessor :uuid
|
15
|
+
# @return [String]
|
16
|
+
# Canonical resource reference.
|
17
|
+
attr_accessor :uri
|
18
|
+
# @return [String]
|
19
|
+
# Name of the event.
|
20
|
+
attr_accessor :name
|
21
|
+
# @return [String]
|
22
|
+
# Whether the event is active or canceled.
|
23
|
+
attr_accessor :status
|
24
|
+
# @return [Time]
|
25
|
+
# Moment when event is (or was) scheduled to begin.
|
26
|
+
attr_accessor :start_time
|
27
|
+
# @return [Time]
|
28
|
+
# Moment when event is (or was) scheduled to end.
|
29
|
+
attr_accessor :end_time
|
30
|
+
# @return [Time]
|
31
|
+
# Moment when user record was first created.
|
32
|
+
attr_accessor :created_at
|
33
|
+
# @return [Time]
|
34
|
+
# Moment when user record was last updated.
|
35
|
+
attr_accessor :updated_at
|
36
|
+
|
37
|
+
# @return [EventType]
|
38
|
+
# Reference to Event Type associated with this event.
|
39
|
+
attr_accessor :event_type
|
40
|
+
|
41
|
+
# @return [Calendly::Location]
|
42
|
+
# location in this event.
|
43
|
+
attr_accessor :location
|
44
|
+
|
45
|
+
# @return [Integer]
|
46
|
+
# number of total invitees in this event.
|
47
|
+
attr_accessor :invitees_counter_total
|
48
|
+
# @return [Integer]
|
49
|
+
# number of active invitees in this event.
|
50
|
+
attr_accessor :invitees_counter_active
|
51
|
+
# @return [Integer]
|
52
|
+
# max invitees in this event.
|
53
|
+
attr_accessor :invitees_counter_limit
|
54
|
+
|
55
|
+
#
|
56
|
+
# Get Scheduled Event associated with self.
|
57
|
+
#
|
58
|
+
# @return [Calendly::Event]
|
59
|
+
# @raise [Calendly::Error] if the uuid is empty.
|
60
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
61
|
+
# @since 0.1.0
|
62
|
+
def fetch
|
63
|
+
client.scheduled_event uuid
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Returns all Event Invitees associated with self.
|
68
|
+
#
|
69
|
+
# @param [Hash] opts the optional request parameters.
|
70
|
+
# @option opts [Integer] :count Number of rows to return.
|
71
|
+
# @option opts [String] :email Filter by email.
|
72
|
+
# @option opts [String] :page_token Pass this to get the next portion of collection.
|
73
|
+
# @option opts [String] :sort Order results by the specified field and directin. Accepts comma-separated list of {field}:{direction} values.
|
74
|
+
# @option opts [String] :status Whether the scheduled event is active or canceled.
|
75
|
+
# @return [Array<Calendly::Invitee>]
|
76
|
+
# @raise [Calendly::Error] if the uuid is empty.
|
77
|
+
# @raise [Calendly::ApiError] if the api returns error code.
|
78
|
+
# @since 0.1.0
|
79
|
+
def invitees(opts = {})
|
80
|
+
request_proc = proc { |options| client.event_invitees uuid, options }
|
81
|
+
auto_pagination request_proc, opts
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def after_set_attributes(attrs)
|
87
|
+
super attrs
|
88
|
+
loc_params = attrs[:location]
|
89
|
+
@location = Location.new loc_params if loc_params&.is_a? Hash
|
90
|
+
|
91
|
+
inv_cnt_attrs = attrs[:invitees_counter]
|
92
|
+
if inv_cnt_attrs&.is_a? Hash
|
93
|
+
@invitees_counter_total = inv_cnt_attrs[:total]
|
94
|
+
@invitees_counter_active = inv_cnt_attrs[:active]
|
95
|
+
@invitees_counter_limit = inv_cnt_attrs[:limit]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Calendly
|
4
|
+
# Calendly's event type model.
|
5
|
+
# A configuration for a schedulable event
|
6
|
+
class EventType
|
7
|
+
include ModelUtils
|
8
|
+
UUID_RE = %r{\A#{Client::API_HOST}/event_types/(\w+)\z}.freeze
|
9
|
+
TIME_FIELDS = %i[created_at updated_at].freeze
|
10
|
+
|
11
|
+
# @return [String]
|
12
|
+
# unique id of the EventType object.
|
13
|
+
attr_accessor :uuid
|
14
|
+
# @return [String]
|
15
|
+
# Canonical resource reference.
|
16
|
+
attr_accessor :uri
|
17
|
+
# @return [Boolean]
|
18
|
+
# Is this event type currently active?
|
19
|
+
attr_accessor :active
|
20
|
+
# @return [String]
|
21
|
+
# The web page styling color for this event type,
|
22
|
+
# expressed as a hexadecimal RGB value (e.g. #fa12e4).
|
23
|
+
attr_accessor :color
|
24
|
+
# @return [String]
|
25
|
+
# Longer text description with HTML formatting.
|
26
|
+
attr_accessor :description_html
|
27
|
+
# @return [String]
|
28
|
+
# Longer text description in plain text.
|
29
|
+
attr_accessor :description_plain
|
30
|
+
# @return [Integer]
|
31
|
+
# Length of event type in minutes.
|
32
|
+
attr_accessor :duration
|
33
|
+
# @return [String]
|
34
|
+
# Optional internal note on an event type.
|
35
|
+
attr_accessor :internal_note
|
36
|
+
# @return [String]
|
37
|
+
# Whether the event type is “solo” or with a “group”.
|
38
|
+
attr_accessor :kind
|
39
|
+
# @return [String]
|
40
|
+
# Human-readable name. Note: some Event Types don't have a name.
|
41
|
+
attr_accessor :name
|
42
|
+
# @return [String]
|
43
|
+
# Whether the event type is "round_robin" or "collective".
|
44
|
+
# This value is null if the event type does not pool team members' availability.
|
45
|
+
attr_accessor :pooling_type
|
46
|
+
# @return [String]
|
47
|
+
# The full URL of the web page for this event type.
|
48
|
+
attr_accessor :scheduling_url
|
49
|
+
# @return [String]
|
50
|
+
# Unique human-readable slug used in page URL.
|
51
|
+
attr_accessor :slug
|
52
|
+
# @return [String]
|
53
|
+
# Whether the event type is a “StandardEventType” or an "AdhocEventType”.
|
54
|
+
attr_accessor :type
|
55
|
+
# @return [Time]
|
56
|
+
# Moment when event type was eventually created.
|
57
|
+
attr_accessor :created_at
|
58
|
+
# @return [Time]
|
59
|
+
# Moment when event type was last updated.
|
60
|
+
attr_accessor :updated_at
|
61
|
+
|
62
|
+
# @return [String]
|
63
|
+
# uuid of User or Team object.
|
64
|
+
attr_accessor :owner_uuid
|
65
|
+
# @return [String]
|
66
|
+
# Reference to the profile owner.
|
67
|
+
attr_accessor :owner_uri
|
68
|
+
# @return [String]
|
69
|
+
# Human-readable name.
|
70
|
+
attr_accessor :owner_name
|
71
|
+
# @return [String]
|
72
|
+
# Whether the profile belongs to a “User” or a “Team”.
|
73
|
+
attr_accessor :owner_type
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def after_set_attributes(attrs)
|
78
|
+
super attrs
|
79
|
+
if attrs[:profile]
|
80
|
+
|
81
|
+
@owner_uri = attrs[:profile][:owner]
|
82
|
+
@owner_uuid = User.extract_uuid owner_uri
|
83
|
+
@owner_name = attrs[:profile][:name]
|
84
|
+
@owner_type = attrs[:profile][:type]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|