@webex/internal-plugin-conversation 2.37.0 → 2.37.2

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 (44) 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 +764 -1196
  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/share-activity.js +39 -105
  21. package/dist/share-activity.js.map +1 -1
  22. package/dist/to-array.js +9 -11
  23. package/dist/to-array.js.map +1 -1
  24. package/package.json +15 -15
  25. package/src/activities.js +10 -7
  26. package/src/activity-thread-ordering.js +27 -30
  27. package/src/activity-threading.md +68 -49
  28. package/src/config.js +5 -5
  29. package/src/conversation.js +604 -587
  30. package/src/decryption-transforms.js +103 -62
  31. package/src/encryption-transforms.js +103 -83
  32. package/src/index.js +82 -66
  33. package/src/share-activity.js +63 -54
  34. package/src/to-array.js +2 -2
  35. package/test/integration/spec/create.js +184 -118
  36. package/test/integration/spec/encryption.js +250 -186
  37. package/test/integration/spec/get.js +761 -513
  38. package/test/integration/spec/mercury.js +37 -27
  39. package/test/integration/spec/share.js +292 -229
  40. package/test/integration/spec/verbs.js +628 -441
  41. package/test/unit/spec/conversation.js +224 -163
  42. package/test/unit/spec/decrypt-transforms.js +112 -131
  43. package/test/unit/spec/encryption-transforms.js +24 -18
  44. 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,9 +302,8 @@ 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
  /**
@@ -302,14 +317,14 @@ const Conversation = WebexPlugin.extend({
302
317
  actor: {objectType: 'person', id: this.webex.internal.device.userId},
303
318
  object: {
304
319
  id: reactionId,
305
- objectType: 'activity'
320
+ objectType: 'activity',
306
321
  },
307
322
  objectType: 'activity',
308
323
  target: {
309
324
  id: conversation.id,
310
- objectType: 'conversation'
325
+ objectType: 'conversation',
311
326
  },
312
- verb: 'delete'
327
+ verb: 'delete',
313
328
  };
314
329
 
315
330
  return this.sendReaction(conversation, deleteReactionPayload);
@@ -328,26 +343,25 @@ const Conversation = WebexPlugin.extend({
328
343
  actor: {objectType: 'person', id: this.webex.internal.device.userId},
329
344
  target: {
330
345
  id: conversation.id,
331
- objectType: 'conversation'
346
+ objectType: 'conversation',
332
347
  },
333
348
  verb: 'add',
334
349
  objectType: 'activity',
335
350
  parent: {
336
351
  type: 'reaction',
337
- id: activity.id
352
+ id: activity.id,
338
353
  },
339
354
  object: {
340
355
  objectType: 'reaction2',
341
356
  displayName,
342
- hmac
343
- }
357
+ hmac,
358
+ },
344
359
  };
345
360
 
346
361
  return this.sendReaction(conversation, addReactionPayload);
347
362
  });
348
363
  },
349
364
 
350
-
351
365
  /**
352
366
  * delete content
353
367
  * @param {Object} conversation
@@ -357,7 +371,7 @@ const Conversation = WebexPlugin.extend({
357
371
  */
358
372
  delete(conversation, object, activity) {
359
373
  const url = this.getConvoUrl(conversation);
360
- const convoWithUrl = Object.assign({}, conversation, {url});
374
+ const convoWithUrl = {...conversation, url};
361
375
 
362
376
  if (!isObject(object)) {
363
377
  return Promise.reject(new Error('`object` must be an object'));
@@ -375,12 +389,13 @@ const Conversation = WebexPlugin.extend({
375
389
  request.target.kmsResourceObjectUrl = object.object.kmsResourceObjectUrl;
376
390
  request.kmsMessage = {
377
391
  method: 'delete',
378
- uri: `<KRO>/authorizations?${querystring.stringify({authId: convoWithUrl.kmsResourceObjectUrl})}`
392
+ uri: `<KRO>/authorizations?${querystring.stringify({
393
+ authId: convoWithUrl.kmsResourceObjectUrl,
394
+ })}`,
379
395
  };
380
396
  }
381
397
 
382
- return this.prepare(activity, request)
383
- .then((a) => this.submit(a));
398
+ return this.prepare(activity, request).then((a) => this.submit(a));
384
399
  },
385
400
 
386
401
  /**
@@ -400,11 +415,9 @@ const Conversation = WebexPlugin.extend({
400
415
 
401
416
  if (isEncrypted) {
402
417
  promise = this.webex.internal.encryption.download(item.scr, item.options);
403
- }
404
- else if (item.scr && item.scr.loc) {
418
+ } else if (item.scr && item.scr.loc) {
405
419
  promise = this._downloadUnencryptedFile(item.scr.loc, options);
406
- }
407
- else {
420
+ } else {
408
421
  promise = this._downloadUnencryptedFile(item.url, options);
409
422
  }
410
423
 
@@ -446,11 +459,10 @@ const Conversation = WebexPlugin.extend({
446
459
  _downloadUnencryptedFile(uri, options = {}) {
447
460
  Object.assign(options, {
448
461
  uri,
449
- responseType: 'buffer'
462
+ responseType: 'buffer',
450
463
  });
451
464
 
452
- const promise = this.request(options)
453
- .then((res) => res.body);
465
+ const promise = this.request(options).then((res) => res.body);
454
466
 
455
467
  proxyEvents(options.download, promise);
456
468
 
@@ -469,7 +481,7 @@ const Conversation = WebexPlugin.extend({
469
481
  const activity = {
470
482
  actor,
471
483
  objectType: 'activity',
472
- verb
484
+ verb,
473
485
  };
474
486
 
475
487
  if (!actor) {
@@ -479,7 +491,7 @@ const Conversation = WebexPlugin.extend({
479
491
  if (isString(actor)) {
480
492
  activity.actor = {
481
493
  objectType: 'person',
482
- id: actor
494
+ id: actor,
483
495
  };
484
496
  }
485
497
 
@@ -495,20 +507,20 @@ const Conversation = WebexPlugin.extend({
495
507
  },
496
508
 
497
509
  /**
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
- */
510
+ * Gets an array of activities with an array of activity URLS
511
+ * @param {Array} activityUrls
512
+ * @param {Object} options
513
+ * @param {String} options.cluster cluster where the activities are located
514
+ * @param {String} options.url base convo url where the activities are located
515
+ * @returns {Promise<Object>} Resolves with the activities
516
+ */
505
517
  bulkActivitiesFetch(activityUrls, options = {}) {
506
- let cluster, url;
518
+ let cluster;
519
+ let url;
507
520
 
508
521
  if (typeof options === 'string') {
509
522
  cluster = options;
510
- }
511
- else {
523
+ } else {
512
524
  ({cluster, url} = options);
513
525
  }
514
526
 
@@ -516,45 +528,42 @@ const Conversation = WebexPlugin.extend({
516
528
  const params = {
517
529
  method: 'POST',
518
530
  body: {
519
- activityUrls
520
- }
531
+ activityUrls,
532
+ },
521
533
  };
522
534
 
523
535
  if (url) {
524
536
  const uri = `${url}/${resource}`;
525
537
 
526
538
  Object.assign(params, {
527
- uri
539
+ uri,
528
540
  });
529
- }
530
- else if (cluster) {
541
+ } else if (cluster) {
531
542
  const uri = `${this.getUrlFromClusterId({cluster})}/${resource}`;
532
543
 
533
544
  Object.assign(params, {
534
- uri
545
+ uri,
535
546
  });
536
- }
537
- else {
547
+ } else {
538
548
  Object.assign(params, {
539
549
  api: 'conversation',
540
- resource
550
+ resource,
541
551
  });
542
552
  }
543
553
 
544
- return this.webex.request(params)
545
- .then((res) => {
546
- const activitiesArr = [];
554
+ return this.webex.request(params).then((res) => {
555
+ const activitiesArr = [];
547
556
 
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
- }
557
+ if (res.body.multistatus) {
558
+ res.body.multistatus.forEach((statusData) => {
559
+ if (statusData.status === '200' && statusData.data && statusData.data.activity) {
560
+ activitiesArr.push(statusData.data.activity);
561
+ }
562
+ });
563
+ }
555
564
 
556
- return activitiesArr;
557
- });
565
+ return activitiesArr;
566
+ });
558
567
  },
559
568
 
560
569
  /**
@@ -572,27 +581,27 @@ const Conversation = WebexPlugin.extend({
572
581
 
573
582
  try {
574
583
  uri = !user ? this.getConvoUrl(conversation) : '';
575
- }
576
- catch (err) {
584
+ } catch (err) {
577
585
  return Promise.reject(Error(err));
578
586
  }
579
587
 
580
588
  const params = {
581
- qs: Object.assign({
589
+ qs: {
582
590
  uuidEntryFormat: true,
583
591
  personRefresh: true,
584
592
  activitiesLimit: 0,
585
593
  includeConvWithDeletedUserUUID: false,
586
- includeParticipants: false
587
- }, omit(options, 'id', 'user', 'url')),
588
- disableTransform: options.disableTransform
594
+ includeParticipants: false,
595
+ ...omit(options, 'id', 'user', 'url'),
596
+ },
597
+ disableTransform: options.disableTransform,
589
598
  };
590
599
 
591
600
  // Default behavior is to set includeParticipants=false,
592
601
  // which makes the payload lighter by removing participant info.
593
602
  // If the caller explicitly sets the participantAckFilter or
594
603
  // participantsLimit, we don't want that default setting.
595
- if (('participantAckFilter' in options) || ('participantsLimit' in options)) {
604
+ if ('participantAckFilter' in options || 'participantsLimit' in options) {
596
605
  delete params.qs.includeParticipants;
597
606
  }
598
607
 
@@ -601,21 +610,22 @@ const Conversation = WebexPlugin.extend({
601
610
  if (userId) {
602
611
  Object.assign(params, {
603
612
  service: 'conversation',
604
- resource: `conversations/user/${userId}`
613
+ resource: `conversations/user/${userId}`,
605
614
  });
606
- }
607
- else {
615
+ } else {
608
616
  params.uri = uri;
609
617
  }
610
618
 
611
619
  return this.request(params);
612
620
  })
613
- .then(tap(({body}) => {
614
- const {id, url} = body;
615
-
616
- this._recordUUIDs(body);
617
- idToUrl.set(id, url);
618
- }))
621
+ .then(
622
+ tap(({body}) => {
623
+ const {id, url} = body;
624
+
625
+ this._recordUUIDs(body);
626
+ idToUrl.set(id, url);
627
+ })
628
+ )
619
629
  .then((res) => res.body);
620
630
  },
621
631
 
@@ -631,10 +641,7 @@ const Conversation = WebexPlugin.extend({
631
641
  * @returns {Promise<Activity>}
632
642
  */
633
643
  leave(conversation, participant, activity) {
634
- const convoWithUrl =
635
- Object.assign(
636
- {}, conversation, {url: this.getConvoUrl(conversation)}
637
- );
644
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
638
645
 
639
646
  return Promise.resolve()
640
647
  .then(() => {
@@ -642,19 +649,20 @@ const Conversation = WebexPlugin.extend({
642
649
  participant = this.webex.internal.device.userId;
643
650
  }
644
651
 
645
- return this.webex.internal.user.asUUID(participant)
646
- .then((id) => this.prepare(activity, {
652
+ return this.webex.internal.user.asUUID(participant).then((id) =>
653
+ this.prepare(activity, {
647
654
  verb: 'leave',
648
655
  target: this.prepareConversation(convoWithUrl),
649
656
  object: {
650
657
  id,
651
- objectType: 'person'
658
+ objectType: 'person',
652
659
  },
653
660
  kmsMessage: {
654
661
  method: 'delete',
655
- uri: `<KRO>/authorizations?${querystring.stringify({authId: id})}`
656
- }
657
- }));
662
+ uri: `<KRO>/authorizations?${querystring.stringify({authId: id})}`,
663
+ },
664
+ })
665
+ );
658
666
  })
659
667
  .then((a) => this.submit(a));
660
668
  },
@@ -677,15 +685,14 @@ const Conversation = WebexPlugin.extend({
677
685
  resource: options.summary ? 'conversationsSummary' : 'conversations',
678
686
  qs: omit(options, ['deferDecrypt', 'summary']),
679
687
  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
- }
688
+ limit: getConvoLimit(options),
689
+ }).then((results) => {
690
+ for (const convo of results) {
691
+ idToUrl.set(convo.id, convo.url);
692
+ }
686
693
 
687
- return results;
688
- });
694
+ return results;
695
+ });
689
696
  },
690
697
 
691
698
  /**
@@ -709,42 +716,40 @@ const Conversation = WebexPlugin.extend({
709
716
 
710
717
  // Go get the next page of results
711
718
  return this.request({
712
- url: options.page.links.next
719
+ url: options.page.links.next,
713
720
  }).then((res) => ({page: new Page(res, this.webex)}));
714
721
  }
715
722
 
716
723
  // No page - so this is the first request to kick off the pagination process
717
- const queryOptions = Object.assign({
724
+ const queryOptions = {
718
725
  personRefresh: true,
719
726
  uuidEntryFormat: true,
720
727
  activitiesLimit: 0,
721
728
  participantsLimit: 0,
722
- paginate: true
723
- }, omit(options, ['deferDecrypt', 'url']));
729
+ paginate: true,
730
+ ...omit(options, ['deferDecrypt', 'url']),
731
+ };
724
732
 
725
733
  const reqOptions = {
726
734
  qs: queryOptions,
727
735
  deferDecrypt: options.deferDecrypt,
728
- limit: getConvoLimit(options)
736
+ limit: getConvoLimit(options),
729
737
  };
730
738
 
731
739
  // if options.url is present we likely received one or more additional urls due to federation. In this case
732
740
  // we need to initialize pagination against that url instead of the default home cluster
733
741
  if (options.url) {
734
742
  reqOptions.uri = `${options.url}/conversations`;
735
- }
736
- else {
743
+ } else {
737
744
  reqOptions.service = 'conversation';
738
745
  reqOptions.resource = 'conversations';
739
746
  }
740
747
 
741
-
742
748
  return this.request(reqOptions).then((res) => {
743
749
  const response = {
744
- page: new Page(res, this.webex)
750
+ page: new Page(res, this.webex),
745
751
  };
746
752
 
747
-
748
753
  if (res.body && res.body.additionalUrls) {
749
754
  response.additionalUrls = res.body.additionalUrls;
750
755
  }
@@ -764,15 +769,14 @@ const Conversation = WebexPlugin.extend({
764
769
  service: 'conversation',
765
770
  resource: 'conversations/left',
766
771
  qs: options,
767
- limit: getConvoLimit(options)
768
- })
769
- .then((results) => {
770
- for (const convo of results) {
771
- idToUrl.set(convo.id, convo.url);
772
- }
772
+ limit: getConvoLimit(options),
773
+ }).then((results) => {
774
+ for (const convo of results) {
775
+ idToUrl.set(convo.id, convo.url);
776
+ }
773
777
 
774
- return results;
775
- });
778
+ return results;
779
+ });
776
780
  },
777
781
 
778
782
  /**
@@ -807,7 +811,7 @@ const Conversation = WebexPlugin.extend({
807
811
  const params = {
808
812
  method: 'GET',
809
813
  url: `${conversationUrl}/parents`,
810
- qs: query
814
+ qs: query,
811
815
  };
812
816
 
813
817
  const response = await this.request(params);
@@ -827,7 +831,12 @@ const Conversation = WebexPlugin.extend({
827
831
  const {conversationUrl, activityParentId, query} = options;
828
832
  const {activityType} = query;
829
833
 
830
- const initialResponse = await this.listChildActivitiesByParentId(conversationUrl, activityParentId, activityType, query);
834
+ const initialResponse = await this.listChildActivitiesByParentId(
835
+ conversationUrl,
836
+ activityParentId,
837
+ activityType,
838
+ query
839
+ );
831
840
 
832
841
  let page = new Page(initialResponse, this.webex);
833
842
 
@@ -861,12 +870,12 @@ const Conversation = WebexPlugin.extend({
861
870
  async listChildActivitiesByParentId(conversationUrl, activityParentId, activityType, query = {}) {
862
871
  const finalQuery = {
863
872
  ...query,
864
- activityType
873
+ activityType,
865
874
  };
866
875
  const params = {
867
876
  method: 'GET',
868
877
  url: `${conversationUrl}/parents/${activityParentId}`,
869
- qs: finalQuery
878
+ qs: finalQuery,
870
879
  };
871
880
 
872
881
  return this.request(params);
@@ -883,10 +892,14 @@ const Conversation = WebexPlugin.extend({
883
892
  const {body} = await this.request({
884
893
  method: 'GET',
885
894
  url: `${conversationUrl}/activities/${activityParentId}`,
886
- qs: query
895
+ qs: query,
887
896
  });
888
897
 
889
- const reactionObjects = body.children ? body.children.filter((child) => child.type === 'reactionSelfSummary' || child.type === 'reactionSummary') : [];
898
+ const reactionObjects = body.children
899
+ ? body.children.filter(
900
+ (child) => child.type === 'reactionSelfSummary' || child.type === 'reactionSummary'
901
+ )
902
+ : [];
890
903
 
891
904
  return reactionObjects;
892
905
  },
@@ -900,7 +913,7 @@ const Conversation = WebexPlugin.extend({
900
913
  return this._list({
901
914
  service: 'conversation',
902
915
  resource: 'mentions',
903
- qs: omit(options, 'mentions')
916
+ qs: omit(options, 'mentions'),
904
917
  });
905
918
  },
906
919
 
@@ -911,9 +924,13 @@ const Conversation = WebexPlugin.extend({
911
924
  * @returns {Promise} Resolves with the created activity
912
925
  */
913
926
  muteMentions(conversation, activity) {
914
- return this.tag(conversation, {
915
- tags: ['MENTION_NOTIFICATIONS_OFF']
916
- }, activity);
927
+ return this.tag(
928
+ conversation,
929
+ {
930
+ tags: ['MENTION_NOTIFICATIONS_OFF'],
931
+ },
932
+ activity
933
+ );
917
934
  },
918
935
 
919
936
  /**
@@ -923,9 +940,13 @@ const Conversation = WebexPlugin.extend({
923
940
  * @returns {Promise} Resolves with the created activity
924
941
  */
925
942
  muteMessages(conversation, activity) {
926
- return this.tag(conversation, {
927
- tags: ['MESSAGE_NOTIFICATIONS_OFF']
928
- }, activity);
943
+ return this.tag(
944
+ conversation,
945
+ {
946
+ tags: ['MESSAGE_NOTIFICATIONS_OFF'],
947
+ },
948
+ activity
949
+ );
929
950
  },
930
951
 
931
952
  /**
@@ -935,9 +956,13 @@ const Conversation = WebexPlugin.extend({
935
956
  * @returns {Promise} Resolves with the created activity
936
957
  */
937
958
  ignore(conversation, activity) {
938
- return this.tag(conversation, {
939
- tags: ['IGNORED']
940
- }, activity);
959
+ return this.tag(
960
+ conversation,
961
+ {
962
+ tags: ['IGNORED'],
963
+ },
964
+ activity
965
+ );
941
966
  },
942
967
 
943
968
  /**
@@ -948,22 +973,18 @@ const Conversation = WebexPlugin.extend({
948
973
  * @returns {Promise}
949
974
  */
950
975
  cardAction(conversation, inputs, parentActivity, activity = {}) {
951
- const convoWithUrl =
952
- Object.assign(
953
- {}, conversation, {url: this.getConvoUrl(conversation)}
954
- );
976
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
955
977
 
956
978
  activity.parent = {
957
979
  id: parentActivity.id,
958
- type: 'cardAction'
980
+ type: 'cardAction',
959
981
  };
960
982
 
961
983
  return this.prepare(activity, {
962
984
  verb: 'cardAction',
963
985
  target: this.prepareConversation(convoWithUrl),
964
- object: Object.assign({objectType: 'submit'}, inputs)
965
- })
966
- .then((a) => this.submit(a));
986
+ object: {objectType: 'submit', ...inputs},
987
+ }).then((a) => this.submit(a));
967
988
  },
968
989
 
969
990
  /**
@@ -977,105 +998,122 @@ const Conversation = WebexPlugin.extend({
977
998
  * @returns {Promise<Activity>}
978
999
  */
979
1000
  post(conversation, message, activity) {
980
- const convoWithUrl =
981
- Object.assign(
982
- {}, conversation, {url: this.getConvoUrl(conversation)}
983
- );
1001
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
984
1002
 
985
1003
  if (isString(message)) {
986
1004
  message = {
987
- displayName: message
1005
+ displayName: message,
988
1006
  };
989
1007
  }
990
1008
 
991
1009
  return this.prepare(activity, {
992
1010
  verb: 'post',
993
1011
  target: this.prepareConversation(convoWithUrl),
994
- object: Object.assign({objectType: 'comment'}, message)
995
- })
996
- .then((a) => this.submit(a));
1012
+ object: {objectType: 'comment', ...message},
1013
+ }).then((a) => this.submit(a));
997
1014
  },
998
1015
 
999
1016
  prepareConversation(conversation) {
1000
- return defaults(pick(conversation, 'id', 'url', 'objectType', 'defaultActivityEncryptionKeyUrl', 'kmsResourceObjectUrl'), {
1001
- objectType: 'conversation'
1002
- });
1017
+ return defaults(
1018
+ pick(
1019
+ conversation,
1020
+ 'id',
1021
+ 'url',
1022
+ 'objectType',
1023
+ 'defaultActivityEncryptionKeyUrl',
1024
+ 'kmsResourceObjectUrl'
1025
+ ),
1026
+ {
1027
+ objectType: 'conversation',
1028
+ }
1029
+ );
1003
1030
  },
1004
1031
 
1005
1032
  prepare(activity, params) {
1006
1033
  params = params || {};
1007
1034
  activity = activity || {};
1008
1035
 
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
- });
1018
-
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
- }
1036
+ return Promise.resolve(activity.prepare ? activity.prepare(params) : activity).then((act) => {
1037
+ defaults(act, {
1038
+ verb: params.verb,
1039
+ kmsMessage: params.kmsMessage,
1040
+ objectType: 'activity',
1041
+ clientTempId: uuid.v4(),
1042
+ actor: this.webex.internal.device.userId,
1043
+ });
1026
1044
 
1027
- if (isString(act.actor)) {
1028
- act.actor = {
1029
- objectType: 'person',
1030
- id: act.actor
1031
- };
1032
- }
1045
+ // Workaround because parent is a reserved props in Ampersand
1046
+ if (
1047
+ (activity.parentActivityId && activity.activityType) ||
1048
+ (activity.parent && activity.parent.id && activity.parent.type)
1049
+ ) {
1050
+ act.parent = {
1051
+ id: activity.parentActivityId || activity.parent.id,
1052
+ type: activity.activityType || activity.parent.type,
1053
+ };
1054
+ }
1033
1055
 
1034
- ['actor', 'object'].forEach((key) => {
1035
- if (params[key]) {
1036
- act[key] = act[key] || {};
1037
- defaults(act[key], params[key]);
1038
- }
1039
- });
1056
+ if (isString(act.actor)) {
1057
+ act.actor = {
1058
+ objectType: 'person',
1059
+ id: act.actor,
1060
+ };
1061
+ }
1040
1062
 
1041
- if (params.target) {
1042
- merge(act, {
1043
- target: pick(params.target, 'id', 'url', 'objectType', 'kmsResourceObjectUrl', 'defaultActivityEncryptionKeyUrl')
1044
- });
1063
+ ['actor', 'object'].forEach((key) => {
1064
+ if (params[key]) {
1065
+ act[key] = act[key] || {};
1066
+ defaults(act[key], params[key]);
1045
1067
  }
1068
+ });
1046
1069
 
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
- }
1070
+ if (params.target) {
1071
+ merge(act, {
1072
+ target: pick(
1073
+ params.target,
1074
+ 'id',
1075
+ 'url',
1076
+ 'objectType',
1077
+ 'kmsResourceObjectUrl',
1078
+ 'defaultActivityEncryptionKeyUrl'
1079
+ ),
1059
1080
  });
1081
+ }
1060
1082
 
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`'));
1083
+ ['object', 'target'].forEach((key) => {
1084
+ if (act[key] && act[key].url && !act[key].id) {
1085
+ act[key].id = act[key].url.split('/').pop();
1063
1086
  }
1087
+ });
1064
1088
 
1065
- return act;
1089
+ ['actor', 'object', 'target'].forEach((key) => {
1090
+ if (act[key] && !act[key].objectType) {
1091
+ // Reminder: throwing here because it's the only way to get out of
1092
+ // this loop in event of an error.
1093
+ throw new Error(`\`act.${key}.objectType\` must be defined`);
1094
+ }
1066
1095
  });
1096
+
1097
+ if (act.object && act.object.content && !act.object.displayName) {
1098
+ return Promise.reject(
1099
+ new Error('Cannot submit activity object with `content` but no `displayName`')
1100
+ );
1101
+ }
1102
+
1103
+ return act;
1104
+ });
1067
1105
  },
1068
1106
 
1069
1107
  /**
1070
- * Get a subset of threads for a user.
1071
- * @param {Object} options
1072
- * @returns {Promise<Array<Activity>>}
1073
- */
1108
+ * Get a subset of threads for a user.
1109
+ * @param {Object} options
1110
+ * @returns {Promise<Array<Activity>>}
1111
+ */
1074
1112
  async listThreads(options) {
1075
1113
  return this._list({
1076
1114
  service: 'conversation',
1077
1115
  resource: 'threads',
1078
- qs: omit(options, 'showAllTypes')
1116
+ qs: omit(options, 'showAllTypes'),
1079
1117
  });
1080
1118
  },
1081
1119
 
@@ -1085,8 +1123,7 @@ const Conversation = WebexPlugin.extend({
1085
1123
  * @returns {Promise}
1086
1124
  */
1087
1125
  processActivityEvent(event) {
1088
- return this.webex.transform('inbound', event)
1089
- .then(() => event);
1126
+ return this.webex.transform('inbound', event).then(() => event);
1090
1127
  },
1091
1128
 
1092
1129
  /**
@@ -1095,8 +1132,7 @@ const Conversation = WebexPlugin.extend({
1095
1132
  * @returns {Promise}
1096
1133
  */
1097
1134
  processInmeetingchatEvent(event) {
1098
- return this.webex.transform('inbound', event)
1099
- .then(() => event);
1135
+ return this.webex.transform('inbound', event).then(() => event);
1100
1136
  },
1101
1137
 
1102
1138
  /**
@@ -1106,14 +1142,18 @@ const Conversation = WebexPlugin.extend({
1106
1142
  * @returns {Promise} Resolves with the created activity
1107
1143
  */
1108
1144
  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);
1145
+ return this.untag(
1146
+ conversation,
1147
+ {
1148
+ tags: [
1149
+ 'MENTION_NOTIFICATIONS_OFF',
1150
+ 'MENTION_NOTIFICATIONS_ON',
1151
+ 'MESSAGE_NOTIFICATIONS_OFF',
1152
+ 'MESSAGE_NOTIFICATIONS_ON',
1153
+ ],
1154
+ },
1155
+ activity
1156
+ );
1117
1157
  },
1118
1158
 
1119
1159
  /**
@@ -1144,10 +1184,7 @@ const Conversation = WebexPlugin.extend({
1144
1184
  return Promise.reject(new Error('Room avatars must be less than 1MB'));
1145
1185
  }
1146
1186
 
1147
- const convoWithUrl =
1148
- Object.assign(
1149
- {}, conversation, {url: this.getConvoUrl(conversation)}
1150
- );
1187
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1151
1188
 
1152
1189
  return Promise.resolve()
1153
1190
  .then(() => {
@@ -1157,7 +1194,7 @@ const Conversation = WebexPlugin.extend({
1157
1194
  activity.add(avatar, uploadOptions);
1158
1195
 
1159
1196
  return this.prepare(activity, {
1160
- target: this.prepareConversation(convoWithUrl)
1197
+ target: this.prepareConversation(convoWithUrl),
1161
1198
  });
1162
1199
  })
1163
1200
  .then((a) => {
@@ -1179,9 +1216,7 @@ const Conversation = WebexPlugin.extend({
1179
1216
  * @param {Object} conversations If this is a team, the list of conversations in the team
1180
1217
  * @returns {String} url for the specific convo
1181
1218
  */
1182
- getConvoUrl({
1183
- id, url, cluster, conversations, generalConversationUuid
1184
- }) {
1219
+ getConvoUrl({id, url, cluster, conversations, generalConversationUuid}) {
1185
1220
  if (generalConversationUuid) {
1186
1221
  // This is a Team
1187
1222
  // Because Convo doesn't have an endpoint for the team URL
@@ -1201,9 +1236,7 @@ const Conversation = WebexPlugin.extend({
1201
1236
  if (cluster) {
1202
1237
  return this.getUrlFromClusterId({cluster, id});
1203
1238
  }
1204
- this.logger.warn(
1205
- 'You should be using the `url` instead of the `id` property'
1206
- );
1239
+ this.logger.warn('You should be using the `url` instead of the `id` property');
1207
1240
  const relatedUrl = idToUrl.get(id);
1208
1241
 
1209
1242
  if (!relatedUrl) {
@@ -1228,11 +1261,8 @@ const Conversation = WebexPlugin.extend({
1228
1261
  if (!conversation.id) {
1229
1262
  if (conversation.url) {
1230
1263
  conversation.id = conversation.url.split('/').pop();
1231
- }
1232
- else {
1233
- return Promise.reject(
1234
- new Error('conversation: could not identify conversation')
1235
- );
1264
+ } else {
1265
+ return Promise.reject(new Error('conversation: could not identify conversation'));
1236
1266
  }
1237
1267
  }
1238
1268
 
@@ -1240,8 +1270,7 @@ const Conversation = WebexPlugin.extend({
1240
1270
 
1241
1271
  if (options.typing) {
1242
1272
  eventType = 'status.start_typing';
1243
- }
1244
- else {
1273
+ } else {
1245
1274
  eventType = 'status.stop_typing';
1246
1275
  }
1247
1276
 
@@ -1251,9 +1280,9 @@ const Conversation = WebexPlugin.extend({
1251
1280
  method: 'POST',
1252
1281
  body: {
1253
1282
  conversationId: conversation.id,
1254
- eventType
1283
+ eventType,
1255
1284
  },
1256
- url: `${url}/${resource}`
1285
+ url: `${url}/${resource}`,
1257
1286
  };
1258
1287
 
1259
1288
  return this.request(params);
@@ -1269,27 +1298,22 @@ const Conversation = WebexPlugin.extend({
1269
1298
  if (isArray(activity)) {
1270
1299
  activity = {
1271
1300
  object: {
1272
- files: activity
1273
- }
1301
+ files: activity,
1302
+ },
1274
1303
  };
1275
1304
  }
1276
1305
 
1277
- const convoWithUrl =
1278
- Object.assign(
1279
- {}, conversation, {url: this.getConvoUrl(conversation)}
1280
- );
1306
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1281
1307
 
1282
1308
  if (!(activity instanceof ShareActivity)) {
1283
1309
  activity = ShareActivity.create(convoWithUrl, activity, this.webex);
1284
1310
  }
1285
1311
 
1286
1312
  return this.prepare(activity, {
1287
- target: this.prepareConversation(convoWithUrl)
1288
- })
1289
- .then((a) => this.submit(a));
1313
+ target: this.prepareConversation(convoWithUrl),
1314
+ }).then((a) => this.submit(a));
1290
1315
  },
1291
1316
 
1292
-
1293
1317
  /**
1294
1318
  * Submits an activity to the conversation service
1295
1319
  * @param {Object} activity
@@ -1303,15 +1327,15 @@ const Conversation = WebexPlugin.extend({
1303
1327
  method: 'POST',
1304
1328
  body: activity,
1305
1329
  qs: {
1306
- personRefresh: true
1330
+ personRefresh: true,
1307
1331
  },
1308
- url: `${url}/${resource}`
1332
+ url: `${url}/${resource}`,
1309
1333
  };
1310
1334
 
1311
1335
  if (activity.verb === 'share') {
1312
1336
  Object.assign(params.qs, {
1313
1337
  transcode: true,
1314
- async: false
1338
+ async: false,
1315
1339
  });
1316
1340
  }
1317
1341
  /**
@@ -1323,7 +1347,12 @@ const Conversation = WebexPlugin.extend({
1323
1347
  const customActivityCopy = (value) => {
1324
1348
  const {files} = params.body.object;
1325
1349
 
1326
- if (files && value && files.items.length > 0 && value.constructor === files.items[0].scr.constructor) {
1350
+ if (
1351
+ files &&
1352
+ value &&
1353
+ files.items.length > 0 &&
1354
+ value.constructor === files.items[0].scr.constructor
1355
+ ) {
1327
1356
  const copySrc = cloneDeep(value);
1328
1357
 
1329
1358
  copySrc.toJWE = value.toJWE;
@@ -1344,22 +1373,24 @@ const Conversation = WebexPlugin.extend({
1344
1373
  if (error.body && error.body.errorCode === KEY_ROTATION_REQUIRED) {
1345
1374
  cloneActivity.body.target.defaultActivityEncryptionKeyUrl = null;
1346
1375
  this.request(cloneActivity);
1347
- }
1348
- else if (
1376
+ } else if (
1349
1377
  error.body &&
1350
- (error.body.errorCode === KEY_ALREADY_ROTATED || error.body.errorCode === ENCRYPTION_KEY_URL_MISMATCH)
1378
+ (error.body.errorCode === KEY_ALREADY_ROTATED ||
1379
+ error.body.errorCode === ENCRYPTION_KEY_URL_MISMATCH)
1351
1380
  ) {
1352
1381
  // 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 {
1382
+ this.webex
1383
+ .request({
1384
+ method: 'GET',
1385
+ api: 'conversation',
1386
+ resource: `conversations/${params.body.target.id}`,
1387
+ })
1388
+ .then((res) => {
1389
+ cloneActivity.body.target.defaultActivityEncryptionKeyUrl =
1390
+ res.body.defaultActivityEncryptionkeyUrl;
1391
+ this.request(cloneActivity);
1392
+ });
1393
+ } else {
1363
1394
  throw error;
1364
1395
  }
1365
1396
  });
@@ -1371,10 +1402,7 @@ const Conversation = WebexPlugin.extend({
1371
1402
  * @returns {Promise}
1372
1403
  */
1373
1404
  unassign(conversation, activity) {
1374
- const convoWithUrl =
1375
- Object.assign(
1376
- {}, conversation, {url: this.getConvoUrl(conversation)}
1377
- );
1405
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1378
1406
 
1379
1407
  return this.prepare(activity, {
1380
1408
  verb: 'unassign',
@@ -1382,11 +1410,10 @@ const Conversation = WebexPlugin.extend({
1382
1410
  object: {
1383
1411
  objectType: 'content',
1384
1412
  files: {
1385
- items: []
1386
- }
1387
- }
1388
- })
1389
- .then((a) => this.submit(a));
1413
+ items: [],
1414
+ },
1415
+ },
1416
+ }).then((a) => this.submit(a));
1390
1417
  },
1391
1418
 
1392
1419
  /**
@@ -1396,9 +1423,13 @@ const Conversation = WebexPlugin.extend({
1396
1423
  * @returns {Promise} Resolves with the created activity
1397
1424
  */
1398
1425
  unmuteMentions(conversation, activity) {
1399
- return this.tag(conversation, {
1400
- tags: ['MENTION_NOTIFICATIONS_ON']
1401
- }, activity);
1426
+ return this.tag(
1427
+ conversation,
1428
+ {
1429
+ tags: ['MENTION_NOTIFICATIONS_ON'],
1430
+ },
1431
+ activity
1432
+ );
1402
1433
  },
1403
1434
 
1404
1435
  /**
@@ -1408,9 +1439,13 @@ const Conversation = WebexPlugin.extend({
1408
1439
  * @returns {Promise} Resolves with the created activity
1409
1440
  */
1410
1441
  unmuteMessages(conversation, activity) {
1411
- return this.tag(conversation, {
1412
- tags: ['MESSAGE_NOTIFICATIONS_ON']
1413
- }, activity);
1442
+ return this.tag(
1443
+ conversation,
1444
+ {
1445
+ tags: ['MESSAGE_NOTIFICATIONS_ON'],
1446
+ },
1447
+ activity
1448
+ );
1414
1449
  },
1415
1450
 
1416
1451
  /**
@@ -1420,9 +1455,13 @@ const Conversation = WebexPlugin.extend({
1420
1455
  * @returns {Promise} Resolves with the created activity
1421
1456
  */
1422
1457
  unignore(conversation, activity) {
1423
- return this.untag(conversation, {
1424
- tags: ['IGNORED']
1425
- }, activity);
1458
+ return this.untag(
1459
+ conversation,
1460
+ {
1461
+ tags: ['IGNORED'],
1462
+ },
1463
+ activity
1464
+ );
1426
1465
  },
1427
1466
 
1428
1467
  /**
@@ -1437,17 +1476,13 @@ const Conversation = WebexPlugin.extend({
1437
1476
  return Promise.reject(new Error('`object` must be an object'));
1438
1477
  }
1439
1478
 
1440
- const convoWithUrl =
1441
- Object.assign(
1442
- {}, conversation, {url: this.getConvoUrl(conversation)}
1443
- );
1479
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1444
1480
 
1445
1481
  return this.prepare(activity, {
1446
1482
  verb: 'update',
1447
1483
  target: this.prepareConversation(convoWithUrl),
1448
- object
1449
- })
1450
- .then((a) => this.submit(a));
1484
+ object,
1485
+ }).then((a) => this.submit(a));
1451
1486
  },
1452
1487
 
1453
1488
  /**
@@ -1460,16 +1495,12 @@ const Conversation = WebexPlugin.extend({
1460
1495
  * @returns {Promise<Activity>}
1461
1496
  */
1462
1497
  updateKey(conversation, key, activity) {
1463
- const convoWithUrl =
1464
- Object.assign(
1465
- {}, conversation, {url: this.getConvoUrl(conversation)}
1466
- );
1498
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1467
1499
 
1468
1500
  return this.get(convoWithUrl, {
1469
1501
  activitiesLimit: 0,
1470
- includeParticipants: true
1471
- })
1472
- .then((c) => this._updateKey(c, key, activity));
1502
+ includeParticipants: true,
1503
+ }).then((c) => this._updateKey(c, key, activity));
1473
1504
  },
1474
1505
 
1475
1506
  /**
@@ -1483,52 +1514,44 @@ const Conversation = WebexPlugin.extend({
1483
1514
  * @returns {Promise<Activity>}
1484
1515
  */
1485
1516
  _updateKey(conversation, key, activity) {
1486
- const convoWithUrl =
1487
- Object.assign(
1488
- {}, conversation, {url: this.getConvoUrl(conversation)}
1489
- );
1517
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
1490
1518
 
1491
1519
  return Promise.resolve(
1492
1520
  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
- };
1521
+ ).then((keys) => {
1522
+ const k = isArray(keys) ? keys[0] : keys;
1523
+ const params = {
1524
+ verb: 'updateKey',
1525
+ target: this.prepareConversation(convoWithUrl),
1526
+ object: {
1527
+ defaultActivityEncryptionKeyUrl: k.uri,
1528
+ objectType: 'conversation',
1529
+ },
1530
+ };
1504
1531
 
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
- }
1532
+ // Reminder: the kmsResourceObjectUrl is only usable if there is
1533
+ // defaultActivityEncryptionKeyUrl.
1534
+ // Valid defaultActivityEncryptionKeyUrl start with 'kms:'
1535
+ if (
1536
+ convoWithUrl.kmsResourceObjectUrl &&
1537
+ convoWithUrl.kmsResourceObjectUrl.startsWith('kms:')
1538
+ ) {
1539
+ params.kmsMessage = {
1540
+ method: 'update',
1541
+ resourceUri: '<KRO>',
1542
+ uri: k.uri,
1543
+ };
1544
+ } else {
1545
+ params.kmsMessage = {
1546
+ method: 'create',
1547
+ uri: '/resources',
1548
+ userIds: map(convoWithUrl.participants.items, 'id'),
1549
+ keyUris: [k.uri],
1550
+ };
1551
+ }
1528
1552
 
1529
- return this.prepare(activity, params)
1530
- .then((a) => this.submit(a));
1531
- });
1553
+ return this.prepare(activity, params).then((a) => this.submit(a));
1554
+ });
1532
1555
  },
1533
1556
 
1534
1557
  /**
@@ -1544,10 +1567,9 @@ const Conversation = WebexPlugin.extend({
1544
1567
  resource: 'conversations',
1545
1568
  body: payload,
1546
1569
  qs: {
1547
- forceCreate: options.allowPartialCreation
1548
- }
1549
- })
1550
- .then((res) => res.body);
1570
+ forceCreate: options.allowPartialCreation,
1571
+ },
1572
+ }).then((res) => res.body);
1551
1573
  },
1552
1574
 
1553
1575
  /**
@@ -1592,13 +1614,11 @@ const Conversation = WebexPlugin.extend({
1592
1614
 
1593
1615
  // Wait for the postauth catalog to update and then try to retrieve the
1594
1616
  // conversation service url again.
1595
- return this.webex.internal.waitForCatalog('postauth')
1617
+ return this.webex.internal
1618
+ .waitForCatalog('postauth')
1596
1619
  .then(() => this.webex.internal.services.get('conversation'))
1597
1620
  .catch((error) => {
1598
- this.logger.warn(
1599
- 'conversation: unable to get conversation url',
1600
- error.message
1601
- );
1621
+ this.logger.warn('conversation: unable to get conversation url', error.message);
1602
1622
 
1603
1623
  return Promise.reject(error);
1604
1624
  });
@@ -1611,29 +1631,30 @@ const Conversation = WebexPlugin.extend({
1611
1631
  */
1612
1632
  _inferConversationUrl(conversation) {
1613
1633
  if (conversation.id) {
1614
- return this.webex.internal.feature.getFeature('developer', 'web-high-availability')
1634
+ return this.webex.internal.feature
1635
+ .getFeature('developer', 'web-high-availability')
1615
1636
  .then((haMessagingEnabled) => {
1616
1637
  if (haMessagingEnabled) {
1617
1638
  // recompute conversation URL each time as the host may have changed
1618
1639
  // since last usage
1619
- return this.getConversationUrl()
1620
- .then((url) => {
1621
- conversation.url = `${url}/conversations/${conversation.id}`;
1640
+ return this.getConversationUrl().then((url) => {
1641
+ conversation.url = `${url}/conversations/${conversation.id}`;
1622
1642
 
1623
- return conversation;
1624
- });
1643
+ return conversation;
1644
+ });
1625
1645
  }
1626
1646
  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
- });
1647
+ return this.getConversationUrl().then((url) => {
1648
+ conversation.url = `${url}/conversations/${conversation.id}`;
1649
+ /* istanbul ignore else */
1650
+ if (process.env.NODE_ENV !== 'production') {
1651
+ this.logger.warn(
1652
+ 'conversation: inferred conversation url from conversation id; please pass whole conversation objects to Conversation methods'
1653
+ );
1654
+ }
1655
+
1656
+ return conversation;
1657
+ });
1637
1658
  }
1638
1659
 
1639
1660
  return Promise.resolve(conversation);
@@ -1657,11 +1678,10 @@ const Conversation = WebexPlugin.extend({
1657
1678
 
1658
1679
  return this._list({
1659
1680
  qs: omit(options, 'resource'),
1660
- url: `${url}/${resource}`
1681
+ url: `${url}/${resource}`,
1661
1682
  });
1662
1683
  },
1663
1684
 
1664
-
1665
1685
  /**
1666
1686
  * common interface for facade of generator functions
1667
1687
  * @typedef {object} IGeneratorResponse
@@ -1688,10 +1708,7 @@ const Conversation = WebexPlugin.extend({
1688
1708
  * jumpToActivity - gets searched-for activity and surrounding activities
1689
1709
  */
1690
1710
  listActivitiesThreadOrdered(options) {
1691
- const {
1692
- conversationUrl,
1693
- conversationId
1694
- } = options;
1711
+ const {conversationUrl, conversationId} = options;
1695
1712
 
1696
1713
  if (!conversationUrl && !conversationId) {
1697
1714
  throw new Error('must provide a conversation URL or conversation ID');
@@ -1723,7 +1740,10 @@ const Conversation = WebexPlugin.extend({
1723
1740
  }
1724
1741
 
1725
1742
  const searchOptions = {
1726
- ...baseOptions, url: newUrl, queryType: MID, search: searchObject
1743
+ ...baseOptions,
1744
+ url: newUrl,
1745
+ queryType: MID,
1746
+ search: searchObject,
1727
1747
  };
1728
1748
 
1729
1749
  threadOrderer = this._listActivitiesThreadOrdered(searchOptions);
@@ -1732,7 +1752,7 @@ const Conversation = WebexPlugin.extend({
1732
1752
 
1733
1753
  return {
1734
1754
  done: true,
1735
- value: searchResults
1755
+ value: searchResults,
1736
1756
  };
1737
1757
  };
1738
1758
 
@@ -1744,11 +1764,12 @@ const Conversation = WebexPlugin.extend({
1744
1764
  const {value = []} = await threadOrderer.next(olderOptions);
1745
1765
 
1746
1766
  const oldestInBatch = value[0] && value[0].activity;
1747
- const moreActivitiesExist = oldestInBatch && getActivityType(oldestInBatch) !== ACTIVITY_TYPES.CREATE;
1767
+ const moreActivitiesExist =
1768
+ oldestInBatch && getActivityType(oldestInBatch) !== ACTIVITY_TYPES.CREATE;
1748
1769
 
1749
1770
  return {
1750
1771
  done: !moreActivitiesExist,
1751
- value
1772
+ value,
1752
1773
  };
1753
1774
  };
1754
1775
 
@@ -1763,22 +1784,22 @@ const Conversation = WebexPlugin.extend({
1763
1784
 
1764
1785
  return {
1765
1786
  done: !value.length,
1766
- value
1787
+ value,
1767
1788
  };
1768
1789
  };
1769
1790
 
1770
1791
  return {
1771
1792
  jumpToActivity,
1772
1793
  getNewer,
1773
- getOlder
1794
+ getOlder,
1774
1795
  };
1775
1796
  },
1776
1797
 
1777
1798
  /**
1778
- * Represents reactions to messages
1779
- * @typedef {object} Reaction
1780
- * @property {object} activity reaction2summary server activity object
1781
- */
1799
+ * Represents reactions to messages
1800
+ * @typedef {object} Reaction
1801
+ * @property {object} activity reaction2summary server activity object
1802
+ */
1782
1803
 
1783
1804
  /**
1784
1805
  * Represents a root (parent, with or without children) activity, along with any replies and reactions
@@ -1804,34 +1825,30 @@ const Conversation = WebexPlugin.extend({
1804
1825
  *
1805
1826
  * @returns {void}
1806
1827
  */
1807
- async* _listActivitiesThreadOrdered(options = {}) {
1828
+ async *_listActivitiesThreadOrdered(options = {}) {
1808
1829
  // ***********************************************
1809
1830
  // INSTANCE STATE VARIABLES
1810
1831
  // variables that will be used for the life of the generator
1811
1832
  // ***********************************************
1812
1833
 
1813
- let {
1814
- minActivities = defaultMinDisplayableActivities,
1815
- queryType = INITIAL
1816
- } = options;
1834
+ let {minActivities = defaultMinDisplayableActivities, queryType = INITIAL} = options;
1817
1835
 
1818
1836
  // must fetch initially before getting newer activities!
1819
1837
  if (queryType === NEWER) {
1820
1838
  queryType = INITIAL;
1821
1839
  }
1822
1840
 
1823
- const {
1824
- url: convoUrl,
1825
- search = {},
1826
- includeChildren
1827
- } = options;
1841
+ const {url: convoUrl, search = {}, includeChildren} = options;
1828
1842
 
1829
1843
  // manage oldest, newest activities (ie bookends)
1830
1844
  const {setBookends, getNewestAct, getOldestAct} = bookendManager();
1831
1845
 
1832
1846
  // 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
1847
  // reduces server RTs when fetching older activities
1834
- const defaultBatchSize = (queryType === INITIAL || queryType === OLDER) ? minActivities : Math.max(minBatchSize, Math.ceil(minActivities / 2));
1848
+ const defaultBatchSize =
1849
+ queryType === INITIAL || queryType === OLDER
1850
+ ? minActivities
1851
+ : Math.max(minBatchSize, Math.ceil(minActivities / 2));
1835
1852
  let batchSize = defaultBatchSize;
1836
1853
 
1837
1854
  // exposes activity states and handlers with simple getters
@@ -1853,22 +1870,19 @@ const Conversation = WebexPlugin.extend({
1853
1870
 
1854
1871
  // used to determine if we should continue to fetch older activities
1855
1872
  // 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]);
1873
+ const {getNoMoreActs, checkAndSetNoMoreActs, checkAndSetNoOlderActs, checkAndSetNoNewerActs} =
1874
+ noMoreActivitiesManager();
1875
+
1876
+ const getActivityHandlerByType = (type) =>
1877
+ ({
1878
+ [ACTIVITY_TYPES.ROOT]: addNewRoot,
1879
+ [ACTIVITY_TYPES.REPLY]: getActivityHandlerByKey(ACTIVITY_TYPES.REPLY),
1880
+ [ACTIVITY_TYPES.EDIT]: getActivityHandlerByKey(ACTIVITY_TYPES.EDIT),
1881
+ [ACTIVITY_TYPES.REACTION]: getActivityHandlerByKey(ACTIVITY_TYPES.REACTION),
1882
+ [ACTIVITY_TYPES.REACTION_SELF]: getActivityHandlerByKey(ACTIVITY_TYPES.REACTION_SELF),
1883
+ [ACTIVITY_TYPES.TOMBSTONE]: addNewRoot,
1884
+ [ACTIVITY_TYPES.CREATE]: addNewRoot,
1885
+ }[type]);
1872
1886
 
1873
1887
  const handleNewActivity = (activity) => {
1874
1888
  const actType = getActivityType(activity);
@@ -1906,12 +1920,13 @@ const Conversation = WebexPlugin.extend({
1906
1920
  handleNewActivities(activities);
1907
1921
  };
1908
1922
 
1909
- const getQueryResponseHandler = (type) => ({
1910
- [OLDER]: handleOlderQuery,
1911
- [NEWER]: handleNewerQuery,
1912
- [MID]: handleSearch,
1913
- [INITIAL]: handleOlderQuery
1914
- }[type]);
1923
+ const getQueryResponseHandler = (type) =>
1924
+ ({
1925
+ [OLDER]: handleOlderQuery,
1926
+ [NEWER]: handleNewerQuery,
1927
+ [MID]: handleSearch,
1928
+ [INITIAL]: handleOlderQuery,
1929
+ }[type]);
1915
1930
 
1916
1931
  // ***********************************************
1917
1932
  // INNER LOOP
@@ -1930,7 +1945,7 @@ const Conversation = WebexPlugin.extend({
1930
1945
  conversationUrl: convoUrl,
1931
1946
  limit: batchSize,
1932
1947
  includeChildren,
1933
- ...query
1948
+ ...query,
1934
1949
  };
1935
1950
 
1936
1951
  // request activities in batches
@@ -1953,10 +1968,7 @@ const Conversation = WebexPlugin.extend({
1953
1968
  }
1954
1969
 
1955
1970
  // we dont always need to fetch for parents
1956
- const [
1957
- allBatchActivities,
1958
- parents = {}
1959
- ] = await Promise.all($fetchRequests);
1971
+ const [allBatchActivities, parents = {}] = await Promise.all($fetchRequests);
1960
1972
 
1961
1973
  // use query type to decide how to handle response
1962
1974
  const handler = getQueryResponseHandler(queryType);
@@ -1968,11 +1980,7 @@ const Conversation = WebexPlugin.extend({
1968
1980
  do this by checking the hash for each of the above parent IDs
1969
1981
  fetch children when we have a parent whose ID is represented in the parent ID lists
1970
1982
  */
1971
- const {
1972
- reply: replyIds = [],
1973
- edit: editIds = [],
1974
- reaction: reactionIds = []
1975
- } = parents;
1983
+ const {reply: replyIds = [], edit: editIds = [], reaction: reactionIds = []} = parents;
1976
1984
 
1977
1985
  // if no parent IDs returned, do nothing
1978
1986
  if (replyIds.length || editIds.length || reactionIds.length) {
@@ -1985,11 +1993,16 @@ const Conversation = WebexPlugin.extend({
1985
1993
 
1986
1994
  const childFetchOptions = {
1987
1995
  conversationUrl: convoUrl,
1988
- activityParentId: actId
1996
+ activityParentId: actId,
1989
1997
  };
1990
1998
 
1991
1999
  if (reactionIds.includes(actId)) {
1992
- $reactionFetches.push(this.getReactionSummaryByParentId(convoUrl, actId, {activityType: 'reactionSummary', includeChildren: true}));
2000
+ $reactionFetches.push(
2001
+ this.getReactionSummaryByParentId(convoUrl, actId, {
2002
+ activityType: 'reactionSummary',
2003
+ includeChildren: true,
2004
+ })
2005
+ );
1993
2006
  }
1994
2007
  if (replyIds.includes(actId)) {
1995
2008
  childFetchOptions.query = {activityType: 'reply'};
@@ -2005,14 +2018,19 @@ const Conversation = WebexPlugin.extend({
2005
2018
  const [reactions, replies, edits] = await Promise.all([
2006
2019
  Promise.all($reactionFetches),
2007
2020
  Promise.all($replyFetches),
2008
- Promise.all($editFetches)
2021
+ Promise.all($editFetches),
2009
2022
  ]);
2010
2023
 
2011
2024
  // new reactions may have come in that also need their reactions fetched
2012
2025
  const newReplyReactions = await Promise.all(
2013
2026
  replies
2014
2027
  .filter((reply) => replyIds.includes(reply.id))
2015
- .map((reply) => this.getReactionSummaryByParentId(convoUrl, reply.id, {activityType: 'reactionSummary', includeChildren: true}))
2028
+ .map((reply) =>
2029
+ this.getReactionSummaryByParentId(convoUrl, reply.id, {
2030
+ activityType: 'reactionSummary',
2031
+ includeChildren: true,
2032
+ })
2033
+ )
2016
2034
  );
2017
2035
 
2018
2036
  const allReactions = [...reactions, ...newReplyReactions];
@@ -2060,13 +2078,12 @@ const Conversation = WebexPlugin.extend({
2060
2078
  // we're still building our activity list - derive new query from prior query and start loop again
2061
2079
  if (queryType === INITIAL) {
2062
2080
  query = getQuery(OLDER, {oldestPublishedDate: currentOldestPublishedDate, batchSize});
2063
- }
2064
- else {
2081
+ } else {
2065
2082
  query = getQuery(queryType, {
2066
2083
  batchSize,
2067
2084
  activityToSearch: search,
2068
2085
  oldestPublishedDate: currentOldestPublishedDate,
2069
- newestPublishedDate: currentNewestPublishedDate
2086
+ newestPublishedDate: currentNewestPublishedDate,
2070
2087
  });
2071
2088
  }
2072
2089
 
@@ -2087,7 +2104,9 @@ const Conversation = WebexPlugin.extend({
2087
2104
  return replies;
2088
2105
  }
2089
2106
 
2090
- const sortedReplies = sortActivitiesByPublishedDate(getActivityObjectsFromMap(repliesByParentId));
2107
+ const sortedReplies = sortActivitiesByPublishedDate(
2108
+ getActivityObjectsFromMap(repliesByParentId)
2109
+ );
2091
2110
 
2092
2111
  sortedReplies.forEach((replyActivity) => {
2093
2112
  const replyId = replyActivity.id;
@@ -2097,20 +2116,26 @@ const Conversation = WebexPlugin.extend({
2097
2116
 
2098
2117
  const latestActivity = edit || replyActivity;
2099
2118
  // hash of root activities (in case of plain reply) and the reply activity (in case of edit)
2100
- const allRelevantActivitiesArr = [...getActivityObjectsFromMap(getRootActivityHash()), ...getActivityObjectsFromMap(repliesByParentId)];
2119
+ const allRelevantActivitiesArr = [
2120
+ ...getActivityObjectsFromMap(getRootActivityHash()),
2121
+ ...getActivityObjectsFromMap(repliesByParentId),
2122
+ ];
2101
2123
  const allRelevantActivities = allRelevantActivitiesArr.reduce((hashMap, act) => {
2102
2124
  hashMap[act.id] = act;
2103
2125
 
2104
2126
  return hashMap;
2105
2127
  }, {});
2106
2128
 
2107
- const finalReply = this._createParsedServerActivity(latestActivity, allRelevantActivities);
2129
+ const finalReply = this._createParsedServerActivity(
2130
+ latestActivity,
2131
+ allRelevantActivities
2132
+ );
2108
2133
 
2109
2134
  const fullReply = {
2110
2135
  id: replyId,
2111
2136
  activity: finalReply,
2112
2137
  reaction,
2113
- reactionSelf
2138
+ reactionSelf,
2114
2139
  };
2115
2140
 
2116
2141
  const sanitizedFullReply = sanitizeActivity(fullReply);
@@ -2121,7 +2146,9 @@ const Conversation = WebexPlugin.extend({
2121
2146
  return replies;
2122
2147
  };
2123
2148
 
2124
- const orderedRoots = sortActivitiesByPublishedDate(getActivityObjectsFromMap(getRootActivityHash()));
2149
+ const orderedRoots = sortActivitiesByPublishedDate(
2150
+ getActivityObjectsFromMap(getRootActivityHash())
2151
+ );
2125
2152
 
2126
2153
  orderedRoots.forEach((rootActivity) => {
2127
2154
  const rootId = rootActivity.id;
@@ -2131,13 +2158,15 @@ const Conversation = WebexPlugin.extend({
2131
2158
  const reactionSelf = getActivityByTypeAndParentId(ACTIVITY_TYPES.REACTION_SELF, rootId);
2132
2159
 
2133
2160
  const latestActivity = edit || rootActivity;
2134
- const finalActivity = this._createParsedServerActivity(latestActivity, {[rootId]: rootActivity});
2161
+ const finalActivity = this._createParsedServerActivity(latestActivity, {
2162
+ [rootId]: rootActivity,
2163
+ });
2135
2164
 
2136
2165
  const fullRoot = {
2137
2166
  id: rootId,
2138
2167
  activity: finalActivity,
2139
2168
  reaction,
2140
- reactionSelf
2169
+ reactionSelf,
2141
2170
  };
2142
2171
 
2143
2172
  const sanitizedFullRoot = sanitizeActivity(fullRoot);
@@ -2159,10 +2188,9 @@ const Conversation = WebexPlugin.extend({
2159
2188
  activityToSearch: search,
2160
2189
  oldestPublishedDate: currentOldestPublishedDate,
2161
2190
  newestPublishedDate: currentNewestPublishedDate,
2162
- batchSize
2191
+ batchSize,
2163
2192
  });
2164
- }
2165
- else {
2193
+ } else {
2166
2194
  return;
2167
2195
  }
2168
2196
  }
@@ -2183,10 +2211,10 @@ const Conversation = WebexPlugin.extend({
2183
2211
  */
2184
2212
 
2185
2213
  /**
2186
- * hashmap of server activities, keyed by id
2187
- * @typedef {object} ActivityHash
2188
- * @property {Object}
2189
- */
2214
+ * hashmap of server activities, keyed by id
2215
+ * @typedef {object} ActivityHash
2216
+ * @property {Object}
2217
+ */
2190
2218
 
2191
2219
  /**
2192
2220
  * extends a given server object with fields that point to their parent activities from the hashmap passed in
@@ -2198,7 +2226,9 @@ const Conversation = WebexPlugin.extend({
2198
2226
  const isOrphan = getIsActivityOrphaned(activity, allActivitiesHash);
2199
2227
 
2200
2228
  if (isOrphan) {
2201
- throw new Error('activity has a parent that cannot be found in allActivitiesHash! please handle this as necessary');
2229
+ throw new Error(
2230
+ 'activity has a parent that cannot be found in allActivitiesHash! please handle this as necessary'
2231
+ );
2202
2232
  }
2203
2233
 
2204
2234
  const activityType = determineActivityType(activity, allActivitiesHash);
@@ -2230,12 +2260,13 @@ const Conversation = WebexPlugin.extend({
2230
2260
  * @returns {Promise<Array<Conversation>>}
2231
2261
  */
2232
2262
  async _list(options) {
2233
- options.qs = Object.assign({
2263
+ options.qs = {
2234
2264
  personRefresh: true,
2235
2265
  uuidEntryFormat: true,
2236
2266
  activitiesLimit: 0,
2237
- participantsLimit: 0
2238
- }, options.qs);
2267
+ participantsLimit: 0,
2268
+ ...options.qs,
2269
+ };
2239
2270
 
2240
2271
  const res = await this.request(options);
2241
2272
 
@@ -2243,8 +2274,7 @@ const Conversation = WebexPlugin.extend({
2243
2274
 
2244
2275
  if (!res.body || !res.body.items || res.body.items.length === 0) {
2245
2276
  list = [];
2246
- }
2247
- else {
2277
+ } else {
2248
2278
  list = res.body.items.slice(0);
2249
2279
  if (last(list).published < list[0].published) {
2250
2280
  list.reverse();
@@ -2263,9 +2293,7 @@ const Conversation = WebexPlugin.extend({
2263
2293
  // This won't get us the exact limit but it will retrieve something
2264
2294
  // from every cluster listed.
2265
2295
  if (options.limit) {
2266
- limit = Math.floor(
2267
- (options.limit.value - list.length) / res.body.additionalUrls.length
2268
- );
2296
+ limit = Math.floor((options.limit.value - list.length) / res.body.additionalUrls.length);
2269
2297
  }
2270
2298
 
2271
2299
  // If the limit is 0 for some reason,
@@ -2274,7 +2302,7 @@ const Conversation = WebexPlugin.extend({
2274
2302
  const results = await Promise.all(
2275
2303
  res.body.additionalUrls.map((host) => {
2276
2304
  const url = `${host}/${options.resource}`;
2277
- const newOptions = Object.assign({}, options, {uri: url, url});
2305
+ const newOptions = {...options, uri: url, url};
2278
2306
 
2279
2307
  if (options.limit) {
2280
2308
  newOptions.qs[newOptions.limit.name] = limit;
@@ -2309,19 +2337,23 @@ const Conversation = WebexPlugin.extend({
2309
2337
  * @returns {Promise<Conversation>}
2310
2338
  */
2311
2339
  _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}))
2340
+ return this.get(
2341
+ defaults({
2342
+ // the use of uniq in Conversation#create guarantees participant[1] will
2343
+ // always be the other user
2344
+ user: params.participants[1],
2345
+ }),
2346
+ Object.assign(options, {includeConvWithDeletedUserUUID: true, includeParticipants: true})
2347
+ )
2317
2348
  .then((conversation) => {
2318
2349
  if (params.comment || params.html) {
2319
- return this.post(conversation, {content: params.html, displayName: params.comment})
2320
- .then((activity) => {
2350
+ return this.post(conversation, {content: params.html, displayName: params.comment}).then(
2351
+ (activity) => {
2321
2352
  conversation.activities.items.push(activity);
2322
2353
 
2323
2354
  return conversation;
2324
- });
2355
+ }
2356
+ );
2325
2357
  }
2326
2358
 
2327
2359
  return conversation;
@@ -2343,17 +2375,15 @@ const Conversation = WebexPlugin.extend({
2343
2375
  _prepareConversationForCreation(params) {
2344
2376
  const payload = {
2345
2377
  activities: {
2346
- items: [
2347
- this.expand('create')
2348
- ]
2378
+ items: [this.expand('create')],
2349
2379
  },
2350
2380
  objectType: 'conversation',
2351
2381
  kmsMessage: {
2352
2382
  method: 'create',
2353
2383
  uri: '/resources',
2354
2384
  userIds: cloneDeep(params.participants),
2355
- keyUris: []
2356
- }
2385
+ keyUris: [],
2386
+ },
2357
2387
  };
2358
2388
 
2359
2389
  if (params.displayName) {
@@ -2365,32 +2395,40 @@ const Conversation = WebexPlugin.extend({
2365
2395
  }
2366
2396
 
2367
2397
  params.participants.forEach((participant) => {
2368
- payload.activities.items.push(this.expand('add', {
2369
- objectType: 'person',
2370
- id: participant
2371
- }));
2398
+ payload.activities.items.push(
2399
+ this.expand('add', {
2400
+ objectType: 'person',
2401
+ id: participant,
2402
+ })
2403
+ );
2372
2404
  });
2373
2405
 
2374
2406
  if (params.comment) {
2375
- payload.activities.items.push(this.expand('post', {
2376
- objectType: 'comment',
2377
- content: params.html,
2378
- displayName: params.comment
2379
- }));
2407
+ payload.activities.items.push(
2408
+ this.expand('post', {
2409
+ objectType: 'comment',
2410
+ content: params.html,
2411
+ displayName: params.comment,
2412
+ })
2413
+ );
2380
2414
  }
2381
2415
 
2382
2416
  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
- }));
2417
+ payload.activities.items.push(
2418
+ this.expand('update', {
2419
+ objectType: 'classification',
2420
+ classificationId: params.classificationId,
2421
+ effectiveDate: params.effectiveDate,
2422
+ })
2423
+ );
2388
2424
  }
2389
2425
 
2390
2426
  if (params.favorite) {
2391
- payload.activities.items.push(this.expand('favorite', {
2392
- objectType: 'conversation'
2393
- }));
2427
+ payload.activities.items.push(
2428
+ this.expand('favorite', {
2429
+ objectType: 'conversation',
2430
+ })
2431
+ );
2394
2432
  }
2395
2433
 
2396
2434
  return payload;
@@ -2406,68 +2444,59 @@ const Conversation = WebexPlugin.extend({
2406
2444
  return Promise.resolve(conversation);
2407
2445
  }
2408
2446
 
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
- }
2447
+ return Promise.all(
2448
+ conversation.participants.items.map((participant) => {
2449
+ // ROOMs or LYRA_SPACEs do not have email addresses, so there's no point attempting to
2450
+ // record their UUIDs.
2451
+ if (participant.type === 'ROOM' || participant.type === 'LYRA_SPACE') {
2452
+ return Promise.resolve();
2453
+ }
2415
2454
 
2416
- return this.webex.internal.user.recordUUID(participant)
2417
- .catch((err) => this.logger.warn('Could not record uuid', err));
2418
- }));
2419
- }
2455
+ return this.webex.internal.user
2456
+ .recordUUID(participant)
2457
+ .catch((err) => this.logger.warn('Could not record uuid', err));
2458
+ })
2459
+ );
2460
+ },
2420
2461
  });
2421
2462
 
2422
- [
2423
- 'favorite',
2424
- 'hide',
2425
- 'lock',
2426
- 'mute',
2427
- 'unfavorite',
2428
- 'unhide',
2429
- 'unlock',
2430
- 'unmute'
2431
- ].forEach((verb) => {
2463
+ ['favorite', 'hide', 'lock', 'mute', 'unfavorite', 'unhide', 'unlock', 'unmute'].forEach((verb) => {
2432
2464
  Conversation.prototype[verb] = function submitSimpleActivity(conversation, activity) {
2433
- const convoWithUrl =
2434
- this.prepareConversation(
2435
- Object.assign(
2436
- {}, conversation, {url: this.getConvoUrl(conversation)}
2437
- )
2438
- );
2465
+ const convoWithUrl = this.prepareConversation({
2466
+ ...conversation,
2467
+ url: this.getConvoUrl(conversation),
2468
+ });
2439
2469
 
2440
2470
  return this.prepare(activity, {
2441
2471
  verb,
2442
2472
  object: convoWithUrl,
2443
- target: convoWithUrl
2444
- })
2445
- .then((a) => this.submit(a));
2473
+ target: convoWithUrl,
2474
+ }).then((a) => this.submit(a));
2446
2475
  };
2447
2476
  });
2448
2477
 
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
- );
2478
+ ['assignModerator', 'unassignModerator'].forEach((verb) => {
2479
+ Conversation.prototype[verb] = function submitModerationChangeActivity(
2480
+ conversation,
2481
+ moderator,
2482
+ activity
2483
+ ) {
2484
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
2458
2485
 
2459
2486
  return Promise.all([
2460
2487
  convoWithUrl,
2461
- moderator ? this.webex.internal.user.asUUID(moderator) : this.webex.internal.device.userId
2488
+ moderator ? this.webex.internal.user.asUUID(moderator) : this.webex.internal.device.userId,
2462
2489
  ])
2463
- .then(([c, userId]) => this.prepare(activity, {
2464
- verb,
2465
- target: this.prepareConversation(c),
2466
- object: {
2467
- id: userId,
2468
- objectType: 'person'
2469
- }
2470
- }))
2490
+ .then(([c, userId]) =>
2491
+ this.prepare(activity, {
2492
+ verb,
2493
+ target: this.prepareConversation(c),
2494
+ object: {
2495
+ id: userId,
2496
+ objectType: 'person',
2497
+ },
2498
+ })
2499
+ )
2471
2500
  .then((a) => this.submit(a));
2472
2501
  };
2473
2502
  });
@@ -2479,56 +2508,44 @@ const Conversation = WebexPlugin.extend({
2479
2508
  * @param {Activity} activity
2480
2509
  * @returns {Promise<Activity>}
2481
2510
  */
2482
- [
2483
- 'setSpaceProperty',
2484
- 'unsetSpaceProperty'
2485
- ].forEach((fnName) => {
2511
+ ['setSpaceProperty', 'unsetSpaceProperty'].forEach((fnName) => {
2486
2512
  const verb = fnName.startsWith('set') ? 'set' : 'unset';
2487
2513
 
2488
- Conversation.prototype[fnName] = function submitSpacePropertyActivity(conversation, tag, activity) {
2514
+ Conversation.prototype[fnName] = function submitSpacePropertyActivity(
2515
+ conversation,
2516
+ tag,
2517
+ activity
2518
+ ) {
2489
2519
  if (!isString(tag)) {
2490
2520
  return Promise.reject(new Error('`tag` must be a string'));
2491
2521
  }
2492
2522
 
2493
- const convoWithUrl =
2494
- Object.assign(
2495
- {}, conversation, {url: this.getConvoUrl(conversation)}
2496
- );
2523
+ const convoWithUrl = {...conversation, url: this.getConvoUrl(conversation)};
2497
2524
 
2498
2525
  return this.prepare(activity, {
2499
2526
  verb,
2500
2527
  target: this.prepareConversation(convoWithUrl),
2501
2528
  object: {
2502
2529
  tags: [tag],
2503
- objectType: 'spaceProperty'
2504
- }
2505
- })
2506
- .then((a) => this.submit(a));
2530
+ objectType: 'spaceProperty',
2531
+ },
2532
+ }).then((a) => this.submit(a));
2507
2533
  };
2508
2534
  });
2509
2535
 
2510
- [
2511
- 'tag',
2512
- 'untag'
2513
- ].forEach((verb) => {
2536
+ ['tag', 'untag'].forEach((verb) => {
2514
2537
  Conversation.prototype[verb] = function submitObjectActivity(conversation, object, activity) {
2515
2538
  if (!isObject(object)) {
2516
2539
  return Promise.reject(new Error('`object` must be an object'));
2517
2540
  }
2518
2541
 
2519
- const c =
2520
- this.prepareConversation(
2521
- Object.assign(
2522
- {}, conversation, {url: this.getConvoUrl(conversation)}
2523
- )
2524
- );
2542
+ const c = this.prepareConversation({...conversation, url: this.getConvoUrl(conversation)});
2525
2543
 
2526
2544
  return this.prepare(activity, {
2527
2545
  verb,
2528
2546
  target: c,
2529
- object: Object.assign(c, object)
2530
- })
2531
- .then((a) => this.submit(a));
2547
+ object: Object.assign(c, object),
2548
+ }).then((a) => this.submit(a));
2532
2549
  };
2533
2550
  });
2534
2551