@webex/plugin-meetings 3.0.0-beta.39 → 3.0.0-beta.391

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 (393) hide show
  1. package/README.md +58 -8
  2. package/dist/annotation/annotation.types.js +7 -0
  3. package/dist/annotation/annotation.types.js.map +1 -0
  4. package/dist/annotation/constants.js +49 -0
  5. package/dist/annotation/constants.js.map +1 -0
  6. package/dist/annotation/index.js +342 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +94 -15
  9. package/dist/breakouts/breakout.js.map +1 -1
  10. package/dist/breakouts/events.js +45 -0
  11. package/dist/breakouts/events.js.map +1 -0
  12. package/dist/breakouts/index.js +671 -81
  13. package/dist/breakouts/index.js.map +1 -1
  14. package/dist/breakouts/utils.js +45 -1
  15. package/dist/breakouts/utils.js.map +1 -1
  16. package/dist/common/errors/no-meeting-info.js +51 -0
  17. package/dist/common/errors/no-meeting-info.js.map +1 -0
  18. package/dist/common/errors/reclaim-host-role-errors.js +158 -0
  19. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  20. package/dist/common/errors/webex-errors.js +48 -7
  21. package/dist/common/errors/webex-errors.js.map +1 -1
  22. package/dist/common/logs/logger-proxy.js +1 -1
  23. package/dist/common/logs/logger-proxy.js.map +1 -1
  24. package/dist/common/logs/request.js +5 -1
  25. package/dist/common/logs/request.js.map +1 -1
  26. package/dist/common/queue.js +24 -9
  27. package/dist/common/queue.js.map +1 -1
  28. package/dist/config.js +5 -10
  29. package/dist/config.js.map +1 -1
  30. package/dist/constants.js +242 -33
  31. package/dist/constants.js.map +1 -1
  32. package/dist/controls-options-manager/enums.js +14 -2
  33. package/dist/controls-options-manager/enums.js.map +1 -1
  34. package/dist/controls-options-manager/index.js +109 -15
  35. package/dist/controls-options-manager/index.js.map +1 -1
  36. package/dist/controls-options-manager/types.js +7 -0
  37. package/dist/controls-options-manager/types.js.map +1 -0
  38. package/dist/controls-options-manager/util.js +309 -18
  39. package/dist/controls-options-manager/util.js.map +1 -1
  40. package/dist/index.js +110 -2
  41. package/dist/index.js.map +1 -1
  42. package/dist/interceptors/index.js +15 -0
  43. package/dist/interceptors/index.js.map +1 -0
  44. package/dist/interceptors/locusRetry.js +93 -0
  45. package/dist/interceptors/locusRetry.js.map +1 -0
  46. package/dist/interpretation/collection.js +23 -0
  47. package/dist/interpretation/collection.js.map +1 -0
  48. package/dist/interpretation/index.js +380 -0
  49. package/dist/interpretation/index.js.map +1 -0
  50. package/dist/interpretation/siLanguage.js +25 -0
  51. package/dist/interpretation/siLanguage.js.map +1 -0
  52. package/dist/locus-info/controlsUtils.js +91 -2
  53. package/dist/locus-info/controlsUtils.js.map +1 -1
  54. package/dist/locus-info/index.js +386 -62
  55. package/dist/locus-info/index.js.map +1 -1
  56. package/dist/locus-info/infoUtils.js +7 -1
  57. package/dist/locus-info/infoUtils.js.map +1 -1
  58. package/dist/locus-info/mediaSharesUtils.js +71 -1
  59. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  60. package/dist/locus-info/parser.js +249 -72
  61. package/dist/locus-info/parser.js.map +1 -1
  62. package/dist/locus-info/selfUtils.js +89 -14
  63. package/dist/locus-info/selfUtils.js.map +1 -1
  64. package/dist/media/index.js +65 -102
  65. package/dist/media/index.js.map +1 -1
  66. package/dist/media/properties.js +73 -124
  67. package/dist/media/properties.js.map +1 -1
  68. package/dist/mediaQualityMetrics/config.js +135 -330
  69. package/dist/mediaQualityMetrics/config.js.map +1 -1
  70. package/dist/meeting/in-meeting-actions.js +86 -2
  71. package/dist/meeting/in-meeting-actions.js.map +1 -1
  72. package/dist/meeting/index.js +4075 -2827
  73. package/dist/meeting/index.js.map +1 -1
  74. package/dist/meeting/locusMediaRequest.js +292 -0
  75. package/dist/meeting/locusMediaRequest.js.map +1 -0
  76. package/dist/meeting/muteState.js +224 -136
  77. package/dist/meeting/muteState.js.map +1 -1
  78. package/dist/meeting/request.js +177 -152
  79. package/dist/meeting/request.js.map +1 -1
  80. package/dist/meeting/util.js +672 -417
  81. package/dist/meeting/util.js.map +1 -1
  82. package/dist/meeting-info/index.js +73 -7
  83. package/dist/meeting-info/index.js.map +1 -1
  84. package/dist/meeting-info/meeting-info-v2.js +192 -51
  85. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  86. package/dist/meeting-info/util.js +1 -1
  87. package/dist/meeting-info/util.js.map +1 -1
  88. package/dist/meeting-info/utilv2.js +36 -36
  89. package/dist/meeting-info/utilv2.js.map +1 -1
  90. package/dist/meetings/collection.js +39 -0
  91. package/dist/meetings/collection.js.map +1 -1
  92. package/dist/meetings/index.js +484 -119
  93. package/dist/meetings/index.js.map +1 -1
  94. package/dist/meetings/meetings.types.js +7 -0
  95. package/dist/meetings/meetings.types.js.map +1 -0
  96. package/dist/meetings/request.js +2 -0
  97. package/dist/meetings/request.js.map +1 -1
  98. package/dist/meetings/util.js +73 -7
  99. package/dist/meetings/util.js.map +1 -1
  100. package/dist/member/index.js +58 -0
  101. package/dist/member/index.js.map +1 -1
  102. package/dist/member/types.js +25 -0
  103. package/dist/member/types.js.map +1 -0
  104. package/dist/member/util.js +132 -25
  105. package/dist/member/util.js.map +1 -1
  106. package/dist/members/collection.js +10 -0
  107. package/dist/members/collection.js.map +1 -1
  108. package/dist/members/index.js +102 -6
  109. package/dist/members/index.js.map +1 -1
  110. package/dist/members/request.js +106 -38
  111. package/dist/members/request.js.map +1 -1
  112. package/dist/members/types.js +15 -0
  113. package/dist/members/types.js.map +1 -0
  114. package/dist/members/util.js +326 -232
  115. package/dist/members/util.js.map +1 -1
  116. package/dist/metrics/constants.js +18 -1
  117. package/dist/metrics/constants.js.map +1 -1
  118. package/dist/metrics/index.js +1 -446
  119. package/dist/metrics/index.js.map +1 -1
  120. package/dist/multistream/mediaRequestManager.js +223 -32
  121. package/dist/multistream/mediaRequestManager.js.map +1 -1
  122. package/dist/multistream/receiveSlot.js +10 -0
  123. package/dist/multistream/receiveSlot.js.map +1 -1
  124. package/dist/multistream/receiveSlotManager.js +39 -36
  125. package/dist/multistream/receiveSlotManager.js.map +1 -1
  126. package/dist/multistream/remoteMedia.js +3 -1
  127. package/dist/multistream/remoteMedia.js.map +1 -1
  128. package/dist/multistream/remoteMediaGroup.js +76 -5
  129. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  130. package/dist/multistream/remoteMediaManager.js +366 -104
  131. package/dist/multistream/remoteMediaManager.js.map +1 -1
  132. package/dist/multistream/sendSlotManager.js +255 -0
  133. package/dist/multistream/sendSlotManager.js.map +1 -0
  134. package/dist/reachability/clusterReachability.js +356 -0
  135. package/dist/reachability/clusterReachability.js.map +1 -0
  136. package/dist/reachability/index.js +263 -390
  137. package/dist/reachability/index.js.map +1 -1
  138. package/dist/reachability/request.js +6 -4
  139. package/dist/reachability/request.js.map +1 -1
  140. package/dist/reachability/util.js +29 -0
  141. package/dist/reachability/util.js.map +1 -0
  142. package/dist/reconnection-manager/index.js +266 -202
  143. package/dist/reconnection-manager/index.js.map +1 -1
  144. package/dist/recording-controller/index.js +21 -2
  145. package/dist/recording-controller/index.js.map +1 -1
  146. package/dist/recording-controller/util.js +9 -8
  147. package/dist/recording-controller/util.js.map +1 -1
  148. package/dist/roap/index.js +51 -28
  149. package/dist/roap/index.js.map +1 -1
  150. package/dist/roap/request.js +48 -64
  151. package/dist/roap/request.js.map +1 -1
  152. package/dist/roap/turnDiscovery.js +220 -70
  153. package/dist/roap/turnDiscovery.js.map +1 -1
  154. package/dist/rtcMetrics/constants.js +12 -0
  155. package/dist/rtcMetrics/constants.js.map +1 -0
  156. package/dist/rtcMetrics/index.js +179 -0
  157. package/dist/rtcMetrics/index.js.map +1 -0
  158. package/dist/statsAnalyzer/index.js +357 -295
  159. package/dist/statsAnalyzer/index.js.map +1 -1
  160. package/dist/statsAnalyzer/mqaUtil.js +296 -156
  161. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  162. package/dist/types/annotation/annotation.types.d.ts +42 -0
  163. package/dist/types/annotation/constants.d.ts +31 -0
  164. package/dist/types/annotation/index.d.ts +117 -0
  165. package/dist/types/breakouts/events.d.ts +8 -0
  166. package/dist/types/breakouts/utils.d.ts +14 -0
  167. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  168. package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
  169. package/dist/types/common/errors/webex-errors.d.ts +25 -1
  170. package/dist/types/common/logs/request.d.ts +2 -0
  171. package/dist/types/common/queue.d.ts +9 -7
  172. package/dist/types/config.d.ts +2 -7
  173. package/dist/types/constants.d.ts +203 -31
  174. package/dist/types/controls-options-manager/enums.d.ts +11 -1
  175. package/dist/types/controls-options-manager/index.d.ts +17 -1
  176. package/dist/types/controls-options-manager/types.d.ts +43 -0
  177. package/dist/types/controls-options-manager/util.d.ts +1 -7
  178. package/dist/types/index.d.ts +6 -5
  179. package/dist/types/interceptors/index.d.ts +2 -0
  180. package/dist/types/interceptors/locusRetry.d.ts +27 -0
  181. package/dist/types/interpretation/collection.d.ts +5 -0
  182. package/dist/types/interpretation/index.d.ts +5 -0
  183. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  184. package/dist/types/locus-info/index.d.ts +57 -4
  185. package/dist/types/locus-info/parser.d.ts +66 -6
  186. package/dist/types/media/index.d.ts +2 -0
  187. package/dist/types/media/properties.d.ts +34 -49
  188. package/dist/types/mediaQualityMetrics/config.d.ts +99 -223
  189. package/dist/types/meeting/in-meeting-actions.d.ts +86 -2
  190. package/dist/types/meeting/index.d.ts +567 -496
  191. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  192. package/dist/types/meeting/muteState.d.ts +93 -25
  193. package/dist/types/meeting/request.d.ts +64 -43
  194. package/dist/types/meeting/util.d.ts +117 -1
  195. package/dist/types/meeting-info/index.d.ts +13 -1
  196. package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
  197. package/dist/types/meetings/collection.d.ts +17 -0
  198. package/dist/types/meetings/index.d.ts +113 -21
  199. package/dist/types/meetings/meetings.types.d.ts +4 -0
  200. package/dist/types/member/index.d.ts +14 -0
  201. package/dist/types/member/types.d.ts +32 -0
  202. package/dist/types/members/collection.d.ts +5 -0
  203. package/dist/types/members/index.d.ts +35 -2
  204. package/dist/types/members/request.d.ts +73 -9
  205. package/dist/types/members/types.d.ts +25 -0
  206. package/dist/types/members/util.d.ts +214 -1
  207. package/dist/types/metrics/constants.d.ts +17 -0
  208. package/dist/types/metrics/index.d.ts +4 -111
  209. package/dist/types/multistream/mediaRequestManager.d.ts +72 -3
  210. package/dist/types/multistream/receiveSlot.d.ts +7 -3
  211. package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
  212. package/dist/types/multistream/remoteMedia.d.ts +3 -31
  213. package/dist/types/multistream/remoteMediaGroup.d.ts +2 -9
  214. package/dist/types/multistream/remoteMediaManager.d.ts +62 -2
  215. package/dist/types/multistream/sendSlotManager.d.ts +70 -0
  216. package/dist/types/reachability/clusterReachability.d.ts +109 -0
  217. package/dist/types/reachability/index.d.ts +60 -95
  218. package/dist/types/reachability/request.d.ts +3 -1
  219. package/dist/types/reachability/util.d.ts +8 -0
  220. package/dist/types/reconnection-manager/index.d.ts +19 -0
  221. package/dist/types/recording-controller/index.d.ts +15 -1
  222. package/dist/types/recording-controller/util.d.ts +5 -4
  223. package/dist/types/roap/index.d.ts +2 -1
  224. package/dist/types/roap/request.d.ts +9 -8
  225. package/dist/types/roap/turnDiscovery.d.ts +39 -5
  226. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  227. package/dist/types/rtcMetrics/index.d.ts +61 -0
  228. package/dist/types/statsAnalyzer/index.d.ts +34 -12
  229. package/dist/types/statsAnalyzer/mqaUtil.d.ts +28 -4
  230. package/dist/types/webinar/collection.d.ts +16 -0
  231. package/dist/types/webinar/index.d.ts +5 -0
  232. package/dist/webinar/collection.js +44 -0
  233. package/dist/webinar/collection.js.map +1 -0
  234. package/dist/webinar/index.js +69 -0
  235. package/dist/webinar/index.js.map +1 -0
  236. package/package.json +22 -19
  237. package/src/annotation/annotation.types.ts +50 -0
  238. package/src/annotation/constants.ts +36 -0
  239. package/src/annotation/index.ts +328 -0
  240. package/src/breakouts/README.md +35 -11
  241. package/src/breakouts/breakout.ts +67 -9
  242. package/src/breakouts/events.ts +56 -0
  243. package/src/breakouts/index.ts +558 -59
  244. package/src/breakouts/utils.ts +42 -0
  245. package/src/common/errors/no-meeting-info.ts +24 -0
  246. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  247. package/src/common/errors/webex-errors.ts +44 -2
  248. package/src/common/logs/logger-proxy.ts +1 -1
  249. package/src/common/logs/request.ts +5 -1
  250. package/src/common/queue.ts +22 -8
  251. package/src/config.ts +4 -9
  252. package/src/constants.ts +229 -21
  253. package/src/controls-options-manager/enums.ts +12 -0
  254. package/src/controls-options-manager/index.ts +116 -21
  255. package/src/controls-options-manager/types.ts +59 -0
  256. package/src/controls-options-manager/util.ts +294 -14
  257. package/src/index.ts +44 -0
  258. package/src/interceptors/index.ts +3 -0
  259. package/src/interceptors/locusRetry.ts +67 -0
  260. package/src/interpretation/README.md +60 -0
  261. package/src/interpretation/collection.ts +19 -0
  262. package/src/interpretation/index.ts +349 -0
  263. package/src/interpretation/siLanguage.ts +18 -0
  264. package/src/locus-info/controlsUtils.ts +108 -0
  265. package/src/locus-info/index.ts +417 -59
  266. package/src/locus-info/infoUtils.ts +10 -2
  267. package/src/locus-info/mediaSharesUtils.ts +80 -0
  268. package/src/locus-info/parser.ts +258 -47
  269. package/src/locus-info/selfUtils.ts +81 -5
  270. package/src/media/index.ts +100 -108
  271. package/src/media/properties.ts +88 -117
  272. package/src/mediaQualityMetrics/config.ts +103 -238
  273. package/src/meeting/in-meeting-actions.ts +171 -3
  274. package/src/meeting/index.ts +3411 -2435
  275. package/src/meeting/locusMediaRequest.ts +313 -0
  276. package/src/meeting/muteState.ts +223 -136
  277. package/src/meeting/request.ts +155 -120
  278. package/src/meeting/util.ts +685 -395
  279. package/src/meeting-info/index.ts +81 -8
  280. package/src/meeting-info/meeting-info-v2.ts +170 -14
  281. package/src/meeting-info/util.ts +1 -1
  282. package/src/meeting-info/utilv2.ts +23 -23
  283. package/src/meetings/collection.ts +33 -0
  284. package/src/meetings/index.ts +507 -127
  285. package/src/meetings/meetings.types.ts +12 -0
  286. package/src/meetings/request.ts +2 -0
  287. package/src/meetings/util.ts +81 -12
  288. package/src/member/index.ts +58 -0
  289. package/src/member/types.ts +38 -0
  290. package/src/member/util.ts +141 -25
  291. package/src/members/collection.ts +8 -0
  292. package/src/members/index.ts +134 -8
  293. package/src/members/request.ts +97 -17
  294. package/src/members/types.ts +29 -0
  295. package/src/members/util.ts +333 -240
  296. package/src/metrics/constants.ts +17 -0
  297. package/src/metrics/index.ts +1 -469
  298. package/src/multistream/mediaRequestManager.ts +271 -56
  299. package/src/multistream/receiveSlot.ts +11 -4
  300. package/src/multistream/receiveSlotManager.ts +34 -24
  301. package/src/multistream/remoteMedia.ts +5 -3
  302. package/src/multistream/remoteMediaGroup.ts +78 -0
  303. package/src/multistream/remoteMediaManager.ts +248 -44
  304. package/src/multistream/sendSlotManager.ts +199 -0
  305. package/src/reachability/clusterReachability.ts +320 -0
  306. package/src/reachability/index.ts +229 -346
  307. package/src/reachability/request.ts +8 -4
  308. package/src/reachability/util.ts +24 -0
  309. package/src/reconnection-manager/index.ts +128 -97
  310. package/src/recording-controller/index.ts +20 -3
  311. package/src/recording-controller/util.ts +26 -9
  312. package/src/roap/index.ts +52 -23
  313. package/src/roap/request.ts +48 -67
  314. package/src/roap/turnDiscovery.ts +147 -49
  315. package/src/rtcMetrics/constants.ts +3 -0
  316. package/src/rtcMetrics/index.ts +166 -0
  317. package/src/statsAnalyzer/index.ts +457 -416
  318. package/src/statsAnalyzer/mqaUtil.ts +317 -170
  319. package/src/webinar/collection.ts +31 -0
  320. package/src/webinar/index.ts +62 -0
  321. package/test/integration/spec/converged-space-meetings.js +60 -3
  322. package/test/integration/spec/journey.js +320 -261
  323. package/test/integration/spec/space-meeting.js +76 -3
  324. package/test/unit/spec/annotation/index.ts +418 -0
  325. package/test/unit/spec/breakouts/breakout.ts +118 -28
  326. package/test/unit/spec/breakouts/events.ts +89 -0
  327. package/test/unit/spec/breakouts/index.ts +1349 -114
  328. package/test/unit/spec/breakouts/utils.js +52 -1
  329. package/test/unit/spec/common/queue.js +31 -2
  330. package/test/unit/spec/controls-options-manager/index.js +163 -0
  331. package/test/unit/spec/controls-options-manager/util.js +576 -60
  332. package/test/unit/spec/fixture/locus.js +1 -0
  333. package/test/unit/spec/interceptors/locusRetry.ts +131 -0
  334. package/test/unit/spec/interpretation/collection.ts +15 -0
  335. package/test/unit/spec/interpretation/index.ts +625 -0
  336. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  337. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  338. package/test/unit/spec/locus-info/index.js +1363 -37
  339. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  340. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  341. package/test/unit/spec/locus-info/mediaSharesUtils.ts +41 -0
  342. package/test/unit/spec/locus-info/parser.js +116 -35
  343. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  344. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  345. package/test/unit/spec/media/index.ts +173 -81
  346. package/test/unit/spec/media/properties.ts +2 -2
  347. package/test/unit/spec/meeting/in-meeting-actions.ts +85 -3
  348. package/test/unit/spec/meeting/index.js +6821 -2172
  349. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  350. package/test/unit/spec/meeting/muteState.js +402 -212
  351. package/test/unit/spec/meeting/request.js +473 -54
  352. package/test/unit/spec/meeting/utils.js +773 -67
  353. package/test/unit/spec/meeting-info/index.js +300 -0
  354. package/test/unit/spec/meeting-info/meetinginfov2.js +526 -5
  355. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  356. package/test/unit/spec/meetings/collection.js +26 -0
  357. package/test/unit/spec/meetings/index.js +1415 -213
  358. package/test/unit/spec/meetings/utils.js +229 -2
  359. package/test/unit/spec/member/index.js +61 -6
  360. package/test/unit/spec/member/util.js +510 -34
  361. package/test/unit/spec/members/index.js +432 -1
  362. package/test/unit/spec/members/request.js +206 -27
  363. package/test/unit/spec/members/utils.js +210 -0
  364. package/test/unit/spec/metrics/index.js +1 -50
  365. package/test/unit/spec/multistream/mediaRequestManager.ts +781 -114
  366. package/test/unit/spec/multistream/receiveSlot.ts +9 -1
  367. package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
  368. package/test/unit/spec/multistream/remoteMedia.ts +2 -0
  369. package/test/unit/spec/multistream/remoteMediaGroup.ts +345 -0
  370. package/test/unit/spec/multistream/remoteMediaManager.ts +525 -0
  371. package/test/unit/spec/multistream/sendSlotManager.ts +274 -0
  372. package/test/unit/spec/reachability/clusterReachability.ts +279 -0
  373. package/test/unit/spec/reachability/index.ts +551 -14
  374. package/test/unit/spec/reachability/request.js +3 -1
  375. package/test/unit/spec/reachability/util.ts +40 -0
  376. package/test/unit/spec/reconnection-manager/index.js +171 -11
  377. package/test/unit/spec/recording-controller/index.js +294 -218
  378. package/test/unit/spec/recording-controller/util.js +223 -96
  379. package/test/unit/spec/roap/index.ts +180 -83
  380. package/test/unit/spec/roap/request.ts +100 -62
  381. package/test/unit/spec/roap/turnDiscovery.ts +388 -96
  382. package/test/unit/spec/rtcMetrics/index.ts +122 -0
  383. package/test/unit/spec/stats-analyzer/index.js +1252 -12
  384. package/test/unit/spec/webinar/collection.ts +13 -0
  385. package/test/unit/spec/webinar/index.ts +60 -0
  386. package/test/utils/integrationTestUtils.js +46 -0
  387. package/test/utils/testUtils.js +0 -57
  388. package/test/utils/webex-test-users.js +12 -4
  389. package/dist/metrics/config.js +0 -289
  390. package/dist/metrics/config.js.map +0 -1
  391. package/dist/types/metrics/config.d.ts +0 -169
  392. package/src/index.js +0 -18
  393. package/src/metrics/config.ts +0 -485
@@ -2,14 +2,16 @@
2
2
 
3
3
  import '@webex/internal-plugin-mercury';
4
4
  import '@webex/internal-plugin-conversation';
5
+ import '@webex/internal-plugin-metrics';
5
6
  // @ts-ignore
6
7
  import {WebexPlugin} from '@webex/webex-core';
7
8
  import {setLogger} from '@webex/internal-media-core';
8
9
 
10
+ import * as mediaHelpersModule from '@webex/media-helpers';
11
+
9
12
  import 'webrtc-adapter';
10
13
 
11
14
  import Metrics from '../metrics';
12
- import {trigger, eventType} from '../metrics/config';
13
15
  import LoggerConfig from '../common/logs/logger-config';
14
16
  import StaticConfig from '../common/config';
15
17
  import LoggerProxy from '../common/logs/logger-proxy';
@@ -40,11 +42,14 @@ import {
40
42
  MEETING_REMOVED_REASON,
41
43
  _CONVERSATION_URL_,
42
44
  CONVERSATION_URL,
45
+ MEETINGNUMBER,
46
+ _JOINED_,
47
+ _MOVED_,
43
48
  } from '../constants';
44
49
  import BEHAVIORAL_METRICS from '../metrics/constants';
45
50
  import MeetingInfo from '../meeting-info';
46
51
  import MeetingInfoV2 from '../meeting-info/meeting-info-v2';
47
- import Meeting from '../meeting';
52
+ import Meeting, {CallStateForMetrics} from '../meeting';
48
53
  import PersonalMeetingRoom from '../personal-meeting-room';
49
54
  import Reachability from '../reachability';
50
55
  import Request from './request';
@@ -53,6 +58,10 @@ import CaptchaError from '../common/errors/captcha-error';
53
58
 
54
59
  import MeetingCollection from './collection';
55
60
  import MeetingsUtil from './util';
61
+ import PermissionError from '../common/errors/permission';
62
+ import {INoiseReductionEffect, IVirtualBackgroundEffect} from './meetings.types';
63
+ import {SpaceIDDeprecatedError} from '../common/errors/webex-errors';
64
+ import NoMeetingInfoError from '../common/errors/no-meeting-info';
56
65
 
57
66
  let mediaLogger;
58
67
 
@@ -139,12 +148,13 @@ export default class Meetings extends WebexPlugin {
139
148
  meetingCollection: any;
140
149
  personalMeetingRoom: any;
141
150
  preferredWebexSite: any;
142
- reachability: any;
151
+ reachability: Reachability;
143
152
  registered: any;
144
153
  request: any;
145
154
  geoHintInfo: any;
146
155
  meetingInfo: any;
147
-
156
+ mediaHelpers: any;
157
+ breakoutLocusForHandleLater: any;
148
158
  namespace = MEETINGS;
149
159
 
150
160
  /**
@@ -156,6 +166,17 @@ export default class Meetings extends WebexPlugin {
156
166
  constructor(...args) {
157
167
  super(...args);
158
168
 
169
+ /**
170
+ * The webrtc-core media helpers. This is a temporary solution required for the SDK sample app
171
+ * to be able to call media helper functions.
172
+ *
173
+ * @instance
174
+ * @type {Object}
175
+ * @private
176
+ * @memberof Meetings
177
+ */
178
+ this.mediaHelpers = mediaHelpersModule;
179
+
159
180
  /**
160
181
  * The Meetings request to interact with server
161
182
  * @instance
@@ -183,15 +204,17 @@ export default class Meetings extends WebexPlugin {
183
204
  * @memberof Meetings
184
205
  */
185
206
  this.personalMeetingRoom = null;
207
+
186
208
  /**
187
- * The Reachability object to interact with server, starts as null until {@link Meeting#setReachability} is called
209
+ * The Reachability object to interact with server
188
210
  * starts as null
189
211
  * @instance
190
212
  * @type {Object}
191
213
  * @private
192
214
  * @memberof Meetings
193
215
  */
194
- this.reachability = null;
216
+ // @ts-ignore
217
+ this.reachability = new Reachability(this.webex);
195
218
 
196
219
  /**
197
220
  * If the meetings plugin has been registered and listening via {@link Meetings#register}
@@ -221,30 +244,137 @@ export default class Meetings extends WebexPlugin {
221
244
  */
222
245
  this.media = {
223
246
  getUserMedia: Media.getUserMedia,
224
- getSupportedDevice: Media.getSupportedDevice,
225
247
  };
226
248
 
227
249
  this.onReady();
228
250
  }
229
251
 
230
252
  /**
231
- * handle locus events and takes meeting actions with them as they come in
253
+ * check whether you need to handle this main session's locus data or not
254
+ * @param {Object} meeting current meeting data
255
+ * @param {Object} newLocus new locus data
256
+ * @returns {boolean}
257
+ * @private
258
+ * @memberof Meetings
259
+ */
260
+ private isNeedHandleMainLocus(meeting: any, newLocus: any) {
261
+ const breakoutUrl = newLocus.controls?.breakout?.url;
262
+ const breakoutLocus = this.meetingCollection.getActiveBreakoutLocus(breakoutUrl);
263
+
264
+ const isSelfJoined = newLocus?.self?.state === _JOINED_;
265
+ const isSelfMoved = newLocus?.self?.state === _LEFT_ && newLocus?.self?.reason === _MOVED_;
266
+ // @ts-ignore
267
+ const deviceFromNewLocus = MeetingsUtil.getThisDevice(newLocus, this.webex.internal.device.url);
268
+ const isResourceMovedOnThisDevice =
269
+ deviceFromNewLocus?.state === _LEFT_ && deviceFromNewLocus?.reason === _MOVED_;
270
+
271
+ const isNewLocusJoinThisDevice = MeetingsUtil.joinedOnThisDevice(
272
+ meeting,
273
+ newLocus,
274
+ // @ts-ignore
275
+ this.webex.internal.device.url
276
+ );
277
+ const isBreakoutLocusJoinThisDevice =
278
+ breakoutLocus?.joinedWith?.correlationId &&
279
+ breakoutLocus.joinedWith.correlationId === meeting?.correlationId;
280
+
281
+ if (isSelfJoined && isNewLocusJoinThisDevice) {
282
+ LoggerProxy.logger.log(
283
+ 'Meetings:index#isNeedHandleMainLocus --> self this device shown as JOINED in the main session'
284
+ );
285
+ if (breakoutLocus?.joinedWith && deviceFromNewLocus) {
286
+ const breakoutReplaceAt =
287
+ breakoutLocus.joinedWith.replaces?.length > 0
288
+ ? breakoutLocus.joinedWith.replaces[0].replaceAt
289
+ : '';
290
+ const newLocusReplaceAt =
291
+ deviceFromNewLocus.replaces?.length > 0 ? deviceFromNewLocus.replaces[0].replaceAt : '';
292
+ if (breakoutReplaceAt && newLocusReplaceAt && breakoutReplaceAt > newLocusReplaceAt) {
293
+ LoggerProxy.logger.log(
294
+ `Meetings:index#isNeedHandleMainLocus --> this is expired main joined status locus_dto replacedAt ${newLocusReplaceAt} bo replacedAt ${breakoutReplaceAt}`
295
+ );
296
+
297
+ return false;
298
+ }
299
+ }
300
+
301
+ return true;
302
+ }
303
+ if (isBreakoutLocusJoinThisDevice) {
304
+ LoggerProxy.logger.log(
305
+ `Meetings:index#isNeedHandleMainLocus --> there is active breakout session and joined on this device, and don't need to handle main session: ${breakoutUrl}`
306
+ );
307
+
308
+ return false;
309
+ }
310
+ if (isSelfMoved && (newLocus?.self?.removed || isResourceMovedOnThisDevice)) {
311
+ LoggerProxy.logger.log(
312
+ 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
313
+ );
314
+
315
+ return false;
316
+ }
317
+ if (isSelfJoined && isResourceMovedOnThisDevice) {
318
+ LoggerProxy.logger.log(
319
+ 'Meetings:index#isNeedHandleMainLocus --> self device left&moved in main locus with self joined status, not need to handle'
320
+ );
321
+
322
+ return false;
323
+ }
324
+ LoggerProxy.logger.log(
325
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
326
+ );
327
+
328
+ return true;
329
+ }
330
+
331
+ /**
332
+ * check whether you need to handle this locus data or not
333
+ * @param {Object} meeting old locus data
334
+ * @param {Object} newLocus new locus data
335
+ * @returns {boolean}
336
+ * @private
337
+ * @memberof Meetings
338
+ */
339
+ private isNeedHandleLocusDTO(meeting: any, newLocus: any) {
340
+ if (newLocus) {
341
+ const isNewLocusAsBreakout = MeetingsUtil.isBreakoutLocusDTO(newLocus);
342
+ const isSelfMoved = newLocus?.self?.state === _LEFT_ && newLocus?.self?.reason === _MOVED_;
343
+ if (!meeting) {
344
+ if (isNewLocusAsBreakout) {
345
+ LoggerProxy.logger.log(
346
+ `Meetings:index#isNeedHandleLocusDTO --> the first breakout session locusDTO active status: ${newLocus.fullState?.active}`
347
+ );
348
+
349
+ return newLocus.self?.state === _JOINED_;
350
+ }
351
+
352
+ return this.isNeedHandleMainLocus(meeting, newLocus);
353
+ }
354
+ if (!isNewLocusAsBreakout) {
355
+ return this.isNeedHandleMainLocus(meeting, newLocus);
356
+ }
357
+
358
+ return !isSelfMoved;
359
+ }
360
+
361
+ return true;
362
+ }
363
+
364
+ /**
365
+ * get corresponding meeting object by locus data
232
366
  * @param {Object} data a locus event
233
367
  * @param {String} data.locusUrl
234
368
  * @param {Object} data.locus
235
- * @param {Boolean} useRandomDelayForInfo whether a random delay should be added to fetching meeting info
236
- * @param {String} data.eventType
237
- * @returns {undefined}
369
+ * @returns {Object}
238
370
  * @private
239
371
  * @memberof Meetings
240
372
  */
241
- private handleLocusEvent(data: {locusUrl: string; locus: any}, useRandomDelayForInfo = false) {
242
- let meeting = null;
243
-
373
+ getCorrespondingMeetingByLocus(data) {
244
374
  // getting meeting by correlationId. This will happen for the new event
245
375
  // Either the locus
246
376
  // TODO : Add check for the callBack Address
247
- meeting =
377
+ return (
248
378
  this.meetingCollection.getByKey(LOCUS_URL, data.locusUrl) ||
249
379
  // @ts-ignore
250
380
  this.meetingCollection.getByKey(
@@ -260,7 +390,24 @@ export default class Meetings extends WebexPlugin {
260
390
  ) ||
261
391
  (data.locus.info?.isUnifiedSpaceMeeting
262
392
  ? undefined
263
- : this.meetingCollection.getByKey(CONVERSATION_URL, data.locus.conversationUrl));
393
+ : this.meetingCollection.getByKey(CONVERSATION_URL, data.locus.conversationUrl)) ||
394
+ this.meetingCollection.getByKey(MEETINGNUMBER, data.locus?.info?.webExMeetingId)
395
+ );
396
+ }
397
+
398
+ /**
399
+ * handle locus events and takes meeting actions with them as they come in
400
+ * @param {Object} data a locus event
401
+ * @param {String} data.locusUrl
402
+ * @param {Object} data.locus
403
+ * @param {Boolean} useRandomDelayForInfo whether a random delay should be added to fetching meeting info
404
+ * @param {String} data.eventType
405
+ * @returns {undefined}
406
+ * @private
407
+ * @memberof Meetings
408
+ */
409
+ private handleLocusEvent(data: {locusUrl: string; locus: any}, useRandomDelayForInfo = false) {
410
+ let meeting = this.getCorrespondingMeetingByLocus(data);
264
411
 
265
412
  // Special case when locus has got replaced, This only happend once if a replace locus exists
266
413
  // https://sqbu-github.cisco.com/WebExSquared/locus/wiki/Locus-changing-mid-call
@@ -273,6 +420,16 @@ export default class Meetings extends WebexPlugin {
273
420
  );
274
421
  }
275
422
 
423
+ if (meeting && !MeetingsUtil.isBreakoutLocusDTO(data.locus)) {
424
+ meeting.locusInfo.updateMainSessionLocusCache(data.locus);
425
+ }
426
+ if (!this.isNeedHandleLocusDTO(meeting, data.locus)) {
427
+ LoggerProxy.logger.log(
428
+ `Meetings:index#handleLocusEvent --> doesn't need to process locus event`
429
+ );
430
+
431
+ return;
432
+ }
276
433
  if (!meeting) {
277
434
  // TODO: create meeting when we get a meeting object
278
435
  // const checkForEnded = (locus) => {
@@ -329,6 +486,7 @@ export default class Meetings extends WebexPlugin {
329
486
 
330
487
  // It's a new meeting so initialize the locus data
331
488
  meeting.locusInfo.initialSetup(data.locus);
489
+ this.checkHandleBreakoutLocus(data.locus);
332
490
  })
333
491
  .catch((e) => {
334
492
  LoggerProxy.logger.error(e);
@@ -338,10 +496,15 @@ export default class Meetings extends WebexPlugin {
338
496
  // because the other user left so before sending 'added' event make sure it exists in the collection
339
497
 
340
498
  if (this.getMeetingByType(_ID_, meeting.id)) {
341
- Metrics.postEvent({
342
- event: eventType.REMOTE_STARTED,
343
- meeting,
344
- data: {trigger: trigger.MERCURY_EVENT},
499
+ // @ts-ignore
500
+ this.webex.internal.newMetrics.submitClientEvent({
501
+ name: 'client.call.remote-started',
502
+ payload: {
503
+ trigger: 'mercury-event',
504
+ },
505
+ options: {
506
+ meetingId: meeting.id,
507
+ },
345
508
  });
346
509
  Trigger.trigger(
347
510
  this,
@@ -421,7 +584,7 @@ export default class Meetings extends WebexPlugin {
421
584
 
422
585
  // @ts-ignore
423
586
  this.webex.internal.mercury.on(ONLINE, () => {
424
- this.syncMeetings();
587
+ this.syncMeetings({keepOnlyLocusMeetings: false});
425
588
  });
426
589
 
427
590
  // @ts-ignore
@@ -494,7 +657,7 @@ export default class Meetings extends WebexPlugin {
494
657
 
495
658
  MeetingsUtil.checkH264Support({disableNotifications: true});
496
659
  // @ts-ignore
497
- Metrics.initialSetup(this.meetingCollection, this.webex);
660
+ Metrics.initialSetup(this.webex);
498
661
  });
499
662
  }
500
663
 
@@ -519,35 +682,38 @@ export default class Meetings extends WebexPlugin {
519
682
  }
520
683
 
521
684
  /**
522
- * API to enable or disable TURN discovery
523
- * @param {Boolean} enable
685
+ * API to toggle starting adhoc meeting
686
+ * @param {Boolean} changeState
524
687
  * @private
525
688
  * @memberof Meetings
526
689
  * @returns {undefined}
527
690
  */
528
- private _toggleTurnDiscovery(enable: boolean) {
529
- if (typeof enable !== 'boolean') {
691
+ private _toggleAdhocMeetings(changeState: boolean) {
692
+ if (typeof changeState !== 'boolean') {
530
693
  return;
531
694
  }
532
695
  // @ts-ignore
533
- this.config.experimental.enableTurnDiscovery = enable;
696
+ if (this.config?.experimental?.enableAdhocMeetings !== changeState) {
697
+ // @ts-ignore
698
+ this.config.experimental.enableAdhocMeetings = changeState;
699
+ }
534
700
  }
535
701
 
536
702
  /**
537
- * API to toggle starting adhoc meeting
538
- * @param {Boolean} changeState
703
+ * API to toggle TCP reachability, needs to be called before webex.meetings.register()
704
+ * @param {Boolean} newValue
539
705
  * @private
540
706
  * @memberof Meetings
541
707
  * @returns {undefined}
542
708
  */
543
- private _toggleAdhocMeetings(changeState: boolean) {
544
- if (typeof changeState !== 'boolean') {
709
+ private _toggleTcpReachability(newValue: boolean) {
710
+ if (typeof newValue !== 'boolean') {
545
711
  return;
546
712
  }
547
713
  // @ts-ignore
548
- if (this.config?.experimental?.enableAdhocMeetings !== changeState) {
714
+ if (this.config.experimental.enableTcpReachability !== newValue) {
549
715
  // @ts-ignore
550
- this.config.experimental.enableAdhocMeetings = changeState;
716
+ this.config.experimental.enableTcpReachability = newValue;
551
717
  }
552
718
  }
553
719
 
@@ -663,6 +829,36 @@ export default class Meetings extends WebexPlugin {
663
829
  );
664
830
  }
665
831
 
832
+ /**
833
+ * Creates a noise reduction effect
834
+ *
835
+ * @param {INoiseReductionEffect} options optional custom effect options
836
+ * @returns {Promise<effect>} noise reduction effect.
837
+ * @public
838
+ * @memberof Meetings
839
+ */
840
+ createNoiseReductionEffect = async (options?: INoiseReductionEffect) => {
841
+ // @ts-ignore
842
+ const authToken = this.webex.credentials.supertoken.access_token;
843
+
844
+ return new mediaHelpersModule.NoiseReductionEffect({authToken, ...options});
845
+ };
846
+
847
+ /**
848
+ * Creates a virtual background effect
849
+ *
850
+ * @param {IVirtualBackgroundEffect} options optional custom effect options
851
+ * @returns {Promise<effect>} virtual background effect.
852
+ * @public
853
+ * @memberof Meetings
854
+ */
855
+ createVirtualBackgroundEffect = async (options?: IVirtualBackgroundEffect) => {
856
+ // @ts-ignore
857
+ const authToken = this.webex.credentials.supertoken.access_token;
858
+
859
+ return new mediaHelpersModule.VirtualBackgroundEffect({authToken, ...options});
860
+ };
861
+
666
862
  /**
667
863
  * Uploads logs to the webex services for tracking
668
864
  * @param {Object} [options={}]
@@ -677,8 +873,10 @@ export default class Meetings extends WebexPlugin {
677
873
  */
678
874
  uploadLogs(
679
875
  options: {
876
+ autoupload?: boolean;
680
877
  callStart?: string;
681
878
  feedbackId?: string;
879
+ locussessionid?: string;
682
880
  locusId?: string;
683
881
  correlationId?: string;
684
882
  meetingId?: string;
@@ -695,6 +893,7 @@ export default class Meetings extends WebexPlugin {
695
893
  'Meetings:index#uploadLogs --> Upload logs for meeting completed.',
696
894
  uploadResult
697
895
  );
896
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UPLOAD_LOGS_SUCCESS, options);
698
897
  Trigger.trigger(
699
898
  this,
700
899
  {
@@ -729,8 +928,7 @@ export default class Meetings extends WebexPlugin {
729
928
  );
730
929
 
731
930
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UPLOAD_LOGS_FAILURE, {
732
- // @ts-ignore - seems like typo
733
- meetingId: options.meetingsId,
931
+ ...options,
734
932
  reason: uploadError.message,
735
933
  stack: uploadError.stack,
736
934
  code: uploadError.code,
@@ -738,17 +936,6 @@ export default class Meetings extends WebexPlugin {
738
936
  });
739
937
  }
740
938
 
741
- /**
742
- * initializes the reachability instance for Meetings
743
- * @returns {undefined}
744
- * @public
745
- * @memberof Meetings
746
- */
747
- setReachability() {
748
- // @ts-ignore
749
- this.reachability = new Reachability(this.webex);
750
- }
751
-
752
939
  /**
753
940
  * gets the reachability instance for Meetings
754
941
  * @returns {Reachability}
@@ -766,10 +953,6 @@ export default class Meetings extends WebexPlugin {
766
953
  * @memberof Meetings
767
954
  */
768
955
  startReachability() {
769
- if (!this.reachability) {
770
- this.setReachability();
771
- }
772
-
773
956
  return this.getReachability().gatherReachability();
774
957
  }
775
958
 
@@ -797,6 +980,29 @@ export default class Meetings extends WebexPlugin {
797
980
  if (res) {
798
981
  this.preferredWebexSite = MeetingsUtil.parseDefaultSiteFromMeetingPreferences(res);
799
982
  }
983
+
984
+ // fall back to getting the preferred site from the user information
985
+ if (!this.preferredWebexSite) {
986
+ // @ts-ignore
987
+ return this.webex.internal.user
988
+ .get()
989
+ .then((user) => {
990
+ const preferredWebexSite =
991
+ user?.userPreferences?.userPreferencesItems?.preferredWebExSite;
992
+ if (preferredWebexSite) {
993
+ this.preferredWebexSite = preferredWebexSite;
994
+ } else {
995
+ throw new Error('site not found');
996
+ }
997
+ })
998
+ .catch(() => {
999
+ LoggerProxy.logger.error(
1000
+ 'Failed to fetch preferred site from user - no site will be set'
1001
+ );
1002
+ });
1003
+ }
1004
+
1005
+ return Promise.resolve();
800
1006
  });
801
1007
  }
802
1008
 
@@ -837,29 +1043,55 @@ export default class Meetings extends WebexPlugin {
837
1043
  }
838
1044
 
839
1045
  /**
840
- * Create a meeting.
841
- * @param {string} destination - sipURL, spaceId, phonenumber, or locus object}
1046
+ * Create a meeting or return an existing meeting.
1047
+ *
1048
+ * When meeting info passed it should be complete, e.g.: fetched after password or captcha provided
1049
+ *
1050
+ * @param {string} destination - sipURL, phonenumber, or locus object}
842
1051
  * @param {string} [type] - the optional specified type, such as locusId
843
1052
  * @param {Boolean} useRandomDelayForInfo - whether a random delay should be added to fetching meeting info
1053
+ * @param {Object} infoExtraParams extra parameters to be provided when fetching meeting info
1054
+ * @param {string} correlationId - the optional specified correlationId (callStateForMetrics.correlationId can be provided instead)
1055
+ * @param {Boolean} failOnMissingMeetingInfo - whether to throw an error if meeting info fails to fetch (for calls that are not 1:1 or content share)
1056
+ * @param {CallStateForMetrics} callStateForMetrics - information about call state for metrics
1057
+ * @param {Object} [meetingInfo] - Pre-fetched complete meeting info
1058
+ * @param {String} [meetingLookupUrl] - meeting info prefetch url
844
1059
  * @returns {Promise<Meeting>} A new Meeting.
845
1060
  * @public
846
1061
  * @memberof Meetings
847
1062
  */
848
- public create(destination: string, type: string = null, useRandomDelayForInfo = false) {
1063
+ public create(
1064
+ destination: string,
1065
+ type: string = null,
1066
+ useRandomDelayForInfo = false,
1067
+ infoExtraParams = {},
1068
+ correlationId: string = undefined,
1069
+ failOnMissingMeetingInfo = false,
1070
+ callStateForMetrics: CallStateForMetrics = undefined,
1071
+ meetingInfo = undefined,
1072
+ meetingLookupUrl = undefined
1073
+ ) {
849
1074
  // TODO: type should be from a dictionary
850
1075
 
851
1076
  // Validate meeting information based on the provided destination and
852
1077
  // type. This must be performed prior to determining if the meeting is
853
1078
  // found in the collection, as we mutate the destination for hydra person
854
1079
  // id values.
1080
+ if (correlationId) {
1081
+ callStateForMetrics = {...(callStateForMetrics || {}), correlationId};
1082
+ }
1083
+
855
1084
  return (
856
1085
  this.meetingInfo
857
1086
  .fetchInfoOptions(destination, type)
858
1087
  // Catch a failure to fetch info options.
859
1088
  .catch((error) => {
860
- LoggerProxy.logger.info(
861
- `Meetings:index#create --> INFO, unable to determine info options: ${error.message}`
1089
+ LoggerProxy.logger.error(
1090
+ `Meetings:index#create --> ERROR, unable to determine info options: ${error.message}`
862
1091
  );
1092
+ if (error instanceof SpaceIDDeprecatedError) {
1093
+ throw new SpaceIDDeprecatedError();
1094
+ }
863
1095
  })
864
1096
  .then((options: any = {}) => {
865
1097
  // Normalize the destination.
@@ -890,49 +1122,61 @@ export default class Meetings extends WebexPlugin {
890
1122
  // Validate if a meeting was found.
891
1123
  if (!meeting) {
892
1124
  // Create a meeting based on the normalized destination and type.
893
- return this.createMeeting(targetDest, type, useRandomDelayForInfo).then(
894
- (createdMeeting: any) => {
895
- // If the meeting was successfully created.
896
- if (createdMeeting && createdMeeting.on) {
897
- // Create a destruction event for the meeting.
898
- createdMeeting.on(EVENTS.DESTROY_MEETING, (payload) => {
899
- // @ts-ignore
900
- if (this.config.autoUploadLogs) {
901
- this.uploadLogs({
902
- callStart: createdMeeting.locusInfo?.fullState?.lastActive,
903
- correlationId: createdMeeting.correlationId,
904
- feedbackId: createdMeeting.correlationId,
905
- locusId: createdMeeting.locusId,
906
- meetingId: createdMeeting.locusInfo?.info?.webExMeetingId,
907
- }).then(() => this.destroy(createdMeeting, payload.reason));
908
- } else {
909
- this.destroy(createdMeeting, payload.reason);
910
- }
911
- });
912
-
913
- createdMeeting.on(EVENTS.REQUEST_UPLOAD_LOGS, (meetingInstance) => {
914
- // @ts-ignore
915
- if (this.config.autoUploadLogs) {
916
- this.uploadLogs({
917
- callStart: meetingInstance?.locusInfo?.fullState?.lastActive,
918
- correlationId: meetingInstance.correlationId,
919
- feedbackId: meetingInstance.correlationId,
920
- locusId: meetingInstance.locusId,
921
- meetingId: meetingInstance.locusInfo?.info?.webExMeetingId,
922
- });
923
- }
924
- });
925
- } else {
926
- LoggerProxy.logger.error(
927
- `Meetings:index#create --> ERROR, meeting does not have on method, will not be destroyed, meeting cleanup impossible for meeting: ${meeting}`
928
- );
929
- }
930
-
931
- // Return the newly created meeting.
932
- return Promise.resolve(createdMeeting);
1125
+ return this.createMeeting(
1126
+ targetDest,
1127
+ type,
1128
+ useRandomDelayForInfo,
1129
+ infoExtraParams,
1130
+ callStateForMetrics,
1131
+ failOnMissingMeetingInfo,
1132
+ meetingInfo,
1133
+ meetingLookupUrl
1134
+ ).then((createdMeeting: any) => {
1135
+ // If the meeting was successfully created.
1136
+ if (createdMeeting && createdMeeting.on) {
1137
+ // Create a destruction event for the meeting.
1138
+ createdMeeting.on(EVENTS.DESTROY_MEETING, (payload) => {
1139
+ // @ts-ignore
1140
+ if (this.config.autoUploadLogs) {
1141
+ this.uploadLogs({
1142
+ callStart: createdMeeting.locusInfo?.fullState?.lastActive,
1143
+ locussessionid: createdMeeting.locusInfo?.fullState?.sessionId,
1144
+ correlationId: createdMeeting.correlationId,
1145
+ feedbackId: createdMeeting.correlationId,
1146
+ locusId: createdMeeting.locusId,
1147
+ meetingId: createdMeeting.locusInfo?.info?.webExMeetingId,
1148
+ autoupload: true,
1149
+ }).then(() => this.destroy(createdMeeting, payload.reason));
1150
+ } else {
1151
+ this.destroy(createdMeeting, payload.reason);
1152
+ }
1153
+ });
1154
+
1155
+ createdMeeting.on(EVENTS.REQUEST_UPLOAD_LOGS, (meetingInstance) => {
1156
+ // @ts-ignore
1157
+ if (this.config.autoUploadLogs) {
1158
+ this.uploadLogs({
1159
+ callStart: meetingInstance?.locusInfo?.fullState?.lastActive,
1160
+ locussessionid: meetingInstance?.locusInfo?.fullState?.sessionId,
1161
+ correlationId: meetingInstance.correlationId,
1162
+ feedbackId: meetingInstance.correlationId,
1163
+ locusId: meetingInstance.locusId,
1164
+ meetingId: meetingInstance.locusInfo?.info?.webExMeetingId,
1165
+ autoupload: true,
1166
+ });
1167
+ }
1168
+ });
1169
+ } else {
1170
+ LoggerProxy.logger.error(
1171
+ `Meetings:index#create --> ERROR, meeting does not have on method, will not be destroyed, meeting cleanup impossible for meeting: ${meeting}`
1172
+ );
933
1173
  }
934
- );
1174
+
1175
+ // Return the newly created meeting.
1176
+ return Promise.resolve(createdMeeting);
1177
+ });
935
1178
  }
1179
+ meeting.setCallStateForMetrics(callStateForMetrics);
936
1180
 
937
1181
  // Return the existing meeting.
938
1182
  return Promise.resolve(meeting);
@@ -941,9 +1185,18 @@ export default class Meetings extends WebexPlugin {
941
1185
  }
942
1186
 
943
1187
  /**
1188
+ * Create meeting
1189
+ *
1190
+ * When meeting info passed it should be complete, e.g.: fetched after password or captcha provided
1191
+ *
944
1192
  * @param {String} destination see create()
945
1193
  * @param {String} type see create()
946
1194
  * @param {Boolean} useRandomDelayForInfo whether a random delay should be added to fetching meeting info
1195
+ * @param {Object} infoExtraParams extra parameters to be provided when fetching meeting info
1196
+ * @param {CallStateForMetrics} callStateForMetrics - information about call state for metrics
1197
+ * @param {Boolean} failOnMissingMeetingInfo - whether to throw an error if meeting info fails to fetch (for calls that are not 1:1 or content share)
1198
+ * @param {Object} [meetingInfo] - Pre-fetched complete meeting info
1199
+ * @param {String} [meetingLookupUrl] - meeting info prefetch url
947
1200
  * @returns {Promise} a new meeting instance complete with meeting info and destination
948
1201
  * @private
949
1202
  * @memberof Meetings
@@ -951,7 +1204,12 @@ export default class Meetings extends WebexPlugin {
951
1204
  private async createMeeting(
952
1205
  destination: any,
953
1206
  type: string = null,
954
- useRandomDelayForInfo = false
1207
+ useRandomDelayForInfo = false,
1208
+ infoExtraParams = {},
1209
+ callStateForMetrics: CallStateForMetrics = undefined,
1210
+ failOnMissingMeetingInfo = false,
1211
+ meetingInfo = undefined,
1212
+ meetingLookupUrl = undefined
955
1213
  ) {
956
1214
  const meeting = new Meeting(
957
1215
  {
@@ -965,6 +1223,7 @@ export default class Meetings extends WebexPlugin {
965
1223
  meetingInfoProvider: this.meetingInfo,
966
1224
  destination,
967
1225
  destinationType: type,
1226
+ callStateForMetrics,
968
1227
  },
969
1228
  {
970
1229
  // @ts-ignore
@@ -996,22 +1255,45 @@ export default class Meetings extends WebexPlugin {
996
1255
  const isMeetingActive = !!destination.fullState?.active;
997
1256
  // @ts-ignore
998
1257
  const {enableUnifiedMeetings} = this.config.experimental;
999
-
1000
- if (enableUnifiedMeetings && !isMeetingActive && useRandomDelayForInfo && waitingTime > 0) {
1258
+ const meetingInfoOptions = {
1259
+ extraParams: infoExtraParams,
1260
+ sendCAevents: !!callStateForMetrics?.correlationId, // if client sends correlation id as argument of public create(), then it means that this meeting creation is part of a pre-join intent from user
1261
+ };
1262
+
1263
+ if (meetingInfo) {
1264
+ meeting.injectMeetingInfo(meetingInfo, meetingInfoOptions, meetingLookupUrl);
1265
+ } else if (
1266
+ enableUnifiedMeetings &&
1267
+ !isMeetingActive &&
1268
+ useRandomDelayForInfo &&
1269
+ waitingTime > 0
1270
+ ) {
1001
1271
  meeting.fetchMeetingInfoTimeoutId = setTimeout(
1002
- () => meeting.fetchMeetingInfo({}),
1272
+ () => meeting.fetchMeetingInfo(meetingInfoOptions),
1003
1273
  waitingTime
1004
1274
  );
1005
1275
  meeting.parseMeetingInfo(undefined, destination);
1006
1276
  } else {
1007
- await meeting.fetchMeetingInfo({});
1277
+ await meeting.fetchMeetingInfo(meetingInfoOptions);
1008
1278
  }
1009
1279
  } catch (err) {
1010
- if (!(err instanceof CaptchaError) && !(err instanceof PasswordError)) {
1011
- // if there is no meeting info we assume its a 1:1 call or wireless share
1280
+ if (
1281
+ !(err instanceof CaptchaError) &&
1282
+ !(err instanceof PasswordError) &&
1283
+ !(err instanceof PermissionError)
1284
+ ) {
1012
1285
  LoggerProxy.logger.info(
1013
1286
  `Meetings:index#createMeeting --> Info Unable to fetch meeting info for ${destination}.`
1014
1287
  );
1288
+ if (failOnMissingMeetingInfo) {
1289
+ LoggerProxy.logger.info(
1290
+ `Meetings:index#createMeeting --> Destroying meeting due to missing meeting info.`
1291
+ );
1292
+ // @ts-ignore
1293
+ this.destroy(meeting, MEETING_REMOVED_REASON.MISSING_MEETING_INFO);
1294
+ throw new NoMeetingInfoError();
1295
+ }
1296
+ // if there is no meeting info and no error should be thrown then we assume its a 1:1 call or wireless share
1015
1297
  LoggerProxy.logger.info(
1016
1298
  'Meetings:index#createMeeting --> Info assuming this destination is a 1:1 or wireless share'
1017
1299
  );
@@ -1064,7 +1346,7 @@ export default class Meetings extends WebexPlugin {
1064
1346
  //
1065
1347
  // Our job is to determine the appropriate one
1066
1348
  // and its corresponding service so that developers
1067
- // need only sipURL or spaceID to get a meeting
1349
+ // need only sipURL to get a meeting
1068
1350
  // and its ID, but have the option to use createWithType()
1069
1351
  // and specify those types to get meetingInfo
1070
1352
  }
@@ -1102,39 +1384,126 @@ export default class Meetings extends WebexPlugin {
1102
1384
  }
1103
1385
 
1104
1386
  /**
1105
- * syncs all the meeting from server
1106
- * @returns {undefined}
1387
+ * Syncs all the meetings from server. Does nothing and returns immediately if unverified guest.
1388
+ * @param {boolean} keepOnlyLocusMeetings - whether the sync should keep only locus meetings or any other meeting in meetingCollection
1389
+ * @returns {Promise<void>}
1107
1390
  * @public
1108
1391
  * @memberof Meetings
1109
1392
  */
1110
- public syncMeetings() {
1111
- return this.request.getActiveMeetings().then((locusArray) => {
1112
- const activeLocusUrl = [];
1113
-
1114
- if (locusArray?.loci && locusArray.loci.length > 0) {
1115
- locusArray.loci.forEach((locus) => {
1116
- activeLocusUrl.push(locus.url);
1117
- this.handleLocusEvent({
1118
- locus,
1119
- locusUrl: locus.url,
1393
+ public syncMeetings({keepOnlyLocusMeetings = true} = {}): Promise<void> {
1394
+ // @ts-ignore
1395
+ if (this.webex.credentials.isUnverifiedGuest) {
1396
+ LoggerProxy.logger.info(
1397
+ 'Meetings:index#syncMeetings --> skipping meeting sync as unverified guest'
1398
+ );
1399
+
1400
+ return Promise.resolve();
1401
+ }
1402
+
1403
+ return this.request
1404
+ .getActiveMeetings()
1405
+ .then((locusArray) => {
1406
+ const activeLocusUrl = [];
1407
+
1408
+ if (locusArray?.loci && locusArray.loci.length > 0) {
1409
+ const lociToUpdate = this.sortLocusArrayToUpdate(locusArray.loci);
1410
+ lociToUpdate.forEach((locus) => {
1411
+ activeLocusUrl.push(locus.url);
1412
+ this.handleLocusEvent({
1413
+ locus,
1414
+ locusUrl: locus.url,
1415
+ });
1120
1416
  });
1121
- });
1122
- }
1123
- const meetingsCollection = this.meetingCollection.getAll();
1417
+ }
1418
+ const meetingsCollection = this.meetingCollection.getAll();
1124
1419
 
1125
- if (Object.keys(meetingsCollection).length > 0) {
1126
- // Some time the mercury event is missed after mercury reconnect
1127
- // if sync returns no locus then clear all the meetings
1128
- for (const meeting of Object.values(meetingsCollection)) {
1129
- // @ts-ignore
1130
- if (!activeLocusUrl.includes(meeting.locusUrl)) {
1131
- // destroy function also uploads logs
1420
+ if (Object.keys(meetingsCollection).length > 0) {
1421
+ // Sometimes the mercury events are lost after mercury reconnect
1422
+ // Remove any Locus meetings that are not returned by Locus
1423
+ // (they had a locusUrl previously but are no longer active) in the sync
1424
+ for (const meeting of Object.values(meetingsCollection)) {
1132
1425
  // @ts-ignore
1133
- this.destroy(meeting, MEETING_REMOVED_REASON.NO_MEETINGS_TO_SYNC);
1426
+ const {locusUrl} = meeting;
1427
+ if ((keepOnlyLocusMeetings || locusUrl) && !activeLocusUrl.includes(locusUrl)) {
1428
+ // destroy function also uploads logs
1429
+ // @ts-ignore
1430
+ this.destroy(meeting, MEETING_REMOVED_REASON.NO_MEETINGS_TO_SYNC);
1431
+ }
1134
1432
  }
1135
1433
  }
1434
+ })
1435
+ .catch((error) => {
1436
+ LoggerProxy.logger.error(
1437
+ `Meetings:index#syncMeetings --> failed to sync meetings, ${error}`
1438
+ );
1439
+ throw new Error(error);
1440
+ });
1441
+ }
1442
+
1443
+ /**
1444
+ * sort out locus array for initial creating
1445
+ * @param {Array} loci original locus array
1446
+ * @returns {undefined}
1447
+ * @public
1448
+ * @memberof Meetings
1449
+ */
1450
+ sortLocusArrayToUpdate(loci: any[]) {
1451
+ const mainLoci = loci.filter((locus) => !MeetingsUtil.isBreakoutLocusDTO(locus));
1452
+ const breakoutLoci = loci.filter((locus) => MeetingsUtil.isValidBreakoutLocus(locus));
1453
+ this.breakoutLocusForHandleLater = [];
1454
+ const lociToUpdate = [...mainLoci];
1455
+ breakoutLoci.forEach((breakoutLocus) => {
1456
+ const associateMainLocus = mainLoci.find(
1457
+ (mainLocus) => mainLocus.controls?.breakout?.url === breakoutLocus.controls?.breakout?.url
1458
+ );
1459
+ const existCorrespondingMeeting = this.getCorrespondingMeetingByLocus({
1460
+ locus: breakoutLocus,
1461
+ locusUrl: breakoutLocus.url,
1462
+ });
1463
+
1464
+ if (associateMainLocus && !existCorrespondingMeeting) {
1465
+ // if exists both main session and breakout session locus of the same non-exist meeting, handle main locus first,
1466
+ // after meeting create with main locus, then handle the associate breakout locus.
1467
+ // if only handle breakout locus, will miss some date
1468
+ this.breakoutLocusForHandleLater.push(breakoutLocus);
1469
+ } else {
1470
+ lociToUpdate.push(breakoutLocus);
1136
1471
  }
1137
1472
  });
1473
+
1474
+ return lociToUpdate;
1475
+ }
1476
+
1477
+ /**
1478
+ * check breakout locus which waiting for main locus's meeting to be created, then handle the breakout locus
1479
+ * @param {Object} newCreatedLocus the locus which just create meeting object of it
1480
+ * @returns {undefined}
1481
+ * @public
1482
+ * @memberof Meetings
1483
+ */
1484
+ checkHandleBreakoutLocus(newCreatedLocus) {
1485
+ if (
1486
+ !newCreatedLocus ||
1487
+ !this.breakoutLocusForHandleLater ||
1488
+ !this.breakoutLocusForHandleLater.length
1489
+ ) {
1490
+ return;
1491
+ }
1492
+ if (MeetingsUtil.isBreakoutLocusDTO(newCreatedLocus)) {
1493
+ return;
1494
+ }
1495
+ const existIndex = this.breakoutLocusForHandleLater.findIndex(
1496
+ (breakoutLocus) =>
1497
+ breakoutLocus.controls?.breakout?.url === newCreatedLocus.controls?.breakout?.url
1498
+ );
1499
+
1500
+ if (existIndex < 0) {
1501
+ return;
1502
+ }
1503
+
1504
+ const associateBreakoutLocus = this.breakoutLocusForHandleLater[existIndex];
1505
+ this.handleLocusEvent({locus: associateBreakoutLocus, locusUrl: associateBreakoutLocus.url});
1506
+ this.breakoutLocusForHandleLater.splice(existIndex, 1);
1138
1507
  }
1139
1508
 
1140
1509
  /**
@@ -1156,4 +1525,15 @@ export default class Meetings extends WebexPlugin {
1156
1525
  getLogger() {
1157
1526
  return LoggerProxy.get();
1158
1527
  }
1528
+
1529
+ /**
1530
+ * Returns the first meeting it finds that has the webrtc media connection created.
1531
+ * Useful for debugging in the console.
1532
+ *
1533
+ * @private
1534
+ * @returns {Meeting} Meeting object that has a webrtc media connection, else undefined
1535
+ */
1536
+ getActiveWebrtcMeeting() {
1537
+ return this.meetingCollection.getActiveWebrtcMeeting();
1538
+ }
1159
1539
  }