@webex/plugin-meetings 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 (601) hide show
  1. package/README.md +46 -8
  2. package/UPGRADING.md +9 -9
  3. package/browsers.js +19 -24
  4. package/dist/annotation/annotation.types.js +7 -0
  5. package/dist/annotation/annotation.types.js.map +1 -0
  6. package/dist/annotation/constants.js +49 -0
  7. package/dist/annotation/constants.js.map +1 -0
  8. package/dist/annotation/index.js +342 -0
  9. package/dist/annotation/index.js.map +1 -0
  10. package/dist/breakouts/breakout.js +216 -0
  11. package/dist/breakouts/breakout.js.map +1 -0
  12. package/dist/breakouts/collection.js +23 -0
  13. package/dist/breakouts/collection.js.map +1 -0
  14. package/dist/breakouts/edit-lock-error.js +52 -0
  15. package/dist/breakouts/edit-lock-error.js.map +1 -0
  16. package/dist/breakouts/events.js +45 -0
  17. package/dist/breakouts/events.js.map +1 -0
  18. package/dist/breakouts/index.js +1048 -0
  19. package/dist/breakouts/index.js.map +1 -0
  20. package/dist/breakouts/request.js +78 -0
  21. package/dist/breakouts/request.js.map +1 -0
  22. package/dist/breakouts/utils.js +67 -0
  23. package/dist/breakouts/utils.js.map +1 -0
  24. package/dist/common/browser-detection.js +1 -20
  25. package/dist/common/browser-detection.js.map +1 -1
  26. package/dist/common/collection.js +5 -20
  27. package/dist/common/collection.js.map +1 -1
  28. package/dist/common/config.js +0 -7
  29. package/dist/common/config.js.map +1 -1
  30. package/dist/common/errors/captcha-error.js +10 -24
  31. package/dist/common/errors/captcha-error.js.map +1 -1
  32. package/dist/common/errors/intent-to-join.js +11 -24
  33. package/dist/common/errors/intent-to-join.js.map +1 -1
  34. package/dist/common/errors/join-meeting.js +12 -25
  35. package/dist/common/errors/join-meeting.js.map +1 -1
  36. package/dist/common/errors/media.js +10 -24
  37. package/dist/common/errors/media.js.map +1 -1
  38. package/dist/common/errors/no-meeting-info.js +51 -0
  39. package/dist/common/errors/no-meeting-info.js.map +1 -0
  40. package/dist/common/errors/parameter.js +5 -33
  41. package/dist/common/errors/parameter.js.map +1 -1
  42. package/dist/common/errors/password-error.js +10 -24
  43. package/dist/common/errors/password-error.js.map +1 -1
  44. package/dist/common/errors/permission.js +9 -23
  45. package/dist/common/errors/permission.js.map +1 -1
  46. package/dist/common/errors/reclaim-host-role-errors.js +158 -0
  47. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  48. package/dist/common/errors/reconnection-in-progress.js +0 -17
  49. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  50. package/dist/common/errors/reconnection.js +10 -24
  51. package/dist/common/errors/reconnection.js.map +1 -1
  52. package/dist/common/errors/stats.js +10 -24
  53. package/dist/common/errors/stats.js.map +1 -1
  54. package/dist/common/errors/webex-errors.js +54 -48
  55. package/dist/common/errors/webex-errors.js.map +1 -1
  56. package/dist/common/errors/webex-meetings-error.js +5 -25
  57. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  58. package/dist/common/events/events-scope.js +0 -22
  59. package/dist/common/events/events-scope.js.map +1 -1
  60. package/dist/common/events/events.js +0 -23
  61. package/dist/common/events/events.js.map +1 -1
  62. package/dist/common/events/trigger-proxy.js +0 -12
  63. package/dist/common/events/trigger-proxy.js.map +1 -1
  64. package/dist/common/events/util.js +0 -15
  65. package/dist/common/events/util.js.map +1 -1
  66. package/dist/common/logs/logger-config.js +0 -4
  67. package/dist/common/logs/logger-config.js.map +1 -1
  68. package/dist/common/logs/logger-proxy.js +1 -8
  69. package/dist/common/logs/logger-proxy.js.map +1 -1
  70. package/dist/common/logs/request.js +41 -60
  71. package/dist/common/logs/request.js.map +1 -1
  72. package/dist/common/queue.js +28 -23
  73. package/dist/common/queue.js.map +1 -1
  74. package/dist/config.js +9 -15
  75. package/dist/config.js.map +1 -1
  76. package/dist/constants.js +315 -68
  77. package/dist/constants.js.map +1 -1
  78. package/dist/controls-options-manager/constants.js +14 -0
  79. package/dist/controls-options-manager/constants.js.map +1 -0
  80. package/dist/controls-options-manager/enums.js +27 -0
  81. package/dist/controls-options-manager/enums.js.map +1 -0
  82. package/dist/controls-options-manager/index.js +297 -0
  83. package/dist/controls-options-manager/index.js.map +1 -0
  84. package/dist/controls-options-manager/types.js +7 -0
  85. package/dist/controls-options-manager/types.js.map +1 -0
  86. package/dist/controls-options-manager/util.js +319 -0
  87. package/dist/controls-options-manager/util.js.map +1 -0
  88. package/dist/index.js +114 -17
  89. package/dist/index.js.map +1 -1
  90. package/dist/interpretation/collection.js +23 -0
  91. package/dist/interpretation/collection.js.map +1 -0
  92. package/dist/interpretation/index.js +366 -0
  93. package/dist/interpretation/index.js.map +1 -0
  94. package/dist/interpretation/siLanguage.js +25 -0
  95. package/dist/interpretation/siLanguage.js.map +1 -0
  96. package/dist/locus-info/controlsUtils.js +101 -29
  97. package/dist/locus-info/controlsUtils.js.map +1 -1
  98. package/dist/locus-info/embeddedAppsUtils.js +3 -26
  99. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  100. package/dist/locus-info/fullState.js +0 -15
  101. package/dist/locus-info/fullState.js.map +1 -1
  102. package/dist/locus-info/hostUtils.js +4 -12
  103. package/dist/locus-info/hostUtils.js.map +1 -1
  104. package/dist/locus-info/index.js +561 -246
  105. package/dist/locus-info/index.js.map +1 -1
  106. package/dist/locus-info/infoUtils.js +10 -38
  107. package/dist/locus-info/infoUtils.js.map +1 -1
  108. package/dist/locus-info/mediaSharesUtils.js +68 -38
  109. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  110. package/dist/locus-info/parser.js +314 -163
  111. package/dist/locus-info/parser.js.map +1 -1
  112. package/dist/locus-info/selfUtils.js +110 -92
  113. package/dist/locus-info/selfUtils.js.map +1 -1
  114. package/dist/media/index.js +103 -231
  115. package/dist/media/index.js.map +1 -1
  116. package/dist/media/properties.js +137 -222
  117. package/dist/media/properties.js.map +1 -1
  118. package/dist/media/util.js +2 -9
  119. package/dist/media/util.js.map +1 -1
  120. package/dist/mediaQualityMetrics/config.js +505 -495
  121. package/dist/mediaQualityMetrics/config.js.map +1 -1
  122. package/dist/meeting/in-meeting-actions.js +93 -14
  123. package/dist/meeting/in-meeting-actions.js.map +1 -1
  124. package/dist/meeting/index.js +4624 -3740
  125. package/dist/meeting/index.js.map +1 -1
  126. package/dist/meeting/locusMediaRequest.js +292 -0
  127. package/dist/meeting/locusMediaRequest.js.map +1 -0
  128. package/dist/meeting/muteState.js +249 -184
  129. package/dist/meeting/muteState.js.map +1 -1
  130. package/dist/meeting/request.js +400 -346
  131. package/dist/meeting/request.js.map +1 -1
  132. package/dist/meeting/request.type.js +7 -0
  133. package/dist/meeting/request.type.js.map +1 -0
  134. package/dist/meeting/state.js +21 -31
  135. package/dist/meeting/state.js.map +1 -1
  136. package/dist/meeting/util.js +598 -586
  137. package/dist/meeting/util.js.map +1 -1
  138. package/dist/meeting-info/collection.js +6 -25
  139. package/dist/meeting-info/collection.js.map +1 -1
  140. package/dist/meeting-info/index.js +87 -39
  141. package/dist/meeting-info/index.js.map +1 -1
  142. package/dist/meeting-info/meeting-info-v2.js +349 -283
  143. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  144. package/dist/meeting-info/request.js +3 -15
  145. package/dist/meeting-info/request.js.map +1 -1
  146. package/dist/meeting-info/util.js +98 -183
  147. package/dist/meeting-info/util.js.map +1 -1
  148. package/dist/meeting-info/utilv2.js +143 -234
  149. package/dist/meeting-info/utilv2.js.map +1 -1
  150. package/dist/meetings/collection.js +26 -19
  151. package/dist/meetings/collection.js.map +1 -1
  152. package/dist/meetings/index.js +813 -596
  153. package/dist/meetings/index.js.map +1 -1
  154. package/dist/meetings/meetings.types.js +7 -0
  155. package/dist/meetings/meetings.types.js.map +1 -0
  156. package/dist/meetings/request.js +26 -41
  157. package/dist/meetings/request.js.map +1 -1
  158. package/dist/meetings/util.js +183 -156
  159. package/dist/meetings/util.js.map +1 -1
  160. package/dist/member/index.js +135 -85
  161. package/dist/member/index.js.map +1 -1
  162. package/dist/member/types.js +25 -0
  163. package/dist/member/types.js.map +1 -0
  164. package/dist/member/util.js +158 -88
  165. package/dist/member/util.js.map +1 -1
  166. package/dist/members/collection.js +13 -12
  167. package/dist/members/collection.js.map +1 -1
  168. package/dist/members/index.js +194 -204
  169. package/dist/members/index.js.map +1 -1
  170. package/dist/members/request.js +113 -68
  171. package/dist/members/request.js.map +1 -1
  172. package/dist/members/types.js +15 -0
  173. package/dist/members/types.js.map +1 -0
  174. package/dist/members/util.js +324 -259
  175. package/dist/members/util.js.map +1 -1
  176. package/dist/metrics/constants.js +14 -7
  177. package/dist/metrics/constants.js.map +1 -1
  178. package/dist/metrics/index.js +11 -558
  179. package/dist/metrics/index.js.map +1 -1
  180. package/dist/multistream/mediaRequestManager.js +263 -50
  181. package/dist/multistream/mediaRequestManager.js.map +1 -1
  182. package/dist/multistream/receiveSlot.js +58 -65
  183. package/dist/multistream/receiveSlot.js.map +1 -1
  184. package/dist/multistream/receiveSlotManager.js +76 -95
  185. package/dist/multistream/receiveSlotManager.js.map +1 -1
  186. package/dist/multistream/remoteMedia.js +62 -76
  187. package/dist/multistream/remoteMedia.js.map +1 -1
  188. package/dist/multistream/remoteMediaGroup.js +66 -43
  189. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  190. package/dist/multistream/remoteMediaManager.js +536 -439
  191. package/dist/multistream/remoteMediaManager.js.map +1 -1
  192. package/dist/multistream/sendSlotManager.js +233 -0
  193. package/dist/multistream/sendSlotManager.js.map +1 -0
  194. package/dist/networkQualityMonitor/index.js +40 -59
  195. package/dist/networkQualityMonitor/index.js.map +1 -1
  196. package/dist/personal-meeting-room/index.js +21 -45
  197. package/dist/personal-meeting-room/index.js.map +1 -1
  198. package/dist/personal-meeting-room/request.js +1 -31
  199. package/dist/personal-meeting-room/request.js.map +1 -1
  200. package/dist/personal-meeting-room/util.js +0 -13
  201. package/dist/personal-meeting-room/util.js.map +1 -1
  202. package/dist/reachability/index.js +322 -200
  203. package/dist/reachability/index.js.map +1 -1
  204. package/dist/reachability/request.js +20 -26
  205. package/dist/reachability/request.js.map +1 -1
  206. package/dist/reactions/constants.js +13 -0
  207. package/dist/reactions/constants.js.map +1 -0
  208. package/dist/reactions/reactions.js +109 -0
  209. package/dist/reactions/reactions.js.map +1 -0
  210. package/dist/reactions/reactions.type.js +36 -0
  211. package/dist/reactions/reactions.type.js.map +1 -0
  212. package/dist/reconnection-manager/index.js +388 -476
  213. package/dist/reconnection-manager/index.js.map +1 -1
  214. package/dist/recording-controller/enums.js +17 -0
  215. package/dist/recording-controller/enums.js.map +1 -0
  216. package/dist/recording-controller/index.js +362 -0
  217. package/dist/recording-controller/index.js.map +1 -0
  218. package/dist/recording-controller/util.js +64 -0
  219. package/dist/recording-controller/util.js.map +1 -0
  220. package/dist/roap/index.js +99 -94
  221. package/dist/roap/index.js.map +1 -1
  222. package/dist/roap/request.js +131 -135
  223. package/dist/roap/request.js.map +1 -1
  224. package/dist/roap/turnDiscovery.js +151 -101
  225. package/dist/roap/turnDiscovery.js.map +1 -1
  226. package/dist/rtcMetrics/constants.js +12 -0
  227. package/dist/rtcMetrics/constants.js.map +1 -0
  228. package/dist/rtcMetrics/index.js +117 -0
  229. package/dist/rtcMetrics/index.js.map +1 -0
  230. package/dist/statsAnalyzer/global.js +1 -95
  231. package/dist/statsAnalyzer/global.js.map +1 -1
  232. package/dist/statsAnalyzer/index.js +416 -497
  233. package/dist/statsAnalyzer/index.js.map +1 -1
  234. package/dist/statsAnalyzer/mqaUtil.js +145 -88
  235. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  236. package/dist/transcription/index.js +22 -47
  237. package/dist/transcription/index.js.map +1 -1
  238. package/dist/types/annotation/annotation.types.d.ts +42 -0
  239. package/dist/types/annotation/constants.d.ts +31 -0
  240. package/dist/types/annotation/index.d.ts +117 -0
  241. package/dist/types/breakouts/breakout.d.ts +8 -0
  242. package/dist/types/breakouts/collection.d.ts +5 -0
  243. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  244. package/dist/types/breakouts/events.d.ts +8 -0
  245. package/dist/types/breakouts/index.d.ts +5 -0
  246. package/dist/types/breakouts/request.d.ts +22 -0
  247. package/dist/types/breakouts/utils.d.ts +15 -0
  248. package/dist/types/common/browser-detection.d.ts +9 -0
  249. package/dist/types/common/collection.d.ts +48 -0
  250. package/dist/types/common/config.d.ts +2 -0
  251. package/dist/types/common/errors/captcha-error.d.ts +15 -0
  252. package/dist/types/common/errors/intent-to-join.d.ts +16 -0
  253. package/dist/types/common/errors/join-meeting.d.ts +17 -0
  254. package/dist/types/common/errors/media.d.ts +15 -0
  255. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  256. package/dist/types/common/errors/parameter.d.ts +15 -0
  257. package/dist/types/common/errors/password-error.d.ts +15 -0
  258. package/dist/types/common/errors/permission.d.ts +14 -0
  259. package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
  260. package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
  261. package/dist/types/common/errors/reconnection.d.ts +15 -0
  262. package/dist/types/common/errors/stats.d.ts +15 -0
  263. package/dist/types/common/errors/webex-errors.d.ts +93 -0
  264. package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
  265. package/dist/types/common/events/events-scope.d.ts +17 -0
  266. package/dist/types/common/events/events.d.ts +12 -0
  267. package/dist/types/common/events/trigger-proxy.d.ts +2 -0
  268. package/dist/types/common/events/util.d.ts +2 -0
  269. package/dist/types/common/logs/logger-config.d.ts +2 -0
  270. package/dist/types/common/logs/logger-proxy.d.ts +2 -0
  271. package/dist/types/common/logs/request.d.ts +36 -0
  272. package/dist/types/common/queue.d.ts +34 -0
  273. package/dist/types/config.d.ts +71 -0
  274. package/dist/types/constants.d.ts +1066 -0
  275. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  276. package/dist/types/controls-options-manager/enums.d.ts +15 -0
  277. package/dist/types/controls-options-manager/index.d.ts +136 -0
  278. package/dist/types/controls-options-manager/types.d.ts +43 -0
  279. package/dist/types/controls-options-manager/util.d.ts +1 -0
  280. package/dist/types/index.d.ts +7 -0
  281. package/dist/types/interpretation/collection.d.ts +5 -0
  282. package/dist/types/interpretation/index.d.ts +5 -0
  283. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  284. package/dist/types/locus-info/controlsUtils.d.ts +2 -0
  285. package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
  286. package/dist/types/locus-info/fullState.d.ts +2 -0
  287. package/dist/types/locus-info/hostUtils.d.ts +2 -0
  288. package/dist/types/locus-info/index.d.ts +322 -0
  289. package/dist/types/locus-info/infoUtils.d.ts +2 -0
  290. package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
  291. package/dist/types/locus-info/parser.d.ts +273 -0
  292. package/dist/types/locus-info/selfUtils.d.ts +2 -0
  293. package/dist/types/media/index.d.ts +34 -0
  294. package/dist/types/media/properties.d.ts +93 -0
  295. package/dist/types/media/util.d.ts +2 -0
  296. package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
  297. package/dist/types/meeting/in-meeting-actions.d.ts +163 -0
  298. package/dist/types/meeting/index.d.ts +1676 -0
  299. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  300. package/dist/types/meeting/muteState.d.ts +184 -0
  301. package/dist/types/meeting/request.d.ts +290 -0
  302. package/dist/types/meeting/request.type.d.ts +11 -0
  303. package/dist/types/meeting/state.d.ts +9 -0
  304. package/dist/types/meeting/util.d.ts +102 -0
  305. package/dist/types/meeting-info/collection.d.ts +20 -0
  306. package/dist/types/meeting-info/index.d.ts +69 -0
  307. package/dist/types/meeting-info/meeting-info-v2.d.ts +123 -0
  308. package/dist/types/meeting-info/request.d.ts +22 -0
  309. package/dist/types/meeting-info/util.d.ts +2 -0
  310. package/dist/types/meeting-info/utilv2.d.ts +2 -0
  311. package/dist/types/meetings/collection.d.ts +31 -0
  312. package/dist/types/meetings/index.d.ts +367 -0
  313. package/dist/types/meetings/meetings.types.d.ts +4 -0
  314. package/dist/types/meetings/request.d.ts +27 -0
  315. package/dist/types/meetings/util.d.ts +18 -0
  316. package/dist/types/member/index.d.ts +160 -0
  317. package/dist/types/member/types.d.ts +32 -0
  318. package/dist/types/member/util.d.ts +2 -0
  319. package/dist/types/members/collection.d.ts +29 -0
  320. package/dist/types/members/index.d.ts +353 -0
  321. package/dist/types/members/request.d.ts +114 -0
  322. package/dist/types/members/types.d.ts +25 -0
  323. package/dist/types/members/util.d.ts +215 -0
  324. package/dist/types/metrics/constants.d.ts +65 -0
  325. package/dist/types/metrics/index.d.ts +45 -0
  326. package/dist/types/multistream/mediaRequestManager.d.ts +118 -0
  327. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  328. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  329. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  330. package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
  331. package/dist/types/multistream/remoteMediaManager.d.ts +285 -0
  332. package/dist/types/multistream/sendSlotManager.d.ts +61 -0
  333. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  334. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  335. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  336. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  337. package/dist/types/reachability/index.d.ts +194 -0
  338. package/dist/types/reachability/request.d.ts +39 -0
  339. package/dist/types/reactions/constants.d.ts +3 -0
  340. package/dist/types/reactions/reactions.d.ts +4 -0
  341. package/dist/types/reactions/reactions.type.d.ts +52 -0
  342. package/dist/types/reconnection-manager/index.d.ts +126 -0
  343. package/dist/types/recording-controller/enums.d.ts +7 -0
  344. package/dist/types/recording-controller/index.d.ts +207 -0
  345. package/dist/types/recording-controller/util.d.ts +14 -0
  346. package/dist/types/roap/index.d.ts +78 -0
  347. package/dist/types/roap/request.d.ts +39 -0
  348. package/dist/types/roap/turnDiscovery.d.ts +92 -0
  349. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  350. package/dist/types/rtcMetrics/index.d.ts +47 -0
  351. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  352. package/dist/types/statsAnalyzer/index.d.ts +201 -0
  353. package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
  354. package/dist/types/transcription/index.d.ts +64 -0
  355. package/dist/types/webinar/collection.d.ts +16 -0
  356. package/dist/types/webinar/index.d.ts +5 -0
  357. package/dist/webinar/collection.js +44 -0
  358. package/dist/webinar/collection.js.map +1 -0
  359. package/dist/webinar/index.js +69 -0
  360. package/dist/webinar/index.js.map +1 -0
  361. package/internal-README.md +7 -6
  362. package/package.json +29 -21
  363. package/src/annotation/annotation.types.ts +50 -0
  364. package/src/annotation/constants.ts +36 -0
  365. package/src/annotation/index.ts +328 -0
  366. package/src/breakouts/README.md +220 -0
  367. package/src/breakouts/breakout.ts +188 -0
  368. package/src/breakouts/collection.ts +19 -0
  369. package/src/breakouts/edit-lock-error.ts +25 -0
  370. package/src/breakouts/events.ts +56 -0
  371. package/src/breakouts/index.ts +925 -0
  372. package/src/breakouts/request.ts +55 -0
  373. package/src/breakouts/utils.ts +57 -0
  374. package/src/common/{browser-detection.js → browser-detection.ts} +9 -6
  375. package/src/common/collection.ts +9 -7
  376. package/src/common/{config.js → config.ts} +1 -1
  377. package/src/common/errors/{captcha-error.js → captcha-error.ts} +11 -7
  378. package/src/common/errors/{intent-to-join.js → intent-to-join.ts} +12 -7
  379. package/src/common/errors/{join-meeting.js → join-meeting.ts} +17 -8
  380. package/src/common/errors/{media.js → media.ts} +11 -7
  381. package/src/common/errors/no-meeting-info.ts +24 -0
  382. package/src/common/errors/parameter.ts +11 -7
  383. package/src/common/errors/{password-error.js → password-error.ts} +11 -7
  384. package/src/common/errors/{permission.js → permission.ts} +10 -6
  385. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  386. package/src/common/errors/{reconnection.js → reconnection.ts} +11 -7
  387. package/src/common/errors/{stats.js → stats.ts} +11 -7
  388. package/src/common/errors/{webex-errors.js → webex-errors.ts} +51 -8
  389. package/src/common/errors/{webex-meetings-error.js → webex-meetings-error.ts} +4 -2
  390. package/src/common/events/{events-scope.js → events-scope.ts} +6 -2
  391. package/src/common/events/{events.js → events.ts} +5 -1
  392. package/src/common/events/{trigger-proxy.js → trigger-proxy.ts} +9 -5
  393. package/src/common/events/{util.js → util.ts} +2 -3
  394. package/src/common/logs/{logger-config.js → logger-config.ts} +1 -2
  395. package/src/common/logs/logger-proxy.ts +44 -0
  396. package/src/common/logs/{request.js → request.ts} +26 -9
  397. package/src/common/queue.ts +22 -9
  398. package/src/{config.js → config.ts} +18 -19
  399. package/src/constants.ts +260 -22
  400. package/src/controls-options-manager/constants.ts +5 -0
  401. package/src/controls-options-manager/enums.ts +18 -0
  402. package/src/controls-options-manager/index.ts +278 -0
  403. package/src/controls-options-manager/types.ts +59 -0
  404. package/src/controls-options-manager/util.ts +300 -0
  405. package/src/index.ts +40 -0
  406. package/src/interpretation/README.md +60 -0
  407. package/src/interpretation/collection.ts +19 -0
  408. package/src/interpretation/index.ts +332 -0
  409. package/src/interpretation/siLanguage.ts +18 -0
  410. package/src/locus-info/controlsUtils.ts +222 -0
  411. package/src/locus-info/{embeddedAppsUtils.js → embeddedAppsUtils.ts} +5 -6
  412. package/src/locus-info/{fullState.js → fullState.ts} +16 -12
  413. package/src/locus-info/{hostUtils.js → hostUtils.ts} +9 -8
  414. package/src/locus-info/{index.js → index.ts} +557 -119
  415. package/src/locus-info/{infoUtils.js → infoUtils.ts} +29 -10
  416. package/src/locus-info/{mediaSharesUtils.js → mediaSharesUtils.ts} +81 -17
  417. package/src/locus-info/{parser.js → parser.ts} +303 -104
  418. package/src/locus-info/{selfUtils.js → selfUtils.ts} +199 -68
  419. package/src/media/index.ts +458 -0
  420. package/src/media/properties.ts +283 -0
  421. package/src/media/{util.js → util.ts} +2 -2
  422. package/src/mediaQualityMetrics/config.ts +384 -0
  423. package/src/meeting/in-meeting-actions.ts +191 -3
  424. package/src/meeting/index.ts +7882 -0
  425. package/src/meeting/locusMediaRequest.ts +313 -0
  426. package/src/meeting/muteState.ts +451 -0
  427. package/src/meeting/{request.js → request.ts} +421 -220
  428. package/src/meeting/request.type.ts +13 -0
  429. package/src/meeting/{state.js → state.ts} +50 -35
  430. package/src/meeting/util.ts +697 -0
  431. package/src/meeting-info/{collection.js → collection.ts} +6 -2
  432. package/src/meeting-info/index.ts +210 -0
  433. package/src/meeting-info/meeting-info-v2.ts +429 -0
  434. package/src/meeting-info/{request.js → request.ts} +14 -4
  435. package/src/meeting-info/{util.js → util.ts} +60 -51
  436. package/src/meeting-info/{utilv2.js → utilv2.ts} +78 -71
  437. package/src/meetings/{collection.js → collection.ts} +26 -3
  438. package/src/meetings/index.ts +1470 -0
  439. package/src/meetings/meetings.types.ts +12 -0
  440. package/src/meetings/{request.js → request.ts} +34 -25
  441. package/src/meetings/{util.js → util.ts} +132 -37
  442. package/src/member/{index.js → index.ts} +160 -56
  443. package/src/member/types.ts +38 -0
  444. package/src/member/util.ts +397 -0
  445. package/src/members/{collection.js → collection.ts} +10 -2
  446. package/src/members/{index.js → index.ts} +351 -146
  447. package/src/members/request.ts +255 -0
  448. package/src/members/types.ts +29 -0
  449. package/src/members/util.ts +353 -0
  450. package/src/metrics/{constants.js → constants.ts} +12 -6
  451. package/src/metrics/index.ts +73 -0
  452. package/src/multistream/mediaRequestManager.ts +337 -63
  453. package/src/multistream/receiveSlot.ts +69 -26
  454. package/src/multistream/receiveSlotManager.ts +66 -42
  455. package/src/multistream/remoteMedia.ts +40 -5
  456. package/src/multistream/remoteMediaGroup.ts +63 -3
  457. package/src/multistream/remoteMediaManager.ts +300 -66
  458. package/src/multistream/sendSlotManager.ts +170 -0
  459. package/src/networkQualityMonitor/{index.js → index.ts} +41 -29
  460. package/src/personal-meeting-room/{index.js → index.ts} +28 -19
  461. package/src/personal-meeting-room/{request.js → request.ts} +13 -4
  462. package/src/personal-meeting-room/{util.js → util.ts} +4 -4
  463. package/src/reachability/index.ts +671 -0
  464. package/src/reachability/request.ts +50 -35
  465. package/src/reactions/constants.ts +4 -0
  466. package/src/reactions/reactions.ts +104 -0
  467. package/src/reactions/reactions.type.ts +62 -0
  468. package/src/reconnection-manager/{index.js → index.ts} +258 -138
  469. package/src/recording-controller/enums.ts +8 -0
  470. package/src/recording-controller/index.ts +332 -0
  471. package/src/recording-controller/util.ts +75 -0
  472. package/src/roap/{index.js → index.ts} +127 -79
  473. package/src/roap/request.ts +153 -0
  474. package/src/roap/turnDiscovery.ts +109 -47
  475. package/src/rtcMetrics/constants.ts +3 -0
  476. package/src/rtcMetrics/index.ts +100 -0
  477. package/src/statsAnalyzer/global.ts +37 -0
  478. package/src/statsAnalyzer/index.ts +1250 -0
  479. package/src/statsAnalyzer/mqaUtil.ts +292 -0
  480. package/src/transcription/{index.js → index.ts} +46 -39
  481. package/src/webinar/collection.ts +31 -0
  482. package/src/webinar/index.ts +62 -0
  483. package/test/integration/spec/converged-space-meetings.js +233 -0
  484. package/test/integration/spec/journey.js +790 -530
  485. package/test/integration/spec/space-meeting.js +391 -204
  486. package/test/integration/spec/transcription.js +7 -8
  487. package/test/unit/spec/annotation/index.ts +418 -0
  488. package/test/unit/spec/breakouts/breakout.ts +237 -0
  489. package/test/unit/spec/breakouts/collection.ts +15 -0
  490. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  491. package/test/unit/spec/breakouts/events.ts +89 -0
  492. package/test/unit/spec/breakouts/index.ts +1790 -0
  493. package/test/unit/spec/breakouts/request.ts +104 -0
  494. package/test/unit/spec/breakouts/utils.js +72 -0
  495. package/test/unit/spec/common/browser-detection.js +9 -28
  496. package/test/unit/spec/common/queue.js +31 -2
  497. package/test/unit/spec/controls-options-manager/index.js +287 -0
  498. package/test/unit/spec/controls-options-manager/util.js +582 -0
  499. package/test/unit/spec/fixture/locus.js +93 -90
  500. package/test/unit/spec/interpretation/collection.ts +15 -0
  501. package/test/unit/spec/interpretation/index.ts +589 -0
  502. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  503. package/test/unit/spec/locus-info/controlsUtils.js +325 -32
  504. package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
  505. package/test/unit/spec/locus-info/index.js +1390 -17
  506. package/test/unit/spec/locus-info/infoUtils.js +71 -40
  507. package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
  508. package/test/unit/spec/locus-info/lib/SeqCmp.json +529 -685
  509. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  510. package/test/unit/spec/locus-info/parser.js +119 -44
  511. package/test/unit/spec/locus-info/selfConstant.js +120 -103
  512. package/test/unit/spec/locus-info/selfUtils.js +296 -12
  513. package/test/unit/spec/media/index.ts +128 -77
  514. package/test/unit/spec/media/properties.ts +11 -11
  515. package/test/unit/spec/meeting/in-meeting-actions.ts +92 -3
  516. package/test/unit/spec/meeting/index.js +7433 -2752
  517. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  518. package/test/unit/spec/meeting/muteState.js +420 -211
  519. package/test/unit/spec/meeting/request.js +545 -79
  520. package/test/unit/spec/meeting/utils.js +722 -174
  521. package/test/unit/spec/meeting-info/index.js +300 -0
  522. package/test/unit/spec/meeting-info/meetinginfov2.js +624 -76
  523. package/test/unit/spec/meeting-info/request.js +7 -9
  524. package/test/unit/spec/meeting-info/util.js +11 -12
  525. package/test/unit/spec/meeting-info/utilv2.js +131 -74
  526. package/test/unit/spec/meetings/collection.js +15 -1
  527. package/test/unit/spec/meetings/index.js +1365 -377
  528. package/test/unit/spec/meetings/utils.js +216 -14
  529. package/test/unit/spec/member/index.js +61 -7
  530. package/test/unit/spec/member/util.js +526 -26
  531. package/test/unit/spec/members/index.js +536 -55
  532. package/test/unit/spec/members/request.js +228 -40
  533. package/test/unit/spec/members/utils.js +217 -4
  534. package/test/unit/spec/metrics/index.js +12 -66
  535. package/test/unit/spec/multistream/mediaRequestManager.ts +1012 -109
  536. package/test/unit/spec/multistream/receiveSlot.ts +77 -18
  537. package/test/unit/spec/multistream/receiveSlotManager.ts +69 -39
  538. package/test/unit/spec/multistream/remoteMedia.ts +40 -2
  539. package/test/unit/spec/multistream/remoteMediaGroup.ts +271 -5
  540. package/test/unit/spec/multistream/remoteMediaManager.ts +738 -65
  541. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  542. package/test/unit/spec/networkQualityMonitor/index.js +24 -18
  543. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
  544. package/test/unit/spec/reachability/index.ts +598 -26
  545. package/test/unit/spec/reachability/request.js +68 -0
  546. package/test/unit/spec/reconnection-manager/index.js +181 -12
  547. package/test/unit/spec/recording-controller/index.js +307 -0
  548. package/test/unit/spec/recording-controller/util.js +229 -0
  549. package/test/unit/spec/roap/index.ts +179 -64
  550. package/test/unit/spec/roap/request.ts +232 -0
  551. package/test/unit/spec/roap/turnDiscovery.ts +123 -58
  552. package/test/unit/spec/rtcMetrics/index.ts +73 -0
  553. package/test/unit/spec/stats-analyzer/index.js +199 -60
  554. package/test/unit/spec/webinar/collection.ts +13 -0
  555. package/test/unit/spec/webinar/index.ts +60 -0
  556. package/test/utils/cmr.js +44 -42
  557. package/test/utils/constants.js +9 -0
  558. package/test/utils/integrationTestUtils.js +46 -0
  559. package/test/utils/testUtils.js +63 -99
  560. package/test/utils/webex-config.js +22 -18
  561. package/test/utils/webex-test-users.js +57 -50
  562. package/tsconfig.json +6 -0
  563. package/dist/media/internal-media-core-wrapper.js +0 -22
  564. package/dist/media/internal-media-core-wrapper.js.map +0 -1
  565. package/dist/meeting/effectsState.js +0 -327
  566. package/dist/meeting/effectsState.js.map +0 -1
  567. package/dist/metrics/config.js +0 -301
  568. package/dist/metrics/config.js.map +0 -1
  569. package/dist/multistream/multistreamMedia.js +0 -116
  570. package/dist/multistream/multistreamMedia.js.map +0 -1
  571. package/dist/peer-connection-manager/util.js +0 -124
  572. package/dist/peer-connection-manager/util.js.map +0 -1
  573. package/src/common/logs/logger-proxy.js +0 -33
  574. package/src/index.js +0 -15
  575. package/src/locus-info/controlsUtils.js +0 -102
  576. package/src/media/index.js +0 -459
  577. package/src/media/internal-media-core-wrapper.ts +0 -9
  578. package/src/media/properties.js +0 -289
  579. package/src/mediaQualityMetrics/config.js +0 -382
  580. package/src/meeting/effectsState.js +0 -205
  581. package/src/meeting/index.js +0 -6284
  582. package/src/meeting/muteState.js +0 -318
  583. package/src/meeting/util.js +0 -506
  584. package/src/meeting-info/index.js +0 -131
  585. package/src/meeting-info/meeting-info-v2.js +0 -255
  586. package/src/meetings/index.js +0 -1015
  587. package/src/member/util.js +0 -254
  588. package/src/members/request.js +0 -131
  589. package/src/members/util.js +0 -258
  590. package/src/metrics/config.js +0 -324
  591. package/src/metrics/index.js +0 -530
  592. package/src/multistream/multistreamMedia.ts +0 -92
  593. package/src/peer-connection-manager/util.ts +0 -117
  594. package/src/reachability/index.js +0 -464
  595. package/src/roap/request.js +0 -127
  596. package/src/statsAnalyzer/global.js +0 -133
  597. package/src/statsAnalyzer/index.js +0 -1006
  598. package/src/statsAnalyzer/mqaUtil.js +0 -173
  599. package/test/unit/spec/meeting/effectsState.js +0 -291
  600. package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -389
  601. /package/src/common/errors/{reconnection-in-progress.js → reconnection-in-progress.ts} +0 -0
@@ -0,0 +1,1470 @@
1
+ /* eslint no-shadow: ["error", { "allow": ["eventType"] }] */
2
+
3
+ import '@webex/internal-plugin-mercury';
4
+ import '@webex/internal-plugin-conversation';
5
+ import '@webex/internal-plugin-metrics';
6
+ // @ts-ignore
7
+ import {WebexPlugin} from '@webex/webex-core';
8
+ import {setLogger} from '@webex/internal-media-core';
9
+
10
+ import * as mediaHelpersModule from '@webex/media-helpers';
11
+
12
+ import 'webrtc-adapter';
13
+
14
+ import Metrics from '../metrics';
15
+ import LoggerConfig from '../common/logs/logger-config';
16
+ import StaticConfig from '../common/config';
17
+ import LoggerProxy from '../common/logs/logger-proxy';
18
+ import LoggerRequest from '../common/logs/request';
19
+ import Trigger from '../common/events/trigger-proxy';
20
+ import Media from '../media';
21
+ import MeetingUtil from '../meeting/util';
22
+ import {
23
+ MEETINGS,
24
+ EVENTS,
25
+ EVENT_TRIGGERS,
26
+ READY,
27
+ LOCUSEVENT,
28
+ LOCUS_URL,
29
+ MAX_RANDOM_DELAY_FOR_MEETING_INFO,
30
+ ROAP,
31
+ ONLINE,
32
+ OFFLINE,
33
+ _MEETING_,
34
+ _JOIN_,
35
+ _LOCUS_ID_,
36
+ _INCOMING_,
37
+ LOCUS,
38
+ CORRELATION_ID,
39
+ SIP_URI,
40
+ _LEFT_,
41
+ _ID_,
42
+ MEETING_REMOVED_REASON,
43
+ _CONVERSATION_URL_,
44
+ CONVERSATION_URL,
45
+ MEETINGNUMBER,
46
+ _JOINED_,
47
+ _MOVED_,
48
+ } from '../constants';
49
+ import BEHAVIORAL_METRICS from '../metrics/constants';
50
+ import MeetingInfo from '../meeting-info';
51
+ import MeetingInfoV2 from '../meeting-info/meeting-info-v2';
52
+ import Meeting from '../meeting';
53
+ import PersonalMeetingRoom from '../personal-meeting-room';
54
+ import Reachability from '../reachability';
55
+ import Request from './request';
56
+ import PasswordError from '../common/errors/password-error';
57
+ import CaptchaError from '../common/errors/captcha-error';
58
+
59
+ import MeetingCollection from './collection';
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';
65
+
66
+ let mediaLogger;
67
+
68
+ class MediaLogger {
69
+ info(...args) {
70
+ LoggerProxy.logger.info(...args);
71
+ }
72
+
73
+ log(...args) {
74
+ LoggerProxy.logger.log(...args);
75
+ }
76
+
77
+ error(...args) {
78
+ LoggerProxy.logger.error(...args);
79
+ }
80
+
81
+ warn(...args) {
82
+ LoggerProxy.logger.warn(...args);
83
+ }
84
+
85
+ trace(...args) {
86
+ LoggerProxy.logger.trace(...args);
87
+ }
88
+
89
+ debug(...args) {
90
+ LoggerProxy.logger.debug(...args);
91
+ }
92
+ }
93
+ /**
94
+ * Meetings Ready Event
95
+ * Emitted when the meetings instance on webex is ready
96
+ * @event meetings:ready
97
+ * @instance
98
+ * @memberof Meetings
99
+ */
100
+
101
+ /**
102
+ * Meetings Network Disconnected Event
103
+ * Emitted when the meetings instance is disconnected from
104
+ * the internal mercury server
105
+ * @event network:disconnected
106
+ * @instance
107
+ * @memberof Meetings
108
+ */
109
+
110
+ /**
111
+ * Meetings Registered Event
112
+ * Emitted when the meetings instance has been registered and listening
113
+ * @event meetings:registered
114
+ * @instance
115
+ * @memberof Meetings
116
+ */
117
+
118
+ /**
119
+ * Meeting Removed Event
120
+ * Emitted when a meeting was removed from the cache of meetings
121
+ * @event meeting:removed
122
+ * @instance
123
+ * @type {Object}
124
+ * @property {String} meetingId the removed meeting
125
+ * @property {Object} response the server response
126
+ * @property {String} type what type of meeting it was
127
+ * @memberof Meetings
128
+ */
129
+
130
+ /**
131
+ * Meeting Added Event
132
+ * Emitted when a meeting was added to the cache of meetings
133
+ * @event meeting:added
134
+ * @instance
135
+ * @type {Object}
136
+ * @property {String} meetingId the added meeting
137
+ * @property {String} type what type of meeting it was
138
+ * @memberof Meetings
139
+ */
140
+
141
+ /**
142
+ * Maintain a cache of meetings and sync with services.
143
+ * @class
144
+ */
145
+ export default class Meetings extends WebexPlugin {
146
+ loggerRequest: any;
147
+ media: any;
148
+ meetingCollection: any;
149
+ personalMeetingRoom: any;
150
+ preferredWebexSite: any;
151
+ reachability: Reachability;
152
+ registered: any;
153
+ request: any;
154
+ geoHintInfo: any;
155
+ meetingInfo: any;
156
+ mediaHelpers: any;
157
+ breakoutLocusForHandleLater: any;
158
+ namespace = MEETINGS;
159
+
160
+ /**
161
+ * Initializes the Meetings Plugin
162
+ * @constructor
163
+ * @public
164
+ * @memberof Meetings
165
+ */
166
+ constructor(...args) {
167
+ super(...args);
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
+
180
+ /**
181
+ * The Meetings request to interact with server
182
+ * @instance
183
+ * @type {Object}
184
+ * @private
185
+ * @memberof Meetings
186
+ */
187
+ // @ts-ignore
188
+ this.request = new Request({}, {parent: this.webex});
189
+ /**
190
+ * Log upload request helper
191
+ * @instance
192
+ * @type {Object}
193
+ * @private
194
+ * @memberof Meetings
195
+ */
196
+ // @ts-ignore
197
+ this.loggerRequest = new LoggerRequest({webex: this.webex});
198
+ this.meetingCollection = new MeetingCollection();
199
+ /**
200
+ * The PersonalMeetingRoom object to interact with server
201
+ * @instance
202
+ * @type {Object}
203
+ * @public
204
+ * @memberof Meetings
205
+ */
206
+ this.personalMeetingRoom = null;
207
+
208
+ /**
209
+ * The Reachability object to interact with server
210
+ * starts as null
211
+ * @instance
212
+ * @type {Object}
213
+ * @private
214
+ * @memberof Meetings
215
+ */
216
+ // @ts-ignore
217
+ this.reachability = new Reachability(this.webex);
218
+
219
+ /**
220
+ * If the meetings plugin has been registered and listening via {@link Meetings#register}
221
+ * @instance
222
+ * @type {Boolean}
223
+ * @public
224
+ * @memberof Meetings
225
+ */
226
+ this.registered = false;
227
+
228
+ /**
229
+ * This values indicates the preferred webex site the user will start there meeting, getsits value from {@link Meetings#register}
230
+ * @instance
231
+ * @type {String}
232
+ * @private
233
+ * @memberof Meetings
234
+ */
235
+ this.preferredWebexSite = '';
236
+
237
+ /**
238
+ * The public interface for the internal Media util files. These are helpful to expose outside the context
239
+ * of a meeting so that a user can access media without creating a meeting instance.
240
+ * @instance
241
+ * @type {Object}
242
+ * @private
243
+ * @memberof Meetings
244
+ */
245
+ this.media = {
246
+ getUserMedia: Media.getUserMedia,
247
+ };
248
+
249
+ this.onReady();
250
+ }
251
+
252
+ /**
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
366
+ * @param {Object} data a locus event
367
+ * @param {String} data.locusUrl
368
+ * @param {Object} data.locus
369
+ * @returns {Object}
370
+ * @private
371
+ * @memberof Meetings
372
+ */
373
+ getCorrespondingMeetingByLocus(data) {
374
+ // getting meeting by correlationId. This will happen for the new event
375
+ // Either the locus
376
+ // TODO : Add check for the callBack Address
377
+ return (
378
+ this.meetingCollection.getByKey(LOCUS_URL, data.locusUrl) ||
379
+ // @ts-ignore
380
+ this.meetingCollection.getByKey(
381
+ CORRELATION_ID,
382
+ // @ts-ignore
383
+ MeetingsUtil.checkForCorrelationId(this.webex.internal.device.url, data.locus)
384
+ ) ||
385
+ this.meetingCollection.getByKey(
386
+ SIP_URI,
387
+ data.locus.self &&
388
+ data.locus.self.callbackInfo &&
389
+ data.locus.self.callbackInfo.callbackAddress
390
+ ) ||
391
+ (data.locus.info?.isUnifiedSpaceMeeting
392
+ ? undefined
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);
411
+
412
+ // Special case when locus has got replaced, This only happend once if a replace locus exists
413
+ // https://sqbu-github.cisco.com/WebExSquared/locus/wiki/Locus-changing-mid-call
414
+
415
+ if (!meeting && data.locus?.replaces?.length > 0) {
416
+ // Always the last element in the replace is the active one
417
+ meeting = this.meetingCollection.getByKey(
418
+ LOCUS_URL,
419
+ data.locus.replaces[data.locus.replaces.length - 1].locusUrl
420
+ );
421
+ }
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
+ }
433
+ if (!meeting) {
434
+ // TODO: create meeting when we get a meeting object
435
+ // const checkForEnded = (locus) => {
436
+ // TODO: you already ended the meeting but you got an event later
437
+ // Mainly for 1:1 Callsor meeting
438
+ // Happens mainly after refresh
439
+
440
+ // 1:1 Meeting
441
+ // 1) You ended a call before but you got a mercury event
442
+ // Make sure end the call and cleanup the meeting only if the mercury
443
+ // event says so
444
+ // 2) Maintain lastSync time in the meetings object which helps to compare
445
+ // If the meeting came befor or after the sync . ANy meeting start time before the sync time is invalid
446
+
447
+ // For space Meeting
448
+ // Check the locus object and see who has joined
449
+
450
+ // };
451
+ // rather then locus object change to locus url
452
+
453
+ if (
454
+ data.locus &&
455
+ data.locus.fullState &&
456
+ data.locus.fullState.state === LOCUS.STATE.INACTIVE
457
+ ) {
458
+ // just ignore the event as its already ended and not active
459
+ LoggerProxy.logger.warn(
460
+ 'Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.'
461
+ );
462
+
463
+ return;
464
+ }
465
+
466
+ // When its wireless share or guest and user leaves the meeting we dont have to keep the meeting object
467
+ // Any future events will be neglected
468
+
469
+ if (
470
+ data.locus &&
471
+ data.locus.self &&
472
+ data.locus.self.state === _LEFT_ &&
473
+ data.locus.self.removed === true
474
+ ) {
475
+ // just ignore the event as its already ended and not active
476
+ LoggerProxy.logger.warn(
477
+ 'Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.'
478
+ );
479
+
480
+ return;
481
+ }
482
+
483
+ this.create(data.locus, _LOCUS_ID_, useRandomDelayForInfo)
484
+ .then((newMeeting) => {
485
+ meeting = newMeeting;
486
+
487
+ // It's a new meeting so initialize the locus data
488
+ meeting.locusInfo.initialSetup(data.locus);
489
+ this.checkHandleBreakoutLocus(data.locus);
490
+ })
491
+ .catch((e) => {
492
+ LoggerProxy.logger.error(e);
493
+ })
494
+ .finally(() => {
495
+ // There will be cases where locus event comes in gets created and deleted because its a 1:1 and meeting gets deleted
496
+ // because the other user left so before sending 'added' event make sure it exists in the collection
497
+
498
+ if (this.getMeetingByType(_ID_, meeting.id)) {
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
+ },
508
+ });
509
+ Trigger.trigger(
510
+ this,
511
+ {
512
+ file: 'meetings',
513
+ function: 'handleLocusEvent',
514
+ },
515
+ EVENT_TRIGGERS.MEETING_ADDED,
516
+ {
517
+ meeting,
518
+ type: meeting.type === _MEETING_ ? _JOIN_ : _INCOMING_,
519
+ }
520
+ );
521
+ } else {
522
+ // Meeting got added but was not found in the collection. It might have got destroyed
523
+ LoggerProxy.logger.warn(
524
+ 'Meetings:index#handleLocusEvent --> Created and destroyed meeting object before sending an event'
525
+ );
526
+ }
527
+ });
528
+ } else {
529
+ meeting.locusInfo.parse(meeting, data);
530
+ }
531
+ }
532
+
533
+ /**
534
+ * handles locus events through mercury that are not roap
535
+ * @param {Object} envelope
536
+ * @param {Object} envelope.data
537
+ * @param {String} envelope.data.eventType
538
+ * @returns {undefined}
539
+ * @private
540
+ * @memberof Meetings
541
+ */
542
+ private handleLocusMercury(envelope: {data: any}) {
543
+ const {data} = envelope;
544
+ // eslint-disable-next-line @typescript-eslint/no-shadow
545
+ const {eventType} = data;
546
+
547
+ if (eventType && eventType !== LOCUSEVENT.MESSAGE_ROAP) {
548
+ this.handleLocusEvent(data, true);
549
+ }
550
+ }
551
+
552
+ /**
553
+ * handles mecury offline event
554
+ * @returns {undefined}
555
+ * @private
556
+ * @memberof Meetings
557
+ */
558
+ private handleMercuryOffline() {
559
+ Trigger.trigger(
560
+ this,
561
+ {
562
+ file: 'meetings/index',
563
+ function: 'handleMercuryOffline',
564
+ },
565
+ EVENT_TRIGGERS.MEETINGS_NETWORK_DISCONNECTED
566
+ );
567
+ }
568
+
569
+ /**
570
+ * registers for locus and roap mercury events
571
+ * @returns {undefined}
572
+ * @private
573
+ * @memberof Meetings
574
+ */
575
+ private listenForEvents() {
576
+ // @ts-ignore
577
+ this.webex.internal.mercury.on(LOCUSEVENT.LOCUS_MERCURY, (envelope) => {
578
+ this.handleLocusMercury(envelope);
579
+ });
580
+ // @ts-ignore
581
+ this.webex.internal.mercury.on(ROAP.ROAP_MERCURY, (envelope) => {
582
+ MeetingsUtil.handleRoapMercury(envelope, this.meetingCollection);
583
+ });
584
+
585
+ // @ts-ignore
586
+ this.webex.internal.mercury.on(ONLINE, () => {
587
+ this.syncMeetings();
588
+ });
589
+
590
+ // @ts-ignore
591
+ this.webex.internal.mercury.on(OFFLINE, () => {
592
+ this.handleMercuryOffline();
593
+ });
594
+ }
595
+
596
+ /**
597
+ * stops listening for locus and roap mercury events
598
+ * @returns {undefined}
599
+ * @private
600
+ * @memberof Meetings
601
+ */
602
+ private stopListeningForEvents() {
603
+ // @ts-ignore
604
+ this.webex.internal.mercury.off(LOCUSEVENT.LOCUS_MERCURY);
605
+ // @ts-ignore
606
+ this.webex.internal.mercury.off(ROAP.ROAP_MERCURY);
607
+ // @ts-ignore
608
+ this.webex.internal.mercury.off(ONLINE);
609
+ }
610
+
611
+ /**
612
+ * @returns {undefined}
613
+ * @private
614
+ * @memberof Meetings
615
+ */
616
+ private onReady() {
617
+ // @ts-ignore
618
+ this.webex.once(READY, () => {
619
+ // @ts-ignore
620
+ StaticConfig.set(this.config);
621
+ // @ts-ignore
622
+ LoggerConfig.set(this.config.logging);
623
+ // @ts-ignore
624
+ LoggerProxy.set(this.webex.logger);
625
+
626
+ mediaLogger = new MediaLogger();
627
+ setLogger(mediaLogger);
628
+
629
+ /**
630
+ * The MeetingInfo object to interact with server
631
+ * @instance
632
+ * @type {Object}
633
+ * @private
634
+ * @memberof Meetings
635
+ */
636
+ // @ts-ignore
637
+ this.meetingInfo = this.config.experimental.enableUnifiedMeetings
638
+ ? // @ts-ignore
639
+ new MeetingInfoV2(this.webex)
640
+ : // @ts-ignore
641
+ new MeetingInfo(this.webex);
642
+ // @ts-ignore
643
+ this.personalMeetingRoom = new PersonalMeetingRoom(
644
+ {meetingInfo: this.meetingInfo},
645
+ // @ts-ignore
646
+ {parent: this.webex}
647
+ );
648
+
649
+ Trigger.trigger(
650
+ this,
651
+ {
652
+ file: 'meetings',
653
+ function: 'onReady',
654
+ },
655
+ EVENT_TRIGGERS.MEETINGS_READY
656
+ );
657
+
658
+ MeetingsUtil.checkH264Support({disableNotifications: true});
659
+ // @ts-ignore
660
+ Metrics.initialSetup(this.webex);
661
+ });
662
+ }
663
+
664
+ /**
665
+ * API to toggle unified meetings
666
+ * @param {Boolean} changeState
667
+ * @private
668
+ * @memberof Meetings
669
+ * @returns {undefined}
670
+ */
671
+ private _toggleUnifiedMeetings(changeState: boolean) {
672
+ if (typeof changeState !== 'boolean') {
673
+ return;
674
+ }
675
+ // @ts-ignore
676
+ if (this.config?.experimental?.enableUnifiedMeetings !== changeState) {
677
+ // @ts-ignore
678
+ this.config.experimental.enableUnifiedMeetings = changeState;
679
+ // @ts-ignore
680
+ this.meetingInfo = changeState ? new MeetingInfoV2(this.webex) : new MeetingInfo(this.webex);
681
+ }
682
+ }
683
+
684
+ /**
685
+ * API to toggle starting adhoc meeting
686
+ * @param {Boolean} changeState
687
+ * @private
688
+ * @memberof Meetings
689
+ * @returns {undefined}
690
+ */
691
+ private _toggleAdhocMeetings(changeState: boolean) {
692
+ if (typeof changeState !== 'boolean') {
693
+ return;
694
+ }
695
+ // @ts-ignore
696
+ if (this.config?.experimental?.enableAdhocMeetings !== changeState) {
697
+ // @ts-ignore
698
+ this.config.experimental.enableAdhocMeetings = changeState;
699
+ }
700
+ }
701
+
702
+ /**
703
+ * Explicitly sets up the meetings plugin by registering
704
+ * the device, connecting to mercury, and listening for locus events.
705
+ *
706
+ * @returns {Promise}
707
+ * @public
708
+ * @memberof Meetings
709
+ */
710
+ public register() {
711
+ // @ts-ignore
712
+ if (!this.webex.canAuthorize) {
713
+ LoggerProxy.logger.error(
714
+ 'Meetings:index#register --> ERROR, Unable to register, SDK cannot authorize'
715
+ );
716
+
717
+ return Promise.reject(new Error('SDK cannot authorize'));
718
+ }
719
+
720
+ if (this.registered) {
721
+ LoggerProxy.logger.info(
722
+ 'Meetings:index#register --> INFO, Meetings plugin already registered'
723
+ );
724
+
725
+ return Promise.resolve();
726
+ }
727
+
728
+ return Promise.all([
729
+ this.fetchUserPreferredWebexSite(),
730
+ this.getGeoHint(),
731
+ this.startReachability().catch((error) => {
732
+ LoggerProxy.logger.error(`Meetings:index#register --> GDM error, ${error.message}`);
733
+ }),
734
+ // @ts-ignore
735
+ this.webex.internal.device
736
+ .register()
737
+ // @ts-ignore
738
+ .then(() =>
739
+ LoggerProxy.logger.info(
740
+ // @ts-ignore
741
+ `Meetings:index#register --> INFO, Device registered ${this.webex.internal.device.url}`
742
+ )
743
+ )
744
+ // @ts-ignore
745
+ .then(() => this.webex.internal.mercury.connect()),
746
+ MeetingsUtil.checkH264Support.call(this),
747
+ ])
748
+ .then(() => {
749
+ this.listenForEvents();
750
+ Trigger.trigger(
751
+ this,
752
+ {
753
+ file: 'meetings',
754
+ function: 'register',
755
+ },
756
+ EVENT_TRIGGERS.MEETINGS_REGISTERED
757
+ );
758
+ this.registered = true;
759
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETINGS_REGISTRATION_SUCCESS);
760
+ })
761
+ .catch((error) => {
762
+ LoggerProxy.logger.error(
763
+ `Meetings:index#register --> ERROR, Unable to register, ${error.message}`
764
+ );
765
+
766
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETINGS_REGISTRATION_FAILED, {
767
+ reason: error.message,
768
+ stack: error.stack,
769
+ });
770
+
771
+ return Promise.reject(error);
772
+ });
773
+ }
774
+
775
+ /**
776
+ * Explicitly tears down the meetings plugin by deregistering
777
+ * the device, disconnecting from mercury, and stops listening to locus events
778
+ *
779
+ * @returns {Promise}
780
+ * @public
781
+ * @memberof Meetings
782
+ */
783
+ unregister() {
784
+ if (!this.registered) {
785
+ LoggerProxy.logger.info(
786
+ 'Meetings:index#unregister --> INFO, Meetings plugin already unregistered'
787
+ );
788
+
789
+ return Promise.resolve();
790
+ }
791
+
792
+ this.stopListeningForEvents();
793
+
794
+ return (
795
+ // @ts-ignore
796
+ this.webex.internal.mercury
797
+ .disconnect()
798
+ // @ts-ignore
799
+ .then(() => this.webex.internal.device.unregister())
800
+ .then(() => {
801
+ Trigger.trigger(
802
+ this,
803
+ {
804
+ file: 'meetings',
805
+ function: 'unregister',
806
+ },
807
+ EVENT_TRIGGERS.MEETINGS_UNREGISTERED
808
+ );
809
+ this.registered = false;
810
+ })
811
+ );
812
+ }
813
+
814
+ /**
815
+ * Creates a noise reduction effect
816
+ *
817
+ * @param {INoiseReductionEffect} options optional custom effect options
818
+ * @returns {Promise<effect>} noise reduction effect.
819
+ * @public
820
+ * @memberof Meetings
821
+ */
822
+ createNoiseReductionEffect = async (options?: INoiseReductionEffect) => {
823
+ // @ts-ignore
824
+ const authToken = this.webex.credentials.supertoken.access_token;
825
+
826
+ return new mediaHelpersModule.NoiseReductionEffect({authToken, ...options});
827
+ };
828
+
829
+ /**
830
+ * Creates a virtual background effect
831
+ *
832
+ * @param {IVirtualBackgroundEffect} options optional custom effect options
833
+ * @returns {Promise<effect>} virtual background effect.
834
+ * @public
835
+ * @memberof Meetings
836
+ */
837
+ createVirtualBackgroundEffect = async (options?: IVirtualBackgroundEffect) => {
838
+ // @ts-ignore
839
+ const authToken = this.webex.credentials.supertoken.access_token;
840
+
841
+ return new mediaHelpersModule.VirtualBackgroundEffect({authToken, ...options});
842
+ };
843
+
844
+ /**
845
+ * Uploads logs to the webex services for tracking
846
+ * @param {Object} [options={}]
847
+ * @param {String} [options.callStart] Call Start Time
848
+ * @param {String} [options.feedbackId] ID used for tracking
849
+ * @param {String} [options.locusId]
850
+ * @param {String} [options.correlationId]
851
+ * @param {String} [options.meetingId] webex meeting ID
852
+ * @param {String} [options.userId] userId
853
+ * @param {String} [options.orgId] org id
854
+ * @returns {String} feedback ID logs were submitted under
855
+ */
856
+ uploadLogs(
857
+ options: {
858
+ autoupload?: boolean;
859
+ callStart?: string;
860
+ feedbackId?: string;
861
+ locussessionid?: string;
862
+ locusId?: string;
863
+ correlationId?: string;
864
+ meetingId?: string;
865
+ userId?: string;
866
+ orgId?: string;
867
+ } = {}
868
+ ) {
869
+ LoggerProxy.logger.info('Meetings:index#uploadLogs --> uploading logs');
870
+
871
+ return this.loggerRequest
872
+ .uploadLogs(options)
873
+ .then((uploadResult) => {
874
+ LoggerProxy.logger.info(
875
+ 'Meetings:index#uploadLogs --> Upload logs for meeting completed.',
876
+ uploadResult
877
+ );
878
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UPLOAD_LOGS_SUCCESS, options);
879
+ Trigger.trigger(
880
+ this,
881
+ {
882
+ file: 'meetings',
883
+ function: 'uploadLogs',
884
+ },
885
+ EVENT_TRIGGERS.MEETING_LOG_UPLOAD_SUCCESS,
886
+ {
887
+ meetingId: options.meetingId,
888
+ details: uploadResult,
889
+ }
890
+ );
891
+
892
+ return uploadResult;
893
+ })
894
+ .catch((uploadError) => {
895
+ LoggerProxy.logger.error(
896
+ 'Meetings:index#uploadLogs --> Unable to upload logs for meeting',
897
+ uploadError
898
+ );
899
+ Trigger.trigger(
900
+ this,
901
+ {
902
+ file: 'meetings',
903
+ function: 'uploadLogs',
904
+ },
905
+ EVENT_TRIGGERS.MEETING_LOG_UPLOAD_FAILURE,
906
+ {
907
+ meetingId: options.meetingId,
908
+ reason: uploadError,
909
+ }
910
+ );
911
+
912
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UPLOAD_LOGS_FAILURE, {
913
+ ...options,
914
+ reason: uploadError.message,
915
+ stack: uploadError.stack,
916
+ code: uploadError.code,
917
+ });
918
+ });
919
+ }
920
+
921
+ /**
922
+ * gets the reachability instance for Meetings
923
+ * @returns {Reachability}
924
+ * @public
925
+ * @memberof Meetings
926
+ */
927
+ getReachability() {
928
+ return this.reachability;
929
+ }
930
+
931
+ /**
932
+ * initializes and starts gathering reachability for Meetings
933
+ * @returns {Promise}
934
+ * @public
935
+ * @memberof Meetings
936
+ */
937
+ startReachability() {
938
+ return this.getReachability().gatherReachability();
939
+ }
940
+
941
+ /**
942
+ * Get geoHint for info for meetings
943
+ * @returns {Promise}
944
+ * @private
945
+ * @memberof Meetings
946
+ */
947
+ getGeoHint() {
948
+ return this.request.fetchGeoHint().then((res) => {
949
+ this.geoHintInfo = res;
950
+ });
951
+ }
952
+
953
+ /**
954
+ * Fetch user preferred webex site information
955
+ * This also has other infomation about the user
956
+ * @returns {Promise}
957
+ * @private
958
+ * @memberof Meetings
959
+ */
960
+ fetchUserPreferredWebexSite() {
961
+ return this.request.getMeetingPreferences().then((res) => {
962
+ if (res) {
963
+ this.preferredWebexSite = MeetingsUtil.parseDefaultSiteFromMeetingPreferences(res);
964
+ }
965
+
966
+ // fall back to getting the preferred site from the user information
967
+ if (!this.preferredWebexSite) {
968
+ // @ts-ignore
969
+ return this.webex.internal.user
970
+ .get()
971
+ .then((user) => {
972
+ const preferredWebexSite =
973
+ user?.userPreferences?.userPreferencesItems?.preferredWebExSite;
974
+ if (preferredWebexSite) {
975
+ this.preferredWebexSite = preferredWebexSite;
976
+ } else {
977
+ throw new Error('site not found');
978
+ }
979
+ })
980
+ .catch(() => {
981
+ LoggerProxy.logger.error(
982
+ 'Failed to fetch preferred site from user - no site will be set'
983
+ );
984
+ });
985
+ }
986
+
987
+ return Promise.resolve();
988
+ });
989
+ }
990
+
991
+ /**
992
+ * gets the personal meeting room instance, for saved PMR values for this user
993
+ * @returns {PersonalMeetingRoom}
994
+ * @public
995
+ * @memberof Meetings
996
+ */
997
+
998
+ getPersonalMeetingRoom() {
999
+ return this.personalMeetingRoom;
1000
+ }
1001
+
1002
+ /**
1003
+ * @param {Meeting} meeting
1004
+ * @param {Object} reason
1005
+ * @param {String} type
1006
+ * @returns {Undefined}
1007
+ * @private
1008
+ * @memberof Meetings
1009
+ */
1010
+ private destroy(meeting: Meeting, reason: object) {
1011
+ MeetingUtil.cleanUp(meeting);
1012
+ this.meetingCollection.delete(meeting.id);
1013
+ Trigger.trigger(
1014
+ this,
1015
+ {
1016
+ file: 'meetings',
1017
+ function: 'destroy',
1018
+ },
1019
+ EVENT_TRIGGERS.MEETING_REMOVED,
1020
+ {
1021
+ meetingId: meeting.id,
1022
+ reason,
1023
+ }
1024
+ );
1025
+ }
1026
+
1027
+ /**
1028
+ * Create a meeting.
1029
+ * @param {string} destination - sipURL, phonenumber, or locus object}
1030
+ * @param {string} [type] - the optional specified type, such as locusId
1031
+ * @param {Boolean} useRandomDelayForInfo - whether a random delay should be added to fetching meeting info
1032
+ * @param {Object} infoExtraParams extra parameters to be provided when fetching meeting info
1033
+ * @param {string} correlationId - the optional specified correlationId
1034
+ * @param {Boolean} failOnMissingMeetingInfo - whether to throw an error if meeting info fails to fetch (for calls that are not 1:1 or content share)
1035
+ * @returns {Promise<Meeting>} A new Meeting.
1036
+ * @public
1037
+ * @memberof Meetings
1038
+ */
1039
+ public create(
1040
+ destination: string,
1041
+ type: string = null,
1042
+ useRandomDelayForInfo = false,
1043
+ infoExtraParams = {},
1044
+ correlationId: string = undefined,
1045
+ failOnMissingMeetingInfo = false
1046
+ ) {
1047
+ // TODO: type should be from a dictionary
1048
+
1049
+ // Validate meeting information based on the provided destination and
1050
+ // type. This must be performed prior to determining if the meeting is
1051
+ // found in the collection, as we mutate the destination for hydra person
1052
+ // id values.
1053
+ return (
1054
+ this.meetingInfo
1055
+ .fetchInfoOptions(destination, type)
1056
+ // Catch a failure to fetch info options.
1057
+ .catch((error) => {
1058
+ LoggerProxy.logger.error(
1059
+ `Meetings:index#create --> ERROR, unable to determine info options: ${error.message}`
1060
+ );
1061
+ if (error instanceof SpaceIDDeprecatedError) {
1062
+ throw new SpaceIDDeprecatedError();
1063
+ }
1064
+ })
1065
+ .then((options: any = {}) => {
1066
+ // Normalize the destination.
1067
+ const targetDest = options.destination || destination;
1068
+
1069
+ // check for the conversation URL then sip Url
1070
+ let meeting = null;
1071
+
1072
+ if (type === _CONVERSATION_URL_ || options.type === _CONVERSATION_URL_) {
1073
+ const foundMeeting = this.meetingCollection.getByKey(CONVERSATION_URL, targetDest);
1074
+
1075
+ if (foundMeeting) {
1076
+ const foundMeetingIsNotCalendarMeeting = !foundMeeting.locusInfo.scheduledMeeting;
1077
+
1078
+ // If the found meeting is not a calendar meeting, return that meeting.
1079
+ // This allows for the creation of instant-meetings when calendar meetings are present.
1080
+ if (foundMeetingIsNotCalendarMeeting) {
1081
+ meeting = foundMeeting;
1082
+ }
1083
+ }
1084
+ }
1085
+
1086
+ // Attempt to collect the meeting if it exists.
1087
+ if (!meeting) {
1088
+ meeting = this.meetingCollection.getByKey(SIP_URI, targetDest);
1089
+ }
1090
+
1091
+ // Validate if a meeting was found.
1092
+ if (!meeting) {
1093
+ // Create a meeting based on the normalized destination and type.
1094
+ return this.createMeeting(
1095
+ targetDest,
1096
+ type,
1097
+ useRandomDelayForInfo,
1098
+ infoExtraParams,
1099
+ correlationId,
1100
+ failOnMissingMeetingInfo
1101
+ ).then((createdMeeting: any) => {
1102
+ // If the meeting was successfully created.
1103
+ if (createdMeeting && createdMeeting.on) {
1104
+ // Create a destruction event for the meeting.
1105
+ createdMeeting.on(EVENTS.DESTROY_MEETING, (payload) => {
1106
+ // @ts-ignore
1107
+ if (this.config.autoUploadLogs) {
1108
+ this.uploadLogs({
1109
+ callStart: createdMeeting.locusInfo?.fullState?.lastActive,
1110
+ locussessionid: createdMeeting.locusInfo?.fullState?.sessionId,
1111
+ correlationId: createdMeeting.correlationId,
1112
+ feedbackId: createdMeeting.correlationId,
1113
+ locusId: createdMeeting.locusId,
1114
+ meetingId: createdMeeting.locusInfo?.info?.webExMeetingId,
1115
+ autoupload: true,
1116
+ }).then(() => this.destroy(createdMeeting, payload.reason));
1117
+ } else {
1118
+ this.destroy(createdMeeting, payload.reason);
1119
+ }
1120
+ });
1121
+
1122
+ createdMeeting.on(EVENTS.REQUEST_UPLOAD_LOGS, (meetingInstance) => {
1123
+ // @ts-ignore
1124
+ if (this.config.autoUploadLogs) {
1125
+ this.uploadLogs({
1126
+ callStart: meetingInstance?.locusInfo?.fullState?.lastActive,
1127
+ locussessionid: meetingInstance?.locusInfo?.fullState?.sessionId,
1128
+ correlationId: meetingInstance.correlationId,
1129
+ feedbackId: meetingInstance.correlationId,
1130
+ locusId: meetingInstance.locusId,
1131
+ meetingId: meetingInstance.locusInfo?.info?.webExMeetingId,
1132
+ autoupload: true,
1133
+ });
1134
+ }
1135
+ });
1136
+ } else {
1137
+ LoggerProxy.logger.error(
1138
+ `Meetings:index#create --> ERROR, meeting does not have on method, will not be destroyed, meeting cleanup impossible for meeting: ${meeting}`
1139
+ );
1140
+ }
1141
+
1142
+ // Return the newly created meeting.
1143
+ return Promise.resolve(createdMeeting);
1144
+ });
1145
+ }
1146
+
1147
+ // Return the existing meeting.
1148
+ return Promise.resolve(meeting);
1149
+ })
1150
+ );
1151
+ }
1152
+
1153
+ /**
1154
+ * @param {String} destination see create()
1155
+ * @param {String} type see create()
1156
+ * @param {Boolean} useRandomDelayForInfo whether a random delay should be added to fetching meeting info
1157
+ * @param {Object} infoExtraParams extra parameters to be provided when fetching meeting info
1158
+ * @param {String} correlationId the optional specified correlationId
1159
+ * @param {Boolean} failOnMissingMeetingInfo - whether to throw an error if meeting info fails to fetch (for calls that are not 1:1 or content share)
1160
+ * @returns {Promise} a new meeting instance complete with meeting info and destination
1161
+ * @private
1162
+ * @memberof Meetings
1163
+ */
1164
+ private async createMeeting(
1165
+ destination: any,
1166
+ type: string = null,
1167
+ useRandomDelayForInfo = false,
1168
+ infoExtraParams = {},
1169
+ correlationId: string = undefined,
1170
+ failOnMissingMeetingInfo = false
1171
+ ) {
1172
+ const meeting = new Meeting(
1173
+ {
1174
+ // @ts-ignore
1175
+ userId: this.webex.internal.device.userId,
1176
+ // @ts-ignore
1177
+ deviceUrl: this.webex.internal.device.url,
1178
+ // @ts-ignore
1179
+ orgId: this.webex.internal.device.orgId,
1180
+ locus: type === _LOCUS_ID_ ? destination : null, // pass the locus object if present
1181
+ meetingInfoProvider: this.meetingInfo,
1182
+ destination,
1183
+ destinationType: type,
1184
+ correlationId,
1185
+ },
1186
+ {
1187
+ // @ts-ignore
1188
+ parent: this.webex,
1189
+ }
1190
+ );
1191
+
1192
+ this.meetingCollection.set(meeting);
1193
+
1194
+ try {
1195
+ // if no participant has joined the scheduled meeting (meaning meeting is not active) and we get a locusEvent,
1196
+ // it means the meeting will start in 5-6 min. In that case, we want to fetchMeetingInfo
1197
+ // between 5 and 2 min (random between 3 minutes) before the meeting starts
1198
+ // to avoid a spike in traffic to the wbxappi service
1199
+ let waitingTime = 0;
1200
+
1201
+ if (destination.meeting) {
1202
+ const {startTime} = destination.meeting;
1203
+ const startTimeDate = new Date(startTime);
1204
+ const startTimeDatestamp = startTimeDate.getTime();
1205
+ const timeToStart = startTimeDatestamp - Date.now();
1206
+ const maxWaitingTime = Math.max(
1207
+ Math.min(timeToStart, MAX_RANDOM_DELAY_FOR_MEETING_INFO),
1208
+ 0
1209
+ );
1210
+
1211
+ waitingTime = Math.round(Math.random() * maxWaitingTime);
1212
+ }
1213
+ const isMeetingActive = !!destination.fullState?.active;
1214
+ // @ts-ignore
1215
+ const {enableUnifiedMeetings} = this.config.experimental;
1216
+
1217
+ if (enableUnifiedMeetings && !isMeetingActive && useRandomDelayForInfo && waitingTime > 0) {
1218
+ meeting.fetchMeetingInfoTimeoutId = setTimeout(
1219
+ () =>
1220
+ meeting.fetchMeetingInfo({
1221
+ extraParams: infoExtraParams,
1222
+ sendCAevents: !!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
1223
+ }),
1224
+ waitingTime
1225
+ );
1226
+ meeting.parseMeetingInfo(undefined, destination);
1227
+ } else {
1228
+ await meeting.fetchMeetingInfo({
1229
+ extraParams: infoExtraParams,
1230
+ sendCAevents: !!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
1231
+ });
1232
+ }
1233
+ } catch (err) {
1234
+ if (
1235
+ !(err instanceof CaptchaError) &&
1236
+ !(err instanceof PasswordError) &&
1237
+ !(err instanceof PermissionError)
1238
+ ) {
1239
+ LoggerProxy.logger.info(
1240
+ `Meetings:index#createMeeting --> Info Unable to fetch meeting info for ${destination}.`
1241
+ );
1242
+ if (failOnMissingMeetingInfo) {
1243
+ LoggerProxy.logger.info(
1244
+ `Meetings:index#createMeeting --> Destroying meeting due to missing meeting info.`
1245
+ );
1246
+ // @ts-ignore
1247
+ this.destroy(meeting, MEETING_REMOVED_REASON.MISSING_MEETING_INFO);
1248
+ throw new NoMeetingInfoError();
1249
+ }
1250
+ // if there is no meeting info and no error should be thrown then we assume its a 1:1 call or wireless share
1251
+ LoggerProxy.logger.info(
1252
+ 'Meetings:index#createMeeting --> Info assuming this destination is a 1:1 or wireless share'
1253
+ );
1254
+ }
1255
+ LoggerProxy.logger.debug(
1256
+ `Meetings:index#createMeeting --> Debug ${err} fetching /meetingInfo for creation.`
1257
+ );
1258
+ } finally {
1259
+ // For type LOCUS_ID we need to parse the locus object to get the information
1260
+ // about the caller and callee
1261
+ // Meeting Added event will be created in `handleLocusEvent`
1262
+ if (type !== _LOCUS_ID_) {
1263
+ if (!meeting.sipUri) {
1264
+ meeting.setSipUri(destination);
1265
+ }
1266
+
1267
+ // TODO: check if we have to move this to parser
1268
+ const meetingAddedType = MeetingsUtil.getMeetingAddedType(type);
1269
+
1270
+ // We typically shouldn't need to trigger both and event and return a promise.
1271
+ // Is this a special case? We want to make the public API usage as simple as possible.
1272
+ Trigger.trigger(
1273
+ this,
1274
+ {
1275
+ file: 'meetings',
1276
+ function: 'createMeeting',
1277
+ },
1278
+ EVENT_TRIGGERS.MEETING_ADDED,
1279
+ {
1280
+ meeting,
1281
+ type: meetingAddedType,
1282
+ }
1283
+ );
1284
+ }
1285
+ }
1286
+
1287
+ return meeting;
1288
+
1289
+ // Create the meeting calling the necessary service endpoints.
1290
+
1291
+ // Internally, there are many more destinations:
1292
+ //
1293
+ // - locusID
1294
+ // - meetingURL
1295
+ // - globalMeetingID, e.g, *00*meetingID
1296
+ // - meetingID
1297
+ // - meetingURL
1298
+ // - PSTN
1299
+ // - phone number
1300
+ //
1301
+ // Our job is to determine the appropriate one
1302
+ // and its corresponding service so that developers
1303
+ // need only sipURL to get a meeting
1304
+ // and its ID, but have the option to use createWithType()
1305
+ // and specify those types to get meetingInfo
1306
+ }
1307
+
1308
+ /**
1309
+ * get a specifc meeting given it's type matched to the value, i.e., locus url
1310
+ * @param {String} type
1311
+ * @param {Object} value
1312
+ * @returns {Meeting}
1313
+ * @public
1314
+ * @memberof Meetings
1315
+ */
1316
+ public getMeetingByType(type: string, value: object) {
1317
+ return this.meetingCollection.getByKey(type, value);
1318
+ }
1319
+
1320
+ /**
1321
+ * Get all meetings.
1322
+ * @param {object} options
1323
+ * @param {object} options.startDate - get meetings after this start date
1324
+ * @param {object} options.endDate - get meetings before this end date
1325
+ * @returns {Object} All currently active meetings.
1326
+ * @public
1327
+ * @memberof Meetings
1328
+ */
1329
+ public getAllMeetings(
1330
+ options: {
1331
+ startDate: object;
1332
+ endDate: object;
1333
+ } = {} as any
1334
+ ) {
1335
+ // Options may include other parameters to filter this collection
1336
+ // of meetings.
1337
+ return this.meetingCollection.getAll(options);
1338
+ }
1339
+
1340
+ /**
1341
+ * syncs all the meeting from server
1342
+ * @returns {undefined}
1343
+ * @public
1344
+ * @memberof Meetings
1345
+ */
1346
+ public syncMeetings() {
1347
+ return this.request
1348
+ .getActiveMeetings()
1349
+ .then((locusArray) => {
1350
+ const activeLocusUrl = [];
1351
+
1352
+ if (locusArray?.loci && locusArray.loci.length > 0) {
1353
+ const lociToUpdate = this.sortLocusArrayToUpdate(locusArray.loci);
1354
+ lociToUpdate.forEach((locus) => {
1355
+ activeLocusUrl.push(locus.url);
1356
+ this.handleLocusEvent({
1357
+ locus,
1358
+ locusUrl: locus.url,
1359
+ });
1360
+ });
1361
+ }
1362
+ const meetingsCollection = this.meetingCollection.getAll();
1363
+
1364
+ if (Object.keys(meetingsCollection).length > 0) {
1365
+ // Some time the mercury event is missed after mercury reconnect
1366
+ // if sync returns no locus then clear all the meetings
1367
+ for (const meeting of Object.values(meetingsCollection)) {
1368
+ // @ts-ignore
1369
+ if (!activeLocusUrl.includes(meeting.locusUrl)) {
1370
+ // destroy function also uploads logs
1371
+ // @ts-ignore
1372
+ this.destroy(meeting, MEETING_REMOVED_REASON.NO_MEETINGS_TO_SYNC);
1373
+ }
1374
+ }
1375
+ }
1376
+ })
1377
+ .catch((error) => {
1378
+ LoggerProxy.logger.error(
1379
+ `Meetings:index#syncMeetings --> failed to sync meetings, ${error}`
1380
+ );
1381
+ throw new Error(error);
1382
+ });
1383
+ }
1384
+
1385
+ /**
1386
+ * sort out locus array for initial creating
1387
+ * @param {Array} loci original locus array
1388
+ * @returns {undefined}
1389
+ * @public
1390
+ * @memberof Meetings
1391
+ */
1392
+ sortLocusArrayToUpdate(loci: any[]) {
1393
+ const mainLoci = loci.filter((locus) => !MeetingsUtil.isBreakoutLocusDTO(locus));
1394
+ const breakoutLoci = loci.filter((locus) => MeetingsUtil.isValidBreakoutLocus(locus));
1395
+ this.breakoutLocusForHandleLater = [];
1396
+ const lociToUpdate = [...mainLoci];
1397
+ breakoutLoci.forEach((breakoutLocus) => {
1398
+ const associateMainLocus = mainLoci.find(
1399
+ (mainLocus) => mainLocus.controls?.breakout?.url === breakoutLocus.controls?.breakout?.url
1400
+ );
1401
+ const existCorrespondingMeeting = this.getCorrespondingMeetingByLocus({
1402
+ locus: breakoutLocus,
1403
+ locusUrl: breakoutLocus.url,
1404
+ });
1405
+
1406
+ if (associateMainLocus && !existCorrespondingMeeting) {
1407
+ // if exists both main session and breakout session locus of the same non-exist meeting, handle main locus first,
1408
+ // after meeting create with main locus, then handle the associate breakout locus.
1409
+ // if only handle breakout locus, will miss some date
1410
+ this.breakoutLocusForHandleLater.push(breakoutLocus);
1411
+ } else {
1412
+ lociToUpdate.push(breakoutLocus);
1413
+ }
1414
+ });
1415
+
1416
+ return lociToUpdate;
1417
+ }
1418
+
1419
+ /**
1420
+ * check breakout locus which waiting for main locus's meeting to be created, then handle the breakout locus
1421
+ * @param {Object} newCreatedLocus the locus which just create meeting object of it
1422
+ * @returns {undefined}
1423
+ * @public
1424
+ * @memberof Meetings
1425
+ */
1426
+ checkHandleBreakoutLocus(newCreatedLocus) {
1427
+ if (
1428
+ !newCreatedLocus ||
1429
+ !this.breakoutLocusForHandleLater ||
1430
+ !this.breakoutLocusForHandleLater.length
1431
+ ) {
1432
+ return;
1433
+ }
1434
+ if (MeetingsUtil.isBreakoutLocusDTO(newCreatedLocus)) {
1435
+ return;
1436
+ }
1437
+ const existIndex = this.breakoutLocusForHandleLater.findIndex(
1438
+ (breakoutLocus) =>
1439
+ breakoutLocus.controls?.breakout?.url === newCreatedLocus.controls?.breakout?.url
1440
+ );
1441
+
1442
+ if (existIndex < 0) {
1443
+ return;
1444
+ }
1445
+
1446
+ const associateBreakoutLocus = this.breakoutLocusForHandleLater[existIndex];
1447
+ this.handleLocusEvent({locus: associateBreakoutLocus, locusUrl: associateBreakoutLocus.url});
1448
+ this.breakoutLocusForHandleLater.splice(existIndex, 1);
1449
+ }
1450
+
1451
+ /**
1452
+ * Get all scheduled meetings.
1453
+ * @param {object} options
1454
+ * @param {object} options.startDate - get meetings after this start date
1455
+ * @param {object} options.endDate - get meetings before this end date
1456
+ * @returns {Object} All scheduled meetings.
1457
+ * @memberof Meetings
1458
+ */
1459
+ getScheduledMeetings() {
1460
+ return this.meetingCollection.getAll({scheduled: true});
1461
+ }
1462
+
1463
+ /**
1464
+ * Get the logger instance for plugin-meetings
1465
+ * @returns {Logger}
1466
+ */
1467
+ getLogger() {
1468
+ return LoggerProxy.get();
1469
+ }
1470
+ }