cronofy 0.0.5 → 0.37.7
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 +5 -5
- data/CHANGELOG.md +262 -0
- data/Gemfile +2 -0
- data/README.md +100 -46
- data/cronofy.gemspec +16 -13
- data/lib/cronofy/api_key.rb +73 -0
- data/lib/cronofy/auth.rb +149 -46
- data/lib/cronofy/client.rb +1928 -72
- data/lib/cronofy/errors.rb +68 -8
- data/lib/cronofy/response_parser.rb +36 -3
- data/lib/cronofy/time_encoding.rb +31 -0
- data/lib/cronofy/types.rb +420 -0
- data/lib/cronofy/version.rb +1 -1
- data/lib/cronofy.rb +68 -4
- data/spec/lib/cronofy/auth_spec.rb +559 -0
- data/spec/lib/cronofy/client_spec.rb +3712 -0
- data/spec/lib/cronofy/date_or_time_spec.rb +12 -0
- data/spec/lib/cronofy/errors_spec.rb +81 -0
- data/spec/lib/cronofy/event_spec.rb +121 -0
- data/spec/response_parser_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -0
- metadata +73 -21
- data/.gitignore +0 -14
- data/.travis.yml +0 -16
- data/script/ci +0 -7
data/lib/cronofy/client.rb
CHANGED
@@ -1,119 +1,1975 @@
|
|
1
|
-
|
1
|
+
require 'uri'
|
2
2
|
|
3
|
+
module Cronofy
|
4
|
+
# Public: Primary class for interacting with the Cronofy API.
|
3
5
|
class Client
|
6
|
+
include TimeEncoding
|
4
7
|
|
5
|
-
|
6
|
-
|
8
|
+
# Public: The scope to request if none is explicitly specified by the
|
9
|
+
# caller.
|
10
|
+
DEFAULT_OAUTH_SCOPE = %w{
|
11
|
+
read_account
|
12
|
+
read_events
|
13
|
+
create_event
|
14
|
+
delete_event
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
# Public: Initialize a new Cronofy::Client.
|
18
|
+
#
|
19
|
+
# options - A Hash of options used to initialize the client (default: {}):
|
20
|
+
# :access_token - An existing access token String for the user's
|
21
|
+
# account (optional).
|
22
|
+
# :client_id - The client ID String of your Cronofy OAuth
|
23
|
+
# application (default:
|
24
|
+
# ENV["CRONOFY_CLIENT_ID"]).
|
25
|
+
# :client_secret - The client secret String of your Cronofy OAuth
|
26
|
+
# application (default:
|
27
|
+
# ENV["CRONOFY_CLIENT_SECRET"]).
|
28
|
+
# :refresh_token - An existing refresh token String for the user's
|
29
|
+
# account (optional).
|
30
|
+
# :data_center - An identifier to override the default data
|
31
|
+
# center (optional).
|
32
|
+
def initialize(options = {})
|
33
|
+
access_token = options[:access_token]
|
34
|
+
refresh_token = options[:refresh_token]
|
35
|
+
|
36
|
+
@client_id = options.fetch(:client_id, ENV["CRONOFY_CLIENT_ID"])
|
37
|
+
@client_secret = options.fetch(:client_secret, ENV["CRONOFY_CLIENT_SECRET"])
|
38
|
+
@data_center = options[:data_center] || options[:data_centre]
|
39
|
+
|
40
|
+
@auth = Auth.new(
|
41
|
+
client_id: @client_id,
|
42
|
+
client_secret: @client_secret,
|
43
|
+
access_token: access_token,
|
44
|
+
refresh_token: refresh_token,
|
45
|
+
data_center: @data_center
|
46
|
+
)
|
7
47
|
end
|
8
48
|
|
9
|
-
|
10
|
-
|
11
|
-
|
49
|
+
# Public: Creates a new calendar for the profile.
|
50
|
+
#
|
51
|
+
# profile_id - The String ID of the profile to create the calendar within.
|
52
|
+
# name - The String to use as the name of the calendar.
|
53
|
+
# options - The Hash options used to customize the calendar
|
54
|
+
# (default: {}):
|
55
|
+
# :color - The color to make the calendar (optional).
|
56
|
+
#
|
57
|
+
# See https://www.cronofy.com/developers/api/#create-calendar for reference.
|
58
|
+
#
|
59
|
+
# Returns the created Calendar
|
60
|
+
#
|
61
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
62
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
63
|
+
# longer valid.
|
64
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
65
|
+
# include the required scope.
|
66
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
67
|
+
# parameters.
|
68
|
+
# Raises Cronofy::AccountLockedError if the profile is not in a writable
|
69
|
+
# state and so a calendar cannot be created.
|
70
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
71
|
+
# limits for the application.
|
72
|
+
def create_calendar(profile_id, name, options = {})
|
73
|
+
request = options.merge(profile_id: profile_id, name: name)
|
74
|
+
response = post("/v1/calendars", request)
|
75
|
+
parse_json(Calendar, "calendar", response)
|
12
76
|
end
|
13
77
|
|
14
|
-
# Public
|
15
|
-
#
|
78
|
+
# Public: Lists all the calendars for the account.
|
79
|
+
#
|
80
|
+
# See http://www.cronofy.com/developers/api#calendars for reference.
|
16
81
|
#
|
17
|
-
# Returns
|
82
|
+
# Returns an Array of Calendars
|
83
|
+
#
|
84
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
85
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
86
|
+
# longer valid.
|
87
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
88
|
+
# limits for the application.
|
18
89
|
def list_calendars
|
19
|
-
response =
|
20
|
-
|
90
|
+
response = get("/v1/calendars")
|
91
|
+
parse_collection(Calendar, "calendars", response)
|
21
92
|
end
|
22
93
|
|
23
|
-
# Public
|
24
|
-
#
|
25
|
-
# aliased as upsert_event
|
94
|
+
# Public: Creates or updates an event for the event_id in the calendar
|
95
|
+
# relating to the given calendar_id.
|
26
96
|
#
|
27
|
-
# calendar_id
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
97
|
+
# calendar_id - The String Cronofy ID for the calendar to upsert the event
|
98
|
+
# to.
|
99
|
+
# event - A Hash describing the event with symbolized keys:
|
100
|
+
# :event_id - A String uniquely identifying the event for
|
101
|
+
# your application (note: this is NOT an ID
|
102
|
+
# generated by Cronofy).
|
103
|
+
# :summary - A String to use as the summary, sometimes
|
104
|
+
# referred to as the name or title, of the
|
105
|
+
# event.
|
106
|
+
# :description - A String to use as the description, sometimes
|
107
|
+
# referred to as the notes or body, of the
|
108
|
+
# event.
|
109
|
+
# :start - The Time or Date the event starts.
|
110
|
+
# :end - The Time or Date the event ends.
|
111
|
+
# :url - The URL associated with the event.
|
112
|
+
# :location - A Hash describing the location of the event
|
113
|
+
# with symbolized keys (optional):
|
114
|
+
# :description - A String describing the
|
115
|
+
# location.
|
116
|
+
# :lat - A String of the location's latitude.
|
117
|
+
# :long - A String of the location's longitude.
|
118
|
+
# :reminders - An Array of Hashes describing the desired
|
119
|
+
# reminders for the event. Reminders should be
|
120
|
+
# specified in priority order as, for example,
|
121
|
+
# when the underlying provider only supports a
|
122
|
+
# single reminder then the first reminder will
|
123
|
+
# be used.
|
124
|
+
# :minutes - An Integer specifying the number
|
125
|
+
# of minutes before the start of the
|
126
|
+
# event that the reminder should
|
127
|
+
# occur.
|
128
|
+
# :transparency - The transparency state for the event (optional).
|
129
|
+
# Accepted values are "transparent" and "opaque".
|
130
|
+
# :color - The color of the event (optional).
|
131
|
+
# :attendees - A Hash of :invite and :reject, each of which is
|
132
|
+
# an array of invitees to invite to or reject from
|
133
|
+
# the event. Invitees are represented by a hash of
|
134
|
+
# :email and :display_name (optional).
|
33
135
|
#
|
34
|
-
#
|
35
|
-
|
136
|
+
# Examples
|
137
|
+
#
|
138
|
+
# client.upsert_event(
|
139
|
+
# "cal_n23kjnwrw2_jsdfjksn234",
|
140
|
+
# event_id: "qTtZdczOccgaPncGJaCiLg",
|
141
|
+
# summary: "Board meeting",
|
142
|
+
# description: "Discuss plans for the next quarter.",
|
143
|
+
# start: Time.utc(2014, 8, 5, 15, 30),
|
144
|
+
# end: Time.utc(2014, 8, 5, 17, 30),
|
145
|
+
# location: {
|
146
|
+
# description: "Board room",
|
147
|
+
# lat: "1.2345",
|
148
|
+
# long: "0.1234"
|
149
|
+
# })
|
150
|
+
#
|
151
|
+
# See http://www.cronofy.com/developers/api#upsert-event for reference.
|
152
|
+
#
|
153
|
+
# Returns nothing.
|
154
|
+
#
|
155
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
156
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
157
|
+
# longer valid.
|
158
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
159
|
+
# include the required scope.
|
160
|
+
# Raises Cronofy::NotFoundError if the calendar does not exist.
|
161
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
162
|
+
# parameters.
|
163
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
164
|
+
# limits for the application.
|
165
|
+
def upsert_event(calendar_id, event)
|
36
166
|
body = event.dup
|
37
|
-
body[:start] = event[:start].utc.iso8601
|
38
|
-
body[:end] = event[:end].utc.iso8601
|
39
167
|
|
40
|
-
|
41
|
-
|
168
|
+
body[:start] = encode_event_time(body[:start])
|
169
|
+
body[:end] = encode_event_time(body[:end])
|
170
|
+
|
171
|
+
post("/v1/calendars/#{calendar_id}/events", body)
|
172
|
+
nil
|
173
|
+
end
|
174
|
+
|
175
|
+
# Public: Alias for #upsert_event
|
176
|
+
alias_method :create_or_update_event, :upsert_event
|
177
|
+
|
178
|
+
# Public: Returns a lazily-evaluated Enumerable of Events that satisfy the
|
179
|
+
# given query criteria.
|
180
|
+
#
|
181
|
+
# options - The Hash options used to refine the selection (default: {}):
|
182
|
+
# :from - The minimum Date from which to return events
|
183
|
+
# (optional).
|
184
|
+
# :to - The Date to return events up until (optional).
|
185
|
+
# :tzid - A String representing a known time zone
|
186
|
+
# identifier from the IANA Time Zone Database
|
187
|
+
# (default: Etc/UTC).
|
188
|
+
# :include_deleted - A Boolean specifying whether events that have
|
189
|
+
# been deleted should be included or excluded
|
190
|
+
# from the results (optional).
|
191
|
+
# :include_moved - A Boolean specifying whether events that have
|
192
|
+
# ever existed within the given window should
|
193
|
+
# be included or excluded from the results
|
194
|
+
# (optional).
|
195
|
+
# :include_managed - A Boolean specifying whether events that you
|
196
|
+
# are managing for the account should be
|
197
|
+
# included or excluded from the results
|
198
|
+
# (optional).
|
199
|
+
# :only_managed - A Boolean specifying whether only events that
|
200
|
+
# you are managing for the account should
|
201
|
+
# trigger notifications (optional).
|
202
|
+
# :localized_times - A Boolean specifying whether the start and
|
203
|
+
# end times should be returned with any
|
204
|
+
# available localization information
|
205
|
+
# (optional).
|
206
|
+
# :last_modified - The Time that events must be modified on or
|
207
|
+
# after in order to be returned (optional).
|
208
|
+
# :calendar_ids - An Array of calendar ids for restricting the
|
209
|
+
# returned events (optional).
|
210
|
+
# :include_geo - A Boolean specifying whether the events should
|
211
|
+
# have their location.lat and location.long
|
212
|
+
# returned where available (optional).
|
213
|
+
#
|
214
|
+
# The first page will be retrieved eagerly so that common errors will happen
|
215
|
+
# inline. However, subsequent pages (if any) will be requested lazily.
|
216
|
+
#
|
217
|
+
# See http://www.cronofy.com/developers/api#read-events for reference.
|
218
|
+
#
|
219
|
+
# Returns a lazily-evaluated Enumerable of Events
|
220
|
+
#
|
221
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
222
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
223
|
+
# longer valid.
|
224
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
225
|
+
# include the required scope.
|
226
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
227
|
+
# parameters.
|
228
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
229
|
+
# limits for the application.
|
230
|
+
def read_events(options = {})
|
231
|
+
params = READ_EVENTS_DEFAULT_PARAMS.merge(options)
|
232
|
+
|
233
|
+
READ_EVENTS_TIME_PARAMS.select { |tp| params.key?(tp) }.each do |tp|
|
234
|
+
params[tp] = to_iso8601(params[tp])
|
235
|
+
end
|
236
|
+
|
237
|
+
url = api_url + "/v1/events"
|
238
|
+
PagedResultIterator.new(PagedEventsResult, :events, access_token!, url, params)
|
239
|
+
end
|
240
|
+
|
241
|
+
# Public: Returns a lazily-evaluated Enumerable of FreeBusy that satisfy the
|
242
|
+
# given query criteria.
|
243
|
+
#
|
244
|
+
# options - The Hash options used to refine the selection (default: {}):
|
245
|
+
# :from - The minimum Date from which to return events
|
246
|
+
# (optional).
|
247
|
+
# :to - The Date to return events up until (optional).
|
248
|
+
# :tzid - A String representing a known time zone
|
249
|
+
# identifier from the IANA Time Zone Database
|
250
|
+
# (default: Etc/UTC).
|
251
|
+
# :include_managed - A Boolean specifying whether events that you
|
252
|
+
# are managing for the account should be
|
253
|
+
# included or excluded from the results
|
254
|
+
# (optional).
|
255
|
+
# :localized_times - A Boolean specifying whether the start and
|
256
|
+
# end times should be returned with any
|
257
|
+
# available localization information
|
258
|
+
# (optional).
|
259
|
+
# :calendar_ids - An Array of calendar ids for restricting the
|
260
|
+
# returned events (optional).
|
261
|
+
#
|
262
|
+
# The first page will be retrieved eagerly so that common errors will happen
|
263
|
+
# inline. However, subsequent pages (if any) will be requested lazily.
|
264
|
+
#
|
265
|
+
# See http://www.cronofy.com/developers/api/#free-busy for reference.
|
266
|
+
#
|
267
|
+
# Returns a lazily-evaluated Enumerable of FreeBusy
|
268
|
+
#
|
269
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
270
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
271
|
+
# longer valid.
|
272
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
273
|
+
# include the required scope.
|
274
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
275
|
+
# parameters.
|
276
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
277
|
+
# limits for the application.
|
278
|
+
def free_busy(options = {})
|
279
|
+
params = FREE_BUSY_DEFAULT_PARAMS.merge(options)
|
280
|
+
|
281
|
+
FREE_BUSY_TIME_PARAMS.select { |tp| params.key?(tp) }.each do |tp|
|
282
|
+
params[tp] = to_iso8601(params[tp])
|
283
|
+
end
|
284
|
+
|
285
|
+
url = api_url + "/v1/free_busy"
|
286
|
+
PagedResultIterator.new(PagedFreeBusyResult, :free_busy, access_token!, url, params)
|
287
|
+
end
|
288
|
+
|
289
|
+
# Public: Deletes an event from the specified calendar
|
290
|
+
#
|
291
|
+
# calendar_id - The String Cronofy ID for the calendar to delete the event
|
292
|
+
# from.
|
293
|
+
# event_id - A String uniquely identifying the event for your application
|
294
|
+
# (note: this is NOT an ID generated by Cronofy).
|
295
|
+
#
|
296
|
+
# See http://www.cronofy.com/developers/api#delete-event for reference.
|
297
|
+
#
|
298
|
+
# Returns nothing.
|
299
|
+
#
|
300
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
301
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
302
|
+
# longer valid.
|
303
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
304
|
+
# include the required scope.
|
305
|
+
# Raises Cronofy::NotFoundError if the calendar does not exist.
|
306
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
307
|
+
# parameters.
|
308
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
309
|
+
# limits for the application.
|
310
|
+
def delete_event(calendar_id, event_id)
|
311
|
+
delete("/v1/calendars/#{calendar_id}/events", event_id: event_id)
|
312
|
+
nil
|
313
|
+
end
|
314
|
+
|
315
|
+
class BatchBuilder
|
316
|
+
include TimeEncoding
|
317
|
+
|
318
|
+
def initialize
|
319
|
+
@entries = []
|
320
|
+
end
|
321
|
+
|
322
|
+
def upsert_event(calendar_id, event)
|
323
|
+
data = event.dup
|
324
|
+
|
325
|
+
data[:start] = encode_event_time(data[:start])
|
326
|
+
data[:end] = encode_event_time(data[:end])
|
327
|
+
|
328
|
+
post "/v1/calendars/#{calendar_id}/events", data
|
329
|
+
end
|
330
|
+
|
331
|
+
alias_method :create_or_update_event, :upsert_event
|
332
|
+
|
333
|
+
def delete_event(calendar_id, event_id)
|
334
|
+
delete "/v1/calendars/#{calendar_id}/events", event_id: event_id
|
335
|
+
end
|
336
|
+
|
337
|
+
def delete_external_event(calendar_id, event_uid)
|
338
|
+
delete "/v1/calendars/#{calendar_id}/events", event_uid: event_uid
|
339
|
+
end
|
340
|
+
|
341
|
+
def add_entry(args)
|
342
|
+
@entries << BatchEntryRequest.new(args)
|
343
|
+
nil
|
344
|
+
end
|
345
|
+
|
346
|
+
def build
|
347
|
+
@entries.dup
|
348
|
+
end
|
349
|
+
|
350
|
+
private
|
351
|
+
|
352
|
+
def delete(relative_url, data)
|
353
|
+
add_entry(method: "DELETE", relative_url: relative_url, data: data)
|
354
|
+
end
|
355
|
+
|
356
|
+
def post(relative_url, data)
|
357
|
+
add_entry(method: "POST", relative_url: relative_url, data: data)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
def batch
|
362
|
+
yield builder = BatchBuilder.new
|
363
|
+
|
364
|
+
requests = builder.build
|
365
|
+
|
366
|
+
response = post("/v1/batch", batch: requests)
|
367
|
+
responses = parse_collection(BatchEntryResponse, "batch", response)
|
368
|
+
|
369
|
+
entries = requests.zip(responses).map do |request, response|
|
370
|
+
response.request = request
|
371
|
+
response
|
372
|
+
end
|
373
|
+
|
374
|
+
result = BatchResponse.new(entries)
|
375
|
+
|
376
|
+
if result.errors?
|
377
|
+
msg = "Batch contains #{result.errors.count} errors"
|
378
|
+
raise BatchResponse::PartialSuccessError.new(msg, result)
|
379
|
+
end
|
380
|
+
|
381
|
+
result
|
382
|
+
end
|
383
|
+
|
384
|
+
# Public: Deletes an external event from the specified calendar
|
385
|
+
#
|
386
|
+
# calendar_id - The String Cronofy ID for the calendar to delete the event
|
387
|
+
# from.
|
388
|
+
# event_uid - The unique ID of the event to delete.
|
389
|
+
#
|
390
|
+
# Returns nothing.
|
391
|
+
#
|
392
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
393
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
394
|
+
# longer valid.
|
395
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
396
|
+
# include the required scope or the client has not been granted elevated
|
397
|
+
# permissions to the calendar.
|
398
|
+
# Raises Cronofy::NotFoundError if the calendar does not exist.
|
399
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
400
|
+
# parameters.
|
401
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
402
|
+
# limits for the application.
|
403
|
+
def delete_external_event(calendar_id, event_uid)
|
404
|
+
delete("/v1/calendars/#{calendar_id}/events", event_uid: event_uid)
|
405
|
+
nil
|
406
|
+
end
|
407
|
+
|
408
|
+
# Public: Deletes all events you are managing for the account.
|
409
|
+
#
|
410
|
+
# See https://www.cronofy.com/developers/api/#bulk-delete-events for
|
411
|
+
# reference.
|
412
|
+
#
|
413
|
+
# options - The Hash options used to refine the selection (optional):
|
414
|
+
# :calendar_ids - An Array of calendar ids to delete managed
|
415
|
+
# events from returned events.
|
416
|
+
#
|
417
|
+
# If no options are specified it defaults to deleting all the events you are
|
418
|
+
# managing.
|
419
|
+
#
|
420
|
+
# Returns nothing.
|
421
|
+
#
|
422
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
423
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
424
|
+
# longer valid.
|
425
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
426
|
+
# include the required scope.
|
427
|
+
# Raises Cronofy::NotFoundError if the calendar does not exist.
|
428
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
429
|
+
# parameters.
|
430
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
431
|
+
# limits for the application.
|
432
|
+
def delete_all_events(options = nil)
|
433
|
+
options ||= { delete_all: true }
|
434
|
+
delete("/v1/events", options)
|
435
|
+
nil
|
436
|
+
end
|
437
|
+
|
438
|
+
# Public: Creates a notification channel with a callback URL
|
439
|
+
#
|
440
|
+
# callback_url - A String specifing the callback URL for the channel.
|
441
|
+
# options - The Hash options used to refine the notifications of the
|
442
|
+
# channel (default: {}):
|
443
|
+
# :filters - A Hash of filters to use for the notification
|
444
|
+
# channel (optional):
|
445
|
+
# :calendar_ids - An Array of calendar ID strings
|
446
|
+
# to restrict the returned events
|
447
|
+
# to (optional).
|
448
|
+
# :only_managed - A Boolean specifying whether
|
449
|
+
# only events that you are
|
450
|
+
# managing for the account should
|
451
|
+
# trigger notifications
|
452
|
+
# (optional).
|
453
|
+
#
|
454
|
+
# See http://www.cronofy.com/developers/api#create-channel for reference.
|
455
|
+
#
|
456
|
+
# Returns a Channel.
|
457
|
+
#
|
458
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
459
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
460
|
+
# longer valid.
|
461
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
462
|
+
# include the required scope.
|
463
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
464
|
+
# parameters.
|
465
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
466
|
+
# limits for the application.
|
467
|
+
def create_channel(callback_url, options = {})
|
468
|
+
params = options.merge(callback_url: callback_url)
|
469
|
+
|
470
|
+
response = post("/v1/channels", params)
|
471
|
+
parse_json(Channel, "channel", response)
|
472
|
+
end
|
473
|
+
|
474
|
+
# DEPRECATED: Please use hmac_valid instead.
|
475
|
+
def hmac_match?(args)
|
476
|
+
warn "[DEPRECATION] `hmac_match?` is deprecated. Please use `hmac_valid?` instead."
|
477
|
+
hmac_valid?(args)
|
478
|
+
end
|
479
|
+
|
480
|
+
# Public: Verifies a HMAC from a push notification using the client secret.
|
481
|
+
#
|
482
|
+
# args - A Hash containing the details of the push notification:
|
483
|
+
# :body - A String of the body of the notification.
|
484
|
+
# :hmac - A String containing comma-separated values describing HMACs of the notification taken from the
|
485
|
+
# Cronofy-HMAC-SHA256 header.
|
486
|
+
#
|
487
|
+
# Returns true if one of the HMAC provided matches the one calculated using the
|
488
|
+
# client secret, otherwise false.
|
489
|
+
def hmac_valid?(args)
|
490
|
+
body = args[:body]
|
491
|
+
hmac = args[:hmac]
|
492
|
+
|
493
|
+
return false if hmac.nil? || hmac.empty?
|
494
|
+
|
495
|
+
sha256 = OpenSSL::Digest.new('sha256')
|
496
|
+
digest = OpenSSL::HMAC.digest(sha256, @client_secret, body)
|
497
|
+
calculated = Base64.encode64(digest).strip
|
498
|
+
|
499
|
+
hmac_list = hmac.split(',')
|
500
|
+
hmac_list.include?(calculated)
|
501
|
+
end
|
502
|
+
|
503
|
+
# Public: Lists all the notification channels for the account.
|
504
|
+
#
|
505
|
+
# See http://www.cronofy.com/developers/api#list-channels for reference.
|
506
|
+
#
|
507
|
+
# Returns an Array of Channels.
|
508
|
+
#
|
509
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
510
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
511
|
+
# longer valid.
|
512
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
513
|
+
# include the required scope.
|
514
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
515
|
+
# limits for the application.
|
516
|
+
def list_channels
|
517
|
+
response = get("/v1/channels")
|
518
|
+
parse_collection(Channel, "channels", response)
|
519
|
+
end
|
520
|
+
|
521
|
+
# Public: Closes a notification channel.
|
522
|
+
#
|
523
|
+
# channel_id - The String Cronofy ID for the channel to close.
|
524
|
+
#
|
525
|
+
# See http://www.cronofy.com/developers/api#close-channel for reference.
|
526
|
+
#
|
527
|
+
# Returns nothing.
|
528
|
+
#
|
529
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
530
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
531
|
+
# longer valid.
|
532
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
533
|
+
# include the required scope.
|
534
|
+
# Raises Cronofy::NotFoundError if the channel does not exist.
|
535
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
536
|
+
# limits for the application.
|
537
|
+
def close_channel(channel_id)
|
538
|
+
delete("/v1/channels/#{channel_id}")
|
539
|
+
nil
|
540
|
+
end
|
541
|
+
|
542
|
+
# Public: Retrieves the details of the account.
|
543
|
+
#
|
544
|
+
# See http://www.cronofy.com/developers/api#account for reference.
|
545
|
+
#
|
546
|
+
# Returns an Account.
|
547
|
+
#
|
548
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
549
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
550
|
+
# longer valid.
|
551
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
552
|
+
# include the required scope.
|
553
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
554
|
+
# limits for the application.
|
555
|
+
def account
|
556
|
+
response = get("/v1/account")
|
557
|
+
parse_json(Account, "account", response)
|
558
|
+
end
|
559
|
+
|
560
|
+
# Public: Lists all the profiles for the account.
|
561
|
+
#
|
562
|
+
# See https://www.cronofy.com/developers/api/#profiles for reference.
|
563
|
+
#
|
564
|
+
# Returns an Array of Profiles
|
565
|
+
#
|
566
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
567
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
568
|
+
# longer valid.
|
569
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
570
|
+
# limits for the application.
|
571
|
+
def list_profiles
|
572
|
+
response = get("/v1/profiles")
|
573
|
+
parse_collection(Profile, "profiles", response)
|
574
|
+
end
|
575
|
+
|
576
|
+
# Public: Retrieves the userinfo for the account
|
577
|
+
#
|
578
|
+
# See http://openid.net/specs/openid-connect-core-1_0.html#UserInfo for
|
579
|
+
# reference.
|
580
|
+
#
|
581
|
+
# Returns an UserInfo.
|
582
|
+
#
|
583
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
584
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
585
|
+
# longer valid.
|
586
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
587
|
+
# include the required scope.
|
588
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
589
|
+
# limits for the application.
|
590
|
+
def userinfo
|
591
|
+
response = get("/v1/userinfo")
|
592
|
+
parse_json(UserInfo, nil, response)
|
593
|
+
end
|
594
|
+
|
595
|
+
|
596
|
+
# Public: Changes the participation status for a calendar event
|
597
|
+
#
|
598
|
+
# calendar_id - The String Cronofy ID for the calendar to delete the event
|
599
|
+
# from.
|
600
|
+
# event_uid - A String uniquely identifying the event for your application
|
601
|
+
# (note: this is NOT an ID generated by Cronofy).
|
602
|
+
# status - A String or Symbol to set the participation status of the
|
603
|
+
# invite to
|
604
|
+
#
|
605
|
+
#
|
606
|
+
# See http://www.cronofy.com/developers/api#delete-event for reference.
|
607
|
+
#
|
608
|
+
# Returns nothing.
|
609
|
+
#
|
610
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
611
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
612
|
+
# longer valid.
|
613
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
614
|
+
# include the required scope.
|
615
|
+
# Raises Cronofy::NotFoundError if the calendar does not exist.
|
616
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
617
|
+
# parameters.
|
618
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
619
|
+
# limits for the application.
|
620
|
+
def change_participation_status(calendar_id, event_uid, status)
|
621
|
+
body = {
|
622
|
+
status: status.to_s,
|
42
623
|
}
|
43
624
|
|
44
|
-
|
625
|
+
url = "/v1/calendars/#{calendar_id}/events/#{event_uid}/participation_status"
|
626
|
+
post(url, body)
|
45
627
|
end
|
46
|
-
alias_method :upsert_event, :create_or_update_event
|
47
628
|
|
48
|
-
# Public
|
49
|
-
#
|
629
|
+
# Public: Attempts to authorize the email with impersonation from a service
|
630
|
+
# account
|
50
631
|
#
|
51
|
-
#
|
52
|
-
#
|
632
|
+
# email - the email address to impersonate
|
633
|
+
# scope - Array or String of scopes describing the access to
|
634
|
+
# request from the user to the users calendars (required).
|
635
|
+
# callback_url - the url to callback to
|
53
636
|
#
|
54
637
|
# Returns nothing
|
55
|
-
|
56
|
-
|
638
|
+
#
|
639
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
640
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
641
|
+
# longer valid.
|
642
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
643
|
+
# limits for the application.
|
644
|
+
def authorize_with_service_account(email, scope, callback_url)
|
645
|
+
if scope.respond_to?(:join)
|
646
|
+
scope = scope.join(' ')
|
647
|
+
end
|
57
648
|
|
58
|
-
|
649
|
+
params = {
|
650
|
+
email: email,
|
651
|
+
scope: scope,
|
652
|
+
callback_url: callback_url
|
653
|
+
}
|
654
|
+
post("/v1/service_account_authorizations", params)
|
655
|
+
nil
|
59
656
|
end
|
60
657
|
|
61
|
-
# Public
|
62
|
-
#
|
63
|
-
# see http://www.cronofy.com/developers/api#authorization
|
658
|
+
# Public: Generates a URL to send the user to in order to perform the OAuth
|
659
|
+
# 2.0 authorization process.
|
64
660
|
#
|
65
|
-
# redirect_uri
|
66
|
-
#
|
661
|
+
# redirect_uri - A String specifing the URI to return the user to once they
|
662
|
+
# have completed the authorization steps.
|
663
|
+
# options - The Hash options used to refine the selection
|
664
|
+
# (default: {}):
|
665
|
+
# :scope - Array or String of scopes describing the access to
|
666
|
+
# request from the user to the users calendars
|
667
|
+
# (default: DEFAULT_OAUTH_SCOPE).
|
668
|
+
# :state - Array of states to retain during the OAuth
|
669
|
+
# authorization process (optional).
|
67
670
|
#
|
68
|
-
#
|
69
|
-
|
70
|
-
|
671
|
+
# See http://www.cronofy.com/developers/api#authorization for reference.
|
672
|
+
#
|
673
|
+
# Returns the URL as a String.
|
674
|
+
def user_auth_link(redirect_url, options = {})
|
675
|
+
options = { scope: DEFAULT_OAUTH_SCOPE }.merge(options)
|
676
|
+
@auth.user_auth_link(redirect_url, options)
|
71
677
|
end
|
72
678
|
|
73
|
-
# Public
|
74
|
-
#
|
679
|
+
# Public: Retrieves the OAuth credentials authorized for the given code and
|
680
|
+
# redirect URL pair.
|
681
|
+
#
|
682
|
+
# code - String code returned to redirect_url after authorization.
|
683
|
+
# redirect_url - A String specifing the URL the user returned to once they
|
684
|
+
# had completed the authorization steps.
|
75
685
|
#
|
76
|
-
#
|
77
|
-
# redirect_uri - String URI returned to
|
686
|
+
# See http://www.cronofy.com/developers/api#token-issue for reference.
|
78
687
|
#
|
79
|
-
# Returns Cronofy::Credentials
|
80
|
-
|
81
|
-
|
688
|
+
# Returns a set of Cronofy::Credentials for the account.
|
689
|
+
#
|
690
|
+
# Raises Cronofy::BadRequestError if the code is unknown, has been revoked,
|
691
|
+
# or the code and redirect URL do not match.
|
692
|
+
# Raises Cronofy::AuthenticationFailureError if the client ID and secret are
|
693
|
+
# not valid.
|
694
|
+
def get_token_from_code(code, redirect_url)
|
695
|
+
@auth.get_token_from_code(code, redirect_url)
|
82
696
|
end
|
83
697
|
|
84
|
-
# Public
|
85
|
-
#
|
698
|
+
# Public: Refreshes the credentials for the account's access token.
|
699
|
+
#
|
700
|
+
# Usually called in response to a Cronofy::AuthenticationFailureError as
|
701
|
+
# these usually occur when the access token has expired and needs
|
702
|
+
# refreshing.
|
86
703
|
#
|
87
|
-
#
|
704
|
+
# See http://www.cronofy.com/developers/api#token-refresh for reference.
|
705
|
+
#
|
706
|
+
# Returns a set of Cronofy::Credentials for the account.
|
707
|
+
#
|
708
|
+
# Raises Cronofy::BadRequestError if refresh token code is unknown or has
|
709
|
+
# been revoked.
|
710
|
+
# Raises Cronofy::AuthenticationFailureError if the client ID and secret are
|
711
|
+
# not valid.
|
712
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
88
713
|
def refresh_access_token
|
89
714
|
@auth.refresh!
|
90
715
|
end
|
91
716
|
|
92
|
-
|
717
|
+
# Public: Obtains access to an application calendar
|
718
|
+
#
|
719
|
+
# See http://www.cronofy.com/developers/alpha/api#application-calendar for reference.
|
720
|
+
#
|
721
|
+
# Returns a set of Cronofy::Credentials for the account.
|
722
|
+
#
|
723
|
+
# Raises Cronofy::BadRequestError if refresh token code is unknown or has
|
724
|
+
# been revoked.
|
725
|
+
# Raises Cronofy::AuthenticationFailureError if the client ID and secret are
|
726
|
+
# not valid.
|
727
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
728
|
+
def application_calendar(application_calendar_id)
|
729
|
+
@auth.application_calendar(application_calendar_id)
|
730
|
+
end
|
731
|
+
|
732
|
+
# Public: Revokes the account's refresh token and access token.
|
733
|
+
#
|
734
|
+
# After making this call the Client will become unusable. You should also
|
735
|
+
# delete the stored credentials used to create this instance.
|
736
|
+
#
|
737
|
+
# See http://www.cronofy.com/developers/api#revoke-authorization for
|
738
|
+
# reference.
|
739
|
+
#
|
740
|
+
# Returns nothing.
|
741
|
+
#
|
742
|
+
# Raises Cronofy::AuthenticationFailureError if the client ID and secret are
|
743
|
+
# not valid.
|
744
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
745
|
+
def revoke_authorization
|
746
|
+
@auth.revoke!
|
747
|
+
end
|
748
|
+
|
749
|
+
def revoke_by_sub(sub)
|
750
|
+
@auth.revoke_by_sub(sub)
|
751
|
+
end
|
752
|
+
|
753
|
+
def revoke_by_token(token)
|
754
|
+
@auth.revoke_by_token(token)
|
755
|
+
end
|
756
|
+
|
757
|
+
# Public: Requests elevated permissions for a set of calendars.
|
758
|
+
#
|
759
|
+
# args - A Hash of options used to initialize the request (default: {}):
|
760
|
+
# :permissions - An Array of calendar permission hashes to set on
|
761
|
+
# the each hash must contain symbols for both
|
762
|
+
# `calendar_id` and `permission_level`
|
763
|
+
# :redirect_uri - A uri to redirect the end user back to after they
|
764
|
+
# have either granted or rejected the request for
|
765
|
+
# elevated permission.
|
766
|
+
#
|
767
|
+
# In the case of normal accounts:
|
768
|
+
# After making this call the end user will have to grant the extended
|
769
|
+
# permissions to their calendar via rhe url returned from the response.
|
770
|
+
#
|
771
|
+
# In the case of service accounts:
|
772
|
+
# After making this call the exteneded permissions will be granted provided
|
773
|
+
# the relevant scope has been granted to the account
|
774
|
+
#
|
775
|
+
# Returns a extended permissions response.
|
776
|
+
#
|
777
|
+
# Raises Cronofy::AuthenticationFailureError if the client ID and secret are
|
778
|
+
# not valid.
|
779
|
+
def elevated_permissions(args = {})
|
780
|
+
filtered_permissions = args[:permissions].map do |permission|
|
781
|
+
{ calendar_id: permission[:calendar_id], permission_level: permission[:permission_level] }
|
782
|
+
end
|
783
|
+
|
784
|
+
body = { permissions: filtered_permissions }
|
785
|
+
body[:redirect_uri] = args[:redirect_uri] if args[:redirect_uri]
|
786
|
+
|
787
|
+
response = post("/v1/permissions", body)
|
788
|
+
parse_json(PermissionsResponse, "permissions_request", response)
|
789
|
+
end
|
790
|
+
|
791
|
+
# Public: Lists all the resources for the service account.
|
792
|
+
#
|
793
|
+
# Returns an Array of Resources.
|
794
|
+
#
|
795
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available
|
796
|
+
# or if non-service account credentials are provided.
|
797
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
798
|
+
# longer valid.
|
799
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
800
|
+
# include the required scope.
|
801
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
802
|
+
# limits for the application.
|
803
|
+
def resources
|
804
|
+
response = get("/v1/resources")
|
805
|
+
parse_collection(Resource, "resources", response)
|
806
|
+
end
|
807
|
+
|
808
|
+
# Public: Performs an availability query.
|
809
|
+
#
|
810
|
+
# options - The Hash options used to refine the selection (default: {}):
|
811
|
+
# :participants - An Array of participant groups or a Hash
|
812
|
+
# for a single participant group.
|
813
|
+
# :required_duration - An Integer representing the minimum number
|
814
|
+
# of minutes of availability required.
|
815
|
+
# :query_periods - An Array of available time periods Hashes,
|
816
|
+
# each must specify a start and end Time.
|
817
|
+
# :start_interval - An Integer representing the start interval
|
818
|
+
# of minutes for the availability query.
|
819
|
+
# :buffer - An Hash containing the buffer to apply to
|
820
|
+
# the availability query.
|
821
|
+
#
|
822
|
+
# Returns an Array of AvailablePeriods.
|
823
|
+
#
|
824
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
825
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
826
|
+
# longer valid.
|
827
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
828
|
+
# include the required scope.
|
829
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
830
|
+
# parameters.
|
831
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
832
|
+
# limits for the application.
|
833
|
+
def availability(options = {})
|
834
|
+
options[:participants] = map_availability_participants(options[:participants])
|
835
|
+
options[:required_duration] = map_availability_required_duration(options[:required_duration])
|
93
836
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
404 => ::Cronofy::NotFoundError,
|
98
|
-
422 => ::Cronofy::InvalidRequestError,
|
99
|
-
429 => ::Cronofy::TooManyRequestsError
|
100
|
-
}
|
837
|
+
if options[:start_interval]
|
838
|
+
options[:start_interval] = map_availability_required_duration(options[:start_interval])
|
839
|
+
end
|
101
840
|
|
102
|
-
|
103
|
-
|
104
|
-
block.call
|
105
|
-
rescue OAuth2::Error => e
|
106
|
-
error_class = ERROR_MAP.fetch(e.response.status, UnknownError)
|
107
|
-
raise error_class.new(e.response.headers['status'], e.response)
|
841
|
+
if buffer = options[:buffer]
|
842
|
+
options[:buffer] = map_availability_buffer(buffer)
|
108
843
|
end
|
844
|
+
|
845
|
+
translate_available_periods(options[:query_periods] || options[:available_periods])
|
846
|
+
|
847
|
+
response = availability_post("/v1/availability", options)
|
848
|
+
|
849
|
+
parse_collections(
|
850
|
+
response,
|
851
|
+
available_periods: AvailablePeriod,
|
852
|
+
available_slots: AvailableSlot,
|
853
|
+
)
|
109
854
|
end
|
110
855
|
|
111
|
-
|
856
|
+
# Public: Performs an sequenced availability query.
|
857
|
+
#
|
858
|
+
# options - The Hash options used to refine the selection (default: {}):
|
859
|
+
# :sequence - An Array of sequence defintions containing
|
860
|
+
# a Hash of:
|
861
|
+
# :sequence_id - A String to uniquely identify this part
|
862
|
+
# of the proposed sequence.
|
863
|
+
# :ordinal - An integer to define the ordering of the
|
864
|
+
# proposed sequence. (Optional)
|
865
|
+
# :participants - An Array of participant groups or a Hash
|
866
|
+
# for a single participant group.
|
867
|
+
# :required_duration - An Integer representing the minimum
|
868
|
+
# number of minutes of availability required.
|
869
|
+
# :start_interval - An Integer representing the start interval
|
870
|
+
# of minutes for the availability query.
|
871
|
+
# :buffer - An Hash containing the buffer to apply to
|
872
|
+
# the availability query.
|
873
|
+
# :query_periods - An Array of available time periods Hashes,
|
874
|
+
# each must specify a start and end Time.
|
875
|
+
#
|
876
|
+
# Returns an Array of Sequences.
|
877
|
+
#
|
878
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
879
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
880
|
+
# longer valid.
|
881
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
882
|
+
# include the required scope.
|
883
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
884
|
+
# parameters.
|
885
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
886
|
+
# limits for the application.
|
887
|
+
def sequenced_availability(options = {})
|
888
|
+
options[:sequence] = map_availability_sequence(options[:sequence])
|
112
889
|
|
113
|
-
|
114
|
-
|
115
|
-
|
890
|
+
translate_available_periods(options[:query_periods] || options[:available_periods])
|
891
|
+
|
892
|
+
response = availability_post("/v1/sequenced_availability", options)
|
893
|
+
parse_collection(Sequence, "sequences", response)
|
894
|
+
end
|
116
895
|
|
896
|
+
# Public: Generates an add to calendar link to start the OAuth process with
|
897
|
+
# an event to be automatically upserted
|
898
|
+
#
|
899
|
+
# oauth - A Hash describing the OAuth flow required:
|
900
|
+
# :scope - A String representing the scopes to ask for
|
901
|
+
# within the OAuth flow
|
902
|
+
# :redirect_uri - A String containing a url to redirect the
|
903
|
+
# user to after completing the OAuth flow.
|
904
|
+
# :scope - A String representing additional state to
|
905
|
+
# be passed within the OAuth flow.
|
906
|
+
#
|
907
|
+
# event - A Hash describing the event with symbolized keys:
|
908
|
+
# :event_id - A String uniquely identifying the event for
|
909
|
+
# your application (note: this is NOT an ID
|
910
|
+
# generated by Cronofy).
|
911
|
+
# :summary - A String to use as the summary, sometimes
|
912
|
+
# referred to as the name or title, of the
|
913
|
+
# event.
|
914
|
+
# :description - A String to use as the description, sometimes
|
915
|
+
# referred to as the notes or body, of the
|
916
|
+
# event.
|
917
|
+
# :start - The Time or Date the event starts.
|
918
|
+
# :end - The Time or Date the event ends.
|
919
|
+
# :url - The URL associated with the event.
|
920
|
+
# :location - A Hash describing the location of the event
|
921
|
+
# with symbolized keys (optional):
|
922
|
+
# :description - A String describing the
|
923
|
+
# location.
|
924
|
+
# :lat - A String of the location's latitude.
|
925
|
+
# :long - A String of the location's longitude.
|
926
|
+
# :reminders - An Array of Hashes describing the desired
|
927
|
+
# reminders for the event. Reminders should be
|
928
|
+
# specified in priority order as, for example,
|
929
|
+
# when the underlying provider only supports a
|
930
|
+
# single reminder then the first reminder will
|
931
|
+
# be used.
|
932
|
+
# :minutes - An Integer specifying the number
|
933
|
+
# of minutes before the start of the
|
934
|
+
# event that the reminder should
|
935
|
+
# occur.
|
936
|
+
# :transparency - The transparency state for the event (optional).
|
937
|
+
# Accepted values are "transparent" and "opaque".
|
938
|
+
# :attendees - A Hash of :invite and :reject, each of which is
|
939
|
+
# an array of invitees to invite to or reject from
|
940
|
+
# the event. Invitees are represented by a hash of
|
941
|
+
# :email and :display_name (optional).
|
942
|
+
#
|
943
|
+
# Example
|
944
|
+
#
|
945
|
+
# client.add_to_calendar(
|
946
|
+
# oauth: {
|
947
|
+
# scopes: 'read_events delete_events',
|
948
|
+
# redirect_uri: 'http://www.example.com',
|
949
|
+
# state: 'example_state'
|
950
|
+
# },
|
951
|
+
# event: {
|
952
|
+
# event_id: "qTtZdczOccgaPncGJaCiLg",
|
953
|
+
# summary: "Board meeting",
|
954
|
+
# description: "Discuss plans for the next quarter.",
|
955
|
+
# start: Time.utc(2014, 8, 5, 15, 30),
|
956
|
+
# end: Time.utc(2014, 8, 5, 17, 30),
|
957
|
+
# location: {
|
958
|
+
# description: "Board room",
|
959
|
+
# lat: "1.2345",
|
960
|
+
# long: "0.1234"
|
961
|
+
# })
|
962
|
+
#
|
963
|
+
# See http://www.cronofy.com/developers/api#upsert-event for reference.
|
964
|
+
#
|
965
|
+
# Returns a AddToCalendarResponse.
|
966
|
+
#
|
967
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
968
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
969
|
+
# longer valid.
|
970
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
971
|
+
# include the required scope.
|
972
|
+
# Raises Cronofy::NotFoundError if the calendar does not exist.
|
973
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
974
|
+
# parameters.
|
975
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
976
|
+
# limits for the application.
|
977
|
+
def add_to_calendar(args = {})
|
978
|
+
body = args.merge(client_id: @client_id, client_secret: @client_secret)
|
979
|
+
|
980
|
+
body[:event][:start] = encode_event_time(body[:event][:start])
|
981
|
+
body[:event][:end] = encode_event_time(body[:event][:end])
|
982
|
+
|
983
|
+
response = post("/v1/add_to_calendar", body)
|
984
|
+
parse_json(AddToCalendarResponse, nil , response)
|
985
|
+
end
|
986
|
+
|
987
|
+
# Public: Generates an real time scheduling link to start the OAuth process with
|
988
|
+
# an event to be automatically upserted
|
989
|
+
#
|
990
|
+
# oauth - A Hash describing the OAuth flow required:
|
991
|
+
# :scope - A String representing the scopes to ask for
|
992
|
+
# within the OAuth flow
|
993
|
+
# :redirect_uri - A String containing a url to redirect the
|
994
|
+
# user to after completing the OAuth flow.
|
995
|
+
# :scope - A String representing additional state to
|
996
|
+
# be passed within the OAuth flow.
|
997
|
+
#
|
998
|
+
# event - A Hash describing the event with symbolized keys:
|
999
|
+
# :event_id - A String uniquely identifying the event for
|
1000
|
+
# your application (note: this is NOT an ID
|
1001
|
+
# generated by Cronofy).
|
1002
|
+
# :summary - A String to use as the summary, sometimes
|
1003
|
+
# referred to as the name or title, of the
|
1004
|
+
# event.
|
1005
|
+
# :description - A String to use as the description, sometimes
|
1006
|
+
# referred to as the notes or body, of the
|
1007
|
+
# event.
|
1008
|
+
# :url - The URL associated with the event.
|
1009
|
+
# :location - A Hash describing the location of the event
|
1010
|
+
# with symbolized keys (optional):
|
1011
|
+
# :description - A String describing the
|
1012
|
+
# location.
|
1013
|
+
# :lat - A String of the location's latitude.
|
1014
|
+
# :long - A String of the location's longitude.
|
1015
|
+
# :reminders - An Array of Hashes describing the desired
|
1016
|
+
# reminders for the event. Reminders should be
|
1017
|
+
# specified in priority order as, for example,
|
1018
|
+
# when the underlying provider only supports a
|
1019
|
+
# single reminder then the first reminder will
|
1020
|
+
# be used.
|
1021
|
+
# :minutes - An Integer specifying the number
|
1022
|
+
# of minutes before the start of the
|
1023
|
+
# event that the reminder should
|
1024
|
+
# occur.
|
1025
|
+
# :transparency - The transparency state for the event (optional).
|
1026
|
+
# Accepted values are "transparent" and "opaque".
|
1027
|
+
# :attendees - A Hash of :invite and :reject, each of which is
|
1028
|
+
# an array of invitees to invite to or reject from
|
1029
|
+
# the event. Invitees are represented by a hash of
|
1030
|
+
# :email and :display_name (optional).
|
1031
|
+
# availability - A Hash describing the availability details for the event:
|
1032
|
+
# :participants - A hash stating who is required for the availability
|
1033
|
+
# call
|
1034
|
+
# :required_duration - A hash stating the length of time the event will
|
1035
|
+
# last for
|
1036
|
+
# :query_periods - A hash stating the available periods for the event
|
1037
|
+
# :start_interval - An Integer representing the start interval
|
1038
|
+
# of minutes for the availability query.
|
1039
|
+
# :buffer - An Hash containing the buffer to apply to
|
1040
|
+
# the availability query.
|
1041
|
+
# target_calendars - An array of hashes stating into which calendars to insert the created
|
1042
|
+
# event
|
1043
|
+
#
|
1044
|
+
# Examples
|
1045
|
+
#
|
1046
|
+
# - Availability example
|
1047
|
+
# client.add_to_calendar(
|
1048
|
+
# oauth: {
|
1049
|
+
# redirect_uri: 'http://www.example.com'
|
1050
|
+
# },
|
1051
|
+
# event: {
|
1052
|
+
# event_id: "qTtZdczOccgaPncGJaCiLg",
|
1053
|
+
# summary: "Board meeting",
|
1054
|
+
# description: "Discuss plans for the next quarter.",
|
1055
|
+
# location: {
|
1056
|
+
# description: "Board room",
|
1057
|
+
# lat: "1.2345",
|
1058
|
+
# long: "0.1234"
|
1059
|
+
# }
|
1060
|
+
# },
|
1061
|
+
# availability: {
|
1062
|
+
# participants: [
|
1063
|
+
# {
|
1064
|
+
# members: [{
|
1065
|
+
# sub: "acc_567236000909002",
|
1066
|
+
# calendar_ids: ["cal_n23kjnwrw2_jsdfjksn234"]
|
1067
|
+
# }],
|
1068
|
+
# required: 'all'
|
1069
|
+
# }
|
1070
|
+
# ],
|
1071
|
+
# required_duration: { minutes: 60 },
|
1072
|
+
# query_periods: [{
|
1073
|
+
# start: Time.utc(2017, 1, 1, 9, 00),
|
1074
|
+
# end: Time.utc(2017, 1, 1, 17, 00),
|
1075
|
+
# }]
|
1076
|
+
# },
|
1077
|
+
# target_calendars: [{
|
1078
|
+
# sub: "acc_567236000909002",
|
1079
|
+
# calendar_id: "cal_n23kjnwrw2_jsdfjksn234"
|
1080
|
+
# }]
|
1081
|
+
# )
|
1082
|
+
#
|
1083
|
+
# See http://www.cronofy.com/developers/api#real-time-scheduling for reference.
|
1084
|
+
#
|
1085
|
+
# Returns a AddToCalendarResponse.
|
1086
|
+
#
|
1087
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1088
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
1089
|
+
# longer valid.
|
1090
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
1091
|
+
# include the required scope.
|
1092
|
+
# Raises Cronofy::NotFoundError if the calendar does not exist.
|
1093
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1094
|
+
# parameters.
|
1095
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1096
|
+
# limits for the application.
|
1097
|
+
def real_time_scheduling(args = {})
|
1098
|
+
body = args.merge(client_id: @client_id, client_secret: @client_secret)
|
1099
|
+
|
1100
|
+
if availability = args[:availability]
|
1101
|
+
availability[:participants] = map_availability_participants(availability[:participants])
|
1102
|
+
availability[:required_duration] = map_availability_required_duration(availability[:required_duration])
|
1103
|
+
|
1104
|
+
if value = availability[:start_interval]
|
1105
|
+
availability[:start_interval] = map_availability_required_duration(value)
|
1106
|
+
end
|
1107
|
+
|
1108
|
+
if buffer = availability[:buffer]
|
1109
|
+
availability[:buffer] = map_availability_buffer(buffer)
|
1110
|
+
end
|
1111
|
+
end
|
1112
|
+
|
1113
|
+
translate_available_periods(availability[:query_periods] || availability[:available_periods])
|
1114
|
+
body[:availability] = availability
|
1115
|
+
|
1116
|
+
response = raw_post("/v1/real_time_scheduling", body)
|
1117
|
+
parse_json(AddToCalendarResponse, nil , response)
|
1118
|
+
end
|
1119
|
+
|
1120
|
+
# Public: Gets the status of a Real-Time Scheduling link.
|
1121
|
+
#
|
1122
|
+
# Provide one of the following arguments to identify the link:
|
1123
|
+
# id - A String uniquely identifying the link, returned on initial
|
1124
|
+
# creation
|
1125
|
+
# token - The token portion of the link's URL
|
1126
|
+
#
|
1127
|
+
# See https://docs.cronofy.com/developers/api/scheduling/real-time-scheduling/status/ for reference.
|
1128
|
+
#
|
1129
|
+
# Returns a RealTimeSchedulingStatus.
|
1130
|
+
#
|
1131
|
+
# Raises ArgumentError if neither 'id' nor 'token' arguments are passed.
|
1132
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1133
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1134
|
+
# limits for the application.
|
1135
|
+
def get_real_time_scheduling_status(args = {})
|
1136
|
+
if args[:token]
|
1137
|
+
url = "/v1/real_time_scheduling?token=#{args[:token]}"
|
1138
|
+
elsif args[:id]
|
1139
|
+
url = "/v1/real_time_scheduling/#{args[:id]}"
|
1140
|
+
else
|
1141
|
+
raise ArgumentError.new("Must pass either token or id argument")
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
response = wrapped_request { api_key!.get(url) }
|
1145
|
+
parse_json(RealTimeSchedulingStatus, 'real_time_scheduling' , response)
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
# Public: Disables a Real-Time Scheduling link.
|
1149
|
+
#
|
1150
|
+
# id - A String uniquely identifying the link, returned
|
1151
|
+
# on initial creation
|
1152
|
+
# display_message - A message to display to visitors of the disabled link
|
1153
|
+
#
|
1154
|
+
# See https://docs.cronofy.com/developers/api/scheduling/real-time-scheduling/disable/ for reference.
|
1155
|
+
#
|
1156
|
+
# Returns a RealTimeSchedulingStatus.
|
1157
|
+
#
|
1158
|
+
# Raises ArgumentError if no 'id' argument is passed.
|
1159
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1160
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1161
|
+
# parameters.
|
1162
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1163
|
+
# limits for the application.
|
1164
|
+
def disable_real_time_scheduling(args = {})
|
1165
|
+
id = args.delete(:id)
|
1166
|
+
|
1167
|
+
raise ArgumentError.new('id argument is required') unless id
|
1168
|
+
|
1169
|
+
response = wrapped_request { api_key!.post("/v1/real_time_scheduling/#{id}/disable", json_request_args(args)) }
|
1170
|
+
parse_json(RealTimeSchedulingStatus, 'real_time_scheduling' , response)
|
1171
|
+
end
|
1172
|
+
|
1173
|
+
# Public: Generates an real time sequencing link to start the OAuth process with
|
1174
|
+
# an event to be automatically upserted
|
1175
|
+
#
|
1176
|
+
# oauth - A Hash describing the OAuth flow required:
|
1177
|
+
# :scope - A String representing the scopes to ask for
|
1178
|
+
# within the OAuth flow
|
1179
|
+
# :redirect_uri - A String containing a url to redirect the
|
1180
|
+
# user to after completing the OAuth flow.
|
1181
|
+
# :scope - A String representing additional state to
|
1182
|
+
# be passed within the OAuth flow.
|
1183
|
+
#
|
1184
|
+
# availability - A Hash describing the availability details for the event:
|
1185
|
+
# :sequence - An Array of sequence defintions containing
|
1186
|
+
# a Hash of:
|
1187
|
+
# :sequence_id - A String to uniquely identify this part
|
1188
|
+
# of the proposed sequence.
|
1189
|
+
# :ordinal - An integer to define the ordering of the
|
1190
|
+
# proposed sequence. (Optional)
|
1191
|
+
# :participants - An Array of participant groups or a Hash
|
1192
|
+
# for a single participant group.
|
1193
|
+
# :required_duration - An Integer representing the minimum
|
1194
|
+
# number of minutes of availability required.
|
1195
|
+
# :start_interval - An Integer representing the start interval
|
1196
|
+
# of minutes for the availability query.
|
1197
|
+
# :buffer - An Hash containing the buffer to apply to
|
1198
|
+
# the availability query.
|
1199
|
+
# :event - A Hash describing the event:
|
1200
|
+
# :event_id - A String uniquely identifying the event for
|
1201
|
+
# your application (note: this is NOT an ID
|
1202
|
+
# generated by Cronofy).
|
1203
|
+
# :summary - A String to use as the summary, sometimes
|
1204
|
+
# referred to as the name or title, of the
|
1205
|
+
# event.
|
1206
|
+
# :description - A String to use as the description, sometimes
|
1207
|
+
# referred to as the notes or body, of the
|
1208
|
+
# event.
|
1209
|
+
# :url - The URL associated with the event.
|
1210
|
+
# :location - A Hash describing the location of the event
|
1211
|
+
# with symbolized keys (optional):
|
1212
|
+
# :description - A String describing the
|
1213
|
+
# location.
|
1214
|
+
# :lat - A String of the location's latitude.
|
1215
|
+
# :long - A String of the location's longitude.
|
1216
|
+
# :reminders - An Array of Hashes describing the desired
|
1217
|
+
# reminders for the event. Reminders should be
|
1218
|
+
# specified in priority order as, for example,
|
1219
|
+
# when the underlying provider only supports a
|
1220
|
+
# single reminder then the first reminder will
|
1221
|
+
# be used.
|
1222
|
+
# :minutes - An Integer specifying the number
|
1223
|
+
# of minutes before the start of the
|
1224
|
+
# event that the reminder should
|
1225
|
+
# occur.
|
1226
|
+
# :transparency - The transparency state for the event (optional).
|
1227
|
+
# Accepted values are "transparent" and "opaque".
|
1228
|
+
# :attendees - A Hash of :invite and :reject, each of which is
|
1229
|
+
# an array of invitees to invite to or reject from
|
1230
|
+
# the event. Invitees are represented by a hash of
|
1231
|
+
# :email and :display_name (optional).
|
1232
|
+
# :query_periods - A hash stating the query periods for the event
|
1233
|
+
# target_calendars - An array of hashes stating into which calendars to insert the created
|
1234
|
+
# event
|
1235
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1236
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
1237
|
+
# longer valid.
|
1238
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
1239
|
+
# include the required scope.
|
1240
|
+
# Raises Cronofy::NotFoundError if the calendar does not exist.
|
1241
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1242
|
+
# parameters.
|
1243
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1244
|
+
# limits for the application.
|
1245
|
+
def real_time_sequencing(args)
|
1246
|
+
body = args.merge(client_id: @client_id, client_secret: @client_secret)
|
1247
|
+
|
1248
|
+
if availability = args[:availability]
|
1249
|
+
availability[:sequence] = map_availability_sequence(availability[:sequence])
|
1250
|
+
periods = availability[:query_periods] || availability[:available_periods]
|
1251
|
+
translate_available_periods(periods) if periods
|
1252
|
+
end
|
1253
|
+
|
1254
|
+
body[:availability] = availability
|
1255
|
+
|
1256
|
+
response = raw_post("/v1/real_time_sequencing", body)
|
1257
|
+
parse_json(AddToCalendarResponse, nil , response)
|
1258
|
+
end
|
1259
|
+
|
1260
|
+
# Public: Creates a link_token to allow explicitly linking of an account
|
1261
|
+
#
|
1262
|
+
# See https://www.cronofy.com/developers/api/alpha/#auth-explicit-linking for
|
1263
|
+
# reference.
|
1264
|
+
#
|
1265
|
+
# Returns a link token
|
1266
|
+
#
|
1267
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1268
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
1269
|
+
# longer valid.
|
1270
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1271
|
+
# limits for the application.
|
1272
|
+
def link_token
|
1273
|
+
response = post("/v1/link_tokens", nil)
|
1274
|
+
parse_json(String, 'link_token', response)
|
1275
|
+
end
|
1276
|
+
|
1277
|
+
# Public: Revokes the authorization to the given profile.
|
1278
|
+
#
|
1279
|
+
# See https://www.cronofy.com/developers/api/alpha/#revoke-profile for
|
1280
|
+
# reference.
|
1281
|
+
#
|
1282
|
+
# Returns nothing.
|
1283
|
+
#
|
1284
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1285
|
+
def revoke_profile_authorization(profile_id)
|
1286
|
+
post("/v1/profiles/#{profile_id}/revoke", nil)
|
1287
|
+
nil
|
1288
|
+
end
|
1289
|
+
|
1290
|
+
# Public: Creates or updates smart invite.
|
1291
|
+
#
|
1292
|
+
# smart_invite_id - A String uniquely identifying the event for your
|
1293
|
+
# application (note: this is NOT an ID generated
|
1294
|
+
# by Cronofy).
|
1295
|
+
# callback_url - The URL within your application you want Cronofy to
|
1296
|
+
# send notifications to about user interactions with
|
1297
|
+
# the Smart Invite.
|
1298
|
+
# recipient - A Hash containing the intended recipient of the invite
|
1299
|
+
# :email - A String for the email address you are
|
1300
|
+
# going to send the Smart Invite to.
|
1301
|
+
# event - A Hash describing the event with symbolized keys:
|
1302
|
+
# :summary - A String to use as the summary, sometimes
|
1303
|
+
# referred to as the name or title, of the
|
1304
|
+
# event.
|
1305
|
+
# :description - A String to use as the description, sometimes
|
1306
|
+
# referred to as the notes or body, of the
|
1307
|
+
# event.
|
1308
|
+
# :start - The Time or Date the event starts.
|
1309
|
+
# :end - The Time or Date the event ends.
|
1310
|
+
# :url - The URL associated with the event.
|
1311
|
+
# :location - A Hash describing the location of the event
|
1312
|
+
# with symbolized keys (optional):
|
1313
|
+
# :description - A String describing the
|
1314
|
+
# location.
|
1315
|
+
# :lat - A String of the location's latitude.
|
1316
|
+
# :long - A String of the location's longitude.
|
1317
|
+
# :reminders - An Array of Hashes describing the desired
|
1318
|
+
# reminders for the event. Reminders should be
|
1319
|
+
# specified in priority order as, for example,
|
1320
|
+
# when the underlying provider only supports a
|
1321
|
+
# single reminder then the first reminder will
|
1322
|
+
# be used.
|
1323
|
+
# :minutes - An Integer specifying the number
|
1324
|
+
# of minutes before the start of the
|
1325
|
+
# event that the reminder should
|
1326
|
+
# occur.
|
1327
|
+
# :transparency - The transparency state for the event (optional).
|
1328
|
+
# Accepted values are "transparent" and "opaque".
|
1329
|
+
# :color - The color of the event (optional).
|
1330
|
+
#
|
1331
|
+
# organizer - A Hash containing the details of the organizer.
|
1332
|
+
# :name - A String value for the display name of the
|
1333
|
+
# event organizer
|
1334
|
+
# Examples
|
1335
|
+
#
|
1336
|
+
# client.upsert_smart_invite(
|
1337
|
+
# smart_invite_id: "qTtZdczOccgaPncGJaCiLg",
|
1338
|
+
# callback_url: "http://www.example.com",
|
1339
|
+
# recipient: {
|
1340
|
+
# email: "example@example.com"
|
1341
|
+
# },
|
1342
|
+
# event: {
|
1343
|
+
# summary: "Board meeting",
|
1344
|
+
# description: "Discuss plans for the next quarter.",
|
1345
|
+
# start: Time.utc(2014, 8, 5, 15, 30),
|
1346
|
+
# end: Time.utc(2014, 8, 5, 17, 30),
|
1347
|
+
# location: {
|
1348
|
+
# description: "Board room",
|
1349
|
+
# lat: "1.2345",
|
1350
|
+
# long: "0.1234"
|
1351
|
+
# },
|
1352
|
+
# organizer: {
|
1353
|
+
# name: "Smart invite application"
|
1354
|
+
# }
|
1355
|
+
# )
|
1356
|
+
#
|
1357
|
+
# See http://www.cronofy.com/developers/alpha/api#smart-invite for reference.
|
1358
|
+
#
|
1359
|
+
# Returns a SmartInviteResponse.
|
1360
|
+
#
|
1361
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1362
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1363
|
+
# parameters.
|
1364
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1365
|
+
# limits for the application.
|
1366
|
+
def upsert_smart_invite(body={})
|
1367
|
+
body[:event][:start] = encode_event_time(body[:event][:start])
|
1368
|
+
body[:event][:end] = encode_event_time(body[:event][:end])
|
1369
|
+
|
1370
|
+
response = wrapped_request { api_key!.post("/v1/smart_invites", json_request_args(body)) }
|
1371
|
+
parse_json(SmartInviteResponse, nil, response)
|
1372
|
+
end
|
1373
|
+
|
1374
|
+
|
1375
|
+
# Public: Cancels a smart invite
|
1376
|
+
#
|
1377
|
+
# smart_invite_id - A String uniquely identifying the event for your
|
1378
|
+
# application (note: this is NOT an ID generated
|
1379
|
+
# by Cronofy).
|
1380
|
+
# recipient - A Hash containing the intended recipient of the invite
|
1381
|
+
# :email - A String for thee email address you are
|
1382
|
+
# going to send the Smart Invite to.
|
1383
|
+
#
|
1384
|
+
# See http://www.cronofy.com/developers/alpha/api#smart-invite for reference.
|
1385
|
+
#
|
1386
|
+
# Returns a SmartInviteResponse.
|
1387
|
+
#
|
1388
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1389
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1390
|
+
# parameters.
|
1391
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1392
|
+
# limits for the application.
|
1393
|
+
def cancel_smart_invite(body={})
|
1394
|
+
body[:method] = 'cancel'
|
1395
|
+
response = wrapped_request { api_key!.post("/v1/smart_invites", json_request_args(body)) }
|
1396
|
+
parse_json(SmartInviteResponse, nil, response)
|
1397
|
+
end
|
1398
|
+
|
1399
|
+
# Public: Removes an individual recipient from a multiple recipient smart invite
|
1400
|
+
#
|
1401
|
+
# smart_invite_id - A String uniquely identifying the event for your
|
1402
|
+
# application (note: this is NOT an ID generated
|
1403
|
+
# by Cronofy).
|
1404
|
+
#
|
1405
|
+
# recipient - A Hash containing the recipient to be removed
|
1406
|
+
# :email - A String for the email address of
|
1407
|
+
# the recipient to remove.
|
1408
|
+
#
|
1409
|
+
# See https://docs.cronofy.com/developers/api-alpha/smart-invites/multiple-recipients/#remove-invite-recipient
|
1410
|
+
# for reference.
|
1411
|
+
#
|
1412
|
+
# Returns a SmartInviteResponse
|
1413
|
+
#
|
1414
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1415
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1416
|
+
# parameters.
|
1417
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1418
|
+
# limits for the application.
|
1419
|
+
def remove_recipient_smart_invite(body={})
|
1420
|
+
body[:method] = 'remove'
|
1421
|
+
response = wrapped_request { api_key!.post("/v1/smart_invites", json_request_args(body)) }
|
1422
|
+
parse_json(SmartInviteResponse, nil, response)
|
1423
|
+
end
|
1424
|
+
|
1425
|
+
# Public: Gets the details for a smart invite.
|
1426
|
+
#
|
1427
|
+
# smart_invite_id - A String uniquely identifying the event for your
|
1428
|
+
# application (note: this is NOT an ID generated
|
1429
|
+
# by Cronofy).
|
1430
|
+
# recipient_email - The email address for the recipient to get details for.
|
1431
|
+
#
|
1432
|
+
# See http://www.cronofy.com/developers/alpha/api#smart-invite for reference.
|
1433
|
+
#
|
1434
|
+
# Returns a SmartInviteResponse.
|
1435
|
+
#
|
1436
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1437
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1438
|
+
# parameters.
|
1439
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1440
|
+
# limits for the application.
|
1441
|
+
def get_smart_invite(smart_invite_id, recipient_email)
|
1442
|
+
response = wrapped_request { api_key!.get("/v1/smart_invites?recipient_email=#{recipient_email}&smart_invite_id=#{smart_invite_id}") }
|
1443
|
+
parse_json(SmartInviteResponse, nil, response)
|
1444
|
+
end
|
1445
|
+
|
1446
|
+
# Public: Creates an element_token to pass to a UI Element
|
1447
|
+
#
|
1448
|
+
# options - A Hash of options for the token
|
1449
|
+
# :permissions - An Array of strings describing the
|
1450
|
+
# permissions required for the token
|
1451
|
+
# :subs - An Array of sub values for the account(s)
|
1452
|
+
# the element will be accessing
|
1453
|
+
# :origin - The scheme://hostname where the token will
|
1454
|
+
# be used.
|
1455
|
+
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin
|
1456
|
+
#
|
1457
|
+
# See https://docs.cronofy.com/developers/ui-elements/authentication for
|
1458
|
+
# reference.
|
1459
|
+
#
|
1460
|
+
# Returns an element token
|
1461
|
+
#
|
1462
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1463
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
1464
|
+
# longer valid.
|
1465
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1466
|
+
# limits for the application.
|
1467
|
+
def element_token(options)
|
1468
|
+
response = wrapped_request { api_key!.post("/v1/element_tokens", json_request_args(options)) }
|
1469
|
+
parse_json(ElementToken, "element_token", response)
|
1470
|
+
end
|
1471
|
+
|
1472
|
+
# Public: Creates or updates an AvailabilityRule.
|
1473
|
+
#
|
1474
|
+
# availability_rule_id - A String uniquely identifying the availability rule
|
1475
|
+
# for the authenticated user in your application
|
1476
|
+
# (note: this is NOT an ID generated by Cronofy).
|
1477
|
+
# tzid - The time zone identifier for the rule.
|
1478
|
+
# calendar_ids - An optional array of calendar_ids that should impact the
|
1479
|
+
# user's availability.
|
1480
|
+
# weekly_periods - An array of objects describing a weekly recurring available period
|
1481
|
+
# :day - A String for the week day
|
1482
|
+
# :start_time - A String for 24hr time that period starts eg: 09:30
|
1483
|
+
# :end_time - A String for 24hr time that period ends eg: 17:30
|
1484
|
+
# Examples
|
1485
|
+
#
|
1486
|
+
# client.upsert_availability_rule(
|
1487
|
+
# availability_rule_id: "qTtZdczOccgaPncGJaCiLg",
|
1488
|
+
# tzid: "America/Chicago",
|
1489
|
+
# calendar_ids: [
|
1490
|
+
# "cal_n23kjnwrw2_jsdfjksn234"
|
1491
|
+
# ],
|
1492
|
+
# weekly_periods: [
|
1493
|
+
# {
|
1494
|
+
# day: "monday",
|
1495
|
+
# start_time: "09:30",
|
1496
|
+
# end_time: "12:30",
|
1497
|
+
# },
|
1498
|
+
# {
|
1499
|
+
# day: "tuesday",
|
1500
|
+
# start_time: "09:30",
|
1501
|
+
# end_time: "12:30",
|
1502
|
+
# }
|
1503
|
+
# ]
|
1504
|
+
# )
|
1505
|
+
#
|
1506
|
+
# See http://www.cronofy.com/developers/alpha/api#availability_rules for reference.
|
1507
|
+
#
|
1508
|
+
# Returns an AvailabilityRuleResponse.
|
1509
|
+
#
|
1510
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1511
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1512
|
+
# parameters.
|
1513
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1514
|
+
# limits for the application.
|
1515
|
+
def upsert_availability_rule(body)
|
1516
|
+
response = wrapped_request { post("/v1/availability_rules", body) }
|
1517
|
+
parse_json(AvailabilityRule, 'availability_rule', response)
|
1518
|
+
end
|
1519
|
+
|
1520
|
+
# Public: Gets an AvailabilityRule.
|
1521
|
+
#
|
1522
|
+
# availability_rule_id - A String uniquely identifying the availability rule
|
1523
|
+
# for the authenticated user in your application
|
1524
|
+
#
|
1525
|
+
# Returns an AvailabilityRuleResponse.
|
1526
|
+
#
|
1527
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1528
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1529
|
+
# parameters.
|
1530
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1531
|
+
# limits for the application.
|
1532
|
+
def get_availability_rule(availability_rule_id)
|
1533
|
+
response = wrapped_request { get("/v1/availability_rules/#{availability_rule_id}") }
|
1534
|
+
parse_json(AvailabilityRule, 'availability_rule', response)
|
1535
|
+
end
|
1536
|
+
|
1537
|
+
# Public: Gets all AvailabilityRules for an account.
|
1538
|
+
#
|
1539
|
+
# Returns an array of AvailabilityRules.
|
1540
|
+
#
|
1541
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1542
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1543
|
+
# parameters.
|
1544
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1545
|
+
# limits for the application.
|
1546
|
+
def get_availability_rules
|
1547
|
+
response = wrapped_request { get("/v1/availability_rules") }
|
1548
|
+
parse_collection(AvailabilityRule, 'availability_rules', response)
|
1549
|
+
end
|
1550
|
+
|
1551
|
+
# Public: Deletes an AvailabilityRule.
|
1552
|
+
#
|
1553
|
+
# availability_rule_id - A String uniquely identifying the availability rule
|
1554
|
+
# for the authenticated user in your application
|
1555
|
+
#
|
1556
|
+
# Returns nothing.
|
1557
|
+
#
|
1558
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1559
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1560
|
+
# parameters.
|
1561
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1562
|
+
# limits for the application.
|
1563
|
+
def delete_availability_rule(availability_rule_id)
|
1564
|
+
wrapped_request { delete("/v1/availability_rules/#{availability_rule_id}") }
|
1565
|
+
nil
|
1566
|
+
end
|
1567
|
+
|
1568
|
+
# Public: Creates or updates an AvailablePeriod.
|
1569
|
+
#
|
1570
|
+
# available_period_id - A String uniquely identifying the available period
|
1571
|
+
# for the authenticated user in your application
|
1572
|
+
# (note: this is NOT an ID generated by Cronofy).
|
1573
|
+
# body - A Hash describing the available period with
|
1574
|
+
# symbolized keys:
|
1575
|
+
# :start - A String (ISO-8601 date/time)
|
1576
|
+
# :end - A String (ISO-8601 date/time)
|
1577
|
+
#
|
1578
|
+
# See https://docs.cronofy.com/developers/api/scheduling/available-periods/upsert/
|
1579
|
+
# for reference.
|
1580
|
+
#
|
1581
|
+
# Returns nothing.
|
1582
|
+
#
|
1583
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1584
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1585
|
+
# parameters.
|
1586
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1587
|
+
# limits for the application.
|
1588
|
+
def upsert_available_period(available_period_id, body)
|
1589
|
+
payload = body.merge(available_period_id: available_period_id)
|
1590
|
+
wrapped_request { post("/v1/available_periods", payload) }
|
1591
|
+
nil
|
1592
|
+
end
|
1593
|
+
|
1594
|
+
# Public: Gets all AvailablePeriods for an account.
|
1595
|
+
#
|
1596
|
+
# options - The Hash options used to refine the selection (default: {}):
|
1597
|
+
# :from - The minimum Date from which to return periods
|
1598
|
+
# (optional).
|
1599
|
+
# :to - The Date to return periods up until (optional).
|
1600
|
+
# :tzid - A String representing a known time zone
|
1601
|
+
# identifier from the IANA Time Zone Database
|
1602
|
+
# (default: Etc/UTC).
|
1603
|
+
# :localized_times - A Boolean specifying whether the start and
|
1604
|
+
# end times should be returned with any
|
1605
|
+
# available localization information
|
1606
|
+
# (optional).
|
1607
|
+
#
|
1608
|
+
# Returns an array of AvailablePeriods.
|
1609
|
+
#
|
1610
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1611
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1612
|
+
# parameters.
|
1613
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1614
|
+
# limits for the application.
|
1615
|
+
def get_available_periods(options={})
|
1616
|
+
query = {}
|
1617
|
+
query[:from] = to_iso8601(options[:from]) if options[:from]
|
1618
|
+
query[:to] = to_iso8601(options[:to]) if options[:to]
|
1619
|
+
query[:tzid] = options[:tzid] if options[:tzid]
|
1620
|
+
query[:localized_times] = options[:localized_times] if options[:localized_times]
|
1621
|
+
if query.any?
|
1622
|
+
query_string = "?#{URI.encode_www_form(query)}"
|
1623
|
+
end
|
1624
|
+
|
1625
|
+
response = wrapped_request { get("/v1/available_periods#{query_string}") }
|
1626
|
+
parse_collection(AvailablePeriod, 'available_periods', response)
|
1627
|
+
end
|
1628
|
+
|
1629
|
+
# Public: Deletes an AvailablePeriod.
|
1630
|
+
#
|
1631
|
+
# available_period_id - A String uniquely identifying the available period
|
1632
|
+
# for the authenticated user in your application
|
1633
|
+
#
|
1634
|
+
# Returns nothing.
|
1635
|
+
#
|
1636
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
1637
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
1638
|
+
# parameters.
|
1639
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
1640
|
+
# limits for the application.
|
1641
|
+
def delete_available_period(available_period_id)
|
1642
|
+
wrapped_request { delete("/v1/available_periods", available_period_id: available_period_id) }
|
1643
|
+
nil
|
1644
|
+
end
|
1645
|
+
|
1646
|
+
# Public: Creates a scheduling conversation
|
1647
|
+
#
|
1648
|
+
# pre release end-point documentation to follow
|
1649
|
+
#
|
1650
|
+
def create_scheduling_conversation(body)
|
1651
|
+
response = wrapped_request { post("/v1/scheduling_conversations", body) }
|
1652
|
+
parse_json(SchedulingConversation, 'scheduling_conversation', response)
|
1653
|
+
end
|
1654
|
+
|
1655
|
+
# Public: Creates a scheduling conversation
|
1656
|
+
#
|
1657
|
+
# pre release end-point documentation to follow
|
1658
|
+
#
|
1659
|
+
def get_scheduling_conversation(id)
|
1660
|
+
response = wrapped_request { get("/v1/scheduling_conversations/#{id}") }
|
1661
|
+
parse_json(SchedulingConversation, 'scheduling_conversation', response)
|
1662
|
+
end
|
1663
|
+
|
1664
|
+
# Public: Looks up a scheduling conversation with a token returned by a redirect
|
1665
|
+
#
|
1666
|
+
# pre release end-point documentation to follow
|
1667
|
+
#
|
1668
|
+
def lookup_scheduling_conversation(token)
|
1669
|
+
response = wrapped_request { get("/v1/scheduling_conversations?token=#{token}") }
|
1670
|
+
parse_json(SchedulingConversationResponse, nil, response)
|
1671
|
+
end
|
1672
|
+
|
1673
|
+
# Public: List available slots for a scheduling conversation
|
1674
|
+
#
|
1675
|
+
# pre release end-point documentation to follow
|
1676
|
+
#
|
1677
|
+
def list_scheduling_conversation_participant_slots(url)
|
1678
|
+
response = wrapped_request { get(url) }
|
1679
|
+
parse_collection(SchedulingConversationSlot, "slots", response )
|
1680
|
+
end
|
1681
|
+
|
1682
|
+
# Public: Choose one or more slots for a scheduling conversation
|
1683
|
+
#
|
1684
|
+
# pre release end-point documentation to follow
|
1685
|
+
#
|
1686
|
+
def select_scheduling_conversation_participant_slots(url, args)
|
1687
|
+
response = wrapped_request { post(url, args)}
|
1688
|
+
parse_json(SchedulingConversation, 'scheduling_conversation', response)
|
1689
|
+
end
|
1690
|
+
|
1691
|
+
private
|
1692
|
+
|
1693
|
+
def translate_available_periods(periods)
|
1694
|
+
periods.each do |params|
|
1695
|
+
AVAILABLE_PERIODS_TIME_PARAMS.select { |tp| params.key?(tp) }.each do |tp|
|
1696
|
+
params[tp] = to_iso8601(params[tp])
|
1697
|
+
end
|
1698
|
+
end
|
1699
|
+
end
|
1700
|
+
|
1701
|
+
def map_availability_participants(participants)
|
1702
|
+
case participants
|
1703
|
+
when Hash
|
1704
|
+
# Allow one group to be specified without being nested
|
1705
|
+
[map_availability_participants_group(participants)]
|
1706
|
+
when Enumerable
|
1707
|
+
participants.map do |group|
|
1708
|
+
map_availability_participants_group(group)
|
1709
|
+
end
|
1710
|
+
else
|
1711
|
+
participants
|
1712
|
+
end
|
1713
|
+
end
|
1714
|
+
|
1715
|
+
def map_availability_participants_group(participants)
|
1716
|
+
case participants
|
1717
|
+
when Hash
|
1718
|
+
participants[:members].map! do |member|
|
1719
|
+
map_availability_member(member)
|
1720
|
+
end
|
1721
|
+
|
1722
|
+
unless participants.key?(:required)
|
1723
|
+
participants[:required] = :all
|
1724
|
+
end
|
1725
|
+
|
1726
|
+
participants
|
1727
|
+
when Array
|
1728
|
+
participants.map do |group|
|
1729
|
+
map_availability_participants(group)
|
1730
|
+
end
|
1731
|
+
else
|
1732
|
+
participants
|
1733
|
+
end
|
1734
|
+
end
|
1735
|
+
|
1736
|
+
def map_availability_member(member)
|
1737
|
+
case member
|
1738
|
+
when String
|
1739
|
+
{ sub: member }
|
1740
|
+
when Hash
|
1741
|
+
if member[:available_periods]
|
1742
|
+
translate_available_periods(member[:available_periods])
|
1743
|
+
end
|
1744
|
+
member
|
1745
|
+
else
|
1746
|
+
member
|
1747
|
+
end
|
1748
|
+
end
|
1749
|
+
|
1750
|
+
def map_availability_required_duration(required_duration)
|
1751
|
+
case required_duration
|
1752
|
+
when Integer
|
1753
|
+
{ minutes: required_duration }
|
1754
|
+
else
|
1755
|
+
required_duration
|
1756
|
+
end
|
1757
|
+
end
|
1758
|
+
|
1759
|
+
def map_availability_buffer(buffer)
|
1760
|
+
result = {}
|
1761
|
+
|
1762
|
+
unless buffer.is_a?(Hash)
|
1763
|
+
return result
|
1764
|
+
end
|
1765
|
+
|
1766
|
+
if before_buffer = buffer[:before]
|
1767
|
+
result[:before] = map_buffer_details(before_buffer)
|
1768
|
+
end
|
1769
|
+
|
1770
|
+
if after_buffer = buffer[:after]
|
1771
|
+
result[:after] = map_buffer_details(after_buffer)
|
1772
|
+
end
|
1773
|
+
|
1774
|
+
result
|
1775
|
+
end
|
1776
|
+
|
1777
|
+
def map_buffer_details(buffer)
|
1778
|
+
result = map_availability_required_duration(buffer)
|
1779
|
+
|
1780
|
+
if minimum_buffer = buffer[:minimum]
|
1781
|
+
result[:minimum] = map_availability_required_duration(minimum_buffer)
|
1782
|
+
end
|
1783
|
+
|
1784
|
+
if maximum_buffer = buffer[:maximum]
|
1785
|
+
result[:maximum] = map_availability_required_duration(maximum_buffer)
|
1786
|
+
end
|
1787
|
+
|
1788
|
+
result
|
1789
|
+
end
|
1790
|
+
|
1791
|
+
def map_availability_sequence(sequence)
|
1792
|
+
case sequence
|
1793
|
+
when Enumerable
|
1794
|
+
sequence.map do |sequence_item|
|
1795
|
+
hash = {}
|
1796
|
+
|
1797
|
+
if value = sequence_item[:participants]
|
1798
|
+
hash[:participants] = map_availability_participants(value)
|
1799
|
+
end
|
1800
|
+
|
1801
|
+
if value = sequence_item[:required_duration]
|
1802
|
+
hash[:required_duration] = map_availability_required_duration(value)
|
1803
|
+
end
|
1804
|
+
|
1805
|
+
periods = sequence_item[:query_periods] || sequence_item[:available_periods]
|
1806
|
+
|
1807
|
+
if periods
|
1808
|
+
translate_available_periods(periods)
|
1809
|
+
end
|
1810
|
+
|
1811
|
+
if value = sequence_item[:start_interval]
|
1812
|
+
hash[:start_interval] = map_availability_required_duration(value)
|
1813
|
+
end
|
1814
|
+
|
1815
|
+
if buffer = sequence_item[:buffer]
|
1816
|
+
hash[:buffer] = map_availability_buffer(buffer)
|
1817
|
+
end
|
1818
|
+
|
1819
|
+
sequence_item.merge(hash)
|
1820
|
+
end
|
1821
|
+
else
|
1822
|
+
sequence
|
1823
|
+
end
|
1824
|
+
end
|
1825
|
+
|
1826
|
+
AVAILABLE_PERIODS_TIME_PARAMS = %i{
|
1827
|
+
start
|
1828
|
+
end
|
1829
|
+
}.freeze
|
1830
|
+
|
1831
|
+
FREE_BUSY_DEFAULT_PARAMS = { tzid: "Etc/UTC" }.freeze
|
1832
|
+
FREE_BUSY_TIME_PARAMS = %i{
|
1833
|
+
from
|
1834
|
+
to
|
1835
|
+
}.freeze
|
1836
|
+
|
1837
|
+
READ_EVENTS_DEFAULT_PARAMS = { tzid: "Etc/UTC" }.freeze
|
1838
|
+
READ_EVENTS_TIME_PARAMS = %i{
|
1839
|
+
from
|
1840
|
+
to
|
1841
|
+
last_modified
|
1842
|
+
}.freeze
|
1843
|
+
|
1844
|
+
def access_token!
|
1845
|
+
raise CredentialsMissingError.new unless @auth.access_token
|
1846
|
+
@auth.access_token
|
1847
|
+
end
|
1848
|
+
|
1849
|
+
def api_key!
|
1850
|
+
raise CredentialsMissingError.new unless @auth.api_key
|
1851
|
+
@auth.api_key
|
1852
|
+
end
|
1853
|
+
|
1854
|
+
def get(url, opts = {})
|
1855
|
+
wrapped_request { access_token!.get(url, opts) }
|
1856
|
+
end
|
1857
|
+
|
1858
|
+
def post(url, body)
|
1859
|
+
wrapped_request { access_token!.post(url, json_request_args(body)) }
|
1860
|
+
end
|
1861
|
+
|
1862
|
+
def delete(url, body = nil)
|
1863
|
+
wrapped_request { access_token!.delete(url, json_request_args(body)) }
|
1864
|
+
end
|
1865
|
+
|
1866
|
+
def raw_post(url, body)
|
1867
|
+
wrapped_request { @auth.api_client.request(:post, url, json_request_args(body)) }
|
1868
|
+
end
|
1869
|
+
|
1870
|
+
# Availability Query could originally be authenticated via an access_token
|
1871
|
+
# Whilst it should be authed via an API key now, we try access_token first
|
1872
|
+
# for backward compatibility
|
1873
|
+
def availability_post(url, body)
|
1874
|
+
if @auth.access_token
|
1875
|
+
post(url, body)
|
1876
|
+
else
|
1877
|
+
wrapped_request { api_key!.post(url, json_request_args(body)) }
|
1878
|
+
end
|
1879
|
+
end
|
1880
|
+
|
1881
|
+
def wrapped_request
|
1882
|
+
yield
|
1883
|
+
rescue OAuth2::Error => e
|
1884
|
+
raise Errors.map_error(e)
|
1885
|
+
end
|
1886
|
+
|
1887
|
+
def parse_collection(type, attr, response)
|
1888
|
+
ResponseParser.new(response).parse_collection(type, attr)
|
1889
|
+
end
|
1890
|
+
|
1891
|
+
def parse_collections(response, mappings)
|
1892
|
+
ResponseParser.new(response).parse_collections(mappings)
|
1893
|
+
end
|
1894
|
+
|
1895
|
+
def parse_json(type, attr = nil, response)
|
1896
|
+
ResponseParser.new(response).parse_json(type, attr)
|
1897
|
+
end
|
1898
|
+
|
1899
|
+
def json_request_args(body_hash)
|
1900
|
+
if body_hash
|
1901
|
+
{
|
1902
|
+
body: JSON.generate(body_hash),
|
1903
|
+
headers: { "Content-Type" => "application/json; charset=utf-8" },
|
1904
|
+
}
|
1905
|
+
else
|
1906
|
+
{}
|
1907
|
+
end
|
1908
|
+
end
|
1909
|
+
|
1910
|
+
class PagedResultIterator
|
1911
|
+
include Enumerable
|
1912
|
+
|
1913
|
+
def initialize(page_parser, items_key, access_token, url, params)
|
1914
|
+
@page_parser = page_parser
|
1915
|
+
@items_key = items_key
|
1916
|
+
@access_token = access_token
|
1917
|
+
@url = url
|
1918
|
+
@params = params
|
1919
|
+
@first_page = get_page(url, params)
|
1920
|
+
end
|
1921
|
+
|
1922
|
+
def each
|
1923
|
+
page = @first_page
|
1924
|
+
|
1925
|
+
page[@items_key].each do |item|
|
1926
|
+
yield item
|
1927
|
+
end
|
1928
|
+
|
1929
|
+
while page.pages.next_page?
|
1930
|
+
page = get_page(page.pages.next_page)
|
1931
|
+
|
1932
|
+
page[@items_key].each do |item|
|
1933
|
+
yield item
|
1934
|
+
end
|
1935
|
+
end
|
1936
|
+
end
|
1937
|
+
|
1938
|
+
private
|
1939
|
+
|
1940
|
+
attr_reader :access_token
|
1941
|
+
attr_reader :params
|
1942
|
+
attr_reader :url
|
1943
|
+
|
1944
|
+
def get_page(url, params = {})
|
1945
|
+
response = http_get(url, params)
|
1946
|
+
parse_page(response)
|
1947
|
+
end
|
1948
|
+
|
1949
|
+
def http_get(url, params = {})
|
1950
|
+
response = Faraday.get(url, params, oauth_headers)
|
1951
|
+
Errors.raise_if_error(response)
|
1952
|
+
response
|
1953
|
+
end
|
1954
|
+
|
1955
|
+
def oauth_headers
|
1956
|
+
{
|
1957
|
+
"Authorization" => "Bearer #{access_token.token}",
|
1958
|
+
"User-Agent" => "Cronofy Ruby #{::Cronofy::VERSION}",
|
1959
|
+
}
|
1960
|
+
end
|
1961
|
+
|
1962
|
+
def parse_page(response)
|
1963
|
+
ResponseParser.new(response).parse_json(@page_parser)
|
1964
|
+
end
|
1965
|
+
end
|
1966
|
+
|
1967
|
+
def api_url
|
1968
|
+
::Cronofy.api_url(@data_center)
|
1969
|
+
end
|
117
1970
|
end
|
118
1971
|
|
119
|
-
|
1972
|
+
# Deprecated: Alias for Client for backwards compatibility.
|
1973
|
+
class Cronofy < Client
|
1974
|
+
end
|
1975
|
+
end
|