@oneuptime/common 8.0.5237 → 8.0.5283

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 (371) hide show
  1. package/Models/DatabaseModels/Index.ts +4 -2
  2. package/Models/DatabaseModels/OnCallDutyPolicy.ts +7 -0
  3. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +7 -0
  4. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +7 -0
  5. package/Models/DatabaseModels/OnCallDutyPolicyTimeLog.ts +7 -0
  6. package/Models/DatabaseModels/OnCallDutyPolicyUserOverride.ts +5 -3
  7. package/Models/DatabaseModels/Project.ts +4 -2
  8. package/Models/DatabaseModels/ProjectSmtpConfig.ts +4 -2
  9. package/Models/DatabaseModels/StatusPageDomain.ts +6 -4
  10. package/Models/DatabaseModels/User.ts +0 -46
  11. package/Models/DatabaseModels/{UserTwoFactorAuth.ts → UserTotpAuth.ts} +16 -16
  12. package/Models/DatabaseModels/UserWebAuthn.ts +244 -0
  13. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +21 -0
  14. package/Server/API/BaseAPI.ts +4 -2
  15. package/Server/API/GlobalConfigAPI.ts +16 -12
  16. package/Server/API/MicrosoftTeamsAPI.ts +1240 -0
  17. package/Server/API/ProjectAPI.ts +4 -2
  18. package/Server/API/ResellerPlanAPI.ts +4 -2
  19. package/Server/API/SlackAPI.ts +54 -48
  20. package/Server/API/StatusPageAPI.ts +5 -3
  21. package/Server/API/UserOnCallLogTimelineAPI.ts +5 -3
  22. package/Server/API/{UserTwoFactorAuthAPI.ts → UserTotpAuthAPI.ts} +20 -20
  23. package/Server/API/UserWebAuthnAPI.ts +103 -0
  24. package/Server/EnvironmentConfig.ts +6 -0
  25. package/Server/Images/MicrosoftTeams/color.png +0 -0
  26. package/Server/Images/MicrosoftTeams/outline.png +0 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1753131488925-AddEnableCustomSubscriberEmailNotificationFooterText.ts +4 -2
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1759175457008-MigrationName.ts +27 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1759232954703-MigrationName.ts +25 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1759234532998-MigrationName.ts +15 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  32. package/Server/Infrastructure/Queue.ts +4 -2
  33. package/Server/Infrastructure/SocketIO.ts +4 -2
  34. package/Server/Middleware/ProjectAuthorization.ts +5 -3
  35. package/Server/Middleware/SlackAuthorization.ts +2 -2
  36. package/Server/Middleware/TelemetryIngest.ts +12 -6
  37. package/Server/Services/AlertStateTimelineService.ts +34 -18
  38. package/Server/Services/BillingInvoiceService.ts +8 -4
  39. package/Server/Services/BillingService.ts +13 -9
  40. package/Server/Services/DatabaseService.ts +42 -30
  41. package/Server/Services/IncidentService.ts +5 -3
  42. package/Server/Services/IncidentStateTimelineService.ts +34 -18
  43. package/Server/Services/Index.ts +4 -2
  44. package/Server/Services/MonitorStatusTimelineService.ts +34 -18
  45. package/Server/Services/OnCallDutyPolicyScheduleService.ts +4 -2
  46. package/Server/Services/ProjectService.ts +6 -4
  47. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +26 -14
  48. package/Server/Services/StatusPageService.ts +4 -2
  49. package/Server/Services/UserService.ts +21 -5
  50. package/Server/Services/{UserTwoFactorAuthService.ts → UserTotpAuthService.ts} +26 -7
  51. package/Server/Services/UserWebAuthnService.ts +419 -0
  52. package/Server/Services/WorkspaceNotificationRuleService.ts +257 -77
  53. package/Server/Services/WorkspaceProjectAuthTokenService.ts +2 -2
  54. package/Server/Types/AnalyticsDatabase/ModelPermission.ts +9 -5
  55. package/Server/Types/Database/Permissions/BasePermission.ts +4 -2
  56. package/Server/Types/Database/Permissions/TenantPermission.ts +5 -3
  57. package/Server/Types/Database/QueryHelper.ts +4 -2
  58. package/Server/Types/Markdown.ts +6 -4
  59. package/Server/Types/Workflow/ComponentCode.ts +4 -2
  60. package/Server/Types/Workflow/Components/Conditions/IfElse.ts +5 -3
  61. package/Server/Types/Workflow/Components/JavaScript.ts +5 -3
  62. package/Server/Types/Workflow/TriggerCode.ts +4 -2
  63. package/Server/Utils/AnalyticsDatabase/Statement.ts +4 -2
  64. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +21 -11
  65. package/Server/Utils/Browser.ts +6 -4
  66. package/Server/Utils/CodeRepository/GitHub/GitHub.ts +4 -2
  67. package/Server/Utils/LocalFile.ts +14 -0
  68. package/Server/Utils/Monitor/MonitorResource.ts +17 -9
  69. package/Server/Utils/Realtime.ts +4 -2
  70. package/Server/Utils/StartServer.ts +1 -1
  71. package/Server/Utils/Telemetry.ts +15 -9
  72. package/Server/Utils/{TwoFactorAuth.ts → TotpAuth.ts} +2 -2
  73. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.ts +75 -16
  74. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +649 -0
  75. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +237 -0
  76. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +1321 -0
  77. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.ts +155 -0
  78. package/Server/Utils/Workspace/MicrosoftTeams/Actions/OnCallDutyPolicy.ts +119 -0
  79. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +959 -0
  80. package/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.ts +16 -14
  81. package/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.ts +17 -14
  82. package/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.ts +18 -13
  83. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +2547 -14
  84. package/Server/Utils/Workspace/Slack/Actions/Alert.ts +4 -2
  85. package/Server/Utils/Workspace/Slack/Actions/Auth.ts +4 -2
  86. package/Server/Utils/Workspace/Slack/Actions/Incident.ts +14 -10
  87. package/Server/Utils/Workspace/Slack/Actions/Monitor.ts +4 -2
  88. package/Server/Utils/Workspace/Slack/Actions/OnCallDutyPolicy.ts +4 -2
  89. package/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.ts +14 -10
  90. package/Server/Utils/Workspace/Slack/Messages/Alert.ts +9 -7
  91. package/Server/Utils/Workspace/Slack/Messages/Incident.ts +9 -7
  92. package/Server/Utils/Workspace/Slack/Messages/Monitor.ts +9 -7
  93. package/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.ts +9 -7
  94. package/Server/Utils/Workspace/Slack/Slack.ts +6 -0
  95. package/Server/Utils/Workspace/Workspace.ts +13 -10
  96. package/Server/Utils/Workspace/WorkspaceBase.ts +9 -0
  97. package/Tests/Server/API/BaseAPI.test.ts +64 -52
  98. package/Tests/Server/Services/BillingService.test.ts +4 -4
  99. package/Tests/Server/Services/TeamMemberService.test.ts +20 -12
  100. package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +2 -2
  101. package/Tests/Types/OnCallDutyPolicy/LayerUtil.test.ts +8 -4
  102. package/Tests/UI/Components/DictionaryOfStrings.test.tsx +4 -2
  103. package/Tests/UI/Components/FilePicker.test.tsx +2 -2
  104. package/Tests/Utils/API.test.ts +9 -8
  105. package/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.ts +5 -3
  106. package/Types/Html.ts +5 -3
  107. package/Types/JSONFunctions.ts +5 -5
  108. package/Types/Metrics/MetricsQuery.ts +6 -4
  109. package/Types/Monitor/MonitorType.ts +8 -6
  110. package/Types/OnCallDutyPolicy/Layer.ts +29 -17
  111. package/Types/Phone.ts +5 -3
  112. package/Types/Workspace/NotificationRules/BaseNotificationRule.ts +1 -0
  113. package/Types/Workspace/NotificationRules/CreateChannelNotificationRule.ts +5 -2
  114. package/Types/Workspace/WorkspaceMessagePayload.ts +1 -0
  115. package/Types/Workspace/WorkspaceType.ts +13 -0
  116. package/UI/Components/Charts/Utils/DataPoint.ts +8 -6
  117. package/UI/Components/Detail/Detail.tsx +4 -1
  118. package/UI/Components/FilePicker/FilePicker.tsx +1 -1
  119. package/UI/Components/Forms/Types/Field.ts +4 -2
  120. package/UI/Components/Image/Image.tsx +1 -1
  121. package/UI/Components/JSONTable/JSONTable.tsx +4 -2
  122. package/UI/Components/ModelTable/BaseModelTable.tsx +5 -3
  123. package/UI/Components/SideMenu/SideMenu.tsx +4 -2
  124. package/UI/Components/SideMenu/SideMenuItem.tsx +69 -45
  125. package/UI/Config.ts +3 -0
  126. package/UI/Utils/API/API.ts +5 -3
  127. package/UI/Utils/Countries.ts +5 -3
  128. package/UI/Utils/Login.ts +6 -1
  129. package/Utils/Base64.ts +13 -0
  130. package/Utils/Schema/ModelSchema.ts +4 -2
  131. package/build/dist/Models/DatabaseModels/Index.js +4 -2
  132. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  133. package/build/dist/Models/DatabaseModels/OnCallDutyPolicy.js +7 -0
  134. package/build/dist/Models/DatabaseModels/OnCallDutyPolicy.js.map +1 -1
  135. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +7 -0
  136. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  137. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +7 -0
  138. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  139. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js +7 -0
  140. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js.map +1 -1
  141. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js +5 -3
  142. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js.map +1 -1
  143. package/build/dist/Models/DatabaseModels/Project.js +4 -2
  144. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  145. package/build/dist/Models/DatabaseModels/ProjectSmtpConfig.js +4 -2
  146. package/build/dist/Models/DatabaseModels/ProjectSmtpConfig.js.map +1 -1
  147. package/build/dist/Models/DatabaseModels/StatusPageDomain.js +6 -4
  148. package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
  149. package/build/dist/Models/DatabaseModels/User.js +0 -49
  150. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  151. package/build/dist/Models/DatabaseModels/{UserTwoFactorAuth.js → UserTotpAuth.js} +27 -27
  152. package/build/dist/Models/DatabaseModels/UserTotpAuth.js.map +1 -0
  153. package/build/dist/Models/DatabaseModels/UserWebAuthn.js +270 -0
  154. package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -0
  155. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  156. package/build/dist/Server/API/BaseAPI.js +4 -2
  157. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  158. package/build/dist/Server/API/GlobalConfigAPI.js +16 -12
  159. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  160. package/build/dist/Server/API/MicrosoftTeamsAPI.js +771 -0
  161. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -0
  162. package/build/dist/Server/API/ProjectAPI.js +4 -2
  163. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  164. package/build/dist/Server/API/ResellerPlanAPI.js +4 -2
  165. package/build/dist/Server/API/ResellerPlanAPI.js.map +1 -1
  166. package/build/dist/Server/API/SlackAPI.js +53 -47
  167. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  168. package/build/dist/Server/API/StatusPageAPI.js +5 -3
  169. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  170. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +5 -3
  171. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
  172. package/build/dist/Server/API/{UserTwoFactorAuthAPI.js → UserTotpAuthAPI.js} +16 -16
  173. package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -0
  174. package/build/dist/Server/API/UserWebAuthnAPI.js +65 -0
  175. package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -0
  176. package/build/dist/Server/EnvironmentConfig.js +3 -0
  177. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  178. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1753131488925-AddEnableCustomSubscriberEmailNotificationFooterText.js +4 -2
  179. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1753131488925-AddEnableCustomSubscriberEmailNotificationFooterText.js.map +1 -1
  180. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759175457008-MigrationName.js +16 -0
  181. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759175457008-MigrationName.js.map +1 -0
  182. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759232954703-MigrationName.js +16 -0
  183. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759232954703-MigrationName.js.map +1 -0
  184. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759234532998-MigrationName.js +12 -0
  185. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759234532998-MigrationName.js.map +1 -0
  186. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  187. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  188. package/build/dist/Server/Infrastructure/Queue.js +4 -2
  189. package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
  190. package/build/dist/Server/Infrastructure/SocketIO.js +4 -2
  191. package/build/dist/Server/Infrastructure/SocketIO.js.map +1 -1
  192. package/build/dist/Server/Middleware/ProjectAuthorization.js +5 -3
  193. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  194. package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
  195. package/build/dist/Server/Middleware/TelemetryIngest.js +12 -6
  196. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  197. package/build/dist/Server/Services/AlertStateTimelineService.js +34 -18
  198. package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
  199. package/build/dist/Server/Services/BillingInvoiceService.js +8 -4
  200. package/build/dist/Server/Services/BillingInvoiceService.js.map +1 -1
  201. package/build/dist/Server/Services/BillingService.js +13 -9
  202. package/build/dist/Server/Services/BillingService.js.map +1 -1
  203. package/build/dist/Server/Services/DatabaseService.js +40 -28
  204. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  205. package/build/dist/Server/Services/IncidentService.js +5 -3
  206. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  207. package/build/dist/Server/Services/IncidentStateTimelineService.js +34 -18
  208. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  209. package/build/dist/Server/Services/Index.js +4 -2
  210. package/build/dist/Server/Services/Index.js.map +1 -1
  211. package/build/dist/Server/Services/MonitorStatusTimelineService.js +34 -18
  212. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  213. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +4 -2
  214. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  215. package/build/dist/Server/Services/ProjectService.js +6 -4
  216. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  217. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +26 -14
  218. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  219. package/build/dist/Server/Services/StatusPageService.js +4 -2
  220. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  221. package/build/dist/Server/Services/UserService.js +16 -3
  222. package/build/dist/Server/Services/UserService.js.map +1 -1
  223. package/build/dist/Server/Services/{UserTwoFactorAuthService.js → UserTotpAuthService.js} +22 -8
  224. package/build/dist/Server/Services/UserTotpAuthService.js.map +1 -0
  225. package/build/dist/Server/Services/UserWebAuthnService.js +365 -0
  226. package/build/dist/Server/Services/UserWebAuthnService.js.map +1 -0
  227. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +142 -51
  228. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  229. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +9 -5
  230. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
  231. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +4 -2
  232. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  233. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +5 -3
  234. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
  235. package/build/dist/Server/Types/Database/QueryHelper.js +4 -2
  236. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  237. package/build/dist/Server/Types/Markdown.js +6 -4
  238. package/build/dist/Server/Types/Markdown.js.map +1 -1
  239. package/build/dist/Server/Types/Workflow/ComponentCode.js +4 -2
  240. package/build/dist/Server/Types/Workflow/ComponentCode.js.map +1 -1
  241. package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js +5 -3
  242. package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js.map +1 -1
  243. package/build/dist/Server/Types/Workflow/Components/JavaScript.js +5 -3
  244. package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
  245. package/build/dist/Server/Types/Workflow/TriggerCode.js.map +1 -1
  246. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +4 -2
  247. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  248. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +21 -11
  249. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  250. package/build/dist/Server/Utils/Browser.js +6 -4
  251. package/build/dist/Server/Utils/Browser.js.map +1 -1
  252. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +4 -2
  253. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
  254. package/build/dist/Server/Utils/LocalFile.js +16 -0
  255. package/build/dist/Server/Utils/LocalFile.js.map +1 -1
  256. package/build/dist/Server/Utils/Monitor/MonitorResource.js +17 -9
  257. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  258. package/build/dist/Server/Utils/Realtime.js +4 -2
  259. package/build/dist/Server/Utils/Realtime.js.map +1 -1
  260. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  261. package/build/dist/Server/Utils/Telemetry.js +6 -4
  262. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  263. package/build/dist/Server/Utils/{TwoFactorAuth.js → TotpAuth.js} +8 -8
  264. package/build/dist/Server/Utils/TotpAuth.js.map +1 -0
  265. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.js +86 -36
  266. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.js.map +1 -1
  267. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +531 -0
  268. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -0
  269. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +206 -0
  270. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -0
  271. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +1102 -0
  272. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -0
  273. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.js +136 -0
  274. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.js.map +1 -0
  275. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/OnCallDutyPolicy.js +107 -0
  276. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/OnCallDutyPolicy.js.map +1 -0
  277. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +795 -0
  278. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -0
  279. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.js +16 -14
  280. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.js.map +1 -1
  281. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.js +16 -14
  282. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.js.map +1 -1
  283. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.js +15 -13
  284. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.js.map +1 -1
  285. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +1982 -13
  286. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  287. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js +4 -2
  288. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js.map +1 -1
  289. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js +4 -2
  290. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js.map +1 -1
  291. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +14 -10
  292. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js.map +1 -1
  293. package/build/dist/Server/Utils/Workspace/Slack/Actions/Monitor.js +4 -2
  294. package/build/dist/Server/Utils/Workspace/Slack/Actions/Monitor.js.map +1 -1
  295. package/build/dist/Server/Utils/Workspace/Slack/Actions/OnCallDutyPolicy.js +4 -2
  296. package/build/dist/Server/Utils/Workspace/Slack/Actions/OnCallDutyPolicy.js.map +1 -1
  297. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js +14 -10
  298. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js.map +1 -1
  299. package/build/dist/Server/Utils/Workspace/Slack/Messages/Alert.js +9 -7
  300. package/build/dist/Server/Utils/Workspace/Slack/Messages/Alert.js.map +1 -1
  301. package/build/dist/Server/Utils/Workspace/Slack/Messages/Incident.js +9 -7
  302. package/build/dist/Server/Utils/Workspace/Slack/Messages/Incident.js.map +1 -1
  303. package/build/dist/Server/Utils/Workspace/Slack/Messages/Monitor.js +9 -7
  304. package/build/dist/Server/Utils/Workspace/Slack/Messages/Monitor.js.map +1 -1
  305. package/build/dist/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.js +9 -7
  306. package/build/dist/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.js.map +1 -1
  307. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +5 -0
  308. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  309. package/build/dist/Server/Utils/Workspace/Workspace.js +12 -10
  310. package/build/dist/Server/Utils/Workspace/Workspace.js.map +1 -1
  311. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
  312. package/build/dist/Tests/Server/API/BaseAPI.test.js +59 -47
  313. package/build/dist/Tests/Server/API/BaseAPI.test.js.map +1 -1
  314. package/build/dist/Tests/Server/Services/BillingService.test.js +4 -4
  315. package/build/dist/Tests/Server/Services/BillingService.test.js.map +1 -1
  316. package/build/dist/Tests/Server/Services/TeamMemberService.test.js +20 -12
  317. package/build/dist/Tests/Server/Services/TeamMemberService.test.js.map +1 -1
  318. package/build/dist/Tests/Server/TestingUtils/Services/BillingServiceHelper.js +2 -2
  319. package/build/dist/Tests/Server/TestingUtils/Services/BillingServiceHelper.js.map +1 -1
  320. package/build/dist/Tests/Types/OnCallDutyPolicy/LayerUtil.test.js +8 -4
  321. package/build/dist/Tests/Types/OnCallDutyPolicy/LayerUtil.test.js.map +1 -1
  322. package/build/dist/Tests/UI/Components/DictionaryOfStrings.test.js +4 -2
  323. package/build/dist/Tests/UI/Components/DictionaryOfStrings.test.js.map +1 -1
  324. package/build/dist/Tests/UI/Components/FilePicker.test.js +2 -2
  325. package/build/dist/Tests/UI/Components/FilePicker.test.js.map +1 -1
  326. package/build/dist/Tests/Utils/API.test.js +8 -7
  327. package/build/dist/Tests/Utils/API.test.js.map +1 -1
  328. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js +5 -3
  329. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js.map +1 -1
  330. package/build/dist/Types/Html.js +5 -3
  331. package/build/dist/Types/Html.js.map +1 -1
  332. package/build/dist/Types/JSONFunctions.js +5 -5
  333. package/build/dist/Types/JSONFunctions.js.map +1 -1
  334. package/build/dist/Types/Monitor/MonitorType.js +8 -6
  335. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  336. package/build/dist/Types/OnCallDutyPolicy/Layer.js +29 -17
  337. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  338. package/build/dist/Types/Phone.js +5 -3
  339. package/build/dist/Types/Phone.js.map +1 -1
  340. package/build/dist/Types/Workspace/WorkspaceType.js +9 -0
  341. package/build/dist/Types/Workspace/WorkspaceType.js.map +1 -1
  342. package/build/dist/UI/Components/Charts/Utils/DataPoint.js +8 -6
  343. package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
  344. package/build/dist/UI/Components/Detail/Detail.js +4 -1
  345. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  346. package/build/dist/UI/Components/FilePicker/FilePicker.js +1 -1
  347. package/build/dist/UI/Components/FilePicker/FilePicker.js.map +1 -1
  348. package/build/dist/UI/Components/Image/Image.js +1 -1
  349. package/build/dist/UI/Components/Image/Image.js.map +1 -1
  350. package/build/dist/UI/Components/JSONTable/JSONTable.js.map +1 -1
  351. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  352. package/build/dist/UI/Components/SideMenu/SideMenu.js +4 -2
  353. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  354. package/build/dist/UI/Components/SideMenu/SideMenuItem.js +62 -38
  355. package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
  356. package/build/dist/UI/Config.js +1 -0
  357. package/build/dist/UI/Config.js.map +1 -1
  358. package/build/dist/UI/Utils/API/API.js +5 -3
  359. package/build/dist/UI/Utils/API/API.js.map +1 -1
  360. package/build/dist/UI/Utils/Countries.js.map +1 -1
  361. package/build/dist/UI/Utils/Login.js +6 -1
  362. package/build/dist/UI/Utils/Login.js.map +1 -1
  363. package/build/dist/Utils/Base64.js +12 -0
  364. package/build/dist/Utils/Base64.js.map +1 -0
  365. package/build/dist/Utils/Schema/ModelSchema.js +4 -2
  366. package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
  367. package/package.json +5 -1
  368. package/build/dist/Models/DatabaseModels/UserTwoFactorAuth.js.map +0 -1
  369. package/build/dist/Server/API/UserTwoFactorAuthAPI.js.map +0 -1
  370. package/build/dist/Server/Services/UserTwoFactorAuthService.js.map +0 -1
  371. package/build/dist/Server/Utils/TwoFactorAuth.js.map +0 -1
@@ -8,15 +8,238 @@ var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
10
  import HTTPErrorResponse from "../../../../Types/API/HTTPErrorResponse";
11
+ import URL from "../../../../Types/API/URL";
11
12
  import API from "../../../../Utils/API";
12
13
  import logger from "../../Logger";
13
14
  import WorkspaceBase from "../WorkspaceBase";
15
+ import WorkspaceType from "../../../../Types/Workspace/WorkspaceType";
14
16
  import CaptureSpan from "../../Telemetry/CaptureSpan";
15
- export default class MicrosoftTeams extends WorkspaceBase {
17
+ import BadDataException from "../../../../Types/Exception/BadDataException";
18
+ import WorkspaceProjectAuthTokenService from "../../../Services/WorkspaceProjectAuthTokenService";
19
+ import OneUptimeDate from "../../../../Types/Date";
20
+ import { MicrosoftTeamsAppClientId, MicrosoftTeamsAppClientSecret, } from "../../../EnvironmentConfig";
21
+ // Import services for bot commands
22
+ import IncidentService from "../../../Services/IncidentService";
23
+ import AlertService from "../../../Services/AlertService";
24
+ import ScheduledMaintenanceService from "../../../Services/ScheduledMaintenanceService";
25
+ import IncidentStateService from "../../../Services/IncidentStateService";
26
+ import AlertStateService from "../../../Services/AlertStateService";
27
+ // Import database utilities
28
+ import QueryHelper from "../../../Types/Database/QueryHelper";
29
+ import SortOrder from "../../../../Types/BaseDatabase/SortOrder";
30
+ // Microsoft Teams apps should always be single-tenant
31
+ const MICROSOFT_TEAMS_APP_TYPE = "SingleTenant";
32
+ // Bot Framework SDK imports
33
+ import { CloudAdapter, ConfigurationBotFrameworkAuthentication, TeamsActivityHandler, MessageFactory, } from "botbuilder";
34
+ // Teams action handlers and types
35
+ import MicrosoftTeamsAuthAction from "./Actions/Auth";
36
+ import MicrosoftTeamsIncidentActions from "./Actions/Incident";
37
+ import MicrosoftTeamsAlertActions from "./Actions/Alert";
38
+ import MicrosoftTeamsMonitorActions from "./Actions/Monitor";
39
+ import MicrosoftTeamsScheduledMaintenanceActions from "./Actions/ScheduledMaintenance";
40
+ import MicrosoftTeamsOnCallDutyActions from "./Actions/OnCallDutyPolicy";
41
+ export default class MicrosoftTeamsUtil extends WorkspaceBase {
42
+ // Get or create Bot Framework adapter for a specific tenant
43
+ static getBotAdapter(microsoftAppTenantId) {
44
+ if (!MicrosoftTeamsAppClientId || !MicrosoftTeamsAppClientSecret) {
45
+ throw new BadDataException("Microsoft Teams App credentials not configured");
46
+ }
47
+ logger.debug("Creating Bot Framework adapter with authentication configuration");
48
+ logger.debug(`App ID: ${MicrosoftTeamsAppClientId}`);
49
+ logger.debug(`App Type: ${MICROSOFT_TEAMS_APP_TYPE}`);
50
+ logger.debug(`Tenant ID: ${microsoftAppTenantId}`);
51
+ const authConfig = {
52
+ MicrosoftAppId: MicrosoftTeamsAppClientId,
53
+ MicrosoftAppPassword: MicrosoftTeamsAppClientSecret,
54
+ MicrosoftAppType: MICROSOFT_TEAMS_APP_TYPE,
55
+ MicrosoftAppTenantId: microsoftAppTenantId,
56
+ };
57
+ const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(authConfig);
58
+ const adapter = new CloudAdapter(botFrameworkAuthentication);
59
+ logger.debug("Bot Framework adapter created successfully");
60
+ return adapter;
61
+ }
62
+ // Helper method to get a valid access token, refreshing if necessary
63
+ static async getValidAccessToken(data) {
64
+ var _a;
65
+ logger.debug("=== getValidAccessToken called ===");
66
+ logger.debug(`Project ID: ${data.projectId.toString()}`);
67
+ logger.debug(`Auth token (first 20 chars): ${(_a = data.authToken) === null || _a === void 0 ? void 0 : _a.substring(0, 20)}...`);
68
+ // Get project auth and check token expiration
69
+ const projectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
70
+ projectId: data.projectId,
71
+ workspaceType: WorkspaceType.MicrosoftTeams,
72
+ });
73
+ logger.debug(`Project auth found: ${Boolean(projectAuth)}`);
74
+ if (projectAuth) {
75
+ logger.debug(`Project auth has miscData: ${Boolean(projectAuth.miscData)}`);
76
+ }
77
+ if (!projectAuth || !projectAuth.miscData) {
78
+ logger.error("Microsoft Teams integration not found for this project - no project auth or miscData");
79
+ throw new BadDataException("Microsoft Teams integration not found for this project");
80
+ }
81
+ const miscData = projectAuth.miscData;
82
+ logger.debug(`MiscData appAccessToken exists: ${Boolean(miscData.appAccessToken)}`);
83
+ logger.debug(`MiscData appAccessTokenExpiresAt: ${miscData.appAccessTokenExpiresAt}`);
84
+ // Check if token exists and is valid
85
+ if (miscData.appAccessToken && miscData.appAccessToken.includes(".")) {
86
+ logger.debug("Found app access token in miscData");
87
+ // Check if token is expired
88
+ if (miscData.appAccessTokenExpiresAt) {
89
+ const expiryDate = OneUptimeDate.fromString(miscData.appAccessTokenExpiresAt);
90
+ const now = OneUptimeDate.getCurrentDate();
91
+ const isExpired = OneUptimeDate.isAfter(now, expiryDate);
92
+ const secondsToExpiry = OneUptimeDate.getSecondsTo(expiryDate);
93
+ logger.debug(`Token expires in ${secondsToExpiry} seconds`);
94
+ logger.debug(`Token is expired: ${isExpired}`);
95
+ // If token is already expired or expires within the next 5 minutes, refresh it
96
+ if (isExpired || secondsToExpiry <= 300) {
97
+ logger.debug("Access token is expired or expiring soon, attempting to refresh");
98
+ const newToken = await this.refreshAccessToken({
99
+ projectId: data.projectId,
100
+ miscData,
101
+ });
102
+ if (newToken) {
103
+ logger.debug("Successfully refreshed token");
104
+ return newToken;
105
+ }
106
+ logger.warn("Failed to refresh token, falling back to cached token");
107
+ }
108
+ else {
109
+ logger.debug("Using cached appAccessToken from miscData for Microsoft Graph API call");
110
+ return miscData.appAccessToken;
111
+ }
112
+ }
113
+ else {
114
+ // No expiry information, use the token but it might be expired
115
+ logger.debug("Using appAccessToken from miscData (no expiry info available)");
116
+ return miscData.appAccessToken;
117
+ }
118
+ }
119
+ // If we couldn't find a valid token, try to refresh
120
+ logger.debug("No valid app access token found, attempting to refresh");
121
+ const newToken = await this.refreshAccessToken({
122
+ projectId: data.projectId,
123
+ miscData,
124
+ });
125
+ if (newToken) {
126
+ logger.debug("Successfully refreshed token");
127
+ return newToken;
128
+ }
129
+ // If refresh failed, throw error
130
+ logger.error("Could not obtain valid access token for Microsoft Teams");
131
+ throw new BadDataException("Could not obtain valid access token for Microsoft Teams");
132
+ }
133
+ // Method to refresh the Microsoft Teams access token
134
+ static async refreshAccessToken(data) {
135
+ logger.debug("=== refreshAccessToken called ===");
136
+ logger.debug(`Project ID: ${data.projectId.toString()}`);
137
+ logger.debug(`Tenant ID: ${data.miscData.tenantId}`);
138
+ try {
139
+ // Check if we have the necessary client credentials
140
+ if (!MicrosoftTeamsAppClientId || !MicrosoftTeamsAppClientSecret) {
141
+ logger.error("Microsoft Teams app client credentials are not configured");
142
+ logger.error("Please set MICROSOFT_TEAMS_APP_CLIENT_ID and MICROSOFT_TEAMS_APP_CLIENT_SECRET environment variables");
143
+ return null;
144
+ }
145
+ logger.debug("Client credentials are configured");
146
+ if (!data.miscData.tenantId) {
147
+ logger.error("Tenant ID not found in miscData, cannot refresh token");
148
+ return null;
149
+ }
150
+ logger.debug(`Attempting to refresh Microsoft Teams access token for project ${data.projectId.toString()}`);
151
+ logger.debug(`Using tenant ID: ${data.miscData.tenantId}`);
152
+ // Use OAuth 2.0 client credentials flow to get a new app access token
153
+ const tokenUrl = `https://login.microsoftonline.com/${data.miscData.tenantId}/oauth2/v2.0/token`;
154
+ logger.debug(`Token URL: ${tokenUrl}`);
155
+ const tokenRequestBody = {
156
+ client_id: MicrosoftTeamsAppClientId,
157
+ client_secret: MicrosoftTeamsAppClientSecret,
158
+ grant_type: "client_credentials",
159
+ scope: "https://graph.microsoft.com/.default",
160
+ };
161
+ logger.debug("Making token refresh request to Microsoft");
162
+ const response = await API.post({
163
+ url: URL.fromString(tokenUrl),
164
+ data: tokenRequestBody,
165
+ headers: {
166
+ "Content-Type": "application/x-www-form-urlencoded",
167
+ Accept: "application/json",
168
+ },
169
+ });
170
+ if (response instanceof HTTPErrorResponse) {
171
+ logger.error("Error refreshing Microsoft Teams access token:");
172
+ logger.error(response);
173
+ return null;
174
+ }
175
+ logger.debug("Token refresh response received successfully");
176
+ const tokenData = response.data;
177
+ const newAccessToken = tokenData["access_token"];
178
+ const expiresIn = tokenData["expires_in"]; // seconds
179
+ logger.debug(`New access token received: ${Boolean(newAccessToken)}`);
180
+ logger.debug(`Token expires in: ${expiresIn} seconds`);
181
+ if (!newAccessToken) {
182
+ logger.error("No access token received in token refresh response");
183
+ return null;
184
+ }
185
+ // Calculate expiry time
186
+ const now = OneUptimeDate.getCurrentDate();
187
+ const expiryDate = OneUptimeDate.addRemoveSeconds(now, expiresIn - 300); // Subtrutes buffer
188
+ logger.debug(`Token expiry calculated: ${OneUptimeDate.toString(expiryDate)}`);
189
+ // Update the miscData with new token and expiry
190
+ const updatedMiscData = Object.assign(Object.assign({}, data.miscData), { appAccessToken: newAccessToken, appAccessTokenExpiresAt: OneUptimeDate.toString(expiryDate), lastAppTokenIssuedAt: OneUptimeDate.toString(now) });
191
+ logger.debug("Saving updated token to database");
192
+ // Save the updated token to the database
193
+ await WorkspaceProjectAuthTokenService.refreshAuthToken({
194
+ projectId: data.projectId,
195
+ workspaceType: WorkspaceType.MicrosoftTeams,
196
+ authToken: newAccessToken,
197
+ workspaceProjectId: data.miscData.tenantId,
198
+ miscData: updatedMiscData,
199
+ });
200
+ logger.debug("Microsoft Teams access token refreshed successfully");
201
+ logger.debug(`New token expires at: ${updatedMiscData.appAccessTokenExpiresAt}`);
202
+ return newAccessToken;
203
+ }
204
+ catch (error) {
205
+ logger.error("Error refreshing Microsoft Teams access token:");
206
+ logger.error(error);
207
+ return null;
208
+ }
209
+ }
210
+ // Extract action type and value from Teams Adaptive Card submit value
211
+ static extractActionFromValue(value) {
212
+ /*
213
+ * Support multiple shapes that Teams may send for Adaptive Card submits
214
+ * 1) { action: "ack-incident", actionValue: "<id>" }
215
+ * 2) { data: { action: "ack-incident", actionValue: "<id>" } }
216
+ * 3) { action: { type: "Action.Submit", data: { action: "ack-incident", actionValue: "<id>" } } }
217
+ */
218
+ let actionType = value["action"] || "";
219
+ let actionValue = value["actionValue"] || "";
220
+ const valData = value["data"] || undefined;
221
+ if ((!actionType || !actionValue) && valData) {
222
+ actionType = valData["action"] || actionType;
223
+ actionValue = valData["actionValue"] || actionValue;
224
+ }
225
+ const actionObj = value["action"];
226
+ if ((!actionType || !actionValue) &&
227
+ actionObj &&
228
+ typeof actionObj === "object") {
229
+ const embeddedData = actionObj["data"] || undefined;
230
+ if (embeddedData) {
231
+ actionType = embeddedData["action"] || actionType;
232
+ actionValue = embeddedData["actionValue"] || actionValue;
233
+ }
234
+ }
235
+ return { actionType: actionType, actionValue };
236
+ }
16
237
  static buildMessageCardFromMarkdown(markdown) {
17
238
  var _a, _b, _c, _d, _e;
18
- // Teams MessageCard has limited markdown support. Headings like '##' are not supported
19
- // and single newlines can collapse. Convert common patterns to a structured card.
239
+ /*
240
+ * Teams MessageCard has limited markdown support. Headings like '##' are not supported
241
+ * and single newlines can collapse. Convert common patterns to a structured card.
242
+ */
20
243
  const lines = markdown
21
244
  .split("\n")
22
245
  .map((l) => {
@@ -36,11 +259,29 @@ export default class MicrosoftTeams extends WorkspaceBase {
36
259
  .replace(/^#+\s*/, "") // remove leading markdown headers like ##
37
260
  .replace(/^\*\*|\*\*$/g, "") // remove stray bold markers if any
38
261
  .trim();
262
+ // Remove markdown link syntax from title for cleaner rendering
263
+ const titleLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
264
+ title = title.replace(titleLinkRegex, "$1");
265
+ // Sanitize unmatched bold markers if any remain
266
+ const boldCountTitle = (title.match(/\*\*/g) || []).length;
267
+ if (boldCountTitle % 2 !== 0) {
268
+ title = title.replace(/\*\*/g, "");
269
+ }
39
270
  lines.shift();
40
271
  }
41
272
  const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g; // [text](url)
273
+ // Helper to clean up unmatched bold markers that can break rendering
274
+ const sanitizeMarkdownText = (text) => {
275
+ const boldCount = (text.match(/\*\*/g) || []).length;
276
+ // If we have an odd number of **, remove them all to avoid raw markers showing
277
+ if (boldCount % 2 !== 0) {
278
+ text = text.replace(/\*\*/g, "");
279
+ }
280
+ // Collapse multiple spaces introduced by replacements
281
+ return text.replace(/\s{2,}/g, " ");
282
+ };
42
283
  for (const line of lines) {
43
- // Extract links to actions and strip them from text
284
+ // Extract links to actions and keep link display text in-place (without markdown)
44
285
  let lineWithoutLinks = line;
45
286
  let match = null;
46
287
  while ((match = linkRegex.exec(line))) {
@@ -56,7 +297,8 @@ export default class MicrosoftTeams extends WorkspaceBase {
56
297
  },
57
298
  ],
58
299
  });
59
- lineWithoutLinks = lineWithoutLinks.replace(match[0], "").trim();
300
+ // Replace markdown link with just the display text to preserve sentence flow
301
+ lineWithoutLinks = lineWithoutLinks.replace(match[0], name).trim();
60
302
  }
61
303
  // Parse facts of the form **Label:** value
62
304
  const factMatch = new RegExp("\\*\\*(.*?):\\*\\*\\s*(.*)").exec(lineWithoutLinks);
@@ -72,7 +314,7 @@ export default class MicrosoftTeams extends WorkspaceBase {
72
314
  }
73
315
  }
74
316
  else if (lineWithoutLinks) {
75
- bodyTextParts.push(lineWithoutLinks);
317
+ bodyTextParts.push(sanitizeMarkdownText(lineWithoutLinks));
76
318
  }
77
319
  }
78
320
  const payload = {
@@ -81,15 +323,16 @@ export default class MicrosoftTeams extends WorkspaceBase {
81
323
  title: title,
82
324
  summary: title,
83
325
  };
326
+ // Build a single section so we can enable markdown explicitly
327
+ const section = { markdown: true };
84
328
  if (bodyTextParts.length > 0) {
85
- payload["text"] = bodyTextParts.join("\n\n");
329
+ section["text"] = bodyTextParts.join("\n\n");
86
330
  }
87
331
  if (facts.length > 0) {
88
- payload["sections"] = [
89
- {
90
- facts: facts,
91
- },
92
- ];
332
+ section["facts"] = facts;
333
+ }
334
+ if (section["text"] || section["facts"]) {
335
+ payload["sections"] = [section];
93
336
  }
94
337
  if (actions.length > 0) {
95
338
  payload["potentialAction"] = actions;
@@ -124,11 +367,1737 @@ export default class MicrosoftTeams extends WorkspaceBase {
124
367
  return (urlString.includes("outlook.office.com") ||
125
368
  urlString.includes("office.com"));
126
369
  }
370
+ static async getUsernameFromUserId(data) {
371
+ logger.debug("Getting username from user ID with data:");
372
+ logger.debug(data);
373
+ // Get valid access token
374
+ const accessToken = await this.getValidAccessToken({
375
+ authToken: data.authToken,
376
+ projectId: data.projectId,
377
+ });
378
+ const response = await API.get({
379
+ url: URL.fromString(`https://graph.microsoft.com/v1.0/users/${data.userId}`),
380
+ headers: {
381
+ Authorization: `Bearer ${accessToken}`,
382
+ "Content-Type": "application/json",
383
+ },
384
+ });
385
+ logger.debug("Response from Microsoft Graph API for getting user info:");
386
+ logger.debug(response);
387
+ if (response instanceof HTTPErrorResponse) {
388
+ logger.error("Error response from Microsoft Graph API:");
389
+ logger.error(response);
390
+ throw response;
391
+ }
392
+ const userData = response.data;
393
+ const username = userData["displayName"] ||
394
+ userData["userPrincipalName"];
395
+ logger.debug("Username obtained:");
396
+ logger.debug(username);
397
+ return username;
398
+ }
399
+ static async sendDirectMessageToUser(data) {
400
+ // Send direct message to user via Microsoft Graph API
401
+ const adaptiveCard = this.buildAdaptiveCardFromMessageBlocks({
402
+ messageBlocks: data.messageBlocks,
403
+ });
404
+ const chatMessage = {
405
+ body: {
406
+ contentType: "html",
407
+ content: this.convertAdaptiveCardToHtml(adaptiveCard),
408
+ },
409
+ attachments: [
410
+ {
411
+ contentType: "application/vnd.microsoft.card.adaptive",
412
+ content: adaptiveCard,
413
+ },
414
+ ],
415
+ };
416
+ await API.post({
417
+ url: URL.fromString(`https://graph.microsoft.com/v1.0/chats/${data.workspaceUserId}/messages`),
418
+ data: chatMessage,
419
+ headers: {
420
+ Authorization: `Bearer ${data.authToken}`,
421
+ "Content-Type": "application/json",
422
+ },
423
+ });
424
+ }
425
+ static async createChannelsIfDoesNotExist(data) {
426
+ logger.debug("Creating channels if they do not exist with data:");
427
+ logger.debug(data);
428
+ const workspaceChannels = [];
429
+ for (let channelName of data.channelNames) {
430
+ // Normalize channel name - Teams has different naming requirements
431
+ if (channelName && channelName.startsWith("#")) {
432
+ channelName = channelName.substring(1);
433
+ }
434
+ // Teams channels cannot have spaces in the name for some operations
435
+ const normalizedChannelName = channelName.replace(/\s+/g, "-");
436
+ // Check if channel exists
437
+ const existingChannel = await this.getWorkspaceChannelByName({
438
+ authToken: data.authToken,
439
+ channelName: normalizedChannelName,
440
+ projectId: data.projectId,
441
+ teamId: data.teamId,
442
+ });
443
+ if (existingChannel) {
444
+ logger.debug(`Channel ${channelName} already exists.`);
445
+ workspaceChannels.push(existingChannel);
446
+ continue;
447
+ }
448
+ logger.debug(`Channel ${channelName} does not exist. Creating channel.`);
449
+ const createChannelData = {
450
+ authToken: data.authToken,
451
+ channelName: normalizedChannelName,
452
+ projectId: data.projectId,
453
+ teamId: data.teamId,
454
+ };
455
+ const channel = await this.createChannel(createChannelData);
456
+ if (channel) {
457
+ logger.debug(`Channel ${channelName} created successfully.`);
458
+ workspaceChannels.push(channel);
459
+ }
460
+ }
461
+ logger.debug("Channels created or found:");
462
+ logger.debug(workspaceChannels);
463
+ return workspaceChannels;
464
+ }
465
+ static async createChannel(data) {
466
+ const teamId = data.teamId;
467
+ // Get valid access token
468
+ const accessToken = await this.getValidAccessToken({
469
+ authToken: data.authToken,
470
+ projectId: data.projectId,
471
+ });
472
+ const channelPayload = {
473
+ displayName: data.channelName,
474
+ description: `OneUptime notifications for ${data.channelName}`,
475
+ membershipType: "standard",
476
+ };
477
+ logger.debug("Creating Teams channel with payload:");
478
+ logger.debug(channelPayload);
479
+ const response = await API.post({
480
+ url: URL.fromString(`https://graph.microsoft.com/v1.0/teams/${teamId}/channels`),
481
+ data: channelPayload,
482
+ headers: {
483
+ Authorization: `Bearer ${accessToken}`,
484
+ "Content-Type": "application/json",
485
+ },
486
+ });
487
+ if (response instanceof HTTPErrorResponse) {
488
+ logger.error("Error response from Microsoft Graph API:");
489
+ logger.error(response);
490
+ throw response;
491
+ }
492
+ const channelData = response.data;
493
+ const channel = {
494
+ id: channelData["id"],
495
+ name: channelData["displayName"],
496
+ workspaceType: WorkspaceType.MicrosoftTeams,
497
+ teamId: data.teamId,
498
+ };
499
+ logger.debug("Channel created successfully:");
500
+ logger.debug(channel);
501
+ return channel;
502
+ }
503
+ static async getWorkspaceChannelFromChannelName(data) {
504
+ const channel = await this.getWorkspaceChannelByName({
505
+ authToken: data.authToken,
506
+ channelName: data.channelName,
507
+ projectId: data.projectId,
508
+ teamId: data.teamId,
509
+ });
510
+ if (!channel) {
511
+ throw new BadDataException("Channel not found.");
512
+ }
513
+ return channel;
514
+ }
515
+ static async getWorkspaceChannelByName(data) {
516
+ logger.debug(`Getting workspace channel by name: ${data.channelName}`);
517
+ // Get project auth to get available teams
518
+ const projectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
519
+ projectId: data.projectId,
520
+ workspaceType: WorkspaceType.MicrosoftTeams,
521
+ });
522
+ if (!(projectAuth === null || projectAuth === void 0 ? void 0 : projectAuth.miscData)) {
523
+ logger.error("Microsoft Teams integration not found for this project");
524
+ throw new BadDataException("Microsoft Teams integration not found for this project");
525
+ }
526
+ // Get valid access token
527
+ const accessToken = await this.getValidAccessToken({
528
+ authToken: data.authToken,
529
+ projectId: data.projectId,
530
+ });
531
+ // Get channels for this team
532
+ const response = await API.get({
533
+ url: URL.fromString(`https://graph.microsoft.com/v1.0/teams/${data.teamId}/channels`),
534
+ headers: {
535
+ Authorization: `Bearer ${accessToken}`,
536
+ "Content-Type": "application/json",
537
+ },
538
+ });
539
+ if (response instanceof HTTPErrorResponse) {
540
+ logger.error("Error response from Microsoft Graph API:");
541
+ logger.error(response);
542
+ throw response;
543
+ }
544
+ const channelsData = response.data;
545
+ const channels = channelsData["value"] || [];
546
+ logger.debug(`Found ${channels.length} channels from API`);
547
+ const channelName = data.channelName.toLowerCase();
548
+ for (const channelData of channels) {
549
+ const displayName = channelData["displayName"];
550
+ if (!displayName) {
551
+ continue;
552
+ }
553
+ const apiChannelName = displayName.toLowerCase();
554
+ logger.debug(`Comparing channel '${apiChannelName}' with requested '${channelName}'`);
555
+ if (apiChannelName === channelName) {
556
+ const foundChannel = {
557
+ id: `${channelData["id"]}`,
558
+ name: displayName,
559
+ workspaceType: WorkspaceType.MicrosoftTeams,
560
+ teamId: data.teamId,
561
+ };
562
+ logger.debug(`Channel match found: ${JSON.stringify(foundChannel)}`);
563
+ return foundChannel;
564
+ }
565
+ }
566
+ logger.debug(`No channel found with name: ${data.channelName}`);
567
+ return null;
568
+ }
569
+ static async sendMessage(data) {
570
+ logger.debug("=== MicrosoftTeamsUtil.sendMessage called ===");
571
+ logger.debug("Sending message to Microsoft Teams with data:");
572
+ logger.debug(data);
573
+ const adaptiveCard = this.buildAdaptiveCardFromMessageBlocks({
574
+ messageBlocks: data.workspaceMessagePayload.messageBlocks,
575
+ });
576
+ logger.debug("Adaptive card built successfully:");
577
+ logger.debug(JSON.stringify(adaptiveCard, null, 2));
578
+ const workspaceChannelsToPostTo = [];
579
+ logger.debug(`Processing ${data.workspaceMessagePayload.channelNames.length} channel names`);
580
+ logger.debug(`Channel names: ${JSON.stringify(data.workspaceMessagePayload.channelNames)}`);
581
+ // Resolve channel names
582
+ for (const channelName of data.workspaceMessagePayload.channelNames) {
583
+ logger.debug(`Attempting to resolve channel name: ${channelName}`);
584
+ if (!data.workspaceMessagePayload.teamId) {
585
+ throw new BadDataException("Team ID is required to resolve channel names.");
586
+ }
587
+ const channel = await this.getWorkspaceChannelByName({
588
+ authToken: data.authToken,
589
+ channelName: channelName,
590
+ projectId: data.projectId,
591
+ teamId: data.workspaceMessagePayload.teamId,
592
+ });
593
+ if (channel) {
594
+ logger.debug(`Channel resolved successfully: ${JSON.stringify(channel)}`);
595
+ workspaceChannelsToPostTo.push(channel);
596
+ }
597
+ else {
598
+ logger.warn(`Channel not found: ${channelName}`);
599
+ }
600
+ }
601
+ logger.debug("=== Starting message sending loop ===");
602
+ logger.debug(`Total channels to post to: ${workspaceChannelsToPostTo.length}`);
603
+ logger.debug(`Channels: ${JSON.stringify(workspaceChannelsToPostTo)}`);
604
+ // Add channels by ID
605
+ for (const channelId of data.workspaceMessagePayload.channelIds) {
606
+ if (!data.workspaceMessagePayload.teamId) {
607
+ throw new BadDataException("Team ID is required to resolve channel IDs.");
608
+ }
609
+ try {
610
+ logger.debug(`Getting channel info for channel ID: ${channelId}`);
611
+ const channel = await this.getWorkspaceChannelFromChannelId({
612
+ authToken: data.authToken,
613
+ channelId: channelId,
614
+ projectId: data.projectId,
615
+ teamId: data.workspaceMessagePayload.teamId,
616
+ });
617
+ logger.debug(`Channel info obtained: ${JSON.stringify(channel)}`);
618
+ workspaceChannelsToPostTo.push(channel);
619
+ }
620
+ catch (err) {
621
+ logger.error(`Error getting channel info for channel ID ${channelId}:`);
622
+ logger.error(err);
623
+ }
624
+ }
625
+ logger.debug("=== Starting message sending loop ===");
626
+ logger.debug(`Total channels to post to: ${workspaceChannelsToPostTo.length}`);
627
+ logger.debug(`Channels: ${JSON.stringify(workspaceChannelsToPostTo)}`);
628
+ const workspaceMessageResponse = {
629
+ threads: [],
630
+ workspaceType: WorkspaceType.MicrosoftTeams,
631
+ errors: [],
632
+ };
633
+ for (const channel of workspaceChannelsToPostTo) {
634
+ try {
635
+ logger.debug(`Attempting to send message to channel: ${JSON.stringify(channel)}`);
636
+ if (!data.workspaceMessagePayload.teamId) {
637
+ throw new BadDataException("Team ID is required to send messages to channels.");
638
+ }
639
+ const thread = await this.sendAdaptiveCardToChannel({
640
+ authToken: data.authToken,
641
+ teamId: data.workspaceMessagePayload.teamId,
642
+ workspaceChannel: channel,
643
+ adaptiveCard: adaptiveCard,
644
+ projectId: data.projectId,
645
+ });
646
+ logger.debug(`Message sent successfully to channel ${channel.name}, thread: ${JSON.stringify(thread)}`);
647
+ workspaceMessageResponse.threads.push(thread);
648
+ }
649
+ catch (e) {
650
+ logger.error(`Error sending message to channel ID ${channel.id}:`);
651
+ logger.error(e);
652
+ workspaceMessageResponse.errors.push({
653
+ channel: channel,
654
+ error: e instanceof Error ? e.message : String(e),
655
+ });
656
+ }
657
+ }
658
+ logger.debug("=== Message sending completed ===");
659
+ logger.debug(`Final thread count: ${workspaceMessageResponse.threads.length}`);
660
+ logger.debug(`Final response: ${JSON.stringify(workspaceMessageResponse)}`);
661
+ return workspaceMessageResponse;
662
+ }
663
+ static async sendAdaptiveCardToChannel(data) {
664
+ logger.debug(`Sending adaptive card to channel via Bot Framework: ${data.workspaceChannel.name} (${data.workspaceChannel.id})`);
665
+ logger.debug(`Team ID: ${data.teamId}`);
666
+ logger.debug(`Adaptive card: ${JSON.stringify(data.adaptiveCard)}`);
667
+ try {
668
+ // Get project auth to retrieve bot ID
669
+ const projectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
670
+ projectId: data.projectId,
671
+ workspaceType: WorkspaceType.MicrosoftTeams,
672
+ });
673
+ if (!projectAuth || !projectAuth.miscData) {
674
+ throw new BadDataException("Microsoft Teams integration not found for this project");
675
+ }
676
+ const miscData = projectAuth.miscData;
677
+ if (!miscData.botId) {
678
+ throw new BadDataException("Bot ID not found in Microsoft Teams integration");
679
+ }
680
+ // Check if app client ID is configured
681
+ if (!MicrosoftTeamsAppClientId) {
682
+ throw new BadDataException("Microsoft Teams App Client ID not configured");
683
+ }
684
+ logger.debug(`Using bot ID: ${miscData.botId}`);
685
+ // Get Bot Framework adapter
686
+ const adapter = this.getBotAdapter(miscData.tenantId);
687
+ // Create conversation reference for the channel
688
+ const conversationReference = {
689
+ bot: {
690
+ id: MicrosoftTeamsAppClientId,
691
+ name: "OneUptime Bot",
692
+ },
693
+ conversation: {
694
+ id: data.workspaceChannel.id,
695
+ name: data.workspaceChannel.name,
696
+ isGroup: true,
697
+ conversationType: "channel",
698
+ tenantId: miscData.tenantId,
699
+ },
700
+ channelId: "msteams",
701
+ serviceUrl: "https://smba.trafficmanager.net/teams/",
702
+ };
703
+ logger.debug(`Conversation reference: ${JSON.stringify(conversationReference)}`);
704
+ // Send proactive message using Bot Framework
705
+ let messageId = "";
706
+ await adapter.continueConversationAsync(MicrosoftTeamsAppClientId, conversationReference, async (context) => {
707
+ logger.debug("Sending adaptive card as proactive message");
708
+ // Create message with adaptive card attachment
709
+ const message = MessageFactory.attachment({
710
+ contentType: "application/vnd.microsoft.card.adaptive",
711
+ content: data.adaptiveCard,
712
+ });
713
+ const response = await context.sendActivity(message);
714
+ messageId = (response === null || response === void 0 ? void 0 : response.id) || "";
715
+ logger.debug(`Message sent with ID: ${messageId}`);
716
+ });
717
+ const thread = {
718
+ channel: data.workspaceChannel,
719
+ threadId: messageId,
720
+ };
721
+ logger.debug(`Created thread via Bot Framework: ${JSON.stringify(thread)}`);
722
+ return thread;
723
+ }
724
+ catch (error) {
725
+ logger.error("Error sending adaptive card via Bot Framework:");
726
+ logger.error(error);
727
+ throw error;
728
+ }
729
+ }
730
+ static async getWorkspaceChannelFromChannelId(data) {
731
+ logger.debug("=== getWorkspaceChannelFromChannelId called ===");
732
+ logger.debug(`Channel ID: ${data.channelId}`);
733
+ logger.debug(`Team ID: ${data.teamId}`);
734
+ logger.debug(`Project ID: ${data.projectId.toString()}`);
735
+ try {
736
+ // Get valid access token
737
+ const accessToken = await this.getValidAccessToken({
738
+ authToken: data.authToken,
739
+ projectId: data.projectId,
740
+ });
741
+ logger.debug("Access token obtained for channel info retrieval");
742
+ // Fetch channel information from Microsoft Graph API
743
+ const apiUrl = `https://graph.microsoft.com/v1.0/teams/${data.teamId}/channels/${data.channelId}`;
744
+ logger.debug(`Making API call to: ${apiUrl}`);
745
+ const response = await API.get({
746
+ url: URL.fromString(apiUrl),
747
+ headers: {
748
+ Authorization: `Bearer ${accessToken}`,
749
+ "Content-Type": "application/json",
750
+ },
751
+ });
752
+ if (response instanceof HTTPErrorResponse) {
753
+ logger.error("Error getting channel info from Microsoft Graph API:");
754
+ logger.error(response);
755
+ // Fall back to basic channel object
756
+ logger.debug("Falling back to basic channel object");
757
+ return {
758
+ id: data.channelId,
759
+ name: data.channelId,
760
+ workspaceType: WorkspaceType.MicrosoftTeams,
761
+ teamId: data.teamId,
762
+ };
763
+ }
764
+ logger.debug("Channel info API call successful");
765
+ const channelData = response.data;
766
+ const channel = {
767
+ id: data.channelId,
768
+ name: channelData["displayName"],
769
+ workspaceType: WorkspaceType.MicrosoftTeams,
770
+ teamId: data.teamId,
771
+ };
772
+ logger.debug(`Channel info retrieved: ${JSON.stringify(channel)}`);
773
+ return channel;
774
+ }
775
+ catch (error) {
776
+ logger.error("Error fetching channel information:");
777
+ logger.error(error);
778
+ throw error;
779
+ }
780
+ }
781
+ static buildAdaptiveCardFromMessageBlocks(data) {
782
+ logger.debug("=== buildAdaptiveCardFromMessageBlocks called ===");
783
+ logger.debug(`Number of message blocks: ${data.messageBlocks.length}`);
784
+ const card = {
785
+ type: "AdaptiveCard",
786
+ $schema: "http://adaptivecards.io/schemas/adaptive-card.json",
787
+ version: "1.5",
788
+ body: [],
789
+ actions: [],
790
+ };
791
+ const body = [];
792
+ const actions = [];
793
+ for (const block of data.messageBlocks) {
794
+ logger.debug(`Processing message block of type: ${block._type}`);
795
+ if (block._type === "WorkspacePayloadMarkdown") {
796
+ const markdownBlock = block;
797
+ logger.debug(`Markdown text: ${markdownBlock.text}`);
798
+ const markdownObj = this.getMarkdownBlock({
799
+ payloadMarkdownBlock: markdownBlock,
800
+ });
801
+ body.push(markdownObj);
802
+ }
803
+ else if (block._type === "WorkspacePayloadHeader") {
804
+ const headerBlock = block;
805
+ logger.debug(`Header text: ${headerBlock.text}`);
806
+ const headerObj = this.getHeaderBlock({
807
+ payloadHeaderBlock: headerBlock,
808
+ });
809
+ body.push(headerObj);
810
+ }
811
+ else if (block._type === "WorkspacePayloadButtons") {
812
+ const buttonsBlock = block;
813
+ logger.debug(`Processing ${buttonsBlock.buttons.length} buttons`);
814
+ for (const button of buttonsBlock.buttons) {
815
+ logger.debug(`Button: ${button.title} -> ${button.url ? button.url.toString() : "invoke"}`);
816
+ const actionObj = this.getButtonBlock({
817
+ payloadButtonBlock: button,
818
+ });
819
+ actions.push(actionObj);
820
+ }
821
+ }
822
+ }
823
+ card["body"] = body;
824
+ card["actions"] = actions;
825
+ logger.debug(`Built adaptive card with ${body.length} body elements and ${actions.length} actions`);
826
+ return card;
827
+ }
828
+ static convertAdaptiveCardToHtml(adaptiveCard) {
829
+ logger.debug("=== convertAdaptiveCardToHtml called ===");
830
+ // Convert adaptive card to basic HTML for fallback
831
+ let html = "";
832
+ const body = adaptiveCard["body"] || [];
833
+ logger.debug(`Converting ${body.length} body elements to HTML`);
834
+ for (const element of body) {
835
+ if (element["type"] === "TextBlock") {
836
+ const text = element["text"];
837
+ const size = element["size"];
838
+ if (size === "Large") {
839
+ html += `<h2>${text}</h2>`;
840
+ logger.debug(`Added header: ${text}`);
841
+ }
842
+ else {
843
+ html += `<p>${text}</p>`;
844
+ logger.debug(`Added paragraph: ${text}`);
845
+ }
846
+ }
847
+ }
848
+ const actions = adaptiveCard["actions"] || [];
849
+ if (actions.length > 0) {
850
+ logger.debug(`Converting ${actions.length} actions to HTML`);
851
+ html += "<div>";
852
+ for (const action of actions) {
853
+ if (action["type"] === "Action.OpenUrl") {
854
+ const title = action["title"];
855
+ const url = action["url"];
856
+ html += `<a href="${url}">${title}</a> `;
857
+ logger.debug(`Added link: ${title} -> ${url}`);
858
+ }
859
+ }
860
+ html += "</div>";
861
+ }
862
+ logger.debug(`Generated HTML length: ${html.length} characters`);
863
+ return html;
864
+ }
865
+ // Placeholder implementations for abstract methods
866
+ static async showModalToUser(_data) {
867
+ // Microsoft Teams doesn't support modals in the same way as Slack
868
+ throw new Error("Modals are not supported in Microsoft Teams integration");
869
+ }
870
+ static async archiveChannels(_data) {
871
+ // Microsoft Teams doesn't support archiving channels via API
872
+ throw new Error("Channel archiving is not supported in Microsoft Teams integration");
873
+ }
874
+ static async joinChannel(_data) {
875
+ // Bot automatically has access to channels in Teams
876
+ logger.debug("Bot automatically has access to Teams channels");
877
+ }
878
+ static async inviteUserToChannelByChannelId(_data) {
879
+ // Teams channel membership is managed differently
880
+ logger.debug("Teams channel membership is managed at the team level");
881
+ }
882
+ static async inviteUserToChannelByChannelName(_data) {
883
+ // Teams channel membership is managed differently
884
+ logger.debug("Teams channel membership is managed at the team level");
885
+ }
886
+ static async getAllWorkspaceChannels(data) {
887
+ logger.debug("Getting all workspace channels for team ID: " + data.teamId);
888
+ // Get valid access token
889
+ const accessToken = await this.getValidAccessToken({
890
+ authToken: data.authToken,
891
+ projectId: data.projectId,
892
+ });
893
+ const response = await API.get({
894
+ url: URL.fromString(`https://graph.microsoft.com/v1.0/teams/${data.teamId}/channels`),
895
+ headers: {
896
+ Authorization: `Bearer ${accessToken}`,
897
+ "Content-Type": "application/json",
898
+ },
899
+ });
900
+ if (response instanceof HTTPErrorResponse) {
901
+ logger.error("Error response from Microsoft Graph API:");
902
+ logger.error(response);
903
+ throw response;
904
+ }
905
+ const channelsData = response.data;
906
+ const channelsArray = channelsData["value"] || [];
907
+ const channelsDict = {};
908
+ for (const channelData of channelsArray) {
909
+ const channel = {
910
+ id: channelData["id"],
911
+ name: channelData["displayName"],
912
+ workspaceType: WorkspaceType.MicrosoftTeams,
913
+ };
914
+ channelsDict[channel.id] = channel;
915
+ }
916
+ logger.debug(`Retrieved ${Object.keys(channelsDict).length} channels from API`);
917
+ return channelsDict;
918
+ }
919
+ static async doesChannelExist(data) {
920
+ if (!data.teamId) {
921
+ throw new BadDataException("teamId is required for Microsoft Teams doesChannelExist");
922
+ }
923
+ const channel = await this.getWorkspaceChannelByName({
924
+ authToken: data.authToken,
925
+ channelName: data.channelName,
926
+ projectId: data.projectId,
927
+ teamId: data.teamId,
928
+ });
929
+ return channel !== null;
930
+ }
931
+ static async isUserInDirectMessageChannel(_data) {
932
+ return false; // Placeholder
933
+ }
934
+ static async isUserInChannel(_data) {
935
+ return false; // Placeholder
936
+ }
937
+ // Block generation methods - these create adaptive card elements
938
+ static getDividerBlock() {
939
+ return {
940
+ type: "Container",
941
+ separator: true,
942
+ items: [],
943
+ };
944
+ }
945
+ static getButtonsBlock(_data) {
946
+ // Return adaptive card actions
947
+ return {
948
+ type: "ActionSet",
949
+ actions: [],
950
+ };
951
+ }
952
+ static getHeaderBlock(data) {
953
+ return {
954
+ type: "TextBlock",
955
+ text: data.payloadHeaderBlock.text,
956
+ size: "Large",
957
+ weight: "Bolder",
958
+ };
959
+ }
960
+ static getMarkdownBlock(data) {
961
+ return {
962
+ type: "TextBlock",
963
+ text: data.payloadMarkdownBlock.text,
964
+ wrap: true,
965
+ markdown: true,
966
+ };
967
+ }
968
+ static getButtonBlock(data) {
969
+ // If URL is present, render as link; otherwise use Action.Submit to post back action/value
970
+ if (data.payloadButtonBlock.url) {
971
+ return {
972
+ type: "Action.OpenUrl",
973
+ title: data.payloadButtonBlock.title,
974
+ url: data.payloadButtonBlock.url.toString(),
975
+ };
976
+ }
977
+ return {
978
+ type: "Action.Submit",
979
+ title: data.payloadButtonBlock.title,
980
+ data: {
981
+ action: data.payloadButtonBlock.actionId,
982
+ actionValue: data.payloadButtonBlock.value,
983
+ },
984
+ };
985
+ }
986
+ // Other block methods - placeholders for now
987
+ static getCheckboxBlock(_data) {
988
+ return { type: "Input.Toggle" };
989
+ }
990
+ static getDateTimePickerBlock(_data) {
991
+ return { type: "Input.Date" };
992
+ }
993
+ static getTextAreaBlock(_data) {
994
+ return { type: "Input.Text", isMultiline: true };
995
+ }
996
+ static getTextBoxBlock(_data) {
997
+ return { type: "Input.Text" };
998
+ }
999
+ static getImageBlock(_data) {
1000
+ return { type: "Image" };
1001
+ }
1002
+ static getDropdownBlock(_data) {
1003
+ return { type: "Input.ChoiceSet" };
1004
+ }
1005
+ static getModalBlock(_data) {
1006
+ // Teams doesn't support modals like Slack
1007
+ return {};
1008
+ }
1009
+ static async sendPayloadBlocksToChannel(_data) {
1010
+ // This is handled by sendAdaptiveCardToChannel
1011
+ throw new Error("Use sendAdaptiveCardToChannel instead");
1012
+ }
1013
+ static convertMarkdownToTeamsRichText(markdown) {
1014
+ // Basic markdown to Teams format conversion
1015
+ return markdown
1016
+ .replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
1017
+ .replace(/\*(.*?)\*/g, "<em>$1</em>")
1018
+ .replace(/`(.*?)`/g, "<code>$1</code>");
1019
+ }
1020
+ // Bot Framework specific methods
1021
+ static async handleBotMessageActivity(data) {
1022
+ var _a, _b, _c;
1023
+ // Handle direct messages to bot or @mentions via Bot Framework
1024
+ const messageText = data.activity["text"] || "";
1025
+ const possibleActionValue = data.activity["value"] || {};
1026
+ const from = data.activity["from"] || {};
1027
+ const conversation = data.activity["conversation"] || {};
1028
+ const channelData = data.activity["channelData"] || {};
1029
+ const entities = data.activity["entities"] || [];
1030
+ logger.debug(`Bot message from: ${JSON.stringify(from)}`);
1031
+ logger.debug(`Message text: ${messageText}`);
1032
+ logger.debug(`Conversation: ${JSON.stringify(conversation)}`);
1033
+ logger.debug(`Channel data: ${JSON.stringify(channelData)}`);
1034
+ logger.debug(`Entities: ${JSON.stringify(entities)}`);
1035
+ // If this is actually an Adaptive Card submit wrapped as a message, route to invoke handler
1036
+ if (possibleActionValue["action"] ||
1037
+ ((_a = possibleActionValue["data"]) === null || _a === void 0 ? void 0 : _a["action"])) {
1038
+ logger.debug("Message activity contains action payload; routing to invoke handler");
1039
+ await this.handleBotInvokeActivity({
1040
+ activity: data.activity,
1041
+ turnContext: data.turnContext,
1042
+ });
1043
+ return;
1044
+ }
1045
+ // Check if the bot was mentioned
1046
+ const recipientId = (_b = data.activity["recipient"]) === null || _b === void 0 ? void 0 : _b["id"];
1047
+ const conversationType = conversation["conversationType"] || "";
1048
+ const isDirectMessage = conversationType === "personal";
1049
+ const isMentioned = entities.some((entity) => {
1050
+ var _a;
1051
+ return (entity["type"] === "mention" &&
1052
+ ((_a = entity["mentioned"]) === null || _a === void 0 ? void 0 : _a["id"]) === recipientId);
1053
+ });
1054
+ // Only respond if it's a direct message or the bot was mentioned
1055
+ if (!isDirectMessage && !isMentioned) {
1056
+ logger.debug("Bot not mentioned in channel message, ignoring");
1057
+ return;
1058
+ }
1059
+ // Extract tenant ID to get project ID
1060
+ const tenantId = (_c = channelData["tenant"]) === null || _c === void 0 ? void 0 : _c["id"];
1061
+ if (!tenantId) {
1062
+ logger.error("Tenant ID not found in channelData");
1063
+ await data.turnContext.sendActivity("Sorry, I couldn't identify your organization. Please try again later.");
1064
+ return;
1065
+ }
1066
+ // Get project auth by tenant ID
1067
+ const projectAuth = await WorkspaceProjectAuthTokenService.findOneBy({
1068
+ query: {
1069
+ workspaceType: WorkspaceType.MicrosoftTeams,
1070
+ miscData: {
1071
+ tenantId: tenantId,
1072
+ },
1073
+ },
1074
+ select: {
1075
+ projectId: true,
1076
+ miscData: true,
1077
+ },
1078
+ props: {
1079
+ isRoot: true,
1080
+ },
1081
+ });
1082
+ if (!projectAuth || !projectAuth.projectId) {
1083
+ logger.error("Project auth not found for tenant ID: " + tenantId);
1084
+ await data.turnContext.sendActivity("Sorry, I couldn't find your project configuration. Please try again later.");
1085
+ return;
1086
+ }
1087
+ const projectId = projectAuth.projectId;
1088
+ logger.debug(`Found project ID: ${projectId.toString()} for tenant ID: ${tenantId}`);
1089
+ // Clean the message text by removing bot mentions
1090
+ const cleanText = messageText
1091
+ .replace(/<at[^>]*>.*?<\/at>/g, "")
1092
+ .trim()
1093
+ .toLowerCase();
1094
+ let responseText = "";
1095
+ try {
1096
+ if (cleanText.includes("help") || cleanText === "") {
1097
+ responseText = this.getHelpMessage();
1098
+ }
1099
+ else if (cleanText === "/incident" ||
1100
+ cleanText.startsWith("/incident ")) {
1101
+ // Handle /incident slash command
1102
+ logger.debug("Processing /incident command");
1103
+ const card = await MicrosoftTeamsIncidentActions.buildNewIncidentCard(projectId);
1104
+ await data.turnContext.sendActivity({
1105
+ attachments: [
1106
+ {
1107
+ contentType: "application/vnd.microsoft.card.adaptive",
1108
+ content: card,
1109
+ },
1110
+ ],
1111
+ });
1112
+ logger.debug("New incident card sent successfully");
1113
+ return;
1114
+ }
1115
+ else if (cleanText === "/maintenance" ||
1116
+ cleanText.startsWith("/maintenance ")) {
1117
+ // Handle /maintenance slash command
1118
+ logger.debug("Processing /maintenance command");
1119
+ const card = await MicrosoftTeamsScheduledMaintenanceActions.buildNewScheduledMaintenanceCard(projectId);
1120
+ await data.turnContext.sendActivity({
1121
+ attachments: [
1122
+ {
1123
+ contentType: "application/vnd.microsoft.card.adaptive",
1124
+ content: card,
1125
+ },
1126
+ ],
1127
+ });
1128
+ logger.debug("New scheduled maintenance card sent successfully");
1129
+ return;
1130
+ }
1131
+ else if (cleanText.includes("show active incidents") ||
1132
+ cleanText.includes("active incidents")) {
1133
+ responseText = await this.getActiveIncidentsMessage(projectId);
1134
+ }
1135
+ else if (cleanText.includes("show scheduled maintenance") ||
1136
+ cleanText.includes("scheduled maintenance")) {
1137
+ responseText = await this.getScheduledMaintenanceMessage(projectId);
1138
+ }
1139
+ else if (cleanText.includes("show ongoing maintenance") ||
1140
+ cleanText.includes("ongoing maintenance")) {
1141
+ responseText = await this.getOngoingMaintenanceMessage(projectId);
1142
+ }
1143
+ else if (cleanText.includes("show active alerts") ||
1144
+ cleanText.includes("active alerts")) {
1145
+ responseText = await this.getActiveAlertsMessage(projectId);
1146
+ }
1147
+ else {
1148
+ responseText = `I received your message: "${cleanText}". Type 'help' to see what I can do for you.`;
1149
+ }
1150
+ // Send response directly using TurnContext - this is the recommended Bot Framework pattern
1151
+ await data.turnContext.sendActivity(responseText);
1152
+ logger.debug("Bot message sent successfully using TurnContext");
1153
+ }
1154
+ catch (error) {
1155
+ logger.error("Error sending bot message via TurnContext: " + error);
1156
+ await data.turnContext.sendActivity("Sorry, I encountered an error processing your request. Please try again later.");
1157
+ throw error;
1158
+ }
1159
+ }
1160
+ // Helper methods for bot commands
1161
+ static getHelpMessage() {
1162
+ return `Hello! I'm the OneUptime bot. I can help you with the following commands:
1163
+
1164
+ **Available Commands:**
1165
+ - **help** — Show this help message
1166
+ - **/incident** — Create a new incident
1167
+ - **/maintenance** — Create a new scheduled maintenance event
1168
+ - **show active incidents** — Display all currently active incidents
1169
+ - **show scheduled maintenance** — Show upcoming scheduled maintenance events
1170
+ - **show ongoing maintenance** — Display currently ongoing maintenance events
1171
+ - **show active alerts** — Display all active alerts
1172
+
1173
+ Just type any of these commands to get the information you need!`;
1174
+ }
1175
+ static async getActiveIncidentsMessage(projectId) {
1176
+ var _a, _b;
1177
+ try {
1178
+ logger.debug("Getting active incidents for project: " + projectId.toString());
1179
+ // Get unresolved incident states
1180
+ const unresolvedIncidentStates = await IncidentStateService.getUnresolvedIncidentStates(projectId, {
1181
+ isRoot: true,
1182
+ });
1183
+ const unresolvedIncidentStateIds = unresolvedIncidentStates.map((state) => {
1184
+ return state.id;
1185
+ });
1186
+ // Find active incidents
1187
+ const activeIncidents = await IncidentService.findBy({
1188
+ query: {
1189
+ projectId: projectId,
1190
+ currentIncidentStateId: QueryHelper.any(unresolvedIncidentStateIds),
1191
+ },
1192
+ select: {
1193
+ _id: true,
1194
+ incidentNumber: true,
1195
+ title: true,
1196
+ description: true,
1197
+ currentIncidentState: {
1198
+ name: true,
1199
+ color: true,
1200
+ },
1201
+ incidentSeverity: {
1202
+ name: true,
1203
+ color: true,
1204
+ },
1205
+ createdAt: true,
1206
+ monitors: {
1207
+ name: true,
1208
+ },
1209
+ },
1210
+ sort: {
1211
+ createdAt: SortOrder.Descending,
1212
+ },
1213
+ limit: 10,
1214
+ skip: 0,
1215
+ props: {
1216
+ isRoot: true,
1217
+ },
1218
+ });
1219
+ if (activeIncidents.length === 0) {
1220
+ return `**Active Incidents**
1221
+
1222
+ Currently, there are no active incidents in the system. All services are operating normally.
1223
+
1224
+ If you need to report an incident or check historical incidents, please visit the OneUptime dashboard.`;
1225
+ }
1226
+ let message = `**Active Incidents** (${activeIncidents.length})
1227
+
1228
+ `;
1229
+ for (const incident of activeIncidents) {
1230
+ const severity = ((_a = incident.incidentSeverity) === null || _a === void 0 ? void 0 : _a.name) || "Unknown";
1231
+ const state = ((_b = incident.currentIncidentState) === null || _b === void 0 ? void 0 : _b.name) || "Unknown";
1232
+ const createdAt = incident.createdAt
1233
+ ? OneUptimeDate.getDateAsFormattedString(incident.createdAt)
1234
+ : "Unknown";
1235
+ const severityIcon = ["Critical", "Major"].includes(severity)
1236
+ ? "🔴"
1237
+ : severity === "Minor"
1238
+ ? "🟠"
1239
+ : "🟡";
1240
+ const incidentUrl = await IncidentService.getIncidentLinkInDashboard(projectId, incident.id);
1241
+ message += `${severityIcon} **[Incident #${incident.incidentNumber}: ${incident.title}](${incidentUrl.toString()})**
1242
+ • **Severity:** ${severity}
1243
+ • **Status:** ${state}
1244
+ • **Created:** ${createdAt}
1245
+ `;
1246
+ if (incident.monitors && incident.monitors.length > 0) {
1247
+ message += `• **Affected Services:** ${incident.monitors
1248
+ .map((m) => {
1249
+ return m.name;
1250
+ })
1251
+ .join(", ")}\n`;
1252
+ }
1253
+ if (incident.description) {
1254
+ const desc = incident.description.replace(/\s+/g, " ");
1255
+ message += `• **Description:** ${desc.substring(0, 180)}${desc.length > 180 ? "..." : ""}\n`;
1256
+ }
1257
+ message += `• [Open in Dashboard](${incidentUrl.toString()})\n\n`;
1258
+ }
1259
+ return message;
1260
+ }
1261
+ catch (error) {
1262
+ logger.error("Error getting active incidents: " + error);
1263
+ return "Sorry, I couldn't retrieve active incidents information at the moment. Please try again later.";
1264
+ }
1265
+ }
1266
+ static async getScheduledMaintenanceMessage(projectId) {
1267
+ var _a;
1268
+ try {
1269
+ logger.debug("Getting scheduled maintenance events for project: " +
1270
+ projectId.toString());
1271
+ // Get scheduled maintenance events
1272
+ const scheduledEvents = await ScheduledMaintenanceService.findBy({
1273
+ query: {
1274
+ projectId: projectId,
1275
+ currentScheduledMaintenanceState: {
1276
+ isScheduledState: true,
1277
+ },
1278
+ isVisibleOnStatusPage: true, // Only show events visible on status page
1279
+ },
1280
+ select: {
1281
+ _id: true,
1282
+ title: true,
1283
+ description: true,
1284
+ startsAt: true,
1285
+ endsAt: true,
1286
+ currentScheduledMaintenanceState: {
1287
+ name: true,
1288
+ },
1289
+ monitors: {
1290
+ name: true,
1291
+ },
1292
+ scheduledMaintenanceNumber: true,
1293
+ },
1294
+ sort: {
1295
+ startsAt: SortOrder.Ascending,
1296
+ },
1297
+ limit: 10,
1298
+ skip: 0,
1299
+ props: {
1300
+ isRoot: true,
1301
+ },
1302
+ });
1303
+ if (scheduledEvents.length === 0) {
1304
+ return `**Scheduled Maintenance Events**
1305
+
1306
+ There are currently no scheduled maintenance events.
1307
+
1308
+ When maintenance is scheduled, you'll see details here including:
1309
+ • Event title and description
1310
+ • Scheduled start and end times
1311
+ • Affected services
1312
+ • Status updates
1313
+
1314
+ Check back later for upcoming maintenance windows.`;
1315
+ }
1316
+ let message = `**Scheduled Maintenance Events** (${scheduledEvents.length})
1317
+
1318
+ `;
1319
+ for (const event of scheduledEvents) {
1320
+ const state = ((_a = event.currentScheduledMaintenanceState) === null || _a === void 0 ? void 0 : _a.name) || "Scheduled";
1321
+ const startTime = event.startsAt
1322
+ ? OneUptimeDate.getDateAsFormattedString(event.startsAt)
1323
+ : "TBD";
1324
+ const endTime = event.endsAt
1325
+ ? OneUptimeDate.getDateAsFormattedString(event.endsAt)
1326
+ : "TBD";
1327
+ const eventUrl = await ScheduledMaintenanceService.getScheduledMaintenanceLinkInDashboard(projectId, event.id);
1328
+ message += `🛠️ **[Scheduled Maintenance #${event.scheduledMaintenanceNumber}: ${event.title}](${eventUrl.toString()})**
1329
+ • **Status:** ${state}
1330
+ • **Starts:** ${startTime}
1331
+ • **Ends:** ${endTime}
1332
+ `;
1333
+ if (event.monitors && event.monitors.length > 0) {
1334
+ message += `• **Affected Services:** ${event.monitors
1335
+ .map((m) => {
1336
+ return m.name;
1337
+ })
1338
+ .join(", ")}\n`;
1339
+ }
1340
+ if (event.description) {
1341
+ const desc = event.description.replace(/\s+/g, " ");
1342
+ message += `• **Description:** ${desc.substring(0, 180)}${desc.length > 180 ? "..." : ""}\n`;
1343
+ }
1344
+ message += `• [View Event](${eventUrl.toString()})\n\n`;
1345
+ }
1346
+ return message;
1347
+ }
1348
+ catch (error) {
1349
+ logger.error("Error getting scheduled maintenance: " + error);
1350
+ return "Sorry, I couldn't retrieve scheduled maintenance information at the moment. Please try again later.";
1351
+ }
1352
+ }
1353
+ static async getOngoingMaintenanceMessage(projectId) {
1354
+ var _a;
1355
+ try {
1356
+ logger.debug("Getting ongoing maintenance events for project: " +
1357
+ projectId.toString());
1358
+ // Get ongoing maintenance events
1359
+ const ongoingEvents = await ScheduledMaintenanceService.findBy({
1360
+ query: {
1361
+ projectId: projectId,
1362
+ currentScheduledMaintenanceState: {
1363
+ isOngoingState: true,
1364
+ },
1365
+ },
1366
+ select: {
1367
+ _id: true,
1368
+ title: true,
1369
+ description: true,
1370
+ startsAt: true,
1371
+ endsAt: true,
1372
+ currentScheduledMaintenanceState: {
1373
+ name: true,
1374
+ },
1375
+ monitors: {
1376
+ name: true,
1377
+ },
1378
+ scheduledMaintenanceNumber: true,
1379
+ },
1380
+ sort: {
1381
+ startsAt: SortOrder.Descending,
1382
+ },
1383
+ limit: 10,
1384
+ skip: 0,
1385
+ props: {
1386
+ isRoot: true,
1387
+ },
1388
+ });
1389
+ if (ongoingEvents.length === 0) {
1390
+ return `**Ongoing Maintenance Events**
1391
+
1392
+ There are currently no ongoing maintenance events.
1393
+
1394
+ When maintenance is in progress, you'll see details here including:
1395
+ • Event title and description
1396
+ • Current status and progress
1397
+ • Affected services
1398
+ • Expected completion time
1399
+
1400
+ All systems are currently operating normally.`;
1401
+ }
1402
+ let message = `**Ongoing Maintenance Events** (${ongoingEvents.length})
1403
+
1404
+ `;
1405
+ for (const event of ongoingEvents) {
1406
+ const state = ((_a = event.currentScheduledMaintenanceState) === null || _a === void 0 ? void 0 : _a.name) || "Ongoing";
1407
+ const startTime = event.startsAt
1408
+ ? OneUptimeDate.getDateAsFormattedString(event.startsAt)
1409
+ : "Unknown";
1410
+ const endTime = event.endsAt
1411
+ ? OneUptimeDate.getDateAsFormattedString(event.endsAt)
1412
+ : "TBD";
1413
+ const eventUrl = await ScheduledMaintenanceService.getScheduledMaintenanceLinkInDashboard(projectId, event.id);
1414
+ message += `🔧 **[Scheduled Maintenance #${event.scheduledMaintenanceNumber}: ${event.title}](${eventUrl.toString()})**
1415
+ • **Status:** ${state}
1416
+ • **Started:** ${startTime}
1417
+ • **Expected End:** ${endTime}
1418
+ `;
1419
+ if (event.monitors && event.monitors.length > 0) {
1420
+ message += `• **Affected Services:** ${event.monitors
1421
+ .map((m) => {
1422
+ return m.name;
1423
+ })
1424
+ .join(", ")}\n`;
1425
+ }
1426
+ if (event.description) {
1427
+ const desc = event.description.replace(/\s+/g, " ");
1428
+ message += `• **Description:** ${desc.substring(0, 180)}${desc.length > 180 ? "..." : ""}\n`;
1429
+ }
1430
+ message += `• [View Event](${eventUrl.toString()})\n\n`;
1431
+ }
1432
+ return message;
1433
+ }
1434
+ catch (error) {
1435
+ logger.error("Error getting ongoing maintenance: " + error);
1436
+ return "Sorry, I couldn't retrieve ongoing maintenance information at the moment. Please try again later.";
1437
+ }
1438
+ }
1439
+ static async getActiveAlertsMessage(projectId) {
1440
+ var _a, _b, _c;
1441
+ try {
1442
+ logger.debug("Getting active alerts for project: " + projectId.toString());
1443
+ // Get unresolved alert states
1444
+ const unresolvedAlertStates = await AlertStateService.getUnresolvedAlertStates(projectId, {
1445
+ isRoot: true,
1446
+ });
1447
+ const unresolvedAlertStateIds = unresolvedAlertStates.map((state) => {
1448
+ return state.id;
1449
+ });
1450
+ // Find active alerts
1451
+ const activeAlerts = await AlertService.findBy({
1452
+ query: {
1453
+ projectId: projectId,
1454
+ currentAlertStateId: QueryHelper.any(unresolvedAlertStateIds),
1455
+ },
1456
+ select: {
1457
+ _id: true,
1458
+ alertNumber: true,
1459
+ title: true,
1460
+ description: true,
1461
+ currentAlertState: {
1462
+ name: true,
1463
+ color: true,
1464
+ },
1465
+ alertSeverity: {
1466
+ name: true,
1467
+ color: true,
1468
+ },
1469
+ createdAt: true,
1470
+ monitor: {
1471
+ name: true,
1472
+ },
1473
+ },
1474
+ sort: {
1475
+ createdAt: SortOrder.Descending,
1476
+ },
1477
+ limit: 10,
1478
+ skip: 0,
1479
+ props: {
1480
+ isRoot: true,
1481
+ },
1482
+ });
1483
+ if (activeAlerts.length === 0) {
1484
+ return `**Active Alerts**
1485
+
1486
+ Currently, there are no active alerts in the system.
1487
+
1488
+ When alerts are triggered, you'll see details here including:
1489
+ • Alert title and description
1490
+ • Severity level
1491
+ • Affected services or monitors
1492
+ • Time triggered
1493
+ • Current status
1494
+
1495
+ All monitoring checks are passing normally.`;
1496
+ }
1497
+ let message = `**Active Alerts** (${activeAlerts.length})
1498
+
1499
+ `;
1500
+ for (const alert of activeAlerts) {
1501
+ const severity = ((_a = alert.alertSeverity) === null || _a === void 0 ? void 0 : _a.name) || "Unknown";
1502
+ const state = ((_b = alert.currentAlertState) === null || _b === void 0 ? void 0 : _b.name) || "Unknown";
1503
+ const createdAt = alert.createdAt
1504
+ ? OneUptimeDate.getDateAsFormattedString(alert.createdAt)
1505
+ : "Unknown";
1506
+ const alertUrl = await AlertService.getAlertLinkInDashboard(projectId, alert.id);
1507
+ message += `⚠️ **[Alert #${alert.alertNumber}: ${alert.title}](${alertUrl.toString()})**
1508
+ • **Severity:** ${severity}
1509
+ • **Status:** ${state}
1510
+ • **Triggered:** ${createdAt}
1511
+ `;
1512
+ if ((_c = alert.monitor) === null || _c === void 0 ? void 0 : _c.name) {
1513
+ message += `• **Monitor:** ${alert.monitor.name}\n`;
1514
+ }
1515
+ if (alert.description) {
1516
+ const desc = alert.description.replace(/\s+/g, " ");
1517
+ message += `• **Description:** ${desc.substring(0, 180)}${desc.length > 180 ? "..." : ""}\n`;
1518
+ }
1519
+ message += `• [Open in Dashboard](${alertUrl.toString()})\n\n`;
1520
+ }
1521
+ return message;
1522
+ }
1523
+ catch (error) {
1524
+ logger.error("Error getting active alerts: " + error);
1525
+ return "Sorry, I couldn't retrieve active alerts information at the moment. Please try again later.";
1526
+ }
1527
+ }
1528
+ static async handleBotInvokeActivity(data) {
1529
+ // Handle adaptive card button clicks via Bot Framework
1530
+ const value = data.activity["value"] || {};
1531
+ // Extract action type and value from the value object
1532
+ const { actionType, actionValue } = this.extractActionFromValue(value);
1533
+ logger.debug(`Bot invoke activity - Action type: ${actionType}`);
1534
+ logger.debug(`Bot invoke value: ${JSON.stringify(value)}`);
1535
+ try {
1536
+ // Resolve project and user context from activity
1537
+ const channelData = data.activity["channelData"] || {};
1538
+ const tenantId = (channelData["tenant"] || {})["id"];
1539
+ if (!tenantId) {
1540
+ logger.error("Tenant ID not found in invoke activity");
1541
+ await data.turnContext.sendActivity("Sorry, I couldn't identify your organization. Please try again later.");
1542
+ return;
1543
+ }
1544
+ const projectAuth = await WorkspaceProjectAuthTokenService.findOneBy({
1545
+ query: {
1546
+ workspaceType: WorkspaceType.MicrosoftTeams,
1547
+ miscData: { tenantId: tenantId },
1548
+ },
1549
+ select: { projectId: true, authToken: true },
1550
+ props: { isRoot: true },
1551
+ });
1552
+ if (!projectAuth || !projectAuth.projectId) {
1553
+ logger.error("Project auth not found for invoke activity tenant: " + tenantId);
1554
+ await data.turnContext.sendActivity("Sorry, I couldn't find your project configuration.");
1555
+ return;
1556
+ }
1557
+ const projectId = projectAuth.projectId;
1558
+ const fromObj = (data.activity["from"] ||
1559
+ {});
1560
+ const teamsUserId = fromObj["aadObjectId"] || undefined;
1561
+ if (!teamsUserId) {
1562
+ logger.error("AAD Object ID (teamsUserId) not found in invoke activity from object");
1563
+ await data.turnContext.sendActivity("Sorry, I couldn't identify you. Please try again later.");
1564
+ return;
1565
+ }
1566
+ const userLookupParamsRes = {
1567
+ teamsUserId: teamsUserId,
1568
+ projectId: projectId,
1569
+ };
1570
+ const oneUptimeUserId = await MicrosoftTeamsAuthAction.getOneUptimeUserIdFromTeamsUserId(userLookupParamsRes);
1571
+ // Handle incident actions
1572
+ if (MicrosoftTeamsIncidentActions.isIncidentAction({ actionType })) {
1573
+ await MicrosoftTeamsIncidentActions.handleBotIncidentAction({
1574
+ actionType,
1575
+ actionValue,
1576
+ value,
1577
+ projectId,
1578
+ oneUptimeUserId,
1579
+ turnContext: data.turnContext,
1580
+ });
1581
+ return;
1582
+ }
1583
+ // Handle alert actions
1584
+ if (MicrosoftTeamsAlertActions.isAlertAction({ actionType })) {
1585
+ await MicrosoftTeamsAlertActions.handleBotAlertAction({
1586
+ actionType,
1587
+ actionValue,
1588
+ value,
1589
+ projectId,
1590
+ oneUptimeUserId,
1591
+ turnContext: data.turnContext,
1592
+ });
1593
+ return;
1594
+ }
1595
+ // Handle monitor actions
1596
+ if (MicrosoftTeamsMonitorActions.isMonitorAction({ actionType })) {
1597
+ await MicrosoftTeamsMonitorActions.handleBotMonitorAction({
1598
+ actionType,
1599
+ actionValue,
1600
+ value,
1601
+ projectId,
1602
+ oneUptimeUserId,
1603
+ turnContext: data.turnContext,
1604
+ });
1605
+ return;
1606
+ }
1607
+ // Handle scheduled maintenance actions
1608
+ if (MicrosoftTeamsScheduledMaintenanceActions.isScheduledMaintenanceAction({
1609
+ actionType,
1610
+ })) {
1611
+ await MicrosoftTeamsScheduledMaintenanceActions.handleBotScheduledMaintenanceAction(actionType, data.turnContext, value, {
1612
+ userId: oneUptimeUserId.toString(),
1613
+ projectId,
1614
+ isAuthorized: true,
1615
+ authToken: "",
1616
+ payloadType: "invoke",
1617
+ });
1618
+ return;
1619
+ }
1620
+ // Handle on-call duty actions
1621
+ if (MicrosoftTeamsOnCallDutyActions.isOnCallDutyAction({ actionType })) {
1622
+ await MicrosoftTeamsOnCallDutyActions.handleBotOnCallDutyAction(actionType, data.turnContext, value);
1623
+ return;
1624
+ }
1625
+ }
1626
+ catch (error) {
1627
+ logger.error("Error handling bot invoke activity:");
1628
+ logger.error(error);
1629
+ await data.turnContext.sendActivity("Sorry, that action failed. Please try again later.");
1630
+ }
1631
+ }
1632
+ static async handleConversationUpdateActivity(data) {
1633
+ // Handle bot added to team/channel or members added/removed
1634
+ const membersAdded = data.activity["membersAdded"] || [];
1635
+ const membersRemoved = data.activity["membersRemoved"] || [];
1636
+ const conversation = data.activity["conversation"] || {};
1637
+ const channelData = data.activity["channelData"] || {};
1638
+ logger.debug(`Conversation update - Members added: ${JSON.stringify(membersAdded)}`);
1639
+ logger.debug(`Conversation update - Members removed: ${JSON.stringify(membersRemoved)}`);
1640
+ logger.debug(`Conversation: ${JSON.stringify(conversation)}`);
1641
+ logger.debug(`Channel data: ${JSON.stringify(channelData)}`);
1642
+ // Check if the bot was added
1643
+ const botWasAdded = membersAdded.some((member) => {
1644
+ return member["id"] === MicrosoftTeamsAppClientId;
1645
+ });
1646
+ if (botWasAdded) {
1647
+ logger.debug("OneUptime bot was added to a Teams conversation");
1648
+ const welcomeText = "🎉 Welcome to OneUptime!\n\nI'm your monitoring and alerting assistant. I'll help you stay on top of your system's health and notify you about any incidents.\n\nType 'help' to see what I can do for you.";
1649
+ try {
1650
+ // Send welcome message directly using TurnContext
1651
+ await data.turnContext.sendActivity(welcomeText);
1652
+ logger.debug("Welcome message sent successfully using TurnContext");
1653
+ }
1654
+ catch (error) {
1655
+ logger.error("Error sending welcome message via TurnContext: " + error);
1656
+ }
1657
+ }
1658
+ }
1659
+ static async handleInstallationUpdateActivity(data) {
1660
+ // Handle bot installation/uninstallation
1661
+ const action = data.activity["action"] || "";
1662
+ const conversation = data.activity["conversation"] || {};
1663
+ logger.debug(`Installation update - Action: ${action}`);
1664
+ logger.debug(`Conversation: ${JSON.stringify(conversation)}`);
1665
+ if (action === "add") {
1666
+ logger.debug("OneUptime bot was installed");
1667
+ }
1668
+ else if (action === "remove") {
1669
+ logger.debug("OneUptime bot was uninstalled");
1670
+ }
1671
+ }
1672
+ /**
1673
+ * Process Bot Framework activity using the botbuilder SDK adapter.processActivity
1674
+ * This replaces the manual JWT validation and activity handling with proper SDK methods
1675
+ */
1676
+ static async processBotActivity(req, res) {
1677
+ var _a, _b, _c;
1678
+ logger.debug("Processing Bot Framework activity using adapter.processActivity");
1679
+ logger.debug("Request body: " + JSON.stringify(req.body, null, 2));
1680
+ try {
1681
+ if (!MicrosoftTeamsAppClientId || !MicrosoftTeamsAppClientSecret) {
1682
+ logger.error("Microsoft Teams App credentials not configured");
1683
+ res.status(500).json({ error: "Bot credentials not configured" });
1684
+ return;
1685
+ }
1686
+ // Extract tenant ID from the activity
1687
+ const tenantId = (_c = (_b = (_a = req.body) === null || _a === void 0 ? void 0 : _a.channelData) === null || _b === void 0 ? void 0 : _b.tenant) === null || _c === void 0 ? void 0 : _c.id;
1688
+ if (!tenantId) {
1689
+ logger.error("Tenant ID not found in activity channelData");
1690
+ res.status(400).json({ error: "Invalid activity: missing tenant ID" });
1691
+ return;
1692
+ }
1693
+ // Get Bot Framework adapter
1694
+ const adapter = this.getBotAdapter(tenantId);
1695
+ // Create custom activity handler class that extends TeamsActivityHandler
1696
+ class OneUptimeTeamsActivityHandler extends TeamsActivityHandler {
1697
+ constructor() {
1698
+ super();
1699
+ // Set up message handlers using the proper API
1700
+ this.onMessage(async (context, next) => {
1701
+ logger.debug("Handling message activity: " +
1702
+ JSON.stringify(context.activity));
1703
+ await MicrosoftTeamsUtil.handleBotMessageActivity({
1704
+ activity: context.activity,
1705
+ turnContext: context,
1706
+ });
1707
+ await next();
1708
+ });
1709
+ this.onMembersAdded(async (context, next) => {
1710
+ logger.debug("Handling members added activity: " +
1711
+ JSON.stringify(context.activity));
1712
+ await MicrosoftTeamsUtil.handleConversationUpdateActivity({
1713
+ activity: context.activity,
1714
+ turnContext: context,
1715
+ });
1716
+ await next();
1717
+ });
1718
+ }
1719
+ async onInvokeActivity(context) {
1720
+ logger.debug("Handling invoke activity: " + JSON.stringify(context.activity));
1721
+ await MicrosoftTeamsUtil.handleBotInvokeActivity({
1722
+ activity: context.activity,
1723
+ turnContext: context,
1724
+ });
1725
+ // Return empty response for invoke activities
1726
+ return { status: 200 };
1727
+ }
1728
+ }
1729
+ // Create activity handler instance
1730
+ const activityHandler = new OneUptimeTeamsActivityHandler();
1731
+ // Use the adapter's process method with Express-style req/res
1732
+ await adapter.process(req, res, async (context) => {
1733
+ var _a, _b;
1734
+ logger.debug("Processing activity with TurnContext: " +
1735
+ JSON.stringify({
1736
+ activityType: context.activity.type,
1737
+ activityId: context.activity.id,
1738
+ from: (_a = context.activity.from) === null || _a === void 0 ? void 0 : _a.name,
1739
+ conversationId: (_b = context.activity.conversation) === null || _b === void 0 ? void 0 : _b.id,
1740
+ }));
1741
+ // Run the activity through our activity handler
1742
+ await activityHandler.run(context);
1743
+ });
1744
+ logger.debug("Bot Framework activity processed successfully");
1745
+ }
1746
+ catch (error) {
1747
+ logger.error("Error processing Bot Framework activity: " + error);
1748
+ if (!res.headersSent) {
1749
+ res.status(500).json({ error: "Failed to process bot activity" });
1750
+ }
1751
+ }
1752
+ }
1753
+ // Method to refresh teams list for a user
1754
+ static async refreshTeams(data) {
1755
+ logger.debug("=== refreshTeams called ===");
1756
+ logger.debug(`Project ID: ${data.projectId.toString()}`);
1757
+ try {
1758
+ // Get project auth to get app access token
1759
+ const projectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
1760
+ projectId: data.projectId,
1761
+ workspaceType: WorkspaceType.MicrosoftTeams,
1762
+ });
1763
+ if (!projectAuth || !projectAuth.miscData) {
1764
+ throw new BadDataException("Microsoft Teams integration not found for this project");
1765
+ }
1766
+ // Get a valid app access token
1767
+ const accessToken = await this.refreshAccessToken({
1768
+ projectId: data.projectId,
1769
+ miscData: projectAuth.miscData,
1770
+ });
1771
+ if (!accessToken) {
1772
+ throw new BadDataException("Could not obtain valid access token for Microsoft Teams");
1773
+ }
1774
+ // Fetch all teams from Microsoft Graph API using app permissions
1775
+ const teamsResponse = await API.get({
1776
+ url: URL.fromString("https://graph.microsoft.com/v1.0/teams"),
1777
+ headers: {
1778
+ Authorization: `Bearer ${accessToken}`,
1779
+ },
1780
+ });
1781
+ if (teamsResponse instanceof HTTPErrorResponse) {
1782
+ logger.error("Error fetching teams from Microsoft Teams:");
1783
+ logger.error(teamsResponse);
1784
+ throw new BadDataException("Failed to fetch teams from Microsoft Teams");
1785
+ }
1786
+ const teams = teamsResponse.data["value"] || [];
1787
+ if (teams.length === 0) {
1788
+ logger.debug("No teams found in organization");
1789
+ return {};
1790
+ }
1791
+ // Process teams
1792
+ const availableTeams = teams.reduce((acc, t) => {
1793
+ const team = {
1794
+ id: t["id"],
1795
+ name: t["displayName"] || "Unnamed Team",
1796
+ };
1797
+ acc[team.name] = team;
1798
+ return acc;
1799
+ }, {});
1800
+ logger.debug(`Fetched ${Object.keys(availableTeams).length} teams`);
1801
+ // Update project auth token with new teams
1802
+ const miscData = projectAuth.miscData || {};
1803
+ miscData.availableTeams = availableTeams;
1804
+ await WorkspaceProjectAuthTokenService.updateOneById({
1805
+ id: projectAuth.id,
1806
+ data: {
1807
+ miscData: miscData,
1808
+ },
1809
+ props: {
1810
+ isRoot: true,
1811
+ },
1812
+ });
1813
+ logger.debug("Updated project auth token with refreshed teams");
1814
+ return availableTeams;
1815
+ }
1816
+ catch (error) {
1817
+ logger.error("Error refreshing teams:");
1818
+ logger.error(error);
1819
+ throw error;
1820
+ }
1821
+ }
1822
+ // Method to get user's joined teams using user access token
1823
+ static async getUserJoinedTeams(accessToken) {
1824
+ logger.debug("=== getUserJoinedTeams called ===");
1825
+ try {
1826
+ // Get user's teams
1827
+ const teamsResponse = await API.get({
1828
+ url: URL.fromString("https://graph.microsoft.com/v1.0/me/joinedTeams"),
1829
+ headers: {
1830
+ Authorization: `Bearer ${accessToken}`,
1831
+ },
1832
+ });
1833
+ if (teamsResponse instanceof HTTPErrorResponse) {
1834
+ logger.error("Error getting teams:");
1835
+ logger.error(teamsResponse);
1836
+ throw teamsResponse;
1837
+ }
1838
+ const teamsData = teamsResponse.data;
1839
+ const teams = teamsData["value"] || [];
1840
+ if (teams.length === 0) {
1841
+ logger.debug("No joined teams found for user");
1842
+ return {};
1843
+ }
1844
+ // Process teams
1845
+ const availableTeams = teams.reduce((acc, t) => {
1846
+ const team = {
1847
+ id: t["id"],
1848
+ name: t["displayName"] || "Unnamed Team",
1849
+ };
1850
+ acc[team.name] = team;
1851
+ return acc;
1852
+ }, {});
1853
+ logger.debug(`Fetched ${Object.keys(availableTeams).length} joined teams`);
1854
+ return availableTeams;
1855
+ }
1856
+ catch (error) {
1857
+ logger.error("Error getting user joined teams:");
1858
+ logger.error(error);
1859
+ throw error;
1860
+ }
1861
+ }
127
1862
  }
128
1863
  __decorate([
129
1864
  CaptureSpan(),
130
1865
  __metadata("design:type", Function),
131
1866
  __metadata("design:paramtypes", [Object]),
132
1867
  __metadata("design:returntype", Promise)
133
- ], MicrosoftTeams, "sendMessageToChannelViaIncomingWebhook", null);
1868
+ ], MicrosoftTeamsUtil, "sendMessageToChannelViaIncomingWebhook", null);
1869
+ __decorate([
1870
+ CaptureSpan(),
1871
+ __metadata("design:type", Function),
1872
+ __metadata("design:paramtypes", [Object]),
1873
+ __metadata("design:returntype", Promise)
1874
+ ], MicrosoftTeamsUtil, "getUsernameFromUserId", null);
1875
+ __decorate([
1876
+ CaptureSpan(),
1877
+ __metadata("design:type", Function),
1878
+ __metadata("design:paramtypes", [Object]),
1879
+ __metadata("design:returntype", Promise)
1880
+ ], MicrosoftTeamsUtil, "sendDirectMessageToUser", null);
1881
+ __decorate([
1882
+ CaptureSpan(),
1883
+ __metadata("design:type", Function),
1884
+ __metadata("design:paramtypes", [Object]),
1885
+ __metadata("design:returntype", Promise)
1886
+ ], MicrosoftTeamsUtil, "createChannelsIfDoesNotExist", null);
1887
+ __decorate([
1888
+ CaptureSpan(),
1889
+ __metadata("design:type", Function),
1890
+ __metadata("design:paramtypes", [Object]),
1891
+ __metadata("design:returntype", Promise)
1892
+ ], MicrosoftTeamsUtil, "createChannel", null);
1893
+ __decorate([
1894
+ CaptureSpan(),
1895
+ __metadata("design:type", Function),
1896
+ __metadata("design:paramtypes", [Object]),
1897
+ __metadata("design:returntype", Promise)
1898
+ ], MicrosoftTeamsUtil, "getWorkspaceChannelFromChannelName", null);
1899
+ __decorate([
1900
+ CaptureSpan(),
1901
+ __metadata("design:type", Function),
1902
+ __metadata("design:paramtypes", [Object]),
1903
+ __metadata("design:returntype", Promise)
1904
+ ], MicrosoftTeamsUtil, "getWorkspaceChannelByName", null);
1905
+ __decorate([
1906
+ CaptureSpan(),
1907
+ __metadata("design:type", Function),
1908
+ __metadata("design:paramtypes", [Object]),
1909
+ __metadata("design:returntype", Promise)
1910
+ ], MicrosoftTeamsUtil, "sendMessage", null);
1911
+ __decorate([
1912
+ CaptureSpan(),
1913
+ __metadata("design:type", Function),
1914
+ __metadata("design:paramtypes", [Object]),
1915
+ __metadata("design:returntype", Promise)
1916
+ ], MicrosoftTeamsUtil, "sendAdaptiveCardToChannel", null);
1917
+ __decorate([
1918
+ CaptureSpan(),
1919
+ __metadata("design:type", Function),
1920
+ __metadata("design:paramtypes", [Object]),
1921
+ __metadata("design:returntype", Promise)
1922
+ ], MicrosoftTeamsUtil, "getWorkspaceChannelFromChannelId", null);
1923
+ __decorate([
1924
+ CaptureSpan(),
1925
+ __metadata("design:type", Function),
1926
+ __metadata("design:paramtypes", [Object]),
1927
+ __metadata("design:returntype", Promise)
1928
+ ], MicrosoftTeamsUtil, "showModalToUser", null);
1929
+ __decorate([
1930
+ CaptureSpan(),
1931
+ __metadata("design:type", Function),
1932
+ __metadata("design:paramtypes", [Object]),
1933
+ __metadata("design:returntype", Promise)
1934
+ ], MicrosoftTeamsUtil, "archiveChannels", null);
1935
+ __decorate([
1936
+ CaptureSpan(),
1937
+ __metadata("design:type", Function),
1938
+ __metadata("design:paramtypes", [Object]),
1939
+ __metadata("design:returntype", Promise)
1940
+ ], MicrosoftTeamsUtil, "joinChannel", null);
1941
+ __decorate([
1942
+ CaptureSpan(),
1943
+ __metadata("design:type", Function),
1944
+ __metadata("design:paramtypes", [Object]),
1945
+ __metadata("design:returntype", Promise)
1946
+ ], MicrosoftTeamsUtil, "inviteUserToChannelByChannelId", null);
1947
+ __decorate([
1948
+ CaptureSpan(),
1949
+ __metadata("design:type", Function),
1950
+ __metadata("design:paramtypes", [Object]),
1951
+ __metadata("design:returntype", Promise)
1952
+ ], MicrosoftTeamsUtil, "inviteUserToChannelByChannelName", null);
1953
+ __decorate([
1954
+ CaptureSpan(),
1955
+ __metadata("design:type", Function),
1956
+ __metadata("design:paramtypes", [Object]),
1957
+ __metadata("design:returntype", Promise)
1958
+ ], MicrosoftTeamsUtil, "getAllWorkspaceChannels", null);
1959
+ __decorate([
1960
+ CaptureSpan(),
1961
+ __metadata("design:type", Function),
1962
+ __metadata("design:paramtypes", [Object]),
1963
+ __metadata("design:returntype", Promise)
1964
+ ], MicrosoftTeamsUtil, "doesChannelExist", null);
1965
+ __decorate([
1966
+ CaptureSpan(),
1967
+ __metadata("design:type", Function),
1968
+ __metadata("design:paramtypes", [Object]),
1969
+ __metadata("design:returntype", Promise)
1970
+ ], MicrosoftTeamsUtil, "isUserInDirectMessageChannel", null);
1971
+ __decorate([
1972
+ CaptureSpan(),
1973
+ __metadata("design:type", Function),
1974
+ __metadata("design:paramtypes", [Object]),
1975
+ __metadata("design:returntype", Promise)
1976
+ ], MicrosoftTeamsUtil, "isUserInChannel", null);
1977
+ __decorate([
1978
+ CaptureSpan(),
1979
+ __metadata("design:type", Function),
1980
+ __metadata("design:paramtypes", []),
1981
+ __metadata("design:returntype", Object)
1982
+ ], MicrosoftTeamsUtil, "getDividerBlock", null);
1983
+ __decorate([
1984
+ CaptureSpan(),
1985
+ __metadata("design:type", Function),
1986
+ __metadata("design:paramtypes", [Object]),
1987
+ __metadata("design:returntype", Object)
1988
+ ], MicrosoftTeamsUtil, "getButtonsBlock", null);
1989
+ __decorate([
1990
+ CaptureSpan(),
1991
+ __metadata("design:type", Function),
1992
+ __metadata("design:paramtypes", [Object]),
1993
+ __metadata("design:returntype", Object)
1994
+ ], MicrosoftTeamsUtil, "getHeaderBlock", null);
1995
+ __decorate([
1996
+ CaptureSpan(),
1997
+ __metadata("design:type", Function),
1998
+ __metadata("design:paramtypes", [Object]),
1999
+ __metadata("design:returntype", Object)
2000
+ ], MicrosoftTeamsUtil, "getMarkdownBlock", null);
2001
+ __decorate([
2002
+ CaptureSpan(),
2003
+ __metadata("design:type", Function),
2004
+ __metadata("design:paramtypes", [Object]),
2005
+ __metadata("design:returntype", Object)
2006
+ ], MicrosoftTeamsUtil, "getButtonBlock", null);
2007
+ __decorate([
2008
+ CaptureSpan(),
2009
+ __metadata("design:type", Function),
2010
+ __metadata("design:paramtypes", [Object]),
2011
+ __metadata("design:returntype", Object)
2012
+ ], MicrosoftTeamsUtil, "getCheckboxBlock", null);
2013
+ __decorate([
2014
+ CaptureSpan(),
2015
+ __metadata("design:type", Function),
2016
+ __metadata("design:paramtypes", [Object]),
2017
+ __metadata("design:returntype", Object)
2018
+ ], MicrosoftTeamsUtil, "getDateTimePickerBlock", null);
2019
+ __decorate([
2020
+ CaptureSpan(),
2021
+ __metadata("design:type", Function),
2022
+ __metadata("design:paramtypes", [Object]),
2023
+ __metadata("design:returntype", Object)
2024
+ ], MicrosoftTeamsUtil, "getTextAreaBlock", null);
2025
+ __decorate([
2026
+ CaptureSpan(),
2027
+ __metadata("design:type", Function),
2028
+ __metadata("design:paramtypes", [Object]),
2029
+ __metadata("design:returntype", Object)
2030
+ ], MicrosoftTeamsUtil, "getTextBoxBlock", null);
2031
+ __decorate([
2032
+ CaptureSpan(),
2033
+ __metadata("design:type", Function),
2034
+ __metadata("design:paramtypes", [Object]),
2035
+ __metadata("design:returntype", Object)
2036
+ ], MicrosoftTeamsUtil, "getImageBlock", null);
2037
+ __decorate([
2038
+ CaptureSpan(),
2039
+ __metadata("design:type", Function),
2040
+ __metadata("design:paramtypes", [Object]),
2041
+ __metadata("design:returntype", Object)
2042
+ ], MicrosoftTeamsUtil, "getDropdownBlock", null);
2043
+ __decorate([
2044
+ CaptureSpan(),
2045
+ __metadata("design:type", Function),
2046
+ __metadata("design:paramtypes", [Object]),
2047
+ __metadata("design:returntype", Object)
2048
+ ], MicrosoftTeamsUtil, "getModalBlock", null);
2049
+ __decorate([
2050
+ CaptureSpan(),
2051
+ __metadata("design:type", Function),
2052
+ __metadata("design:paramtypes", [Object]),
2053
+ __metadata("design:returntype", Promise)
2054
+ ], MicrosoftTeamsUtil, "sendPayloadBlocksToChannel", null);
2055
+ __decorate([
2056
+ CaptureSpan(),
2057
+ __metadata("design:type", Function),
2058
+ __metadata("design:paramtypes", [String]),
2059
+ __metadata("design:returntype", String)
2060
+ ], MicrosoftTeamsUtil, "convertMarkdownToTeamsRichText", null);
2061
+ __decorate([
2062
+ CaptureSpan(),
2063
+ __metadata("design:type", Function),
2064
+ __metadata("design:paramtypes", [Object]),
2065
+ __metadata("design:returntype", Promise)
2066
+ ], MicrosoftTeamsUtil, "handleBotMessageActivity", null);
2067
+ __decorate([
2068
+ CaptureSpan(),
2069
+ __metadata("design:type", Function),
2070
+ __metadata("design:paramtypes", [Object]),
2071
+ __metadata("design:returntype", Promise)
2072
+ ], MicrosoftTeamsUtil, "handleBotInvokeActivity", null);
2073
+ __decorate([
2074
+ CaptureSpan(),
2075
+ __metadata("design:type", Function),
2076
+ __metadata("design:paramtypes", [Object]),
2077
+ __metadata("design:returntype", Promise)
2078
+ ], MicrosoftTeamsUtil, "handleConversationUpdateActivity", null);
2079
+ __decorate([
2080
+ CaptureSpan(),
2081
+ __metadata("design:type", Function),
2082
+ __metadata("design:paramtypes", [Object]),
2083
+ __metadata("design:returntype", Promise)
2084
+ ], MicrosoftTeamsUtil, "handleInstallationUpdateActivity", null);
2085
+ __decorate([
2086
+ CaptureSpan(),
2087
+ __metadata("design:type", Function),
2088
+ __metadata("design:paramtypes", [Object, Object]),
2089
+ __metadata("design:returntype", Promise)
2090
+ ], MicrosoftTeamsUtil, "processBotActivity", null);
2091
+ __decorate([
2092
+ CaptureSpan(),
2093
+ __metadata("design:type", Function),
2094
+ __metadata("design:paramtypes", [Object]),
2095
+ __metadata("design:returntype", Promise)
2096
+ ], MicrosoftTeamsUtil, "refreshTeams", null);
2097
+ __decorate([
2098
+ CaptureSpan(),
2099
+ __metadata("design:type", Function),
2100
+ __metadata("design:paramtypes", [String]),
2101
+ __metadata("design:returntype", Promise)
2102
+ ], MicrosoftTeamsUtil, "getUserJoinedTeams", null);
134
2103
  //# sourceMappingURL=MicrosoftTeams.js.map