@webex/plugin-meetings 3.0.0-beta.2 → 3.0.0-beta.200

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