@webex/internal-plugin-calendar 2.59.3-next.1 → 2.59.4

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.
package/src/calendar.js CHANGED
@@ -1,490 +1,490 @@
1
- /*!
2
- * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
- */
4
-
5
- /**
6
- * Calendar Item Create Event
7
- * Emitted when a calendar item has been added
8
- * @event calendar:meeting:create
9
- * @instance
10
- * @memberof Calendar
11
- */
12
-
13
- /**
14
- * Calendar Item Update Event
15
- * Emitted when a calendar item has been updated
16
- * @event calendar:meeting:update
17
- * @instance
18
- * @memberof Calendar
19
- */
20
-
21
- /**
22
- * Calendar Item Update Event
23
- * Emitted when a calendar item has been deleted
24
- * @event calendar:meeting:delete
25
- * @instance
26
- * @memberof Calendar
27
- */
28
-
29
- /**
30
- * Calendar Registered Event
31
- * Emitted when the calendar instance has been registered and listening
32
- * @event calendar:registered
33
- * @instance
34
- * @memberof Calendar
35
- */
36
-
37
- /**
38
- * Calendar Registered Event
39
- * Emitted when the calendar instance has been registered and listening
40
- * @event calendar:unregistered
41
- * @instance
42
- * @memberof Calendar
43
- */
44
- import {isArray} from 'lodash';
45
- import {base64} from '@webex/common';
46
- import {WebexPlugin} from '@webex/webex-core';
47
-
48
- import CalendarCollection from './collection';
49
- import {
50
- CALENDAR_REGISTERED,
51
- CALENDAR_UNREGISTERED,
52
- CALENDAR_DELETE,
53
- CALENDAR_CREATE,
54
- CALENDAR_UPDATED,
55
- } from './constants';
56
-
57
- import EncryptHelper from './calendar.encrypt.helper';
58
- import DecryptHelper from './calendar.decrypt.helper';
59
-
60
- const Calendar = WebexPlugin.extend({
61
- namespace: 'Calendar',
62
-
63
- /**
64
- * registered value indicating events registration is successful
65
- * @instance
66
- * @type {Boolean}
67
- * @memberof Calendar
68
- */
69
- registered: false,
70
-
71
- /**
72
- * Cache all rpc event request locally
73
- * */
74
- rpcEventRequests: [],
75
-
76
- /**
77
- * Cache KMS encryptionKeyUrl
78
- * */
79
- encryptionKeyUrl: null,
80
-
81
- /**
82
- * WebexPlugin initialize method. This triggers once Webex has completed its
83
- * initialization workflow.
84
- *
85
- * If the plugin is meant to perform startup actions, place them in this
86
- * `initialize()` method instead of the `constructor()` method.
87
- * @returns {void}
88
- */
89
- initialize() {
90
- // Used to perform actions after webex is fully qualified and ready for
91
- // operation.
92
- this.listenToOnce(this.webex, 'ready', () => {
93
- // Pre-fetch a KMS encryption key url to improve performance
94
- this.webex.internal.encryption.kms.createUnboundKeys({count: 1}).then((keys) => {
95
- const key = isArray(keys) ? keys[0] : keys;
96
- this.encryptionKeyUrl = key ? key.uri : null;
97
- this.logger.info('calendar->bind a KMS encryption key url');
98
- this.webex.internal.encryption
99
- .getKey(this.encryptionKeyUrl, {onBehalfOf: null})
100
- .then((retrievedKey) => {
101
- this.encryptionKeyUrl = retrievedKey ? retrievedKey.uri : null;
102
- this.logger.info('calendar->retrieve the KMS encryption key url and cache it');
103
- });
104
- });
105
- });
106
- },
107
-
108
- /**
109
- * Explicitly sets up the calendar plugin by registering
110
- * the device, connecting to mercury, and listening for calendar events.
111
- * @returns {Promise}
112
- * @public
113
- * @memberof Calendar
114
- */
115
- register() {
116
- if (!this.webex.canAuthorize) {
117
- this.logger.error('calendar->register#ERROR, Unable to register, SDK cannot authorize');
118
-
119
- return Promise.reject(new Error('SDK cannot authorize'));
120
- }
121
-
122
- if (this.registered) {
123
- this.logger.info('calendar->register#INFO, Calendar plugin already registered');
124
-
125
- return Promise.resolve();
126
- }
127
-
128
- return this.webex.internal.device
129
- .register()
130
- .then(() => this.webex.internal.mercury.connect())
131
- .then(() => {
132
- this.listenForEvents();
133
- this.trigger(CALENDAR_REGISTERED);
134
- this.registered = true;
135
- })
136
- .catch((error) => {
137
- this.logger.error(`calendar->register#ERROR, Unable to register, ${error.message}`);
138
-
139
- return Promise.reject(error);
140
- });
141
- },
142
-
143
- /**
144
- * Explicitly tears down the calendar plugin by deregistering
145
- * the device, disconnecting from mercury, and stops listening to calendar events
146
- *
147
- * @returns {Promise}
148
- * @public
149
- * @memberof Calendar
150
- */
151
- unregister() {
152
- if (!this.registered) {
153
- this.logger.info('calendar->unregister#INFO, Calendar plugin already unregistered');
154
-
155
- return Promise.resolve();
156
- }
157
-
158
- this.stopListeningForEvents();
159
-
160
- return this.webex.internal.mercury
161
- .disconnect()
162
- .then(() => this.webex.internal.device.unregister())
163
- .then(() => {
164
- this.trigger(CALENDAR_UNREGISTERED);
165
- this.registered = false;
166
- });
167
- },
168
-
169
- /**
170
- * registers for calendar events through mercury
171
- * @returns {undefined}
172
- * @private
173
- */
174
- listenForEvents() {
175
- // Calendar mercury events listener
176
- this.webex.internal.mercury.on('event:calendar.meeting.create', (envelope) => {
177
- this._handleCreate(envelope.data);
178
- });
179
- this.webex.internal.mercury.on('event:calendar.meeting.update', (envelope) => {
180
- this._handleUpdate(envelope.data);
181
- });
182
- this.webex.internal.mercury.on('event:calendar.meeting.create.minimal', (envelope) => {
183
- this._handleCreate(envelope.data);
184
- });
185
- this.webex.internal.mercury.on('event:calendar.meeting.update.minimal', (envelope) => {
186
- this._handleUpdate(envelope.data);
187
- });
188
- this.webex.internal.mercury.on('event:calendar.meeting.delete', (envelope) => {
189
- this._handleDelete(envelope.data);
190
- });
191
- this.webex.internal.mercury.on('event:calendar.free_busy', (envelope) => {
192
- this._handleFreeBusy(envelope.data);
193
- });
194
- },
195
-
196
- /**
197
- * unregisteres all the calendar events from mercury
198
- * @returns {undefined}
199
- * @private
200
- */
201
- stopListeningForEvents() {
202
- this.webex.internal.mercury.off('event:calendar.meeting.create');
203
- this.webex.internal.mercury.off('event:calendar.meeting.create.minimal');
204
- this.webex.internal.mercury.off('event:calendar.meeting.update');
205
- this.webex.internal.mercury.off('event:calendar.meeting.update.minimal');
206
- this.webex.internal.mercury.off('event:calendar.meeting.delete');
207
- this.webex.internal.mercury.off('event:calendar.free_busy');
208
- },
209
-
210
- /**
211
- * handles update events, triggers after collection updates
212
- * @param {Object} data
213
- * @returns {undefined}
214
- * @private
215
- */
216
- _handleUpdate(data) {
217
- const id = CalendarCollection.set(data.calendarMeetingExternal);
218
-
219
- this.trigger(CALENDAR_UPDATED, CalendarCollection.get(id));
220
- },
221
-
222
- /**
223
- * handles create events, triggers after collection updates
224
- * @param {Object} data
225
- * @returns {undefined}
226
- * @private
227
- */
228
- _handleCreate(data) {
229
- const id = CalendarCollection.set(data.calendarMeetingExternal);
230
-
231
- this.trigger(CALENDAR_CREATE, CalendarCollection.get(id));
232
- },
233
-
234
- /**
235
- * handles delete events, triggers after collection updates
236
- * @param {Object} data
237
- * @returns {undefined}
238
- * @private
239
- */
240
- _handleDelete(data) {
241
- const item = CalendarCollection.remove(data.calendarMeetingExternal.id);
242
-
243
- this.trigger(CALENDAR_DELETE, item);
244
- },
245
-
246
- /**
247
- * handles free_busy events
248
- * @param {Object} data
249
- * @returns {undefined}
250
- * @private
251
- */
252
- _handleFreeBusy(data) {
253
- DecryptHelper.decryptFreeBusyResponse(this, data).then(() => {
254
- let response = {};
255
- if (data && data.calendarFreeBusyScheduleResponse) {
256
- response = data.calendarFreeBusyScheduleResponse;
257
- }
258
- if (response && response.requestId && response.requestId in this.rpcEventRequests) {
259
- this.logger.log(
260
- `webex.internal.calendar - receive requests, requestId: ${response.requestId}`
261
- );
262
- delete response.encryptionKeyUrl;
263
- const {resolve} = this.rpcEventRequests[response.requestId];
264
- resolve(response);
265
- delete this.rpcEventRequests[response.requestId];
266
- } else {
267
- this.logger.log('webex.internal.calendar - receive other requests.');
268
- }
269
- });
270
- },
271
-
272
- /**
273
- * Retrieves a collection of calendars based on the request parameters
274
- * Defaults to 1 day before and 7 days ahead
275
- * @param {Object} options
276
- * @param {Date} options.fromDate the start of the time range
277
- * @param {Date} options.toDate the end of the time range
278
- * @returns {Promise} Resolves with an array of calendars
279
- */
280
- syncCalendar(options = {fromDate: this.config.fromDate, toDate: this.config.toDate}) {
281
- return this.list({fromDate: options.fromDate, toDate: options.toDate}).then((res) => {
282
- CalendarCollection.setAll(res);
283
-
284
- return CalendarCollection.getAll();
285
- });
286
- },
287
- /**
288
- * get the calendar item that has a matching value
289
- * @param {String} key meeting property
290
- * @param {Any} value the meeting property to match
291
- * @returns {Object}
292
- */
293
- getByType(key, value) {
294
- if (['spaceURI', 'spaceMeetURL', 'conversationId'].includes(key)) {
295
- return CalendarCollection.getBy(key, value);
296
- }
297
- throw new Error('key must be one of, spaceURI, spaceMeetURL, or conversationId');
298
- },
299
-
300
- /**
301
- * gets all the calendar items that have been populated
302
- * @returns {Object}
303
- */
304
- getAll() {
305
- return CalendarCollection.getAll();
306
- },
307
-
308
- /**
309
- * Decrypts an encrypted incoming calendar event
310
- * @param {Object} event
311
- * @returns {Promise} Resolves with a decrypted calendar event
312
- */
313
- processMeetingEvent(event) {
314
- return this.webex.transform('inbound', event).then(() => event);
315
- },
316
-
317
- /**
318
- * Retrieves an array of meeting participants for the meeting id
319
- * @param {String} id
320
- * @returns {Promise} Resolves with an object of meeting participants
321
- */
322
- getParticipants(id) {
323
- return this.request({
324
- method: 'GET',
325
- service: 'calendar',
326
- resource: `calendarEvents/${base64.encode(id)}/participants`,
327
- });
328
- },
329
-
330
- /**
331
- * Retrieves a collection of meetings based on the request parameters
332
- * @param {String} id
333
- * @returns {Promise} Resolves with an object of meeting notes
334
- */
335
- getNotes(id) {
336
- return this.request({
337
- method: 'GET',
338
- service: 'calendar',
339
- resource: `calendarEvents/${base64.encode(id)}/notes`,
340
- });
341
- },
342
-
343
- /**
344
- * Retrieves a collection of meetings based on the request parameters
345
- * @param {Object} options
346
- * @param {Date} options.fromDate the start of the time range
347
- * @param {Date} options.toDate the end of the time range
348
- * @returns {Promise} Resolves with an array of meetings
349
- */
350
- list(options) {
351
- options = options || {};
352
-
353
- return this.webex
354
- .request({
355
- method: 'GET',
356
- service: 'calendar',
357
- resource: 'calendarEvents',
358
- qs: options,
359
- })
360
- .then((res) => {
361
- const meetingObjects = res.body.items;
362
- const promises = [];
363
-
364
- meetingObjects.forEach((meeting) => {
365
- if (!meeting.encryptedParticipants) {
366
- promises.push(
367
- this.getParticipants(meeting.id).then((notesResponse) => {
368
- meeting.encryptedParticipants = notesResponse.body.encryptedParticipants;
369
- })
370
- );
371
- }
372
- });
373
-
374
- return Promise.all(promises).then(() => meetingObjects);
375
- });
376
- },
377
-
378
- /**
379
- * Create calendar event
380
- * @param {object} [data] meeting payload data
381
- * @param {object} [query] the query parameters for specific usage
382
- * @returns {Promise} Resolves with creating calendar event response
383
- * */
384
- createCalendarEvent(data, query) {
385
- return EncryptHelper.encryptCalendarEventRequest(this, data).then(() =>
386
- this.request({
387
- method: 'POST',
388
- service: 'calendar',
389
- body: data,
390
- resource: 'calendarEvents/sync',
391
- qs: query || {},
392
- })
393
- );
394
- },
395
-
396
- /**
397
- * Update calendar event
398
- * @param {string} [id] calendar event id
399
- * @param {object} [data] meeting payload data
400
- * @param {object} [query] the query parameters for specific usage
401
- * @returns {Promise} Resolves with updating calendar event response
402
- * */
403
- updateCalendarEvent(id, data, query) {
404
- return EncryptHelper.encryptCalendarEventRequest(this, data).then(() =>
405
- this.request({
406
- method: 'PATCH',
407
- service: 'calendar',
408
- body: data,
409
- resource: `calendarEvents/${base64.encode(id)}/sync`,
410
- qs: query || {},
411
- })
412
- );
413
- },
414
-
415
- /**
416
- * Delete calendar event
417
- * @param {string} [id] calendar event id
418
- * @param {object} [query] the query parameters for specific usage
419
- * @returns {Promise} Resolves with deleting calendar event response
420
- * */
421
- deleteCalendarEvent(id, query) {
422
- return this.request({
423
- method: 'DELETE',
424
- service: 'calendar',
425
- resource: `calendarEvents/${base64.encode(id)}/sync`,
426
- qs: query || {},
427
- });
428
- },
429
-
430
- /**
431
- * @typedef QuerySchedulerDataOptions
432
- * @param {string} [siteName] it is site full url, must have. Example: ccctest.dmz.webex.com
433
- * @param {string} [id] it is seriesOrOccurrenceId. If present, the series/occurrence meeting ID to fetch data for.
434
- * Example: 040000008200E00074C5B7101A82E008000000004A99F11A0841D9010000000000000000100000009EE499D4A71C1A46B51494C70EC7BFE5
435
- * @param {string} [clientMeetingId] If present, the client meeting UUID to fetch data for.
436
- * Example: 7f318aa9-887c-6e94-802a-8dc8e6eb1a0a
437
- * @param {string} [scheduleTemplateId] it template id.
438
- * @param {string} [sessionTypeId] it session type id.
439
- * @param {string} [organizerCIUserId] required in schedule-on-behalf case. It is the organizer's CI UUID.
440
- * @param {boolean} [usmPreference]
441
- * @param {string} [webexMeetingId] webex side meeting UUID
442
- * @param {string} [eventId] event ID.
443
- * @param {string} [icalUid] icalendar UUID.
444
- * @param {string} [thirdPartyType] third part type, such as: Microsoft
445
- */
446
- /**
447
- * Get scheduler data from calendar service
448
- * @param {QuerySchedulerDataOptions} [query] the command parameters for fetching scheduler data.
449
- * @returns {Promise} Resolves with a decrypted scheduler data
450
- * */
451
- getSchedulerData(query) {
452
- return this.request({
453
- method: 'GET',
454
- service: 'calendar',
455
- resource: 'schedulerData',
456
- qs: query || {},
457
- }).then((response) => {
458
- return DecryptHelper.decryptSchedulerDataResponse(this, response.body).then(() => response);
459
- });
460
- },
461
-
462
- /**
463
- * Get free busy status from calendar service
464
- * @param {Object} [data] the command parameters for fetching free busy status.
465
- * @param {object} [query] the query parameters for specific usage
466
- * @returns {Promise} Resolves with a decrypted response
467
- * */
468
- getFreeBusy(data, query) {
469
- return EncryptHelper.encryptFreeBusyRequest(this, data)
470
- .then(() => {
471
- return this.request({
472
- method: 'POST',
473
- service: 'calendar',
474
- body: data,
475
- resource: 'freebusy',
476
- qs: query || {},
477
- });
478
- })
479
- .then(() => {
480
- return new Promise((resolve, reject) => {
481
- this.rpcEventRequests[data.requestId] = {resolve, reject};
482
- });
483
- })
484
- .catch((error) => {
485
- throw error;
486
- });
487
- },
488
- });
489
-
490
- export default Calendar;
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ /**
6
+ * Calendar Item Create Event
7
+ * Emitted when a calendar item has been added
8
+ * @event calendar:meeting:create
9
+ * @instance
10
+ * @memberof Calendar
11
+ */
12
+
13
+ /**
14
+ * Calendar Item Update Event
15
+ * Emitted when a calendar item has been updated
16
+ * @event calendar:meeting:update
17
+ * @instance
18
+ * @memberof Calendar
19
+ */
20
+
21
+ /**
22
+ * Calendar Item Update Event
23
+ * Emitted when a calendar item has been deleted
24
+ * @event calendar:meeting:delete
25
+ * @instance
26
+ * @memberof Calendar
27
+ */
28
+
29
+ /**
30
+ * Calendar Registered Event
31
+ * Emitted when the calendar instance has been registered and listening
32
+ * @event calendar:registered
33
+ * @instance
34
+ * @memberof Calendar
35
+ */
36
+
37
+ /**
38
+ * Calendar Registered Event
39
+ * Emitted when the calendar instance has been registered and listening
40
+ * @event calendar:unregistered
41
+ * @instance
42
+ * @memberof Calendar
43
+ */
44
+ import {isArray} from 'lodash';
45
+ import {base64} from '@webex/common';
46
+ import {WebexPlugin} from '@webex/webex-core';
47
+
48
+ import CalendarCollection from './collection';
49
+ import {
50
+ CALENDAR_REGISTERED,
51
+ CALENDAR_UNREGISTERED,
52
+ CALENDAR_DELETE,
53
+ CALENDAR_CREATE,
54
+ CALENDAR_UPDATED,
55
+ } from './constants';
56
+
57
+ import EncryptHelper from './calendar.encrypt.helper';
58
+ import DecryptHelper from './calendar.decrypt.helper';
59
+
60
+ const Calendar = WebexPlugin.extend({
61
+ namespace: 'Calendar',
62
+
63
+ /**
64
+ * registered value indicating events registration is successful
65
+ * @instance
66
+ * @type {Boolean}
67
+ * @memberof Calendar
68
+ */
69
+ registered: false,
70
+
71
+ /**
72
+ * Cache all rpc event request locally
73
+ * */
74
+ rpcEventRequests: [],
75
+
76
+ /**
77
+ * Cache KMS encryptionKeyUrl
78
+ * */
79
+ encryptionKeyUrl: null,
80
+
81
+ /**
82
+ * WebexPlugin initialize method. This triggers once Webex has completed its
83
+ * initialization workflow.
84
+ *
85
+ * If the plugin is meant to perform startup actions, place them in this
86
+ * `initialize()` method instead of the `constructor()` method.
87
+ * @returns {void}
88
+ */
89
+ initialize() {
90
+ // Used to perform actions after webex is fully qualified and ready for
91
+ // operation.
92
+ this.listenToOnce(this.webex, 'ready', () => {
93
+ // Pre-fetch a KMS encryption key url to improve performance
94
+ this.webex.internal.encryption.kms.createUnboundKeys({count: 1}).then((keys) => {
95
+ const key = isArray(keys) ? keys[0] : keys;
96
+ this.encryptionKeyUrl = key ? key.uri : null;
97
+ this.logger.info('calendar->bind a KMS encryption key url');
98
+ this.webex.internal.encryption
99
+ .getKey(this.encryptionKeyUrl, {onBehalfOf: null})
100
+ .then((retrievedKey) => {
101
+ this.encryptionKeyUrl = retrievedKey ? retrievedKey.uri : null;
102
+ this.logger.info('calendar->retrieve the KMS encryption key url and cache it');
103
+ });
104
+ });
105
+ });
106
+ },
107
+
108
+ /**
109
+ * Explicitly sets up the calendar plugin by registering
110
+ * the device, connecting to mercury, and listening for calendar events.
111
+ * @returns {Promise}
112
+ * @public
113
+ * @memberof Calendar
114
+ */
115
+ register() {
116
+ if (!this.webex.canAuthorize) {
117
+ this.logger.error('calendar->register#ERROR, Unable to register, SDK cannot authorize');
118
+
119
+ return Promise.reject(new Error('SDK cannot authorize'));
120
+ }
121
+
122
+ if (this.registered) {
123
+ this.logger.info('calendar->register#INFO, Calendar plugin already registered');
124
+
125
+ return Promise.resolve();
126
+ }
127
+
128
+ return this.webex.internal.device
129
+ .register()
130
+ .then(() => this.webex.internal.mercury.connect())
131
+ .then(() => {
132
+ this.listenForEvents();
133
+ this.trigger(CALENDAR_REGISTERED);
134
+ this.registered = true;
135
+ })
136
+ .catch((error) => {
137
+ this.logger.error(`calendar->register#ERROR, Unable to register, ${error.message}`);
138
+
139
+ return Promise.reject(error);
140
+ });
141
+ },
142
+
143
+ /**
144
+ * Explicitly tears down the calendar plugin by deregistering
145
+ * the device, disconnecting from mercury, and stops listening to calendar events
146
+ *
147
+ * @returns {Promise}
148
+ * @public
149
+ * @memberof Calendar
150
+ */
151
+ unregister() {
152
+ if (!this.registered) {
153
+ this.logger.info('calendar->unregister#INFO, Calendar plugin already unregistered');
154
+
155
+ return Promise.resolve();
156
+ }
157
+
158
+ this.stopListeningForEvents();
159
+
160
+ return this.webex.internal.mercury
161
+ .disconnect()
162
+ .then(() => this.webex.internal.device.unregister())
163
+ .then(() => {
164
+ this.trigger(CALENDAR_UNREGISTERED);
165
+ this.registered = false;
166
+ });
167
+ },
168
+
169
+ /**
170
+ * registers for calendar events through mercury
171
+ * @returns {undefined}
172
+ * @private
173
+ */
174
+ listenForEvents() {
175
+ // Calendar mercury events listener
176
+ this.webex.internal.mercury.on('event:calendar.meeting.create', (envelope) => {
177
+ this._handleCreate(envelope.data);
178
+ });
179
+ this.webex.internal.mercury.on('event:calendar.meeting.update', (envelope) => {
180
+ this._handleUpdate(envelope.data);
181
+ });
182
+ this.webex.internal.mercury.on('event:calendar.meeting.create.minimal', (envelope) => {
183
+ this._handleCreate(envelope.data);
184
+ });
185
+ this.webex.internal.mercury.on('event:calendar.meeting.update.minimal', (envelope) => {
186
+ this._handleUpdate(envelope.data);
187
+ });
188
+ this.webex.internal.mercury.on('event:calendar.meeting.delete', (envelope) => {
189
+ this._handleDelete(envelope.data);
190
+ });
191
+ this.webex.internal.mercury.on('event:calendar.free_busy', (envelope) => {
192
+ this._handleFreeBusy(envelope.data);
193
+ });
194
+ },
195
+
196
+ /**
197
+ * unregisteres all the calendar events from mercury
198
+ * @returns {undefined}
199
+ * @private
200
+ */
201
+ stopListeningForEvents() {
202
+ this.webex.internal.mercury.off('event:calendar.meeting.create');
203
+ this.webex.internal.mercury.off('event:calendar.meeting.create.minimal');
204
+ this.webex.internal.mercury.off('event:calendar.meeting.update');
205
+ this.webex.internal.mercury.off('event:calendar.meeting.update.minimal');
206
+ this.webex.internal.mercury.off('event:calendar.meeting.delete');
207
+ this.webex.internal.mercury.off('event:calendar.free_busy');
208
+ },
209
+
210
+ /**
211
+ * handles update events, triggers after collection updates
212
+ * @param {Object} data
213
+ * @returns {undefined}
214
+ * @private
215
+ */
216
+ _handleUpdate(data) {
217
+ const id = CalendarCollection.set(data.calendarMeetingExternal);
218
+
219
+ this.trigger(CALENDAR_UPDATED, CalendarCollection.get(id));
220
+ },
221
+
222
+ /**
223
+ * handles create events, triggers after collection updates
224
+ * @param {Object} data
225
+ * @returns {undefined}
226
+ * @private
227
+ */
228
+ _handleCreate(data) {
229
+ const id = CalendarCollection.set(data.calendarMeetingExternal);
230
+
231
+ this.trigger(CALENDAR_CREATE, CalendarCollection.get(id));
232
+ },
233
+
234
+ /**
235
+ * handles delete events, triggers after collection updates
236
+ * @param {Object} data
237
+ * @returns {undefined}
238
+ * @private
239
+ */
240
+ _handleDelete(data) {
241
+ const item = CalendarCollection.remove(data.calendarMeetingExternal.id);
242
+
243
+ this.trigger(CALENDAR_DELETE, item);
244
+ },
245
+
246
+ /**
247
+ * handles free_busy events
248
+ * @param {Object} data
249
+ * @returns {undefined}
250
+ * @private
251
+ */
252
+ _handleFreeBusy(data) {
253
+ DecryptHelper.decryptFreeBusyResponse(this, data).then(() => {
254
+ let response = {};
255
+ if (data && data.calendarFreeBusyScheduleResponse) {
256
+ response = data.calendarFreeBusyScheduleResponse;
257
+ }
258
+ if (response && response.requestId && response.requestId in this.rpcEventRequests) {
259
+ this.logger.log(
260
+ `webex.internal.calendar - receive requests, requestId: ${response.requestId}`
261
+ );
262
+ delete response.encryptionKeyUrl;
263
+ const {resolve} = this.rpcEventRequests[response.requestId];
264
+ resolve(response);
265
+ delete this.rpcEventRequests[response.requestId];
266
+ } else {
267
+ this.logger.log('webex.internal.calendar - receive other requests.');
268
+ }
269
+ });
270
+ },
271
+
272
+ /**
273
+ * Retrieves a collection of calendars based on the request parameters
274
+ * Defaults to 1 day before and 7 days ahead
275
+ * @param {Object} options
276
+ * @param {Date} options.fromDate the start of the time range
277
+ * @param {Date} options.toDate the end of the time range
278
+ * @returns {Promise} Resolves with an array of calendars
279
+ */
280
+ syncCalendar(options = {fromDate: this.config.fromDate, toDate: this.config.toDate}) {
281
+ return this.list({fromDate: options.fromDate, toDate: options.toDate}).then((res) => {
282
+ CalendarCollection.setAll(res);
283
+
284
+ return CalendarCollection.getAll();
285
+ });
286
+ },
287
+ /**
288
+ * get the calendar item that has a matching value
289
+ * @param {String} key meeting property
290
+ * @param {Any} value the meeting property to match
291
+ * @returns {Object}
292
+ */
293
+ getByType(key, value) {
294
+ if (['spaceURI', 'spaceMeetURL', 'conversationId'].includes(key)) {
295
+ return CalendarCollection.getBy(key, value);
296
+ }
297
+ throw new Error('key must be one of, spaceURI, spaceMeetURL, or conversationId');
298
+ },
299
+
300
+ /**
301
+ * gets all the calendar items that have been populated
302
+ * @returns {Object}
303
+ */
304
+ getAll() {
305
+ return CalendarCollection.getAll();
306
+ },
307
+
308
+ /**
309
+ * Decrypts an encrypted incoming calendar event
310
+ * @param {Object} event
311
+ * @returns {Promise} Resolves with a decrypted calendar event
312
+ */
313
+ processMeetingEvent(event) {
314
+ return this.webex.transform('inbound', event).then(() => event);
315
+ },
316
+
317
+ /**
318
+ * Retrieves an array of meeting participants for the meeting id
319
+ * @param {String} id
320
+ * @returns {Promise} Resolves with an object of meeting participants
321
+ */
322
+ getParticipants(id) {
323
+ return this.request({
324
+ method: 'GET',
325
+ service: 'calendar',
326
+ resource: `calendarEvents/${base64.encode(id)}/participants`,
327
+ });
328
+ },
329
+
330
+ /**
331
+ * Retrieves a collection of meetings based on the request parameters
332
+ * @param {String} id
333
+ * @returns {Promise} Resolves with an object of meeting notes
334
+ */
335
+ getNotes(id) {
336
+ return this.request({
337
+ method: 'GET',
338
+ service: 'calendar',
339
+ resource: `calendarEvents/${base64.encode(id)}/notes`,
340
+ });
341
+ },
342
+
343
+ /**
344
+ * Retrieves a collection of meetings based on the request parameters
345
+ * @param {Object} options
346
+ * @param {Date} options.fromDate the start of the time range
347
+ * @param {Date} options.toDate the end of the time range
348
+ * @returns {Promise} Resolves with an array of meetings
349
+ */
350
+ list(options) {
351
+ options = options || {};
352
+
353
+ return this.webex
354
+ .request({
355
+ method: 'GET',
356
+ service: 'calendar',
357
+ resource: 'calendarEvents',
358
+ qs: options,
359
+ })
360
+ .then((res) => {
361
+ const meetingObjects = res.body.items;
362
+ const promises = [];
363
+
364
+ meetingObjects.forEach((meeting) => {
365
+ if (!meeting.encryptedParticipants) {
366
+ promises.push(
367
+ this.getParticipants(meeting.id).then((notesResponse) => {
368
+ meeting.encryptedParticipants = notesResponse.body.encryptedParticipants;
369
+ })
370
+ );
371
+ }
372
+ });
373
+
374
+ return Promise.all(promises).then(() => meetingObjects);
375
+ });
376
+ },
377
+
378
+ /**
379
+ * Create calendar event
380
+ * @param {object} [data] meeting payload data
381
+ * @param {object} [query] the query parameters for specific usage
382
+ * @returns {Promise} Resolves with creating calendar event response
383
+ * */
384
+ createCalendarEvent(data, query) {
385
+ return EncryptHelper.encryptCalendarEventRequest(this, data).then(() =>
386
+ this.request({
387
+ method: 'POST',
388
+ service: 'calendar',
389
+ body: data,
390
+ resource: 'calendarEvents/sync',
391
+ qs: query || {},
392
+ })
393
+ );
394
+ },
395
+
396
+ /**
397
+ * Update calendar event
398
+ * @param {string} [id] calendar event id
399
+ * @param {object} [data] meeting payload data
400
+ * @param {object} [query] the query parameters for specific usage
401
+ * @returns {Promise} Resolves with updating calendar event response
402
+ * */
403
+ updateCalendarEvent(id, data, query) {
404
+ return EncryptHelper.encryptCalendarEventRequest(this, data).then(() =>
405
+ this.request({
406
+ method: 'PATCH',
407
+ service: 'calendar',
408
+ body: data,
409
+ resource: `calendarEvents/${base64.encode(id)}/sync`,
410
+ qs: query || {},
411
+ })
412
+ );
413
+ },
414
+
415
+ /**
416
+ * Delete calendar event
417
+ * @param {string} [id] calendar event id
418
+ * @param {object} [query] the query parameters for specific usage
419
+ * @returns {Promise} Resolves with deleting calendar event response
420
+ * */
421
+ deleteCalendarEvent(id, query) {
422
+ return this.request({
423
+ method: 'DELETE',
424
+ service: 'calendar',
425
+ resource: `calendarEvents/${base64.encode(id)}/sync`,
426
+ qs: query || {},
427
+ });
428
+ },
429
+
430
+ /**
431
+ * @typedef QuerySchedulerDataOptions
432
+ * @param {string} [siteName] it is site full url, must have. Example: ccctest.dmz.webex.com
433
+ * @param {string} [id] it is seriesOrOccurrenceId. If present, the series/occurrence meeting ID to fetch data for.
434
+ * Example: 040000008200E00074C5B7101A82E008000000004A99F11A0841D9010000000000000000100000009EE499D4A71C1A46B51494C70EC7BFE5
435
+ * @param {string} [clientMeetingId] If present, the client meeting UUID to fetch data for.
436
+ * Example: 7f318aa9-887c-6e94-802a-8dc8e6eb1a0a
437
+ * @param {string} [scheduleTemplateId] it template id.
438
+ * @param {string} [sessionTypeId] it session type id.
439
+ * @param {string} [organizerCIUserId] required in schedule-on-behalf case. It is the organizer's CI UUID.
440
+ * @param {boolean} [usmPreference]
441
+ * @param {string} [webexMeetingId] webex side meeting UUID
442
+ * @param {string} [eventId] event ID.
443
+ * @param {string} [icalUid] icalendar UUID.
444
+ * @param {string} [thirdPartyType] third part type, such as: Microsoft
445
+ */
446
+ /**
447
+ * Get scheduler data from calendar service
448
+ * @param {QuerySchedulerDataOptions} [query] the command parameters for fetching scheduler data.
449
+ * @returns {Promise} Resolves with a decrypted scheduler data
450
+ * */
451
+ getSchedulerData(query) {
452
+ return this.request({
453
+ method: 'GET',
454
+ service: 'calendar',
455
+ resource: 'schedulerData',
456
+ qs: query || {},
457
+ }).then((response) => {
458
+ return DecryptHelper.decryptSchedulerDataResponse(this, response.body).then(() => response);
459
+ });
460
+ },
461
+
462
+ /**
463
+ * Get free busy status from calendar service
464
+ * @param {Object} [data] the command parameters for fetching free busy status.
465
+ * @param {object} [query] the query parameters for specific usage
466
+ * @returns {Promise} Resolves with a decrypted response
467
+ * */
468
+ getFreeBusy(data, query) {
469
+ return EncryptHelper.encryptFreeBusyRequest(this, data)
470
+ .then(() => {
471
+ return this.request({
472
+ method: 'POST',
473
+ service: 'calendar',
474
+ body: data,
475
+ resource: 'freebusy',
476
+ qs: query || {},
477
+ });
478
+ })
479
+ .then(() => {
480
+ return new Promise((resolve, reject) => {
481
+ this.rpcEventRequests[data.requestId] = {resolve, reject};
482
+ });
483
+ })
484
+ .catch((error) => {
485
+ throw error;
486
+ });
487
+ },
488
+ });
489
+
490
+ export default Calendar;