@webex/internal-plugin-conversation 3.0.0-beta.3 → 3.0.0-beta.300

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