@webex/plugin-meetings 3.0.0-beta.1 → 3.0.0-beta.104

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