@webex/plugin-meetings 1.147.1 → 1.149.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.
@@ -57,6 +57,7 @@ import {
57
57
  ONLINE,
58
58
  OFFLINE,
59
59
  PC_BAIL_TIMEOUT,
60
+ PSTN_STATUS,
60
61
  QUALITY_LEVELS,
61
62
  RECORDING_STATE,
62
63
  ROAP_SEQ_PRE,
@@ -710,13 +711,14 @@ export default class Meeting extends StatelessWebexPlugin {
710
711
  */
711
712
  this.floorGrantPending = false;
712
713
  /**
713
- * The latest status of the dial in device (can be "JOINED", "CONNECTED", "LEFT" or "")
714
+ * The latest status of the dial in device (can be "JOINED", "CONNECTED", "LEFT",
715
+ * "TRANSFERRING", "SUCCESS" or "")
714
716
  * @instance
715
717
  * @type {String}
716
718
  * @private
717
719
  * @memberof Meeting
718
720
  */
719
- this.dialInDeviceStatus = '';
721
+ this.dialInDeviceStatus = PSTN_STATUS.UNKNOWN;
720
722
  /**
721
723
  * the url for provisioned device used to dial in
722
724
  * @instance
@@ -725,6 +727,23 @@ export default class Meeting extends StatelessWebexPlugin {
725
727
  * @memberof Meeting
726
728
  */
727
729
  this.dialInUrl = '';
730
+ /**
731
+ * The latest status of the dial out device (can be "JOINED", "CONNECTED", "LEFT",
732
+ * "TRANSFERRING", "SUCCESS" or "")
733
+ * @instance
734
+ * @type {String}
735
+ * @private
736
+ * @memberof Meeting
737
+ */
738
+ this.dialOutDeviceStatus = PSTN_STATUS.UNKNOWN;
739
+ /**
740
+ * the url for provisioned device used to dial out
741
+ * @instance
742
+ * @type {String}
743
+ * @private
744
+ * @memberof Meeting
745
+ */
746
+ this.dialOutUrl = '';
728
747
  /**
729
748
  * @instance
730
749
  * @type {MediaMetrics}
@@ -1028,6 +1047,24 @@ export default class Meeting extends StatelessWebexPlugin {
1028
1047
  };
1029
1048
  }
1030
1049
 
1050
+ const joinRespTxStartAudio = this.getSendingMediaDelayDuration('audio');
1051
+
1052
+ if (joinRespTxStartAudio) {
1053
+ options.audioSetupDelay = {
1054
+ ...options.audioSetupDelay,
1055
+ joinRespTxStart: joinRespTxStartAudio
1056
+ };
1057
+ }
1058
+
1059
+ const joinRespTxStartVideo = this.getSendingMediaDelayDuration('video');
1060
+
1061
+ if (joinRespTxStartVideo) {
1062
+ options.videoSetupDelay = {
1063
+ ...options.videoSetupDelay,
1064
+ joinRespTxStart: joinRespTxStartVideo
1065
+ };
1066
+ }
1067
+
1031
1068
  if (options.type === MQA_STATS.CA_TYPE) {
1032
1069
  payload = Metrics.initMediaPayload(options.event, identifiers, options);
1033
1070
  }
@@ -1144,9 +1181,28 @@ export default class Meeting extends StatelessWebexPlugin {
1144
1181
  pstnUpdate(payload) {
1145
1182
  if (this.locusInfo.self) {
1146
1183
  const dialInPstnDevice = payload.newSelf?.pstnDevices.find((device) => device.url === this.dialInUrl);
1184
+ const dialOutPstnDevice = payload.newSelf?.pstnDevices.find((device) => device.url === this.dialOutUrl);
1185
+ let changed = false;
1147
1186
 
1148
1187
  if (dialInPstnDevice) {
1149
- this.dialInDeviceStatus = dialInPstnDevice.dialingStatus ?? dialInPstnDevice.state;
1188
+ const newStatus = dialInPstnDevice.dialingStatus ?? dialInPstnDevice.state;
1189
+
1190
+ if (newStatus !== this.dialInDeviceStatus) {
1191
+ this.dialInDeviceStatus = newStatus;
1192
+ changed = true;
1193
+ }
1194
+ }
1195
+
1196
+ if (dialOutPstnDevice) {
1197
+ const newStatus = dialOutPstnDevice.dialingStatus ?? dialOutPstnDevice.state;
1198
+
1199
+ if (newStatus !== this.dialOutDeviceStatus) {
1200
+ this.dialOutDeviceStatus = newStatus;
1201
+ changed = true;
1202
+ }
1203
+ }
1204
+
1205
+ if (changed) {
1150
1206
  Trigger.trigger(
1151
1207
  this,
1152
1208
  {
@@ -1157,7 +1213,11 @@ export default class Meeting extends StatelessWebexPlugin {
1157
1213
  {
1158
1214
  dialIn: {
1159
1215
  status: this.dialInDeviceStatus,
1160
- attendeeId: dialInPstnDevice.attendeeId
1216
+ attendeeId: dialInPstnDevice?.attendeeId
1217
+ },
1218
+ dialOut: {
1219
+ status: this.dialOutDeviceStatus,
1220
+ attendeeId: dialOutPstnDevice?.attendeeId
1161
1221
  }
1162
1222
  }
1163
1223
  );
@@ -3313,7 +3373,7 @@ export default class Meeting extends StatelessWebexPlugin {
3313
3373
  /**
3314
3374
  * Use phone for meeting audio
3315
3375
  * @param {String} phoneNumber If provided, it will dial-out using this number. If not provided, dial-in will be used
3316
- * @returns {Promise} Resolves once the dial-in or dial-out request has completed
3376
+ * @returns {Promise} Resolves once the dial-in or dial-out request has completed, or rejects if it failed
3317
3377
  * @public
3318
3378
  * @memberof Meeting
3319
3379
  */
@@ -3322,17 +3382,28 @@ export default class Meeting extends StatelessWebexPlugin {
3322
3382
  return this.dialInPstn();
3323
3383
  }
3324
3384
 
3325
- return Promise.reject(new Error('Dial-out is not supported yet'));
3385
+ return this.dialOutPstn(phoneNumber);
3386
+ }
3387
+
3388
+ /**
3389
+ * Determines if the given pstnStatus is in a state which implies the phone is provisioned
3390
+ * @param {String} pstnStatus
3391
+ * @returns {Boolean}
3392
+ * @private
3393
+ * @memberof Meeting
3394
+ */
3395
+ isPhoneProvisioned(pstnStatus) {
3396
+ return [PSTN_STATUS.JOINED, PSTN_STATUS.CONNECTED, PSTN_STATUS.SUCCESS].includes(pstnStatus);
3326
3397
  }
3327
3398
 
3328
3399
  /**
3329
3400
  * Enable dial-in for audio
3330
- * @returns {Promise} Resolves once the dial-in request has completed
3401
+ * @returns {Promise} Resolves once the dial-in request has completed, or rejects if it failed
3331
3402
  * @private
3332
3403
  * @memberof Meeting
3333
3404
  */
3334
3405
  dialInPstn() {
3335
- if (this.dialInDeviceStatus === 'CONNECTED' || this.dialInDeviceStatus === 'JOINED') return Promise.resolve(); // prevent multiple dial in devices from being provisioned
3406
+ if (this.isPhoneProvisioned(this.dialInDeviceStatus)) return Promise.resolve(); // prevent multiple dial in devices from being provisioned
3336
3407
 
3337
3408
  const {correlationId, locusUrl} = this;
3338
3409
 
@@ -3357,6 +3428,47 @@ export default class Meeting extends StatelessWebexPlugin {
3357
3428
  stack: error.stack
3358
3429
  }
3359
3430
  );
3431
+
3432
+ return Promise.reject(error);
3433
+ });
3434
+ }
3435
+
3436
+ /**
3437
+ * Enable dial-out for audio
3438
+ * @param {String} phoneNumber Phone number to dial out to
3439
+ * @returns {Promise} Resolves once the dial-out request has completed (it doesn't wait for the user to answer the phone), or rejects if it failed
3440
+ * @private
3441
+ * @memberof Meeting
3442
+ */
3443
+ dialOutPstn(phoneNumber) {
3444
+ if (this.isPhoneProvisioned(this.dialOutDeviceStatus)) return Promise.resolve(); // prevent multiple dial out devices from being provisioned
3445
+
3446
+ const {correlationId, locusUrl} = this;
3447
+
3448
+ if (!this.dialOutUrl) this.dialOutUrl = `dialout:///${uuid.v4()}`;
3449
+
3450
+ return this.meetingRequest.dialOut({
3451
+ correlationId,
3452
+ dialOutUrl: this.dialOutUrl,
3453
+ phoneNumber,
3454
+ locusUrl,
3455
+ clientUrl: this.deviceUrl
3456
+ }).then((res) => {
3457
+ this.locusInfo.onFullLocus(res.body.locus);
3458
+ }).catch((error) => {
3459
+ Metrics.sendOperationalMetric(
3460
+ METRICS_OPERATIONAL_MEASURES.ADD_DIAL_OUT_FAILURE,
3461
+ {
3462
+ correlation_id: this.correlationId,
3463
+ dial_out_url: this.dialOutUrl,
3464
+ locus_id: locusUrl.split('/').pop(),
3465
+ client_url: this.deviceUrl,
3466
+ reason: error.error?.message,
3467
+ stack: error.stack
3468
+ }
3469
+ );
3470
+
3471
+ return Promise.reject(error);
3360
3472
  });
3361
3473
  }
3362
3474
 
@@ -3368,13 +3480,14 @@ export default class Meeting extends StatelessWebexPlugin {
3368
3480
  * @returns {Promise}
3369
3481
  */
3370
3482
  disconnectPhoneAudio() {
3371
- if (this.dialInDeviceStatus === 'CONNECTED') {
3372
- return MeetingUtil.leavePstn(this, this.dialInUrl);
3373
- }
3374
-
3375
- // TODO: handle dial out
3376
-
3377
- return Promise.resolve();
3483
+ return Promise.all([
3484
+ this.isPhoneProvisioned(this.dialInDeviceStatus) ?
3485
+ MeetingUtil.disconnectPhoneAudio(this, this.dialInUrl) :
3486
+ Promise.resolve(),
3487
+ this.isPhoneProvisioned(this.dialOutDeviceStatus) ?
3488
+ MeetingUtil.disconnectPhoneAudio(this, this.dialOutUrl) :
3489
+ Promise.resolve()
3490
+ ]);
3378
3491
  }
3379
3492
 
3380
3493
  /**
@@ -4954,4 +5067,32 @@ export default class Meeting extends StatelessWebexPlugin {
4954
5067
 
4955
5068
  return (start && end) ? end - start : undefined;
4956
5069
  }
5070
+
5071
+ /**
5072
+ * @param {string} typeMedia 'audio' or 'video'
5073
+ * @returns {undefined}
5074
+ */
5075
+ setStartSendingMediaDelay(typeMedia) {
5076
+ this[`startSendingMediaDelay${typeMedia}`] = performance.now();
5077
+ this[`endSendingMediaDelay${typeMedia}`] = undefined;
5078
+ }
5079
+
5080
+ /**
5081
+ * @param {string} typeMedia 'audio' or 'video'
5082
+ * @returns {undefined}
5083
+ */
5084
+ setEndSendingMediaDelay(typeMedia) {
5085
+ this[`endSendingMediaDelay${typeMedia}`] = performance.now();
5086
+ }
5087
+
5088
+ /**
5089
+ * @param {string} typeMedia 'audio' or 'video'
5090
+ * @returns {string} duration between join response and first media tx
5091
+ */
5092
+ getSendingMediaDelayDuration(typeMedia) {
5093
+ const start = this[`startSendingMediaDelay${typeMedia}`];
5094
+ const end = this[`endSendingMediaDelay${typeMedia}`];
5095
+
5096
+ return (start && end) ? end - start : undefined;
5097
+ }
4957
5098
  }
@@ -1,9 +1,7 @@
1
1
  import uuid from 'uuid';
2
2
  import {debounce} from 'lodash';
3
3
  import {StatelessWebexPlugin} from '@webex/webex-core';
4
- import {
5
- deviceType
6
- } from '@webex/common';
4
+ import {deviceType} from '@webex/common';
7
5
 
8
6
  import LoggerProxy from '../common/logs/logger-proxy';
9
7
  import {
@@ -20,6 +18,7 @@ import {
20
18
  MEDIA,
21
19
  PARTICIPANT,
22
20
  PROVISIONAL_TYPE_DIAL_IN,
21
+ PROVISIONAL_TYPE_DIAL_OUT,
23
22
  SEND_DTMF_ENDPOINT,
24
23
  _SLIDES_
25
24
  } from '../constants';
@@ -50,7 +49,19 @@ export default class MeetingRequest extends StatelessWebexPlugin {
50
49
  */
51
50
  async joinMeeting(options) {
52
51
  const {
53
- asResourceOccupant, sipUri, meetingNumber, deviceUrl, locusUrl, resourceId, correlationId, ensureConversation, moderator, pin, moveToResource, roapMessage, preferTranscoding
52
+ asResourceOccupant,
53
+ sipUri,
54
+ meetingNumber,
55
+ deviceUrl,
56
+ locusUrl,
57
+ resourceId,
58
+ correlationId,
59
+ ensureConversation,
60
+ moderator,
61
+ pin,
62
+ moveToResource,
63
+ roapMessage,
64
+ preferTranscoding
54
65
  } = options;
55
66
 
56
67
  LoggerProxy.logger.info(
@@ -94,29 +105,16 @@ export default class MeetingRequest extends StatelessWebexPlugin {
94
105
  if (locusUrl) {
95
106
  url = `${locusUrl}/${PARTICIPANT}`;
96
107
  }
97
- else if (meetingNumber) {
98
- try {
99
- await this.webex.internal.services.waitForCatalog('postauth');
100
- url = `${this.webex.internal.services.get('locus')}/${LOCI}/${CALL}`;
101
- body.invitee = {
102
- address: `wbxmn:${meetingNumber}`
103
- };
104
- }
105
- catch (e) {
106
- LoggerProxy.logger.error(`Meeting:request#joinMeeting webex meeting id--> ${e}`);
107
- throw (e);
108
- }
109
- }
110
- else if (sipUri) {
108
+ else if (sipUri || meetingNumber) {
111
109
  try {
112
110
  await this.webex.internal.services.waitForCatalog('postauth');
113
111
  url = `${this.webex.internal.services.get('locus')}/${LOCI}/${CALL}`;
114
112
  body.invitee = {
115
- address: sipUri
113
+ address: sipUri || `wbxmn:${meetingNumber}`
116
114
  };
117
115
  }
118
116
  catch (e) {
119
- LoggerProxy.logger.error(`Meeting:request#joinMeeting sipUrl --> ${e}`);
117
+ LoggerProxy.logger.error(`Meeting:request#joinMeeting ${sipUri ? 'sipUri' : 'meetingNumber'} --> ${e}`);
120
118
  throw (e);
121
119
  }
122
120
  }
@@ -153,7 +151,10 @@ export default class MeetingRequest extends StatelessWebexPlugin {
153
151
  * @private
154
152
  */
155
153
  dialIn({
156
- locusUrl, dialInUrl, clientUrl, correlationId
154
+ locusUrl,
155
+ dialInUrl,
156
+ clientUrl,
157
+ correlationId
157
158
  }) {
158
159
  LoggerProxy.logger.info(
159
160
  'Meeting:request#dialIn --> Provisioning a dial in device',
@@ -182,6 +183,52 @@ export default class MeetingRequest extends StatelessWebexPlugin {
182
183
  });
183
184
  }
184
185
 
186
+ /**
187
+ * Make a network request to add a dial out device
188
+ * @param {Object} options
189
+ * @param {String} options.correlationId
190
+ * @param {String} options.localUrl url for the meeting
191
+ * @param {String} options.dialOutUrl identifier for the to-be provisioned device
192
+ * @param {String} options.phoneNumber phone number to dial out to
193
+ * @param {String} options.clientUrl identifier for the web device
194
+ * @returns {Promise}
195
+ * @private
196
+ */
197
+ dialOut({
198
+ locusUrl,
199
+ dialOutUrl,
200
+ phoneNumber,
201
+ clientUrl,
202
+ correlationId
203
+ }) {
204
+ LoggerProxy.logger.info(
205
+ 'Meeting:request#dialOut --> Provisioning a dial out device',
206
+ correlationId
207
+ );
208
+ const uri = `${locusUrl}/${PARTICIPANT}`;
209
+
210
+ const body = {
211
+ device: {
212
+ deviceType: deviceType.PROVISIONAL,
213
+ provisionalType: PROVISIONAL_TYPE_DIAL_OUT,
214
+ url: dialOutUrl,
215
+ dialoutAddress: phoneNumber,
216
+ clientUrl
217
+ },
218
+ correlationId
219
+ };
220
+
221
+ return this.request({
222
+ method: HTTP_VERBS.POST,
223
+ uri,
224
+ body
225
+ }).catch((err) => {
226
+ LoggerProxy.logger.error(`Meeting:request#dialOut --> Error provisioning a dial out device, error ${err}`);
227
+
228
+ throw err;
229
+ });
230
+ }
231
+
185
232
  /**
186
233
  * Syns the missed delta event
187
234
  * @param {Object} options
@@ -241,21 +288,23 @@ export default class MeetingRequest extends StatelessWebexPlugin {
241
288
  }
242
289
 
243
290
  /**
244
- * Make a network request to make a provisioned pstn device leave the meeting
291
+ * Make a network request to make a provisioned phone leave the meeting
245
292
  * @param {Object} options
246
293
  * @param {String} options.locusUrl
247
- * @param {String} options.selfId
248
- * @param {String} options.deviceUrl
249
- * @param {String} options.resourceId,
294
+ * @param {String} options.phoneUrl
250
295
  * @param {String} options.correlationId
296
+ * @param {String} options.selfId
251
297
  * @returns {Promise}
252
298
  * @private
253
299
  */
254
- leavePstn({
255
- locusUrl, dialInUrl, correlationId, selfId
300
+ disconnectPhoneAudio({
301
+ locusUrl,
302
+ phoneUrl,
303
+ correlationId,
304
+ selfId
256
305
  }) {
257
306
  LoggerProxy.logger.info(
258
- `Meeting:request#leavePstn --> request device ${dialInUrl} to leaving`,
307
+ `Meeting:request#disconnectPhoneAudio --> request phone ${phoneUrl} to leave`,
259
308
  correlationId
260
309
  );
261
310
  const uri = `${locusUrl}/${PARTICIPANT}/${selfId}/${LEAVE}`;
@@ -263,7 +312,7 @@ export default class MeetingRequest extends StatelessWebexPlugin {
263
312
  const body = {
264
313
  device: {
265
314
  deviceType: deviceType.PROVISIONAL,
266
- url: dialInUrl
315
+ url: phoneUrl
267
316
  },
268
317
  correlationId
269
318
  };
@@ -273,7 +322,9 @@ export default class MeetingRequest extends StatelessWebexPlugin {
273
322
  uri,
274
323
  body
275
324
  }).catch((err) => {
276
- LoggerProxy.logger.error(`Meeting:request#leavePstn --> Error when requesting pstn device ${dialInUrl} to leave, error ${err}`);
325
+ LoggerProxy.logger.error(
326
+ `Meeting:request#disconnectPhoneAudio --> Error when requesting phone ${phoneUrl} to leave, error ${err}`
327
+ );
277
328
 
278
329
  throw err;
279
330
  });
@@ -290,7 +341,11 @@ export default class MeetingRequest extends StatelessWebexPlugin {
290
341
  * @returns {Promise}
291
342
  */
292
343
  leaveMeeting({
293
- locusUrl, selfId, deviceUrl: url, resourceId, correlationId
344
+ locusUrl,
345
+ selfId,
346
+ deviceUrl: url,
347
+ resourceId,
348
+ correlationId
294
349
  }) {
295
350
  LoggerProxy.logger.info(
296
351
  'Meeting:request#leaveMeeting --> Leaving a meeting',
@@ -515,7 +570,11 @@ export default class MeetingRequest extends StatelessWebexPlugin {
515
570
  * @returns {Promise}
516
571
  */
517
572
  changeVideoLayout({
518
- locusUrl, deviceUrl, layoutType, main, content
573
+ locusUrl,
574
+ deviceUrl,
575
+ layoutType,
576
+ main,
577
+ content
519
578
  }) {
520
579
  // send main/content renderInfo only if both width and height are specified
521
580
  if (main && (!main.width || !main.height)) {
@@ -134,7 +134,7 @@ MeetingUtil.cleanUp = (meeting) => {
134
134
  .then(() => meeting.roap.stop(meeting.correlationId, meeting.roapSeq));
135
135
  };
136
136
 
137
- MeetingUtil.leavePstn = (meeting, dialInUrl) => {
137
+ MeetingUtil.disconnectPhoneAudio = (meeting, phoneUrl) => {
138
138
  if (meeting.meetingState === FULL_STATE.INACTIVE) {
139
139
  return Promise.reject(new MeetingNotActiveError());
140
140
  }
@@ -143,11 +143,11 @@ MeetingUtil.leavePstn = (meeting, dialInUrl) => {
143
143
  locusUrl: meeting.locusUrl,
144
144
  selfId: meeting.selfId,
145
145
  correlationId: meeting.correlationId,
146
- dialInUrl
146
+ phoneUrl
147
147
  };
148
148
 
149
149
  return meeting.meetingRequest
150
- .leavePstn(options)
150
+ .disconnectPhoneAudio(options)
151
151
  .then((response) => {
152
152
  if (response?.body?.locus) {
153
153
  meeting.locusInfo.onFullLocus(response.body.locus);
@@ -155,7 +155,7 @@ MeetingUtil.leavePstn = (meeting, dialInUrl) => {
155
155
  })
156
156
  .catch((err) => {
157
157
  LoggerProxy.logger.error(
158
- `Meeting:util#leavePstn --> An error occured while trying to leave pstn with an id of ${
158
+ `Meeting:util#disconnectPhoneAudio --> An error occured while disconnecting phone audio in meeting ${
159
159
  meeting.id
160
160
  }, error: ${err}`
161
161
  );
@@ -108,7 +108,10 @@ export default class MeetingInfo {
108
108
  * @memberof MeetingInfo
109
109
  */
110
110
  fetchMeetingInfo(destination, type = null) {
111
- return this.fetchInfoOptions(destination, type).then((options) =>
111
+ return this.fetchInfoOptions(
112
+ MeetingInfoUtil.extractDestination(destination, type),
113
+ type
114
+ ).then((options) =>
112
115
  // fetch meeting info
113
116
  this.requestFetchInfo(options).catch((error) => {
114
117
  // if it failed the first time as meeting link
@@ -35,6 +35,19 @@ import {
35
35
 
36
36
  const MeetingInfoUtil = {};
37
37
 
38
+ MeetingInfoUtil.extractDestination = (destination, type) => {
39
+ let dest = destination;
40
+
41
+ if (type === _LOCUS_ID_) {
42
+ if (!(destination && destination.url)) {
43
+ throw new ParameterError('You cannot create a meeting by locus without a locus.url defined');
44
+ }
45
+ dest = destination.url;
46
+ }
47
+
48
+ return dest;
49
+ };
50
+
38
51
  MeetingInfoUtil.getParsedUrl = (link) => {
39
52
  try {
40
53
  let parsedUrl = url.parse(link);
@@ -116,15 +116,7 @@ export default class Meetings extends WebexPlugin {
116
116
  */
117
117
  constructor(...args) {
118
118
  super(...args);
119
- /**
120
- * The MeetingInfo object to interact with server
121
- * @instance
122
- * @type {Object}
123
- * @private
124
- * @memberof Meetings
125
- */
126
119
 
127
- this.meetingInfo = null;
128
120
  /**
129
121
  * The Meetings request to interact with server
130
122
  * @instance
@@ -381,6 +373,15 @@ export default class Meetings extends WebexPlugin {
381
373
  LoggerConfig.set(this.config.logging);
382
374
  LoggerProxy.set(this.webex.logger);
383
375
 
376
+ /**
377
+ * The MeetingInfo object to interact with server
378
+ * @instance
379
+ * @type {Object}
380
+ * @private
381
+ * @memberof Meetings
382
+ */
383
+ this.meetingInfo = this.config.experimental.enableUnifiedMeetings ? new MeetingInfoV2(this.webex) : new MeetingInfo(this.webex);
384
+
384
385
  Trigger.trigger(
385
386
  this,
386
387
  {
@@ -407,8 +408,6 @@ export default class Meetings extends WebexPlugin {
407
408
  return Promise.reject(new Error('SDK cannot authorize'));
408
409
  }
409
410
 
410
- this.meetingInfo = this.config.experimental.enableUnifiedMeetings ? new MeetingInfoV2(this.webex) : new MeetingInfo(this.webex);
411
-
412
411
 
413
412
  if (this.registered) {
414
413
  LoggerProxy.logger.info('Meetings:index#register --> INFO, Meetings plugin already registered');
@@ -725,7 +724,7 @@ export default class Meetings extends WebexPlugin {
725
724
  this.meetingCollection.set(meeting);
726
725
 
727
726
  try {
728
- const info = await this.meetingInfo.fetchMeetingInfo(MeetingsUtil.extractDestination(destination, type), type);
727
+ const info = await this.meetingInfo.fetchMeetingInfo(destination, type);
729
728
 
730
729
  meeting.parseMeetingInfo(info);
731
730
  meeting.meetingInfo = info ? info.body : null;
@@ -8,7 +8,6 @@ import {
8
8
  CORRELATION_ID,
9
9
  EVENT_TRIGGERS
10
10
  } from '../constants';
11
- import ParameterError from '../common/errors/parameter';
12
11
  import LoggerProxy from '../common/logs/logger-proxy';
13
12
  import Trigger from '../common/events/trigger-proxy';
14
13
 
@@ -32,19 +31,6 @@ import Trigger from '../common/events/trigger-proxy';
32
31
 
33
32
  const MeetingsUtil = {};
34
33
 
35
- MeetingsUtil.extractDestination = (destination, type) => {
36
- let dest = destination;
37
-
38
- if (type === _LOCUS_ID_) {
39
- if (!(destination && destination.url)) {
40
- throw new ParameterError('You cannot create a meeting by locus without a locus.url defined');
41
- }
42
- dest = destination.url;
43
- }
44
-
45
- return dest;
46
- };
47
-
48
34
  MeetingsUtil.getMeetingAddedType = (type) => (type === _LOCUS_ID_ ? _INCOMING_ : _CREATED_);
49
35
 
50
36
  MeetingsUtil.handleRoapMercury = (envelope, meetingCollection) => {
@@ -51,11 +51,15 @@ const triggerTimers = ({event, meeting, data}) => {
51
51
  case eventType.LOCUS_JOIN_RESPONSE:
52
52
  meeting.setStartSetupDelay(mediaType.AUDIO);
53
53
  meeting.setStartSetupDelay(mediaType.VIDEO);
54
+ meeting.setStartSendingMediaDelay(mediaType.AUDIO);
55
+ meeting.setStartSendingMediaDelay(mediaType.VIDEO);
54
56
  break;
55
57
  case eventType.RECEIVING_MEDIA_START:
56
58
  meeting.setEndSetupDelay(data.mediaType);
57
59
  break;
58
-
60
+ case eventType.SENDING_MEDIA_START:
61
+ meeting.setEndSendingMediaDelay(data.mediaType);
62
+ break;
59
63
  default:
60
64
  break;
61
65
  }
@@ -482,10 +482,7 @@ skipInNode(describe)('plugin-meetings', () => {
482
482
  .then((response) => {
483
483
  assert.equal(response[0].result.memberId, alice.meeting.selfId);
484
484
  }),
485
- testUtils.waitForEvents([{scope: bob.meeting.members, event: 'members:update'}])
486
- .then((response) => {
487
- console.log('SCREEN SHARE RESPONSE ', JSON.stringify(response));
488
- }),
485
+ testUtils.waitForEvents([{scope: bob.meeting.members, event: 'members:update'}]),
489
486
  testUtils.waitForEvents([{scope: alice.meeting, event: 'media:ready'}])
490
487
  .then((response) => {
491
488
  console.log('MEDIA:READY event ', response[0].result);
@@ -44,6 +44,15 @@ skipInNode(describe)('plugin-meetings', () => {
44
44
  console.log('CONVERSATION', conversation);
45
45
  space = conversation;
46
46
  })
47
+ .then(async () => {
48
+ const destinationWithType = await alice.webex.meetings.meetingInfo.fetchMeetingInfo(space.url, 'CONVERSATION_URL');
49
+ const destinationNoType = await alice.webex.meetings.meetingInfo.fetchMeetingInfo(space.url);
50
+
51
+ assert.exists(destinationNoType);
52
+ assert.exists(destinationWithType);
53
+ assert.exists(destinationNoType.body.meetingNumber);
54
+ assert.exists(destinationWithType.body.meetingNumber);
55
+ })
47
56
  .then(function aliceStartsMeeting() {
48
57
  return Promise.all([
49
58
  testUtils.delayedPromise(alice.webex.meetings.create(space.url)),
@@ -97,7 +106,7 @@ skipInNode(describe)('plugin-meetings', () => {
97
106
 
98
107
 
99
108
  it('alice adds x user as guest to space meeting', () => Promise.all([
100
- testUtils.delayedPromise(guest.webex.meetings.create(alice.meeting.meetingInfo.uri)),
109
+ testUtils.delayedPromise(guest.webex.meetings.create(alice.meeting.sipUri)),
101
110
  testUtils.waitForEvents([{scope: guest.webex.meetings, event: 'meeting:added', user: guest}])
102
111
  ]).then(() =>
103
112
  Promise.all([