@webex/internal-plugin-conversation 3.0.0-beta.8 → 3.0.0-bnr.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +1 -3
  2. package/dist/activities.js +8 -69
  3. package/dist/activities.js.map +1 -1
  4. package/dist/activity-thread-ordering.js +19 -79
  5. package/dist/activity-thread-ordering.js.map +1 -1
  6. package/dist/config.js +1 -7
  7. package/dist/config.js.map +1 -1
  8. package/dist/constants.js +4 -5
  9. package/dist/constants.js.map +1 -1
  10. package/dist/conversation.js +790 -1199
  11. package/dist/conversation.js.map +1 -1
  12. package/dist/convo-error.js +0 -23
  13. package/dist/convo-error.js.map +1 -1
  14. package/dist/decryption-transforms.js +35 -98
  15. package/dist/decryption-transforms.js.map +1 -1
  16. package/dist/encryption-transforms.js +11 -48
  17. package/dist/encryption-transforms.js.map +1 -1
  18. package/dist/index.js +7 -50
  19. package/dist/index.js.map +1 -1
  20. package/dist/internal-plugin-conversation.d.ts +21 -0
  21. package/dist/share-activity.js +40 -106
  22. package/dist/share-activity.js.map +1 -1
  23. package/dist/to-array.js +9 -11
  24. package/dist/to-array.js.map +1 -1
  25. package/dist/tsdoc-metadata.json +11 -0
  26. package/dist/types/activities.d.ts +32 -0
  27. package/dist/types/activity-thread-ordering.d.ts +18 -0
  28. package/dist/types/config.d.ts +19 -0
  29. package/dist/types/constants.d.ts +5 -0
  30. package/dist/types/conversation.d.ts +2 -0
  31. package/dist/types/convo-error.d.ts +10 -0
  32. package/dist/types/decryption-transforms.d.ts +1 -0
  33. package/dist/types/encryption-transforms.d.ts +1 -0
  34. package/dist/types/index.d.ts +3 -0
  35. package/dist/types/share-activity.d.ts +7 -0
  36. package/dist/types/to-array.d.ts +9 -0
  37. package/package.json +15 -15
  38. package/src/activities.js +10 -7
  39. package/src/activity-thread-ordering.js +27 -30
  40. package/src/activity-threading.md +68 -49
  41. package/src/config.js +5 -5
  42. package/src/conversation.js +621 -589
  43. package/src/decryption-transforms.js +103 -62
  44. package/src/encryption-transforms.js +103 -83
  45. package/src/index.js +82 -66
  46. package/src/share-activity.js +64 -55
  47. package/src/to-array.js +2 -2
  48. package/test/integration/spec/create.js +184 -118
  49. package/test/integration/spec/encryption.js +250 -186
  50. package/test/integration/spec/get.js +761 -513
  51. package/test/integration/spec/mercury.js +37 -27
  52. package/test/integration/spec/share.js +292 -229
  53. package/test/integration/spec/verbs.js +628 -441
  54. package/test/unit/spec/conversation.js +265 -163
  55. package/test/unit/spec/decrypt-transforms.js +112 -131
  56. package/test/unit/spec/encryption-transforms.js +24 -18
  57. package/test/unit/spec/share-activity.js +37 -40
@@ -9,14 +9,28 @@ import hmacSHA256 from 'crypto-js/hmac-sha256';
9
9
  import hex from 'crypto-js/enc-hex';
10
10
  import {proxyEvents, tap} from '@webex/common';
11
11
  import {Page, WebexPlugin} from '@webex/webex-core';
12
- import {cloneDeep, cloneDeepWith, defaults, isArray, isObject, isString, last, map, merge, omit, pick, uniq} from 'lodash';
12
+ import {
13
+ cloneDeep,
14
+ cloneDeepWith,
15
+ defaults,
16
+ isArray,
17
+ isObject,
18
+ isString,
19
+ last,
20
+ map,
21
+ merge,
22
+ omit,
23
+ pick,
24
+ uniq,
25
+ } from 'lodash';
13
26
  import {readExifData} from '@webex/helper-image';
14
27
  import uuid from 'uuid';
15
28
 
16
29
  import {InvalidUserCreation} from './convo-error';
17
30
  import ShareActivity from './share-activity';
18
31
  import {
19
- minBatchSize, defaultMinDisplayableActivities,
32
+ minBatchSize,
33
+ defaultMinDisplayableActivities,
20
34
  getLoopCounterFailsafe,
21
35
  batchSizeIncrementCount,
22
36
  getActivityObjectsFromMap,
@@ -24,7 +38,7 @@ import {
24
38
  noMoreActivitiesManager,
25
39
  getQuery,
26
40
  rootActivityManager,
27
- activityManager
41
+ activityManager,
28
42
  } from './activity-thread-ordering';
29
43
  import {
30
44
  ACTIVITY_TYPES,
@@ -36,23 +50,25 @@ import {
36
50
  createReplyActivity,
37
51
  createEditActivity,
38
52
  createReplyEditActivity,
39
- OLDER, MID, INITIAL, NEWER,
40
- getPublishedDate, sortActivitiesByPublishedDate,
41
- sanitizeActivity
53
+ OLDER,
54
+ MID,
55
+ INITIAL,
56
+ NEWER,
57
+ getPublishedDate,
58
+ sortActivitiesByPublishedDate,
59
+ sanitizeActivity,
42
60
  } from './activities';
43
61
  import {
44
62
  DEFAULT_CLUSTER,
45
63
  DEFAULT_CLUSTER_SERVICE,
46
64
  ENCRYPTION_KEY_URL_MISMATCH,
47
65
  KEY_ALREADY_ROTATED,
48
- KEY_ROTATION_REQUIRED
66
+ KEY_ROTATION_REQUIRED,
49
67
  } from './constants';
50
68
 
51
-
52
69
  const CLUSTER_SERVICE = process.env.WEBEX_CONVERSATION_CLUSTER_SERVICE || DEFAULT_CLUSTER_SERVICE;
53
70
  const DEFAULT_CLUSTER_IDENTIFIER =
54
- process.env.WEBEX_CONVERSATION_DEFAULT_CLUSTER ||
55
- `${DEFAULT_CLUSTER}:${CLUSTER_SERVICE}`;
71
+ process.env.WEBEX_CONVERSATION_DEFAULT_CLUSTER || `${DEFAULT_CLUSTER}:${CLUSTER_SERVICE}`;
56
72
 
57
73
  const idToUrl = new Map();
58
74
 
@@ -62,7 +78,7 @@ const getConvoLimit = (options = {}) => {
62
78
  if (options.conversationsLimit) {
63
79
  limit = {
64
80
  value: options.conversationsLimit,
65
- name: 'conversationsLimit'
81
+ name: 'conversationsLimit',
66
82
  };
67
83
  }
68
84
 
@@ -79,8 +95,7 @@ const Conversation = WebexPlugin.extend({
79
95
  * @returns {String} url of the conversation
80
96
  */
81
97
  getUrlFromClusterId({cluster = 'us', id} = {}) {
82
- let clusterId =
83
- cluster === 'us' ? DEFAULT_CLUSTER_IDENTIFIER : cluster;
98
+ let clusterId = cluster === 'us' ? DEFAULT_CLUSTER_IDENTIFIER : cluster;
84
99
 
85
100
  // Determine if cluster has service name (non-US clusters from hydra do not)
86
101
  if (clusterId.split(':').length < 4) {
@@ -88,8 +103,7 @@ const Conversation = WebexPlugin.extend({
88
103
  clusterId = `${cluster}:${CLUSTER_SERVICE}`;
89
104
  }
90
105
 
91
- const {url} = this.webex.internal.services
92
- .getServiceFromClusterId({clusterId}) || {};
106
+ const {url} = this.webex.internal.services.getServiceFromClusterId({clusterId}) || {};
93
107
 
94
108
  if (!url) {
95
109
  throw Error(`Could not find service for cluster [${cluster}]`);
@@ -106,7 +120,7 @@ const Conversation = WebexPlugin.extend({
106
120
  */
107
121
  acknowledge(conversation, object, activity) {
108
122
  const url = this.getConvoUrl(conversation);
109
- const convoWithUrl = Object.assign({}, conversation, {url});
123
+ const convoWithUrl = {...conversation, url};
110
124
 
111
125
  if (!isObject(object)) {
112
126
  return Promise.reject(new Error('`object` must be an object'));
@@ -118,10 +132,9 @@ const Conversation = WebexPlugin.extend({
118
132
  object: {
119
133
  objectType: 'activity',
120
134
  id: object.id,
121
- url: object.url
122
- }
123
- })
124
- .then((a) => this.submit(a));
135
+ url: object.url,
136
+ },
137
+ }).then((a) => this.submit(a));
125
138
  },
126
139
 
127
140
  /**
@@ -135,26 +148,24 @@ const Conversation = WebexPlugin.extend({
135
148
  */
136
149
  add(conversation, participant, activity) {
137
150
  const url = this.getConvoUrl(conversation);
138
- const convoWithUrl = Object.assign({}, conversation, {url});
151
+ const convoWithUrl = {...conversation, url};
139
152
 
140
- return this.webex.internal.user.asUUID(participant, {create: true})
141
- .then((id) => this.prepare(activity, {
153
+ return this.webex.internal.user.asUUID(participant, {create: true}).then((id) =>
154
+ this.prepare(activity, {
142
155
  verb: 'add',
143
156
  target: this.prepareConversation(convoWithUrl),
144
157
  object: {
145
158
  id,
146
- objectType: 'person'
159
+ objectType: 'person',
147
160
  },
148
161
  kmsMessage: {
149
162
  method: 'create',
150
163
  uri: '/authorizations',
151
164
  resourceUri: '<KRO>',
152
- userIds: [
153
- id
154
- ]
155
- }
156
- })
157
- .then((a) => this.submit(a)));
165
+ userIds: [id],
166
+ },
167
+ }).then((a) => this.submit(a))
168
+ );
158
169
  },
159
170
 
160
171
  /**
@@ -181,11 +192,16 @@ const Conversation = WebexPlugin.extend({
181
192
  return Promise.reject(new Error('`params.participants` is required'));
182
193
  }
183
194
 
184
- return Promise.all(params.participants.map((participant) => this.webex.internal.user.asUUID(participant, {create: true})
185
- // eslint-disable-next-line arrow-body-style
186
- .catch((err) => {
187
- return options.allowPartialCreation ? undefined : Promise.reject(err);
188
- })))
195
+ return Promise.all(
196
+ params.participants.map((participant) =>
197
+ this.webex.internal.user
198
+ .asUUID(participant, {create: true})
199
+ // eslint-disable-next-line arrow-body-style
200
+ .catch((err) => {
201
+ return options.allowPartialCreation ? undefined : Promise.reject(err);
202
+ })
203
+ )
204
+ )
189
205
  .then((participants) => {
190
206
  participants.unshift(this.webex.internal.device.userId);
191
207
  participants = uniq(participants);
@@ -216,12 +232,11 @@ const Conversation = WebexPlugin.extend({
216
232
  return c;
217
233
  }
218
234
 
219
- return this.webex.internal.conversation.share(c, params.files)
220
- .then((a) => {
221
- c.activities.items.push(a);
235
+ return this.webex.internal.conversation.share(c, params.files).then((a) => {
236
+ c.activities.items.push(a);
222
237
 
223
- return c;
224
- });
238
+ return c;
239
+ });
225
240
  });
226
241
  },
227
242
 
@@ -236,7 +251,8 @@ const Conversation = WebexPlugin.extend({
236
251
  // not using webex.internal.encryption.getKey() because the JWK it returns does not have a 'k'
237
252
  // property. we need jwk.k to correctly generate the HMAC
238
253
 
239
- return this.webex.internal.encryption.unboundedStorage.get(parent.encryptionKeyUrl)
254
+ return this.webex.internal.encryption.unboundedStorage
255
+ .get(parent.encryptionKeyUrl)
240
256
  .then((keyString) => {
241
257
  const key = JSON.parse(keyString);
242
258
  // when we stringify this object, keys must be in this order to generate same HMAC as
@@ -278,7 +294,7 @@ const Conversation = WebexPlugin.extend({
278
294
  */
279
295
  sendReaction(conversation, reactionPayload) {
280
296
  const url = this.getConvoUrl(conversation);
281
- const convoWithUrl = Object.assign({}, conversation, {url});
297
+ const convoWithUrl = {...conversation, url};
282
298
 
283
299
  if (!isObject(reactionPayload)) {
284
300
  return Promise.reject(new Error('`object` must be an object'));
@@ -286,32 +302,37 @@ const Conversation = WebexPlugin.extend({
286
302
 
287
303
  return this.prepare(reactionPayload, {
288
304
  target: this.prepareConversation(convoWithUrl),
289
- object: pick(reactionPayload, 'id', 'url', 'objectType')
290
- })
291
- .then((act) => this.submit(act));
305
+ object: pick(reactionPayload, 'id', 'url', 'objectType'),
306
+ }).then((act) => this.submit(act));
292
307
  },
293
308
 
294
309
  /**
295
310
  * delete a reaction
296
311
  * @param {Object} conversation
297
- * @param {Object} reactionId
312
+ * @param {Object} reactionId,
313
+ * @param {String} recipientId,
298
314
  * @returns {Promise<Activity>}
299
315
  */
300
- deleteReaction(conversation, reactionId) {
316
+ deleteReaction(conversation, reactionId, recipientId) {
301
317
  const deleteReactionPayload = {
302
318
  actor: {objectType: 'person', id: this.webex.internal.device.userId},
303
319
  object: {
304
320
  id: reactionId,
305
- objectType: 'activity'
321
+ objectType: 'activity',
306
322
  },
307
323
  objectType: 'activity',
308
324
  target: {
309
325
  id: conversation.id,
310
- objectType: 'conversation'
326
+ objectType: 'conversation',
311
327
  },
312
- verb: 'delete'
328
+ verb: 'delete',
313
329
  };
314
330
 
331
+ // Is not required for the request to be accepted, but follows specification.
332
+ if (recipientId) {
333
+ deleteReactionPayload.recipients = {items: [{id: recipientId, objectType: 'person'}]};
334
+ }
335
+
315
336
  return this.sendReaction(conversation, deleteReactionPayload);
316
337
  },
317
338
 
@@ -320,34 +341,38 @@ const Conversation = WebexPlugin.extend({
320
341
  * @param {Object} conversation
321
342
  * @param {Object} displayName must be 'celebrate', 'heart', 'thumbsup', 'smiley', 'haha', 'confused', 'sad'
322
343
  * @param {Object} activity activity object from convo we are reacting to
344
+ * @param {String} recipientId,
323
345
  * @returns {Promise<Activity>}
324
346
  */
325
- addReaction(conversation, displayName, activity) {
347
+ addReaction(conversation, displayName, activity, recipientId) {
326
348
  return this.createReactionHmac(displayName, activity).then((hmac) => {
327
349
  const addReactionPayload = {
328
350
  actor: {objectType: 'person', id: this.webex.internal.device.userId},
329
351
  target: {
330
352
  id: conversation.id,
331
- objectType: 'conversation'
353
+ objectType: 'conversation',
332
354
  },
333
355
  verb: 'add',
334
356
  objectType: 'activity',
335
357
  parent: {
336
358
  type: 'reaction',
337
- id: activity.id
359
+ id: activity.id,
338
360
  },
339
361
  object: {
340
362
  objectType: 'reaction2',
341
363
  displayName,
342
- hmac
343
- }
364
+ hmac,
365
+ },
344
366
  };
345
367
 
368
+ if (recipientId) {
369
+ addReactionPayload.recipients = {items: [{id: recipientId, objectType: 'person'}]};
370
+ }
371
+
346
372
  return this.sendReaction(conversation, addReactionPayload);
347
373
  });
348
374
  },
349
375
 
350
-
351
376
  /**
352
377
  * delete content
353
378
  * @param {Object} conversation
@@ -357,7 +382,7 @@ const Conversation = WebexPlugin.extend({
357
382
  */
358
383
  delete(conversation, object, activity) {
359
384
  const url = this.getConvoUrl(conversation);
360
- const convoWithUrl = Object.assign({}, conversation, {url});
385
+ const convoWithUrl = {...conversation, url};
361
386
 
362
387
  if (!isObject(object)) {
363
388
  return Promise.reject(new Error('`object` must be an object'));
@@ -375,12 +400,13 @@ const Conversation = WebexPlugin.extend({
375
400
  request.target.kmsResourceObjectUrl = object.object.kmsResourceObjectUrl;
376
401
  request.kmsMessage = {
377
402
  method: 'delete',
378
- uri: `<KRO>/authorizations?${querystring.stringify({authId: convoWithUrl.kmsResourceObjectUrl})}`
403
+ uri: `<KRO>/authorizations?${querystring.stringify({
404
+ authId: convoWithUrl.kmsResourceObjectUrl,
405
+ })}`,
379
406
  };
380
407
  }
381
408
 
382
- return this.prepare(activity, request)
383
- .then((a) => this.submit(a));
409
+ return this.prepare(activity, request).then((a) => this.submit(a));
384
410
  },
385
411
 
386
412
  /**
@@ -400,11 +426,9 @@ const Conversation = WebexPlugin.extend({
400
426
 
401
427
  if (isEncrypted) {
402
428
  promise = this.webex.internal.encryption.download(item.scr, item.options);
403
- }
404
- else if (item.scr && item.scr.loc) {
429
+ } else if (item.scr && item.scr.loc) {
405
430
  promise = this._downloadUnencryptedFile(item.scr.loc, options);
406
- }
407
- else {
431
+ } else {
408
432
  promise = this._downloadUnencryptedFile(item.url, options);
409
433
  }
410
434
 
@@ -446,11 +470,10 @@ const Conversation = WebexPlugin.extend({
446
470
  _downloadUnencryptedFile(uri, options = {}) {
447
471
  Object.assign(options, {
448
472
  uri,
449
- responseType: 'buffer'
473
+ responseType: 'buffer',
450
474
  });
451
475
 
452
- const promise = this.request(options)
453
- .then((res) => res.body);
476
+ const promise = this.request(options).then((res) => res.body);
454
477
 
455
478
  proxyEvents(options.download, promise);
456
479
 
@@ -469,7 +492,7 @@ const Conversation = WebexPlugin.extend({
469
492
  const activity = {
470
493
  actor,
471
494
  objectType: 'activity',
472
- verb
495
+ verb,
473
496
  };
474
497
 
475
498
  if (!actor) {
@@ -479,7 +502,7 @@ const Conversation = WebexPlugin.extend({
479
502
  if (isString(actor)) {
480
503
  activity.actor = {
481
504
  objectType: 'person',
482
- id: actor
505
+ id: actor,
483
506
  };
484
507
  }
485
508
 
@@ -495,20 +518,20 @@ const Conversation = WebexPlugin.extend({
495
518
  },
496
519
 
497
520
  /**
498
- * Gets an array of activities with an array of activity URLS
499
- * @param {Array} activityUrls
500
- * @param {Object} options
501
- * @param {String} options.cluster cluster where the activities are located
502
- * @param {String} options.url base convo url where the activities are located
503
- * @returns {Promise<Object>} Resolves with the activities
504
- */
521
+ * Gets an array of activities with an array of activity URLS
522
+ * @param {Array} activityUrls
523
+ * @param {Object} options
524
+ * @param {String} options.cluster cluster where the activities are located
525
+ * @param {String} options.url base convo url where the activities are located
526
+ * @returns {Promise<Object>} Resolves with the activities
527
+ */
505
528
  bulkActivitiesFetch(activityUrls, options = {}) {
506
- let cluster, url;
529
+ let cluster;
530
+ let url;
507
531
 
508
532
  if (typeof options === 'string') {
509
533
  cluster = options;
510
- }
511
- else {
534
+ } else {
512
535
  ({cluster, url} = options);
513
536
  }
514
537
 
@@ -516,45 +539,42 @@ const Conversation = WebexPlugin.extend({
516
539
  const params = {
517
540
  method: 'POST',
518
541
  body: {
519
- activityUrls
520
- }
542
+ activityUrls,
543
+ },
521
544
  };
522
545
 
523
546
  if (url) {
524
547
  const uri = `${url}/${resource}`;
525
548
 
526
549
  Object.assign(params, {
527
- uri
550
+ uri,
528
551
  });
529
- }
530
- else if (cluster) {
552
+ } else if (cluster) {
531
553
  const uri = `${this.getUrlFromClusterId({cluster})}/${resource}`;
532
554
 
533
555
  Object.assign(params, {
534
- uri
556
+ uri,
535
557
  });
536
- }
537
- else {
558
+ } else {
538
559
  Object.assign(params, {
539
560
  api: 'conversation',
540
- resource
561
+ resource,
541
562
  });
542
563
  }
543
564
 
544
- return this.webex.request(params)
545
- .then((res) => {
546
- const activitiesArr = [];
565
+ return this.webex.request(params).then((res) => {
566
+ const activitiesArr = [];
547
567
 
548
- if (res.body.multistatus) {
549
- res.body.multistatus.forEach((statusData) => {
550
- if (statusData.status === '200' && statusData.data && statusData.data.activity) {
551
- activitiesArr.push(statusData.data.activity);
552
- }
553
- });
554
- }
568
+ if (res.body.multistatus) {
569
+ res.body.multistatus.forEach((statusData) => {
570
+ if (statusData.status === '200' && statusData.data && statusData.data.activity) {
571
+ activitiesArr.push(statusData.data.activity);
572
+ }
573
+ });
574
+ }
555
575
 
556
- return activitiesArr;
557
- });
576
+ return activitiesArr;
577
+ });
558
578
  },
559
579
 
560
580
  /**
@@ -572,27 +592,27 @@ const Conversation = WebexPlugin.extend({
572
592
 
573
593
  try {
574
594
  uri = !user ? this.getConvoUrl(conversation) : '';
575
- }
576
- catch (err) {
595
+ } catch (err) {
577
596
  return Promise.reject(Error(err));
578
597
  }
579
598
 
580
599
  const params = {
581
- qs: Object.assign({
600
+ qs: {
582
601
  uuidEntryFormat: true,
583
602
  personRefresh: true,
584
603
  activitiesLimit: 0,
585
604
  includeConvWithDeletedUserUUID: false,
586
- includeParticipants: false
587
- }, omit(options, 'id', 'user', 'url')),
588
- disableTransform: options.disableTransform
605
+ includeParticipants: false,
606
+ ...omit(options, 'id', 'user', 'url'),
607
+ },
608
+ disableTransform: options.disableTransform,
589
609
  };
590
610
 
591
611
  // Default behavior is to set includeParticipants=false,
592
612
  // which makes the payload lighter by removing participant info.
593
613
  // If the caller explicitly sets the participantAckFilter or
594
614
  // participantsLimit, we don't want that default setting.
595
- if (('participantAckFilter' in options) || ('participantsLimit' in options)) {
615
+ if ('participantAckFilter' in options || 'participantsLimit' in options) {
596
616
  delete params.qs.includeParticipants;
597
617
  }
598
618
 
@@ -601,21 +621,22 @@ const Conversation = WebexPlugin.extend({
601
621
  if (userId) {
602
622
  Object.assign(params, {
603
623
  service: 'conversation',
604
- resource: `conversations/user/${userId}`
624
+ resource: `conversations/user/${userId}`,
605
625
  });
606
- }
607
- else {
626
+ } else {
608
627
  params.uri = uri;
609
628
  }
610
629
 
611
630
  return this.request(params);
612
631
  })
613
- .then(tap(({body}) => {
614
- const {id, url} = body;
615
-
616
- this._recordUUIDs(body);
617
- idToUrl.set(id, url);
618
- }))
632
+ .then(
633
+ tap(({body}) => {
634
+ const {id, url} = body;
635
+
636
+ this._recordUUIDs(body);
637
+ idToUrl.set(id, url);
638
+ })
639
+ )
619
640
  .then((res) => res.body);
620
641
  },
621
642
 
@@ -631,10 +652,7 @@ const Conversation = WebexPlugin.extend({
631
652
  * @returns {Promise<Activity>}
632
653
  */
633
654
  leave(conversation, participant, activity) {
634
- const convoWithUrl =
635
- Object.assign(
636
- {}, conversation, {url: this.getConvoUrl(conversation)}
637
- );
655
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
638
656
 
639
657
  return Promise.resolve()
640
658
  .then(() => {
@@ -642,19 +660,20 @@ const Conversation = WebexPlugin.extend({
642
660
  participant = this.webex.internal.device.userId;
643
661
  }
644
662
 
645
- return this.webex.internal.user.asUUID(participant)
646
- .then((id) => this.prepare(activity, {
663
+ return this.webex.internal.user.asUUID(participant).then((id) =>
664
+ this.prepare(activity, {
647
665
  verb: 'leave',
648
666
  target: this.prepareConversation(convoWithUrl),
649
667
  object: {
650
668
  id,
651
- objectType: 'person'
669
+ objectType: 'person',
652
670
  },
653
671
  kmsMessage: {
654
672
  method: 'delete',
655
- uri: `<KRO>/authorizations?${querystring.stringify({authId: id})}`
656
- }
657
- }));
673
+ uri: `<KRO>/authorizations?${querystring.stringify({authId: id})}`,
674
+ },
675
+ })
676
+ );
658
677
  })
659
678
  .then((a) => this.submit(a));
660
679
  },
@@ -677,15 +696,14 @@ const Conversation = WebexPlugin.extend({
677
696
  resource: options.summary ? 'conversationsSummary' : 'conversations',
678
697
  qs: omit(options, ['deferDecrypt', 'summary']),
679
698
  deferDecrypt: options.deferDecrypt,
680
- limit: getConvoLimit(options)
681
- })
682
- .then((results) => {
683
- for (const convo of results) {
684
- idToUrl.set(convo.id, convo.url);
685
- }
699
+ limit: getConvoLimit(options),
700
+ }).then((results) => {
701
+ for (const convo of results) {
702
+ idToUrl.set(convo.id, convo.url);
703
+ }
686
704
 
687
- return results;
688
- });
705
+ return results;
706
+ });
689
707
  },
690
708
 
691
709
  /**
@@ -709,42 +727,40 @@ const Conversation = WebexPlugin.extend({
709
727
 
710
728
  // Go get the next page of results
711
729
  return this.request({
712
- url: options.page.links.next
730
+ url: options.page.links.next,
713
731
  }).then((res) => ({page: new Page(res, this.webex)}));
714
732
  }
715
733
 
716
734
  // No page - so this is the first request to kick off the pagination process
717
- const queryOptions = Object.assign({
735
+ const queryOptions = {
718
736
  personRefresh: true,
719
737
  uuidEntryFormat: true,
720
738
  activitiesLimit: 0,
721
739
  participantsLimit: 0,
722
- paginate: true
723
- }, omit(options, ['deferDecrypt', 'url']));
740
+ paginate: true,
741
+ ...omit(options, ['deferDecrypt', 'url']),
742
+ };
724
743
 
725
744
  const reqOptions = {
726
745
  qs: queryOptions,
727
746
  deferDecrypt: options.deferDecrypt,
728
- limit: getConvoLimit(options)
747
+ limit: getConvoLimit(options),
729
748
  };
730
749
 
731
750
  // if options.url is present we likely received one or more additional urls due to federation. In this case
732
751
  // we need to initialize pagination against that url instead of the default home cluster
733
752
  if (options.url) {
734
753
  reqOptions.uri = `${options.url}/conversations`;
735
- }
736
- else {
754
+ } else {
737
755
  reqOptions.service = 'conversation';
738
756
  reqOptions.resource = 'conversations';
739
757
  }
740
758
 
741
-
742
759
  return this.request(reqOptions).then((res) => {
743
760
  const response = {
744
- page: new Page(res, this.webex)
761
+ page: new Page(res, this.webex),
745
762
  };
746
763
 
747
-
748
764
  if (res.body && res.body.additionalUrls) {
749
765
  response.additionalUrls = res.body.additionalUrls;
750
766
  }
@@ -764,15 +780,14 @@ const Conversation = WebexPlugin.extend({
764
780
  service: 'conversation',
765
781
  resource: 'conversations/left',
766
782
  qs: options,
767
- limit: getConvoLimit(options)
768
- })
769
- .then((results) => {
770
- for (const convo of results) {
771
- idToUrl.set(convo.id, convo.url);
772
- }
783
+ limit: getConvoLimit(options),
784
+ }).then((results) => {
785
+ for (const convo of results) {
786
+ idToUrl.set(convo.id, convo.url);
787
+ }
773
788
 
774
- return results;
775
- });
789
+ return results;
790
+ });
776
791
  },
777
792
 
778
793
  /**
@@ -807,7 +822,7 @@ const Conversation = WebexPlugin.extend({
807
822
  const params = {
808
823
  method: 'GET',
809
824
  url: `${conversationUrl}/parents`,
810
- qs: query
825
+ qs: query,
811
826
  };
812
827
 
813
828
  const response = await this.request(params);
@@ -827,7 +842,12 @@ const Conversation = WebexPlugin.extend({
827
842
  const {conversationUrl, activityParentId, query} = options;
828
843
  const {activityType} = query;
829
844
 
830
- const initialResponse = await this.listChildActivitiesByParentId(conversationUrl, activityParentId, activityType, query);
845
+ const initialResponse = await this.listChildActivitiesByParentId(
846
+ conversationUrl,
847
+ activityParentId,
848
+ activityType,
849
+ query
850
+ );
831
851
 
832
852
  let page = new Page(initialResponse, this.webex);
833
853
 
@@ -861,12 +881,12 @@ const Conversation = WebexPlugin.extend({
861
881
  async listChildActivitiesByParentId(conversationUrl, activityParentId, activityType, query = {}) {
862
882
  const finalQuery = {
863
883
  ...query,
864
- activityType
884
+ activityType,
865
885
  };
866
886
  const params = {
867
887
  method: 'GET',
868
888
  url: `${conversationUrl}/parents/${activityParentId}`,
869
- qs: finalQuery
889
+ qs: finalQuery,
870
890
  };
871
891
 
872
892
  return this.request(params);
@@ -883,10 +903,14 @@ const Conversation = WebexPlugin.extend({
883
903
  const {body} = await this.request({
884
904
  method: 'GET',
885
905
  url: `${conversationUrl}/activities/${activityParentId}`,
886
- qs: query
906
+ qs: query,
887
907
  });
888
908
 
889
- const reactionObjects = body.children ? body.children.filter((child) => child.type === 'reactionSelfSummary' || child.type === 'reactionSummary') : [];
909
+ const reactionObjects = body.children
910
+ ? body.children.filter(
911
+ (child) => child.type === 'reactionSelfSummary' || child.type === 'reactionSummary'
912
+ )
913
+ : [];
890
914
 
891
915
  return reactionObjects;
892
916
  },
@@ -900,7 +924,7 @@ const Conversation = WebexPlugin.extend({
900
924
  return this._list({
901
925
  service: 'conversation',
902
926
  resource: 'mentions',
903
- qs: omit(options, 'mentions')
927
+ qs: omit(options, 'mentions'),
904
928
  });
905
929
  },
906
930
 
@@ -911,9 +935,13 @@ const Conversation = WebexPlugin.extend({
911
935
  * @returns {Promise} Resolves with the created activity
912
936
  */
913
937
  muteMentions(conversation, activity) {
914
- return this.tag(conversation, {
915
- tags: ['MENTION_NOTIFICATIONS_OFF']
916
- }, activity);
938
+ return this.tag(
939
+ conversation,
940
+ {
941
+ tags: ['MENTION_NOTIFICATIONS_OFF'],
942
+ },
943
+ activity
944
+ );
917
945
  },
918
946
 
919
947
  /**
@@ -923,9 +951,13 @@ const Conversation = WebexPlugin.extend({
923
951
  * @returns {Promise} Resolves with the created activity
924
952
  */
925
953
  muteMessages(conversation, activity) {
926
- return this.tag(conversation, {
927
- tags: ['MESSAGE_NOTIFICATIONS_OFF']
928
- }, activity);
954
+ return this.tag(
955
+ conversation,
956
+ {
957
+ tags: ['MESSAGE_NOTIFICATIONS_OFF'],
958
+ },
959
+ activity
960
+ );
929
961
  },
930
962
 
931
963
  /**
@@ -935,9 +967,13 @@ const Conversation = WebexPlugin.extend({
935
967
  * @returns {Promise} Resolves with the created activity
936
968
  */
937
969
  ignore(conversation, activity) {
938
- return this.tag(conversation, {
939
- tags: ['IGNORED']
940
- }, activity);
970
+ return this.tag(
971
+ conversation,
972
+ {
973
+ tags: ['IGNORED'],
974
+ },
975
+ activity
976
+ );
941
977
  },
942
978
 
943
979
  /**
@@ -948,22 +984,18 @@ const Conversation = WebexPlugin.extend({
948
984
  * @returns {Promise}
949
985
  */
950
986
  cardAction(conversation, inputs, parentActivity, activity = {}) {
951
- const convoWithUrl =
952
- Object.assign(
953
- {}, conversation, {url: this.getConvoUrl(conversation)}
954
- );
987
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
955
988
 
956
989
  activity.parent = {
957
990
  id: parentActivity.id,
958
- type: 'cardAction'
991
+ type: 'cardAction',
959
992
  };
960
993
 
961
994
  return this.prepare(activity, {
962
995
  verb: 'cardAction',
963
996
  target: this.prepareConversation(convoWithUrl),
964
- object: Object.assign({objectType: 'submit'}, inputs)
965
- })
966
- .then((a) => this.submit(a));
997
+ object: {objectType: 'submit', ...inputs},
998
+ }).then((a) => this.submit(a));
967
999
  },
968
1000
 
969
1001
  /**
@@ -977,105 +1009,126 @@ const Conversation = WebexPlugin.extend({
977
1009
  * @returns {Promise<Activity>}
978
1010
  */
979
1011
  post(conversation, message, activity) {
980
- const convoWithUrl =
981
- Object.assign(
982
- {}, conversation, {url: this.getConvoUrl(conversation)}
983
- );
1012
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
984
1013
 
985
1014
  if (isString(message)) {
986
1015
  message = {
987
- displayName: message
1016
+ displayName: message,
988
1017
  };
989
1018
  }
990
1019
 
991
1020
  return this.prepare(activity, {
992
1021
  verb: 'post',
993
1022
  target: this.prepareConversation(convoWithUrl),
994
- object: Object.assign({objectType: 'comment'}, message)
995
- })
996
- .then((a) => this.submit(a));
1023
+ object: {objectType: 'comment', ...message},
1024
+ }).then((a) => this.submit(a));
997
1025
  },
998
1026
 
999
1027
  prepareConversation(conversation) {
1000
- return defaults(pick(conversation, 'id', 'url', 'objectType', 'defaultActivityEncryptionKeyUrl', 'kmsResourceObjectUrl'), {
1001
- objectType: 'conversation'
1002
- });
1028
+ return defaults(
1029
+ pick(
1030
+ conversation,
1031
+ 'id',
1032
+ 'url',
1033
+ 'objectType',
1034
+ 'defaultActivityEncryptionKeyUrl',
1035
+ 'kmsResourceObjectUrl'
1036
+ ),
1037
+ {
1038
+ objectType: 'conversation',
1039
+ }
1040
+ );
1003
1041
  },
1004
1042
 
1005
1043
  prepare(activity, params) {
1006
1044
  params = params || {};
1007
1045
  activity = activity || {};
1008
1046
 
1009
- return Promise.resolve(activity.prepare ? activity.prepare(params) : activity)
1010
- .then((act) => {
1011
- defaults(act, {
1012
- verb: params.verb,
1013
- kmsMessage: params.kmsMessage,
1014
- objectType: 'activity',
1015
- clientTempId: uuid.v4(),
1016
- actor: this.webex.internal.device.userId
1017
- });
1047
+ return Promise.resolve(activity.prepare ? activity.prepare(params) : activity).then((act) => {
1048
+ defaults(act, {
1049
+ verb: params.verb,
1050
+ kmsMessage: params.kmsMessage,
1051
+ objectType: 'activity',
1052
+ clientTempId: uuid.v4(),
1053
+ actor: this.webex.internal.device.userId,
1054
+ });
1018
1055
 
1019
- // Workaround because parent is a reserved props in Ampersand
1020
- if ((activity.parentActivityId && activity.activityType) || (activity.parent && activity.parent.id && activity.parent.type)) {
1021
- act.parent = {
1022
- id: activity.parentActivityId || activity.parent.id,
1023
- type: activity.activityType || activity.parent.type
1024
- };
1025
- }
1056
+ // Workaround because parent is a reserved props in Ampersand
1057
+ if (
1058
+ (activity.parentActivityId && activity.activityType) ||
1059
+ (activity.parent && activity.parent.id && activity.parent.type)
1060
+ ) {
1061
+ act.parent = {
1062
+ id: activity.parentActivityId || activity.parent.id,
1063
+ type: activity.activityType || activity.parent.type,
1064
+ };
1065
+ }
1026
1066
 
1027
- if (isString(act.actor)) {
1028
- act.actor = {
1029
- objectType: 'person',
1030
- id: act.actor
1031
- };
1032
- }
1067
+ if (activity.recipients) {
1068
+ act.recipients = activity.recipients;
1069
+ }
1033
1070
 
1034
- ['actor', 'object'].forEach((key) => {
1035
- if (params[key]) {
1036
- act[key] = act[key] || {};
1037
- defaults(act[key], params[key]);
1038
- }
1039
- });
1071
+ if (isString(act.actor)) {
1072
+ act.actor = {
1073
+ objectType: 'person',
1074
+ id: act.actor,
1075
+ };
1076
+ }
1040
1077
 
1041
- if (params.target) {
1042
- merge(act, {
1043
- target: pick(params.target, 'id', 'url', 'objectType', 'kmsResourceObjectUrl', 'defaultActivityEncryptionKeyUrl')
1044
- });
1078
+ ['actor', 'object'].forEach((key) => {
1079
+ if (params[key]) {
1080
+ act[key] = act[key] || {};
1081
+ defaults(act[key], params[key]);
1045
1082
  }
1083
+ });
1046
1084
 
1047
- ['object', 'target'].forEach((key) => {
1048
- if (act[key] && act[key].url && !act[key].id) {
1049
- act[key].id = act[key].url.split('/').pop();
1050
- }
1051
- });
1052
-
1053
- ['actor', 'object', 'target'].forEach((key) => {
1054
- if (act[key] && !act[key].objectType) {
1055
- // Reminder: throwing here because it's the only way to get out of
1056
- // this loop in event of an error.
1057
- throw new Error(`\`act.${key}.objectType\` must be defined`);
1058
- }
1085
+ if (params.target) {
1086
+ merge(act, {
1087
+ target: pick(
1088
+ params.target,
1089
+ 'id',
1090
+ 'url',
1091
+ 'objectType',
1092
+ 'kmsResourceObjectUrl',
1093
+ 'defaultActivityEncryptionKeyUrl'
1094
+ ),
1059
1095
  });
1096
+ }
1060
1097
 
1061
- if (act.object && act.object.content && !act.object.displayName) {
1062
- return Promise.reject(new Error('Cannot submit activity object with `content` but no `displayName`'));
1098
+ ['object', 'target'].forEach((key) => {
1099
+ if (act[key] && act[key].url && !act[key].id) {
1100
+ act[key].id = act[key].url.split('/').pop();
1063
1101
  }
1102
+ });
1064
1103
 
1065
- return act;
1104
+ ['actor', 'object', 'target'].forEach((key) => {
1105
+ if (act[key] && !act[key].objectType) {
1106
+ // Reminder: throwing here because it's the only way to get out of
1107
+ // this loop in event of an error.
1108
+ throw new Error(`\`act.${key}.objectType\` must be defined`);
1109
+ }
1066
1110
  });
1111
+
1112
+ if (act.object && act.object.content && !act.object.displayName) {
1113
+ return Promise.reject(
1114
+ new Error('Cannot submit activity object with `content` but no `displayName`')
1115
+ );
1116
+ }
1117
+
1118
+ return act;
1119
+ });
1067
1120
  },
1068
1121
 
1069
1122
  /**
1070
- * Get a subset of threads for a user.
1071
- * @param {Object} options
1072
- * @returns {Promise<Array<Activity>>}
1073
- */
1123
+ * Get a subset of threads for a user.
1124
+ * @param {Object} options
1125
+ * @returns {Promise<Array<Activity>>}
1126
+ */
1074
1127
  async listThreads(options) {
1075
1128
  return this._list({
1076
1129
  service: 'conversation',
1077
1130
  resource: 'threads',
1078
- qs: omit(options, 'showAllTypes')
1131
+ qs: omit(options, 'showAllTypes'),
1079
1132
  });
1080
1133
  },
1081
1134
 
@@ -1085,8 +1138,7 @@ const Conversation = WebexPlugin.extend({
1085
1138
  * @returns {Promise}
1086
1139
  */
1087
1140
  processActivityEvent(event) {
1088
- return this.webex.transform('inbound', event)
1089
- .then(() => event);
1141
+ return this.webex.transform('inbound', event).then(() => event);
1090
1142
  },
1091
1143
 
1092
1144
  /**
@@ -1095,8 +1147,7 @@ const Conversation = WebexPlugin.extend({
1095
1147
  * @returns {Promise}
1096
1148
  */
1097
1149
  processInmeetingchatEvent(event) {
1098
- return this.webex.transform('inbound', event)
1099
- .then(() => event);
1150
+ return this.webex.transform('inbound', event).then(() => event);
1100
1151
  },
1101
1152
 
1102
1153
  /**
@@ -1106,14 +1157,18 @@ const Conversation = WebexPlugin.extend({
1106
1157
  * @returns {Promise} Resolves with the created activity
1107
1158
  */
1108
1159
  removeAllMuteTags(conversation, activity) {
1109
- return this.untag(conversation, {
1110
- tags: [
1111
- 'MENTION_NOTIFICATIONS_OFF',
1112
- 'MENTION_NOTIFICATIONS_ON',
1113
- 'MESSAGE_NOTIFICATIONS_OFF',
1114
- 'MESSAGE_NOTIFICATIONS_ON'
1115
- ]
1116
- }, activity);
1160
+ return this.untag(
1161
+ conversation,
1162
+ {
1163
+ tags: [
1164
+ 'MENTION_NOTIFICATIONS_OFF',
1165
+ 'MENTION_NOTIFICATIONS_ON',
1166
+ 'MESSAGE_NOTIFICATIONS_OFF',
1167
+ 'MESSAGE_NOTIFICATIONS_ON',
1168
+ ],
1169
+ },
1170
+ activity
1171
+ );
1117
1172
  },
1118
1173
 
1119
1174
  /**
@@ -1144,10 +1199,7 @@ const Conversation = WebexPlugin.extend({
1144
1199
  return Promise.reject(new Error('Room avatars must be less than 1MB'));
1145
1200
  }
1146
1201
 
1147
- const convoWithUrl =
1148
- Object.assign(
1149
- {}, conversation, {url: this.getConvoUrl(conversation)}
1150
- );
1202
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1151
1203
 
1152
1204
  return Promise.resolve()
1153
1205
  .then(() => {
@@ -1157,7 +1209,7 @@ const Conversation = WebexPlugin.extend({
1157
1209
  activity.add(avatar, uploadOptions);
1158
1210
 
1159
1211
  return this.prepare(activity, {
1160
- target: this.prepareConversation(convoWithUrl)
1212
+ target: this.prepareConversation(convoWithUrl),
1161
1213
  });
1162
1214
  })
1163
1215
  .then((a) => {
@@ -1179,9 +1231,7 @@ const Conversation = WebexPlugin.extend({
1179
1231
  * @param {Object} conversations If this is a team, the list of conversations in the team
1180
1232
  * @returns {String} url for the specific convo
1181
1233
  */
1182
- getConvoUrl({
1183
- id, url, cluster, conversations, generalConversationUuid
1184
- }) {
1234
+ getConvoUrl({id, url, cluster, conversations, generalConversationUuid}) {
1185
1235
  if (generalConversationUuid) {
1186
1236
  // This is a Team
1187
1237
  // Because Convo doesn't have an endpoint for the team URL
@@ -1201,9 +1251,7 @@ const Conversation = WebexPlugin.extend({
1201
1251
  if (cluster) {
1202
1252
  return this.getUrlFromClusterId({cluster, id});
1203
1253
  }
1204
- this.logger.warn(
1205
- 'You should be using the `url` instead of the `id` property'
1206
- );
1254
+ this.logger.warn('You should be using the `url` instead of the `id` property');
1207
1255
  const relatedUrl = idToUrl.get(id);
1208
1256
 
1209
1257
  if (!relatedUrl) {
@@ -1228,11 +1276,8 @@ const Conversation = WebexPlugin.extend({
1228
1276
  if (!conversation.id) {
1229
1277
  if (conversation.url) {
1230
1278
  conversation.id = conversation.url.split('/').pop();
1231
- }
1232
- else {
1233
- return Promise.reject(
1234
- new Error('conversation: could not identify conversation')
1235
- );
1279
+ } else {
1280
+ return Promise.reject(new Error('conversation: could not identify conversation'));
1236
1281
  }
1237
1282
  }
1238
1283
 
@@ -1240,8 +1285,7 @@ const Conversation = WebexPlugin.extend({
1240
1285
 
1241
1286
  if (options.typing) {
1242
1287
  eventType = 'status.start_typing';
1243
- }
1244
- else {
1288
+ } else {
1245
1289
  eventType = 'status.stop_typing';
1246
1290
  }
1247
1291
 
@@ -1251,9 +1295,9 @@ const Conversation = WebexPlugin.extend({
1251
1295
  method: 'POST',
1252
1296
  body: {
1253
1297
  conversationId: conversation.id,
1254
- eventType
1298
+ eventType,
1255
1299
  },
1256
- url: `${url}/${resource}`
1300
+ url: `${url}/${resource}`,
1257
1301
  };
1258
1302
 
1259
1303
  return this.request(params);
@@ -1269,27 +1313,22 @@ const Conversation = WebexPlugin.extend({
1269
1313
  if (isArray(activity)) {
1270
1314
  activity = {
1271
1315
  object: {
1272
- files: activity
1273
- }
1316
+ files: activity,
1317
+ },
1274
1318
  };
1275
1319
  }
1276
1320
 
1277
- const convoWithUrl =
1278
- Object.assign(
1279
- {}, conversation, {url: this.getConvoUrl(conversation)}
1280
- );
1321
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1281
1322
 
1282
1323
  if (!(activity instanceof ShareActivity)) {
1283
1324
  activity = ShareActivity.create(convoWithUrl, activity, this.webex);
1284
1325
  }
1285
1326
 
1286
1327
  return this.prepare(activity, {
1287
- target: this.prepareConversation(convoWithUrl)
1288
- })
1289
- .then((a) => this.submit(a));
1328
+ target: this.prepareConversation(convoWithUrl),
1329
+ }).then((a) => this.submit(a));
1290
1330
  },
1291
1331
 
1292
-
1293
1332
  /**
1294
1333
  * Submits an activity to the conversation service
1295
1334
  * @param {Object} activity
@@ -1303,15 +1342,15 @@ const Conversation = WebexPlugin.extend({
1303
1342
  method: 'POST',
1304
1343
  body: activity,
1305
1344
  qs: {
1306
- personRefresh: true
1345
+ personRefresh: true,
1307
1346
  },
1308
- url: `${url}/${resource}`
1347
+ url: `${url}/${resource}`,
1309
1348
  };
1310
1349
 
1311
1350
  if (activity.verb === 'share') {
1312
1351
  Object.assign(params.qs, {
1313
1352
  transcode: true,
1314
- async: false
1353
+ async: false,
1315
1354
  });
1316
1355
  }
1317
1356
  /**
@@ -1323,7 +1362,12 @@ const Conversation = WebexPlugin.extend({
1323
1362
  const customActivityCopy = (value) => {
1324
1363
  const {files} = params.body.object;
1325
1364
 
1326
- if (files && value && files.items.length > 0 && value.constructor === files.items[0].scr.constructor) {
1365
+ if (
1366
+ files &&
1367
+ value &&
1368
+ files.items.length > 0 &&
1369
+ value.constructor === files.items[0].scr.constructor
1370
+ ) {
1327
1371
  const copySrc = cloneDeep(value);
1328
1372
 
1329
1373
  copySrc.toJWE = value.toJWE;
@@ -1344,22 +1388,24 @@ const Conversation = WebexPlugin.extend({
1344
1388
  if (error.body && error.body.errorCode === KEY_ROTATION_REQUIRED) {
1345
1389
  cloneActivity.body.target.defaultActivityEncryptionKeyUrl = null;
1346
1390
  this.request(cloneActivity);
1347
- }
1348
- else if (
1391
+ } else if (
1349
1392
  error.body &&
1350
- (error.body.errorCode === KEY_ALREADY_ROTATED || error.body.errorCode === ENCRYPTION_KEY_URL_MISMATCH)
1393
+ (error.body.errorCode === KEY_ALREADY_ROTATED ||
1394
+ error.body.errorCode === ENCRYPTION_KEY_URL_MISMATCH)
1351
1395
  ) {
1352
1396
  // handle when key need to update
1353
- this.webex.request({
1354
- method: 'GET',
1355
- api: 'conversation',
1356
- resource: `conversations/${params.body.target.id}`
1357
- }).then((res) => {
1358
- cloneActivity.body.target.defaultActivityEncryptionKeyUrl = res.body.defaultActivityEncryptionkeyUrl;
1359
- this.request(cloneActivity);
1360
- });
1361
- }
1362
- else {
1397
+ this.webex
1398
+ .request({
1399
+ method: 'GET',
1400
+ api: 'conversation',
1401
+ resource: `conversations/${params.body.target.id}`,
1402
+ })
1403
+ .then((res) => {
1404
+ cloneActivity.body.target.defaultActivityEncryptionKeyUrl =
1405
+ res.body.defaultActivityEncryptionkeyUrl;
1406
+ this.request(cloneActivity);
1407
+ });
1408
+ } else {
1363
1409
  throw error;
1364
1410
  }
1365
1411
  });
@@ -1371,10 +1417,7 @@ const Conversation = WebexPlugin.extend({
1371
1417
  * @returns {Promise}
1372
1418
  */
1373
1419
  unassign(conversation, activity) {
1374
- const convoWithUrl =
1375
- Object.assign(
1376
- {}, conversation, {url: this.getConvoUrl(conversation)}
1377
- );
1420
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1378
1421
 
1379
1422
  return this.prepare(activity, {
1380
1423
  verb: 'unassign',
@@ -1382,11 +1425,10 @@ const Conversation = WebexPlugin.extend({
1382
1425
  object: {
1383
1426
  objectType: 'content',
1384
1427
  files: {
1385
- items: []
1386
- }
1387
- }
1388
- })
1389
- .then((a) => this.submit(a));
1428
+ items: [],
1429
+ },
1430
+ },
1431
+ }).then((a) => this.submit(a));
1390
1432
  },
1391
1433
 
1392
1434
  /**
@@ -1396,9 +1438,13 @@ const Conversation = WebexPlugin.extend({
1396
1438
  * @returns {Promise} Resolves with the created activity
1397
1439
  */
1398
1440
  unmuteMentions(conversation, activity) {
1399
- return this.tag(conversation, {
1400
- tags: ['MENTION_NOTIFICATIONS_ON']
1401
- }, activity);
1441
+ return this.tag(
1442
+ conversation,
1443
+ {
1444
+ tags: ['MENTION_NOTIFICATIONS_ON'],
1445
+ },
1446
+ activity
1447
+ );
1402
1448
  },
1403
1449
 
1404
1450
  /**
@@ -1408,9 +1454,13 @@ const Conversation = WebexPlugin.extend({
1408
1454
  * @returns {Promise} Resolves with the created activity
1409
1455
  */
1410
1456
  unmuteMessages(conversation, activity) {
1411
- return this.tag(conversation, {
1412
- tags: ['MESSAGE_NOTIFICATIONS_ON']
1413
- }, activity);
1457
+ return this.tag(
1458
+ conversation,
1459
+ {
1460
+ tags: ['MESSAGE_NOTIFICATIONS_ON'],
1461
+ },
1462
+ activity
1463
+ );
1414
1464
  },
1415
1465
 
1416
1466
  /**
@@ -1420,9 +1470,13 @@ const Conversation = WebexPlugin.extend({
1420
1470
  * @returns {Promise} Resolves with the created activity
1421
1471
  */
1422
1472
  unignore(conversation, activity) {
1423
- return this.untag(conversation, {
1424
- tags: ['IGNORED']
1425
- }, activity);
1473
+ return this.untag(
1474
+ conversation,
1475
+ {
1476
+ tags: ['IGNORED'],
1477
+ },
1478
+ activity
1479
+ );
1426
1480
  },
1427
1481
 
1428
1482
  /**
@@ -1437,17 +1491,13 @@ const Conversation = WebexPlugin.extend({
1437
1491
  return Promise.reject(new Error('`object` must be an object'));
1438
1492
  }
1439
1493
 
1440
- const convoWithUrl =
1441
- Object.assign(
1442
- {}, conversation, {url: this.getConvoUrl(conversation)}
1443
- );
1494
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1444
1495
 
1445
1496
  return this.prepare(activity, {
1446
1497
  verb: 'update',
1447
1498
  target: this.prepareConversation(convoWithUrl),
1448
- object
1449
- })
1450
- .then((a) => this.submit(a));
1499
+ object,
1500
+ }).then((a) => this.submit(a));
1451
1501
  },
1452
1502
 
1453
1503
  /**
@@ -1460,16 +1510,12 @@ const Conversation = WebexPlugin.extend({
1460
1510
  * @returns {Promise<Activity>}
1461
1511
  */
1462
1512
  updateKey(conversation, key, activity) {
1463
- const convoWithUrl =
1464
- Object.assign(
1465
- {}, conversation, {url: this.getConvoUrl(conversation)}
1466
- );
1513
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1467
1514
 
1468
1515
  return this.get(convoWithUrl, {
1469
1516
  activitiesLimit: 0,
1470
- includeParticipants: true
1471
- })
1472
- .then((c) => this._updateKey(c, key, activity));
1517
+ includeParticipants: true,
1518
+ }).then((c) => this._updateKey(c, key, activity));
1473
1519
  },
1474
1520
 
1475
1521
  /**
@@ -1483,52 +1529,44 @@ const Conversation = WebexPlugin.extend({
1483
1529
  * @returns {Promise<Activity>}
1484
1530
  */
1485
1531
  _updateKey(conversation, key, activity) {
1486
- const convoWithUrl =
1487
- Object.assign(
1488
- {}, conversation, {url: this.getConvoUrl(conversation)}
1489
- );
1532
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1490
1533
 
1491
1534
  return Promise.resolve(
1492
1535
  key || this.webex.internal.encryption.kms.createUnboundKeys({count: 1})
1493
- )
1494
- .then((keys) => {
1495
- const k = isArray(keys) ? keys[0] : keys;
1496
- const params = {
1497
- verb: 'updateKey',
1498
- target: this.prepareConversation(convoWithUrl),
1499
- object: {
1500
- defaultActivityEncryptionKeyUrl: k.uri,
1501
- objectType: 'conversation'
1502
- }
1503
- };
1536
+ ).then((keys) => {
1537
+ const k = isArray(keys) ? keys[0] : keys;
1538
+ const params = {
1539
+ verb: 'updateKey',
1540
+ target: this.prepareConversation(convoWithUrl),
1541
+ object: {
1542
+ defaultActivityEncryptionKeyUrl: k.uri,
1543
+ objectType: 'conversation',
1544
+ },
1545
+ };
1504
1546
 
1505
- // Reminder: the kmsResourceObjectUrl is only usable if there is
1506
- // defaultActivityEncryptionKeyUrl.
1507
- // Valid defaultActivityEncryptionKeyUrl start with 'kms:'
1508
- if (
1509
- convoWithUrl.kmsResourceObjectUrl &&
1510
- convoWithUrl.kmsResourceObjectUrl.startsWith('kms:')
1511
- ) {
1512
- params.kmsMessage = {
1513
- method: 'update',
1514
- resourceUri: '<KRO>',
1515
- uri: k.uri
1516
- };
1517
- }
1518
- else {
1519
- params.kmsMessage = {
1520
- method: 'create',
1521
- uri: '/resources',
1522
- userIds: map(convoWithUrl.participants.items, 'id'),
1523
- keyUris: [
1524
- k.uri
1525
- ]
1526
- };
1527
- }
1547
+ // Reminder: the kmsResourceObjectUrl is only usable if there is
1548
+ // defaultActivityEncryptionKeyUrl.
1549
+ // Valid defaultActivityEncryptionKeyUrl start with 'kms:'
1550
+ if (
1551
+ convoWithUrl.kmsResourceObjectUrl &&
1552
+ convoWithUrl.kmsResourceObjectUrl.startsWith('kms:')
1553
+ ) {
1554
+ params.kmsMessage = {
1555
+ method: 'update',
1556
+ resourceUri: '<KRO>',
1557
+ uri: k.uri,
1558
+ };
1559
+ } else {
1560
+ params.kmsMessage = {
1561
+ method: 'create',
1562
+ uri: '/resources',
1563
+ userIds: map(convoWithUrl.participants.items, 'id'),
1564
+ keyUris: [k.uri],
1565
+ };
1566
+ }
1528
1567
 
1529
- return this.prepare(activity, params)
1530
- .then((a) => this.submit(a));
1531
- });
1568
+ return this.prepare(activity, params).then((a) => this.submit(a));
1569
+ });
1532
1570
  },
1533
1571
 
1534
1572
  /**
@@ -1544,10 +1582,9 @@ const Conversation = WebexPlugin.extend({
1544
1582
  resource: 'conversations',
1545
1583
  body: payload,
1546
1584
  qs: {
1547
- forceCreate: options.allowPartialCreation
1548
- }
1549
- })
1550
- .then((res) => res.body);
1585
+ forceCreate: options.allowPartialCreation,
1586
+ },
1587
+ }).then((res) => res.body);
1551
1588
  },
1552
1589
 
1553
1590
  /**
@@ -1592,13 +1629,11 @@ const Conversation = WebexPlugin.extend({
1592
1629
 
1593
1630
  // Wait for the postauth catalog to update and then try to retrieve the
1594
1631
  // conversation service url again.
1595
- return this.webex.internal.waitForCatalog('postauth')
1632
+ return this.webex.internal
1633
+ .waitForCatalog('postauth')
1596
1634
  .then(() => this.webex.internal.services.get('conversation'))
1597
1635
  .catch((error) => {
1598
- this.logger.warn(
1599
- 'conversation: unable to get conversation url',
1600
- error.message
1601
- );
1636
+ this.logger.warn('conversation: unable to get conversation url', error.message);
1602
1637
 
1603
1638
  return Promise.reject(error);
1604
1639
  });
@@ -1611,29 +1646,30 @@ const Conversation = WebexPlugin.extend({
1611
1646
  */
1612
1647
  _inferConversationUrl(conversation) {
1613
1648
  if (conversation.id) {
1614
- return this.webex.internal.feature.getFeature('developer', 'web-high-availability')
1649
+ return this.webex.internal.feature
1650
+ .getFeature('developer', 'web-high-availability')
1615
1651
  .then((haMessagingEnabled) => {
1616
1652
  if (haMessagingEnabled) {
1617
1653
  // recompute conversation URL each time as the host may have changed
1618
1654
  // since last usage
1619
- return this.getConversationUrl()
1620
- .then((url) => {
1621
- conversation.url = `${url}/conversations/${conversation.id}`;
1655
+ return this.getConversationUrl().then((url) => {
1656
+ conversation.url = `${url}/conversations/${conversation.id}`;
1622
1657
 
1623
- return conversation;
1624
- });
1658
+ return conversation;
1659
+ });
1625
1660
  }
1626
1661
  if (!conversation.url) {
1627
- return this.getConversationUrl()
1628
- .then((url) => {
1629
- conversation.url = `${url}/conversations/${conversation.id}`;
1630
- /* istanbul ignore else */
1631
- if (process.env.NODE_ENV !== 'production') {
1632
- this.logger.warn('conversation: inferred conversation url from conversation id; please pass whole conversation objects to Conversation methods');
1633
- }
1634
-
1635
- return conversation;
1636
- });
1662
+ return this.getConversationUrl().then((url) => {
1663
+ conversation.url = `${url}/conversations/${conversation.id}`;
1664
+ /* istanbul ignore else */
1665
+ if (process.env.NODE_ENV !== 'production') {
1666
+ this.logger.warn(
1667
+ 'conversation: inferred conversation url from conversation id; please pass whole conversation objects to Conversation methods'
1668
+ );
1669
+ }
1670
+
1671
+ return conversation;
1672
+ });
1637
1673
  }
1638
1674
 
1639
1675
  return Promise.resolve(conversation);
@@ -1657,11 +1693,10 @@ const Conversation = WebexPlugin.extend({
1657
1693
 
1658
1694
  return this._list({
1659
1695
  qs: omit(options, 'resource'),
1660
- url: `${url}/${resource}`
1696
+ url: `${url}/${resource}`,
1661
1697
  });
1662
1698
  },
1663
1699
 
1664
-
1665
1700
  /**
1666
1701
  * common interface for facade of generator functions
1667
1702
  * @typedef {object} IGeneratorResponse
@@ -1688,10 +1723,7 @@ const Conversation = WebexPlugin.extend({
1688
1723
  * jumpToActivity - gets searched-for activity and surrounding activities
1689
1724
  */
1690
1725
  listActivitiesThreadOrdered(options) {
1691
- const {
1692
- conversationUrl,
1693
- conversationId
1694
- } = options;
1726
+ const {conversationUrl, conversationId} = options;
1695
1727
 
1696
1728
  if (!conversationUrl && !conversationId) {
1697
1729
  throw new Error('must provide a conversation URL or conversation ID');
@@ -1723,7 +1755,10 @@ const Conversation = WebexPlugin.extend({
1723
1755
  }
1724
1756
 
1725
1757
  const searchOptions = {
1726
- ...baseOptions, url: newUrl, queryType: MID, search: searchObject
1758
+ ...baseOptions,
1759
+ url: newUrl,
1760
+ queryType: MID,
1761
+ search: searchObject,
1727
1762
  };
1728
1763
 
1729
1764
  threadOrderer = this._listActivitiesThreadOrdered(searchOptions);
@@ -1732,7 +1767,7 @@ const Conversation = WebexPlugin.extend({
1732
1767
 
1733
1768
  return {
1734
1769
  done: true,
1735
- value: searchResults
1770
+ value: searchResults,
1736
1771
  };
1737
1772
  };
1738
1773
 
@@ -1744,11 +1779,12 @@ const Conversation = WebexPlugin.extend({
1744
1779
  const {value = []} = await threadOrderer.next(olderOptions);
1745
1780
 
1746
1781
  const oldestInBatch = value[0] && value[0].activity;
1747
- const moreActivitiesExist = oldestInBatch && getActivityType(oldestInBatch) !== ACTIVITY_TYPES.CREATE;
1782
+ const moreActivitiesExist =
1783
+ oldestInBatch && getActivityType(oldestInBatch) !== ACTIVITY_TYPES.CREATE;
1748
1784
 
1749
1785
  return {
1750
1786
  done: !moreActivitiesExist,
1751
- value
1787
+ value,
1752
1788
  };
1753
1789
  };
1754
1790
 
@@ -1763,22 +1799,22 @@ const Conversation = WebexPlugin.extend({
1763
1799
 
1764
1800
  return {
1765
1801
  done: !value.length,
1766
- value
1802
+ value,
1767
1803
  };
1768
1804
  };
1769
1805
 
1770
1806
  return {
1771
1807
  jumpToActivity,
1772
1808
  getNewer,
1773
- getOlder
1809
+ getOlder,
1774
1810
  };
1775
1811
  },
1776
1812
 
1777
1813
  /**
1778
- * Represents reactions to messages
1779
- * @typedef {object} Reaction
1780
- * @property {object} activity reaction2summary server activity object
1781
- */
1814
+ * Represents reactions to messages
1815
+ * @typedef {object} Reaction
1816
+ * @property {object} activity reaction2summary server activity object
1817
+ */
1782
1818
 
1783
1819
  /**
1784
1820
  * Represents a root (parent, with or without children) activity, along with any replies and reactions
@@ -1804,34 +1840,30 @@ const Conversation = WebexPlugin.extend({
1804
1840
  *
1805
1841
  * @returns {void}
1806
1842
  */
1807
- async* _listActivitiesThreadOrdered(options = {}) {
1843
+ async *_listActivitiesThreadOrdered(options = {}) {
1808
1844
  // ***********************************************
1809
1845
  // INSTANCE STATE VARIABLES
1810
1846
  // variables that will be used for the life of the generator
1811
1847
  // ***********************************************
1812
1848
 
1813
- let {
1814
- minActivities = defaultMinDisplayableActivities,
1815
- queryType = INITIAL
1816
- } = options;
1849
+ let {minActivities = defaultMinDisplayableActivities, queryType = INITIAL} = options;
1817
1850
 
1818
1851
  // must fetch initially before getting newer activities!
1819
1852
  if (queryType === NEWER) {
1820
1853
  queryType = INITIAL;
1821
1854
  }
1822
1855
 
1823
- const {
1824
- url: convoUrl,
1825
- search = {},
1826
- includeChildren
1827
- } = options;
1856
+ const {url: convoUrl, search = {}, includeChildren} = options;
1828
1857
 
1829
1858
  // manage oldest, newest activities (ie bookends)
1830
1859
  const {setBookends, getNewestAct, getOldestAct} = bookendManager();
1831
1860
 
1832
1861
  // default batch should be equal to minActivities when fetching back in time, but halved when fetching newer due to subsequent child fetches filling up the minActivities count
1833
1862
  // reduces server RTs when fetching older activities
1834
- const defaultBatchSize = (queryType === INITIAL || queryType === OLDER) ? minActivities : Math.max(minBatchSize, Math.ceil(minActivities / 2));
1863
+ const defaultBatchSize =
1864
+ queryType === INITIAL || queryType === OLDER
1865
+ ? minActivities
1866
+ : Math.max(minBatchSize, Math.ceil(minActivities / 2));
1835
1867
  let batchSize = defaultBatchSize;
1836
1868
 
1837
1869
  // exposes activity states and handlers with simple getters
@@ -1853,22 +1885,19 @@ const Conversation = WebexPlugin.extend({
1853
1885
 
1854
1886
  // used to determine if we should continue to fetch older activities
1855
1887
  // must be set per iteration, as querying newer activities is still valid when all end of convo has been reached
1856
- const {
1857
- getNoMoreActs,
1858
- checkAndSetNoMoreActs,
1859
- checkAndSetNoOlderActs,
1860
- checkAndSetNoNewerActs
1861
- } = noMoreActivitiesManager();
1862
-
1863
- const getActivityHandlerByType = (type) => ({
1864
- [ACTIVITY_TYPES.ROOT]: addNewRoot,
1865
- [ACTIVITY_TYPES.REPLY]: getActivityHandlerByKey(ACTIVITY_TYPES.REPLY),
1866
- [ACTIVITY_TYPES.EDIT]: getActivityHandlerByKey(ACTIVITY_TYPES.EDIT),
1867
- [ACTIVITY_TYPES.REACTION]: getActivityHandlerByKey(ACTIVITY_TYPES.REACTION),
1868
- [ACTIVITY_TYPES.REACTION_SELF]: getActivityHandlerByKey(ACTIVITY_TYPES.REACTION_SELF),
1869
- [ACTIVITY_TYPES.TOMBSTONE]: addNewRoot,
1870
- [ACTIVITY_TYPES.CREATE]: addNewRoot
1871
- }[type]);
1888
+ const {getNoMoreActs, checkAndSetNoMoreActs, checkAndSetNoOlderActs, checkAndSetNoNewerActs} =
1889
+ noMoreActivitiesManager();
1890
+
1891
+ const getActivityHandlerByType = (type) =>
1892
+ ({
1893
+ [ACTIVITY_TYPES.ROOT]: addNewRoot,
1894
+ [ACTIVITY_TYPES.REPLY]: getActivityHandlerByKey(ACTIVITY_TYPES.REPLY),
1895
+ [ACTIVITY_TYPES.EDIT]: getActivityHandlerByKey(ACTIVITY_TYPES.EDIT),
1896
+ [ACTIVITY_TYPES.REACTION]: getActivityHandlerByKey(ACTIVITY_TYPES.REACTION),
1897
+ [ACTIVITY_TYPES.REACTION_SELF]: getActivityHandlerByKey(ACTIVITY_TYPES.REACTION_SELF),
1898
+ [ACTIVITY_TYPES.TOMBSTONE]: addNewRoot,
1899
+ [ACTIVITY_TYPES.CREATE]: addNewRoot,
1900
+ }[type]);
1872
1901
 
1873
1902
  const handleNewActivity = (activity) => {
1874
1903
  const actType = getActivityType(activity);
@@ -1906,12 +1935,13 @@ const Conversation = WebexPlugin.extend({
1906
1935
  handleNewActivities(activities);
1907
1936
  };
1908
1937
 
1909
- const getQueryResponseHandler = (type) => ({
1910
- [OLDER]: handleOlderQuery,
1911
- [NEWER]: handleNewerQuery,
1912
- [MID]: handleSearch,
1913
- [INITIAL]: handleOlderQuery
1914
- }[type]);
1938
+ const getQueryResponseHandler = (type) =>
1939
+ ({
1940
+ [OLDER]: handleOlderQuery,
1941
+ [NEWER]: handleNewerQuery,
1942
+ [MID]: handleSearch,
1943
+ [INITIAL]: handleOlderQuery,
1944
+ }[type]);
1915
1945
 
1916
1946
  // ***********************************************
1917
1947
  // INNER LOOP
@@ -1930,7 +1960,7 @@ const Conversation = WebexPlugin.extend({
1930
1960
  conversationUrl: convoUrl,
1931
1961
  limit: batchSize,
1932
1962
  includeChildren,
1933
- ...query
1963
+ ...query,
1934
1964
  };
1935
1965
 
1936
1966
  // request activities in batches
@@ -1953,10 +1983,7 @@ const Conversation = WebexPlugin.extend({
1953
1983
  }
1954
1984
 
1955
1985
  // we dont always need to fetch for parents
1956
- const [
1957
- allBatchActivities,
1958
- parents = {}
1959
- ] = await Promise.all($fetchRequests);
1986
+ const [allBatchActivities, parents = {}] = await Promise.all($fetchRequests);
1960
1987
 
1961
1988
  // use query type to decide how to handle response
1962
1989
  const handler = getQueryResponseHandler(queryType);
@@ -1968,11 +1995,7 @@ const Conversation = WebexPlugin.extend({
1968
1995
  do this by checking the hash for each of the above parent IDs
1969
1996
  fetch children when we have a parent whose ID is represented in the parent ID lists
1970
1997
  */
1971
- const {
1972
- reply: replyIds = [],
1973
- edit: editIds = [],
1974
- reaction: reactionIds = []
1975
- } = parents;
1998
+ const {reply: replyIds = [], edit: editIds = [], reaction: reactionIds = []} = parents;
1976
1999
 
1977
2000
  // if no parent IDs returned, do nothing
1978
2001
  if (replyIds.length || editIds.length || reactionIds.length) {
@@ -1985,11 +2008,16 @@ const Conversation = WebexPlugin.extend({
1985
2008
 
1986
2009
  const childFetchOptions = {
1987
2010
  conversationUrl: convoUrl,
1988
- activityParentId: actId
2011
+ activityParentId: actId,
1989
2012
  };
1990
2013
 
1991
2014
  if (reactionIds.includes(actId)) {
1992
- $reactionFetches.push(this.getReactionSummaryByParentId(convoUrl, actId, {activityType: 'reactionSummary', includeChildren: true}));
2015
+ $reactionFetches.push(
2016
+ this.getReactionSummaryByParentId(convoUrl, actId, {
2017
+ activityType: 'reactionSummary',
2018
+ includeChildren: true,
2019
+ })
2020
+ );
1993
2021
  }
1994
2022
  if (replyIds.includes(actId)) {
1995
2023
  childFetchOptions.query = {activityType: 'reply'};
@@ -2005,14 +2033,19 @@ const Conversation = WebexPlugin.extend({
2005
2033
  const [reactions, replies, edits] = await Promise.all([
2006
2034
  Promise.all($reactionFetches),
2007
2035
  Promise.all($replyFetches),
2008
- Promise.all($editFetches)
2036
+ Promise.all($editFetches),
2009
2037
  ]);
2010
2038
 
2011
2039
  // new reactions may have come in that also need their reactions fetched
2012
2040
  const newReplyReactions = await Promise.all(
2013
2041
  replies
2014
2042
  .filter((reply) => replyIds.includes(reply.id))
2015
- .map((reply) => this.getReactionSummaryByParentId(convoUrl, reply.id, {activityType: 'reactionSummary', includeChildren: true}))
2043
+ .map((reply) =>
2044
+ this.getReactionSummaryByParentId(convoUrl, reply.id, {
2045
+ activityType: 'reactionSummary',
2046
+ includeChildren: true,
2047
+ })
2048
+ )
2016
2049
  );
2017
2050
 
2018
2051
  const allReactions = [...reactions, ...newReplyReactions];
@@ -2060,13 +2093,12 @@ const Conversation = WebexPlugin.extend({
2060
2093
  // we're still building our activity list - derive new query from prior query and start loop again
2061
2094
  if (queryType === INITIAL) {
2062
2095
  query = getQuery(OLDER, {oldestPublishedDate: currentOldestPublishedDate, batchSize});
2063
- }
2064
- else {
2096
+ } else {
2065
2097
  query = getQuery(queryType, {
2066
2098
  batchSize,
2067
2099
  activityToSearch: search,
2068
2100
  oldestPublishedDate: currentOldestPublishedDate,
2069
- newestPublishedDate: currentNewestPublishedDate
2101
+ newestPublishedDate: currentNewestPublishedDate,
2070
2102
  });
2071
2103
  }
2072
2104
 
@@ -2087,7 +2119,9 @@ const Conversation = WebexPlugin.extend({
2087
2119
  return replies;
2088
2120
  }
2089
2121
 
2090
- const sortedReplies = sortActivitiesByPublishedDate(getActivityObjectsFromMap(repliesByParentId));
2122
+ const sortedReplies = sortActivitiesByPublishedDate(
2123
+ getActivityObjectsFromMap(repliesByParentId)
2124
+ );
2091
2125
 
2092
2126
  sortedReplies.forEach((replyActivity) => {
2093
2127
  const replyId = replyActivity.id;
@@ -2097,20 +2131,26 @@ const Conversation = WebexPlugin.extend({
2097
2131
 
2098
2132
  const latestActivity = edit || replyActivity;
2099
2133
  // hash of root activities (in case of plain reply) and the reply activity (in case of edit)
2100
- const allRelevantActivitiesArr = [...getActivityObjectsFromMap(getRootActivityHash()), ...getActivityObjectsFromMap(repliesByParentId)];
2134
+ const allRelevantActivitiesArr = [
2135
+ ...getActivityObjectsFromMap(getRootActivityHash()),
2136
+ ...getActivityObjectsFromMap(repliesByParentId),
2137
+ ];
2101
2138
  const allRelevantActivities = allRelevantActivitiesArr.reduce((hashMap, act) => {
2102
2139
  hashMap[act.id] = act;
2103
2140
 
2104
2141
  return hashMap;
2105
2142
  }, {});
2106
2143
 
2107
- const finalReply = this._createParsedServerActivity(latestActivity, allRelevantActivities);
2144
+ const finalReply = this._createParsedServerActivity(
2145
+ latestActivity,
2146
+ allRelevantActivities
2147
+ );
2108
2148
 
2109
2149
  const fullReply = {
2110
2150
  id: replyId,
2111
2151
  activity: finalReply,
2112
2152
  reaction,
2113
- reactionSelf
2153
+ reactionSelf,
2114
2154
  };
2115
2155
 
2116
2156
  const sanitizedFullReply = sanitizeActivity(fullReply);
@@ -2121,7 +2161,9 @@ const Conversation = WebexPlugin.extend({
2121
2161
  return replies;
2122
2162
  };
2123
2163
 
2124
- const orderedRoots = sortActivitiesByPublishedDate(getActivityObjectsFromMap(getRootActivityHash()));
2164
+ const orderedRoots = sortActivitiesByPublishedDate(
2165
+ getActivityObjectsFromMap(getRootActivityHash())
2166
+ );
2125
2167
 
2126
2168
  orderedRoots.forEach((rootActivity) => {
2127
2169
  const rootId = rootActivity.id;
@@ -2131,13 +2173,15 @@ const Conversation = WebexPlugin.extend({
2131
2173
  const reactionSelf = getActivityByTypeAndParentId(ACTIVITY_TYPES.REACTION_SELF, rootId);
2132
2174
 
2133
2175
  const latestActivity = edit || rootActivity;
2134
- const finalActivity = this._createParsedServerActivity(latestActivity, {[rootId]: rootActivity});
2176
+ const finalActivity = this._createParsedServerActivity(latestActivity, {
2177
+ [rootId]: rootActivity,
2178
+ });
2135
2179
 
2136
2180
  const fullRoot = {
2137
2181
  id: rootId,
2138
2182
  activity: finalActivity,
2139
2183
  reaction,
2140
- reactionSelf
2184
+ reactionSelf,
2141
2185
  };
2142
2186
 
2143
2187
  const sanitizedFullRoot = sanitizeActivity(fullRoot);
@@ -2159,10 +2203,9 @@ const Conversation = WebexPlugin.extend({
2159
2203
  activityToSearch: search,
2160
2204
  oldestPublishedDate: currentOldestPublishedDate,
2161
2205
  newestPublishedDate: currentNewestPublishedDate,
2162
- batchSize
2206
+ batchSize,
2163
2207
  });
2164
- }
2165
- else {
2208
+ } else {
2166
2209
  return;
2167
2210
  }
2168
2211
  }
@@ -2183,10 +2226,10 @@ const Conversation = WebexPlugin.extend({
2183
2226
  */
2184
2227
 
2185
2228
  /**
2186
- * hashmap of server activities, keyed by id
2187
- * @typedef {object} ActivityHash
2188
- * @property {Object}
2189
- */
2229
+ * hashmap of server activities, keyed by id
2230
+ * @typedef {object} ActivityHash
2231
+ * @property {Object}
2232
+ */
2190
2233
 
2191
2234
  /**
2192
2235
  * extends a given server object with fields that point to their parent activities from the hashmap passed in
@@ -2198,7 +2241,9 @@ const Conversation = WebexPlugin.extend({
2198
2241
  const isOrphan = getIsActivityOrphaned(activity, allActivitiesHash);
2199
2242
 
2200
2243
  if (isOrphan) {
2201
- throw new Error('activity has a parent that cannot be found in allActivitiesHash! please handle this as necessary');
2244
+ throw new Error(
2245
+ 'activity has a parent that cannot be found in allActivitiesHash! please handle this as necessary'
2246
+ );
2202
2247
  }
2203
2248
 
2204
2249
  const activityType = determineActivityType(activity, allActivitiesHash);
@@ -2230,12 +2275,13 @@ const Conversation = WebexPlugin.extend({
2230
2275
  * @returns {Promise<Array<Conversation>>}
2231
2276
  */
2232
2277
  async _list(options) {
2233
- options.qs = Object.assign({
2278
+ options.qs = {
2234
2279
  personRefresh: true,
2235
2280
  uuidEntryFormat: true,
2236
2281
  activitiesLimit: 0,
2237
- participantsLimit: 0
2238
- }, options.qs);
2282
+ participantsLimit: 0,
2283
+ ...options.qs,
2284
+ };
2239
2285
 
2240
2286
  const res = await this.request(options);
2241
2287
 
@@ -2243,8 +2289,7 @@ const Conversation = WebexPlugin.extend({
2243
2289
 
2244
2290
  if (!res.body || !res.body.items || res.body.items.length === 0) {
2245
2291
  list = [];
2246
- }
2247
- else {
2292
+ } else {
2248
2293
  list = res.body.items.slice(0);
2249
2294
  if (last(list).published < list[0].published) {
2250
2295
  list.reverse();
@@ -2263,9 +2308,7 @@ const Conversation = WebexPlugin.extend({
2263
2308
  // This won't get us the exact limit but it will retrieve something
2264
2309
  // from every cluster listed.
2265
2310
  if (options.limit) {
2266
- limit = Math.floor(
2267
- (options.limit.value - list.length) / res.body.additionalUrls.length
2268
- );
2311
+ limit = Math.floor((options.limit.value - list.length) / res.body.additionalUrls.length);
2269
2312
  }
2270
2313
 
2271
2314
  // If the limit is 0 for some reason,
@@ -2274,7 +2317,7 @@ const Conversation = WebexPlugin.extend({
2274
2317
  const results = await Promise.all(
2275
2318
  res.body.additionalUrls.map((host) => {
2276
2319
  const url = `${host}/${options.resource}`;
2277
- const newOptions = Object.assign({}, options, {uri: url, url});
2320
+ const newOptions = {...options, uri: url, url};
2278
2321
 
2279
2322
  if (options.limit) {
2280
2323
  newOptions.qs[newOptions.limit.name] = limit;
@@ -2309,19 +2352,23 @@ const Conversation = WebexPlugin.extend({
2309
2352
  * @returns {Promise<Conversation>}
2310
2353
  */
2311
2354
  _maybeCreateOneOnOneThenPost(params, options) {
2312
- return this.get(defaults({
2313
- // the use of uniq in Conversation#create guarantees participant[1] will
2314
- // always be the other user
2315
- user: params.participants[1]
2316
- }), Object.assign(options, {includeConvWithDeletedUserUUID: true, includeParticipants: true}))
2355
+ return this.get(
2356
+ defaults({
2357
+ // the use of uniq in Conversation#create guarantees participant[1] will
2358
+ // always be the other user
2359
+ user: params.participants[1],
2360
+ }),
2361
+ Object.assign(options, {includeConvWithDeletedUserUUID: true, includeParticipants: true})
2362
+ )
2317
2363
  .then((conversation) => {
2318
2364
  if (params.comment || params.html) {
2319
- return this.post(conversation, {content: params.html, displayName: params.comment})
2320
- .then((activity) => {
2365
+ return this.post(conversation, {content: params.html, displayName: params.comment}).then(
2366
+ (activity) => {
2321
2367
  conversation.activities.items.push(activity);
2322
2368
 
2323
2369
  return conversation;
2324
- });
2370
+ }
2371
+ );
2325
2372
  }
2326
2373
 
2327
2374
  return conversation;
@@ -2343,17 +2390,15 @@ const Conversation = WebexPlugin.extend({
2343
2390
  _prepareConversationForCreation(params) {
2344
2391
  const payload = {
2345
2392
  activities: {
2346
- items: [
2347
- this.expand('create')
2348
- ]
2393
+ items: [this.expand('create')],
2349
2394
  },
2350
2395
  objectType: 'conversation',
2351
2396
  kmsMessage: {
2352
2397
  method: 'create',
2353
2398
  uri: '/resources',
2354
2399
  userIds: cloneDeep(params.participants),
2355
- keyUris: []
2356
- }
2400
+ keyUris: [],
2401
+ },
2357
2402
  };
2358
2403
 
2359
2404
  if (params.displayName) {
@@ -2365,32 +2410,40 @@ const Conversation = WebexPlugin.extend({
2365
2410
  }
2366
2411
 
2367
2412
  params.participants.forEach((participant) => {
2368
- payload.activities.items.push(this.expand('add', {
2369
- objectType: 'person',
2370
- id: participant
2371
- }));
2413
+ payload.activities.items.push(
2414
+ this.expand('add', {
2415
+ objectType: 'person',
2416
+ id: participant,
2417
+ })
2418
+ );
2372
2419
  });
2373
2420
 
2374
2421
  if (params.comment) {
2375
- payload.activities.items.push(this.expand('post', {
2376
- objectType: 'comment',
2377
- content: params.html,
2378
- displayName: params.comment
2379
- }));
2422
+ payload.activities.items.push(
2423
+ this.expand('post', {
2424
+ objectType: 'comment',
2425
+ content: params.html,
2426
+ displayName: params.comment,
2427
+ })
2428
+ );
2380
2429
  }
2381
2430
 
2382
2431
  if (!params.isDefaultClassification && params.classificationId) {
2383
- payload.activities.items.push(this.expand('update', {
2384
- objectType: 'classification',
2385
- classificationId: params.classificationId,
2386
- effectiveDate: params.effectiveDate
2387
- }));
2432
+ payload.activities.items.push(
2433
+ this.expand('update', {
2434
+ objectType: 'classification',
2435
+ classificationId: params.classificationId,
2436
+ effectiveDate: params.effectiveDate,
2437
+ })
2438
+ );
2388
2439
  }
2389
2440
 
2390
2441
  if (params.favorite) {
2391
- payload.activities.items.push(this.expand('favorite', {
2392
- objectType: 'conversation'
2393
- }));
2442
+ payload.activities.items.push(
2443
+ this.expand('favorite', {
2444
+ objectType: 'conversation',
2445
+ })
2446
+ );
2394
2447
  }
2395
2448
 
2396
2449
  return payload;
@@ -2406,68 +2459,59 @@ const Conversation = WebexPlugin.extend({
2406
2459
  return Promise.resolve(conversation);
2407
2460
  }
2408
2461
 
2409
- return Promise.all(conversation.participants.items.map((participant) => {
2410
- // ROOMs or LYRA_SPACEs do not have email addresses, so there's no point attempting to
2411
- // record their UUIDs.
2412
- if (participant.type === 'ROOM' || participant.type === 'LYRA_SPACE') {
2413
- return Promise.resolve();
2414
- }
2462
+ return Promise.all(
2463
+ conversation.participants.items.map((participant) => {
2464
+ // ROOMs or LYRA_SPACEs do not have email addresses, so there's no point attempting to
2465
+ // record their UUIDs.
2466
+ if (participant.type === 'ROOM' || participant.type === 'LYRA_SPACE') {
2467
+ return Promise.resolve();
2468
+ }
2415
2469
 
2416
- return this.webex.internal.user.recordUUID(participant)
2417
- .catch((err) => this.logger.warn('Could not record uuid', err));
2418
- }));
2419
- }
2470
+ return this.webex.internal.user
2471
+ .recordUUID(participant)
2472
+ .catch((err) => this.logger.warn('Could not record uuid', err));
2473
+ })
2474
+ );
2475
+ },
2420
2476
  });
2421
2477
 
2422
- [
2423
- 'favorite',
2424
- 'hide',
2425
- 'lock',
2426
- 'mute',
2427
- 'unfavorite',
2428
- 'unhide',
2429
- 'unlock',
2430
- 'unmute'
2431
- ].forEach((verb) => {
2478
+ ['favorite', 'hide', 'lock', 'mute', 'unfavorite', 'unhide', 'unlock', 'unmute'].forEach((verb) => {
2432
2479
  Conversation.prototype[verb] = function submitSimpleActivity(conversation, activity) {
2433
- const convoWithUrl =
2434
- this.prepareConversation(
2435
- Object.assign(
2436
- {}, conversation, {url: this.getConvoUrl(conversation)}
2437
- )
2438
- );
2480
+ const convoWithUrl = this.prepareConversation({
2481
+ ...conversation,
2482
+ url: this.getConvoUrl(conversation),
2483
+ });
2439
2484
 
2440
2485
  return this.prepare(activity, {
2441
2486
  verb,
2442
2487
  object: convoWithUrl,
2443
- target: convoWithUrl
2444
- })
2445
- .then((a) => this.submit(a));
2488
+ target: convoWithUrl,
2489
+ }).then((a) => this.submit(a));
2446
2490
  };
2447
2491
  });
2448
2492
 
2449
- [
2450
- 'assignModerator',
2451
- 'unassignModerator'
2452
- ].forEach((verb) => {
2453
- Conversation.prototype[verb] = function submitModerationChangeActivity(conversation, moderator, activity) {
2454
- const convoWithUrl =
2455
- Object.assign(
2456
- {}, conversation, {url: this.getConvoUrl(conversation)}
2457
- );
2493
+ ['assignModerator', 'unassignModerator'].forEach((verb) => {
2494
+ Conversation.prototype[verb] = function submitModerationChangeActivity(
2495
+ conversation,
2496
+ moderator,
2497
+ activity
2498
+ ) {
2499
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
2458
2500
 
2459
2501
  return Promise.all([
2460
2502
  convoWithUrl,
2461
- moderator ? this.webex.internal.user.asUUID(moderator) : this.webex.internal.device.userId
2503
+ moderator ? this.webex.internal.user.asUUID(moderator) : this.webex.internal.device.userId,
2462
2504
  ])
2463
- .then(([c, userId]) => this.prepare(activity, {
2464
- verb,
2465
- target: this.prepareConversation(c),
2466
- object: {
2467
- id: userId,
2468
- objectType: 'person'
2469
- }
2470
- }))
2505
+ .then(([c, userId]) =>
2506
+ this.prepare(activity, {
2507
+ verb,
2508
+ target: this.prepareConversation(c),
2509
+ object: {
2510
+ id: userId,
2511
+ objectType: 'person',
2512
+ },
2513
+ })
2514
+ )
2471
2515
  .then((a) => this.submit(a));
2472
2516
  };
2473
2517
  });
@@ -2479,56 +2523,44 @@ const Conversation = WebexPlugin.extend({
2479
2523
  * @param {Activity} activity
2480
2524
  * @returns {Promise<Activity>}
2481
2525
  */
2482
- [
2483
- 'setSpaceProperty',
2484
- 'unsetSpaceProperty'
2485
- ].forEach((fnName) => {
2526
+ ['setSpaceProperty', 'unsetSpaceProperty'].forEach((fnName) => {
2486
2527
  const verb = fnName.startsWith('set') ? 'set' : 'unset';
2487
2528
 
2488
- Conversation.prototype[fnName] = function submitSpacePropertyActivity(conversation, tag, activity) {
2529
+ Conversation.prototype[fnName] = function submitSpacePropertyActivity(
2530
+ conversation,
2531
+ tag,
2532
+ activity
2533
+ ) {
2489
2534
  if (!isString(tag)) {
2490
2535
  return Promise.reject(new Error('`tag` must be a string'));
2491
2536
  }
2492
2537
 
2493
- const convoWithUrl =
2494
- Object.assign(
2495
- {}, conversation, {url: this.getConvoUrl(conversation)}
2496
- );
2538
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
2497
2539
 
2498
2540
  return this.prepare(activity, {
2499
2541
  verb,
2500
2542
  target: this.prepareConversation(convoWithUrl),
2501
2543
  object: {
2502
2544
  tags: [tag],
2503
- objectType: 'spaceProperty'
2504
- }
2505
- })
2506
- .then((a) => this.submit(a));
2545
+ objectType: 'spaceProperty',
2546
+ },
2547
+ }).then((a) => this.submit(a));
2507
2548
  };
2508
2549
  });
2509
2550
 
2510
- [
2511
- 'tag',
2512
- 'untag'
2513
- ].forEach((verb) => {
2551
+ ['tag', 'untag'].forEach((verb) => {
2514
2552
  Conversation.prototype[verb] = function submitObjectActivity(conversation, object, activity) {
2515
2553
  if (!isObject(object)) {
2516
2554
  return Promise.reject(new Error('`object` must be an object'));
2517
2555
  }
2518
2556
 
2519
- const c =
2520
- this.prepareConversation(
2521
- Object.assign(
2522
- {}, conversation, {url: this.getConvoUrl(conversation)}
2523
- )
2524
- );
2557
+ const c = this.prepareConversation({...conversation, url: this.getConvoUrl(conversation)});
2525
2558
 
2526
2559
  return this.prepare(activity, {
2527
2560
  verb,
2528
2561
  target: c,
2529
- object: Object.assign(c, object)
2530
- })
2531
- .then((a) => this.submit(a));
2562
+ object: Object.assign(c, object),
2563
+ }).then((a) => this.submit(a));
2532
2564
  };
2533
2565
  });
2534
2566